clang 18.0.0git
AnalysisConsumer.cpp
Go to the documentation of this file.
1//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// "Meta" ASTConsumer for running different source analyses.
10//
11//===----------------------------------------------------------------------===//
12
14#include "ModelInjector.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclObjC.h"
20#include "clang/Analysis/CFG.h"
36#include "llvm/ADT/PostOrderIterator.h"
37#include "llvm/ADT/ScopeExit.h"
38#include "llvm/ADT/Statistic.h"
39#include "llvm/Support/FileSystem.h"
40#include "llvm/Support/Path.h"
41#include "llvm/Support/Program.h"
42#include "llvm/Support/Timer.h"
43#include "llvm/Support/raw_ostream.h"
44#include <memory>
45#include <queue>
46#include <utility>
47
48using namespace clang;
49using namespace ento;
50
51#define DEBUG_TYPE "AnalysisConsumer"
52
53STATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
54STATISTIC(NumFunctionsAnalyzed,
55 "The # of functions and blocks analyzed (as top level "
56 "with inlining turned on).");
57STATISTIC(NumBlocksInAnalyzedFunctions,
58 "The # of basic blocks in the analyzed functions.");
59STATISTIC(NumVisitedBlocksInAnalyzedFunctions,
60 "The # of visited basic blocks in the analyzed functions.");
61STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
62STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");
63
64//===----------------------------------------------------------------------===//
65// AnalysisConsumer declaration.
66//===----------------------------------------------------------------------===//
67
68namespace {
69
70class AnalysisConsumer : public AnalysisASTConsumer,
71 public RecursiveASTVisitor<AnalysisConsumer> {
72 enum {
73 AM_None = 0,
74 AM_Syntax = 0x1,
75 AM_Path = 0x2
76 };
77 typedef unsigned AnalysisMode;
78
79 /// Mode of the analyzes while recursively visiting Decls.
80 AnalysisMode RecVisitorMode;
81 /// Bug Reporter to use while recursively visiting Decls.
82 BugReporter *RecVisitorBR;
83
84 std::vector<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns;
85
86public:
87 ASTContext *Ctx;
88 Preprocessor &PP;
89 const std::string OutDir;
90 AnalyzerOptions &Opts;
92 CodeInjector *Injector;
94
95 /// Stores the declarations from the local translation unit.
96 /// Note, we pre-compute the local declarations at parse time as an
97 /// optimization to make sure we do not deserialize everything from disk.
98 /// The local declaration to all declarations ratio might be very small when
99 /// working with a PCH file.
100 SetOfDecls LocalTUDecls;
101
102 MacroExpansionContext MacroExpansions;
103
104 // Set of PathDiagnosticConsumers. Owned by AnalysisManager.
105 PathDiagnosticConsumers PathConsumers;
106
107 StoreManagerCreator CreateStoreMgr;
108 ConstraintManagerCreator CreateConstraintMgr;
109
110 std::unique_ptr<CheckerManager> checkerMgr;
111 std::unique_ptr<AnalysisManager> Mgr;
112
113 /// Time the analyzes time of each translation unit.
114 std::unique_ptr<llvm::TimerGroup> AnalyzerTimers;
115 std::unique_ptr<llvm::Timer> SyntaxCheckTimer;
116 std::unique_ptr<llvm::Timer> ExprEngineTimer;
117 std::unique_ptr<llvm::Timer> BugReporterTimer;
118
119 /// The information about analyzed functions shared throughout the
120 /// translation unit.
121 FunctionSummariesTy FunctionSummaries;
122
123 AnalysisConsumer(CompilerInstance &CI, const std::string &outdir,
125 CodeInjector *injector)
126 : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr),
127 PP(CI.getPreprocessor()), OutDir(outdir), Opts(opts),
128 Plugins(plugins), Injector(injector), CTU(CI),
129 MacroExpansions(CI.getLangOpts()) {
130 DigestAnalyzerOptions();
131 if (Opts.AnalyzerDisplayProgress || Opts.PrintStats ||
132 Opts.ShouldSerializeStats) {
133 AnalyzerTimers = std::make_unique<llvm::TimerGroup>(
134 "analyzer", "Analyzer timers");
135 SyntaxCheckTimer = std::make_unique<llvm::Timer>(
136 "syntaxchecks", "Syntax-based analysis time", *AnalyzerTimers);
137 ExprEngineTimer = std::make_unique<llvm::Timer>(
138 "exprengine", "Path exploration time", *AnalyzerTimers);
139 BugReporterTimer = std::make_unique<llvm::Timer>(
140 "bugreporter", "Path-sensitive report post-processing time",
141 *AnalyzerTimers);
142 }
143
144 if (Opts.PrintStats || Opts.ShouldSerializeStats) {
145 llvm::EnableStatistics(/* DoPrintOnExit= */ false);
146 }
147
148 if (Opts.ShouldDisplayMacroExpansions)
149 MacroExpansions.registerForPreprocessor(PP);
150 }
151
152 ~AnalysisConsumer() override {
153 if (Opts.PrintStats) {
154 llvm::PrintStatistics();
155 }
156 }
157
158 void DigestAnalyzerOptions() {
159 switch (Opts.AnalysisDiagOpt) {
160 case PD_NONE:
161 break;
162#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
163 case PD_##NAME: \
164 CREATEFN(Opts.getDiagOpts(), PathConsumers, OutDir, PP, CTU, \
165 MacroExpansions); \
166 break;
167#include "clang/StaticAnalyzer/Core/Analyses.def"
168 default:
169 llvm_unreachable("Unknown analyzer output type!");
170 }
171
172 // Create the analyzer component creators.
173 CreateStoreMgr = &CreateRegionStoreManager;
174
175 switch (Opts.AnalysisConstraintsOpt) {
176 default:
177 llvm_unreachable("Unknown constraint manager.");
178#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
179 case NAME##Model: CreateConstraintMgr = CREATEFN; break;
180#include "clang/StaticAnalyzer/Core/Analyses.def"
181 }
182 }
183
184 void DisplayTime(llvm::TimeRecord &Time) {
185 if (!Opts.AnalyzerDisplayProgress) {
186 return;
187 }
188 llvm::errs() << " : " << llvm::format("%1.1f", Time.getWallTime() * 1000)
189 << " ms\n";
190 }
191
192 void DisplayFunction(const Decl *D, AnalysisMode Mode,
194 if (!Opts.AnalyzerDisplayProgress)
195 return;
196
197 SourceManager &SM = Mgr->getASTContext().getSourceManager();
198 PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
199 if (Loc.isValid()) {
200 llvm::errs() << "ANALYZE";
201
202 if (Mode == AM_Syntax)
203 llvm::errs() << " (Syntax)";
204 else if (Mode == AM_Path) {
205 llvm::errs() << " (Path, ";
206 switch (IMode) {
208 llvm::errs() << " Inline_Minimal";
209 break;
211 llvm::errs() << " Inline_Regular";
212 break;
213 }
214 llvm::errs() << ")";
215 } else
216 assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!");
217
218 llvm::errs() << ": " << Loc.getFilename() << ' '
220 }
221 }
222
223 void Initialize(ASTContext &Context) override {
224 Ctx = &Context;
225 checkerMgr = std::make_unique<CheckerManager>(*Ctx, Opts, PP, Plugins,
226 CheckerRegistrationFns);
227
228 Mgr = std::make_unique<AnalysisManager>(*Ctx, PP, PathConsumers,
229 CreateStoreMgr, CreateConstraintMgr,
230 checkerMgr.get(), Opts, Injector);
231 }
232
233 /// Store the top level decls in the set to be processed later on.
234 /// (Doing this pre-processing avoids deserialization of data from PCH.)
235 bool HandleTopLevelDecl(DeclGroupRef D) override;
237
238 void HandleTranslationUnit(ASTContext &C) override;
239
240 /// Determine which inlining mode should be used when this function is
241 /// analyzed. This allows to redefine the default inlining policies when
242 /// analyzing a given function.
244 getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);
245
246 /// Build the call graph for all the top level decls of this TU and
247 /// use it to define the order in which the functions should be visited.
248 void HandleDeclsCallGraph(const unsigned LocalTUDeclsSize);
249
250 /// Run analyzes(syntax or path sensitive) on the given function.
251 /// \param Mode - determines if we are requesting syntax only or path
252 /// sensitive only analysis.
253 /// \param VisitedCallees - The output parameter, which is populated with the
254 /// set of functions which should be considered analyzed after analyzing the
255 /// given root function.
256 void HandleCode(Decl *D, AnalysisMode Mode,
258 SetOfConstDecls *VisitedCallees = nullptr);
259
260 void RunPathSensitiveChecks(Decl *D,
262 SetOfConstDecls *VisitedCallees);
263
264 /// Visitors for the RecursiveASTVisitor.
265 bool shouldWalkTypesOfTypeLocs() const { return false; }
266
267 /// Handle callbacks for arbitrary Decls.
268 bool VisitDecl(Decl *D) {
269 AnalysisMode Mode = getModeForDecl(D, RecVisitorMode);
270 if (Mode & AM_Syntax) {
271 if (SyntaxCheckTimer)
272 SyntaxCheckTimer->startTimer();
273 checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
274 if (SyntaxCheckTimer)
275 SyntaxCheckTimer->stopTimer();
276 }
277 return true;
278 }
279
280 bool VisitVarDecl(VarDecl *VD) {
281 if (!Opts.IsNaiveCTUEnabled)
282 return true;
283
284 if (VD->hasExternalStorage() || VD->isStaticDataMember()) {
285 if (!cross_tu::shouldImport(VD, *Ctx))
286 return true;
287 } else {
288 // Cannot be initialized in another TU.
289 return true;
290 }
291
292 if (VD->getAnyInitializer())
293 return true;
294
295 llvm::Expected<const VarDecl *> CTUDeclOrError =
296 CTU.getCrossTUDefinition(VD, Opts.CTUDir, Opts.CTUIndexName,
297 Opts.DisplayCTUProgress);
298
299 if (!CTUDeclOrError) {
300 handleAllErrors(CTUDeclOrError.takeError(),
301 [&](const cross_tu::IndexError &IE) {
302 CTU.emitCrossTUDiagnostics(IE);
303 });
304 }
305
306 return true;
307 }
308
309 bool VisitFunctionDecl(FunctionDecl *FD) {
310 IdentifierInfo *II = FD->getIdentifier();
311 if (II && II->getName().startswith("__inline"))
312 return true;
313
314 // We skip function template definitions, as their semantics is
315 // only determined when they are instantiated.
317 !FD->isDependentContext()) {
318 assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
319 HandleCode(FD, RecVisitorMode);
320 }
321 return true;
322 }
323
324 bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
326 assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
327 HandleCode(MD, RecVisitorMode);
328 }
329 return true;
330 }
331
332 bool VisitBlockDecl(BlockDecl *BD) {
333 if (BD->hasBody()) {
334 assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
335 // Since we skip function template definitions, we should skip blocks
336 // declared in those functions as well.
337 if (!BD->isDependentContext()) {
338 HandleCode(BD, RecVisitorMode);
339 }
340 }
341 return true;
342 }
343
344 void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
345 PathConsumers.push_back(Consumer);
346 }
347
348 void AddCheckerRegistrationFn(std::function<void(CheckerRegistry&)> Fn) override {
349 CheckerRegistrationFns.push_back(std::move(Fn));
350 }
351
352private:
353 void storeTopLevelDecls(DeclGroupRef DG);
354
355 /// Check if we should skip (not analyze) the given function.
356 AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode);
357 void runAnalysisOnTranslationUnit(ASTContext &C);
358
359 /// Print \p S to stderr if \c Opts.AnalyzerDisplayProgress is set.
360 void reportAnalyzerProgress(StringRef S);
361}; // namespace
362} // end anonymous namespace
363
364
365//===----------------------------------------------------------------------===//
366// AnalysisConsumer implementation.
367//===----------------------------------------------------------------------===//
368bool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
369 storeTopLevelDecls(DG);
370 return true;
371}
372
373void AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
374 storeTopLevelDecls(DG);
375}
376
377void AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) {
378 for (auto &I : DG) {
379
380 // Skip ObjCMethodDecl, wait for the objc container to avoid
381 // analyzing twice.
382 if (isa<ObjCMethodDecl>(I))
383 continue;
384
385 LocalTUDecls.push_back(I);
386 }
387}
388
389static bool shouldSkipFunction(const Decl *D,
391 const SetOfConstDecls &VisitedAsTopLevel) {
392 if (VisitedAsTopLevel.count(D))
393 return true;
394
395 // Skip analysis of inheriting constructors as top-level functions. These
396 // constructors don't even have a body written down in the code, so even if
397 // we find a bug, we won't be able to display it.
398 if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
399 if (CD->isInheritingConstructor())
400 return true;
401
402 // We want to re-analyse the functions as top level in the following cases:
403 // - The 'init' methods should be reanalyzed because
404 // ObjCNonNilReturnValueChecker assumes that '[super init]' never returns
405 // 'nil' and unless we analyze the 'init' functions as top level, we will
406 // not catch errors within defensive code.
407 // - We want to reanalyze all ObjC methods as top level to report Retain
408 // Count naming convention errors more aggressively.
409 if (isa<ObjCMethodDecl>(D))
410 return false;
411 // We also want to reanalyze all C++ copy and move assignment operators to
412 // separately check the two cases where 'this' aliases with the parameter and
413 // where it may not. (cplusplus.SelfAssignmentChecker)
414 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
415 if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())
416 return false;
417 }
418
419 // Otherwise, if we visited the function before, do not reanalyze it.
420 return Visited.count(D);
421}
422
424AnalysisConsumer::getInliningModeForFunction(const Decl *D,
425 const SetOfConstDecls &Visited) {
426 // We want to reanalyze all ObjC methods as top level to report Retain
427 // Count naming convention errors more aggressively. But we should tune down
428 // inlining when reanalyzing an already inlined function.
429 if (Visited.count(D) && isa<ObjCMethodDecl>(D)) {
430 const ObjCMethodDecl *ObjCM = cast<ObjCMethodDecl>(D);
431 if (ObjCM->getMethodFamily() != OMF_init)
433 }
434
436}
437
438void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
439 // Build the Call Graph by adding all the top level declarations to the graph.
440 // Note: CallGraph can trigger deserialization of more items from a pch
441 // (though HandleInterestingDecl); triggering additions to LocalTUDecls.
442 // We rely on random access to add the initially processed Decls to CG.
443 CallGraph CG;
444 for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
445 CG.addToCallGraph(LocalTUDecls[i]);
446 }
447
448 // Walk over all of the call graph nodes in topological order, so that we
449 // analyze parents before the children. Skip the functions inlined into
450 // the previously processed functions. Use external Visited set to identify
451 // inlined functions. The topological order allows the "do not reanalyze
452 // previously inlined function" performance heuristic to be triggered more
453 // often.
455 SetOfConstDecls VisitedAsTopLevel;
456 llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG);
457 for (auto &N : RPOT) {
458 NumFunctionTopLevel++;
459
460 Decl *D = N->getDecl();
461
462 // Skip the abstract root node.
463 if (!D)
464 continue;
465
466 // Skip the functions which have been processed already or previously
467 // inlined.
468 if (shouldSkipFunction(D, Visited, VisitedAsTopLevel))
469 continue;
470
471 // The CallGraph might have declarations as callees. However, during CTU
472 // the declaration might form a declaration chain with the newly imported
473 // definition from another TU. In this case we don't want to analyze the
474 // function definition as toplevel.
475 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
476 // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
477 // that has the body.
478 FD->hasBody(FD);
479 if (CTU.isImportedAsNew(FD))
480 continue;
481 }
482
483 // Analyze the function.
484 SetOfConstDecls VisitedCallees;
485
486 HandleCode(D, AM_Path, getInliningModeForFunction(D, Visited),
487 (Mgr->options.InliningMode == All ? nullptr : &VisitedCallees));
488
489 // Add the visited callees to the global visited set.
490 for (const Decl *Callee : VisitedCallees)
491 // Decls from CallGraph are already canonical. But Decls coming from
492 // CallExprs may be not. We should canonicalize them manually.
493 Visited.insert(isa<ObjCMethodDecl>(Callee) ? Callee
494 : Callee->getCanonicalDecl());
495 VisitedAsTopLevel.insert(D);
496 }
497}
498
499static bool fileContainsString(StringRef Substring, ASTContext &C) {
500 const SourceManager &SM = C.getSourceManager();
501 FileID FID = SM.getMainFileID();
502 StringRef Buffer = SM.getBufferOrFake(FID).getBuffer();
503 return Buffer.contains(Substring);
504}
505
507 const ASTContext &Ctx) {
508 llvm::errs() << "Every top-level function was skipped.\n";
509
510 if (!Opts.AnalyzerDisplayProgress)
511 llvm::errs() << "Pass the -analyzer-display-progress for tracking which "
512 "functions are analyzed.\n";
513
514 bool HasBrackets =
515 Opts.AnalyzeSpecificFunction.find("(") != std::string::npos;
516
517 if (Ctx.getLangOpts().CPlusPlus && !HasBrackets) {
518 llvm::errs()
519 << "For analyzing C++ code you need to pass the function parameter "
520 "list: -analyze-function=\"foobar(int, _Bool)\"\n";
521 } else if (!Ctx.getLangOpts().CPlusPlus && HasBrackets) {
522 llvm::errs() << "For analyzing C code you shouldn't pass the function "
523 "parameter list, only the name of the function: "
524 "-analyze-function=foobar\n";
525 }
526}
527
528void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) {
529 BugReporter BR(*Mgr);
530 TranslationUnitDecl *TU = C.getTranslationUnitDecl();
531 if (SyntaxCheckTimer)
532 SyntaxCheckTimer->startTimer();
533 checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
534 if (SyntaxCheckTimer)
535 SyntaxCheckTimer->stopTimer();
536
537 // Run the AST-only checks using the order in which functions are defined.
538 // If inlining is not turned on, use the simplest function order for path
539 // sensitive analyzes as well.
540 RecVisitorMode = AM_Syntax;
541 if (!Mgr->shouldInlineCall())
542 RecVisitorMode |= AM_Path;
543 RecVisitorBR = &BR;
544
545 // Process all the top level declarations.
546 //
547 // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
548 // entries. Thus we don't use an iterator, but rely on LocalTUDecls
549 // random access. By doing so, we automatically compensate for iterators
550 // possibly being invalidated, although this is a bit slower.
551 const unsigned LocalTUDeclsSize = LocalTUDecls.size();
552 for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
553 TraverseDecl(LocalTUDecls[i]);
554 }
555
556 if (Mgr->shouldInlineCall())
557 HandleDeclsCallGraph(LocalTUDeclsSize);
558
559 // After all decls handled, run checkers on the entire TranslationUnit.
560 checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
561
562 BR.FlushReports();
563 RecVisitorBR = nullptr;
564
565 // If the user wanted to analyze a specific function and the number of basic
566 // blocks analyzed is zero, than the user might not specified the function
567 // name correctly.
568 // FIXME: The user might have analyzed the requested function in Syntax mode,
569 // but we are unaware of that.
570 if (!Opts.AnalyzeSpecificFunction.empty() && NumFunctionsAnalyzed == 0)
572}
573
574void AnalysisConsumer::reportAnalyzerProgress(StringRef S) {
576 llvm::errs() << S;
577}
578
579void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
580 // Don't run the actions if an error has occurred with parsing the file.
581 DiagnosticsEngine &Diags = PP.getDiagnostics();
582 if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
583 return;
584
585 // Explicitly destroy the PathDiagnosticConsumer. This will flush its output.
586 // FIXME: This should be replaced with something that doesn't rely on
587 // side-effects in PathDiagnosticConsumer's destructor. This is required when
588 // used with option -disable-free.
589 const auto DiagFlusherScopeExit =
590 llvm::make_scope_exit([this] { Mgr.reset(); });
591
592 if (Opts.ShouldIgnoreBisonGeneratedFiles &&
593 fileContainsString("/* A Bison parser, made by", C)) {
594 reportAnalyzerProgress("Skipping bison-generated file\n");
595 return;
596 }
597
598 if (Opts.ShouldIgnoreFlexGeneratedFiles &&
599 fileContainsString("/* A lexical scanner generated by flex", C)) {
600 reportAnalyzerProgress("Skipping flex-generated file\n");
601 return;
602 }
603
604 // Don't analyze if the user explicitly asked for no checks to be performed
605 // on this file.
606 if (Opts.DisableAllCheckers) {
607 reportAnalyzerProgress("All checks are disabled using a supplied option\n");
608 return;
609 }
610
611 // Otherwise, just run the analysis.
612 runAnalysisOnTranslationUnit(C);
613
614 // Count how many basic blocks we have not covered.
615 NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
616 NumVisitedBlocksInAnalyzedFunctions =
617 FunctionSummaries.getTotalNumVisitedBasicBlocks();
618 if (NumBlocksInAnalyzedFunctions > 0)
619 PercentReachableBlocks =
620 (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
621 NumBlocksInAnalyzedFunctions;
622}
623
624AnalysisConsumer::AnalysisMode
625AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
626 if (!Opts.AnalyzeSpecificFunction.empty() &&
628 return AM_None;
629
630 // Unless -analyze-all is specified, treat decls differently depending on
631 // where they came from:
632 // - Main source file: run both path-sensitive and non-path-sensitive checks.
633 // - Header files: run non-path-sensitive checks only.
634 // - System headers: don't run any checks.
635 if (Opts.AnalyzeAll)
636 return Mode;
637
638 const SourceManager &SM = Ctx->getSourceManager();
639
640 const SourceLocation Loc = [&SM](Decl *D) -> SourceLocation {
641 const Stmt *Body = D->getBody();
642 SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation();
643 return SM.getExpansionLoc(SL);
644 }(D);
645
646 // Ignore system headers.
647 if (Loc.isInvalid() || SM.isInSystemHeader(Loc))
648 return AM_None;
649
650 // Disable path sensitive analysis in user-headers.
651 if (!Mgr->isInCodeFile(Loc))
652 return Mode & ~AM_Path;
653
654 return Mode;
655}
656
657void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
659 SetOfConstDecls *VisitedCallees) {
660 if (!D->hasBody())
661 return;
662 Mode = getModeForDecl(D, Mode);
663 if (Mode == AM_None)
664 return;
665
666 // Clear the AnalysisManager of old AnalysisDeclContexts.
667 Mgr->ClearContexts();
668 // Ignore autosynthesized code.
669 if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized())
670 return;
671
672 CFG *DeclCFG = Mgr->getCFG(D);
673 if (DeclCFG)
674 MaxCFGSize.updateMax(DeclCFG->size());
675
676 DisplayFunction(D, Mode, IMode);
677 BugReporter BR(*Mgr);
678
679 if (Mode & AM_Syntax) {
680 llvm::TimeRecord CheckerStartTime;
681 if (SyntaxCheckTimer) {
682 CheckerStartTime = SyntaxCheckTimer->getTotalTime();
683 SyntaxCheckTimer->startTimer();
684 }
685 checkerMgr->runCheckersOnASTBody(D, *Mgr, BR);
686 if (SyntaxCheckTimer) {
687 SyntaxCheckTimer->stopTimer();
688 llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime();
689 CheckerEndTime -= CheckerStartTime;
690 DisplayTime(CheckerEndTime);
691 }
692 }
693
694 BR.FlushReports();
695
696 if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
697 RunPathSensitiveChecks(D, IMode, VisitedCallees);
698 if (IMode != ExprEngine::Inline_Minimal)
699 NumFunctionsAnalyzed++;
700 }
701}
702
703//===----------------------------------------------------------------------===//
704// Path-sensitive checking.
705//===----------------------------------------------------------------------===//
706
707void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
709 SetOfConstDecls *VisitedCallees) {
710 // Construct the analysis engine. First check if the CFG is valid.
711 // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
712 if (!Mgr->getCFG(D))
713 return;
714
715 // See if the LiveVariables analysis scales.
716 if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
717 return;
718
719 ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);
720
721 // Execute the worklist algorithm.
722 llvm::TimeRecord ExprEngineStartTime;
723 if (ExprEngineTimer) {
724 ExprEngineStartTime = ExprEngineTimer->getTotalTime();
725 ExprEngineTimer->startTimer();
726 }
727 Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
728 Mgr->options.MaxNodesPerTopLevelFunction);
729 if (ExprEngineTimer) {
730 ExprEngineTimer->stopTimer();
731 llvm::TimeRecord ExprEngineEndTime = ExprEngineTimer->getTotalTime();
732 ExprEngineEndTime -= ExprEngineStartTime;
733 DisplayTime(ExprEngineEndTime);
734 }
735
736 if (!Mgr->options.DumpExplodedGraphTo.empty())
737 Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
738
739 // Visualize the exploded graph.
740 if (Mgr->options.visualizeExplodedGraphWithGraphViz)
741 Eng.ViewGraph(Mgr->options.TrimGraph);
742
743 // Display warnings.
744 if (BugReporterTimer)
745 BugReporterTimer->startTimer();
746 Eng.getBugReporter().FlushReports();
747 if (BugReporterTimer)
748 BugReporterTimer->stopTimer();
749}
750
751//===----------------------------------------------------------------------===//
752// AnalysisConsumer creation.
753//===----------------------------------------------------------------------===//
754
755std::unique_ptr<AnalysisASTConsumer>
757 // Disable the effects of '-Werror' when using the AnalysisConsumer.
759
760 AnalyzerOptions &analyzerOpts = CI.getAnalyzerOpts();
761 bool hasModelPath = analyzerOpts.Config.count("model-path") > 0;
762
763 return std::make_unique<AnalysisConsumer>(
764 CI, CI.getFrontendOpts().OutputFile, analyzerOpts,
766 hasModelPath ? new ModelInjector(CI) : nullptr);
767}
STATISTIC(NumFunctionTopLevel, "The # of functions at top level.")
static bool shouldSkipFunction(const Decl *D, const SetOfConstDecls &Visited, const SetOfConstDecls &VisitedAsTopLevel)
static bool fileContainsString(StringRef Substring, ASTContext &C)
static void reportAnalyzerFunctionMisuse(const AnalyzerOptions &Opts, const ASTContext &Ctx)
#define SM(sm)
Definition: Cuda.cpp:80
Defines the clang::CodeInjector interface which is responsible for injecting AST of function definiti...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:143
This file defines the clang::ento::ModelInjector class which implements the clang::CodeInjector inter...
Defines the clang::Preprocessor interface.
Defines the SourceManager interface.
virtual void HandleTranslationUnit(ASTContext &Ctx)
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
Definition: ASTConsumer.h:66
virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D)
Handle the specified top-level declaration that occurred inside and ObjC container.
Definition: ASTConsumer.cpp:26
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Definition: ASTConsumer.cpp:18
virtual void Initialize(ASTContext &Context)
Initialize - This is called to initialize the consumer, providing the ASTContext.
Definition: ASTConsumer.h:47
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
SourceManager & getSourceManager()
Definition: ASTContext.h:691
const LangOptions & getLangOpts() const
Definition: ASTContext.h:761
static std::string getFunctionName(const Decl *D)
Stores options for the analyzer from the command line.
unsigned DisableAllCheckers
Disable all analyzer checkers.
AnalysisDiagClients AnalysisDiagOpt
AnalysisConstraints AnalysisConstraintsOpt
ConfigTable Config
A key-value table of use-specified configuration values.
std::string AnalyzeSpecificFunction
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:4379
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition: CFG.h:1211
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
Definition: CFG.h:1402
The AST-based call graph.
Definition: CallGraph.h:42
void addToCallGraph(Decl *D)
Populate the call graph with the functions in the given declaration.
Definition: CallGraph.h:62
CodeInjector is an interface which is responsible for injecting AST of function definitions that may ...
Definition: CodeInjector.h:35
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
AnalyzerOptions & getAnalyzerOpts()
Preprocessor & getPreprocessor() const
Return the current preprocessor.
FrontendOptions & getFrontendOpts()
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1209
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:1055
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
Definition: DeclBase.h:1061
SourceLocation getLocation() const
Definition: DeclBase.h:432
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
bool hasErrorOccurred() const
Definition: Diagnostic.h:838
void setWarningsAsErrors(bool Val)
When set to true, any warnings reported are issued as errors.
Definition: Diagnostic.h:664
bool hasFatalErrorOccurred() const
Definition: Diagnostic.h:845
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
std::string OutputFile
The output file, if any.
std::vector< std::string > Plugins
The list of plugins to load.
Represents a function declaration or definition.
Definition: Decl.h:1919
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
Definition: Decl.h:2218
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:3094
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
MacroExpansionContext tracks the macro expansions processed by the Preprocessor.
void registerForPreprocessor(Preprocessor &PP)
Register the necessary callbacks to the Preprocessor to record the expansion events and the generated...
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:268
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:138
bool isThisDeclarationADefinition() const
Returns whether this specific method is a definition.
Definition: DeclObjC.h:535
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:1053
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:128
DiagnosticsEngine & getDiagnostics() const
Represents an unpacked "presumed" location which can be presented to the user.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool shouldWalkTypesOfTypeLocs() const
Return whether this visitor should recurse into the types of TypeLocs.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
Stmt - This represents one statement.
Definition: Stmt.h:72
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:337
The top declaration context.
Definition: Decl.h:82
Represents a variable declaration or definition.
Definition: Decl.h:915
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition: Decl.h:1242
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition: Decl.h:1176
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition: Decl.h:1317
This class is used for tools that requires cross translation unit capability.
llvm::Expected< const FunctionDecl * > getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, StringRef IndexName, bool DisplayCTUProgress=false)
This function loads a function or variable definition from an external AST file and merges it into th...
bool isImportedAsNew(const Decl *ToDecl) const
Returns true if the given Decl is newly created during the import.
virtual void AddCheckerRegistrationFn(std::function< void(CheckerRegistry &)> Fn)=0
This method allows registering statically linked custom checkers that are not a part of the Clang tre...
virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer)=0
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:585
Manages a set of available checkers for running a static analysis.
bool isValid() const =delete
InliningModes
The modes of inlining, which override the default analysis-wide settings.
Definition: ExprEngine.h:129
@ Inline_Minimal
Do minimal inlining of callees.
Definition: ExprEngine.h:134
@ Inline_Regular
Follow the default settings for inlining callees.
Definition: ExprEngine.h:131
bool shouldImport(const VarDecl *VD, const ASTContext &ACtx)
Returns true if it makes sense to import a foreign variable definition.
std::unique_ptr< AnalysisASTConsumer > CreateAnalysisConsumer(CompilerInstance &CI)
CreateAnalysisConsumer - Creates an ASTConsumer to run various code analysis passes.
std::unique_ptr< ConstraintManager >(* ConstraintManagerCreator)(ProgramStateManager &, ExprEngine *)
Definition: ProgramState.h:42
std::vector< PathDiagnosticConsumer * > PathDiagnosticConsumers
std::unique_ptr< StoreManager >(* StoreManagerCreator)(ProgramStateManager &)
Definition: ProgramState.h:44
std::deque< Decl * > SetOfDecls
std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)
@ C
Languages that the frontend can parse and compile.