[cfe-commits] r92284 - in /cfe/trunk: lib/CodeGen/CGRTTI.cpp test/CodeGenCXX/rtti-layout.cpp test/CodeGenCXX/rtti-linkage.cpp

Anders Carlsson andersca at mac.com
Tue Dec 29 17:00:12 PST 2009


Author: andersca
Date: Tue Dec 29 19:00:12 2009
New Revision: 92284

URL: http://llvm.org/viewvc/llvm-project?rev=92284&view=rev
Log:
More RTTI cleanup, test that RTTI classes have the correct vtables.

Modified:
    cfe/trunk/lib/CodeGen/CGRTTI.cpp
    cfe/trunk/test/CodeGenCXX/rtti-layout.cpp
    cfe/trunk/test/CodeGenCXX/rtti-linkage.cpp

Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=92284&r1=92283&r2=92284&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Tue Dec 29 19:00:12 2009
@@ -37,8 +37,12 @@
   /// BuildVtablePointer - Build the vtable pointer for the given type.
   void BuildVtablePointer(const Type *Ty);
   
-  /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
-  /// used for pointer types.
+  /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
+  /// inheritance, according to the Itanium C++ ABI, 2.95p6b.
+  void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
+  
+  /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used
+  /// for pointer types.
   void BuildPointerTypeInfo(const PointerType *Ty);
   
   /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info 
@@ -262,33 +266,6 @@
     return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), n);
   }
 
-  // FIXME: unify with getTypeInfoLinkage
-  bool DecideExtern(QualType Ty) {
-    // For this type, see if all components are never in an anonymous namespace.
-    if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>())
-      return (DecideExtern(MPT->getPointeeType())
-              && DecideExtern(QualType(MPT->getClass(), 0)));
-    if (const PointerType *PT = Ty->getAs<PointerType>())
-      return DecideExtern(PT->getPointeeType());
-    if (const FunctionType *FT = Ty->getAs<FunctionType>()) {
-      if (DecideExtern(FT->getResultType()) == false)
-        return false;
-      if (const FunctionProtoType *FPT = Ty->getAs<FunctionProtoType>()) {
-        for (unsigned i = 0; i <FPT->getNumArgs(); ++i)
-          if (DecideExtern(FPT->getArgType(i)) == false)
-            return false;
-        for (unsigned i = 0; i <FPT->getNumExceptions(); ++i)
-          if (DecideExtern(FPT->getExceptionType(i)) == false)
-            return false;
-        return true;
-      }
-    }
-    if (const RecordType *RT = Ty->getAs<RecordType>())
-      if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
-        return !RD->isInAnonymousNamespace() && RD->hasLinkage();
-    return true;
-  }
-
   // FIXME: unify with DecideExtern
   bool DecideHidden(QualType Ty) {
     // For this type, see if all components are never hidden.
@@ -316,27 +293,6 @@
     return false;
   }
 
-  llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) {
-    llvm::SmallString<256> OutName;
-    CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
-    llvm::StringRef Name = OutName.str();
-
-    llvm::GlobalVariable *GV;
-    GV = CGM.getModule().getNamedGlobal(Name);
-    if (GV && !GV->isDeclaration())
-      return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
-
-    bool Extern = DecideExtern(Ty);
-    bool Hidden = DecideHidden(Ty);
-
-    Info.push_back(BuildVtableRef(vtbl));
-    Info.push_back(BuildName(Ty, Hidden, Extern));
-    
-    // We always generate these as hidden, only the name isn't hidden.
-    return finish(GV, Name, /*Hidden=*/Extern ? true : false, 
-                  GetLinkageFromExternFlag(Extern));
-  }
-
   /// BuildType - Builds the type info for the given type.
   llvm::Constant *BuildType(QualType Ty) {
     const clang::Type &Type
@@ -357,7 +313,7 @@
       const RecordType *RT = cast<RecordType>(&Type);
       
       const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-      if (RD->getNumBases())
+      if (RD->getNumBases() != 0 && !SimpleInheritance(RD))
         return BuildClassTypeInfo(RD);
 
       // Fall through.
@@ -685,6 +641,35 @@
   return llvm::GlobalValue::WeakODRLinkage;
 }
 
+// CanUseSingleInheritance - Return whether the given record decl has a "single, 
+// public, non-virtual base at offset zero (i.e. the derived class is dynamic 
+// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
+static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
+  // Check the number of bases.
+  if (RD->getNumBases() != 1)
+    return false;
+  
+  // Get the base.
+  CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
+  
+  // Check that the base is not virtual.
+  if (Base->isVirtual())
+    return false;
+  
+  // Check that the base is public.
+  if (Base->getAccessSpecifier() != AS_public)
+    return false;
+  
+  // Check that the class is dynamic iff the base is.
+  const CXXRecordDecl *BaseDecl = 
+    cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+  if (!BaseDecl->isEmpty() && 
+      BaseDecl->isDynamicClass() != RD->isDynamicClass())
+    return false;
+  
+  return true;
+}
+
 void RTTIBuilder::BuildVtablePointer(const Type *Ty) {
   const char *VtableName;
 
@@ -721,8 +706,14 @@
     if (!RD->getNumBases()) {
       // abi::__class_type_info
       VtableName = "_ZTVN10__cxxabiv117__class_type_infoE";
-      break;
+    } else if (CanUseSingleInheritance(RD)) {
+      // abi::__si_class_type_info;
+      VtableName = "_ZTVN10__cxxabiv120__si_class_type_infoE";
+    } else {
+      assert(false && "Should not get here!");
     }
+    
+    break;
   }
 
   case Type::Pointer:
@@ -812,6 +803,11 @@
       // We don't need to emit any fields.
       break;
     }
+    
+    if (CanUseSingleInheritance(RD)) {
+      BuildSIClassTypeInfo(RD);
+      break;
+    }
   }
       
   case Type::Pointer:
@@ -858,6 +854,15 @@
   return Flags;
 }
 
+/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
+/// inheritance, according to the Itanium C++ ABI, 2.95p6b.
+void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
+  // Itanium C++ ABI 2.9.5p6b:
+  // It adds to abi::__class_type_info a single member pointing to the 
+  // type_info structure for the base type,
+  Info.push_back(RTTIBuilder(CGM).BuildType(RD->bases_begin()->getType()));
+}
+
 /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
 /// used for pointer types.
 void RTTIBuilder::BuildPointerTypeInfo(const PointerType *Ty) {

Modified: cfe/trunk/test/CodeGenCXX/rtti-layout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/rtti-layout.cpp?rev=92284&r1=92283&r2=92284&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/rtti-layout.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/rtti-layout.cpp Tue Dec 29 19:00:12 2009
@@ -1,6 +1,20 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s
 #include <typeinfo>
 
+// vtables.
+extern "C" {
+  const void *_ZTVN10__cxxabiv123__fundamental_type_infoE;
+  const void *_ZTVN10__cxxabiv117__class_type_infoE;
+  const void *_ZTVN10__cxxabiv120__si_class_type_infoE;
+  const void *_ZTVN10__cxxabiv119__pointer_type_infoE;
+  const void *_ZTVN10__cxxabiv129__pointer_to_member_type_infoE;
+};
+#define fundamental_type_info_vtable _ZTVN10__cxxabiv123__fundamental_type_infoE
+#define class_type_info_vtable _ZTVN10__cxxabiv117__class_type_infoE
+#define si_class_type_info_vtable _ZTVN10__cxxabiv120__si_class_type_infoE
+#define pointer_type_info_vtable _ZTVN10__cxxabiv119__pointer_type_infoE
+#define pointer_to_member_type_info_vtable _ZTVN10__cxxabiv129__pointer_to_member_type_infoE
+
 class __pbase_type_info : public std::type_info {
 public:
   unsigned int __flags;
@@ -22,16 +36,23 @@
 
 struct A { };
 
-#define CHECK(x) if (!(x)) return __LINE__;
+#define CHECK(x) if (!(x)) return __LINE__
+#define CHECK_VTABLE(type, vtable) if (&vtable##_type_info_vtable + 2 != (((void **)&(typeid(type)))[0])) return __LINE__
 
 // CHECK: define i32 @_Z1fv()
 int f() {
+  // Vectors should be treated as fundamental types.
+  typedef short __v4hi __attribute__ ((__vector_size__ (8)));
+  CHECK_VTABLE(__v4hi, fundamental);
+  
   // Pointers to incomplete classes.
+  CHECK_VTABLE(Incomplete *, pointer);
   CHECK(to<__pbase_type_info>(typeid(Incomplete *)).__flags == __pbase_type_info::__incomplete_mask);
   CHECK(to<__pbase_type_info>(typeid(Incomplete **)).__flags == __pbase_type_info::__incomplete_mask);
   CHECK(to<__pbase_type_info>(typeid(Incomplete ***)).__flags == __pbase_type_info::__incomplete_mask);
 
   // Member pointers.
+  CHECK_VTABLE(int Incomplete::*, pointer_to_member);
   CHECK(to<__pbase_type_info>(typeid(int Incomplete::*)).__flags == __pbase_type_info::__incomplete_class_mask);
   CHECK(to<__pbase_type_info>(typeid(Incomplete Incomplete::*)).__flags == (__pbase_type_info::__incomplete_class_mask | __pbase_type_info::__incomplete_mask));
   CHECK(to<__pbase_type_info>(typeid(Incomplete A::*)).__flags == (__pbase_type_info::__incomplete_mask));

Modified: cfe/trunk/test/CodeGenCXX/rtti-linkage.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/rtti-linkage.cpp?rev=92284&r1=92283&r2=92284&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/rtti-linkage.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/rtti-linkage.cpp Tue Dec 29 19:00:12 2009
@@ -52,7 +52,7 @@
 void B::f() { }
 
 // C is an incomplete class type, so any direct or indirect pointer types should have 
-// internal linkage, as should the type info for C itself (FIXME).
+// internal linkage, as should the type info for C itself.
 struct C;
 
 void t1() {





More information about the cfe-commits mailing list