Use the naming class from the overloaded lookup when access-checking an
address of overloaded function, instead of assuming that a nested name
specifier was used.  A nested name specifier is not required for static
functions.

Fixes PR6886.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102107 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 7f7f085..262d2b4 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1289,6 +1289,9 @@
     Results.append(Begin, End);
   }
 
+  /// Gets the naming class of this lookup, if any.
+  CXXRecordDecl *getNamingClass() const;
+
   typedef UnresolvedSetImpl::iterator decls_iterator;
   decls_iterator decls_begin() const { return Results.begin(); }
   decls_iterator decls_end() const { return Results.end(); }
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index b9a4ee6..c19fd83 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -180,6 +180,13 @@
   return false;
 }
 
+CXXRecordDecl *OverloadExpr::getNamingClass() const {
+  if (isa<UnresolvedLookupExpr>(this))
+    return cast<UnresolvedLookupExpr>(this)->getNamingClass();
+  else
+    return cast<UnresolvedMemberExpr>(this)->getNamingClass();
+}
+
 Stmt::child_iterator UnresolvedLookupExpr::child_begin() {
   return child_iterator();
 }
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index af0c5b5..14a693f 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -1230,15 +1230,7 @@
     return AR_accessible;
 
   OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer();
-  NestedNameSpecifier *Qualifier = Ovl->getQualifier();
-  assert(Qualifier && "address of overloaded member without qualifier");
-
-  CXXScopeSpec SS;
-  SS.setScopeRep(Qualifier);
-  SS.setRange(Ovl->getQualifierRange());
-  DeclContext *DC = computeDeclContext(SS);
-  assert(DC && DC->isRecord() && "scope did not resolve to record");
-  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(DC);
+  CXXRecordDecl *NamingClass = Ovl->getNamingClass();
 
   AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
                       Context.getTypeDeclType(NamingClass));
diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp
index 391fc30..f8b00df 100644
--- a/test/SemaCXX/addr-of-overloaded-function.cpp
+++ b/test/SemaCXX/addr-of-overloaded-function.cpp
@@ -70,3 +70,19 @@
     int (&fp)() = f; // expected-error{{address of overloaded function 'f' does not match required type 'int ()'}}
   }
 };
+
+// PR6886
+namespace test0 {
+  void myFunction(void (*)(void *));
+
+  class Foo {
+    void foo();
+
+    static void bar(void*);
+    static void bar();
+  };
+
+  void Foo::foo() {
+    myFunction(bar);
+  }
+}