Home | History | Annotate | Download | only in SemaCXX
      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 &);
     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