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