11#include "clang/AST/Decl.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13#include "clang/ASTMatchers/ASTMatchers.h"
14#include "clang/ASTMatchers/ASTMatchersMacros.h"
15#include "clang/Basic/SourceLocation.h"
16#include "clang/Basic/Specifiers.h"
17#include "clang/Lex/Token.h"
18#include "llvm/ADT/DenseSet.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/SmallVector.h"
28 static llvm::ArrayRef<
29 std::pair<misc::UseInternalLinkageCheck::FixModeKind, StringRef>>
48AST_MATCHER(Decl, isFirstDecl) {
return Node.isFirstDecl(); }
50AST_MATCHER(FunctionDecl, hasBody) {
return Node.hasBody(); }
52static bool isInMainFile(SourceLocation L, SourceManager &SM,
57 if (SM.isInMainFile(L))
60 L = SM.getIncludeLoc(SM.getFileID(L));
69 HeaderFileExtensions) {
70 return llvm::all_of(Node.redecls(), [&](
const Decl *D) {
71 return isInMainFile(D->getLocation(),
72 Finder->getASTContext().getSourceManager(),
73 HeaderFileExtensions);
78 AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
80 return Node.getStorageClass() == SC_Extern;
83AST_MATCHER(FunctionDecl, isAllocationOrDeallocationOverloadedFunction) {
90 static const llvm::DenseSet<OverloadedOperatorKind> OverloadedOperators{
91 OverloadedOperatorKind::OO_New,
92 OverloadedOperatorKind::OO_Array_New,
93 OverloadedOperatorKind::OO_Delete,
94 OverloadedOperatorKind::OO_Array_Delete,
96 return OverloadedOperators.contains(Node.getOverloadedOperator());
104 HeaderFileExtensions(Context->getHeaderFileExtensions()),
108 Options.store(Opts,
"FixMode", FixMode);
113 allOf(isFirstDecl(), isAllRedeclsInMainFile(HeaderFileExtensions),
116 isStaticStorageClass(), isInAnonymousNamespace(),
118 isExternStorageClass(), isExternC(),
120 isExplicitTemplateSpecialization(),
121 hasAncestor(decl(anyOf(
127 functionDecl(Common, hasBody(),
128 unless(anyOf(cxxMethodDecl(), isConsteval(),
129 isAllocationOrDeallocationOverloadedFunction(),
134 varDecl(Common, hasGlobalStorage(), unless(hasThreadStorageDuration()))
140 "%0 %1 can be made static or moved into an anonymous namespace "
141 "to enforce internal linkage";
144 if (
const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(
"fn")) {
145 DiagnosticBuilder DB = diag(FD->getLocation(),
Message) <<
"function" << FD;
146 const SourceLocation FixLoc = FD->getInnerLocStart();
147 if (FixLoc.isInvalid() || FixLoc.isMacroID())
150 DB << FixItHint::CreateInsertion(FixLoc,
"static ");
153 if (
const auto *VD = Result.Nodes.getNodeAs<VarDecl>(
"var")) {
157 if (getLangOpts().CPlusPlus && VD->getType().isConstQualified())
160 DiagnosticBuilder DB = diag(VD->getLocation(),
Message) <<
"variable" << VD;
161 const SourceLocation FixLoc = VD->getInnerLocStart();
162 if (FixLoc.isInvalid() || FixLoc.isMacroID())
165 DB << FixItHint::CreateInsertion(FixLoc,
"static ");
168 llvm_unreachable(
"");
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
UseInternalLinkageCheck(StringRef Name, ClangTidyContext *Context)
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
AST_POLYMORPHIC_MATCHER(isInAbseilFile, AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc, NestedNameSpecifierLoc))
Matches AST nodes that were found within Abseil files.
AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID)
AST_MATCHER(BinaryOperator, isRelationalOperator)
static constexpr StringRef Message
bool isExpansionLocInHeaderFile(SourceLocation Loc, const SourceManager &SM, const FileExtensionsSet &HeaderFileExtensions)
Checks whether expansion location of Loc is in header file.
llvm::SmallSet< llvm::StringRef, 5 > FileExtensionsSet
llvm::StringMap< ClangTidyValue > OptionMap
static llvm::ArrayRef< std::pair< misc::UseInternalLinkageCheck::FixModeKind, StringRef > > getEnumMapping()
This class should be specialized by any enum type that needs to be converted to and from an llvm::Str...