Model temporary lifetime-extension explicitly in the AST. Use this model to
handle temporaries which have been lifetime-extended to static storage duration
within constant expressions. This correctly handles nested lifetime extension
(through reference members of aggregates in aggregate initializers) but
non-constant-expression emission hasn't yet been updated to do the same.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183283 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index 9e5b5ef..46eca0e 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -224,12 +224,50 @@
     constexpr Lit() : n(5) {}
     int n;
   };
-  // FIXME: This should have static initialization, but we do not implement
-  // that yet. For now, just check that we don't set the (pointer) value of
-  // the reference to 5!
-  //
-  // CHECK: @_ZN16LiteralReference3litE = global {{.*}} null
+
+  // This creates a non-const temporary and binds a reference to it.
+  // CHECK: @[[TEMP:.*]] = private global {{.*}} { i32 5 }, align 4
+  // CHECK: @_ZN16LiteralReference3litE = constant {{.*}} @[[TEMP]], align 8
   const Lit &lit = Lit();
+
+  // This creates a const temporary as part of the reference initialization.
+  // CHECK: @[[TEMP:.*]] = private constant {{.*}} { i32 5 }, align 4
+  // CHECK: @_ZN16LiteralReference4lit2E = constant {{.*}} @[[TEMP]], align 8
+  const Lit &lit2 = {};
+
+  struct A { int &&r1; const int &&r2; };
+  struct B { A &&a1; const A &&a2; };
+  B b = { { 0, 1 }, { 2, 3 } };
+  // CHECK: @[[TEMP0:.*]] = private global i32 0, align 4
+  // CHECK: @[[TEMP1:.*]] = private constant i32 1, align 4
+  // CHECK: @[[TEMPA1:.*]] = private global {{.*}} { i32* @[[TEMP0]], i32* @[[TEMP1]] }, align 8
+  // CHECK: @[[TEMP2:.*]] = private global i32 2, align 4
+  // CHECK: @[[TEMP3:.*]] = private constant i32 3, align 4
+  // CHECK: @[[TEMPA2:.*]] = private constant {{.*}} { i32* @[[TEMP2]], i32* @[[TEMP3]] }, align 8
+  // CHECK: @_ZN16LiteralReference1bE = global {{.*}} { {{.*}}* @[[TEMPA1]], {{.*}}* @[[TEMPA2]] }, align 8
+
+  struct Subobj {
+    int a, b, c;
+  };
+  // CHECK: @[[TEMP:.*]] = private global {{.*}} { i32 1, i32 2, i32 3 }, align 4
+  // CHECK: @_ZN16LiteralReference2soE = constant {{.*}} (i8* getelementptr {{.*}} @[[TEMP]]{{.*}}, i64 4)
+  constexpr int &&so = Subobj{ 1, 2, 3 }.b;
+
+  struct Dummy { int padding; };
+  struct Derived : Dummy, Subobj {
+    constexpr Derived() : Dummy{200}, Subobj{4, 5, 6} {}
+  };
+  using ConstDerived = const Derived;
+  // CHECK: @[[TEMPCOMMA:.*]] = private constant {{.*}} { i32 200, i32 4, i32 5, i32 6 }
+  // CHECK: @_ZN16LiteralReference5commaE = constant {{.*}} getelementptr {{.*}} @[[TEMPCOMMA]]{{.*}}, i64 8)
+  constexpr const int &comma = (1, (2, ConstDerived{}).b);
+
+  // CHECK: @[[TEMPDERIVED:.*]] = private global {{.*}} { i32 200, i32 4, i32 5, i32 6 }
+  // CHECK: @_ZN16LiteralReference4baseE = constant {{.*}} getelementptr {{.*}} @[[TEMPDERIVED]]{{.*}}, i64 4)
+  constexpr Subobj &&base = Derived{};
+
+  // CHECK: @_ZN16LiteralReference7derivedE = constant {{.*}} @[[TEMPDERIVED]]
+  constexpr Derived &derived = static_cast<Derived&>(base);
 }
 
 namespace NonLiteralConstexpr {
@@ -330,6 +368,17 @@
   extern const S s {};
 }
 
+namespace UnemittedTemporaryDecl {
+  constexpr int &&ref = 0;
+  extern constexpr int &ref2 = ref;
+  // CHECK: @_ZGRN22UnemittedTemporaryDecl3refE = private global i32 0
+
+  // FIXME: This declaration should not be emitted -- it isn't odr-used.
+  // CHECK: @_ZN22UnemittedTemporaryDecl3refE
+
+  // CHECK: @_ZN22UnemittedTemporaryDecl4ref2E = constant i32* @_ZGRN22UnemittedTemporaryDecl3refE
+}
+
 // CHECK: @_ZZN12LocalVarInit3aggEvE1a = internal constant {{.*}} i32 101
 // CHECK: @_ZZN12LocalVarInit4ctorEvE1a = internal constant {{.*}} i32 102
 // CHECK: @_ZZN12LocalVarInit8mutable_EvE1a = private unnamed_addr constant {{.*}} i32 103