case SD_Automatic:
case SD_FullExpression:
- assert(!ObjCARCReferenceLifetimeType->isArrayType());
CodeGenFunction::Destroyer *Destroy;
CleanupKind CleanupKind;
if (Lifetime == Qualifiers::OCL_Strong) {
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());
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;
--- /dev/null
+// 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);
+};
+}
+
+@interface I
++ (instancetype) new;
+@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]])
+