On Wed, Feb 15, 2017 at 11:56:30AM -0500, Jason Merrill wrote:
> On Tue, Feb 14, 2017 at 3:13 PM, Jakub Jelinek <ja...@redhat.com> wrote:
> > The following testcase fails, because while we have the nodiscard
> > attribute on the template, we actually never propagate it to the
> > instantiation, which is where it is checked (I'm really surprised about
> > this).
> 
> Normally we propagate attributes when instantiating the class; see the
> call to apply_late_template_attributes in
> instantiate_class_template_1.  I'm not sure why that wouldn't be

Yes, instantiate_class_template_1 calls apply_late_template_attributes,
but that actually does nothing if there are no dependent attributes.
If there are any, it sets TYPE_ATTRIBUTES (or DECL_ATTRIBUTES) to
a copy of the attributes list, removes all the dependent attributes
from there and calls cplus_decl_attributes on the late attrs (after
tsubst_attribute them).  So setting {TYPE,DECL}_ATTRIBUTES to the
attributes list unmodified if there are no dependent ones matches
the behavior for non-dependent ones if there is at least one dependent.

So, does the following patch look better?

2017-02-15  Jakub Jelinek  <ja...@redhat.com>

        PR c++/79502
        * pt.c (apply_late_template_attributes): If there are
        no dependent attributes, set *p to attributes.

        * g++.dg/cpp1z/nodiscard4.C: New test.

--- gcc/cp/pt.c.jj      2017-02-14 09:23:49.000000000 +0100
+++ gcc/cp/pt.c 2017-02-15 18:21:45.581055915 +0100
@@ -10113,6 +10113,8 @@ apply_late_template_attributes (tree *de
 
       cplus_decl_attributes (decl_p, late_attrs, attr_flags);
     }
+  else
+    *p = attributes;
 }
 
 /* Perform (or defer) access check for typedefs that were referenced
--- gcc/testsuite/g++.dg/cpp1z/nodiscard4.C.jj  2017-02-15 18:11:33.281135469 
+0100
+++ gcc/testsuite/g++.dg/cpp1z/nodiscard4.C     2017-02-15 18:11:33.281135469 
+0100
@@ -0,0 +1,14 @@
+// PR c++/79502
+// { dg-do compile { target c++11 } }
+
+template<typename>
+struct [[nodiscard]] missiles {};
+
+missiles<void> make() { return {}; }
+missiles<void> (*fnptr)() = make;
+
+int main()
+{
+  make();      // { dg-warning "ignoring returned value of type" }
+  fnptr();     // { dg-warning "ignoring returned value of type" }
+}


        Jakub

Reply via email to