1// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
3
4template <typename T>
5struct Foo {
6private:
7  T x;
8
9public:
10  Foo(T x) : x(x) {}
11  ~Foo() {}
12
13  T get() { return x; }
14  void set(T _x) { x = _x; }
15};
16
17template <typename T>
18struct Bar {
19private:
20  struct Foo<T> foo;
21
22public:
23  Bar(T x) : foo(x) {}
24  ~Bar() {}
25
26  T get() { return foo.get(); }
27  void set(T _x) { foo.set(_x); }
28};
29
30template <typename T>
31struct Baz : Foo<T> {
32public:
33  Baz(T x) : Foo<T>(x) {}
34  ~Baz() {}
35};
36
37// These two specializations should generate lines for all of Foo's methods.
38
39// CHECK-LABEL: @_ZN3FooIcEC1Ec(
40// CHECK-NEXT:  entry:
41// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
42// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i8, align 1
43// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
44// CHECK-NEXT:    store i8 [[X:%.*]], ptr [[X_ADDR]], align 1
45// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
46// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[X_ADDR]], align 1
47// CHECK-NEXT:    call void @_ZN3FooIcEC2Ec(ptr noundef nonnull align 1 dereferenceable(1) [[THIS1]], i8 noundef signext [[TMP0]])
48// CHECK-NEXT:    ret void
49//
50// CHECK-LABEL: @_ZN3FooIcED1Ev(
51// CHECK-NEXT:  entry:
52// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
53// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
54// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
55// CHECK-NEXT:    call void @_ZN3FooIcED2Ev(ptr noundef nonnull align 1 dereferenceable(1) [[THIS1]]) #[[ATTR1:[0-9]+]]
56// CHECK-NEXT:    ret void
57//
58// CHECK-LABEL: @_ZN3FooIcE3getEv(
59// CHECK-NEXT:  entry:
60// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
61// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
62// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
63// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO:%.*]], ptr [[THIS1]], i32 0, i32 0
64// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[X]], align 1
65// CHECK-NEXT:    ret i8 [[TMP0]]
66//
67// CHECK-LABEL: @_ZN3FooIcE3setEc(
68// CHECK-NEXT:  entry:
69// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
70// CHECK-NEXT:    [[_X_ADDR:%.*]] = alloca i8, align 1
71// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
72// CHECK-NEXT:    store i8 [[_X:%.*]], ptr [[_X_ADDR]], align 1
73// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
74// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[_X_ADDR]], align 1
75// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO:%.*]], ptr [[THIS1]], i32 0, i32 0
76// CHECK-NEXT:    store i8 [[TMP0]], ptr [[X]], align 1
77// CHECK-NEXT:    ret void
78//
79template struct Foo<char>;
80
81// CHECK-LABEL: @_ZN3FooIsEC1Es(
82// CHECK-NEXT:  entry:
83// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
84// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i16, align 2
85// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
86// CHECK-NEXT:    store i16 [[X:%.*]], ptr [[X_ADDR]], align 2
87// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
88// CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[X_ADDR]], align 2
89// CHECK-NEXT:    call void @_ZN3FooIsEC2Es(ptr noundef nonnull align 2 dereferenceable(2) [[THIS1]], i16 noundef signext [[TMP0]])
90// CHECK-NEXT:    ret void
91//
92// CHECK-LABEL: @_ZN3FooIsED1Ev(
93// CHECK-NEXT:  entry:
94// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
95// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
96// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
97// CHECK-NEXT:    call void @_ZN3FooIsED2Ev(ptr noundef nonnull align 2 dereferenceable(2) [[THIS1]]) #[[ATTR1]]
98// CHECK-NEXT:    ret void
99//
100// CHECK-LABEL: @_ZN3FooIsE3getEv(
101// CHECK-NEXT:  entry:
102// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
103// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
104// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
105// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO_0:%.*]], ptr [[THIS1]], i32 0, i32 0
106// CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[X]], align 2
107// CHECK-NEXT:    ret i16 [[TMP0]]
108//
109// CHECK-LABEL: @_ZN3FooIsE3setEs(
110// CHECK-NEXT:  entry:
111// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
112// CHECK-NEXT:    [[_X_ADDR:%.*]] = alloca i16, align 2
113// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
114// CHECK-NEXT:    store i16 [[_X:%.*]], ptr [[_X_ADDR]], align 2
115// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
116// CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[_X_ADDR]], align 2
117// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO_0:%.*]], ptr [[THIS1]], i32 0, i32 0
118// CHECK-NEXT:    store i16 [[TMP0]], ptr [[X]], align 2
119// CHECK-NEXT:    ret void
120//
121template struct Foo<short>;
122
123// This should not generate lines for the implicit specialization of Foo, but
124// should generate lines for the explicit specialization of Bar.
125
126// CHECK-LABEL: @_ZN3BarIiEC1Ei(
127// CHECK-NEXT:  entry:
128// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
129// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
130// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
131// CHECK-NEXT:    store i32 [[X:%.*]], ptr [[X_ADDR]], align 4
132// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
133// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
134// CHECK-NEXT:    call void @_ZN3BarIiEC2Ei(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], i32 noundef [[TMP0]])
135// CHECK-NEXT:    ret void
136//
137// CHECK-LABEL: @_ZN3BarIiED1Ev(
138// CHECK-NEXT:  entry:
139// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
140// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
141// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
142// CHECK-NEXT:    call void @_ZN3BarIiED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR1]]
143// CHECK-NEXT:    ret void
144//
145// CHECK-LABEL: @_ZN3BarIiE3getEv(
146// CHECK-NEXT:  entry:
147// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
148// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
149// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
150// CHECK-NEXT:    [[FOO:%.*]] = getelementptr inbounds nuw [[STRUCT_BAR:%.*]], ptr [[THIS1]], i32 0, i32 0
151// CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_ZN3FooIiE3getEv(ptr noundef nonnull align 4 dereferenceable(4) [[FOO]])
152// CHECK-NEXT:    ret i32 [[CALL]]
153//
154// CHECK-LABEL: @_ZN3BarIiE3setEi(
155// CHECK-NEXT:  entry:
156// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
157// CHECK-NEXT:    [[_X_ADDR:%.*]] = alloca i32, align 4
158// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
159// CHECK-NEXT:    store i32 [[_X:%.*]], ptr [[_X_ADDR]], align 4
160// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
161// CHECK-NEXT:    [[FOO:%.*]] = getelementptr inbounds nuw [[STRUCT_BAR:%.*]], ptr [[THIS1]], i32 0, i32 0
162// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[_X_ADDR]], align 4
163// CHECK-NEXT:    call void @_ZN3FooIiE3setEi(ptr noundef nonnull align 4 dereferenceable(4) [[FOO]], i32 noundef [[TMP0]])
164// CHECK-NEXT:    ret void
165//
166template struct Bar<int>;
167
168// This should not generate lines for the implicit specialization of Foo, but
169// should generate lines for the explicit specialization of Baz.
170
171// CHECK-LABEL: @_ZN3BazIlEC1El(
172// CHECK-NEXT:  entry:
173// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
174// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i64, align 8
175// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
176// CHECK-NEXT:    store i64 [[X:%.*]], ptr [[X_ADDR]], align 8
177// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
178// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr [[X_ADDR]], align 8
179// CHECK-NEXT:    call void @_ZN3BazIlEC2El(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]], i64 noundef [[TMP0]])
180// CHECK-NEXT:    ret void
181//
182// CHECK-LABEL: @_ZN3BazIlED1Ev(
183// CHECK-NEXT:  entry:
184// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
185// CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
186// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
187// CHECK-NEXT:    call void @_ZN3BazIlED2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]]) #[[ATTR1]]
188// CHECK-NEXT:    ret void
189//
190template struct Baz<long>;
191