diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -1143,7 +1143,9 @@ SVal InitVal; if (!FieldForCapture->hasCapturedVLAType()) { - Expr *InitExpr = *i; + const Expr *InitExpr = *i; + + assert(InitExpr && "Capture missing initialization expression"); if (const auto AILE = dyn_cast(InitExpr)) { // If the AILE initializes a POD array, we need to keep it as the @@ -1152,7 +1154,12 @@ InitExpr = AILE->getSubExpr(); } - assert(InitExpr && "Capture missing initialization expression"); + // With C++17 copy elision this can happen. + if (const auto *FC = dyn_cast(InitExpr)) + InitExpr = FC->getSubExpr(); + + assert(InitExpr && + "Extracted capture initialization expression is missing"); if (dyn_cast(InitExpr)) { InitVal = *getObjectUnderConstruction(State, {LE, Idx}, LocCtxt); diff --git a/clang/test/Analysis/lambdas.cpp b/clang/test/Analysis/lambdas.cpp --- a/clang/test/Analysis/lambdas.cpp +++ b/clang/test/Analysis/lambdas.cpp @@ -203,6 +203,22 @@ clang_analyzer_eval(i == 7); // expected-warning{{TRUE}} } +#if __cplusplus >= 201402L +// Capture copy elided object. + +struct Elided{ + int x = 0; + Elided(int) {} +}; + +void testCopyElidedObjectCaptured(int x) { + [e = Elided(x)] { + clang_analyzer_eval(e.x == 0); // expected-warning{{TRUE}} + }(); +} + +#endif + // Test inline defensive checks int getNum();