1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s
// CHECK: @x ={{.*}} global %"struct.outer<foo>::inner" zeroinitializer, align 4, !dbg [[X:![0-9]+]]
struct MyClass {
template <int i> int add(int j) {
return i + j;
}
virtual void func() {
}
};
int add2(int x) {
return MyClass().add<2>(x);
}
inline int add3(int x) {
return MyClass().add<3>(x); // even though add<3> is ODR used, don't emit it since we don't codegen it
}
// The compile unit pulls in the global variables first.
// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:.*]], expr: !DIExpression())
// CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x",
// CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]]
//
// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable(
// CHECK-SAME: name: "var"
// CHECK-SAME: templateParams: {{![0-9]+}}
// CHECK: !DITemplateTypeParameter(name: "T", type: [[TY:![0-9]+]])
// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable(
// CHECK-SAME: name: "var"
// CHECK-SAME: templateParams: {{![0-9]+}}
// CHECK: !DITemplateTypeParameter(name: "T", type: {{![0-9]+}})
// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable(
// CHECK-SAME: name: "varray"
// CHECK-SAME: templateParams: {{![0-9]+}}
// CHECK: !DITemplateValueParameter(name: "N", type: [[TY]], value: i32 1)
// CHECK: ![[OUTER_FOO_INNER_ID:[0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier:
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
// CHECK-SAME: elements: [[FOO_MEM:![0-9]*]]
// CHECK-SAME: identifier: "_ZTS3foo"
// CHECK: [[FOO_MEM]] = !{[[FOO_FUNC:![0-9]*]]}
// CHECK: [[FOO_FUNC]] = !DISubprogram(name: "func", linkageName: "_ZN3foo4funcEN5outerIS_E5innerE",
// CHECK-SAME: type: [[FOO_FUNC_TYPE:![0-9]*]]
// CHECK: [[FOO_FUNC_TYPE]] = !DISubroutineType(types: [[FOO_FUNC_PARAMS:![0-9]*]])
// CHECK: [[FOO_FUNC_PARAMS]] = !{null, !{{[0-9]*}}, ![[OUTER_FOO_INNER_ID]]}
// CHECK: [[C:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass"
// CHECK-SAME: elements: [[C_MEM:![0-9]*]]
// CHECK-SAME: vtableHolder: [[C]]
// CHECK-SAME: identifier: "_ZTS7MyClass")
// CHECK: [[C_MEM]] = !{[[C_VPTR:![0-9]*]], [[C_FUNC:![0-9]*]]}
// CHECK: [[C_VPTR]] = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$MyClass"
// CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 9,
// CHECK: !DISubprogram(name: "add<2>"
// CHECK-SAME: scope: [[C]]
//
// CHECK: [[VIRT_TEMP:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "virt<elem>"
// CHECK-SAME: elements: [[VIRT_MEM:![0-9]*]]
// CHECK-SAME: vtableHolder: [[VIRT_TEMP]]
// CHECK-SAME: templateParams: [[VIRT_TEMP_PARAM:![0-9]*]]
// CHECK-SAME: identifier: "_ZTS4virtI4elemE"
// CHECK: [[ELEM:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "elem"
// CHECK-SAME: elements: [[ELEM_MEM:![0-9]*]]
// CHECK-SAME: identifier: "_ZTS4elem"
// CHECK: [[ELEM_MEM]] = !{[[ELEM_X:![0-9]*]]}
// CHECK: [[ELEM_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: [[ELEM]]
// CHECK-SAME: baseType: [[VIRT_TEMP:![0-9]+]]
// CHECK: [[VIRT_TEMP_PARAM]] = !{[[VIRT_T:![0-9]*]]}
// CHECK: [[VIRT_T]] = !DITemplateTypeParameter(name: "T", type: [[ELEM]])
template<typename T>
struct outer {
struct inner {
int i;
};
};
struct foo {
void func(outer<foo>::inner);
};
inline void func() {
// require 'foo' to be complete before the emission of 'inner' so that, when
// constructing the context chain for 'x' we emit the full definition of
// 'foo', which requires the definition of 'inner' again
foo f;
}
outer<foo>::inner x;
template <typename T>
struct virt {
T* values;
virtual ~virt();
};
struct elem {
static virt<elem> x; // ensure that completing 'elem' will require/completing 'virt<elem>'
};
inline void f1() {
elem e; // ensure 'elem' is required to be complete when it is emitted as a template argument for 'virt<elem>'
};
void f2() {
virt<elem> d; // emit 'virt<elem>'
}
// Check that the member function template specialization and implicit special
// members (the default ctor) refer to their class by scope, even though they
// didn't appear in the class's member list (C_MEM). This prevents the functions
// from being added to type units, while still appearing in the type
// declaration/reference in the compile unit.
// CHECK: !DISubprogram(name: "MyClass"
// CHECK-SAME: scope: [[C]]
template <typename T>
T var = T();
template <typename P>
P var<P *> = P();
template <typename T, int N>
T varray[N];
void f3() {
var<int> = 1;
var<int *> = 1;
varray<int, 1>[0] = 1;
}
|