Message ID | ef1c97f4-ee73-0317-11fd-d0e73735408a@gmail.com |
---|---|
State | New |
Headers | show |
Series | diagnose specializations of deprecated templates (PR c++/84318) | expand |
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. Jason
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). 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.
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.
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.) Martin
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 Jason
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. I think we need to give users the choice of being able to do one without the other (in addition to both). I.e., either of 1) Deprecate a primary and all its uses (including partial and explicit specializations). 2) Deprecate just a subset of specializations of a template without also deprecating the rest. An example of (1) is std::auto_ptr or the std::is_literal_type type trait. The intent is to remove them from namespace std someday and providing any specializations for them will then become an error. An example of (2) is the std::numeric_limits primary template that Richard brought up. That was my understanding of what he wanted to do but even if that's not what he meant it's a reasonable use case as well. Martin
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. > I think we need to give users the choice of being able to do > one without the other (in addition to both). I.e., either of > > 1) Deprecate a primary and all its uses (including partial and > explicit specializations). > > 2) Deprecate just a subset of specializations of a template > without also deprecating the rest. > > An example of (1) is std::auto_ptr or the std::is_literal_type > type trait. The intent is to remove them from namespace std > someday and providing any specializations for them will then > become an error. > > An example of (2) is the std::numeric_limits primary template > that Richard brought up. That was my understanding of what > he wanted to do but even if that's not what he meant it's > a reasonable use case as well. > > Martin >
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. Martin
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
On 02/13/2018 10:28 PM, Jason Merrill wrote: > 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. 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? Martin
On Wed, Feb 14, 2018 at 10:18 AM, Martin Sebor <msebor@gmail.com> wrote: > On 02/13/2018 10:28 PM, Jason Merrill wrote: >> 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. >>>>>>>> >>>>>>>>> [*] 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
PR c++/84318 - attribute deprecated on function templates different than class templates gcc/cp/ChangeLog: PR c++/84318 * pt.c (check_explicit_specialization): Warn for explicit specializations of deprecated primary templates. gcc/testsuite/ChangeLog: PR c++/84318 * g++.dg/ext/attr-deprecated-2.C: New test. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b58c60f..aa5f0dd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3104,6 +3104,20 @@ check_explicit_specialization (tree declarator, else if (VAR_P (decl)) DECL_COMDAT (decl) = false; + if (TREE_CODE (gen_tmpl) != TYPE_DECL) + { + tree tmpl = gen_tmpl; + if (DECL_FUNCTION_TEMPLATE_P (tmpl) + || TREE_CODE (tmpl) == TEMPLATE_DECL) + tmpl = DECL_TEMPLATE_RESULT (tmpl); + + /* Diagnose declarations of specializations of + a deprecated primary template. */ + if (TREE_DEPRECATED (tmpl) + || lookup_attribute ("deprecated", DECL_ATTRIBUTES (tmpl))) + warn_deprecated_use (tmpl, NULL_TREE); + } + /* If this is a full specialization, register it so that we can find it again. Partial specializations will be registered in process_partial_specialization. */ diff --git a/gcc/testsuite/g++.dg/ext/attr-deprecated-2.C b/gcc/testsuite/g++.dg/ext/attr-deprecated-2.C new file mode 100644 index 0000000..f639a73 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attr-deprecated-2.C @@ -0,0 +1,63 @@ +// PR c++/84318 - attribute deprecated on function templates different +// than class templates +// { dg-do compile } +// { dg-options "-Wall" } + +#define DEPRECATED __attribute__ ((deprecated)) + +template <typename T> +struct DEPRECATED +ClassPartial { }; // { dg-message "declared here" } + +// Verify that a partial specialization is diagnosed. +template <typename T> +struct ClassPartial<const T> { }; // { dg-warning ".template *<class T> struct ClassPartial. is deprecated" } + + +template <typename T> +struct +ClassPartialDeprecated { }; + +template <typename T> +struct DEPRECATED +ClassPartialDeprecated<T*> { }; + +ClassPartialDeprecated<int> cpdi; +ClassPartialDeprecated<int*> cpdci; // { dg-warning "is deprecated" "bug 84347" { xfail *-*-* } } + + +template <typename T> +struct DEPRECATED +ClassExplicit { }; // { dg-message "declared here" } + +template <> +struct +ClassExplicit<int> { }; // { dg-warning ".template *<class T> struct ClassExplicit. is deprecated" } + + +template <typename T> +void DEPRECATED +FuncExplicit (); // { dg-message "declared here" } + +template <> +void +FuncExplicit<int>(); // { dg-warning ".void FuncExplicit\\\(\\\). is deprecated" } + + +template <typename T> +int DEPRECATED +VarPartial; // { dg-message "declared here" } + +template <class T> +int +VarPartial<const T>; // { dg-warning ".VarPartial<T>. is deprecated" } + +template <typename T> +int DEPRECATED +VarExplicit; // { dg-message "declared here" } + +template <> +int +VarExplicit<int>; // { dg-warning ".VarExplicit<T>. is deprecated" } + +// { dg-prune-output "variable templates only available" }