[cfe-commits] r111987 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp
John McCall
rjmccall at apple.com
Tue Aug 24 15:52:39 PDT 2010
Author: rjmccall
Date: Tue Aug 24 17:52:39 2010
New Revision: 111987
URL: http://llvm.org/viewvc/llvm-project?rev=111987&view=rev
Log:
When trying to resolve the address of an overloaded expression,
only form pointers-to-member if the expression has the appropriate
form. This avoids assertions later on on invalid code, but also
allows us to properly resolve mixed-staticity overloads.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=111987&r1=111986&r2=111987&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Aug 24 17:52:39 2010
@@ -1286,6 +1286,8 @@
"address of overloaded function %0 is ambiguous">;
def err_addr_ovl_not_func_ptrref : Error<
"address of overloaded function %0 cannot be converted to type %1">;
+def err_addr_ovl_no_qualifier : Error<
+ "can't form member pointer of type %0 without '&' and class name">;
// C++ Template Declarations
def err_template_param_shadow : Error<
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=111987&r1=111986&r2=111987&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Aug 24 17:52:39 2010
@@ -1063,10 +1063,10 @@
}
ExprResult Sema::ActOnIdExpression(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Id,
- bool HasTrailingLParen,
- bool isAddressOfOperand) {
+ CXXScopeSpec &SS,
+ UnqualifiedId &Id,
+ bool HasTrailingLParen,
+ bool isAddressOfOperand) {
assert(!(isAddressOfOperand && HasTrailingLParen) &&
"cannot be direct & operand and have a trailing lparen");
@@ -1223,12 +1223,16 @@
}
// Check whether this might be a C++ implicit instance member access.
- // C++ [expr.prim.general]p6:
- // Within the definition of a non-static member function, an
- // identifier that names a non-static member is transformed to a
- // class member access expression.
- // But note that &SomeClass::foo is grammatically distinct, even
- // though we don't parse it that way.
+ // C++ [class.mfct.non-static]p3:
+ // When an id-expression that is not part of a class member access
+ // syntax and not used to form a pointer to member is used in the
+ // body of a non-static member function of class X, if name lookup
+ // resolves the name in the id-expression to a non-static non-type
+ // member of some class C, the id-expression is transformed into a
+ // class member access expression using (*this) as the
+ // postfix-expression to the left of the . operator.
+ // So if we found a class member with an expression of form other
+ // than &A::foo, we have to try to build an implicit member expr.
if (!R.empty() && (*R.begin())->isCXXClassMember()) {
bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty());
if (!isAbstractMemberPointer)
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=111987&r1=111986&r2=111987&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Aug 24 17:52:39 2010
@@ -6216,13 +6216,9 @@
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
- OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer();
- TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0;
- if (OvlExpr->hasExplicitTemplateArgs()) {
- OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
- ExplicitTemplateArgs = &ETABuffer;
- }
-
+ llvm::PointerIntPair<OverloadExpr*,1> Ovl = OverloadExpr::find(From);
+ OverloadExpr *OvlExpr = Ovl.getPointer();
+
// We expect a pointer or reference to function, or a function pointer.
FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
if (!FunctionType->isFunctionType()) {
@@ -6233,6 +6229,30 @@
return 0;
}
+ // If the overload expression doesn't have the form of a pointer to
+ // member, don't try to convert it to a pointer-to-member type:
+ // C++ [expr.unary.op]p4:
+ // A pointer to member is only formed when an explicit & is used
+ // and its operand is a qualified-id not enclosed in
+ // parentheses.
+ // We don't diagnose the parentheses here, though. Should we?
+ if (IsMember && !(Ovl.getInt() && OvlExpr->getQualifier())) {
+ if (!Complain) return 0;
+
+ // TODO: Should we condition this on whether any functions might
+ // have matched, or is it more appropriate to do that in callers?
+ // TODO: a fixit wouldn't hurt.
+ Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
+ << ToType << OvlExpr->getSourceRange();
+ return 0;
+ }
+
+ TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0;
+ if (OvlExpr->hasExplicitTemplateArgs()) {
+ OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
+ ExplicitTemplateArgs = &ETABuffer;
+ }
+
assert(From->getType() == Context.OverloadTy);
// Look through all of the overloaded functions, searching for one
Modified: cfe/trunk/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp?rev=111987&r1=111986&r2=111987&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp (original)
+++ cfe/trunk/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp Tue Aug 24 17:52:39 2010
@@ -91,3 +91,28 @@
a.test3(); // expected-note {{in instantiation}}
}
}
+
+namespace test3 {
+ struct A {
+ void foo(void (A::*)(int)); // expected-note {{passing argument to parameter here}}
+ template<typename T> void g(T);
+
+ void test() {
+ foo(&g<int>); // expected-error {{cannot initialize a parameter}}
+ }
+ };
+}
+
+// This should succeed.
+namespace test4 {
+ struct A {
+ static void f(void (A::*)());
+ static void f(void (*)(int));
+ void g();
+ static void g(int);
+
+ void test() {
+ f(&g);
+ }
+ };
+}
More information about the cfe-commits
mailing list