14544c2d9SRichard Smith // RUN: %clang_cc1 -verify %s -DTEST=1
24544c2d9SRichard Smith // RUN: %clang_cc1 -verify %s -DTEST=2
34544c2d9SRichard Smith // RUN: %clang_cc1 -verify %s -DTEST=3
426a92d58SRichard Smith // REQUIRES: thread_support
526a92d58SRichard Smith 
603c13e57SRichard Smith // FIXME: Detection of, or recovery from, stack exhaustion does not work on
703c13e57SRichard Smith // NetBSD at the moment. Since this is a best-effort mitigation for exceeding
803c13e57SRichard Smith // implementation limits, just disable the test.
903c13e57SRichard Smith // UNSUPPORTED: system-netbsd
1003c13e57SRichard Smith 
11*c06417b2SVitaly Buka // asan has own stack-overflow check.
12*c06417b2SVitaly Buka // UNSUPPORTED: asan
13*c06417b2SVitaly Buka 
1426a92d58SRichard Smith // expected-warning@* 0-1{{stack nearly exhausted}}
1526a92d58SRichard Smith // expected-note@* 0+{{}}
1626a92d58SRichard Smith 
174544c2d9SRichard Smith #if TEST == 1
184544c2d9SRichard Smith 
1926a92d58SRichard Smith template<int N> struct X : X<N-1> {};
2026a92d58SRichard Smith template<> struct X<0> {};
2126a92d58SRichard Smith X<1000> x;
2226a92d58SRichard Smith 
2326a92d58SRichard Smith template<typename ...T> struct tuple {};
f(tuple<T...> t)2426a92d58SRichard Smith template<typename ...T> auto f(tuple<T...> t) -> decltype(f(tuple<T...>(t))) {} // expected-error {{exceeded maximum depth}}
g()2526a92d58SRichard Smith void g() { f(tuple<int, int>()); }
2626a92d58SRichard Smith 
2726a92d58SRichard Smith int f(X<0>);
2826a92d58SRichard Smith template<int N> auto f(X<N>) -> f(X<N-1>());
2926a92d58SRichard Smith 
3026a92d58SRichard Smith int k = f(X<1000>());
314544c2d9SRichard Smith 
324544c2d9SRichard Smith #elif TEST == 2
334544c2d9SRichard Smith 
344544c2d9SRichard Smith namespace template_argument_recursion {
354544c2d9SRichard Smith   struct ostream;
364544c2d9SRichard Smith   template<typename T> T &&declval();
374544c2d9SRichard Smith 
384544c2d9SRichard Smith   namespace mlir {
394544c2d9SRichard Smith     template<typename T, typename = decltype(declval<ostream&>() << declval<T&>())>
404544c2d9SRichard Smith     ostream &operator<<(ostream& os, const T& obj); // expected-error {{exceeded maximum depth}}
414544c2d9SRichard Smith     struct Value;
424544c2d9SRichard Smith   }
434544c2d9SRichard Smith 
printFunctionalType(ostream & os,mlir::Value & v)444544c2d9SRichard Smith   void printFunctionalType(ostream &os, mlir::Value &v) { os << v; }
454544c2d9SRichard Smith }
464544c2d9SRichard Smith 
474544c2d9SRichard Smith #elif TEST == 3
484544c2d9SRichard Smith 
494544c2d9SRichard Smith namespace template_parameter_type_recursion {
504544c2d9SRichard Smith   struct ostream;
514544c2d9SRichard Smith   template<typename T> T &&declval();
524544c2d9SRichard Smith   template<bool B, typename T> struct enable_if { using type = T; };
534544c2d9SRichard Smith 
544544c2d9SRichard Smith   namespace mlir {
554544c2d9SRichard Smith     template<typename T, typename enable_if<declval<ostream&>() << declval<T&>(), void*>::type = nullptr>
564544c2d9SRichard Smith     ostream &operator<<(ostream& os, const T& obj); // expected-error {{exceeded maximum depth}}
574544c2d9SRichard Smith     struct Value;
584544c2d9SRichard Smith   }
594544c2d9SRichard Smith 
printFunctionalType(ostream & os,mlir::Value & v)604544c2d9SRichard Smith   void printFunctionalType(ostream &os, mlir::Value &v) { os << v; }
614544c2d9SRichard Smith }
624544c2d9SRichard Smith 
634544c2d9SRichard Smith #else
644544c2d9SRichard Smith #error unknown test
654544c2d9SRichard Smith #endif
66