diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-11-18 18:10:53 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-11-18 18:10:53 +0000 |
commit | 76d69bb7f984c390f90504a06dfc7485387ffdd7 (patch) | |
tree | 5932d2f4a8f25691000dacb198368d52f629b68c | |
parent | a4f64805e032fa6a669434ca3f9c04b02f1bbd97 (diff) |
CastsAwayConstness shouldn't care if member pointers point into different classes. Fixes PR5545.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89215 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 26 | ||||
-rw-r--r-- | test/SemaCXX/reinterpret-cast.cpp | 6 |
2 files changed, 31 insertions, 1 deletions
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index e5ad338502..6b4f87ef1d 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -175,6 +175,30 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, return ExprError(); } +/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes, +/// this removes one level of indirection from both types, provided that they're +/// the same kind of pointer (plain or to-member). Unlike the Sema function, +/// this one doesn't care if the two pointers-to-member don't point into the +/// same class. This is because CastsAwayConstness doesn't care. +bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { + const PointerType *T1PtrType = T1->getAs<PointerType>(), + *T2PtrType = T2->getAs<PointerType>(); + if (T1PtrType && T2PtrType) { + T1 = T1PtrType->getPointeeType(); + T2 = T2PtrType->getPointeeType(); + return true; + } + + const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(), + *T2MPType = T2->getAs<MemberPointerType>(); + if (T1MPType && T2MPType) { + T1 = T1MPType->getPointeeType(); + T2 = T2MPType->getPointeeType(); + return true; + } + return false; +} + /// 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) @@ -195,7 +219,7 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { llvm::SmallVector<Qualifiers, 8> cv1, cv2; // Find the qualifications. - while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { + while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { cv1.push_back(UnwrappedSrcType.getQualifiers()); cv2.push_back(UnwrappedDestType.getQualifiers()); } diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp index 91b72cc022..be960a3af8 100644 --- a/test/SemaCXX/reinterpret-cast.cpp +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -88,3 +88,9 @@ void memptrs() (void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (struct structure::*)()' is not allowed}} (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int struct structure::*' is not allowed}} } + +// PR5545 +class A; +class B; +void (A::*a)(); +void (B::*b)() = reinterpret_cast<void (B::*)()>(a); |