brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · 93b5b96 Raw
122 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 "InitVariablesCheck.h"10 11#include "../utils/LexerUtils.h"12#include "clang/AST/ASTContext.h"13#include "clang/AST/Type.h"14#include "clang/ASTMatchers/ASTMatchFinder.h"15#include "clang/Lex/Preprocessor.h"16#include <optional>17 18using namespace clang::ast_matchers;19 20namespace clang::tidy::cppcoreguidelines {21 22namespace {23AST_MATCHER(VarDecl, isLocalVarDecl) { return Node.isLocalVarDecl(); }24} // namespace25 26InitVariablesCheck::InitVariablesCheck(StringRef Name,27                                       ClangTidyContext *Context)28    : ClangTidyCheck(Name, Context),29      IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",30                                               utils::IncludeSorter::IS_LLVM),31                      areDiagsSelfContained()),32      MathHeader(Options.get("MathHeader", "<math.h>")) {}33 34void InitVariablesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {35  Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());36  Options.store(Opts, "MathHeader", MathHeader);37}38 39void InitVariablesCheck::registerMatchers(MatchFinder *Finder) {40  const std::string BadDecl = "badDecl";41  Finder->addMatcher(42      varDecl(unless(hasInitializer(anything())), unless(isInstantiated()),43              isLocalVarDecl(), unless(isStaticLocal()), isDefinition(),44              unless(hasParent(cxxCatchStmt())),45              optionally(hasParent(declStmt(hasParent(46                  cxxForRangeStmt(hasLoopVariable(varDecl().bind(BadDecl))))))),47              unless(equalsBoundNode(BadDecl)))48          .bind("vardecl"),49      this);50}51 52void InitVariablesCheck::registerPPCallbacks(const SourceManager &SM,53                                             Preprocessor *PP,54                                             Preprocessor *ModuleExpanderPP) {55  IncludeInserter.registerPreprocessor(PP);56}57 58void InitVariablesCheck::check(const MatchFinder::MatchResult &Result) {59  const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("vardecl");60  const ASTContext &Context = *Result.Context;61  const SourceManager &Source = Context.getSourceManager();62 63  // Clang diagnostic error may cause the variable to be an invalid int vardecl64  if (MatchedDecl->isInvalidDecl())65    return;66 67  // We want to warn about cases where the type name68  // comes from a macro like this:69  //70  // TYPENAME_FROM_MACRO var;71  //72  // but not if the entire declaration comes from73  // one:74  //75  // DEFINE_SOME_VARIABLE();76  //77  // or if the definition comes from a macro like SWAP78  // that uses an internal temporary variable.79  //80  // Thus check that the variable name does81  // not come from a macro expansion.82  if (MatchedDecl->getEndLoc().isMacroID())83    return;84 85  const QualType TypePtr = MatchedDecl->getType();86  std::optional<const char *> InitializationString;87  bool AddMathInclude = false;88 89  if (TypePtr->isEnumeralType())90    InitializationString = nullptr;91  else if (TypePtr->isBooleanType())92    InitializationString = " = false";93  else if (TypePtr->isIntegerType())94    InitializationString = " = 0";95  else if (TypePtr->isFloatingType()) {96    InitializationString = " = NAN";97    AddMathInclude = true;98  } else if (TypePtr->isAnyPointerType()) {99    if (getLangOpts().CPlusPlus11)100      InitializationString = " = nullptr";101    else102      InitializationString = " = NULL";103  }104 105  if (InitializationString) {106    auto Diagnostic =107        diag(MatchedDecl->getLocation(), "variable %0 is not initialized")108        << MatchedDecl;109    if (*InitializationString != nullptr)110      Diagnostic << FixItHint::CreateInsertion(111          utils::lexer::findNextTerminator(MatchedDecl->getEndLoc(),112                                           *Result.SourceManager,113                                           Result.Context->getLangOpts()),114          *InitializationString);115    if (AddMathInclude) {116      Diagnostic << IncludeInserter.createIncludeInsertion(117          Source.getFileID(MatchedDecl->getBeginLoc()), MathHeader);118    }119  }120}121} // namespace clang::tidy::cppcoreguidelines122