Nick Williams
Nick Williams

Reputation: 3198

Deprecation of typedef does not work on GCC and MSVC (does on Apple Clang) when used as a stream operator argument

In our code we have a class which has an alias (typedef), and we are trying to deprecate that alias. We do not want to deprecate the original class (really, the class with its new name). We want to deprecate only the alias (the old name).

The C++14 spec indicates that this should be very simple:

[[deprecated]] typedef AliasName RealName;

We were confused that this was working for us on Apple Clang (16) but was not working on GCC (8, 11) or MSVC (VS 2022). Then, after much experimentation, we realize it was not working because the object created with the alias name was being used as an argument to a stream operator. Here's the simplest possible reproduction code:

#include <iostream>
#include <string>

class Foo
{
public:
  Foo(std::string const & name) : _name(name) {}
  ~Foo() {}

  std::string _name;
};

std::ostream &
operator<<(std::ostream & o, Foo const & f)
{
  return o << f._name;
}

[[deprecated]] typedef Foo Bar;

int main()
{
  std::cout
    << Foo("one") << " / "
    << Bar("two") << std::endl;

  Foo one("one");
  Bar two("two");

  std::cout << one << " / " << two << std::endl;

  return 0;
}

This is the result of compiling on Apple Clang (notice the warnings for both uses of the alias):

$ clang++ -std=c++17 -Wall -o test_deprecation test_deprecation.cpp 
test_deprecation.cpp:25:8: warning: 'Bar' is deprecated [-Wdeprecated-declarations]
   25 |     << Bar("two") << std::endl;
      |        ^
test_deprecation.cpp:19:3: note: 'Bar' has been explicitly marked deprecated here
   19 | [[deprecated]] typedef Foo Bar;
      |   ^
test_deprecation.cpp:28:3: warning: 'Bar' is deprecated [-Wdeprecated-declarations]
   28 |   Bar two("two");
      |   ^
test_deprecation.cpp:19:3: note: 'Bar' has been explicitly marked deprecated here
   19 | [[deprecated]] typedef Foo Bar;
      |   ^
2 warnings generated.

This is the result on GCC (notice the warning only for the second usage but not the one within the streaming) (and here is a Godbolt link):

$ g++ -std=c++17 -Wall -o test_deprecation test_deprecation.cpp
test_deprecation.cpp: In function ‘int main()’:
test_deprecation.cpp:28:10: warning: ‘Bar’ is deprecated [-Wdeprecated-declarations]
   28 |   Bar two("two");
      |          ^
test_deprecation.cpp:19:28: note: declared here
   19 | [[deprecated]] typedef Foo Bar;
      |     

And this is the result from MSVC (same as GCC, and here is a Godbolt link):

example.cpp
<source>(28): warning C4996: 'Bar': was declared deprecated
ASM generation compiler returned: 0

I have also tried deprecating a using statement instead of a typedef with the exact same result on all three compilers:

using Bar [[deprecated]] = Foo;

I hate to use the "this is a compiler bug" trope but ... I think this is a compiler bug (really, compilers' bugs). Am I missing something?

Upvotes: 2

Views: 94

Answers (0)

Related Questions