diff options
| author | Akira Hatanaka <ahatanaka@apple.com> | 2019-11-29 09:56:02 -0800 |
|---|---|---|
| committer | Akira Hatanaka <ahatanaka@apple.com> | 2019-12-03 23:44:30 -0800 |
| commit | d8136f14f125fb27f2326f397df0964bf62078ca (patch) | |
| tree | e927eb6aa7e29cdaa30c2b90dab6258fc22ffae1 /clang | |
| parent | d08dc0655e74d5c226789e1a2378c7c215ee7297 (diff) | |
| download | bcm5719-llvm-d8136f14f125fb27f2326f397df0964bf62078ca.tar.gz bcm5719-llvm-d8136f14f125fb27f2326f397df0964bf62078ca.zip | |
[CodeGen][ObjC] Emit a primitive store to store a __strong field in
ExpandTypeFromArgs
This fixes a bug in IRGen where a call to `llvm.objc.storeStrong` was
being emitted to initialize a __strong field of an uninitialized
temporary struct, which caused crashes at runtime.
rdar://problem/51807365
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 6 | ||||
| -rw-r--r-- | clang/test/CodeGenObjC/nontrivial-struct-param-init.m | 17 |
3 files changed, 28 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index f992f904fe7..ca6b1d409c2 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1047,8 +1047,13 @@ void CodeGenFunction::ExpandTypeFromArgs( auto imagValue = *AI++; EmitStoreOfComplex(ComplexPairTy(realValue, imagValue), LV, /*init*/ true); } else { + // Call EmitStoreOfScalar except when the lvalue is a bitfield to emit a + // primitive store. assert(isa<NoExpansion>(Exp.get())); - EmitStoreThroughLValue(RValue::get(*AI++), LV); + if (LV.isBitField()) + EmitStoreThroughLValue(RValue::get(*AI++), LV); + else + EmitStoreOfScalar(*AI++, LV); } } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 6e3a26e2c78..cd42faefab0 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4544,7 +4544,11 @@ RValue CodeGenFunction::EmitRValueForField(LValue LV, // don't load reference fields. if (FD->getType()->isReferenceType()) return RValue::get(FieldLV.getPointer(*this)); - return EmitLoadOfLValue(FieldLV, Loc); + // Call EmitLoadOfScalar except when the lvalue is a bitfield to emit a + // primitive load. + if (FieldLV.isBitField()) + return EmitLoadOfLValue(FieldLV, Loc); + return RValue::get(EmitLoadOfScalar(FieldLV, Loc)); } llvm_unreachable("bad evaluation kind"); } diff --git a/clang/test/CodeGenObjC/nontrivial-struct-param-init.m b/clang/test/CodeGenObjC/nontrivial-struct-param-init.m new file mode 100644 index 00000000000..96a63b83ac7 --- /dev/null +++ b/clang/test/CodeGenObjC/nontrivial-struct-param-init.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple i386-apple-watchos6.0-simulator -emit-llvm -fblocks -fobjc-arc -o - %s | FileCheck %s + +// CHECK: %[[STRUCT_S:.*]] = type { i8* } + +typedef struct { + id x; +} S; + +// CHECK: define void @test0(i8* %[[A_0:.*]]) +// CHECK: %[[A:.*]] = alloca %[[STRUCT_S]], align 4 +// CHECK: %[[X:.*]] = getelementptr inbounds %[[STRUCT_S]], %[[STRUCT_S]]* %[[A]], i32 0, i32 0 +// CHECK: store i8* %[[A_0]], i8** %[[X]], align 4 +// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_S]]* %[[A]] to i8** +// CHECK: call void @__destructor_4_s0(i8** %[[V0]]) #2 + +void test0(S a) { +} |

