r220590 - CodeGen: correct materialize temporary aggregates in ARC mode
Saleem Abdulrasool
compnerd at compnerd.org
Fri Oct 24 13:23:44 PDT 2014
Author: compnerd
Date: Fri Oct 24 15:23:43 2014
New Revision: 220590
URL: http://llvm.org/viewvc/llvm-project?rev=220590&view=rev
Log:
CodeGen: correct materialize temporary aggregates in ARC mode
Avoid an assertion when materializing a lifetime type aggregate temporary. When
performing CodeGen for ObjC++, we could generate a lifetime-only aggregate
temporary by using an initializer list (which is effectively an array). We
would reach through the temporary expression, fishing out the inner expression.
If this expression was a lifetime expression, we would attempt to emit this as a
scalar. This would eventually result in an assertion as the emission would
eventually assert that the expression being emitted has a scalar evaluation
kind.
Add a case to handle the aggregate expressions. Use the EmitAggExpr to emit the
aggregate expression rather than the EmitScalarInit.
Addresses PR21347.
Added:
cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm
Modified:
cfe/trunk/lib/CodeGen/CGExpr.cpp
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=220590&r1=220589&r2=220590&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Oct 24 15:23:43 2014
@@ -210,7 +210,6 @@ pushTemporaryCleanup(CodeGenFunction &CG
case SD_Automatic:
case SD_FullExpression:
- assert(!ObjCARCReferenceLifetimeType->isArrayType());
CodeGenFunction::Destroyer *Destroy;
CleanupKind CleanupKind;
if (Lifetime == Qualifiers::OCL_Strong) {
@@ -317,11 +316,12 @@ LValue CodeGenFunction::
EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
const Expr *E = M->GetTemporaryExpr();
+ // FIXME: ideally this would use EmitAnyExprToMem, however, we cannot do so
+ // as that will cause the lifetime adjustment to be lost for ARC
if (getLangOpts().ObjCAutoRefCount &&
M->getType()->isObjCLifetimeType() &&
M->getType().getObjCLifetime() != Qualifiers::OCL_None &&
M->getType().getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
- // FIXME: Fold this into the general case below.
llvm::Value *Object = createReferenceTemporary(*this, M, E);
LValue RefTempDst = MakeAddrLValue(Object, M->getType());
@@ -332,7 +332,21 @@ EmitMaterializeTemporaryExpr(const Mater
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
}
- EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false);
+ switch (getEvaluationKind(E->getType())) {
+ default: llvm_unreachable("expected scalar or aggregate expression");
+ case TEK_Scalar:
+ EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false);
+ break;
+ case TEK_Aggregate: {
+ CharUnits Alignment = getContext().getTypeAlignInChars(E->getType());
+ EmitAggExpr(E, AggValueSlot::forAddr(Object, Alignment,
+ E->getType().getQualifiers(),
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased));
+ break;
+ }
+ }
pushTemporaryCleanup(*this, M, E, Object);
return RefTempDst;
Added: cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm?rev=220590&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm (added)
+++ cfe/trunk/test/CodeGenObjCXX/arc-cxx11-init-list.mm Fri Oct 24 15:23:43 2014
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -triple armv7-ios5.0 -std=c++11 -fobjc-arc -Os -emit-llvm -o - %s \
+// RUN: | FileCheck %s
+
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+template <typename _Ep>
+class initializer_list {
+ const _Ep* __begin_;
+ size_t __size_;
+
+ initializer_list(const _Ep* __b, size_t __s);
+};
+}
+
+ at interface I
++ (instancetype) new;
+ at end
+
+void function(std::initializer_list<I *>);
+
+extern "C" void single() { function({ [I new] }); }
+
+// CHECK: [[INSTANCE:%.*]] = {{.*}} call {{.*}} i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}})
+// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[INSTANCE]] to %0*
+// CHECK-NEXT: store %0* [[CAST]], %0** [[ARRAY:%.*]],
+// CHECK: call {{.*}} void @objc_release(i8* {{.*}})
+
+extern "C" void multiple() { function({ [I new], [I new] }); }
+
+// CHECK: [[INSTANCE:%.*]] = {{.*}} call {{.*}} i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}})
+// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[INSTANCE]] to %0*
+// CHECK-NEXT: store %0* [[CAST]], %0** [[ARRAY:%.*]],
+// CHECK: call {{.*}} void @objc_release(i8* {{.*}})
+// CHECK-NEXT: icmp eq
+
+void external();
+
+extern "C" void extended() {
+ const auto && temporary = { [I new] };
+ external();
+}
+
+// CHECK: [[INSTANCE:%.*]] = {{.*}} call {{.*}} i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}})
+// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[INSTANCE:%.*]] to {{.*}}*
+// CHECK-NEXT: store {{.*}}* [[CAST]], {{.*}}** {{.*}}
+// CHECK: {{.*}} call {{.*}} void @_Z8externalv()
+// CHECK: {{.*}} call {{.*}} void @objc_release(i8* {{.*}})
+
+std::initializer_list<I *> il = { [I new] };
+
+// CHECK: [[POOL:%.*]] = {{.*}} call {{.*}} i8* @objc_autoreleasePoolPush()
+// CHECK: [[INSTANCE:%.*]] = {{.*}} call {{.*}} i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}})
+// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[INSTANCE]] to [[POOL]]*
+// CHECK-NEXT: store [[POOL]]* [[CAST]], [[POOL]]** getelementptr inbounds ([1 x [[POOL]]*]* @_ZGR2il_, i32 0, i32 0)
+// CHECK: {{.*}} call {{.*}} void @objc_autoreleasePoolPop(i8* [[POOL]])
+
More information about the cfe-commits
mailing list