From: Richard Smith Date: Sat, 8 Jun 2013 00:02:08 +0000 (+0000) Subject: Recursively lifetime-extend into array temporaries. These can get implicitly X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b6e3808bfe385da8d90bb431e41e30d721d5433f;p=clang Recursively lifetime-extend into array temporaries. These can get implicitly 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 --- diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 60c67cd38b..7d73e0890e 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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(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"); diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp index 46eca0e5c9..843532b2a1 100644 --- a/test/CodeGenCXX/const-init-cxx11.cpp +++ b/test/CodeGenCXX/const-init-cxx11.cpp @@ -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; diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index fb2e6a32ee..8968ba05f9 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -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) {