1 // This is a test for an egregious hack in Clang that works around
2 // an issue with GCC's <utility> implementation. std::pair::swap
3 // has an exception specification that makes an unqualified call to
4 // swap. This is invalid, because it ends up calling itself with
5 // the wrong number of arguments.
6 //
7 // The same problem afflicts a bunch of other class templates. Those
8 // affected are array, pair, priority_queue, stack, and queue.
9 
10 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array
11 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DPR28423
12 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=pair
13 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=priority_queue
14 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=stack
15 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=queue
16 //
17 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__debug
18 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__profile
19 
20 // MSVC's standard library uses a very similar pattern that relies on delayed
21 // parsing of exception specifications.
22 //
23 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DMSVC
24 
25 #ifdef BE_THE_HEADER
26 
27 #pragma GCC system_header
28 #ifdef PR28423
29 using namespace std;
30 #endif
31 
32 namespace std {
33   template<typename T> void swap(T &, T &);
do_swap(T & a,T & b)34   template<typename T> void do_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) {
35     swap(a, b);
36   }
37 
38 #ifdef NAMESPACE
39   namespace NAMESPACE {
40 #define STD_CLASS std::NAMESPACE::CLASS
41 #else
42 #define STD_CLASS std::CLASS
43 #endif
44 
45   template<typename A, typename B> struct CLASS {
46 #ifdef MSVC
47     void swap(CLASS &other) noexcept(noexcept(do_swap(member, other.member)));
48 #endif
49     A member;
50 #ifndef MSVC
51     void swap(CLASS &other) noexcept(noexcept(swap(member, other.member)));
52 #endif
53   };
54 
55 //  template<typename T> void do_swap(T &, T &);
56 //  template<typename A> struct vector {
57 //    void swap(vector &other) noexcept(noexcept(do_swap(member, other.member)));
58 //    A member;
59 //  };
60 
61 #ifdef NAMESPACE
62   }
63 #endif
64 }
65 
66 #else
67 
68 #define BE_THE_HEADER
69 #include __FILE__
70 
71 struct X {};
72 using PX = STD_CLASS<X, X>;
73 using PI = STD_CLASS<int, int>;
74 void swap(X &, X &) noexcept;
75 PX px;
76 PI pi;
77 
78 static_assert(noexcept(px.swap(px)), "");
79 static_assert(!noexcept(pi.swap(pi)), "");
80 
81 namespace sad {
82   template<typename T> void swap(T &, T &);
83 
84   template<typename A, typename B> struct CLASS {
85     void swap(CLASS &other) noexcept(noexcept(swap(*this, other))); // expected-error {{too many arguments}} expected-note {{declared here}}
86     // expected-error@-1{{uses itself}} expected-note@-1{{in instantiation of}}
87   };
88 
89   CLASS<int, int> pi;
90 
91   static_assert(!noexcept(pi.swap(pi)), ""); // expected-note 2{{in instantiation of exception specification for 'swap'}}
92 }
93 
94 #endif
95