From: Chris Lattner Date: Fri, 11 Apr 2008 07:06:57 +0000 (+0000) Subject: two new files for previous patch, by Argiris Kirtzidis X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a2f42b1d18db7a6e05314b04532a6643e1ffba0f;p=clang two new files for previous patch, by Argiris Kirtzidis git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49521 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp new file mode 100644 index 0000000000..eae64384cd --- /dev/null +++ b/lib/Sema/IdentifierResolver.cpp @@ -0,0 +1,235 @@ +//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the IdentifierResolver class,which is used for lexical +// scoped lookup, based on identifier. +// +//===----------------------------------------------------------------------===// + +#include "IdentifierResolver.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/AST/Decl.h" +#include + +using namespace clang; + +class IdDeclInfo; + +/// FETokenInfo of an identifier contains a Decl pointer if lower bit == 0 +static inline bool isDeclPtr(void *Ptr) { + return (reinterpret_cast(Ptr) & 0x1) == 0; +} + +/// FETokenInfo of an identifier contains a IdDeclInfo pointer if lower bit == 1 +static inline IdDeclInfo *toIdDeclInfo(void *Ptr) { + return reinterpret_cast( + reinterpret_cast(Ptr) & ~0x1 + ); +} + + +/// IdDeclInfo - Keeps track of information about decls associated to a particular +/// identifier. IdDeclInfos are lazily constructed and assigned to an identifier +/// the first time a decl with that identifier is shadowed in some scope. +class IdDeclInfo { + typedef llvm::SmallVector ShadowedTy; + ShadowedTy ShadowedDecls; + +public: + typedef ShadowedTy::iterator ShadowedIter; + + inline ShadowedIter shadowed_begin() { return ShadowedDecls.begin(); } + inline ShadowedIter shadowed_end() { return ShadowedDecls.end(); } + + /// Add a decl in the scope chain + void PushShadowed(NamedDecl *D) { + assert(D && "Decl null"); + ShadowedDecls.push_back(D); + } + + /// Add the decl at the top of scope chain + void PushGlobalShadowed(NamedDecl *D) { + assert(D && "Decl null"); + ShadowedDecls.insert(ShadowedDecls.begin(), D); + } + + /// RemoveShadowed - Remove the decl from the scope chain. + /// The decl must already be part of the decl chain. + void RemoveShadowed(NamedDecl *D); +}; + + +/// IdDeclInfoMap - Associates IdDeclInfos with Identifiers. +/// Allocates 'pools' (arrays of IdDeclInfos) to avoid allocating each +/// individual IdDeclInfo to heap. +class IdentifierResolver::IdDeclInfoMap { + static const unsigned int ARRAY_SIZE = 512; + // Holds pointers to arrays of IdDeclInfos that serve as 'pools'. + // Used only to iterate and destroy them at destructor. + std::list IDIArrPtrs; + IdDeclInfo *CurArr; + unsigned int CurIndex; + +public: + IdDeclInfoMap() : CurIndex(ARRAY_SIZE) {} + ~IdDeclInfoMap() { + for (std::list::iterator it = IDIArrPtrs.begin(); + it != IDIArrPtrs.end(); ++it) + delete[] *it; + } + + /// Returns the IdDeclInfo associated to the IdentifierInfo. + /// It creates a new IdDeclInfo if one was not created before for this id. + IdDeclInfo &operator[](IdentifierInfo *II); +}; + + +IdentifierResolver::IdentifierResolver() : IdDeclInfos(*new IdDeclInfoMap) {} +IdentifierResolver::~IdentifierResolver() { delete &IdDeclInfos; } + +/// AddDecl - Link the decl to its shadowed decl chain +void IdentifierResolver::AddDecl(NamedDecl *D, Scope *S) { + assert(D && S && "null param passed"); + IdentifierInfo *II = D->getIdentifier(); + void *Ptr = II->getFETokenInfo(); + + if (!Ptr) { + II->setFETokenInfo(D); + return; + } + + IdDeclInfo *IDI; + + if (isDeclPtr(Ptr)) { + II->setFETokenInfo(NULL); + IDI = &IdDeclInfos[II]; + IDI->PushShadowed(static_cast(Ptr)); + } else + IDI = toIdDeclInfo(Ptr); + + IDI->PushShadowed(D); +} + +/// AddGlobalDecl - Link the decl at the top of the shadowed decl chain +void IdentifierResolver::AddGlobalDecl(NamedDecl *D) { + assert(D && "null param passed"); + IdentifierInfo *II = D->getIdentifier(); + void *Ptr = II->getFETokenInfo(); + + if (!Ptr) { + II->setFETokenInfo(D); + return; + } + + IdDeclInfo *IDI; + + if (isDeclPtr(Ptr)) { + II->setFETokenInfo(NULL); + IDI = &IdDeclInfos[II]; + IDI->PushShadowed(static_cast(Ptr)); + } else + IDI = toIdDeclInfo(Ptr); + + IDI->PushGlobalShadowed(D); +} + +/// RemoveDecl - Unlink the decl from its shadowed decl chain +/// The decl must already be part of the decl chain. +void IdentifierResolver::RemoveDecl(NamedDecl *D) { + assert(D && "null param passed"); + IdentifierInfo *II = D->getIdentifier(); + void *Ptr = II->getFETokenInfo(); + + assert(Ptr && "Didn't find this decl on its identifier's chain!"); + + if (isDeclPtr(Ptr)) { + assert(D == Ptr && "Didn't find this decl on its identifier's chain!"); + II->setFETokenInfo(NULL); + return; + } + + return toIdDeclInfo(Ptr)->RemoveShadowed(D); +} + +/// Lookup - Find the non-shadowed decl that belongs to a particular +/// Decl::IdentifierNamespace. +NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NSI) { + assert(II && "null param passed"); + Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI; + void *Ptr = II->getFETokenInfo(); + + if (!Ptr) return NULL; + + if (isDeclPtr(Ptr)) { + NamedDecl *D = static_cast(Ptr); + return (D->getIdentifierNamespace() == NS) ? D : NULL; + } + + IdDeclInfo *IDI = toIdDeclInfo(Ptr); + + // ShadowedDecls are ordered from most shadowed to less shadowed. + // So we do a reverse iteration from end to begin. + for (IdDeclInfo::ShadowedIter SI = IDI->shadowed_end(); + SI != IDI->shadowed_begin(); --SI) { + NamedDecl *D = *(SI-1); + if (D->getIdentifierNamespace() == NS) + return D; + } + + // we didn't find the decl. + return NULL; +} + +/// RemoveShadowed - Remove the decl from the scope chain. +/// The decl must already be part of the decl chain. +void IdDeclInfo::RemoveShadowed(NamedDecl *D) { + assert(D && "null decl passed"); + assert(ShadowedDecls.size() > 0 && + "Didn't find this decl on its identifier's chain!"); + + // common case + if (D == ShadowedDecls.back()) { + ShadowedDecls.pop_back(); + return; + } + + for (ShadowedIter SI = ShadowedDecls.end()-1; + SI != ShadowedDecls.begin(); --SI) { + if (*(SI-1) == D) { + ShadowedDecls.erase(SI-1); + return; + } + } + + assert(false && "Didn't find this decl on its identifier's chain!"); +} + +/// Returns the IdDeclInfo associated to the IdentifierInfo. +/// It creates a new IdDeclInfo if one was not created before for this id. +IdDeclInfo &IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) { + assert (II && "null IdentifierInfo passed"); + void *Ptr = II->getFETokenInfo(); + + if (Ptr) { + assert(!isDeclPtr(Ptr) && "didn't clear decl for FEToken"); + return *toIdDeclInfo(Ptr); + } + + if (CurIndex == ARRAY_SIZE) { + CurArr = new IdDeclInfo[ARRAY_SIZE]; + IDIArrPtrs.push_back(CurArr); + CurIndex = 0; + } + IdDeclInfo *IDI = CurArr + CurIndex; + II->setFETokenInfo(reinterpret_cast( + reinterpret_cast(IDI) | 0x1) + ); + ++CurIndex; + return *IDI; +} diff --git a/lib/Sema/IdentifierResolver.h b/lib/Sema/IdentifierResolver.h new file mode 100644 index 0000000000..8db4615df2 --- /dev/null +++ b/lib/Sema/IdentifierResolver.h @@ -0,0 +1,52 @@ +//===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the IdentifierResolver class,which is used for lexical +// scoped lookup, based on identifier. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H +#define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H + +namespace clang { + class IdentifierInfo; + class NamedDecl; + class Scope; + +/// IdentifierResolver - Keeps track of shadowed decls on enclosing scopes. +/// it manages the shadowing chains of identifiers and implements efficent decl +/// lookup based on an identifier. +class IdentifierResolver { +public: + IdentifierResolver(); + ~IdentifierResolver(); + + /// AddDecl - Link the decl to its shadowed decl chain + void AddDecl(NamedDecl *D, Scope *S); + + /// AddGlobalDecl - Link the decl at the top of the shadowed decl chain + void AddGlobalDecl(NamedDecl *D); + + /// RemoveDecl - Unlink the decl from its shadowed decl chain + /// The decl must already be part of the decl chain. + void RemoveDecl(NamedDecl *D); + + /// Lookup - Find the non-shadowed decl that belongs to a particular + /// Decl::IdentifierNamespace. + NamedDecl *Lookup(const IdentifierInfo *II, unsigned NSI); + +private: + class IdDeclInfoMap; + IdDeclInfoMap &IdDeclInfos; +}; + +} // end namespace clang + +#endif