Proposed resolution (February, 2018):
Change 6.5.3 [basic.lookup.unqual] paragraph 8 as follows:
For the members of a class X, a name used in a member function body, in a default argument, in a noexcept-specifier, in the brace-or-equal-initializer of a non-static data member (11.4 [class.mem]), or in the
definitiondeclaration of a class member outside of the definition of X,following the member's declarator-id32, shall be declared in one of the following ways:
before its use in the block in which it is used or in an enclosing block (8.4 [stmt.block]) within the body of the member function, or
shall beas a member of class X orbeas a member of a base class of X (6.5.2 [class.member.lookup]), orif X is a nested class of class Y (11.4.12 [class.nest]), shall be a member of Y, or shall be a member of a base class of Y (this lookup applies in turn to Y's enclosing classes, starting with the innermost enclosing class),33 or
if X is a local class (11.6 [class.local]) or is a nested class of a local class, before the definition of class X in a block enclosing the definition of class X, or
if X is a member of namespace N, or is a nested class of a class that is a member of N, or is a local class or a nested class within a local class of a function that is a member of N, before the use of the name, in namespace N or in one of N's enclosing namespaces
., orfor a friend declaration in a class Y, in a scope that would be searched for a name appearing within Y.
Delete 6.5.3 [basic.lookup.unqual] paragraph 10 and combine its example with that of paragraph 8:
In a friend declaration naming a member function, a name used in the function declarator and not part of a template-argument in the declarator-id is first looked up in the scope of the member function's class (6.5.2 [class.member.lookup]). If it is not found, or if the name is part of a template-argument in the declarator-id, the look up is as described for unqualified names in the definition of the class granting friendship. [Example:struct A { typedef int AT; void f1(AT); void f2(float); template <class T> void f3(); }; struct B { typedef char AT; typedef float BT; friend void A::f1(AT); // parameter type is A::AT friend void A::f2(BT); // parameter type is B::BT friend void A::f3<AT>(); // template argument is B::AT };
—end example]