[cfe-dev] Qualified and unqualified name lookup and IdResolver
Douglas Gregor
dgregor at apple.com
Fri Dec 5 10:44:47 PST 2008
Hi Argiris!
On Dec 4, 2008, at 7:58 PM, Argiris Kirtzidis wrote:
> I like the idea, for unqualified lookup, of declaration chains based
> on lexical scope plus fall back to qualified lookup.
> But for qualified lookup, did you consider using the "array
> +hashtable efficient data structure" not for answering "does N
> contain x ?" (#1) but for answering "is x contained in N ?" (#2) ?
> (I mean an identifier having that data structure for storing the
> DeclContexts where it appears).
> Both cases may have to deal with large number of declarations; #1
> may deal with namespaces with lots of decls, while #2 may deal with
> decls contained in lots of namespaces.
> The difference is that #1 optimizes for namespaces with few
> declarations while #2 optimizes for "differently named" declarations
> which is more common.
> Also, #2 will immediately answer for not-declared-before
> identifiers, without requiring any lookup.
I did think about #2, but I don't think it's the right architecture
and I think there are more performance issues lurking, particularly in
the case where we are instantiating many templates that all contain
members with the same names.
On the architecture side: the problem with having a data structure
hanging off the identifiers is that the data structure has global
knowledge: it needs to know about every "x" in every context. That
makes it hard to build up the data structure in any way other than
directly parsing the translation unit. For example, a module system
that supports lazy deserialization might be careful to only record
that the identifier "std" exists in the global namespace. When someone
writes "std::vector", qualified lookup into std forces "std" to be
populated by loading its declarations (but not the declarations they
contain). It would be quite easy to implement this with #1, since
DeclContext can be taught to deserialize when something performs a
lookup() on it. Perhaps we could do something similar with #2, but it
seems less obvious to me.
But, much of my bias comes from the fact that I find #1 to be far
easier to reason about.
Overall, I think the decision between #1 and #2 would actually have a
very small impact on the compiler. Most of the work in my patch is in
making the declaration chains contain only identifiers in our lexical
scope, and the "perform qualified lookup of name 'x' in scope 'y'"
part is relatively separate. If you do want to go try implementing #2,
make sure you use DeclContext::getPrimaryContext before trying to
match the context of a declaration, because in
namespace N {
int x;
}
namespace N {
int y;
}
N::x and N::y have different DeclContexts (but they have the same
primary DeclContext).
- Doug
More information about the cfe-dev
mailing list