[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">✓</td>
- <td class="basic" align="center"></td>
- <td class="basic" align="center"></td>
+ <td class="complete" align="center">✓</td>
+ <td class="complete" align="center">✓</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