diff options
author | Haojian Wu <hokein@google.com> | 2016-04-05 11:42:08 +0000 |
---|---|---|
committer | Haojian Wu <hokein@google.com> | 2016-04-05 11:42:08 +0000 |
commit | c253f8b06be7d8fe23cb08613fad439c01d51521 (patch) | |
tree | c73a300b4bc7c02e037f790fa17d1352d9e266e4 /clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp | |
parent | 591ae468201532c6ce59826d10f596c6bba37a7b (diff) | |
download | llvm-c253f8b06be7d8fe23cb08613fad439c01d51521.zip llvm-c253f8b06be7d8fe23cb08613fad439c01d51521.tar.gz llvm-c253f8b06be7d8fe23cb08613fad439c01d51521.tar.bz2 |
[clang-tidy] Add a check to detect static definitions in anonymous namespace.
Summary: Fixes PR26595
Reviewers: alexfh
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D18180
llvm-svn: 265384
Diffstat (limited to 'clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp')
-rw-r--r-- | clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp new file mode 100644 index 0000000..9de2d40 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp @@ -0,0 +1,72 @@ +//===--- StaticDefinitionInAnonymousNamespaceCheck.cpp - clang-tidy--------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "StaticDefinitionInAnonymousNamespaceCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +namespace { +AST_POLYMORPHIC_MATCHER(isStatic, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + VarDecl)) { + return Node.getStorageClass() == SC_Static; +} +} // namespace + +void StaticDefinitionInAnonymousNamespaceCheck::registerMatchers( + MatchFinder *Finder) { + Finder->addMatcher(namedDecl(anyOf(functionDecl(isDefinition(), isStatic()), + varDecl(isDefinition(), isStatic())), + hasParent(namespaceDecl(isAnonymous()))) + .bind("static-def"), + this); +} + +void StaticDefinitionInAnonymousNamespaceCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *Def = Result.Nodes.getNodeAs<NamedDecl>("static-def"); + // Skips all static definitions defined in Macro. + if (Def->getLocation().isMacroID()) + return; + + // Skips all static definitions in function scope. + const DeclContext *DC = Def->getDeclContext(); + if (DC->getDeclKind() != Decl::Namespace) + return; + + auto Diag = + diag(Def->getLocation(), "%0 is a static definition in " + "anonymous namespace; static is redundant here") + << Def; + Token Tok; + SourceLocation Loc = Def->getSourceRange().getBegin(); + while (Loc < Def->getSourceRange().getEnd() && + !Lexer::getRawToken(Loc, Tok, *Result.SourceManager, + Result.Context->getLangOpts(), true)) { + SourceRange TokenRange(Tok.getLocation(), Tok.getEndLoc()); + StringRef SourceText = Lexer::getSourceText( + CharSourceRange::getTokenRange(TokenRange), + *Result.SourceManager, Result.Context->getLangOpts()); + if (SourceText == "static") { + Diag << FixItHint::CreateRemoval(TokenRange); + break; + } + Loc = Tok.getEndLoc(); + } +} + +} // namespace readability +} // namespace tidy +} // namespace clang |