xref: /freebsd-src/contrib/llvm-project/clang/include/clang/Sema/Lookup.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- Lookup.h - Classes for name lookup -----------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the LookupResult class, which is integral to
100b57cec5SDimitry Andric // Sema's name-lookup subsystem.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_SEMA_LOOKUP_H
150b57cec5SDimitry Andric #define LLVM_CLANG_SEMA_LOOKUP_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "clang/AST/Decl.h"
180b57cec5SDimitry Andric #include "clang/AST/DeclBase.h"
190b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
200b57cec5SDimitry Andric #include "clang/AST/DeclarationName.h"
210b57cec5SDimitry Andric #include "clang/AST/Type.h"
220b57cec5SDimitry Andric #include "clang/AST/UnresolvedSet.h"
230b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
240b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
250b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
260b57cec5SDimitry Andric #include "clang/Basic/Specifiers.h"
270b57cec5SDimitry Andric #include "clang/Sema/Sema.h"
280b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h"
290b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
300b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
310b57cec5SDimitry Andric #include <cassert>
32bdd1243dSDimitry Andric #include <optional>
330b57cec5SDimitry Andric #include <utility>
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric namespace clang {
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric class CXXBasePaths;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric /// Represents the results of name lookup.
400b57cec5SDimitry Andric ///
410b57cec5SDimitry Andric /// An instance of the LookupResult class captures the results of a
420b57cec5SDimitry Andric /// single name lookup, which can return no result (nothing found),
430b57cec5SDimitry Andric /// a single declaration, a set of overloaded functions, or an
440b57cec5SDimitry Andric /// ambiguity. Use the getKind() method to determine which of these
450b57cec5SDimitry Andric /// results occurred for a given lookup.
460b57cec5SDimitry Andric class LookupResult {
470b57cec5SDimitry Andric public:
480b57cec5SDimitry Andric   enum LookupResultKind {
490b57cec5SDimitry Andric     /// No entity found met the criteria.
500b57cec5SDimitry Andric     NotFound = 0,
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric     /// No entity found met the criteria within the current
530b57cec5SDimitry Andric     /// instantiation,, but there were dependent base classes of the
540b57cec5SDimitry Andric     /// current instantiation that could not be searched.
550b57cec5SDimitry Andric     NotFoundInCurrentInstantiation,
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric     /// Name lookup found a single declaration that met the
580b57cec5SDimitry Andric     /// criteria.  getFoundDecl() will return this declaration.
590b57cec5SDimitry Andric     Found,
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric     /// Name lookup found a set of overloaded functions that
620b57cec5SDimitry Andric     /// met the criteria.
630b57cec5SDimitry Andric     FoundOverloaded,
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric     /// Name lookup found an unresolvable value declaration
660b57cec5SDimitry Andric     /// and cannot yet complete.  This only happens in C++ dependent
670b57cec5SDimitry Andric     /// contexts with dependent using declarations.
680b57cec5SDimitry Andric     FoundUnresolvedValue,
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric     /// Name lookup results in an ambiguity; use
710b57cec5SDimitry Andric     /// getAmbiguityKind to figure out what kind of ambiguity
720b57cec5SDimitry Andric     /// we have.
730b57cec5SDimitry Andric     Ambiguous
740b57cec5SDimitry Andric   };
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   enum AmbiguityKind {
770b57cec5SDimitry Andric     /// Name lookup results in an ambiguity because multiple
780b57cec5SDimitry Andric     /// entities that meet the lookup criteria were found in
790b57cec5SDimitry Andric     /// subobjects of different types. For example:
800b57cec5SDimitry Andric     /// @code
810b57cec5SDimitry Andric     /// struct A { void f(int); }
820b57cec5SDimitry Andric     /// struct B { void f(double); }
830b57cec5SDimitry Andric     /// struct C : A, B { };
840b57cec5SDimitry Andric     /// void test(C c) {
850b57cec5SDimitry Andric     ///   c.f(0); // error: A::f and B::f come from subobjects of different
860b57cec5SDimitry Andric     ///           // types. overload resolution is not performed.
870b57cec5SDimitry Andric     /// }
880b57cec5SDimitry Andric     /// @endcode
890b57cec5SDimitry Andric     AmbiguousBaseSubobjectTypes,
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric     /// Name lookup results in an ambiguity because multiple
920b57cec5SDimitry Andric     /// nonstatic entities that meet the lookup criteria were found
930b57cec5SDimitry Andric     /// in different subobjects of the same type. For example:
940b57cec5SDimitry Andric     /// @code
950b57cec5SDimitry Andric     /// struct A { int x; };
960b57cec5SDimitry Andric     /// struct B : A { };
970b57cec5SDimitry Andric     /// struct C : A { };
980b57cec5SDimitry Andric     /// struct D : B, C { };
990b57cec5SDimitry Andric     /// int test(D d) {
1000b57cec5SDimitry Andric     ///   return d.x; // error: 'x' is found in two A subobjects (of B and C)
1010b57cec5SDimitry Andric     /// }
1020b57cec5SDimitry Andric     /// @endcode
1030b57cec5SDimitry Andric     AmbiguousBaseSubobjects,
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric     /// Name lookup results in an ambiguity because multiple definitions
1060b57cec5SDimitry Andric     /// of entity that meet the lookup criteria were found in different
1070b57cec5SDimitry Andric     /// declaration contexts.
1080b57cec5SDimitry Andric     /// @code
1090b57cec5SDimitry Andric     /// namespace A {
1100b57cec5SDimitry Andric     ///   int i;
1110b57cec5SDimitry Andric     ///   namespace B { int i; }
1120b57cec5SDimitry Andric     ///   int test() {
1130b57cec5SDimitry Andric     ///     using namespace B;
1140b57cec5SDimitry Andric     ///     return i; // error 'i' is found in namespace A and A::B
1150b57cec5SDimitry Andric     ///    }
1160b57cec5SDimitry Andric     /// }
1170b57cec5SDimitry Andric     /// @endcode
1180b57cec5SDimitry Andric     AmbiguousReference,
1190b57cec5SDimitry Andric 
1205f757f3fSDimitry Andric     /// Name lookup results in an ambiguity because multiple placeholder
1215f757f3fSDimitry Andric     /// variables were found in the same scope.
1225f757f3fSDimitry Andric     /// @code
1235f757f3fSDimitry Andric     /// void f() {
1245f757f3fSDimitry Andric     ///    int _ = 0;
1255f757f3fSDimitry Andric     ///    int _ = 0;
1265f757f3fSDimitry Andric     ///    return _; // ambiguous use of placeholder variable
1275f757f3fSDimitry Andric     /// }
1285f757f3fSDimitry Andric     /// @endcode
1295f757f3fSDimitry Andric     AmbiguousReferenceToPlaceholderVariable,
1305f757f3fSDimitry Andric 
1310b57cec5SDimitry Andric     /// Name lookup results in an ambiguity because an entity with a
1320b57cec5SDimitry Andric     /// tag name was hidden by an entity with an ordinary name from
1330b57cec5SDimitry Andric     /// a different context.
1340b57cec5SDimitry Andric     /// @code
1350b57cec5SDimitry Andric     /// namespace A { struct Foo {}; }
1360b57cec5SDimitry Andric     /// namespace B { void Foo(); }
1370b57cec5SDimitry Andric     /// namespace C {
1380b57cec5SDimitry Andric     ///   using namespace A;
1390b57cec5SDimitry Andric     ///   using namespace B;
1400b57cec5SDimitry Andric     /// }
1410b57cec5SDimitry Andric     /// void test() {
1420b57cec5SDimitry Andric     ///   C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
1430b57cec5SDimitry Andric     ///             // different namespace
1440b57cec5SDimitry Andric     /// }
1450b57cec5SDimitry Andric     /// @endcode
1460b57cec5SDimitry Andric     AmbiguousTagHiding
1470b57cec5SDimitry Andric   };
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   /// A little identifier for flagging temporary lookup results.
1500b57cec5SDimitry Andric   enum TemporaryToken {
1510b57cec5SDimitry Andric     Temporary
1520b57cec5SDimitry Andric   };
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   using iterator = UnresolvedSetImpl::iterator;
1550b57cec5SDimitry Andric 
156*0fca6ea1SDimitry Andric   LookupResult(
157*0fca6ea1SDimitry Andric       Sema &SemaRef, const DeclarationNameInfo &NameInfo,
1580b57cec5SDimitry Andric       Sema::LookupNameKind LookupKind,
159*0fca6ea1SDimitry Andric       RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration)
1600b57cec5SDimitry Andric       : SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind),
161*0fca6ea1SDimitry Andric         Redecl(Redecl != RedeclarationKind::NotForRedeclaration),
162*0fca6ea1SDimitry Andric         ExternalRedecl(Redecl == RedeclarationKind::ForExternalRedeclaration),
163*0fca6ea1SDimitry Andric         DiagnoseAccess(Redecl == RedeclarationKind::NotForRedeclaration),
164*0fca6ea1SDimitry Andric         DiagnoseAmbiguous(Redecl == RedeclarationKind::NotForRedeclaration) {
1650b57cec5SDimitry Andric     configure();
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   // TODO: consider whether this constructor should be restricted to take
1690b57cec5SDimitry Andric   // as input a const IdentifierInfo* (instead of Name),
1700b57cec5SDimitry Andric   // forcing other cases towards the constructor taking a DNInfo.
171*0fca6ea1SDimitry Andric   LookupResult(
172*0fca6ea1SDimitry Andric       Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
1735f757f3fSDimitry Andric       Sema::LookupNameKind LookupKind,
174*0fca6ea1SDimitry Andric       RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration)
1750b57cec5SDimitry Andric       : SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind),
176*0fca6ea1SDimitry Andric         Redecl(Redecl != RedeclarationKind::NotForRedeclaration),
177*0fca6ea1SDimitry Andric         ExternalRedecl(Redecl == RedeclarationKind::ForExternalRedeclaration),
178*0fca6ea1SDimitry Andric         DiagnoseAccess(Redecl == RedeclarationKind::NotForRedeclaration),
179*0fca6ea1SDimitry Andric         DiagnoseAmbiguous(Redecl == RedeclarationKind::NotForRedeclaration) {
1800b57cec5SDimitry Andric     configure();
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   /// Creates a temporary lookup result, initializing its core data
1840b57cec5SDimitry Andric   /// using the information from another result.  Diagnostics are always
1850b57cec5SDimitry Andric   /// disabled.
1860b57cec5SDimitry Andric   LookupResult(TemporaryToken _, const LookupResult &Other)
1870b57cec5SDimitry Andric       : SemaPtr(Other.SemaPtr), NameInfo(Other.NameInfo),
1880b57cec5SDimitry Andric         LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl),
1890b57cec5SDimitry Andric         ExternalRedecl(Other.ExternalRedecl), HideTags(Other.HideTags),
1900b57cec5SDimitry Andric         AllowHidden(Other.AllowHidden),
1910b57cec5SDimitry Andric         TemplateNameLookup(Other.TemplateNameLookup) {}
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   // FIXME: Remove these deleted methods once the default build includes
1940b57cec5SDimitry Andric   // -Wdeprecated.
1950b57cec5SDimitry Andric   LookupResult(const LookupResult &) = delete;
1960b57cec5SDimitry Andric   LookupResult &operator=(const LookupResult &) = delete;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   LookupResult(LookupResult &&Other)
1990b57cec5SDimitry Andric       : ResultKind(std::move(Other.ResultKind)),
2000b57cec5SDimitry Andric         Ambiguity(std::move(Other.Ambiguity)), Decls(std::move(Other.Decls)),
2010b57cec5SDimitry Andric         Paths(std::move(Other.Paths)),
2020b57cec5SDimitry Andric         NamingClass(std::move(Other.NamingClass)),
2030b57cec5SDimitry Andric         BaseObjectType(std::move(Other.BaseObjectType)),
2040b57cec5SDimitry Andric         SemaPtr(std::move(Other.SemaPtr)), NameInfo(std::move(Other.NameInfo)),
2050b57cec5SDimitry Andric         NameContextRange(std::move(Other.NameContextRange)),
2060b57cec5SDimitry Andric         LookupKind(std::move(Other.LookupKind)), IDNS(std::move(Other.IDNS)),
2070b57cec5SDimitry Andric         Redecl(std::move(Other.Redecl)),
2080b57cec5SDimitry Andric         ExternalRedecl(std::move(Other.ExternalRedecl)),
2090b57cec5SDimitry Andric         HideTags(std::move(Other.HideTags)),
2105f757f3fSDimitry Andric         DiagnoseAccess(std::move(Other.DiagnoseAccess)),
2115f757f3fSDimitry Andric         DiagnoseAmbiguous(std::move(Other.DiagnoseAmbiguous)),
2120b57cec5SDimitry Andric         AllowHidden(std::move(Other.AllowHidden)),
2130b57cec5SDimitry Andric         Shadowed(std::move(Other.Shadowed)),
2140b57cec5SDimitry Andric         TemplateNameLookup(std::move(Other.TemplateNameLookup)) {
2150b57cec5SDimitry Andric     Other.Paths = nullptr;
2165f757f3fSDimitry Andric     Other.DiagnoseAccess = false;
2175f757f3fSDimitry Andric     Other.DiagnoseAmbiguous = false;
2180b57cec5SDimitry Andric   }
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   LookupResult &operator=(LookupResult &&Other) {
2210b57cec5SDimitry Andric     ResultKind = std::move(Other.ResultKind);
2220b57cec5SDimitry Andric     Ambiguity = std::move(Other.Ambiguity);
2230b57cec5SDimitry Andric     Decls = std::move(Other.Decls);
2240b57cec5SDimitry Andric     Paths = std::move(Other.Paths);
2250b57cec5SDimitry Andric     NamingClass = std::move(Other.NamingClass);
2260b57cec5SDimitry Andric     BaseObjectType = std::move(Other.BaseObjectType);
2270b57cec5SDimitry Andric     SemaPtr = std::move(Other.SemaPtr);
2280b57cec5SDimitry Andric     NameInfo = std::move(Other.NameInfo);
2290b57cec5SDimitry Andric     NameContextRange = std::move(Other.NameContextRange);
2300b57cec5SDimitry Andric     LookupKind = std::move(Other.LookupKind);
2310b57cec5SDimitry Andric     IDNS = std::move(Other.IDNS);
2320b57cec5SDimitry Andric     Redecl = std::move(Other.Redecl);
2330b57cec5SDimitry Andric     ExternalRedecl = std::move(Other.ExternalRedecl);
2340b57cec5SDimitry Andric     HideTags = std::move(Other.HideTags);
2355f757f3fSDimitry Andric     DiagnoseAccess = std::move(Other.DiagnoseAccess);
2365f757f3fSDimitry Andric     DiagnoseAmbiguous = std::move(Other.DiagnoseAmbiguous);
2370b57cec5SDimitry Andric     AllowHidden = std::move(Other.AllowHidden);
2380b57cec5SDimitry Andric     Shadowed = std::move(Other.Shadowed);
2390b57cec5SDimitry Andric     TemplateNameLookup = std::move(Other.TemplateNameLookup);
2400b57cec5SDimitry Andric     Other.Paths = nullptr;
2415f757f3fSDimitry Andric     Other.DiagnoseAccess = false;
2425f757f3fSDimitry Andric     Other.DiagnoseAmbiguous = false;
2430b57cec5SDimitry Andric     return *this;
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   ~LookupResult() {
2475f757f3fSDimitry Andric     if (DiagnoseAccess)
2485f757f3fSDimitry Andric       diagnoseAccess();
2495f757f3fSDimitry Andric     if (DiagnoseAmbiguous)
2505f757f3fSDimitry Andric       diagnoseAmbiguous();
2510b57cec5SDimitry Andric     if (Paths) deletePaths(Paths);
2520b57cec5SDimitry Andric   }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   /// Gets the name info to look up.
2550b57cec5SDimitry Andric   const DeclarationNameInfo &getLookupNameInfo() const {
2560b57cec5SDimitry Andric     return NameInfo;
2570b57cec5SDimitry Andric   }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   /// Sets the name info to look up.
2600b57cec5SDimitry Andric   void setLookupNameInfo(const DeclarationNameInfo &NameInfo) {
2610b57cec5SDimitry Andric     this->NameInfo = NameInfo;
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   /// Gets the name to look up.
2650b57cec5SDimitry Andric   DeclarationName getLookupName() const {
2660b57cec5SDimitry Andric     return NameInfo.getName();
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   /// Sets the name to look up.
2700b57cec5SDimitry Andric   void setLookupName(DeclarationName Name) {
2710b57cec5SDimitry Andric     NameInfo.setName(Name);
2720b57cec5SDimitry Andric   }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   /// Gets the kind of lookup to perform.
2750b57cec5SDimitry Andric   Sema::LookupNameKind getLookupKind() const {
2760b57cec5SDimitry Andric     return LookupKind;
2770b57cec5SDimitry Andric   }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   /// True if this lookup is just looking for an existing declaration.
2800b57cec5SDimitry Andric   bool isForRedeclaration() const {
2810b57cec5SDimitry Andric     return Redecl;
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   /// True if this lookup is just looking for an existing declaration to link
2850b57cec5SDimitry Andric   /// against a declaration with external linkage.
2860b57cec5SDimitry Andric   bool isForExternalRedeclaration() const {
2870b57cec5SDimitry Andric     return ExternalRedecl;
2880b57cec5SDimitry Andric   }
2890b57cec5SDimitry Andric 
290*0fca6ea1SDimitry Andric   RedeclarationKind redeclarationKind() const {
291*0fca6ea1SDimitry Andric     return ExternalRedecl ? RedeclarationKind::ForExternalRedeclaration
292*0fca6ea1SDimitry Andric            : Redecl       ? RedeclarationKind::ForVisibleRedeclaration
293*0fca6ea1SDimitry Andric                           : RedeclarationKind::NotForRedeclaration;
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   /// Specify whether hidden declarations are visible, e.g.,
2970b57cec5SDimitry Andric   /// for recovery reasons.
2980b57cec5SDimitry Andric   void setAllowHidden(bool AH) {
2990b57cec5SDimitry Andric     AllowHidden = AH;
3000b57cec5SDimitry Andric   }
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   /// Determine whether this lookup is permitted to see hidden
3030b57cec5SDimitry Andric   /// declarations, such as those in modules that have not yet been imported.
3040b57cec5SDimitry Andric   bool isHiddenDeclarationVisible(NamedDecl *ND) const {
3050b57cec5SDimitry Andric     return AllowHidden ||
3060b57cec5SDimitry Andric            (isForExternalRedeclaration() && ND->isExternallyDeclarable());
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   /// Sets whether tag declarations should be hidden by non-tag
3100b57cec5SDimitry Andric   /// declarations during resolution.  The default is true.
3110b57cec5SDimitry Andric   void setHideTags(bool Hide) {
3120b57cec5SDimitry Andric     HideTags = Hide;
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   /// Sets whether this is a template-name lookup. For template-name lookups,
3160b57cec5SDimitry Andric   /// injected-class-names are treated as naming a template rather than a
3170b57cec5SDimitry Andric   /// template specialization.
3180b57cec5SDimitry Andric   void setTemplateNameLookup(bool TemplateName) {
3190b57cec5SDimitry Andric     TemplateNameLookup = TemplateName;
3200b57cec5SDimitry Andric   }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   bool isTemplateNameLookup() const { return TemplateNameLookup; }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   bool isAmbiguous() const {
3250b57cec5SDimitry Andric     return getResultKind() == Ambiguous;
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   /// Determines if this names a single result which is not an
3290b57cec5SDimitry Andric   /// unresolved value using decl.  If so, it is safe to call
3300b57cec5SDimitry Andric   /// getFoundDecl().
3310b57cec5SDimitry Andric   bool isSingleResult() const {
3320b57cec5SDimitry Andric     return getResultKind() == Found;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   /// Determines if the results are overloaded.
3360b57cec5SDimitry Andric   bool isOverloadedResult() const {
3370b57cec5SDimitry Andric     return getResultKind() == FoundOverloaded;
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   bool isUnresolvableResult() const {
3410b57cec5SDimitry Andric     return getResultKind() == FoundUnresolvedValue;
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   LookupResultKind getResultKind() const {
3455e801ac6SDimitry Andric     assert(checkDebugAssumptions());
3460b57cec5SDimitry Andric     return ResultKind;
3470b57cec5SDimitry Andric   }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   AmbiguityKind getAmbiguityKind() const {
3500b57cec5SDimitry Andric     assert(isAmbiguous());
3510b57cec5SDimitry Andric     return Ambiguity;
3520b57cec5SDimitry Andric   }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   const UnresolvedSetImpl &asUnresolvedSet() const {
3550b57cec5SDimitry Andric     return Decls;
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   iterator begin() const { return iterator(Decls.begin()); }
3590b57cec5SDimitry Andric   iterator end() const { return iterator(Decls.end()); }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   /// Return true if no decls were found
3620b57cec5SDimitry Andric   bool empty() const { return Decls.empty(); }
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   /// Return the base paths structure that's associated with
3650b57cec5SDimitry Andric   /// these results, or null if none is.
3660b57cec5SDimitry Andric   CXXBasePaths *getBasePaths() const {
3670b57cec5SDimitry Andric     return Paths;
3680b57cec5SDimitry Andric   }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   /// Determine whether the given declaration is visible to the
3710b57cec5SDimitry Andric   /// program.
37281ad6265SDimitry Andric   static bool isVisible(Sema &SemaRef, NamedDecl *D);
3730b57cec5SDimitry Andric 
37481ad6265SDimitry Andric   static bool isReachable(Sema &SemaRef, NamedDecl *D);
37581ad6265SDimitry Andric 
37681ad6265SDimitry Andric   static bool isAcceptable(Sema &SemaRef, NamedDecl *D,
37781ad6265SDimitry Andric                            Sema::AcceptableKind Kind) {
37881ad6265SDimitry Andric     return Kind == Sema::AcceptableKind::Visible ? isVisible(SemaRef, D)
37981ad6265SDimitry Andric                                                  : isReachable(SemaRef, D);
3800b57cec5SDimitry Andric   }
3810b57cec5SDimitry Andric 
38281ad6265SDimitry Andric   /// Determine whether this lookup is permitted to see the declaration.
38381ad6265SDimitry Andric   /// Note that a reachable but not visible declaration inhabiting a namespace
38481ad6265SDimitry Andric   /// is not allowed to be seen during name lookup.
38581ad6265SDimitry Andric   ///
38681ad6265SDimitry Andric   /// For example:
38781ad6265SDimitry Andric   /// ```
38881ad6265SDimitry Andric   /// // m.cppm
38981ad6265SDimitry Andric   /// export module m;
39081ad6265SDimitry Andric   /// struct reachable { int v; }
39181ad6265SDimitry Andric   /// export auto func() { return reachable{43}; }
39281ad6265SDimitry Andric   /// // Use.cpp
39381ad6265SDimitry Andric   /// import m;
39481ad6265SDimitry Andric   /// auto Use() {
39581ad6265SDimitry Andric   ///   // Not valid. We couldn't see reachable here.
39681ad6265SDimitry Andric   ///   // So isAvailableForLookup would return false when we look
39781ad6265SDimitry Andric   ///   up 'reachable' here.
39881ad6265SDimitry Andric   ///   // return reachable(43).v;
39981ad6265SDimitry Andric   ///   // Valid. The field name 'v' is allowed during name lookup.
40081ad6265SDimitry Andric   ///   // So isAvailableForLookup would return true when we look up 'v' here.
40181ad6265SDimitry Andric   ///   return func().v;
40281ad6265SDimitry Andric   /// }
40381ad6265SDimitry Andric   /// ```
40481ad6265SDimitry Andric   static bool isAvailableForLookup(Sema &SemaRef, NamedDecl *ND);
40581ad6265SDimitry Andric 
4060b57cec5SDimitry Andric   /// Retrieve the accepted (re)declaration of the given declaration,
4070b57cec5SDimitry Andric   /// if there is one.
4080b57cec5SDimitry Andric   NamedDecl *getAcceptableDecl(NamedDecl *D) const {
4090b57cec5SDimitry Andric     if (!D->isInIdentifierNamespace(IDNS))
4100b57cec5SDimitry Andric       return nullptr;
4110b57cec5SDimitry Andric 
41281ad6265SDimitry Andric     if (isAvailableForLookup(getSema(), D) || isHiddenDeclarationVisible(D))
4130b57cec5SDimitry Andric       return D;
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric     return getAcceptableDeclSlow(D);
4160b57cec5SDimitry Andric   }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric private:
41981ad6265SDimitry Andric   static bool isAcceptableSlow(Sema &SemaRef, NamedDecl *D,
42081ad6265SDimitry Andric                                Sema::AcceptableKind Kind);
42181ad6265SDimitry Andric   static bool isReachableSlow(Sema &SemaRef, NamedDecl *D);
4220b57cec5SDimitry Andric   NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const;
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric public:
4250b57cec5SDimitry Andric   /// Returns the identifier namespace mask for this lookup.
4260b57cec5SDimitry Andric   unsigned getIdentifierNamespace() const {
4270b57cec5SDimitry Andric     return IDNS;
4280b57cec5SDimitry Andric   }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   /// Returns whether these results arose from performing a
4310b57cec5SDimitry Andric   /// lookup into a class.
4320b57cec5SDimitry Andric   bool isClassLookup() const {
4330b57cec5SDimitry Andric     return NamingClass != nullptr;
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   /// Returns the 'naming class' for this lookup, i.e. the
4370b57cec5SDimitry Andric   /// class which was looked into to find these results.
4380b57cec5SDimitry Andric   ///
4390b57cec5SDimitry Andric   /// C++0x [class.access.base]p5:
4400b57cec5SDimitry Andric   ///   The access to a member is affected by the class in which the
4410b57cec5SDimitry Andric   ///   member is named. This naming class is the class in which the
4420b57cec5SDimitry Andric   ///   member name was looked up and found. [Note: this class can be
4430b57cec5SDimitry Andric   ///   explicit, e.g., when a qualified-id is used, or implicit,
4440b57cec5SDimitry Andric   ///   e.g., when a class member access operator (5.2.5) is used
4450b57cec5SDimitry Andric   ///   (including cases where an implicit "this->" is added). If both
4460b57cec5SDimitry Andric   ///   a class member access operator and a qualified-id are used to
4470b57cec5SDimitry Andric   ///   name the member (as in p->T::m), the class naming the member
4480b57cec5SDimitry Andric   ///   is the class named by the nested-name-specifier of the
4490b57cec5SDimitry Andric   ///   qualified-id (that is, T). -- end note ]
4500b57cec5SDimitry Andric   ///
4510b57cec5SDimitry Andric   /// This is set by the lookup routines when they find results in a class.
4520b57cec5SDimitry Andric   CXXRecordDecl *getNamingClass() const {
4530b57cec5SDimitry Andric     return NamingClass;
4540b57cec5SDimitry Andric   }
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric   /// Sets the 'naming class' for this lookup.
4570b57cec5SDimitry Andric   void setNamingClass(CXXRecordDecl *Record) {
4580b57cec5SDimitry Andric     NamingClass = Record;
4590b57cec5SDimitry Andric   }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   /// Returns the base object type associated with this lookup;
4620b57cec5SDimitry Andric   /// important for [class.protected].  Most lookups do not have an
4630b57cec5SDimitry Andric   /// associated base object.
4640b57cec5SDimitry Andric   QualType getBaseObjectType() const {
4650b57cec5SDimitry Andric     return BaseObjectType;
4660b57cec5SDimitry Andric   }
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   /// Sets the base object type for this lookup.
4690b57cec5SDimitry Andric   void setBaseObjectType(QualType T) {
4700b57cec5SDimitry Andric     BaseObjectType = T;
4710b57cec5SDimitry Andric   }
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric   /// Add a declaration to these results with its natural access.
4740b57cec5SDimitry Andric   /// Does not test the acceptance criteria.
4750b57cec5SDimitry Andric   void addDecl(NamedDecl *D) {
4760b57cec5SDimitry Andric     addDecl(D, D->getAccess());
4770b57cec5SDimitry Andric   }
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   /// Add a declaration to these results with the given access.
4800b57cec5SDimitry Andric   /// Does not test the acceptance criteria.
4810b57cec5SDimitry Andric   void addDecl(NamedDecl *D, AccessSpecifier AS) {
4820b57cec5SDimitry Andric     Decls.addDecl(D, AS);
4830b57cec5SDimitry Andric     ResultKind = Found;
4840b57cec5SDimitry Andric   }
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   /// Add all the declarations from another set of lookup
4870b57cec5SDimitry Andric   /// results.
4880b57cec5SDimitry Andric   void addAllDecls(const LookupResult &Other) {
4890b57cec5SDimitry Andric     Decls.append(Other.Decls.begin(), Other.Decls.end());
4900b57cec5SDimitry Andric     ResultKind = Found;
4910b57cec5SDimitry Andric   }
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric   /// Determine whether no result was found because we could not
4940b57cec5SDimitry Andric   /// search into dependent base classes of the current instantiation.
4950b57cec5SDimitry Andric   bool wasNotFoundInCurrentInstantiation() const {
4960b57cec5SDimitry Andric     return ResultKind == NotFoundInCurrentInstantiation;
4970b57cec5SDimitry Andric   }
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   /// Note that while no result was found in the current instantiation,
5000b57cec5SDimitry Andric   /// there were dependent base classes that could not be searched.
5010b57cec5SDimitry Andric   void setNotFoundInCurrentInstantiation() {
502*0fca6ea1SDimitry Andric     assert((ResultKind == NotFound ||
503*0fca6ea1SDimitry Andric             ResultKind == NotFoundInCurrentInstantiation) &&
504*0fca6ea1SDimitry Andric            Decls.empty());
5050b57cec5SDimitry Andric     ResultKind = NotFoundInCurrentInstantiation;
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   /// Determine whether the lookup result was shadowed by some other
5090b57cec5SDimitry Andric   /// declaration that lookup ignored.
5100b57cec5SDimitry Andric   bool isShadowed() const { return Shadowed; }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   /// Note that we found and ignored a declaration while performing
5130b57cec5SDimitry Andric   /// lookup.
5140b57cec5SDimitry Andric   void setShadowed() { Shadowed = true; }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   /// Resolves the result kind of the lookup, possibly hiding
5170b57cec5SDimitry Andric   /// decls.
5180b57cec5SDimitry Andric   ///
5190b57cec5SDimitry Andric   /// This should be called in any environment where lookup might
5200b57cec5SDimitry Andric   /// generate multiple lookup results.
5210b57cec5SDimitry Andric   void resolveKind();
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   /// Re-resolves the result kind of the lookup after a set of
5240b57cec5SDimitry Andric   /// removals has been performed.
5250b57cec5SDimitry Andric   void resolveKindAfterFilter() {
5260b57cec5SDimitry Andric     if (Decls.empty()) {
5270b57cec5SDimitry Andric       if (ResultKind != NotFoundInCurrentInstantiation)
5280b57cec5SDimitry Andric         ResultKind = NotFound;
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric       if (Paths) {
5310b57cec5SDimitry Andric         deletePaths(Paths);
5320b57cec5SDimitry Andric         Paths = nullptr;
5330b57cec5SDimitry Andric       }
5340b57cec5SDimitry Andric     } else {
535bdd1243dSDimitry Andric       std::optional<AmbiguityKind> SavedAK;
5360b57cec5SDimitry Andric       bool WasAmbiguous = false;
5370b57cec5SDimitry Andric       if (ResultKind == Ambiguous) {
5380b57cec5SDimitry Andric         SavedAK = Ambiguity;
5390b57cec5SDimitry Andric         WasAmbiguous = true;
5400b57cec5SDimitry Andric       }
5410b57cec5SDimitry Andric       ResultKind = Found;
5420b57cec5SDimitry Andric       resolveKind();
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric       // If we didn't make the lookup unambiguous, restore the old
5450b57cec5SDimitry Andric       // ambiguity kind.
5460b57cec5SDimitry Andric       if (ResultKind == Ambiguous) {
5470b57cec5SDimitry Andric         (void)WasAmbiguous;
5480b57cec5SDimitry Andric         assert(WasAmbiguous);
54981ad6265SDimitry Andric         Ambiguity = *SavedAK;
5500b57cec5SDimitry Andric       } else if (Paths) {
5510b57cec5SDimitry Andric         deletePaths(Paths);
5520b57cec5SDimitry Andric         Paths = nullptr;
5530b57cec5SDimitry Andric       }
5540b57cec5SDimitry Andric     }
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   template <class DeclClass>
5580b57cec5SDimitry Andric   DeclClass *getAsSingle() const {
5590b57cec5SDimitry Andric     if (getResultKind() != Found) return nullptr;
5600b57cec5SDimitry Andric     return dyn_cast<DeclClass>(getFoundDecl());
5610b57cec5SDimitry Andric   }
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   /// Fetch the unique decl found by this lookup.  Asserts
5640b57cec5SDimitry Andric   /// that one was found.
5650b57cec5SDimitry Andric   ///
5660b57cec5SDimitry Andric   /// This is intended for users who have examined the result kind
5670b57cec5SDimitry Andric   /// and are certain that there is only one result.
5680b57cec5SDimitry Andric   NamedDecl *getFoundDecl() const {
5690b57cec5SDimitry Andric     assert(getResultKind() == Found
5700b57cec5SDimitry Andric            && "getFoundDecl called on non-unique result");
5710b57cec5SDimitry Andric     return (*begin())->getUnderlyingDecl();
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   /// Fetches a representative decl.  Useful for lazy diagnostics.
5750b57cec5SDimitry Andric   NamedDecl *getRepresentativeDecl() const {
5760b57cec5SDimitry Andric     assert(!Decls.empty() && "cannot get representative of empty set");
5770b57cec5SDimitry Andric     return *begin();
5780b57cec5SDimitry Andric   }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   /// Asks if the result is a single tag decl.
5810b57cec5SDimitry Andric   bool isSingleTagDecl() const {
5820b57cec5SDimitry Andric     return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
5830b57cec5SDimitry Andric   }
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   /// Make these results show that the name was found in
5860b57cec5SDimitry Andric   /// base classes of different types.
5870b57cec5SDimitry Andric   ///
5880b57cec5SDimitry Andric   /// The given paths object is copied and invalidated.
5890b57cec5SDimitry Andric   void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   /// Make these results show that the name was found in
5920b57cec5SDimitry Andric   /// distinct base classes of the same type.
5930b57cec5SDimitry Andric   ///
5940b57cec5SDimitry Andric   /// The given paths object is copied and invalidated.
5950b57cec5SDimitry Andric   void setAmbiguousBaseSubobjects(CXXBasePaths &P);
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   /// Make these results show that the name was found in
5980b57cec5SDimitry Andric   /// different contexts and a tag decl was hidden by an ordinary
5990b57cec5SDimitry Andric   /// decl in a different context.
6000b57cec5SDimitry Andric   void setAmbiguousQualifiedTagHiding() {
6010b57cec5SDimitry Andric     setAmbiguous(AmbiguousTagHiding);
6020b57cec5SDimitry Andric   }
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   /// Clears out any current state.
6050b57cec5SDimitry Andric   LLVM_ATTRIBUTE_REINITIALIZES void clear() {
6060b57cec5SDimitry Andric     ResultKind = NotFound;
6070b57cec5SDimitry Andric     Decls.clear();
6080b57cec5SDimitry Andric     if (Paths) deletePaths(Paths);
6090b57cec5SDimitry Andric     Paths = nullptr;
6100b57cec5SDimitry Andric     NamingClass = nullptr;
6110b57cec5SDimitry Andric     Shadowed = false;
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   /// Clears out any current state and re-initializes for a
6150b57cec5SDimitry Andric   /// different kind of lookup.
6160b57cec5SDimitry Andric   void clear(Sema::LookupNameKind Kind) {
6170b57cec5SDimitry Andric     clear();
6180b57cec5SDimitry Andric     LookupKind = Kind;
6190b57cec5SDimitry Andric     configure();
6200b57cec5SDimitry Andric   }
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric   /// Change this lookup's redeclaration kind.
623*0fca6ea1SDimitry Andric   void setRedeclarationKind(RedeclarationKind RK) {
624*0fca6ea1SDimitry Andric     Redecl = (RK != RedeclarationKind::NotForRedeclaration);
625*0fca6ea1SDimitry Andric     ExternalRedecl = (RK == RedeclarationKind::ForExternalRedeclaration);
6260b57cec5SDimitry Andric     configure();
6270b57cec5SDimitry Andric   }
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric   void dump();
6300b57cec5SDimitry Andric   void print(raw_ostream &);
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   /// Suppress the diagnostics that would normally fire because of this
6330b57cec5SDimitry Andric   /// lookup.  This happens during (e.g.) redeclaration lookups.
6340b57cec5SDimitry Andric   void suppressDiagnostics() {
6355f757f3fSDimitry Andric     DiagnoseAccess = false;
6365f757f3fSDimitry Andric     DiagnoseAmbiguous = false;
6370b57cec5SDimitry Andric   }
6380b57cec5SDimitry Andric 
6395f757f3fSDimitry Andric   /// Suppress the diagnostics that would normally fire because of this
6405f757f3fSDimitry Andric   /// lookup due to access control violations.
6415f757f3fSDimitry Andric   void suppressAccessDiagnostics() { DiagnoseAccess = false; }
6425f757f3fSDimitry Andric 
6435f757f3fSDimitry Andric   /// Determines whether this lookup is suppressing access control diagnostics.
6445f757f3fSDimitry Andric   bool isSuppressingAccessDiagnostics() const { return !DiagnoseAccess; }
6455f757f3fSDimitry Andric 
6465f757f3fSDimitry Andric   /// Determines whether this lookup is suppressing ambiguous lookup
6475f757f3fSDimitry Andric   /// diagnostics.
6485f757f3fSDimitry Andric   bool isSuppressingAmbiguousDiagnostics() const { return !DiagnoseAmbiguous; }
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   /// Sets a 'context' source range.
6510b57cec5SDimitry Andric   void setContextRange(SourceRange SR) {
6520b57cec5SDimitry Andric     NameContextRange = SR;
6530b57cec5SDimitry Andric   }
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   /// Gets the source range of the context of this name; for C++
6560b57cec5SDimitry Andric   /// qualified lookups, this is the source range of the scope
6570b57cec5SDimitry Andric   /// specifier.
6580b57cec5SDimitry Andric   SourceRange getContextRange() const {
6590b57cec5SDimitry Andric     return NameContextRange;
6600b57cec5SDimitry Andric   }
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric   /// Gets the location of the identifier.  This isn't always defined:
6630b57cec5SDimitry Andric   /// sometimes we're doing lookups on synthesized names.
6640b57cec5SDimitry Andric   SourceLocation getNameLoc() const {
6650b57cec5SDimitry Andric     return NameInfo.getLoc();
6660b57cec5SDimitry Andric   }
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric   /// Get the Sema object that this lookup result is searching
6690b57cec5SDimitry Andric   /// with.
6700b57cec5SDimitry Andric   Sema &getSema() const { return *SemaPtr; }
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   /// A class for iterating through a result set and possibly
6730b57cec5SDimitry Andric   /// filtering out results.  The results returned are possibly
6740b57cec5SDimitry Andric   /// sugared.
6750b57cec5SDimitry Andric   class Filter {
6760b57cec5SDimitry Andric     friend class LookupResult;
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric     LookupResult &Results;
6790b57cec5SDimitry Andric     LookupResult::iterator I;
6800b57cec5SDimitry Andric     bool Changed = false;
6810b57cec5SDimitry Andric     bool CalledDone = false;
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric     Filter(LookupResult &Results) : Results(Results), I(Results.begin()) {}
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric   public:
6860b57cec5SDimitry Andric     Filter(Filter &&F)
6870b57cec5SDimitry Andric         : Results(F.Results), I(F.I), Changed(F.Changed),
6880b57cec5SDimitry Andric           CalledDone(F.CalledDone) {
6890b57cec5SDimitry Andric       F.CalledDone = true;
6900b57cec5SDimitry Andric     }
6910b57cec5SDimitry Andric 
69206c3fb27SDimitry Andric     // The move assignment operator is defined as deleted pending
69306c3fb27SDimitry Andric     // further motivation.
69406c3fb27SDimitry Andric     Filter &operator=(Filter &&) = delete;
69506c3fb27SDimitry Andric 
69606c3fb27SDimitry Andric     // The copy constrcutor and copy assignment operator is defined as deleted
69706c3fb27SDimitry Andric     // pending further motivation.
69806c3fb27SDimitry Andric     Filter(const Filter &) = delete;
69906c3fb27SDimitry Andric     Filter &operator=(const Filter &) = delete;
70006c3fb27SDimitry Andric 
7010b57cec5SDimitry Andric     ~Filter() {
7020b57cec5SDimitry Andric       assert(CalledDone &&
7030b57cec5SDimitry Andric              "LookupResult::Filter destroyed without done() call");
7040b57cec5SDimitry Andric     }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric     bool hasNext() const {
7070b57cec5SDimitry Andric       return I != Results.end();
7080b57cec5SDimitry Andric     }
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric     NamedDecl *next() {
7110b57cec5SDimitry Andric       assert(I != Results.end() && "next() called on empty filter");
7120b57cec5SDimitry Andric       return *I++;
7130b57cec5SDimitry Andric     }
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric     /// Restart the iteration.
7160b57cec5SDimitry Andric     void restart() {
7170b57cec5SDimitry Andric       I = Results.begin();
7180b57cec5SDimitry Andric     }
7190b57cec5SDimitry Andric 
7200b57cec5SDimitry Andric     /// Erase the last element returned from this iterator.
7210b57cec5SDimitry Andric     void erase() {
7220b57cec5SDimitry Andric       Results.Decls.erase(--I);
7230b57cec5SDimitry Andric       Changed = true;
7240b57cec5SDimitry Andric     }
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric     /// Replaces the current entry with the given one, preserving the
7270b57cec5SDimitry Andric     /// access bits.
7280b57cec5SDimitry Andric     void replace(NamedDecl *D) {
7290b57cec5SDimitry Andric       Results.Decls.replace(I-1, D);
7300b57cec5SDimitry Andric       Changed = true;
7310b57cec5SDimitry Andric     }
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric     /// Replaces the current entry with the given one.
7340b57cec5SDimitry Andric     void replace(NamedDecl *D, AccessSpecifier AS) {
7350b57cec5SDimitry Andric       Results.Decls.replace(I-1, D, AS);
7360b57cec5SDimitry Andric       Changed = true;
7370b57cec5SDimitry Andric     }
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric     void done() {
7400b57cec5SDimitry Andric       assert(!CalledDone && "done() called twice");
7410b57cec5SDimitry Andric       CalledDone = true;
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric       if (Changed)
7440b57cec5SDimitry Andric         Results.resolveKindAfterFilter();
7450b57cec5SDimitry Andric     }
7460b57cec5SDimitry Andric   };
7470b57cec5SDimitry Andric 
7480b57cec5SDimitry Andric   /// Create a filter for this result set.
7490b57cec5SDimitry Andric   Filter makeFilter() {
7500b57cec5SDimitry Andric     return Filter(*this);
7510b57cec5SDimitry Andric   }
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   void setFindLocalExtern(bool FindLocalExtern) {
7540b57cec5SDimitry Andric     if (FindLocalExtern)
7550b57cec5SDimitry Andric       IDNS |= Decl::IDNS_LocalExtern;
7560b57cec5SDimitry Andric     else
7570b57cec5SDimitry Andric       IDNS &= ~Decl::IDNS_LocalExtern;
7580b57cec5SDimitry Andric   }
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric private:
7615f757f3fSDimitry Andric   void diagnoseAccess() {
762b3edf446SDimitry Andric     if (!isAmbiguous() && isClassLookup() &&
763b3edf446SDimitry Andric         getSema().getLangOpts().AccessControl)
7645f757f3fSDimitry Andric       getSema().CheckLookupAccess(*this);
7655f757f3fSDimitry Andric   }
7665f757f3fSDimitry Andric 
7675f757f3fSDimitry Andric   void diagnoseAmbiguous() {
7680b57cec5SDimitry Andric     if (isAmbiguous())
7690b57cec5SDimitry Andric       getSema().DiagnoseAmbiguousLookup(*this);
7700b57cec5SDimitry Andric   }
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric   void setAmbiguous(AmbiguityKind AK) {
7730b57cec5SDimitry Andric     ResultKind = Ambiguous;
7740b57cec5SDimitry Andric     Ambiguity = AK;
7750b57cec5SDimitry Andric   }
7760b57cec5SDimitry Andric 
7770b57cec5SDimitry Andric   void addDeclsFromBasePaths(const CXXBasePaths &P);
7780b57cec5SDimitry Andric   void configure();
7790b57cec5SDimitry Andric 
7805e801ac6SDimitry Andric   bool checkDebugAssumptions() const;
7810b57cec5SDimitry Andric 
7825e801ac6SDimitry Andric   bool checkUnresolved() const {
7830b57cec5SDimitry Andric     for (iterator I = begin(), E = end(); I != E; ++I)
7840b57cec5SDimitry Andric       if (isa<UnresolvedUsingValueDecl>((*I)->getUnderlyingDecl()))
7850b57cec5SDimitry Andric         return true;
7860b57cec5SDimitry Andric     return false;
7870b57cec5SDimitry Andric   }
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric   static void deletePaths(CXXBasePaths *);
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   // Results.
7920b57cec5SDimitry Andric   LookupResultKind ResultKind = NotFound;
7930b57cec5SDimitry Andric   // ill-defined unless ambiguous. Still need to be initialized it will be
7940b57cec5SDimitry Andric   // copied/moved.
7950b57cec5SDimitry Andric   AmbiguityKind Ambiguity = {};
7960b57cec5SDimitry Andric   UnresolvedSet<8> Decls;
7970b57cec5SDimitry Andric   CXXBasePaths *Paths = nullptr;
7980b57cec5SDimitry Andric   CXXRecordDecl *NamingClass = nullptr;
7990b57cec5SDimitry Andric   QualType BaseObjectType;
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric   // Parameters.
8020b57cec5SDimitry Andric   Sema *SemaPtr;
8030b57cec5SDimitry Andric   DeclarationNameInfo NameInfo;
8040b57cec5SDimitry Andric   SourceRange NameContextRange;
8050b57cec5SDimitry Andric   Sema::LookupNameKind LookupKind;
8060b57cec5SDimitry Andric   unsigned IDNS = 0; // set by configure()
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric   bool Redecl;
8090b57cec5SDimitry Andric   bool ExternalRedecl;
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric   /// True if tag declarations should be hidden if non-tags
8120b57cec5SDimitry Andric   ///   are present
8130b57cec5SDimitry Andric   bool HideTags = true;
8140b57cec5SDimitry Andric 
8155f757f3fSDimitry Andric   bool DiagnoseAccess = false;
8165f757f3fSDimitry Andric   bool DiagnoseAmbiguous = false;
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric   /// True if we should allow hidden declarations to be 'visible'.
8190b57cec5SDimitry Andric   bool AllowHidden = false;
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric   /// True if the found declarations were shadowed by some other
8220b57cec5SDimitry Andric   /// declaration that we skipped. This only happens when \c LookupKind
8230b57cec5SDimitry Andric   /// is \c LookupRedeclarationWithLinkage.
8240b57cec5SDimitry Andric   bool Shadowed = false;
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric   /// True if we're looking up a template-name.
8270b57cec5SDimitry Andric   bool TemplateNameLookup = false;
8280b57cec5SDimitry Andric };
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric /// Consumes visible declarations found when searching for
8310b57cec5SDimitry Andric /// all visible names within a given scope or context.
8320b57cec5SDimitry Andric ///
8330b57cec5SDimitry Andric /// This abstract class is meant to be subclassed by clients of \c
8340b57cec5SDimitry Andric /// Sema::LookupVisibleDecls(), each of which should override the \c
8350b57cec5SDimitry Andric /// FoundDecl() function to process declarations as they are found.
8360b57cec5SDimitry Andric class VisibleDeclConsumer {
8370b57cec5SDimitry Andric public:
8380b57cec5SDimitry Andric   /// Destroys the visible declaration consumer.
8390b57cec5SDimitry Andric   virtual ~VisibleDeclConsumer();
8400b57cec5SDimitry Andric 
8410b57cec5SDimitry Andric   /// Determine whether hidden declarations (from unimported
8420b57cec5SDimitry Andric   /// modules) should be given to this consumer. By default, they
8430b57cec5SDimitry Andric   /// are not included.
8440b57cec5SDimitry Andric   virtual bool includeHiddenDecls() const;
8450b57cec5SDimitry Andric 
8460b57cec5SDimitry Andric   /// Invoked each time \p Sema::LookupVisibleDecls() finds a
8470b57cec5SDimitry Andric   /// declaration visible from the current scope or context.
8480b57cec5SDimitry Andric   ///
8490b57cec5SDimitry Andric   /// \param ND the declaration found.
8500b57cec5SDimitry Andric   ///
8510b57cec5SDimitry Andric   /// \param Hiding a declaration that hides the declaration \p ND,
8520b57cec5SDimitry Andric   /// or NULL if no such declaration exists.
8530b57cec5SDimitry Andric   ///
8540b57cec5SDimitry Andric   /// \param Ctx the original context from which the lookup started.
8550b57cec5SDimitry Andric   ///
8560b57cec5SDimitry Andric   /// \param InBaseClass whether this declaration was found in base
8570b57cec5SDimitry Andric   /// class of the context we searched.
8580b57cec5SDimitry Andric   virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
8590b57cec5SDimitry Andric                          bool InBaseClass) = 0;
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric   /// Callback to inform the client that Sema entered into a new context
8620b57cec5SDimitry Andric   /// to find a visible declaration.
8630b57cec5SDimitry Andric   //
8640b57cec5SDimitry Andric   /// \param Ctx the context which Sema entered.
8650b57cec5SDimitry Andric   virtual void EnteredContext(DeclContext *Ctx) {}
8660b57cec5SDimitry Andric };
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric /// A class for storing results from argument-dependent lookup.
8690b57cec5SDimitry Andric class ADLResult {
8700b57cec5SDimitry Andric private:
8710b57cec5SDimitry Andric   /// A map from canonical decls to the 'most recent' decl.
8720b57cec5SDimitry Andric   llvm::MapVector<NamedDecl*, NamedDecl*> Decls;
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric   struct select_second {
8750b57cec5SDimitry Andric     NamedDecl *operator()(std::pair<NamedDecl*, NamedDecl*> P) const {
8760b57cec5SDimitry Andric       return P.second;
8770b57cec5SDimitry Andric     }
8780b57cec5SDimitry Andric   };
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric public:
8810b57cec5SDimitry Andric   /// Adds a new ADL candidate to this map.
8820b57cec5SDimitry Andric   void insert(NamedDecl *D);
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric   /// Removes any data associated with a given decl.
8850b57cec5SDimitry Andric   void erase(NamedDecl *D) {
8860b57cec5SDimitry Andric     Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
8870b57cec5SDimitry Andric   }
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric   using iterator =
8900b57cec5SDimitry Andric       llvm::mapped_iterator<decltype(Decls)::iterator, select_second>;
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric   iterator begin() { return iterator(Decls.begin(), select_second()); }
8930b57cec5SDimitry Andric   iterator end() { return iterator(Decls.end(), select_second()); }
8940b57cec5SDimitry Andric };
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric } // namespace clang
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric #endif // LLVM_CLANG_SEMA_LOOKUP_H
899