mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 12:56:08 +00:00

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
131 lines
4.8 KiB
C++
131 lines
4.8 KiB
C++
// 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;
|
|
}
|