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


Reply via email to