[cfe-commits] r111997 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp test/CXX/expr/expr.unary/expr.unary.op/p4.cpp
John McCall
rjmccall at apple.com
Tue Aug 24 16:26:21 PDT 2010
Author: rjmccall
Date: Tue Aug 24 18:26:21 2010
New Revision: 111997
URL: http://llvm.org/viewvc/llvm-project?rev=111997&view=rev
Log:
Catch the case of trying to turn '&(X::a)' into a member pointer as well.
Added:
cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp
Modified:
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=111997&r1=111996&r2=111997&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Aug 24 18:26:21 2010
@@ -6216,9 +6216,24 @@
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
- llvm::PointerIntPair<OverloadExpr*,1> Ovl = OverloadExpr::find(From);
- OverloadExpr *OvlExpr = Ovl.getPointer();
-
+ // However, remember whether the expression has member-pointer form:
+ // 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.
+ bool HasFormOfMemberPointer = false;
+ OverloadExpr *OvlExpr;
+ {
+ Expr *Tmp = From->IgnoreParens();
+ if (isa<UnaryOperator>(Tmp)) {
+ Tmp = cast<UnaryOperator>(Tmp)->getSubExpr();
+ OvlExpr = cast<OverloadExpr>(Tmp->IgnoreParens());
+ HasFormOfMemberPointer = (Tmp == OvlExpr && OvlExpr->getQualifier());
+ } else {
+ OvlExpr = cast<OverloadExpr>(Tmp);
+ }
+ }
+
// We expect a pointer or reference to function, or a function pointer.
FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
if (!FunctionType->isFunctionType()) {
@@ -6230,13 +6245,8 @@
}
// 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())) {
+ // member, don't try to convert it to a pointer-to-member type.
+ if (IsMember && !HasFormOfMemberPointer) {
if (!Complain) return 0;
// TODO: Should we condition this on whether any functions might
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=111997&r1=111996&r2=111997&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 18:26:21 2010
@@ -91,28 +91,3 @@
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);
- }
- };
-}
Added: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp?rev=111997&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp Tue Aug 24 18:26:21 2010
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// rdar://problem/8347416
+namespace test0 {
+ struct A {
+ void foo(void (A::*)(int)); // expected-note {{passing argument to parameter here}}
+ template<typename T> void g(T);
+
+ void test() {
+ // FIXME: this diagnostic is terrible
+ foo(&g<int>); // expected-error {{cannot initialize a parameter of type 'void (test0::A::*)(int)' with an rvalue of type '<overloaded function type>'}}
+ }
+ };
+}
+
+// This should succeed.
+namespace test1 {
+ struct A {
+ static void f(void (A::*)());
+ static void f(void (*)(int));
+ void g();
+ static void g(int);
+
+ void test() {
+ f(&g);
+ }
+ };
+}
+
+// Also rdar://problem/8347416
+namespace test2 {
+ struct A {
+ static int foo(short);
+ static int foo(float);
+ int foo(int);
+ int foo(double);
+
+ void test();
+ };
+
+ void A::test() {
+ // FIXME: This diagnostic is terrible.
+ int (A::*ptr)(int) = &(A::foo); // expected-error {{cannot initialize a variable of type 'int (test2::A::*)(int)' with an rvalue of type '<overloaded function type>'}}
+ }
+}
More information about the cfe-commits
mailing list