[PATCH] D100276: [clang] p1099 using enum part 1

2021-05-11 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan updated this revision to Diff 344396.
urnathan edited the summary of this revision.
urnathan edited reviewers, added: davrec; removed: Quuxplusone.
urnathan added a comment.

This update relies upon D101777  & D102239 
 (let's see if I can figure out how to note 
that elsewhere)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100276/new/

https://reviews.llvm.org/D100276

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7.cpp
  clang/test/SemaCXX/enum-scoped.cpp

Index: clang/test/SemaCXX/enum-scoped.cpp
===
--- clang/test/SemaCXX/enum-scoped.cpp
+++ clang/test/SemaCXX/enum-scoped.cpp
@@ -301,8 +301,8 @@
   int E::*p; // expected-error {{does not point into a class}}
   using E::f; // expected-error {{no member named 'f'}}
 
-  using E::a; // expected-error {{using declaration cannot refer to a scoped enumerator}}
-  E b = a; // expected-error {{undeclared}}
+  using E::a; // expected-warning {{using declaration naming a scoped enumerator is a C++20 extension}}
+  E b = a;
 }
 
 namespace test11 {
Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7.cpp
===
--- clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7.cpp
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7.cpp
@@ -1,4 +1,11 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s
+// RUN: %clang_cc1 -std=c++17 -verify %s
+// RUN: %clang_cc1 -std=c++20 -verify %s
 
 enum class EC { ec };
-using EC::ec; // expected-error {{using declaration cannot refer to a scoped enumerator}}
+using EC::ec;
+#if __cplusplus < 202002
+// expected-warning@-2 {{using declaration naming a scoped enumerator is a C++20 extension}}
+#else
+// expected-no-diagnostics
+#endif
Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
@@ -0,0 +1,271 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+
+// p1099 'using SCOPEDENUM::MEMBER;'
+
+namespace Zero {
+namespace Bob {
+enum class Kevin {
+  Stuart,
+  AlsoStuart
+#if __cplusplus >= 202002L
+// expected-note@-3{{target of using declaration}}
+// expected-note@-3{{target of using declaration}}
+#endif
+};
+} // namespace Bob
+
+using Bob::Kevin::Stuart;
+#if __cplusplus < 202002L
+// expected-warning@-2{{using declaration naming a scoped enumerator is a C++20 extension}}
+#else
+using Bob::Kevin::Stuart;
+
+auto b = Stuart;
+
+namespace Foo {
+int Stuart;   // expected-note{{conflicting declaration}}
+using Bob::Kevin::Stuart; // expected-error{{target of using declaration conflicts}}
+
+using Bob::Kevin::AlsoStuart; // expected-note{{using declaration}}
+int AlsoStuart;   // expected-error{{declaration conflicts with target}}
+} // namespace Foo
+#endif
+
+} // namespace Zero
+
+namespace One {
+
+// derived from [namespace.udecl]/3
+enum class button { up,
+down };
+struct S {
+  using button::up;
+#if __cplusplus < 202002L
+  // expected-warning@-2{{a C++20 extension}}
+  // expected-error@-3{{using declaration in class}}
+#else
+  button b = up;
+#endif
+};
+
+#if __cplusplus >= 202002L
+// some more
+struct T : S {
+  button c = up;
+};
+#endif
+enum E2 { e2 };
+} // namespace One
+
+namespace Two {
+enum class E1 { e1 };
+
+struct S {
+  using One::e2;
+#if __cplusplus < 202002L
+  // expected-error@-2{{using declaration in class}}
+#else
+  One::E2 c = e2;
+#endif
+};
+
+} // namespace Two
+
+namespace Three {
+
+enum E3 { e3 };
+struct e3;
+
+struct S {
+  using Three::e3; // expected-error{{using declaration in class}}
+
+  enum class E4 { e4 };
+  enum E5 { e5 };
+};
+
+using S::e5;
+using S::E4::e4;
+#if __cplusplus < 202002L
+// expected-error@-3{{using declaration cannot refer to class member}}
+// expected-note@-4{{use a constexpr variable instead}}
+// expected-warning@-4{{a C++20 extension}}
+// expected-error@-5{{using declaration cannot refer to class member}}
+// expected-note@-6{{use a constexpr variable instead}}
+#else
+auto a = e4;
+auto b = e5;
+#endif
+} // namespace Three
+
+namespace Four {
+
+template 
+struct TPL {
+  enum class E1 { e1 };
+  struct IN {
+enum class E2 { e2 };
+  };
+
+protected:
+  enum class E3 { e3 }; // expected-note{{declared protected here}}
+};
+
+using TPL::E1::e1;
+#if __cplusplus < 202002L
+// expected-warning@-2{{a C++20 extension}}
+// 

[PATCH] D100276: [clang] p1099 using enum part 1

2021-04-21 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan updated this revision to Diff 339293.
urnathan added a comment.

Updated to fix formatting etc (pretty sure I got clang-format to work this 
time).  I changed the pre-c++20 behaviour to be a warning along the lines you 
suggested.  Trying to move the qualifier checking until after generating the 
shadow decls died horribly -- the shadow generation presumes the context is 
sane :(

As mentioned, I intend updating docs and feature macro once the second half is 
done.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100276/new/

https://reviews.llvm.org/D100276

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7.cpp
  clang/test/SemaCXX/enum-scoped.cpp

Index: clang/test/SemaCXX/enum-scoped.cpp
===
--- clang/test/SemaCXX/enum-scoped.cpp
+++ clang/test/SemaCXX/enum-scoped.cpp
@@ -301,8 +301,8 @@
   int E::*p; // expected-error {{does not point into a class}}
   using E::f; // expected-error {{no member named 'f'}}
 
-  using E::a; // expected-error {{using declaration cannot refer to a scoped enumerator}}
-  E b = a; // expected-error {{undeclared}}
+  using E::a; // expected-warning {{using declaration naming a scoped enumerator is a C++20 extension}}
+  E b = a;
 }
 
 namespace test11 {
Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7.cpp
===
--- clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7.cpp
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7.cpp
@@ -1,4 +1,11 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s
+// RUN: %clang_cc1 -std=c++17 -verify %s
+// RUN: %clang_cc1 -std=c++20 -verify %s
 
 enum class EC { ec };
-using EC::ec; // expected-error {{using declaration cannot refer to a scoped enumerator}}
+using EC::ec;
+#if __cplusplus < 202002
+// expected-warning@-2 {{using declaration naming a scoped enumerator is a C++20 extension}}
+#else
+// expected-no-diagnostics
+#endif
Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
@@ -0,0 +1,149 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+
+// p1099 'using SCOPEDENUM::MEMBER;'
+
+namespace Bob {
+enum class Kevin {
+  Stuart,
+  AlsoStuart
+#if __cplusplus >= 202002L
+// expected-note@-3{{target of using declaration}}
+// expected-note@-3{{target of using declaration}}
+#endif
+};
+} // namespace Bob
+
+using Bob::Kevin::Stuart;
+#if __cplusplus < 202002L
+// expected-warning@-2{{using declaration naming a scoped enumerator is a C++20 extension}}
+#else
+using Bob::Kevin::Stuart;
+
+auto b = Stuart;
+
+namespace Foo {
+int Stuart;   // expected-note{{conflicting declaration}}
+using Bob::Kevin::Stuart; // expected-error{{target of using declaration conflicts}}
+
+using Bob::Kevin::AlsoStuart; // expected-note{{using declaration}}
+int AlsoStuart;   // expected-error{{declaration conflicts with target}}
+} // namespace Foo
+#endif
+
+namespace One {
+
+// derived from [namespace.udecl]/3
+enum class button { up,
+down };
+struct S {
+  using button::up;
+#if __cplusplus < 202002L
+  // expected-error@-2{{using declaration in class}}
+#else
+  button b = up;
+#endif
+};
+
+#if __cplusplus >= 202002L
+// some more
+struct T : S {
+  button c = up;
+};
+#endif
+enum E2 { e2 };
+} // namespace One
+
+namespace Two {
+enum class E1 { e1 };
+
+struct S {
+  using One::e2;
+#if __cplusplus < 202002L
+  // expected-error@-2{{using declaration in class}}
+#else
+  One::E2 c = e2;
+#endif
+};
+
+} // namespace Two
+
+namespace Three {
+
+enum E3 { e3 };
+struct e3;
+
+struct S {
+  using Three::e3; // expected-error{{using declaration in class}}
+
+  enum class E4 { e4 };
+  enum E5 { e5 };
+};
+
+using S::e5;
+using S::E4::e4;
+#if __cplusplus < 202002L
+// expected-error@-3{{using declaration cannot refer to class member}}
+// expected-note@-4{{use a constexpr variable instead}}
+// expected-warning@-4{{using declaration naming a scoped enumerator is a C++20 extension}}
+#else
+auto a = e4;
+auto b = e5;
+#endif
+} // namespace Three
+
+namespace Four {
+
+template 
+struct TPL {
+  enum class E1 { e1 };
+  struct IN {
+enum class E2 { e2 };
+  };
+
+protected:
+  enum class E3 { e3 }; // expected-note{{declared protected here}}
+};
+
+using TPL::E1::e1;
+#if __cplusplus < 202002L
+// expected-warning@-2{{using declaration naming a scoped enumerator is a C++20 extension}}
+#else
+using 

[PATCH] D100276: [clang] p1099 using enum part 1

2021-04-21 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan added a comment.

thanks for the comments.  My plan wrt documentation was to address that (and 
the feature macro) once the patches are in.




Comment at: clang/lib/Sema/SemaDeclCXX.cpp:12353
+  ED = R->getAsSingle();
+else if (UD && UD->shadow_size () == 1)
+  ED = dyn_cast(UD->shadow_begin()->getTargetDecl());

bruno wrote:
> -> `UD->shadow_size()`
Hm, I wonder what happened, I was pretty sure I ran git clang-format.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100276/new/

https://reviews.llvm.org/D100276

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100276: [clang] p1099 using enum part 1

2021-04-20 Thread Bruno Cardoso Lopes via Phabricator via cfe-commits
bruno added a comment.

Hi Nathan, thanks for implementing this. Besides formatting nitpicks, few other 
comments/questions:

- Update needed in cxx_status.html
- Should we support this as an extension for earlier C++ versions? This is a 
very handy feature. In clang terms, 
`warn_cxx17_compat_constexpr_body_invalid_stmt` and 
`ext_constexpr_body_invalid_stmt_cxx20` would be examples for that.

> Perhaps deferring the scope check until after construction of the 
> shadow-decls in the parsing case would be preferred?

Doing it as part of `BuildUsingDeclaration` seem reasonable, anything that 
might not work because of that?




Comment at: clang/lib/Sema/SemaDeclCXX.cpp:12353
+  ED = R->getAsSingle();
+else if (UD && UD->shadow_size () == 1)
+  ED = dyn_cast(UD->shadow_begin()->getTargetDecl());

-> `UD->shadow_size()`



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:12370
 // If we weren't able to compute a valid scope, it might validly be a
 // dependent class scope or a dependent enumeration unscoped scope. If
 // we have a 'typename' keyword, the scope must resolve to a class type.

Does this comment needs update?



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:12452
+  // The current scope is a record.
+
   if (!NamedContext->isRecord()) {

trim off newline



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:12538
 
+
 Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,

same here.



Comment at: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:3079
+  // recheck the inheritance
+
   if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName)

here too



Comment at: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp:20
 class C {
+public:
   int g();

> The change to clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp 
> is to silence an uninteresting access error that the above change causes.

The fact that the access check changed for previous version of the language 
(not necessarily related to p1099) indicates that this specific change deserves 
its own patch.



Comment at: 
clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp:1
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s

Why not c++17?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100276/new/

https://reviews.llvm.org/D100276

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100276: [clang] p1099 using enum part 1

2021-04-14 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan updated this revision to Diff 337416.
urnathan added a comment.

Remove orthogonal lbstdc++ FIXME comment


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100276/new/

https://reviews.llvm.org/D100276

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp

Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
@@ -0,0 +1,149 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+
+// p1099 'using SCOPEDENUM::MEMBER;'
+
+namespace Bob {
+enum class Kevin {
+  Stuart,
+  AlsoStuart
+#if __cplusplus >= 202002L
+  // expected-note@-3{{target of using declaration}}
+  // expected-note@-3{{target of using declaration}}
+#endif
+};
+}
+
+using Bob::Kevin::Stuart;
+#if __cplusplus < 202002L
+// expected-error@-2{{using declaration cannot refer to a scoped enumerator}}
+#else
+using Bob::Kevin::Stuart;
+
+auto b = Stuart;
+
+namespace Foo {
+int Stuart; // expected-note{{conflicting declaration}}
+using Bob::Kevin::Stuart; // expected-error{{target of using declaration conflicts}}
+
+using Bob::Kevin::AlsoStuart; // expected-note{{using declaration}}
+int AlsoStuart; // expected-error{{declaration conflicts with target}}
+}
+#endif
+
+
+namespace One {
+
+// derived from [namespace.udecl]/3
+enum class button { up, down };
+struct S {
+  using button::up;
+#if __cplusplus < 202002L
+  // expected-error@-2{{using declaration in class}}
+#else
+  button b = up;
+#endif
+};
+
+#if __cplusplus >= 202002L
+// some more
+struct T : S {
+  button c = up;
+};
+#endif
+enum E2 {e2};
+}
+
+namespace Two {
+enum class E1 {e1};
+
+struct S {
+  using One::e2;
+#if __cplusplus < 202002L
+  // expected-error@-2{{using declaration in class}}
+#else
+  One::E2 c = e2;
+#endif
+};
+
+}
+
+namespace Three {
+
+enum E3{e3};
+struct e3;
+
+struct S {
+  using Three::e3; // expected-error{{using declaration in class}}
+
+  enum class E4 {e4};
+  enum E5 {e5};
+};
+
+using S::e5;
+using S::E4::e4;
+#if __cplusplus < 202002L
+// expected-error@-3{{using declaration cannot refer to class member}}
+// expected-note@-4{{use a constexpr variable instead}}
+// expected-error@-4{{using declaration cannot refer to a scoped enumerator}}
+#else
+auto a = e4;
+auto b = e5;
+#endif
+}
+
+namespace Four {
+
+template
+struct TPL {
+  enum class E1 {e1};
+  struct IN {
+enum class E2 {e2};
+  };
+protected:
+  enum class E3 {e3}; // expected-note{{declared protected here}}
+};
+
+using TPL::E1::e1;
+#if __cplusplus < 202002L
+// expected-error@-2{{cannot refer to a scoped enumerator}}
+#else
+using TPL::IN::E2::e2;
+
+auto a = e1;
+auto b = e2;
+#endif
+
+enum class E4 {e4};
+template
+struct DER : TPL
+{
+  using TPL::E1::e1;
+#if __cplusplus < 202002L
+  // expected-error@-2{{'TPL::E1::', which is not a class}}
+  // expected-error@-3{{'TPL::E1::', which is not a class}}
+#endif
+  using TPL::E3::e3; // expected-error{{is a protected member}}
+#if __cplusplus < 202002L
+  // expected-error@-2{{'TPL::E3::', which is not a class}}
+  // expected-error@-3{{'TPL::E3::', which is not a class}}
+#endif
+  
+  using E4::e4;
+#if __cplusplus < 202002L
+  // expected-error@-2{{which is not a class}}
+#else
+  auto Foo () { return e1;}
+  auto Bar () { return e2;}
+#endif
+};
+
+DER x; // expected-note{{requested here}}
+DER y;
+#if __cplusplus < 202002L
+// expected-note@-2{{requested here}}
+#else
+auto y1 = y.Foo ();
+auto y2 = y.Bar ();
+#endif
+}
Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp
===
--- clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp
@@ -17,6 +17,7 @@
 };
 
 class C {
+public:
   int g();
 };
 
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3063,10 +3063,9 @@
   }
 
   if (!NewUD->isInvalidDecl() &&
-  SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(),
-  SS, NameInfo, D->getLocation()))
+  SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(), SS,
+  NameInfo, D->getLocation(), nullptr, D))
 NewUD->setInvalidDecl();
-
   SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
   NewUD->setAccess(D->getAccess());
   Owner->addDecl(NewUD);
@@ -3075,6 +3074,9 @@
   if 

[PATCH] D100276: [clang] p1099 using enum part 1

2021-04-12 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan added inline comments.



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:12144
   NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) 
{
+// FIXME: 2021-04-07: When was this hack needed?  Can it be deleted now?
 // HACK: Work around a bug in libstdc++'s detection of ::gets. Sometimes

urnathan wrote:
> I noticed this in passing.  I have found it useful to add dates in such 
> workaround comments -- having found really old ones in GCC that have been 
> obsolete for like 15 years or more :)  Which  version(s) of libstdc++ got 
> this wrong?
to answer my own question:
f501cc313e9e0 (Richard Smith 2012-10-05 01:46:25 +

Workaround for libstdc++4.6  bug: make comment more explicit about 
what's going on, per Sean Silva's suggestion.

the last 4.6 release was GCC 4.6.4 in 2013-04-12

so (a) probably removable but I've not checked if/when libstdc++ fixed the 
problem, and (b) should be treated as a separate issue, of course.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100276/new/

https://reviews.llvm.org/D100276

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100276: [clang] p1099 using enum part 1

2021-04-12 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan added inline comments.



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:12144
   NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) 
{
+// FIXME: 2021-04-07: When was this hack needed?  Can it be deleted now?
 // HACK: Work around a bug in libstdc++'s detection of ::gets. Sometimes

I noticed this in passing.  I have found it useful to add dates in such 
workaround comments -- having found really old ones in GCC that have been 
obsolete for like 15 years or more :)  Which  version(s) of libstdc++ got this 
wrong?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100276/new/

https://reviews.llvm.org/D100276

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100276: [clang] p1099 using enum part 1

2021-04-11 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan created this revision.
urnathan added reviewers: rsmith, Quuxplusone, bruno.
urnathan requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This adds support for p1099's 'using SCOPED_ENUM::MEMNER;'
functionality, bringing a member of an enumerator into the current
scope.  The novel feature here, is that there need not be a class
hierarchical relationship between the current scope and the scope of
the SCOPED_ENUM.  That's a new thing, the closest equivalent is a
typedef or alias declaration.  But this means that
Sema::CheckUsingDeclQualifier needs adjustment.  (a) one can't call it
until one knows the set of decls that are being referenced -- if
exactly one is an enumerator, we're in the new territory.  Thus it
needs calling later in some cases.  Also (b) there are two ways we
hold the set of such decls.  During parsing (or instantiating a
dependent scope) we have a lookup result, and during instantiation we
have a set of shadow decls.  Thus two optional arguments, at most one
of which should be non-null.

The change to
clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp is to
silence an uninteresting access error that the above change causes.

Perhaps deferring the scope check until after construction of the
shadow-decls in the parsing case would be preferred?  Also moving up
the check for naming a scoped-enumerator member might be more helpful?


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100276

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp

Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p7-cxx20.cpp
@@ -0,0 +1,149 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+
+// p1099 'using SCOPEDENUM::MEMBER;'
+
+namespace Bob {
+enum class Kevin {
+  Stuart,
+  AlsoStuart
+#if __cplusplus >= 202002L
+// expected-note@-3{{target of using declaration}}
+// expected-note@-3{{target of using declaration}}
+#endif
+};
+} // namespace Bob
+
+using Bob::Kevin::Stuart;
+#if __cplusplus < 202002L
+// expected-error@-2{{using declaration cannot refer to a scoped enumerator}}
+#else
+using Bob::Kevin::Stuart;
+
+auto b = Stuart;
+
+namespace Foo {
+int Stuart;   // expected-note{{conflicting declaration}}
+using Bob::Kevin::Stuart; // expected-error{{target of using declaration conflicts}}
+
+using Bob::Kevin::AlsoStuart; // expected-note{{using declaration}}
+int AlsoStuart;   // expected-error{{declaration conflicts with target}}
+} // namespace Foo
+#endif
+
+namespace One {
+
+// derived from [namespace.udecl]/3
+enum class button { up,
+down };
+struct S {
+  using button::up;
+#if __cplusplus < 202002L
+  // expected-error@-2{{using declaration in class}}
+#else
+  button b = up;
+#endif
+};
+
+#if __cplusplus >= 202002L
+// some more
+struct T : S {
+  button c = up;
+};
+#endif
+enum E2 { e2 };
+} // namespace One
+
+namespace Two {
+enum class E1 { e1 };
+
+struct S {
+  using One::e2;
+#if __cplusplus < 202002L
+  // expected-error@-2{{using declaration in class}}
+#else
+  One::E2 c = e2;
+#endif
+};
+
+} // namespace Two
+
+namespace Three {
+
+enum E3 { e3 };
+struct e3;
+
+struct S {
+  using Three::e3; // expected-error{{using declaration in class}}
+
+  enum class E4 { e4 };
+  enum E5 { e5 };
+};
+
+using S::e5;
+using S::E4::e4;
+#if __cplusplus < 202002L
+// expected-error@-3{{using declaration cannot refer to class member}}
+// expected-note@-4{{use a constexpr variable instead}}
+// expected-error@-4{{using declaration cannot refer to a scoped enumerator}}
+#else
+auto a = e4;
+auto b = e5;
+#endif
+} // namespace Three
+
+namespace Four {
+
+template 
+struct TPL {
+  enum class E1 { e1 };
+  struct IN {
+enum class E2 { e2 };
+  };
+
+protected:
+  enum class E3 { e3 }; // expected-note{{declared protected here}}
+};
+
+using TPL::E1::e1;
+#if __cplusplus < 202002L
+// expected-error@-2{{cannot refer to a scoped enumerator}}
+#else
+using TPL::IN::E2::e2;
+
+auto a = e1;
+auto b = e2;
+#endif
+
+enum class E4 { e4 };
+template 
+struct DER : TPL {
+  using TPL::E1::e1;
+#if __cplusplus < 202002L
+  // expected-error@-2{{'TPL::E1::', which is not a class}}
+  // expected-error@-3{{'TPL::E1::', which is not a class}}
+#endif
+  using TPL::E3::e3; // expected-error{{is a protected member}}
+#if __cplusplus < 202002L
+  // expected-error@-2{{'TPL::E3::', which is not a class}}
+  // expected-error@-3{{'TPL::E3::', which is not a class}}
+#endif
+
+  using E4::e4;
+#if