aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-08-15 22:36:18 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2025-08-15 22:36:18 +0200
commit828c48f0680e209e96bcb76a232665ed047e92cc (patch)
treeed478563d1f1549f5c1a7fb001ae343eb0606031
parent4bed19cf6170541ff757ee1b21d9fec9eb0c6541 (diff)
downloadgcc-828c48f0680e209e96bcb76a232665ed047e92cc.zip
gcc-828c48f0680e209e96bcb76a232665ed047e92cc.tar.gz
gcc-828c48f0680e209e96bcb76a232665ed047e92cc.tar.bz2
c++: Implement C++20 P1766R1 - Mitigating minor modules maladies [PR121552]
The following patch attempts to implement the C++20 P1766R1 - Mitigating minor modules maladies paper. clang++ a few years ago introduced for the diagnostics required in the paper -Wnon-c-typedef-for-linkage pedwarn and the following patch does that too. The paper was accepted as a DR, the patch enables the warning also for C++98, dunno whether it might not be better to do it only for C++11 onwards. The paper is also about differences in default arguments of functions in different TUs and in modules, I think within the same TU we diagnose it correctly (maybe I should add some testcase) and perhaps try something with modules as well. But in different TUs it is IFNDR. 2025-08-15 Jakub Jelinek <jakub@redhat.com> PR c++/121552 gcc/ * doc/invoke.texi (-Wno-non-c-typedef-for-linkage): Document. gcc/c-family/ * c.opt (Wnon-c-typedef-for-linkage): New option. * c.opt.urls: Regenerate. gcc/cp/ * decl.cc: Implement C++20 P1766R1 - Mitigating minor modules maladies. (diagnose_non_c_class_typedef_for_linkage, maybe_diagnose_non_c_class_typedef_for_linkage): New functions. (name_unnamed_type): Call maybe_diagnose_non_c_class_typedef_for_linkage. gcc/testsuite/ * g++.dg/cpp2a/typedef1.C: New test. * g++.dg/debug/dwarf2/typedef5.C: Add -Wno-non-c-typedef-for-linkage to dg-options. * g++.dg/inherit/typeinfo1.C: Add -Wno-non-c-typedef-for-linkage to dg-additional-options. * g++.dg/parse/ctor2.C: Likewise. * g++.dg/ext/anon-struct9.C: Add -Wno-non-c-typedef-for-linkage to dg-options. * g++.dg/ext/visibility/anon11.C: Add -Wno-non-c-typedef-for-linkage to dg-additional-options. * g++.dg/lto/pr69137_0.C: Add -Wno-non-c-typedef-for-linkage to dg-lto-options. * g++.dg/other/anon8.C: Add -Wno-non-c-typedef-for-linkage to dg-additional-options. * g++.dg/template/pr84973.C: Likewise. * g++.dg/template/pr84973-2.C: Likewise. * g++.dg/template/pr84973-3.C: Likewise. * g++.dg/abi/anon2.C: Likewise. * g++.dg/abi/anon3.C: Likewise. * g++.old-deja/g++.oliva/linkage1.C: Likewise.
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/c-family/c.opt.urls3
-rw-r--r--gcc/cp/decl.cc85
-rw-r--r--gcc/doc/invoke.texi24
-rw-r--r--gcc/testsuite/g++.dg/abi/anon2.C1
-rw-r--r--gcc/testsuite/g++.dg/abi/anon3.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/typedef1.C94
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/typedef5.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/anon-struct9.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon11.C1
-rw-r--r--gcc/testsuite/g++.dg/inherit/typeinfo1.C2
-rw-r--r--gcc/testsuite/g++.dg/lto/pr69137_0.C2
-rw-r--r--gcc/testsuite/g++.dg/other/anon8.C1
-rw-r--r--gcc/testsuite/g++.dg/parse/ctor2.C1
-rw-r--r--gcc/testsuite/g++.dg/template/pr84973-2.C1
-rw-r--r--gcc/testsuite/g++.dg/template/pr84973-3.C1
-rw-r--r--gcc/testsuite/g++.dg/template/pr84973.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.oliva/linkage1.C1
18 files changed, 223 insertions, 4 deletions
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 0ee2c30..3f5e2f0 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1110,6 +1110,10 @@ Wnoexcept-type
C++ ObjC++ Warning Var(warn_noexcept_type) LangEnabledBy(C++ ObjC++,Wabi || Wc++17-compat)
Warn if C++17 noexcept function type will change the mangled name of a symbol.
+Wnon-c-typedef-for-linkage
+C++ ObjC++ Var(warn_non_c_typedef_for_linkage) Init(1) Warning
+Warn for non-C compatible unnamed classes with a typedef name for linkage purposes.
+
Wnon-template-friend
C++ ObjC++ Var(warn_nontemplate_friend) Init(1) Warning
Warn when non-templatized friend functions are declared within a template.
diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls
index 6eb1178..e09d51d 100644
--- a/gcc/c-family/c.opt.urls
+++ b/gcc/c-family/c.opt.urls
@@ -613,6 +613,9 @@ UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-noexcept)
Wnoexcept-type
UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-noexcept-type)
+Wnon-c-typedef-for-linkage
+UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-non-c-typedef-for-linkage)
+
Wnon-template-friend
UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-non-template-friend)
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 1d12bef..728b61c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -13022,6 +13022,88 @@ mark_inline_variable (tree decl, location_t loc)
}
+/* Diagnose -Wnon-c-typedef-for-linkage pedwarn. TYPE is the unnamed class
+ with a typedef name for linkage purposes with freshly updated TYPE_NAME,
+ ORIG is the anonymous TYPE_NAME before that change. */
+
+static bool
+diagnose_non_c_class_typedef_for_linkage (tree type, tree orig)
+{
+ gcc_rich_location richloc (DECL_SOURCE_LOCATION (orig));
+ tree name = DECL_NAME (TYPE_NAME (type));
+ richloc.add_fixit_insert_before (IDENTIFIER_POINTER (name));
+ return pedwarn (&richloc, OPT_Wnon_c_typedef_for_linkage,
+ "anonymous non-C-compatible type given name for linkage "
+ "purposes by %<typedef%> declaration");
+}
+
+/* Diagnose -Wnon-c-typedef-for-linkage violations on T. TYPE and ORIG
+ like for diagnose_non_c_class_typedef_for_linkage, T is initially equal
+ to TYPE but during recursion can be set to nested classes. */
+
+static bool
+maybe_diagnose_non_c_class_typedef_for_linkage (tree type, tree orig, tree t)
+{
+ if (!BINFO_BASE_BINFOS (TYPE_BINFO (t))->is_empty ())
+ {
+ auto_diagnostic_group d;
+ if (diagnose_non_c_class_typedef_for_linkage (type, orig))
+ inform (DECL_SOURCE_LOCATION (TYPE_NAME (t)),
+ "type is not C-compatible because it has a base class");
+ return true;
+ }
+ for (tree field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ switch (TREE_CODE (field))
+ {
+ case VAR_DECL:
+ /* static data members have been diagnosed already. */
+ continue;
+ case FIELD_DECL:
+ if (DECL_INITIAL (field))
+ {
+ auto_diagnostic_group d;
+ if (diagnose_non_c_class_typedef_for_linkage (type, orig))
+ inform (DECL_SOURCE_LOCATION (field),
+ "type is not C-compatible because %qD has default "
+ "member initializer", field);
+ return true;
+ }
+ continue;
+ case CONST_DECL:
+ continue;
+ case TYPE_DECL:
+ if (DECL_SELF_REFERENCE_P (field))
+ continue;
+ if (DECL_IMPLICIT_TYPEDEF_P (field))
+ {
+ if (TREE_CODE (TREE_TYPE (field)) == ENUMERAL_TYPE)
+ continue;
+ if (CLASS_TYPE_P (TREE_TYPE (field)))
+ {
+ tree tf = TREE_TYPE (field);
+ if (maybe_diagnose_non_c_class_typedef_for_linkage (type, orig,
+ tf))
+ return true;
+ continue;
+ }
+ }
+ /* FALLTHRU */
+ case FUNCTION_DECL:
+ case TEMPLATE_DECL:
+ {
+ auto_diagnostic_group d;
+ if (diagnose_non_c_class_typedef_for_linkage (type, orig))
+ inform (DECL_SOURCE_LOCATION (field),
+ "type is not C-compatible because it contains %qD "
+ "declaration", field);
+ return true;
+ }
+ default:
+ break;
+ }
+ return false;
+}
+
/* Assign a typedef-given name to a class or enumeration type declared
as anonymous at first. This was split out of grokdeclarator
because it is also used in libcc1. */
@@ -13047,6 +13129,9 @@ name_unnamed_type (tree type, tree decl)
/* Adjust linkage now that we aren't unnamed anymore. */
reset_type_linkage (type);
+ if (CLASS_TYPE_P (type) && warn_non_c_typedef_for_linkage)
+ maybe_diagnose_non_c_class_typedef_for_linkage (type, orig, type);
+
/* FIXME remangle member functions; member functions of a
type with external linkage have external linkage. */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 28466c4..4bec80a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -268,7 +268,7 @@ in the following sections.
-Wrange-loop-construct -Wredundant-move -Wredundant-tags
-Wreorder -Wregister -Wno-sfinae-incomplete
-Wstrict-null-sentinel -Wno-subobject-linkage -Wtemplates
--Wno-non-template-friend -Wold-style-cast
+-Wno-non-c-typedef-for-linkage -Wno-non-template-friend -Wold-style-cast
-Woverloaded-virtual -Wno-pmf-conversions -Wself-move -Wsign-promo
-Wsized-deallocation -Wsuggest-final-methods
-Wsuggest-final-types -Wsuggest-override -Wno-template-body
@@ -4494,6 +4494,28 @@ to @code{__null}. Although it is a null pointer constant rather than a
null pointer, it is guaranteed to be of the same size as a pointer.
But this use is not portable across different compilers.
+@opindex Wno-non-c-typedef-for-linkage
+@opindex Wnon-c-typedef-for-linkage
+@item -Wno-non-c-typedef-for-linkage @r{(C++ and Objective-C++ only)}
+Disable pedwarn for unnamed classes with a typedef name for linkage purposes
+containing C++ specific members, base classes, default member initializers
+or lambda expressions, including those on nested member classes.
+
+@smallexample
+typedef struct @{
+ int a; // non-static data members are ok
+ struct T @{ int b; @}; // member classes too
+ enum E @{ E1, E2, E3 @}; // member enumerations as well
+ int c = 42; // default member initializers are not ok
+ struct U : A @{ int c; @}; // classes with base classes are not ok
+ typedef int V; // typedef is not ok
+ using W = int; // using declaration is not ok
+ decltype([]()@{@}) x; // lambda expressions not ok
+@} S;
+@end smallexample
+
+In all these cases, the tag name S should be added after the struct keyword.
+
@opindex Wno-non-template-friend
@opindex Wnon-template-friend
@item -Wno-non-template-friend @r{(C++ and Objective-C++ only)}
diff --git a/gcc/testsuite/g++.dg/abi/anon2.C b/gcc/testsuite/g++.dg/abi/anon2.C
index 396edd3..dbf7b93 100644
--- a/gcc/testsuite/g++.dg/abi/anon2.C
+++ b/gcc/testsuite/g++.dg/abi/anon2.C
@@ -1,5 +1,6 @@
// PR c++/55877
// { dg-require-weak "" }
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
namespace N1 {
typedef struct {
diff --git a/gcc/testsuite/g++.dg/abi/anon3.C b/gcc/testsuite/g++.dg/abi/anon3.C
index 3e38024..9e41ac6 100644
--- a/gcc/testsuite/g++.dg/abi/anon3.C
+++ b/gcc/testsuite/g++.dg/abi/anon3.C
@@ -1,4 +1,5 @@
// { dg-require-weak "" }
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
typedef struct {
// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZN4Heya4blahEv" } }
diff --git a/gcc/testsuite/g++.dg/cpp2a/typedef1.C b/gcc/testsuite/g++.dg/cpp2a/typedef1.C
new file mode 100644
index 0000000..10a053f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/typedef1.C
@@ -0,0 +1,94 @@
+// C++20 P1766R1 - Mitigating minor modules maladies
+// { dg-do compile }
+
+typedef struct
+{
+ int a;
+ enum B { C1, C2, C3 };
+ struct T {
+ int b;
+#if __cplusplus >= 201103L
+ static_assert (sizeof (b) == sizeof (int), "");
+#endif
+ friend int freddy (int);
+ friend int garply (int x) { return x; }
+ };
+ union U { int c; long d; };
+ union { int e; long f; };
+ int g : 5;
+#if __cplusplus >= 201103L
+ static_assert (sizeof (a) == sizeof (int), "");
+#endif
+ friend int qux (int);
+ friend int corge (int x) { return x; }
+private:
+ int h;
+protected:
+ int i;
+public:
+ int j;
+} S;
+struct A {};
+typedef struct { // { dg-message "unnamed class defined here" }
+ static int a; // { dg-error "static data member '<unnamed struct>::a' in unnamed class" }
+} B;
+typedef struct : public A { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ int a;
+} C; // { dg-message "type is not C-compatible because it has a base class" }
+#if __cplusplus >= 201103L
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" "" { target c++11 } }
+ int b = 42; // { dg-message "type is not C-compatible because 'D::b' has default member initializer" "" { target c++11 } }
+} D;
+#endif
+struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ int foo (); } typedef E; // { dg-message "type is not C-compatible because it contains 'int E::foo\\\(\\\)' declaration" }
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ static int bar (); // { dg-message "type is not C-compatible because it contains 'static int F::bar\\\(\\\)' declaration" }
+} F;
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ typedef int T; // { dg-message "type is not C-compatible because it contains 'G::T' declaration" }
+} G;
+#if __cplusplus >= 201103L
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" "" { target c++11 } }
+ using T = int; // { dg-message "type is not C-compatible because it contains 'using H::T = int' declaration" "" { target c++11 } }
+} H;
+#endif
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ template <int N> struct B { int a; }; // { dg-message "type is not C-compatible because it contains 'template<int N> struct I::B' declaration" }
+} I;
+typedef struct { // { dg-message "unnamed class defined here" }
+ struct B { static int a; }; // { dg-error "static data member '<unnamed struct>::B::a' in unnamed class" }
+} J;
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ struct B : public A { int c; }; // { dg-message "type is not C-compatible because it has a base class" }
+} K;
+#if __cplusplus >= 201103L
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" "" { target c++11 } }
+ struct B { int d = 42; }; // { dg-message "type is not C-compatible because 'L::B::d' has default member initializer" "" { target c++11 } }
+} L;
+#endif
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ struct B { int foo (); }; // { dg-message "type is not C-compatible because it contains 'int M::B::foo\\\(\\\)' declaration" }
+} M;
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ struct B { static int bar (); }; // { dg-message "type is not C-compatible because it contains 'static int N::B::bar\\\(\\\)' declaration" }
+} N;
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ struct B { typedef int T; }; // { dg-message "type is not C-compatible because it contains 'O::B::T' declaration" }
+} O;
+#if __cplusplus >= 201103L
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" "" { target c++11 } }
+ struct B { using T = int; }; // { dg-message "type is not C-compatible because it contains 'using P::B::T = int' declaration" "" { target c++11 } }
+} P;
+#endif
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" }
+ struct B { template <int N> struct C { int a; }; }; // { dg-message "type is not C-compatible because it contains 'template<int N> struct Q::B::C' declaration" }
+} Q;
+#if __cplusplus >= 201103L
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" "" { target c++11 } }
+ decltype([](int i){ return i; }) a; // { dg-message "type is not C-compatible because it contains '\[^\n\r]*R::<lambda\\\(int\\\)>\[^\n\r]*' declaration" "" { target c++11 } }
+} R; // { dg-error "lambda-expression in unevaluated context only available with" "" { target { c++11 && c++17_down } } .-1 }
+typedef struct { // { dg-error "anonymous non-C-compatible type given name for linkage purposes by 'typedef' declaration" "" { target c++11 } }
+ struct B { decltype([](int i){ return i; }) a; }; // { dg-message "type is not C-compatible because it contains '\[^\n\r]*T::B::<lambda\\\(int\\\)>\[^\n\r]*' declaration" "" { target c++11 } }
+} T; // { dg-error "lambda-expression in unevaluated context only available with" "" { target { c++11 && c++17_down } } .-1 }
+#endif
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/typedef5.C b/gcc/testsuite/g++.dg/debug/dwarf2/typedef5.C
index ca06433..e317360 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/typedef5.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/typedef5.C
@@ -1,5 +1,5 @@
// Origin: PR debug/46101
-// { dg-options "-gdwarf-2" }
+// { dg-options "-gdwarf-2 -Wno-non-c-typedef-for-linkage" }
// { dg-do compile }
typedef struct
diff --git a/gcc/testsuite/g++.dg/ext/anon-struct9.C b/gcc/testsuite/g++.dg/ext/anon-struct9.C
index 5675942..915e149 100644
--- a/gcc/testsuite/g++.dg/ext/anon-struct9.C
+++ b/gcc/testsuite/g++.dg/ext/anon-struct9.C
@@ -1,5 +1,5 @@
// PR c++/96636
-// { dg-options "" }
+// { dg-options "-Wno-non-c-typedef-for-linkage" }
typedef class {
class a {};
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon11.C b/gcc/testsuite/g++.dg/ext/visibility/anon11.C
index dfb4f12..31ae323 100644
--- a/gcc/testsuite/g++.dg/ext/visibility/anon11.C
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon11.C
@@ -1,5 +1,6 @@
// PR c++/55877
// { dg-final { scan-assembler-not "\\.local" } }
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
typedef struct {
typedef enum { X, Y } A;
diff --git a/gcc/testsuite/g++.dg/inherit/typeinfo1.C b/gcc/testsuite/g++.dg/inherit/typeinfo1.C
index 794776e..819e37c 100644
--- a/gcc/testsuite/g++.dg/inherit/typeinfo1.C
+++ b/gcc/testsuite/g++.dg/inherit/typeinfo1.C
@@ -1,3 +1,5 @@
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
+
typedef struct {
virtual const char *blah() {
return "Heya::blah";
diff --git a/gcc/testsuite/g++.dg/lto/pr69137_0.C b/gcc/testsuite/g++.dg/lto/pr69137_0.C
index 7d5ed2d..cc74502 100644
--- a/gcc/testsuite/g++.dg/lto/pr69137_0.C
+++ b/gcc/testsuite/g++.dg/lto/pr69137_0.C
@@ -1,6 +1,6 @@
// { dg-lto-do link }
// { dg-require-effective-target lto_incremental }
-// { dg-lto-options { { -std=c++11 -g -flto } } }
+// { dg-lto-options { { -std=c++11 -g -flto -Wno-non-c-typedef-for-linkage } } }
// { dg-extra-ld-options "-r -nostdlib" }
typedef struct {
diff --git a/gcc/testsuite/g++.dg/other/anon8.C b/gcc/testsuite/g++.dg/other/anon8.C
index 1fdd4c1..a21a15a 100644
--- a/gcc/testsuite/g++.dg/other/anon8.C
+++ b/gcc/testsuite/g++.dg/other/anon8.C
@@ -1,4 +1,5 @@
// PR c++/68679
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
typedef struct {
struct {
diff --git a/gcc/testsuite/g++.dg/parse/ctor2.C b/gcc/testsuite/g++.dg/parse/ctor2.C
index 604fb2f..36f23e1 100644
--- a/gcc/testsuite/g++.dg/parse/ctor2.C
+++ b/gcc/testsuite/g++.dg/parse/ctor2.C
@@ -1,4 +1,5 @@
// PR c++/19244
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
typedef struct { void f(); } f;
void f::f() { }
diff --git a/gcc/testsuite/g++.dg/template/pr84973-2.C b/gcc/testsuite/g++.dg/template/pr84973-2.C
index 41c205a..6d5a6fe 100644
--- a/gcc/testsuite/g++.dg/template/pr84973-2.C
+++ b/gcc/testsuite/g++.dg/template/pr84973-2.C
@@ -1,4 +1,5 @@
// { dg-do compile }
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
template <int> void a() {
typedef struct {
diff --git a/gcc/testsuite/g++.dg/template/pr84973-3.C b/gcc/testsuite/g++.dg/template/pr84973-3.C
index eeac214..aafa170 100644
--- a/gcc/testsuite/g++.dg/template/pr84973-3.C
+++ b/gcc/testsuite/g++.dg/template/pr84973-3.C
@@ -1,4 +1,5 @@
// { dg-do link }
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
template <int> void a() {
typedef struct {
diff --git a/gcc/testsuite/g++.dg/template/pr84973.C b/gcc/testsuite/g++.dg/template/pr84973.C
index b3f7170..023dc7c 100644
--- a/gcc/testsuite/g++.dg/template/pr84973.C
+++ b/gcc/testsuite/g++.dg/template/pr84973.C
@@ -1,4 +1,5 @@
// { dg-do compile }
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
template <int> void a() {
typedef struct {
diff --git a/gcc/testsuite/g++.old-deja/g++.oliva/linkage1.C b/gcc/testsuite/g++.old-deja/g++.oliva/linkage1.C
index 6c4874b..b5a9f39 100644
--- a/gcc/testsuite/g++.old-deja/g++.oliva/linkage1.C
+++ b/gcc/testsuite/g++.old-deja/g++.oliva/linkage1.C
@@ -1,5 +1,6 @@
// { dg-do link }
// { dg-additional-sources " linkage1-main.cc" }
+// { dg-additional-options "-Wno-non-c-typedef-for-linkage" }
// Copyright 2002 Free Software Foundation