diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 14 | ||||
-rw-r--r-- | include/clang/AST/DeclBase.h | 43 | ||||
-rw-r--r-- | include/clang/AST/DeclContextInternals.h | 170 | ||||
-rw-r--r-- | include/clang/AST/ExternalASTSource.h | 94 | ||||
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 239 | ||||
-rw-r--r-- | include/clang/Frontend/PCHReader.h | 169 | ||||
-rw-r--r-- | include/clang/Frontend/PCHWriter.h | 114 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 18 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 112 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 602 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 636 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 11 | ||||
-rw-r--r-- | test/PCH/variables.c | 6 | ||||
-rw-r--r-- | test/PCH/variables.h | 5 | ||||
-rwxr-xr-x | test/TestRunner.sh | 3 | ||||
-rw-r--r-- | tools/clang-cc/ASTConsumers.h | 5 | ||||
-rw-r--r-- | tools/clang-cc/GeneratePCH.cpp | 78 | ||||
-rw-r--r-- | tools/clang-cc/clang-cc.cpp | 23 |
19 files changed, 2300 insertions, 48 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 873806ffd2..ee9f99c57e 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -24,6 +24,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/Bitcode/SerializationFwd.h" #include "llvm/Support/Allocator.h" #include <vector> @@ -36,6 +37,7 @@ namespace clang { class FileManager; class ASTRecordLayout; class Expr; + class ExternalASTSource; class IdentifierTable; class SelectorTable; class SourceManager; @@ -146,6 +148,7 @@ public: IdentifierTable &Idents; SelectorTable &Selectors; DeclarationNameTable DeclarationNames; + llvm::OwningPtr<ExternalASTSource> ExternalSource; SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } @@ -190,6 +193,17 @@ public: ~ASTContext(); + /// \brief Attach an external AST source to the AST context. + /// + /// The external AST source provides the ability to load parts of + /// the abstract syntax tree as needed from some external storage, + /// e.g., a precompiled header. + void setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source); + + /// \brief Retrieve a pointer to the external AST source associated + /// with this AST context, if any. + ExternalASTSource *getExternalSource() const { return ExternalSource.get(); } + void PrintStats() const; const std::vector<Type*>& getTypes() const { return Types; } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 3244c63146..46af4ec6b6 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -349,24 +349,36 @@ class DeclContext { /// DeclKind - This indicates which class this is. Decl::Kind DeclKind : 8; + /// \brief Whether this declaration context also has some external + /// storage that contains additional declarations that are lexically + /// part of this context. + mutable bool ExternalLexicalStorage : 1; + + /// \brief Whether this declaration context also has some external + /// storage that contains additional declarations that are visible + /// in this context. + mutable bool ExternalVisibleStorage : 1; + /// \brief Pointer to the data structure used to lookup declarations /// within this context, which is a DenseMap<DeclarationName, /// StoredDeclsList>. - void* LookupPtr; + mutable void* LookupPtr; /// FirstDecl - The first declaration stored within this declaration /// context. - Decl *FirstDecl; + mutable Decl *FirstDecl; /// LastDecl - The last declaration stored within this declaration /// context. FIXME: We could probably cache this value somewhere /// outside of the DeclContext, to reduce the size of DeclContext by /// another pointer. - Decl *LastDecl; + mutable Decl *LastDecl; protected: DeclContext(Decl::Kind K) - : DeclKind(K), LookupPtr(0), FirstDecl(0), LastDecl(0) { } + : DeclKind(K), ExternalLexicalStorage(false), + ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), + LastDecl(0) { } void DestroyDecls(ASTContext &C); @@ -751,6 +763,26 @@ public: /// \brief Retrieve the internal representation of the lookup structure. void* getLookupPtr() const { return LookupPtr; } + /// \brief Whether this DeclContext has external storage containing + /// additional declarations that are lexically in this context. + bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; } + + /// \brief State whether this DeclContext has external storage for + /// declarations lexically in this context. + void setHasExternalLexicalStorage(bool ES = true) { + ExternalLexicalStorage = ES; + } + + /// \brief Whether this DeclContext has external storage containing + /// additional declarations that are visible in this context. + bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; } + + /// \brief State whether this DeclContext has external storage for + /// declarations visible in this context. + void setHasExternalVisibleStorage(bool ES = true) { + ExternalVisibleStorage = ES; + } + static bool classof(const Decl *D); static bool classof(const DeclContext *D) { return true; } #define DECL_CONTEXT(Name) \ @@ -758,6 +790,9 @@ public: #include "clang/AST/DeclNodes.def" private: + void LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const; + void LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const; + void buildLookup(ASTContext &Context, DeclContext *DCtx); void makeDeclVisibleInContextImpl(ASTContext &Context, NamedDecl *D); diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 9341a7de37..7489413be8 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -19,54 +19,128 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" -#include <functional> +#include <algorithm> namespace clang { /// StoredDeclsList - This is an array of decls optimized a common case of only /// containing one entry. struct StoredDeclsList { + /// The kind of data encoded in this list. + enum DataKind { + /// \brief The data is a NamedDecl*. + DK_Decl = 0, + /// \brief The data is a declaration ID (an unsigned value), + /// shifted left by 2 bits. + DK_DeclID = 1, + /// \brief The data is a pointer to a vector (of type VectorTy) + /// that contains declarations. + DK_Decl_Vector = 2, + /// \brief The data is a pointer to a vector (of type VectorTy) + /// that contains declaration ID. + DK_ID_Vector = 3 + }; + /// VectorTy - When in vector form, this is what the Data pointer points to. - typedef llvm::SmallVector<NamedDecl*, 4> VectorTy; + typedef llvm::SmallVector<uintptr_t, 4> VectorTy; + + /// \brief The stored data, which will be either a declaration ID, a + /// pointer to a NamedDecl, or a pointer to a vector. + uintptr_t Data; - /// Data - Union of NamedDecl*/VectorTy*. - llvm::PointerUnion<NamedDecl*, VectorTy*> Data; public: - StoredDeclsList() {} + StoredDeclsList() : Data(0) {} + StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { - if (isVector()) - Data = new VectorTy(*Data.get<VectorTy*>()); + if (VectorTy *RHSVec = RHS.getAsVector()) { + VectorTy *New = new VectorTy(*RHSVec); + Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); + } } ~StoredDeclsList() { // If this is a vector-form, free the vector. - if (isVector()) - delete Data.get<VectorTy*>(); + if (VectorTy *Vector = getAsVector()) + delete Vector; } StoredDeclsList &operator=(const StoredDeclsList &RHS) { - if (isVector()) - delete Data.get<VectorTy*>(); + if (VectorTy *Vector = getAsVector()) + delete Vector; Data = RHS.Data; - if (isVector()) - Data = new VectorTy(*Data.get<VectorTy*>()); + if (VectorTy *RHSVec = RHS.getAsVector()) { + VectorTy *New = new VectorTy(*RHSVec); + Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); + } return *this; } - bool isVector() const { return Data.is<VectorTy*>(); } - bool isInline() const { return Data.is<NamedDecl*>(); } - bool isNull() const { return Data.isNull(); } + bool isNull() const { return (Data & ~0x03) == 0; } + NamedDecl *getAsDecl() const { + if ((Data & 0x03) != DK_Decl) + return 0; + + return reinterpret_cast<NamedDecl *>(Data & ~0x03); + } + + VectorTy *getAsVector() const { + if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector) + return 0; + + return reinterpret_cast<VectorTy *>(Data & ~0x03); + } + void setOnlyValue(NamedDecl *ND) { - assert(isInline() && "Not inline"); - Data = ND; + assert(!getAsVector() && "Not inline"); + Data = reinterpret_cast<uintptr_t>(ND); + } + + void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) { + if (Vec.size() > 1) { + VectorTy *Vector = getAsVector(); + if (!Vector) { + Vector = new VectorTy; + Data = reinterpret_cast<uintptr_t>(Vector) | DK_Decl_Vector; + } + + Vector->resize(Vec.size()); + std::copy(Vec.begin(), Vec.end(), Vector->begin()); + return; + } + + if (VectorTy *Vector = getAsVector()) + delete Vector; + + if (Vec.size() == 0) + Data = 0; + else + Data = (Vec[0] << 2) | DK_DeclID; + } + + /// \brief Force the stored declarations list to contain actual + /// declarations. + /// + /// This routine will resolve any declaration IDs for declarations + /// that may not yet have been loaded from external storage. + void materializeDecls(ASTContext &Context); + + bool hasDeclarationIDs() const { + DataKind DK = (DataKind)(Data & 0x03); + return DK == DK_DeclID || DK == DK_ID_Vector; } /// getLookupResult - Return an array of all the decls that this list /// represents. DeclContext::lookup_result getLookupResult(ASTContext &Context) { - // If we have a single inline unit, return it. - if (isInline()) { + if (isNull()) + return DeclContext::lookup_result(0, 0); + + if (hasDeclarationIDs()) + materializeDecls(Context); + + // If we have a single NamedDecl, return it. + if (getAsDecl()) { assert(!isNull() && "Empty list isn't allowed"); // Data is a raw pointer to a NamedDecl*, return it. @@ -74,57 +148,67 @@ public: return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1); } + assert(getAsVector() && "Must have a vector at this point"); + VectorTy &Vector = *getAsVector(); + // Otherwise, we have a range result. - VectorTy &V = *Data.get<VectorTy*>(); - return DeclContext::lookup_result(&V[0], &V[0]+V.size()); + return DeclContext::lookup_result((NamedDecl **)&Vector[0], + (NamedDecl **)&Vector[0]+Vector.size()); } /// HandleRedeclaration - If this is a redeclaration of an existing decl, /// replace the old one with D and return true. Otherwise return false. bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) { + if (hasDeclarationIDs()) + materializeDecls(Context); + // Most decls only have one entry in their list, special case it. - if (isInline()) { - if (!D->declarationReplaces(Data.get<NamedDecl*>())) + if (NamedDecl *OldD = getAsDecl()) { + if (!D->declarationReplaces(OldD)) return false; setOnlyValue(D); return true; } // Determine if this declaration is actually a redeclaration. - VectorTy &Vec = *Data.get<VectorTy*>(); - VectorTy::iterator RDI - = std::find_if(Vec.begin(), Vec.end(), - std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces), - D)); - if (RDI == Vec.end()) - return false; - *RDI = D; - return true; + VectorTy &Vec = *getAsVector(); + for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); + OD != ODEnd; ++OD) { + NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD); + if (D->declarationReplaces(OldD)) { + *OD = reinterpret_cast<uintptr_t>(D); + return true; + } + } + + return false; } /// AddSubsequentDecl - This is called on the second and later decl when it is /// not a redeclaration to merge it into the appropriate place in our list. /// void AddSubsequentDecl(NamedDecl *D) { + assert(!hasDeclarationIDs() && "Must materialize before adding decls"); + // If this is the second decl added to the list, convert this to vector // form. - if (isInline()) { - NamedDecl *OldD = Data.get<NamedDecl*>(); + if (NamedDecl *OldD = getAsDecl()) { VectorTy *VT = new VectorTy(); - VT->push_back(OldD); - Data = VT; + VT->push_back(reinterpret_cast<uintptr_t>(OldD)); + Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector; } - VectorTy &Vec = *Data.get<VectorTy*>(); + VectorTy &Vec = *getAsVector(); if (isa<UsingDirectiveDecl>(D) || D->getIdentifierNamespace() == Decl::IDNS_Tag) - Vec.push_back(D); - else if (Vec.back()->getIdentifierNamespace() == Decl::IDNS_Tag) { - NamedDecl *TagD = Vec.back(); - Vec.back() = D; + Vec.push_back(reinterpret_cast<uintptr_t>(D)); + else if (reinterpret_cast<NamedDecl *>(Vec.back()) + ->getIdentifierNamespace() == Decl::IDNS_Tag) { + uintptr_t TagD = Vec.back(); + Vec.back() = reinterpret_cast<uintptr_t>(D); Vec.push_back(TagD); } else - Vec.push_back(D); + Vec.push_back(reinterpret_cast<uintptr_t>(D)); } }; diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h new file mode 100644 index 0000000000..17fa72612f --- /dev/null +++ b/include/clang/AST/ExternalASTSource.h @@ -0,0 +1,94 @@ +//===--- ExternalASTSource.h - Abstract External AST Interface --*- 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 ExternalASTSource interface, +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H +#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H + +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Type.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + +class Decl; +class DeclContext; + +/// \brief The deserialized representation of a set of declarations +/// with the same name that are visible in a given context. +struct VisibleDeclaration { + /// \brief The name of the declarations. + DeclarationName Name; + + /// \brief The ID numbers of all of the declarations with this name. + /// + /// These declarations have not necessarily been de-serialized. + llvm::SmallVector<unsigned, 4> Declarations; +}; + +/// \brief Abstract interface for external sources of AST nodes. +/// +/// External AST sources provide AST nodes constructed from some +/// external source, such as a precompiled header. External AST +/// sources can resolve types and declarations from abstract IDs into +/// actual type and declaration nodes, and read parts of declaration +/// contexts. +class ExternalASTSource { +public: + virtual ~ExternalASTSource(); + + /// \brief Resolve a type ID into a type, potentially building a new + /// type. + virtual QualType GetType(unsigned ID) = 0; + + /// \brief Resolve a declaration ID into a declaration, potentially + /// building a new declaration. + virtual Decl *GetDecl(unsigned ID) = 0; + + /// \brief Read all of the declarations lexically stored in a + /// declaration context. + /// + /// \param DC The declaration context whose declarations will be + /// read. + /// + /// \param Decls Vector that will contain the declarations loaded + /// from the external source. The caller is responsible for merging + /// these declarations with any declarations already stored in the + /// declaration context. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + virtual bool ReadDeclsLexicallyInContext(DeclContext *DC, + llvm::SmallVectorImpl<unsigned> &Decls) = 0; + + /// \brief Read all of the declarations visible from a declaration + /// context. + /// + /// \param DC The declaration context whose visible declarations + /// will be read. + /// + /// \param Decls A vector of visible declaration structures, + /// providing the mapping from each name visible in the declaration + /// context to the declaration IDs of declarations with that name. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + virtual bool ReadDeclsVisibleInContext(DeclContext *DC, + llvm::SmallVectorImpl<VisibleDeclaration> & Decls) = 0; + + /// \brief Print any statistics that have been gathered regarding + /// the external AST source. + virtual void PrintStats(); +}; + +} // end namespace clang + +#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h new file mode 100644 index 0000000000..8835098361 --- /dev/null +++ b/include/clang/Frontend/PCHBitCodes.h @@ -0,0 +1,239 @@ +//===- PCHBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines Bitcode enum values for Clang precompiled header files. +// +// The enum values defined in this file should be considered permanent. If +// new features are added, they should have values added at the end of the +// respective lists. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H +#define LLVM_CLANG_FRONTEND_PCHBITCODES_H + +#include "llvm/Bitcode/BitCodes.h" +#include "llvm/Support/DataTypes.h" + +namespace clang { + namespace pch { + const int IDBits = 32; + typedef uint32_t ID; + + /// \brief Describes the various kinds of blocks that occur within + /// a PCH file. + enum BlockIDs { + /// \brief The PCH block, which acts as a container around the + /// full PCH block. + PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, + + /// \brief The block containing the definitions of all of the + /// types used within the PCH file. + TYPES_BLOCK_ID, + + /// \brief The block containing the offsets of all of the types + /// used within the PCH. + /// + /// The offsets in this block point into the block identified by + /// TYPES_BLOCK_ID, and are indexed by the type ID. + TYPE_OFFSETS_BLOCK_ID, + + /// \brief The block containing the definitions of all of the + /// declarations stored in the PCH file. + DECLS_BLOCK_ID, + + /// \brief The block containing the offsets of all of the + /// declarations stored within the PCH file. + /// + /// The offsets in this block point into the block identified by + /// DECLS_BLOCK_ID, and are indexed by the decaration ID. + DECL_OFFSETS_BLOCK_ID + }; + + /// \brief Predefined type IDs. + /// + /// These type IDs correspond to predefined types in the AST + /// context, such as built-in types (int) and special place-holder + /// types (the <overload> and <dependent> type markers). Such + /// types are never actually serialized, since they will be built + /// by the AST context when it is created. + enum PredefinedTypeIDs { + /// \brief The NULL type. + PREDEF_TYPE_NULL_ID = 0, + /// \brief The void type. + PREDEF_TYPE_VOID_ID = 1, + /// \brief The 'bool' or '_Bool' type. + PREDEF_TYPE_BOOL_ID = 2, + /// \brief The 'char' type, when it is unsigned. + PREDEF_TYPE_CHAR_U_ID = 3, + /// \brief The 'unsigned char' type. + PREDEF_TYPE_UCHAR_ID = 4, + /// \brief The 'unsigned short' type. + PREDEF_TYPE_USHORT_ID = 5, + /// \brief The 'unsigned int' type. + PREDEF_TYPE_UINT_ID = 6, + /// \brief The 'unsigned long' type. + PREDEF_TYPE_ULONG_ID = 7, + /// \brief The 'unsigned long long' type. + PREDEF_TYPE_ULONGLONG_ID = 8, + /// \brief The 'char' type, when it is signed. + PREDEF_TYPE_CHAR_S_ID = 9, + /// \brief The 'signed char' type. + PREDEF_TYPE_SCHAR_ID = 10, + /// \brief The C++ 'wchar_t' type. + PREDEF_TYPE_WCHAR_ID = 11, + /// \brief The (signed) 'short' type. + PREDEF_TYPE_SHORT_ID = 12, + /// \brief The (signed) 'int' type. + PREDEF_TYPE_INT_ID = 13, + /// \brief The (signed) 'long' type. + PREDEF_TYPE_LONG_ID = 14, + /// \brief The (signed) 'long long' type. + PREDEF_TYPE_LONGLONG_ID = 15, + /// \brief The 'float' type. + PREDEF_TYPE_FLOAT_ID = 16, + /// \brief The 'double' type. + PREDEF_TYPE_DOUBLE_ID = 17, + /// \brief The 'long double' type. + PREDEF_TYPE_LONGDOUBLE_ID = 18, + /// \brief The placeholder type for overloaded function sets. + PREDEF_TYPE_OVERLOAD_ID = 19, + /// \brief The placeholder type for dependent types. + PREDEF_TYPE_DEPENDENT_ID = 20 + }; + + /// \brief The number of predefined type IDs that are reserved for + /// the PREDEF_TYPE_* constants. + /// + /// Type IDs for non-predefined types will start at + /// NUM_PREDEF_TYPE_IDs. + const unsigned NUM_PREDEF_TYPE_IDS = 100; + + /// \brief Record codes for each kind of type. + /// + /// These constants describe the records that can occur within a + /// block identified by TYPES_BLOCK_ID in the PCH file. Each + /// constant describes a record for a specific type class in the + /// AST. + enum TypeCode { + /// \brief An ExtQualType record. + TYPE_EXT_QUAL = 1, + /// \brief A FixedWidthIntType record. + TYPE_FIXED_WIDTH_INT = 2, + /// \brief A ComplexType record. + TYPE_COMPLEX = 3, + /// \brief A PointerType record. + TYPE_POINTER = 4, + /// \brief A BlockPointerType record. + TYPE_BLOCK_POINTER = 5, + /// \brief An LValueReferenceType record. + TYPE_LVALUE_REFERENCE = 6, + /// \brief An RValueReferenceType record. + TYPE_RVALUE_REFERENCE = 7, + /// \brief A MemberPointerType record. + TYPE_MEMBER_POINTER = 8, + /// \brief A ConstantArrayType record. + TYPE_CONSTANT_ARRAY = 9, + /// \brief An IncompleteArrayType record. + TYPE_INCOMPLETE_ARRAY = 10, + /// \brief A VariableArrayType record. + TYPE_VARIABLE_ARRAY = 11, + /// \brief A VectorType record. + TYPE_VECTOR = 12, + /// \brief An ExtVectorType record. + TYPE_EXT_VECTOR = 13, + /// \brief A FunctionNoProtoType record. + TYPE_FUNCTION_NO_PROTO = 14, + /// \brief A FunctionProtoType record. + TYPE_FUNCTION_PROTO = 15, + /// \brief A TypedefType record. + TYPE_TYPEDEF = 16, + /// \brief A TypeOfExprType record. + TYPE_TYPEOF_EXPR = 17, + /// \brief A TypeOfType record. + TYPE_TYPEOF = 18, + /// \brief A RecordType record. + TYPE_RECORD = 19, + /// \brief An EnumType record. + TYPE_ENUM = 20, + /// \brief An ObjCInterfaceType record. + TYPE_OBJC_INTERFACE = 21, + /// \brief An ObjCQualifiedInterfaceType record. + TYPE_OBJC_QUALIFIED_INTERFACE = 22, + /// \brief An ObjCQualifiedIdType record. + TYPE_OBJC_QUALIFIED_ID = 23, + /// \brief An ObjCQualifiedClassType record. + TYPE_OBJC_QUALIFIED_CLASS = 24 + }; + + /// \brief Record code for the offsets of each type. + /// + /// The TYPE_OFFSET constant describes the record that occurs + /// within the block identified by TYPE_OFFSETS_BLOCK_ID within + /// the PCH file. The record itself is an array of offsets that + /// point into the types block (identified by TYPES_BLOCK_ID in + /// the PCH file). The index into the array is based on the ID of + /// a type. For a given type ID @c T, the lower three bits of @c T + /// are its qualifiers (const, volatile, restrict), as in the + /// QualType class. The upper bits, after being shifted and + /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the + /// TYPE_OFFSET block to determine the offset of that type's + /// corresponding record within the TYPES_BLOCK_ID block. + enum TypeOffsetCode { + TYPE_OFFSET = 1 + }; + + /// \brief Record codes for each kind of declaration. + /// + /// These constants describe the records that can occur within a + /// declarations block (identified by DECLS_BLOCK_ID). Each + /// constant describes a record for a specific declaration class + /// in the AST. + enum DeclCode { + /// \brief A TranslationUnitDecl record. + DECL_TRANSLATION_UNIT = 1, + /// \brief A TypedefDecl record. + DECL_TYPEDEF, + /// \brief A VarDecl record. + DECL_VAR, + /// \brief A record that stores the set of declarations that are + /// lexically stored within a given DeclContext. + /// + /// The record itself is an array of declaration IDs, in the + /// order in which those declarations were added to the + /// declaration context. This data is used when iterating over + /// the contents of a DeclContext, e.g., via + /// DeclContext::decls_begin()/DeclContext::decls_end(). + DECL_CONTEXT_LEXICAL, + /// \brief A record that stores the set of declarations that are + /// visible from a given DeclContext. + /// + /// The record itself stores a set of mappings, each of which + /// associates a declaration name with one or more declaration + /// IDs. This data is used when performing qualified name lookup + /// into a DeclContext via DeclContext::lookup. + DECL_CONTEXT_VISIBLE + }; + + /// \brief Record code for the offsets of each decl. + /// + /// The DECL_OFFSET constant describes the record that occurs + /// within the block identifier by DECL_OFFSETS_BLOCK_ID within + /// the PCH file. The record itself is an array of offsets that + /// point into the declarations block (identified by + /// DECLS_BLOCK_ID). The declaration ID is an index into this + /// record, after subtracting one to account for the use of + /// declaration ID 0 for a NULL declaration pointer. Index 0 is + /// reserved for the translation unit declaration. + enum DeclOffsetCode { + DECL_OFFSET = 1 + }; + } +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h new file mode 100644 index 0000000000..1338d3c03b --- /dev/null +++ b/include/clang/Frontend/PCHReader.h @@ -0,0 +1,169 @@ +//===--- PCHReader.h - Precompiled Headers Reader ---------------*- 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 PCHReader class, which reads a precompiled header. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_FRONTEND_PCH_READER_H +#define LLVM_CLANG_FRONTEND_PCH_READER_H + +#include "clang/AST/DeclarationName.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/AST/Type.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/DataTypes.h" +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + class MemoryBuffer; +} + +namespace clang { + +class ASTContext; +class Decl; +class DeclContext; + +/// \brief Reads a precompiled head containing the contents of a +/// translation unit. +/// +/// The PCHReader class reads a bitstream (produced by the PCHWriter +/// class) containing the serialized representation of a given +/// abstract syntax tree and its supporting data structures. An +/// instance of the PCHReader can be attached to an ASTContext object, +/// which will provide access to the contents of the PCH file. +/// +/// The PCH reader provides lazy de-serialization of declarations, as +/// required when traversing the AST. Only those AST nodes that are +/// actually required will be de-serialized. +class PCHReader : public ExternalASTSource { + /// \brief The AST context into which we'll read the PCH file. + ASTContext &Context; + + /// \brief The bitstream reader from which we'll read the PCH file. + llvm::BitstreamReader Stream; + + /// \brief The memory buffer that stores the data associated with + /// this PCH file. + llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + + /// \brief Offset of each type within the bitstream, indexed by the + /// type ID, or the representation of a Type*. + llvm::SmallVector<uint64_t, 16> TypeOffsets; + + /// \brief Whether the type with a given index has already been loaded. + /// + /// When the bit at a given index I is true, then TypeOffsets[I] is + /// the already-loaded Type*. Otherwise, TypeOffsets[I] is the + /// location of the type's record in the PCH file. + /// + /// FIXME: We can probably eliminate this, e.g., by bitmangling the + /// values in TypeOffsets. + std::vector<bool> TypeAlreadyLoaded; + + /// \brief Offset of each declaration within the bitstream, indexed + /// by the declaration ID. + llvm::SmallVector<uint64_t, 16> DeclOffsets; + + /// \brief Whether the declaration with a given index has already + /// been loaded. + /// + /// When the bit at the given index I is true, then DeclOffsets[I] + /// is the already-loaded Decl*. Otherwise, DeclOffsets[I] is the + /// location of the declaration's record in the PCH file. + /// + /// FIXME: We can probably eliminate this, e.g., by bitmangling the + /// values in DeclOffsets. + std::vector<bool> DeclAlreadyLoaded; + + typedef llvm::DenseMap<const DeclContext *, std::pair<uint64_t, uint64_t> > + DeclContextOffsetsMap; + + /// \brief Offsets of the lexical and visible declarations for each + /// DeclContext. + DeclContextOffsetsMap DeclContextOffsets; + + bool ReadPCHBlock(); + bool ReadTypeOffsets(); + bool ReadDeclOffsets(); + + QualType ReadTypeRecord(uint64_t Offset); + void LoadedDecl(unsigned Index, Decl *D); + Decl *ReadDeclRecord(uint64_t Offset, unsigned Index); + + PCHReader(const PCHReader&); // do not implement + PCHReader &operator=(const PCHReader &); // do not implement + +public: + typedef llvm::SmallVector<uint64_t, 64> RecordData; + + PCHReader(ASTContext &Context) : Context(Context), Buffer() { } + ~PCHReader(); + + bool ReadPCH(const std::string &FileName); + + /// \brief Resolve a type ID into a type, potentially building a new + /// type. + virtual QualType GetType(unsigned ID); + + /// \brief Resolve a declaration ID into a declaration, potentially + /// building a new declaration. + virtual Decl *GetDecl(unsigned ID); + + /// \brief Read all of the declarations lexically stored in a + /// declaration context. + /// + /// \param DC The declaration context whose declarations will be + /// read. + /// + /// \param Decls Vector that will contain the declarations loaded + /// from the external source. The caller is responsible for merging + /// these declarations with any declarations already stored in the + /// declaration context. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + virtual bool ReadDeclsLexicallyInContext(DeclContext *DC, + llvm::SmallVectorImpl<unsigned> &Decls); + + /// \brief Read all of the declarations visible from a declaration + /// context. + /// + /// \param DC The declaration context whose visible declarations + /// will be read. + /// + /// \param Decls A vector of visible declaration structures, + /// providing the mapping from each name visible in the declaration + /// context to the declaration IDs of declarations with that name. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + /// + /// FIXME: Using this interm |