[cfe-dev] PATCH: C++ Function Overloading (v2)

Argiris Kirtzidis akyrtzi at gmail.com
Tue Oct 21 06:35:06 PDT 2008

Doug Gregor wrote:
> We certainly need some way to represent the notion of an expression
> that refers to an overloaded function; that's a basic notion in C++,
> because name lookup can return a set of overloaded functions. Maybe it
> could be something other than a DeclRefExpr that references an
> OverloadedFunctionDecl.

Yes, I question only the use of OverloadedFunctionDecl. Currently, 
IdentifierResolver can already provide the set of overloaded functions 
so the overhead of OverloadedFunctionDecl is not strictly needed.

> Templates will need to store sets of overloaded functions.

Even now, with no trace of a template implementation in clang, the use 
of OverloadedFunctionDecl is questionable:

-First, consider this example:

void f(char); #1

template<class T> void g(T t)
  f(t); #2 //dependent

void f(int); #3

void h()
  g(2); #4 //should cause a call of f(int)

At #2 'f' does not have any overloads and no OverloadedFunctionDecl 
exists, how should this be represented ?
If #2 is regarded as a call to #1, then we miss #3 at instantiation time 
(#4) (as specified in C++ 14.6p9).
In order to pickup #3, should we turn 'f' into a OverloadedFunctionDecl, 
even if 'f' nevers gets an overload, just because it gets called in a 
templated expression ?

-Second, I see no reason why IdentifierResolver can't be made to 
eventually work with templates and be used to get the overload set for 
'f' at #4 (if it turns out that there are overloads)

> I can think of two kinds of clients that might want or need to deal
> with OverloadedFunctionDecls.
> First of all, any clients that are focused on parsing and don't need
> to do much semantic analysis could certainly skip overload resolution,
> and would therefore leave the OverloadedFunctionDecls in place since
> they don't need to be resolved.
> Second, clients that want to do some kind of speculative overload
> resolution would need to query the overloads that show up in the
> overload set. For example, an IDE that tries to help with overload
> resolution by showing options while you type. Type "f(17, " and it
> shows you all of the f's that could still be called. This client needs
> to be able to ask the AST or Sema (it's not clear which) which "f"'s
> are available, and then ask Sema which ones are still callable.
> None of these require the exact OverloadedFunctionDecl formulation in
> my patch, but they are AST clients to consider.

There was a discussion here:
about how clients should reason about symbols/identifiers. The consensus 
was that Sema builds up a lot of useful semantic information that later 
discards. It would be useful to somehow expose semantic information from 
Sema and avoid bloating the AST with semantic information (as would be 
the case with OverloadedFunctionDecl).
For example, I think that eventually IdentifierResolver will either be 
exposed by Sema to clients or a similar construct will be used. By your 
example, an IDE usually wants to inquire "I'm in this scope, what can 
this identifier mean in this context ? Give me a set of decls." which is 
exactly the functionality and purpose of IdentifierResolver.

>> How about if a reference of overloaded function "f", results in a
>> OverloadExpr (with OverloadType), that contains the "f" IdentifierInfo and a
>> 'void*' opaque value meant to be used by Sema (or in general, the Action
>> implementation that created the OverloadExpr) ?
>> The advantage of this is that Sema has full control and flexibility over the
>> overload resolution mechanism, e.g. it can change it completely and it will
>> have no impact on the AST or the AST clients.
> The representation of the set of overloaded functions doesn't really
> have anything to do with the overload resolution mechanism. Overload
> resolution has to pass over the set of overloaded functions found by
> name lookup and build its own data structures, collect other functions
> found via argument-dependent lookup, etc., so I think it is very
> unlikely even that two different Semas would need different
> representations of the set of overloaded functions.
> The disadvantage of having the 'void*' opaque value is that it makes
> ownership harder: how does this void* get deallocated, serialized, or
> de-serialized?

I agree, the opaque value definitely complicates things. How about a 
OverloadExpr that contains a DeclContext* and an IdentifierInfo* (for 
the moment, not sure what exact structure would be needed for templates).

To summarize, my point is that currently OverloadedFunctionDecl is an 
unnecessary overhead since IdentifierResolver already can be used to get 
the set of overloads. If later on (e.g. for templates), we find out that 
IdentifierResolver is not sufficient, we can always add 
OverloadedFunctionDecl too. At the moment it makes little sense to have 
them since the only expressions that are supposed to reference them (and 
not get immediately resolved) are expressions in templates, and there's 
a long way ahead before reaching the "template hill" :-)

A bit off-topic:
Currently the iterator abstraction of IdentifierResolver is stretched 
thin and will probably snap when more name lookup rules are added. I 
lean towards removing the iterator and using a single function that 
returns the set of decls based on an identifier.


More information about the cfe-dev mailing list