Skip to content

Commit 3c48263

Browse files
committed
[analyzer] Remove pattern matching of lambda capture initializers
Prior to this patch we handled lambda captures based on their initializer expression, which resulted in pattern matching. With C++17 copy elision the initializer expression can be anything, and this approach proved to be fragile and a source of crashes. This patch removes pattern matching and only checks whether the object is under construction or not. Differential Revision: https://reviews.llvm.org/D131944
1 parent c860fd3 commit 3c48263

File tree

2 files changed

+15
-17
lines changed

2 files changed

+15
-17
lines changed

clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,23 +1147,12 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
11471147

11481148
assert(InitExpr && "Capture missing initialization expression");
11491149

1150-
if (const auto AILE = dyn_cast<ArrayInitLoopExpr>(InitExpr)) {
1151-
// If the AILE initializes a POD array, we need to keep it as the
1152-
// InitExpr.
1153-
if (dyn_cast<CXXConstructExpr>(AILE->getSubExpr()))
1154-
InitExpr = AILE->getSubExpr();
1155-
}
1156-
1157-
// With C++17 copy elision this can happen.
1158-
if (const auto *FC = dyn_cast<CXXFunctionalCastExpr>(InitExpr))
1159-
InitExpr = FC->getSubExpr();
1160-
1161-
assert(InitExpr &&
1162-
"Extracted capture initialization expression is missing");
1163-
1164-
if (dyn_cast<CXXConstructExpr>(InitExpr)) {
1165-
InitVal = *getObjectUnderConstruction(State, {LE, Idx}, LocCtxt);
1166-
InitVal = State->getSVal(InitVal.getAsRegion());
1150+
// With C++17 copy elision the InitExpr can be anything, so instead of
1151+
// pattern matching all cases, we simple check if the current field is
1152+
// under construction or not, regardless what it's InitExpr is.
1153+
if (const auto OUC =
1154+
getObjectUnderConstruction(State, {LE, Idx}, LocCtxt)) {
1155+
InitVal = State->getSVal(OUC->getAsRegion());
11671156

11681157
State = finishObjectConstruction(State, {LE, Idx}, LocCtxt);
11691158
} else

clang/test/Analysis/lambdas.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -analyzer-config inline-lambdas=true %s > %t 2>&1
44
// RUN: FileCheck --input-file=%t %s
55

6+
#include "Inputs/system-header-simulator-cxx.h"
7+
68
void clang_analyzer_warnIfReached();
79
void clang_analyzer_eval(int);
810

@@ -217,6 +219,13 @@ void testCopyElidedObjectCaptured(int x) {
217219
}();
218220
}
219221

222+
static auto MakeUniquePtr() { return std::make_unique<std::vector<int>>(); }
223+
224+
void testCopyElidedUniquePtr() {
225+
[uniquePtr = MakeUniquePtr()] {}();
226+
clang_analyzer_warnIfReached(); // expected-warning{{TRUE}}
227+
}
228+
220229
#endif
221230

222231
// Test inline defensive checks

0 commit comments

Comments
 (0)