diff options
| author | George Karpenkov <ekarpenkov@apple.com> | 2018-03-20 00:20:58 +0000 |
|---|---|---|
| committer | George Karpenkov <ekarpenkov@apple.com> | 2018-03-20 00:20:58 +0000 |
| commit | 5ffe52395a39ebc800dcd8a1c9975b89416d770c (patch) | |
| tree | 239108d0b8ce0a916ff225fcbbece783b8451316 /clang/lib | |
| parent | 487b0c6b66ce6f2fbd91fc268839bd06f1fdd89d (diff) | |
| download | bcm5719-llvm-5ffe52395a39ebc800dcd8a1c9975b89416d770c.tar.gz bcm5719-llvm-5ffe52395a39ebc800dcd8a1c9975b89416d770c.zip | |
[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
llvm-svn: 327926
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 28 |
1 files changed, 13 insertions, 15 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 2c3d2f0bc5c..e6e5be0d137 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -2462,8 +2462,8 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, 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(const Expr *Ex, const NamedDecl *D, 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) { |

