From: Gabor Horvath Date: Tue, 27 Oct 2015 13:46:39 +0000 (+0000) Subject: [analyzer] Fix lambdas that are capturing constants. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f0ecf646e05ea51f0c2d7603700d24f6bb214c8f;p=clang [analyzer] Fix lambdas that are capturing constants. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@251407 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index afef624f5d..f6129a963f 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1859,13 +1859,20 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, FieldDecl *LambdaThisCaptureField; CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField); const FieldDecl *FD = LambdaCaptureFields[VD]; - Loc CXXThis = - svalBuilder.getCXXThis(MD, LocCtxt->getCurrentStackFrame()); - SVal CXXThisVal = state->getSVal(CXXThis); - V = state->getLValue(FD, CXXThisVal); - if (FD->getType()->isReferenceType() && - !VD->getType()->isReferenceType()) - CaptureByReference = true; + if (!FD) { + // When a constant is captured, sometimes no corresponding field is + // created in the lambda object. + assert(VD->getType().isConstQualified()); + V = state->getLValue(VD, LocCtxt); + } else { + Loc CXXThis = + svalBuilder.getCXXThis(MD, LocCtxt->getCurrentStackFrame()); + SVal CXXThisVal = state->getSVal(CXXThis); + V = state->getLValue(FD, CXXThisVal); + if (FD->getType()->isReferenceType() && + !VD->getType()->isReferenceType()) + CaptureByReference = true; + } } else { V = state->getLValue(VD, LocCtxt); } diff --git a/test/Analysis/lambdas.cpp b/test/Analysis/lambdas.cpp index 36af7e1e84..10f6d55958 100644 --- a/test/Analysis/lambdas.cpp +++ b/test/Analysis/lambdas.cpp @@ -195,6 +195,21 @@ struct DontCrash { } }; + +// Capture constants + +void captureConstants() { + const int i = 5; + [=]() { + if (i != 5) + clang_analyzer_warnIfReached(); + }(); + [&] { + if (i != 5) + clang_analyzer_warnIfReached(); + }(); +} + // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1]