Clang Project

clang_source_code/test/SemaCXX/libstdcxx_pair_swap_hack.cpp
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=array -DPR28423
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
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
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
24
25#ifdef BE_THE_HEADER
26
27#pragma GCC system_header
28#ifdef PR28423
29using namespace std;
30#endif
31
32namespace std {
33  template<typename T> void swap(T &, T &);
34  template<typename T> void do_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) {
35    swap(a, b);
36  }
37
38#ifdef NAMESPACE
39  namespace NAMESPACE {
40#define STD_CLASS std::NAMESPACE::CLASS
41#else
42#define STD_CLASS std::CLASS
43#endif
44
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
53  };
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//  };
60
61#ifdef NAMESPACE
62  }
63#endif
64}
65
66#else
67
68#define BE_THE_HEADER
69#include __FILE__
70
71struct X {};
72using PX = STD_CLASS<X, X>;
73using PI = STD_CLASS<int, int>;
74void swap(X &, X &) noexcept;
75PX px;
76PI pi;
77
78static_assert(noexcept(px.swap(px)), "");
79static_assert(!noexcept(pi.swap(pi)), "");
80
81namespace sad {
82  template<typename T> void swap(T &, T &);
83
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}}
86    // expected-error@-1{{uses itself}} expected-note@-1{{in instantiation of}}
87  };
88
89  CLASS<int, int> pi;
90
91  static_assert(!noexcept(pi.swap(pi)), ""); // expected-note 2{{in instantiation of exception specification for 'swap'}}
92}
93
94#endif
95