Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

P1811 says it's OK to redefine an imported global module entity in a
different translation unit.  The simplest (and fastest) way to handle that
is skipping the tokens of the redundant definition.  At some later point we
might want to optionally parse the new definition and compare it to the
imported one for ODR checking, but it isn't necessary for supporting
well-formed code.  This does allow wildly ill-formed code in the
redefinitions for the sake of speed, on the assumption that the the
definitions satisfy the ODR, probably because they are from the same source
code.

The core addition is redefinable_import_p; various places that have errored
about redefinition now discard the redefinition if it is true.

For convenience, I'm also adding -fno-module-include-translate to use to
force textual inclusion in compile-std1.C.

For redefinition of classes, I've gone back and forth between trying to
merge reachable non-exports in lookup_elaborated_type (as with the
__class_type_info hack removed by this patch) or waiting until
check_module_override.  I eventually settled on the latter approach for
consistency, but it does mean that we need to check for a previous
definition after lookup and again after push.

This patch wrongly allows multiple redefinitions after an import, as in
p1811-5.  I expect that fixing this should mostly mean clarifying what
DECL_MODULE_IMPORT_P means for global module entities, but additional
machinery would be needed for default arguments.  And it doesn't seem
necessary to fix in this patch, given that I'm deliberately allowing other
ill-formed redefinitions; if a shared header has multiple definitions, we
will diagnose it when building the imported module.

Assisted-by: GPT-5.6 Sol (p1811* testcases)

        P1811
        PR c++/99000

gcc/c-family/ChangeLog:

        * c.opt (fmodule-include-translate): New option.

gcc/cp/ChangeLog:

        * module.cc (maybe_translate_include): Check
        -fmodule-include-translate.
        * name-lookup.cc (redefinable_import_p): New.
        (pushdecl): Check DECL_IS_UNDECLARED_BUILTIN instead of hidden_p.
        (lookup_elaborated_type): Don't special-case cxxabi classes.
        (pushtag): Handle pushdecl finding a previous definition.
        * decl.cc (merge_default_template_args): Check redefinable_import_p.
        (duplicate_decls, grokfndecl, start_enum): Likewise.
        (redeclaration_error_message): Likewise.
        * parser.cc (cp_parser_skip_to_end_of_balanced_tokens): New.
        (cp_parser_skip_function_definition): New.
        (cp_parser_skip_base_clause): New.
        (cp_parser_enum_specifier): Skip redundant definition.
        (cp_parser_class_specifier): Likewise.
        (cp_parser_class_head): Likewise.
        (cp_parser_function_definition_from_specifiers_and_declarator):
        Likewise.
        * pt.cc (redeclare_class_template): Adjust.
        * cp-tree.h: Adjust.
        * name-lookup.h: Adjust.

gcc/testsuite/ChangeLog:

        * g++.dg/modules/compile-std1.C: Also test #include after import.
        * g++.dg/modules/hello-1_b.C: Likewise.
        * g++.dg/modules/default-arg-4_b.C: Remove xfails.
        * g++.dg/modules/pr122053_b.C: Likewise.
        * g++.dg/modules/gmf-3.h: New test.
        * g++.dg/modules/gmf-3_a.C: New test.
        * g++.dg/modules/gmf-3_b.C: New test.
        * g++.dg/modules/gmf-4_a.C: New test.
        * g++.dg/modules/gmf-4_b.C: New test.
---
 gcc/c-family/c.opt                            |   4 +
 gcc/cp/cp-tree.h                              |   2 +-
 gcc/cp/name-lookup.h                          |   1 +
 gcc/testsuite/g++.dg/modules/gmf-3.h          |   2 +
 gcc/testsuite/g++.dg/modules/p1811-1.h        |   9 ++
 gcc/testsuite/g++.dg/modules/p1811-2.h        |   5 +
 gcc/testsuite/g++.dg/modules/p1811-3.h        |   1 +
 gcc/testsuite/g++.dg/modules/p1811-5.h        |   1 +
 gcc/testsuite/g++.dg/modules/p1811-6.h        |   2 +
 gcc/cp/decl.cc                                | 116 ++++++++++++----
 gcc/cp/module.cc                              |  33 ++++-
 gcc/cp/name-lookup.cc                         |  28 ++--
 gcc/cp/parser.cc                              | 128 ++++++++++++++++--
 gcc/cp/pt.cc                                  |   2 +-
 gcc/testsuite/g++.dg/modules/compile-std1.C   |   9 +-
 .../g++.dg/modules/default-arg-4_b.C          |   9 +-
 gcc/testsuite/g++.dg/modules/gmf-3_a.C        |  14 ++
 gcc/testsuite/g++.dg/modules/gmf-3_b.C        |   7 +
 gcc/testsuite/g++.dg/modules/gmf-4_a.C        |  13 ++
 gcc/testsuite/g++.dg/modules/gmf-4_b.C        |  12 ++
 gcc/testsuite/g++.dg/modules/hello-1_b.C      |   4 +-
 gcc/testsuite/g++.dg/modules/p1811-1_a.C      |  11 ++
 gcc/testsuite/g++.dg/modules/p1811-1_b.C      |   8 ++
 gcc/testsuite/g++.dg/modules/p1811-2_a.C      |  11 ++
 gcc/testsuite/g++.dg/modules/p1811-2_b.C      |   9 ++
 gcc/testsuite/g++.dg/modules/p1811-3_a.C      |  11 ++
 gcc/testsuite/g++.dg/modules/p1811-3_b.C      |   8 ++
 gcc/testsuite/g++.dg/modules/p1811-4_a.C      |   8 ++
 gcc/testsuite/g++.dg/modules/p1811-4_b.C      |   7 +
 gcc/testsuite/g++.dg/modules/p1811-5_a.C      |  11 ++
 gcc/testsuite/g++.dg/modules/p1811-5_b.C      |   7 +
 gcc/testsuite/g++.dg/modules/p1811-6_a.C      |  12 ++
 gcc/testsuite/g++.dg/modules/p1811-6_b.C      |   9 ++
 gcc/testsuite/g++.dg/modules/pr122053_b.C     |   4 +-
 34 files changed, 445 insertions(+), 73 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/gmf-3.h
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-1.h
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-2.h
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-3.h
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-5.h
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-6.h
 create mode 100644 gcc/testsuite/g++.dg/modules/gmf-3_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/gmf-3_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/gmf-4_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/gmf-4_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-1_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-1_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-2_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-2_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-3_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-3_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-4_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-4_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-5_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-5_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-6_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/p1811-6_b.C

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 3ad96a5fe78..d5b973baa85 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -2153,6 +2153,10 @@ fmodule-implicit-inline
 C++ ObjC++ Var(flag_module_implicit_inline,0) Integer
 Member functions defined within their class are inline in module purview.
 
+fmodule-include-translate
+C++ ObjC++ Var(flag_module_include_translate) Init(1) Integer
+Implicitly translate #include to import when possible.
+
 fmodule-only
 C++ ObjC RejectNegative Var(flag_module_only) Integer
 Only emit Compiled Module Interface.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 947bf62ff98..7b461e4f528 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7605,7 +7605,7 @@ extern bool fns_correspond                        (tree, 
tree);
 extern int decls_match                         (tree, tree, bool = true);
 extern bool maybe_version_functions            (tree, tree);
 extern bool validate_constexpr_redeclaration   (tree, tree);
-extern bool merge_default_template_args                (tree, tree, bool);
+extern bool merge_default_template_args                (tree, tree, tree);
 extern void merge_decl_arguments               (tree, tree, bool, bool, bool);
 extern tree duplicate_decls                    (tree, tree,
                                                 bool hiding = false,
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 3737ae0ebac..48b4a363cf5 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -509,6 +509,7 @@ extern void finish_nonmember_using_decl (tree scope, tree 
name,
                                         bool typename_p = false);
 extern void finish_using_directive (tree target, tree attribs);
 void push_local_extern_decl_alias (tree decl);
+extern bool redefinable_import_p (tree decl);
 extern tree pushdecl (tree, bool hiding = false);
 extern tree pushdecl_outermost_localscope (tree);
 extern tree pushdecl_top_level (tree);
diff --git a/gcc/testsuite/g++.dg/modules/gmf-3.h 
b/gcc/testsuite/g++.dg/modules/gmf-3.h
new file mode 100644
index 00000000000..fc83c3d3fb5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-3.h
@@ -0,0 +1,2 @@
+struct A { };
+template <class T> struct B { };
diff --git a/gcc/testsuite/g++.dg/modules/p1811-1.h 
b/gcc/testsuite/g++.dg/modules/p1811-1.h
new file mode 100644
index 00000000000..f29b80a747d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-1.h
@@ -0,0 +1,9 @@
+inline int
+f () try
+{
+  return 1;
+}
+catch (...)
+{
+  return 2;
+}
diff --git a/gcc/testsuite/g++.dg/modules/p1811-2.h 
b/gcc/testsuite/g++.dg/modules/p1811-2.h
new file mode 100644
index 00000000000..433344d3b17
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-2.h
@@ -0,0 +1,5 @@
+struct C {
+  enum E : int;
+};
+
+enum C::E : int { e };
diff --git a/gcc/testsuite/g++.dg/modules/p1811-3.h 
b/gcc/testsuite/g++.dg/modules/p1811-3.h
new file mode 100644
index 00000000000..8ae11367b64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-3.h
@@ -0,0 +1 @@
+struct A { };
diff --git a/gcc/testsuite/g++.dg/modules/p1811-5.h 
b/gcc/testsuite/g++.dg/modules/p1811-5.h
new file mode 100644
index 00000000000..8ae11367b64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-5.h
@@ -0,0 +1 @@
+struct A { };
diff --git a/gcc/testsuite/g++.dg/modules/p1811-6.h 
b/gcc/testsuite/g++.dg/modules/p1811-6.h
new file mode 100644
index 00000000000..1b99bed4bab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-6.h
@@ -0,0 +1,2 @@
+template <class T> struct A { };
+template <class T> struct B { };
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index a14e9a4cb71..fe210c48cfe 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1754,12 +1754,13 @@ duplicate_function_template_decls (tree newdecl, tree 
olddecl)
 /* OLD_PARMS is the innermost set of template parameters for some template
    declaration, and NEW_PARMS is the corresponding set of template parameters
    for a redeclaration of that template.  Merge the default arguments within
-   these two sets of parameters.  CLASS_P is true iff the template in
-   question is a class template.  */
+   these two sets of parameters.  OLDDECL is the origin of OLD_PARMS.  */
 
 bool
-merge_default_template_args (tree new_parms, tree old_parms, bool class_p)
+merge_default_template_args (tree new_parms, tree old_parms, tree olddecl)
 {
+  bool class_p = DECL_IMPLICIT_TYPEDEF_P (STRIP_TEMPLATE (olddecl));
+
   gcc_checking_assert (TREE_VEC_LENGTH (new_parms)
                       == TREE_VEC_LENGTH (old_parms));
   for (int i = 0; i < TREE_VEC_LENGTH (new_parms); i++)
@@ -1770,7 +1771,9 @@ merge_default_template_args (tree new_parms, tree 
old_parms, bool class_p)
       tree& old_default = TREE_PURPOSE (TREE_VEC_ELT (old_parms, i));
       if (error_operand_p (new_parm) || error_operand_p (old_parm))
        return false;
-      if (new_default != NULL_TREE && old_default != NULL_TREE)
+      if (new_default != NULL_TREE && old_default != NULL_TREE
+         && !(redefinable_import_p (olddecl)
+              && cp_tree_equal (new_default, old_default)))
        {
          auto_diagnostic_group d;
          error ("redefinition of default argument for %q+#D", new_parm);
@@ -1942,6 +1945,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
       || TREE_TYPE (olddecl) == error_mark_node)
     return error_mark_node;
 
+  bool mod_redefinable = redefinable_import_p (olddecl);
+
   /* Check for redeclaration and other discrepancies.  */
   if (TREE_CODE (olddecl) == FUNCTION_DECL
       && DECL_IS_UNDECLARED_BUILTIN (olddecl))
@@ -2228,6 +2233,14 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
          if (TREE_CODE (oldres) == TYPE_DECL
              || TREE_CODE (newres) == TYPE_DECL)
            {
+             /* E.g. cstddef __byte_operand.  Alternatively we could find a
+                mergeable definition in lookup_elaborated_type, but we'd still
+                need to push it into scope in the current TU.  */
+             if (mod_redefinable
+                 && (DECL_IMPLICIT_TYPEDEF_P (oldres)
+                     == DECL_IMPLICIT_TYPEDEF_P (newres)))
+               goto return_old;
+
              auto_diagnostic_group d;
              error_at (newdecl_loc,
                        "conflicting declaration of template %q#D", newdecl);
@@ -2283,6 +2296,18 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
          else
            return NULL_TREE;
        }
+      else if (mod_redefinable
+              && TREE_CODE (newdecl) == TYPE_DECL
+              && (DECL_IMPLICIT_TYPEDEF_P (newdecl)
+                  == DECL_IMPLICIT_TYPEDEF_P (olddecl)))
+       /* Can also get here with e.g. typedef class {...} foo.  */
+       goto return_old;
+      else if (mod_redefinable
+              && TREE_CODE (newdecl) == VAR_DECL
+              && undeduced_auto_decl (newdecl)
+              && !undeduced_auto_decl (olddecl))
+       /* We don't have fndecl_declared_return_type for vars.  */
+       goto return_old;
       else
        {
          auto_diagnostic_group d;
@@ -2478,7 +2503,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
                     of the member function within the class template.  */
                  || CLASSTYPE_TEMPLATE_INFO (CP_DECL_CONTEXT (olddecl))))
            {
-             check_redeclaration_no_default_args (newdecl);
+             if (!mod_redefinable)
+               check_redeclaration_no_default_args (newdecl);
 
              if (DECL_TEMPLATE_INFO (olddecl)
                  && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (olddecl)))
@@ -2488,8 +2514,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
                    : INNERMOST_TEMPLATE_PARMS (current_template_parms);
                  tree old_parms
                    = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE 
(olddecl));
-                 merge_default_template_args (new_parms, old_parms,
-                                              /*class_p=*/false);
+                 merge_default_template_args (new_parms, old_parms, olddecl);
                }
            }
          else
@@ -2502,18 +2527,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
                   t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
                if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
                  {
-                   if (simple_cst_equal (TREE_PURPOSE (t1),
-                                         TREE_PURPOSE (t2)) == 1)
-                     {
-                       auto_diagnostic_group d;
-                       if (permerror (newdecl_loc,
-                                      "default argument given for parameter "
-                                      "%d of %q#D", i, newdecl))
-                         inform (olddecl_loc,
-                                 "previous specification in %q#D here",
-                                 olddecl);
-                     }
-                   else
+                   if (!cp_tree_equal (TREE_PURPOSE (t1),
+                                       TREE_PURPOSE (t2)))
                      {
                        auto_diagnostic_group d;
                        error_at (newdecl_loc,
@@ -2523,6 +2538,16 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
                                "previous specification in %q#D here",
                                olddecl);
                      }
+                   else if (!mod_redefinable)
+                     {
+                       auto_diagnostic_group d;
+                       if (permerror (newdecl_loc,
+                                      "default argument given for parameter "
+                                      "%d of %q#D", i, newdecl))
+                         inform (olddecl_loc,
+                                 "previous specification in %q#D here",
+                                 olddecl);
+                     }
                  }
 
              /* C++17 11.3.6/4: "If a friend declaration specifies a default
@@ -2653,6 +2678,17 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
          = DECL_OVERLOADED_OPERATOR_CODE_RAW (olddecl);
       new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
 
+      if (new_defines_function && mod_redefinable
+         && DECL_INITIAL (olddecl))
+       {
+         if (GNU_INLINE_P (STRIP_TEMPLATE (olddecl))
+             && !GNU_INLINE_P (STRIP_TEMPLATE (newdecl)))
+           /* Normal out-of-line redefinition of gnu_inline.  */
+           mod_redefinable = false;
+         else
+           new_defines_function = false;
+       }
+
       check_redecl_contract (newdecl, olddecl);
 
       /* Optionally warn about more than one declaration for the same
@@ -2684,7 +2720,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
       if (!(DECL_TEMPLATE_INSTANTIATION (olddecl)
            && DECL_TEMPLATE_SPECIALIZATION (newdecl)))
        {
-         if (DECL_DELETED_FN (newdecl))
+         if (DECL_DELETED_FN (newdecl)
+             && !(mod_redefinable
+                  && DECL_DELETED_FN (olddecl)))
            {
              auto_diagnostic_group d;
              if (pedwarn (newdecl_loc, 0, "deleted definition of %qD "
@@ -2748,7 +2786,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
            {
              /* Per C++11 8.3.6/4, default arguments cannot be added in
                 later declarations of a function template.  */
-             check_redeclaration_no_default_args (newdecl);
+             if (!mod_redefinable)
+               check_redeclaration_no_default_args (newdecl);
              /* C++17 11.3.6/4: "If a friend declaration specifies a default
                 argument expression, that declaration... shall be the only
                 declaration of the function or function template in the
@@ -2758,8 +2797,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
 
              tree new_parms = DECL_INNERMOST_TEMPLATE_PARMS (newdecl);
              tree old_parms = DECL_INNERMOST_TEMPLATE_PARMS (olddecl);
-             merge_default_template_args (new_parms, old_parms,
-                                          /*class_p=*/false);
+             merge_default_template_args (new_parms, old_parms, olddecl);
            }
          if (!DECL_UNIQUE_FRIEND_P (new_result))
            DECL_UNIQUE_FRIEND_P (old_result) = false;
@@ -2769,6 +2807,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
          if (GNU_INLINE_P (old_result) != GNU_INLINE_P (new_result)
              && DECL_INITIAL (new_result))
            {
+             mod_redefinable = false;
              if (DECL_INITIAL (old_result))
                DECL_UNINLINABLE (old_result) = 1;
              else
@@ -2798,7 +2837,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
       /* If the new declaration is a definition, update the file and
         line information on the declaration, and also make
         the old declaration the same definition.  */
-      if (DECL_INITIAL (new_result) != NULL_TREE)
+      if (DECL_INITIAL (new_result) != NULL_TREE
+         && !(DECL_INITIAL (old_result)
+              && mod_redefinable))
        {
          DECL_SOURCE_LOCATION (olddecl)
            = DECL_SOURCE_LOCATION (old_result)
@@ -2982,8 +3023,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
        }
 
       /* Merge the initialization information.  */
-      if (DECL_INITIAL (newdecl) == NULL_TREE
-         && DECL_INITIAL (olddecl) != NULL_TREE)
+      if (DECL_INITIAL (olddecl) != NULL_TREE
+         && (DECL_INITIAL (newdecl) == NULL_TREE
+             || mod_redefinable))
        {
          DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
          DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
@@ -3611,6 +3653,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
 static const char *
 redeclaration_error_message (tree newdecl, tree olddecl)
 {
+  if (redefinable_import_p (olddecl))
+    return NULL;
+
   if (TREE_CODE (newdecl) == TYPE_DECL)
     {
       /* Because C++ can put things into name space for free,
@@ -12871,7 +12916,9 @@ grokfndecl (tree ctype,
              error ("definition of implicitly-declared %qD", old_decl);
              return NULL_TREE;
            }
-         else if (DECL_DEFAULTED_FN (old_decl))
+         else if (DECL_DEFAULTED_FN (old_decl)
+                  && !(initialized == SD_DEFAULTED
+                       && redefinable_import_p (old_decl)))
            {
              auto_diagnostic_group d;
              error ("definition of explicitly-defaulted %q+D", decl);
@@ -18498,7 +18545,11 @@ lookup_and_check_tag (enum tag_types tag_code, tree 
name,
     {
       tree u = decl;
       decl = strip_using_decl (decl);
-      if (how == TAG_how::CURRENT_ONLY)
+      if (how == TAG_how::CURRENT_ONLY
+         && TREE_CODE (decl) == TYPE_DECL
+         && !(DECL_IMPLICIT_TYPEDEF_P (decl)
+              && CP_DECL_CONTEXT (decl) == CP_DECL_CONTEXT (u)
+              && redefinable_import_p (decl)))
        {
          auto_diagnostic_group _;
          error ("%qD conflicts with a previous declaration", name);
@@ -19095,6 +19146,9 @@ start_enum (tree name, tree enumtype, tree 
underlying_type,
          tree decl = TYPE_NAME (enumtype);
          if (!module_may_redeclare (decl))
            enumtype = error_mark_node;
+         else if (COMPLETE_TYPE_P (enumtype)
+                  && redefinable_import_p (decl))
+           return enumtype;
          else
            set_instantiating_module (decl);
        }
@@ -19163,6 +19217,12 @@ start_enum (tree name, tree enumtype, tree 
underlying_type,
 
          if (enumtype != error_mark_node)
            {
+             /* ??? We wouldn't need to repeat this if lookup_elaborated_type
+                found (and pushed) mergeable types.  */
+             if (COMPLETE_TYPE_P (enumtype)
+                 && redefinable_import_p (TYPE_NAME (enumtype)))
+               return enumtype;
+
              /* The enum is considered opaque until the opening '{' of the
                 enumerator list.  */
              SET_OPAQUE_ENUM_P (enumtype, true);
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 1e9e27a3ec2..6d7d650c638 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -22220,6 +22220,37 @@ set_originating_module (tree decl, bool friend_p 
ATTRIBUTE_UNUSED)
     DECL_MODULE_EXPORT_P (decl) = true;
 }
 
+/* True if it's OK to redefine DECL under P1811 because it is attached to the
+   global module and its definition was imported; [basic.def.odr]/12 "there can
+   be more than one definition...provided that each definition appears in a
+   different translation unit"
+
+   This does not depend on whether DECL was already defined, so that for
+   instance it can affect redefinition of default arguments.  This should only
+   be used when we notice a redefinition.  */
+
+bool
+redefinable_import_p (tree decl)
+{
+  if (!modules_p () || named_module_attach_p ())
+    return false;
+
+  decl = STRIP_TEMPLATE (decl);
+
+  if (TREE_CODE (decl) == TYPE_DECL
+      && !DECL_IMPLICIT_TYPEDEF_P (decl)
+      && !TYPE_DECL_FOR_LINKAGE_PURPOSES_P (decl))
+    /* Typedefs are always redefinable, use normal handling.  */
+    return false;
+
+  return (DECL_LANG_SPECIFIC (decl)
+         && DECL_MODULE_ENTITY_P (decl)
+         /* Use this instead of DECL_MODULE_IMPORT_P so we don't get confused
+            by partitions or set_instantiating_module.  */
+         /* FIXME this also means we allow multiple redefinitions.  */
+         && get_importing_module (decl, /*flexible*/true) > 0);
+}
+
 /* Checks whether DECL within a module unit has valid linkage for its kind.
    Must be called after visibility for DECL has been finalised.  */
 
@@ -23171,7 +23202,7 @@ static char *
 maybe_translate_include (cpp_reader *reader, line_maps *lmaps, location_t loc,
                         _cpp_file *file, bool angle, const char **alternate)
 {
-  if (!modules_p ())
+  if (!modules_p () || !flag_module_include_translate)
     {
       /* Turn off.  */
       cpp_get_callbacks (reader)->translate_include = NULL;
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 56d21bf50d6..e2fc89e6b32 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -4071,7 +4071,7 @@ pushdecl (tree decl, bool hiding)
          for (ovl_iterator iter (oldi); iter; ++iter)
            if (iter.using_p ())
              ; /* Ignore using decls here.  */
-           else if (iter.hidden_p ()
+           else if (DECL_IS_UNDECLARED_BUILTIN (*iter)
                     && TREE_CODE (*iter) == FUNCTION_DECL
                     && DECL_LANG_SPECIFIC (*iter)
                     && DECL_MODULE_IMPORT_P (*iter))
@@ -8643,24 +8643,8 @@ lookup_elaborated_type (tree name, TAG_how how)
                  return bind;
              }
 
-         if (!module_purview_p ())
-           {
-             /* We're in the global module, perhaps there's a tag
-                there?  */
-
-             /* FIXME: In general we should probably merge global module
-                classes in check_module_override rather than here, but for
-                GCC14 let's just fix lazy declarations of __class_type_info in
-                build_dynamic_cast_1.  */
-             if (current_namespace == abi_node)
-               {
-                 tree g = (BINDING_VECTOR_CLUSTER (*slot, 0)
-                           .slots[BINDING_SLOT_GLOBAL]);
-                 for (ovl_iterator iter (g); iter; ++iter)
-                   if (qualify_lookup (*iter, LOOK_want::TYPE))
-                     return *iter;
-               }
-           }
+         /* We'll find mergeable types in check_module_override when we try to
+            push a new one, no need to handle them specially here.  */
        }
     }
 
@@ -8825,6 +8809,9 @@ pushtag (tree name, tree type, TAG_how how)
        (type, how == TAG_how::HIDDEN_FRIEND, b);
       if (decl == error_mark_node)
        return decl;
+      if (TREE_TYPE (decl) != type)
+       /* Found an imported version of the same type.  */
+       return TREE_TYPE (decl);
 
       if (b->kind == sk_class)
        {
@@ -8854,6 +8841,9 @@ pushtag (tree name, tree type, TAG_how how)
            (decl, b, /*hiding=*/(how == TAG_how::HIDDEN_FRIEND));
          if (decl == error_mark_node)
            return decl;
+         if (TREE_TYPE (decl) != type)
+           /* Found an imported version of the same type.  */
+           return TREE_TYPE (decl);
 
          if (DECL_CONTEXT (decl) == std_node
              && init_list_identifier == DECL_NAME (TYPE_NAME (type))
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 9c54b2f22e2..48e3117a71e 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -4435,6 +4435,81 @@ cp_parser_consume_semicolon_at_end_of_statement 
(cp_parser *parser)
     }
 }
 
+/* Consume the entire balanced token sequence at point.  Returns true
+   if that was successful.  */
+
+static bool
+cp_parser_skip_to_end_of_balanced_tokens (cp_parser *parser)
+{
+  size_t n = cp_parser_skip_balanced_tokens (parser, 1);
+  if (n == 1)
+    return false;
+  while (--n)
+    cp_lexer_consume_token (parser->lexer);
+  return true;
+}
+
+/* Consume the entire function definition at point, including
+   function-try-block and mem-initializers.  */
+
+static void
+cp_parser_skip_function_definition (cp_parser *parser)
+{
+  bool fn_try = cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY);
+  if (fn_try)
+    cp_lexer_consume_token (parser->lexer);
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+    do
+      {
+       cp_lexer_consume_token (parser->lexer);
+       cp_parser_mem_initializer_id (parser);
+       cp_parser_skip_to_end_of_balanced_tokens (parser);
+      }
+    while (cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
+  cp_parser_skip_to_end_of_block_or_statement (parser);
+  if (fn_try)
+    while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH))
+      {
+       cp_lexer_consume_token (parser->lexer);
+       cp_parser_skip_to_end_of_balanced_tokens (parser);
+       cp_parser_skip_to_end_of_block_or_statement (parser);
+      }
+  /* Parse error if what we skipped didn't end with }.  */
+  if (cp_token *prev = cp_lexer_safe_previous_token (parser->lexer))
+    if (!prev || prev->type != CPP_CLOSE_BRACE)
+      cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+}
+
+/* Skip past any base clause to the open brace of the class definition.  */
+
+static void
+cp_parser_skip_base_clause (cp_parser *parser)
+{
+  while (true)
+    {
+      cp_token *t = cp_lexer_peek_token (parser->lexer);
+      switch (t->type)
+       {
+       case CPP_EOF:
+       case CPP_OPEN_BRACE:
+         goto done;
+       case CPP_OPEN_PAREN:
+       case CPP_OPEN_SPLICE:
+       case CPP_OPEN_SQUARE:
+         if (!cp_parser_skip_to_end_of_balanced_tokens (parser))
+           goto done;
+         break;
+       default:
+         cp_lexer_consume_token (parser->lexer);
+         break;
+       }
+    }
+ done:
+  /* Parse error if this didn't get us to the {.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+    cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
+}
+
 /* Skip tokens until we have consumed an entire block, or until we
    have consumed a non-nested `;'.  */
 
@@ -24121,6 +24196,23 @@ cp_parser_enum_specifier (cp_parser* parser)
     type = start_enum (identifier, type, underlying_type,
                       attributes, scoped_enum_p, &is_new_type);
 
+  if (type != error_mark_node && COMPLETE_TYPE_P (type)
+      && redefinable_import_p (TYPE_NAME (type)))
+    {
+      /* We already have an imported definition of this enum; skip over
+        the redefinition and push any non-scoped enumerators.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+       {
+         cp_parser_skip_to_end_of_block_or_statement (parser);
+         if (!SCOPED_ENUM_P (type))
+           for (tree l = TYPE_VALUES (type); l; l = TREE_CHAIN (l))
+             pushdecl (TREE_VALUE (l));
+       }
+      if (cp_parser_allow_gnu_extensions_p (parser))
+       cp_parser_gnu_attributes_opt (parser);
+      goto done;
+    }
+
   /* If the next token is not '{' it is an opaque-enum-specifier or an
      elaborated-type-specifier.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
@@ -24269,6 +24361,7 @@ cp_parser_enum_specifier (cp_parser* parser)
        finish_enum (type);
     }
 
+ done:
   if (nested_name_specifier)
     {
       if (CLASS_TYPE_P (nested_name_specifier))
@@ -29854,11 +29947,17 @@ cp_parser_class_specifier (cp_parser* parser)
                               &nested_name_specifier_p);
   /* If the class-head was a semantic disaster, skip the entire body
      of the class.  */
-  if (!type)
+  if (!type
+      /* Or if the class is already complete from an import, skip the
+        redefinition.  */
+      || (CLASS_TYPE_P (type) && COMPLETE_TYPE_P (type)))
     {
       cp_parser_skip_to_end_of_block_or_statement (parser);
       pop_deferring_access_checks ();
-      return error_mark_node;
+      /* Consume trailing attributes like below.  */
+      if (cp_parser_allow_gnu_extensions_p (parser))
+       cp_parser_gnu_attributes_opt (parser);
+      return type ? type : error_mark_node;
     }
 
   /* Look for the `{'.  */
@@ -30835,12 +30934,19 @@ cp_parser_class_head (cp_parser* parser,
   if (type != error_mark_node
       && (COMPLETE_TYPE_P (type) || TYPE_BEING_DEFINED (type)))
     {
-      auto_diagnostic_group d;
-      error_at (type_start_token->location, "redefinition of %q#T",
-               type);
-      inform (location_of (type), "previous definition of %q#T",
-             type);
-      type = NULL_TREE;
+      if (redefinable_import_p (TYPE_NAME (type)))
+       /* Redefinition of an imported type is OK under P1811;
+          cp_parser_class_specifier will skip the body.  */
+       cp_parser_skip_base_clause (parser);
+      else
+       {
+         auto_diagnostic_group d;
+         error_at (type_start_token->location, "redefinition of %q#T",
+                   type);
+         inform (location_of (type), "previous definition of %q#T",
+                 type);
+         type = NULL_TREE;
+       }
       goto done;
     }
   else if (type == error_mark_node)
@@ -36265,13 +36371,13 @@ 
cp_parser_function_definition_from_specifiers_and_declarator
   if (!success_p)
     {
       /* Skip the entire function.  */
-      cp_parser_skip_to_end_of_block_or_statement (parser);
+      cp_parser_skip_function_definition (parser);
       fn = error_mark_node;
     }
   else if (DECL_INITIAL (current_function_decl) != error_mark_node)
     {
-      /* Seen already, skip it.  An error message has already been output.  */
-      cp_parser_skip_to_end_of_block_or_statement (parser);
+      /* start_preparsed_function exited early, also skip parsing.  */
+      cp_parser_skip_function_definition (parser);
       fn = current_function_decl;
       current_function_decl = NULL_TREE;
       /* If this is a function from a class, pop the nested class.  */
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index fd60878ef2a..945554663a2 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6687,7 +6687,7 @@ redeclare_class_template (tree type, tree parms, tree 
cons)
        }
     }
 
-  if (!merge_default_template_args (parms, tmpl_parms, /*class_p=*/true))
+  if (!merge_default_template_args (parms, tmpl_parms, tmpl))
     return false;
 
   tree ci = get_constraints (tmpl);
diff --git a/gcc/testsuite/g++.dg/modules/compile-std1.C 
b/gcc/testsuite/g++.dg/modules/compile-std1.C
index 1de9ea78976..069ec32e858 100644
--- a/gcc/testsuite/g++.dg/modules/compile-std1.C
+++ b/gcc/testsuite/g++.dg/modules/compile-std1.C
@@ -1,5 +1,9 @@
+// Test both that --compile-std-module works and that P1811 redefinition works
+// for all of libstdc++.
+
 // { dg-additional-options "-fmodules --compile-std-module -g -O" }
-// { dg-additional-options "-flang-info-include-translate" }
+// { dg-additional-options "-fno-module-include-translate" }
+// { dg-additional-options "-fno-module-lazy" }
 // { dg-do compile { target c++20 } }
 // { dg-module-cmi std }
 // { dg-module-cmi std.compat }
@@ -7,8 +11,7 @@
 
 import std;
 import std.compat;
-#include <vector>              // { dg-message "translated to import" }
-import <bits/stdc++.h>;
+#include <bits/stdc++.h>
 
 void f()
 {
diff --git a/gcc/testsuite/g++.dg/modules/default-arg-4_b.C 
b/gcc/testsuite/g++.dg/modules/default-arg-4_b.C
index 5800ea20807..fcc07d31aaa 100644
--- a/gcc/testsuite/g++.dg/modules/default-arg-4_b.C
+++ b/gcc/testsuite/g++.dg/modules/default-arg-4_b.C
@@ -1,24 +1,23 @@
 // C++20 P1766R1 - Mitigating minor modules maladies
-// FIXME mark as run once we no longer xfail below.
-// { dg-module-do compile }
+// { dg-module-do run }
 // { dg-additional-options "-fmodules-ts" }
 
 import M;
 
 int
-foo (int i = 42)                       // { dg-bogus "default argument given 
for parameter 1 of 'int foo\\\(int\\\)'" "PR99000" { xfail *-*-* } }
+foo (int i = 42)                       // { dg-bogus "default argument given 
for parameter 1 of 'int foo\\\(int\\\)'" "PR99000" }
 {
   return i;
 }
 
-template <typename T, typename U = int>        // { dg-bogus "redefinition of 
default argument for 'class U'" "PR99000" { xfail *-*-* } }
+template <typename T, typename U = int>        // { dg-bogus "redefinition of 
default argument for 'class U'" "PR99000" }
 int
 bar ()
 {
   return sizeof (U);
 }
 
-template <typename T, int N = 42>      // { dg-bogus "redefinition of default 
argument for 'int N'" "PR99000" { xfail *-*-* } }
+template <typename T, int N = 42>      // { dg-bogus "redefinition of default 
argument for 'int N'" "PR99000" }
 int
 baz ()
 {
diff --git a/gcc/testsuite/g++.dg/modules/gmf-3_a.C 
b/gcc/testsuite/g++.dg/modules/gmf-3_a.C
new file mode 100644
index 00000000000..bb28144ea13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-3_a.C
@@ -0,0 +1,14 @@
+// Test that a forward declaration of a class (template) in the global module
+// combines with a reachable imported definition.
+
+// { dg-additional-options -fmodules-ts }
+
+module;
+#include "gmf-3.h"
+
+// { dg-module-cmi M1 }
+export module M1;
+
+// Keep A and B from being discarded per [module.global.frag]
+export A f1();
+export B<int> f2();
diff --git a/gcc/testsuite/g++.dg/modules/gmf-3_b.C 
b/gcc/testsuite/g++.dg/modules/gmf-3_b.C
new file mode 100644
index 00000000000..be5de6b3862
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-3_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+
+import M1;
+
+struct A a;
+template <class T> struct B;
+B<int> b;
diff --git a/gcc/testsuite/g++.dg/modules/gmf-4_a.C 
b/gcc/testsuite/g++.dg/modules/gmf-4_a.C
new file mode 100644
index 00000000000..c1e08da16ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-4_a.C
@@ -0,0 +1,13 @@
+// Test P1811 redefinition of class and class template
+
+// { dg-additional-options -fmodules-ts }
+
+module;
+#include "gmf-3.h"
+
+// { dg-module-cmi M1 }
+export module M1;
+
+// Keep A and B from being discarded per [module.global.frag]
+export A f1();
+export B<int> f2();
diff --git a/gcc/testsuite/g++.dg/modules/gmf-4_b.C 
b/gcc/testsuite/g++.dg/modules/gmf-4_b.C
new file mode 100644
index 00000000000..6fb01f83d94
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-4_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodules-ts }
+
+import M1;
+
+// Force lazy loading of A since gmf-3 does.
+auto x1 = f1();
+auto x2 = f2();
+
+#include "gmf-3.h"
+
+A a;
+B<int> b;
diff --git a/gcc/testsuite/g++.dg/modules/hello-1_b.C 
b/gcc/testsuite/g++.dg/modules/hello-1_b.C
index b7d78c476c6..624af70ed18 100644
--- a/gcc/testsuite/g++.dg/modules/hello-1_b.C
+++ b/gcc/testsuite/g++.dg/modules/hello-1_b.C
@@ -1,7 +1,7 @@
-// { dg-additional-options -fmodules-ts }
+// { dg-additional-options "-fmodules -fno-module-lazy" }
 
-#include <string_view>
 import hello;
+#include <string_view>
 int main (void)
 {
   greeter ("world");
diff --git a/gcc/testsuite/g++.dg/modules/p1811-1_a.C 
b/gcc/testsuite/g++.dg/modules/p1811-1_a.C
new file mode 100644
index 00000000000..608ea10a6db
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-1_a.C
@@ -0,0 +1,11 @@
+// Test P1811 redefinition of a function-try-block.
+
+// { dg-additional-options "-fmodules" }
+
+module;
+#include "p1811-1.h"
+
+// { dg-module-cmi M }
+export module M;
+
+export inline auto pf = &f;
diff --git a/gcc/testsuite/g++.dg/modules/p1811-1_b.C 
b/gcc/testsuite/g++.dg/modules/p1811-1_b.C
new file mode 100644
index 00000000000..46b18f19bb0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules" }
+
+import M;
+
+auto p = pf;
+#include "p1811-1.h"
+
+int after;
diff --git a/gcc/testsuite/g++.dg/modules/p1811-2_a.C 
b/gcc/testsuite/g++.dg/modules/p1811-2_a.C
new file mode 100644
index 00000000000..6b816cb47e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-2_a.C
@@ -0,0 +1,11 @@
+// Test P1811 redefinition of a qualified enum.
+
+// { dg-additional-options "-fmodules" }
+
+module;
+#include "p1811-2.h"
+
+// { dg-module-cmi M }
+export module M;
+
+export C make_c ();
diff --git a/gcc/testsuite/g++.dg/modules/p1811-2_b.C 
b/gcc/testsuite/g++.dg/modules/p1811-2_b.C
new file mode 100644
index 00000000000..5ea46095c35
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-2_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules" }
+
+import M;
+
+auto imported_c = make_c ();
+using C = decltype (imported_c);
+enum C::E : int { e };
+
+int after;
diff --git a/gcc/testsuite/g++.dg/modules/p1811-3_a.C 
b/gcc/testsuite/g++.dg/modules/p1811-3_a.C
new file mode 100644
index 00000000000..7444dd13123
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-3_a.C
@@ -0,0 +1,11 @@
+// Test recovery from an incomplete redundant class definition.
+
+// { dg-additional-options "-fmodules" }
+
+module;
+#include "p1811-3.h"
+
+// { dg-module-cmi M }
+export module M;
+
+export A make_a ();
diff --git a/gcc/testsuite/g++.dg/modules/p1811-3_b.C 
b/gcc/testsuite/g++.dg/modules/p1811-3_b.C
new file mode 100644
index 00000000000..5985dedc5aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-3_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules" }
+// { dg-timeout-factor 0.05 }
+
+import M;
+
+auto imported_a = make_a ();
+struct A : ( // { dg-error "expected" }
+// { dg-prune-output "at end of input" }
diff --git a/gcc/testsuite/g++.dg/modules/p1811-4_a.C 
b/gcc/testsuite/g++.dg/modules/p1811-4_a.C
new file mode 100644
index 00000000000..10c2a6ffdd4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-4_a.C
@@ -0,0 +1,8 @@
+// Definitions attached to a named module cannot be repeated.
+
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi P:a }
+
+export module P:a;
+
+export struct A { };
diff --git a/gcc/testsuite/g++.dg/modules/p1811-4_b.C 
b/gcc/testsuite/g++.dg/modules/p1811-4_b.C
new file mode 100644
index 00000000000..5d31bb1883b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-4_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi !P:b }
+
+module P:b;
+import :a;
+
+struct A { }; // { dg-error "redefinition" }
diff --git a/gcc/testsuite/g++.dg/modules/p1811-5_a.C 
b/gcc/testsuite/g++.dg/modules/p1811-5_a.C
new file mode 100644
index 00000000000..1b87579e8dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-5_a.C
@@ -0,0 +1,11 @@
+// Test that P1811 does not allow multiple definitions in one TU.
+
+// { dg-additional-options "-fmodules" }
+
+module;
+#include "p1811-5.h"
+
+// { dg-module-cmi M }
+export module M;
+
+export A make_a ();
diff --git a/gcc/testsuite/g++.dg/modules/p1811-5_b.C 
b/gcc/testsuite/g++.dg/modules/p1811-5_b.C
new file mode 100644
index 00000000000..63c86631c7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-5_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules" }
+
+import M;
+
+auto imported_a = make_a ();
+struct A { };
+struct A { };                // { dg-error "redefinition" "" { xfail *-*-* } }
diff --git a/gcc/testsuite/g++.dg/modules/p1811-6_a.C 
b/gcc/testsuite/g++.dg/modules/p1811-6_a.C
new file mode 100644
index 00000000000..83180c3bcd6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-6_a.C
@@ -0,0 +1,12 @@
+// Test that P1811 does not allow changing the kind of a template.
+
+// { dg-additional-options "-fmodules" }
+
+module;
+#include "p1811-6.h"
+
+// { dg-module-cmi M }
+export module M;
+
+export A<int> make_a ();
+export B<int> make_b ();
diff --git a/gcc/testsuite/g++.dg/modules/p1811-6_b.C 
b/gcc/testsuite/g++.dg/modules/p1811-6_b.C
new file mode 100644
index 00000000000..a815da5c9b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p1811-6_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules" }
+
+import M;
+
+auto imported_a = make_a ();
+auto imported_b = make_b ();
+
+template <class T> using A = T; // { dg-error "conflicting declaration" }
+template <class T> int B; // { dg-error "conflicting declaration" }
diff --git a/gcc/testsuite/g++.dg/modules/pr122053_b.C 
b/gcc/testsuite/g++.dg/modules/pr122053_b.C
index a7084b74040..e7038fa0723 100644
--- a/gcc/testsuite/g++.dg/modules/pr122053_b.C
+++ b/gcc/testsuite/g++.dg/modules/pr122053_b.C
@@ -3,7 +3,7 @@
 // Test we don't ICE when redefining a type coming from an import.
 
 import M;
-struct mytime {  // { dg-bogus "conflicting" "PR99000" { xfail *-*-* } }
+struct mytime {  // { dg-bogus "conflicting" "PR99000" }
   long a, b;
 };
-mytime m = foo();  // { dg-bogus "" "PR99000" { xfail *-*-* } }
+mytime m = foo();  // { dg-bogus "" "PR99000" }
-- 
2.55.0

Reply via email to