[cfe-dev] Resolving non-dependent function names within a template definition

Erik Pilkington via cfe-dev cfe-dev at lists.llvm.org
Tue Nov 21 12:42:46 PST 2017

On 2017-11-21 2:10 PM, Davis, Matthew via cfe-dev wrote:
> I  have a few questions about how Clang handles template definition parsing and argument dependent lookup (ADL).
> I was investigating the following bug: https://bugs.llvm.org/show_bug.cgi?id=28290
> I would expect the following code (from the bug report), to emit an error message, since Clang does not default to MSVC/delayed-template-parsing behavior.  However,  Clang does not emit an error.
> ////////// From bug #28290
> class UBS;
>    template <bool bCS> struct FIBH
>    {
>     FIBH() { GDN(BS); }  // GDN() is an error, it's non-dependent and not resolvable yet.
>     class UBS* BS;
>    };
>    extern void foo();
>    void foo()
>    {
>     FIBH<false> IBH;  // Instantiation
>    }
>    void GDN(UBS* BS);
> //////////
>  From what I understand in the spec [temp.res9], "GDN" is a name belonging to a non-dependent expression, and therefore the compiler must be able to resolve it at the lexical point in the parse.  Namely, at the point of template definition.
I believe that this is a duplicate of a pretty longstanding bug where 
the MemberExpr to BS is considered type-dependent because the implicit 
'this' is, where it really should be non-dependent. The standard says 

A class member access expression (5.2.5) is type-dependent if the 
expression refers to a member of the current instantiation and the type 
of the referenced member is dependent, or the class member access 
expression refers to a member of an unknown specialization.

Here, the implicit MemberExpr to BS refers to a member of the current 
instantation, but the type of the referenced member isn't dependent. 
Despite this, BS is considered type-dependent and lookup of GDN is 
deferred until instantiation because of ADL, which is why your not 
getting the diagnostic.
> The Clang parser does recognize this name as not being locatable during parse, and it suppresses the unresolved name error, in this case by creating an UnresolveLookupExpr to represent the "GDN()" in the template definition.  The lookup for GDN is then delayed, until instantiation when ADL is performed.  The result is that we get the -fdelayed-template-parsing (MSVC) semantics, which I do not believe is what we want.  The delay in the lookup allows for ADL to occur.   That seems problematic, as if the instantiation never occurs, the UnresolvedLookupExpr is never processed, and the following error message will never be produced: diag::err_not_found_by_two_phase_lookup: "a call to function %0 that is neither visible in the template definition nor found by argument dependent lookup."  I think we would want this error message to be reported even if the instantiation never occurs.
> The other issue of delaying  ADL, is that in the case of the example above, GDN will be known at the point of template instantiation, and therefore ADL will resolve GDN, and never produce the aforementioned error message.  The ADL will recognize the GDN function decl from the global namespace, and use that.
> With that said, I have two questions:
> 1) Should we emit an error for GDN during parse when the template is being parsed?
I believe so; it should be non-dependent, so we should be able to look 
it up early.
> 2) Should we allow ADL to resolve GDN in the template, when GDN is not really visible at the point of template definition?
I believe we should try to look up GDN and error out if we can't while 
parsing the template definition.

Hope that helps!
> -Matt
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

More information about the cfe-dev mailing list