Author: george.karpenkov Date: Mon Mar 19 17:20:58 2018 New Revision: 327926
URL: http://llvm.org/viewvc/llvm-project?rev=327926&view=rev Log: [analyzer] Fix the assertion failure when static globals are used in lambda by reference Also use the opportunity to clean up the code and remove unnecessary duplication. rdar://37625895 Differential Revision: https://reviews.llvm.org/D44594 Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp cfe/trunk/test/Analysis/lambdas.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=327926&r1=327925&r2=327926&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Mar 19 17:20:58 2018 @@ -2462,8 +2462,8 @@ void ExprEngine::VisitCommonDeclRefExpr( const Decl *D = LocCtxt->getDecl(); const auto *MD = D ? dyn_cast<CXXMethodDecl>(D) : nullptr; const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex); - SVal V; - bool IsReference; + Optional<std::pair<SVal, QualType>> VInfo; + if (AMgr.options.shouldInlineLambdas() && DeclRefEx && DeclRefEx->refersToEnclosingVariableOrCapture() && MD && MD->getParent()->isLambda()) { @@ -2472,25 +2472,23 @@ void ExprEngine::VisitCommonDeclRefExpr( llvm::DenseMap<const VarDecl *, FieldDecl *> 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) { Modified: cfe/trunk/test/Analysis/lambdas.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/lambdas.cpp?rev=327926&r1=327925&r2=327926&view=diff ============================================================================== --- cfe/trunk/test/Analysis/lambdas.cpp (original) +++ cfe/trunk/test/Analysis/lambdas.cpp Mon Mar 19 17:20:58 2018 @@ -348,6 +348,23 @@ void testCapturedConstExprFloat() { lambda(); } + +static int b = 0; + +int f() { + b = 0; + auto &bm = b; + [&] { + bm++; + bm++; + }(); + if (bm != 2) { + int *y = 0; + return *y; // no-warning + } + return 0; +} + // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits