summaryrefslogtreecommitdiff
path: root/test/CXX/drs/dr5xx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CXX/drs/dr5xx.cpp')
-rw-r--r--test/CXX/drs/dr5xx.cpp785
1 files changed, 784 insertions, 1 deletions
diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp
index 0c0d451c4b22..5bf085f52204 100644
--- a/test/CXX/drs/dr5xx.cpp
+++ b/test/CXX/drs/dr5xx.cpp
@@ -1,6 +1,13 @@
// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++1y %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+
+// FIXME: This is included to avoid a diagnostic with no source location
+// pointing at the implicit operator new. We can't match such a diagnostic
+// with -verify.
+__extension__ typedef __SIZE_TYPE__ size_t;
+void *operator new(size_t); // expected-warning 0-1{{missing exception spec}} expected-note{{candidate}}
namespace dr500 { // dr500: dup 372
class D;
@@ -195,6 +202,153 @@ namespace dr525 { // dr525: yes
}
}
+namespace dr526 { // dr526: yes
+ template<int> struct S {};
+ template<int N> void f1(S<N> s);
+ template<int N> void f2(S<(N)> s); // expected-note {{couldn't infer}}
+ template<int N> void f3(S<+N> s); // expected-note {{couldn't infer}}
+ template<int N> void g1(int (&)[N]);
+ template<int N> void g2(int (&)[(N)]); // expected-note {{couldn't infer}}
+ template<int N> void g3(int (&)[+N]); // expected-note {{couldn't infer}}
+
+ void test(int (&a)[3], S<3> s) {
+ f1(s);
+ f2(s); // expected-error {{no matching}}
+ f3(s); // expected-error {{no matching}}
+ g1(a);
+ g2(a); // expected-error {{no matching}}
+ g3(a); // expected-error {{no matching}}
+ }
+
+ template<int N> struct X {
+ typedef int type;
+ X<N>::type v1;
+ X<(N)>::type v2; // expected-error {{missing 'typename'}}
+ X<+N>::type v3; // expected-error {{missing 'typename'}}
+ };
+}
+
+namespace dr527 { // dr527: na
+ // This DR is meaningless. It removes a required diagnostic from the case
+ // where a not-externally-visible object is odr-used but not defined, which
+ // requires a diagnostic for a different reason.
+ extern struct { int x; } a; // FIXME: We should reject this, per dr389.
+ static struct { int x; } b;
+ extern "C" struct { int x; } c;
+ namespace { extern struct { int x; } d; }
+ typedef struct { int x; } *P;
+ struct E { static P e; }; // FIXME: We should reject this, per dr389.
+ namespace { struct F { static P f; }; }
+
+ int ax = a.x, bx = b.x, cx = c.x, dx = d.x, ex = E::e->x, fx = F::f->x;
+}
+
+namespace dr530 { // dr530: yes
+ template<int*> struct S { enum { N = 1 }; };
+ template<void(*)()> struct T { enum { N = 1 }; };
+ int n;
+ void f();
+ int a[S<&n>::N];
+ int b[T<&f>::N];
+}
+
+namespace dr531 { // dr531: partial
+ namespace good {
+ template<typename T> struct A {
+ void f(T) { T::error; }
+ template<typename U> void g(T, U) { T::error; }
+ struct B { typename T::error error; };
+ template<typename U> struct C { typename T::error error; };
+ static T n;
+ };
+ template<typename T> T A<T>::n = T::error;
+
+ template<> void A<int>::f(int) {}
+ template<> template<typename U> void A<int>::g(int, U) {}
+ template<> struct A<int>::B {};
+ template<> template<typename U> struct A<int>::C {};
+ template<> int A<int>::n = 0;
+
+ void use(A<int> a) {
+ a.f(a.n);
+ a.g(0, 0);
+ A<int>::B b;
+ A<int>::C<int> c;
+ }
+
+ template<> struct A<char> {
+ void f(char);
+ template<typename U> void g(char, U);
+ struct B;
+ template<typename U> struct C;
+ static char n;
+ };
+
+ void A<char>::f(char) {}
+ template<typename U> void A<char>::g(char, U) {}
+ struct A<char>::B {};
+ template<typename U> struct A<char>::C {};
+ char A<char>::n = 0;
+ }
+
+ namespace bad {
+ template<typename T> struct A {
+ void f(T) { T::error; }
+ template<typename U> void g(T, U) { T::error; }
+ struct B { typename T::error error; };
+ template<typename U> struct C { typename T::error error; }; // expected-note {{here}}
+ static T n;
+ };
+ template<typename T> T A<T>::n = T::error;
+
+ void A<int>::f(int) {} // expected-error {{requires 'template<>'}}
+ template<typename U> void A<int>::g(int, U) {} // expected-error {{should be empty}}
+ struct A<int>::B {}; // expected-error {{requires 'template<>'}}
+ template<typename U> struct A<int>::C {}; // expected-error {{should be empty}} expected-error {{different kind of symbol}}
+ int A<int>::n = 0; // expected-error {{requires 'template<>'}}
+
+ template<> struct A<char> { // expected-note 2{{here}}
+ void f(char);
+ template<typename U> void g(char, U);
+ struct B; // expected-note {{here}}
+ template<typename U> struct C;
+ static char n;
+ };
+
+ template<> void A<char>::f(char) {} // expected-error {{no function template matches}}
+ // FIXME: This is ill-formed; -pedantic-errors should reject.
+ template<> template<typename U> void A<char>::g(char, U) {} // expected-warning {{extraneous template parameter list}}
+ template<> struct A<char>::B {}; // expected-error {{extraneous 'template<>'}} expected-error {{does not specialize}}
+ // FIXME: This is ill-formed; -pedantic-errors should reject.
+ template<> template<typename U> struct A<char>::C {}; // expected-warning {{extraneous template parameter list}}
+ template<> char A<char>::n = 0; // expected-error {{extraneous 'template<>'}}
+ }
+
+ namespace nested {
+ template<typename T> struct A {
+ template<typename U> struct B;
+ };
+ template<> template<typename U> struct A<int>::B {
+ void f();
+ void g();
+ template<typename V> void h();
+ template<typename V> void i();
+ };
+ template<> template<typename U> void A<int>::B<U>::f() {}
+ template<typename U> void A<int>::B<U>::g() {} // expected-error {{should be empty}}
+
+ template<> template<typename U> template<typename V> void A<int>::B<U>::h() {}
+ template<typename U> template<typename V> void A<int>::B<U>::i() {} // expected-error {{should be empty}}
+
+ template<> template<> void A<int>::B<int>::f() {}
+ template<> template<> template<typename V> void A<int>::B<int>::h() {}
+ template<> template<> template<> void A<int>::B<int>::h<int>() {}
+
+ template<> void A<int>::B<char>::f() {} // expected-error {{requires 'template<>'}}
+ template<> template<typename V> void A<int>::B<char>::h() {} // expected-error {{should be empty}}
+ }
+}
+
// PR8130
namespace dr532 { // dr532: 3.5
struct A { };
@@ -210,3 +364,632 @@ namespace dr532 { // dr532: 3.5
int &ir = b * a;
}
}
+
+// dr533: na
+
+namespace dr534 { // dr534: yes
+ struct S {};
+ template<typename T> void operator+(S, T);
+ template<typename T> void operator+<T*>(S, T*) {} // expected-error {{function template partial spec}}
+}
+
+namespace dr535 { // dr535: yes
+ class X { private: X(const X&); };
+ struct A {
+ X x;
+ template<typename T> A(T&);
+ };
+ struct B : A {
+ X y;
+ B(volatile A&);
+ };
+
+ extern A a1;
+ A a2(a1); // ok, uses constructor template
+
+ extern volatile B b1;
+ B b2(b1); // ok, uses converting constructor
+
+ void f() { throw a1; }
+
+#if __cplusplus >= 201103L
+ struct C {
+ constexpr C() : n(0) {}
+ template<typename T> constexpr C(T&t) : n(t.n == 0 ? throw 0 : 0) {}
+ int n;
+ };
+ constexpr C c() { return C(); }
+ // ok, copy is elided
+ constexpr C x = c();
+#endif
+}
+
+// dr537: na
+// dr538: na
+
+// dr539: yes
+const dr539( // expected-error {{requires a type specifier}}
+ const a) { // expected-error {{unknown type name 'a'}}
+ const b; // expected-error {{requires a type specifier}}
+ new const; // expected-error {{expected a type}}
+ try {} catch (const n) {} // expected-error {{unknown type name 'n'}}
+ try {} catch (const) {} // expected-error {{expected a type}}
+ if (const n = 0) {} // expected-error {{requires a type specifier}}
+ switch (const n = 0) {} // expected-error {{requires a type specifier}}
+ while (const n = 0) {} // expected-error {{requires a type specifier}}
+ for (const n = 0; // expected-error {{requires a type specifier}}
+ const m = 0; ) {} // expected-error {{requires a type specifier}}
+ sizeof(const); // expected-error {{requires a type specifier}}
+ struct S {
+ const n; // expected-error {{requires a type specifier}}
+ operator const(); // expected-error {{expected a type}}
+ };
+#if __cplusplus >= 201103L
+ int arr[3];
+ // FIXME: The extra braces here are to avoid the parser getting too
+ // badly confused when recovering here. We should fix this recovery.
+ { for (const n // expected-error {{unknown type name 'n'}} expected-note {{}}
+ : arr) ; {} } // expected-error +{{}}
+ (void) [](const) {}; // expected-error {{requires a type specifier}}
+ (void) [](const n) {}; // expected-error {{unknown type name 'n'}}
+ enum E : const {}; // expected-error {{expected a type}}
+ using T = const; // expected-error {{expected a type}}
+ auto f() -> const; // expected-error {{expected a type}}
+#endif
+}
+
+namespace dr540 { // dr540: yes
+ typedef int &a;
+ typedef const a &a; // expected-warning {{has no effect}}
+ typedef const int &b;
+ typedef b &b;
+ typedef const a &c; // expected-note {{previous}} expected-warning {{has no effect}}
+ typedef const b &c; // expected-error {{different}} expected-warning {{has no effect}}
+}
+
+namespace dr541 { // dr541: yes
+ template<int> struct X { typedef int type; };
+ template<typename T> struct S {
+ int f(T);
+
+ int g(int);
+ T g(bool);
+
+ int h();
+ int h(T);
+
+ void x() {
+ // These are type-dependent expressions, even though we could
+ // determine that all calls have type 'int'.
+ X<sizeof(f(0))>::type a; // expected-error +{{}}
+ X<sizeof(g(0))>::type b; // expected-error +{{}}
+ X<sizeof(h(0))>::type b; // expected-error +{{}}
+
+ typename X<sizeof(f(0))>::type a;
+ typename X<sizeof(h(0))>::type b;
+ }
+ };
+}
+
+namespace dr542 { // dr542: yes
+#if __cplusplus >= 201103L
+ struct A { A() = delete; int n; };
+ A a[32] = {}; // ok, constructor not called
+
+ struct B {
+ int n;
+ private:
+ B() = default;
+ };
+ B b[32] = {}; // ok, constructor not called
+#endif
+}
+
+namespace dr543 { // dr543: yes
+ // In C++98+DR543, this is valid because value-initialization doesn't call a
+ // trivial default constructor, so we never notice that defining the
+ // constructor would be ill-formed.
+ //
+ // In C++11+DR543, this is ill-formed, because the default constructor is
+ // deleted, and value-initialization *does* call a deleted default
+ // constructor, even if it is trivial.
+ struct A {
+ const int n;
+ };
+ A a = A();
+#if __cplusplus >= 201103L
+ // expected-error@-2 {{deleted}}
+ // expected-note@-5 {{would not be initialized}}
+#endif
+}
+
+namespace dr544 { // dr544: yes
+ int *n;
+
+ template<class T> struct A { int n; };
+ template<class T> struct B : A<T> { int get(); };
+ template<> int B<int>::get() { return n; }
+ int k = B<int>().get();
+}
+
+namespace dr546 { // dr546: yes
+ template<typename T> struct A { void f(); };
+ template struct A<int>;
+ template<typename T> void A<T>::f() { T::error; }
+}
+
+namespace dr547 { // dr547: yes
+ // When targeting the MS x86 ABI, the type of a member function includes a
+ // __thiscall qualifier. This is non-conforming, but we still implement
+ // the intent of dr547
+#if defined(_M_IX86) || (defined(__MINGW32__) && !defined(__MINGW64__))
+#define THISCALL __thiscall
+#else
+#define THISCALL
+#endif
+
+ template<typename T> struct X;
+ template<typename T> struct X<THISCALL T() const> {};
+ template<typename T, typename C> X<T> f(T C::*) { return X<T>(); }
+
+ struct S { void f() const; };
+ X<THISCALL void() const> x = f(&S::f);
+
+#undef THISCALL
+}
+
+namespace dr548 { // dr548: dup 482
+ template<typename T> struct S {};
+ template<typename T> void f() {}
+ template struct dr548::S<int>;
+ template void dr548::f<int>();
+}
+
+namespace dr551 { // dr551: yes c++11
+ // FIXME: This obviously should apply in C++98 mode too.
+ template<typename T> void f() {}
+ template inline void f<int>();
+#if __cplusplus >= 201103L
+ // expected-error@-2 {{cannot be 'inline'}}
+#endif
+
+ template<typename T> inline void g() {}
+ template inline void g<int>();
+#if __cplusplus >= 201103L
+ // expected-error@-2 {{cannot be 'inline'}}
+#endif
+
+ template<typename T> struct X {
+ void f() {}
+ };
+ template inline void X<int>::f();
+#if __cplusplus >= 201103L
+ // expected-error@-2 {{cannot be 'inline'}}
+#endif
+}
+
+namespace dr552 { // dr552: yes
+ template<typename T, typename T::U> struct X {};
+ struct Y { typedef int U; };
+ X<Y, 0> x;
+}
+
+struct dr553_class {
+ friend void *operator new(size_t, dr553_class);
+};
+namespace dr553 {
+ dr553_class c;
+ // Contrary to the apparent intention of the DR, operator new is not actually
+ // looked up with a lookup mechanism that performs ADL; the standard says it
+ // "is looked up in global scope", where it is not visible.
+ void *p = new (c) int; // expected-error {{no matching function}}
+
+ struct namespace_scope {
+ friend void *operator new(size_t, namespace_scope); // expected-error {{cannot be declared inside a namespace}}
+ };
+}
+
+// dr556: na
+
+namespace dr557 { // dr557: yes
+ template<typename T> struct S {
+ friend void f(S<T> *);
+ friend void g(S<S<T> > *);
+ };
+ void x(S<int> *p, S<S<int> > *q) {
+ f(p);
+ g(q);
+ }
+}
+
+namespace dr558 { // dr558: yes
+ wchar_t a = L'\uD7FF';
+ wchar_t b = L'\xD7FF';
+ wchar_t c = L'\uD800'; // expected-error {{invalid universal character}}
+ wchar_t d = L'\xD800';
+ wchar_t e = L'\uDFFF'; // expected-error {{invalid universal character}}
+ wchar_t f = L'\xDFFF';
+ wchar_t g = L'\uE000';
+ wchar_t h = L'\xE000';
+}
+
+template<typename> struct dr559 { typedef int T; dr559::T u; }; // dr559: yes
+
+namespace dr561 { // dr561: yes
+ template<typename T> void f(int);
+ template<typename T> void g(T t) {
+ f<T>(t);
+ }
+ namespace {
+ struct S {};
+ template<typename T> static void f(S);
+ }
+ void h(S s) {
+ g(s);
+ }
+}
+
+namespace dr564 { // dr564: yes
+ extern "C++" void f(int);
+ void f(int); // ok
+ extern "C++" { extern int n; }
+ int n; // ok
+}
+
+namespace dr565 { // dr565: yes
+ namespace N {
+ template<typename T> int f(T); // expected-note {{target}}
+ }
+ using N::f; // expected-note {{using}}
+ template<typename T> int f(T*);
+ template<typename T> void f(T);
+ template<typename T, int = 0> int f(T); // expected-error 0-1{{extension}}
+ template<typename T> int f(T, int = 0);
+ template<typename T> int f(T); // expected-error {{conflicts with}}
+}
+
+namespace dr566 { // dr566: yes
+#if __cplusplus >= 201103L
+ int check[int(-3.99) == -3 ? 1 : -1];
+#endif
+}
+
+// dr567: na
+
+namespace dr568 { // dr568: yes c++11
+ // FIXME: This is a DR issue against C++98, so should probably apply there
+ // too.
+ struct x { int y; };
+ class trivial : x {
+ x y;
+ public:
+ int n;
+ };
+ int check_trivial[__is_trivial(trivial) ? 1 : -1];
+
+ struct std_layout {
+ std_layout();
+ std_layout(const std_layout &);
+ ~std_layout();
+ private:
+ int n;
+ };
+ int check_std_layout[__is_standard_layout(std_layout) ? 1 : -1];
+
+ struct aggregate {
+ int x;
+ int y;
+ trivial t;
+ std_layout sl;
+ };
+ aggregate aggr = {};
+
+ void f(...);
+ void g(trivial t) { f(t); }
+#if __cplusplus < 201103L
+ // expected-error@-2 {{non-POD}}
+#endif
+
+ void jump() {
+ goto x;
+#if __cplusplus < 201103L
+ // expected-error@-2 {{cannot jump}}
+ // expected-note@+2 {{non-POD}}
+#endif
+ trivial t;
+ x: ;
+ }
+}
+
+namespace dr569 { // dr569: yes c++11
+ // FIXME: This is a DR issue against C++98, so should probably apply there
+ // too.
+ ;;;;;
+#if __cplusplus < 201103L
+ // expected-error@-2 {{C++11 extension}}
+#endif
+}
+
+namespace dr570 { // dr570: dup 633
+ int n;
+ int &r = n; // expected-note {{previous}}
+ int &r = n; // expected-error {{redefinition}}
+}
+
+namespace dr571 { // dr571 unknown
+ // FIXME: Add a codegen test.
+ typedef int &ir;
+ int n;
+ const ir r = n; // expected-warning {{has no effect}} FIXME: Test if this has internal linkage.
+}
+
+namespace dr572 { // dr572: yes
+ enum E { a = 1, b = 2 };
+ int check[a + b == 3 ? 1 : -1];
+}
+
+namespace dr573 { // dr573: no
+ void *a;
+ int *b = reinterpret_cast<int*>(a);
+ void (*c)() = reinterpret_cast<void(*)()>(a);
+ void *d = reinterpret_cast<void*>(c);
+#if __cplusplus < 201103L
+ // expected-error@-3 {{extension}}
+ // expected-error@-3 {{extension}}
+#endif
+ void f() { delete a; } // expected-error {{cannot delete}}
+ int n = d - a; // expected-error {{arithmetic on pointers to void}}
+ // FIXME: This is ill-formed.
+ template<void*> struct S;
+ template<int*> struct T;
+}
+
+namespace dr574 { // dr574: yes
+ struct A {
+ A &operator=(const A&) const; // expected-note {{does not match because it is const}}
+ };
+ struct B {
+ B &operator=(const B&) volatile; // expected-note {{nearly matches}}
+ };
+#if __cplusplus >= 201103L
+ struct C {
+ C &operator=(const C&) &; // expected-note {{not viable}} expected-note {{nearly matches}} expected-note {{here}}
+ };
+ struct D {
+ D &operator=(const D&) &&; // expected-note {{not viable}} expected-note {{nearly matches}} expected-note {{here}}
+ };
+ void test(C c, D d) {
+ c = c;
+ C() = c; // expected-error {{no viable}}
+ d = d; // expected-error {{no viable}}
+ D() = d;
+ }
+#endif
+ struct Test {
+ friend A &A::operator=(const A&); // expected-error {{does not match}}
+ friend B &B::operator=(const B&); // expected-error {{does not match}}
+#if __cplusplus >= 201103L
+ // FIXME: We shouldn't produce the 'cannot overload' diagnostics here.
+ friend C &C::operator=(const C&); // expected-error {{does not match}} expected-error {{cannot overload}}
+ friend D &D::operator=(const D&); // expected-error {{does not match}} expected-error {{cannot overload}}
+#endif
+ };
+}
+
+namespace dr575 { // dr575: yes
+ template<typename T, typename U = typename T::type> void a(T); void a(...); // expected-error 0-1{{extension}}
+ template<typename T, typename T::type U = 0> void b(T); void b(...); // expected-error 0-1{{extension}}
+ template<typename T, int U = T::value> void c(T); void c(...); // expected-error 0-1{{extension}}
+ template<typename T> void d(T, int = T::value); void d(...); // expected-error {{cannot be used prior to '::'}}
+ void x() {
+ a(0);
+ b(0);
+ c(0);
+ d(0); // expected-note {{in instantiation of default function argument}}
+ }
+
+ template<typename T = int&> void f(T* = 0); // expected-error 0-1{{extension}}
+ template<typename T = int> void f(T = 0); // expected-error 0-1{{extension}}
+ void g() { f<>(); }
+
+ template<typename T> T &h(T *);
+ template<typename T> T *h(T *);
+ void *p = h((void*)0);
+}
+
+namespace dr576 { // dr576: yes
+ typedef void f() {} // expected-error {{function definition declared 'typedef'}}
+ void f(typedef int n); // expected-error {{invalid storage class}}
+ void f(char c) { typedef int n; }
+}
+
+namespace dr577 { // dr577: yes
+ typedef void V;
+ typedef const void CV;
+ void a(void);
+ void b(const void); // expected-error {{qualifiers}}
+ void c(V);
+ void d(CV); // expected-error {{qualifiers}}
+ void (*e)(void) = c;
+ void (*f)(const void); // expected-error {{qualifiers}}
+ void (*g)(V) = a;
+ void (*h)(CV); // expected-error {{qualifiers}}
+ template<typename T> void i(T); // expected-note 2{{requires 1 arg}}
+ template<typename T> void j(void (*)(T)); // expected-note 2{{argument may not have 'void' type}}
+ void k() {
+ a();
+ c();
+ i<void>(); // expected-error {{no match}}
+ i<const void>(); // expected-error {{no match}}
+ j<void>(0); // expected-error {{no match}}
+ j<const void>(0); // expected-error {{no match}}
+ }
+}
+
+namespace dr580 { // dr580: no
+ class C;
+ struct A { static C c; };
+ struct B { static C c; };
+ class C {
+ C(); // expected-note {{here}}
+ ~C(); // expected-note {{here}}
+
+ typedef int I; // expected-note {{here}}
+ template<int> struct X;
+ template<int> friend struct Y;
+ template<int> void f();
+ template<int> friend void g();
+ friend struct A;
+ };
+
+ template<C::I> struct C::X {};
+ template<C::I> struct Y {};
+ template<C::I> struct Z {}; // FIXME: should reject, accepted because C befriends A!
+
+ template<C::I> void C::f() {}
+ template<C::I> void g() {}
+ template<C::I> void h() {} // expected-error {{private}}
+
+ C A::c;
+ C B::c; // expected-error 2{{private}}
+}
+
+// dr582: na
+
+namespace dr583 { // dr583: no
+ // see n3624
+ int *p;
+ // FIXME: These are all ill-formed.
+ bool b1 = p < 0;
+ bool b2 = p > 0;
+ bool b3 = p <= 0;
+ bool b4 = p >= 0;
+}
+
+// dr584: na
+
+namespace dr585 { // dr585: yes
+ template<typename> struct T;
+ struct A {
+ friend T; // expected-error {{requires a type specifier}} expected-error {{can only be classes or functions}}
+ // FIXME: It's not clear whether the standard allows this or what it means,
+ // but the DR585 writeup suggests it as an alternative.
+ template<typename U> friend T<U>; // expected-error {{must use an elaborated type}}
+ };
+ template<template<typename> class T> struct B {
+ friend T; // expected-error {{requires a type specifier}} expected-error {{can only be classes or functions}}
+ template<typename U> friend T<U>; // expected-error {{must use an elaborated type}}
+ };
+}
+
+// dr586: na
+
+namespace dr587 { // dr587: yes
+ template<typename T> void f(bool b, const T x, T y) {
+ const T *p = &(b ? x : y);
+ }
+ struct S {};
+ template void f(bool, const int, int);
+ template void f(bool, const S, S);
+}
+
+namespace dr588 { // dr588: yes
+ struct A { int n; }; // expected-note {{ambiguous}}
+ template<typename T> int f() {
+ struct S : A, T { int f() { return n; } } s;
+ int a = s.f();
+ int b = s.n; // expected-error {{found in multiple}}
+ }
+ struct B { int n; }; // expected-note {{ambiguous}}
+ int k = f<B>(); // expected-note {{here}}
+}
+
+namespace dr589 { // dr589: yes
+ struct B { };
+ struct D : B { };
+ D f();
+ extern const B &b;
+ bool a;
+ const B *p = &(a ? f() : b); // expected-error {{temporary}}
+ const B *q = &(a ? D() : b); // expected-error {{temporary}}
+}
+
+namespace dr590 { // dr590: yes
+ template<typename T> struct A {
+ struct B {
+ struct C {
+ A<T>::B::C f(A<T>::B::C); // ok, no 'typename' required.
+ };
+ };
+ };
+ template<typename T> typename A<T>::B::C A<T>::B::C::f(A<T>::B::C) {}
+}
+
+namespace dr591 { // dr591: no
+ template<typename T> struct A {
+ typedef int M;
+ struct B {
+ typedef void M;
+ struct C;
+ };
+ };
+
+ template<typename T> struct A<T>::B::C : A<T> {
+ // FIXME: Should find member of non-dependent base class A<T>.
+ M m; // expected-error {{incomplete type 'M' (aka 'void'}}
+ };
+}
+
+// dr592: na
+// dr593 needs an IRGen test.
+// dr594: na
+
+namespace dr595 { // dr595: dup 1330
+ template<class T> struct X {
+ void f() throw(T) {}
+ };
+ struct S {
+ X<S> xs;
+ };
+}
+
+// dr597: na
+
+namespace dr598 { // dr598: yes
+ namespace N {
+ void f(int);
+ void f(char);
+ // Not found by ADL.
+ void g(void (*)(int));
+ void h(void (*)(int));
+
+ namespace M {
+ struct S {};
+ int &h(void (*)(S));
+ }
+ void i(M::S);
+ void i();
+ }
+ int &g(void(*)(char));
+ int &r = g(N::f);
+ int &s = h(N::f); // expected-error {{undeclared}}
+ int &t = h(N::i);
+}
+
+namespace dr599 { // dr599: partial
+ typedef int Fn();
+ struct S { operator void*(); };
+ struct T { operator Fn*(); };
+ struct U { operator int*(); operator void*(); }; // expected-note 2{{conversion}}
+ struct V { operator int*(); operator Fn*(); };
+ void f(void *p, void (*q)(), S s, T t, U u, V v) {
+ delete p; // expected-error {{cannot delete}}
+ delete q; // expected-error {{cannot delete}}
+ delete s; // expected-error {{cannot delete}}
+ delete t; // expected-error {{cannot delete}}
+ // FIXME: This is valid, but is rejected due to a non-conforming GNU
+ // extension allowing deletion of pointers to void.
+ delete u; // expected-error {{ambiguous}}
+ delete v;
+ }
+}