Index: lib/Sema/SemaLookup.cpp =================================================================== --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -2625,12 +2625,11 @@ } } -// Add the associated classes and namespaces for -// argument-dependent lookup with an argument of type T -// (C++ [basic.lookup.koenig]p2). +// Add the associated classes and namespaces for argument-dependent +// lookup with an argument of type T (C++ [basic.lookup.argdep]p2). static void addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { - // C++ [basic.lookup.koenig]p2: + // C++ [basic.lookup.argdep]p2: // // For each argument type T in the function call, there is a set // of zero or more associated namespaces and a set of zero or more @@ -2806,7 +2805,7 @@ AssociatedLookup Result(*this, InstantiationLoc, AssociatedNamespaces, AssociatedClasses); - // C++ [basic.lookup.koenig]p2: + // C++ [basic.lookup.argdep]p2: // For each argument type T in the function call, there is a set // of zero or more associated namespaces and a set of zero or more // associated classes to be considered. The sets of namespaces and @@ -2821,15 +2820,16 @@ continue; } - // [...] In addition, if the argument is the name or address of a - // set of overloaded functions and/or function templates, its - // associated classes and namespaces are the union of those - // associated with each of the members of the set: the namespace - // in which the function or function template is defined and the - // classes and namespaces associated with its (non-dependent) - // parameter types and return type. OverloadExpr *OE = OverloadExpr::find(Arg).Expression; + // C++ [basic.lookup.argdep] end of p2: + // [...] In addition, if the argument is the name or address of a set of + // overloaded functions and/or function templates, its associated classes + // and namespaces are the union of those associated with each of the + // members of the set, i.e., the classes and namespaces associated with + // its parameter types and return type. + // + // TODO: CWG 997 removed the restriction on non-dependent types. for (const NamedDecl *D : OE->decls()) { // Look through any using declarations to find the underlying function. const FunctionDecl *FDecl = D->getUnderlyingDecl()->getAsFunction(); @@ -2838,6 +2838,17 @@ // types and return type of this function. addAssociatedClassesAndNamespaces(Result, FDecl->getType()); } + + // [...] Additionally, if the aforementioned set of overloaded functions + // is named with a template-id, its associated classes and namespaces also + // include those of its type template-arguments and its template + // template-arguments. + // + // Added by CWG 997. + for (const TemplateArgumentLoc &TemplateArgLoc : OE->template_arguments()) { + const TemplateArgument &TemplateArg = TemplateArgLoc.getArgument(); + addAssociatedClassesAndNamespaces(Result, TemplateArg); + } } } Index: test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp =================================================================== --- test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp +++ test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp @@ -315,7 +315,7 @@ namespace N { struct S {}; constexpr int f(int (*g)()) { return g(); } - // expected-note@-1 2{{'N::f' declared here}} + // expected-note@-1 {{'N::f' declared here}} template struct Q; } @@ -328,11 +328,13 @@ constexpr int g3() { return 4; } template constexpr int g3(T, N::Q) { return 5; } + template