The implementation of P1152R4 in Clang has resulted in some deprecation warnings appearing in the libc++ and libc++abi test suite. Fix or suppress these warnings.
mclow.lists EricWF ldionne
- rCXXA375307: P1152R4: Fix deprecation warnings in libc++ testsuite and in uses of…
rCXX375307: P1152R4: Fix deprecation warnings in libc++ testsuite and in uses of…
rGa9727033fb5f: P1152R4: Fix deprecation warnings in libc++ testsuite and in uses of…
rL375307: P1152R4: Fix deprecation warnings in libc++ testsuite and in uses of…
Please document that we're talking about compiler deprecation warnings, otherwise this can be confused as also turning off library deprecation warnings. Ignoring -Wdeprecated won't have that effect, right?
// Macros to enter and leave a state where compiler deprecation warnings are suppressed. This doesn't impact library deprecation warnings.
Or something along those lines.
Please indent nested #defines:
# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH
Wait, I don't see any volatile qualification here?
Extend comment to explain how __declval gets a volatile-qualified return type.
Ignoring -Wdeprecated turns off all deprecation warnings, regardless of whether they come from attributes or something else. (This might also be useful if libc++ wants to implement something in terms of deprecated library functionality.)
The volatile comes from _Tp, specified indirectly through various callers that internally use declval. In particular, the is_invocable<volatile T> tests end up here.
That's what I thought, but isn't that warning broken then? Isn't any template going to produce a warning when instantiated with a volatile T? I must be misunderstanding something.
We warn when instantiating the second overload of __declval with _Tp = volatile T, because that causes it to have a volatile-qualified return type, which is deprecated. We don't warn on the first overload, because it doesn't have a volatile-qualified return type regardless of _Tp. Does that make more sense?
Let's not block this because I have questions about the warning implemented in Clang. Richard, you can ship this. Thanks for the fix and sorry for the delay.
My question was: why don't we warn in the location where the user says std::declval<volatile Foo>(), and only there?
The thing that's deprecated is declaring a function with a volatile-qualified function type, so we warn at the point where that happens, which is here, inside the implementation of declval. (This warning will be "in instantiation of" something else, but we use the warning state at the location the warning is pointed at, not the warning state at the point of instantiation, which is why we need the suppression here.)
Note that decltype(_VSTD::__declval<volatile Foo>(0)) (the return type of declval below) will be (non-volatile) Foo if Foo is not a class type, because there are no volatile-qualified non-class (non-array) prvalues. So the volatile gets stripped off before we even get to std::declval. The volatile only appears here temporarily as an implementation detail. Incidentally, the only case when we'll actually select the __declval overload with a volatile-qualified return type is when calling declval<volatile void>(), because all non-volatile _Tps will call the other __declval overload.
This could possibly be fixed in a different way, by rewriting declval to follow the way the standard specifies it:
template<class T> add_rvalue_reference_t<T> declval() noexcept;
This would only warn when T is (possibly-const) volatile void, which seems appropriate. However, I suspect the class template instantiation in here would be significantly more expensive than the current implementation. Maybe we could add an __add_rvalue_reference builtin to Clang for use implementing declval?