]> granicus.if.org Git - clang/commitdiff
Incomplete structs should also have internal linkage.
authorAnders Carlsson <andersca@mac.com>
Mon, 21 Dec 2009 00:41:42 +0000 (00:41 +0000)
committerAnders Carlsson <andersca@mac.com>
Mon, 21 Dec 2009 00:41:42 +0000 (00:41 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91805 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGRTTI.cpp
test/CodeGenCXX/rtti-linkage.cpp

index 416bb1694c52d5d6271b78d38598733a27ecd29e..ae5af6d7750db06d8c61b130625f0885c735daf3 100644 (file)
@@ -314,10 +314,6 @@ public:
     const clang::Type &Type
       = *CGM.getContext().getCanonicalType(Ty).getTypePtr();
 
-    if (const RecordType *RT = Ty.getTypePtr()->getAs<RecordType>())
-      if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()))
-        return BuildClassTypeInfo(RD);
-
     switch (Type.getTypeClass()) {
     default: {
       assert(0 && "typeid expression");
@@ -329,10 +325,20 @@ public:
       return GetAddrOfExternalRTTIDescriptor(Ty);
     }
 
+    case Type::Record: {
+      const RecordType *RT = cast<RecordType>(&Type);
+      
+      const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+      if (RD->getNumBases())
+        return BuildClassTypeInfo(RD);
+
+      // Fall through.
+    }
+
     case Type::Pointer:
     case Type::MemberPointer:
-        
       return BuildTypeInfo(Ty);
+
     case Type::FunctionProto:
     case Type::FunctionNoProto:
       return BuildSimpleType(Ty, "_ZTVN10__cxxabiv120__function_type_infoE");
@@ -496,8 +502,17 @@ bool ShouldUseExternalRTTIDescriptor(QualType Ty) {
     return TypeInfoIsInStandardLibrary(PointerTy);
 
   if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
-    (void)RecordTy;
-    assert(false && "FIXME");
+    const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+    if (!RD->isDynamicClass())
+      return false;
+
+    // Get the key function.
+    const CXXMethodDecl *KeyFunction = RD->getASTContext().getKeyFunction(RD);
+    if (KeyFunction && !KeyFunction->getBody()) {
+      // The class has a key function, but it is not defined in this translation
+      // unit, so we should use the external descriptor for it.
+      return true;
+    }
   }
   
   return false;
@@ -555,8 +570,40 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty) {
   //   making it a local static object.
   if (ContainsIncompleteClassType(Ty))
     return llvm::GlobalValue::InternalLinkage;
-   
-  // FIXME: Check linkage and anonymous namespace.
+  
+  if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty)) {
+    // If the pointee type has internal linkage, then the pointer type needs to
+    // have it as well.
+    if (getTypeInfoLinkage(PointerTy->getPointeeType()) == 
+        llvm::GlobalVariable::InternalLinkage)
+      return llvm::GlobalVariable::InternalLinkage;
+    
+    return llvm::GlobalVariable::WeakODRLinkage;
+  }
+    
+  if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+    const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+
+    // If we're in an anonymous namespace, then we always want internal linkage.
+    if (RD->isInAnonymousNamespace() || !RD->hasLinkage())
+      return llvm::GlobalVariable::InternalLinkage;
+    
+    if (!RD->isDynamicClass())
+      return llvm::GlobalValue::WeakODRLinkage;
+    
+    // Get the key function.
+    const CXXMethodDecl *KeyFunction = RD->getASTContext().getKeyFunction(RD);
+    if (!KeyFunction) {
+      // There is no key function, the RTTI descriptor is emitted with weak_odr
+      // linkage.
+      return llvm::GlobalValue::WeakODRLinkage;
+    }
+
+    // Otherwise, the RTTI descriptor is emitted with external linkage.
+    return llvm::GlobalValue::ExternalLinkage;
+  }
+
+  assert(false && "Unhandled type!");
   return llvm::GlobalValue::WeakODRLinkage;
 }
 
@@ -565,6 +612,17 @@ void RTTIBuilder::BuildVtablePointer(const Type *Ty) {
 
   switch (Ty->getTypeClass()) {
   default: assert(0 && "Unhandled type!");
+  
+  case Type::Record: {
+    const CXXRecordDecl *RD = 
+      cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+    if (!RD->getNumBases()) {
+      // abi::__class_type_info
+      VtableName = "_ZTVN10__cxxabiv117__class_type_infoE";
+      break;
+    }
+  }
+
   case Type::Pointer:
     // abi::__pointer_type_info
     VtableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
@@ -620,6 +678,15 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty) {
     assert(false && "Builtin type info must be in the standard library!");
     break;
 
+  case Type::Record: {
+    const CXXRecordDecl *RD = 
+      cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+    if (!RD->getNumBases()) {
+      // We don't need to emit any fields.
+      break;
+    }
+  }
+      
   case Type::Pointer:
     BuildPointerTypeInfo(cast<PointerType>(Ty));
     break;
index 5b4a8e42dd6faeadbf4de1ce7b4e5e4a2146159a..2875e19ae3110602c6b1f684f7c82d612fd7010e 100644 (file)
@@ -6,6 +6,8 @@
 // CHECK: _ZTI1A = weak_odr constant
 // CHECK: _ZTI1B = constant
 // CHECK: _ZTSP1C = internal constant
+// CHECK: _ZTS1C = internal constant
+// CHECK: _ZTI1C = internal constant
 // CHECK: _ZTIP1C = internal constant
 // CHECK: _ZTSPP1C = internal constant
 // CHECK: _ZTIPP1C = internal constant