;
51#define DEBUG_TYPE "AnalysisConsumer" 53STATISTIC(NumFunctionTopLevel,
"The # of functions at top level.");
55 "The # of functions and blocks analyzed (as top level " 56 "with inlining turned on).");
58 "The # of basic blocks in the analyzed functions.");
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.");
77 typedef unsignedAnalysisMode;
80AnalysisMode RecVisitorMode;
84std::vector<std::function<void(
CheckerRegistry&)>> CheckerRegistrationFns;
89 conststd::string OutDir;
110std::unique_ptr<CheckerManager> checkerMgr;
111std::unique_ptr<AnalysisManager> Mgr;
114std::unique_ptr<llvm::TimerGroup> AnalyzerTimers;
115std::unique_ptr<llvm::Timer> SyntaxCheckTimer;
116std::unique_ptr<llvm::Timer> ExprEngineTimer;
117std::unique_ptr<llvm::Timer> BugReporterTimer;
126: RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr),
127PP(CI.getPreprocessor()), OutDir(outdir), Opts(opts),
128Plugins(plugins), Injector(injector), CTU(CI),
129MacroExpansions(CI.getLangOpts()) {
130DigestAnalyzerOptions();
132Opts.ShouldSerializeStats) {
133AnalyzerTimers = std::make_unique<llvm::TimerGroup>(
134 "analyzer",
"Analyzer timers");
135SyntaxCheckTimer = std::make_unique<llvm::Timer>(
136 "syntaxchecks",
"Syntax-based analysis time", *AnalyzerTimers);
137ExprEngineTimer = std::make_unique<llvm::Timer>(
138 "exprengine",
"Path exploration time", *AnalyzerTimers);
139BugReporterTimer = std::make_unique<llvm::Timer>(
140 "bugreporter",
"Path-sensitive report post-processing time",
144 if(Opts.
PrintStats|| Opts.ShouldSerializeStats) {
145llvm::EnableStatistics(
false);
148 if(Opts.ShouldDisplayMacroExpansions)
152ShouldWalkTypesOfTypeLocs =
false;
155~AnalysisConsumer()
override{
157llvm::PrintStatistics();
161 voidDigestAnalyzerOptions() {
165#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \ 167 CREATEFN(Opts.getDiagOpts(), PathConsumers, OutDir, PP, CTU, \ 170#include "clang/StaticAnalyzer/Core/Analyses.def" 172llvm_unreachable(
"Unknown analyzer output type!");
180llvm_unreachable(
"Unknown constraint manager.");
181#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \ 182 case NAME##Model: CreateConstraintMgr = CREATEFN; break; 183#include "clang/StaticAnalyzer/Core/Analyses.def" 187 voidDisplayTime(llvm::TimeRecord &Time) {
191llvm::errs() <<
" : "<< llvm::format(
"%1.1f", Time.getWallTime() * 1000)
195 voidDisplayFunction(
const Decl*
D, AnalysisMode Mode,
203llvm::errs() <<
"ANALYZE";
205 if(Mode == AM_Syntax)
206llvm::errs() <<
" (Syntax)";
207 else if(Mode == AM_Path) {
208llvm::errs() <<
" (Path, ";
211llvm::errs() <<
" Inline_Minimal";
214llvm::errs() <<
" Inline_Regular";
217llvm::errs() <<
")";
219assert(Mode == (AM_Syntax | AM_Path) &&
"Unexpected mode!");
221llvm::errs() <<
": "<<
Loc.getFilename() <<
' ' 228checkerMgr = std::make_unique<CheckerManager>(*Ctx, Opts, PP, Plugins,
229CheckerRegistrationFns);
231Mgr = std::make_unique<AnalysisManager>(*Ctx, PP, PathConsumers,
232CreateStoreMgr, CreateConstraintMgr,
233checkerMgr.get(), Opts, Injector);
251 voidHandleDeclsCallGraph(
const unsignedLocalTUDeclsSize);
259 voidHandleCode(
Decl*
D, AnalysisMode Mode,
263 voidRunPathSensitiveChecks(
Decl*
D,
269AnalysisMode Mode = getModeForDecl(
D, RecVisitorMode);
270 if(Mode & AM_Syntax) {
271 if(SyntaxCheckTimer)
272SyntaxCheckTimer->startTimer();
273checkerMgr->runCheckersOnASTDecl(
D, *Mgr, *RecVisitorBR);
274 if(SyntaxCheckTimer)
275SyntaxCheckTimer->stopTimer();
280 boolVisitVarDecl(
VarDecl*VD)
override{
281 if(!Opts.IsNaiveCTUEnabled)
297Opts.DisplayCTUProgress);
299 if(!CTUDeclOrError) {
300handleAllErrors(CTUDeclOrError.takeError(),
302CTU.emitCrossTUDiagnostics(IE);
311 if(II && II->
getName().starts_with(
"__inline"))
318assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() ==
false);
319HandleCode(FD, RecVisitorMode);
326assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() ==
false);
327HandleCode(MD, RecVisitorMode);
332 boolVisitBlockDecl(
BlockDecl*BD)
override{
334assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() ==
false);
338HandleCode(BD, RecVisitorMode);
345PathConsumers.push_back(Consumer);
349CheckerRegistrationFns.push_back(std::move(Fn));
356AnalysisMode getModeForDecl(
Decl*
D, AnalysisMode Mode);
357 voidrunAnalysisOnTranslationUnit(
ASTContext&
C);
360 voidreportAnalyzerProgress(StringRef S);
368boolAnalysisConsumer::HandleTopLevelDecl(
DeclGroupRefDG) {
369storeTopLevelDecls(DG);
373voidAnalysisConsumer::HandleTopLevelDeclInObjCContainer(
DeclGroupRefDG) {
374storeTopLevelDecls(DG);
377voidAnalysisConsumer::storeTopLevelDecls(
DeclGroupRefDG) {
378 for(
auto&I : DG) {
382 if(isa<ObjCMethodDecl>(I))
385LocalTUDecls.push_back(I);
392 if(VisitedAsTopLevel.count(
D))
398 if(
const auto*CD = dyn_cast<CXXConstructorDecl>(
D))
399 if(CD->isInheritingConstructor())
409 if(isa<ObjCMethodDecl>(
D))
414 if(
const auto*MD = dyn_cast<CXXMethodDecl>(
D)) {
415 if(MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())
424AnalysisConsumer::getInliningModeForFunction(
const Decl*
D,
429 if(
Visited.count(
D) && isa<ObjCMethodDecl>(
D)) {
438voidAnalysisConsumer::HandleDeclsCallGraph(
const unsignedLocalTUDeclsSize) {
444 for(
unsignedi = 0 ; i < LocalTUDeclsSize ; ++i) {
456llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG);
457 for(
auto&N : RPOT) {
458NumFunctionTopLevel++;
460 Decl*
D= N->getDecl();
475 if(
const auto*FD = dyn_cast<FunctionDecl>(
D)) {
486HandleCode(
D, AM_Path, getInliningModeForFunction(
D,
Visited),
487(Mgr->options.InliningMode == All ?
nullptr: &VisitedCallees));
490 for(
const Decl*Callee : VisitedCallees)
493 Visited.insert(isa<ObjCMethodDecl>(Callee) ? Callee
494:
Callee->getCanonicalDecl());
495VisitedAsTopLevel.insert(
D);
502StringRef Buffer =
SM.getBufferOrFake(FID).getBuffer();
503 returnBuffer.contains(Substring);
508llvm::errs() <<
"Every top-level function was skipped.\n";
511llvm::errs() <<
"Pass the -analyzer-display-progress for tracking which " 512 "functions are analyzed.\n";
517 if(Ctx.
getLangOpts().CPlusPlus && !HasBrackets) {
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) {
522llvm::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";
528voidAnalysisConsumer::runAnalysisOnTranslationUnit(
ASTContext&
C) {
531BR.setAnalysisEntryPoint(TU);
532 if(SyntaxCheckTimer)
533SyntaxCheckTimer->startTimer();
534checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
535 if(SyntaxCheckTimer)
536SyntaxCheckTimer->stopTimer();
541RecVisitorMode = AM_Syntax;
542 if(!Mgr->shouldInlineCall())
543RecVisitorMode |= AM_Path;
552 const unsignedLocalTUDeclsSize = LocalTUDecls.size();
553 for(
unsignedi = 0 ; i < LocalTUDeclsSize ; ++i) {
554TraverseDecl(LocalTUDecls[i]);
557 if(Mgr->shouldInlineCall())
558HandleDeclsCallGraph(LocalTUDeclsSize);
561checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
564RecVisitorBR =
nullptr;
575voidAnalysisConsumer::reportAnalyzerProgress(StringRef S) {
580voidAnalysisConsumer::HandleTranslationUnit(
ASTContext&
C) {
590 const autoDiagFlusherScopeExit =
591llvm::make_scope_exit([
this] { Mgr.reset(); });
593 if(Opts.ShouldIgnoreBisonGeneratedFiles &&
595reportAnalyzerProgress(
"Skipping bison-generated file\n");
599 if(Opts.ShouldIgnoreFlexGeneratedFiles &&
601reportAnalyzerProgress(
"Skipping flex-generated file\n");
608reportAnalyzerProgress(
"All checks are disabled using a supplied option\n");
613runAnalysisOnTranslationUnit(
C);
617NumVisitedBlocksInAnalyzedFunctions =
619 if(NumBlocksInAnalyzedFunctions > 0)
620PercentReachableBlocks =
622NumBlocksInAnalyzedFunctions;
625AnalysisConsumer::AnalysisMode
626AnalysisConsumer::getModeForDecl(
Decl*
D, AnalysisMode Mode) {
644 return SM.getExpansionLoc(SL);
648 if(
Loc.isInvalid() ||
SM.isInSystemHeader(
Loc))
652 if(!Mgr->isInCodeFile(
Loc))
653 returnMode & ~AM_Path;
658voidAnalysisConsumer::HandleCode(
Decl*
D, AnalysisMode Mode,
663Mode = getModeForDecl(
D, Mode);
668Mgr->ClearContexts();
670 if(Mgr->getAnalysisDeclContext(
D)->isBodyAutosynthesized())
673 CFG*DeclCFG = Mgr->getCFG(
D);
675MaxCFGSize.updateMax(DeclCFG->
size());
677DisplayFunction(
D, Mode, IMode);
679BR.setAnalysisEntryPoint(
D);
681 if(Mode & AM_Syntax) {
682llvm::TimeRecord CheckerStartTime;
683 if(SyntaxCheckTimer) {
684CheckerStartTime = SyntaxCheckTimer->getTotalTime();
685SyntaxCheckTimer->startTimer();
687checkerMgr->runCheckersOnASTBody(
D, *Mgr, BR);
688 if(SyntaxCheckTimer) {
689SyntaxCheckTimer->stopTimer();
690llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime();
691CheckerEndTime -= CheckerStartTime;
692DisplayTime(CheckerEndTime);
698 if((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
699RunPathSensitiveChecks(
D, IMode, VisitedCallees);
701NumFunctionsAnalyzed++;
709voidAnalysisConsumer::RunPathSensitiveChecks(
Decl*
D,
714 if(!Mgr->getCFG(
D))
721 ExprEngineEng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);
724llvm::TimeRecord ExprEngineStartTime;
725 if(ExprEngineTimer) {
726ExprEngineStartTime = ExprEngineTimer->getTotalTime();
727ExprEngineTimer->startTimer();
729Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(
D),
730Mgr->options.MaxNodesPerTopLevelFunction);
731 if(ExprEngineTimer) {
732ExprEngineTimer->stopTimer();
733llvm::TimeRecord ExprEngineEndTime = ExprEngineTimer->getTotalTime();
734ExprEngineEndTime -= ExprEngineStartTime;
735DisplayTime(ExprEngineEndTime);
738 if(!Mgr->options.DumpExplodedGraphTo.empty())
739Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
742 if(Mgr->options.visualizeExplodedGraphWithGraphViz)
743Eng.ViewGraph(Mgr->options.TrimGraph);
746 if(BugReporterTimer)
747BugReporterTimer->startTimer();
748Eng.getBugReporter().FlushReports();
749 if(BugReporterTimer)
750BugReporterTimer->stopTimer();
757std::unique_ptr<AnalysisASTConsumer>
763 boolhasModelPath = analyzerOpts.
Config.count(
"model-path") > 0;
765 returnstd::make_unique<AnalysisConsumer>(
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)
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
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...
virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D)
Handle the specified top-level declaration that occurred inside and ObjC container.
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
virtual void Initialize(ASTContext &Context)
Initialize - This is called to initialize the consumer, providing the ASTContext.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const LangOptions & getLangOpts() const
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
unsigned AnalyzerDisplayProgress
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
The AST-based call graph.
void addToCallGraph(Decl *D)
Populate the call graph with the functions in the given declaration.
CodeInjector is an interface which is responsible for injecting AST of function definitions that may ...
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.
Decl - This represents one declaration (or definition), e.g.
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
Concrete class used by the front-end to report problems and issues.
bool hasErrorOccurred() const
void setWarningsAsErrors(bool Val)
When set to true, any warnings reported are issued as errors.
bool hasFatalErrorOccurred() const
Recursive AST visitor that supports extension via dynamic dispatch.
virtual bool VisitDecl(MaybeConst< Decl > *D)
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.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
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.
ObjCMethodDecl - Represents an instance or class method declaration.
bool isThisDeclarationADefinition() const
Returns whether this specific method is a definition.
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
DiagnosticsEngine & getDiagnostics() const
Represents an unpacked "presumed" location which can be presented to the user.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
Stmt - This represents one statement.
SourceLocation getBeginLoc() const LLVM_READONLY
The top declaration context.
Represents a variable declaration or definition.
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
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.
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.
@ Inline_Minimal
Do minimal inlining of callees.
@ Inline_Regular
Follow the default settings for inlining callees.
unsigned getTotalNumBasicBlocks()
unsigned getTotalNumVisitedBasicBlocks()
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 *)
std::vector< PathDiagnosticConsumer * > PathDiagnosticConsumers
std::unique_ptr< StoreManager >(* StoreManagerCreator)(ProgramStateManager &)
std::deque< Decl * > SetOfDecls
std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)
The JSON file list parser is used to communicate input to InstallAPI.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4