Search code examples
c++gccclanglanguage-lawyer

Bug on both clang and gcc on unqualified call


The standard manifests:

6.4.1

The lookup for an unqualified name used as the postfix-expression of a function call is described in [basic.lookup.argdep]. [ Note: For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply. In some cases a name followed by < is treated as a template-name even though name lookup did not find a template-name (see [temp.names]). For example,

namespace N {
  struct A {};
  template <class T> int f(T);
}

 int main() {
  int x = f<N::A>(N::A());        // OK: lookup of f finds nothing, f treated as template name
}

Both gcc and clang do not compile this simple program and they issue a similar diagnostic:

no templated name f found did you mean N::f?

This is clearly an implementation bug unless something is not clear. Should I fill in a defect report?


Solution

  • The rule that you quote is different in C++17. The change proposal: p0846r0. If you are compiling for C++20, then the example should compile, and if it doesn't, then the compiler has incomplete C++20 support.

    No compiler has stable support for C++20, which hasn't even been released yet officially (the feature list was recently frozen though), so some bugs are to be expected, as support for that future language version may not be complete.

    The latest development version of both GCC and Clang successfully compile the example, so bug report should not be necessary.


    The standard draft for C++17 says:

    [basic.lookup.unqual]

    The lookup for an unqualified name used as the postfix-expression of a function call is described in 6.4.2. [Note: For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply. The rules in 6.4.2 have no effect on the syntactic interpretation of an expression. For example,

    typedef int f;
    namespace N {
        struct A {
            friend void f(A &);
            operator int();
            void g(A a) {
                int i = f(a); // f is the typedef, not the friend function: equivalent to int(a)
            }
        };
    }
    

    This example compiles fine in clang 5.0.0-3~16.04.1 as well as GCC 8.2.0.