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