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=pair 12 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=priority_queue 13 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=stack 14 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=queue 15 16 // MSVC's standard library uses a very similar pattern that relies on delayed 17 // parsing of exception specifications. 18 // 19 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DMSVC 20 21 #ifdef BE_THE_HEADER 22 23 #pragma GCC system_header 24 namespace std { 25 template<typename T> void swap(T &, T &); do_swap(T & a,T & b)26 template<typename T> void do_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) { 27 swap(a, b); 28 } 29 30 template<typename A, typename B> struct CLASS { 31 #ifdef MSVC 32 void swap(CLASS &other) noexcept(noexcept(do_swap(member, other.member))); 33 #endif 34 A member; 35 #ifndef MSVC 36 void swap(CLASS &other) noexcept(noexcept(swap(member, other.member))); 37 #endif 38 }; 39 40 // template<typename T> void do_swap(T &, T &); 41 // template<typename A> struct vector { 42 // void swap(vector &other) noexcept(noexcept(do_swap(member, other.member))); 43 // A member; 44 // }; 45 } 46 47 #else 48 49 #define BE_THE_HEADER 50 #include __FILE__ 51 52 struct X {}; 53 using PX = std::CLASS<X, X>; 54 using PI = std::CLASS<int, int>; 55 void swap(X &, X &) noexcept; 56 PX px; 57 PI pi; 58 59 static_assert(noexcept(px.swap(px)), ""); 60 static_assert(!noexcept(pi.swap(pi)), ""); 61 62 namespace sad { 63 template<typename T> void swap(T &, T &); 64 65 template<typename A, typename B> struct CLASS { 66 void swap(CLASS &other) noexcept(noexcept(swap(*this, other))); // expected-error {{too many arguments}} expected-note {{declared here}} 67 }; 68 69 CLASS<int, int> pi; 70 71 static_assert(!noexcept(pi.swap(pi)), ""); // expected-note {{in instantiation of}} 72 } 73 74 #endif 75