[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