Allows const_casts of similar non-record types.
Diff Detail
Event Timeline
clang/lib/Sema/SemaCast.cpp | ||
---|---|---|
1792–1793 | This is the bullet that causes class pvalues and non-class prvalues to be treated differently by const_cast to an rvalue reference type, and it still exists unchanged in the latest C++ draft. As far as I can tell, the change here is not in line with the wording for N4261 / CWG issue 330, which Clang does implement. (Now, I think the change you're suggesting here makes a lot of sense, but we should get agreement in WG21 to fix the language rules first.) | |
1808–1812 | In (for example) const_cast<int&&>(0);, T1 is int, and T2 is "rvalue reference to int". T1 and T2 are not similar types, because they have different types U (for T1, U is int; for T2, U is "rvalue reference to int"). So this doesn't apply. |
For what it's worth, the most recent thoughts from CWG on this question are from 2015 (prior to guaranteed copy elision, which probably changes the answer): http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1965. That direction would permit const_cast to rvalue reference type to materialize a temporary for arrays and classes but not scalar types (which seems just as arbitrary as the current set of rules to me).
Thanks for the additional information. I agree that the current situation seems a bit arbitrary.
I did some further research to see what GCC allows https://godbolt.org/. I've updated the patch to match that behavior.
Match the behavior of const_cast to match GCC's behavior. N4261 was proposed as solution to DR330. Since GCC allows the new const_cast behavior retroactively the patch also matches that behavior and no longer restricts the new usage to C++17.
clang/lib/Sema/SemaCast.cpp | ||
---|---|---|
1817–1819 | It looks like GCC allowing a cast from T* to T*&& is just a bug in their implementation. Consider: using T = int*; T &&r1 = const_cast<T&&>(T{}); // GCC accepts T &&r2 = const_cast<T&&>(T()); // GCC rejects ... and the same behavior seems to show up for all scalar types: they permit const_cast from T{} but not from T() when T is int, int*, .... This doesn't seem like good behavior to follow. I think we should either implement the current direction of 1965 (that is, only allow classes and arrays here) or leave the current behavior (following the standard as-is) alone. |
clang/lib/Sema/SemaCast.cpp | ||
---|---|---|
1817–1819 |
Interesting I hadn't test with T() only with T{}
Agreed.
I'll then limit the patch to array types (next to the already allowed record types.
Now I'm somewhat confused, because I thought arrays are allowed in the standard http://eel.is/c++draft/expr.const.cast#3 as introduced by N4261. |
Removes the support for the pointer types.
I adjusted the unit test for void f(), but I think it would be better remove this test now pointers are no longer allowed. Do you agree?
This is the bullet that causes class pvalues and non-class prvalues to be treated differently by const_cast to an rvalue reference type, and it still exists unchanged in the latest C++ draft. As far as I can tell, the change here is not in line with the wording for N4261 / CWG issue 330, which Clang does implement.
(Now, I think the change you're suggesting here makes a lot of sense, but we should get agreement in WG21 to fix the language rules first.)