[PATCH] D87565: [Sema] Improve const_cast conformance to N4261
Mark de Wever via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 17 10:42:54 PDT 2020
Mordante updated this revision to Diff 298838.
Mordante marked an inline comment as done.
Mordante added a comment.
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?
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D87565/new/
https://reviews.llvm.org/D87565
Files:
clang/lib/Sema/SemaCast.cpp
clang/test/SemaCXX/const-cast.cpp
Index: clang/test/SemaCXX/const-cast.cpp
===================================================================
--- clang/test/SemaCXX/const-cast.cpp
+++ clang/test/SemaCXX/const-cast.cpp
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
struct A {};
@@ -80,3 +83,35 @@
template <typename T>
char *PR21845() { return const_cast<char *>((void)T::x); } // expected-error {{const_cast from 'void' to 'char *' is not allowed}}
+
+#if __cplusplus >= 201103L
+namespace N4261 {
+typedef int *A[3];
+typedef const int *const CA[3];
+
+CA &&r = A{};
+A &&r1 = const_cast<A>(CA{}); // expected-error {{const_cast to 'N4261::A' (aka 'int *[3]'), which is not a reference, pointer-to-object, or pointer-to-data-member}}
+
+A &&r2 = const_cast<A &&>(CA{});
+
+void f() {
+ typedef void (*F)();
+ F &&f = F{};
+ (void)const_cast<F>(F{}); // expected-error {{const_cast to 'F' (aka 'void (*)()'), which is not a reference, pointer-to-object, or pointer-to-data-member}}
+ (void)const_cast<F &&>(F{}); // expected-error {{const_cast from rvalue to reference type 'F &&' (aka 'void (*&&)()')}}
+
+ class C;
+ typedef void (C::*CF)();
+ CF &&cf = CF{};
+ (void)const_cast<CF>(CF{}); // expected-error {{const_cast to 'CF' (aka 'void (C::*)()'), which is not a reference, pointer-to-object, or pointer-to-data-member}}
+ (void)const_cast<CF &&>(CF{}); // expected-error {{const_cast from rvalue to reference type 'CF &&' (aka 'void (C::*&&)()')}}
+
+ typedef int C::*CM;
+ CM &&cm = CM{};
+ (void)const_cast<CM>(CM{});
+ (void)const_cast<CM &&>(CM{}); // expected-error {{const_cast from rvalue to reference type 'CM &&' (aka 'int C::*&&')}}
+}
+
+} // namespace N4261
+
+#endif
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -1780,7 +1780,7 @@
QualType SrcType = SrcExpr.get()->getType();
bool NeedToMaterializeTemporary = false;
- if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) {
+ if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
// C++11 5.2.11p4:
// if a pointer to T1 can be explicitly converted to the type "pointer to
// T2" using a const_cast, then the following conversions can also be
@@ -1801,16 +1801,28 @@
}
if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isRValue()) {
- if (!SrcType->isRecordType()) {
+ // C++17 [expr.const.cast]p3
+ // For two similar types T1 and T2, a prvalue of type T1 may be explicitly
+ // converted to the type T2 using a const_cast if, considering the
+ // cv-decompositions of both types, each P1i is the same as P2i for all i.
+ // The result of a const_cast refers to the original entity.
+ //
+ // The test for the similarity is done later in this function. Here it
+ // only avoids issuing an diagnostic for possible similar types.
+ //
+ // [expr.const.cast]p4
+ // The result of a reference const_cast refers to the original object if
+ // the operand is a glvalue and to the result of applying the temporary
+ // materialization conversion otherwise.
+ NeedToMaterializeTemporary =
+ SrcType->isRecordType() || SrcType->isArrayType();
+
+ if (!NeedToMaterializeTemporary) {
// Cannot const_cast non-class prvalue to rvalue reference type. But if
// this is C-style, static_cast can do this.
msg = diag::err_bad_cxx_cast_rvalue;
return TC_NotApplicable;
}
-
- // Materialize the class prvalue so that the const_cast can bind a
- // reference to it.
- NeedToMaterializeTemporary = true;
}
// It's not completely clear under the standard whether we can
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87565.298838.patch
Type: text/x-patch
Size: 4079 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20201017/55fbade7/attachment.bin>
More information about the cfe-commits
mailing list