aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp107
-rw-r--r--clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp43
-rw-r--r--clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp1
3 files changed, 112 insertions, 39 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
index 033eb8c..f60d193 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
@@ -50,7 +50,9 @@ public:
llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIgnore;
llvm::DenseSet<const LambdaExpr *> LambdasToIgnore;
llvm::DenseSet<const ValueDecl *> ProtectedThisDecls;
+ llvm::DenseSet<const CallExpr *> CallToIgnore;
llvm::DenseSet<const CXXConstructExpr *> ConstructToIgnore;
+ llvm::DenseMap<const VarDecl *, const LambdaExpr *> LambdaOwnerMap;
QualType ClsType;
@@ -101,10 +103,60 @@ public:
auto *Init = VD->getInit();
if (!Init)
return true;
- auto *L = dyn_cast_or_null<LambdaExpr>(Init->IgnoreParenCasts());
- if (!L)
+ if (auto *L = dyn_cast_or_null<LambdaExpr>(Init->IgnoreParenCasts())) {
+ LambdasToIgnore.insert(L); // Evaluate lambdas in VisitDeclRefExpr.
+ return true;
+ }
+ if (!VD->hasLocalStorage())
return true;
- LambdasToIgnore.insert(L); // Evaluate lambdas in VisitDeclRefExpr.
+ if (auto *E = dyn_cast<ExprWithCleanups>(Init))
+ Init = E->getSubExpr();
+ if (auto *E = dyn_cast<CXXBindTemporaryExpr>(Init))
+ Init = E->getSubExpr();
+ if (auto *CE = dyn_cast<CallExpr>(Init)) {
+ if (auto *Callee = CE->getDirectCallee()) {
+ auto FnName = safeGetName(Callee);
+ unsigned ArgCnt = CE->getNumArgs();
+ if (FnName == "makeScopeExit" && ArgCnt == 1) {
+ auto *Arg = CE->getArg(0);
+ if (auto *E = dyn_cast<MaterializeTemporaryExpr>(Arg))
+ Arg = E->getSubExpr();
+ if (auto *L = dyn_cast<LambdaExpr>(Arg)) {
+ LambdaOwnerMap.insert(std::make_pair(VD, L));
+ CallToIgnore.insert(CE);
+ LambdasToIgnore.insert(L);
+ }
+ } else if (FnName == "makeVisitor") {
+ for (unsigned ArgIndex = 0; ArgIndex < ArgCnt; ++ArgIndex) {
+ auto *Arg = CE->getArg(ArgIndex);
+ if (auto *E = dyn_cast<MaterializeTemporaryExpr>(Arg))
+ Arg = E->getSubExpr();
+ if (auto *L = dyn_cast<LambdaExpr>(Arg)) {
+ LambdaOwnerMap.insert(std::make_pair(VD, L));
+ CallToIgnore.insert(CE);
+ LambdasToIgnore.insert(L);
+ }
+ }
+ }
+ }
+ } else if (auto *CE = dyn_cast<CXXConstructExpr>(Init)) {
+ if (auto *Ctor = CE->getConstructor()) {
+ if (auto *Cls = Ctor->getParent()) {
+ auto FnName = safeGetName(Cls);
+ unsigned ArgCnt = CE->getNumArgs();
+ if (FnName == "ScopeExit" && ArgCnt == 1) {
+ auto *Arg = CE->getArg(0);
+ if (auto *E = dyn_cast<MaterializeTemporaryExpr>(Arg))
+ Arg = E->getSubExpr();
+ if (auto *L = dyn_cast<LambdaExpr>(Arg)) {
+ LambdaOwnerMap.insert(std::make_pair(VD, L));
+ ConstructToIgnore.insert(CE);
+ LambdasToIgnore.insert(L);
+ }
+ }
+ }
+ }
+ }
return true;
}
@@ -114,6 +166,12 @@ public:
auto *VD = dyn_cast_or_null<VarDecl>(DRE->getDecl());
if (!VD)
return true;
+ if (auto It = LambdaOwnerMap.find(VD); It != LambdaOwnerMap.end()) {
+ auto *L = It->second;
+ Checker->visitLambdaExpr(L, shouldCheckThis() && !hasProtectedThis(L),
+ ClsType);
+ return true;
+ }
auto *Init = VD->getInit();
if (!Init)
return true;
@@ -167,10 +225,14 @@ public:
}
bool VisitCallExpr(CallExpr *CE) override {
+ if (CallToIgnore.contains(CE))
+ return true;
checkCalleeLambda(CE);
- if (auto *Callee = CE->getDirectCallee())
+ if (auto *Callee = CE->getDirectCallee()) {
+ if (isVisitFunction(CE, Callee))
+ return true;
checkParameters(CE, Callee);
- else if (auto *CalleeE = CE->getCallee()) {
+ } else if (auto *CalleeE = CE->getCallee()) {
if (auto *DRE = dyn_cast<DeclRefExpr>(CalleeE->IgnoreParenCasts())) {
if (auto *Callee = dyn_cast_or_null<FunctionDecl>(DRE->getDecl()))
checkParameters(CE, Callee);
@@ -179,6 +241,34 @@ public:
return true;
}
+ bool isVisitFunction(CallExpr *CallExpr, FunctionDecl *FnDecl) {
+ bool IsVisitFn = safeGetName(FnDecl) == "visit";
+ if (!IsVisitFn)
+ return false;
+ bool ArgCnt = CallExpr->getNumArgs();
+ if (!ArgCnt)
+ return false;
+ auto *Ns = FnDecl->getParent();
+ if (!Ns)
+ return false;
+ auto NsName = safeGetName(Ns);
+ if (NsName != "WTF" && NsName != "std")
+ return false;
+ auto *Arg = CallExpr->getArg(0);
+ if (!Arg)
+ return false;
+ auto *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenCasts());
+ if (!DRE)
+ return false;
+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ if (!VD)
+ return false;
+ if (!LambdaOwnerMap.contains(VD))
+ return false;
+ DeclRefExprsToIgnore.insert(DRE);
+ return true;
+ }
+
void checkParameters(CallExpr *CE, FunctionDecl *Callee) {
unsigned ArgIndex = isa<CXXOperatorCallExpr>(CE);
bool TreatAllArgsAsNoEscape = shouldTreatAllArgAsNoEscape(Callee);
@@ -280,7 +370,7 @@ public:
LambdasToIgnore.insert(L);
}
- bool hasProtectedThis(LambdaExpr *L) {
+ bool hasProtectedThis(const LambdaExpr *L) {
for (const LambdaCapture &OtherCapture : L->captures()) {
if (!OtherCapture.capturesVariable())
continue;
@@ -378,7 +468,8 @@ public:
visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
}
- void visitLambdaExpr(LambdaExpr *L, bool shouldCheckThis, const QualType T,
+ void visitLambdaExpr(const LambdaExpr *L, bool shouldCheckThis,
+ const QualType T,
bool ignoreParamVarDecl = false) const {
if (TFA.isTrivial(L->getBody()))
return;
@@ -410,7 +501,7 @@ public:
}
void reportBug(const LambdaCapture &Capture, ValueDecl *CapturedVar,
- const QualType T, LambdaExpr *L) const {
+ const QualType T, const LambdaExpr *L) const {
assert(CapturedVar);
auto Location = Capture.getLocation();
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 871400e..e0deec1 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -128,7 +128,6 @@ public:
std::unique_ptr<llvm::Timer> SyntaxCheckTimer;
std::unique_ptr<llvm::Timer> ExprEngineTimer;
std::unique_ptr<llvm::Timer> BugReporterTimer;
- bool ShouldClearTimersToPreventDisplayingThem;
/// The information about analyzed functions shared throughout the
/// translation unit.
@@ -149,7 +148,10 @@ public:
if (Opts.AnalyzerDisplayProgress || Opts.PrintStats ||
Opts.ShouldSerializeStats || !Opts.DumpEntryPointStatsToCSV.empty()) {
AnalyzerTimers = std::make_unique<llvm::TimerGroup>(
- "analyzer", "Analyzer timers");
+ "analyzer", "Analyzer timers",
+ /*PrintOnExit=*/
+ (Opts.AnalyzerDisplayProgress || Opts.PrintStats ||
+ Opts.ShouldSerializeStats));
SyntaxCheckTimer = std::make_unique<llvm::Timer>(
"syntaxchecks", "Syntax-based analysis time", *AnalyzerTimers);
ExprEngineTimer = std::make_unique<llvm::Timer>(
@@ -159,12 +161,6 @@ public:
*AnalyzerTimers);
}
- // Avoid displaying the timers created above in case we only want to record
- // per-entry-point stats.
- ShouldClearTimersToPreventDisplayingThem = !Opts.AnalyzerDisplayProgress &&
- !Opts.PrintStats &&
- !Opts.ShouldSerializeStats;
-
if (Opts.PrintStats || Opts.ShouldSerializeStats) {
llvm::EnableStatistics(/* DoPrintOnExit= */ false);
}
@@ -287,9 +283,6 @@ public:
checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
if (SyntaxCheckTimer)
SyntaxCheckTimer->stopTimer();
- if (AnalyzerTimers && ShouldClearTimersToPreventDisplayingThem) {
- AnalyzerTimers->clear();
- }
}
return true;
}
@@ -583,9 +576,6 @@ void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) {
checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
if (SyntaxCheckTimer)
SyntaxCheckTimer->stopTimer();
- if (AnalyzerTimers && ShouldClearTimersToPreventDisplayingThem) {
- AnalyzerTimers->clear();
- }
// Run the AST-only checks using the order in which functions are defined.
// If inlining is not turned on, use the simplest function order for path
@@ -760,14 +750,11 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
++NumFunctionsAnalyzedSyntaxOnly;
if (SyntaxCheckTimer) {
SyntaxCheckTimer->stopTimer();
- llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime();
- CheckerEndTime -= CheckerStartTime;
+ llvm::TimeRecord CheckerDuration =
+ SyntaxCheckTimer->getTotalTime() - CheckerStartTime;
FunctionSummaries.findOrInsertSummary(D)->second.SyntaxRunningTime =
- std::lround(CheckerEndTime.getWallTime() * 1000);
- DisplayTime(CheckerEndTime);
- if (AnalyzerTimers && ShouldClearTimersToPreventDisplayingThem) {
- AnalyzerTimers->clear();
- }
+ std::lround(CheckerDuration.getWallTime() * 1000);
+ DisplayTime(CheckerDuration);
}
}
@@ -825,14 +812,11 @@ void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
Mgr->options.MaxNodesPerTopLevelFunction);
if (ExprEngineTimer) {
ExprEngineTimer->stopTimer();
- llvm::TimeRecord ExprEngineEndTime = ExprEngineTimer->getTotalTime();
- ExprEngineEndTime -= ExprEngineStartTime;
+ llvm::TimeRecord ExprEngineDuration =
+ ExprEngineTimer->getTotalTime() - ExprEngineStartTime;
PathRunningTime.set(static_cast<unsigned>(
- std::lround(ExprEngineEndTime.getWallTime() * 1000)));
- DisplayTime(ExprEngineEndTime);
- if (AnalyzerTimers && ShouldClearTimersToPreventDisplayingThem) {
- AnalyzerTimers->clear();
- }
+ std::lround(ExprEngineDuration.getWallTime() * 1000)));
+ DisplayTime(ExprEngineDuration);
}
if (!Mgr->options.DumpExplodedGraphTo.empty())
@@ -843,9 +827,6 @@ void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
Eng.ViewGraph(Mgr->options.TrimGraph);
flushReports(BugReporterTimer.get(), Eng.getBugReporter());
- if (AnalyzerTimers && ShouldClearTimersToPreventDisplayingThem) {
- AnalyzerTimers->clear();
- }
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index 5301f88..531c642b 100644
--- a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -93,6 +93,7 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
// The instance wants to take ownership, however DisableFree frontend option
// is set to true to avoid double free issues
+ Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr());
Instance.setFileManager(CI.getFileManagerPtr());
Instance.setSourceManager(SM);
Instance.setPreprocessor(CI.getPreprocessorPtr());