aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h14
-rw-r--r--include/clang/AST/DeclBase.h43
-rw-r--r--include/clang/AST/DeclContextInternals.h170
-rw-r--r--include/clang/AST/ExternalASTSource.h94
-rw-r--r--include/clang/Frontend/PCHBitCodes.h239
-rw-r--r--include/clang/Frontend/PCHReader.h169
-rw-r--r--include/clang/Frontend/PCHWriter.h114
-rw-r--r--lib/AST/ASTContext.cpp18
-rw-r--r--lib/AST/DeclBase.cpp112
-rw-r--r--lib/Frontend/PCHReader.cpp602
-rw-r--r--lib/Frontend/PCHWriter.cpp636
-rw-r--r--lib/Sema/SemaDecl.cpp6
-rw-r--r--lib/Sema/SemaLookup.cpp11
-rw-r--r--test/PCH/variables.c6
-rw-r--r--test/PCH/variables.h5
-rwxr-xr-xtest/TestRunner.sh3
-rw-r--r--tools/clang-cc/ASTConsumers.h5
-rw-r--r--tools/clang-cc/GeneratePCH.cpp78
-rw-r--r--tools/clang-cc/clang-cc.cpp23
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