[clang-tools-extra] [clang-tidy] Add MLIR check for old op builder usage. (PR #149148)
Jacques Pienaar via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 24 06:10:28 PDT 2025
https://github.com/jpienaar updated https://github.com/llvm/llvm-project/pull/149148
>From b404f5390ac5684c7452e69f6fe209e5215f8929 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jpienaar at google.com>
Date: Wed, 16 Jul 2025 17:37:53 +0000
Subject: [PATCH 01/14] [clang-tidy] Add MLIR check for old op builder usage.
Moving towards new create method invocation, add check to flag old usage.
---
clang-tools-extra/clang-tidy/CMakeLists.txt | 2 +
.../clang-tidy/ClangTidyForceLinker.h | 5 +
.../clang-tidy/mlir/CMakeLists.txt | 28 +++++
.../clang-tidy/mlir/MLIRTidyModule.cpp | 39 +++++++
.../clang-tidy/mlir/OpBuilderCheck.cpp | 102 ++++++++++++++++++
.../clang-tidy/mlir/OpBuilderCheck.h | 21 ++++
clang-tools-extra/docs/ReleaseNotes.rst | 5 +
.../docs/clang-tidy/checks/list.rst | 2 +
.../clang-tidy/checks/mlir/op-builder.rst | 22 ++++
.../clang-tidy/checkers/mlir/op_builder.cpp | 51 +++++++++
10 files changed, 277 insertions(+)
create mode 100644 clang-tools-extra/clang-tidy/mlir/CMakeLists.txt
create mode 100644 clang-tools-extra/clang-tidy/mlir/MLIRTidyModule.cpp
create mode 100644 clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/mlir/op-builder.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/mlir/op_builder.cpp
diff --git a/clang-tools-extra/clang-tidy/CMakeLists.txt b/clang-tools-extra/clang-tidy/CMakeLists.txt
index 93117cf1d6373..b89003bf6c926 100644
--- a/clang-tools-extra/clang-tidy/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/CMakeLists.txt
@@ -66,6 +66,7 @@ add_subdirectory(linuxkernel)
add_subdirectory(llvm)
add_subdirectory(llvmlibc)
add_subdirectory(misc)
+add_subdirectory(mlir)
add_subdirectory(modernize)
if(CLANG_TIDY_ENABLE_STATIC_ANALYZER)
add_subdirectory(mpi)
@@ -93,6 +94,7 @@ set(ALL_CLANG_TIDY_CHECKS
clangTidyLLVMModule
clangTidyLLVMLibcModule
clangTidyMiscModule
+ clangTidyMLIRModule
clangTidyModernizeModule
clangTidyObjCModule
clangTidyOpenMPModule
diff --git a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
index adde9136ff1dd..3cde93124c6e4 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
@@ -94,6 +94,11 @@ extern volatile int MiscModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination =
MiscModuleAnchorSource;
+// This anchor is used to force the linker to link the MLIRModule.
+extern volatile int MLIRModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED MLIRModuleAnchorDestination =
+ MLIRModuleAnchorSource;
+
// This anchor is used to force the linker to link the ModernizeModule.
extern volatile int ModernizeModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
diff --git a/clang-tools-extra/clang-tidy/mlir/CMakeLists.txt b/clang-tools-extra/clang-tidy/mlir/CMakeLists.txt
new file mode 100644
index 0000000000000..7d0b2de1df24c
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/mlir/CMakeLists.txt
@@ -0,0 +1,28 @@
+set(LLVM_LINK_COMPONENTS
+ FrontendOpenMP
+ Support
+ )
+
+add_clang_library(clangTidyMLIRModule STATIC
+ MLIRTidyModule.cpp
+ OpBuilderCheck.cpp
+
+ LINK_LIBS
+ clangTidy
+ clangTidyReadabilityModule
+ clangTidyUtils
+ clangTransformer
+
+ DEPENDS
+ omp_gen
+ ClangDriverOptions
+ )
+
+clang_target_link_libraries(clangTidyMLIRModule
+ PRIVATE
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangLex
+ clangTooling
+ )
diff --git a/clang-tools-extra/clang-tidy/mlir/MLIRTidyModule.cpp b/clang-tools-extra/clang-tidy/mlir/MLIRTidyModule.cpp
new file mode 100644
index 0000000000000..f542020a0afdd
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/mlir/MLIRTidyModule.cpp
@@ -0,0 +1,39 @@
+//===--- MLIRTidyModule.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 "../ClangTidy.h"
+#include "../ClangTidyModule.h"
+#include "../ClangTidyModuleRegistry.h"
+#include "OpBuilderCheck.h"
+
+namespace clang::tidy {
+namespace mlir_check {
+
+class MLIRModule : public ClangTidyModule {
+public:
+ void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<OpBuilderCheck>("mlir-op-builder");
+ }
+
+ ClangTidyOptions getModuleOptions() override {
+ ClangTidyOptions Options;
+ return Options;
+ }
+};
+
+// Register the ModuleModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<MLIRModule> X("mlir-module",
+ "Adds MLIR lint checks.");
+
+} // namespace mlir_check
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the MLIRModule.
+volatile int MLIRModuleAnchorSource = 0; // NOLINT(misc-use-internal-linkage)
+
+} // namespace clang::tidy
diff --git a/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.cpp
new file mode 100644
index 0000000000000..7521096d5b91d
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.cpp
@@ -0,0 +1,102 @@
+//===--- OpBuilderCheck.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 "OpBuilderCheck.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
+#include "clang/Tooling/Transformer/RewriteRule.h"
+#include "clang/Tooling/Transformer/SourceCode.h"
+#include "clang/Tooling/Transformer/Stencil.h"
+#include "llvm/Support/Error.h"
+
+namespace clang::tidy::mlir_check {
+namespace {
+
+using namespace ::clang::ast_matchers; // NOLINT: Too many names.
+using namespace ::clang::transformer; // NOLINT: Too many names.
+
+class TypeAsWrittenStencil : public StencilInterface {
+public:
+ explicit TypeAsWrittenStencil(std::string S) : id(std::move(S)) {}
+ std::string toString() const override {
+ return (llvm::Twine("TypeAsWritten(\"") + id + "\")").str();
+ }
+
+ llvm::Error eval(const MatchFinder::MatchResult &match,
+ std::string *result) const override {
+ auto n = node(id)(match);
+ if (!n)
+ return n.takeError();
+ auto srcRange = n->getAsRange();
+ if (srcRange.isInvalid()) {
+ return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
+ "srcRange is invalid");
+ }
+ auto range = n->getTokenRange(srcRange);
+ auto nextToken = [&](std::optional<Token> token) {
+ if (!token)
+ return token;
+ return clang::Lexer::findNextToken(token->getLocation(),
+ *match.SourceManager,
+ match.Context->getLangOpts());
+ };
+ auto lessToken = clang::Lexer::findNextToken(
+ range.getBegin(), *match.SourceManager, match.Context->getLangOpts());
+ while (lessToken && lessToken->getKind() != clang::tok::less) {
+ lessToken = nextToken(lessToken);
+ }
+ if (!lessToken) {
+ return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
+ "missing '<' token");
+ }
+ std::optional<Token> endToken = nextToken(lessToken);
+ for (auto greaterToken = nextToken(endToken);
+ greaterToken && greaterToken->getKind() != clang::tok::greater;
+ greaterToken = nextToken(greaterToken)) {
+ endToken = greaterToken;
+ }
+ if (!endToken) {
+ return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
+ "missing '>' token");
+ }
+ *result += clang::tooling::getText(
+ CharSourceRange::getTokenRange(lessToken->getEndLoc(),
+ endToken->getLastLoc()),
+ *match.Context);
+ return llvm::Error::success();
+ }
+ std::string id;
+};
+
+Stencil typeAsWritten(StringRef Id) {
+ // Using this instead of `describe` so that we get the exact same spelling.
+ return std::make_shared<TypeAsWrittenStencil>(std::string(Id));
+}
+
+RewriteRuleWith<std::string> OpBuilderCheckRule() {
+ return makeRule(
+ cxxMemberCallExpr(
+ on(expr(hasType(
+ cxxRecordDecl(isSameOrDerivedFrom("::mlir::OpBuilder"))))
+ .bind("builder")),
+ callee(cxxMethodDecl(hasTemplateArgument(0, templateArgument()))),
+ callee(cxxMethodDecl(hasName("create"))))
+ .bind("call"),
+ changeTo(cat(typeAsWritten("call"), "::create(", node("builder"), ", ",
+ callArgs("call"), ")")),
+ cat("Use OpType::create(builder, ...) instead of "
+ "builder.create<OpType>(...)"));
+}
+} // namespace
+
+OpBuilderCheck::OpBuilderCheck(StringRef Name, ClangTidyContext *Context)
+ : TransformerClangTidyCheck(OpBuilderCheckRule(), Name, Context) {}
+
+} // namespace clang::tidy::mlir_check
diff --git a/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.h b/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.h
new file mode 100644
index 0000000000000..792ac7b782add
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.h
@@ -0,0 +1,21 @@
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MLIR_OPBUILDERCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MLIR_OPBUILDERCHECK_H
+
+#include "../utils/TransformerClangTidyCheck.h"
+
+namespace clang::tidy::mlir_check {
+
+/// Checks for uses of `OpBuilder::create<T>` and suggests using `T::create`
+/// instead.
+class OpBuilderCheck : public utils::TransformerClangTidyCheck {
+public:
+ OpBuilderCheck(StringRef Name, ClangTidyContext *Context);
+
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return getLangOpts().CPlusPlus;
+ }
+};
+
+} // namespace clang::tidy::mlir_check
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MLIR_OPBUILDERCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 07ebf8008928d..09cb793533837 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -96,6 +96,11 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^
+- New :doc:`mlir-op-builder
+ <clang-tidy/checks/mlir/op-builder>` check.
+
+ Flags usage of old OpBuilder format.
+
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 0cffbd323caa2..49cd008e7588c 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -24,6 +24,7 @@ Clang-Tidy Checks
llvm/*
llvmlibc/*
misc/*
+ mlir/*
modernize/*
mpi/*
objc/*
@@ -279,6 +280,7 @@ Clang-Tidy Checks
:doc:`misc-unused-using-decls <misc/unused-using-decls>`, "Yes"
:doc:`misc-use-anonymous-namespace <misc/use-anonymous-namespace>`,
:doc:`misc-use-internal-linkage <misc/use-internal-linkage>`, "Yes"
+ :doc:`mlir-op-builder <mlir/op-builder>`, "Yes"
:doc:`modernize-avoid-bind <modernize/avoid-bind>`, "Yes"
:doc:`modernize-avoid-c-arrays <modernize/avoid-c-arrays>`,
:doc:`modernize-concat-nested-namespaces <modernize/concat-nested-namespaces>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/mlir/op-builder.rst b/clang-tools-extra/docs/clang-tidy/checks/mlir/op-builder.rst
new file mode 100644
index 0000000000000..30bae06a36836
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/mlir/op-builder.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - mlir-op-builder
+
+mlir-op-builder
+===============
+
+Flags usage of old form of invoking create on `OpBuilder` and suggesting new
+form.
+
+Example
+-------
+
+.. code-block:: c++
+
+ builder.create<FooOp>(builder.getUnknownLoc(), "baz");
+
+
+Transforms to:
+
+.. code-block:: c++
+
+ FooOp::create(builder, builder.getUnknownLoc(), "baz");
+
diff --git a/clang-tools-extra/test/clang-tidy/checkers/mlir/op_builder.cpp b/clang-tools-extra/test/clang-tidy/checkers/mlir/op_builder.cpp
new file mode 100644
index 0000000000000..bf60c665e86ad
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/mlir/op_builder.cpp
@@ -0,0 +1,51 @@
+// RUN: %check_clang_tidy --match-partial-fixes %s mlir-op-builder %t
+
+namespace mlir {
+class Location {};
+class OpBuilder {
+public:
+ template <typename OpTy, typename... Args>
+ OpTy create(Location location, Args &&...args) {
+ return OpTy(args...);
+ }
+ Location getUnknownLoc() { return Location(); }
+};
+class ImplicitLocOpBuilder : public OpBuilder {
+public:
+ template <typename OpTy, typename... Args>
+ OpTy create(Args &&...args) {
+ return OpTy(args...);
+ }
+};
+struct ModuleOp {
+ ModuleOp() {}
+ static ModuleOp create(OpBuilder &builder, Location location) {
+ return ModuleOp();
+ }
+};
+struct NamedOp {
+ NamedOp(const char* name) {}
+ static NamedOp create(OpBuilder &builder, Location location, const char* name) {
+ return NamedOp(name);
+ }
+};
+} // namespace mlir
+
+void f() {
+ mlir::OpBuilder builder;
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [mlir-op-builder]
+ // CHECK-FIXES: mlir:: ModuleOp::create(builder, builder.getUnknownLoc())
+ builder.create<mlir:: ModuleOp>(builder.getUnknownLoc());
+
+ using mlir::NamedOp;
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [mlir-op-builder]
+ // CHECK-FIXES: NamedOp::create(builder, builder.getUnknownLoc(), "baz")
+ builder.create<NamedOp>(builder.getUnknownLoc(), "baz");
+
+ mlir::ImplicitLocOpBuilder ib;
+ // Note: extra space in the case where there is no other arguments. Could be
+ // improved, but also clang-format will do that just post.
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [mlir-op-builder]
+ // CHECK-FIXES: mlir::ModuleOp::create(ib )
+ ib.create<mlir::ModuleOp>();
+}
>From 34b2a3a586ac6730b1f0e1f1f124a5f7d5d17ac2 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 17 Jul 2025 01:25:27 +0000
Subject: [PATCH 02/14] Move into LLVM module as this seems better spot given
lack of other planned rewrites & limited scope
---
clang-tools-extra/clang-tidy/CMakeLists.txt | 2 -
.../clang-tidy/ClangTidyForceLinker.h | 5 ---
.../clang-tidy/llvm/CMakeLists.txt | 2 +
.../clang-tidy/llvm/LLVMTidyModule.cpp | 2 +
.../MLIROpBuilderCheck.cpp} | 12 +++---
.../clang-tidy/llvm/MLIROpBuilderCheck.h | 21 ++++++++++
.../clang-tidy/mlir/CMakeLists.txt | 28 -------------
.../clang-tidy/mlir/MLIRTidyModule.cpp | 39 -------------------
.../clang-tidy/mlir/OpBuilderCheck.h | 21 ----------
clang-tools-extra/docs/ReleaseNotes.rst | 4 +-
.../docs/clang-tidy/checks/list.rst | 3 +-
.../mlir-op-builder.rst} | 8 ++--
.../mlir_op_builder.cpp} | 8 ++--
13 files changed, 42 insertions(+), 113 deletions(-)
rename clang-tools-extra/clang-tidy/{mlir/OpBuilderCheck.cpp => llvm/MLIROpBuilderCheck.cpp} (91%)
create mode 100644 clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
delete mode 100644 clang-tools-extra/clang-tidy/mlir/CMakeLists.txt
delete mode 100644 clang-tools-extra/clang-tidy/mlir/MLIRTidyModule.cpp
delete mode 100644 clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.h
rename clang-tools-extra/docs/clang-tidy/checks/{mlir/op-builder.rst => llvm/mlir-op-builder.rst} (57%)
rename clang-tools-extra/test/clang-tidy/checkers/{mlir/op_builder.cpp => llvm/mlir_op_builder.cpp} (83%)
diff --git a/clang-tools-extra/clang-tidy/CMakeLists.txt b/clang-tools-extra/clang-tidy/CMakeLists.txt
index b89003bf6c926..93117cf1d6373 100644
--- a/clang-tools-extra/clang-tidy/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/CMakeLists.txt
@@ -66,7 +66,6 @@ add_subdirectory(linuxkernel)
add_subdirectory(llvm)
add_subdirectory(llvmlibc)
add_subdirectory(misc)
-add_subdirectory(mlir)
add_subdirectory(modernize)
if(CLANG_TIDY_ENABLE_STATIC_ANALYZER)
add_subdirectory(mpi)
@@ -94,7 +93,6 @@ set(ALL_CLANG_TIDY_CHECKS
clangTidyLLVMModule
clangTidyLLVMLibcModule
clangTidyMiscModule
- clangTidyMLIRModule
clangTidyModernizeModule
clangTidyObjCModule
clangTidyOpenMPModule
diff --git a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
index 3cde93124c6e4..adde9136ff1dd 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
@@ -94,11 +94,6 @@ extern volatile int MiscModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination =
MiscModuleAnchorSource;
-// This anchor is used to force the linker to link the MLIRModule.
-extern volatile int MLIRModuleAnchorSource;
-static int LLVM_ATTRIBUTE_UNUSED MLIRModuleAnchorDestination =
- MLIRModuleAnchorSource;
-
// This anchor is used to force the linker to link the ModernizeModule.
extern volatile int ModernizeModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
diff --git a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
index 3232f6e2cafe5..70fc4b24cfed5 100644
--- a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
@@ -7,6 +7,7 @@ add_clang_library(clangTidyLLVMModule STATIC
HeaderGuardCheck.cpp
IncludeOrderCheck.cpp
LLVMTidyModule.cpp
+ MLIROpBuilderCheck.cpp
PreferIsaOrDynCastInConditionalsCheck.cpp
PreferRegisterOverUnsignedCheck.cpp
PreferStaticOverAnonymousNamespaceCheck.cpp
@@ -16,6 +17,7 @@ add_clang_library(clangTidyLLVMModule STATIC
clangTidy
clangTidyReadabilityModule
clangTidyUtils
+ clangTransformer
DEPENDS
omp_gen
diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
index 075453046f0a1..40c906a62b22d 100644
--- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -14,6 +14,7 @@
#include "../readability/QualifiedAutoCheck.h"
#include "HeaderGuardCheck.h"
#include "IncludeOrderCheck.h"
+#include "MLIROpBuilderCheck.h"
#include "PreferIsaOrDynCastInConditionalsCheck.h"
#include "PreferRegisterOverUnsignedCheck.h"
#include "PreferStaticOverAnonymousNamespaceCheck.h"
@@ -40,6 +41,7 @@ class LLVMModule : public ClangTidyModule {
CheckFactories.registerCheck<readability::QualifiedAutoCheck>(
"llvm-qualified-auto");
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
+ CheckFactories.registerCheck<MlirOpBuilderCheck>("llvm-mlir-op-builder");
}
ClangTidyOptions getModuleOptions() override {
diff --git a/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
similarity index 91%
rename from clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.cpp
rename to clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index 7521096d5b91d..126d4d3d649d7 100644
--- a/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -1,4 +1,4 @@
-//===--- OpBuilderCheck.cpp - clang-tidy ----------------------------------===//
+//===--- MLIROpBuilderCheck.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.
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "OpBuilderCheck.h"
+#include "MLIROpBuilderCheck.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/LLVM.h"
#include "clang/Lex/Lexer.h"
@@ -16,7 +16,7 @@
#include "clang/Tooling/Transformer/Stencil.h"
#include "llvm/Support/Error.h"
-namespace clang::tidy::mlir_check {
+namespace clang::tidy::llvm_check {
namespace {
using namespace ::clang::ast_matchers; // NOLINT: Too many names.
@@ -80,7 +80,7 @@ Stencil typeAsWritten(StringRef Id) {
return std::make_shared<TypeAsWrittenStencil>(std::string(Id));
}
-RewriteRuleWith<std::string> OpBuilderCheckRule() {
+RewriteRuleWith<std::string> MlirOpBuilderCheckRule() {
return makeRule(
cxxMemberCallExpr(
on(expr(hasType(
@@ -96,7 +96,7 @@ RewriteRuleWith<std::string> OpBuilderCheckRule() {
}
} // namespace
-OpBuilderCheck::OpBuilderCheck(StringRef Name, ClangTidyContext *Context)
- : TransformerClangTidyCheck(OpBuilderCheckRule(), Name, Context) {}
+MlirOpBuilderCheck::MlirOpBuilderCheck(StringRef Name, ClangTidyContext *Context)
+ : TransformerClangTidyCheck(MlirOpBuilderCheckRule(), Name, Context) {}
} // namespace clang::tidy::mlir_check
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
new file mode 100644
index 0000000000000..d0d356e0f2711
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
@@ -0,0 +1,21 @@
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_MLIROPBUILDERCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_MLIROPBUILDERCHECK_H
+
+#include "../utils/TransformerClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
+/// Checks for uses of MLIR's `OpBuilder::create<T>` and suggests using
+/// `T::create` instead.
+class MlirOpBuilderCheck : public utils::TransformerClangTidyCheck {
+public:
+ MlirOpBuilderCheck(StringRef Name, ClangTidyContext *Context);
+
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return getLangOpts().CPlusPlus;
+ }
+};
+
+} // namespace clang::tidy::llvm_check
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_MLIROPBUILDERCHECK_H
diff --git a/clang-tools-extra/clang-tidy/mlir/CMakeLists.txt b/clang-tools-extra/clang-tidy/mlir/CMakeLists.txt
deleted file mode 100644
index 7d0b2de1df24c..0000000000000
--- a/clang-tools-extra/clang-tidy/mlir/CMakeLists.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- FrontendOpenMP
- Support
- )
-
-add_clang_library(clangTidyMLIRModule STATIC
- MLIRTidyModule.cpp
- OpBuilderCheck.cpp
-
- LINK_LIBS
- clangTidy
- clangTidyReadabilityModule
- clangTidyUtils
- clangTransformer
-
- DEPENDS
- omp_gen
- ClangDriverOptions
- )
-
-clang_target_link_libraries(clangTidyMLIRModule
- PRIVATE
- clangAST
- clangASTMatchers
- clangBasic
- clangLex
- clangTooling
- )
diff --git a/clang-tools-extra/clang-tidy/mlir/MLIRTidyModule.cpp b/clang-tools-extra/clang-tidy/mlir/MLIRTidyModule.cpp
deleted file mode 100644
index f542020a0afdd..0000000000000
--- a/clang-tools-extra/clang-tidy/mlir/MLIRTidyModule.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//===--- MLIRTidyModule.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 "../ClangTidy.h"
-#include "../ClangTidyModule.h"
-#include "../ClangTidyModuleRegistry.h"
-#include "OpBuilderCheck.h"
-
-namespace clang::tidy {
-namespace mlir_check {
-
-class MLIRModule : public ClangTidyModule {
-public:
- void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
- CheckFactories.registerCheck<OpBuilderCheck>("mlir-op-builder");
- }
-
- ClangTidyOptions getModuleOptions() override {
- ClangTidyOptions Options;
- return Options;
- }
-};
-
-// Register the ModuleModule using this statically initialized variable.
-static ClangTidyModuleRegistry::Add<MLIRModule> X("mlir-module",
- "Adds MLIR lint checks.");
-
-} // namespace mlir_check
-
-// This anchor is used to force the linker to link in the generated object file
-// and thus register the MLIRModule.
-volatile int MLIRModuleAnchorSource = 0; // NOLINT(misc-use-internal-linkage)
-
-} // namespace clang::tidy
diff --git a/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.h b/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.h
deleted file mode 100644
index 792ac7b782add..0000000000000
--- a/clang-tools-extra/clang-tidy/mlir/OpBuilderCheck.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MLIR_OPBUILDERCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MLIR_OPBUILDERCHECK_H
-
-#include "../utils/TransformerClangTidyCheck.h"
-
-namespace clang::tidy::mlir_check {
-
-/// Checks for uses of `OpBuilder::create<T>` and suggests using `T::create`
-/// instead.
-class OpBuilderCheck : public utils::TransformerClangTidyCheck {
-public:
- OpBuilderCheck(StringRef Name, ClangTidyContext *Context);
-
- bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
- return getLangOpts().CPlusPlus;
- }
-};
-
-} // namespace clang::tidy::mlir_check
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MLIR_OPBUILDERCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 09cb793533837..aeefcb1532772 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -96,8 +96,8 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^
-- New :doc:`mlir-op-builder
- <clang-tidy/checks/mlir/op-builder>` check.
+- New :doc:`llvm-mlir-op-builder
+ <clang-tidy/checks/llvm/mlir-op-builder>` check.
Flags usage of old OpBuilder format.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 49cd008e7588c..ea911c9363ef0 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -24,7 +24,6 @@ Clang-Tidy Checks
llvm/*
llvmlibc/*
misc/*
- mlir/*
modernize/*
mpi/*
objc/*
@@ -248,6 +247,7 @@ Clang-Tidy Checks
:doc:`linuxkernel-must-check-errs <linuxkernel/must-check-errs>`,
:doc:`llvm-header-guard <llvm/header-guard>`,
:doc:`llvm-include-order <llvm/include-order>`, "Yes"
+ :doc:`llvm-mlir-op-builder <llvm/mlir-op-builder>`, "Yes"
:doc:`llvm-namespace-comment <llvm/namespace-comment>`,
:doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm/prefer-isa-or-dyn-cast-in-conditionals>`, "Yes"
:doc:`llvm-prefer-register-over-unsigned <llvm/prefer-register-over-unsigned>`, "Yes"
@@ -280,7 +280,6 @@ Clang-Tidy Checks
:doc:`misc-unused-using-decls <misc/unused-using-decls>`, "Yes"
:doc:`misc-use-anonymous-namespace <misc/use-anonymous-namespace>`,
:doc:`misc-use-internal-linkage <misc/use-internal-linkage>`, "Yes"
- :doc:`mlir-op-builder <mlir/op-builder>`, "Yes"
:doc:`modernize-avoid-bind <modernize/avoid-bind>`, "Yes"
:doc:`modernize-avoid-c-arrays <modernize/avoid-c-arrays>`,
:doc:`modernize-concat-nested-namespaces <modernize/concat-nested-namespaces>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/mlir/op-builder.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
similarity index 57%
rename from clang-tools-extra/docs/clang-tidy/checks/mlir/op-builder.rst
rename to clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
index 30bae06a36836..1a4b88a7492ef 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/mlir/op-builder.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
@@ -1,10 +1,10 @@
-.. title:: clang-tidy - mlir-op-builder
+.. title:: clang-tidy - llvm-mlir-op-builder
-mlir-op-builder
+llvm-mlir-op-builder
===============
-Flags usage of old form of invoking create on `OpBuilder` and suggesting new
-form.
+Flags usage of old form of invoking create on MLIR's `OpBuilder` and suggesting
+new form.
Example
-------
diff --git a/clang-tools-extra/test/clang-tidy/checkers/mlir/op_builder.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/mlir_op_builder.cpp
similarity index 83%
rename from clang-tools-extra/test/clang-tidy/checkers/mlir/op_builder.cpp
rename to clang-tools-extra/test/clang-tidy/checkers/llvm/mlir_op_builder.cpp
index bf60c665e86ad..27e91a2be37e3 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/mlir/op_builder.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/mlir_op_builder.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy --match-partial-fixes %s mlir-op-builder %t
+// RUN: %check_clang_tidy --match-partial-fixes %s llvm-mlir-op-builder %t
namespace mlir {
class Location {};
@@ -33,19 +33,19 @@ struct NamedOp {
void f() {
mlir::OpBuilder builder;
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [mlir-op-builder]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-mlir-op-builder]
// CHECK-FIXES: mlir:: ModuleOp::create(builder, builder.getUnknownLoc())
builder.create<mlir:: ModuleOp>(builder.getUnknownLoc());
using mlir::NamedOp;
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [mlir-op-builder]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-mlir-op-builder]
// CHECK-FIXES: NamedOp::create(builder, builder.getUnknownLoc(), "baz")
builder.create<NamedOp>(builder.getUnknownLoc(), "baz");
mlir::ImplicitLocOpBuilder ib;
// Note: extra space in the case where there is no other arguments. Could be
// improved, but also clang-format will do that just post.
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [mlir-op-builder]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-mlir-op-builder]
// CHECK-FIXES: mlir::ModuleOp::create(ib )
ib.create<mlir::ModuleOp>();
}
>From dc85637888fc9aec62da37fd8c29d108ecb0a4a2 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 17 Jul 2025 01:25:51 +0000
Subject: [PATCH 03/14] Fix formatting
---
clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index 126d4d3d649d7..c17e319287da2 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -1,4 +1,5 @@
-//===--- MLIROpBuilderCheck.cpp - clang-tidy -------------------------------===//
+//===--- MLIROpBuilderCheck.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.
@@ -96,7 +97,8 @@ RewriteRuleWith<std::string> MlirOpBuilderCheckRule() {
}
} // namespace
-MlirOpBuilderCheck::MlirOpBuilderCheck(StringRef Name, ClangTidyContext *Context)
+MlirOpBuilderCheck::MlirOpBuilderCheck(StringRef Name,
+ ClangTidyContext *Context)
: TransformerClangTidyCheck(MlirOpBuilderCheckRule(), Name, Context) {}
-} // namespace clang::tidy::mlir_check
+} // namespace clang::tidy::llvm_check
>From a74232f829640a6796ce091a7da0a4b686f7a01d Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 17 Jul 2025 04:06:37 +0000
Subject: [PATCH 04/14] Address review comments
---
.../clang-tidy/llvm/MLIROpBuilderCheck.cpp | 13 ++++++-------
clang-tools-extra/docs/ReleaseNotes.rst | 3 ++-
.../docs/clang-tidy/checks/llvm/mlir-op-builder.rst | 5 ++---
3 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index c17e319287da2..12c115946f9ea 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -1,5 +1,4 @@
-//===--- MLIROpBuilderCheck.cpp - clang-tidy
-//-------------------------------===//
+//===--- MLIROpBuilderCheck.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.
@@ -32,15 +31,15 @@ class TypeAsWrittenStencil : public StencilInterface {
llvm::Error eval(const MatchFinder::MatchResult &match,
std::string *result) const override {
- auto n = node(id)(match);
+ RangeSelector n = node(id)(match);
if (!n)
return n.takeError();
- auto srcRange = n->getAsRange();
+ SourceRange srcRange = n->getAsRange();
if (srcRange.isInvalid()) {
return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
"srcRange is invalid");
}
- auto range = n->getTokenRange(srcRange);
+ const CharSourceRange range = n->getTokenRange(srcRange);
auto nextToken = [&](std::optional<Token> token) {
if (!token)
return token;
@@ -48,7 +47,7 @@ class TypeAsWrittenStencil : public StencilInterface {
*match.SourceManager,
match.Context->getLangOpts());
};
- auto lessToken = clang::Lexer::findNextToken(
+ std::optional<Token> lessToken = clang::Lexer::findNextToken(
range.getBegin(), *match.SourceManager, match.Context->getLangOpts());
while (lessToken && lessToken->getKind() != clang::tok::less) {
lessToken = nextToken(lessToken);
@@ -58,7 +57,7 @@ class TypeAsWrittenStencil : public StencilInterface {
"missing '<' token");
}
std::optional<Token> endToken = nextToken(lessToken);
- for (auto greaterToken = nextToken(endToken);
+ for (std::optional<Token> greaterToken = nextToken(endToken);
greaterToken && greaterToken->getKind() != clang::tok::greater;
greaterToken = nextToken(greaterToken)) {
endToken = greaterToken;
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index aeefcb1532772..e738570ac9b82 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -99,7 +99,8 @@ New checks
- New :doc:`llvm-mlir-op-builder
<clang-tidy/checks/llvm/mlir-op-builder>` check.
- Flags usage of old OpBuilder format.
+ Flags usage of old form of invoking create on MLIR's `OpBuilder` and suggests
+ new form.
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
index 1a4b88a7492ef..e45360d33b4fa 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
@@ -1,9 +1,9 @@
.. title:: clang-tidy - llvm-mlir-op-builder
llvm-mlir-op-builder
-===============
+====================
-Flags usage of old form of invoking create on MLIR's `OpBuilder` and suggesting
+Flags usage of old form of invoking create on MLIR's `OpBuilder` and suggests
new form.
Example
@@ -19,4 +19,3 @@ Transforms to:
.. code-block:: c++
FooOp::create(builder, builder.getUnknownLoc(), "baz");
-
>From 4fe574aaac7d7ce314fbac24e0f10a1f0014649c Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 17 Jul 2025 04:09:41 +0000
Subject: [PATCH 05/14] Address missed review comments
---
clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h | 8 ++++++++
clang-tools-extra/docs/ReleaseNotes.rst | 4 ++--
.../docs/clang-tidy/checks/llvm/mlir-op-builder.rst | 2 +-
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
index d0d356e0f2711..9dbbf239da50b 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
@@ -1,3 +1,11 @@
+//===--- MLIROpBuilderCheck.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_MLIROPBUILDERCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_MLIROPBUILDERCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index e738570ac9b82..5f8467c969cae 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -99,8 +99,8 @@ New checks
- New :doc:`llvm-mlir-op-builder
<clang-tidy/checks/llvm/mlir-op-builder>` check.
- Flags usage of old form of invoking create on MLIR's `OpBuilder` and suggests
- new form.
+ Flags usage of old form of invoking create on MLIR's ``OpBuilder`` and
+ suggests new form.
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
index e45360d33b4fa..7d45399842c2b 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
@@ -3,7 +3,7 @@
llvm-mlir-op-builder
====================
-Flags usage of old form of invoking create on MLIR's `OpBuilder` and suggests
+Flags usage of old form of invoking create on MLIR's ``OpBuilder`` and suggests
new form.
Example
>From a25b8aff022a0bab37b013bc8eb242571847ed82 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 17 Jul 2025 04:17:18 +0000
Subject: [PATCH 06/14] Fix wrong type
---
clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index 12c115946f9ea..7e63a19190fe4 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -31,7 +31,7 @@ class TypeAsWrittenStencil : public StencilInterface {
llvm::Error eval(const MatchFinder::MatchResult &match,
std::string *result) const override {
- RangeSelector n = node(id)(match);
+ llvm::Expected<CharSourceRange> n = node(id)(match);
if (!n)
return n.takeError();
SourceRange srcRange = n->getAsRange();
>From 9a86c0fbdafb02861341f2e04558f6cb0295afb6 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 17 Jul 2025 15:36:30 +0000
Subject: [PATCH 07/14] Address clang-tidy warnings except in
mlir_op_builder.cpp which is following MLIR coding conventions
---
.../clang-tidy/llvm/MLIROpBuilderCheck.cpp | 54 +++++++++----------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index 7e63a19190fe4..46c3b4f8a0cca 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -24,55 +24,55 @@ using namespace ::clang::transformer; // NOLINT: Too many names.
class TypeAsWrittenStencil : public StencilInterface {
public:
- explicit TypeAsWrittenStencil(std::string S) : id(std::move(S)) {}
+ explicit TypeAsWrittenStencil(std::string S) : Id(std::move(S)) {}
std::string toString() const override {
- return (llvm::Twine("TypeAsWritten(\"") + id + "\")").str();
+ return (llvm::Twine("TypeAsWritten(\"") + Id + "\")").str();
}
llvm::Error eval(const MatchFinder::MatchResult &match,
std::string *result) const override {
- llvm::Expected<CharSourceRange> n = node(id)(match);
+ llvm::Expected<CharSourceRange> n = node(Id)(match);
if (!n)
return n.takeError();
- SourceRange srcRange = n->getAsRange();
- if (srcRange.isInvalid()) {
+ const SourceRange SrcRange = n->getAsRange();
+ if (SrcRange.isInvalid()) {
return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
- "srcRange is invalid");
+ "SrcRange is invalid");
}
- const CharSourceRange range = n->getTokenRange(srcRange);
- auto nextToken = [&](std::optional<Token> token) {
- if (!token)
- return token;
- return clang::Lexer::findNextToken(token->getLocation(),
+ const CharSourceRange Range = n->getTokenRange(SrcRange);
+ auto NextToken = [&](std::optional<Token> Token) {
+ if (!Token)
+ return Token;
+ return clang::Lexer::findNextToken(Token->getLocation(),
*match.SourceManager,
match.Context->getLangOpts());
};
- std::optional<Token> lessToken = clang::Lexer::findNextToken(
- range.getBegin(), *match.SourceManager, match.Context->getLangOpts());
- while (lessToken && lessToken->getKind() != clang::tok::less) {
- lessToken = nextToken(lessToken);
+ std::optional<Token> LessToken = clang::Lexer::findNextToken(
+ Range.getBegin(), *match.SourceManager, match.Context->getLangOpts());
+ while (LessToken && LessToken->getKind() != clang::tok::less) {
+ LessToken = NextToken(LessToken);
}
- if (!lessToken) {
+ if (!LessToken) {
return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
"missing '<' token");
}
- std::optional<Token> endToken = nextToken(lessToken);
- for (std::optional<Token> greaterToken = nextToken(endToken);
- greaterToken && greaterToken->getKind() != clang::tok::greater;
- greaterToken = nextToken(greaterToken)) {
- endToken = greaterToken;
+ std::optional<Token> EndToken = NextToken(LessToken);
+ for (std::optional<Token> GreaterToken = NextToken(EndToken);
+ GreaterToken && GreaterToken->getKind() != clang::tok::greater;
+ GreaterToken = NextToken(GreaterToken)) {
+ EndToken = GreaterToken;
}
- if (!endToken) {
+ if (!EndToken) {
return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
"missing '>' token");
}
*result += clang::tooling::getText(
- CharSourceRange::getTokenRange(lessToken->getEndLoc(),
- endToken->getLastLoc()),
+ CharSourceRange::getTokenRange(LessToken->getEndLoc(),
+ EndToken->getLastLoc()),
*match.Context);
return llvm::Error::success();
}
- std::string id;
+ std::string Id;
};
Stencil typeAsWritten(StringRef Id) {
@@ -80,7 +80,7 @@ Stencil typeAsWritten(StringRef Id) {
return std::make_shared<TypeAsWrittenStencil>(std::string(Id));
}
-RewriteRuleWith<std::string> MlirOpBuilderCheckRule() {
+RewriteRuleWith<std::string> mlirOpBuilderCheckRule() {
return makeRule(
cxxMemberCallExpr(
on(expr(hasType(
@@ -98,6 +98,6 @@ RewriteRuleWith<std::string> MlirOpBuilderCheckRule() {
MlirOpBuilderCheck::MlirOpBuilderCheck(StringRef Name,
ClangTidyContext *Context)
- : TransformerClangTidyCheck(MlirOpBuilderCheckRule(), Name, Context) {}
+ : TransformerClangTidyCheck(mlirOpBuilderCheckRule(), Name, Context) {}
} // namespace clang::tidy::llvm_check
>From 46ca80b0bad62892ecde57c39ed5e089f3df662c Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Sat, 19 Jul 2025 23:55:34 -0700
Subject: [PATCH 08/14] Update
clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
Co-authored-by: Baranov Victor <bar.victor.2002 at gmail.com>
---
clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index 46c3b4f8a0cca..85b728c99e42e 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -91,8 +91,8 @@ RewriteRuleWith<std::string> mlirOpBuilderCheckRule() {
.bind("call"),
changeTo(cat(typeAsWritten("call"), "::create(", node("builder"), ", ",
callArgs("call"), ")")),
- cat("Use OpType::create(builder, ...) instead of "
- "builder.create<OpType>(...)"));
+ cat("use 'OpType::create(builder, ...)' instead of "
+ "'builder.create<OpType>(...)'"));
}
} // namespace
>From 01f5fbbc4929f676ccae479f87c2f34a6a25a3e6 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Sun, 20 Jul 2025 11:59:12 +0000
Subject: [PATCH 09/14] Renamings & extra tests
---
.../clang-tidy/llvm/LLVMTidyModule.cpp | 3 +-
.../clang-tidy/llvm/MLIROpBuilderCheck.cpp | 4 +-
.../clang-tidy/llvm/MLIROpBuilderCheck.h | 4 +-
clang-tools-extra/docs/ReleaseNotes.rst | 6 +-
.../docs/clang-tidy/checks/list.rst | 2 +-
...uilder.rst => use-new-mlir-op-builder.rst} | 4 +-
.../checkers/llvm/mlir_op_builder.cpp | 51 -------------
.../checkers/llvm/use-new-mlir-op-builder.cpp | 75 +++++++++++++++++++
8 files changed, 87 insertions(+), 62 deletions(-)
rename clang-tools-extra/docs/clang-tidy/checks/llvm/{mlir-op-builder.rst => use-new-mlir-op-builder.rst} (71%)
delete mode 100644 clang-tools-extra/test/clang-tidy/checkers/llvm/mlir_op_builder.cpp
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp
diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
index 40c906a62b22d..dea8b0b68fa8b 100644
--- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -30,6 +30,8 @@ class LLVMModule : public ClangTidyModule {
"llvm-else-after-return");
CheckFactories.registerCheck<LLVMHeaderGuardCheck>("llvm-header-guard");
CheckFactories.registerCheck<IncludeOrderCheck>("llvm-include-order");
+ CheckFactories.registerCheck<MlirOpBuilderCheck>(
+ "llvm-use-new-mlir-op-builder");
CheckFactories.registerCheck<readability::NamespaceCommentCheck>(
"llvm-namespace-comment");
CheckFactories.registerCheck<PreferIsaOrDynCastInConditionalsCheck>(
@@ -41,7 +43,6 @@ class LLVMModule : public ClangTidyModule {
CheckFactories.registerCheck<readability::QualifiedAutoCheck>(
"llvm-qualified-auto");
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
- CheckFactories.registerCheck<MlirOpBuilderCheck>("llvm-mlir-op-builder");
}
ClangTidyOptions getModuleOptions() override {
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index 85b728c99e42e..5f288f476ca27 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -19,8 +19,8 @@
namespace clang::tidy::llvm_check {
namespace {
-using namespace ::clang::ast_matchers; // NOLINT: Too many names.
-using namespace ::clang::transformer; // NOLINT: Too many names.
+using namespace ::clang::ast_matchers;
+using namespace ::clang::transformer;
class TypeAsWrittenStencil : public StencilInterface {
public:
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
index 9dbbf239da50b..edbe9b2873fa7 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
@@ -13,8 +13,8 @@
namespace clang::tidy::llvm_check {
-/// Checks for uses of MLIR's `OpBuilder::create<T>` and suggests using
-/// `T::create` instead.
+/// Checks for uses of MLIR's old/to be deprecated `OpBuilder::create<T>` form
+/// and suggests using `T::create` instead.
class MlirOpBuilderCheck : public utils::TransformerClangTidyCheck {
public:
MlirOpBuilderCheck(StringRef Name, ClangTidyContext *Context);
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 5f8467c969cae..41fb8059bc960 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -97,10 +97,10 @@ New checks
^^^^^^^^^^
- New :doc:`llvm-mlir-op-builder
- <clang-tidy/checks/llvm/mlir-op-builder>` check.
+ <clang-tidy/checks/llvm/use-new-mlir-op-builder>` check.
- Flags usage of old form of invoking create on MLIR's ``OpBuilder`` and
- suggests new form.
+ Checks for uses of MLIR's old/to be deprecated ``OpBuilder::create<T>`` form
+ and suggests using ``T::create`` instead.
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index ea911c9363ef0..20a43274f9788 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -247,7 +247,7 @@ Clang-Tidy Checks
:doc:`linuxkernel-must-check-errs <linuxkernel/must-check-errs>`,
:doc:`llvm-header-guard <llvm/header-guard>`,
:doc:`llvm-include-order <llvm/include-order>`, "Yes"
- :doc:`llvm-mlir-op-builder <llvm/mlir-op-builder>`, "Yes"
+ :doc:`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>`, "Yes"
:doc:`llvm-namespace-comment <llvm/namespace-comment>`,
:doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm/prefer-isa-or-dyn-cast-in-conditionals>`, "Yes"
:doc:`llvm-prefer-register-over-unsigned <llvm/prefer-register-over-unsigned>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst
similarity index 71%
rename from clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
rename to clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst
index 7d45399842c2b..4953b51d9be92 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/mlir-op-builder.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst
@@ -3,8 +3,8 @@
llvm-mlir-op-builder
====================
-Flags usage of old form of invoking create on MLIR's ``OpBuilder`` and suggests
-new form.
+Checks for uses of MLIR's old/to be deprecated `OpBuilder::create<T>` form
+and suggests using `T::create` instead.
Example
-------
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/mlir_op_builder.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/mlir_op_builder.cpp
deleted file mode 100644
index 27e91a2be37e3..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/llvm/mlir_op_builder.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// RUN: %check_clang_tidy --match-partial-fixes %s llvm-mlir-op-builder %t
-
-namespace mlir {
-class Location {};
-class OpBuilder {
-public:
- template <typename OpTy, typename... Args>
- OpTy create(Location location, Args &&...args) {
- return OpTy(args...);
- }
- Location getUnknownLoc() { return Location(); }
-};
-class ImplicitLocOpBuilder : public OpBuilder {
-public:
- template <typename OpTy, typename... Args>
- OpTy create(Args &&...args) {
- return OpTy(args...);
- }
-};
-struct ModuleOp {
- ModuleOp() {}
- static ModuleOp create(OpBuilder &builder, Location location) {
- return ModuleOp();
- }
-};
-struct NamedOp {
- NamedOp(const char* name) {}
- static NamedOp create(OpBuilder &builder, Location location, const char* name) {
- return NamedOp(name);
- }
-};
-} // namespace mlir
-
-void f() {
- mlir::OpBuilder builder;
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-mlir-op-builder]
- // CHECK-FIXES: mlir:: ModuleOp::create(builder, builder.getUnknownLoc())
- builder.create<mlir:: ModuleOp>(builder.getUnknownLoc());
-
- using mlir::NamedOp;
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-mlir-op-builder]
- // CHECK-FIXES: NamedOp::create(builder, builder.getUnknownLoc(), "baz")
- builder.create<NamedOp>(builder.getUnknownLoc(), "baz");
-
- mlir::ImplicitLocOpBuilder ib;
- // Note: extra space in the case where there is no other arguments. Could be
- // improved, but also clang-format will do that just post.
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: Use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-mlir-op-builder]
- // CHECK-FIXES: mlir::ModuleOp::create(ib )
- ib.create<mlir::ModuleOp>();
-}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp
new file mode 100644
index 0000000000000..6805bcd7d671e
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp
@@ -0,0 +1,75 @@
+// RUN: %check_clang_tidy --match-partial-fixes %s llvm-use-new-mlir-op-builder %t
+
+namespace mlir {
+class Location {};
+class OpBuilder {
+public:
+ template <typename OpTy, typename... Args>
+ OpTy create(Location location, Args &&...args) {
+ return OpTy(args...);
+ }
+ Location getUnknownLoc() { return Location(); }
+};
+class ImplicitLocOpBuilder : public OpBuilder {
+public:
+ template <typename OpTy, typename... Args>
+ OpTy create(Args &&...args) {
+ return OpTy(args...);
+ }
+};
+struct ModuleOp {
+ ModuleOp() {}
+ static ModuleOp create(OpBuilder &builder, Location location) {
+ return ModuleOp();
+ }
+};
+struct NamedOp {
+ NamedOp(const char* name) {}
+ static NamedOp create(OpBuilder &builder, Location location, const char* name) {
+ return NamedOp(name);
+ }
+};
+} // namespace mlir
+
+#define ASSIGN(A, B, C, D) A = B.create<C>(B.getUnknownLoc(), D)
+
+template <typename T>
+void g(mlir::OpBuilder &b) {
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: T::create(b, b.getUnknownLoc(), "gaz")
+ b.create<T>(b.getUnknownLoc(), "gaz");
+}
+
+void f() {
+ mlir::OpBuilder builder;
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: mlir:: ModuleOp::create(builder, builder.getUnknownLoc())
+ builder.create<mlir:: ModuleOp>(builder.getUnknownLoc());
+
+ using mlir::NamedOp;
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: NamedOp::create(builder, builder.getUnknownLoc(), "baz")
+ builder.create<NamedOp>(builder.getUnknownLoc(), "baz");
+
+ // CHECK-MESSAGES: :[[@LINE+4]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: NamedOp::create(builder,
+ // CHECK-FIXES: builder.getUnknownLoc(),
+ // CHECK-FIXES: "caz")
+ builder.
+ create<NamedOp>(
+ builder.getUnknownLoc(),
+ "caz");
+
+ NamedOp op("unused");
+ // FIXME: This is matching, but the changeTo not called.
+ ASSIGN(op, builder, NamedOp, "daz");
+
+ g<NamedOp>(builder);
+
+ mlir::ImplicitLocOpBuilder ib;
+ // Note: extra space in the case where there is no other arguments. Could be
+ // improved, but also clang-format will do that just post.
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: mlir::ModuleOp::create(ib )
+ ib.create<mlir::ModuleOp>();
+}
>From 4d104f48c76292d6f9f5c02e3744a86ffe1208ea Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 24 Jul 2025 10:11:58 +0200
Subject: [PATCH 10/14] Update
clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
.../docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst
index 4953b51d9be92..bb7427d4a4fbc 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst
@@ -3,8 +3,8 @@
llvm-mlir-op-builder
====================
-Checks for uses of MLIR's old/to be deprecated `OpBuilder::create<T>` form
-and suggests using `T::create` instead.
+Checks for uses of MLIR's old/to be deprecated ``OpBuilder::create<T>`` form
+and suggests using ``T::create`` instead.
Example
-------
>From e4f78d0dd28f73d9dbd29431373865c70332846b Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 24 Jul 2025 08:13:47 +0000
Subject: [PATCH 11/14] Switch to EditGenerator so that macros are at least
warned about
---
.../clang-tidy/llvm/MLIROpBuilderCheck.cpp | 96 ++++++++++++-------
.../checkers/llvm/use-new-mlir-op-builder.cpp | 21 ++--
2 files changed, 68 insertions(+), 49 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index 5f288f476ca27..7ffd7036e397a 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -22,33 +22,40 @@ namespace {
using namespace ::clang::ast_matchers;
using namespace ::clang::transformer;
-class TypeAsWrittenStencil : public StencilInterface {
-public:
- explicit TypeAsWrittenStencil(std::string S) : Id(std::move(S)) {}
- std::string toString() const override {
- return (llvm::Twine("TypeAsWritten(\"") + Id + "\")").str();
- }
+EditGenerator rewrite(RangeSelector Call, RangeSelector Builder,
+ RangeSelector CallArgs) {
+ return [Call = std::move(Call), Builder = std::move(Builder),
+ CallArgs =
+ std::move(CallArgs)](const MatchFinder::MatchResult &Result)
+ -> Expected<SmallVector<transformer::Edit, 1>> {
+ Expected<CharSourceRange> CallRange = Call(Result);
+ if (!CallRange)
+ return CallRange.takeError();
+ SourceManager &SM = *Result.SourceManager;
+ const LangOptions &LangOpts = Result.Context->getLangOpts();
- llvm::Error eval(const MatchFinder::MatchResult &match,
- std::string *result) const override {
- llvm::Expected<CharSourceRange> n = node(Id)(match);
- if (!n)
- return n.takeError();
- const SourceRange SrcRange = n->getAsRange();
- if (SrcRange.isInvalid()) {
- return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
- "SrcRange is invalid");
+ // This will result in just a warning and no edit.
+ SourceLocation Begin = CallRange->getBegin();
+ bool InMacro = CallRange->getBegin().isMacroID();
+ if (InMacro) {
+ while (SM.isMacroArgExpansion(Begin))
+ Begin = SM.getImmediateExpansionRange(Begin).getBegin();
+ Edit WarnOnly;
+ WarnOnly.Kind = EditKind::Range;
+ WarnOnly.Range = CharSourceRange::getCharRange(Begin, Begin);
+ return SmallVector<Edit, 1>({WarnOnly});
}
- const CharSourceRange Range = n->getTokenRange(SrcRange);
- auto NextToken = [&](std::optional<Token> Token) {
- if (!Token)
- return Token;
- return clang::Lexer::findNextToken(Token->getLocation(),
- *match.SourceManager,
- match.Context->getLangOpts());
+
+ auto NextToken = [&](std::optional<Token> CurrentToken) {
+ if (!CurrentToken)
+ return CurrentToken;
+ if (CurrentToken->getEndLoc() >= CallRange->getEnd())
+ return std::optional<Token>();
+ return clang::Lexer::findNextToken(CurrentToken->getLocation(), SM,
+ LangOpts);
};
- std::optional<Token> LessToken = clang::Lexer::findNextToken(
- Range.getBegin(), *match.SourceManager, match.Context->getLangOpts());
+ std::optional<Token> LessToken =
+ clang::Lexer::findNextToken(Begin, SM, LangOpts);
while (LessToken && LessToken->getKind() != clang::tok::less) {
LessToken = NextToken(LessToken);
}
@@ -66,18 +73,34 @@ class TypeAsWrittenStencil : public StencilInterface {
return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
"missing '>' token");
}
- *result += clang::tooling::getText(
- CharSourceRange::getTokenRange(LessToken->getEndLoc(),
- EndToken->getLastLoc()),
- *match.Context);
- return llvm::Error::success();
- }
- std::string Id;
-};
-Stencil typeAsWritten(StringRef Id) {
- // Using this instead of `describe` so that we get the exact same spelling.
- return std::make_shared<TypeAsWrittenStencil>(std::string(Id));
+ auto GetText = [&](const CharSourceRange &Range) {
+ return clang::Lexer::getSourceText(Range, SM, LangOpts);
+ };
+ Expected<CharSourceRange> BuilderRange = Builder(Result);
+ if (!BuilderRange)
+ return BuilderRange.takeError();
+ Expected<CharSourceRange> CallArgsRange = CallArgs(Result);
+ if (!CallArgsRange)
+ return CallArgsRange.takeError();
+
+ Edit Replace;
+ Replace.Kind = EditKind::Range;
+ Replace.Range = *CallRange;
+ Replace.Replacement = GetText(CharSourceRange::getTokenRange(
+ LessToken->getEndLoc(), EndToken->getLastLoc()));
+ Replace.Replacement += "::create(";
+ Replace.Replacement += GetText(*BuilderRange);
+ // Only emit args if there are any.
+ if (auto CallArgsText = GetText(*CallArgsRange).ltrim();
+ !CallArgsText.rtrim().empty()) {
+ Replace.Replacement += ", ";
+ Replace.Replacement += CallArgsText;
+ }
+ Replace.Replacement += ")";
+
+ return SmallVector<Edit, 1>({Replace});
+ };
}
RewriteRuleWith<std::string> mlirOpBuilderCheckRule() {
@@ -89,8 +112,7 @@ RewriteRuleWith<std::string> mlirOpBuilderCheckRule() {
callee(cxxMethodDecl(hasTemplateArgument(0, templateArgument()))),
callee(cxxMethodDecl(hasName("create"))))
.bind("call"),
- changeTo(cat(typeAsWritten("call"), "::create(", node("builder"), ", ",
- callArgs("call"), ")")),
+ rewrite(node("call"), node("builder"), callArgs("call")),
cat("use 'OpType::create(builder, ...)' instead of "
"'builder.create<OpType>(...)'"));
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp
index 6805bcd7d671e..57e026c10bf53 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp
@@ -31,27 +31,27 @@ struct NamedOp {
};
} // namespace mlir
-#define ASSIGN(A, B, C, D) A = B.create<C>(B.getUnknownLoc(), D)
+#define ASSIGN(A, B, C, D) C A = B.create<C>(B.getUnknownLoc(), D)
template <typename T>
void g(mlir::OpBuilder &b) {
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
// CHECK-FIXES: T::create(b, b.getUnknownLoc(), "gaz")
b.create<T>(b.getUnknownLoc(), "gaz");
}
void f() {
mlir::OpBuilder builder;
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
// CHECK-FIXES: mlir:: ModuleOp::create(builder, builder.getUnknownLoc())
builder.create<mlir:: ModuleOp>(builder.getUnknownLoc());
using mlir::NamedOp;
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
// CHECK-FIXES: NamedOp::create(builder, builder.getUnknownLoc(), "baz")
builder.create<NamedOp>(builder.getUnknownLoc(), "baz");
- // CHECK-MESSAGES: :[[@LINE+4]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
+ // CHECK-MESSAGES: :[[@LINE+4]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
// CHECK-FIXES: NamedOp::create(builder,
// CHECK-FIXES: builder.getUnknownLoc(),
// CHECK-FIXES: "caz")
@@ -60,16 +60,13 @@ void f() {
builder.getUnknownLoc(),
"caz");
- NamedOp op("unused");
- // FIXME: This is matching, but the changeTo not called.
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
ASSIGN(op, builder, NamedOp, "daz");
g<NamedOp>(builder);
mlir::ImplicitLocOpBuilder ib;
- // Note: extra space in the case where there is no other arguments. Could be
- // improved, but also clang-format will do that just post.
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use OpType::create(builder, ...) instead of builder.create<OpType>(...) [llvm-use-new-mlir-op-builder]
- // CHECK-FIXES: mlir::ModuleOp::create(ib )
- ib.create<mlir::ModuleOp>();
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: mlir::ModuleOp::create(ib)
+ ib.create<mlir::ModuleOp>( );
}
>From 9e3f97356d8b033f8dc843585bb3bf0fe3f71d9e Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 24 Jul 2025 08:22:57 +0000
Subject: [PATCH 12/14] Use formatv to make easier to see concat
---
.../clang-tidy/llvm/MLIROpBuilderCheck.cpp | 29 ++++++++++++-------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index 7ffd7036e397a..82763bcf2e9f8 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -15,6 +15,7 @@
#include "clang/Tooling/Transformer/SourceCode.h"
#include "clang/Tooling/Transformer/Stencil.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
namespace clang::tidy::llvm_check {
namespace {
@@ -24,6 +25,8 @@ using namespace ::clang::transformer;
EditGenerator rewrite(RangeSelector Call, RangeSelector Builder,
RangeSelector CallArgs) {
+ // This is using an EditGenerator rather than ASTEdit as we want to warn even
+ // if in macro.
return [Call = std::move(Call), Builder = std::move(Builder),
CallArgs =
std::move(CallArgs)](const MatchFinder::MatchResult &Result)
@@ -33,9 +36,9 @@ EditGenerator rewrite(RangeSelector Call, RangeSelector Builder,
return CallRange.takeError();
SourceManager &SM = *Result.SourceManager;
const LangOptions &LangOpts = Result.Context->getLangOpts();
+ SourceLocation Begin = CallRange->getBegin();
// This will result in just a warning and no edit.
- SourceLocation Begin = CallRange->getBegin();
bool InMacro = CallRange->getBegin().isMacroID();
if (InMacro) {
while (SM.isMacroArgExpansion(Begin))
@@ -46,6 +49,8 @@ EditGenerator rewrite(RangeSelector Call, RangeSelector Builder,
return SmallVector<Edit, 1>({WarnOnly});
}
+ // This will try to extract the template argument as written so that the
+ // rewritten code looks closest to original.
auto NextToken = [&](std::optional<Token> CurrentToken) {
if (!CurrentToken)
return CurrentToken;
@@ -74,9 +79,6 @@ EditGenerator rewrite(RangeSelector Call, RangeSelector Builder,
"missing '>' token");
}
- auto GetText = [&](const CharSourceRange &Range) {
- return clang::Lexer::getSourceText(Range, SM, LangOpts);
- };
Expected<CharSourceRange> BuilderRange = Builder(Result);
if (!BuilderRange)
return BuilderRange.takeError();
@@ -84,20 +86,25 @@ EditGenerator rewrite(RangeSelector Call, RangeSelector Builder,
if (!CallArgsRange)
return CallArgsRange.takeError();
+ // Helper for concatting below.
+ auto GetText = [&](const CharSourceRange &Range) {
+ return clang::Lexer::getSourceText(Range, SM, LangOpts);
+ };
+
Edit Replace;
Replace.Kind = EditKind::Range;
Replace.Range = *CallRange;
- Replace.Replacement = GetText(CharSourceRange::getTokenRange(
- LessToken->getEndLoc(), EndToken->getLastLoc()));
- Replace.Replacement += "::create(";
- Replace.Replacement += GetText(*BuilderRange);
+ std::string CallArgsStr;
// Only emit args if there are any.
if (auto CallArgsText = GetText(*CallArgsRange).ltrim();
!CallArgsText.rtrim().empty()) {
- Replace.Replacement += ", ";
- Replace.Replacement += CallArgsText;
+ CallArgsStr = llvm::formatv(", {}", CallArgsText);
}
- Replace.Replacement += ")";
+ Replace.Replacement =
+ llvm::formatv("{}::create({}{})",
+ GetText(CharSourceRange::getTokenRange(
+ LessToken->getEndLoc(), EndToken->getLastLoc())),
+ GetText(*BuilderRange), CallArgsStr);
return SmallVector<Edit, 1>({Replace});
};
>From de7c822b95c3eb7b2364bac894f91670ee39e3d2 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 24 Jul 2025 14:55:02 +0200
Subject: [PATCH 13/14] Update
clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
Co-authored-by: Baranov Victor <bar.victor.2002 at gmail.com>
---
clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
index 82763bcf2e9f8..6d740e4b0ec61 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
@@ -1,4 +1,4 @@
-//===--- MLIROpBuilderCheck.cpp - clang-tidy ------------------------------===//
+//===--- UseNewMLIROpBuilderCheck.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.
>From cd50bdb2776ee1d9eada1b4579f4c0dbb6d50467 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 24 Jul 2025 13:01:36 +0000
Subject: [PATCH 14/14] Update to UseNewMLIROpBuilderCheck more uniformly
---
clang-tools-extra/clang-tidy/llvm/CMakeLists.txt | 2 +-
clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp | 6 +++---
...BuilderCheck.cpp => UseNewMLIROpBuilderCheck.cpp} | 11 ++++++-----
...IROpBuilderCheck.h => UseNewMLIROpBuilderCheck.h} | 12 ++++++------
4 files changed, 16 insertions(+), 15 deletions(-)
rename clang-tools-extra/clang-tidy/llvm/{MLIROpBuilderCheck.cpp => UseNewMLIROpBuilderCheck.cpp} (93%)
rename clang-tools-extra/clang-tidy/llvm/{MLIROpBuilderCheck.h => UseNewMLIROpBuilderCheck.h} (61%)
diff --git a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
index 70fc4b24cfed5..4f1da43d3f1b7 100644
--- a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
@@ -7,11 +7,11 @@ add_clang_library(clangTidyLLVMModule STATIC
HeaderGuardCheck.cpp
IncludeOrderCheck.cpp
LLVMTidyModule.cpp
- MLIROpBuilderCheck.cpp
PreferIsaOrDynCastInConditionalsCheck.cpp
PreferRegisterOverUnsignedCheck.cpp
PreferStaticOverAnonymousNamespaceCheck.cpp
TwineLocalCheck.cpp
+ UseNewMLIROpBuilderCheck.cpp
LINK_LIBS
clangTidy
diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
index dea8b0b68fa8b..c7c61fd1649cc 100644
--- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -14,11 +14,11 @@
#include "../readability/QualifiedAutoCheck.h"
#include "HeaderGuardCheck.h"
#include "IncludeOrderCheck.h"
-#include "MLIROpBuilderCheck.h"
#include "PreferIsaOrDynCastInConditionalsCheck.h"
#include "PreferRegisterOverUnsignedCheck.h"
#include "PreferStaticOverAnonymousNamespaceCheck.h"
#include "TwineLocalCheck.h"
+#include "UseNewMLIROpBuilderCheck.h"
namespace clang::tidy {
namespace llvm_check {
@@ -30,8 +30,6 @@ class LLVMModule : public ClangTidyModule {
"llvm-else-after-return");
CheckFactories.registerCheck<LLVMHeaderGuardCheck>("llvm-header-guard");
CheckFactories.registerCheck<IncludeOrderCheck>("llvm-include-order");
- CheckFactories.registerCheck<MlirOpBuilderCheck>(
- "llvm-use-new-mlir-op-builder");
CheckFactories.registerCheck<readability::NamespaceCommentCheck>(
"llvm-namespace-comment");
CheckFactories.registerCheck<PreferIsaOrDynCastInConditionalsCheck>(
@@ -43,6 +41,8 @@ class LLVMModule : public ClangTidyModule {
CheckFactories.registerCheck<readability::QualifiedAutoCheck>(
"llvm-qualified-auto");
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
+ CheckFactories.registerCheck<UseNewMlirOpBuilderCheck>(
+ "llvm-use-new-mlir-op-builder");
}
ClangTidyOptions getModuleOptions() override {
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp
similarity index 93%
rename from clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
rename to clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp
index 6d740e4b0ec61..0b28ea2508977 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "MLIROpBuilderCheck.h"
+#include "UseNewMLIROpBuilderCheck.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/LLVM.h"
#include "clang/Lex/Lexer.h"
@@ -110,7 +110,7 @@ EditGenerator rewrite(RangeSelector Call, RangeSelector Builder,
};
}
-RewriteRuleWith<std::string> mlirOpBuilderCheckRule() {
+RewriteRuleWith<std::string> useNewMlirOpBuilderCheckRule() {
return makeRule(
cxxMemberCallExpr(
on(expr(hasType(
@@ -125,8 +125,9 @@ RewriteRuleWith<std::string> mlirOpBuilderCheckRule() {
}
} // namespace
-MlirOpBuilderCheck::MlirOpBuilderCheck(StringRef Name,
- ClangTidyContext *Context)
- : TransformerClangTidyCheck(mlirOpBuilderCheckRule(), Name, Context) {}
+UseNewMlirOpBuilderCheck::UseNewMlirOpBuilderCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : TransformerClangTidyCheck(useNewMlirOpBuilderCheckRule(), Name, Context) {
+}
} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.h
similarity index 61%
rename from clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
rename to clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.h
index edbe9b2873fa7..813a23c564782 100644
--- a/clang-tools-extra/clang-tidy/llvm/MLIROpBuilderCheck.h
+++ b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.h
@@ -1,4 +1,4 @@
-//===--- MLIROpBuilderCheck.h - clang-tidy ----------------------*- C++ -*-===//
+//===--- UseNewMLIROpBuilderCheck.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.
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_MLIROPBUILDERCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_MLIROPBUILDERCHECK_H
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USENEWMLIROPBUILDERCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USENEWMLIROPBUILDERCHECK_H
#include "../utils/TransformerClangTidyCheck.h"
@@ -15,9 +15,9 @@ namespace clang::tidy::llvm_check {
/// Checks for uses of MLIR's old/to be deprecated `OpBuilder::create<T>` form
/// and suggests using `T::create` instead.
-class MlirOpBuilderCheck : public utils::TransformerClangTidyCheck {
+class UseNewMlirOpBuilderCheck : public utils::TransformerClangTidyCheck {
public:
- MlirOpBuilderCheck(StringRef Name, ClangTidyContext *Context);
+ UseNewMlirOpBuilderCheck(StringRef Name, ClangTidyContext *Context);
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return getLangOpts().CPlusPlus;
@@ -26,4 +26,4 @@ class MlirOpBuilderCheck : public utils::TransformerClangTidyCheck {
} // namespace clang::tidy::llvm_check
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_MLIROPBUILDERCHECK_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USENEWMLIROPBUILDERCHECK_H
More information about the cfe-commits
mailing list