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 // rdar://23810407
65 // An IRGen failure due to a symbol collision due to a default argument
66 // being instantiated twice.  Credit goes to Richard Smith for this
67 // reduction to a -fsyntax-only failure.
68 namespace rdar23810407 {
69   // Instantiating the default argument multiple times will produce two
70   // different lambda types and thus instantiate this function multiple
71   // times, which will produce conflicting extern variable declarations.
f(T t)72   template<typename T> int f(T t) {
73     extern T rdar23810407_variable;
74     return 0;
75   }
__anon20d920540102null76   template<typename T> int g(int a = f([] {}));
test()77   void test() {
78     g<int>();
79     g<int>();
80   }
81 }
82 
83 // rdar://problem/24480205
84 namespace PR13986 {
85   constexpr unsigned Dynamic = 0;
86   template <unsigned> class A { template <unsigned = Dynamic> void m_fn1(); };
87   class Test {
~Test()88     ~Test() {}
89     A<1> m_target;
90   };
91 }
92 
93 // rdar://problem/34167492
94 // Template B is instantiated during checking if defaulted A copy constructor
95 // is constexpr. For this we check if S<int> copy constructor is constexpr. And
96 // for this we check S constructor template with default argument that mentions
97 // template B. In  turn, template instantiation triggers checking defaulted
98 // members exception spec. The problem is that it checks defaulted members not
99 // for instantiated class only, but all defaulted members so far. In this case
100 // we try to check exception spec for A default constructor which requires
101 // initializer for the field _a. But initializers are added after constexpr
102 // check so we reject the code because cannot find _a initializer.
103 namespace rdar34167492 {
104   template <typename T> struct B { using type = bool; };
105 
106   template <typename T> struct S {
107     S() noexcept;
108 
109     template <typename U, typename B<U>::type = true>
110     S(const S<U>&) noexcept;
111   };
112 
113   class A {
114     A() noexcept = default;
115     A(const A&) noexcept = default;
116     S<int> _a{};
117   };
118 }
119 
120 namespace use_of_earlier_param {
121   template<typename T> void f(T a, int = decltype(a)());
g()122   void g() { f(0); }
123 }
124 
125 #if __cplusplus >= 201402L
126 namespace lambda {
127   // Verify that a default argument in a lambda can refer to the type of a
128   // previous `auto` argument without crashing.
129   template <class T>
bar()130   void bar() {
131     (void) [](auto c, int x = sizeof(decltype(c))) {};
132   }
foo()133   void foo() {
134     bar<int>();
135   }
136 
137 #if __cplusplus >= 202002L
138   // PR46648: ensure we don't reject this by triggering default argument
139   // instantiation spuriously.
140   auto x = []<typename T>(T x = 123) {};
y()141   void y() { x(nullptr); }
142 
143   template<int A> struct X {
flambda::X144     template<int B> constexpr int f() {
145       auto l = []<int C>(int n = A + B + C) { return n; };
146       return l.template operator()<3>();
147     }
148   };
149   static_assert(X<100>().f<20>() == 123);
150 
f()151   template<> template<int B> constexpr int X<200>::f() {
152     auto l = []<int C>(int n = 300 + B + C) { return n; };
153     return l.template operator()<1>();
154   }
155   static_assert(X<200>().f<20>() == 321);
156 
f()157   template<> template<> constexpr int X<300>::f<20>() {
158     auto l = []<int C>(int n = 450 + C) { return n; };
159     return l.template operator()<6>();
160   }
161   static_assert(X<300>().f<20>() == 456);
162 #endif
163 } // namespace lambda
164 #endif
165