]> granicus.if.org Git - clang/commitdiff
Recursively lifetime-extend into array temporaries. These can get implicitly
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 8 Jun 2013 00:02:08 +0000 (00:02 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 8 Jun 2013 00:02:08 +0000 (00:02 +0000)
created through binding a reference-to-array to an initializer list.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183594 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaInit.cpp
test/CodeGenCXX/const-init-cxx11.cpp
test/SemaCXX/constant-expression-cxx11.cpp

index 60c67cd38bbe5fde13fb2f603b0288480b09fd9d..7d73e0890ec9bdd668c3f7982148f405d3bf23e7 100644 (file)
@@ -3149,8 +3149,7 @@ static void TryReferenceListInitialization(Sema &S,
                                            const InitializedEntity &Entity,
                                            const InitializationKind &Kind,
                                            InitListExpr *InitList,
-                                           InitializationSequence &Sequence)
-{
+                                           InitializationSequence &Sequence) {
   // First, catch C++03 where this isn't possible.
   if (!S.getLangOpts().CPlusPlus11) {
     Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
@@ -5216,7 +5215,7 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
       Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
 
   if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
-    if (ILE->initializesStdInitializerList()) {
+    if (ILE->initializesStdInitializerList() || ILE->getType()->isArrayType()) {
       // FIXME: If this is an InitListExpr which creates a std::initializer_list
       //        object, we also need to lifetime-extend the underlying array
       //        itself. Fix the representation to explicitly materialize an
@@ -5226,7 +5225,7 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
       return;
     }
 
-    CXXRecordDecl *RD = Init->getType()->getAsCXXRecordDecl();
+    CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl();
     if (RD) {
       assert(RD->isAggregate() && "aggregate init on non-aggregate");
 
index 46eca0e5c94b069f83220e172f6f86fda03902b9..843532b2a1044fae9730036230e2336816adce7d 100644 (file)
@@ -368,6 +368,17 @@ namespace PR13273 {
   extern const S s {};
 }
 
+namespace ArrayTemporary {
+  struct A { const int (&x)[3]; };
+  struct B { const A (&x)[2]; };
+  // CHECK: @[[A1:_ZGRN14ArrayTemporary1bE.*]] = private constant [3 x i32] [i32 1, i32 2, i32 3]
+  // CHECK: @[[A2:_ZGRN14ArrayTemporary1bE.*]] = private constant [3 x i32] [i32 4, i32 5, i32 6]
+  // CHECK: @[[ARR:_ZGRN14ArrayTemporary1bE.*]] = private constant [2 x {{.*}}] [{{.*}} { [3 x i32]* @[[A1]] }, {{.*}} { [3 x i32]* @[[A2]] }]
+  // CHECK: @[[B:_ZGRN14ArrayTemporary1bE.*]] = private global {{.*}} { [2 x {{.*}}]* @[[ARR]] }
+  // CHECK: @_ZN14ArrayTemporary1bE = constant {{.*}}* @[[B]]
+  B &&b = { { { { 1, 2, 3 } }, { { 4, 5, 6 } } } };
+}
+
 namespace UnemittedTemporaryDecl {
   constexpr int &&ref = 0;
   extern constexpr int &ref2 = ref;
index fb2e6a32ee2035e9633fadfa56f6115dee8f7320..8968ba05f9032f3137e51c28305f4f6ecdfc649e 100644 (file)
@@ -373,6 +373,12 @@ namespace NestedNonStatic {
   constexpr B b = { A(A{0}) }; // expected-error {{constant expression}} expected-note {{reference to temporary}} expected-note {{here}}
 }
 
+namespace FakeInitList {
+  struct init_list_3_ints { const int (&x)[3]; };
+  struct init_list_2_init_list_3_ints { const init_list_3_ints (&x)[2]; };
+  constexpr init_list_2_init_list_3_ints ils = { { { { 1, 2, 3 } }, { { 4, 5, 6 } } } };
+}
+
 }
 
 constexpr int strcmp_ce(const char *p, const char *q) {