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