Resolving non-dependent function names within a template definition

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Resolving non-dependent function names within a template definition

Robinson, Paul via cfe-dev
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.

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?
2) Should we allow ADL to resolve GDN in the template, when GDN is not really visible at the point of template definition?

-Matt
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Resolving non-dependent function names within a template definition

Robinson, Paul via cfe-dev


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
[temp.dep.expr]p5:

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.
Agreed!
> 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!
Erik
>
> -Matt
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev