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.
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