|
| 1 | +// For CTemplate we check in case of: |
| 2 | +// - Implicitly instantiate whole class by up-casting: |
| 3 | +// * The vtable is generated with comdat |
| 4 | +// * Its '_vtable$' is generated |
| 5 | +// - Implicitly instantiate member function only: |
| 6 | +// * The vtable is NOT generated |
| 7 | +// * Its '_vtable$' is generated |
| 8 | +// - Define explicitly instantiation: |
| 9 | +// * The vtable is generated with comdat |
| 10 | +// * Its '_vtable$' is generated |
| 11 | +// - Declare explicitly instantiation as extern: |
| 12 | +// # for COFF targets: |
| 13 | +// * The vtable is declared but NOT associated with '_vtable$' |
| 14 | +// # for non-COFF targets: |
| 15 | +// * The vtable is declared |
| 16 | +// * Its '_vtable$' is generated |
| 17 | + |
| 18 | +struct CBase { |
| 19 | + virtual void f() noexcept {} |
| 20 | +}; |
| 21 | + |
| 22 | +template <typename T> |
| 23 | +struct CTemplate: CBase { |
| 24 | + void f() noexcept override; |
| 25 | + virtual ~CTemplate() noexcept; |
| 26 | +}; |
| 27 | +template <typename T> |
| 28 | +void CTemplate<T>::f() noexcept {} |
| 29 | +template <typename T> |
| 30 | +CTemplate<T>::~CTemplate() noexcept {} |
| 31 | + |
| 32 | +#ifdef EXPLICIT |
| 33 | +template struct CTemplate<void>; |
| 34 | +#endif |
| 35 | +#ifdef EXTERN |
| 36 | +extern template struct CTemplate<void>; |
| 37 | +#endif |
| 38 | + |
| 39 | +CTemplate<void> *get(CBase *) noexcept; |
| 40 | + |
| 41 | +int main() { |
| 42 | + CTemplate<void> Template; |
| 43 | +#ifdef NOCAST |
| 44 | + get(nullptr)->f(); |
| 45 | +#else |
| 46 | + get(&Template)->f(); |
| 47 | +#endif |
| 48 | + |
| 49 | + return 0; |
| 50 | +} |
| 51 | + |
| 52 | +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -debug-info-kind=limited -dwarf-version=5 -O1 %s -o - | FileCheck %s -check-prefix IMPLICIT |
| 53 | +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -debug-info-kind=limited -dwarf-version=5 -O1 %s -o - -DNOCAST | FileCheck %s -check-prefix NOCAST |
| 54 | +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -debug-info-kind=limited -dwarf-version=5 -O1 %s -o - -DEXPLICIT | FileCheck %s -check-prefix EXPLICIT |
| 55 | +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -debug-info-kind=limited -dwarf-version=5 -O1 %s -o - -DEXTERN | FileCheck %s -check-prefix EXTERN |
| 56 | + |
| 57 | +// IMPLICIT: $_ZTV9CTemplateIvE = comdat any |
| 58 | +// IMPLICIT: @_ZTV9CTemplateIvE = linkonce_odr {{.*}}unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[VTABLE_VAR:![0-9]*]] |
| 59 | +// IMPLICIT-DAG: [[VTABLE:![0-9]+]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV9CTemplateIvE" |
| 60 | +// IMPLICIT-DAG: !DIGlobalVariableExpression(var: [[VTABLE]], expr: !DIExpression()) |
| 61 | +// IMPLICIT-DAG: [[TYPE:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CTemplate<void>" |
| 62 | +// IMPLICIT-DAG: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[TYPE]], file: {{.*}}, baseType: [[PVOID:![0-9]+]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) |
| 63 | +// IMPLICIT-DAG: [[PVOID]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) |
| 64 | + |
| 65 | +// NOCAST-NOT: $_ZTV9CTemplateIvE |
| 66 | +// NOCAST-NOT: @_ZTV9CTemplateIvE |
| 67 | +// NOCAST-DAG: [[VTABLE:![0-9]+]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV9CTemplateIvE" |
| 68 | +// NOCAST-DAG: !DIGlobalVariableExpression(var: [[VTABLE]], expr: !DIExpression()) |
| 69 | +// NOCAST-DAG: [[TYPE:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CTemplate<void>" |
| 70 | +// NOCAST-DAG: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[TYPE]], file: {{.*}}, baseType: [[PVOID:![0-9]+]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) |
| 71 | +// NOCAST-DAG: [[PVOID]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) |
| 72 | + |
| 73 | +// EXPLICIT: $_ZTV9CTemplateIvE = comdat any |
| 74 | +// EXPLICIT: @_ZTV9CTemplateIvE = weak_odr {{.*}}unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[VTABLE_VAR:![0-9]*]] |
| 75 | +// EXPLICIT-DAG: [[VTABLE:![0-9]+]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV9CTemplateIvE" |
| 76 | +// EXPLICIT-DAG: [[VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[VTABLE]], expr: !DIExpression()) |
| 77 | +// EXPLICIT-DAG: [[TYPE:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CTemplate<void>" |
| 78 | +// EXPLICIT-DAG: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[TYPE]], file: {{.*}}, baseType: [[PVOID:![0-9]+]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) |
| 79 | +// EXPLICIT-DAG: [[PVOID]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) |
| 80 | + |
| 81 | +// EXTERN-NOT: $_ZTV9CTemplateIvE |
| 82 | +// EXTERN: @_ZTV9CTemplateIvE = external {{.*}}unnamed_addr constant {{.*}}, align 8, !dbg [[VTABLE_VAR:![0-9]*]] |
| 83 | +// EXTERN-DAG: [[VTABLE:![0-9]+]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV9CTemplateIvE" |
| 84 | +// EXTERN-DAG: [[VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[VTABLE]], expr: !DIExpression()) |
| 85 | +// EXTERN-DAG: [[TYPE:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "CTemplate<void>" |
| 86 | +// EXTERN-DAG: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[TYPE]], file: {{.*}}, baseType: [[PVOID:![0-9]+]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) |
| 87 | +// EXTERN-DAG: [[PVOID]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) |
0 commit comments