[PATCH] D87565: [Sema] Improve const_cast conformance to N4261
Mark de Wever via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Sat Sep 12 10:53:59 PDT 2020
Mordante created this revision.
Mordante added reviewers: rjmccall, rsmith.
Mordante added a project: clang.
Mordante requested review of this revision.
Allows `const_cast`s of similar non-record types.
Repository:
rG LLVM Github Monorepo
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 {};
@@ -71,12 +74,30 @@
f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}}
void (A::*mfn)() = 0;
(void)const_cast<void (A::*)()>(mfn); // expected-error-re {{const_cast to 'void (A::*)(){{( __attribute__\(\(thiscall\)\))?}}', which is not a reference, pointer-to-object, or pointer-to-data-member}}
- (void)const_cast<int&&>(0); // expected-error {{const_cast from rvalue to reference type 'int &&'}}
+ (void)const_cast<int&&>(0);
+#if __cplusplus < 201703L // N4261
+ // expected-error at -2 {{const_cast from rvalue to reference type 'int &&'}}
+#endif
#if __cplusplus <= 199711L // C++03 or earlier modes
- // expected-warning at -2 {{rvalue references are a C++11 extension}}
+ // expected-warning at -5 {{rvalue references are a C++11 extension}}
#endif
return **var3;
}
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{});
+#if __cplusplus < 201703L
+// expected-error at -2 {{const_cast from rvalue to reference type 'N4261::A &&' (aka 'int *(&&)[3]')}}
+#endif
+} // namespace N4261
+#endif
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -1769,7 +1769,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
@@ -1790,16 +1790,23 @@
}
if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isRValue()) {
- if (!SrcType->isRecordType()) {
+ // Materialize the class prvalue so that the const_cast can bind a
+ // reference to it.
+ NeedToMaterializeTemporary = 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.
+ //
+ // Prior to C++17 only RecordTypes were allowed.
+ if (!NeedToMaterializeTemporary && !Self.getLangOpts().CPlusPlus17) {
// 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.291404.patch
Type: text/x-patch
Size: 3949 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200912/90814858/attachment.bin>
More information about the cfe-commits
mailing list