forked from OSchip/llvm-project
PR15884: In the 'taking the address of a temporary' extension, materialize the
temporary to an lvalue before taking its address. This removes a weird special case from the AST representation, and allows the constant expression evaluator to deal with it without (broken) hacks. llvm-svn: 180866
This commit is contained in:
parent
dc16628c93
commit
9f8400eca4
|
@ -3215,14 +3215,12 @@ public:
|
|||
} // end anonymous namespace
|
||||
|
||||
/// Evaluate an expression as an lvalue. This can be legitimately called on
|
||||
/// expressions which are not glvalues, in a few cases:
|
||||
/// * function designators in C,
|
||||
/// * "extern void" objects,
|
||||
/// * temporaries, if building with -Wno-address-of-temporary.
|
||||
static bool EvaluateLValue(const Expr* E, LValue& Result, EvalInfo &Info) {
|
||||
assert((E->isGLValue() || E->getType()->isFunctionType() ||
|
||||
E->getType()->isVoidType() || isa<CXXTemporaryObjectExpr>(E)) &&
|
||||
"can't evaluate expression as an lvalue");
|
||||
/// expressions which are not glvalues, in two cases:
|
||||
/// * function designators in C, and
|
||||
/// * "extern void" objects
|
||||
static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info) {
|
||||
assert(E->isGLValue() || E->getType()->isFunctionType() ||
|
||||
E->getType()->isVoidType());
|
||||
return LValueExprEvaluator(Info, Result).Visit(E);
|
||||
}
|
||||
|
||||
|
|
|
@ -8306,6 +8306,9 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
|
|||
<< op->getType() << op->getSourceRange();
|
||||
if (sfinae)
|
||||
return QualType();
|
||||
// Materialize the temporary as an lvalue so that we can take its address.
|
||||
OrigOp = op = new (S.Context)
|
||||
MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true);
|
||||
} else if (isa<ObjCSelectorExpr>(op)) {
|
||||
return S.Context.getPointerType(op->getType());
|
||||
} else if (lval == Expr::LV_MemberFunction) {
|
||||
|
|
|
@ -1480,3 +1480,13 @@ namespace ArrayEltInit {
|
|||
static_assert(b[0].p != &b[9].p, "");
|
||||
static_assert(b[9].p != &b[0].p, "");
|
||||
}
|
||||
|
||||
namespace PR15884 {
|
||||
struct S {};
|
||||
constexpr S f() { return {}; }
|
||||
constexpr S *p = &f();
|
||||
// expected-error@-1 {{taking the address of a temporary}}
|
||||
// expected-error@-2 {{constexpr variable 'p' must be initialized by a constant expression}}
|
||||
// expected-note@-3 {{pointer to temporary is not a constant expression}}
|
||||
// expected-note@-4 {{temporary created here}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue