From: Martin Sebor <msebor@gmail.com>
To: gcc-patches <gcc-patches@gcc.gnu.org>, Jason Merrill <jason@redhat.com>
Subject: [PATCH] avoid -Wredundant-tags on a first declaration in use (PR 93824)
Date: Mon, 24 Feb 2020 23:58:00 -0000 [thread overview]
Message-ID: <f726a433-0bb9-33d4-9929-7c018913d0ca@gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 579 bytes --]
-Wredundant-tags doesn't consider type declarations that are also
the first uses of the type, such as in 'void f (struct S);' and
issues false positives for those. According to the reported that's
making it harder to use the warning to clean up LibreOffice.
The attached patch extends -Wredundant-tags to avoid these false
positives by relying on the same class_decl_loc_t::class2loc mapping
as -Wmismatched-tags. The patch also somewhat improves the detection
of both issues in template declarations (though more work is still
needed there).
Tested on x86_64-linux.
Martin
[-- Attachment #2: gcc-93824.diff --]
[-- Type: text/x-patch, Size: 11661 bytes --]
PR c++/93824 - bogus -Wredundant-tags on a first declaration in use
PR c++/93810 - missing -Wmismatched-tags and -Wredundant-tags on a typedef of an implicit class template specialization
gcc/cp/ChangeLog:
PR c++/93824
PR c++/93810
* parser.c (cp_parser_check_class_key): Move code...
(class_decl_loc_t::add): ...to here. Add parameters. Avoid issuing
-Wredundant-tags on first-time declarations in other declarators.
(class_decl_loc_t::diag_mismatched_tags): Also expect to be called
when -Wredundant-tags is enabled.
gcc/testsuite/ChangeLog:
PR c++/93824
PR c++/93810
* g++.dg/warn/Wmismatched-tags-3.C: New test.
* g++.dg/warn/Wredundant-tags-3.C: Remove xfails.
* g++.dg/warn/Wredundant-tags-6.C: New test.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ca85d899427..3cf2f2d8b34 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30924,8 +30924,9 @@ class class_decl_loc_t
/* Issues -Wmismatched-tags for all classes. */
static void diag_mismatched_tags ();
- /* Adds TYPE_DECL to the collection of class decls. */
- static void add (tree, tag_types, bool, bool);
+ /* Adds TYPE_DECL to the collection of class decls and diagnoses
+ redundant tags (if -Wredundant-tags is enabled). */
+ static void add (cp_parser *, location_t, tag_types, tree, bool, bool);
/* Either adds this decl to the collection of class decls
or diagnoses it, whichever is appropriate. */
@@ -31021,6 +31022,19 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc,
&& class_key != union_type)
return;
+ class_decl_loc_t::add (parser, key_loc, class_key, type, def_p, decl_p);
+}
+
+/* Adds TYPE to the collection of class decls and diagnoses redundant
+ tags (if -Wredundant-tags is enabled).
+ DEF_P is expected to be set for a definition of class TYPE. DECL_P
+ is set for a declaration of class TYPE and clear for a reference to
+ it that is not a declaration of it. */
+
+void
+class_decl_loc_t::add (cp_parser *parser, location_t key_loc,
+ tag_types class_key, tree type, bool def_p, bool decl_p)
+{
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
@@ -31032,7 +31046,10 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc,
/* The class-key is redundant for uses of the CLASS_TYPE that are
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;
+ bool key_redundant = (!def_p && !decl_p
+ && (decl == type_decl
+ || TREE_CODE (decl) == TEMPLATE_DECL
+ || TYPE_BEING_DEFINED (type)));
if (key_redundant
&& class_key != class_type
@@ -31050,29 +31067,8 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc,
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);
- }
-
- if (seen_as_union || !warn_mismatched_tags)
- return;
-
- class_decl_loc_t::add (type_decl, class_key, key_redundant, def_p);
-}
-
-/* Adds TYPE_DECL to the collection of class decls. */
-
-void
-class_decl_loc_t::add (tree type_decl, tag_types class_key, bool redundant,
- bool def_p)
-{
+ /* Set if a declaration of TYPE has previously been seen or if it
+ must exist in a precompiled header. */
bool exist;
class_decl_loc_t *rdl = &class2loc.get_or_insert (type_decl, &exist);
if (!exist)
@@ -31082,30 +31078,51 @@ class_decl_loc_t::add (tree type_decl, tag_types class_key, bool redundant,
{
/* TYPE_DECL is the first declaration or definition of the type
(outside precompiled headers -- see below). Just create
- a new entry for it. */
+ a new entry for it and return unless it's a declaration
+ involving a template that may need to be diagnosed by
+ -Wredundant-tags. */
*rdl = class_decl_loc_t (class_key, false, def_p);
- return;
+ if (TREE_CODE (decl) != TEMPLATE_DECL)
+ return;
+ }
+ else
+ {
+ /* TYPE was previously defined in some unknown precompiled hdeader.
+ Simply add a record of its definition at an unknown location and
+ proceed below to add a reference to it at the current location.
+ (Declarations in precompiled headers that are not definitions
+ are ignored.) */
+ tag_types def_key
+ = CLASSTYPE_DECLARED_CLASS (type) ? class_type : record_type;
+ location_t def_loc = DECL_SOURCE_LOCATION (type_decl);
+ *rdl = class_decl_loc_t (def_key, false, true, def_loc);
+ exist = true;
}
-
- /* TYPE was previously defined in some unknown precompiled hdeader.
- Simply add a record of its definition at an unknown location and
- proceed below to add a reference to it at the current location.
- (Declarations in precompiled headers that are not definitions
- are ignored.) */
- tag_types def_key
- = CLASSTYPE_DECLARED_CLASS (type) ? class_type : record_type;
- location_t def_loc = DECL_SOURCE_LOCATION (type_decl);
- *rdl = class_decl_loc_t (def_key, false, true, def_loc);
}
/* A prior declaration of TYPE_DECL has been seen. */
+ 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);
+ }
+
+ if (!exist)
+ /* Do nothing if this is the first declaration of the type. */
+ return;
+
if (rdl->idxdef != UINT_MAX && rdl->def_class_key == class_key)
/* Do nothing if the class-key in this declaration matches
the definition. */
return;
- rdl->add_or_diag_mismatched_tag (type_decl, class_key, redundant, def_p);
+ rdl->add_or_diag_mismatched_tag (type_decl, class_key, key_redundant, def_p);
}
/* Either adds this DECL corresponding to the TYPE_DECL to the collection
@@ -31158,6 +31175,9 @@ class_decl_loc_t::add_or_diag_mismatched_tag (tree type_decl,
void
class_decl_loc_t::diag_mismatched_tags (tree type_decl)
{
+ if (!warn_mismatched_tags)
+ return;
+
unsigned ndecls = locvec.length ();
/* Skip a declaration that consistently uses the same class-key
@@ -31249,20 +31269,26 @@ class_decl_loc_t::diag_mismatched_tags (tree type_decl)
void
class_decl_loc_t::diag_mismatched_tags ()
{
- /* CLASS2LOC should be empty if -Wmismatched-tags is disabled. */
- gcc_assert (warn_mismatched_tags || class2loc.is_empty ());
+ /* CLASS2LOC should be empty if both -Wmismatched-tags and
+ -Wredundant-tags are disabled. */
+ gcc_assert (warn_mismatched_tags
+ || warn_redundant_tags
+ || class2loc.is_empty ());
/* Save the current function before changing it below. It should
be null at this point. */
tree save_func = current_function_decl;
- /* Iterate over the collected class/struct declarations. */
- typedef class_to_loc_map_t::iterator iter_t;
- for (iter_t it = class2loc.begin (); it != class2loc.end (); ++it)
+ if (warn_mismatched_tags)
{
- tree type_decl = (*it).first;
- class_decl_loc_t &recloc = (*it).second;
- recloc.diag_mismatched_tags (type_decl);
+ /* Iterate over the collected class/struct declarations. */
+ typedef class_to_loc_map_t::iterator iter_t;
+ for (iter_t it = class2loc.begin (); it != class2loc.end (); ++it)
+ {
+ tree type_decl = (*it).first;
+ class_decl_loc_t &recloc = (*it).second;
+ recloc.diag_mismatched_tags (type_decl);
+ }
}
class2loc.empty ();
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-tags-3.C b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-3.C
new file mode 100644
index 00000000000..ecbe66d037e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-3.C
@@ -0,0 +1,14 @@
+/* { dg-do compile }
+ { dg-options "-Wall -Wmismatched-tags" } */
+
+extern class C1 c1; // { dg-message "declared as 'class'" }
+extern struct C1 c1; // { dg-warning "\\\[-Wmismatched-tags" }
+
+void fs1 (struct S1); // { dg-message "declared as 'struct'" }
+void fs1 (class S1); // { dg-warning "\\\[-Wmismatched-tags" }
+
+enum
+{
+ ec2 = sizeof (struct C2*), // { dg-message "declared as 'struct'" }
+ fc2 = sizeof (class C2*) // { dg-warning "\\\[-Wmismatched-tags" }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C
index 7b30e949d0c..0eeee34dae7 100644
--- a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C
+++ b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C
@@ -34,12 +34,12 @@ union N::U u3; // { dg-warning "-Wredundant-tags" }
typedef N::TC<0> TC0;
typedef typename N::TC<0> TC0;
-typedef class N::TC<0> TC0; // { dg-warning "-Wredundant-tags" "pr93809" { xfail *-*-*} .-1 }
+typedef class N::TC<0> TC0; // { dg-warning "-Wredundant-tags" }
typedef N::TS<0> TS0;
typedef typename N::TS<0> TS0;
-typedef struct N::TS<0> TS0; // { dg-warning "-Wredundant-tags" "pr93809" { xfail *-*-*} .-1 }
+typedef struct N::TS<0> TS0; // { dg-warning "-Wredundant-tags" }
typedef N::TS<0> TS0;
typedef typename N::TS<0> TS0;
-typedef struct N::TS<0> TS0; // { dg-warning "-Wredundant-tags" "pr93809" { xfail *-*-*} .-1 }
+typedef struct N::TS<0> TS0; // { dg-warning "-Wredundant-tags" }
diff --git a/gcc/testsuite/g++.dg/warn/Wredundant-tags-6.C b/gcc/testsuite/g++.dg/warn/Wredundant-tags-6.C
new file mode 100644
index 00000000000..a21cc14b2d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wredundant-tags-6.C
@@ -0,0 +1,51 @@
+/* PR c++/93824 - bogus -Wredundant-tags on a first declaration in use
+ { dg-do compile }
+ { dg-options "-Wredundant-tags" } */
+
+extern class C1 &c1; // { dg-bogus "\\\[-Wredundant-tags" }
+extern class C1 &c1; // { dg-warning "\\\[-Wredundant-tags" }
+
+void fc2 (class C2); // { dg-bogus "\\\[-Wredundant-tags" }
+void fc2 (class C2); // { dg-warning "\\\[-Wredundant-tags" }
+
+const int
+npc3 = sizeof (class C3*); // { dg-bogus "\\\[-Wredundant-tags" }
+const int
+nppc3 = sizeof (class C3**); // { dg-warning "\\\[-Wredundant-tags" }
+
+extern struct S1 *s1p; // { dg-bogus "\\\[-Wredundant-tags" }
+extern struct S1 s1a[]; // { dg-warning "\\\[-Wredundant-tags" }
+
+struct S3
+{
+ struct S3 *p1s3; // { dg-warning "\\\[-Wredundant-tags" }
+ S3 *p2s3;
+
+ union U1 *p1u1; // { dg-bogus "\\\[-Wredundant-tags" }
+ union U1 *p2u1; // { dg-warning "\\\[-Wredundant-tags" }
+} s3;
+
+typedef struct S3 TS3; // { dg-warning "\\\[-Wredundant-tags" }
+
+typedef struct S4 TS4;
+
+struct S5
+{
+ struct S6
+ {
+ private:
+ // 'struct' is redundant in a declaration of a pointer to ::S5;
+ struct S5 *ps5; // { dg-warning "\\\[-Wredundant-tags" }
+ // 'struct' is required in a definition of a new type.
+ struct S5 { } *ps5_2;
+ struct S5 *p2s5_2; // { dg-warning "\\\[-Wredundant-tags" }
+ };
+};
+
+
+template <class> struct S7;
+template <class> struct S7 { };
+
+template <> struct S7<int>;
+template <> struct S7<int> { };
+struct S7<void> s7v; // { dg-warning "\\\[-Wredundant-tags" }
next reply other threads:[~2020-02-24 23:58 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-24 23:58 Martin Sebor [this message]
2020-02-28 16:59 ` Jason Merrill
2020-02-28 17:45 ` Martin Sebor
2020-02-28 20:24 ` Jason Merrill
2020-03-09 16:31 ` Martin Sebor
2020-03-09 19:40 ` Jason Merrill
2020-03-09 21:39 ` Martin Sebor
2020-03-10 0:08 ` Jason Merrill
2020-03-11 16:57 ` Martin Sebor
2020-03-11 20:10 ` Jason Merrill
2020-03-11 21:30 ` Martin Sebor
2020-03-12 17:03 ` Martin Sebor
2020-03-12 22:38 ` Martin Sebor
2020-03-18 22:09 ` [PING][PATCH] " Martin Sebor
2020-03-19 3:07 ` [PATCH] " Jason Merrill
2020-03-19 23:55 ` Martin Sebor
2020-03-20 21:53 ` Jason Merrill
2020-03-21 21:59 ` Martin Sebor
2020-03-23 14:49 ` Jason Merrill
2020-03-23 16:50 ` Martin Sebor
2020-03-26 5:36 ` Jason Merrill
2020-03-26 18:58 ` Martin Sebor
2020-03-26 22:16 ` Jason Merrill
2020-03-26 22:51 ` Martin Sebor
2020-03-27 16:33 ` Jason Merrill
2020-03-25 20:54 ` Martin Sebor
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f726a433-0bb9-33d4-9929-7c018913d0ca@gmail.com \
--to=msebor@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).