]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: check mismatching exports for class tags [PR98885]
authorNathaniel Shead <nathanieloshead@gmail.com>
Sun, 12 Nov 2023 11:49:45 +0000 (22:49 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Fri, 24 Nov 2023 01:30:07 +0000 (12:30 +1100)
Checks for exporting a declaration that was previously declared as not
exported is implemented in 'duplicate_decls', but this doesn't handle
declarations of classes. This patch adds these checks and slightly
adjusts the associated error messages for clarity.

PR c++/98885

gcc/cp/ChangeLog:

* decl.cc (duplicate_decls): Adjust error message.
(xref_tag): Adjust error message. Check exporting decl that is
already declared as non-exporting.

gcc/testsuite/ChangeLog:

* g++.dg/modules/export-1.C: Adjust error messages. Remove
xfails for working case. Add new test case.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
gcc/cp/decl.cc
gcc/testsuite/g++.dg/modules/export-1.C

index e7701afdefd826d08c5d5118d65277a6cc4c8cc8..16b04ebe0f897240d0491565362109346a42475e 100644 (file)
@@ -2236,8 +2236,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
          if (DECL_MODULE_EXPORT_P (STRIP_TEMPLATE (newdecl))
              && !DECL_MODULE_EXPORT_P (not_tmpl))
            {
-             error ("conflicting exporting declaration %qD", newdecl);
-             inform (olddecl_loc, "previous declaration %q#D here", olddecl);
+             auto_diagnostic_group d;
+             error ("conflicting exporting for declaration %qD", newdecl);
+             inform (olddecl_loc,
+                     "previously declared here without exporting");
            }
        }
       else if (DECL_MODULE_EXPORT_P (newdecl))
@@ -16261,11 +16263,24 @@ xref_tag (enum tag_types tag_code, tree name,
          tree decl = TYPE_NAME (t);
          if (!module_may_redeclare (decl))
            {
+             auto_diagnostic_group d;
              error ("cannot declare %qD in a different module", decl);
-             inform (DECL_SOURCE_LOCATION (decl), "declared here");
+             inform (DECL_SOURCE_LOCATION (decl), "previously declared here");
              return error_mark_node;
            }
 
+         tree not_tmpl = STRIP_TEMPLATE (decl);
+         if (DECL_LANG_SPECIFIC (not_tmpl)
+             && DECL_MODULE_ATTACH_P (not_tmpl)
+             && !DECL_MODULE_EXPORT_P (not_tmpl)
+             && module_exporting_p ())
+           {
+             auto_diagnostic_group d;
+             error ("conflicting exporting for declaration %qD", decl);
+             inform (DECL_SOURCE_LOCATION (decl),
+                     "previously declared here without exporting");
+           }
+
          tree maybe_tmpl = decl;
          if (CLASS_TYPE_P (t) && CLASSTYPE_IS_TEMPLATE (t))
            maybe_tmpl = CLASSTYPE_TI_TEMPLATE (t);
index 8ca696ebee0b95e3fd8b07a253428a505a71d9ff..3f93814d270bd29106a253afd76bcd60129e89f2 100644 (file)
@@ -4,19 +4,21 @@ export module frob;
 // { dg-module-cmi !frob }
 
 int x ();
-export int x (); // { dg-error "conflicting exporting declaration" }
+export int x (); // { dg-error "conflicting exporting for declaration" }
 
 int y;
-export extern int y; // { dg-error "conflicting exporting declaration" }
+export extern int y; // { dg-error "conflicting exporting for declaration" }
 
 typedef int z;
-export typedef int z; // { dg-error "conflicting exporting declaration" }
+export typedef int z; // { dg-error "conflicting exporting for declaration" }
 
 template <typename T> int f (T);
-export template <typename T> int f (T); // { dg-error "conflicting exporting declaration" }
+export template <typename T> int f (T); // { dg-error "conflicting exporting for declaration" }
 
-// doesn't go via duplicate_decls so we miss this for now
 class A;
-export class A; // { dg-error "conflicting exporting declaration" "" { xfail *-*-* } }
+export class A; // { dg-error "conflicting exporting for declaration" }
 
-// { dg-warning  "due to errors" "" { target *-*-* } 0 }
+template <typename T> struct B;
+export template <typename T> struct B {};  // { dg-error "conflicting exporting for declaration" }
+
+// { dg-warning "due to errors" "" { target *-*-* } 0 }