mirror of https://github.com/microsoft/clang.git
[CodeGen][ObjC] Do not call objc_storeStrong when initializing a
constexpr variable. When compiling a constexpr NSString initialized with an objective-c string literal, CodeGen emits objc_storeStrong on an uninitialized alloca, which causes a crash. This patch folds the code in EmitScalarInit into EmitStoreThroughLValue and fixes the crash by calling objc_retain on the string instead of using objc_storeStrong. rdar://problem/28562009 Differential Revision: https://reviews.llvm.org/D25547 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@284516 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3a5a4d80a5
commit
d698b929bc
|
@ -774,37 +774,6 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
|
|||
EmitStoreOfScalar(value, lvalue, /* isInitialization */ true);
|
||||
}
|
||||
|
||||
/// EmitScalarInit - Initialize the given lvalue with the given object.
|
||||
void CodeGenFunction::EmitScalarInit(llvm::Value *init, LValue lvalue) {
|
||||
Qualifiers::ObjCLifetime lifetime = lvalue.getObjCLifetime();
|
||||
if (!lifetime)
|
||||
return EmitStoreThroughLValue(RValue::get(init), lvalue, true);
|
||||
|
||||
switch (lifetime) {
|
||||
case Qualifiers::OCL_None:
|
||||
llvm_unreachable("present but none");
|
||||
|
||||
case Qualifiers::OCL_ExplicitNone:
|
||||
// nothing to do
|
||||
break;
|
||||
|
||||
case Qualifiers::OCL_Strong:
|
||||
init = EmitARCRetain(lvalue.getType(), init);
|
||||
break;
|
||||
|
||||
case Qualifiers::OCL_Weak:
|
||||
// Initialize and then skip the primitive store.
|
||||
EmitARCInitWeak(lvalue.getAddress(), init);
|
||||
return;
|
||||
|
||||
case Qualifiers::OCL_Autoreleasing:
|
||||
init = EmitARCRetainAutorelease(lvalue.getType(), init);
|
||||
break;
|
||||
}
|
||||
|
||||
EmitStoreOfScalar(init, lvalue, /* isInitialization */ true);
|
||||
}
|
||||
|
||||
/// canEmitInitWithFewStoresAfterMemset - Decide whether we can emit the
|
||||
/// non-zero parts of the specified initializer with equal or fewer than
|
||||
/// NumStores scalar stores.
|
||||
|
|
|
@ -1629,11 +1629,19 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
|
|||
break;
|
||||
|
||||
case Qualifiers::OCL_Strong:
|
||||
if (isInit) {
|
||||
Src = RValue::get(EmitARCRetain(Dst.getType(), Src.getScalarVal()));
|
||||
break;
|
||||
}
|
||||
EmitARCStoreStrong(Dst, Src.getScalarVal(), /*ignore*/ true);
|
||||
return;
|
||||
|
||||
case Qualifiers::OCL_Weak:
|
||||
EmitARCStoreWeak(Dst.getAddress(), Src.getScalarVal(), /*ignore*/ true);
|
||||
if (isInit)
|
||||
// Initialize and then skip the primitive store.
|
||||
EmitARCInitWeak(Dst.getAddress(), Src.getScalarVal());
|
||||
else
|
||||
EmitARCStoreWeak(Dst.getAddress(), Src.getScalarVal(), /*ignore*/ true);
|
||||
return;
|
||||
|
||||
case Qualifiers::OCL_Autoreleasing:
|
||||
|
|
|
@ -1662,7 +1662,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
|||
elementLValue = EmitLValue(cast<Expr>(S.getElement()));
|
||||
EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue);
|
||||
} else {
|
||||
EmitScalarInit(CurrentItem, elementLValue);
|
||||
EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue,
|
||||
/*isInit*/ true);
|
||||
}
|
||||
|
||||
// If we do have an element variable, this assignment is the end of
|
||||
|
|
|
@ -188,7 +188,7 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, QualType DstType,
|
|||
auto *RefVal = TmpAddr.getPointer();
|
||||
TmpAddr = CGF.CreateMemTemp(RefType, Twine(Name) + ".ref");
|
||||
auto TmpLVal = CGF.MakeAddrLValue(TmpAddr, RefType);
|
||||
CGF.EmitScalarInit(RefVal, TmpLVal);
|
||||
CGF.EmitStoreThroughLValue(RValue::get(RefVal), TmpLVal, /*isInit*/ true);
|
||||
}
|
||||
|
||||
return TmpAddr;
|
||||
|
@ -2192,7 +2192,7 @@ static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
|
|||
llvm::Value *Init = nullptr) {
|
||||
auto LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
|
||||
if (Init)
|
||||
CGF.EmitScalarInit(Init, LVal);
|
||||
CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true);
|
||||
return LVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -2119,7 +2119,6 @@ public:
|
|||
|
||||
void EmitScalarInit(const Expr *init, const ValueDecl *D, LValue lvalue,
|
||||
bool capturedByInit);
|
||||
void EmitScalarInit(llvm::Value *init, LValue lvalue);
|
||||
|
||||
typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D,
|
||||
llvm::Value *Address);
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// 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: %[[V0:[0-9]+]] = call i8* @objc_retain(i8* bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]]
|
||||
// CHECK: %[[V1:[0-9]+]] = bitcast i8* %[[V0]] to %[[TYPE]]*
|
||||
// CHECK: store %[[TYPE]]* %[[V1]], %[[TYPE]]** %[[ALLOCA]]
|
||||
// CHECK: %[[V2:[0-9]+]] = bitcast %[[TYPE]]** %[[ALLOCA]]
|
||||
// CHECK: call void @objc_storeStrong(i8** %[[V2]], i8* null)
|
||||
|
||||
@class NSString;
|
||||
|
||||
void test1() {
|
||||
constexpr NSString *S = @"abc";
|
||||
}
|
Loading…
Reference in New Issue