On Wed, Feb 14, 2018 at 10:18 AM, Martin Sebor <mse...@gmail.com> wrote: > On 02/13/2018 10:28 PM, Jason Merrill wrote: >> On Tue, Feb 13, 2018 at 5:20 PM, Martin Sebor <mse...@gmail.com> wrote: >>> On 02/13/2018 01:09 PM, Jason Merrill wrote: >>>> On Tue, Feb 13, 2018 at 2:59 PM, Martin Sebor <mse...@gmail.com> wrote: >>>>> On 02/13/2018 12:15 PM, Jason Merrill wrote: >>>>>> On Tue, Feb 13, 2018 at 1:31 PM, Martin Sebor <mse...@gmail.com> wrote: >>>>>>> On 02/13/2018 09:24 AM, Martin Sebor wrote: >>>>>>>> On 02/13/2018 08:35 AM, Martin Sebor wrote: >>>>>>>>> On 02/13/2018 07:40 AM, Jason Merrill wrote: >>>>>>>>>> On Mon, Feb 12, 2018 at 6:32 PM, Martin Sebor <mse...@gmail.com> >>>>>>>>>> wrote: >>>>>>>>>>> >>>>>>>>>>> While testing my fix for 83871 (handling attributes on explicit >>>>>>>>>>> specializations) I noticed another old regression: while GCC 4.4 >>>>>>>>>>> would diagnose declarations of explicit specializations of all >>>>>>>>>>> primary templates declared deprecated, GCC 4.5 and later only >>>>>>>>>>> diagnose declarations of explicit specializations of class >>>>>>>>>>> templates but not those of function or variable templates. >>>>>>>>>> >>>>>>>>>> Hmm, the discussion on the core reflector seemed to be agreeing that >>>>>>>>>> we want to be able to define non-deprecated specializations of a >>>>>>>>>> deprecated primary template. >>>>>>>>> >>>>>>>>> Yes, that's what Richard wanted to do. The only way to do it >>>>>>>>> within the existing constraints(*) is to define a non-deprecated >>>>>>>>> primary, and a deprecated partial specialization. This is in line >>>>>>>>> with that approach and supported by Clang and all other compilers >>>>>>>>> I tested (including Clang). >>>>>>>> >>>>>>>> To clarify, this approach works for class templates (e.g., like >>>>>>>> std::numeric_limits that was mentioned in the core discussion) >>>>>>>> and for variable templates. Functions have no partial >>>>>>>> specilizations so they have to be overloaded to achieve the same >>>>>>>> effect. >>>>>>>> >>>>>>>> Implementations don't treat the deprecated attribute on partial >>>>>>>> specializations consistently. >>>>>>>> >>>>>>>> EDG accepts and honors it on class template partial specializations >>>>>>>> but rejects it with an error on those of variables. >>>>>>>> >>>>>>>> Clang accepts but silently ignores it on class template partial >>>>>>>> specializations and rejects with an error it on variables. >>>>>>>> >>>>>>>> MSVC accepts and honors it on variables but silently ignores it >>>>>>>> on class template partial specializations. >>>>>>>> >>>>>>>> GCC ignores it silently on class partial specializations and >>>>>>>> with a warning on variables (I opened bug 84347 to track this >>>>>>>> and to have GCC honor is everywhere). >>>>>>>> >>>>>>>> This is clearly a mess, which isn't surprising given how poorly >>>>>>>> specified this is in the standard. But from the test cases and >>>>>>>> from the core discussion it seems clear that deprecating >>>>>>>> a template, including its partial specializations (as opposed >>>>>>>> to just a single explicit specialization) is desirable and >>>>>>>> already supported, and that the wording in the standard just >>>>>>>> needs to be adjusted to reflect that. >>>>>>>> >>>>>>>>> [*] Except (as Richard noted) that the standard doesn't seem to >>>>>>>>> allow a template to be deprecated. I think that's a bug in the >>>>>>>>> spec because all implementations allow it to some degree. >>>>>>> >>>>>>> One other note. While thinking about this problem during >>>>>>> the core discussion, another approach to deprecating a primary >>>>>>> template without also deprecating all of its specializations >>>>>>> occurred to me. >>>>>>> >>>>>>> 1) First declare the primary template without [[deprecated]]. >>>>>>> 2) Next declare its non-deprecated specializations (partial >>>>>>> or explicit). >>>>>>> 3) Finally declare the primary again, this time [[deprecated]]. >>>>>>> >>>>>>> Like this: >>>>>>> >>>>>>> template <class T> struct S; >>>>>>> template <class T> struct S<const T> { }; >>>>>>> template <class T> struct [[deprecated]] S<volatile T> { }; >>>>>>> template <class T> struct [[deprecated]] S { }; >>>>>>> >>>>>>> S<int> si; // warning >>>>>>> S<const int> sci; // no warning >>>>>>> S<volatile int> svi; // warning >>>>>>> >>>>>>> This works as expected with Intel ICC. All other compilers >>>>>>> diagnose all three variables. I'd say for [[deprecated]] it >>>>>>> should work the way ICC does. (For [[noreturn]] the first >>>>>>> declaration must be [[noreturn]], so there this solution >>>>>>> wouldn't work also because of that, in addition to function >>>>>>> templates not being partially-specializable.) >>>>>> >>>>>> My understanding of the reflector discussion, and Richard's comment in >>>>>> particular, was that [[deprecated]] should apply to the instances, not >>>>>> the template itself, so that declaring the primary template >>>>>> [[deprecated]] doesn't affect explicit specializations. Your last >>>>>> example should work as you expect in this model, but you can also >>>>>> write the simpler >>>>>> >>>>>> template <class T> struct [[deprecated]] S { }; >>>>>> template <class T> struct S<const T> { }; // no warning >>>>> >>>>> With this approach there would be no way to deprecate all of >>>>> a template's specializations) because it would always be >>>>> possible for a user to get around deprecation by defining >>>>> their own specialization, partial or explicit. >>>> >>>> Yep. And so he suggested that we might want to add a new way to write >>>> attributes that do apply to the template name. >>> >>> [[deprecated]] was introduced in part to make it possible for >>> C++ standard library implementers to add warnings for stuff >>> the committee has deprecated. Most C++ deprecated features >>> are templates. Declaring that [[deprecated]] isn't meant to >>> serve its purpose for templates and that some new form of >>> it is needed would make the attribute useless for standard >>> library implementers in the meantime, until that new form >>> is invented, as well as for all other template library >>> authors. It would also make the current attribute useless >>> for existing code which almost surely intends it to apply >>> to all specializations of the deprecated template, implicit >>> or explicit. There is no need to introduce new syntax. >>> What we have meets all the needs fine. It can be used to >>> selectively deprecate a primary template, its partial >>> specializations, or its explicit specializations, or any >>> combination of the three. >> >> This seems like a discussion to have on the reflector. > > Okay, let me follow up there about [[deprecated]]. > > In the meantime, what should we do with the bug and with > __attribute__ ((deprecated))? > > It used the work the way I expect but changed/regressed in GCC > 4.4 when the attribute was enhanced to take a string argument. > > Do you agree that it should be viewed as a regression and that > it should work the way it did so that all uses of deprecated > standard library templates can be diagnosed even when they are > specialized?
Given the uncertainty about the desired semantics, I'm not inclined to do anything about the bug in GCC 8. Jason