diff options
author | Akira Hatanaka <ahatanaka@apple.com> | 2018-02-28 07:15:55 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@apple.com> | 2018-02-28 07:15:55 +0000 |
commit | 7275da0f2ee24336fe83cb7cfe2ba22f9cefc117 (patch) | |
tree | 9faf6e67f81d54afcaa45b6300b4c150070a2eb3 /clang/lib/CodeGen/CGDecl.cpp | |
parent | ac799b05d42fee69a91bf35beb7f87c548827a42 (diff) | |
download | llvm-7275da0f2ee24336fe83cb7cfe2ba22f9cefc117.zip llvm-7275da0f2ee24336fe83cb7cfe2ba22f9cefc117.tar.gz llvm-7275da0f2ee24336fe83cb7cfe2ba22f9cefc117.tar.bz2 |
[ObjC] Allow declaring __strong pointer fields in structs in Objective-C
ARC mode.
Declaring __strong pointer fields in structs was not allowed in
Objective-C ARC until now because that would make the struct non-trivial
to default-initialize, copy/move, and destroy, which is not something C
was designed to do. This patch lifts that restriction.
Special functions for non-trivial C structs are synthesized that are
needed to default-initialize, copy/move, and destroy the structs and
manage the ownership of the objects the __strong pointer fields point
to. Non-trivial structs passed to functions are destructed in the callee
function.
rdar://problem/33599681
Differential Revision: https://reviews.llvm.org/D41228
llvm-svn: 326307
Diffstat (limited to 'clang/lib/CodeGen/CGDecl.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 007dcf2..41c1684 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1289,6 +1289,19 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { if (emission.IsByRef) emitByrefStructureInit(emission); + // Initialize the variable here if it doesn't have a initializer and it is a + // C struct that is non-trivial to initialize or an array containing such a + // struct. + if (!Init && + type.isNonTrivialToPrimitiveDefaultInitialize() == + QualType::PDIK_Struct) { + LValue Dst = MakeAddrLValue(emission.getAllocatedAddress(), type); + if (emission.IsByRef) + drillIntoBlockVariable(*this, Dst, &D); + defaultInitNonTrivialCStructVar(Dst); + return; + } + if (isTrivialInitializer(Init)) return; @@ -1464,6 +1477,10 @@ void CodeGenFunction::emitAutoVarTypeCleanup( case QualType::DK_objc_weak_lifetime: break; + + case QualType::DK_nontrivial_c_struct: + destroyer = CodeGenFunction::destroyNonTrivialCStruct; + break; } // If we haven't chosen a more specific destroyer, use the default. @@ -1525,6 +1542,8 @@ CodeGenFunction::getDestroyer(QualType::DestructionKind kind) { return destroyARCStrongPrecise; case QualType::DK_objc_weak_lifetime: return destroyARCWeak; + case QualType::DK_nontrivial_c_struct: + return destroyNonTrivialCStruct; } llvm_unreachable("Unknown DestructionKind"); } @@ -1876,9 +1895,12 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // cleanup. if (!IsScalar && !CurFuncIsThunk && getContext().isParamDestroyedInCallee(Ty)) { - const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - if (RD && RD->hasNonTrivialDestructor()) - pushDestroy(QualType::DK_cxx_destructor, DeclPtr, Ty); + if (QualType::DestructionKind DtorKind = Ty.isDestructedType()) { + assert((DtorKind == QualType::DK_cxx_destructor || + DtorKind == QualType::DK_nontrivial_c_struct) && + "unexpected destructor type"); + pushDestroy(DtorKind, DeclPtr, Ty); + } } } else { // Otherwise, create a temporary to hold the value. |