From: Douglas Gregor Date: Tue, 16 Dec 2008 06:37:47 +0000 (+0000) Subject: Partial fix for qualified name lookup, such that the lookup of N in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3dde5a3fa28cae4b8b2fb060abc0bfc2b4425ed8;p=clang Partial fix for qualified name lookup, such that the lookup of N in N::X only skips those entities specified in C++ [basic.lookup.qual]p1. Note that both EDG and GCC currently get this wrong. EDG has confirmed that the bug will be fixed in a future version. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61079 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 8b3218b33b..fe9ae07eba 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -28,8 +28,8 @@ namespace { DeclContext::lookup_const_iterator I, E; for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I) { IdIsUndeclared = false; - if (((*I)->getIdentifierNamespace() & Decl::IDNS_Tag) && - !isa(*I)) + if (((*I)->getIdentifierNamespace() & Decl::IDNS_Tag) || + isa(*I)) return *I; } @@ -56,12 +56,10 @@ namespace { // not a class-name or namespace-name, the program is ill-formed. for (; I != E; ++I) { - if (TypedefDecl *TD = dyn_cast(*I)) { - if (TD->getUnderlyingType()->isRecordType()) - break; - continue; + if (isa(*I)) { + break; } - if (((*I)->getIdentifierNamespace()&Decl::IDNS_Tag) && !isa(*I)) + if (((*I)->getIdentifierNamespace() & Decl::IDNS_Tag)) break; } @@ -100,13 +98,14 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, if (SD) { if (TypedefDecl *TD = dyn_cast(SD)) { - assert(TD->getUnderlyingType()->isRecordType() &&"Invalid Scope Decl!"); - SD = TD->getUnderlyingType()->getAsRecordType()->getDecl(); + if (const RecordType* Record = TD->getUnderlyingType()->getAsRecordType()) + return cast(Record->getDecl()); + } else if (isa(SD) || isa(SD)) { + return cast(SD); } - assert((isa(SD) || isa(SD)) && - "Invalid Scope Decl!"); - return cast(SD); + // Fall through to produce an error: we found something that isn't + // a class or a namespace. } unsigned DiagID; diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index 1d91c24b96..7422066247 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -1,4 +1,4 @@ -// RUN: clang -fsyntax-only -verify %s +// RUN: clang -fsyntax-only -verify -std=c++98 %s namespace A { struct C { static int cx; @@ -72,10 +72,8 @@ void f3() { int N; N::x = 0; // expected-error {{expected a class or namespace}} { int A; A::ax = 0; } - { enum A {}; A::ax = 0; } - { enum A { A }; A::ax = 0; } - { typedef int A; A::ax = 0; } - { typedef int A(); A::ax = 0; } + { typedef int A; A::ax = 0; } // expected-error{{expected a class or namespace}} + { int A(); A::ax = 0; } { typedef A::C A; A::ax = 0; } // expected-error {{no member named 'ax'}} { typedef A::C A; A::cx = 0; } } @@ -90,3 +88,18 @@ void f6(int A2::RC::x); // expected-error{{parameter declarator cannot be qualif int A2::RC::x; // expected-error{{non-static data member defined out-of-line}} void A2::CC::NC::m(); // expected-error{{out-of-line declaration of a member must be a definition}} + + +namespace E { + int X = 5; + + namespace Nested { + enum E { + X = 0 + }; + + void f() { + return E::X; // expected-error{{expected a class or namespace}} + } + } +}