diff options
author | George Karpenkov <ekarpenkov@apple.com> | 2018-08-10 18:28:04 +0000 |
---|---|---|
committer | George Karpenkov <ekarpenkov@apple.com> | 2018-08-10 18:28:04 +0000 |
commit | 088adbfa166310bcf69a862bc10fee951ae915b0 (patch) | |
tree | 7f587a0e0c7f766bf313d4994774926d07faacc8 /clang/lib/StaticAnalyzer/Core/RegionStore.cpp | |
parent | 5bb9d798b486e6f7d100a340544967c7845d48b2 (diff) | |
download | bcm5719-llvm-088adbfa166310bcf69a862bc10fee951ae915b0.tar.gz bcm5719-llvm-088adbfa166310bcf69a862bc10fee951ae915b0.zip |
Invalidate static locals when escaping lambdas
Lambdas can affect static locals even without an explicit capture.
rdar://39537031
Differential Revision: https://reviews.llvm.org/D50368
llvm-svn: 339459
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/RegionStore.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index db6449e6d5f..821b7f0edbe 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -17,6 +17,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/TargetInfo.h" @@ -1033,6 +1034,32 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR, B = B.remove(baseR); } + if (const auto *TO = dyn_cast<TypedValueRegion>(baseR)) { + if (const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) { + + // Lambdas can affect all static local variables without explicitly + // capturing those. + // We invalidate all static locals referenced inside the lambda body. + if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) { + using namespace ast_matchers; + + const char *DeclBind = "DeclBind"; + StatementMatcher RefToStatic = stmt(hasDescendant(declRefExpr( + to(varDecl(hasStaticStorageDuration()).bind(DeclBind))))); + auto Matches = + match(RefToStatic, *RD->getLambdaCallOperator()->getBody(), + RD->getASTContext()); + + for (BoundNodes &Match : Matches) { + auto *VD = Match.getNodeAs<VarDecl>(DeclBind); + const VarRegion *ToInvalidate = + RM.getRegionManager().getVarRegion(VD, LCtx); + AddToWorkList(ToInvalidate); + } + } + } + } + // BlockDataRegion? If so, invalidate captured variables that are passed // by reference. if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) { |