]> granicus.if.org Git - clang/commitdiff
When a static storage duration temporary appears in a constant expression, it
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 6 Jun 2013 08:19:16 +0000 (08:19 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 6 Jun 2013 08:19:16 +0000 (08:19 +0000)
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

lib/AST/ExprConstant.cpp
test/SemaCXX/constant-expression-cxx11.cpp

index 19eaf55ba431c64dc0fd48300f2fa9435b630d99..d94efc134132279a22fa39f875648701c0a64c56 100644 (file)
@@ -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) {
index 3a460c93af0d67ccad08a031411d9d14b9b13cc6..fb2e6a32ee2035e9633fadfa56f6115dee8f7320 100644 (file)
@@ -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) {