[clang-tools-extra] [clang-tidy] Add MLIR check for old op builder usage. (PR #149148)
Baranov Victor via cfe-commits
cfe-commits at lists.llvm.org
Sat Jul 19 14:37:03 PDT 2025
================
@@ -0,0 +1,103 @@
+//===--- 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MLIROpBuilderCheck.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::llvm_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 {
+ 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");
+ }
+ 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);
+ }
+ 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;
+ }
+ 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> mlirOpBuilderCheckRule() {
+ 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>(...)"));
----------------
vbvictor wrote:
```suggestion
cat("use 'OpType::create(builder, ...)' instead of "
"'builder.create<OpType>(...)'"));
```
https://github.com/llvm/llvm-project/pull/149148
More information about the cfe-commits
mailing list