diff options
author | Daniel Dunbar <daniel@zuster.org> | 2010-04-23 13:07:39 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2010-04-23 13:07:39 +0000 |
commit | 00b40d3f2fb8b2f9043daf3dd4558bff98346b3c (patch) | |
tree | d48af4c3cb69fada518349e2d467bf2c93c9eccf /lib/Sema | |
parent | 1444aefa635ea46806bba1c7cbc01a85f6faff90 (diff) |
Revert "C++ doesn't really use "namespaces" for different kinds of names the same", which seems to break most C++ nightly test apps.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102174 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 105 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 54 |
3 files changed, 71 insertions, 108 deletions
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 8be3da06ac..e71f8c84eb 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -415,9 +415,6 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND, return false; } - - if (Filter == &ResultBuilder::IsNestedNameSpecifier) - AsNestedNameSpecifier = true; // ... then it must be interesting! return true; @@ -507,8 +504,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { } for (; I != IEnd; ++I) { // A tag declaration does not hide a non-tag declaration. - if (I->first->getIdentifierNamespace() - == (Decl::IDNS_Tag | Decl::IDNS_Type) && + if (I->first->getIdentifierNamespace() == Decl::IDNS_Tag && (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | Decl::IDNS_ObjCProtocol))) continue; @@ -633,7 +629,7 @@ void ResultBuilder::ExitScope() { bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { unsigned IDNS = Decl::IDNS_Ordinary; if (SemaRef.getLangOptions().CPlusPlus) - IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; + IDNS |= Decl::IDNS_Tag; else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND)) return true; @@ -645,7 +641,7 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const { unsigned IDNS = Decl::IDNS_Ordinary; if (SemaRef.getLangOptions().CPlusPlus) - IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; + IDNS |= Decl::IDNS_Tag; return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND); @@ -2098,16 +2094,10 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { return; } - ResultBuilder Results(*this); + ResultBuilder Results(*this, Filter); + Results.allowNestedNameSpecifiers(); CodeCompletionDeclConsumer Consumer(Results, CurContext); - - // First pass: look for tags. - Results.setFilter(Filter); LookupVisibleDecls(S, LookupTagName, Consumer); - - // Second pass: look for nested name specifiers. - Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); - LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer); HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e0ca252b06..c9001f1030 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5000,8 +5000,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SearchDC = SearchDC->getEnclosingNamespaceContext(); } - // In C++, we need to do a redeclaration lookup to properly - // diagnose some problems. + // In C++, look for a shadow friend decl. if (getLangOptions().CPlusPlus) { Previous.setRedeclarationKind(ForRedeclaration); LookupQualifiedName(Previous, SearchDC); @@ -5010,26 +5009,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (!Previous.empty()) { NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl(); - - // It's okay to have a tag decl in the same scope as a typedef - // which shadows a tag decl in the same scope. Finding this - // insanity with a redeclaration lookup can only actually happen - // in C++. - if (getLangOptions().CPlusPlus && - TUK != TUK_Reference && TUK != TUK_Friend) { - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(PrevDecl)) { - if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) { - TagDecl *Tag = TT->getDecl(); - if (Tag->getDeclName() == Name && - Tag->getDeclContext()->Equals(SearchDC)) { - PrevDecl = Tag; - Previous.clear(); - Previous.addDecl(Tag); - } - } - } - } - if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { // If this is a use of a previous tag, or if the tag is already declared // in the same scope (so that the definition/declaration completes or @@ -5121,61 +5100,23 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // If we get here, we're going to create a new Decl. If PrevDecl // is non-NULL, it's a definition of the tag declared by // PrevDecl. If it's NULL, we have a new definition. - - - // Otherwise, PrevDecl is not a tag, but was found with tag - // lookup. This is only actually possible in C++, where a few - // things like templates still live in the tag namespace. } else { - assert(getLangOptions().CPlusPlus); - - // Use a better diagnostic if an elaborated-type-specifier - // found the wrong kind of type on the first - // (non-redeclaration) lookup. - if ((TUK == TUK_Reference || TUK == TUK_Friend) && - !Previous.isForRedeclaration()) { - unsigned Kind = 0; - if (isa<TypedefDecl>(PrevDecl)) Kind = 1; - else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2; - Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind; - Diag(PrevDecl->getLocation(), diag::note_declared_at); - Invalid = true; - - // Otherwise, only diagnose if the declaration is in scope. - } else if (!isDeclInScope(PrevDecl, SearchDC, S)) { - // do nothing - - // Diagnose implicit declarations introduced by elaborated types. - } else if (TUK == TUK_Reference || TUK == TUK_Friend) { - unsigned Kind = 0; - if (isa<TypedefDecl>(PrevDecl)) Kind = 1; - else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2; - Diag(NameLoc, diag::err_tag_reference_conflict) << Kind; - Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; - Invalid = true; - - // Otherwise it's a declaration. Call out a particularly common - // case here. - } else if (isa<TypedefDecl>(PrevDecl)) { - Diag(NameLoc, diag::err_tag_definition_of_typedef) - << Name - << cast<TypedefDecl>(PrevDecl)->getUnderlyingType(); - Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; - Invalid = true; - - // Otherwise, diagnose. - } else { - // The tag name clashes with something else in the target scope, - // issue an error and recover by making this tag be anonymous. + // PrevDecl is a namespace, template, or anything else + // that lives in the IDNS_Tag identifier namespace. + if (TUK == TUK_Reference || TUK == TUK_Friend || + isDeclInScope(PrevDecl, SearchDC, S)) { + // The tag name clashes with a namespace name, issue an error and + // recover by making this tag be anonymous. Diag(NameLoc, diag::err_redefinition_different_kind) << Name; Diag(PrevDecl->getLocation(), diag::note_previous_definition); Name = 0; + Previous.clear(); Invalid = true; + } else { + // The existing declaration isn't relevant to us; we're in a + // new scope, so clear out the previous declaration. + Previous.clear(); } - - // The existing declaration isn't relevant to us; we're in a - // new scope, so clear out the previous declaration. - Previous.clear(); } } @@ -5246,6 +5187,28 @@ CreateNewDecl: New->addAttr(::new (Context) PragmaPackAttr(Alignment * 8)); } + if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) { + // C++ [dcl.typedef]p3: + // [...] Similarly, in a given scope, a class or enumeration + // shall not be declared with the same name as a typedef-name + // that is declared in that scope and refers to a type other + // than the class or enumeration itself. + LookupResult Lookup(*this, Name, NameLoc, LookupOrdinaryName, + ForRedeclaration); + LookupName(Lookup, S); + TypedefDecl *PrevTypedef = Lookup.getAsSingle<TypedefDecl>(); + NamedDecl *PrevTypedefNamed = PrevTypedef; + if (PrevTypedef && isDeclInScope(PrevTypedefNamed, SearchDC, S) && + Context.getCanonicalType(Context.getTypeDeclType(PrevTypedef)) != + Context.getCanonicalType(Context.getTypeDeclType(New))) { + Diag(Loc, diag::err_tag_definition_of_typedef) + << Context.getTypeDeclType(New) + << PrevTypedef->getUnderlyingType(); + Diag(PrevTypedef->getLocation(), diag::note_previous_definition); + Invalid = true; + } + } + // If this is a specialization of a member class (of a class template), // check the specialization. if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous)) diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 445d08e666..8de0c40fb7 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -202,6 +202,26 @@ static bool IsAcceptableOperatorName(NamedDecl *D, unsigned IDNS) { !D->getDeclContext()->isRecord(); } +static bool IsAcceptableNestedNameSpecifierName(NamedDecl *D, unsigned IDNS) { + // This lookup ignores everything that isn't a type. + + // This is a fast check for the far most common case. + if (D->isInIdentifierNamespace(Decl::IDNS_Tag)) + return true; + + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + return isa<TypeDecl>(D); +} + +static bool IsAcceptableNamespaceName(NamedDecl *D, unsigned IDNS) { + // We don't need to look through using decls here because + // using decls aren't allowed to name namespaces. + + return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D); +} + /// Gets the default result filter for the given lookup. static inline LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) { @@ -212,12 +232,16 @@ LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) { case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping case Sema::LookupUsingDeclName: case Sema::LookupObjCProtocolName: - case Sema::LookupNestedNameSpecifierName: - case Sema::LookupNamespaceName: return &IsAcceptableIDNS; case Sema::LookupOperatorName: return &IsAcceptableOperatorName; + + case Sema::LookupNestedNameSpecifierName: + return &IsAcceptableNestedNameSpecifierName; + + case Sema::LookupNamespaceName: + return &IsAcceptableNamespaceName; } llvm_unreachable("unkknown lookup kind"); @@ -236,25 +260,15 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, case Sema::LookupRedeclarationWithLinkage: IDNS = Decl::IDNS_Ordinary; if (CPlusPlus) { - IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace; + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member; if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend; } break; case Sema::LookupTagName: - if (CPlusPlus) { - IDNS = Decl::IDNS_Type; - - // When looking for a redeclaration of a tag name, we add: - // 1) TagFriend to find undeclared friend decls - // 2) Namespace because they can't "overload" with tag decls. - // 3) Tag because it includes class templates, which can't - // "overload" with tag decls. - if (Redeclaration) - IDNS |= Decl::IDNS_Tag | Decl::IDNS_TagFriend | Decl::IDNS_Namespace; - } else { - IDNS = Decl::IDNS_Tag; - } + IDNS = Decl::IDNS_Tag; + if (CPlusPlus && Redeclaration) + IDNS |= Decl::IDNS_TagFriend; break; case Sema::LookupMemberName: @@ -264,11 +278,8 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, break; case Sema::LookupNestedNameSpecifierName: - IDNS = Decl::IDNS_Type | Decl::IDNS_Namespace; - break; - case Sema::LookupNamespaceName: - IDNS = Decl::IDNS_Namespace; + IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member; break; case Sema::LookupUsingDeclName: @@ -2123,8 +2134,7 @@ NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) { IEnd = Pos->second.end(); I != IEnd; ++I) { // A tag declaration does not hide a non-tag declaration. - if ((*I)->getIdentifierNamespace() - == (Decl::IDNS_Tag|Decl::IDNS_Type) && + if ((*I)->getIdentifierNamespace() == Decl::IDNS_Tag && (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | Decl::IDNS_ObjCProtocol))) continue; |