diff options
Diffstat (limited to 'include/clang')
-rw-r--r-- | include/clang/AST/ExternalASTSource.h | 12 | ||||
-rw-r--r-- | include/clang/Basic/IdentifierTable.h | 38 | ||||
-rw-r--r-- | include/clang/Basic/OnDiskHashTable.h | 29 | ||||
-rw-r--r-- | include/clang/Frontend/PCHReader.h | 60 | ||||
-rw-r--r-- | include/clang/Sema/ExternalSemaSource.h | 45 | ||||
-rw-r--r-- | include/clang/Sema/SemaConsumer.h | 2 |
6 files changed, 162 insertions, 24 deletions
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 267b4838a4..ef09770933 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file defines the ExternalASTSource interface, +// This file defines the ExternalASTSource interface, which enables +// construction of AST nodes from some external source.x // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H @@ -22,6 +23,7 @@ namespace clang { class ASTConsumer; class Decl; class DeclContext; +class ExternalSemaSource; // layering violation required for downcasting class Stmt; /// \brief The deserialized representation of a set of declarations @@ -44,7 +46,15 @@ struct VisibleDeclaration { /// actual type and declaration nodes, and read parts of declaration /// contexts. class ExternalASTSource { + /// \brief Whether this AST source also provides information for + /// semantic analysis. + bool SemaSource; + + friend class ExternalSemaSource; + public: + ExternalASTSource() : SemaSource(false) { } + virtual ~ExternalASTSource(); /// \brief Resolve a type ID into a type, potentially building a new diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index d4f680494e..3156bbc4e9 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -229,7 +229,7 @@ private: }; /// IdentifierInfoLookup - An abstract class used by IdentifierTable that -/// provides an interface for for performing lookups from strings +/// provides an interface for performing lookups from strings /// (const char *) to IdentiferInfo objects. class IdentifierInfoLookup { public: @@ -260,6 +260,11 @@ public: IdentifierTable(const LangOptions &LangOpts, IdentifierInfoLookup* externalLookup = 0); + /// \brief Set the external identifier lookup mechanism. + void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) { + ExternalLookup = IILookup; + } + llvm::BumpPtrAllocator& getAllocator() { return HashTable.getAllocator(); } @@ -295,6 +300,34 @@ public: return *II; } + /// \brief Creates a new IdentifierInfo from the given string. + /// + /// This is a lower-level version of get() that requires that this + /// identifier not be known previously and that does not consult an + /// external source for identifiers. In particular, external + /// identifier sources can use this routine to build IdentifierInfo + /// nodes and then introduce additional information about those + /// identifiers. + IdentifierInfo &CreateIdentifierInfo(const char *NameStart, + const char *NameEnd) { + llvm::StringMapEntry<IdentifierInfo*> &Entry = + HashTable.GetOrCreateValue(NameStart, NameEnd); + + IdentifierInfo *II = Entry.getValue(); + assert(!II && "IdentifierInfo already exists"); + + // Lookups failed, make a new IdentifierInfo. + void *Mem = getAllocator().Allocate<IdentifierInfo>(); + II = new (Mem) IdentifierInfo(); + Entry.setValue(II); + + // Make sure getName() knows how to find the IdentifierInfo + // contents. + II->Entry = &Entry; + + return *II; + } + IdentifierInfo &get(const char *Name) { return get(Name, Name+strlen(Name)); } @@ -304,14 +337,11 @@ public: return get(NameBytes, NameBytes+Name.size()); } -private: typedef HashTableTy::const_iterator iterator; typedef HashTableTy::const_iterator const_iterator; iterator begin() const { return HashTable.begin(); } iterator end() const { return HashTable.end(); } -public: - unsigned size() const { return HashTable.size(); } /// PrintStats - Print some statistics to stderr that indicate how well the diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index 631d497f1a..3caeb9ffd8 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -242,6 +242,8 @@ class OnDiskChainedHashTable { const unsigned NumEntries; const unsigned char* const Buckets; const unsigned char* const Base; + Info InfoObj; + public: typedef typename Info::internal_key_type internal_key_type; typedef typename Info::external_key_type external_key_type; @@ -249,9 +251,10 @@ public: OnDiskChainedHashTable(unsigned numBuckets, unsigned numEntries, const unsigned char* buckets, - const unsigned char* base) + const unsigned char* base, + const Info &InfoObj = Info()) : NumBuckets(numBuckets), NumEntries(numEntries), - Buckets(buckets), Base(base) { + Buckets(buckets), Base(base), InfoObj(InfoObj) { assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 && "'buckets' must have a 4-byte alignment"); } @@ -267,22 +270,27 @@ public: internal_key_type key; const unsigned char* const data; const unsigned len; + Info *InfoObj; public: iterator() : data(0), len(0) {} - iterator(const internal_key_type k, const unsigned char* d, unsigned l) - : key(k), data(d), len(l) {} + iterator(const internal_key_type k, const unsigned char* d, unsigned l, + Info *InfoObj) + : key(k), data(d), len(l), InfoObj(InfoObj) {} - data_type operator*() const { return Info::ReadData(key, data, len); } + data_type operator*() const { return InfoObj->ReadData(key, data, len); } bool operator==(const iterator& X) const { return X.data == data; } bool operator!=(const iterator& X) const { return X.data != data; } }; - iterator find(const external_key_type& eKey) { + iterator find(const external_key_type& eKey, Info *InfoPtr = 0) { + if (!InfoPtr) + InfoPtr = &InfoObj; + using namespace io; const internal_key_type& iKey = Info::GetInternalKey(eKey); unsigned key_hash = Info::ComputeHash(iKey); - // Each bucket is just a 32-bit offset into the PTH file. + // Each bucket is just a 32-bit offset into the hash table file. unsigned idx = key_hash & (NumBuckets - 1); const unsigned char* Bucket = Buckets + sizeof(uint32_t)*idx; @@ -319,7 +327,7 @@ public: } // The key matches! - return iterator(X, Items + L.first, L.second); + return iterator(X, Items + L.first, L.second, InfoPtr); } return iterator(); @@ -329,7 +337,8 @@ public: static OnDiskChainedHashTable* Create(const unsigned char* buckets, - const unsigned char* const base) { + const unsigned char* const base, + const Info &InfoObj = Info()) { using namespace io; assert(buckets > base); assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 && @@ -338,7 +347,7 @@ public: unsigned numBuckets = ReadLE32(buckets); unsigned numEntries = ReadLE32(buckets); return new OnDiskChainedHashTable<Info>(numBuckets, numEntries, buckets, - base); + base, InfoObj); } }; diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 6ee549abf5..3af147f7a9 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -15,9 +15,10 @@ #include "clang/Frontend/PCHBitCodes.h" #include "clang/AST/DeclarationName.h" -#include "clang/AST/ExternalASTSource.h" +#include "clang/Sema/ExternalSemaSource.h" #include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" @@ -44,7 +45,9 @@ class Decl; class DeclContext; class GotoStmt; class LabelStmt; +class NamedDecl; class Preprocessor; +class Sema; class SwitchCase; /// \brief Reads a precompiled head containing the contents of a @@ -59,11 +62,15 @@ class SwitchCase; /// 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 { +class PCHReader : public ExternalSemaSource, public IdentifierInfoLookup { public: enum PCHReadResult { Success, Failure, IgnorePCH }; private: + /// \brief The semantic analysis object that will be processing the + /// PCH file and the translation unit that uses it. + Sema *SemaObj; + /// \brief The preprocessor that will be loading the source file. Preprocessor &PP; @@ -116,8 +123,14 @@ private: /// DeclContext. DeclContextOffsetsMap DeclContextOffsets; - /// \brief String data for the identifiers in the PCH file. - const char *IdentifierTable; + /// \brief Actual data for the on-disk hash table. + /// + /// FIXME: This will eventually go away. + const char *IdentifierTableData; + + /// \brief A pointer to an on-disk hash table of opaque type + /// IdentifierHashTable. + void *IdentifierLookupTable; /// \brief String data for identifiers, indexed by the identifier ID /// minus one. @@ -158,10 +171,10 @@ private: /// in the PCH file. unsigned TotalNumStatements; - /// \brief + /// \brief FIXME: document! llvm::SmallVector<uint64_t, 4> SpecialTypes; - PCHReadResult ReadPCHBlock(); + PCHReadResult ReadPCHBlock(uint64_t &PreprocessorBlockOffset); bool CheckPredefinesBuffer(const char *PCHPredef, unsigned PCHPredefLen, FileID PCHBufferID); @@ -179,8 +192,9 @@ private: public: typedef llvm::SmallVector<uint64_t, 64> RecordData; - PCHReader(Preprocessor &PP, ASTContext &Context) - : PP(PP), Context(Context), IdentifierTable(0), NumStatementsRead(0) { } + explicit PCHReader(Preprocessor &PP, ASTContext &Context) + : SemaObj(0), PP(PP), Context(Context), + IdentifierTableData(0), NumStatementsRead(0) { } ~PCHReader() {} @@ -246,6 +260,23 @@ public: /// \brief Print some statistics about PCH usage. virtual void PrintStats(); + /// \brief Initialize the semantic source with the Sema instance + /// being used to perform semantic analysis on the abstract syntax + /// tree. + virtual void InitializeSema(Sema &S); + + /// \brief Retrieve the IdentifierInfo for the named identifier. + /// + /// This routine builds a new IdentifierInfo for the given + /// identifier. If any declarations with this name are visible from + /// translation unit scope, their declarations will be deserialized + /// and introduced into the declaration chain of the + /// identifier. FIXME: if this identifier names a macro, deserialize + /// the macro. + virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd); + + void SetIdentifierInfo(unsigned ID, const IdentifierInfo *II); + /// \brief Report a diagnostic. DiagnosticBuilder Diag(unsigned DiagID); @@ -284,9 +315,22 @@ public: /// supplements. ASTContext &getContext() { return Context; } + // FIXME: temporary hack to store declarations that we deserialized + // before we had access to the Sema object. + llvm::SmallVector<NamedDecl *, 16> TUDecls; + + /// \brief Retrieve the semantic analysis object used to analyze the + /// translation unit in which the precompiled header is being + /// imported. + Sema *getSema() { return SemaObj; } + /// \brief Retrieve the stream that this PCH reader is reading from. llvm::BitstreamReader &getStream() { return Stream; } + /// \brief Retrieve the identifier table associated with the + /// preprocessor. + IdentifierTable &getIdentifierTable(); + /// \brief Record that the given ID maps to the given switch-case /// statement. void RecordSwitchCaseID(SwitchCase *SC, unsigned ID); diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h new file mode 100644 index 0000000000..1c216e4b86 --- /dev/null +++ b/include/clang/Sema/ExternalSemaSource.h @@ -0,0 +1,45 @@ +//===--- ExternalSemaSource.h - External Sema 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 ExternalSemaSource interface. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H +#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H + +#include "clang/AST/ExternalASTSource.h" + +namespace clang { + +class Sema; + +/// \brief An abstract interface that should be implemented by +/// external AST sources that also provide information for semantic +/// analysis. +class ExternalSemaSource : public ExternalASTSource { +public: + ExternalSemaSource() { + ExternalASTSource::SemaSource = true; + } + + /// \brief Initialize the semantic source with the Sema instance + /// being used to perform semantic analysis on the abstract syntax + /// tree. + virtual void InitializeSema(Sema &S) {} + + // isa/cast/dyn_cast support + static bool classof(const ExternalASTSource *Source) { + return Source->SemaSource; + } + static bool classof(const ExternalSemaSource *) { return true; } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Sema/SemaConsumer.h b/include/clang/Sema/SemaConsumer.h index 25d4253390..e821947035 100644 --- a/include/clang/Sema/SemaConsumer.h +++ b/include/clang/Sema/SemaConsumer.h @@ -25,7 +25,7 @@ namespace clang { /// analysis of the entities in those ASTs. class SemaConsumer : public ASTConsumer { public: - explicit SemaConsumer() { + SemaConsumer() { ASTConsumer::SemaConsumer = true; } |