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