From f68e0e09b0b746666cd3acd1d7ef188320cae45f Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Fri, 13 May 2016 01:21:23 +0000 Subject: [PATCH] [ObjC][CodeGen] Remove an assert that is no longer correct. clang asserts when compiling the following code because r231508 made changes to promote constant temporary arrays and records to globals with constant initializers: std::vector strs = {@"a", @"b"}; This commit changes the code to return early if the object returned by createReferenceTemporary is a global variable with an initializer. rdar://problem/25504992 rdar://problem/25955179 Differential Revision: http://reviews.llvm.org/D20045 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269385 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExpr.cpp | 13 ++++++++++--- test/CodeGenObjCXX/arc-cxx11-init-list.mm | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 8896eb4db1..1001a00b62 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -361,9 +361,16 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { ConvertTypeForMem(E->getType()) ->getPointerTo(Object.getAddressSpace())), Object.getAlignment()); - // We should not have emitted the initializer for this temporary as a - // constant. - assert(!Var->hasInitializer()); + + // createReferenceTemporary will promote the temporary to a global with a + // constant initializer if it can. It can only do this to a value of + // ARC-manageable type if the value is global and therefore "immune" to + // ref-counting operations. Therefore we have no need to emit either a + // dynamic initialization or a cleanup and we can just return the address + // of the temporary. + if (Var->hasInitializer()) + return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl); + Var->setInitializer(CGM.EmitNullConstant(E->getType())); } LValue RefTempDst = MakeAddrLValue(Object, M->getType(), diff --git a/test/CodeGenObjCXX/arc-cxx11-init-list.mm b/test/CodeGenObjCXX/arc-cxx11-init-list.mm index 7e1f10c35f..27442f8130 100644 --- a/test/CodeGenObjCXX/arc-cxx11-init-list.mm +++ b/test/CodeGenObjCXX/arc-cxx11-init-list.mm @@ -1,5 +1,11 @@ // RUN: %clang_cc1 -triple armv7-ios5.0 -std=c++11 -fobjc-arc -Os -emit-llvm -o - %s | FileCheck %s +// CHECK: @[[STR0:.*]] = private unnamed_addr constant [5 x i8] c"str0\00", section "__TEXT,__cstring,cstring_literals" +// CHECK: @[[UNNAMED_CFSTRING0:.*]] = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @[[STR0]], i32 0, i32 0), i32 4 }, section "__DATA,__cfstring" +// CHECK: @[[STR1:.*]] = private unnamed_addr constant [5 x i8] c"str1\00", section "__TEXT,__cstring,cstring_literals" +// CHECK: @[[UNNAMED_CFSTRING1:.*]] = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @[[STR1]], i32 0, i32 0), i32 4 }, section "__DATA,__cfstring" +// CHECK: @[[REFTMP:.*]] = private constant [2 x i8*] [i8* bitcast (%struct.__NSConstantString_tag* @[[UNNAMED_CFSTRING0]] to i8*), i8* bitcast (%struct.__NSConstantString_tag* @[[UNNAMED_CFSTRING1]] to i8*)] + typedef __SIZE_TYPE__ size_t; namespace std { @@ -32,6 +38,17 @@ extern "C" void multiple() { function({ [I new], [I new] }); } // CHECK-NEXT: store i8* [[INSTANCE]], i8** [[CAST]], // CHECK: call void @objc_release(i8* {{.*}}) +std::initializer_list foo1() { + return {@"str0", @"str1"}; +} + +// CHECK: define void @_Z4foo1v(%"class.std::initializer_list.0"* {{.*}} %[[AGG_RESULT:.*]]) +// CHECK: %[[BEGIN:.*]] = getelementptr inbounds %"class.std::initializer_list.0", %"class.std::initializer_list.0"* %[[AGG_RESULT]], i32 0, i32 0 +// CHECK: store i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[REFTMP]], i32 0, i32 0), i8*** %[[BEGIN]] +// CHECK: %[[SIZE:.*]] = getelementptr inbounds %"class.std::initializer_list.0", %"class.std::initializer_list.0"* %[[AGG_RESULT]], i32 0, i32 1 +// CHECK: store i32 2, i32* %[[SIZE]] +// CHECK: ret void + void external(); extern "C" void extended() { @@ -49,4 +66,3 @@ std::initializer_list il = { [I new] }; // CHECK: [[INSTANCE:%.*]] = {{.*}} call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) // CHECK-NEXT: store i8* [[INSTANCE]], i8** bitcast ([1 x %0*]* @_ZGR2il_ to i8**) // CHECK: {{.*}} call void @objc_autoreleasePoolPop(i8* [[POOL]]) - -- 2.40.0