2015-10-08 12:24:12 +08:00
|
|
|
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s
|
2012-03-14 07:40:48 +08:00
|
|
|
|
2016-09-13 09:13:19 +08:00
|
|
|
// CHECK: @x = global %"struct.outer<foo>::inner" zeroinitializer, align 4, !dbg [[X:![0-9]+]]
|
|
|
|
|
2013-08-10 01:20:05 +08:00
|
|
|
struct MyClass {
|
|
|
|
template <int i> int add(int j) {
|
|
|
|
return i + j;
|
|
|
|
}
|
2013-08-29 07:06:52 +08:00
|
|
|
virtual void func() {
|
|
|
|
}
|
2012-03-14 07:40:48 +08:00
|
|
|
};
|
|
|
|
|
2013-08-10 01:20:05 +08:00
|
|
|
int add2(int x) {
|
|
|
|
return MyClass().add<2>(x);
|
|
|
|
}
|
2012-03-14 07:40:48 +08:00
|
|
|
|
2013-08-10 01:20:05 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-04-24 05:08:27 +08:00
|
|
|
// The compile unit pulls in the global variables first.
|
2017-08-31 02:22:23 +08:00
|
|
|
// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:.*]], expr: !DIExpression())
|
2016-12-20 10:10:02 +08:00
|
|
|
// CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x",
|
|
|
|
// CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]]
|
2016-04-24 05:08:27 +08:00
|
|
|
|
|
|
|
// CHECK: ![[OUTER_FOO_INNER_ID:[0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier:
|
2015-04-30 00:40:08 +08:00
|
|
|
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
|
2015-03-04 01:25:55 +08:00
|
|
|
// CHECK-SAME: elements: [[FOO_MEM:![0-9]*]]
|
|
|
|
// CHECK-SAME: identifier: "_ZTS3foo"
|
2014-12-16 03:10:08 +08:00
|
|
|
// CHECK: [[FOO_MEM]] = !{[[FOO_FUNC:![0-9]*]]}
|
2015-04-30 00:40:08 +08:00
|
|
|
// CHECK: [[FOO_FUNC]] = !DISubprogram(name: "func", linkageName: "_ZN3foo4funcEN5outerIS_E5innerE",
|
2015-03-04 01:25:55 +08:00
|
|
|
// CHECK-SAME: type: [[FOO_FUNC_TYPE:![0-9]*]]
|
2015-04-30 00:40:08 +08:00
|
|
|
// CHECK: [[FOO_FUNC_TYPE]] = !DISubroutineType(types: [[FOO_FUNC_PARAMS:![0-9]*]])
|
2016-04-24 05:08:27 +08:00
|
|
|
// CHECK: [[FOO_FUNC_PARAMS]] = !{null, !{{[0-9]*}}, ![[OUTER_FOO_INNER_ID]]}
|
2014-12-16 03:10:08 +08:00
|
|
|
|
2016-04-17 15:45:08 +08:00
|
|
|
// CHECK: [[C:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass"
|
2015-03-04 01:25:55 +08:00
|
|
|
// CHECK-SAME: elements: [[C_MEM:![0-9]*]]
|
2016-04-24 05:08:27 +08:00
|
|
|
// CHECK-SAME: vtableHolder: [[C]]
|
2015-03-04 01:25:55 +08:00
|
|
|
// CHECK-SAME: identifier: "_ZTS7MyClass")
|
2014-12-16 03:10:08 +08:00
|
|
|
// CHECK: [[C_MEM]] = !{[[C_VPTR:![0-9]*]], [[C_FUNC:![0-9]*]]}
|
2015-04-30 00:40:08 +08:00
|
|
|
// CHECK: [[C_VPTR]] = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$MyClass"
|
2013-08-30 07:19:58 +08:00
|
|
|
|
2016-09-13 09:13:19 +08:00
|
|
|
// CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 9,
|
2013-08-19 01:36:19 +08:00
|
|
|
|
2016-04-24 05:08:27 +08:00
|
|
|
// 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"
|
2015-03-04 01:25:55 +08:00
|
|
|
// CHECK-SAME: elements: [[ELEM_MEM:![0-9]*]]
|
|
|
|
// CHECK-SAME: identifier: "_ZTS4elem"
|
2014-12-16 03:10:08 +08:00
|
|
|
// CHECK: [[ELEM_MEM]] = !{[[ELEM_X:![0-9]*]]}
|
2016-04-24 05:08:27 +08:00
|
|
|
// CHECK: [[ELEM_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: [[ELEM]]
|
|
|
|
// CHECK-SAME: baseType: [[VIRT_TEMP:![0-9]+]]
|
2013-10-10 03:47:05 +08:00
|
|
|
|
2016-04-24 05:08:27 +08:00
|
|
|
// CHECK: [[VIRT_TEMP_PARAM]] = !{[[VIRT_T:![0-9]*]]}
|
|
|
|
// CHECK: [[VIRT_T]] = !DITemplateTypeParameter(name: "T", type: [[ELEM]])
|
2014-10-06 13:06:54 +08:00
|
|
|
|
2013-08-19 01:36:19 +08:00
|
|
|
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;
|
|
|
|
|
PR17046, PR17092: Debug Info assert-on-valid due to member loss when context creation recreates the item the context is created for
By removing the possibility of strange partial definitions with no
members that older GCC's produced for the otherwise unreferenced outer
types of referenced inner types, we can simplify debug info generation
and correct this bug. Newer (4.8.1 and ToT) GCC's don't produce this
quirky debug info, and instead produce the full definition for the outer
type (except in the case where that type is dynamic and its vtable is
not emitted in this TU).
During the creation of the context for a type, we may revisit that type
(due to the need to visit template parameters, among other things) and
used to end up visiting it first there. Then when we would reach the
original code attempting to define that type, we would lose debug info
by overwriting its members.
By avoiding the possibility of latent "defined with no members" types,
we can be sure than whenever we already have a type in a cache (either a
definition or declaration), we can just return that. In the case of a
full definition, our work is done. In the case of a partial definition,
we must already be in the process of completing it. And in the case of a
declaration, the completed/vtable/etc callbacks can handle converting it
to a definition.
llvm-svn: 190122
2013-09-06 14:45:04 +08:00
|
|
|
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>'
|
|
|
|
}
|
2016-04-15 23:55:45 +08:00
|
|
|
|
|
|
|
// 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"
|
2016-04-24 05:08:27 +08:00
|
|
|
// CHECK-SAME: scope: [[C]]
|