PR c++/93804 - exempt extern C headers from -Wredundant-tags
gcc/cp/ChangeLog: PR c++/93804 * parser.c (cp_parser_check_class_key): Avoid issuing -Wredundant-tags in shared C/C++ code in headers. gcc/testsuite/ChangeLog: PR c++/93804 * g++.dg/warn/Wredundant-tags-4.C: New test. * g++.dg/warn/Wredundant-tags-5.C: New test. * g++.dg/warn/Wredundant-tags-5.h: New test.
This commit is contained in:
parent
004f2c07b6
commit
b73547e40e
6 changed files with 395 additions and 11 deletions
|
@ -1,3 +1,9 @@
|
|||
2020-02-24 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/93804
|
||||
* parser.c (cp_parser_check_class_key): Avoid issuing -Wredundant-tags
|
||||
in shared C/C++ code in headers.
|
||||
|
||||
2020-02-24 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/93869 - ICE with -Wmismatched-tags.
|
||||
|
|
|
@ -30837,15 +30837,31 @@ cp_parser_maybe_warn_enum_key (cp_parser *parser, location_t key_loc,
|
|||
/* The enum-key is redundant for uses of the TYPE that are not
|
||||
declarations and for which name lookup returns just the type
|
||||
itself. */
|
||||
if (decl == type_decl)
|
||||
if (decl != type_decl)
|
||||
return;
|
||||
|
||||
if (scoped_key != RID_CLASS
|
||||
&& scoped_key != RID_STRUCT
|
||||
&& current_lang_name != lang_name_cplusplus
|
||||
&& current_namespace == global_namespace)
|
||||
{
|
||||
gcc_rich_location richloc (key_loc);
|
||||
richloc.add_fixit_remove (key_loc);
|
||||
warning_at (&richloc, OPT_Wredundant_tags,
|
||||
"redundant enum-key %<enum%s%> in reference to %q#T",
|
||||
(scoped_key == RID_CLASS ? " class"
|
||||
: scoped_key == RID_STRUCT ? " struct" : ""), type);
|
||||
/* Avoid issuing the diagnostic for apparently redundant (unscoped)
|
||||
enum tag in shared C/C++ code in files (such as headers) included
|
||||
in the main source file. */
|
||||
const line_map_ordinary *map = NULL;
|
||||
linemap_resolve_location (line_table, key_loc,
|
||||
LRK_MACRO_DEFINITION_LOCATION,
|
||||
&map);
|
||||
if (!MAIN_FILE_P (map))
|
||||
return;
|
||||
}
|
||||
|
||||
gcc_rich_location richloc (key_loc);
|
||||
richloc.add_fixit_remove (key_loc);
|
||||
warning_at (&richloc, OPT_Wredundant_tags,
|
||||
"redundant enum-key %<enum%s%> in reference to %q#T",
|
||||
(scoped_key == RID_CLASS ? " class"
|
||||
: scoped_key == RID_STRUCT ? " struct" : ""), type);
|
||||
}
|
||||
|
||||
/* Describes the set of declarations of a struct, class, or class template
|
||||
|
@ -31005,6 +31021,13 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc,
|
|||
&& class_key != union_type)
|
||||
return;
|
||||
|
||||
/* Only consider the true class-keys below and ignore typename_type,
|
||||
etc. that are not C++ class-keys. */
|
||||
if (class_key != class_type
|
||||
&& class_key != record_type
|
||||
&& class_key != union_type)
|
||||
return;
|
||||
|
||||
tree type_decl = TYPE_MAIN_DECL (type);
|
||||
tree name = DECL_NAME (type_decl);
|
||||
/* Look up the NAME to see if it unambiguously refers to the TYPE
|
||||
|
@ -31017,15 +31040,32 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc,
|
|||
neither definitions of it nor declarations, and for which name
|
||||
lookup returns just the type itself. */
|
||||
bool key_redundant = !def_p && !decl_p && decl == type_decl;
|
||||
|
||||
if (key_redundant
|
||||
&& class_key != class_type
|
||||
&& current_lang_name != lang_name_cplusplus
|
||||
&& current_namespace == global_namespace)
|
||||
{
|
||||
/* Avoid issuing the diagnostic for apparently redundant struct
|
||||
and union class-keys in shared C/C++ code in files (such as
|
||||
headers) included in the main source file. */
|
||||
const line_map_ordinary *map = NULL;
|
||||
linemap_resolve_location (line_table, key_loc,
|
||||
LRK_MACRO_DEFINITION_LOCATION,
|
||||
&map);
|
||||
if (!MAIN_FILE_P (map))
|
||||
key_redundant = false;
|
||||
}
|
||||
|
||||
if (key_redundant)
|
||||
{
|
||||
gcc_rich_location richloc (key_loc);
|
||||
richloc.add_fixit_remove (key_loc);
|
||||
warning_at (&richloc, OPT_Wredundant_tags,
|
||||
"redundant class-key %qs in reference to %q#T",
|
||||
class_key == union_type ? "union"
|
||||
: class_key == record_type ? "struct" : "class",
|
||||
type);
|
||||
"redundant class-key %qs in reference to %q#T",
|
||||
class_key == union_type ? "union"
|
||||
: class_key == record_type ? "struct" : "class",
|
||||
type);
|
||||
}
|
||||
|
||||
if (seen_as_union || !warn_mismatched_tags)
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2020-02-24 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/93804
|
||||
* g++.dg/warn/Wredundant-tags-4.C: New test.
|
||||
* g++.dg/warn/Wredundant-tags-5.C: New test.
|
||||
* g++.dg/warn/Wredundant-tags-5.h: New test.
|
||||
|
||||
2020-02-24 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* gcc.dg/analyzer/analyzer-verbosity-2a.c: New test.
|
||||
|
|
142
gcc/testsuite/g++.dg/warn/Wredundant-tags-4.C
Normal file
142
gcc/testsuite/g++.dg/warn/Wredundant-tags-4.C
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* PR c++/93804 - exempt extern "C" headers from -Wredundant-tags
|
||||
Verify that -Wredundant-tags is not issued for redundant class-key
|
||||
in extern "C" references in a header file.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-Wredundant-tags -ftrack-macro-expansion=0" } */
|
||||
|
||||
# 1 "Wredundant-tags-4.C"
|
||||
# 1 "Wredundant-tags-4.h" 1
|
||||
# line 10
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
# define enum_struct enum struct
|
||||
#else
|
||||
# define enum_struct class
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
class C1 { };
|
||||
enum E1 { };
|
||||
enum_struct ES1 { };
|
||||
struct S1 { enum E1 e1; };
|
||||
union U1 { enum E1 e1; struct S1 s1; };
|
||||
|
||||
/* The warning should be issued for the class-key class even in
|
||||
an extern "C" block. */
|
||||
void f0 (class C1); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
void f1 (enum E1); // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
|
||||
/* Ditto for a scoped enum. */
|
||||
void f2 (enum_struct ES1); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
// { dg-warning "must not use the 'struct' keyword" "enum struct" { target { c++11 } } .-1 }
|
||||
|
||||
void f3 (struct S1); // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
void f4 (union U1); // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
|
||||
inline int
|
||||
finline1 (class C1) // { dg-warning "\\\[-Wredundant-tags" }
|
||||
{ return sizeof (class C1); } // { dg-warning "\\\[-Wredundant-tags" }
|
||||
|
||||
inline int
|
||||
finline2 (enum E1) // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
{ return sizeof (enum E1); } // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
|
||||
inline int
|
||||
finline3 (enum_struct ES1) // { dg-warning "\\\[-Wredundant-tags" }
|
||||
{ return sizeof (ES1); }
|
||||
|
||||
inline int
|
||||
finline4 (struct S1) // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
{ return sizeof (struct S1); }
|
||||
|
||||
inline int
|
||||
finline5 (union U1) // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
{ return sizeof (union U1); }
|
||||
|
||||
extern class C1 c1; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern enum E1 e1; // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
extern enum_struct ES1 es1; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern struct S1 s1; // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
extern union U1 u1; // { dg-bogus "\\\[-Wredundant-tags" }
|
||||
|
||||
namespace N1 {
|
||||
/* Verify that -Wredundant-tags is issued in a namespace enclosed
|
||||
in an extern "C" block. (Such code cannot be shared with C.) */
|
||||
extern class C1 n1c1; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern enum E1 n1e1; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern enum_struct ES1 n1es1; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern struct S1 n1s1; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern union U1 n1u1; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
|
||||
extern "C++" {
|
||||
|
||||
class C2 { };
|
||||
enum E2 { };
|
||||
enum_struct ES2 { };
|
||||
struct S2 {
|
||||
enum E2 e21; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
E2 e22;
|
||||
enum_struct ES2 es21; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
ES2 es22;
|
||||
};
|
||||
union U2 { };
|
||||
|
||||
void f5 (class C2); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
void f6 (enum E2); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
void f7 (enum_struct ES2); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
void f8 (struct S2); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
void f9 (union U2); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
|
||||
extern class C2 c2; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern enum E2 e2; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern enum_struct ES2 es2; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern struct S2 s2; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern union U2 u2; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
} // extern "C++"
|
||||
|
||||
|
||||
namespace N {
|
||||
|
||||
class C3 { };
|
||||
enum E3 { };
|
||||
enum_struct ES3 { };
|
||||
struct S3 { };
|
||||
union U3 { };
|
||||
|
||||
void f10 (class C3); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
void f11 (enum E3); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
void f12 (enum_struct ES3); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
void f13 (struct S3); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
void f14 (union U3); // { dg-warning "\\\[-Wredundant-tags" }
|
||||
|
||||
extern class C3 c3; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern enum E3 e3; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern enum_struct ES3 es3; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern struct S3 s3; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern union U3 u3; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* Verify that -Wredundant-tags is issued in an extern "C" block
|
||||
enclosed within a namespace. (Such code cannot be shared with
|
||||
C.) */
|
||||
class C4 { };
|
||||
enum E4 { };
|
||||
enum_struct ES4 { };
|
||||
struct S4 { };
|
||||
union U4 { };
|
||||
|
||||
extern class C4 c4; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern enum E4 e4; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern enum_struct ES4 es4; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern struct S4 s4; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
extern union U4 u4; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
}
|
||||
|
||||
} // namespace N
|
||||
|
||||
// { dg-prune-output "must not use the 'struct' keyword" }
|
109
gcc/testsuite/g++.dg/warn/Wredundant-tags-5.C
Normal file
109
gcc/testsuite/g++.dg/warn/Wredundant-tags-5.C
Normal file
|
@ -0,0 +1,109 @@
|
|||
// PR c++/93804 - exempt extern "C" headers from -Wredundant-tags
|
||||
// Verify that -Wredundant-tags is issued even for redundant class-key
|
||||
// in references in the main source file to extern "C" classes defined
|
||||
// in headers.
|
||||
// { dg-do compile }
|
||||
// { dg-options "-Wredundant-tags -ftrack-macro-expansion=0" }
|
||||
|
||||
#include "Wredundant-tags-5.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
class C1 // { dg-warning "\\\[-Wredundant-tags" }
|
||||
fc1 (C1)
|
||||
{
|
||||
return C1 ();
|
||||
}
|
||||
|
||||
EC1
|
||||
fce1 (enum_class EC1) // { dg-warning "\\\[-Wredundant-tags" }
|
||||
{
|
||||
return EC1 ();
|
||||
}
|
||||
|
||||
E1
|
||||
fe1 (E1)
|
||||
{
|
||||
return (enum E1)0; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
}
|
||||
|
||||
struct S1 // { dg-warning "\\\[-Wredundant-tags" }
|
||||
fs1 (S1)
|
||||
{
|
||||
return S1 ();
|
||||
}
|
||||
|
||||
U1
|
||||
fu1 (union U1) // { dg-warning "\\\[-Wredundant-tags" }
|
||||
{
|
||||
return U1 ();
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
|
||||
extern "C++" {
|
||||
|
||||
class C2 // { dg-warning "\\\[-Wredundant-tags" }
|
||||
fc2 (C2)
|
||||
{
|
||||
return C2 ();
|
||||
}
|
||||
|
||||
EC2
|
||||
fce2 (enum_class EC2) // { dg-warning "\\\[-Wredundant-tags" }
|
||||
{
|
||||
return EC2 ();
|
||||
}
|
||||
|
||||
E2
|
||||
fe2 (E2)
|
||||
{
|
||||
return (enum E2)0; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
}
|
||||
|
||||
struct S2 // { dg-warning "\\\[-Wredundant-tags" }
|
||||
fs2 (S2)
|
||||
{
|
||||
return S2 ();
|
||||
}
|
||||
|
||||
U2
|
||||
fu2 (union U2) // { dg-warning "\\\[-Wredundant-tags" }
|
||||
{
|
||||
return U2 ();
|
||||
}
|
||||
|
||||
} // extern "C++"
|
||||
|
||||
|
||||
class C3 // { dg-warning "\\\[-Wredundant-tags" }
|
||||
fc3 (C3)
|
||||
{
|
||||
return C3 ();
|
||||
}
|
||||
|
||||
EC3
|
||||
fce3 (enum_class EC3) // { dg-warning "\\\[-Wredundant-tags" }
|
||||
{
|
||||
return EC3 ();
|
||||
}
|
||||
|
||||
E3 fe3 (E3)
|
||||
{
|
||||
return (enum E3)0; // { dg-warning "\\\[-Wredundant-tags" }
|
||||
}
|
||||
|
||||
struct S3 // { dg-warning "\\\[-Wredundant-tags" }
|
||||
fs3 (S3)
|
||||
{
|
||||
return S3 ();
|
||||
}
|
||||
|
||||
U3
|
||||
fu3 (union U3) // { dg-warning "\\\[-Wredundant-tags" }
|
||||
{
|
||||
return U3 ();
|
||||
}
|
||||
|
||||
// { dg-prune-output "must not use the 'class' keyword" }
|
80
gcc/testsuite/g++.dg/warn/Wredundant-tags-5.h
Normal file
80
gcc/testsuite/g++.dg/warn/Wredundant-tags-5.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
#ifndef WREDUNDANT_TAGS_H
|
||||
#define WREDUNDANT_TAGS_H
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
# define enum_class enum class
|
||||
#else
|
||||
# define enum_class class
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
class C1 { };
|
||||
enum_class EC1 { };
|
||||
enum E1 { };
|
||||
struct S1 { };
|
||||
union U1 { };
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wredundant-tags"
|
||||
class C1 fc1 (class C1); // -Wredundant-tags
|
||||
enum_class EC1 fce1 (enum_class EC1);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
enum E1 fe1 (enum E1);
|
||||
struct S1 fs1 (struct S1);
|
||||
union U1 fu1 (union U1);
|
||||
|
||||
C1 fc1 (C1);
|
||||
EC1 fce1 (EC1);
|
||||
E1 fe1 (E1);
|
||||
S1 fs1 (S1);
|
||||
U1 fu1 (U1);
|
||||
}
|
||||
|
||||
|
||||
extern "C++" {
|
||||
|
||||
class C2 { };
|
||||
enum_class EC2 { };
|
||||
enum E2 { };
|
||||
struct S2 { };
|
||||
union U2 { };
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wredundant-tags"
|
||||
class C2 fc2 (class C2); // -Wredundant-tags
|
||||
enum_class EC2 fce2 (enum_class EC2); // -Wredundant-tags
|
||||
struct S2 fs2 (struct S2); // -Wredundant-tags
|
||||
union U2 fu2 (union U2); // -Wredundant-tags
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
C2 fc2 (C2);
|
||||
EC2 fce2 (EC2);
|
||||
E2 fe2 (E2);
|
||||
S2 fs2 (S2);
|
||||
U2 fu2 (U2);
|
||||
}
|
||||
|
||||
|
||||
class C3 { };
|
||||
enum_class EC3 { };
|
||||
enum E3 { };
|
||||
struct S3 { };
|
||||
union U3 { };
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wredundant-tags"
|
||||
class C3 fc3 (class C3); // -Wredundant-tags
|
||||
enum_class EC3 fce3 (enum_class EC3); // -Wredundant-tags
|
||||
struct S3 fs3 (struct S3); // -Wredundant-tags
|
||||
union U3 fu3 (union U3); // -Wredundant-tags
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
C3 fc3 (C3);
|
||||
EC3 fce3 (EC3);
|
||||
E3 fe3 (E3);
|
||||
S3 fs3 (S3);
|
||||
U3 fu3 (U3);
|
||||
|
||||
#endif // WREDUNDANT_TAGS_H
|
Loading…
Add table
Reference in a new issue