llvm/clang/test/CXX/drs/cwg19xx.cpp

// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-11,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-11,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors

namespace std { struct type_info; }

namespace cwg1900 { // cwg1900: 2.7
// See the test for CWG1477 for detailed analysis
namespace N {
struct A {
  friend int f();
};
}
int N::f() { return 0; }
int N::g() { return 0; } 
// expected-error@-1 {{out-of-line definition of 'g' does not match any declaration in namespace 'cwg1900::N'}}
} // namespace cwg1900

namespace cwg1902 { // cwg1902: 3.7
  struct A {};
  struct B {
    B(A); // #cwg1902-B-A
    B() = delete; // #cwg1902-B-ctor
    // cxx98-error@-1 {{deleted function definitions are a C++11 extension}}
    B(const B&) = delete; // #cwg1902-B-copy-ctor
    // cxx98-error@-1 {{deleted function definitions are a C++11 extension}}
    operator A();
  };

  extern B b1;
  B b2(b1);
  // expected-error@-1 {{call to deleted constructor of 'B'}}
  //   expected-note@#cwg1902-B-copy-ctor {{'B' has been explicitly marked deleted here}}

#if __cplusplus >= 201103L
  // This is ambiguous, even though calling the B(const B&) constructor would
  // both directly and indirectly call a deleted function.
  B b({});
  // since-cxx11-error@-1 {{call to constructor of 'B' is ambiguous}}
  //   since-cxx11-note@#cwg1902-B-A {{candidate constructor}}
  //   since-cxx11-note@#cwg1902-B-copy-ctor {{candidate constructor has been explicitly deleted}}
#endif
}

namespace cwg1903 { // cwg1903: 2.7
  namespace A {
    struct a {};
    int a;
    namespace B {
      int b;
    }
    using namespace B;
    namespace {
      int c;
    }
    namespace D {
      int d;
    }
    using D::d;
  }
  namespace X {
    using A::a;
    using A::b;
    using A::c;
    using A::d;
    struct a *p;
  }
}

namespace cwg1909 { // cwg1909: 3.7
  struct A {
    template<typename T> struct A {};
    // expected-error@-1 {{member 'A' has the same name as its class}}
  };
  struct B {
    template<typename T> void B() {}
    // expected-error@-1 {{constructor cannot have a return type}}
  };
  struct C {
    template<typename T> static int C;
    // expected-error@-1 {{member 'C' has the same name as its class}} 
    // cxx98-11-error@-2 {{variable templates are a C++14 extension}}
  };
  struct D {
    template<typename T> using D = int;
    // cxx98-error@-1 {{alias declarations are a C++11 extension}}
    // expected-error@-2 {{member 'D' has the same name as its class}}
  };
}

namespace cwg1918 { // cwg1918: no
template<typename T> struct A {
  class B {
    class C {};
  };
};
class X {
  static int x;
  // FIXME: this is ill-formed, because A<T>::B::C does not end with a simple-template-id
  template <typename T>
  friend class A<T>::B::C;
  // expected-warning@-1 {{dependent nested name specifier 'A<T>::B::' for friend class declaration is not supported; turning off access control for 'X'}}
};
template<> struct A<int> {
  typedef struct Q B;
};
struct Q {
  class C {
    // FIXME: 'f' is not a friend, so 'X::x' is not accessible
    int f() { return X::x; }
  };
};
} // namespace cwg1918

namespace cwg1940 { // cwg1940: 3.5
#if __cplusplus >= 201103L
static union {
  static_assert(true, "");  // ok
  static_assert(false, "");
  // since-cxx11-error@-1 {{static assertion failed}}
  int not_empty;
};
#endif
}

namespace cwg1941 { // cwg1941: 3.9
#if __cplusplus >= 201402L
template<typename X>
struct base {
  template<typename T>
  base(T a, T b, decltype(void(*T()), 0) = 0) {
    while (a != b) (void)*a++;
  }

  template<typename T>
  base(T a, X x, decltype(void(T(0) * 1), 0) = 0) {
    for (T n = 0; n != a; ++n) (void)X(x);
  }
};

struct derived : base<int> {
  using base::base;
};

struct iter {
  iter operator++(int);
  int operator*();
  friend bool operator!=(iter, iter);
} it, end;

derived d1(it, end);
derived d2(42, 9);
#endif
}

namespace cwg1945 { // cwg1945: no
template<typename T> struct A {
  class B {
    class C {};
  };
};
class X {
  static int x;
  // FIXME: this is ill-formed, because A<T>::B::C does not end with a simple-template-id
  template <typename T>
  friend class A<T>::B::C;
  // expected-warning@-1 {{dependent nested name specifier 'A<T>::B::' for friend class declaration is not supported; turning off access control for 'X'}}
};
} // namespace cwg1945

namespace cwg1947 { // cwg1947: 3.5
#if __cplusplus >= 201402L
unsigned o = 0'01;  // ok
unsigned b = 0b'01;
// since-cxx14-error@-1 {{invalid digit 'b' in octal constant}}
unsigned x = 0x'01;
// since-cxx14-error@-1 {{invalid suffix 'x'01' on integer constant}}
#endif
}

#if __cplusplus >= 201103L
// cwg1948: 3.5
// FIXME: This diagnostic could be improved.
void *operator new(__SIZE_TYPE__) noexcept { return nullptr; }
// since-cxx11-error@-1 {{exception specification in declaration does not match previous declaration}}
#endif

namespace cwg1959 { // cwg1959: 3.9
#if __cplusplus >= 201103L
  struct b;
  struct c;
  struct a {
    a() = default;
    a(const a &) = delete; // #cwg1959-copy-ctor
    a(const b &) = delete; // not inherited
    a(c &&) = delete; // #cwg1959-move-ctor
    template<typename T> a(T) = delete; // #cwg1959-temp-ctor
  };

  struct b : a { // #cwg1959-b
    using a::a; // #cwg1959-using-a
  };

  a x;
  // FIXME: As a resolution to an open DR against P0136R0, we disallow
  // use of inherited constructors to construct from a single argument
  // where the base class is reference-related to the argument type.
  b y = x;
  // since-cxx11-error@-1 {{no viable conversion from 'a' to 'b'}}
  //   since-cxx11-note@#cwg1959-move-ctor {{candidate inherited constructor not viable: no known conversion from 'a' to 'c &&' for 1st argument}}
  //   since-cxx11-note@#cwg1959-using-a {{constructor from base class 'a' inherited here}}
  //   since-cxx11-note@#cwg1959-b {{candidate constructor (the implicit copy constructor) not viable: cannot bind base class object of type 'a' to derived class reference 'const b &' for 1st argument}}
  //   since-cxx11-note@#cwg1959-temp-ctor {{candidate template ignored: instantiation would take its own class type by value}}
  //   since-cxx11-note@#cwg1959-using-a {{constructor from base class 'a' inherited here}}
  b z = z;
  // since-cxx11-error@-1 {{call to implicitly-deleted copy constructor of 'b'}}
  //   since-cxx11-note@#cwg1959-b {{copy constructor of 'b' is implicitly deleted because base class 'a' has a deleted copy constructor}}
  //   since-cxx11-note@#cwg1959-copy-ctor {{'a' has been explicitly marked deleted here}}

  struct c : a {
    using a::a;
    c(const c &);
  };
  // FIXME: As a resolution to an open DR against P0136R0, we disallow
  // use of inherited constructors to construct from a single argument
  // where the base class is reference-related to the argument type.
  c q(static_cast<c&&>(q));
#endif
}

namespace cwg1960 { // cwg1960: no
struct A {
void f() {}
protected:
void g() {}
};

struct B: A {
private:
using A::f;
using A::g;
};

struct C : B {
// FIXME: both declarations are ill-formed, because A::f and A::g
// are not accessible.
using A::f;
using A::g;
};
}

namespace cwg1966 { // cwg1966: 11
#if __cplusplus >= 201103L
  struct A {
    enum E : int {1};
    // since-cxx11-error@-1 {{expected identifier}} (not bit-field)
  };
  auto *p1 = new enum E : int;
  // since-cxx11-error@-1 {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration}}
  auto *p2 = new enum F : int {};
  // since-cxx11-error@-1 {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration}}
  auto *p3 = true ? new enum G : int {};
  // since-cxx11-error@-1 {{ISO C++ forbids forward references to 'enum' types}}
  // since-cxx11-error@-2 {{allocation of incomplete type 'enum G'}}
  //   since-cxx11-note@-3 {{forward declaration of 'cwg1966::G'}}
  auto h() -> enum E : int {};
  // since-cxx11-error@-1 {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration}}

  enum X : enum Y : int {} {};
  // since-cxx11-error@-1 {{'cwg1966::Y' cannot be defined in a type specifier}}
  struct Q {
    // FIXME: can we emit something nicer than that?
    enum X : enum Y : int {} {};
    // since-cxx11-error@-1 {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration; missing list of enumerators?}}
    // since-cxx11-error@-2 {{non-integral type 'enum Y' is an invalid underlying type}}
    // since-cxx11-error@-3 {{anonymous bit-field cannot have a default member initializer}}
  };
#endif
}

namespace cwg1968 { // cwg1968: no
#if __cplusplus >= 201103L
  // FIXME: According to CWG1968, both of these should be considered
  // non-constant.
  static_assert(&typeid(int) == &typeid(int), "");

  constexpr const std::type_info *f() { return &typeid(int); }
  static_assert(f() == f(), "");
#endif
}

namespace cwg1991 { // cwg1991: 3.9
#if __cplusplus >= 201103L
  struct A {
    A(int, int) = delete;
  };

  struct B : A {
    using A::A;
    B(int, int, int = 0);
  };

  // FIXME: As a resolution to an open DR against P0136R1, we treat derived
  // class constructors as better than base class constructors in the presence
  // of ambiguity.
  B b(0, 0); // ok, calls B constructor
#endif
}

// cwg1994: dup 529