This is an archive of the discontinued LLVM Phabricator instance.

[libcxx] Add deprecation notices to macros deprecated in P0883R2
ClosedPublic

Authored by tambre on Dec 18 2021, 12:25 PM.

Details

Summary

When P0883R2 was initially implemented in D103769 #pragma clang deprecated didn't exist yet.
We also forgot to cleanup usages in libc++ itself.

This takes care of both.

Diff Detail

Event Timeline

tambre requested review of this revision.Dec 18 2021, 12:25 PM
tambre created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptDec 18 2021, 12:25 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript

Should I bump the version listed for P0883R2 to 14.0? This only adds an extra non-mandated deprecation warning.

libcxx/include/atomic
2703

Separate macro deprecation macros didn't seem worth it as this is likely to be the only place we'd use them for a while. Since other compilers should simply ignore these guarding these shouldn't be necessary either.

Quuxplusone requested changes to this revision.Dec 19 2021, 8:08 AM

LGTM mod important comment.

libcxx/include/atomic
2703

Sadly "other compilers" includes "old Clang."

atomic:2703:15: error: unknown pragma ignored [-Werror,-Wunknown-pragmas]
#pragma clang deprecated(ATOMIC_FLAG_INIT)
              ^

So this should be guarded somehow.
Today, if I grepped correctly, libcxx has zero instances of any pragma clang or pragma GCC except for pragma {clang,GCC} diagnostic. So we're unlikely to have any precedent for how to deal with conditionally supported pragmas. I suggest just this:

#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS)
# if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1400
#  pragma clang deprecated ~~~
# endif
#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS)

(Separating the "semantic, why" from the "compiler-specific, how" — but really I did that only so I wouldn't have to deal with a super-long line. ;))

This revision now requires changes to proceed.Dec 19 2021, 8:08 AM
tambre updated this revision to Diff 395336.Dec 19 2021, 8:39 AM
tambre marked an inline comment as done.

Guard deprecation macros

libcxx/include/atomic
2703

Good point, done.

ldionne accepted this revision.Dec 20 2021, 8:01 AM

Should I bump the version listed for P0883R2 to 14.0? This only adds an extra non-mandated deprecation warning.

Yes, I suggest we bump it so as to not advertise that we implemented a paper fully when we didn't.

LGTM but please update the status page. Thanks a lot for the patch!

tambre updated this revision to Diff 395488.Dec 20 2021, 10:00 AM

Update paper status to version 14.0

This revision was not accepted when it landed; it landed in state Needs Review.Dec 20 2021, 10:30 AM
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.

Okay, now that I'm hitting this in a real codebase, I'm stumped as to what the (WG21 and/or libc++) recommendation is, here. ATOMIC_FLAG_INIT is required up-to-and-including C++17, and then deprecated in-and-above C++20? So if I have code in my codebase today like

std::atomic_flag flag_ = ATOMIC_FLAG_INIT;

should I change it to

std::atomic_flag flag_ = {false};

or

std::atomic_flag flag_;

or what? How am I supposed to eliminate the deprecation warning? I've thought of

  • stop allowing my codebase to compile in C++17 mode; require C++20 (this is a non-starter)
  • write my own macro using #if __cplusplus >= 201700L
  • turn on -Wno-deprecated in the build system
  • just use = {false}; or ; on the assumption that I can file bugs against any library vendor that I catch doing the Wrong Thing in C++17 mode (but then I'd have to fall back to one of the other options anyway)

None of these options feel very nice.

This is the same situation we had with random_shuffle in C++11: https://stackoverflow.com/questions/27791474/what-are-best-practices-for-simple-random-shuffling-in-code-thats-both-c03-an

Okay, now that I'm hitting this in a real codebase, I'm stumped as to what the (WG21 and/or libc++) recommendation is, here. ATOMIC_FLAG_INIT is required up-to-and-including C++17, and then deprecated in-and-above C++20? So if I have code in my codebase today like

I don't see why you'd think using the macro would be required.

How am I supposed to eliminate the deprecation warning?

Explictly init to false. If C++20 and higher, then you can rely on the default constructor.

Okay, now that I'm hitting this in a real codebase, I'm stumped as to what the (WG21 and/or libc++) recommendation is, here. ATOMIC_FLAG_INIT is required up-to-and-including C++17, and then deprecated in-and-above C++20? So if I have code in my codebase today like

I don't see why you'd think using the macro would be required.

AFAICT, on paper, C++17/20 atomic_flag has no constructors
https://en.cppreference.com/w/cpp/atomic/atomic_flag/atomic_flag
except for the default constructor (trivial in C++17) and the deleted copy constructor. So if you want an atomic_flag initialized with false, you need some way of getting false into it. On paper, there's no guarantee that std::atomic_flag f = {false}; will compile. But I just checked Godbolt and every major compiler does support that syntax, so I suppose it's safe to use in practice: https://godbolt.org/z/4cbbGcv96

Explicitly init to false. If C++20 and higher, then you can rely on the default constructor.

Yeah, the default ctor definitely works in C++20-and-above. Below C++20, the default ctor is on-paper "guaranteed" to be trivial and thus "guaranteed" not to work; but it looks like implementations largely ignore that, too, AFAICT, and just do the C++20 thing everywhere (plus the extra constructor from bool which is super helpful).

Anyway, I've added -Wno-deprecated-pragma to my build flags for now; that's not as terrible-feeling a workaround as I was worried it would be. And ultimately we'll probably just use the atomic_flag(bool) ctor, even though (AFAICT) it's technically an extension.

Okay, now that I'm hitting this in a real codebase, I'm stumped as to what the (WG21 and/or libc++) recommendation is, here. ATOMIC_FLAG_INIT is required up-to-and-including C++17, and then deprecated in-and-above C++20? So if I have code in my codebase today like

I don't see why you'd think using the macro would be required.

AFAICT, on paper, C++17/20 atomic_flag has no constructors
https://en.cppreference.com/w/cpp/atomic/atomic_flag/atomic_flag
except for the default constructor (trivial in C++17) and the deleted copy constructor. So if you want an atomic_flag initialized with false, you need some way of getting false into it. On paper, there's no guarantee that std::atomic_flag f = {false}; will compile. But I just checked Godbolt and every major compiler does support that syntax, so I suppose it's safe to use in practice: https://godbolt.org/z/4cbbGcv96

Ouch, you're correct. I was looking at std::atomic' not std::atomic_flag. Does seem like an oversight.