clang 20.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().starts_with("__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 const TranslationUnitDecl *TU = C.getTranslationUnitDecl();
531 BR.setAnalysisEntryPoint(TU);
532 if (SyntaxCheckTimer)
533 SyntaxCheckTimer->startTimer();
534 checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
535 if (SyntaxCheckTimer)
536 SyntaxCheckTimer->stopTimer();
537
538 // Run the AST-only checks using the order in which functions are defined.
539 // If inlining is not turned on, use the simplest function order for path
540 // sensitive analyzes as well.
541 RecVisitorMode = AM_Syntax;
542 if (!Mgr->shouldInlineCall())
543 RecVisitorMode |= AM_Path;
544 RecVisitorBR = &BR;
545
546 // Process all the top level declarations.
547 //
548 // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
549 // entries. Thus we don't use an iterator, but rely on LocalTUDecls
550 // random access. By doing so, we automatically compensate for iterators
551 // possibly being invalidated, although this is a bit slower.
552 const unsigned LocalTUDeclsSize = LocalTUDecls.size();
553 for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
554 TraverseDecl(LocalTUDecls[i]);
555 }
556
557 if (Mgr->shouldInlineCall())
558 HandleDeclsCallGraph(LocalTUDeclsSize);
559
560 // After all decls handled, run checkers on the entire TranslationUnit.
561 checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
562
563 BR.FlushReports();
564 RecVisitorBR = nullptr;
565
566 // If the user wanted to analyze a specific function and the number of basic
567 // blocks analyzed is zero, than the user might not specified the function
568 // name correctly.
569 // FIXME: The user might have analyzed the requested function in Syntax mode,
570 // but we are unaware of that.
571 if (!Opts.AnalyzeSpecificFunction.empty() && NumFunctionsAnalyzed == 0)
573}
574
575void AnalysisConsumer::reportAnalyzerProgress(StringRef S) {
577 llvm::errs() << S;
578}
579
580void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
581 // Don't run the actions if an error has occurred with parsing the file.
582 DiagnosticsEngine &Diags = PP.getDiagnostics();
583 if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
584 return;
585
586 // Explicitly destroy the PathDiagnosticConsumer. This will flush its output.
587 // FIXME: This should be replaced with something that doesn't rely on
588 // side-effects in PathDiagnosticConsumer's destructor. This is required when
589 // used with option -disable-free.
590 const auto DiagFlusherScopeExit =
591 llvm::make_scope_exit([this] { Mgr.reset(); });
592
593 if (Opts.ShouldIgnoreBisonGeneratedFiles &&
594 fileContainsString("/* A Bison parser, made by", C)) {
595 reportAnalyzerProgress("Skipping bison-generated file\n");
596 return;
597 }
598
599 if (Opts.ShouldIgnoreFlexGeneratedFiles &&
600 fileContainsString("/* A lexical scanner generated by flex", C)) {
601 reportAnalyzerProgress("Skipping flex-generated file\n");
602 return;
603 }
604
605 // Don't analyze if the user explicitly asked for no checks to be performed
606 // on this file.
607 if (Opts.DisableAllCheckers) {
608 reportAnalyzerProgress("All checks are disabled using a supplied option\n");
609 return;
610 }
611
612 // Otherwise, just run the analysis.
613 runAnalysisOnTranslationUnit(C);
614
615 // Count how many basic blocks we have not covered.
616 NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
617 NumVisitedBlocksInAnalyzedFunctions =
618 FunctionSummaries.getTotalNumVisitedBasicBlocks();
619 if (NumBlocksInAnalyzedFunctions > 0)
620 PercentReachableBlocks =
621 (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
622 NumBlocksInAnalyzedFunctions;
623}
624
625AnalysisConsumer::AnalysisMode
626AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
627 if (!Opts.AnalyzeSpecificFunction.empty() &&
629 return AM_None;
630
631 // Unless -analyze-all is specified, treat decls differently depending on
632 // where they came from:
633 // - Main source file: run both path-sensitive and non-path-sensitive checks.
634 // - Header files: run non-path-sensitive checks only.
635 // - System headers: don't run any checks.
636 if (Opts.AnalyzeAll)
637 return Mode;
638
639 const SourceManager &SM = Ctx->getSourceManager();
640
641 const SourceLocation Loc = [&SM](Decl *D) -> SourceLocation {
642 const Stmt *Body = D->getBody();
643 SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation();
644 return SM.getExpansionLoc(SL);
645 }(D);
646
647 // Ignore system headers.
648 if (Loc.isInvalid() || SM.isInSystemHeader(Loc))
649 return AM_None;
650
651 // Disable path sensitive analysis in user-headers.
652 if (!Mgr->isInCodeFile(Loc))
653 return Mode & ~AM_Path;
654
655 return Mode;
656}
657
658void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
660 SetOfConstDecls *VisitedCallees) {
661 if (!D->hasBody())
662 return;
663 Mode = getModeForDecl(D, Mode);
664 if (Mode == AM_None)
665 return;
666
667 // Clear the AnalysisManager of old AnalysisDeclContexts.
668 Mgr->ClearContexts();
669 // Ignore autosynthesized code.
670 if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized())
671 return;
672
673 CFG *DeclCFG = Mgr->getCFG(D);
674 if (DeclCFG)
675 MaxCFGSize.updateMax(DeclCFG->size());
676
677 DisplayFunction(D, Mode, IMode);
678 BugReporter BR(*Mgr);
679 BR.setAnalysisEntryPoint(D);
680
681 if (Mode & AM_Syntax) {
682 llvm::TimeRecord CheckerStartTime;
683 if (SyntaxCheckTimer) {
684 CheckerStartTime = SyntaxCheckTimer->getTotalTime();
685 SyntaxCheckTimer->startTimer();
686 }
687 checkerMgr->runCheckersOnASTBody(D, *Mgr, BR);
688 if (SyntaxCheckTimer) {
689 SyntaxCheckTimer->stopTimer();
690 llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime();
691 CheckerEndTime -= CheckerStartTime;
692 DisplayTime(CheckerEndTime);
693 }
694 }
695
696 BR.FlushReports();
697
698 if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
699 RunPathSensitiveChecks(D, IMode, VisitedCallees);
700 if (IMode != ExprEngine::Inline_Minimal)
701 NumFunctionsAnalyzed++;
702 }
703}
704
705//===----------------------------------------------------------------------===//
706// Path-sensitive checking.
707//===----------------------------------------------------------------------===//
708
709void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
711 SetOfConstDecls *VisitedCallees) {
712 // Construct the analysis engine. First check if the CFG is valid.
713 // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
714 if (!Mgr->getCFG(D))
715 return;
716
717 // See if the LiveVariables analysis scales.
718 if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
719 return;
720
721 ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);
722
723 // Execute the worklist algorithm.
724 llvm::TimeRecord ExprEngineStartTime;
725 if (ExprEngineTimer) {
726 ExprEngineStartTime = ExprEngineTimer->getTotalTime();
727 ExprEngineTimer->startTimer();
728 }
729 Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
730 Mgr->options.MaxNodesPerTopLevelFunction);
731 if (ExprEngineTimer) {
732 ExprEngineTimer->stopTimer();
733 llvm::TimeRecord ExprEngineEndTime = ExprEngineTimer->getTotalTime();
734 ExprEngineEndTime -= ExprEngineStartTime;
735 DisplayTime(ExprEngineEndTime);
736 }
737
738 if (!Mgr->options.DumpExplodedGraphTo.empty())
739 Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
740
741 // Visualize the exploded graph.
742 if (Mgr->options.visualizeExplodedGraphWithGraphViz)
743 Eng.ViewGraph(Mgr->options.TrimGraph);
744
745 // Display warnings.
746 if (BugReporterTimer)
747 BugReporterTimer->startTimer();
748 Eng.getBugReporter().FlushReports();
749 if (BugReporterTimer)
750 BugReporterTimer->stopTimer();
751}
752
753//===----------------------------------------------------------------------===//
754// AnalysisConsumer creation.
755//===----------------------------------------------------------------------===//
756
757std::unique_ptr<AnalysisASTConsumer>
759 // Disable the effects of '-Werror' when using the AnalysisConsumer.
761
762 AnalyzerOptions &analyzerOpts = CI.getAnalyzerOpts();
763 bool hasModelPath = analyzerOpts.Config.count("model-path") > 0;
764
765 return std::make_unique<AnalysisConsumer>(
766 CI, CI.getFrontendOpts().OutputFile, analyzerOpts,
768 hasModelPath ? new ModelInjector(CI) : nullptr);
769}
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:83
const Decl * D
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:146
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:67
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:48
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
SourceManager & getSourceManager()
Definition: ASTContext.h:721
const LangOptions & getLangOpts() const
Definition: ASTContext.h:797
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:4471
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition: CFG.h:1214
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
Definition: CFG.h:1407
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:1333
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
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:1077
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:1083
SourceLocation getLocation() const
Definition: DeclBase.h:446
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
bool hasErrorOccurred() const
Definition: Diagnostic.h:843
void setWarningsAsErrors(bool Val)
When set to true, any warnings reported are issued as errors.
Definition: Diagnostic.h:669
bool hasFatalErrorOccurred() const
Definition: Diagnostic.h:850
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:1932
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
Definition: Decl.h:2246
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:3144
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:270
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:140
bool isThisDeclarationADefinition() const
Returns whether this specific method is a definition.
Definition: DeclObjC.h:534
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:137
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:84
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
The top declaration context.
Definition: Decl.h:84
Represents a variable declaration or definition.
Definition: Decl.h:879
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition: Decl.h:1231
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition: Decl.h:1165
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition: Decl.h:1306
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.
llvm::DenseSet< const Decl * > SetOfConstDecls
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)
The JSON file list parser is used to communicate input to InstallAPI.