Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[clang-tidy] Add MLIR check for old op builder usage.#149148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
jpienaar wants to merge9 commits intollvm:main
base:main
Choose a base branch
Loading
fromjpienaar:clangtidy-mlir
Open
Show file tree
Hide file tree
Changes from1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
NextNext commit
[clang-tidy] Add MLIR check for old op builder usage.
Moving towards new create method invocation, add check to flag old usage.
  • Loading branch information
@jpienaar
jpienaar committedJul 17, 2025
commitb404f5390ac5684c7452e69f6fe209e5215f8929
2 changes: 2 additions & 0 deletionsclang-tools-extra/clang-tidy/CMakeLists.txt
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -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)
Expand DownExpand Up@@ -93,6 +94,7 @@ set(ALL_CLANG_TIDY_CHECKS
clangTidyLLVMModule
clangTidyLLVMLibcModule
clangTidyMiscModule
clangTidyMLIRModule
clangTidyModernizeModule
clangTidyObjCModule
clangTidyOpenMPModule
Expand Down
5 changes: 5 additions & 0 deletionsclang-tools-extra/clang-tidy/ClangTidyForceLinker.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 =
Expand Down
28 changes: 28 additions & 0 deletionsclang-tools-extra/clang-tidy/mlir/CMakeLists.txt
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -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
)
39 changes: 39 additions & 0 deletionsclang-tools-extra/clang-tidy/mlir/MLIRTidyModule.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -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
102 changes: 102 additions & 0 deletionsclang-tools-extra/clang-tidy/mlir/OpBuilderCheck.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -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
21 changes: 21 additions & 0 deletionsclang-tools-extra/clang-tidy/mlir/OpBuilderCheck.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -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
5 changes: 5 additions & 0 deletionsclang-tools-extra/docs/ReleaseNotes.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
^^^^^^^^^^^^^^^^^

Expand Down
2 changes: 2 additions & 0 deletionsclang-tools-extra/docs/clang-tidy/checks/list.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,7 @@ Clang-Tidy Checks
llvm/*
llvmlibc/*
misc/*
mlir/*
modernize/*
mpi/*
objc/*
Expand DownExpand Up@@ -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"
Expand Down
22 changes: 22 additions & 0 deletionsclang-tools-extra/docs/clang-tidy/checks/mlir/op-builder.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -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");

View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -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>();
}

[8]ページ先頭

©2009-2025 Movatter.jp