[cfe-commits] r116186 - in /cfe/trunk: lib/CodeGen/CGRTTI.cpp lib/CodeGen/CGVTables.cpp lib/CodeGen/CGVTables.h test/CodeGenCXX/vtable-linkage.cpp

Argyrios Kyrtzidis kyrtzidis at apple.com
Mon Oct 11 11:22:12 PDT 2010


$ cat t.cpp
template <typename T>
struct S {
	virtual void m();
};

void f() {
	S<int> *s = new S<int>;
}

$ clang -S -emit-llvm t.cpp -o -
[...]
@_ZTV1SIiE = external constant [3 x i8*]
[...]

$ llvm-gcc -S -emit-llvm t.cpp -o -
[...]
%struct.__class_type_info_pseudo = type { %struct.__type_info_pseudo }
%struct.__type_info_pseudo = type { i8*, i8* }

@_ZTV1SIiE = weak_odr constant [3 x i32 (...)*] [i32 (...)* null, i32 (...)* bitcast (%struct.__class_type_info_pseudo* @_ZTI1SIiE to i32 (...)*), i32 (...)* bitcast (void (%"struct.S<int>"*)* @_ZN1SIiE1mEv to i32 (...)*)], align 16 ; <[3 x i32 (...)*]*> [#uses=1]
@_ZTI1SIiE = weak_odr constant %struct.__class_type_info_pseudo { %struct.__type_info_pseudo { i8* inttoptr (i64 add (i64 ptrtoint ([0 x i32 (...)*]* @_ZTVN10__cxxabiv117__class_type_infoE to i64), i64 16) to i8*), i8* getelementptr inbounds ([6 x i8]* @_ZTS1SIiE, i64 0, i64 0) } }, align 16 ; <%struct.__class_type_info_pseudo*> [#uses=1]
@_ZTVN10__cxxabiv117__class_type_infoE = external constant [0 x i32 (...)*] ; <[0 x i32 (...)*]*> [#uses=1]
@_ZTS1SIiE = weak_odr constant [6 x i8] c"1SIiE\00" ; <[6 x i8]*> [#uses=2]
[..]


This resulted in an unresolved symbol linker error in Qt.

"C++ ABI 5.2.6 Instantiated Templates" says that template instantiations emit the virtual table in the object where instantiated, it doesn't mention the key function.

-Argyrios

On Oct 11, 2010, at 11:10 AM, Douglas Gregor wrote:

> 
> On Oct 10, 2010, at 8:25 PM, Argyrios Kyrtzidis wrote:
> 
>> Author: akirtzidis
>> Date: Sun Oct 10 22:25:57 2010
>> New Revision: 116186
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=116186&view=rev
>> Log:
>> Make sure the VTables for template instantiations are emitted even if the key function doesn't have a body.
> 
> This doesn't seem right. The vtables should come with the key function, according to the C++ ABI, whenever/wherever it is instantiated.  What prompted this change? I suggest reverting it until we understand the issue that you were seeing.
> 
> 	- Doug
> 
>> Modified:
>>   cfe/trunk/lib/CodeGen/CGRTTI.cpp
>>   cfe/trunk/lib/CodeGen/CGVTables.cpp
>>   cfe/trunk/lib/CodeGen/CGVTables.h
>>   cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp
>> 
>> Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=116186&r1=116185&r2=116186&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Sun Oct 10 22:25:57 2010
>> @@ -270,8 +270,9 @@
>> /// the given type exists somewhere else, and that we should not emit the type
>> /// information in this translation unit.  Assumes that it is not a
>> /// standard-library type.
>> -static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context,
>> -                                            QualType Ty) {
>> +static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) {
>> +  ASTContext &Context = CGM.getContext();
>> +
>>  // If RTTI is disabled, don't consider key functions.
>>  if (!Context.getLangOptions().RTTI) return false;
>> 
>> @@ -283,13 +284,7 @@
>>    if (!RD->isDynamicClass())
>>      return false;
>> 
>> -    // Get the key function.
>> -    const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
>> -    if (KeyFunction && !KeyFunction->hasBody()) {
>> -      // 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 !CGM.getVTables().ShouldEmitVTableInThisTU(RD);
>>  }
>> 
>>  return false;
>> @@ -528,8 +523,7 @@
>> 
>>  // Check if there is already an external RTTI descriptor for this type.
>>  bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
>> -  if (!Force &&
>> -      (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty)))
>> +  if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))
>>    return GetAddrOfExternalRTTIDescriptor(Ty);
>> 
>>  // Emit the standard library with external linkage.
>> 
>> Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=116186&r1=116185&r2=116186&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGVTables.cpp Sun Oct 10 22:25:57 2010
>> @@ -2336,6 +2336,27 @@
>>  NumVirtualFunctionPointers[RD] = CurrentIndex;
>> }
>> 
>> +bool CodeGenVTables::ShouldEmitVTableInThisTU(const CXXRecordDecl *RD) {
>> +  assert(RD->isDynamicClass() && "Non dynamic classes have no VTable.");
>> +
>> +  TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind();
>> +  if (TSK == TSK_ExplicitInstantiationDeclaration)
>> +    return false;
>> +
>> +  const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD);
>> +  if (!KeyFunction)
>> +    return true;
>> +
>> +  // Itanium C++ ABI, 5.2.6 Instantiated Templates:
>> +  //    An instantiation of a class template requires:
>> +  //        - In the object where instantiated, the virtual table...
>> +  if (TSK == TSK_ImplicitInstantiation ||
>> +      TSK == TSK_ExplicitInstantiationDefinition)
>> +    return true;
>> +
>> +  return KeyFunction->hasBody();
>> +}
>> +
>> uint64_t CodeGenVTables::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) {
>>  llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I = 
>>    NumVirtualFunctionPointers.find(RD);
>> @@ -2703,9 +2724,7 @@
>> 
>>  // We may need to generate a definition for this vtable.
>>  if (RequireVTable && !Entry.getInt()) {
>> -    if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) &&
>> -        RD->getTemplateSpecializationKind()
>> -          != TSK_ExplicitInstantiationDeclaration)
>> +    if (ShouldEmitVTableInThisTU(RD))
>>      CGM.DeferredVTables.push_back(RD);
>> 
>>    Entry.setInt(true);
>> 
>> Modified: cfe/trunk/lib/CodeGen/CGVTables.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.h?rev=116186&r1=116185&r2=116186&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGVTables.h (original)
>> +++ cfe/trunk/lib/CodeGen/CGVTables.h Sun Oct 10 22:25:57 2010
>> @@ -295,14 +295,9 @@
>>  CodeGenVTables(CodeGenModule &CGM)
>>    : CGM(CGM) { }
>> 
>> -  // isKeyFunctionInAnotherTU - True if this record has a key function and it is
>> -  // in another translation unit.
>> -  static bool isKeyFunctionInAnotherTU(ASTContext &Context,
>> -				       const CXXRecordDecl *RD) {
>> -    assert (RD->isDynamicClass() && "Non dynamic classes have no key.");
>> -    const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
>> -    return KeyFunction && !KeyFunction->hasBody();
>> -  }
>> +  /// \brief True if the VTable of this record must be emitted in the
>> +  /// translation unit.
>> +  bool ShouldEmitVTableInThisTU(const CXXRecordDecl *RD);
>> 
>>  /// needsVTTParameter - Return whether the given global decl needs a VTT
>>  /// parameter, which it does if it's a base constructor or destructor with
>> 
>> Modified: cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp?rev=116186&r1=116185&r2=116186&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp (original)
>> +++ cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp Sun Oct 10 22:25:57 2010
>> @@ -197,3 +197,18 @@
>> template <typename T>
>> void G<T>::f0() {}
>> void G_f0()  { new G<int>(); }
>> +
>> +// RUN: FileCheck --check-prefix=CHECK-H %s < %t
>> +
>> +// H<int> has a key function without a body but it's a template instantiation
>> +// so its VTable must be emmitted.
>> +// CHECK-H: @_ZTV1HIiE = weak_odr constant
>> +template <typename T>
>> +class H {
>> +public:
>> +  virtual ~H();
>> +};
>> +
>> +void use_H() {
>> +  H<int> h;
>> +}
>> 
>> 
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> 





More information about the cfe-commits mailing list