forked from OSchip/llvm-project
[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
This commit is contained in:
parent
487b0c6b66
commit
5ffe52395a
|
@ -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) {
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue