]> granicus.if.org Git - clang/commitdiff
Perform overload resolution when static_cast'ing from a
authorDouglas Gregor <dgregor@apple.com>
Sun, 7 Mar 2010 23:24:59 +0000 (23:24 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sun, 7 Mar 2010 23:24:59 +0000 (23:24 +0000)
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

lib/CodeGen/CGExprAgg.cpp
lib/Sema/SemaCXXCast.cpp
test/CodeGenCXX/nullptr.cpp
test/SemaCXX/static-cast.cpp

index ac189a0649047e50011c0c8ffbb6a809a3d68e44..5af6f91d14894acc071749a0b3e72932f9f3ec75 100644 (file)
@@ -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());
 
index 0097cd363c8caa81a8040813062df7a664f5b4cd..e04abd2aac97e232626f8edc3571357aff2aaa79 100644 (file)
@@ -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;
 }
index 31bd47522ed4466fb44b5d0e1e29a27abdb2e76d..ab63b432bdfa65ee648f35bf973dd3dbfaa78fc6 100644 (file)
@@ -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();
+}
index 4818b041ad08f39c55a50c52ba670e3fe61d7e43..efdc276e7d0cbe7926a5cee0e1f65ba706085f2a 100644 (file)
@@ -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}}
+  }
+}