зеркало из https://github.com/microsoft/clang.git
Perform overload resolution when static_cast'ing from a
pointer-to-member-to-derived to a pointer-to-member-to-base. Fixes PR6072. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97923 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
a1a9f03585
Коммит
4ce46c2db2
|
@ -178,6 +178,11 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void AggExprEmitter::VisitCastExpr(CastExpr *E) {
|
||||
if (!DestPtr) {
|
||||
Visit(E->getSubExpr());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (E->getCastKind()) {
|
||||
default: assert(0 && "Unhandled cast kind!");
|
||||
|
||||
|
@ -205,6 +210,11 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
|
|||
break;
|
||||
|
||||
case CastExpr::CK_NullToMemberPointer: {
|
||||
// If the subexpression's type is the C++0x nullptr_t, emit the
|
||||
// subexpression, which may have side effects.
|
||||
if (E->getSubExpr()->getType()->isNullPtrType())
|
||||
Visit(E->getSubExpr());
|
||||
|
||||
const llvm::Type *PtrDiffTy =
|
||||
CGF.ConvertType(CGF.getContext().getPointerDiffType());
|
||||
|
||||
|
|
|
@ -84,7 +84,8 @@ static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
|
|||
QualType OrigSrcType,
|
||||
QualType OrigDestType, unsigned &msg,
|
||||
CastExpr::CastKind &Kind);
|
||||
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType,
|
||||
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr,
|
||||
QualType SrcType,
|
||||
QualType DestType,bool CStyle,
|
||||
const SourceRange &OpRange,
|
||||
unsigned &msg,
|
||||
|
@ -554,7 +555,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
|
|||
// Reverse member pointer conversion. C++ 4.11 specifies member pointer
|
||||
// conversion. C++ 5.2.9p9 has additional information.
|
||||
// DR54's access restrictions apply here also.
|
||||
tcr = TryStaticMemberPointerUpcast(Self, SrcType, DestType, CStyle,
|
||||
tcr = TryStaticMemberPointerUpcast(Self, SrcExpr, SrcType, DestType, CStyle,
|
||||
OpRange, msg, Kind);
|
||||
if (tcr != TC_NotApplicable)
|
||||
return tcr;
|
||||
|
@ -798,12 +799,23 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
|
|||
/// where B is a base class of D [...].
|
||||
///
|
||||
TryCastResult
|
||||
TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
|
||||
bool CStyle, const SourceRange &OpRange,
|
||||
TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
|
||||
QualType DestType, bool CStyle,
|
||||
const SourceRange &OpRange,
|
||||
unsigned &msg, CastExpr::CastKind &Kind) {
|
||||
const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
|
||||
if (!DestMemPtr)
|
||||
return TC_NotApplicable;
|
||||
|
||||
bool WasOverloadedFunction = false;
|
||||
if (FunctionDecl *Fn
|
||||
= Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false)) {
|
||||
CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
|
||||
SrcType = Self.Context.getMemberPointerType(Fn->getType(),
|
||||
Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
|
||||
WasOverloadedFunction = true;
|
||||
}
|
||||
|
||||
const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>();
|
||||
if (!SrcMemPtr) {
|
||||
msg = diag::err_bad_static_cast_member_pointer_nonmp;
|
||||
|
@ -853,6 +865,24 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
|
|||
return TC_Failed;
|
||||
}
|
||||
|
||||
if (WasOverloadedFunction) {
|
||||
// Resolve the address of the overloaded function again, this time
|
||||
// allowing complaints if something goes wrong.
|
||||
FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr,
|
||||
DestType,
|
||||
true);
|
||||
if (!Fn) {
|
||||
msg = 0;
|
||||
return TC_Failed;
|
||||
}
|
||||
|
||||
SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, Fn);
|
||||
if (!SrcExpr) {
|
||||
msg = 0;
|
||||
return TC_Failed;
|
||||
}
|
||||
}
|
||||
|
||||
Kind = CastExpr::CK_DerivedToBaseMemberPointer;
|
||||
return TC_Success;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
// RUN: %clang_cc1 -std=c++0x %s -emit-llvm -o %t
|
||||
// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
int* a = nullptr;
|
||||
|
||||
void f() {
|
||||
int* a = nullptr;
|
||||
}
|
||||
|
||||
typedef decltype(nullptr) nullptr_t;
|
||||
|
||||
nullptr_t get_nullptr();
|
||||
|
||||
struct X { };
|
||||
void g() {
|
||||
// CHECK: call i8* @_Z11get_nullptrv()
|
||||
int (X::*pmf)(int) = get_nullptr();
|
||||
}
|
||||
|
|
|
@ -181,3 +181,17 @@ struct X4 {
|
|||
|
||||
// PR5897 - accept static_cast from const void* to const int (*)[1].
|
||||
void PR5897() { (void)static_cast<const int(*)[1]>((const void*)0); }
|
||||
|
||||
namespace PR6072 {
|
||||
struct A { };
|
||||
struct B : A { void f(int); void f(); };
|
||||
struct C : B { };
|
||||
struct D { };
|
||||
|
||||
void f() {
|
||||
(void)static_cast<void (A::*)()>(&B::f);
|
||||
(void)static_cast<void (B::*)()>(&B::f);
|
||||
(void)static_cast<void (C::*)()>(&B::f);
|
||||
(void)static_cast<void (D::*)()>(&B::f); // expected-error{{static_cast from '<overloaded function type>' to 'void (struct PR6072::D::*)()' is not allowed}}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче