aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--lib/Sema/SemaCXXCast.cpp7
-rw-r--r--test/SemaCXX/member-pointer-ms.cpp8
3 files changed, 18 insertions, 0 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 7cdc9f49c7..1d85979621 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2342,6 +2342,9 @@ def err_bad_static_cast_pointer_nonpointer : Error<
"cannot cast from type %1 to pointer type %2">;
def err_bad_static_cast_member_pointer_nonmp : Error<
"cannot cast from type %1 to member pointer type %2">;
+def err_bad_cxx_cast_member_pointer_size : Error<
+ "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer "
+ "type %1 to member pointer type %2 of different size">;
def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">;
// These messages don't adhere to the pattern.
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 59df294772..54018005dc 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -1103,6 +1103,13 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
return TC_Failed;
}
+ // Don't allow casting between member pointers of different sizes.
+ if (Self.Context.getTypeSize(DestMemPtr) !=
+ Self.Context.getTypeSize(SrcMemPtr)) {
+ msg = diag::err_bad_cxx_cast_member_pointer_size;
+ return TC_Failed;
+ }
+
// A valid member pointer cast.
Kind = IsLValueCast? CastExpr::CK_LValueBitCast : CastExpr::CK_BitCast;
return TC_Success;
diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp
index 8987f6d66f..3b2d0fceb9 100644
--- a/test/SemaCXX/member-pointer-ms.cpp
+++ b/test/SemaCXX/member-pointer-ms.cpp
@@ -4,3 +4,11 @@
struct A; //expected-note{{forward declaration of 'A'}}
int A::*pai1; //expected-error{{incomplete type 'A'}}
+// Test that we don't allow reinterpret_casts from pointers of one size to
+// pointers of a different size.
+struct A {};
+struct B {};
+struct C: A, B {};
+
+void (A::*paf)();
+void (C::*pcf)() = reinterpret_cast<void (C::*)()>(paf); //expected-error{{cannot reinterpret_cast from member pointer type}}