From: John McCall Date: Fri, 30 Apr 2010 01:15:21 +0000 (+0000) Subject: Fix -fno-rtti -fexceptions by forcing the emission of (non-"builtin") RTTI X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9dffe6f51c676c1e423c382c62d1648746e36cd4;p=clang Fix -fno-rtti -fexceptions by forcing the emission of (non-"builtin") RTTI when used by the exceptions routines. Fixes PR 6974. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102684 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index a18aaf61c1..c1d05bf233 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -271,7 +271,7 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { // Now throw the exception. const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); - llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType); + llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType, true); // The address of the destructor. If the exception type has a // trivial destructor (or isn't a record), we just pass null. @@ -371,7 +371,7 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { QualType Ty = Proto->getExceptionType(i); QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType(); - llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType); + llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType, true); SelectorArgs.push_back(EHType); } if (Proto->getNumExceptions()) @@ -494,7 +494,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, // are ignored. QualType CaughtType = C->getCaughtType().getNonReferenceType(); llvm::Value *EHTypeInfo - = CGM.GetAddrOfRTTIDescriptor(CaughtType.getUnqualifiedType()); + = CGM.GetAddrOfRTTIDescriptor(CaughtType.getUnqualifiedType(), true); SelectorArgs.push_back(EHTypeInfo); } else { // null indicates catch all diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index 5e3801da1e..aec1c4554a 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -148,6 +148,9 @@ public: }; /// BuildTypeInfo - Build the RTTI type info struct for the given type. + /// + /// \param Force - true to force the creation of this RTTI value + /// \param ForEH - true if this is for exception handling llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false); }; } @@ -242,9 +245,10 @@ static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) { } /// ShouldUseExternalRTTIDescriptor - Returns whether the type information for -/// the given type exists somewhere else, and that we should not emit the typ +/// the given type exists somewhere else, and that we should not emit the type /// information in this translation unit. -bool ShouldUseExternalRTTIDescriptor(QualType Ty) { +static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context, + QualType Ty) { // Type info for builtin types is defined in the standard library. if (const BuiltinType *BuiltinTy = dyn_cast(Ty)) return TypeInfoIsInStandardLibrary(BuiltinTy); @@ -254,6 +258,9 @@ bool ShouldUseExternalRTTIDescriptor(QualType Ty) { if (const PointerType *PointerTy = dyn_cast(Ty)) return TypeInfoIsInStandardLibrary(PointerTy); + // If RTTI is disabled, don't consider key functions. + if (!Context.getLangOptions().RTTI) return false; + if (const RecordType *RecordTy = dyn_cast(Ty)) { const CXXRecordDecl *RD = cast(RecordTy->getDecl()); if (!RD->hasDefinition()) @@ -449,7 +456,8 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) { Fields.push_back(VTable); } -llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { +llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, + bool Force) { // We want to operate on the canonical type. Ty = CGM.getContext().getCanonicalType(Ty); @@ -463,7 +471,7 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy); // Check if there is already an external RTTI descriptor for this type. - if (!Force && ShouldUseExternalRTTIDescriptor(Ty)) + if (!Force && ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty)) return GetAddrOfExternalRTTIDescriptor(Ty); llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(Ty); @@ -782,12 +790,16 @@ void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0))); } -llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty) { - if (!getContext().getLangOptions().RTTI) { +llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, + bool ForEH) { + // Return a bogus pointer if RTTI is disabled, unless it's for EH. + // FIXME: should we even be calling this method if RTTI is disabled + // and it's not for EH? + if (!ForEH && !getContext().getLangOptions().RTTI) { const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); return llvm::Constant::getNullValue(Int8PtrTy); } - + return RTTIBuilder(*this).BuildTypeInfo(Ty); } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index aa30635bfa..93d8ddf3e4 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -232,7 +232,7 @@ public: /// GetAddrOfRTTIDescriptor - Get the address of the RTTI descriptor /// for the given type. - llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty); + llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false); /// GetAddrOfThunk - Get the address of the thunk for the given global decl. llvm::Constant *GetAddrOfThunk(GlobalDecl GD, const ThunkInfo &Thunk); diff --git a/test/CodeGenCXX/exceptions-no-rtti.cpp b/test/CodeGenCXX/exceptions-no-rtti.cpp new file mode 100644 index 0000000000..c26abb26af --- /dev/null +++ b/test/CodeGenCXX/exceptions-no-rtti.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fno-rtti -fexceptions %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// CHECK: @_ZTIN5test11AE = weak_odr constant +// CHECK: @_ZTIN5test11BE = weak_odr constant +// CHECK: @_ZTIN5test11CE = weak_odr constant +// CHECK: @_ZTIN5test11DE = weak_odr constant +// CHECK: @_ZTIPN5test11DE = weak_odr constant {{.*}} @_ZTIN5test11DE + +// PR6974: this shouldn't crash +namespace test0 { + class err {}; + + void f(void) { + try { + } catch (err &) { + } + } +} + +namespace test1 { + // These classes have key functions defined out-of-line. + // Under normal circumstances, we wouldn't generate RTTI for them; + // under -fno-rtti, we generate RTTI only when required by EH. + class A { virtual void foo(); }; + class B { virtual void foo(); }; + class C { virtual void foo(); }; + class D { virtual void foo(); }; + + void opaque(); + + void test0() { + throw A(); + } + + void test1() throw(B) { + opaque(); + } + + void test2() { + try { + opaque(); + } catch (C&) {} + } + + void test3(D *ptr) { + throw ptr; + }; +}