From: Douglas Gregor Date: Mon, 2 Feb 2009 21:35:47 +0000 (+0000) Subject: Add iterators to LookupResult, allowing one to iterate over the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d863517ab7e936cbc3244a0fc431c8b672f5ece4;p=clang Add iterators to LookupResult, allowing one to iterate over the non-ambiguous name lookup results without allocating any memory, e.g., for sets of overloaded functions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63549 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 6036205488..b0a0a5e9ee 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -735,6 +735,55 @@ public: Decl* getAsDecl() const; BasePaths *getBasePaths() const; + + /// \brief Iterate over the results of name lookup. + /// + /// The @c iterator class provides iteration over the results of a + /// non-ambiguous name lookup. + class iterator { + /// The LookupResult structure we're iterating through. + LookupResult *Result; + + /// The current position of this iterator within the sequence of + /// results. This value will have the same representation as the + /// @c First field in the LookupResult structure. + mutable uintptr_t Current; + + public: + typedef Decl * value_type; + typedef Decl * reference; + typedef Decl * pointer; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + iterator() : Result(0), Current(0) { } + + iterator(LookupResult *Res, uintptr_t Cur) : Result(Res), Current(Cur) { } + + reference operator*() const; + + pointer operator->() const { return **this; } + + iterator &operator++(); + + iterator operator++(int) { + iterator tmp(*this); + ++(*this); + return tmp; + } + + friend inline bool operator==(iterator const& x, iterator const& y) { + return x.Current == y.Current; + } + + friend inline bool operator!=(iterator const& x, iterator const& y) { + return x.Current != y.Current; + } + }; + friend class iterator; + + iterator begin(); + iterator end(); }; /// Determines whether D is a suitable lookup result according to the diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index fe7ab92b6a..d03879e907 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1666,35 +1666,22 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, << D.getCXXScopeSpec().getRange(); InvalidDecl = true; - PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName); - if (!PrevDecl) { - // Nothing to suggest. - } else if (OverloadedFunctionDecl *Ovl - = dyn_cast(PrevDecl)) { - for (OverloadedFunctionDecl::function_iterator - Func = Ovl->function_begin(), - FuncEnd = Ovl->function_end(); - Func != FuncEnd; ++Func) { - if (isNearlyMatchingMemberFunction(Context, *Func, NewFD)) - Diag((*Func)->getLocation(), diag::note_member_def_close_match); - - } - } else if (CXXMethodDecl *Method = dyn_cast(PrevDecl)) { - // Suggest this no matter how mismatched it is; it's the only - // thing we have. - unsigned diag; - if (isNearlyMatchingMemberFunction(Context, Method, NewFD)) - diag = diag::note_member_def_close_match; - else if (Method->getBody()) - diag = diag::note_previous_definition; - else - diag = diag::note_previous_declaration; - Diag(Method->getLocation(), diag); + LookupResult Prev = LookupQualifiedName(DC, Name, LookupOrdinaryName, + true); + assert(!Prev.isAmbiguous() && + "Cannot have an ambiguity in previous-declaration lookup"); + for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); + Func != FuncEnd; ++Func) { + if (isa(*Func) && + isNearlyMatchingMemberFunction(Context, cast(*Func), + NewFD)) + Diag((*Func)->getLocation(), diag::note_member_def_close_match); } - + PrevDecl = 0; } } + // Handle attributes. We need to have merged decls when handling attributes // (for example to check for conflicts, etc). ProcessDeclAttributes(NewFD, D); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 8bc3496a19..5ef6de3bf3 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1342,6 +1342,8 @@ bool Sema::CheckValueInitialization(QualType Type, SourceLocation Loc) { // [...] A program that calls for default-initialization or // value-initialization of an entity of reference type is // ill-formed. [...] + // FIXME: Once we have code that goes through this path, add an + // actual diagnostic :) } return false; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index abb265da49..da2deec02a 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -181,6 +181,66 @@ BasePaths *Sema::LookupResult::getBasePaths() const { return reinterpret_cast(First); } +Sema::LookupResult::iterator::reference +Sema::LookupResult::iterator::operator*() const { + switch (Result->StoredKind) { + case SingleDecl: + return reinterpret_cast(Current); + + case OverloadedDeclFromIdResolver: + return *IdentifierResolver::iterator::getFromOpaqueValue(Current); + + case OverloadedDeclFromDeclContext: + return *reinterpret_cast(Current); + + case AmbiguousLookup: + assert(false && "Cannot look into ambiguous lookup results"); + break; + } + + return 0; +} + +Sema::LookupResult::iterator& Sema::LookupResult::iterator::operator++() { + switch (Result->StoredKind) { + case SingleDecl: + Current = reinterpret_cast((Decl*)0); + break; + + case OverloadedDeclFromIdResolver: { + IdentifierResolver::iterator I + = IdentifierResolver::iterator::getFromOpaqueValue(Current); + ++I; + Current = I.getAsOpaqueValue(); + break; + } + + case OverloadedDeclFromDeclContext: { + DeclContext::lookup_iterator I + = reinterpret_cast(Current); + ++I; + Current = reinterpret_cast(I); + break; + } + + case AmbiguousLookup: + assert(false && "Cannot look into ambiguous lookup results"); + break; + } + + return *this; +} + +Sema::LookupResult::iterator Sema::LookupResult::begin() { + assert(StoredKind != AmbiguousLookup && "Lookup into an ambiguous result"); + return iterator(this, First); +} + +Sema::LookupResult::iterator Sema::LookupResult::end() { + assert(StoredKind != AmbiguousLookup && "Lookup into an ambiguous result"); + return iterator(this, Last); +} + // Retrieve the set of identifier namespaces that correspond to a // specific kind of name lookup. inline unsigned diff --git a/test/Sema/init.c b/test/Sema/init.c index 41ca6244ff..3c8f3fe134 100644 --- a/test/Sema/init.c +++ b/test/Sema/init.c @@ -96,3 +96,13 @@ struct { int a; int z[2]; } y = { .z = {} }; + +int bbb[10]; + +struct foo2 { + unsigned a; +}; + +struct foo2 bar2[] = { + { (int)bbb } +};