xref: /freebsd/contrib/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // "Meta" ASTConsumer for running different source analyses.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
14*0b57cec5SDimitry Andric #include "ModelInjector.h"
15*0b57cec5SDimitry Andric #include "clang/AST/Decl.h"
16*0b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
17*0b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
18*0b57cec5SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
19*0b57cec5SDimitry Andric #include "clang/Analysis/Analyses/LiveVariables.h"
20*0b57cec5SDimitry Andric #include "clang/Analysis/CFG.h"
21*0b57cec5SDimitry Andric #include "clang/Analysis/CallGraph.h"
22*0b57cec5SDimitry Andric #include "clang/Analysis/CodeInjector.h"
23*0b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
24*0b57cec5SDimitry Andric #include "clang/CrossTU/CrossTranslationUnit.h"
25*0b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h"
26*0b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
27*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
28*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
29*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
30*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
31*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h"
32*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
33*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
34*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
35*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
36*0b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
37*0b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
38*0b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
39*0b57cec5SDimitry Andric #include "llvm/Support/Path.h"
40*0b57cec5SDimitry Andric #include "llvm/Support/Program.h"
41*0b57cec5SDimitry Andric #include "llvm/Support/Timer.h"
42*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
43*0b57cec5SDimitry Andric #include <memory>
44*0b57cec5SDimitry Andric #include <queue>
45*0b57cec5SDimitry Andric #include <utility>
46*0b57cec5SDimitry Andric 
47*0b57cec5SDimitry Andric using namespace clang;
48*0b57cec5SDimitry Andric using namespace ento;
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric #define DEBUG_TYPE "AnalysisConsumer"
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric STATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
53*0b57cec5SDimitry Andric STATISTIC(NumFunctionsAnalyzed,
54*0b57cec5SDimitry Andric                       "The # of functions and blocks analyzed (as top level "
55*0b57cec5SDimitry Andric                       "with inlining turned on).");
56*0b57cec5SDimitry Andric STATISTIC(NumBlocksInAnalyzedFunctions,
57*0b57cec5SDimitry Andric                       "The # of basic blocks in the analyzed functions.");
58*0b57cec5SDimitry Andric STATISTIC(NumVisitedBlocksInAnalyzedFunctions,
59*0b57cec5SDimitry Andric           "The # of visited basic blocks in the analyzed functions.");
60*0b57cec5SDimitry Andric STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
61*0b57cec5SDimitry Andric STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");
62*0b57cec5SDimitry Andric 
63*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
64*0b57cec5SDimitry Andric // Special PathDiagnosticConsumers.
65*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
66*0b57cec5SDimitry Andric 
67*0b57cec5SDimitry Andric void ento::createPlistHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
68*0b57cec5SDimitry Andric                                              PathDiagnosticConsumers &C,
69*0b57cec5SDimitry Andric                                              const std::string &prefix,
70*0b57cec5SDimitry Andric                                              const Preprocessor &PP) {
71*0b57cec5SDimitry Andric   createHTMLDiagnosticConsumer(AnalyzerOpts, C,
72*0b57cec5SDimitry Andric                                llvm::sys::path::parent_path(prefix), PP);
73*0b57cec5SDimitry Andric   createPlistMultiFileDiagnosticConsumer(AnalyzerOpts, C, prefix, PP);
74*0b57cec5SDimitry Andric }
75*0b57cec5SDimitry Andric 
76*0b57cec5SDimitry Andric void ento::createTextPathDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
77*0b57cec5SDimitry Andric                                             PathDiagnosticConsumers &C,
78*0b57cec5SDimitry Andric                                             const std::string &Prefix,
79*0b57cec5SDimitry Andric                                             const clang::Preprocessor &PP) {
80*0b57cec5SDimitry Andric   llvm_unreachable("'text' consumer should be enabled on ClangDiags");
81*0b57cec5SDimitry Andric }
82*0b57cec5SDimitry Andric 
83*0b57cec5SDimitry Andric namespace {
84*0b57cec5SDimitry Andric class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer {
85*0b57cec5SDimitry Andric   DiagnosticsEngine &Diag;
86*0b57cec5SDimitry Andric   bool IncludePath, ShouldEmitAsError;
87*0b57cec5SDimitry Andric 
88*0b57cec5SDimitry Andric public:
89*0b57cec5SDimitry Andric   ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag)
90*0b57cec5SDimitry Andric       : Diag(Diag), IncludePath(false), ShouldEmitAsError(false) {}
91*0b57cec5SDimitry Andric   ~ClangDiagPathDiagConsumer() override {}
92*0b57cec5SDimitry Andric   StringRef getName() const override { return "ClangDiags"; }
93*0b57cec5SDimitry Andric 
94*0b57cec5SDimitry Andric   bool supportsLogicalOpControlFlow() const override { return true; }
95*0b57cec5SDimitry Andric   bool supportsCrossFileDiagnostics() const override { return true; }
96*0b57cec5SDimitry Andric 
97*0b57cec5SDimitry Andric   PathGenerationScheme getGenerationScheme() const override {
98*0b57cec5SDimitry Andric     return IncludePath ? Minimal : None;
99*0b57cec5SDimitry Andric   }
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric   void enablePaths() {
102*0b57cec5SDimitry Andric     IncludePath = true;
103*0b57cec5SDimitry Andric   }
104*0b57cec5SDimitry Andric 
105*0b57cec5SDimitry Andric   void enableWerror() { ShouldEmitAsError = true; }
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric   void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
108*0b57cec5SDimitry Andric                             FilesMade *filesMade) override {
109*0b57cec5SDimitry Andric     unsigned WarnID =
110*0b57cec5SDimitry Andric         ShouldEmitAsError
111*0b57cec5SDimitry Andric             ? Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0")
112*0b57cec5SDimitry Andric             : Diag.getCustomDiagID(DiagnosticsEngine::Warning, "%0");
113*0b57cec5SDimitry Andric     unsigned NoteID = Diag.getCustomDiagID(DiagnosticsEngine::Note, "%0");
114*0b57cec5SDimitry Andric 
115*0b57cec5SDimitry Andric     for (std::vector<const PathDiagnostic*>::iterator I = Diags.begin(),
116*0b57cec5SDimitry Andric          E = Diags.end(); I != E; ++I) {
117*0b57cec5SDimitry Andric       const PathDiagnostic *PD = *I;
118*0b57cec5SDimitry Andric       SourceLocation WarnLoc = PD->getLocation().asLocation();
119*0b57cec5SDimitry Andric       Diag.Report(WarnLoc, WarnID) << PD->getShortDescription()
120*0b57cec5SDimitry Andric                                    << PD->path.back()->getRanges();
121*0b57cec5SDimitry Andric 
122*0b57cec5SDimitry Andric       // First, add extra notes, even if paths should not be included.
123*0b57cec5SDimitry Andric       for (const auto &Piece : PD->path) {
124*0b57cec5SDimitry Andric         if (!isa<PathDiagnosticNotePiece>(Piece.get()))
125*0b57cec5SDimitry Andric           continue;
126*0b57cec5SDimitry Andric 
127*0b57cec5SDimitry Andric         SourceLocation NoteLoc = Piece->getLocation().asLocation();
128*0b57cec5SDimitry Andric         Diag.Report(NoteLoc, NoteID) << Piece->getString()
129*0b57cec5SDimitry Andric                                      << Piece->getRanges();
130*0b57cec5SDimitry Andric       }
131*0b57cec5SDimitry Andric 
132*0b57cec5SDimitry Andric       if (!IncludePath)
133*0b57cec5SDimitry Andric         continue;
134*0b57cec5SDimitry Andric 
135*0b57cec5SDimitry Andric       // Then, add the path notes if necessary.
136*0b57cec5SDimitry Andric       PathPieces FlatPath = PD->path.flatten(/*ShouldFlattenMacros=*/true);
137*0b57cec5SDimitry Andric       for (const auto &Piece : FlatPath) {
138*0b57cec5SDimitry Andric         if (isa<PathDiagnosticNotePiece>(Piece.get()))
139*0b57cec5SDimitry Andric           continue;
140*0b57cec5SDimitry Andric 
141*0b57cec5SDimitry Andric         SourceLocation NoteLoc = Piece->getLocation().asLocation();
142*0b57cec5SDimitry Andric         Diag.Report(NoteLoc, NoteID) << Piece->getString()
143*0b57cec5SDimitry Andric                                      << Piece->getRanges();
144*0b57cec5SDimitry Andric       }
145*0b57cec5SDimitry Andric     }
146*0b57cec5SDimitry Andric   }
147*0b57cec5SDimitry Andric };
148*0b57cec5SDimitry Andric } // end anonymous namespace
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
151*0b57cec5SDimitry Andric // AnalysisConsumer declaration.
152*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
153*0b57cec5SDimitry Andric 
154*0b57cec5SDimitry Andric namespace {
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric class AnalysisConsumer : public AnalysisASTConsumer,
157*0b57cec5SDimitry Andric                          public RecursiveASTVisitor<AnalysisConsumer> {
158*0b57cec5SDimitry Andric   enum {
159*0b57cec5SDimitry Andric     AM_None = 0,
160*0b57cec5SDimitry Andric     AM_Syntax = 0x1,
161*0b57cec5SDimitry Andric     AM_Path = 0x2
162*0b57cec5SDimitry Andric   };
163*0b57cec5SDimitry Andric   typedef unsigned AnalysisMode;
164*0b57cec5SDimitry Andric 
165*0b57cec5SDimitry Andric   /// Mode of the analyzes while recursively visiting Decls.
166*0b57cec5SDimitry Andric   AnalysisMode RecVisitorMode;
167*0b57cec5SDimitry Andric   /// Bug Reporter to use while recursively visiting Decls.
168*0b57cec5SDimitry Andric   BugReporter *RecVisitorBR;
169*0b57cec5SDimitry Andric 
170*0b57cec5SDimitry Andric   std::vector<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns;
171*0b57cec5SDimitry Andric 
172*0b57cec5SDimitry Andric public:
173*0b57cec5SDimitry Andric   ASTContext *Ctx;
174*0b57cec5SDimitry Andric   const Preprocessor &PP;
175*0b57cec5SDimitry Andric   const std::string OutDir;
176*0b57cec5SDimitry Andric   AnalyzerOptionsRef Opts;
177*0b57cec5SDimitry Andric   ArrayRef<std::string> Plugins;
178*0b57cec5SDimitry Andric   CodeInjector *Injector;
179*0b57cec5SDimitry Andric   cross_tu::CrossTranslationUnitContext CTU;
180*0b57cec5SDimitry Andric 
181*0b57cec5SDimitry Andric   /// Stores the declarations from the local translation unit.
182*0b57cec5SDimitry Andric   /// Note, we pre-compute the local declarations at parse time as an
183*0b57cec5SDimitry Andric   /// optimization to make sure we do not deserialize everything from disk.
184*0b57cec5SDimitry Andric   /// The local declaration to all declarations ratio might be very small when
185*0b57cec5SDimitry Andric   /// working with a PCH file.
186*0b57cec5SDimitry Andric   SetOfDecls LocalTUDecls;
187*0b57cec5SDimitry Andric 
188*0b57cec5SDimitry Andric   // Set of PathDiagnosticConsumers.  Owned by AnalysisManager.
189*0b57cec5SDimitry Andric   PathDiagnosticConsumers PathConsumers;
190*0b57cec5SDimitry Andric 
191*0b57cec5SDimitry Andric   StoreManagerCreator CreateStoreMgr;
192*0b57cec5SDimitry Andric   ConstraintManagerCreator CreateConstraintMgr;
193*0b57cec5SDimitry Andric 
194*0b57cec5SDimitry Andric   std::unique_ptr<CheckerManager> checkerMgr;
195*0b57cec5SDimitry Andric   std::unique_ptr<AnalysisManager> Mgr;
196*0b57cec5SDimitry Andric 
197*0b57cec5SDimitry Andric   /// Time the analyzes time of each translation unit.
198*0b57cec5SDimitry Andric   std::unique_ptr<llvm::TimerGroup> AnalyzerTimers;
199*0b57cec5SDimitry Andric   std::unique_ptr<llvm::Timer> SyntaxCheckTimer;
200*0b57cec5SDimitry Andric   std::unique_ptr<llvm::Timer> ExprEngineTimer;
201*0b57cec5SDimitry Andric   std::unique_ptr<llvm::Timer> BugReporterTimer;
202*0b57cec5SDimitry Andric 
203*0b57cec5SDimitry Andric   /// The information about analyzed functions shared throughout the
204*0b57cec5SDimitry Andric   /// translation unit.
205*0b57cec5SDimitry Andric   FunctionSummariesTy FunctionSummaries;
206*0b57cec5SDimitry Andric 
207*0b57cec5SDimitry Andric   AnalysisConsumer(CompilerInstance &CI, const std::string &outdir,
208*0b57cec5SDimitry Andric                    AnalyzerOptionsRef opts, ArrayRef<std::string> plugins,
209*0b57cec5SDimitry Andric                    CodeInjector *injector)
210*0b57cec5SDimitry Andric       : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr),
211*0b57cec5SDimitry Andric         PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
212*0b57cec5SDimitry Andric         Plugins(plugins), Injector(injector), CTU(CI) {
213*0b57cec5SDimitry Andric     DigestAnalyzerOptions();
214*0b57cec5SDimitry Andric     if (Opts->PrintStats || Opts->ShouldSerializeStats) {
215*0b57cec5SDimitry Andric       AnalyzerTimers = llvm::make_unique<llvm::TimerGroup>(
216*0b57cec5SDimitry Andric           "analyzer", "Analyzer timers");
217*0b57cec5SDimitry Andric       SyntaxCheckTimer = llvm::make_unique<llvm::Timer>(
218*0b57cec5SDimitry Andric           "syntaxchecks", "Syntax-based analysis time", *AnalyzerTimers);
219*0b57cec5SDimitry Andric       ExprEngineTimer = llvm::make_unique<llvm::Timer>(
220*0b57cec5SDimitry Andric           "exprengine", "Path exploration time", *AnalyzerTimers);
221*0b57cec5SDimitry Andric       BugReporterTimer = llvm::make_unique<llvm::Timer>(
222*0b57cec5SDimitry Andric           "bugreporter", "Path-sensitive report post-processing time",
223*0b57cec5SDimitry Andric           *AnalyzerTimers);
224*0b57cec5SDimitry Andric       llvm::EnableStatistics(/* PrintOnExit= */ false);
225*0b57cec5SDimitry Andric     }
226*0b57cec5SDimitry Andric   }
227*0b57cec5SDimitry Andric 
228*0b57cec5SDimitry Andric   ~AnalysisConsumer() override {
229*0b57cec5SDimitry Andric     if (Opts->PrintStats) {
230*0b57cec5SDimitry Andric       llvm::PrintStatistics();
231*0b57cec5SDimitry Andric     }
232*0b57cec5SDimitry Andric   }
233*0b57cec5SDimitry Andric 
234*0b57cec5SDimitry Andric   void DigestAnalyzerOptions() {
235*0b57cec5SDimitry Andric     if (Opts->AnalysisDiagOpt != PD_NONE) {
236*0b57cec5SDimitry Andric       // Create the PathDiagnosticConsumer.
237*0b57cec5SDimitry Andric       ClangDiagPathDiagConsumer *clangDiags =
238*0b57cec5SDimitry Andric           new ClangDiagPathDiagConsumer(PP.getDiagnostics());
239*0b57cec5SDimitry Andric       PathConsumers.push_back(clangDiags);
240*0b57cec5SDimitry Andric 
241*0b57cec5SDimitry Andric       if (Opts->AnalyzerWerror)
242*0b57cec5SDimitry Andric         clangDiags->enableWerror();
243*0b57cec5SDimitry Andric 
244*0b57cec5SDimitry Andric       if (Opts->AnalysisDiagOpt == PD_TEXT) {
245*0b57cec5SDimitry Andric         clangDiags->enablePaths();
246*0b57cec5SDimitry Andric 
247*0b57cec5SDimitry Andric       } else if (!OutDir.empty()) {
248*0b57cec5SDimitry Andric         switch (Opts->AnalysisDiagOpt) {
249*0b57cec5SDimitry Andric         default:
250*0b57cec5SDimitry Andric #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)                    \
251*0b57cec5SDimitry Andric   case PD_##NAME:                                                              \
252*0b57cec5SDimitry Andric     CREATEFN(*Opts.get(), PathConsumers, OutDir, PP);                       \
253*0b57cec5SDimitry Andric     break;
254*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
255*0b57cec5SDimitry Andric         }
256*0b57cec5SDimitry Andric       }
257*0b57cec5SDimitry Andric     }
258*0b57cec5SDimitry Andric 
259*0b57cec5SDimitry Andric     // Create the analyzer component creators.
260*0b57cec5SDimitry Andric     switch (Opts->AnalysisStoreOpt) {
261*0b57cec5SDimitry Andric     default:
262*0b57cec5SDimitry Andric       llvm_unreachable("Unknown store manager.");
263*0b57cec5SDimitry Andric #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
264*0b57cec5SDimitry Andric       case NAME##Model: CreateStoreMgr = CREATEFN; break;
265*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
266*0b57cec5SDimitry Andric     }
267*0b57cec5SDimitry Andric 
268*0b57cec5SDimitry Andric     switch (Opts->AnalysisConstraintsOpt) {
269*0b57cec5SDimitry Andric     default:
270*0b57cec5SDimitry Andric       llvm_unreachable("Unknown constraint manager.");
271*0b57cec5SDimitry Andric #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
272*0b57cec5SDimitry Andric       case NAME##Model: CreateConstraintMgr = CREATEFN; break;
273*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
274*0b57cec5SDimitry Andric     }
275*0b57cec5SDimitry Andric   }
276*0b57cec5SDimitry Andric 
277*0b57cec5SDimitry Andric   void DisplayFunction(const Decl *D, AnalysisMode Mode,
278*0b57cec5SDimitry Andric                        ExprEngine::InliningModes IMode) {
279*0b57cec5SDimitry Andric     if (!Opts->AnalyzerDisplayProgress)
280*0b57cec5SDimitry Andric       return;
281*0b57cec5SDimitry Andric 
282*0b57cec5SDimitry Andric     SourceManager &SM = Mgr->getASTContext().getSourceManager();
283*0b57cec5SDimitry Andric     PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
284*0b57cec5SDimitry Andric     if (Loc.isValid()) {
285*0b57cec5SDimitry Andric       llvm::errs() << "ANALYZE";
286*0b57cec5SDimitry Andric 
287*0b57cec5SDimitry Andric       if (Mode == AM_Syntax)
288*0b57cec5SDimitry Andric         llvm::errs() << " (Syntax)";
289*0b57cec5SDimitry Andric       else if (Mode == AM_Path) {
290*0b57cec5SDimitry Andric         llvm::errs() << " (Path, ";
291*0b57cec5SDimitry Andric         switch (IMode) {
292*0b57cec5SDimitry Andric           case ExprEngine::Inline_Minimal:
293*0b57cec5SDimitry Andric             llvm::errs() << " Inline_Minimal";
294*0b57cec5SDimitry Andric             break;
295*0b57cec5SDimitry Andric           case ExprEngine::Inline_Regular:
296*0b57cec5SDimitry Andric             llvm::errs() << " Inline_Regular";
297*0b57cec5SDimitry Andric             break;
298*0b57cec5SDimitry Andric         }
299*0b57cec5SDimitry Andric         llvm::errs() << ")";
300*0b57cec5SDimitry Andric       }
301*0b57cec5SDimitry Andric       else
302*0b57cec5SDimitry Andric         assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!");
303*0b57cec5SDimitry Andric 
304*0b57cec5SDimitry Andric       llvm::errs() << ": " << Loc.getFilename() << ' '
305*0b57cec5SDimitry Andric                            << getFunctionName(D) << '\n';
306*0b57cec5SDimitry Andric     }
307*0b57cec5SDimitry Andric   }
308*0b57cec5SDimitry Andric 
309*0b57cec5SDimitry Andric   void Initialize(ASTContext &Context) override {
310*0b57cec5SDimitry Andric     Ctx = &Context;
311*0b57cec5SDimitry Andric     checkerMgr = createCheckerManager(
312*0b57cec5SDimitry Andric         *Ctx, *Opts, Plugins, CheckerRegistrationFns, PP.getDiagnostics());
313*0b57cec5SDimitry Andric 
314*0b57cec5SDimitry Andric     Mgr = llvm::make_unique<AnalysisManager>(
315*0b57cec5SDimitry Andric         *Ctx, PP.getDiagnostics(), PathConsumers, CreateStoreMgr,
316*0b57cec5SDimitry Andric         CreateConstraintMgr, checkerMgr.get(), *Opts, Injector);
317*0b57cec5SDimitry Andric   }
318*0b57cec5SDimitry Andric 
319*0b57cec5SDimitry Andric   /// Store the top level decls in the set to be processed later on.
320*0b57cec5SDimitry Andric   /// (Doing this pre-processing avoids deserialization of data from PCH.)
321*0b57cec5SDimitry Andric   bool HandleTopLevelDecl(DeclGroupRef D) override;
322*0b57cec5SDimitry Andric   void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
323*0b57cec5SDimitry Andric 
324*0b57cec5SDimitry Andric   void HandleTranslationUnit(ASTContext &C) override;
325*0b57cec5SDimitry Andric 
326*0b57cec5SDimitry Andric   /// Determine which inlining mode should be used when this function is
327*0b57cec5SDimitry Andric   /// analyzed. This allows to redefine the default inlining policies when
328*0b57cec5SDimitry Andric   /// analyzing a given function.
329*0b57cec5SDimitry Andric   ExprEngine::InliningModes
330*0b57cec5SDimitry Andric     getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);
331*0b57cec5SDimitry Andric 
332*0b57cec5SDimitry Andric   /// Build the call graph for all the top level decls of this TU and
333*0b57cec5SDimitry Andric   /// use it to define the order in which the functions should be visited.
334*0b57cec5SDimitry Andric   void HandleDeclsCallGraph(const unsigned LocalTUDeclsSize);
335*0b57cec5SDimitry Andric 
336*0b57cec5SDimitry Andric   /// Run analyzes(syntax or path sensitive) on the given function.
337*0b57cec5SDimitry Andric   /// \param Mode - determines if we are requesting syntax only or path
338*0b57cec5SDimitry Andric   /// sensitive only analysis.
339*0b57cec5SDimitry Andric   /// \param VisitedCallees - The output parameter, which is populated with the
340*0b57cec5SDimitry Andric   /// set of functions which should be considered analyzed after analyzing the
341*0b57cec5SDimitry Andric   /// given root function.
342*0b57cec5SDimitry Andric   void HandleCode(Decl *D, AnalysisMode Mode,
343*0b57cec5SDimitry Andric                   ExprEngine::InliningModes IMode = ExprEngine::Inline_Minimal,
344*0b57cec5SDimitry Andric                   SetOfConstDecls *VisitedCallees = nullptr);
345*0b57cec5SDimitry Andric 
346*0b57cec5SDimitry Andric   void RunPathSensitiveChecks(Decl *D,
347*0b57cec5SDimitry Andric                               ExprEngine::InliningModes IMode,
348*0b57cec5SDimitry Andric                               SetOfConstDecls *VisitedCallees);
349*0b57cec5SDimitry Andric 
350*0b57cec5SDimitry Andric   /// Visitors for the RecursiveASTVisitor.
351*0b57cec5SDimitry Andric   bool shouldWalkTypesOfTypeLocs() const { return false; }
352*0b57cec5SDimitry Andric 
353*0b57cec5SDimitry Andric   /// Handle callbacks for arbitrary Decls.
354*0b57cec5SDimitry Andric   bool VisitDecl(Decl *D) {
355*0b57cec5SDimitry Andric     AnalysisMode Mode = getModeForDecl(D, RecVisitorMode);
356*0b57cec5SDimitry Andric     if (Mode & AM_Syntax) {
357*0b57cec5SDimitry Andric       if (SyntaxCheckTimer)
358*0b57cec5SDimitry Andric         SyntaxCheckTimer->startTimer();
359*0b57cec5SDimitry Andric       checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
360*0b57cec5SDimitry Andric       if (SyntaxCheckTimer)
361*0b57cec5SDimitry Andric         SyntaxCheckTimer->stopTimer();
362*0b57cec5SDimitry Andric     }
363*0b57cec5SDimitry Andric     return true;
364*0b57cec5SDimitry Andric   }
365*0b57cec5SDimitry Andric 
366*0b57cec5SDimitry Andric   bool VisitVarDecl(VarDecl *VD) {
367*0b57cec5SDimitry Andric     if (!Opts->IsNaiveCTUEnabled)
368*0b57cec5SDimitry Andric       return true;
369*0b57cec5SDimitry Andric 
370*0b57cec5SDimitry Andric     if (VD->hasExternalStorage() || VD->isStaticDataMember()) {
371*0b57cec5SDimitry Andric       if (!cross_tu::containsConst(VD, *Ctx))
372*0b57cec5SDimitry Andric         return true;
373*0b57cec5SDimitry Andric     } else {
374*0b57cec5SDimitry Andric       // Cannot be initialized in another TU.
375*0b57cec5SDimitry Andric       return true;
376*0b57cec5SDimitry Andric     }
377*0b57cec5SDimitry Andric 
378*0b57cec5SDimitry Andric     if (VD->getAnyInitializer())
379*0b57cec5SDimitry Andric       return true;
380*0b57cec5SDimitry Andric 
381*0b57cec5SDimitry Andric     llvm::Expected<const VarDecl *> CTUDeclOrError =
382*0b57cec5SDimitry Andric       CTU.getCrossTUDefinition(VD, Opts->CTUDir, Opts->CTUIndexName,
383*0b57cec5SDimitry Andric                                Opts->DisplayCTUProgress);
384*0b57cec5SDimitry Andric 
385*0b57cec5SDimitry Andric     if (!CTUDeclOrError) {
386*0b57cec5SDimitry Andric       handleAllErrors(CTUDeclOrError.takeError(),
387*0b57cec5SDimitry Andric                       [&](const cross_tu::IndexError &IE) {
388*0b57cec5SDimitry Andric                         CTU.emitCrossTUDiagnostics(IE);
389*0b57cec5SDimitry Andric                       });
390*0b57cec5SDimitry Andric     }
391*0b57cec5SDimitry Andric 
392*0b57cec5SDimitry Andric     return true;
393*0b57cec5SDimitry Andric   }
394*0b57cec5SDimitry Andric 
395*0b57cec5SDimitry Andric   bool VisitFunctionDecl(FunctionDecl *FD) {
396*0b57cec5SDimitry Andric     IdentifierInfo *II = FD->getIdentifier();
397*0b57cec5SDimitry Andric     if (II && II->getName().startswith("__inline"))
398*0b57cec5SDimitry Andric       return true;
399*0b57cec5SDimitry Andric 
400*0b57cec5SDimitry Andric     // We skip function template definitions, as their semantics is
401*0b57cec5SDimitry Andric     // only determined when they are instantiated.
402*0b57cec5SDimitry Andric     if (FD->isThisDeclarationADefinition() &&
403*0b57cec5SDimitry Andric         !FD->isDependentContext()) {
404*0b57cec5SDimitry Andric       assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
405*0b57cec5SDimitry Andric       HandleCode(FD, RecVisitorMode);
406*0b57cec5SDimitry Andric     }
407*0b57cec5SDimitry Andric     return true;
408*0b57cec5SDimitry Andric   }
409*0b57cec5SDimitry Andric 
410*0b57cec5SDimitry Andric   bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
411*0b57cec5SDimitry Andric     if (MD->isThisDeclarationADefinition()) {
412*0b57cec5SDimitry Andric       assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
413*0b57cec5SDimitry Andric       HandleCode(MD, RecVisitorMode);
414*0b57cec5SDimitry Andric     }
415*0b57cec5SDimitry Andric     return true;
416*0b57cec5SDimitry Andric   }
417*0b57cec5SDimitry Andric 
418*0b57cec5SDimitry Andric   bool VisitBlockDecl(BlockDecl *BD) {
419*0b57cec5SDimitry Andric     if (BD->hasBody()) {
420*0b57cec5SDimitry Andric       assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
421*0b57cec5SDimitry Andric       // Since we skip function template definitions, we should skip blocks
422*0b57cec5SDimitry Andric       // declared in those functions as well.
423*0b57cec5SDimitry Andric       if (!BD->isDependentContext()) {
424*0b57cec5SDimitry Andric         HandleCode(BD, RecVisitorMode);
425*0b57cec5SDimitry Andric       }
426*0b57cec5SDimitry Andric     }
427*0b57cec5SDimitry Andric     return true;
428*0b57cec5SDimitry Andric   }
429*0b57cec5SDimitry Andric 
430*0b57cec5SDimitry Andric   void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
431*0b57cec5SDimitry Andric     PathConsumers.push_back(Consumer);
432*0b57cec5SDimitry Andric   }
433*0b57cec5SDimitry Andric 
434*0b57cec5SDimitry Andric   void AddCheckerRegistrationFn(std::function<void(CheckerRegistry&)> Fn) override {
435*0b57cec5SDimitry Andric     CheckerRegistrationFns.push_back(std::move(Fn));
436*0b57cec5SDimitry Andric   }
437*0b57cec5SDimitry Andric 
438*0b57cec5SDimitry Andric private:
439*0b57cec5SDimitry Andric   void storeTopLevelDecls(DeclGroupRef DG);
440*0b57cec5SDimitry Andric   std::string getFunctionName(const Decl *D);
441*0b57cec5SDimitry Andric 
442*0b57cec5SDimitry Andric   /// Check if we should skip (not analyze) the given function.
443*0b57cec5SDimitry Andric   AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode);
444*0b57cec5SDimitry Andric   void runAnalysisOnTranslationUnit(ASTContext &C);
445*0b57cec5SDimitry Andric 
446*0b57cec5SDimitry Andric   /// Print \p S to stderr if \c Opts->AnalyzerDisplayProgress is set.
447*0b57cec5SDimitry Andric   void reportAnalyzerProgress(StringRef S);
448*0b57cec5SDimitry Andric };
449*0b57cec5SDimitry Andric } // end anonymous namespace
450*0b57cec5SDimitry Andric 
451*0b57cec5SDimitry Andric 
452*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
453*0b57cec5SDimitry Andric // AnalysisConsumer implementation.
454*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
455*0b57cec5SDimitry Andric bool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
456*0b57cec5SDimitry Andric   storeTopLevelDecls(DG);
457*0b57cec5SDimitry Andric   return true;
458*0b57cec5SDimitry Andric }
459*0b57cec5SDimitry Andric 
460*0b57cec5SDimitry Andric void AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
461*0b57cec5SDimitry Andric   storeTopLevelDecls(DG);
462*0b57cec5SDimitry Andric }
463*0b57cec5SDimitry Andric 
464*0b57cec5SDimitry Andric void AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) {
465*0b57cec5SDimitry Andric   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
466*0b57cec5SDimitry Andric 
467*0b57cec5SDimitry Andric     // Skip ObjCMethodDecl, wait for the objc container to avoid
468*0b57cec5SDimitry Andric     // analyzing twice.
469*0b57cec5SDimitry Andric     if (isa<ObjCMethodDecl>(*I))
470*0b57cec5SDimitry Andric       continue;
471*0b57cec5SDimitry Andric 
472*0b57cec5SDimitry Andric     LocalTUDecls.push_back(*I);
473*0b57cec5SDimitry Andric   }
474*0b57cec5SDimitry Andric }
475*0b57cec5SDimitry Andric 
476*0b57cec5SDimitry Andric static bool shouldSkipFunction(const Decl *D,
477*0b57cec5SDimitry Andric                                const SetOfConstDecls &Visited,
478*0b57cec5SDimitry Andric                                const SetOfConstDecls &VisitedAsTopLevel) {
479*0b57cec5SDimitry Andric   if (VisitedAsTopLevel.count(D))
480*0b57cec5SDimitry Andric     return true;
481*0b57cec5SDimitry Andric 
482*0b57cec5SDimitry Andric   // We want to re-analyse the functions as top level in the following cases:
483*0b57cec5SDimitry Andric   // - The 'init' methods should be reanalyzed because
484*0b57cec5SDimitry Andric   //   ObjCNonNilReturnValueChecker assumes that '[super init]' never returns
485*0b57cec5SDimitry Andric   //   'nil' and unless we analyze the 'init' functions as top level, we will
486*0b57cec5SDimitry Andric   //   not catch errors within defensive code.
487*0b57cec5SDimitry Andric   // - We want to reanalyze all ObjC methods as top level to report Retain
488*0b57cec5SDimitry Andric   //   Count naming convention errors more aggressively.
489*0b57cec5SDimitry Andric   if (isa<ObjCMethodDecl>(D))
490*0b57cec5SDimitry Andric     return false;
491*0b57cec5SDimitry Andric   // We also want to reanalyze all C++ copy and move assignment operators to
492*0b57cec5SDimitry Andric   // separately check the two cases where 'this' aliases with the parameter and
493*0b57cec5SDimitry Andric   // where it may not. (cplusplus.SelfAssignmentChecker)
494*0b57cec5SDimitry Andric   if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
495*0b57cec5SDimitry Andric     if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())
496*0b57cec5SDimitry Andric       return false;
497*0b57cec5SDimitry Andric   }
498*0b57cec5SDimitry Andric 
499*0b57cec5SDimitry Andric   // Otherwise, if we visited the function before, do not reanalyze it.
500*0b57cec5SDimitry Andric   return Visited.count(D);
501*0b57cec5SDimitry Andric }
502*0b57cec5SDimitry Andric 
503*0b57cec5SDimitry Andric ExprEngine::InliningModes
504*0b57cec5SDimitry Andric AnalysisConsumer::getInliningModeForFunction(const Decl *D,
505*0b57cec5SDimitry Andric                                              const SetOfConstDecls &Visited) {
506*0b57cec5SDimitry Andric   // We want to reanalyze all ObjC methods as top level to report Retain
507*0b57cec5SDimitry Andric   // Count naming convention errors more aggressively. But we should tune down
508*0b57cec5SDimitry Andric   // inlining when reanalyzing an already inlined function.
509*0b57cec5SDimitry Andric   if (Visited.count(D) && isa<ObjCMethodDecl>(D)) {
510*0b57cec5SDimitry Andric     const ObjCMethodDecl *ObjCM = cast<ObjCMethodDecl>(D);
511*0b57cec5SDimitry Andric     if (ObjCM->getMethodFamily() != OMF_init)
512*0b57cec5SDimitry Andric       return ExprEngine::Inline_Minimal;
513*0b57cec5SDimitry Andric   }
514*0b57cec5SDimitry Andric 
515*0b57cec5SDimitry Andric   return ExprEngine::Inline_Regular;
516*0b57cec5SDimitry Andric }
517*0b57cec5SDimitry Andric 
518*0b57cec5SDimitry Andric void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
519*0b57cec5SDimitry Andric   // Build the Call Graph by adding all the top level declarations to the graph.
520*0b57cec5SDimitry Andric   // Note: CallGraph can trigger deserialization of more items from a pch
521*0b57cec5SDimitry Andric   // (though HandleInterestingDecl); triggering additions to LocalTUDecls.
522*0b57cec5SDimitry Andric   // We rely on random access to add the initially processed Decls to CG.
523*0b57cec5SDimitry Andric   CallGraph CG;
524*0b57cec5SDimitry Andric   for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
525*0b57cec5SDimitry Andric     CG.addToCallGraph(LocalTUDecls[i]);
526*0b57cec5SDimitry Andric   }
527*0b57cec5SDimitry Andric 
528*0b57cec5SDimitry Andric   // Walk over all of the call graph nodes in topological order, so that we
529*0b57cec5SDimitry Andric   // analyze parents before the children. Skip the functions inlined into
530*0b57cec5SDimitry Andric   // the previously processed functions. Use external Visited set to identify
531*0b57cec5SDimitry Andric   // inlined functions. The topological order allows the "do not reanalyze
532*0b57cec5SDimitry Andric   // previously inlined function" performance heuristic to be triggered more
533*0b57cec5SDimitry Andric   // often.
534*0b57cec5SDimitry Andric   SetOfConstDecls Visited;
535*0b57cec5SDimitry Andric   SetOfConstDecls VisitedAsTopLevel;
536*0b57cec5SDimitry Andric   llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG);
537*0b57cec5SDimitry Andric   for (llvm::ReversePostOrderTraversal<clang::CallGraph*>::rpo_iterator
538*0b57cec5SDimitry Andric          I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
539*0b57cec5SDimitry Andric     NumFunctionTopLevel++;
540*0b57cec5SDimitry Andric 
541*0b57cec5SDimitry Andric     CallGraphNode *N = *I;
542*0b57cec5SDimitry Andric     Decl *D = N->getDecl();
543*0b57cec5SDimitry Andric 
544*0b57cec5SDimitry Andric     // Skip the abstract root node.
545*0b57cec5SDimitry Andric     if (!D)
546*0b57cec5SDimitry Andric       continue;
547*0b57cec5SDimitry Andric 
548*0b57cec5SDimitry Andric     // Skip the functions which have been processed already or previously
549*0b57cec5SDimitry Andric     // inlined.
550*0b57cec5SDimitry Andric     if (shouldSkipFunction(D, Visited, VisitedAsTopLevel))
551*0b57cec5SDimitry Andric       continue;
552*0b57cec5SDimitry Andric 
553*0b57cec5SDimitry Andric     // Analyze the function.
554*0b57cec5SDimitry Andric     SetOfConstDecls VisitedCallees;
555*0b57cec5SDimitry Andric 
556*0b57cec5SDimitry Andric     HandleCode(D, AM_Path, getInliningModeForFunction(D, Visited),
557*0b57cec5SDimitry Andric                (Mgr->options.InliningMode == All ? nullptr : &VisitedCallees));
558*0b57cec5SDimitry Andric 
559*0b57cec5SDimitry Andric     // Add the visited callees to the global visited set.
560*0b57cec5SDimitry Andric     for (const Decl *Callee : VisitedCallees)
561*0b57cec5SDimitry Andric       // Decls from CallGraph are already canonical. But Decls coming from
562*0b57cec5SDimitry Andric       // CallExprs may be not. We should canonicalize them manually.
563*0b57cec5SDimitry Andric       Visited.insert(isa<ObjCMethodDecl>(Callee) ? Callee
564*0b57cec5SDimitry Andric                                                  : Callee->getCanonicalDecl());
565*0b57cec5SDimitry Andric     VisitedAsTopLevel.insert(D);
566*0b57cec5SDimitry Andric   }
567*0b57cec5SDimitry Andric }
568*0b57cec5SDimitry Andric 
569*0b57cec5SDimitry Andric static bool isBisonFile(ASTContext &C) {
570*0b57cec5SDimitry Andric   const SourceManager &SM = C.getSourceManager();
571*0b57cec5SDimitry Andric   FileID FID = SM.getMainFileID();
572*0b57cec5SDimitry Andric   StringRef Buffer = SM.getBuffer(FID)->getBuffer();
573*0b57cec5SDimitry Andric   if (Buffer.startswith("/* A Bison parser, made by"))
574*0b57cec5SDimitry Andric     return true;
575*0b57cec5SDimitry Andric   return false;
576*0b57cec5SDimitry Andric }
577*0b57cec5SDimitry Andric 
578*0b57cec5SDimitry Andric void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) {
579*0b57cec5SDimitry Andric   BugReporter BR(*Mgr);
580*0b57cec5SDimitry Andric   TranslationUnitDecl *TU = C.getTranslationUnitDecl();
581*0b57cec5SDimitry Andric   if (SyntaxCheckTimer)
582*0b57cec5SDimitry Andric     SyntaxCheckTimer->startTimer();
583*0b57cec5SDimitry Andric   checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
584*0b57cec5SDimitry Andric   if (SyntaxCheckTimer)
585*0b57cec5SDimitry Andric     SyntaxCheckTimer->stopTimer();
586*0b57cec5SDimitry Andric 
587*0b57cec5SDimitry Andric   // Run the AST-only checks using the order in which functions are defined.
588*0b57cec5SDimitry Andric   // If inlining is not turned on, use the simplest function order for path
589*0b57cec5SDimitry Andric   // sensitive analyzes as well.
590*0b57cec5SDimitry Andric   RecVisitorMode = AM_Syntax;
591*0b57cec5SDimitry Andric   if (!Mgr->shouldInlineCall())
592*0b57cec5SDimitry Andric     RecVisitorMode |= AM_Path;
593*0b57cec5SDimitry Andric   RecVisitorBR = &BR;
594*0b57cec5SDimitry Andric 
595*0b57cec5SDimitry Andric   // Process all the top level declarations.
596*0b57cec5SDimitry Andric   //
597*0b57cec5SDimitry Andric   // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
598*0b57cec5SDimitry Andric   // entries.  Thus we don't use an iterator, but rely on LocalTUDecls
599*0b57cec5SDimitry Andric   // random access.  By doing so, we automatically compensate for iterators
600*0b57cec5SDimitry Andric   // possibly being invalidated, although this is a bit slower.
601*0b57cec5SDimitry Andric   const unsigned LocalTUDeclsSize = LocalTUDecls.size();
602*0b57cec5SDimitry Andric   for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
603*0b57cec5SDimitry Andric     TraverseDecl(LocalTUDecls[i]);
604*0b57cec5SDimitry Andric   }
605*0b57cec5SDimitry Andric 
606*0b57cec5SDimitry Andric   if (Mgr->shouldInlineCall())
607*0b57cec5SDimitry Andric     HandleDeclsCallGraph(LocalTUDeclsSize);
608*0b57cec5SDimitry Andric 
609*0b57cec5SDimitry Andric   // After all decls handled, run checkers on the entire TranslationUnit.
610*0b57cec5SDimitry Andric   checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
611*0b57cec5SDimitry Andric 
612*0b57cec5SDimitry Andric   RecVisitorBR = nullptr;
613*0b57cec5SDimitry Andric }
614*0b57cec5SDimitry Andric 
615*0b57cec5SDimitry Andric void AnalysisConsumer::reportAnalyzerProgress(StringRef S) {
616*0b57cec5SDimitry Andric   if (Opts->AnalyzerDisplayProgress)
617*0b57cec5SDimitry Andric     llvm::errs() << S;
618*0b57cec5SDimitry Andric }
619*0b57cec5SDimitry Andric 
620*0b57cec5SDimitry Andric void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
621*0b57cec5SDimitry Andric 
622*0b57cec5SDimitry Andric   // Don't run the actions if an error has occurred with parsing the file.
623*0b57cec5SDimitry Andric   DiagnosticsEngine &Diags = PP.getDiagnostics();
624*0b57cec5SDimitry Andric   if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
625*0b57cec5SDimitry Andric     return;
626*0b57cec5SDimitry Andric 
627*0b57cec5SDimitry Andric   if (isBisonFile(C)) {
628*0b57cec5SDimitry Andric     reportAnalyzerProgress("Skipping bison-generated file\n");
629*0b57cec5SDimitry Andric   } else if (Opts->DisableAllChecks) {
630*0b57cec5SDimitry Andric 
631*0b57cec5SDimitry Andric     // Don't analyze if the user explicitly asked for no checks to be performed
632*0b57cec5SDimitry Andric     // on this file.
633*0b57cec5SDimitry Andric     reportAnalyzerProgress("All checks are disabled using a supplied option\n");
634*0b57cec5SDimitry Andric   } else {
635*0b57cec5SDimitry Andric     // Otherwise, just run the analysis.
636*0b57cec5SDimitry Andric     runAnalysisOnTranslationUnit(C);
637*0b57cec5SDimitry Andric   }
638*0b57cec5SDimitry Andric 
639*0b57cec5SDimitry Andric   // Count how many basic blocks we have not covered.
640*0b57cec5SDimitry Andric   NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
641*0b57cec5SDimitry Andric   NumVisitedBlocksInAnalyzedFunctions =
642*0b57cec5SDimitry Andric       FunctionSummaries.getTotalNumVisitedBasicBlocks();
643*0b57cec5SDimitry Andric   if (NumBlocksInAnalyzedFunctions > 0)
644*0b57cec5SDimitry Andric     PercentReachableBlocks =
645*0b57cec5SDimitry Andric       (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
646*0b57cec5SDimitry Andric         NumBlocksInAnalyzedFunctions;
647*0b57cec5SDimitry Andric 
648*0b57cec5SDimitry Andric   // Explicitly destroy the PathDiagnosticConsumer.  This will flush its output.
649*0b57cec5SDimitry Andric   // FIXME: This should be replaced with something that doesn't rely on
650*0b57cec5SDimitry Andric   // side-effects in PathDiagnosticConsumer's destructor. This is required when
651*0b57cec5SDimitry Andric   // used with option -disable-free.
652*0b57cec5SDimitry Andric   Mgr.reset();
653*0b57cec5SDimitry Andric }
654*0b57cec5SDimitry Andric 
655*0b57cec5SDimitry Andric std::string AnalysisConsumer::getFunctionName(const Decl *D) {
656*0b57cec5SDimitry Andric   std::string Str;
657*0b57cec5SDimitry Andric   llvm::raw_string_ostream OS(Str);
658*0b57cec5SDimitry Andric 
659*0b57cec5SDimitry Andric   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
660*0b57cec5SDimitry Andric     OS << FD->getQualifiedNameAsString();
661*0b57cec5SDimitry Andric 
662*0b57cec5SDimitry Andric     // In C++, there are overloads.
663*0b57cec5SDimitry Andric     if (Ctx->getLangOpts().CPlusPlus) {
664*0b57cec5SDimitry Andric       OS << '(';
665*0b57cec5SDimitry Andric       for (const auto &P : FD->parameters()) {
666*0b57cec5SDimitry Andric         if (P != *FD->param_begin())
667*0b57cec5SDimitry Andric           OS << ", ";
668*0b57cec5SDimitry Andric         OS << P->getType().getAsString();
669*0b57cec5SDimitry Andric       }
670*0b57cec5SDimitry Andric       OS << ')';
671*0b57cec5SDimitry Andric     }
672*0b57cec5SDimitry Andric 
673*0b57cec5SDimitry Andric   } else if (isa<BlockDecl>(D)) {
674*0b57cec5SDimitry Andric     PresumedLoc Loc = Ctx->getSourceManager().getPresumedLoc(D->getLocation());
675*0b57cec5SDimitry Andric 
676*0b57cec5SDimitry Andric     if (Loc.isValid()) {
677*0b57cec5SDimitry Andric       OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
678*0b57cec5SDimitry Andric          << ')';
679*0b57cec5SDimitry Andric     }
680*0b57cec5SDimitry Andric 
681*0b57cec5SDimitry Andric   } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
682*0b57cec5SDimitry Andric 
683*0b57cec5SDimitry Andric     // FIXME: copy-pasted from CGDebugInfo.cpp.
684*0b57cec5SDimitry Andric     OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
685*0b57cec5SDimitry Andric     const DeclContext *DC = OMD->getDeclContext();
686*0b57cec5SDimitry Andric     if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
687*0b57cec5SDimitry Andric       OS << OID->getName();
688*0b57cec5SDimitry Andric     } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
689*0b57cec5SDimitry Andric       OS << OID->getName();
690*0b57cec5SDimitry Andric     } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
691*0b57cec5SDimitry Andric       if (OC->IsClassExtension()) {
692*0b57cec5SDimitry Andric         OS << OC->getClassInterface()->getName();
693*0b57cec5SDimitry Andric       } else {
694*0b57cec5SDimitry Andric         OS << OC->getIdentifier()->getNameStart() << '('
695*0b57cec5SDimitry Andric            << OC->getIdentifier()->getNameStart() << ')';
696*0b57cec5SDimitry Andric       }
697*0b57cec5SDimitry Andric     } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
698*0b57cec5SDimitry Andric       OS << OCD->getClassInterface()->getName() << '('
699*0b57cec5SDimitry Andric          << OCD->getName() << ')';
700*0b57cec5SDimitry Andric     } else if (isa<ObjCProtocolDecl>(DC)) {
701*0b57cec5SDimitry Andric       // We can extract the type of the class from the self pointer.
702*0b57cec5SDimitry Andric       if (ImplicitParamDecl *SelfDecl = OMD->getSelfDecl()) {
703*0b57cec5SDimitry Andric         QualType ClassTy =
704*0b57cec5SDimitry Andric             cast<ObjCObjectPointerType>(SelfDecl->getType())->getPointeeType();
705*0b57cec5SDimitry Andric         ClassTy.print(OS, PrintingPolicy(LangOptions()));
706*0b57cec5SDimitry Andric       }
707*0b57cec5SDimitry Andric     }
708*0b57cec5SDimitry Andric     OS << ' ' << OMD->getSelector().getAsString() << ']';
709*0b57cec5SDimitry Andric 
710*0b57cec5SDimitry Andric   }
711*0b57cec5SDimitry Andric 
712*0b57cec5SDimitry Andric   return OS.str();
713*0b57cec5SDimitry Andric }
714*0b57cec5SDimitry Andric 
715*0b57cec5SDimitry Andric AnalysisConsumer::AnalysisMode
716*0b57cec5SDimitry Andric AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
717*0b57cec5SDimitry Andric   if (!Opts->AnalyzeSpecificFunction.empty() &&
718*0b57cec5SDimitry Andric       getFunctionName(D) != Opts->AnalyzeSpecificFunction)
719*0b57cec5SDimitry Andric     return AM_None;
720*0b57cec5SDimitry Andric 
721*0b57cec5SDimitry Andric   // Unless -analyze-all is specified, treat decls differently depending on
722*0b57cec5SDimitry Andric   // where they came from:
723*0b57cec5SDimitry Andric   // - Main source file: run both path-sensitive and non-path-sensitive checks.
724*0b57cec5SDimitry Andric   // - Header files: run non-path-sensitive checks only.
725*0b57cec5SDimitry Andric   // - System headers: don't run any checks.
726*0b57cec5SDimitry Andric   SourceManager &SM = Ctx->getSourceManager();
727*0b57cec5SDimitry Andric   const Stmt *Body = D->getBody();
728*0b57cec5SDimitry Andric   SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation();
729*0b57cec5SDimitry Andric   SL = SM.getExpansionLoc(SL);
730*0b57cec5SDimitry Andric 
731*0b57cec5SDimitry Andric   if (!Opts->AnalyzeAll && !Mgr->isInCodeFile(SL)) {
732*0b57cec5SDimitry Andric     if (SL.isInvalid() || SM.isInSystemHeader(SL))
733*0b57cec5SDimitry Andric       return AM_None;
734*0b57cec5SDimitry Andric     return Mode & ~AM_Path;
735*0b57cec5SDimitry Andric   }
736*0b57cec5SDimitry Andric 
737*0b57cec5SDimitry Andric   return Mode;
738*0b57cec5SDimitry Andric }
739*0b57cec5SDimitry Andric 
740*0b57cec5SDimitry Andric void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
741*0b57cec5SDimitry Andric                                   ExprEngine::InliningModes IMode,
742*0b57cec5SDimitry Andric                                   SetOfConstDecls *VisitedCallees) {
743*0b57cec5SDimitry Andric   if (!D->hasBody())
744*0b57cec5SDimitry Andric     return;
745*0b57cec5SDimitry Andric   Mode = getModeForDecl(D, Mode);
746*0b57cec5SDimitry Andric   if (Mode == AM_None)
747*0b57cec5SDimitry Andric     return;
748*0b57cec5SDimitry Andric 
749*0b57cec5SDimitry Andric   // Clear the AnalysisManager of old AnalysisDeclContexts.
750*0b57cec5SDimitry Andric   Mgr->ClearContexts();
751*0b57cec5SDimitry Andric   // Ignore autosynthesized code.
752*0b57cec5SDimitry Andric   if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized())
753*0b57cec5SDimitry Andric     return;
754*0b57cec5SDimitry Andric 
755*0b57cec5SDimitry Andric   DisplayFunction(D, Mode, IMode);
756*0b57cec5SDimitry Andric   CFG *DeclCFG = Mgr->getCFG(D);
757*0b57cec5SDimitry Andric   if (DeclCFG)
758*0b57cec5SDimitry Andric     MaxCFGSize.updateMax(DeclCFG->size());
759*0b57cec5SDimitry Andric 
760*0b57cec5SDimitry Andric   BugReporter BR(*Mgr);
761*0b57cec5SDimitry Andric 
762*0b57cec5SDimitry Andric   if (Mode & AM_Syntax) {
763*0b57cec5SDimitry Andric     if (SyntaxCheckTimer)
764*0b57cec5SDimitry Andric       SyntaxCheckTimer->startTimer();
765*0b57cec5SDimitry Andric     checkerMgr->runCheckersOnASTBody(D, *Mgr, BR);
766*0b57cec5SDimitry Andric     if (SyntaxCheckTimer)
767*0b57cec5SDimitry Andric       SyntaxCheckTimer->stopTimer();
768*0b57cec5SDimitry Andric   }
769*0b57cec5SDimitry Andric   if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
770*0b57cec5SDimitry Andric     RunPathSensitiveChecks(D, IMode, VisitedCallees);
771*0b57cec5SDimitry Andric     if (IMode != ExprEngine::Inline_Minimal)
772*0b57cec5SDimitry Andric       NumFunctionsAnalyzed++;
773*0b57cec5SDimitry Andric   }
774*0b57cec5SDimitry Andric }
775*0b57cec5SDimitry Andric 
776*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
777*0b57cec5SDimitry Andric // Path-sensitive checking.
778*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
779*0b57cec5SDimitry Andric 
780*0b57cec5SDimitry Andric void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
781*0b57cec5SDimitry Andric                                               ExprEngine::InliningModes IMode,
782*0b57cec5SDimitry Andric                                               SetOfConstDecls *VisitedCallees) {
783*0b57cec5SDimitry Andric   // Construct the analysis engine.  First check if the CFG is valid.
784*0b57cec5SDimitry Andric   // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
785*0b57cec5SDimitry Andric   if (!Mgr->getCFG(D))
786*0b57cec5SDimitry Andric     return;
787*0b57cec5SDimitry Andric 
788*0b57cec5SDimitry Andric   // See if the LiveVariables analysis scales.
789*0b57cec5SDimitry Andric   if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
790*0b57cec5SDimitry Andric     return;
791*0b57cec5SDimitry Andric 
792*0b57cec5SDimitry Andric   ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);
793*0b57cec5SDimitry Andric 
794*0b57cec5SDimitry Andric   // Execute the worklist algorithm.
795*0b57cec5SDimitry Andric   if (ExprEngineTimer)
796*0b57cec5SDimitry Andric     ExprEngineTimer->startTimer();
797*0b57cec5SDimitry Andric   Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
798*0b57cec5SDimitry Andric                       Mgr->options.MaxNodesPerTopLevelFunction);
799*0b57cec5SDimitry Andric   if (ExprEngineTimer)
800*0b57cec5SDimitry Andric     ExprEngineTimer->stopTimer();
801*0b57cec5SDimitry Andric 
802*0b57cec5SDimitry Andric   if (!Mgr->options.DumpExplodedGraphTo.empty())
803*0b57cec5SDimitry Andric     Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
804*0b57cec5SDimitry Andric 
805*0b57cec5SDimitry Andric   // Visualize the exploded graph.
806*0b57cec5SDimitry Andric   if (Mgr->options.visualizeExplodedGraphWithGraphViz)
807*0b57cec5SDimitry Andric     Eng.ViewGraph(Mgr->options.TrimGraph);
808*0b57cec5SDimitry Andric 
809*0b57cec5SDimitry Andric   // Display warnings.
810*0b57cec5SDimitry Andric   if (BugReporterTimer)
811*0b57cec5SDimitry Andric     BugReporterTimer->startTimer();
812*0b57cec5SDimitry Andric   Eng.getBugReporter().FlushReports();
813*0b57cec5SDimitry Andric   if (BugReporterTimer)
814*0b57cec5SDimitry Andric     BugReporterTimer->stopTimer();
815*0b57cec5SDimitry Andric }
816*0b57cec5SDimitry Andric 
817*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
818*0b57cec5SDimitry Andric // AnalysisConsumer creation.
819*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
820*0b57cec5SDimitry Andric 
821*0b57cec5SDimitry Andric std::unique_ptr<AnalysisASTConsumer>
822*0b57cec5SDimitry Andric ento::CreateAnalysisConsumer(CompilerInstance &CI) {
823*0b57cec5SDimitry Andric   // Disable the effects of '-Werror' when using the AnalysisConsumer.
824*0b57cec5SDimitry Andric   CI.getPreprocessor().getDiagnostics().setWarningsAsErrors(false);
825*0b57cec5SDimitry Andric 
826*0b57cec5SDimitry Andric   AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
827*0b57cec5SDimitry Andric   bool hasModelPath = analyzerOpts->Config.count("model-path") > 0;
828*0b57cec5SDimitry Andric 
829*0b57cec5SDimitry Andric   return llvm::make_unique<AnalysisConsumer>(
830*0b57cec5SDimitry Andric       CI, CI.getFrontendOpts().OutputFile, analyzerOpts,
831*0b57cec5SDimitry Andric       CI.getFrontendOpts().Plugins,
832*0b57cec5SDimitry Andric       hasModelPath ? new ModelInjector(CI) : nullptr);
833*0b57cec5SDimitry Andric }
834