On 3/11/20 12:57 PM, Martin Sebor wrote:
On 3/9/20 6:08 PM, Jason Merrill wrote:
On 3/9/20 5:39 PM, Martin Sebor wrote:
On 3/9/20 1:40 PM, Jason Merrill wrote:
On 3/9/20 12:31 PM, Martin Sebor wrote:
On 2/28/20 1:24 PM, Jason Merrill wrote:
On 2/28/20 12:45 PM, Martin Sebor wrote:
On 2/28/20 9:58 AM, Jason Merrill wrote:
On 2/24/20 6:58 PM, Martin Sebor wrote:
-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).
+ 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;
How can the first appearance of a class template be redundant?
I'm not sure I correctly understand the question. The comment says
"involving a template" (i.e., not one of the first declaration of
a template). The test case that corresponds to this test is:
template <class> struct S7 { };
struct S7<void> s7v; // { dg-warning "\\\[-Wredundant-tags" }
where DECL is the TEPLATE_DECL of S7<void>.
As I mentioned, more work is still needed to handle templates right
because some redundant tags are still not diagnosed. For example:
template <class> struct S7 { };
template <class T>
using U = struct S7<T>; // missing warning
When we get here for an instance of a template, it doesn't make
sense to treat it as a new type.
If decl is a template and type_decl is an instance of that
template, do we want to (before the lookup) change type_decl to
the template or the corresponding generic TYPE_DECL, which should
already be in the table?
I'm struggling with how to do this. Given type (a RECORD_TYPE) and
type_decl (a TEMPLATE_DECL) representing the use of a template, how
do I get the corresponding template (or its explicit or partial
specialization) in the three cases below?
1) Instance of the primary:
template <class> class A;
struct A<int> a;
2) Instance of an explicit specialization:
template <class> class B;
template <> struct B<int>;
class B<int> b;
3) Instance of a partial specialization:
template <class> class C;
template <class T> struct C<T*>;
class C<int*> c;
By trial and (lots of) error I figured out that in both (1) and (2),
but not in (3), TYPE_MAIN_DECL (TYPE_TI_TEMPLATE (type)) returns
the template's type_decl.
Is there some function to call to get it in (3), or even better,
in all three cases?
I think you're looking for most_general_template.
I don't think that's quite what I'm looking for. At least it doesn't
return the template or its specialization in all three cases above.
Ah, true, that function stops at specializations. Oddly, I don't
think there's currently a similar function that looks through them.
You could create one that does a simple loop through DECL_TI_TEMPLATE
like is_specialization_of.
Thanks for the tip. Even with that I'm having trouble with partial
specializations. For example in:
template <class> struct S;
template <class T> class S<const T>;
extern class S<const int> s1;
extern struct S<const int> s2; // expect -Wmismatched-tags
how do I find the declaration of the partial specialization when given
the type in the extern declaration? A loop in my find_template_for()
function (similar to is_specialization_of) only visits the implicit
specialization S<const int> (i.e., its own type) and the primary.
Is that a problem? The name is from the primary template, so does it
matter for this warning whether there's an explicit specialization involved?
Martin
In (2) and (3) it won't distinguish between specializations of B or
C on different types. In (2), the function returns the same result
for both:
template <> struct B<int>;
template <> struct B<char>;
In (3), it similarly returns the same result for both of
template <class T> struct C<T*>;
template <class T> struct C<const T>;
even though they are declarations of distinct types.
Jason