Bug 104760

Summary: Attribute [[deprecated]] causes diagnostic in never-instantiated template
Product: gcc Reporter: Louis Dionne <ldionne.2>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: UNCONFIRMED ---    
Severity: normal CC: jakub, Laurent.Rineau__gcc, mpolacek, redi, webrown.cpp
Priority: P3 Keywords: diagnostic
Version: 12.0   
Target Milestone: ---   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33911
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description Louis Dionne 2022-03-02 14:27:42 UTC
When using the [[deprecated]] attribute on a class template, a diagnostic is produced even if that class template is never actually instantiated. For example, if that class template is only mentioned from another function template (which is never actually instantiated), we get a diagnostic:

    template <class Pred>
    struct [[deprecated]] unary_negate {
        explicit unary_negate(const Pred&);
    };

    template <class Pred>
    [[deprecated]]
    unary_negate<Pred> not1(const Pred& p) { return unary_negate<Pred>(p); }

We get:

    <source>:8:1: warning: 'template<class Pred> struct unary_negate' is deprecated [-Wdeprecated-declarations]
        8 | unary_negate<Pred> not1(const Pred& p) { return unary_negate<Pred>(p); }
        | ^~~~~~~~~~~~
    <source>:2:23: note: declared here
        2 | struct [[deprecated]] unary_negate {
        |                       ^~~~~~~~~~~~
    <source>: In function 'unary_negate<Pred> not1(const Pred&)':
    <source>:8:49: warning: 'template<class Pred> struct unary_negate' is deprecated [-Wdeprecated-declarations]
        8 | unary_negate<Pred> not1(const Pred& p) { return unary_negate<Pred>(p); }
        |                                                 ^~~~~~~~~~~~
    <source>:2:23: note: declared here
        2 | struct [[deprecated]] unary_negate {
        |                       ^~~~~~~~~~~~

We are encountering this issue in libc++, where we do mark several things as [[deprecated]] (per the Standard), and those warnings fire off when the headers are used not as system headers. Any other non-system header library would have the same problem.

Note that in comparison, Clang does not issue a warning in this case. It only issues a warning if we actually instantiate `not1` or `unary_negate`.

Godbolt: https://godbolt.org/z/559EfKn9K
Comment 1 Marek Polacek 2022-03-02 14:43:36 UTC
This is a consequence of treating attribute deprecated specially in is_late_template_attribute (it's not a late attribute).
Comment 2 Marek Polacek 2022-03-02 14:45:01 UTC
And I think this is the same problem as in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33911#c18.  Not sure if we want to change anything.
Comment 3 Louis Dionne 2022-03-02 15:53:02 UTC
(In reply to Marek Polacek from comment #2)
> And I think this is the same problem as in
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33911#c18.  Not sure if we want
> to change anything.

Yup, I agree this is the same problem. However, see my recent comment on that bug report -- I think we should still fix this, and the resolution of PR33911 was IMO incomplete.
Comment 4 Jakub Jelinek 2022-03-02 16:43:29 UTC
CCing Jonathan for insight on what libstdc++ is doing here with [[deprecated]].
Comment 5 Jonathan Wakely 2022-03-02 22:28:43 UTC
Libstdc++ has the attribute on both of these templates. I used diagnostic pragmas to stop the function templates from warning about the use of the class templates.

If other code refers to either of them, it gets a warning. But the use of unary_negate within std::not1 doesn't give a warning.
Comment 6 Jonathan Wakely 2022-03-02 22:33:39 UTC
I think I've argued in another bug that it might be reasonable to not warn about uses within the same header (since that is likely to be part of the same library, and the warnings are probably intended for users of the library code, not within the library itself). But in the absence of such a rule, disabling the warnings locally using pragmas seems reasonable to me. That works for any library, not just the std::lib.