r339459 - Invalidate static locals when escaping lambdas
George Karpenkov via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 10 11:28:04 PDT 2018
Author: george.karpenkov
Date: Fri Aug 10 11:28:04 2018
New Revision: 339459
URL: http://llvm.org/viewvc/llvm-project?rev=339459&view=rev
Log:
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
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
cfe/trunk/test/Analysis/lambdas.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=339459&r1=339458&r2=339459&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Fri Aug 10 11:28:04 2018
@@ -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::VisitClust
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)) {
Modified: cfe/trunk/test/Analysis/lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/lambdas.cpp?rev=339459&r1=339458&r2=339459&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/lambdas.cpp (original)
+++ cfe/trunk/test/Analysis/lambdas.cpp Fri Aug 10 11:28:04 2018
@@ -1,10 +1,26 @@
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,deadcode,debug.ExprInspection -analyzer-config inline-lambdas=true -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-config inline-lambdas=false -DNO_INLINING=1 -verify %s
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -analyzer-config inline-lambdas=true %s > %t 2>&1
// RUN: FileCheck --input-file=%t %s
void clang_analyzer_warnIfReached();
void clang_analyzer_eval(int);
+#ifdef NO_INLINING
+
+// expected-no-diagnostics
+
+int& invalidate_static_on_unknown_lambda() {
+ static int* z;
+ auto f = [] {
+ z = nullptr;
+ }; // should invalidate "z" when inlining is disabled.
+ f();
+ return *z; // no-warning
+}
+
+#else
+
struct X { X(const X&); };
void f(X x) { (void) [x]{}; }
@@ -348,6 +364,18 @@ void testCapturedConstExprFloat() {
lambda();
}
+void escape(void*);
+
+int& invalidate_static_on_unknown_lambda() {
+ static int* z;
+ auto lambda = [] {
+ static float zz;
+ z = new int(120);
+ };
+ escape(&lambda);
+ return *z; // no-warning
+}
+
static int b = 0;
@@ -365,6 +393,8 @@ int f() {
return 0;
}
+#endif
+
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
More information about the cfe-commits
mailing list