[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