| // This is a test for an egregious hack in Clang that works around |
| // an issue with GCC's <utility> implementation. std::pair::swap |
| // has an exception specification that makes an unqualified call to |
| // swap. This is invalid, because it ends up calling itself with |
| // the wrong number of arguments. |
| // |
| // The same problem afflicts a bunch of other class templates. Those |
| // affected are array, pair, priority_queue, stack, and queue. |
| |
| // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array |
| // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DPR28423 |
| // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=pair |
| // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=priority_queue |
| // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=stack |
| // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=queue |
| // |
| // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__debug |
| // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__profile |
| |
| // MSVC's standard library uses a very similar pattern that relies on delayed |
| // parsing of exception specifications. |
| // |
| // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DMSVC |
| |
| #ifdef BE_THE_HEADER |
| |
| #pragma GCC system_header |
| #ifdef PR28423 |
| using namespace std; |
| #endif |
| |
| namespace std { |
| template<typename T> void swap(T &, T &); |
| template<typename T> void do_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) { |
| swap(a, b); |
| } |
| |
| #ifdef NAMESPACE |
| namespace NAMESPACE { |
| #define STD_CLASS std::NAMESPACE::CLASS |
| #else |
| #define STD_CLASS std::CLASS |
| #endif |
| |
| template<typename A, typename B> struct CLASS { |
| #ifdef MSVC |
| void swap(CLASS &other) noexcept(noexcept(do_swap(member, other.member))); |
| #endif |
| A member; |
| #ifndef MSVC |
| void swap(CLASS &other) noexcept(noexcept(swap(member, other.member))); |
| #endif |
| }; |
| |
| // template<typename T> void do_swap(T &, T &); |
| // template<typename A> struct vector { |
| // void swap(vector &other) noexcept(noexcept(do_swap(member, other.member))); |
| // A member; |
| // }; |
| |
| #ifdef NAMESPACE |
| } |
| #endif |
| } |
| |
| #else |
| |
| #define BE_THE_HEADER |
| #include __FILE__ |
| |
| struct X {}; |
| using PX = STD_CLASS<X, X>; |
| using PI = STD_CLASS<int, int>; |
| void swap(X &, X &) noexcept; |
| PX px; |
| PI pi; |
| |
| static_assert(noexcept(px.swap(px)), ""); |
| static_assert(!noexcept(pi.swap(pi)), ""); |
| |
| namespace sad { |
| template<typename T> void swap(T &, T &); |
| |
| template<typename A, typename B> struct CLASS { |
| void swap(CLASS &other) noexcept(noexcept(swap(*this, other))); // expected-error {{too many arguments}} expected-note {{declared here}} |
| // expected-error@-1{{uses itself}} expected-note@-1{{in instantiation of}} |
| }; |
| |
| CLASS<int, int> pi; |
| |
| static_assert(!noexcept(pi.swap(pi)), ""); // expected-note 2{{in instantiation of exception specification for 'swap'}} |
| } |
| |
| #endif |