public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix behavior of using enum in dependent contexts [PR105787]
@ 2022-06-06 19:39 Michael Colavita
  2022-06-06 21:48 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Michael Colavita @ 2022-06-06 19:39 UTC (permalink / raw)
  To: gcc-patches

Per #105787, "using enum" in a dependent context leads to an ICE. This
is because the type substitution logic doesn't properly juggle the
context and abstract origin for CONST_DECLs introduced via using enum.
When we are performing type substitution on the CONST_DECL, we want to
do so in the context of the original enum type. When we return the
resulting value, we want to replace the context with the class in which
the CONST_DECL exists. This amounts to using the abstract origin for the
type substitution, and performing the same clone/abstract origin update
as we do for parsing "using enum" in non-dependent contexts.

PR c++/105787 - internal compiler error: tree check: expected enumeral_type, have record_type in tsubst_copy

        PR c++/105787

gcc/cp/ChangeLog:

        * pt.cc (tsubst_copy): Handle CONST_DECLs involving "using enum"
          in dependent contexts.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp2a/using-enum-10.C: New test.
        * g++.dg/cpp2a/using-enum-11.C: New test.
---
 gcc/cp/pt.cc                               | 24 +++++++++++++-
 gcc/testsuite/g++.dg/cpp2a/using-enum-10.C | 35 ++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp2a/using-enum-11.C | 38 ++++++++++++++++++++++
 3 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/using-enum-10.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/using-enum-11.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 6de8e496859..c11c682ded7 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16892,6 +16892,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       {
 	tree enum_type;
 	tree v;
+	tree original;
 
 	if (DECL_TEMPLATE_PARM_P (t))
 	  return tsubst_copy (DECL_INITIAL (t), args, complain, in_decl);
@@ -16903,6 +16904,14 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	if (args == NULL_TREE)
 	  return scalar_constant_value (t);
 
+	/* When the CONST_DECL is a class-scope clone from using enum, we want
+	   to perform the type substitution in the context of the original enum
+	   (the abstract origin), but return a value in the context of the
+	   class. */
+	original = t;
+	if (CONST_DECL_USING_P (original))
+	  t = DECL_ABSTRACT_ORIGIN (original);
+
 	/* Unfortunately, we cannot just call lookup_name here.
 	   Consider:
 
@@ -16921,7 +16930,20 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	     v != NULL_TREE;
 	     v = TREE_CHAIN (v))
 	  if (TREE_PURPOSE (v) == DECL_NAME (t))
-	    return TREE_VALUE (v);
+	    {
+	      tree value = TREE_VALUE (v);
+	      if (!CONST_DECL_USING_P (original))
+		return value;
+	      else
+		{
+		  value = copy_decl (value);
+		  DECL_ARTIFICIAL (value) = true;
+		  DECL_CONTEXT (value) = DECL_CONTEXT (original);
+		  DECL_IGNORED_P (value) = true;
+		  DECL_ABSTRACT_ORIGIN (value) = DECL_ABSTRACT_ORIGIN (original);
+		  return value;
+		}
+	    }
 
 	  /* We didn't find the name.  That should never happen; if
 	     name-lookup found it during preliminary parsing, we
diff --git a/gcc/testsuite/g++.dg/cpp2a/using-enum-10.C b/gcc/testsuite/g++.dg/cpp2a/using-enum-10.C
new file mode 100644
index 00000000000..ab4cb648e03
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/using-enum-10.C
@@ -0,0 +1,35 @@
+// PR c++/105787
+// { dg-do compile { target c++20 } }
+
+enum class fruit { orange, apple };
+
+struct A {
+public:
+  using enum fruit;
+private:
+};
+
+struct B {
+protected:
+  using enum fruit;
+public:
+};
+
+struct C {
+private:
+  using enum fruit;
+public:
+};
+
+template <int> struct D {
+  char a1 = (char) A::orange;
+  char a2 = (char) A::apple;
+  char b1 = (char) B::orange; // { dg-error "protected" }
+  char b2 = (char) B::apple; // { dg-error "protected" }
+  char c1 = (char) C::orange; // { dg-error "private" }
+  char c2 = (char) C::apple; // { dg-error "private" }
+};
+
+int main() {
+    D<0> d;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/using-enum-11.C b/gcc/testsuite/g++.dg/cpp2a/using-enum-11.C
new file mode 100644
index 00000000000..1899e05c68d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/using-enum-11.C
@@ -0,0 +1,38 @@
+// PR c++/105787
+// { dg-do compile { target c++20 } }
+
+enum class fruit { orange, apple };
+
+struct A {
+public:
+  using fruit::apple;
+  using fruit::orange;
+private:
+};
+
+struct B {
+protected:
+  using fruit::apple;
+  using fruit::orange;
+public:
+};
+
+struct C {
+private:
+  using fruit::apple;
+  using fruit::orange;
+public:
+};
+
+template <int> struct D {
+  char a1 = (char) A::orange;
+  char a2 = (char) A::apple;
+  char b1 = (char) B::orange; // { dg-error "protected" }
+  char b2 = (char) B::apple; // { dg-error "protected" }
+  char c1 = (char) C::orange; // { dg-error "private" }
+  char c2 = (char) C::apple; // { dg-error "private" }
+};
+
+int main() {
+    D<0> d;
+}
-- 
2.23.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-06-06 21:48 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-06 19:39 [PATCH] Fix behavior of using enum in dependent contexts [PR105787] Michael Colavita
2022-06-06 21:48 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).