xref: /llvm-project/clang/test/SemaTemplate/default-arguments-cxx0x.cpp (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
1 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
3 // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
4 // expected-no-diagnostics
5 
6 // Test default template arguments for function templates.
7 template<typename T = int>
8 void f0();
9 
10 template<typename T>
11 void f0();
12 
g0()13 void g0() {
14   f0(); // okay!
15 }
16 
17 template<typename T, int N = T::value>
18 int &f1(T);
19 
20 float &f1(...);
21 
22 struct HasValue {
23   static const int value = 17;
24 };
25 
g1()26 void g1() {
27   float &fr = f1(15);
28   int &ir = f1(HasValue());
29 }
30 
31 namespace PR16689 {
32   template <typename T1, typename T2> class tuple {
33   public:
34       template <typename = T2>
tuple()35       constexpr tuple() {}
36   };
37   template <class X, class... Y> struct a : public X {
38     using X::X;
39   };
40   auto x = a<tuple<int, int> >();
41 }
42 
43 namespace PR16975 {
44   template <typename...> struct is {
operator boolPR16975::is45     constexpr operator bool() const { return false; }
46   };
47 
48   template <typename... Types>
49   struct bar {
50     template <typename T,
51               bool = is<Types...>()>
52     bar(T);
53   };
54 
55   bar<> foo{0};
56 
57   struct baz : public bar<> {
58     using bar::bar;
59   };
60 
61   baz data{0};
62 }
63 
64 // An IRGen failure due to a symbol collision due to a default argument
65 // being instantiated twice.  Credit goes to Richard Smith for this
66 // reduction to a -fsyntax-only failure.
67 namespace rdar23810407 {
68   // Instantiating the default argument multiple times will produce two
69   // different lambda types and thus instantiate this function multiple
70   // times, which will produce conflicting extern variable declarations.
f(T t)71   template<typename T> int f(T t) {
72     extern T rdar23810407_variable;
73     return 0;
74   }
__anon3e8043970102null75   template<typename T> int g(int a = f([] {}));
test()76   void test() {
77     g<int>();
78     g<int>();
79   }
80 }
81 
82 namespace PR13986 {
83   constexpr unsigned Dynamic = 0;
84   template <unsigned> class A { template <unsigned = Dynamic> void m_fn1(); };
85   class Test {
~Test()86     ~Test() {}
87     A<1> m_target;
88   };
89 }
90 
91 // Template B is instantiated during checking if defaulted A copy constructor
92 // is constexpr. For this we check if S<int> copy constructor is constexpr. And
93 // for this we check S constructor template with default argument that mentions
94 // template B. In  turn, template instantiation triggers checking defaulted
95 // members exception spec. The problem is that it checks defaulted members not
96 // for instantiated class only, but all defaulted members so far. In this case
97 // we try to check exception spec for A default constructor which requires
98 // initializer for the field _a. But initializers are added after constexpr
99 // check so we reject the code because cannot find _a initializer.
100 namespace rdar34167492 {
101   template <typename T> struct B { using type = bool; };
102 
103   template <typename T> struct S {
104     S() noexcept;
105 
106     template <typename U, typename B<U>::type = true>
107     S(const S<U>&) noexcept;
108   };
109 
110   class A {
111     A() noexcept = default;
112     A(const A&) noexcept = default;
113     S<int> _a{};
114   };
115 }
116 
117 namespace use_of_earlier_param {
118   template<typename T> void f(T a, int = decltype(a)());
g()119   void g() { f(0); }
120 }
121 
122 #if __cplusplus >= 201402L
123 namespace lambda {
124   // Verify that a default argument in a lambda can refer to the type of a
125   // previous `auto` argument without crashing.
126   template <class T>
bar()127   void bar() {
128     (void) [](auto c, int x = sizeof(decltype(c))) {};
129   }
foo()130   void foo() {
131     bar<int>();
132   }
133 
134 #if __cplusplus >= 202002L
135   // PR46648: ensure we don't reject this by triggering default argument
136   // instantiation spuriously.
137   auto x = []<typename T>(T x = 123) {};
y()138   void y() { x(nullptr); }
139 
140   template<int A> struct X {
flambda::X141     template<int B> constexpr int f() {
142       auto l = []<int C>(int n = A + B + C) { return n; };
143       return l.template operator()<3>();
144     }
145   };
146   static_assert(X<100>().f<20>() == 123);
147 
f()148   template<> template<int B> constexpr int X<200>::f() {
149     auto l = []<int C>(int n = 300 + B + C) { return n; };
150     return l.template operator()<1>();
151   }
152   static_assert(X<200>().f<20>() == 321);
153 
f()154   template<> template<> constexpr int X<300>::f<20>() {
155     auto l = []<int C>(int n = 450 + C) { return n; };
156     return l.template operator()<6>();
157   }
158   static_assert(X<300>().f<20>() == 456);
159 #endif
160 } // namespace lambda
161 #endif
162