Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- C++ -*-===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | // |
||
9 | // This file defines the IdentifierResolver class, which is used for lexical |
||
10 | // scoped lookup, based on declaration names. |
||
11 | // |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H |
||
15 | #define LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H |
||
16 | |||
17 | #include "clang/Basic/LLVM.h" |
||
18 | #include "llvm/ADT/SmallVector.h" |
||
19 | #include <cassert> |
||
20 | #include <cstddef> |
||
21 | #include <cstdint> |
||
22 | #include <iterator> |
||
23 | |||
24 | namespace clang { |
||
25 | |||
26 | class Decl; |
||
27 | class DeclarationName; |
||
28 | class DeclContext; |
||
29 | class IdentifierInfo; |
||
30 | class LangOptions; |
||
31 | class NamedDecl; |
||
32 | class Preprocessor; |
||
33 | class Scope; |
||
34 | |||
35 | /// IdentifierResolver - Keeps track of shadowed decls on enclosing |
||
36 | /// scopes. It manages the shadowing chains of declaration names and |
||
37 | /// implements efficient decl lookup based on a declaration name. |
||
38 | class IdentifierResolver { |
||
39 | /// IdDeclInfo - Keeps track of information about decls associated |
||
40 | /// to a particular declaration name. IdDeclInfos are lazily |
||
41 | /// constructed and assigned to a declaration name the first time a |
||
42 | /// decl with that declaration name is shadowed in some scope. |
||
43 | class IdDeclInfo { |
||
44 | public: |
||
45 | using DeclsTy = SmallVector<NamedDecl *, 2>; |
||
46 | |||
47 | DeclsTy::iterator decls_begin() { return Decls.begin(); } |
||
48 | DeclsTy::iterator decls_end() { return Decls.end(); } |
||
49 | |||
50 | void AddDecl(NamedDecl *D) { Decls.push_back(D); } |
||
51 | |||
52 | /// RemoveDecl - Remove the decl from the scope chain. |
||
53 | /// The decl must already be part of the decl chain. |
||
54 | void RemoveDecl(NamedDecl *D); |
||
55 | |||
56 | /// Insert the given declaration at the given position in the list. |
||
57 | void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) { |
||
58 | Decls.insert(Pos, D); |
||
59 | } |
||
60 | |||
61 | private: |
||
62 | DeclsTy Decls; |
||
63 | }; |
||
64 | |||
65 | public: |
||
66 | /// iterator - Iterate over the decls of a specified declaration name. |
||
67 | /// It will walk or not the parent declaration contexts depending on how |
||
68 | /// it was instantiated. |
||
69 | class iterator { |
||
70 | public: |
||
71 | friend class IdentifierResolver; |
||
72 | |||
73 | using value_type = NamedDecl *; |
||
74 | using reference = NamedDecl *; |
||
75 | using pointer = NamedDecl *; |
||
76 | using iterator_category = std::input_iterator_tag; |
||
77 | using difference_type = std::ptrdiff_t; |
||
78 | |||
79 | /// Ptr - There are 2 forms that 'Ptr' represents: |
||
80 | /// 1) A single NamedDecl. (Ptr & 0x1 == 0) |
||
81 | /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the |
||
82 | /// same declaration context. (Ptr & 0x1 == 0x1) |
||
83 | uintptr_t Ptr = 0; |
||
84 | using BaseIter = IdDeclInfo::DeclsTy::iterator; |
||
85 | |||
86 | /// A single NamedDecl. (Ptr & 0x1 == 0) |
||
87 | iterator(NamedDecl *D) { |
||
88 | Ptr = reinterpret_cast<uintptr_t>(D); |
||
89 | assert((Ptr & 0x1) == 0 && "Invalid Ptr!"); |
||
90 | } |
||
91 | |||
92 | /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration |
||
93 | /// contexts depending on 'LookInParentCtx'. |
||
94 | iterator(BaseIter I) { |
||
95 | Ptr = reinterpret_cast<uintptr_t>(I) | 0x1; |
||
96 | } |
||
97 | |||
98 | bool isIterator() const { return (Ptr & 0x1); } |
||
99 | |||
100 | BaseIter getIterator() const { |
||
101 | assert(isIterator() && "Ptr not an iterator!"); |
||
102 | return reinterpret_cast<BaseIter>(Ptr & ~0x1); |
||
103 | } |
||
104 | |||
105 | void incrementSlowCase(); |
||
106 | |||
107 | public: |
||
108 | iterator() = default; |
||
109 | |||
110 | NamedDecl *operator*() const { |
||
111 | if (isIterator()) |
||
112 | return *getIterator(); |
||
113 | else |
||
114 | return reinterpret_cast<NamedDecl*>(Ptr); |
||
115 | } |
||
116 | |||
117 | bool operator==(const iterator &RHS) const { |
||
118 | return Ptr == RHS.Ptr; |
||
119 | } |
||
120 | bool operator!=(const iterator &RHS) const { |
||
121 | return Ptr != RHS.Ptr; |
||
122 | } |
||
123 | |||
124 | // Preincrement. |
||
125 | iterator& operator++() { |
||
126 | if (!isIterator()) // common case. |
||
127 | Ptr = 0; |
||
128 | else |
||
129 | incrementSlowCase(); |
||
130 | return *this; |
||
131 | } |
||
132 | }; |
||
133 | |||
134 | explicit IdentifierResolver(Preprocessor &PP); |
||
135 | ~IdentifierResolver(); |
||
136 | |||
137 | /// begin - Returns an iterator for decls with the name 'Name'. |
||
138 | iterator begin(DeclarationName Name); |
||
139 | |||
140 | /// end - Returns an iterator that has 'finished'. |
||
141 | iterator end() { |
||
142 | return iterator(); |
||
143 | } |
||
144 | |||
145 | /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true |
||
146 | /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns |
||
147 | /// true if 'D' belongs to the given declaration context. |
||
148 | /// |
||
149 | /// \param AllowInlineNamespace If \c true, we are checking whether a prior |
||
150 | /// declaration is in scope in a declaration that requires a prior |
||
151 | /// declaration (because it is either explicitly qualified or is a |
||
152 | /// template instantiation or specialization). In this case, a |
||
153 | /// declaration is in scope if it's in the inline namespace set of the |
||
154 | /// context. |
||
155 | bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = nullptr, |
||
156 | bool AllowInlineNamespace = false) const; |
||
157 | |||
158 | /// AddDecl - Link the decl to its shadowed decl chain. |
||
159 | void AddDecl(NamedDecl *D); |
||
160 | |||
161 | /// RemoveDecl - Unlink the decl from its shadowed decl chain. |
||
162 | /// The decl must already be part of the decl chain. |
||
163 | void RemoveDecl(NamedDecl *D); |
||
164 | |||
165 | /// Insert the given declaration after the given iterator |
||
166 | /// position. |
||
167 | void InsertDeclAfter(iterator Pos, NamedDecl *D); |
||
168 | |||
169 | /// Try to add the given declaration to the top level scope, if it |
||
170 | /// (or a redeclaration of it) hasn't already been added. |
||
171 | /// |
||
172 | /// \param D The externally-produced declaration to add. |
||
173 | /// |
||
174 | /// \param Name The name of the externally-produced declaration. |
||
175 | /// |
||
176 | /// \returns true if the declaration was added, false otherwise. |
||
177 | bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name); |
||
178 | |||
179 | private: |
||
180 | const LangOptions &LangOpt; |
||
181 | Preprocessor &PP; |
||
182 | |||
183 | class IdDeclInfoMap; |
||
184 | IdDeclInfoMap *IdDeclInfos; |
||
185 | |||
186 | void updatingIdentifier(IdentifierInfo &II); |
||
187 | void readingIdentifier(IdentifierInfo &II); |
||
188 | |||
189 | /// FETokenInfo contains a Decl pointer if lower bit == 0. |
||
190 | static inline bool isDeclPtr(void *Ptr) { |
||
191 | return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0; |
||
192 | } |
||
193 | |||
194 | /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1. |
||
195 | static inline IdDeclInfo *toIdDeclInfo(void *Ptr) { |
||
196 | assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1 |
||
197 | && "Ptr not a IdDeclInfo* !"); |
||
198 | return reinterpret_cast<IdDeclInfo*>( |
||
199 | reinterpret_cast<uintptr_t>(Ptr) & ~0x1); |
||
200 | } |
||
201 | }; |
||
202 | |||
203 | } // namespace clang |
||
204 | |||
205 | #endif // LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H |