brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.8 KiB · d720986 Raw
111 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "PreferStaticOverAnonymousNamespaceCheck.h"10#include "clang/ASTMatchers/ASTMatchFinder.h"11 12using namespace clang::ast_matchers;13 14namespace clang::tidy::llvm_check {15 16namespace {17 18AST_MATCHER(NamedDecl, isInMacro) {19  return Node.getBeginLoc().isMacroID() || Node.getEndLoc().isMacroID();20}21 22AST_MATCHER(VarDecl, isLocalVariable) { return Node.isLocalVarDecl(); }23 24AST_MATCHER(Decl, isLexicallyInAnonymousNamespace) {25  for (const DeclContext *DC = Node.getLexicalDeclContext(); DC != nullptr;26       DC = DC->getLexicalParent()) {27    if (const auto *ND = dyn_cast<NamespaceDecl>(DC))28      if (ND->isAnonymousNamespace())29        return true;30  }31 32  return false;33}34 35} // namespace36 37PreferStaticOverAnonymousNamespaceCheck::38    PreferStaticOverAnonymousNamespaceCheck(StringRef Name,39                                            ClangTidyContext *Context)40    : ClangTidyCheck(Name, Context),41      AllowVariableDeclarations(Options.get("AllowVariableDeclarations", true)),42      AllowMemberFunctionsInClass(43          Options.get("AllowMemberFunctionsInClass", true)) {}44 45void PreferStaticOverAnonymousNamespaceCheck::storeOptions(46    ClangTidyOptions::OptionMap &Opts) {47  Options.store(Opts, "AllowVariableDeclarations", AllowVariableDeclarations);48  Options.store(Opts, "AllowMemberFunctionsInClass",49                AllowMemberFunctionsInClass);50}51 52void PreferStaticOverAnonymousNamespaceCheck::registerMatchers(53    MatchFinder *Finder) {54  const auto IsDefinitionInAnonymousNamespace = allOf(55      unless(isExpansionInSystemHeader()), isLexicallyInAnonymousNamespace(),56      unless(isInMacro()), isDefinition());57 58  if (AllowMemberFunctionsInClass) {59    Finder->addMatcher(60        functionDecl(IsDefinitionInAnonymousNamespace,61                     unless(anyOf(hasParent(cxxRecordDecl()),62                                  hasParent(functionTemplateDecl(63                                      hasParent(cxxRecordDecl()))))))64            .bind("function"),65        this);66  } else {67    Finder->addMatcher(68        functionDecl(IsDefinitionInAnonymousNamespace).bind("function"), this);69  }70 71  if (!AllowVariableDeclarations)72    Finder->addMatcher(varDecl(IsDefinitionInAnonymousNamespace,73                               unless(isLocalVariable()), unless(parmVarDecl()))74                           .bind("var"),75                       this);76}77 78void PreferStaticOverAnonymousNamespaceCheck::check(79    const MatchFinder::MatchResult &Result) {80  if (const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("function")) {81    if (Func->isCXXClassMember())82      diag(Func->getLocation(),83           "place definition of method %0 outside of an anonymous namespace")84          << Func;85    else if (Func->isStatic())86      diag(Func->getLocation(),87           "place static function %0 outside of an anonymous namespace")88          << Func;89    else90      diag(Func->getLocation(),91           "function %0 is declared in an anonymous namespace; "92           "prefer using 'static' for restricting visibility")93          << Func;94    return;95  }96 97  if (const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var")) {98    if (Var->getStorageClass() == SC_Static)99      diag(Var->getLocation(),100           "place static variable %0 outside of an anonymous namespace")101          << Var;102    else103      diag(Var->getLocation(),104           "variable %0 is declared in an anonymous namespace; "105           "prefer using 'static' for restricting visibility")106          << Var;107  }108}109 110} // namespace clang::tidy::llvm_check111