Re: [PATCH] D20045: [ObjC][CodeGen] Remove an assert that is no longer correct.

2016-05-12 Thread Akira Hatanaka via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL269385: [ObjC][CodeGen] Remove an assert that is no longer 
correct. (authored by ahatanak).

Changed prior to commit:
  http://reviews.llvm.org/D20045?vs=57111=57125#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D20045

Files:
  cfe/trunk/lib/CodeGen/CGExpr.cpp
  cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm

Index: cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm
===
--- cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ cfe/trunk/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 @@
 // 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 @@
 // 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]])
-
Index: cfe/trunk/lib/CodeGen/CGExpr.cpp
===
--- cfe/trunk/lib/CodeGen/CGExpr.cpp
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp
@@ -361,9 +361,16 @@
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(),


Index: cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm
===
--- cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ cfe/trunk/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 

Re: [PATCH] D20045: [ObjC][CodeGen] Remove an assert that is no longer correct.

2016-05-12 Thread John McCall via cfe-commits
rjmccall added a comment.

LGTM, thanks.


http://reviews.llvm.org/D20045



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D20045: [ObjC][CodeGen] Remove an assert that is no longer correct.

2016-05-12 Thread Akira Hatanaka via cfe-commits
ahatanak updated this revision to Diff 57111.
ahatanak added a comment.

Thanks, I updated the comment in the new patch.


http://reviews.llvm.org/D20045

Files:
  lib/CodeGen/CGExpr.cpp
  test/CodeGenObjCXX/arc-cxx11-init-list.mm

Index: test/CodeGenObjCXX/arc-cxx11-init-list.mm
===
--- test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ 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 @@
 // 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 @@
 // 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]])
-
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -360,9 +360,16 @@
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(),


Index: test/CodeGenObjCXX/arc-cxx11-init-list.mm
===
--- test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ 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 

Re: [PATCH] D20045: [ObjC][CodeGen] Remove an assert that is no longer correct.

2016-05-12 Thread John McCall via cfe-commits
rjmccall added inline comments.


Comment at: lib/CodeGen/CGExpr.cpp:365
@@ +364,3 @@
+  // If the global variable already has an initializer, there is no need to
+  // emit code for initialization or push a cleanup.
+  if (Var->hasInitializer())

As we discussed in person, please make the comment address *why* this can ever 
have an initializer.  I think something like this would be ok:

  // 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.


http://reviews.llvm.org/D20045



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D20045: [ObjC][CodeGen] Remove an assert that is no longer correct.

2016-05-12 Thread Akira Hatanaka via cfe-commits
ahatanak added a comment.

In http://reviews.llvm.org/D20045#425903, @manmanren wrote:

> After r231508 made changes to promote constant temporaries to globals, the 
> assert fires when a std::initializer_list is constructed using Objective-C 
> string literals.
>
> --> Can you explain the code path after r231508 for your example? Will 
> r231508 change the code path if we start with a global?
>  r231508 seems to change the behavior constant temporaries only.


I think your question is about the following case where initializer_list is 
used to initialize a global variable?

const std::vector CfgFiles = {@"Test0", @"Test1", @"Test2", 
@"Test3"};

This is not different from the case where the vector is declared inside a 
function. In both cases, a temporary std::initializer_list is created and 
passed to std::vector's constructor. 
r231508 made changes to create a global array of strings (@.ref.tmp in the IR 
shown below).

@.ref.tmp = private constant [4 x %0*] [%0* bitcast 
(%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %0*), %0* bitcast 
(%struct.__NSConstantString_tag* @_unnamed_cfstring_.2 to %0*), %0* bitcast 
(%struct.__NSConstantString_tag* @_unnamed_cfstring_.4 to %0*), %0* bitcast 
(%struct.__NSConstantString_tag* @_unnamed_cfstring_.6 to %0*)], align 8
...
%agg.tmp = alloca %"class.std::initializer_list", align 8 ; temporary 
std::initializer_list
%__begin_ = getelementptr inbounds %"class.std::initializer_list", 
%"class.std::initializer_list"* %agg.tmp, i32 0, i32 0
store %0** getelementptr inbounds ([4 x %0*], [4 x %0*]* @.ref.tmp, i64 0, i64 
0), %0*** %__begin_, align 8, !tbaa !7 ; std::initializer_list holds a pointer 
to the array.


http://reviews.llvm.org/D20045



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D20045: [ObjC][CodeGen] Remove an assert that is no longer correct.

2016-05-12 Thread Akira Hatanaka via cfe-commits
ahatanak updated this revision to Diff 57088.
ahatanak added a comment.

Add a comment explaining why it is OK to return early if the global variable 
has an initializer.


http://reviews.llvm.org/D20045

Files:
  lib/CodeGen/CGExpr.cpp
  test/CodeGenObjCXX/arc-cxx11-init-list.mm

Index: test/CodeGenObjCXX/arc-cxx11-init-list.mm
===
--- test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ 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 @@
 // 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 @@
 // 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]])
-
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -360,9 +360,12 @@
ConvertTypeForMem(E->getType())
  ->getPointerTo(Object.getAddressSpace())),
Object.getAlignment());
-  // We should not have emitted the initializer for this temporary as a
-  // constant.
-  assert(!Var->hasInitializer());
+
+  // If the global variable already has an initializer, there is no need to
+  // emit code for initialization or push a cleanup.
+  if (Var->hasInitializer())
+return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
+
   Var->setInitializer(CGM.EmitNullConstant(E->getType()));
 }
 LValue RefTempDst = MakeAddrLValue(Object, M->getType(),


Index: test/CodeGenObjCXX/arc-cxx11-init-list.mm
===
--- test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ 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* 

Re: [PATCH] D20045: [ObjC][CodeGen] Remove an assert that is no longer correct.

2016-05-10 Thread Manman Ren via cfe-commits
manmanren added a comment.

After r231508 made changes to promote constant temporaries to globals, the 
assert fires when a std::initializer_list is constructed using Objective-C 
string literals.

--> Can you explain the code path after r231508 for your example? Will r231508 
change the code path if we start with a global?
r231508 seems to change the behavior constant temporaries only.

Thanks for working on this!
Manman



Comment at: lib/CodeGen/CGExpr.cpp:364
@@ +363,3 @@
+
+  if (Var->hasInitializer())
+return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);

Can you add comments here?


http://reviews.llvm.org/D20045



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20045: [ObjC][CodeGen] Remove an assert that is no longer correct.

2016-05-06 Thread Akira Hatanaka via cfe-commits
ahatanak created this revision.
ahatanak added reviewers: rjmccall, rsmith, manmanren.
ahatanak added a subscriber: cfe-commits.

The assert was committed in r183967. After r231508 made changes to promote 
constant temporaries to globals, the assert fires when a std::initializer_list 
is constructed using Objective-C string literals:

void foo1() {
  std::vector strs = {@"a", @"b"};
}

rdar://problem/25504992
rdar://problem/25955179

http://reviews.llvm.org/D20045

Files:
  lib/CodeGen/CGExpr.cpp
  test/CodeGenObjCXX/arc-cxx11-init-list.mm

Index: test/CodeGenObjCXX/arc-cxx11-init-list.mm
===
--- test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ 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 @@
 // 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 @@
 // 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]])
-
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -360,9 +360,10 @@
ConvertTypeForMem(E->getType())
  ->getPointerTo(Object.getAddressSpace())),
Object.getAlignment());
-  // We should not have emitted the initializer for this temporary as a
-  // constant.
-  assert(!Var->hasInitializer());
+
+  if (Var->hasInitializer())
+return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
+
   Var->setInitializer(CGM.EmitNullConstant(E->getType()));
 }
 LValue RefTempDst = MakeAddrLValue(Object, M->getType(),


Index: test/CodeGenObjCXX/arc-cxx11-init-list.mm
===
--- test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ 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