[cfe-commits] r63779 - in /cfe/trunk: lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp test/SemaCXX/member-pointer.cpp www/cxx_status.html

Sebastian Redl sebastian.redl at getdesigned.at
Wed Feb 4 13:23:32 PST 2009


Author: cornedbee
Date: Wed Feb  4 15:23:32 2009
New Revision: 63779

URL: http://llvm.org/viewvc/llvm-project?rev=63779&view=rev
Log:
Implement taking address of member functions, including overloaded ones.

Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/member-pointer.cpp
    cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=63779&r1=63778&r2=63779&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb  4 15:23:32 2009
@@ -3498,11 +3498,18 @@
       }
     } else if (isa<FunctionDecl>(dcl)) {
       // Okay: we can take the address of a function.
+      // As above.
+      if (isa<QualifiedDeclRefExpr>(op)) {
+        DeclContext *Ctx = dcl->getDeclContext();
+        if (Ctx && Ctx->isRecord())
+          return Context.getMemberPointerType(op->getType(),
+                Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+      }
     }
     else
       assert(0 && "Unknown/unexpected decl type");
   }
-  
+
   // If the operand has type "type", the result has type "pointer to type".
   return Context.getPointerType(op->getType());
 }

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=63779&r1=63778&r2=63779&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Feb  4 15:23:32 2009
@@ -489,7 +489,7 @@
     // type "pointer to T." The result is a pointer to the
     // function. (C++ 4.3p1).
     FromType = Context.getPointerType(FromType);
-  } 
+  }
   // Address of overloaded function (C++ [over.over]).
   else if (FunctionDecl *Fn 
              = ResolveAddressOfOverloadedFunction(From, ToType, false)) {
@@ -500,7 +500,17 @@
     FromType = Fn->getType();
     if (ToType->isReferenceType())
       FromType = Context.getReferenceType(FromType);
-    else
+    else if (ToType->isMemberPointerType()) {
+      // Resolve address only succeeds if both sides are member pointers,
+      // but it doesn't have to be the same class. See DR 247.
+      // Note that this means that the type of &Derived::fn can be
+      // Ret (Base::*)(Args) if the fn overload actually found is from the
+      // base class, even if it was brought into the derived class via a
+      // using declaration. The standard isn't clear on this issue at all.
+      CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
+      FromType = Context.getMemberPointerType(FromType,
+                    Context.getTypeDeclType(M->getParent()).getTypePtr());
+    } else
       FromType = Context.getPointerType(FromType);
   }
   // We don't require any conversions for the first step.
@@ -3409,11 +3419,17 @@
 /// resolved, and NULL otherwise. When @p Complain is true, this
 /// routine will emit diagnostics if there is an error.
 FunctionDecl *
-Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, 
+Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
                                          bool Complain) {
   QualType FunctionType = ToType;
+  bool IsMember = false;
   if (const PointerLikeType *ToTypePtr = ToType->getAsPointerLikeType())
     FunctionType = ToTypePtr->getPointeeType();
+  else if (const MemberPointerType *MemTypePtr =
+                    ToType->getAsMemberPointerType()) {
+    FunctionType = MemTypePtr->getPointeeType();
+    IsMember = true;
+  }
 
   // We only look at pointers or references to functions.
   if (!FunctionType->isFunctionType()) 
@@ -3454,10 +3470,16 @@
     // C++ [over.over]p3:
     //   Non-member functions and static member functions match
     //   targets of type “pointer-to-function”or
-    //   “reference-to-function.”
-    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Fun))
-      if (!Method->isStatic())
+    //   “reference-to-function.” Nonstatic member functions match targets of
+    //   type "pointer-to-member-function."
+    // Note that according to DR 247, the containing class does not matter.
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Fun)) {
+      // Skip non-static functions when converting to pointer, and static
+      // when converting to member pointer.
+      if (Method->isStatic() == IsMember)
         continue;
+    } else if (IsMember)
+      continue;
 
     if (FunctionType == Context.getCanonicalType((*Fun)->getType()))
       return *Fun;

Modified: cfe/trunk/test/SemaCXX/member-pointer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-pointer.cpp?rev=63779&r1=63778&r2=63779&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/member-pointer.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-pointer.cpp Wed Feb  4 15:23:32 2009
@@ -41,10 +41,19 @@
   pdi1 = pdid; // expected-error {{incompatible type assigning 'int struct D::*', expected 'int struct A::*'}}
 }
 
-struct HasMembers
+struct TheBase
+{
+  void d();
+};
+
+struct HasMembers : TheBase
 {
   int i;
   void f();
+
+  void g();
+  void g(int);
+  static void g(double);
 };
 
 namespace Fake
@@ -54,9 +63,19 @@
 }
 
 void g() {
+  HasMembers hm;
+
   int HasMembers::*pmi = &HasMembers::i;
   int *pni = &Fake::i;
+  int *pmii = &hm.i;
 
-  // FIXME: Test the member function, too.
+  void (HasMembers::*pmf)() = &HasMembers::f;
   void (*pnf)() = &Fake::f;
+  &hm.f; // expected-error {{address expression must be an lvalue or a function designator}}
+
+  void (HasMembers::*pmgv)() = &HasMembers::g;
+  void (HasMembers::*pmgi)(int) = &HasMembers::g;
+  void (*pmgd)(double) = &HasMembers::g;
+
+  void (HasMembers::*pmd)() = &HasMembers::d;
 }

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=63779&r1=63778&r2=63779&view=diff

==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Wed Feb  4 15:23:32 2009
@@ -619,10 +619,10 @@
 <tr>
   <td>      5.3.1p2-5 Unary &</td>
   <td class="complete" align="center">&#x2713;</td>
-  <td class="basic" align="center"></td>
-  <td class="basic" align="center"></td>
+  <td class="complete" align="center">&#x2713;</td>
+  <td class="complete" align="center">&#x2713;</td>
+  <td></td>
   <td></td>
-  <td>Member pointers not supported in any way</td>
 </tr>
 <tr>
   <td>      5.3.1p6 Unary +</td>





More information about the cfe-commits mailing list