aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2009-11-18 18:10:53 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2009-11-18 18:10:53 +0000
commit76d69bb7f984c390f90504a06dfc7485387ffdd7 (patch)
tree5932d2f4a8f25691000dacb198368d52f629b68c
parenta4f64805e032fa6a669434ca3f9c04b02f1bbd97 (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.cpp26
-rw-r--r--test/SemaCXX/reinterpret-cast.cpp6
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);