This is an archive of the discontinued LLVM Phabricator instance.

[Sema] Allow static_cast<T&&>(e) to check explicit conversions for non-reference-related types.
ClosedPublic

Authored by EricWF on Nov 1 2016, 7:48 PM.

Details

Summary

[expr.cast.static] states:

  1. A glvalue of type “cv1 T1” can be cast to type “rvalue reference to cv2 T2” if “cv2 T2” is reference-compatible

with “cv1 T1”. The result refers to the object or the specified base class subobject thereof. If T2 is
an inaccessible or ambiguous base class of T1, a program that necessitates such a cast is
ill-formed.

  1. Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_-

cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t. [...]

Currently when checking p3 Clang will diagnose static_cast<T&&>(e) as invalid if the argument is not reference compatible with T. However I believe the correct behavior is to also check p4 in those cases. For example:

double y = 42;
static_cast<int&&>(y); // this should be OK.  'int&& t(y)' is well formed

Note that we still don't check p4 for non-reference-compatible types which are reference-related since T&& t(e); should never be well formed in those cases.

Diff Detail

Event Timeline

EricWF updated this revision to Diff 76667.Nov 1 2016, 7:48 PM
EricWF retitled this revision from to [Sema] Allow static_cast<T&&>(e) to check explicit conversions for non-reference-related types..
EricWF updated this object.
EricWF added a reviewer: rsmith.
EricWF added a subscriber: cfe-commits.
EricWF planned changes to this revision.Nov 2 2016, 1:18 AM

The C++1z wording here is much different than the C++11 wording I was looking at earlier. I'm going to re-adjust this patch to target the new C++1z wording. I'm also planning to add a test under test/CXX/expr/expr.post/expr.static.cast.

EricWF updated this revision to Diff 76775.Nov 2 2016, 1:30 PM
  • Add tests under test/CXX
  • Add FIXME regarding the C++1z change from glvalue to lvalue in p3.
rsmith accepted this revision.Nov 2 2016, 4:06 PM
rsmith edited edge metadata.
rsmith added inline comments.
include/clang/Basic/DiagnosticSemaKinds.td
5949

Delete the first "reference" here. We're never casting from a reference (there are no expressions of reference type).

lib/Sema/SemaCast.cpp
1148

Actually, it does, but it's covered by p4. (p3 now only covers the special lvalue->xvalue case for static_cast, which is not permitted by p4.) It's fine for us to still handle this here, or to allow the p4 case to deal with it instead. It's probably better to keep handling it here, since we produce better diagnostics this way.

1171–1173

OK, so the idea here is that p4 will never apply in a case where the reference is reference-related to the source but not reference-compatible, and no other rules would let us static_cast to reference type? It would be good to add a comment explaining that, since it's not immediately obvious.

test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp
29 ↗(On Diff #76775)

It'd be good to also have some negative tests here, for cases like

A &&ar8 = static_cast<A&&>(prvalue<const A>());
This revision is now accepted and ready to land.Nov 2 2016, 4:06 PM
EricWF marked 2 inline comments as done.Nov 2 2016, 7:22 PM
EricWF added inline comments.
lib/Sema/SemaCast.cpp
1148

Cool sounds good. I knew p4 would end up handling it, but I wasn't sure if forwarding to p4 would allow previously ill-formed conversions. I tried to construct such a case but couldn't.

1171–1173

That's my understanding. I'll add a comment.

EricWF closed this revision.Nov 2 2016, 7:22 PM
EricWF marked an inline comment as done.