[cfe-commits] r97923 - in /cfe/trunk: lib/CodeGen/CGExprAgg.cpp lib/Sema/SemaCXXCast.cpp test/CodeGenCXX/nullptr.cpp test/SemaCXX/static-cast.cpp

Douglas Gregor dgregor at apple.com
Sun Mar 7 15:24:59 PST 2010


Author: dgregor
Date: Sun Mar  7 17:24:59 2010
New Revision: 97923

URL: http://llvm.org/viewvc/llvm-project?rev=97923&view=rev
Log:
Perform overload resolution when static_cast'ing from a
pointer-to-member-to-derived to a pointer-to-member-to-base. Fixes
PR6072.

Modified:
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/test/CodeGenCXX/nullptr.cpp
    cfe/trunk/test/SemaCXX/static-cast.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=97923&r1=97922&r2=97923&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Sun Mar  7 17:24:59 2010
@@ -178,6 +178,11 @@
 //===----------------------------------------------------------------------===//
 
 void AggExprEmitter::VisitCastExpr(CastExpr *E) {
+  if (!DestPtr) {
+    Visit(E->getSubExpr());
+    return;
+  }
+
   switch (E->getCastKind()) {
   default: assert(0 && "Unhandled cast kind!");
 
@@ -205,6 +210,11 @@
     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());
 

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=97923&r1=97922&r2=97923&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Sun Mar  7 17:24:59 2010
@@ -84,7 +84,8 @@
                                        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 @@
   // 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 @@
 ///   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 @@
     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;
 }

Modified: cfe/trunk/test/CodeGenCXX/nullptr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/nullptr.cpp?rev=97923&r1=97922&r2=97923&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/nullptr.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/nullptr.cpp Sun Mar  7 17:24:59 2010
@@ -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();
+}

Modified: cfe/trunk/test/SemaCXX/static-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/static-cast.cpp?rev=97923&r1=97922&r2=97923&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/static-cast.cpp (original)
+++ cfe/trunk/test/SemaCXX/static-cast.cpp Sun Mar  7 17:24:59 2010
@@ -181,3 +181,17 @@
 
 // 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}}
+  }
+}





More information about the cfe-commits mailing list