Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clang-tidy checker to use free functions for casting #103

Open
wants to merge 3 commits into
base: npu/release/18.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/misc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ add_clang_library(clangTidyMiscModule
UnusedParametersCheck.cpp
UnusedUsingDeclsCheck.cpp
UseAnonymousNamespaceCheck.cpp
UseFreeFunctionVariantsCheck.cpp

LINK_LIBS
clangAnalysis
Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "UnusedParametersCheck.h"
#include "UnusedUsingDeclsCheck.h"
#include "UseAnonymousNamespaceCheck.h"
#include "UseFreeFunctionVariantsCheck.h"

namespace clang::tidy {
namespace misc {
Expand Down Expand Up @@ -78,6 +79,8 @@ class MiscModule : public ClangTidyModule {
"misc-unused-using-decls");
CheckFactories.registerCheck<UseAnonymousNamespaceCheck>(
"misc-use-anonymous-namespace");
CheckFactories.registerCheck<UseFreeFunctionVariantsCheck>(
"misc-use-free-function-variants");
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//===--- UseFreeFunctionVariantsCheck.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 "UseFreeFunctionVariantsCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include <iostream>

using namespace clang::ast_matchers;

namespace clang::tidy::misc {

void UseFreeFunctionVariantsCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(cxxMemberCallExpr(on(expr().bind("base")),
callee(cxxMethodDecl(hasAnyName("isa", "dyn_cast", "cast", "dyn_cast_or_null", "isa_and_nonnull")))
).bind("castCall"),
this);
}

// TODO(askrebko): Add checker for types wrapped in pointers and optional
void UseFreeFunctionVariantsCheck::check(
const MatchFinder::MatchResult &Result) {
const auto* CallExpr = Result.Nodes.getNodeAs<CXXMemberCallExpr>("castCall");
const auto* BaseExpr = Result.Nodes.getNodeAs<Expr>("base");

if (!CallExpr || !BaseExpr) {
return;
}
SourceManager &SM = *Result.SourceManager;
LangOptions LangOpts = getLangOpts();

std::string BaseStr = Lexer::getSourceText(
CharSourceRange::getTokenRange(BaseExpr->getSourceRange()), SM, LangOpts).str();

const auto* MethodDecl = CallExpr->getMethodDecl();
if (!MethodDecl->getTemplateSpecializationArgs()) {
return;
}

std::string TemplateArgStr;
for (const auto& Arg : MethodDecl->getTemplateSpecializationArgs()->asArray()) {
if (Arg.getKind() == TemplateArgument::ArgKind::Type) {
PrintingPolicy Policy(LangOpts);
Policy.adjustForCPlusPlus();
if (!TemplateArgStr.empty()) {
TemplateArgStr += ", ";
}
TemplateArgStr += Arg.getAsType().getAsString(Policy);
} else if (Arg.getKind() == TemplateArgument::ArgKind::Pack) {
for (const auto& PackArg : Arg.pack_elements()) {
PrintingPolicy Policy(LangOpts);
Policy.adjustForCPlusPlus();
if (!TemplateArgStr.empty()) {
TemplateArgStr += ", ";
}
TemplateArgStr += PackArg.getAsType().getAsString(Policy);
}
} else {
std::cout << "Unsupported template argument kind: " << Arg.getKind() << std::endl;
return;
}
}

std::string FuncName = MethodDecl->getNameAsString();

std::string Replacement = "mlir::" + FuncName + "<" + TemplateArgStr + ">(" + BaseStr + ")";
diag(CallExpr->getBeginLoc(), "Replace 'type.isa<T>()' with 'mlir::isa<T>(type)'")
<< FixItHint::CreateReplacement(CallExpr->getSourceRange(), Replacement);
}

} // namespace clang::tidy::misc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===--- UseFreeFunctionVariantsCheck.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_MISC_USEFREEFUNCTIONVARIANTSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USEFREEFUNCTIONVARIANTSCHECK_H

#include "../ClangTidyCheck.h"

namespace clang::tidy::misc {

/// FIXME: Write a short description.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/misc/use-free-function-variants.html
class UseFreeFunctionVariantsCheck : public ClangTidyCheck {
public:
UseFreeFunctionVariantsCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

} // namespace clang::tidy::misc

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USEFREEFUNCTIONVARIANTSCHECK_H
5 changes: 5 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ New checks
points in a coroutine. Such hostile types include scoped-lockable types and
types belonging to a configurable denylist.

- New :doc:`misc-use-free-function-variants
<clang-tidy/checks/misc/use-free-function-variants>` check.

FIXME: add release notes.

- New :doc:`modernize-use-constraints
<clang-tidy/checks/modernize/use-constraints>` check.

Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ Clang-Tidy Checks
:doc:`misc-unused-parameters <misc/unused-parameters>`, "Yes"
:doc:`misc-unused-using-decls <misc/unused-using-decls>`, "Yes"
:doc:`misc-use-anonymous-namespace <misc/use-anonymous-namespace>`,
:doc:`misc-use-free-function-variants <misc/use-free-function-variants>`, "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
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. title:: clang-tidy - misc-use-free-function-variants

misc-use-free-function-variants
===============================

FIXME: Describe what patterns does the check detect and why. Give examples.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %check_clang_tidy %s misc-use-free-function-variants %t

// FIXME: Add something that triggers the check here.
void f();
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'f' is insufficiently awesome [misc-use-free-function-variants]

// FIXME: Verify the applied fix.
// * Make the CHECK patterns specific enough and try to make verified lines
// unique to avoid incorrect matches.
// * Use {{}} for regular expressions.
// CHECK-FIXES: {{^}}void awesome_f();{{$}}

// FIXME: Add something that doesn't trigger the check here.
void awesome_f2();
Loading