reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
// 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