From: Anders Carlsson Date: Sat, 28 Mar 2009 23:53:49 +0000 (+0000) Subject: More improvements to namespace aliases. We now support everything except aliases... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=81c85c421197a602523781a6ef730639c4c6ea51;p=clang More improvements to namespace aliases. We now support everything except aliases in using directives. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67966 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index ab1e9d430d..0ebccf3581 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -970,7 +970,7 @@ public: return isa(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag); case Sema::LookupNamespaceName: - return isa(D); + return isa(D) || isa(D); } assert(false && diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index a879989b33..5395869a02 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -144,6 +144,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, return NestedNameSpecifier::Create(Context, Prefix, false, T.getTypePtr()); } + + if (NamespaceAliasDecl *Alias = dyn_cast(SD)) + return NestedNameSpecifier::Create(Context, Prefix, + Alias->getNamespace()); // Fall through to produce an error: we found something that isn't // a class or a namespace. diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 300e7c450f..22e773a7c1 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1676,6 +1676,14 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { S->PushUsingDirective(DeclPtrTy::make(UDir)); } +/// getNamespaceDecl - Returns the namespace a decl represents. If the decl +/// is a namespace alias, returns the namespace it points to. +static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { + if (NamespaceAliasDecl *AD = dyn_cast_or_null(D)) + return AD->getNamespace(); + return dyn_cast_or_null(D); +} + Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, SourceLocation AliasLoc, @@ -1684,10 +1692,18 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation IdentLoc, IdentifierInfo *Ident) { + // Lookup the namespace name. + LookupResult R = LookupParsedName(S, &SS, Ident, LookupNamespaceName, false); + // Check if we have a previous declaration with the same name. if (NamedDecl *PrevDecl = LookupName(S, Alias, LookupOrdinaryName, true)) { - // FIXME: If this is a namespace alias decl, and it points to the same - // namespace, we shouldn't warn. + if (NamespaceAliasDecl *AD = dyn_cast(PrevDecl)) { + // We already have an alias with the same name that points to the same + // namespace, so don't create a new one. + if (!R.isAmbiguous() && AD->getNamespace() == getNamespaceDecl(R)) + return DeclPtrTy(); + } + unsigned DiagID = isa(PrevDecl) ? diag::err_redefinition : diag::err_redefinition_different_kind; Diag(AliasLoc, DiagID) << Alias; @@ -1695,8 +1711,6 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, return DeclPtrTy(); } - // Lookup the namespace name. - LookupResult R = LookupParsedName(S, &SS, Ident, LookupNamespaceName, false); if (R.isAmbiguous()) { DiagnoseAmbiguousLookup(R, Ident, IdentLoc); return DeclPtrTy(); diff --git a/test/SemaCXX/namespace-alias.cpp b/test/SemaCXX/namespace-alias.cpp index 87e8b2c5dd..c715c9f97c 100644 --- a/test/SemaCXX/namespace-alias.cpp +++ b/test/SemaCXX/namespace-alias.cpp @@ -25,3 +25,26 @@ namespace F { namespace G { namespace B = N; } + +namespace H { + namespace A1 { } + namespace A2 { } + + // These all point to A1. + namespace B = A1; // expected-note {{previous definition is here}} + namespace B = A1; + namespace C = B; + namespace B = C; + + namespace B = A2; // expected-error {{redefinition of 'B' as different kind of symbol}} +} + +namespace I { + namespace A1 { int i; } + + namespace A2 = A1; +} + +int f() { + return I::A2::i; +}