Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:00

0001 //===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines the IdentifierResolver class, which is used for lexical
0010 // scoped lookup, based on declaration names.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H
0015 #define LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H
0016 
0017 #include "clang/Basic/LLVM.h"
0018 #include "llvm/ADT/SmallVector.h"
0019 #include <cassert>
0020 #include <cstddef>
0021 #include <cstdint>
0022 #include <iterator>
0023 
0024 namespace clang {
0025 
0026 class Decl;
0027 class DeclarationName;
0028 class DeclContext;
0029 class IdentifierInfo;
0030 class LangOptions;
0031 class NamedDecl;
0032 class Preprocessor;
0033 class Scope;
0034 
0035 /// IdentifierResolver - Keeps track of shadowed decls on enclosing
0036 /// scopes.  It manages the shadowing chains of declaration names and
0037 /// implements efficient decl lookup based on a declaration name.
0038 class IdentifierResolver {
0039   /// IdDeclInfo - Keeps track of information about decls associated
0040   /// to a particular declaration name. IdDeclInfos are lazily
0041   /// constructed and assigned to a declaration name the first time a
0042   /// decl with that declaration name is shadowed in some scope.
0043   class IdDeclInfo {
0044   public:
0045     using DeclsTy = SmallVector<NamedDecl *, 2>;
0046 
0047     DeclsTy::iterator decls_begin() { return Decls.begin(); }
0048     DeclsTy::iterator decls_end() { return Decls.end(); }
0049 
0050     void AddDecl(NamedDecl *D) { Decls.push_back(D); }
0051 
0052     /// RemoveDecl - Remove the decl from the scope chain.
0053     /// The decl must already be part of the decl chain.
0054     void RemoveDecl(NamedDecl *D);
0055 
0056     /// Insert the given declaration at the given position in the list.
0057     void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) {
0058       Decls.insert(Pos, D);
0059     }
0060 
0061   private:
0062     DeclsTy Decls;
0063   };
0064 
0065 public:
0066   /// iterator - Iterate over the decls of a specified declaration name.
0067   /// It will walk or not the parent declaration contexts depending on how
0068   /// it was instantiated.
0069   class iterator {
0070   public:
0071     friend class IdentifierResolver;
0072 
0073     using value_type = NamedDecl *;
0074     using reference = NamedDecl *;
0075     using pointer = NamedDecl *;
0076     using iterator_category = std::input_iterator_tag;
0077     using difference_type = std::ptrdiff_t;
0078 
0079     /// Ptr - There are 2 forms that 'Ptr' represents:
0080     /// 1) A single NamedDecl. (Ptr & 0x1 == 0)
0081     /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the
0082     ///    same declaration context. (Ptr & 0x1 == 0x1)
0083     uintptr_t Ptr = 0;
0084     using BaseIter = IdDeclInfo::DeclsTy::iterator;
0085 
0086     /// A single NamedDecl. (Ptr & 0x1 == 0)
0087     iterator(NamedDecl *D) {
0088       Ptr = reinterpret_cast<uintptr_t>(D);
0089       assert((Ptr & 0x1) == 0 && "Invalid Ptr!");
0090     }
0091 
0092     /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration
0093     /// contexts depending on 'LookInParentCtx'.
0094     iterator(BaseIter I) {
0095       Ptr = reinterpret_cast<uintptr_t>(I) | 0x1;
0096     }
0097 
0098     bool isIterator() const { return (Ptr & 0x1); }
0099 
0100     BaseIter getIterator() const {
0101       assert(isIterator() && "Ptr not an iterator!");
0102       return reinterpret_cast<BaseIter>(Ptr & ~0x1);
0103     }
0104 
0105     void incrementSlowCase();
0106 
0107   public:
0108     iterator() = default;
0109 
0110     NamedDecl *operator*() const {
0111       if (isIterator())
0112         return *getIterator();
0113       else
0114         return reinterpret_cast<NamedDecl*>(Ptr);
0115     }
0116 
0117     bool operator==(const iterator &RHS) const {
0118       return Ptr == RHS.Ptr;
0119     }
0120     bool operator!=(const iterator &RHS) const {
0121       return Ptr != RHS.Ptr;
0122     }
0123 
0124     // Preincrement.
0125     iterator& operator++() {
0126       if (!isIterator()) // common case.
0127         Ptr = 0;
0128       else
0129         incrementSlowCase();
0130       return *this;
0131     }
0132   };
0133 
0134   explicit IdentifierResolver(Preprocessor &PP);
0135   ~IdentifierResolver();
0136 
0137   IdentifierResolver(const IdentifierResolver &) = delete;
0138   IdentifierResolver &operator=(const IdentifierResolver &) = delete;
0139 
0140   /// Returns a range of decls with the name 'Name'.
0141   llvm::iterator_range<iterator> decls(DeclarationName Name);
0142 
0143   /// Returns an iterator over decls with the name 'Name'.
0144   iterator begin(DeclarationName Name);
0145 
0146   /// Returns the end iterator.
0147   iterator end() { return iterator(); }
0148 
0149   /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
0150   /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
0151   /// true if 'D' belongs to the given declaration context.
0152   ///
0153   /// \param AllowInlineNamespace If \c true, we are checking whether a prior
0154   ///        declaration is in scope in a declaration that requires a prior
0155   ///        declaration (because it is either explicitly qualified or is a
0156   ///        template instantiation or specialization). In this case, a
0157   ///        declaration is in scope if it's in the inline namespace set of the
0158   ///        context.
0159   bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = nullptr,
0160                      bool AllowInlineNamespace = false) const;
0161 
0162   /// AddDecl - Link the decl to its shadowed decl chain.
0163   void AddDecl(NamedDecl *D);
0164 
0165   /// RemoveDecl - Unlink the decl from its shadowed decl chain.
0166   /// The decl must already be part of the decl chain.
0167   void RemoveDecl(NamedDecl *D);
0168 
0169   /// Insert the given declaration after the given iterator
0170   /// position.
0171   void InsertDeclAfter(iterator Pos, NamedDecl *D);
0172 
0173   /// Try to add the given declaration to the top level scope, if it
0174   /// (or a redeclaration of it) hasn't already been added.
0175   ///
0176   /// \param D The externally-produced declaration to add.
0177   ///
0178   /// \param Name The name of the externally-produced declaration.
0179   ///
0180   /// \returns true if the declaration was added, false otherwise.
0181   bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name);
0182 
0183 private:
0184   const LangOptions &LangOpt;
0185   Preprocessor &PP;
0186 
0187   class IdDeclInfoMap;
0188   IdDeclInfoMap *IdDeclInfos;
0189 
0190   void updatingIdentifier(IdentifierInfo &II);
0191   void readingIdentifier(IdentifierInfo &II);
0192 
0193   /// FETokenInfo contains a Decl pointer if lower bit == 0.
0194   static inline bool isDeclPtr(void *Ptr) {
0195     return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
0196   }
0197 
0198   /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
0199   static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
0200     assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
0201           && "Ptr not a IdDeclInfo* !");
0202     return reinterpret_cast<IdDeclInfo*>(
0203                     reinterpret_cast<uintptr_t>(Ptr) & ~0x1);
0204   }
0205 };
0206 
0207 } // namespace clang
0208 
0209 #endif // LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H