diff options
Diffstat (limited to 'include/clang/Lex/PreprocessingRecord.h')
-rw-r--r-- | include/clang/Lex/PreprocessingRecord.h | 377 |
1 files changed, 276 insertions, 101 deletions
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index b38303a2f40b6..53da19e6c2961 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -16,6 +16,7 @@ #include "clang/Lex/PPCallbacks.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Allocator.h" #include <vector> @@ -43,14 +44,14 @@ namespace clang { public: /// \brief The kind of preprocessed entity an object describes. enum EntityKind { + /// \brief Indicates a problem trying to load the preprocessed entity. + InvalidKind, + /// \brief A macro expansion. MacroExpansionKind, - /// \brief A preprocessing directive whose kind is not specified. - /// - /// This kind will be used for any preprocessing directive that does not - /// have a more specific kind within the \c DirectiveKind enumeration. - PreprocessingDirectiveKind, + /// \defgroup Preprocessing directives + /// @{ /// \brief A macro definition. MacroDefinitionKind, @@ -59,7 +60,9 @@ namespace clang { /// #import, or \c #include_next. InclusionDirectiveKind, - FirstPreprocessingDirective = PreprocessingDirectiveKind, + /// @} + + FirstPreprocessingDirective = MacroDefinitionKind, LastPreprocessingDirective = InclusionDirectiveKind }; @@ -73,7 +76,9 @@ namespace clang { protected: PreprocessedEntity(EntityKind Kind, SourceRange Range) : Kind(Kind), Range(Range) { } - + + friend class PreprocessingRecord; + public: /// \brief Retrieve the kind of preprocessed entity stored in this object. EntityKind getKind() const { return Kind; } @@ -81,7 +86,11 @@ namespace clang { /// \brief Retrieve the source range that covers this entire preprocessed /// entity. SourceRange getSourceRange() const { return Range; } - + + /// \brief Returns true if there was a problem loading the preprocessed + /// entity. + bool isInvalid() const { return Kind == InvalidKind; } + // Implement isa/cast/dyncast/etc. static bool classof(const PreprocessedEntity *) { return true; } @@ -110,34 +119,6 @@ namespace clang { void operator delete(void* data) throw(); }; - /// \brief Records the location of a macro expansion. - class MacroExpansion : public PreprocessedEntity { - /// \brief The name of the macro being expanded. - IdentifierInfo *Name; - - /// \brief The definition of this macro. - MacroDefinition *Definition; - - public: - MacroExpansion(IdentifierInfo *Name, SourceRange Range, - MacroDefinition *Definition) - : PreprocessedEntity(MacroExpansionKind, Range), Name(Name), - Definition(Definition) { } - - /// \brief The name of the macro being expanded. - IdentifierInfo *getName() const { return Name; } - - /// \brief The definition of the macro being expanded. - MacroDefinition *getDefinition() const { return Definition; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const PreprocessedEntity *PE) { - return PE->getKind() == MacroExpansionKind; - } - static bool classof(const MacroExpansion *) { return true; } - - }; - /// \brief Records the presence of a preprocessor directive. class PreprocessingDirective : public PreprocessedEntity { public: @@ -156,21 +137,16 @@ namespace clang { class MacroDefinition : public PreprocessingDirective { /// \brief The name of the macro being defined. const IdentifierInfo *Name; - - /// \brief The location of the macro name in the macro definition. - SourceLocation Location; public: - explicit MacroDefinition(const IdentifierInfo *Name, SourceLocation Location, - SourceRange Range) - : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name), - Location(Location) { } + explicit MacroDefinition(const IdentifierInfo *Name, SourceRange Range) + : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name) { } /// \brief Retrieve the name of the macro being defined. const IdentifierInfo *getName() const { return Name; } /// \brief Retrieve the location of the macro name in the definition. - SourceLocation getLocation() const { return Location; } + SourceLocation getLocation() const { return getSourceRange().getBegin(); } // Implement isa/cast/dyncast/etc. static bool classof(const PreprocessedEntity *PE) { @@ -178,6 +154,44 @@ namespace clang { } static bool classof(const MacroDefinition *) { return true; } }; + + /// \brief Records the location of a macro expansion. + class MacroExpansion : public PreprocessedEntity { + /// \brief The definition of this macro or the name of the macro if it is + /// a builtin macro. + llvm::PointerUnion<IdentifierInfo *, MacroDefinition *> NameOrDef; + + public: + MacroExpansion(IdentifierInfo *BuiltinName, SourceRange Range) + : PreprocessedEntity(MacroExpansionKind, Range), + NameOrDef(BuiltinName) { } + + MacroExpansion(MacroDefinition *Definition, SourceRange Range) + : PreprocessedEntity(MacroExpansionKind, Range), + NameOrDef(Definition) { } + + /// \brief True if it is a builtin macro. + bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); } + + /// \brief The name of the macro being expanded. + const IdentifierInfo *getName() const { + if (MacroDefinition *Def = getDefinition()) + return Def->getName(); + return NameOrDef.get<IdentifierInfo*>(); + } + + /// \brief The definition of the macro being expanded. May return null if + /// this is a builtin macro. + MacroDefinition *getDefinition() const { + return NameOrDef.dyn_cast<MacroDefinition *>(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const PreprocessedEntity *PE) { + return PE->getKind() == MacroExpansionKind; + } + static bool classof(const MacroExpansion *) { return true; } + }; /// \brief Record the location of an inclusion directive, such as an /// \c #include or \c #import statement. @@ -199,7 +213,7 @@ namespace clang { private: /// \brief The name of the file that was included, as written in /// the source. - llvm::StringRef FileName; + StringRef FileName; /// \brief Whether the file name was in quotation marks; otherwise, it was /// in angle brackets. @@ -215,14 +229,14 @@ namespace clang { public: InclusionDirective(PreprocessingRecord &PPRec, - InclusionKind Kind, llvm::StringRef FileName, + InclusionKind Kind, StringRef FileName, bool InQuotes, const FileEntry *File, SourceRange Range); /// \brief Determine what kind of inclusion directive this is. InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); } /// \brief Retrieve the included file name as it was written in the source. - llvm::StringRef getFileName() const { return FileName; } + StringRef getFileName() const { return FileName; } /// \brief Determine whether the included file name was written in quotes; /// otherwise, it was written in angle brackets. @@ -245,19 +259,24 @@ namespace clang { public: virtual ~ExternalPreprocessingRecordSource(); - /// \brief Read any preallocated preprocessed entities from the external - /// source. - virtual void ReadPreprocessedEntities() = 0; - - /// \brief Read the preprocessed entity at the given offset. - virtual PreprocessedEntity * - ReadPreprocessedEntityAtOffset(uint64_t Offset) = 0; + /// \brief Read a preallocated preprocessed entity from the external source. + /// + /// \returns null if an error occurred that prevented the preprocessed + /// entity from being loaded. + virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0; + + /// \brief Returns a pair of [Begin, End) indices of preallocated + /// preprocessed entities that \arg Range encompasses. + virtual std::pair<unsigned, unsigned> + findPreprocessedEntitiesInRange(SourceRange Range) = 0; }; /// \brief A record of the steps taken while preprocessing a source file, /// including the various preprocessing directives processed, macros /// expanded, etc. class PreprocessingRecord : public PPCallbacks { + SourceManager &SourceMgr; + /// \brief Whether we should include nested macro expansions in /// the preprocessing record. bool IncludeNestedMacroExpansions; @@ -269,24 +288,64 @@ namespace clang { /// were seen. std::vector<PreprocessedEntity *> PreprocessedEntities; + /// \brief The set of preprocessed entities in this record that have been + /// loaded from external sources. + /// + /// The entries in this vector are loaded lazily from the external source, + /// and are referenced by the iterator using negative indices. + std::vector<PreprocessedEntity *> LoadedPreprocessedEntities; + + /// \brief Global (loaded or local) ID for a preprocessed entity. + /// Negative values are used to indicate preprocessed entities + /// loaded from the external source while non-negative values are used to + /// indicate preprocessed entities introduced by the current preprocessor. + /// If M is the number of loaded preprocessed entities, value -M + /// corresponds to element 0 in the loaded entities vector, position -M+1 + /// corresponds to element 1 in the loaded entities vector, etc. + typedef int PPEntityID; + + PPEntityID getPPEntityID(unsigned Index, bool isLoaded) const { + return isLoaded ? PPEntityID(Index) - LoadedPreprocessedEntities.size() + : Index; + } + /// \brief Mapping from MacroInfo structures to their definitions. - llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions; + llvm::DenseMap<const MacroInfo *, PPEntityID> MacroDefinitions; /// \brief External source of preprocessed entities. ExternalPreprocessingRecordSource *ExternalSource; + + /// \brief Retrieve the preprocessed entity at the given ID. + PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID); + + /// \brief Retrieve the loaded preprocessed entity at the given index. + PreprocessedEntity *getLoadedPreprocessedEntity(unsigned Index); - /// \brief The number of preallocated entities (that are known to the - /// external source). - unsigned NumPreallocatedEntities; - - /// \brief Whether we have already loaded all of the preallocated entities. - mutable bool LoadedPreallocatedEntities; - - void MaybeLoadPreallocatedEntities() const ; + /// \brief Determine the number of preprocessed entities that were + /// loaded (or can be loaded) from an external source. + unsigned getNumLoadedPreprocessedEntities() const { + return LoadedPreprocessedEntities.size(); + } + + /// \brief Returns a pair of [Begin, End) indices of local preprocessed + /// entities that \arg Range encompasses. + std::pair<unsigned, unsigned> + findLocalPreprocessedEntitiesInRange(SourceRange Range) const; + unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const; + unsigned findEndLocalPreprocessedEntity(SourceLocation Loc) const; + + /// \brief Allocate space for a new set of loaded preprocessed entities. + /// + /// \returns The index into the set of loaded preprocessed entities, which + /// corresponds to the first newly-allocated entity. + unsigned allocateLoadedEntities(unsigned NumEntities); + + /// \brief Register a new macro definition. + void RegisterMacroDefinition(MacroInfo *Macro, PPEntityID PPID); public: - /// \brief Construct - explicit PreprocessingRecord(bool IncludeNestedMacroExpansions); + /// \brief Construct a new preprocessing record. + PreprocessingRecord(SourceManager &SM, bool IncludeNestedMacroExpansions); /// \brief Allocate memory in the preprocessing record. void *Allocate(unsigned Size, unsigned Align = 8) { @@ -295,64 +354,180 @@ namespace clang { /// \brief Deallocate memory in the preprocessing record. void Deallocate(void *Ptr) { } - - size_t getTotalMemory() const { - return BumpAlloc.getTotalMemory(); - } - + + size_t getTotalMemory() const; + + SourceManager &getSourceManager() const { return SourceMgr; } + // Iteration over the preprocessed entities. - typedef std::vector<PreprocessedEntity *>::iterator iterator; - typedef std::vector<PreprocessedEntity *>::const_iterator const_iterator; - iterator begin(bool OnlyLocalEntities = false); - iterator end(bool OnlyLocalEntities = false); - const_iterator begin(bool OnlyLocalEntities = false) const; - const_iterator end(bool OnlyLocalEntities = false) const; + class iterator { + PreprocessingRecord *Self; + + /// \brief Position within the preprocessed entity sequence. + /// + /// In a complete iteration, the Position field walks the range [-M, N), + /// where negative values are used to indicate preprocessed entities + /// loaded from the external source while non-negative values are used to + /// indicate preprocessed entities introduced by the current preprocessor. + /// However, to provide iteration in source order (for, e.g., chained + /// precompiled headers), dereferencing the iterator flips the negative + /// values (corresponding to loaded entities), so that position -M + /// corresponds to element 0 in the loaded entities vector, position -M+1 + /// corresponds to element 1 in the loaded entities vector, etc. This + /// gives us a reasonably efficient, source-order walk. + PPEntityID Position; + + public: + typedef PreprocessedEntity *value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef std::random_access_iterator_tag iterator_category; + typedef int difference_type; + + iterator() : Self(0), Position(0) { } + + iterator(PreprocessingRecord *Self, int Position) + : Self(Self), Position(Position) { } + + value_type operator*() const { + return Self->getPreprocessedEntity(Position); + } + + value_type operator[](difference_type D) { + return *(*this + D); + } + + iterator &operator++() { + ++Position; + return *this; + } + + iterator operator++(int) { + iterator Prev(*this); + ++Position; + return Prev; + } + + iterator &operator--() { + --Position; + return *this; + } + + iterator operator--(int) { + iterator Prev(*this); + --Position; + return Prev; + } + + friend bool operator==(const iterator &X, const iterator &Y) { + return X.Position == Y.Position; + } + + friend bool operator!=(const iterator &X, const iterator &Y) { + return X.Position != Y.Position; + } + + friend bool operator<(const iterator &X, const iterator &Y) { + return X.Position < Y.Position; + } + + friend bool operator>(const iterator &X, const iterator &Y) { + return X.Position > Y.Position; + } + + friend bool operator<=(const iterator &X, const iterator &Y) { + return X.Position < Y.Position; + } + + friend bool operator>=(const iterator &X, const iterator &Y) { + return X.Position > Y.Position; + } + + friend iterator& operator+=(iterator &X, difference_type D) { + X.Position += D; + return X; + } + + friend iterator& operator-=(iterator &X, difference_type D) { + X.Position -= D; + return X; + } + + friend iterator operator+(iterator X, difference_type D) { + X.Position += D; + return X; + } + + friend iterator operator+(difference_type D, iterator X) { + X.Position += D; + return X; + } + + friend difference_type operator-(const iterator &X, const iterator &Y) { + return X.Position - Y.Position; + } + + friend iterator operator-(iterator X, difference_type D) { + X.Position -= D; + return X; + } + }; + friend class iterator; + + /// \brief Begin iterator for all preprocessed entities. + iterator begin() { + return iterator(this, -(int)LoadedPreprocessedEntities.size()); + } + + /// \brief End iterator for all preprocessed entities. + iterator end() { + return iterator(this, PreprocessedEntities.size()); + } + + /// \brief Begin iterator for local, non-loaded, preprocessed entities. + iterator local_begin() { + return iterator(this, 0); + } + + /// \brief End iterator for local, non-loaded, preprocessed entities. + iterator local_end() { + return iterator(this, PreprocessedEntities.size()); + } + + /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities + /// that source range \arg R encompasses. + std::pair<iterator, iterator> getPreprocessedEntitiesInRange(SourceRange R); /// \brief Add a new preprocessed entity to this record. void addPreprocessedEntity(PreprocessedEntity *Entity); /// \brief Set the external source for preprocessed entities. - void SetExternalSource(ExternalPreprocessingRecordSource &Source, - unsigned NumPreallocatedEntities); + void SetExternalSource(ExternalPreprocessingRecordSource &Source); /// \brief Retrieve the external source for preprocessed entities. ExternalPreprocessingRecordSource *getExternalSource() const { return ExternalSource; } - unsigned getNumPreallocatedEntities() const { - return NumPreallocatedEntities; - } - - /// \brief Set the preallocated entry at the given index to the given - /// preprocessed entity. - void SetPreallocatedEntity(unsigned Index, PreprocessedEntity *Entity); - - /// \brief Register a new macro definition. - void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinition *MD); - - /// \brief Retrieve the preprocessed entity at the given index. - PreprocessedEntity *getPreprocessedEntity(unsigned Index) { - assert(Index < PreprocessedEntities.size() && - "Out-of-bounds preprocessed entity"); - return PreprocessedEntities[Index]; - } - /// \brief Retrieve the macro definition that corresponds to the given /// \c MacroInfo. MacroDefinition *findMacroDefinition(const MacroInfo *MI); - - virtual void MacroExpands(const Token &Id, const MacroInfo* MI); + + virtual void MacroExpands(const Token &Id, const MacroInfo* MI, + SourceRange Range); virtual void MacroDefined(const Token &Id, const MacroInfo *MI); virtual void MacroUndefined(const Token &Id, const MacroInfo *MI); virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, - llvm::StringRef FileName, + StringRef FileName, bool IsAngled, const FileEntry *File, SourceLocation EndLoc, - llvm::StringRef SearchPath, - llvm::StringRef RelativePath); + StringRef SearchPath, + StringRef RelativePath); + + friend class ASTReader; + friend class ASTWriter; }; } // end namespace clang |