[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
vbvictor wrote:
I think we should make a generalised check (with types that can be configure).
In LLVM I can think of `SourceLocation` which is small and should be passed by
value too.
Also, pass by value should be applied to built-in integer/floats and pointers.
Isn't this a misleading behavoir?
```cpp
void badFunctionMutable(MyOp &op) {
op = newOp()
}
```
What if someone overrides `op` inside function - then the check produces FP?
https://github.com/llvm/llvm-project/pull/179882
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
https://github.com/jpienaar updated
https://github.com/llvm/llvm-project/pull/179882
>From 758e5c109b59098f9b72ae2a0b0e7201b5cfc0a5 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar
Date: Wed, 4 Feb 2026 11:22:48 +
Subject: [PATCH 1/3] [clang-tidy][mlir] Add check for passing value type by
reference.
This instance is effectively a wrapper around a pointer and should be
passed by value.
There are a few existing such cases in MLIR upstream. Didn't fix along
with this to avoid mixing discussions.
---
.../llvm/AvoidPassingMlirOpAsRefCheck.cpp | 51 +++
.../llvm/AvoidPassingMlirOpAsRefCheck.h | 31 +++
.../clang-tidy/llvm/CMakeLists.txt| 1 +
.../clang-tidy/llvm/LLVMTidyModule.cpp| 3 ++
clang-tools-extra/docs/ReleaseNotes.rst | 5 ++
.../docs/clang-tidy/checks/list.rst | 1 +
.../llvm/avoid-passing-mlir-op-as-ref.rst | 21
.../llvm/avoid-passing-mlir-op-as-ref.cpp | 33
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 4 +-
.../SCF/Transforms/ParallelLoopFusion.cpp | 2 +-
mlir/unittests/TableGen/OpBuildGen.cpp| 2 +-
11 files changed, 150 insertions(+), 4 deletions(-)
create mode 100644
clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
create mode 100644
clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
create mode 100644
clang-tools-extra/docs/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.rst
create mode 100644
clang-tools-extra/test/clang-tidy/checkers/llvm/avoid-passing-mlir-op-as-ref.cpp
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
new file mode 100644
index 0..dc8d14632582a
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
@@ -0,0 +1,51 @@
+//===--- AvoidPassingMlirOpAsRefCheck.cpp - clang-tidy
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AvoidPassingMlirOpAsRefCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::llvm_check {
+
+void AvoidPassingMlirOpAsRefCheck::registerMatchers(MatchFinder *Finder) {
+ // Match parameters that are references to classes derived from mlir::Op.
+ Finder->addMatcher(
+ parmVarDecl(
+ hasType(qualType(
+ references(qualType(hasDeclaration(
+ cxxRecordDecl(isSameOrDerivedFrom("::mlir::Op"))
+ .bind("op_type",
+ // We want to avoid matching `Op *&` (reference to pointer to Op)
+ // which is not common for Op but possible.
+ unless(references(pointerType(),
+ unless(isImplicit()),
+ unless(hasAncestor(cxxConstructorDecl(
+ anyOf(isCopyConstructor(), isMoveConstructor(),
+ unless(hasAncestor(cxxMethodDecl(isCopyAssignmentOperator(,
+ unless(hasAncestor(cxxMethodDecl(isMoveAssignmentOperator(,
+ decl().bind("param")),
+ this);
+}
+
+void AvoidPassingMlirOpAsRefCheck::check(
+const MatchFinder::MatchResult &Result) {
+ const auto *Param = Result.Nodes.getNodeAs("param");
+ const auto *OpType = Result.Nodes.getNodeAs("op_type");
+
+ // Exclude if we can't find definitions.
+ if (!Param || !OpType)
+return;
+
+ diag(Param->getLocation(),
+ "MLIR Op class '%0' should be passed by value, not by reference")
+ << OpType->getName();
+}
+
+} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
new file mode 100644
index 0..ff9a1172f52d8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
@@ -0,0 +1,31 @@
+//===--- AvoidPassingMlirOpAsRefCheck.h - clang-tidy *- C++
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
+/// Flags function parameters of a type derived from mlir::Op that are passed
by
+/// reference.
+///
+/// For the user-facing documentation see:
+///
http://clang.llvm.org/extra/clang-tidy/chec
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
@@ -0,0 +1,21 @@ +.. title:: clang-tidy - llvm-avoid-passing-mlir-op-as-ref + +llvm-avoid-passing-mlir-op-as-ref += + +Flags function parameters of a type derived from ``mlir::Op`` that are passed EugeneZelenko wrote: Please synchronize first statement with statement in Release Notes. https://github.com/llvm/llvm-project/pull/179882 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
https://github.com/jpienaar updated
https://github.com/llvm/llvm-project/pull/179882
>From 758e5c109b59098f9b72ae2a0b0e7201b5cfc0a5 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar
Date: Wed, 4 Feb 2026 11:22:48 +
Subject: [PATCH 1/2] [clang-tidy][mlir] Add check for passing value type by
reference.
This instance is effectively a wrapper around a pointer and should be
passed by value.
There are a few existing such cases in MLIR upstream. Didn't fix along
with this to avoid mixing discussions.
---
.../llvm/AvoidPassingMlirOpAsRefCheck.cpp | 51 +++
.../llvm/AvoidPassingMlirOpAsRefCheck.h | 31 +++
.../clang-tidy/llvm/CMakeLists.txt| 1 +
.../clang-tidy/llvm/LLVMTidyModule.cpp| 3 ++
clang-tools-extra/docs/ReleaseNotes.rst | 5 ++
.../docs/clang-tidy/checks/list.rst | 1 +
.../llvm/avoid-passing-mlir-op-as-ref.rst | 21
.../llvm/avoid-passing-mlir-op-as-ref.cpp | 33
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 4 +-
.../SCF/Transforms/ParallelLoopFusion.cpp | 2 +-
mlir/unittests/TableGen/OpBuildGen.cpp| 2 +-
11 files changed, 150 insertions(+), 4 deletions(-)
create mode 100644
clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
create mode 100644
clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
create mode 100644
clang-tools-extra/docs/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.rst
create mode 100644
clang-tools-extra/test/clang-tidy/checkers/llvm/avoid-passing-mlir-op-as-ref.cpp
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
new file mode 100644
index 0..dc8d14632582a
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
@@ -0,0 +1,51 @@
+//===--- AvoidPassingMlirOpAsRefCheck.cpp - clang-tidy
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AvoidPassingMlirOpAsRefCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::llvm_check {
+
+void AvoidPassingMlirOpAsRefCheck::registerMatchers(MatchFinder *Finder) {
+ // Match parameters that are references to classes derived from mlir::Op.
+ Finder->addMatcher(
+ parmVarDecl(
+ hasType(qualType(
+ references(qualType(hasDeclaration(
+ cxxRecordDecl(isSameOrDerivedFrom("::mlir::Op"))
+ .bind("op_type",
+ // We want to avoid matching `Op *&` (reference to pointer to Op)
+ // which is not common for Op but possible.
+ unless(references(pointerType(),
+ unless(isImplicit()),
+ unless(hasAncestor(cxxConstructorDecl(
+ anyOf(isCopyConstructor(), isMoveConstructor(),
+ unless(hasAncestor(cxxMethodDecl(isCopyAssignmentOperator(,
+ unless(hasAncestor(cxxMethodDecl(isMoveAssignmentOperator(,
+ decl().bind("param")),
+ this);
+}
+
+void AvoidPassingMlirOpAsRefCheck::check(
+const MatchFinder::MatchResult &Result) {
+ const auto *Param = Result.Nodes.getNodeAs("param");
+ const auto *OpType = Result.Nodes.getNodeAs("op_type");
+
+ // Exclude if we can't find definitions.
+ if (!Param || !OpType)
+return;
+
+ diag(Param->getLocation(),
+ "MLIR Op class '%0' should be passed by value, not by reference")
+ << OpType->getName();
+}
+
+} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
new file mode 100644
index 0..ff9a1172f52d8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
@@ -0,0 +1,31 @@
+//===--- AvoidPassingMlirOpAsRefCheck.h - clang-tidy *- C++
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
+/// Flags function parameters of a type derived from mlir::Op that are passed
by
+/// reference.
+///
+/// For the user-facing documentation see:
+///
http://clang.llvm.org/extra/clang-tidy/chec
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
github-actions[bot] wrote: # :penguin: Linux x64 Test Results * 10559 tests passed * 607 tests skipped * 2 tests failed ## Failed Tests (click on a test name to see its output) ### Clang Tools Clang Tools.clang-tidy/infrastructure/alphabetical-order.test ``` Exit Code: 1 Command Output (stdout): -- # RUN: at line 1 /usr/bin/python3 /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/test/clang-tidy/infrastructure/../../../clang-tidy/tool/check_alphabetical_order.py -o /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/infrastructure/Output/alphabetical-order.test.tmp.clang-tidy-checks-list.rst # executed command: /usr/bin/python3 /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/test/clang-tidy/infrastructure/../../../clang-tidy/tool/check_alphabetical_order.py -o /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/infrastructure/Output/alphabetical-order.test.tmp.clang-tidy-checks-list.rst # note: command had no output on stdout or stderr # RUN: at line 2 diff --strip-trailing-cr /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/test/clang-tidy/infrastructure/../../../docs/clang-tidy/checks/list.rst /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/infrastructure/Output/alphabetical-order.test.tmp.clang-tidy-checks-list.rst # executed command: diff --strip-trailing-cr /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/test/clang-tidy/infrastructure/../../../docs/clang-tidy/checks/list.rst /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/infrastructure/Output/alphabetical-order.test.tmp.clang-tidy-checks-list.rst # note: command had no output on stdout or stderr # RUN: at line 4 /usr/bin/python3 /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/test/clang-tidy/infrastructure/../../../clang-tidy/tool/check_alphabetical_order.py -o /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/infrastructure/Output/alphabetical-order.test.tmp.ReleaseNotes.rst # executed command: /usr/bin/python3 /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/test/clang-tidy/infrastructure/../../../clang-tidy/tool/check_alphabetical_order.py -o /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/infrastructure/Output/alphabetical-order.test.tmp.ReleaseNotes.rst # .---command stderr # | # | Entries in 'clang-tools-extra/docs/ReleaseNotes.rst' are not alphabetically sorted. # | Fix the ordering by applying diff printed below. # | # `- # RUN: at line 5 diff --strip-trailing-cr /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/test/clang-tidy/infrastructure/../../../docs/ReleaseNotes.rst /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/infrastructure/Output/alphabetical-order.test.tmp.ReleaseNotes.rst # executed command: diff --strip-trailing-cr /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/test/clang-tidy/infrastructure/../../../docs/ReleaseNotes.rst /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/infrastructure/Output/alphabetical-order.test.tmp.ReleaseNotes.rst # .---command stdout # | *** /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/test/clang-tidy/infrastructure/../../../docs/ReleaseNotes.rst # | --- /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/infrastructure/Output/alphabetical-order.test.tmp.ReleaseNotes.rst # | *** # | *** 97,107 # | New checks # | ^^ # | # | - - New :doc:`avoid-passing-mlir-op-as-ref` # | - ` check. # | - # | - Finds cases where ``mlir::Op`` derived classes are passed by reference. # | - # | - New :doc:`llvm-type-switch-case-types # | ` check. # | # | --- 97,102 # | *** # | *** 139,144 # | --- 134,144 # | Checks for presence or absence of trailing commas in enum definitions and # | initializer lists. # | # | + - New :doc:`avoid-passing-mlir-op-as-ref` # | + ` check. # | + # | + Finds cases where ``mlir::Op`` derived classes are passed by reference. # | + # | New check aliases # | ^ # | # `- # error: command failed with exit status: 1 -- ``` ### MLIR MLIR.Dialect/SCF/parallel-loop-fusion.mlir ``` Exit Code: 1 Command Output (stdout): -- # RUN: at line 1 /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/mlir-opt -allow-unregistered-dialect /home/gha/actions-runner
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
github-actions[bot] wrote: # :window: Windows x64 Test Results * 6493 tests passed * 442 tests skipped * 2 tests failed ## Failed Tests (click on a test name to see its output) ### MLIR MLIR.Dialect/SCF/parallel-loop-fusion.mlir ``` Exit Code: 1 Command Output (stdout): -- # RUN: at line 1 c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe -allow-unregistered-dialect C:\_work\llvm-project\llvm-project\mlir\test\Dialect\SCF\parallel-loop-fusion.mlir -pass-pipeline='builtin.module(func.func(scf-parallel-loop-fusion))' -split-input-file | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe C:\_work\llvm-project\llvm-project\mlir\test\Dialect\SCF\parallel-loop-fusion.mlir # executed command: 'c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe' -allow-unregistered-dialect 'C:\_work\llvm-project\llvm-project\mlir\test\Dialect\SCF\parallel-loop-fusion.mlir' '-pass-pipeline=builtin.module(func.func(scf-parallel-loop-fusion))' -split-input-file # .---command stderr # | Assertion failed: !region.empty() && "unexpected empty region", file C:\_work\llvm-project\llvm-project\mlir\include\mlir/IR/OpDefinition.h, line 907 # | PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug. # | Stack dump: # | 0. Program arguments: c:\\_work\\llvm-project\\llvm-project\\build\\bin\\mlir-opt.exe -allow-unregistered-dialect C:\\_work\\llvm-project\\llvm-project\\mlir\\test\\Dialect\\SCF\\parallel-loop-fusion.mlir -pass-pipeline=builtin.module(func.func(scf-parallel-loop-fusion)) -split-input-file # | Exception Code: 0xC01D # | #0 0x7ff74234ba56 mlir::detail::FallbackTypeIDResolver::registerImplicitTypeID(class llvm::StringRef) (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x305ba56) # | #1 0x7ffaa109bb04 (C:\Windows\System32\ucrtbase.dll+0x7bb04) # | #2 0x7ffaa109cad1 (C:\Windows\System32\ucrtbase.dll+0x7cad1) # | #3 0x7ffaa109e4a1 (C:\Windows\System32\ucrtbase.dll+0x7e4a1) # | #4 0x7ffaa109e6e1 (C:\Windows\System32\ucrtbase.dll+0x7e6e1) # | #5 0x7ff7414d72ba mlir::detail::FallbackTypeIDResolver::registerImplicitTypeID(class llvm::StringRef) (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x21e72ba) # | #6 0x7ff7414db888 mlir::detail::FallbackTypeIDResolver::registerImplicitTypeID(class llvm::StringRef) (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x21eb888) # | #7 0x7ff73f315929 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x25929) # | #8 0x7ff7414db709 mlir::detail::FallbackTypeIDResolver::registerImplicitTypeID(class llvm::StringRef) (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x21eb709) # | #9 0x7ff73f66bf5f (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x37bf5f) # | #10 0x7ff73f66c976 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x37c976) # | #11 0x7ff73f66f862 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x37f862) # | #12 0x7ff73f66bd14 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x37bd14) # | #13 0x7ff73f66c976 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x37c976) # | #14 0x7ff73f674176 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x384176) # | #15 0x7ff73f6738a3 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x3838a3) # | #16 0x7ff73f2ff812 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0xf812) # | #17 0x7ff73f2fea5a (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0xea5a) # | #18 0x7ff73f65b570 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x36b570) # | #19 0x7ff73f65b1e9 (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x36b1e9) # | #20 0x7ff73f2f358e (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x358e) # | #21 0x7ff73f2f393c (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x393c) # | #22 0x7ff73f2f3c9b (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x3c9b) # | #23 0x7ff73f2f145a (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x145a) # | #24 0x7ff746b37c10 mlir::detail::FallbackTypeIDResolver::registerImplicitTypeID(class llvm::StringRef) (c:\_work\llvm-project\llvm-project\build\bin\mlir-opt.exe+0x7847c10) # | #25 0x7ffaa9734cb0 (C:\Windows\System32\KERNEL32.DLL+0x14cb0) # | #26 0x7ffab543edcb (C:\Windows\SYSTEM32\ntdll.dll+0x7edcb) # `- # error: command failed with exit status: 0xc01d # executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' 'C:\_work\llvm-project\llvm-project\mlir\test\Dialect\SCF\parallel-loop-fusion.mlir' # .---command stderr # | C:\_work\llvm-project\llvm-project\mlir\test\Dialect\SCF\parallel-loop-fusion.mlir:127:17: error: CHECK-LABEL: expected string not found in input # | // CH
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
github-actions[bot] wrote: :warning: RST documentation linter, doc8 found issues in your code. :warning: You can test this locally with the following command: ```bash doc8 -q clang-tools-extra/docs/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.rst clang-tools-extra/docs/clang-tidy/checks/list.rst --config clang-tools-extra/clang-tidy/doc8.ini ``` View the output from doc8 here. ``` clang-tools-extra/docs/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.rst:6: D001 Line too long clang-tools-extra/docs/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.rst:7: D001 Line too long ``` Note: documentation lines should be less than 80 characters wide. https://github.com/llvm/llvm-project/pull/179882 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
llvmbot wrote:
@llvm/pr-subscribers-flang-openmp
Author: Jacques Pienaar (jpienaar)
Changes
This instance is effectively a wrapper around a pointer and should be passed by
value.
There are a few existing such cases in MLIR upstream. Didn't fix along with
this to avoid mixing discussions.
---
Full diff: https://github.com/llvm/llvm-project/pull/179882.diff
11 Files Affected:
- (added) clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
(+51)
- (added) clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
(+31)
- (modified) clang-tools-extra/clang-tidy/llvm/CMakeLists.txt (+1)
- (modified) clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp (+3)
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5)
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1)
- (added)
clang-tools-extra/docs/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.rst
(+21)
- (added)
clang-tools-extra/test/clang-tidy/checkers/llvm/avoid-passing-mlir-op-as-ref.cpp
(+33)
- (modified) mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp (+2-2)
- (modified) mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp (+1-1)
- (modified) mlir/unittests/TableGen/OpBuildGen.cpp (+1-1)
``diff
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
new file mode 100644
index 0..dc8d14632582a
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
@@ -0,0 +1,51 @@
+//===--- AvoidPassingMlirOpAsRefCheck.cpp - clang-tidy
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AvoidPassingMlirOpAsRefCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::llvm_check {
+
+void AvoidPassingMlirOpAsRefCheck::registerMatchers(MatchFinder *Finder) {
+ // Match parameters that are references to classes derived from mlir::Op.
+ Finder->addMatcher(
+ parmVarDecl(
+ hasType(qualType(
+ references(qualType(hasDeclaration(
+ cxxRecordDecl(isSameOrDerivedFrom("::mlir::Op"))
+ .bind("op_type",
+ // We want to avoid matching `Op *&` (reference to pointer to Op)
+ // which is not common for Op but possible.
+ unless(references(pointerType(),
+ unless(isImplicit()),
+ unless(hasAncestor(cxxConstructorDecl(
+ anyOf(isCopyConstructor(), isMoveConstructor(),
+ unless(hasAncestor(cxxMethodDecl(isCopyAssignmentOperator(,
+ unless(hasAncestor(cxxMethodDecl(isMoveAssignmentOperator(,
+ decl().bind("param")),
+ this);
+}
+
+void AvoidPassingMlirOpAsRefCheck::check(
+const MatchFinder::MatchResult &Result) {
+ const auto *Param = Result.Nodes.getNodeAs("param");
+ const auto *OpType = Result.Nodes.getNodeAs("op_type");
+
+ // Exclude if we can't find definitions.
+ if (!Param || !OpType)
+return;
+
+ diag(Param->getLocation(),
+ "MLIR Op class '%0' should be passed by value, not by reference")
+ << OpType->getName();
+}
+
+} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
new file mode 100644
index 0..ff9a1172f52d8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
@@ -0,0 +1,31 @@
+//===--- AvoidPassingMlirOpAsRefCheck.h - clang-tidy *- C++
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
+/// Flags function parameters of a type derived from mlir::Op that are passed
by
+/// reference.
+///
+/// For the user-facing documentation see:
+///
http://clang.llvm.org/extra/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.html
+class AvoidPassingMlirOpAsRefCheck : public ClangTidyCheck {
+public:
+ AvoidPassingMlirOpAsRefCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchF
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
llvmbot wrote:
@llvm/pr-subscribers-clang-tools-extra
Author: Jacques Pienaar (jpienaar)
Changes
This instance is effectively a wrapper around a pointer and should be passed by
value.
There are a few existing such cases in MLIR upstream. Didn't fix along with
this to avoid mixing discussions.
---
Full diff: https://github.com/llvm/llvm-project/pull/179882.diff
11 Files Affected:
- (added) clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
(+51)
- (added) clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
(+31)
- (modified) clang-tools-extra/clang-tidy/llvm/CMakeLists.txt (+1)
- (modified) clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp (+3)
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5)
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1)
- (added)
clang-tools-extra/docs/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.rst
(+21)
- (added)
clang-tools-extra/test/clang-tidy/checkers/llvm/avoid-passing-mlir-op-as-ref.cpp
(+33)
- (modified) mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp (+2-2)
- (modified) mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp (+1-1)
- (modified) mlir/unittests/TableGen/OpBuildGen.cpp (+1-1)
``diff
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
new file mode 100644
index 0..dc8d14632582a
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
@@ -0,0 +1,51 @@
+//===--- AvoidPassingMlirOpAsRefCheck.cpp - clang-tidy
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AvoidPassingMlirOpAsRefCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::llvm_check {
+
+void AvoidPassingMlirOpAsRefCheck::registerMatchers(MatchFinder *Finder) {
+ // Match parameters that are references to classes derived from mlir::Op.
+ Finder->addMatcher(
+ parmVarDecl(
+ hasType(qualType(
+ references(qualType(hasDeclaration(
+ cxxRecordDecl(isSameOrDerivedFrom("::mlir::Op"))
+ .bind("op_type",
+ // We want to avoid matching `Op *&` (reference to pointer to Op)
+ // which is not common for Op but possible.
+ unless(references(pointerType(),
+ unless(isImplicit()),
+ unless(hasAncestor(cxxConstructorDecl(
+ anyOf(isCopyConstructor(), isMoveConstructor(),
+ unless(hasAncestor(cxxMethodDecl(isCopyAssignmentOperator(,
+ unless(hasAncestor(cxxMethodDecl(isMoveAssignmentOperator(,
+ decl().bind("param")),
+ this);
+}
+
+void AvoidPassingMlirOpAsRefCheck::check(
+const MatchFinder::MatchResult &Result) {
+ const auto *Param = Result.Nodes.getNodeAs("param");
+ const auto *OpType = Result.Nodes.getNodeAs("op_type");
+
+ // Exclude if we can't find definitions.
+ if (!Param || !OpType)
+return;
+
+ diag(Param->getLocation(),
+ "MLIR Op class '%0' should be passed by value, not by reference")
+ << OpType->getName();
+}
+
+} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
new file mode 100644
index 0..ff9a1172f52d8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
@@ -0,0 +1,31 @@
+//===--- AvoidPassingMlirOpAsRefCheck.h - clang-tidy *- C++
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
+/// Flags function parameters of a type derived from mlir::Op that are passed
by
+/// reference.
+///
+/// For the user-facing documentation see:
+///
http://clang.llvm.org/extra/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.html
+class AvoidPassingMlirOpAsRefCheck : public ClangTidyCheck {
+public:
+ AvoidPassingMlirOpAsRefCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::M
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
llvmbot wrote:
@llvm/pr-subscribers-clang-tidy
@llvm/pr-subscribers-mlir
Author: Jacques Pienaar (jpienaar)
Changes
This instance is effectively a wrapper around a pointer and should be passed by
value.
There are a few existing such cases in MLIR upstream. Didn't fix along with
this to avoid mixing discussions.
---
Full diff: https://github.com/llvm/llvm-project/pull/179882.diff
11 Files Affected:
- (added) clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
(+51)
- (added) clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
(+31)
- (modified) clang-tools-extra/clang-tidy/llvm/CMakeLists.txt (+1)
- (modified) clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp (+3)
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5)
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1)
- (added)
clang-tools-extra/docs/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.rst
(+21)
- (added)
clang-tools-extra/test/clang-tidy/checkers/llvm/avoid-passing-mlir-op-as-ref.cpp
(+33)
- (modified) mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp (+2-2)
- (modified) mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp (+1-1)
- (modified) mlir/unittests/TableGen/OpBuildGen.cpp (+1-1)
``diff
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
new file mode 100644
index 0..dc8d14632582a
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
@@ -0,0 +1,51 @@
+//===--- AvoidPassingMlirOpAsRefCheck.cpp - clang-tidy
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AvoidPassingMlirOpAsRefCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::llvm_check {
+
+void AvoidPassingMlirOpAsRefCheck::registerMatchers(MatchFinder *Finder) {
+ // Match parameters that are references to classes derived from mlir::Op.
+ Finder->addMatcher(
+ parmVarDecl(
+ hasType(qualType(
+ references(qualType(hasDeclaration(
+ cxxRecordDecl(isSameOrDerivedFrom("::mlir::Op"))
+ .bind("op_type",
+ // We want to avoid matching `Op *&` (reference to pointer to Op)
+ // which is not common for Op but possible.
+ unless(references(pointerType(),
+ unless(isImplicit()),
+ unless(hasAncestor(cxxConstructorDecl(
+ anyOf(isCopyConstructor(), isMoveConstructor(),
+ unless(hasAncestor(cxxMethodDecl(isCopyAssignmentOperator(,
+ unless(hasAncestor(cxxMethodDecl(isMoveAssignmentOperator(,
+ decl().bind("param")),
+ this);
+}
+
+void AvoidPassingMlirOpAsRefCheck::check(
+const MatchFinder::MatchResult &Result) {
+ const auto *Param = Result.Nodes.getNodeAs("param");
+ const auto *OpType = Result.Nodes.getNodeAs("op_type");
+
+ // Exclude if we can't find definitions.
+ if (!Param || !OpType)
+return;
+
+ diag(Param->getLocation(),
+ "MLIR Op class '%0' should be passed by value, not by reference")
+ << OpType->getName();
+}
+
+} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
new file mode 100644
index 0..ff9a1172f52d8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
@@ -0,0 +1,31 @@
+//===--- AvoidPassingMlirOpAsRefCheck.h - clang-tidy *- C++
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
+/// Flags function parameters of a type derived from mlir::Op that are passed
by
+/// reference.
+///
+/// For the user-facing documentation see:
+///
http://clang.llvm.org/extra/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.html
+class AvoidPassingMlirOpAsRefCheck : public ClangTidyCheck {
+public:
+ AvoidPassingMlirOpAsRefCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(co
[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)
https://github.com/jpienaar created
https://github.com/llvm/llvm-project/pull/179882
This instance is effectively a wrapper around a pointer and should be passed by
value.
There are a few existing such cases in MLIR upstream. Didn't fix along with
this to avoid mixing discussions.
>From 758e5c109b59098f9b72ae2a0b0e7201b5cfc0a5 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar
Date: Wed, 4 Feb 2026 11:22:48 +
Subject: [PATCH] [clang-tidy][mlir] Add check for passing value type by
reference.
This instance is effectively a wrapper around a pointer and should be
passed by value.
There are a few existing such cases in MLIR upstream. Didn't fix along
with this to avoid mixing discussions.
---
.../llvm/AvoidPassingMlirOpAsRefCheck.cpp | 51 +++
.../llvm/AvoidPassingMlirOpAsRefCheck.h | 31 +++
.../clang-tidy/llvm/CMakeLists.txt| 1 +
.../clang-tidy/llvm/LLVMTidyModule.cpp| 3 ++
clang-tools-extra/docs/ReleaseNotes.rst | 5 ++
.../docs/clang-tidy/checks/list.rst | 1 +
.../llvm/avoid-passing-mlir-op-as-ref.rst | 21
.../llvm/avoid-passing-mlir-op-as-ref.cpp | 33
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 4 +-
.../SCF/Transforms/ParallelLoopFusion.cpp | 2 +-
mlir/unittests/TableGen/OpBuildGen.cpp| 2 +-
11 files changed, 150 insertions(+), 4 deletions(-)
create mode 100644
clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
create mode 100644
clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
create mode 100644
clang-tools-extra/docs/clang-tidy/checks/llvm/avoid-passing-mlir-op-as-ref.rst
create mode 100644
clang-tools-extra/test/clang-tidy/checkers/llvm/avoid-passing-mlir-op-as-ref.cpp
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
new file mode 100644
index 0..dc8d14632582a
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.cpp
@@ -0,0 +1,51 @@
+//===--- AvoidPassingMlirOpAsRefCheck.cpp - clang-tidy
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AvoidPassingMlirOpAsRefCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::llvm_check {
+
+void AvoidPassingMlirOpAsRefCheck::registerMatchers(MatchFinder *Finder) {
+ // Match parameters that are references to classes derived from mlir::Op.
+ Finder->addMatcher(
+ parmVarDecl(
+ hasType(qualType(
+ references(qualType(hasDeclaration(
+ cxxRecordDecl(isSameOrDerivedFrom("::mlir::Op"))
+ .bind("op_type",
+ // We want to avoid matching `Op *&` (reference to pointer to Op)
+ // which is not common for Op but possible.
+ unless(references(pointerType(),
+ unless(isImplicit()),
+ unless(hasAncestor(cxxConstructorDecl(
+ anyOf(isCopyConstructor(), isMoveConstructor(),
+ unless(hasAncestor(cxxMethodDecl(isCopyAssignmentOperator(,
+ unless(hasAncestor(cxxMethodDecl(isMoveAssignmentOperator(,
+ decl().bind("param")),
+ this);
+}
+
+void AvoidPassingMlirOpAsRefCheck::check(
+const MatchFinder::MatchResult &Result) {
+ const auto *Param = Result.Nodes.getNodeAs("param");
+ const auto *OpType = Result.Nodes.getNodeAs("op_type");
+
+ // Exclude if we can't find definitions.
+ if (!Param || !OpType)
+return;
+
+ diag(Param->getLocation(),
+ "MLIR Op class '%0' should be passed by value, not by reference")
+ << OpType->getName();
+}
+
+} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
new file mode 100644
index 0..ff9a1172f52d8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/AvoidPassingMlirOpAsRefCheck.h
@@ -0,0 +1,31 @@
+//===--- AvoidPassingMlirOpAsRefCheck.h - clang-tidy *- C++
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDPASSINGMLIROPASREFCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
