[cfe-commits] r146587 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/CXX/expr/expr.unary/expr.unary.op/p3.cpp

Douglas Gregor dgregor at apple.com
Wed Dec 14 13:23:13 PST 2011


Author: dgregor
Date: Wed Dec 14 15:23:13 2011
New Revision: 146587

URL: http://llvm.org/viewvc/llvm-project?rev=146587&view=rev
Log:
Don't consider an overloaded operator& when the expression is actually
going to be a pointer-to-member constant. Fixes <rdar://problem/10544564>.

Added:
    cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp
Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=146587&r1=146586&r2=146587&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Dec 14 15:23:13 2011
@@ -8257,6 +8257,48 @@
                                            VK, OK, OpLoc));
 }
 
+/// \brief Determine whether the given expression is a qualified member
+/// access expression, of a form that could be turned into a pointer to member
+/// with the address-of operator.
+static bool isQualifiedMemberAccess(Expr *E) {
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (!DRE->getQualifier())
+      return false;
+    
+    ValueDecl *VD = DRE->getDecl();
+    if (!VD->isCXXClassMember())
+      return false;
+    
+    if (isa<FieldDecl>(VD) || isa<IndirectFieldDecl>(VD))
+      return true;
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(VD))
+      return Method->isInstance();
+      
+    return false;
+  }
+  
+  if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+    if (!ULE->getQualifier())
+      return false;
+    
+    for (UnresolvedLookupExpr::decls_iterator D = ULE->decls_begin(),
+                                           DEnd = ULE->decls_end();
+         D != DEnd; ++D) {
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*D)) {
+        if (Method->isInstance())
+          return true;
+      } else {
+        // Overload set does not contain methods.
+        break;
+      }
+    }
+    
+    return false;
+  }
+  
+  return false;
+}
+
 ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
                               UnaryOperatorKind Opc, Expr *Input) {
   // First things first: handle placeholders so that the
@@ -8286,7 +8328,8 @@
   }
 
   if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() &&
-      UnaryOperator::getOverloadedOperator(Opc) != OO_None) {
+      UnaryOperator::getOverloadedOperator(Opc) != OO_None &&
+      !(Opc == UO_AddrOf && isQualifiedMemberAccess(Input))) {
     // Find all of the overloaded operators visible from this
     // point. We perform both an operator-name lookup from the local
     // scope and an argument-dependent lookup based on the types of

Added: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp?rev=146587&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp Wed Dec 14 15:23:13 2011
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -fsyntax-only %s -verify 
+
+namespace rdar10544564 {
+  // Check that we don't attempt to use an overloaded operator& when
+  // naming a pointer-to-member.
+  struct X {
+    void** operator & ();
+  };
+
+  struct Y
+  {
+  public:
+    X member;
+    X memfunc1();
+    X memfunc2();
+    X memfunc2(int);
+
+    void test() {
+      X Y::*data_mem_ptr = &Y::member;
+      X (Y::*func_mem_ptr1)() = &Y::memfunc1;
+      X (Y::*func_mem_ptr2)() = &Y::memfunc2;
+    }
+  };
+  
+  X Y::*data_mem_ptr = &Y::member;
+  X (Y::*func_mem_ptr1)() = &Y::memfunc1;
+  X (Y::*func_mem_ptr2)() = &Y::memfunc2;
+}





More information about the cfe-commits mailing list