+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.
/* 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)
- {
- 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);
+ if (decl != type_decl)
+ return;
+
+ if (scoped_key != RID_CLASS
+ && scoped_key != RID_STRUCT
+ && current_lang_name != lang_name_cplusplus
+ && current_namespace == global_namespace)
+ {
+ /* 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
&& 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
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)
+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.
--- /dev/null
+/* 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" }
--- /dev/null
+// 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" }
--- /dev/null
+#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