Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -2462,8 +2462,8 @@ const Decl *D = LocCtxt->getDecl(); const auto *MD = D ? dyn_cast(D) : nullptr; const auto *DeclRefEx = dyn_cast(Ex); - SVal V; - bool IsReference; + Optional> VInfo; + if (AMgr.options.shouldInlineLambdas() && DeclRefEx && DeclRefEx->refersToEnclosingVariableOrCapture() && MD && MD->getParent()->isLambda()) { @@ -2472,25 +2472,23 @@ llvm::DenseMap LambdaCaptureFields; FieldDecl *LambdaThisCaptureField; CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField); - const FieldDecl *FD = LambdaCaptureFields[VD]; - 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); - IsReference = false; - } else { + + // Sema follows a sequence of complex rules to determine whether the + // variable should be captured. + if (const FieldDecl *FD = LambdaCaptureFields[VD]) { Loc CXXThis = svalBuilder.getCXXThis(MD, LocCtxt->getCurrentStackFrame()); SVal CXXThisVal = state->getSVal(CXXThis); - V = state->getLValue(FD, CXXThisVal); - IsReference = FD->getType()->isReferenceType(); + VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType()); } - } else { - V = state->getLValue(VD, LocCtxt); - IsReference = VD->getType()->isReferenceType(); } + if (!VInfo) + VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType()); + + SVal V = VInfo->first; + bool IsReference = VInfo->second->isReferenceType(); + // For references, the 'lvalue' is the pointer address stored in the // reference region. if (IsReference) { Index: test/Analysis/lambda_no_capture.cpp =================================================================== --- /dev/null +++ test/Analysis/lambda_no_capture.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -verify %s + +// expected-no-diagnostics +static int b = 0; + +void f() { + b = 0; + auto &bm = b; + [&] { + bm++; + bm++; + }(); + if (bm != 2) { + int *y = 0; + int x = *y; // no-warning + } +}