[cfe-dev] Hello
Sebastian Redl
sebastian.redl at getdesigned.at
Sun Oct 5 05:20:36 PDT 2008
Argiris Kirtzidis wrote:
> Here's an initial discussion about nested-names:
> http://lists.cs.uiuc.edu/pipermail/cfe-dev/2008-August/002417.html
>
> To be more specific about "the conditions", I'm talking about having
> some kind of "annotation tokens" like I propose here:
> http://lists.cs.uiuc.edu/pipermail/cfe-dev/2008-August/002664.html
>
> These will be useful for both nested-names and ambiguity resolution
> (discussed here:
> http://lists.cs.uiuc.edu/pipermail/cfe-dev/2008-August/002594.html)
>
> Please let me know if you have some thoughts on the subject.
I had always thought that it was possible to parse the non-template part
of nested name specifiers without having to refer to sema at all. In my
opinion, C++ would have been better if the specification of nested-id
simply used 'identifier' instead of 'class-or-namespace-name'.
But then, a lot of C++ would be a lot easier (not only to parse) if the
designers had avoided semantically loaded terms in the grammar and
actually looked out for and prevented syntactic ambiguities.
Anyway, I have thought about the old discussions a lot this last week,
and most of my comments turned out to be already answered. Below is what
remains.
I had some thoughts of parsing the entire thing ahead of time and then
having the sema resolve all issues at once, but there is one test case
that really makes this impractical:
typedef int foo;
namespace abc { foo bar(); }
foo::abc::bar()
{
// ...
}
Thus, there is one statement of yours in the discussion that is wrong:
> Anyway, I don't think we need to worry about whether it should be
> "A::B ::C" or "A ::B::C" or whatever.
>
We do have to worry. GCC parses the above example correctly as foo
::abc::bar. It doesn't stumble if foo is in its own namespace or even
template class either. (In my opinion, that's really a defect in the
standard. Nor do I think that there is any program out there that really
relies on this.)
Consider also:
> I think this is correct since the spec says nothing about "'::'
> associativity".
>
:: is part of productions further down the tree than anything else, so
it binds more strongly than anything else. However, it only binds to
left-hand identifiers that actually name a namespace or class.
Otherwise, it's the global scope.
It probably could still be done, but it would be very complex code - the
sema would have to report that there are two identifiers, it would have
to report the split position, and the parser would have to adjust its
state according to this new revelation. It would shift a job to the sema
that really is the parser's problem, and all that for probably no
performance gain at all.
(Hm, or is that what your patch does? I haven't actually looked at any
code.)
Here's a nice pathological case. GCC is so confused by it that it aborts
processing. It doesn't even take any instantiations - the definition is
enough. (Of course, to actually be a definition of the second template
function, there would have to be a typename before the B::A.)
namespace A { template <typename B> B f(); }
template <typename B> typename B::A f();
template <typename B>
B::A::f()
{
return 0;
}
struct s { typedef int A; }
void foo()
{
f<int>();
f<s>();
}
It's not surprising that this confuses GCC. This matter is actually
unspecified in the 2003 standard, see DR215. DR215 is in fact very
important to this whole matter, as is DR125, because the resolutions to
these issues render the first example I've given invalid. The resolution
to 125 has been voted into the C++0x paper in 2004, the one to 215 in
2007. Under these rules, the class-or-namespace-name production
disappears and is replaced by the more sensible type-or-namespace-name,
with qualified name lookup amended to fail if the type name doesn't
denote a class. (A type template parameter is a type-name.)
The question is whether we want to follow the broken rules of C++03, as
GCC does, or the updated rules of C++0x, which introduces a tiny
incompatibility to GCC.
I think that we should forbid using anything but Sema as the C++ Action.
At least when we get to implementing templates, implementing isTypeName
and similar functions is such a burden that it just doesn't make sense
to use a different action, and there is no heuristic that can guess at
types vs non-types with any reasonable accuracy - at least not without
parsing ahead, and an Action can't do that.
The alternative is moving all type analysis, including that from Sema,
to MinimalAction, and deriving Sema from MinimalAction. That would
seriously slow down MinimalAction for C, though, I think.
Parser::isTokenStreamTypeName() - if I understand its purpose correctly,
eventually this function will have to distinguish between types,
templates, perhaps even concepts, and objects/functions. This is a lot
for a function whose name suggests a boolean distinction.
Does whatever final resolution to the name lookup issue has been chosen
handle reentrancy? Does the inner lookup work here?
ns1::templname<ns2::typename>::objname
I don't have any comments on the recently committed disambiguation code.
Sebastian
More information about the cfe-dev
mailing list