brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.2 KiB · 788d057 Raw
55 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 "InterfacesGlobalInitCheck.h"10#include "clang/ASTMatchers/ASTMatchFinder.h"11 12using namespace clang::ast_matchers;13 14namespace clang::tidy::cppcoreguidelines {15 16void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) {17  const auto GlobalVarDecl =18      varDecl(hasGlobalStorage(),19              hasDeclContext(anyOf(translationUnitDecl(), // Global scope.20                                   namespaceDecl(),       // Namespace scope.21                                   recordDecl())),        // Class scope.22              unless(isConstexpr()), unless(isConstinit()));23 24  const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration(25      varDecl(GlobalVarDecl, unless(isDefinition())).bind("referencee")));26 27  Finder->addMatcher(28      traverse(TK_AsIs, varDecl(GlobalVarDecl, isDefinition(),29                                hasInitializer(expr(hasDescendant(30                                    ReferencesUndefinedGlobalVar))))31                            .bind("var")),32      this);33}34 35void InterfacesGlobalInitCheck::check(const MatchFinder::MatchResult &Result) {36  const auto *const Var = Result.Nodes.getNodeAs<VarDecl>("var");37  // For now assume that people who write macros know what they're doing.38  if (Var->getLocation().isMacroID())39    return;40  const auto *const Referencee = Result.Nodes.getNodeAs<VarDecl>("referencee");41  // If the variable has been defined, we're good.42  const auto *const ReferenceeDef = Referencee->getDefinition();43  if (ReferenceeDef != nullptr &&44      Result.SourceManager->isBeforeInTranslationUnit(45          ReferenceeDef->getLocation(), Var->getLocation())) {46    return;47  }48  diag(Var->getLocation(),49       "initializing non-local variable with non-const expression depending on "50       "uninitialized non-local variable %0")51      << Referencee;52}53 54} // namespace clang::tidy::cppcoreguidelines55