1// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
2
3struct A {
4  int &f(int*);
5  float &f(int*) const noexcept;
6
7  int *ptr;
8  auto g1() noexcept(noexcept(f(ptr))) -> decltype(f(this->ptr));
9  auto g2() const noexcept(noexcept(f((*this).ptr))) -> decltype(f(ptr));
10};
11
12void testA(A &a) {
13  int &ir = a.g1();
14  float &fr = a.g2();
15  static_assert(!noexcept(a.g1()), "exception-specification failure");
16  static_assert(noexcept(a.g2()), "exception-specification failure");
17}
18
19struct B {
20  char g();
21  template<class T> auto f(T t) -> decltype(t + g())
22  { return t + g(); }
23};
24
25template auto B::f(int t) -> decltype(t + g());
26
27template<typename T>
28struct C {
29  int &f(T*);
30  float &f(T*) const noexcept;
31
32  T* ptr;
33  auto g1() noexcept(noexcept(f(ptr))) -> decltype(f(ptr));
34  auto g2() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(ptr));
35  auto g3() noexcept(noexcept(f(this->ptr))) -> decltype(f((*this).ptr));
36  auto g4() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(this->ptr));
37  auto g5() noexcept(noexcept(this->f(ptr))) -> decltype(this->f(ptr));
38  auto g6() const noexcept(noexcept(this->f(((this))->ptr))) -> decltype(this->f(ptr));
39  auto g7() noexcept(noexcept(this->f(this->ptr))) -> decltype(this->f((*this).ptr));
40  auto g8() const noexcept(noexcept(this->f(((this))->ptr))) -> decltype(this->f(this->ptr));
41};
42
43void test_C(C<int> ci) {
44  int &ir = ci.g1();
45  float &fr = ci.g2();
46  int &ir2 = ci.g3();
47  float &fr2 = ci.g4();
48  int &ir3 = ci.g5();
49  float &fr3 = ci.g6();
50  int &ir4 = ci.g7();
51  float &fr4 = ci.g8();
52  static_assert(!noexcept(ci.g1()), "exception-specification failure");
53  static_assert(noexcept(ci.g2()), "exception-specification failure");
54  static_assert(!noexcept(ci.g3()), "exception-specification failure");
55  static_assert(noexcept(ci.g4()), "exception-specification failure");
56  static_assert(!noexcept(ci.g5()), "exception-specification failure");
57  static_assert(noexcept(ci.g6()), "exception-specification failure");
58  static_assert(!noexcept(ci.g7()), "exception-specification failure");
59  static_assert(noexcept(ci.g8()), "exception-specification failure");
60}
61
62namespace PR14263 {
63  template<typename T> struct X {
64    void f();
65    T f() const;
66
67    auto g()       -> decltype(this->f()) { return f(); }
68    auto g() const -> decltype(this->f()) { return f(); }
69  };
70  template struct X<int>;
71}
72
73namespace PR10036 {
74  template <class I>
75  void
76  iter_swap(I x, I y) noexcept;
77
78  template <class T>
79  class A
80  {
81    T t_;
82  public:
83    void swap(A& a) noexcept(noexcept(iter_swap(&t_, &a.t_)));
84  };
85
86  void test() {
87    A<int> i, j;
88    i.swap(j);
89  }
90}
91
92namespace PR15290 {
93  template<typename T>
94  class A {
95    T v_;
96    friend int add_to_v(A &t) noexcept(noexcept(v_ + 42))
97    {
98      return t.v_ + 42;
99    }
100  };
101  void f()
102  {
103    A<int> t;
104    add_to_v(t);
105  }
106}
107
108namespace Static {
109  struct X1 {
110    int m;
111    // FIXME: This should be accepted.
112    static auto f() -> decltype(m); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
113    static auto g() -> decltype(this->m); // expected-error{{'this' cannot be used in a static member function declaration}}
114
115    static int h();
116
117    static int i() noexcept(noexcept(m + 2)); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
118  };
119
120  auto X1::h() -> decltype(m) { return 0; } // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
121
122  template<typename T>
123  struct X2 {
124    int m;
125
126    T f(T*);
127    static T f(int);
128
129    auto g(T x) -> decltype(f(x)) { return 0; }
130  };
131
132  void test_X2() {
133    X2<int>().g(0);
134  }
135}
136
137namespace PR12564 {
138  struct Base {
139    void bar(Base&) {} // FIXME: expected-note {{here}}
140  };
141
142  struct Derived : Base {
143    // FIXME: This should be accepted.
144    void foo(Derived& d) noexcept(noexcept(d.bar(d))) {} // expected-error {{cannot bind to a value of unrelated type}}
145  };
146}
147
148namespace rdar13473493 {
149  template <typename F>
150  class wrap
151  {
152  public:
153    template <typename... Args>
154    auto operator()(Args&&... args) const -> decltype(wrapped(args...)) // expected-note{{candidate template ignored: substitution failure [with Args = <int>]: use of undeclared identifier 'wrapped'}}
155    {
156      return wrapped(args...);
157    }
158
159  private:
160    F wrapped;
161  };
162
163  void test(wrap<int (*)(int)> w) {
164    w(5); // expected-error{{no matching function for call to object of type 'wrap<int (*)(int)>'}}
165  }
166}
167