From: Richard Smith Date: Thu, 6 Jun 2013 08:19:16 +0000 (+0000) Subject: When a static storage duration temporary appears in a constant expression, it X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f69dd33cfc0b1f2a6c88d10951dbd29c4dc806c2;p=clang When a static storage duration temporary appears in a constant expression, it must be initialized by a constant expression (not just a core constant expression), because we're going to emit it as a global. Core issue for this is pending. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183388 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 19eaf55ba4..d94efc1341 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -4099,12 +4099,17 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( Result.set(E, Info.CurrentCall->Index); } + QualType Type = Inner->getType(); + // Materialize the temporary itself. - if (!EvaluateInPlace(*Value, Info, Result, Inner)) + if (!EvaluateInPlace(*Value, Info, Result, Inner) || + (E->getStorageDuration() == SD_Static && + !CheckConstantExpression(Info, E->getExprLoc(), Type, *Value))) { + *Value = APValue(); return false; + } // Adjust our lvalue to refer to the desired subobject. - QualType Type = Inner->getType(); for (unsigned I = Adjustments.size(); I != 0; /**/) { --I; switch (Adjustments[I].Kind) { diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 3a460c93af..fb2e6a32ee 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -363,6 +363,16 @@ static_assert(&b4 != &b2, ""); // Proposed DR: copy-elision doesn't trigger lifetime extension. constexpr B b5 = B{ {0}, {0} }; // expected-error {{constant expression}} expected-note {{reference to temporary}} expected-note {{here}} +namespace NestedNonStatic { + // Proposed DR: for a reference constant expression to refer to a static + // storage duration temporary, that temporary must itself be initialized + // by a constant expression (a core constant expression is not enough). + struct A { int &&r; }; + struct B { A &&a; }; + constexpr B a = { A{0} }; // ok + constexpr B b = { A(A{0}) }; // expected-error {{constant expression}} expected-note {{reference to temporary}} expected-note {{here}} +} + } constexpr int strcmp_ce(const char *p, const char *q) {