[PATCH] D26231: [Sema] Allow static_cast<T&&>(e) to check explicit conversions for non-reference-related types.
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 1 19:48:15 PDT 2016
EricWF created this revision.
EricWF added a reviewer: rsmith.
EricWF added a subscriber: cfe-commits.
[expr.cast.static] states:
> 3. 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.
> 4. 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.
https://reviews.llvm.org/D26231
Files:
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaCast.cpp
test/SemaCXX/rval-references.cpp
Index: test/SemaCXX/rval-references.cpp
===================================================================
--- test/SemaCXX/rval-references.cpp
+++ test/SemaCXX/rval-references.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s
typedef int&& irr;
typedef irr& ilr_c1; // Collapses to int&
@@ -30,11 +30,15 @@
int &&virr2 = 0;
int &&virr3 = virr2; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}}
int i1 = 0;
+ const double d1 = 0;
+ const int ci1 = 1;
int &&virr4 = i1; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}}
int &&virr5 = ret_irr();
int &&virr6 = static_cast<int&&>(i1);
- (void)static_cast<not_int&&>(i1); // expected-error {{types are not compatible}}
-
+ (void)static_cast<not_int &&>(i1); // expected-error {{reference to type 'not_int' could not bind to an lvalue of type 'int'}}
+ (void)static_cast<int &&>(static_cast<int const&&>(i1)); // expected-error {{cannot cast from rvalue reference of type 'const int' to rvalue reference type 'int &&'}}
+ (void)static_cast<int &&>(ci1); // expected-error {{types are not compatible}}
+ (void)static_cast<int &&>(d1);
int i2 = over(i1);
not_int ni1 = over(0);
int i3 = over(virr2);
Index: lib/Sema/SemaCast.cpp
===================================================================
--- lib/Sema/SemaCast.cpp
+++ lib/Sema/SemaCast.cpp
@@ -983,7 +983,7 @@
// C++11 [expr.static.cast]p3:
// 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".
- tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
+ tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
BasePath, msg);
if (tcr != TC_NotApplicable)
return tcr;
@@ -1134,10 +1134,10 @@
}
/// Tests whether a conversion according to N2844 is valid.
-TryCastResult
-TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
- bool CStyle, CastKind &Kind, CXXCastPath &BasePath,
- unsigned &msg) {
+TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
+ QualType DestType, bool CStyle,
+ CastKind &Kind, CXXCastPath &BasePath,
+ unsigned &msg) {
// C++11 [expr.static.cast]p3:
// 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".
@@ -1160,15 +1160,15 @@
FromType = FromType.getUnqualifiedType();
ToType = ToType.getUnqualifiedType();
}
-
- if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
- ToType, FromType,
- DerivedToBase, ObjCConversion,
- ObjCLifetimeConversion)
- != Sema::Ref_Compatible) {
- if (CStyle)
+
+ Sema::ReferenceCompareResult RefResult = Self.CompareReferenceRelationship(
+ SrcExpr->getLocStart(), ToType, FromType, DerivedToBase, ObjCConversion,
+ ObjCLifetimeConversion);
+ if (RefResult != Sema::Ref_Compatible) {
+ if (CStyle || RefResult == Sema::Ref_Incompatible)
return TC_NotApplicable;
- msg = diag::err_bad_lvalue_to_rvalue_cast;
+ msg = SrcExpr->isLValue() ? diag::err_bad_lvalue_to_rvalue_cast
+ : diag::err_bad_rvalue_to_rvalue_cast;
return TC_Failed;
}
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -5938,6 +5938,9 @@
def err_bad_lvalue_to_rvalue_cast : Error<
"cannot cast from lvalue of type %1 to rvalue reference type %2; types are "
"not compatible">;
+def err_bad_rvalue_to_rvalue_cast : Error<
+ "cannot cast from rvalue reference of type %1 to rvalue reference type %2; types are "
+ "not compatible">;
def err_bad_static_cast_pointer_nonpointer : Error<
"cannot cast from type %1 to pointer type %2">;
def err_bad_static_cast_member_pointer_nonmp : Error<
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D26231.76667.patch
Type: text/x-patch
Size: 4409 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161102/a00b3d03/attachment-0001.bin>
More information about the cfe-commits
mailing list