[PATCH] diagnose specializations of deprecated templates (PR c++/84318)

Jason Merrill jason@redhat.com
Wed Feb 14 05:29:00 GMT 2018


On Tue, Feb 13, 2018 at 5:20 PM, Martin Sebor <msebor@gmail.com> wrote:
> On 02/13/2018 01:09 PM, Jason Merrill wrote:
>>
>> On Tue, Feb 13, 2018 at 2:59 PM, Martin Sebor <msebor@gmail.com> wrote:
>>>
>>> On 02/13/2018 12:15 PM, Jason Merrill wrote:
>>>>
>>>> On Tue, Feb 13, 2018 at 1:31 PM, Martin Sebor <msebor@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 <msebor@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.
>>>>>>
>>>>>>>
>>>>>>> Martin
>>>>>>>
>>>>>>> [*] 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.

Jason



More information about the Gcc-patches mailing list