]> granicus.if.org Git - clang/commitdiff
Fix -fno-rtti -fexceptions by forcing the emission of (non-"builtin") RTTI
authorJohn McCall <rjmccall@apple.com>
Fri, 30 Apr 2010 01:15:21 +0000 (01:15 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 30 Apr 2010 01:15:21 +0000 (01:15 +0000)
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

lib/CodeGen/CGException.cpp
lib/CodeGen/CGRTTI.cpp
lib/CodeGen/CodeGenModule.h
test/CodeGenCXX/exceptions-no-rtti.cpp [new file with mode: 0644]

index a18aaf61c15be19cf484bd069f3547a8f36663b5..c1d05bf233b2dee1d3e5fdfd2cbdeda4978e23e3 100644 (file)
@@ -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
index 5e3801da1eca4f491ad0e29df650a2486beb03bd..aec1c4554a35e8d746485457b4dbab9340dd576d 100644 (file)
@@ -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<BuiltinType>(Ty))
     return TypeInfoIsInStandardLibrary(BuiltinTy);
@@ -254,6 +258,9 @@ bool ShouldUseExternalRTTIDescriptor(QualType Ty) {
   if (const PointerType *PointerTy = dyn_cast<PointerType>(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<RecordType>(Ty)) {
     const CXXRecordDecl *RD = cast<CXXRecordDecl>(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);
 }
 
index aa30635bfa4c385b39d01757287a62526aa3f2fb..93d8ddf3e485029363c4c1a24090088cda342a63 100644 (file)
@@ -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 (file)
index 0000000..c26abb2
--- /dev/null
@@ -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;
+  };
+}