[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

Argiris Kirtzidis akyrtzi at gmail.com
Fri Nov 14 14:26:32 PST 2008


Douglas Gregor wrote:
>
>> +  bool isFileContext() const {
>> +    return DeclKind == Decl::TranslationUnit || DeclKind == 
>> Decl::Namespace;
>> +  }
>
> isFileContext seems like a weird name for this function... I would 
> have called it isNamespaceContext, since the translation unit context 
> is the same as the global namespace context for name lookup's purposes.

isFileContext makes it more language-neutral (namespace is a C++ thing), 
similar e.g. to VarDecl::isFileVarDecl.
But I don't particularly care, let me know if you still think I should 
change it.

>
>> +DIAG(err_not_tag_in_scope, ERROR,
>> +     "'%0' does not name a tag member in the specified scope")
>
> The term "tag" is very much a compiler-writers term. Could we replace 
> tag with '%1' and fill in the appropriate tag kind (struct, class, 
> union, enum)?

'tag' is mentioned by GCC, Comeau, and Clang in other diags ("use of 
'%0' with tag type that does not match previous declaration").
Again, let me know about changing it or not.

>
>> +  /// 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 ?)

>
>> +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; and that the 
enumeration is ignored because enumerations don't participate in 
qualified name lookup.

> 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') ?

-Argiris



More information about the cfe-commits mailing list