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

Anders Carlsson andersca at mac.com
Sun Dec 20 14:30:55 PST 2009


Author: andersca
Date: Sun Dec 20 16:30:54 2009
New Revision: 91799

URL: http://llvm.org/viewvc/llvm-project?rev=91799&view=rev
Log:
Rework the way pointer types are handled by the RTTI builder. We now get the right linkage for indirect pointers to incomplete structs.

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=91799&r1=91798&r2=91799&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Sun Dec 20 16:30:54 2009
@@ -24,32 +24,27 @@
   const llvm::Type *Int8PtrTy;
   llvm::SmallSet<const CXXRecordDecl *, 16> SeenVBase;
   llvm::SmallSet<const CXXRecordDecl *, 32> SeenBase;
-
-  std::vector<llvm::Constant *> Info;
   
-  // Type info flags.
-  enum {
-    /// TI_Const - Type has const qualifier.
-    TI_Const = 0x1,
-    
-    /// TI_Volatile - Type has volatile qualifier.
-    TI_Volatile = 0x2,
-
-    /// TI_Restrict - Type has restrict qualifier.
-    TI_Restrict = 0x4,
-    
-    /// TI_Incomplete - Type is incomplete.
-    TI_Incomplete = 0x8,
+  std::vector<llvm::Constant *> Info;
 
-    /// TI_ContainingClassIncomplete - Containing class is incomplete.
-    /// (in pointer to member).
-    TI_ContainingClassIncomplete = 0x10
-  };
-  
   /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI 
   /// descriptor of the given type.
   llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
   
+  /// BuildTypeInfo - Build the RTTI type info struct for the given type.
+  llvm::Constant *BuildTypeInfo(QualType Ty);
+
+  /// 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.
+  void BuildPointerTypeInfo(const PointerType *Ty);
+  
+  /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info 
+  /// struct, used for member pointer types.
+  void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
+  
 public:
   RTTIBuilder(CodeGenModule &cgm)
     : CGM(cgm), VMContext(cgm.getModule().getContext()),
@@ -58,7 +53,7 @@
   /// BuildVtableRef - Build a reference to a vtable.
   llvm::Constant *BuildVtableRef(const char *Name) {
     // Build a descriptor for Name
-    llvm::Constant *GV = CGM.getModule().getGlobalVariable(Name);
+    llvm::Constant *GV = CGM.getModule().getNamedGlobal(Name);
     if (GV)
       GV = llvm::ConstantExpr::getBitCast(GV,
                                           llvm::PointerType::get(Int8PtrTy, 0));
@@ -96,7 +91,7 @@
     CGM.getMangleContext().mangleCXXRTTIName(Ty, OutName);
     llvm::StringRef Name = OutName.str();
 
-    llvm::GlobalVariable *OGV = CGM.getModule().getGlobalVariable(Name);
+    llvm::GlobalVariable *OGV = CGM.getModule().getNamedGlobal(Name);
     if (OGV && !OGV->isDeclaration())
       return llvm::ConstantExpr::getBitCast(OGV, Int8PtrTy);
 
@@ -131,7 +126,7 @@
   /// CalculateFlags - Calculate the flags for the __vmi_class_type_info
   /// datastructure.  1 for non-diamond repeated inheritance, 2 for a dimond
   /// shaped class.
-  int CalculateFlags(const CXXRecordDecl*RD) {
+  int CalculateFlags(const CXXRecordDecl *RD) {
     int flags = 0;
     if (SeenBase.count(RD))
       flags |= 1;
@@ -205,7 +200,7 @@
     llvm::StringRef Name = OutName.str();
 
     llvm::GlobalVariable *GV;
-    GV = CGM.getModule().getGlobalVariable(Name);
+    GV = CGM.getModule().getNamedGlobal(Name);
     if (GV && !GV->isDeclaration())
       return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
 
@@ -293,76 +288,13 @@
     return false;
   }
 
-  llvm::Constant *BuildPointerType(QualType Ty) {
-    assert(Info.empty() && "Info vector must be empty!");
-    
-    llvm::Constant *C;
-
-    llvm::SmallString<256> OutName;
-    CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
-    llvm::StringRef Name = OutName.str();
-
-    llvm::GlobalVariable *GV;
-    GV = CGM.getModule().getGlobalVariable(Name);
-    if (GV && !GV->isDeclaration())
-      return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
-
-    bool Extern = DecideExtern(Ty);
-    bool Hidden = DecideHidden(Ty);
-
-    const MemberPointerType *PtrMemTy = dyn_cast<MemberPointerType>(Ty);
-    QualType PointeeTy;
-    
-    if (PtrMemTy)
-      PointeeTy = PtrMemTy->getPointeeType();
-    else
-      PointeeTy = Ty->getPointeeType();
-
-    if (PtrMemTy)
-      C = BuildVtableRef("_ZTVN10__cxxabiv129__pointer_to_member_type_infoE");
-    else
-      C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE");
-    
-    Info.push_back(C);
-    Info.push_back(BuildName(Ty, Hidden, Extern));
-    Qualifiers Q = PointeeTy.getQualifiers();
-    
-    PointeeTy = 
-      CGM.getContext().getCanonicalType(PointeeTy).getUnqualifiedType();
-    
-    unsigned Flags = 0;
-    if (Q.hasConst())
-      Flags |= TI_Const;
-    if (Q.hasVolatile())
-      Flags |= TI_Volatile;
-    if (Q.hasRestrict())
-      Flags |= TI_Restrict;
-    
-    if (Ty->isIncompleteType())
-      Flags |= TI_Incomplete;
-  
-    if (PtrMemTy && PtrMemTy->getClass()->isIncompleteType())
-      Flags |= TI_ContainingClassIncomplete;
-    
-    Info.push_back(BuildInt(Flags));
-    Info.push_back(BuildInt(0));
-    Info.push_back(RTTIBuilder(CGM).BuildType(PointeeTy));
-
-    if (PtrMemTy)
-      Info.push_back(RTTIBuilder(CGM).BuildType(
-                                            QualType(PtrMemTy->getClass(), 0)));
-
-    // We always generate these as hidden, only the name isn't hidden.
-    return finish(GV, Name, /*Hidden=*/true, GetLinkageFromExternFlag(Extern));
-  }
-
   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().getGlobalVariable(Name);
+    GV = CGM.getModule().getNamedGlobal(Name);
     if (GV && !GV->isDeclaration())
       return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
 
@@ -397,18 +329,10 @@
       return GetAddrOfExternalRTTIDescriptor(Ty);
     }
 
-    case Type::Pointer: {
-      QualType PTy = Ty->getPointeeType();
-      Qualifiers Q = PTy.getQualifiers();
-      Q.removeConst();
-      // T* and const T* for all builtin types T are expected in the library.
-      if (isa<BuiltinType>(PTy) && Q.empty())
-        return GetAddrOfExternalRTTIDescriptor(Ty);
-
-      return BuildPointerType(Ty);
-    }
+    case Type::Pointer:
     case Type::MemberPointer:
-      return BuildPointerType(Ty);
+        
+      return BuildTypeInfo(Ty);
     case Type::FunctionProto:
     case Type::FunctionNoProto:
       return BuildSimpleType(Ty, "_ZTVN10__cxxabiv120__function_type_infoE");
@@ -447,6 +371,25 @@
     // linkage.
     return Buildclass_type_info(RD, llvm::GlobalValue::WeakODRLinkage);
   }
+  
+  // Pointer type info flags.
+  enum {
+    /// PTI_Const - Type has const qualifier.
+    PTI_Const = 0x1,
+    
+    /// PTI_Volatile - Type has volatile qualifier.
+    PTI_Volatile = 0x2,
+    
+    /// PTI_Restrict - Type has restrict qualifier.
+    PTI_Restrict = 0x4,
+    
+    /// PTI_Incomplete - Type is incomplete.
+    PTI_Incomplete = 0x8,
+    
+    /// PTI_ContainingClassIncomplete - Containing class is incomplete.
+    /// (in pointer to member).
+    PTI_ContainingClassIncomplete = 0x10
+  };
 };
 }
 
@@ -456,8 +399,8 @@
   CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
   llvm::StringRef Name = OutName.str();
 
-  // Look for an existing global variable.
-  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+  // Look for an existing global.
+  llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
   
   if (!GV) {
     // Create a new global variable.
@@ -468,6 +411,316 @@
   return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
 }
 
+/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
+/// info for that type is defined in the standard library.
+static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
+  // Itanium C++ ABI 2.9.2:
+  //   Basic type information (e.g. for "int", "bool", etc.) will be kept in
+  //   the run-time support library. Specifically, the run-time support
+  //   library should contain type_info objects for the types X, X* and 
+  //   X const*, for every X in: void, bool, wchar_t, char, unsigned char, 
+  //   signed char, short, unsigned short, int, unsigned int, long, 
+  //   unsigned long, long long, unsigned long long, float, double, long double, 
+  //   char16_t, char32_t, and the IEEE 754r decimal and half-precision 
+  //   floating point types.
+  switch (Ty->getKind()) {
+    case BuiltinType::Void:
+    case BuiltinType::Bool:
+    case BuiltinType::WChar:
+    case BuiltinType::Char_U:
+    case BuiltinType::Char_S:
+    case BuiltinType::UChar:
+    case BuiltinType::SChar:
+    case BuiltinType::Short:
+    case BuiltinType::UShort:
+    case BuiltinType::Int:
+    case BuiltinType::UInt:
+    case BuiltinType::Long:
+    case BuiltinType::ULong:
+    case BuiltinType::LongLong:
+    case BuiltinType::ULongLong:
+    case BuiltinType::Float:
+    case BuiltinType::Double:
+    case BuiltinType::LongDouble:
+    case BuiltinType::Char16:
+    case BuiltinType::Char32:
+    case BuiltinType::Int128:
+    case BuiltinType::UInt128:
+      return true;
+      
+    case BuiltinType::Overload:
+    case BuiltinType::Dependent:
+    case BuiltinType::UndeducedAuto:
+      assert(false && "Should not see this type here!");
+      
+    case BuiltinType::NullPtr:
+      assert(false && "FIXME: nullptr_t is not handled!");
+
+    case BuiltinType::ObjCId:
+    case BuiltinType::ObjCClass:
+    case BuiltinType::ObjCSel:
+      assert(false && "FIXME: Objective-C types are unsupported!");
+  }
+  
+  // Silent gcc.
+  return false;
+}
+
+static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
+  QualType PointeeTy = PointerTy->getPointeeType();
+  const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
+  if (!BuiltinTy)
+    return false;
+    
+  // Check the qualifiers.
+  Qualifiers Quals = PointeeTy.getQualifiers();
+  Quals.removeConst();
+    
+  if (!Quals.empty())
+    return false;
+    
+  return TypeInfoIsInStandardLibrary(BuiltinTy);
+}
+
+/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
+/// the given type exists somewhere else, and that we should not emit the typ
+/// information in this translation unit.
+bool ShouldUseExternalRTTIDescriptor(QualType Ty) {
+  // Type info for builtin types is defined in the standard library.
+  if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
+    return TypeInfoIsInStandardLibrary(BuiltinTy);
+  
+  // Type info for some pointer types to builtin types is defined in the
+  // standard library.
+  if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
+    return TypeInfoIsInStandardLibrary(PointerTy);
+
+  if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+    (void)RecordTy;
+    assert(false && "FIXME");
+  }
+  
+  return false;
+}
+
+/// IsIncompleteClassType - Returns whether the given record type is incomplete.
+static bool IsIncompleteClassType(const RecordType *RecordTy) {
+  return !RecordTy->getDecl()->isDefinition();
+}  
+
+/// IsPointerToIncompleteClassType - Returns whether the given pointer type
+/// is an indirect or direct pointer to an incomplete class type.
+static bool IsPointerToIncompleteClassType(const PointerType *PointerTy) {
+  QualType PointeeTy = PointerTy->getPointeeType();
+  while ((PointerTy = dyn_cast<PointerType>(PointeeTy)))
+    PointeeTy = PointerTy->getPointeeType();
+
+  if (const RecordType *RecordTy = dyn_cast<RecordType>(PointeeTy)) {
+    // Check if the record type is incomplete.
+    return IsIncompleteClassType(RecordTy);
+  }
+  
+  return false;
+}
+
+/// getTypeInfoLinkage - Return the linkage that the type info and type info
+/// name constants should have for the given type.
+static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty) {
+  if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty)) {
+    // Itanium C++ ABI 2.9.5p7:
+    //   In addition, it and all of the intermediate abi::__pointer_type_info 
+    //   structs in the chain down to the abi::__class_type_info for the
+    //   incomplete class type must be prevented from resolving to the 
+    //   corresponding type_info structs for the complete class type, possibly
+    //   by making them local static objects. Finally, a dummy class RTTI is
+    //   generated for the incomplete type that will not resolve to the final 
+    //   complete class RTTI (because the latter need not exist), possibly by 
+    //   making it a local static object.
+    if (IsPointerToIncompleteClassType(PointerTy))
+      return llvm::GlobalValue::InternalLinkage;
+   
+    // FIXME: Check linkage and anonymous namespace.
+    return llvm::GlobalValue::WeakODRLinkage;
+  } else if (const MemberPointerType *MemberPointerTy = 
+              dyn_cast<MemberPointerType>(Ty)) {
+    // If the class type is incomplete, then the type info constants should 
+    // have internal linkage.
+    const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
+    if (!ClassType->getDecl()->isDefinition())
+      return llvm::GlobalValue::InternalLinkage;
+    
+    // FIXME: Check linkage and anonymous namespace.
+    return llvm::GlobalValue::WeakODRLinkage;
+  }
+
+  assert(false && "FIXME!");
+  return llvm::GlobalValue::WeakODRLinkage;
+}
+
+void RTTIBuilder::BuildVtablePointer(const Type *Ty) {
+  const char *VtableName;
+
+  switch (Ty->getTypeClass()) {
+  default: assert(0 && "Unhandled type!");
+  case Type::Pointer:
+    // abi::__pointer_type_info
+    VtableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
+    break;
+  case Type::MemberPointer:
+    // abi::__pointer_to_member_type_info
+    VtableName =  "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
+    break;
+  }
+
+  llvm::Constant *Vtable = 
+    CGM.getModule().getOrInsertGlobal(VtableName, Int8PtrTy);
+    
+  const llvm::Type *PtrDiffTy = 
+    CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+
+  // The vtable address point is 2.
+  llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
+  Vtable = llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, &Two, 1);
+  Vtable = llvm::ConstantExpr::getBitCast(Vtable, Int8PtrTy);
+
+  Info.push_back(Vtable);
+}
+
+llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty) {
+  // We want to operate on the canonical type.
+  Ty = CGM.getContext().getCanonicalType(Ty);
+
+  // Check if we've already emitted an RTTI descriptor for this type.
+  llvm::SmallString<256> OutName;
+  CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
+  llvm::StringRef Name = OutName.str();
+  
+  llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
+  if (OldGV && !OldGV->isDeclaration())
+    return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy);
+  
+  // Check if there is already an external RTTI descriptor for this type.
+  if (ShouldUseExternalRTTIDescriptor(Ty))
+    return GetAddrOfExternalRTTIDescriptor(Ty);
+
+  llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(Ty);
+
+  // Add the vtable pointer.
+  BuildVtablePointer(cast<Type>(Ty));
+  
+  // And the name.
+  Info.push_back(BuildName(Ty, DecideHidden(Ty), Linkage));
+  
+  switch (Ty->getTypeClass()) {
+  default: assert(false && "Unhandled type class!");
+  case Type::Builtin:
+    assert(false && "Builtin type info must be in the standard library!");
+    break;
+
+  case Type::Pointer:
+    BuildPointerTypeInfo(cast<PointerType>(Ty));
+    break;
+  
+  case Type::MemberPointer:
+    BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
+    break;
+  }
+
+  llvm::Constant *Init = 
+    llvm::ConstantStruct::get(VMContext, &Info[0], Info.size(), 
+                              /*Packed=*/false);
+
+  llvm::GlobalVariable *GV = 
+    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), 
+                             /*Constant=*/true, Linkage, Init, Name);
+  
+  // If there's already an old global variable, replace it with the new one.
+  if (OldGV) {
+    GV->takeName(OldGV);
+    llvm::Constant *NewPtr = 
+      llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
+    OldGV->replaceAllUsesWith(NewPtr);
+    OldGV->eraseFromParent();
+  }
+    
+  return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
+}
+
+/// DetermineQualifierFlags - Deterine the pointer type info flags from the
+/// given qualifier.
+static unsigned DetermineQualifierFlags(Qualifiers Quals) {
+  unsigned Flags = 0;
+
+  if (Quals.hasConst())
+    Flags |= RTTIBuilder::PTI_Const;
+  if (Quals.hasVolatile())
+    Flags |= RTTIBuilder::PTI_Volatile;
+  if (Quals.hasRestrict())
+    Flags |= RTTIBuilder::PTI_Restrict;
+
+  return Flags;
+}
+
+/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
+/// used for pointer types.
+void RTTIBuilder::BuildPointerTypeInfo(const PointerType *Ty) {
+  const PointerType *PointerTy = cast<PointerType>(Ty);
+  QualType PointeeTy = PointerTy->getPointeeType();
+  
+  // Itanium C++ ABI 2.9.5p7:
+  //   __flags is a flag word describing the cv-qualification and other 
+  //   attributes of the type pointed to
+  unsigned Flags = DetermineQualifierFlags(PointeeTy.getQualifiers());
+
+  // Itanium C++ ABI 2.9.5p7:
+  //   When the abi::__pbase_type_info is for a direct or indirect pointer to an
+  //   incomplete class type, the incomplete target type flag is set. 
+  if (IsPointerToIncompleteClassType(PointerTy))
+    Flags |= PTI_Incomplete;
+
+  const llvm::Type *UnsignedIntLTy = 
+    CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+  Info.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+  
+  // Itanium C++ ABI 2.9.5p7:
+  //  __pointee is a pointer to the std::type_info derivation for the 
+  //  unqualified type being pointed to.
+  Info.push_back(RTTIBuilder(CGM).BuildType(PointeeTy.getUnqualifiedType()));
+}
+
+/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info 
+/// struct, used for member pointer types.
+void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
+  QualType PointeeTy = Ty->getPointeeType();
+  
+  // Itanium C++ ABI 2.9.5p7:
+  //   __flags is a flag word describing the cv-qualification and other 
+  //   attributes of the type pointed to.
+  unsigned Flags = DetermineQualifierFlags(PointeeTy.getQualifiers());
+
+  const RecordType *ClassType = cast<RecordType>(Ty->getClass());
+  
+  if (IsIncompleteClassType(ClassType))
+    Flags |= PTI_ContainingClassIncomplete;
+  
+  // FIXME: Handle PTI_Incomplete.
+  
+  const llvm::Type *UnsignedIntLTy = 
+    CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+  Info.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+  
+  // Itanium C++ ABI 2.9.5p7:
+  //   __pointee is a pointer to the std::type_info derivation for the 
+  //   unqualified type being pointed to.
+  Info.push_back(RTTIBuilder(CGM).BuildType(PointeeTy.getUnqualifiedType()));
+
+  // Itanium C++ ABI 2.9.5p9:
+  //   __context is a pointer to an abi::__class_type_info corresponding to the
+  //   class type containing the member pointed to 
+  //   (e.g., the "A" in "int A::*").
+  Info.push_back(RTTIBuilder(CGM).BuildType(QualType(ClassType, 0)));
+}
+
 llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty) {
   if (!getContext().getLangOptions().RTTI) {
     const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);

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

==============================================================================
--- cfe/trunk/test/CodeGenCXX/rtti-layout.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/rtti-layout.cpp Sun Dec 20 16:30:54 2009
@@ -20,12 +20,20 @@
 }
 struct Incomplete;
 
+#define CHECK(x) if ((x)) return __LINE__;
+
 // CHECK: define i32 @_Z1fv()
 int f() {
-  if (to<__pbase_type_info>(typeid(Incomplete *)).__flags != __pbase_type_info::__incomplete_mask)
-    return 1;
-    
+  // Pointers to incomplete classes.
+  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(to<__pbase_type_info>(typeid(int Incomplete::*)).__flags != __pbase_type_info::__incomplete_class_mask);
+
   // Success!
+  // CHECK: ret i32 0
   return 0;
 }
 
@@ -38,7 +46,7 @@
   if (result == 0)
     printf("success!\n");
   else
-    printf("test %d failed!\n", result);
+    printf("test on line %d failed!\n", result);
 
   return result;
 }

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

==============================================================================
--- cfe/trunk/test/CodeGenCXX/rtti-linkage.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/rtti-linkage.cpp Sun Dec 20 16:30:54 2009
@@ -1,10 +1,14 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+#include <typeinfo>
 
 // CHECK: _ZTS1B = constant
 // CHECK: _ZTS1A = weak_odr constant
 // CHECK: _ZTI1A = weak_odr constant
 // CHECK: _ZTI1B = constant
-
+// CHECK: _ZTSP1C = internal constant
+// CHECK: _ZTIP1C = internal constant
+// CHECK: _ZTSPP1C = internal constant
+// CHECK: _ZTIPP1C = internal constant
 // A has no key function, so its RTTI data should be weak_odr.
 struct A { };
 
@@ -14,3 +18,14 @@
   virtual void f();
 };
 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).
+struct C;
+
+void f() {
+  (void)typeid(C*);
+  (void)typeid(C**);
+  
+}
+





More information about the cfe-commits mailing list