Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 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. |
Richard Smith | 3ef3e89 | 2014-11-20 22:32:11 +0000 | [diff] [blame] | 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 |
Vassil Vassilev | 8643639 | 2016-08-20 14:50:22 +0000 | [diff] [blame] | 11 | // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DPR28423 |
Richard Smith | 3ef3e89 | 2014-11-20 22:32:11 +0000 | [diff] [blame] | 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 |
Richard Smith | 6289546 | 2016-10-19 23:47:37 +0000 | [diff] [blame] | 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 |
Richard Smith | 3ef3e89 | 2014-11-20 22:32:11 +0000 | [diff] [blame] | 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 |
Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 24 | |
| 25 | #ifdef BE_THE_HEADER |
| 26 | |
| 27 | #pragma GCC system_header |
Vassil Vassilev | 8643639 | 2016-08-20 14:50:22 +0000 | [diff] [blame] | 28 | #ifdef PR28423 |
| 29 | using namespace std; |
| 30 | #endif |
| 31 | |
Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 32 | namespace std { |
| 33 | template<typename T> void swap(T &, T &); |
Richard Smith | 3ef3e89 | 2014-11-20 22:32:11 +0000 | [diff] [blame] | 34 | template<typename T> void do_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) { |
| 35 | swap(a, b); |
| 36 | } |
Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 37 | |
Richard Smith | 6289546 | 2016-10-19 23:47:37 +0000 | [diff] [blame] | 38 | #ifdef NAMESPACE |
| 39 | namespace NAMESPACE { |
| 40 | #define STD_CLASS std::NAMESPACE::CLASS |
| 41 | #else |
| 42 | #define STD_CLASS std::CLASS |
| 43 | #endif |
| 44 | |
Richard Smith | 3ef3e89 | 2014-11-20 22:32:11 +0000 | [diff] [blame] | 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 |
Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 53 | }; |
Richard Smith | 3ef3e89 | 2014-11-20 22:32:11 +0000 | [diff] [blame] | 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 | // }; |
Richard Smith | 6289546 | 2016-10-19 23:47:37 +0000 | [diff] [blame] | 60 | |
| 61 | #ifdef NAMESPACE |
| 62 | } |
| 63 | #endif |
Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | #else |
| 67 | |
| 68 | #define BE_THE_HEADER |
| 69 | #include __FILE__ |
| 70 | |
| 71 | struct X {}; |
Richard Smith | 6289546 | 2016-10-19 23:47:37 +0000 | [diff] [blame] | 72 | using PX = STD_CLASS<X, X>; |
| 73 | using PI = STD_CLASS<int, int>; |
Richard Smith | 3ef3e89 | 2014-11-20 22:32:11 +0000 | [diff] [blame] | 74 | void swap(X &, X &) noexcept; |
Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 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 | |
Richard Smith | 3ef3e89 | 2014-11-20 22:32:11 +0000 | [diff] [blame] | 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}} |
Richard Smith | 84a0b6d | 2016-10-18 23:39:12 +0000 | [diff] [blame] | 86 | // expected-error@-1{{uses itself}} expected-note@-1{{in instantiation of}} |
Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 87 | }; |
| 88 | |
Richard Smith | 3ef3e89 | 2014-11-20 22:32:11 +0000 | [diff] [blame] | 89 | CLASS<int, int> pi; |
Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 90 | |
Richard Smith | 73c3c21 | 2017-02-23 02:09:03 +0000 | [diff] [blame] | 91 | static_assert(!noexcept(pi.swap(pi)), ""); // expected-note 2{{in instantiation of exception specification for 'swap'}} |
Richard Smith | 6403e93 | 2014-11-14 00:37:55 +0000 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | #endif |