1 //===--- StaticDefinitionInAnonymousNamespaceCheck.cpp - clang-tidy--------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "StaticDefinitionInAnonymousNamespaceCheck.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 #include "clang/Lex/Lexer.h" 14 15 using namespace clang::ast_matchers; 16 17 namespace clang { 18 namespace tidy { 19 namespace readability { 20 21 void StaticDefinitionInAnonymousNamespaceCheck::registerMatchers( 22 MatchFinder *Finder) { 23 Finder->addMatcher( 24 namedDecl(anyOf(functionDecl(isDefinition(), isStaticStorageClass()), 25 varDecl(isDefinition(), isStaticStorageClass())), 26 hasParent(namespaceDecl(isAnonymous()))) 27 .bind("static-def"), 28 this); 29 } 30 31 void StaticDefinitionInAnonymousNamespaceCheck::check( 32 const MatchFinder::MatchResult &Result) { 33 const auto *Def = Result.Nodes.getNodeAs<NamedDecl>("static-def"); 34 // Skips all static definitions defined in Macro. 35 if (Def->getLocation().isMacroID()) 36 return; 37 38 // Skips all static definitions in function scope. 39 const DeclContext *DC = Def->getDeclContext(); 40 if (DC->getDeclKind() != Decl::Namespace) 41 return; 42 43 auto Diag = 44 diag(Def->getLocation(), "%0 is a static definition in " 45 "anonymous namespace; static is redundant here") 46 << Def; 47 Token Tok; 48 SourceLocation Loc = Def->getSourceRange().getBegin(); 49 while (Loc < Def->getSourceRange().getEnd() && 50 !Lexer::getRawToken(Loc, Tok, *Result.SourceManager, getLangOpts(), 51 true)) { 52 SourceRange TokenRange(Tok.getLocation(), Tok.getEndLoc()); 53 StringRef SourceText = 54 Lexer::getSourceText(CharSourceRange::getTokenRange(TokenRange), 55 *Result.SourceManager, getLangOpts()); 56 if (SourceText == "static") { 57 Diag << FixItHint::CreateRemoval(TokenRange); 58 break; 59 } 60 Loc = Tok.getEndLoc(); 61 } 62 } 63 64 } // namespace readability 65 } // namespace tidy 66 } // namespace clang 67