In the following example, class "foo" gets a deprecated warning, but a similar class template "goo" does not. Typedefs constructed with foo or goo get an error. What up? struct foo { int i; } __attribute__ ((__deprecated__)); template<typename _Tp> struct goo { int i; } __attribute__ ((__deprecated__)); typedef foo foo_type __attribute__ ((__deprecated__)); typedef goo<int> goo_type __attribute__ ((__deprecated__)); int main() { foo f1; goo<int> f2; foo_type f3; goo_type f4; return 0; } I have a patch to mark the C++0x bits deprecated, but it's not working because of this issue.
*** Bug 33912 has been marked as a duplicate of this bug. ***
I can second that problem for template member functions - in contrast to non-template member functions, where the attribute works. This gives a warning about deprecation as expected: ----------------------------------------------------------------- struct T { } ; struct A { inline void foo(T & ) __attribute__((deprecated)); }; inline void A::foo(T & ) { } void test(T & t) { A a; a.foo(t); } ------------------------------------------------------------- ... while this is not causing a warning as it should: ------------------------------------------------------------- struct A { template <class T> inline void foo(T & ) __attribute__((deprecated)); }; template <class T> inline void A::foo(T & ) { } void test(A & t) { A a; a.foo(t); } -------------------------------------------------------------
Subject: Re: attribute deprecated vs. templates niemayer at isg dot de wrote: > I can second that problem for template member functions - in contrast to > non-template member functions, where the attribute works. This is a parser bug: parsing the member template declaration winds up in cp_parser_init_declarator, which ignores attributes at the end of a declaration. A normal member function goes through cp_parser_member_declaration, which handles the attributes properly. You can work around this bug by moving the attribute into the decl-specifier-seq, i.e. "void __attribute ((deprecated)) foo(T&)". Jason
*** Bug 36307 has been marked as a duplicate of this bug. ***
Not planning to work on this soon since there's a reasonable workaround.
*** Bug 55557 has been marked as a duplicate of this bug. ***
I also have experienced bug 55557. I'm porting a project that uses std::auto_ptr in several places to c++11. However, there are no deprecated warnings because it happened that every unit uses auto_ptr once. If there is a workaround, may be it can be added to c++11 deprecated classes?
Personally, I'm not aware of any wa, if somebody finds one, please add it here, thanks.
(In reply to comment #5) > Not planning to work on this soon since there's a reasonable workaround. Jason, that workaround is only for function templates, not class templates, right? It's odd that the warning works for class templates except on the first instantiation (PR 55557)
For template member functions, is concatenating the parsed attributes to prefix_attributes and passing them to grokfield a valid fix? This patch works for a small test case I have and I wonder if this is correct: Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 202261) +++ gcc/cp/parser.c (working copy) @@ -16489,7 +16489,7 @@ cp_parser_init_declarator (cp_parser* parser, decl = grokfield (declarator, decl_specifiers, initializer, !is_non_constant_init, /*asmspec=*/NULL_TREE, - prefix_attributes); + chainon (prefix_attributes, attributes)); if (decl && TREE_CODE (decl) == FUNCTION_DECL) cp_parser_save_default_args (parser, decl); }
Author: eraman Date: Thu Oct 3 17:39:35 2013 New Revision: 203174 URL: http://gcc.gnu.org/viewcvs?rev=203174&root=gcc&view=rev Log: 2013-10-03 Easwaran Raman <eraman@google.com> PR c++/33911 * parser.c (cp_parser_init_declarator): Do not drop attributes of template member functions. 2013-10-03 Easwaran Raman <eraman@google.com> PR c++/33911 * g++.dg/ext/attribute47.C: New. Added: trunk/gcc/testsuite/g++.dg/ext/attrib47.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/parser.c trunk/gcc/testsuite/ChangeLog
The comment below is from Richard Smith. I don't think we do have the same problem for abi_tag, so Jason must have solved this problem there. -------- I was amazed to discover that clang has the *exact* same bug as gcc: template<typename T> struct S {} __attribute__((deprecated)); S<int> s1; // no warning S<int> s2; // warning, deprecated Moving the attribute earlier makes no difference to either compiler. And... I can tell you exactly why this is happening: when we see the use of S<int>, we instantiate the declaration. That does not instantiate attributes. The use is checked, it's not marked deprecated, so no warning occurs. Then we perform initialization of s1. That triggers the instantiation of the definition and the attribute. But we don't use the name S<int> here; that already happened earlier. Finally, we use S<int> again in the declaration of s2, and now we have both a use and an attribute, so we warn. I'm not entirely sure what the right resolution is here. Maybe some attributes should be instantiated when we instantiate a class template specialization declaration, rather than delaying all of them until we instantiate the definition. I expect that your abi_tag attribute has the same bug, by the way, and if you never trigger the instantiation of the definition of basic_string<T>, then that type won't get an ABI tag. =)
Also, even after the template definition (and the attribute) have been instantiated, typedefs for the instantiation don't get a warning unless the typedef itself is also marked deprecated: template<typename T> struct S {} __attribute__((deprecated)); using Si = S<int>; using Sd __attribute__((deprecated)) = S<int>; S<int> s1; // no warning S<int> s2; // warning, deprecated Si s3; // no warning Sd s4; // warning, deprecated This means that users with a typedef for std::auto_ptr<int> will never get the warning, because libstdc++ can only add the attribute to the primary template, not to users' own typedefs. This matters more now because WG21 just voted to remove auto_ptr from C++17 so we really want the deprecated attributes in libstdc++ to issue warnings.
Created attachment 33938 [details] patch Here's a compiler patch. Jonathan, can you decide what to do with the library testsuite regressions it introduces and check it in?
Author: redi Date: Wed Nov 12 10:32:17 2014 New Revision: 217412 URL: https://gcc.gnu.org/viewcvs?rev=217412&root=gcc&view=rev Log: Add -Wno-deprecated to dg-options. PR c++/33911 * testsuite/20_util/shared_ptr/assign/auto_ptr.cc: Use -Wno-deprecated. * testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc: Likewise. * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Likewise. * testsuite/20_util/shared_ptr/cons/auto_ptr.cc: Likewise. * testsuite/20_util/shared_ptr/cons/auto_ptr_neg.cc: Likewise. * testsuite/20_util/unique_ptr/cons/auto_ptr.cc: Likewise. * testsuite/20_util/unique_ptr/cons/auto_ptr_neg.cc: Likewise. * testsuite/ext/array_allocator/variadic_construct.cc: Likewise. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr.cc trunk/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc trunk/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc trunk/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc trunk/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr_neg.cc trunk/libstdc++-v3/testsuite/20_util/unique_ptr/cons/auto_ptr.cc trunk/libstdc++-v3/testsuite/20_util/unique_ptr/cons/auto_ptr_neg.cc trunk/libstdc++-v3/testsuite/ext/array_allocator/variadic_construct.cc
I've fixed most of the tests but I think the remaining ones reveal that the warning is a bit too eager: template<typename T> struct B { B(T t) { } } __attribute__ ((__deprecated__)); template<typename T> B<T> b(T t) { return B<T>(t); } int main() { } dep.cc:9:11: warning: ‘B’ is deprecated (declared at dep.cc:2) [-Wdeprecated-declarations] B<T> b(T t) ^ dep.cc: In function ‘B<T> b(T)’: dep.cc:11:16: warning: ‘B’ is deprecated (declared at dep.cc:2) [-Wdeprecated-declarations] return B<T>(t); ^ The warning comes even when b() isn't instantiated and can't be disabled with a #pragma. I have no idea why this only affects 3 tests, not all the -std=gnu++11 tests, so maybe I should just add -D_GLIBCXX_USE_DEPRECATED=0 to the dg-options for those three tests to prevent the deprecated components being included.
Author: jason Date: Mon Nov 17 22:09:27 2014 New Revision: 217677 URL: https://gcc.gnu.org/viewcvs?rev=217677&root=gcc&view=rev Log: PR c++/33911 gcc/cp/ * call.c (build_call_a): Don't warn_deprecated_use here. (build_over_call): Or here. * decl2.c (mark_used): Do it here. (is_late_template_attribute): Attribute deprecated is not deferred. (cplus_decl_attributes): Propagate TREE_DEPRECATED out to the template. * parser.c (cp_parser_template_name): Warn about deprecated template. (cp_parser_template_argument): Likewise. libstdc++-v3/ * include/backward/binders.h: Suppress -Wdeprecated-declarations. * include/ext/array_allocator.h: Likewise. Added: trunk/gcc/testsuite/g++.dg/ext/attr-deprecated-1.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/gcc/cp/decl2.c trunk/gcc/cp/parser.c trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/backward/binders.h trunk/libstdc++-v3/include/ext/array_allocator.h
The current status (with gcc 5.3) of these deprecation warnings is quite surprising: from my point of view there are both false negatives and false positives. Since clang's behaviour, additionally, differs considerably from gcc's, it's currently almost impossible to deprecate something in a portable fashion. Here's an example. Let's assume I've reimplemented enable_if and want to deprecated it. namespace Dune { template<bool B, class T = void> struct [[deprecated]] enable_if {}; template<class T> struct enable_if<true,T> { typedef T type; }; } This generates a warning even if enable_if is never used anywhere, simply through the template specialisation (if I were to remove the specialisation, the warning would go away): % g++ -c -std=c++14 test.cc -Wall -Wextra test.cc:7:10: warning: ‘template<bool B, class T> struct Dune::enable_if’ is deprecated [-Wdeprecated-declarations] struct enable_if<true,T> ^ test.cc:3:25: note: declared here struct [[deprecated]] enable_if ^ % Clang does not emit a warning here. Fair enough, maybe I should deprecate specialisations rather than the template. But this does not work as expected, either. The following code surprisingly does not emit a single warning: #include <type_traits> namespace Dune { template<bool B, class T = void> struct enable_if {}; template<class T> struct [[deprecated]] enable_if<false,T> {}; template<class T> struct [[deprecated]] enable_if<true,T> { typedef T type; }; } int main() { using newint = Dune::enable_if<std::is_integral<int>::value,int>::type; newint i = 2; ++i; }
(In reply to Elias Pipping from comment #18) In my view (while working on some fixes in this area), deprecating a primary template is a request to diagnose all uses of the template-id, including declarations of partial specializations and explicit specializations. The way to achieve the effect you are looking for is to 1) declare the primary template without deprecated: template<bool B, class T = void> struct enable_if; 2) define one partial specialization deprecated: template<class T> struct [[deprecated]] enable_if<false, T> {}; 3) define the complement of the first partial specialization that's not deprecated: template<class T> struct enable_if<true,T> { }; This should cause uses of the first (deprecated) partial specialization to be diagnosed. This is also what Clang does. GCC doesn't diagnose it because of bug 84347 but will once the bug is fixed.
(In reply to Jonathan Wakely from comment #16) Although Clang doesn't, warning for uses of a deprecated primary seems correct/useful to me because there's no way to define a specialization of the primary that's not deprecated. In your test case, there is no specialization of b() that would not use some specialization of the primary class template, and since every specialization is a use of the primary, that would not be subject to its deprecated attribute. (It seems analogous to warning for an unused constexpr function that can never be used in a core constant expression.) I've compiled all the test cases in this bug and, modulo bug(s) that are already being tracked elsewhere, they all result in the expected warnings. With that I'm going to resolve this bug as fixed. If you feel it's important to only warn for code that's instantiated, rather than reopening this bug I suggest opening a separate bug just for that.
(In reply to Martin Sebor from comment #20) > (In reply to Jonathan Wakely from comment #16) > > Although Clang doesn't, warning for uses of a deprecated primary seems > correct/useful to me because there's no way to define a specialization of > the primary that's not deprecated. In your test case, there is no > specialization of b() that would not use some specialization of the primary > class template, and since every specialization is a use of the primary, that > would not be subject to its deprecated attribute. (It seems analogous to > warning for an unused constexpr function that can never be used in a core > constant expression.) I believe it is important to *not* diagnose when the template is never instantiated. Indeed, imagine a library is providing these declarations. It needs to keep them around for backwards compatibility, but it also wants to mark them as deprecated to make sure that no users actually use them. With the current state of affairs, GCC will issue a warning just because the declarations exist and are marked as deprecated, even if the user doesn't actually use these declarations. This is not useful behavior -- it ends up being so noisy that the only reasonable solution is to remove deprecation warnings altogether, which defeats the whole thing. This is exactly what we're hitting with libc++ on GCC right now. I think it would be worth reconsidering the resolution of this issue to make GCC's behavior match Clang's behavior more closely. > If you feel it's important to only warn for code that's instantiated, rather > than reopening this bug I suggest opening a separate bug just for that. See https://gcc.gnu.org/PR104760.