// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s // p1099 'using enum ELABORATED-ENUM-SPECIFIER ;' namespace One { namespace Bob { enum A { a, // expected-note{{declared here}} b, c }; class C; // expected-note{{previous use}} enum class D : int; enum class D { d, e, f }; enum class D : int; } // namespace Bob using enum Bob::A; #if __cplusplus < 202002 // expected-warning@-2{{is a C++20 extension}} #endif using enum Bob::B; // expected-error{{no enum named 'B'}} #if __cplusplus < 202002 // expected-warning@-2{{is a C++20 extension}} #endif using enum Bob::C; // expected-error{{tag type that does not match}} #if __cplusplus < 202002 // expected-warning@-2{{is a C++20 extension}} #endif auto v = a; A g; // expected-error{{unknown type name 'A'}} int A; using enum Bob::D; #if __cplusplus < 202002 // expected-warning@-2{{is a C++20 extension}} #endif } // namespace One namespace Two { namespace Kevin { enum class B { d, e, f }; } using enum Kevin::B; #if __cplusplus < 202002 // expected-warning@-2{{is a C++20 extension}} #endif auto w = e; } // namespace Two #if __cplusplus >= 202002 // Now only check c++20 onwards namespace Three { namespace Stuart { enum class C : int; // expected-note{{declared here}} } using enum Stuart::C; // expected-error{{is incomplete}} } // namespace Three namespace Four { class Dave { public: enum D { a, b, c }; private: enum class E { d, // expected-note{{declared private here}} e, f }; }; using enum Dave::D; using enum Dave::E; // expected-error{{is a private member}} } // namespace Four namespace Five { enum class A { b, c }; class Dave { public: using enum A; A f = b; }; } // namespace Five namespace Six { template class TPL; template <> class TPL { public: enum A { a }; }; template class USR { using enum TPL::B; // expected-error{{cannot name a dependent type}} using enum TPL::A; }; } // namespace Six // Now instantiate things namespace Seven { namespace Stuart { enum class A { a, b, c }; } static_assert(!int(Stuart::A::a)); constexpr int Bar() { using enum Stuart::A; return int(b); } static_assert(Bar() == 1); template constexpr int Foo() { using enum Stuart::A; return int(b) + I; } static_assert(Foo<10>() == 11); template struct C { using enum Stuart::A; static constexpr int V = int(c) + I; enum class D { d, e, f }; using enum D; static constexpr int W = int(f) + I; }; static_assert(C<2>::V == 4); static_assert(C<20>::W == 22); } // namespace Seven namespace Eight { enum class Bob : int {}; using enum Bob; } // namespace Eight namespace Nine { template struct C { enum class D { i = I }; enum class E : int; // expected-note{{declared here}} }; using enum C<2>::D; constexpr auto d = i; static_assert(unsigned(d) == 2); using enum C<2>::E; // expected-error{{instantiation of undefined member}} } // namespace Nine namespace Ten { enum class Bob { a }; void Foo() { extern void a(); } // We don't see the hidden extern a fn! using enum Bob; auto v = a; } // namespace Ten namespace Eleven { enum class Bob { a }; // expected-note{{conflicting declaration}} struct Base { enum { a }; // expected-note{{target of using}} }; template class TPLa : B { using enum Bob; using B::a; // expected-error{{target of using declaration}} }; TPLa a; // expected-note{{in instantiation}} } // namespace Eleven namespace Twelve { enum class Bob { a }; // expected-note{{target of using}} struct Base { enum { a }; }; template class TPLb : B { using B::a; // expected-note{{conflicting declaration}} using enum Bob; // expected-error{{target of using declaration}} }; TPLb b; } // namespace Twelve namespace Thirteen { enum class Bob { a }; class Foo { using enum Bob; // expected-note{{previous using-enum}} using enum Bob; // expected-error{{redeclaration of using-enum}} }; template class TPLa { using enum Bob; // expected-note{{previous using-enum}} using enum Bob; // expected-error{{redeclaration of using-enum}} }; TPLa a; } // namespace Thirteen #endif