10b57cec5SDimitry Andric //===- IdentifierResolver.h - Lexical Scope 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 IdentifierResolver class, which is used for lexical 100b57cec5SDimitry Andric // scoped lookup, based on declaration names. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H 150b57cec5SDimitry Andric #define LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 190b57cec5SDimitry Andric #include <cassert> 200b57cec5SDimitry Andric #include <cstddef> 210b57cec5SDimitry Andric #include <cstdint> 220b57cec5SDimitry Andric #include <iterator> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace clang { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric class Decl; 270b57cec5SDimitry Andric class DeclarationName; 280b57cec5SDimitry Andric class DeclContext; 290b57cec5SDimitry Andric class IdentifierInfo; 300b57cec5SDimitry Andric class LangOptions; 310b57cec5SDimitry Andric class NamedDecl; 320b57cec5SDimitry Andric class Preprocessor; 330b57cec5SDimitry Andric class Scope; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric /// IdentifierResolver - Keeps track of shadowed decls on enclosing 360b57cec5SDimitry Andric /// scopes. It manages the shadowing chains of declaration names and 370b57cec5SDimitry Andric /// implements efficient decl lookup based on a declaration name. 380b57cec5SDimitry Andric class IdentifierResolver { 390b57cec5SDimitry Andric /// IdDeclInfo - Keeps track of information about decls associated 400b57cec5SDimitry Andric /// to a particular declaration name. IdDeclInfos are lazily 410b57cec5SDimitry Andric /// constructed and assigned to a declaration name the first time a 420b57cec5SDimitry Andric /// decl with that declaration name is shadowed in some scope. 430b57cec5SDimitry Andric class IdDeclInfo { 440b57cec5SDimitry Andric public: 450b57cec5SDimitry Andric using DeclsTy = SmallVector<NamedDecl *, 2>; 460b57cec5SDimitry Andric decls_begin()470b57cec5SDimitry Andric DeclsTy::iterator decls_begin() { return Decls.begin(); } decls_end()480b57cec5SDimitry Andric DeclsTy::iterator decls_end() { return Decls.end(); } 490b57cec5SDimitry Andric AddDecl(NamedDecl * D)500b57cec5SDimitry Andric void AddDecl(NamedDecl *D) { Decls.push_back(D); } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric /// RemoveDecl - Remove the decl from the scope chain. 530b57cec5SDimitry Andric /// The decl must already be part of the decl chain. 540b57cec5SDimitry Andric void RemoveDecl(NamedDecl *D); 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric /// Insert the given declaration at the given position in the list. InsertDecl(DeclsTy::iterator Pos,NamedDecl * D)570b57cec5SDimitry Andric void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) { 580b57cec5SDimitry Andric Decls.insert(Pos, D); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric private: 620b57cec5SDimitry Andric DeclsTy Decls; 630b57cec5SDimitry Andric }; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric public: 660b57cec5SDimitry Andric /// iterator - Iterate over the decls of a specified declaration name. 670b57cec5SDimitry Andric /// It will walk or not the parent declaration contexts depending on how 680b57cec5SDimitry Andric /// it was instantiated. 690b57cec5SDimitry Andric class iterator { 700b57cec5SDimitry Andric public: 710b57cec5SDimitry Andric friend class IdentifierResolver; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric using value_type = NamedDecl *; 740b57cec5SDimitry Andric using reference = NamedDecl *; 750b57cec5SDimitry Andric using pointer = NamedDecl *; 760b57cec5SDimitry Andric using iterator_category = std::input_iterator_tag; 770b57cec5SDimitry Andric using difference_type = std::ptrdiff_t; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Ptr - There are 2 forms that 'Ptr' represents: 800b57cec5SDimitry Andric /// 1) A single NamedDecl. (Ptr & 0x1 == 0) 810b57cec5SDimitry Andric /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the 820b57cec5SDimitry Andric /// same declaration context. (Ptr & 0x1 == 0x1) 830b57cec5SDimitry Andric uintptr_t Ptr = 0; 840b57cec5SDimitry Andric using BaseIter = IdDeclInfo::DeclsTy::iterator; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric /// A single NamedDecl. (Ptr & 0x1 == 0) iterator(NamedDecl * D)870b57cec5SDimitry Andric iterator(NamedDecl *D) { 880b57cec5SDimitry Andric Ptr = reinterpret_cast<uintptr_t>(D); 890b57cec5SDimitry Andric assert((Ptr & 0x1) == 0 && "Invalid Ptr!"); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration 930b57cec5SDimitry Andric /// contexts depending on 'LookInParentCtx'. iterator(BaseIter I)940b57cec5SDimitry Andric iterator(BaseIter I) { 950b57cec5SDimitry Andric Ptr = reinterpret_cast<uintptr_t>(I) | 0x1; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric isIterator()980b57cec5SDimitry Andric bool isIterator() const { return (Ptr & 0x1); } 990b57cec5SDimitry Andric getIterator()1000b57cec5SDimitry Andric BaseIter getIterator() const { 1010b57cec5SDimitry Andric assert(isIterator() && "Ptr not an iterator!"); 1020b57cec5SDimitry Andric return reinterpret_cast<BaseIter>(Ptr & ~0x1); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric void incrementSlowCase(); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric public: 1080b57cec5SDimitry Andric iterator() = default; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric NamedDecl *operator*() const { 1110b57cec5SDimitry Andric if (isIterator()) 1120b57cec5SDimitry Andric return *getIterator(); 1130b57cec5SDimitry Andric else 1140b57cec5SDimitry Andric return reinterpret_cast<NamedDecl*>(Ptr); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric bool operator==(const iterator &RHS) const { 1180b57cec5SDimitry Andric return Ptr == RHS.Ptr; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric bool operator!=(const iterator &RHS) const { 1210b57cec5SDimitry Andric return Ptr != RHS.Ptr; 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric // Preincrement. 1250b57cec5SDimitry Andric iterator& operator++() { 1260b57cec5SDimitry Andric if (!isIterator()) // common case. 1270b57cec5SDimitry Andric Ptr = 0; 1280b57cec5SDimitry Andric else 1290b57cec5SDimitry Andric incrementSlowCase(); 1300b57cec5SDimitry Andric return *this; 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric }; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric explicit IdentifierResolver(Preprocessor &PP); 1350b57cec5SDimitry Andric ~IdentifierResolver(); 1360b57cec5SDimitry Andric 1375f757f3fSDimitry Andric IdentifierResolver(const IdentifierResolver &) = delete; 1385f757f3fSDimitry Andric IdentifierResolver &operator=(const IdentifierResolver &) = delete; 1395f757f3fSDimitry Andric 14006c3fb27SDimitry Andric /// Returns a range of decls with the name 'Name'. 14106c3fb27SDimitry Andric llvm::iterator_range<iterator> decls(DeclarationName Name); 14206c3fb27SDimitry Andric 14306c3fb27SDimitry Andric /// Returns an iterator over decls with the name 'Name'. 1440b57cec5SDimitry Andric iterator begin(DeclarationName Name); 1450b57cec5SDimitry Andric 14606c3fb27SDimitry Andric /// Returns the end iterator. end()14706c3fb27SDimitry Andric iterator end() { return iterator(); } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true 1500b57cec5SDimitry Andric /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns 1510b57cec5SDimitry Andric /// true if 'D' belongs to the given declaration context. 1520b57cec5SDimitry Andric /// 1530b57cec5SDimitry Andric /// \param AllowInlineNamespace If \c true, we are checking whether a prior 1540b57cec5SDimitry Andric /// declaration is in scope in a declaration that requires a prior 1550b57cec5SDimitry Andric /// declaration (because it is either explicitly qualified or is a 1560b57cec5SDimitry Andric /// template instantiation or specialization). In this case, a 1570b57cec5SDimitry Andric /// declaration is in scope if it's in the inline namespace set of the 1580b57cec5SDimitry Andric /// context. 1590b57cec5SDimitry Andric bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = nullptr, 1600b57cec5SDimitry Andric bool AllowInlineNamespace = false) const; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric /// AddDecl - Link the decl to its shadowed decl chain. 1630b57cec5SDimitry Andric void AddDecl(NamedDecl *D); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric /// RemoveDecl - Unlink the decl from its shadowed decl chain. 1660b57cec5SDimitry Andric /// The decl must already be part of the decl chain. 1670b57cec5SDimitry Andric void RemoveDecl(NamedDecl *D); 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric /// Insert the given declaration after the given iterator 1700b57cec5SDimitry Andric /// position. 1710b57cec5SDimitry Andric void InsertDeclAfter(iterator Pos, NamedDecl *D); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric /// Try to add the given declaration to the top level scope, if it 1740b57cec5SDimitry Andric /// (or a redeclaration of it) hasn't already been added. 1750b57cec5SDimitry Andric /// 1760b57cec5SDimitry Andric /// \param D The externally-produced declaration to add. 1770b57cec5SDimitry Andric /// 1780b57cec5SDimitry Andric /// \param Name The name of the externally-produced declaration. 1790b57cec5SDimitry Andric /// 1800b57cec5SDimitry Andric /// \returns true if the declaration was added, false otherwise. 1810b57cec5SDimitry Andric bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric private: 1840b57cec5SDimitry Andric const LangOptions &LangOpt; 1850b57cec5SDimitry Andric Preprocessor &PP; 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric class IdDeclInfoMap; 1880b57cec5SDimitry Andric IdDeclInfoMap *IdDeclInfos; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric void updatingIdentifier(IdentifierInfo &II); 1910b57cec5SDimitry Andric void readingIdentifier(IdentifierInfo &II); 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric /// FETokenInfo contains a Decl pointer if lower bit == 0. isDeclPtr(void * Ptr)1940b57cec5SDimitry Andric static inline bool isDeclPtr(void *Ptr) { 1950b57cec5SDimitry Andric return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0; 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1. toIdDeclInfo(void * Ptr)1990b57cec5SDimitry Andric static inline IdDeclInfo *toIdDeclInfo(void *Ptr) { 2000b57cec5SDimitry Andric assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1 2010b57cec5SDimitry Andric && "Ptr not a IdDeclInfo* !"); 2020b57cec5SDimitry Andric return reinterpret_cast<IdDeclInfo*>( 2030b57cec5SDimitry Andric reinterpret_cast<uintptr_t>(Ptr) & ~0x1); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric }; 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric } // namespace clang 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric #endif // LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H 210