brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · e580799 Raw
157 lines · cpp
1// RUN: %clang_cc1 -std=c++11 -verify %s2 3template<typename T> struct A {4  enum E : T; // expected-note {{here}}5  E v;6  E f() { return A::e1; } // expected-error {{no member named 'e1' in 'A<T>'}}7  E g() { return E::e1; }8  E h();9};10 11A<int> a;12A<int>::E a0 = A<int>().v;13int n = A<int>::E::e1; // expected-error {{implicit instantiation of undefined member}}14 15template<typename T> enum A<T>::E : T { e1, e2 }; // expected-note 2 {{declared here}}16 17// FIXME: Now that A<T>::E is defined, we are supposed to inject its enumerators18// into the already-instantiated class A<T>. This seems like a really bad idea,19// though, so we don't implement that, but what we do implement is inconsistent.20//21// Either do as the standard says, or only include enumerators lexically defined22// within the class in its scope.23A<int>::E a1 = A<int>::e1; // expected-error {{no member named 'e1' in 'A<int>'; did you mean simply 'e1'?}}24 25A<char>::E a2 = A<char>::e2;26 27template<typename T> typename A<T>::E A<T>::h() { return e2; }28A<short>::E a3 = A<short>().h();29 30 31template<typename T> struct B {32  enum class E;33  E v;34  E f() { return E::e1; }35  E g();36};37 38B<int> b;39B<int>::E b0 = B<int>().v;40 41template<typename T> enum class B<T>::E { e1, e2 };42B<int>::E b1 = B<int>::E::e1;43 44B<char>::E b2 = B<char>::E::e2;45 46template<typename T> typename B<T>::E B<T>::g() { return e2; }47B<short>::E b3 = B<short>().g();48 49 50// Enumeration members of class templates can be explicitly specialized. For51// unscoped enumerations, specializations must be defined before the primary52// template is, since otherwise the primary template will be implicitly53// instantiated when we parse the nested name specifier.54template<> enum A<long long>::E : long long { e3, e4 }; // expected-error {{explicit specialization of 'E' after instantiation}} expected-note {{first required here}}55 56template<> enum class B<long long>::E { e3, e4 };57B<long long>::E b4 = B<long long>::E::e4;58 59B<long>::E b5;60template<> enum class B<long>::E { e5 };61void fb5() { b5 = decltype(b5)::e5; }62B<long>::E b6 = B<long>::E::e5;63 64 65template<typename T> struct C {66  enum class E : T;67};68 69template<> enum class C<long long>::E : long long { e3, e4 };70C<long long>::E c0 = C<long long>::E::e3;71 72C<long>::E c1;73template<> enum class C<long>::E : long { e5 };74void fc1() { c1 = decltype(c1)::e5; }75C<long>::E c2 = C<long>::E::e5;76 77template<> enum class C<int>::E : int { e6 };78template<typename T> enum class C<T>::E : T { e0 };79C<int>::E c3 = C<int>::E::e6;80C<int>::E c4 = C<int>::E::e0; // expected-error {{no member named 'e0' in 'C<int>::E'}}81 82 83// Enumeration members can't be partially-specialized.84template<typename T> enum class B<T*>::E { e5, e6 }; // expected-error {{nested name specifier for a declaration cannot depend on a template parameter}}85 86 87// Explicit specializations can be forward-declared.88template<typename T>89struct D {90  enum class E { e1 };91};92template<> enum class D<int>::E;93D<int>::E d1 = D<int>::E::e1; // expected-error {{incomplete type 'D<int>::E'}}94template<> enum class D<int>::E { e2 };95D<int>::E d2 = D<int>::E::e2;96D<char>::E d3 = D<char>::E::e1; // expected-note {{first required here}}97D<char>::E d4 = D<char>::E::e2; // expected-error {{no member named 'e2' in 'D<char>::E'; did you mean simply 'e2'?}}98template<> enum class D<char>::E { e3 }; // expected-error {{explicit specialization of 'E' after instantiation}}99 100template<> enum class D<short>::E;101struct F {102  // Per C++11 [class.friend]p3, these friend declarations have no effect.103  // Only classes and functions can be friends.104  template<typename T> friend enum D<T>::E; // expected-warning {{elaborated enum specifier cannot be declared as a friend}}105                                            // expected-note@-1 {{remove 'enum' to befriend an enum}}106  template<> friend enum D<short>::E; // expected-warning {{elaborated enum specifier cannot be declared as a friend}}107                                      // expected-note@-1 {{remove 'enum' to befriend an enum}}108 109  template<> friend enum D<double>::E { e3 }; // expected-error {{cannot define a type in a friend declaration}}110                                              // expected-warning@-1 {{elaborated enum specifier cannot be declared as a friend}}111                                              // expected-note@-2 {{remove 'enum' to befriend an enum}}112 113private:114  static const int n = 1; // expected-note {{private here}}115};116template<> enum class D<short>::E {117  e = F::n // expected-error {{private member}}118};119 120class Access {121  friend class X;122 123  template<typename T>124  class Priv {125    friend class X;126 127    enum class E : T;128  };129 130  class S {131    typedef int N; // expected-note {{here}}132    static const int k = 3; // expected-note {{here}}133 134    friend class Priv<char>;135  };136 137  static const int k = 5;138};139 140template<> enum class Access::Priv<Access::S::N>::E141  : Access::S::N { // expected-error {{private member}}142  a = Access::k, // ok143  b = Access::S::k // expected-error {{private member}}144};145 146template<typename T> enum class Access::Priv<T>::E : T {147  c = Access::k,148  d = Access::S::k149};150 151class X {152  Access::Priv<int>::E a = Access::Priv<int>::E::a;153  Access::Priv<char>::E c = Access::Priv<char>::E::d;154  // FIXME: We should see an access error for this enumerator.155  Access::Priv<short>::E b = Access::Priv<short>::E::d;156};157