[cfe-commits] r58916 - in /cfe/trunk: include/clang/AST/DeclBase.h include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticKinds.def lib/Sema/Sema.cpp lib/Sema/Sema.h lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp test/SemaCXX/nested-name-spec.cpp
Douglas Gregor
dgregor at apple.com
Tue Nov 18 08:32:12 PST 2008
On Nov 14, 2008, at 5:26 PM, Argiris Kirtzidis wrote:
> Douglas Gregor wrote:
>>
>>> + /// PreDeclaratorDC - Keeps the declaration context before
>>> switching to the
>>> + /// context of a declarator's nested-name-specifier.
>>> + DeclContext *PreDeclaratorDC;
>>
>> I assume that we'll eventually need this to be a stack of
>> DeclContext *'s, to deal with something like:
>>
>> ::foo::bar<wibble::wonka>::type
>>
>> Perhaps we should just make it a stack now so we're ready for the
>> future.
>
> I prefer to avoid a stack, if it's possible, in favor of stricter
> invariants of how DeclContext changes.
> In your particular example I don't think a stack is required, it's
> just nested-name-specifier parsing which doesn't change Sema's
> CurContext (wibble::wonka isn't looked up in the context of ::foo,
> right ?)
Oh, I see now. I was convinced that CurContext was changing more often
than it is. I think you're right that we don't need the stack.
>
>>
>>> +namespace {
>>> + Decl *LookupNestedName(DeclContext *LookupCtx, bool
>>> LookInParentCtx,
>>> + const IdentifierInfo &II, bool
>>> &IdIsUndeclared) {
>>>
>>> + IdentifierResolver::iterator
>>> + I = IdentifierResolver::begin(&II, LookupCtx,
>>> LookInParentCtx),
>>> + E = IdentifierResolver::end();
>>> +
>>> + if (I == E) {
>>> + IdIsUndeclared = true;
>>> + return 0;
>>> + }
>>> + IdIsUndeclared = false;
>>> +
>>> + // C++ 3.4.3p1 :
>>> + // During the lookup for a name preceding the :: scope
>>> resolution operator,
>>> + // object, function, and enumerator names are ignored. If the
>>> name found is
>>> + // not a class-name or namespace-name, the program is ill-
>>> formed.
>>> +
>>> + for (; I != E; ++I) {
>>> + if (TypedefDecl *TD = dyn_cast<TypedefDecl>(*I)) {
>>> + if (TD->getUnderlyingType()->isRecordType())
>>> + break;
>>> + continue;
>>> + }
>>> + if (((*I)->getIdentifierNamespace()&Decl::IDNS_Tag) && !
>>> isa<EnumDecl>(*I))
>>> + break;
>>> + }
>>
>> I don't think this is quite right for C++03. The standard says that
>> we ignore enumerator names (e.g., an EnumConstantDecl), but the
>> check in the "if" is skipping enumeration names (EnumDecl). Here's
>> an example where it matters:
>>
>> namespace N {
>> struct C {
>> static float X;
>> };
>>
>> typedef C Typedef;
>>
>> namespace M {
>> enum E {
>> X = 17
>> };
>>
>> typedef E Typedef;
>>
>> void test() {
>> float& f = Typedef::X;
>> }
>> }
>> }
>>
>> GCC rejects this example:
>>
>> /Users/dgregor/foo.C: In function ‘void N::M::test()’:
>> /Users/dgregor/foo.C:16: error: ‘Typedef’ is not a class or
>> namespace
>>
>> Interestingly, EDG accepts the example, and so does Clang, but I'm
>> pretty certain that both are wrong. Qualified name lookup should
>> find the typedef for the enumeration 'E', and then fail because we
>> can't do qualified name lookup into an enumeration type in C++03.
>
> MSVC and Comeau also accept the example. I find this weird, I
> thought EDG and Comeau have a high standard-conformance reputation;
Comeau uses the EDG front end. EDG does have a reputation as being the
most conforming C++ implementation, but they make mistakes, too :)
> and that the enumeration is ignored because enumerations don't
> participate in qualified name lookup.
That isn't the way I read C++03 3.4.3p1. The second sentence says:
"During the lookup for a name preceding the::scope resolution
operator, object, function, and enumerator names are ignored."
An enumeration name is not an operator, object, function, or
enumerator name, so we shouldn't be ignoring them.
>
>> In C++0x, we *can* do qualified name lookup into an enumeration, so
>> the example fails because we can't bind an 'int' to a reference to
>> a 'float'.
>
> I was under the impression that this happens to 'enum class' which
> is different from 'enum'. You can do qualified name lookup even with
> simple enums (not 'enum class') ?
Yes. The C++0x 3.4.3p1 says:
"The name of a class, concept map (but not a concept), or namespace
member or enumerator can be referred
to after the :: scope resolution operator (5.1) applied to a nested-
name-specifier that nominates its class,
concept map, namespace, or enumeration."
Note that it says "enumeration" not "scoped enumeration". See also C+
+03 7.2p11, which gives an example of a qualified-id that refers to an
enumerator of an unscoped enumeration type.
- Doug
More information about the cfe-commits
mailing list