xref: /llvm-project/clang/test/CXX/except/except.spec/p13.cpp (revision 77c5cea78eac3f20d0ba79f5892235e5aac82603)
1 // RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s
2 
3 struct A {
4   static constexpr bool x = true;
5 };
6 
7 namespace N0 {
8 
9 template<typename T, typename U>
10 void f(T, U) noexcept(T::y); // #1
11 
12 template<typename T, typename U> // #2
13 void f(T, U*) noexcept(T::x);
14 
15 // Deduction should succeed for both candidates, and #2 should be selected as the primary template.
16 // Only the exception specification of #2 should be instantiated.
17 template<>
18 void f(A, int*) noexcept;
19 
20 }
21 
22 namespace N1 {
23 
24 template<typename T, typename U>
25 void f(T, U) noexcept(T::x); // #1
26 
27 template<typename T, typename U>
28 void f(T, U*) noexcept(T::y); // #2
29 // expected-error@-1 {{no member named 'y' in 'A'}}
30 
31 // Deduction should succeed for both candidates, and #2 should be selected as the primary template.
32 // Only the exception specification of #2 should be instantiated.
33 template<>
34 void f(A, int*) noexcept; // expected-error {{exception specification in declaration does not match previous declaration}}
35                           // expected-note@-1 {{in instantiation of exception specification for 'f<A, int>' requested here}}
36                           // expected-note@-2 {{previous declaration is here}}
37 }
38 
39 namespace N2 {
40 
41 template<typename T, typename U>
42 void f(T, U) noexcept(T::x);
43 
44 template<typename T, typename U>
45 void f(T, U*) noexcept(T::x);
46 
47 template<typename T, typename U>
48 void f(T, U**) noexcept(T::y); // expected-error {{no member named 'y' in 'A'}}
49 
50 template<typename T, typename U>
51 void f(T, U***) noexcept(T::x);
52 
53 template<>
54 void f(A, int*) noexcept; // expected-note {{previous declaration is here}}
55 
56 template<>
57 void f(A, int*); // expected-error {{'f<A, int>' is missing exception specification 'noexcept'}}
58 
59 template<>
60 void f(A, int**) noexcept; // expected-error {{exception specification in declaration does not match previous declaration}}
61                            // expected-note@-1 {{in instantiation of exception specification for 'f<A, int>' requested here}}
62                            // expected-note@-2 {{previous declaration is here}}
63 
64 // FIXME: Exception specification is currently set to EST_None if instantiation fails.
65 template<>
66 void f(A, int**);
67 
68 template<>
69 void f(A, int***) noexcept; // expected-note {{previous declaration is here}}
70 
71 template<>
72 void f(A, int***); // expected-error {{'f<A, int>' is missing exception specification 'noexcept'}}
73 
74 }
75 
76 namespace N3 {
77 
78 template<typename T, typename U>
79 void f(T, U) noexcept(T::y); // #1
80 
81 template<typename T, typename U> // #2
82 void f(T, U*) noexcept(T::x);
83 
84 // Deduction should succeed for both candidates, and #2 should be selected by overload resolution.
85 // Only the exception specification of #2 should be instantiated.
86 void (*x)(A, int*) = f;
87 }
88 
89 namespace N4 {
90 
91 template<typename T, typename U>
92 void f(T, U) noexcept(T::x); // #1
93 
94 template<typename T, typename U>
95 void f(T, U*) noexcept(T::y); // #2
96 // expected-error@-1 {{no member named 'y' in 'A'}}
97 
98 // Deduction should succeed for both candidates, and #2 should be selected by overload resolution.
99 // Only the exception specification of #2 should be instantiated.
100 void (*x)(A, int*) = f; // expected-note {{in instantiation of exception specification for 'f<A, int>' requested here}}
101 }
102