diff options
Diffstat (limited to 'clang/lib/CodeGen/ItaniumCXXABI.cpp')
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index bcc0f166203..877d32cc5f8 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -274,6 +274,8 @@ public: classifyRTTIUniqueness(QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const; friend class ItaniumRTTIBuilder; + + void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override; }; class ARMCXXABI : public ItaniumCXXABI { @@ -2996,3 +2998,80 @@ ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness( assert(Linkage == llvm::GlobalValue::WeakODRLinkage); return RUK_NonUniqueVisible; } + +static void emitCXXConstructor(CodeGenModule &CGM, + const CXXConstructorDecl *ctor, + StructorType ctorType) { + if (!CGM.getTarget().getCXXABI().hasConstructorVariants()) { + // If there are no constructor variants, always emit the complete + // destructor. + ctorType = StructorType::Complete; + } else if (!ctor->getParent()->getNumVBases() && + (ctorType == StructorType::Complete || + ctorType == StructorType::Base)) { + // The complete constructor is equivalent to the base constructor + // for classes with no virtual bases. Try to emit it as an alias. + bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias( + GlobalDecl(ctor, Ctor_Complete), GlobalDecl(ctor, Ctor_Base), true); + if (ctorType == StructorType::Complete && ProducedAlias) + return; + } + + const CGFunctionInfo &fnInfo = + CGM.getTypes().arrangeCXXStructorDeclaration(ctor, ctorType); + + auto *fn = cast<llvm::Function>( + CGM.getAddrOfCXXStructor(ctor, ctorType, &fnInfo, nullptr, true)); + GlobalDecl GD(ctor, toCXXCtorType(ctorType)); + CGM.setFunctionLinkage(GD, fn); + CodeGenFunction(CGM).GenerateCode(GD, fn, fnInfo); + + CGM.setFunctionDefinitionAttributes(ctor, fn); + CGM.SetLLVMFunctionAttributesForDefinition(ctor, fn); +} + +static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor, + StructorType dtorType) { + // The complete destructor is equivalent to the base destructor for + // classes with no virtual bases, so try to emit it as an alias. + if (!dtor->getParent()->getNumVBases() && + (dtorType == StructorType::Complete || dtorType == StructorType::Base)) { + bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias( + GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base), true); + if (ProducedAlias) { + if (dtorType == StructorType::Complete) + return; + if (dtor->isVirtual()) + CGM.getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete)); + } + } + + // The base destructor is equivalent to the base destructor of its + // base class if there is exactly one non-virtual base class with a + // non-trivial destructor, there are no fields with a non-trivial + // destructor, and the body of the destructor is trivial. + if (dtorType == StructorType::Base && !CGM.TryEmitBaseDestructorAsAlias(dtor)) + return; + + const CGFunctionInfo &fnInfo = + CGM.getTypes().arrangeCXXStructorDeclaration(dtor, dtorType); + + auto *fn = cast<llvm::Function>( + CGM.getAddrOfCXXStructor(dtor, dtorType, &fnInfo, nullptr, true)); + + GlobalDecl GD(dtor, toCXXDtorType(dtorType)); + CGM.setFunctionLinkage(GD, fn); + CodeGenFunction(CGM).GenerateCode(GD, fn, fnInfo); + + CGM.setFunctionDefinitionAttributes(dtor, fn); + CGM.SetLLVMFunctionAttributesForDefinition(dtor, fn); +} + +void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD, + StructorType Type) { + if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { + emitCXXConstructor(CGM, CD, Type); + return; + } + emitCXXDestructor(CGM, cast<CXXDestructorDecl>(MD), Type); +} |