brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · 367ef52 Raw
155 lines · c
1//===- unittests/StaticAnalyzer/Reusables.h -------------------------------===//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#ifndef LLVM_CLANG_UNITTESTS_STATICANALYZER_REUSABLES_H10#define LLVM_CLANG_UNITTESTS_STATICANALYZER_REUSABLES_H11 12#include "clang/ASTMatchers/ASTMatchFinder.h"13#include "clang/CrossTU/CrossTranslationUnit.h"14#include "clang/Frontend/CompilerInstance.h"15#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"16#include "gtest/gtest.h"17 18namespace clang {19namespace ento {20 21// Find a node in the current AST that matches a matcher.22template <typename T, typename MatcherT>23const T *findNode(const Decl *Where, MatcherT What) {24  using namespace ast_matchers;25  auto Matches = match(decl(hasDescendant(What.bind("root"))),26                       *Where, Where->getASTContext());27  assert(Matches.size() <= 1 && "Ambiguous match!");28  assert(Matches.size() >= 1 && "Match not found!");29  const T *Node = selectFirst<T>("root", Matches);30  assert(Node && "Type mismatch!");31  return Node;32}33 34// Find a declaration in the current AST by name.35template <typename T>36const T *findDeclByName(const Decl *Where, StringRef Name) {37  using namespace ast_matchers;38  return findNode<T>(Where, namedDecl(hasName(Name)));39}40 41// A re-usable consumer that constructs ExprEngine out of CompilerInvocation.42class ExprEngineConsumer : public ASTConsumer {43protected:44  CompilerInstance &C;45 46private:47  // We need to construct all of these in order to construct ExprEngine.48  CheckerManager ChkMgr;49  cross_tu::CrossTranslationUnitContext CTU;50  PathDiagnosticConsumers Consumers;51  AnalysisManager AMgr;52  SetOfConstDecls VisitedCallees;53  FunctionSummariesTy FS;54 55protected:56  ExprEngine Eng;57 58public:59  ExprEngineConsumer(CompilerInstance &C)60      : C(C),61        ChkMgr(C.getASTContext(), C.getAnalyzerOpts(), C.getPreprocessor()),62        CTU(C), AMgr(C.getASTContext(), C.getPreprocessor(), {},63                     CreateRegionStoreManager, CreateRangeConstraintManager,64                     &ChkMgr, C.getAnalyzerOpts()),65        VisitedCallees(), FS(),66        Eng(CTU, AMgr, &VisitedCallees, &FS, ExprEngine::Inline_Regular) {}67};68 69struct ExpectedLocationTy {70  unsigned Line;71  unsigned Column;72 73  void testEquality(SourceLocation L, SourceManager &SM) const {74    EXPECT_EQ(SM.getSpellingLineNumber(L), Line);75    EXPECT_EQ(SM.getSpellingColumnNumber(L), Column);76  }77};78 79struct ExpectedRangeTy {80  ExpectedLocationTy Begin;81  ExpectedLocationTy End;82 83  void testEquality(SourceRange R, SourceManager &SM) const {84    Begin.testEquality(R.getBegin(), SM);85    End.testEquality(R.getEnd(), SM);86  }87};88 89struct ExpectedPieceTy {90  ExpectedLocationTy Loc;91  std::string Text;92  std::vector<ExpectedRangeTy> Ranges;93 94  void testEquality(const PathDiagnosticPiece &Piece, SourceManager &SM) {95    Loc.testEquality(Piece.getLocation().asLocation(), SM);96    EXPECT_EQ(Piece.getString(), Text);97    EXPECT_EQ(Ranges.size(), Piece.getRanges().size());98    for (const auto &RangeItem : llvm::enumerate(Piece.getRanges()))99      Ranges[RangeItem.index()].testEquality(RangeItem.value(), SM);100  }101};102 103struct ExpectedDiagTy {104  ExpectedLocationTy Loc;105  std::string VerboseDescription;106  std::string ShortDescription;107  std::string CheckerName;108  std::string BugType;109  std::string Category;110  std::vector<ExpectedPieceTy> Path;111 112  void testEquality(const PathDiagnostic &Diag, SourceManager &SM) {113    Loc.testEquality(Diag.getLocation().asLocation(), SM);114    EXPECT_EQ(Diag.getVerboseDescription(), VerboseDescription);115    EXPECT_EQ(Diag.getShortDescription(), ShortDescription);116    EXPECT_EQ(Diag.getCheckerName(), CheckerName);117    EXPECT_EQ(Diag.getBugType(), BugType);118    EXPECT_EQ(Diag.getCategory(), Category);119 120    EXPECT_EQ(Path.size(), Diag.path.size());121    for (const auto &PieceItem : llvm::enumerate(Diag.path)) {122      if (PieceItem.index() < Path.size())123        Path[PieceItem.index()].testEquality(*PieceItem.value(), SM);124    }125  }126};127 128using ExpectedDiagsTy = std::vector<ExpectedDiagTy>;129 130// A consumer to verify the generated diagnostics.131class VerifyPathDiagnosticConsumer : public PathDiagnosticConsumer {132  ExpectedDiagsTy ExpectedDiags;133  SourceManager &SM;134 135public:136  VerifyPathDiagnosticConsumer(ExpectedDiagsTy &&ExpectedDiags,137                               SourceManager &SM)138      : ExpectedDiags(ExpectedDiags), SM(SM) {}139 140  StringRef getName() const override { return "verify test diagnostics"; }141 142  void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,143                            FilesMade *filesMade) override {144    EXPECT_EQ(Diags.size(), ExpectedDiags.size());145    for (const auto &Item : llvm::enumerate(Diags))146      if (Item.index() < ExpectedDiags.size())147        ExpectedDiags[Item.index()].testEquality(*Item.value(), SM);148  }149};150 151} // namespace ento152} // namespace clang153 154#endif155