• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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