]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix error recovery when redeclaring enum in different module [PR99573]
authorNathaniel Shead <nathanieloshead@gmail.com>
Mon, 12 Feb 2024 01:40:15 +0000 (12:40 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Wed, 14 Feb 2024 11:06:16 +0000 (22:06 +1100)
This ensures that with modules enabled, redeclaring an enum in the wrong
module or with the wrong underlying type no longer ICEs.

The patch also rearranges the order of the checks a little because I
think it's probably more important to note that you can't redeclare the
enum all before complaining about mismatched underlying types etc.

As a drive by this patch also adds some missing diagnostic groups, and
rewords the module redeclaration error message to more closely match the
wording used in other places this check is done.

PR c++/99573

gcc/cp/ChangeLog:

* decl.cc (start_enum): Reorder check for redeclaring in module.
Add missing auto_diagnostic_groups.

gcc/testsuite/ChangeLog:

* g++.dg/modules/enum-12.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/decl.cc
gcc/testsuite/g++.dg/modules/enum-12.C [new file with mode: 0644]

index 3e41fd4fa313ce55dd8381e42f97e249cf23ae51..d19d09adde43b713b6c4149f0c3c4ed901f9d3d1 100644 (file)
@@ -16955,8 +16955,26 @@ start_enum (tree name, tree enumtype, tree underlying_type,
      to instantiation time is the comparison of underlying types.  */
   if (enumtype && TREE_CODE (enumtype) == ENUMERAL_TYPE)
     {
-      if (scoped_enum_p != SCOPED_ENUM_P (enumtype))
+      /* Attempt to set the declaring module.  */
+      if (modules_p ())
        {
+         tree decl = TYPE_NAME (enumtype);
+         if (!module_may_redeclare (decl))
+           {
+             auto_diagnostic_group d;
+             error ("cannot declare %qD in different module", decl);
+             inform (DECL_SOURCE_LOCATION (decl), "previously declared here");
+             enumtype = error_mark_node;
+           }
+         else
+           set_instantiating_module (decl);
+       }
+
+      if (enumtype == error_mark_node)
+       ;
+      else if (scoped_enum_p != SCOPED_ENUM_P (enumtype))
+       {
+         auto_diagnostic_group d;
          error_at (input_location, "scoped/unscoped mismatch "
                    "in enum %q#T", enumtype);
          inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)),
@@ -16965,6 +16983,7 @@ start_enum (tree name, tree enumtype, tree underlying_type,
        }
       else if (ENUM_FIXED_UNDERLYING_TYPE_P (enumtype) != !! underlying_type)
        {
+         auto_diagnostic_group d;
          error_at (input_location, "underlying type mismatch "
                    "in enum %q#T", enumtype);
          inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)),
@@ -16975,25 +16994,13 @@ start_enum (tree name, tree enumtype, tree underlying_type,
               && !same_type_p (underlying_type,
                                ENUM_UNDERLYING_TYPE (enumtype)))
        {
+         auto_diagnostic_group d;
          error_at (input_location, "different underlying type "
                    "in enum %q#T", enumtype);
          inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)),
                  "previous definition here");
          underlying_type = NULL_TREE;
        }
-
-      if (modules_p ())
-       {
-         if (!module_may_redeclare (TYPE_NAME (enumtype)))
-           {
-             error ("cannot define %qD in different module",
-                    TYPE_NAME (enumtype));
-             inform (DECL_SOURCE_LOCATION (TYPE_NAME (enumtype)),
-                     "declared here");
-             enumtype = error_mark_node;
-           }
-         set_instantiating_module (TYPE_NAME (enumtype));
-       }
     }
 
   if (!enumtype || TREE_CODE (enumtype) != ENUMERAL_TYPE
diff --git a/gcc/testsuite/g++.dg/modules/enum-12.C b/gcc/testsuite/g++.dg/modules/enum-12.C
new file mode 100644 (file)
index 0000000..57eeb85
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/99573
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi !foo }
+
+export module foo;
+namespace std {
+  enum class align_val_t : decltype(sizeof(int)) {};  // { dg-error "different module" }
+}
+
+// { dg-prune-output "not writing module" }