diff options
author | Jakub Jelinek <jakub@redhat.com> | 2025-08-15 22:36:18 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2025-08-15 22:36:18 +0200 |
commit | 828c48f0680e209e96bcb76a232665ed047e92cc (patch) | |
tree | ed478563d1f1549f5c1a7fb001ae343eb0606031 | |
parent | 4bed19cf6170541ff757ee1b21d9fec9eb0c6541 (diff) | |
download | gcc-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.opt | 4 | ||||
-rw-r--r-- | gcc/c-family/c.opt.urls | 3 | ||||
-rw-r--r-- | gcc/cp/decl.cc | 85 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 24 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/anon2.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/anon3.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/typedef1.C | 94 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/debug/dwarf2/typedef5.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/anon-struct9.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/visibility/anon11.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/inherit/typeinfo1.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lto/pr69137_0.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/anon8.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/ctor2.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/pr84973-2.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/pr84973-3.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/pr84973.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.oliva/linkage1.C | 1 |
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 |