Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -1235,7 +1235,7 @@ // For simple scalar/complex initialization, store the value directly. LValue lv = MakeAddrLValue(Loc, type); lv.setNonGC(true); - return EmitStoreThroughLValue(RValue::get(constant), lv, true); + return EmitStoreThroughLValue(RValue::get(constant), lv, true, true); } // If this is a simple aggregate initialization, we can optimize it Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -1593,7 +1593,7 @@ /// lvalue, where both are guaranteed to the have the same type, and that type /// is 'Ty'. void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, - bool isInit) { + bool isInit, bool IsConstExpr) { if (!Dst.isSimple()) { if (Dst.isVectorElt()) { // Read/modify/write the vector, inserting the new element. @@ -1619,62 +1619,63 @@ } // There's special magic for assigning into an ARC-qualified l-value. - if (Qualifiers::ObjCLifetime Lifetime = Dst.getQuals().getObjCLifetime()) { - switch (Lifetime) { - case Qualifiers::OCL_None: - llvm_unreachable("present but none"); + if (!IsConstExpr) { + if (Qualifiers::ObjCLifetime Lifetime = Dst.getQuals().getObjCLifetime()) { + switch (Lifetime) { + case Qualifiers::OCL_None: + llvm_unreachable("present but none"); - case Qualifiers::OCL_ExplicitNone: - // nothing special - break; + case Qualifiers::OCL_ExplicitNone: + // nothing special + break; - case Qualifiers::OCL_Strong: - EmitARCStoreStrong(Dst, Src.getScalarVal(), /*ignore*/ true); - return; + case Qualifiers::OCL_Strong: + EmitARCStoreStrong(Dst, Src.getScalarVal(), /*ignore*/ true); + return; - case Qualifiers::OCL_Weak: - EmitARCStoreWeak(Dst.getAddress(), Src.getScalarVal(), /*ignore*/ true); - return; + case Qualifiers::OCL_Weak: + EmitARCStoreWeak(Dst.getAddress(), Src.getScalarVal(), /*ignore*/ true); + return; - case Qualifiers::OCL_Autoreleasing: - Src = RValue::get(EmitObjCExtendObjectLifetime(Dst.getType(), - Src.getScalarVal())); - // fall into the normal path - break; + case Qualifiers::OCL_Autoreleasing: + Src = RValue::get( + EmitObjCExtendObjectLifetime(Dst.getType(), Src.getScalarVal())); + // fall into the normal path + break; + } } - } - if (Dst.isObjCWeak() && !Dst.isNonGC()) { - // load of a __weak object. - Address LvalueDst = Dst.getAddress(); - llvm::Value *src = Src.getScalarVal(); - CGM.getObjCRuntime().EmitObjCWeakAssign(*this, src, LvalueDst); - return; - } + if (Dst.isObjCWeak() && !Dst.isNonGC()) { + // load of a __weak object. + Address LvalueDst = Dst.getAddress(); + llvm::Value *src = Src.getScalarVal(); + CGM.getObjCRuntime().EmitObjCWeakAssign(*this, src, LvalueDst); + return; + } - if (Dst.isObjCStrong() && !Dst.isNonGC()) { - // load of a __strong object. - Address LvalueDst = Dst.getAddress(); - llvm::Value *src = Src.getScalarVal(); - if (Dst.isObjCIvar()) { - assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); - llvm::Type *ResultType = IntPtrTy; - Address dst = EmitPointerWithAlignment(Dst.getBaseIvarExp()); - llvm::Value *RHS = dst.getPointer(); - RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); - llvm::Value *LHS = - Builder.CreatePtrToInt(LvalueDst.getPointer(), ResultType, - "sub.ptr.lhs.cast"); - llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); - CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, - BytesBetween); - } else if (Dst.isGlobalObjCRef()) { - CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst, - Dst.isThreadLocalRef()); + if (Dst.isObjCStrong() && !Dst.isNonGC()) { + // load of a __strong object. + Address LvalueDst = Dst.getAddress(); + llvm::Value *src = Src.getScalarVal(); + if (Dst.isObjCIvar()) { + assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); + llvm::Type *ResultType = IntPtrTy; + Address dst = EmitPointerWithAlignment(Dst.getBaseIvarExp()); + llvm::Value *RHS = dst.getPointer(); + RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); + llvm::Value *LHS = + Builder.CreatePtrToInt(LvalueDst.getPointer(), ResultType, + "sub.ptr.lhs.cast"); + llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); + CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, + BytesBetween); + } else if (Dst.isGlobalObjCRef()) { + CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst, + Dst.isThreadLocalRef()); + } else + CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst); + return; } - else - CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst); - return; } assert(Src.isScalar() && "Can't emit an agg store with this method"); Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -2709,7 +2709,8 @@ /// EmitStoreThroughLValue - Store the specified rvalue into the specified /// lvalue, where both are guaranteed to the have the same type, and that type /// is 'Ty'. - void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit = false); + void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit = false, + bool IsConstExpr = false); void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst); void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst); Index: test/CodeGenObjCXX/arc-constexpr.mm =================================================================== --- /dev/null +++ test/CodeGenObjCXX/arc-constexpr.mm @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -o - -std=c++11 %s | FileCheck %s + +// CHECK: %[[TYPE:[a-z0-9]+]] = type opaque +// CHECK: @[[CFSTRING:[a-z0-9_]+]] = private global %struct.__NSConstantString_tag + +// CHECK: define void @_Z5test1v +// CHECK: %[[ALLOCA:[A-Z]+]] = alloca %[[TYPE]]* +// CHECK: store %[[TYPE]]* bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]] to %[[TYPE]]*), %[[TYPE]]** %[[ALLOCA]] +// CHECK: %[[V0:[a-z0-9]+]] = bitcast %[[TYPE]]** %[[ALLOCA]] to i8** +// CHECK: call void @objc_storeStrong(i8** %[[V0]], i8* null) + +@class NSString; + +void test1() { + constexpr NSString *S = @"abc"; +}