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

Douglas Gregor dgregor at apple.com
Mon Oct 11 13:42:24 PDT 2010


On Oct 11, 2010, at 11:22 AM, Argyrios Kyrtzidis wrote:

> $ 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.

This should only happen if the method S<int>::m is not instantiated anywhere else in Qt. Is that really the case?

> "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.

Hrm, strange. I guess one could interpret this paragraph as overriding the general rule for emitting vtables, but that's rather unfortunate: it'll mean that we end up emitting vtables and RTTI in many more translation units than we do.

	- Doug


> -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