diff options
Diffstat (limited to 'test/CXX/drs/dr5xx.cpp')
-rw-r--r-- | test/CXX/drs/dr5xx.cpp | 785 |
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; + } +} |