forked from OSchip/llvm-project
Fix crash or wrong code bug if a lifetime-extended temporary contains a
"non-constant" value. If the constant evaluator evaluates part of a variable initializer, including the initializer for some lifetime-extended temporary, but fails to fully evaluate the initializer, it can leave behind wrong values for temporaries encountered in that initialization. Don't try to emit those from CodeGen! Instead, look at the values that constant evaluation produced if (and only if) it actually succeeds and we're emitting the lifetime-extending declaration's initializer as a constant. llvm-svn: 374119
This commit is contained in:
parent
f61f13d4e7
commit
48632af25c
|
@ -13569,8 +13569,10 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage,
|
||||||
if (!Info.discardCleanups())
|
if (!Info.discardCleanups())
|
||||||
llvm_unreachable("Unhandled cleanup; missing full expression marker?");
|
llvm_unreachable("Unhandled cleanup; missing full expression marker?");
|
||||||
|
|
||||||
return CheckConstantExpression(Info, getExprLoc(), getType(), Result.Val,
|
QualType T = getType();
|
||||||
Usage) &&
|
if (!isRValue())
|
||||||
|
T = Ctx.getLValueReferenceType(T);
|
||||||
|
return CheckConstantExpression(Info, getExprLoc(), T, Result.Val, Usage) &&
|
||||||
CheckMemoryLeaks(Info);
|
CheckMemoryLeaks(Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4978,14 +4978,13 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
|
||||||
VD, E->getManglingNumber(), Out);
|
VD, E->getManglingNumber(), Out);
|
||||||
|
|
||||||
APValue *Value = nullptr;
|
APValue *Value = nullptr;
|
||||||
if (E->getStorageDuration() == SD_Static) {
|
if (E->getStorageDuration() == SD_Static && VD && VD->evaluateValue()) {
|
||||||
// We might have a cached constant initializer for this temporary. Note
|
// If the initializer of the extending declaration is a constant
|
||||||
// that this might have a different value from the value computed by
|
// initializer, we should have a cached constant initializer for this
|
||||||
// evaluating the initializer if the surrounding constant expression
|
// temporary. Note that this might have a different value from the value
|
||||||
// modifies the temporary.
|
// computed by evaluating the initializer if the surrounding constant
|
||||||
|
// expression modifies the temporary.
|
||||||
Value = getContext().getMaterializedTemporaryValue(E, false);
|
Value = getContext().getMaterializedTemporaryValue(E, false);
|
||||||
if (Value && Value->isAbsent())
|
|
||||||
Value = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try evaluating it now, it might have a constant initializer.
|
// Try evaluating it now, it might have a constant initializer.
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s -std=c++2a | FileCheck %s
|
||||||
|
|
||||||
|
// CHECK-DAG: @p = {{.*}} null
|
||||||
|
// CHECK-DAG: @_ZGR1p_ = {{.*}} null
|
||||||
|
int *const &p = new int;
|
||||||
|
|
||||||
|
struct d {
|
||||||
|
constexpr d(int &&f) : e(f) {}
|
||||||
|
int &e;
|
||||||
|
};
|
||||||
|
|
||||||
|
// CHECK-DAG: @g = {{.*}} null
|
||||||
|
// CHECK-DAG: @_ZGR1g_ = {{.*}} zeroinitializer
|
||||||
|
d &&g{{0}};
|
||||||
|
|
||||||
|
// CHECK: define {{.*}} @__cxx_global_var_init
|
||||||
|
// CHECK: define {{.*}} @__cxx_global_var_init
|
||||||
|
// CHECK-NOT: define {{.*}} @__cxx_global_var_init
|
Loading…
Reference in New Issue