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

Reply via email to