From db64728e69a45b89870ede13944a934d3c2ed12a Mon Sep 17 00:00:00 2001
From: Sebastian Redl
Date: Tue, 27 Jan 2009 23:18:31 +0000
Subject: [PATCH] Add handling of member pointers to reinterpret_cast.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63150 91177308-0d34-0410-b5e6-96231b3b80d8
---
lib/Sema/SemaNamedCast.cpp | 55 ++++++++++++++++++++++---------
test/SemaCXX/reinterpret-cast.cpp | 18 ++++++++++
www/cxx_status.html | 6 ++--
3 files changed, 61 insertions(+), 18 deletions(-)
diff --git a/lib/Sema/SemaNamedCast.cpp b/lib/Sema/SemaNamedCast.cpp
index 17de7321de..e88a3b2079 100644
--- a/lib/Sema/SemaNamedCast.cpp
+++ b/lib/Sema/SemaNamedCast.cpp
@@ -237,6 +237,32 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
// Canonicalize source for comparison.
SrcType = Self.Context.getCanonicalType(SrcType);
+ const MemberPointerType *DestMemPtr = DestType->getAsMemberPointerType(),
+ *SrcMemPtr = SrcType->getAsMemberPointerType();
+ if (DestMemPtr && SrcMemPtr) {
+ // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1"
+ // can be explicitly converted to an rvalue of type "pointer to member
+ // of Y of type T2" if T1 and T2 are both function types or both object
+ // types.
+ if (DestMemPtr->getPointeeType()->isFunctionType() !=
+ SrcMemPtr->getPointeeType()->isFunctionType()) {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic)
+ << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange;
+ return;
+ }
+
+ // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
+ // constness.
+ if (CastsAwayConstness(Self, SrcType, DestType)) {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away)
+ << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange;
+ return;
+ }
+
+ // A valid member pointer cast.
+ return;
+ }
+
bool destIsPtr = DestType->isPointerType();
bool srcIsPtr = SrcType->isPointerType();
if (!destIsPtr && !srcIsPtr) {
@@ -253,8 +279,8 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
// restrictions, a cast to the same type is allowed. The intent is not
// entirely clear here, since all other paragraphs explicitly forbid casts
// to the same type. However, the behavior of compilers is pretty consistent
- // on this point: allow same-type conversion if the involved are pointers,
- // disallow otherwise.
+ // on this point: allow same-type conversion if the involved types are
+ // pointers, disallow otherwise.
return;
}
@@ -304,8 +330,6 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
return;
}
- // FIXME: Handle member pointers.
-
// C++0x 5.2.10p8: Converting a pointer to a function into a pointer to
// an object type or vice versa is conditionally-supported.
// Compilers support it in C++03 too, though, because it's necessary for
@@ -319,8 +343,6 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
return;
}
- // FIXME: Handle member pointers.
-
if (DestType->isFunctionPointerType()) {
// See above.
if (!Self.getLangOptions().CPlusPlus0x) {
@@ -337,18 +359,21 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
// object pointers.
}
-/// CastsAwayConstness - Check if the pointer conversion from SrcType
-/// to DestType casts away constness as defined in C++
-/// 5.2.11p8ff. This is used by the cast checkers. Both arguments
-/// must denote pointer types.
+/// CastsAwayConstness - Check if the pointer conversion from SrcType to
+/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
+/// the cast checkers. Both arguments must denote pointer (possibly to member)
+/// types.
bool
CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType)
{
- // Casting away constness is defined in C++ 5.2.11p8 with reference to
- // C++ 4.4.
- // We piggyback on Sema::IsQualificationConversion for this, since the rules
- // are non-trivial. So first we construct Tcv *...cv* as described in
- // C++ 5.2.11p8.
+ // Casting away constness is defined in C++ 5.2.11p8 with reference to
+ // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
+ // the rules are non-trivial. So first we construct Tcv *...cv* as described
+ // in C++ 5.2.11p8.
+ assert((SrcType->isPointerType() || SrcType->isMemberPointerType()) &&
+ "Source type is not pointer or pointer to member.");
+ assert((DestType->isPointerType() || DestType->isMemberPointerType()) &&
+ "Destination type is not pointer or pointer to member.");
QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType;
llvm::SmallVector cv1, cv2;
diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp
index 6172c9f8d9..e6d635242d 100644
--- a/test/SemaCXX/reinterpret-cast.cpp
+++ b/test/SemaCXX/reinterpret-cast.cpp
@@ -70,3 +70,21 @@ void refs()
// Bad: from rvalue
(void)reinterpret_cast(&c); // expected-error {{reinterpret_cast from rvalue to reference type 'int &'}}
}
+
+void memptrs()
+{
+ const int structure::*psi = 0;
+ (void)reinterpret_cast(psi);
+ (void)reinterpret_cast(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'int struct structure::*' casts away constness}}
+
+ void (structure::*psf)() = 0;
+ (void)reinterpret_cast(psf);
+
+ (void)reinterpret_cast(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'void (struct structure::*)(void)' is not allowed}}
+ (void)reinterpret_cast(psf); // expected-error {{reinterpret_cast from 'void (struct structure::*)(void)' to 'int struct structure::*' is not allowed}}
+
+ // Cannot cast from integers to member pointers, not even the null pointer
+ // literal.
+ (void)reinterpret_cast(0); // expected-error {{reinterpret_cast from 'int' to 'void (struct structure::*)(void)' is not allowed}}
+ (void)reinterpret_cast(0); // expected-error {{reinterpret_cast from 'int' to 'int struct structure::*' is not allowed}}
+}
diff --git a/www/cxx_status.html b/www/cxx_status.html
index 5c57f913ab..a83157b193 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -579,10 +579,10 @@ welcome!
5.2.10 [expr.reinterpret.cast] |
✓ |
- |
- |
+ ✓ |
+ ✓ |
+ |
|
- Missing member pointer conversions |
5.2.11 [expr.const.cast] |
--
2.40.0