xref: /llvm-project/clang/test/Modules/templates.mm (revision 158d72d728261c1e54dc77931372b2322c52849f)
1// RUN: rm -rf %t
2// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -x objective-c++ -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -verify %s -Wno-objc-root-class
3// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -x objective-c++ -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -emit-llvm %s -o - -Wno-objc-root-class | FileCheck %s
4// expected-no-diagnostics
5// REQUIRES: x86-registered-target
6@import templates_left;
7
8void testInlineRedeclEarly() {
9  // instantiate definition now, we'll add another declaration in _right.
10  OutOfLineInline<int>().h();
11}
12
13@import templates_right;
14
15// CHECK-DAG: @list_left ={{.*}} global %[[LIST:.*]] { ptr null, i32 8 }, align 8
16// CHECK-DAG: @list_right ={{.*}} global %[[LIST]] { ptr null, i32 12 }, align 8
17// CHECK-DAG: @__const._Z15testMixedStructv.l = {{.*}} constant %[[LIST]] { ptr null, i32 1 }, align 8
18// CHECK-DAG: @__const._Z15testMixedStructv.r = {{.*}} constant %[[LIST]] { ptr null, i32 2 }, align 8
19// CHECK-DAG: @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE = external global
20
21void testTemplateClasses() {
22  Vector<int> vec_int;
23  vec_int.push_back(0);
24
25  List<bool> list_bool;
26  list_bool.push_back(false);
27
28  N::Set<char> set_char;
29  set_char.insert('A');
30
31  static_assert(sizeof(List<long>) == sizeof(List<short>), "");
32
33  List<double> list_double;
34  list_double.push_back(0.0);
35}
36
37void testPendingInstantiations() {
38  // CHECK: call {{.*pendingInstantiationEmit}}
39  // CHECK: call {{.*pendingInstantiationEmit}}
40  // CHECK: define {{.*pendingInstantiationEmit.*[(]i}}
41  // CHECK: define {{.*pendingInstantiationEmit.*[(]double}}
42  triggerPendingInstantiation();
43  triggerPendingInstantiationToo();
44}
45
46void testRedeclDefinition() {
47  // CHECK: define {{.*redeclDefinitionEmit}}
48  redeclDefinitionEmit();
49}
50
51void testInlineRedecl() {
52  outOfLineInlineUseLeftF();
53  outOfLineInlineUseRightG();
54
55  outOfLineInlineUseRightF();
56  outOfLineInlineUseLeftG();
57}
58
59// CHECK-NOT: @_ZN21ExplicitInstantiationILb0ELb0EE1fEv(
60// CHECK: declare {{.*}}@_ZN21ExplicitInstantiationILb1ELb0EE1fEv(
61// CHECK: define {{.*}}@_ZN21ExplicitInstantiationILb1ELb1EE1fEv(
62// CHECK-NOT: @_ZN21ExplicitInstantiationILb0ELb0EE1fEv(
63
64// These three are all the same type.
65typedef OuterIntInner_left OuterIntInner;
66typedef OuterIntInner_right OuterIntInner;
67typedef Outer<int>::Inner OuterIntInner;
68
69// CHECK: call {{.*pendingInstantiation}}
70// CHECK: call {{.*redeclDefinitionEmit}}
71
72static_assert(size_left == size_right, "same field both ways");
73void useListInt(List<int> &);
74
75// CHECK-LABEL: define{{.*}} i32 @_Z15testMixedStructv(
76unsigned testMixedStruct() {
77  // CHECK: %[[l:.*]] = alloca %[[ListInt:[^ ]*]], align 8
78  // CHECK: %[[r:.*]] = alloca %[[ListInt]], align 8
79
80  // CHECK: call {{.*}}memcpy{{.*}}(ptr align {{[0-9]+}} %{{.*}}, ptr align {{[0-9]+}} @__const._Z15testMixedStructv.l, i64 16,
81  ListInt_left l{0, 1};
82
83  // CHECK: call {{.*}}memcpy{{.*}}(ptr align {{[0-9]+}} %{{.*}}, ptr align {{[0-9]+}} @__const._Z15testMixedStructv.r, i64 16,
84  ListInt_right r{0, 2};
85
86  // CHECK: call void @_Z10useListIntR4ListIiE(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %[[l]])
87  useListInt(l);
88  // CHECK: call void @_Z10useListIntR4ListIiE(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %[[r]])
89  useListInt(r);
90
91  // CHECK: load i32, ptr getelementptr inbounds (i8, ptr @list_left, i64 8)
92  // CHECK: load i32, ptr getelementptr inbounds (i8, ptr @list_right, i64 8)
93  return list_left.*size_right + list_right.*size_left;
94}
95
96template<typename T> struct MergePatternDecl {
97  typedef int Type;
98  void f(Type);
99};
100template<typename T> void MergePatternDecl<T>::f(Type type) {}
101// CHECK: define {{.*}}@_ZN21ExplicitInstantiationILb0ELb1EE1fEv(
102template struct ExplicitInstantiation<false, true>;
103template struct ExplicitInstantiation<true, true>;
104
105void testDelayUpdatesImpl() { testDelayUpdates<int>(); }
106
107void testStaticDataMember() {
108  WithUndefinedStaticDataMember<int[]> load_it;
109
110  // CHECK-LABEL: define linkonce_odr noundef ptr @_Z23getStaticDataMemberLeftv(
111  // CHECK: ret ptr @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE
112  (void) getStaticDataMemberLeft();
113
114  // CHECK-LABEL: define linkonce_odr noundef ptr @_Z24getStaticDataMemberRightv(
115  // CHECK: ret ptr @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE
116  (void) getStaticDataMemberRight();
117}
118
119void testWithAttributes() {
120  auto a = make_with_attributes_left();
121  auto b = make_with_attributes_right();
122  static_assert(alignof(decltype(a)) == 2, "");
123  static_assert(alignof(decltype(b)) == 2, "");
124}
125
126// Check that returnNonTrivial doesn't return Class0<S0> directly in registers.
127
128// CHECK: declare void @_Z16returnNonTrivialv(ptr dead_on_unwind writable sret(%struct.Class0) align 8)
129
130@import template_nontrivial0;
131@import template_nontrivial1;
132
133S1::S1() : a(returnNonTrivial()) {
134}
135