blob: 9de2d408c0cf5aca8f7039f45d6d6ad0d5e86d41 [file] [log] [blame]
Haojian Wuc253f8b2016-04-05 11:42:08 +00001//===--- 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
15using namespace clang::ast_matchers;
16
17namespace clang {
18namespace tidy {
19namespace readability {
20
21namespace {
22AST_POLYMORPHIC_MATCHER(isStatic, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
23 VarDecl)) {
24 return Node.getStorageClass() == SC_Static;
25}
26} // namespace
27
28void StaticDefinitionInAnonymousNamespaceCheck::registerMatchers(
29 MatchFinder *Finder) {
30 Finder->addMatcher(namedDecl(anyOf(functionDecl(isDefinition(), isStatic()),
31 varDecl(isDefinition(), isStatic())),
32 hasParent(namespaceDecl(isAnonymous())))
33 .bind("static-def"),
34 this);
35}
36
37void StaticDefinitionInAnonymousNamespaceCheck::check(
38 const MatchFinder::MatchResult &Result) {
39 const auto *Def = Result.Nodes.getNodeAs<NamedDecl>("static-def");
40 // Skips all static definitions defined in Macro.
41 if (Def->getLocation().isMacroID())
42 return;
43
44 // Skips all static definitions in function scope.
45 const DeclContext *DC = Def->getDeclContext();
46 if (DC->getDeclKind() != Decl::Namespace)
47 return;
48
49 auto Diag =
50 diag(Def->getLocation(), "%0 is a static definition in "
51 "anonymous namespace; static is redundant here")
52 << Def;
53 Token Tok;
54 SourceLocation Loc = Def->getSourceRange().getBegin();
55 while (Loc < Def->getSourceRange().getEnd() &&
56 !Lexer::getRawToken(Loc, Tok, *Result.SourceManager,
57 Result.Context->getLangOpts(), true)) {
58 SourceRange TokenRange(Tok.getLocation(), Tok.getEndLoc());
59 StringRef SourceText = Lexer::getSourceText(
60 CharSourceRange::getTokenRange(TokenRange),
61 *Result.SourceManager, Result.Context->getLangOpts());
62 if (SourceText == "static") {
63 Diag << FixItHint::CreateRemoval(TokenRange);
64 break;
65 }
66 Loc = Tok.getEndLoc();
67 }
68}
69
70} // namespace readability
71} // namespace tidy
72} // namespace clang