[clang-tools-extra] [mlir] [clang-tidy][mlir] Add check for passing value type by reference. (PR #179882)

2026-02-06 Thread Baranov Victor via cfe-commits

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)

2026-02-05 Thread Jacques Pienaar via cfe-commits

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)

2026-02-05 Thread via cfe-commits


@@ -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)

2026-02-05 Thread Jacques Pienaar via cfe-commits

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)

2026-02-05 Thread via cfe-commits

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)

2026-02-05 Thread via cfe-commits

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)

2026-02-05 Thread via cfe-commits

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)

2026-02-05 Thread via cfe-commits

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)

2026-02-05 Thread via cfe-commits

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)

2026-02-05 Thread via cfe-commits

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)

2026-02-05 Thread Jacques Pienaar via cfe-commits

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 {
+