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]+]]
|
2018-10-04 02:45:04 +08:00
|
|
|
//
|
|
|
|
// 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]+}}
|
Use primary template parameter names for variable template debug info
Summary:
Fixes PR41677
Consider:
template <typename LHS, typename RHS> constexpr bool is_same_v = false;
template <typename T> constexpr bool is_same_v<T, T> = true;
template constexpr bool is_same_v<int, int>;
Before this change, when emitting debug info for the
`is_same_v<int, int>` global variable, clang would crash because it
would try to use the template parameter list from the partial
specialization to give parameter names to template arguments. This
doesn't work in general, since a partial specialization can have fewer
arguments than the primary template. Therefore, always use the primary
template. Hypothetically we could try to use the parameter names from
the partial specialization when possible, but it's not clear this really
helps debugging in practice.
Reviewers: JDevlieghere, aprantl, ormris, dblaikie
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D61408
llvm-svn: 359809
2019-05-03 01:45:54 +08:00
|
|
|
// CHECK: !DITemplateTypeParameter(name: "T", type: {{![0-9]+}})
|
2018-10-04 02:45:04 +08:00
|
|
|
// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable(
|
|
|
|
// CHECK-SAME: name: "varray"
|
|
|
|
// CHECK-SAME: templateParams: {{![0-9]+}}
|
|
|
|
// CHECK: !DITemplateValueParameter(name: "N", type: [[TY]], value: i32 1)
|
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]]
|
2018-10-04 02:45:04 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|