| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 1 | //===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- C++ -*-===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
| Argyrios Kyrtzidis | dfd5222 | 2008-04-12 01:50:47 +0000 | [diff] [blame] | 10 | // This file defines the IdentifierResolver class, which is used for lexical | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 11 | // scoped lookup, based on identifier. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H | 
|  | 16 | #define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H | 
|  | 17 |  | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 18 | #include "clang/Basic/IdentifierTable.h" | 
|  | 19 | #include "clang/Parse/Scope.h" | 
|  | 20 | #include "clang/AST/Decl.h" | 
| Argyrios Kyrtzidis | ac1b916 | 2008-06-24 23:08:34 +0000 | [diff] [blame] | 21 | #include "clang/AST/DeclCXX.h" | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 22 |  | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 23 | namespace clang { | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 24 |  | 
|  | 25 | /// IdentifierResolver - Keeps track of shadowed decls on enclosing scopes. | 
| Argyrios Kyrtzidis | dfd5222 | 2008-04-12 01:50:47 +0000 | [diff] [blame] | 26 | /// It manages the shadowing chains of identifiers and implements efficent decl | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 27 | /// lookup based on an identifier. | 
|  | 28 | class IdentifierResolver { | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 29 |  | 
|  | 30 | /// LookupContext - A wrapper for DeclContext. DeclContext is only part of | 
|  | 31 | /// ScopedDecls, LookupContext can be used with all decls (assumes | 
|  | 32 | /// translation unit context for non ScopedDecls). | 
|  | 33 | class LookupContext { | 
|  | 34 | DeclContext *Ctx; | 
|  | 35 |  | 
|  | 36 | /// TUCtx - Provides a common value for translation unit context for all | 
|  | 37 | /// decls. | 
|  | 38 | /// FIXME: When (if ?) all decls can point to their translation unit context | 
|  | 39 | /// remove this hack. | 
|  | 40 | static inline DeclContext *TUCtx() { | 
|  | 41 | return reinterpret_cast<DeclContext*>(-1); | 
|  | 42 | } | 
|  | 43 |  | 
|  | 44 | /// getContext - Returns translation unit context for non ScopedDecls and | 
|  | 45 | /// for EnumConstantDecls returns the parent context of their EnumDecl. | 
|  | 46 | static DeclContext *getContext(Decl *D) { | 
|  | 47 | DeclContext *Ctx; | 
|  | 48 |  | 
| Argyrios Kyrtzidis | ac1b916 | 2008-06-24 23:08:34 +0000 | [diff] [blame] | 49 | if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D)) | 
|  | 50 | return FD->getParent(); | 
|  | 51 |  | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 52 | if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) { | 
|  | 53 | Ctx = EnumD->getDeclContext()->getParent(); | 
|  | 54 | } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) | 
|  | 55 | Ctx = SD->getDeclContext(); | 
|  | 56 | else | 
|  | 57 | return TUCtx(); | 
|  | 58 |  | 
|  | 59 | if (isa<TranslationUnitDecl>(Ctx)) | 
|  | 60 | return TUCtx(); | 
|  | 61 |  | 
|  | 62 | return Ctx; | 
|  | 63 | } | 
|  | 64 |  | 
|  | 65 | public: | 
|  | 66 | LookupContext(Decl *D) { | 
|  | 67 | Ctx = getContext(D); | 
|  | 68 | } | 
|  | 69 | LookupContext(DeclContext *DC) { | 
|  | 70 | if (!DC || isa<TranslationUnitDecl>(DC)) | 
|  | 71 | Ctx = TUCtx(); | 
|  | 72 | else | 
|  | 73 | Ctx = DC; | 
|  | 74 | } | 
|  | 75 |  | 
|  | 76 | bool isTU() const { | 
|  | 77 | return (Ctx == TUCtx()); | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | /// getParent - Returns the parent context. This should not be called for | 
|  | 81 | /// a translation unit context. | 
|  | 82 | LookupContext getParent() const { | 
|  | 83 | assert(!isTU() && "TU has no parent!"); | 
|  | 84 | return LookupContext(Ctx->getParent()); | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | /// isEqOrContainedBy - Returns true of the given context is the same or a | 
|  | 88 | /// parent of this one. | 
|  | 89 | bool isEqOrContainedBy(const LookupContext &PC) const { | 
|  | 90 | if (PC.isTU()) return true; | 
|  | 91 |  | 
|  | 92 | for (LookupContext Next = *this; !Next.isTU();  Next = Next.getParent()) | 
|  | 93 | if (Next.Ctx == PC.Ctx) return true; | 
|  | 94 |  | 
|  | 95 | return false; | 
|  | 96 | } | 
|  | 97 |  | 
|  | 98 | bool operator==(const LookupContext &RHS) const { | 
|  | 99 | return Ctx == RHS.Ctx; | 
|  | 100 | } | 
|  | 101 | bool operator!=(const LookupContext &RHS) const { | 
|  | 102 | return Ctx != RHS.Ctx; | 
|  | 103 | } | 
|  | 104 | }; | 
|  | 105 |  | 
|  | 106 | /// IdDeclInfo - Keeps track of information about decls associated to a | 
|  | 107 | /// particular identifier. IdDeclInfos are lazily constructed and assigned | 
|  | 108 | /// to an identifier the first time a decl with that identifier is shadowed | 
|  | 109 | /// in some scope. | 
|  | 110 | class IdDeclInfo { | 
|  | 111 | public: | 
|  | 112 | typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy; | 
|  | 113 |  | 
|  | 114 | inline DeclsTy::iterator decls_begin() { return Decls.begin(); } | 
|  | 115 | inline DeclsTy::iterator decls_end() { return Decls.end(); } | 
|  | 116 |  | 
|  | 117 | /// FindContext - Returns an iterator pointing just after the decl that is | 
|  | 118 | /// in the given context or in a parent of it. The search is in reverse | 
|  | 119 | /// order, from end to begin. | 
|  | 120 | DeclsTy::iterator FindContext(const LookupContext &Ctx) { | 
|  | 121 | return FindContext(Ctx, Decls.end()); | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | /// FindContext - Returns an iterator pointing just after the decl that is | 
|  | 125 | /// in the given context or in a parent of it. The search is in reverse | 
|  | 126 | /// order, from end to begin. | 
|  | 127 | DeclsTy::iterator FindContext(const LookupContext &Ctx, | 
|  | 128 | const DeclsTy::iterator &Start) { | 
|  | 129 | for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) { | 
|  | 130 | if (Ctx.isEqOrContainedBy(LookupContext(*(I-1)))) | 
|  | 131 | return I; | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | return Decls.begin(); | 
|  | 135 | } | 
|  | 136 |  | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 137 | void AddDecl(NamedDecl *D) { | 
|  | 138 | Decls.insert(FindContext(LookupContext(D)), D); | 
|  | 139 | } | 
|  | 140 |  | 
|  | 141 | /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl. | 
|  | 142 | /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must | 
|  | 143 | /// be already added to the scope chain and must be in the same context as | 
|  | 144 | /// the decl that we want to add. | 
|  | 145 | void AddShadowed(NamedDecl *D, NamedDecl *Shadow) { | 
|  | 146 | assert(LookupContext(D) == LookupContext(Shadow) && | 
|  | 147 | "Decl and Shadow not in same context!"); | 
|  | 148 |  | 
|  | 149 | for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { | 
|  | 150 | if (Shadow == *(I-1)) { | 
|  | 151 | Decls.insert(I-1, D); | 
|  | 152 | return; | 
|  | 153 | } | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | assert(0 && "Shadow wasn't in scope chain!"); | 
|  | 157 | } | 
|  | 158 |  | 
|  | 159 | /// RemoveDecl - Remove the decl from the scope chain. | 
|  | 160 | /// The decl must already be part of the decl chain. | 
|  | 161 | void RemoveDecl(NamedDecl *D) { | 
|  | 162 | for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { | 
|  | 163 | if (D == *(I-1)) { | 
|  | 164 | Decls.erase(I-1); | 
|  | 165 | return; | 
|  | 166 | } | 
|  | 167 | } | 
|  | 168 |  | 
|  | 169 | assert(0 && "Didn't find this decl on its identifier's chain!"); | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | private: | 
|  | 173 | DeclsTy Decls; | 
|  | 174 | }; | 
|  | 175 |  | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 176 | public: | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 177 |  | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 178 | /// iterator - Iterate over the decls of a specified identifier. | 
|  | 179 | /// It will walk or not the parent declaration contexts depending on how | 
|  | 180 | /// it was instantiated. | 
|  | 181 | class iterator { | 
|  | 182 | /// Ptr - There are 3 forms that 'Ptr' represents: | 
|  | 183 | /// 1) A single NamedDecl. (Ptr & 0x1 == 0) | 
|  | 184 | /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the | 
|  | 185 | ///    same declaration context. (Ptr & 0x3 == 0x1) | 
|  | 186 | /// 3) A IdDeclInfo::DeclsTy::iterator that traverses the decls of parent | 
|  | 187 | ///    declaration contexts too. (Ptr & 0x3 == 0x3) | 
|  | 188 | uintptr_t Ptr; | 
|  | 189 | typedef IdDeclInfo::DeclsTy::iterator BaseIter; | 
|  | 190 |  | 
|  | 191 | iterator() : Ptr(0) {} | 
|  | 192 | /// A single NamedDecl. (Ptr & 0x1 == 0) | 
|  | 193 | iterator(NamedDecl *D) { | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 194 | Ptr = reinterpret_cast<uintptr_t>(D); | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 195 | assert((Ptr & 0x1) == 0 && "Invalid Ptr!"); | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 196 | } | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 197 | /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration | 
|  | 198 | /// contexts depending on 'LookInParentCtx'. | 
|  | 199 | iterator(BaseIter I, bool LookInParentCtx) { | 
|  | 200 | Ptr = reinterpret_cast<uintptr_t>(I) | 0x1; | 
|  | 201 | assert((Ptr & 0x2) == 0 && "Invalid Ptr!"); | 
|  | 202 | if (LookInParentCtx) Ptr |= 0x2; | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 203 | } | 
|  | 204 |  | 
|  | 205 | bool isIterator() const { return (Ptr & 0x1); } | 
|  | 206 |  | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 207 | bool LookInParentCtx() const { | 
|  | 208 | assert(isIterator() && "Ptr not an iterator!"); | 
|  | 209 | return (Ptr & 0x2) != 0; | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 210 | } | 
|  | 211 |  | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 212 | BaseIter getIterator() const { | 
|  | 213 | assert(isIterator() && "Ptr not an iterator!"); | 
|  | 214 | return reinterpret_cast<BaseIter>(Ptr & ~0x3); | 
|  | 215 | } | 
|  | 216 |  | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 217 | friend class IdentifierResolver; | 
|  | 218 | public: | 
|  | 219 | NamedDecl *operator*() const { | 
|  | 220 | if (isIterator()) | 
|  | 221 | return *getIterator(); | 
|  | 222 | else | 
|  | 223 | return reinterpret_cast<NamedDecl*>(Ptr); | 
|  | 224 | } | 
|  | 225 |  | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 226 | bool operator==(const iterator &RHS) const { | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 227 | return Ptr == RHS.Ptr; | 
|  | 228 | } | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 229 | bool operator!=(const iterator &RHS) const { | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 230 | return Ptr != RHS.Ptr; | 
|  | 231 | } | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 232 |  | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 233 | // Preincrement. | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 234 | iterator& operator++() { | 
|  | 235 | if (!isIterator()) // common case. | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 236 | Ptr = 0; | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 237 | else | 
|  | 238 | PreIncIter(); | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 239 | return *this; | 
|  | 240 | } | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 241 |  | 
|  | 242 | private: | 
|  | 243 | void PreIncIter(); | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 244 | }; | 
|  | 245 |  | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 246 | /// begin - Returns an iterator for decls of identifier 'II', starting at | 
|  | 247 | /// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the | 
|  | 248 | /// decls of parent declaration contexts too. | 
|  | 249 | /// Default for 'LookInParentCtx is true. | 
|  | 250 | static iterator begin(const IdentifierInfo *II, DeclContext *Ctx, | 
|  | 251 | bool LookInParentCtx = true); | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 252 |  | 
| Argyrios Kyrtzidis | ef34aed | 2008-07-17 17:49:50 +0000 | [diff] [blame] | 253 | /// end - Returns an iterator that has 'finished'. | 
|  | 254 | static iterator end() { | 
|  | 255 | return iterator(); | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 256 | } | 
|  | 257 |  | 
| Argyrios Kyrtzidis | 3722daf | 2008-05-14 10:49:47 +0000 | [diff] [blame] | 258 | /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true | 
|  | 259 | /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns | 
|  | 260 | /// true if 'D' belongs to the given declaration context. | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 261 | static bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) { | 
| Argyrios Kyrtzidis | 3722daf | 2008-05-14 10:49:47 +0000 | [diff] [blame] | 262 | if (Ctx->isFunctionOrMethod()) | 
|  | 263 | return S->isDeclScope(D); | 
|  | 264 |  | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 265 | return LookupContext(D) == LookupContext(Ctx); | 
|  | 266 | } | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 267 |  | 
| Argyrios Kyrtzidis | dfd5222 | 2008-04-12 01:50:47 +0000 | [diff] [blame] | 268 | /// AddDecl - Link the decl to its shadowed decl chain. | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 269 | void AddDecl(NamedDecl *D); | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 270 |  | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 271 | /// AddShadowedDecl - Link the decl to its shadowed decl chain putting it | 
| Argyrios Kyrtzidis | 212f911 | 2008-05-15 17:26:35 +0000 | [diff] [blame] | 272 | /// after the decl that the iterator points to, thus the 'Shadow' decl will be | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 273 | /// encountered before the 'D' decl. | 
|  | 274 | void AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow); | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 275 |  | 
| Argyrios Kyrtzidis | dfd5222 | 2008-04-12 01:50:47 +0000 | [diff] [blame] | 276 | /// RemoveDecl - Unlink the decl from its shadowed decl chain. | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 277 | /// The decl must already be part of the decl chain. | 
|  | 278 | void RemoveDecl(NamedDecl *D); | 
|  | 279 |  | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 280 | IdentifierResolver(); | 
|  | 281 | ~IdentifierResolver(); | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 282 |  | 
|  | 283 | private: | 
| Argyrios Kyrtzidis | fa8e15b | 2008-05-09 23:39:43 +0000 | [diff] [blame] | 284 | class IdDeclInfoMap; | 
|  | 285 | IdDeclInfoMap *IdDeclInfos; | 
|  | 286 |  | 
|  | 287 | /// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0. | 
|  | 288 | static inline bool isDeclPtr(void *Ptr) { | 
|  | 289 | return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0; | 
|  | 290 | } | 
|  | 291 |  | 
|  | 292 | /// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1. | 
|  | 293 | static inline IdDeclInfo *toIdDeclInfo(void *Ptr) { | 
|  | 294 | assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1 | 
|  | 295 | && "Ptr not a IdDeclInfo* !"); | 
|  | 296 | return reinterpret_cast<IdDeclInfo*>( | 
|  | 297 | reinterpret_cast<uintptr_t>(Ptr) & ~0x1 | 
|  | 298 | ); | 
|  | 299 | } | 
| Chris Lattner | 9950c80 | 2008-04-11 07:06:57 +0000 | [diff] [blame] | 300 | }; | 
|  | 301 |  | 
|  | 302 | } // end namespace clang | 
|  | 303 |  | 
|  | 304 | #endif |