diff options
-rw-r--r-- | lib/Sema/Lookup.h | 39 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 34 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 34 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 130 | ||||
-rw-r--r-- | test/SemaCXX/nested-name-spec.cpp | 17 |
5 files changed, 122 insertions, 132 deletions
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index 78f79eac2b..6b7e28ce3d 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -121,6 +121,8 @@ public: typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy; typedef DeclsTy::const_iterator iterator; + typedef bool (*ResultFilter)(NamedDecl*, unsigned IDNS); + LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc, Sema::LookupNameKind LookupKind, Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) @@ -130,11 +132,14 @@ public: Name(Name), NameLoc(NameLoc), LookupKind(LookupKind), + IsAcceptableFn(0), IDNS(0), Redecl(Redecl != Sema::NotForRedeclaration), HideTags(true), Diagnose(Redecl == Sema::NotForRedeclaration) - {} + { + configure(); + } /// Creates a temporary lookup result, initializing its core data /// using the information from another result. Diagnostics are always @@ -146,6 +151,7 @@ public: Name(Other.Name), NameLoc(Other.NameLoc), LookupKind(Other.LookupKind), + IsAcceptableFn(Other.IsAcceptableFn), IDNS(Other.IDNS), Redecl(Other.Redecl), HideTags(Other.HideTags), @@ -178,17 +184,6 @@ public: HideTags = Hide; } - /// The identifier namespace of this lookup. This information is - /// private to the lookup routines. - unsigned getIdentifierNamespace() const { - assert(IDNS); - return IDNS; - } - - void setIdentifierNamespace(unsigned NS) { - IDNS = NS; - } - bool isAmbiguous() const { return getResultKind() == Ambiguous; } @@ -231,7 +226,19 @@ public: return Paths; } - /// \brief Add a declaration to these results. + /// \brief Tests whether the given declaration is acceptable. + bool isAcceptableDecl(NamedDecl *D) const { + assert(IsAcceptableFn); + return IsAcceptableFn(D, IDNS); + } + + /// \brief Returns the identifier namespace mask for this lookup. + unsigned getIdentifierNamespace() const { + return IDNS; + } + + /// \brief Add a declaration to these results. Does not test the + /// acceptance criteria. void addDecl(NamedDecl *D) { Decls.push_back(D); ResultKind = Found; @@ -334,6 +341,7 @@ public: void clear(Sema::LookupNameKind Kind) { clear(); LookupKind = Kind; + configure(); } void print(llvm::raw_ostream &); @@ -438,6 +446,7 @@ private: } void addDeclsFromBasePaths(const CXXBasePaths &P); + void configure(); // Sanity checks. void sanity() const { @@ -476,7 +485,9 @@ private: SourceLocation NameLoc; SourceRange NameContextRange; Sema::LookupNameKind LookupKind; - unsigned IDNS; // ill-defined until set by lookup + ResultFilter IsAcceptableFn; // set by configure() + unsigned IDNS; // set by configure() + bool Redecl; /// \brief True if tag declarations should be hidden if non-tags diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 9d40a13786..24101c6702 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -613,10 +613,6 @@ public: const LookupResult &Previous, Scope *S); void DiagnoseFunctionSpecifiers(Declarator& D); - bool CheckRedeclaration(DeclContext *DC, - DeclarationName Name, - SourceLocation NameLoc, - unsigned Diagnostic); NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, bool &Redeclaration); @@ -1176,36 +1172,6 @@ private: bool CppLookupName(LookupResult &R, Scope *S); public: - /// Determines whether D is a suitable lookup result according to the - /// lookup criteria. - static bool isAcceptableLookupResult(NamedDecl *D, LookupNameKind NameKind, - unsigned IDNS) { - switch (NameKind) { - case Sema::LookupOrdinaryName: - case Sema::LookupTagName: - case Sema::LookupMemberName: - case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping - case Sema::LookupUsingDeclName: - case Sema::LookupObjCProtocolName: - case Sema::LookupObjCImplementationName: - return D->isInIdentifierNamespace(IDNS); - - case Sema::LookupOperatorName: - return D->isInIdentifierNamespace(IDNS) && - !D->getDeclContext()->isRecord(); - - case Sema::LookupNestedNameSpecifierName: - return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag); - - case Sema::LookupNamespaceName: - return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D); - } - - assert(false && - "isAcceptableLookupResult always returns before this point"); - return false; - } - /// \brief Look up a name, looking for a single declaration. Return /// null if the results were absent, ambiguous, or overloaded. /// diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 5bb168068f..587c141b4b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1519,29 +1519,27 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { return DeclPtrTy::make(Tag); } -/// We are trying to introduce the given name into the given context; +/// We are trying to inject an anonymous member into the given scope; /// check if there's an existing declaration that can't be overloaded. /// /// \return true if this is a forbidden redeclaration -bool Sema::CheckRedeclaration(DeclContext *DC, - DeclarationName Name, - SourceLocation NameLoc, - unsigned diagnostic) { - LookupResult R(*this, Name, NameLoc, LookupOrdinaryName, - ForRedeclaration); - LookupQualifiedName(R, DC); - - if (R.empty()) return false; - - if (R.getResultKind() == LookupResult::Found && - isa<TagDecl>(R.getFoundDecl())) +static bool CheckAnonMemberRedeclaration(Sema &SemaRef, + Scope *S, + DeclarationName Name, + SourceLocation NameLoc, + unsigned diagnostic) { + LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName, + Sema::ForRedeclaration); + if (!SemaRef.LookupName(R, S)) return false; + + if (R.getAsSingle<TagDecl>()) return false; // Pick a representative declaration. - NamedDecl *PrevDecl = (*R.begin())->getUnderlyingDecl(); + NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl(); - Diag(NameLoc, diagnostic) << Name; - Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + SemaRef.Diag(NameLoc, diagnostic) << Name; + SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration); return true; } @@ -1573,8 +1571,8 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, FEnd = AnonRecord->field_end(); F != FEnd; ++F) { if ((*F)->getDeclName()) { - if (CheckRedeclaration(Owner, (*F)->getDeclName(), - (*F)->getLocation(), diagKind)) { + if (CheckAnonMemberRedeclaration(*this, S, (*F)->getDeclName(), + (*F)->getLocation(), diagKind)) { // C++ [class.union]p2: // The names of the members of an anonymous union shall be // distinct from the names of any other entity in the diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 724e2fc1e4..5e60cc8727 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -192,23 +192,71 @@ namespace { }; } +static bool IsAcceptableIDNS(NamedDecl *D, unsigned IDNS) { + return D->isInIdentifierNamespace(IDNS); +} + +static bool IsAcceptableOperatorName(NamedDecl *D, unsigned IDNS) { + return D->isInIdentifierNamespace(IDNS) && + !D->getDeclContext()->isRecord(); +} + +static bool IsAcceptableNestedNameSpecifierName(NamedDecl *D, unsigned IDNS) { + return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag); +} + +static bool IsAcceptableNamespaceName(NamedDecl *D, unsigned IDNS) { + return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D); +} + +/// Gets the default result filter for the given lookup. +static inline +LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) { + switch (NameKind) { + case Sema::LookupOrdinaryName: + case Sema::LookupTagName: + case Sema::LookupMemberName: + case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping + case Sema::LookupUsingDeclName: + case Sema::LookupObjCProtocolName: + case Sema::LookupObjCImplementationName: + return &IsAcceptableIDNS; + + case Sema::LookupOperatorName: + return &IsAcceptableOperatorName; + + case Sema::LookupNestedNameSpecifierName: + return &IsAcceptableNestedNameSpecifierName; + + case Sema::LookupNamespaceName: + return &IsAcceptableNamespaceName; + } + + llvm_unreachable("unkknown lookup kind"); + return 0; +} + // Retrieve the set of identifier namespaces that correspond to a // specific kind of name lookup. -inline unsigned -getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, - bool CPlusPlus) { +static inline unsigned getIDNS(Sema::LookupNameKind NameKind, + bool CPlusPlus, + bool Redeclaration) { unsigned IDNS = 0; switch (NameKind) { case Sema::LookupOrdinaryName: case Sema::LookupOperatorName: case Sema::LookupRedeclarationWithLinkage: IDNS = Decl::IDNS_Ordinary; - if (CPlusPlus) + if (CPlusPlus) { IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member; + if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend; + } break; case Sema::LookupTagName: IDNS = Decl::IDNS_Tag; + if (CPlusPlus && Redeclaration) + IDNS |= Decl::IDNS_TagFriend; break; case Sema::LookupMemberName: @@ -238,6 +286,13 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, return IDNS; } +void LookupResult::configure() { + IDNS = getIDNS(LookupKind, + SemaRef.getLangOptions().CPlusPlus, + isForRedeclaration()); + IsAcceptableFn = getResultFilter(LookupKind); +} + // Necessary because CXXBasePaths is not complete in Sema.h void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; @@ -377,8 +432,7 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) { DeclContext::lookup_const_iterator I, E; for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) - if (Sema::isAcceptableLookupResult(*I, R.getLookupKind(), - R.getIdentifierNamespace())) + if (R.isAcceptableDecl(*I)) R.addDecl(*I), Found = true; return Found; @@ -424,19 +478,7 @@ static DeclContext *findOuterContext(Scope *S) { } bool Sema::CppLookupName(LookupResult &R, Scope *S) { - assert(getLangOptions().CPlusPlus && - "Can perform only C++ lookup"); - LookupNameKind NameKind = R.getLookupKind(); - unsigned IDNS - = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true); - - // If we're testing for redeclarations, also look in the friend namespaces. - if (R.isForRedeclaration()) { - if (IDNS & Decl::IDNS_Tag) IDNS |= Decl::IDNS_TagFriend; - if (IDNS & Decl::IDNS_Ordinary) IDNS |= Decl::IDNS_OrdinaryFriend; - } - - R.setIdentifierNamespace(IDNS); + assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup"); DeclarationName Name = R.getLookupName(); @@ -467,7 +509,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { - if (isAcceptableLookupResult(*I, NameKind, IDNS)) { + if (R.isAcceptableDecl(*I)) { Found = true; R.addDecl(*I); } @@ -531,7 +573,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { - if (isAcceptableLookupResult(*I, NameKind, IDNS)) { + if (R.isAcceptableDecl(*I)) { // We found something. Look for anything else in our scope // with this same name and in an acceptable identifier // namespace, so that we can construct an overload set if we @@ -597,47 +639,18 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { if (!getLangOptions().CPlusPlus) { // Unqualified name lookup in C/Objective-C is purely lexical, so // search in the declarations attached to the name. - unsigned IDNS = 0; - switch (NameKind) { - case Sema::LookupOrdinaryName: - IDNS = Decl::IDNS_Ordinary; - break; - - case Sema::LookupTagName: - IDNS = Decl::IDNS_Tag; - break; - - case Sema::LookupMemberName: - IDNS = Decl::IDNS_Member; - break; - case Sema::LookupOperatorName: - case Sema::LookupNestedNameSpecifierName: - case Sema::LookupNamespaceName: - case Sema::LookupUsingDeclName: - assert(false && "C does not perform these kinds of name lookup"); - break; - - case Sema::LookupRedeclarationWithLinkage: + if (NameKind == Sema::LookupRedeclarationWithLinkage) { // Find the nearest non-transparent declaration scope. while (!(S->getFlags() & Scope::DeclScope) || (S->getEntity() && static_cast<DeclContext *>(S->getEntity()) ->isTransparentContext())) S = S->getParent(); - IDNS = Decl::IDNS_Ordinary; - break; - - case Sema::LookupObjCProtocolName: - IDNS = Decl::IDNS_ObjCProtocol; - break; - - case Sema::LookupObjCImplementationName: - IDNS = Decl::IDNS_ObjCImplementation; - break; - } + unsigned IDNS = R.getIdentifierNamespace(); + // Scan up the scope chain looking for a decl that matches this // identifier that is in the appropriate namespace. This search // should not take long, as shadowing of names is uncommon, and @@ -864,17 +877,6 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) { if (!R.getLookupName()) return false; - // If we're performing qualified name lookup (e.g., lookup into a - // struct), find fields as part of ordinary name lookup. - LookupNameKind NameKind = R.getLookupKind(); - unsigned IDNS - = getIdentifierNamespacesFromLookupNameKind(NameKind, - getLangOptions().CPlusPlus); - if (NameKind == LookupOrdinaryName) - IDNS |= Decl::IDNS_Member; - - R.setIdentifierNamespace(IDNS); - // Make sure that the declaration context is complete. assert((!isa<TagDecl>(LookupCtx) || LookupCtx->isDependentContext() || diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index 223e6ff668..dc8eda5994 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -191,6 +191,19 @@ foo<somens:a> a2; // expected-error {{unexpected ':' in nested name specifier}} somens::a a3 = a2; // expected-error {{cannot initialize 'a3' with an lvalue of type 'foo<somens::a>'}} +// typedefs and using declarations. +namespace test1 { + namespace ns { + class Counter { static int count; }; + typedef Counter counter; + } + using ns::counter; - - + class Test { + void test1() { + counter c; + c.count++; + counter::count++; + } + }; +} |