xref: /llvm-project/clang/test/CXX/except/except.spec/p13.cpp (revision 77c5cea78eac3f20d0ba79f5892235e5aac82603)
19cfb138eSKrystian Stasiowski // RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s
29cfb138eSKrystian Stasiowski 
39cfb138eSKrystian Stasiowski struct A {
49cfb138eSKrystian Stasiowski   static constexpr bool x = true;
59cfb138eSKrystian Stasiowski };
69cfb138eSKrystian Stasiowski 
79cfb138eSKrystian Stasiowski namespace N0 {
89cfb138eSKrystian Stasiowski 
99cfb138eSKrystian Stasiowski template<typename T, typename U>
109cfb138eSKrystian Stasiowski void f(T, U) noexcept(T::y); // #1
119cfb138eSKrystian Stasiowski 
129cfb138eSKrystian Stasiowski template<typename T, typename U> // #2
139cfb138eSKrystian Stasiowski void f(T, U*) noexcept(T::x);
149cfb138eSKrystian Stasiowski 
159cfb138eSKrystian Stasiowski // Deduction should succeed for both candidates, and #2 should be selected as the primary template.
169cfb138eSKrystian Stasiowski // Only the exception specification of #2 should be instantiated.
179cfb138eSKrystian Stasiowski template<>
189cfb138eSKrystian Stasiowski void f(A, int*) noexcept;
199cfb138eSKrystian Stasiowski 
209cfb138eSKrystian Stasiowski }
219cfb138eSKrystian Stasiowski 
229cfb138eSKrystian Stasiowski namespace N1 {
239cfb138eSKrystian Stasiowski 
249cfb138eSKrystian Stasiowski template<typename T, typename U>
259cfb138eSKrystian Stasiowski void f(T, U) noexcept(T::x); // #1
269cfb138eSKrystian Stasiowski 
279cfb138eSKrystian Stasiowski template<typename T, typename U>
289cfb138eSKrystian Stasiowski void f(T, U*) noexcept(T::y); // #2
299cfb138eSKrystian Stasiowski // expected-error@-1 {{no member named 'y' in 'A'}}
309cfb138eSKrystian Stasiowski 
319cfb138eSKrystian Stasiowski // Deduction should succeed for both candidates, and #2 should be selected as the primary template.
329cfb138eSKrystian Stasiowski // Only the exception specification of #2 should be instantiated.
339cfb138eSKrystian Stasiowski template<>
349cfb138eSKrystian Stasiowski void f(A, int*) noexcept; // expected-error {{exception specification in declaration does not match previous declaration}}
359cfb138eSKrystian Stasiowski                           // expected-note@-1 {{in instantiation of exception specification for 'f<A, int>' requested here}}
369cfb138eSKrystian Stasiowski                           // expected-note@-2 {{previous declaration is here}}
379cfb138eSKrystian Stasiowski }
389cfb138eSKrystian Stasiowski 
399cfb138eSKrystian Stasiowski namespace N2 {
409cfb138eSKrystian Stasiowski 
419cfb138eSKrystian Stasiowski template<typename T, typename U>
429cfb138eSKrystian Stasiowski void f(T, U) noexcept(T::x);
439cfb138eSKrystian Stasiowski 
449cfb138eSKrystian Stasiowski template<typename T, typename U>
459cfb138eSKrystian Stasiowski void f(T, U*) noexcept(T::x);
469cfb138eSKrystian Stasiowski 
479cfb138eSKrystian Stasiowski template<typename T, typename U>
489cfb138eSKrystian Stasiowski void f(T, U**) noexcept(T::y); // expected-error {{no member named 'y' in 'A'}}
499cfb138eSKrystian Stasiowski 
509cfb138eSKrystian Stasiowski template<typename T, typename U>
519cfb138eSKrystian Stasiowski void f(T, U***) noexcept(T::x);
529cfb138eSKrystian Stasiowski 
539cfb138eSKrystian Stasiowski template<>
549cfb138eSKrystian Stasiowski void f(A, int*) noexcept; // expected-note {{previous declaration is here}}
559cfb138eSKrystian Stasiowski 
569cfb138eSKrystian Stasiowski template<>
579cfb138eSKrystian Stasiowski void f(A, int*); // expected-error {{'f<A, int>' is missing exception specification 'noexcept'}}
589cfb138eSKrystian Stasiowski 
599cfb138eSKrystian Stasiowski template<>
609cfb138eSKrystian Stasiowski void f(A, int**) noexcept; // expected-error {{exception specification in declaration does not match previous declaration}}
619cfb138eSKrystian Stasiowski                            // expected-note@-1 {{in instantiation of exception specification for 'f<A, int>' requested here}}
629cfb138eSKrystian Stasiowski                            // expected-note@-2 {{previous declaration is here}}
639cfb138eSKrystian Stasiowski 
649cfb138eSKrystian Stasiowski // FIXME: Exception specification is currently set to EST_None if instantiation fails.
659cfb138eSKrystian Stasiowski template<>
669cfb138eSKrystian Stasiowski void f(A, int**);
679cfb138eSKrystian Stasiowski 
689cfb138eSKrystian Stasiowski template<>
699cfb138eSKrystian Stasiowski void f(A, int***) noexcept; // expected-note {{previous declaration is here}}
709cfb138eSKrystian Stasiowski 
719cfb138eSKrystian Stasiowski template<>
729cfb138eSKrystian Stasiowski void f(A, int***); // expected-error {{'f<A, int>' is missing exception specification 'noexcept'}}
739cfb138eSKrystian Stasiowski 
749cfb138eSKrystian Stasiowski }
75*77c5cea7SKrystian Stasiowski 
76*77c5cea7SKrystian Stasiowski namespace N3 {
77*77c5cea7SKrystian Stasiowski 
78*77c5cea7SKrystian Stasiowski template<typename T, typename U>
79*77c5cea7SKrystian Stasiowski void f(T, U) noexcept(T::y); // #1
80*77c5cea7SKrystian Stasiowski 
81*77c5cea7SKrystian Stasiowski template<typename T, typename U> // #2
82*77c5cea7SKrystian Stasiowski void f(T, U*) noexcept(T::x);
83*77c5cea7SKrystian Stasiowski 
84*77c5cea7SKrystian Stasiowski // Deduction should succeed for both candidates, and #2 should be selected by overload resolution.
85*77c5cea7SKrystian Stasiowski // Only the exception specification of #2 should be instantiated.
86*77c5cea7SKrystian Stasiowski void (*x)(A, int*) = f;
87*77c5cea7SKrystian Stasiowski }
88*77c5cea7SKrystian Stasiowski 
89*77c5cea7SKrystian Stasiowski namespace N4 {
90*77c5cea7SKrystian Stasiowski 
91*77c5cea7SKrystian Stasiowski template<typename T, typename U>
92*77c5cea7SKrystian Stasiowski void f(T, U) noexcept(T::x); // #1
93*77c5cea7SKrystian Stasiowski 
94*77c5cea7SKrystian Stasiowski template<typename T, typename U>
95*77c5cea7SKrystian Stasiowski void f(T, U*) noexcept(T::y); // #2
96*77c5cea7SKrystian Stasiowski // expected-error@-1 {{no member named 'y' in 'A'}}
97*77c5cea7SKrystian Stasiowski 
98*77c5cea7SKrystian Stasiowski // Deduction should succeed for both candidates, and #2 should be selected by overload resolution.
99*77c5cea7SKrystian Stasiowski // Only the exception specification of #2 should be instantiated.
100*77c5cea7SKrystian Stasiowski void (*x)(A, int*) = f; // expected-note {{in instantiation of exception specification for 'f<A, int>' requested here}}
101*77c5cea7SKrystian Stasiowski }
102