1205408Srdivacky//===--- PreprocessingRecord.h - Record of Preprocessing --------*- C++ -*-===//
2205408Srdivacky//
3205408Srdivacky//                     The LLVM Compiler Infrastructure
4205408Srdivacky//
5205408Srdivacky// This file is distributed under the University of Illinois Open Source
6205408Srdivacky// License. See LICENSE.TXT for details.
7205408Srdivacky//
8205408Srdivacky//===----------------------------------------------------------------------===//
9205408Srdivacky//
10205408Srdivacky//  This file defines the PreprocessingRecord class, which maintains a record
11205408Srdivacky//  of what occurred during preprocessing.
12205408Srdivacky//
13205408Srdivacky//===----------------------------------------------------------------------===//
14205408Srdivacky#ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
15205408Srdivacky#define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
16205408Srdivacky
17249423Sdim#include "clang/Basic/IdentifierTable.h"
18249423Sdim#include "clang/Basic/SourceLocation.h"
19205408Srdivacky#include "clang/Lex/PPCallbacks.h"
20205408Srdivacky#include "llvm/ADT/DenseMap.h"
21234353Sdim#include "llvm/ADT/Optional.h"
22249423Sdim#include "llvm/ADT/SmallVector.h"
23205408Srdivacky#include "llvm/Support/Allocator.h"
24234353Sdim#include "llvm/Support/Compiler.h"
25205408Srdivacky#include <vector>
26205408Srdivacky
27205408Srdivackynamespace clang {
28205408Srdivacky  class IdentifierInfo;
29249423Sdim  class MacroInfo;
30205408Srdivacky  class PreprocessingRecord;
31205408Srdivacky}
32205408Srdivacky
33205408Srdivacky/// \brief Allocates memory within a Clang preprocessing record.
34205408Srdivackyvoid* operator new(size_t bytes, clang::PreprocessingRecord& PR,
35205408Srdivacky                   unsigned alignment = 8) throw();
36205408Srdivacky
37205408Srdivacky/// \brief Frees memory allocated in a Clang preprocessing record.
38205408Srdivackyvoid operator delete(void* ptr, clang::PreprocessingRecord& PR,
39205408Srdivacky                     unsigned) throw();
40205408Srdivacky
41205408Srdivackynamespace clang {
42205408Srdivacky  class MacroDefinition;
43218893Sdim  class FileEntry;
44205408Srdivacky
45205408Srdivacky  /// \brief Base class that describes a preprocessed entity, which may be a
46224145Sdim  /// preprocessor directive or macro expansion.
47205408Srdivacky  class PreprocessedEntity {
48205408Srdivacky  public:
49205408Srdivacky    /// \brief The kind of preprocessed entity an object describes.
50205408Srdivacky    enum EntityKind {
51226633Sdim      /// \brief Indicates a problem trying to load the preprocessed entity.
52226633Sdim      InvalidKind,
53226633Sdim
54224145Sdim      /// \brief A macro expansion.
55224145Sdim      MacroExpansionKind,
56205408Srdivacky
57226633Sdim      /// \defgroup Preprocessing directives
58226633Sdim      /// @{
59205408Srdivacky
60205408Srdivacky      /// \brief A macro definition.
61205408Srdivacky      MacroDefinitionKind,
62205408Srdivacky
63239462Sdim      /// \brief An inclusion directive, such as \c \#include, \c
64239462Sdim      /// \#import, or \c \#include_next.
65218893Sdim      InclusionDirectiveKind,
66218893Sdim
67226633Sdim      /// @}
68226633Sdim
69226633Sdim      FirstPreprocessingDirective = MacroDefinitionKind,
70218893Sdim      LastPreprocessingDirective = InclusionDirectiveKind
71205408Srdivacky    };
72205408Srdivacky
73205408Srdivacky  private:
74205408Srdivacky    /// \brief The kind of preprocessed entity that this object describes.
75205408Srdivacky    EntityKind Kind;
76205408Srdivacky
77205408Srdivacky    /// \brief The source range that covers this preprocessed entity.
78205408Srdivacky    SourceRange Range;
79205408Srdivacky
80205408Srdivacky  protected:
81205408Srdivacky    PreprocessedEntity(EntityKind Kind, SourceRange Range)
82205408Srdivacky      : Kind(Kind), Range(Range) { }
83226633Sdim
84226633Sdim    friend class PreprocessingRecord;
85226633Sdim
86205408Srdivacky  public:
87205408Srdivacky    /// \brief Retrieve the kind of preprocessed entity stored in this object.
88205408Srdivacky    EntityKind getKind() const { return Kind; }
89205408Srdivacky
90205408Srdivacky    /// \brief Retrieve the source range that covers this entire preprocessed
91205408Srdivacky    /// entity.
92234353Sdim    SourceRange getSourceRange() const LLVM_READONLY { return Range; }
93226633Sdim
94226633Sdim    /// \brief Returns true if there was a problem loading the preprocessed
95226633Sdim    /// entity.
96226633Sdim    bool isInvalid() const { return Kind == InvalidKind; }
97226633Sdim
98205408Srdivacky    // Only allow allocation of preprocessed entities using the allocator
99205408Srdivacky    // in PreprocessingRecord or by doing a placement new.
100205408Srdivacky    void* operator new(size_t bytes, PreprocessingRecord& PR,
101205408Srdivacky                       unsigned alignment = 8) throw() {
102205408Srdivacky      return ::operator new(bytes, PR, alignment);
103205408Srdivacky    }
104205408Srdivacky
105205408Srdivacky    void* operator new(size_t bytes, void* mem) throw() {
106205408Srdivacky      return mem;
107205408Srdivacky    }
108205408Srdivacky
109205408Srdivacky    void operator delete(void* ptr, PreprocessingRecord& PR,
110205408Srdivacky                         unsigned alignment) throw() {
111205408Srdivacky      return ::operator delete(ptr, PR, alignment);
112205408Srdivacky    }
113205408Srdivacky
114205408Srdivacky    void operator delete(void*, std::size_t) throw() { }
115205408Srdivacky    void operator delete(void*, void*) throw() { }
116205408Srdivacky
117205408Srdivacky  private:
118205408Srdivacky    // Make vanilla 'new' and 'delete' illegal for preprocessed entities.
119205408Srdivacky    void* operator new(size_t bytes) throw();
120205408Srdivacky    void operator delete(void* data) throw();
121205408Srdivacky  };
122205408Srdivacky
123205408Srdivacky  /// \brief Records the presence of a preprocessor directive.
124205408Srdivacky  class PreprocessingDirective : public PreprocessedEntity {
125205408Srdivacky  public:
126205408Srdivacky    PreprocessingDirective(EntityKind Kind, SourceRange Range)
127205408Srdivacky      : PreprocessedEntity(Kind, Range) { }
128205408Srdivacky
129205408Srdivacky    // Implement isa/cast/dyncast/etc.
130205408Srdivacky    static bool classof(const PreprocessedEntity *PD) {
131205408Srdivacky      return PD->getKind() >= FirstPreprocessingDirective &&
132205408Srdivacky             PD->getKind() <= LastPreprocessingDirective;
133205408Srdivacky    }
134205408Srdivacky  };
135205408Srdivacky
136205408Srdivacky  /// \brief Record the location of a macro definition.
137205408Srdivacky  class MacroDefinition : public PreprocessingDirective {
138205408Srdivacky    /// \brief The name of the macro being defined.
139205408Srdivacky    const IdentifierInfo *Name;
140205408Srdivacky
141205408Srdivacky  public:
142226633Sdim    explicit MacroDefinition(const IdentifierInfo *Name, SourceRange Range)
143226633Sdim      : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name) { }
144205408Srdivacky
145205408Srdivacky    /// \brief Retrieve the name of the macro being defined.
146205408Srdivacky    const IdentifierInfo *getName() const { return Name; }
147205408Srdivacky
148205408Srdivacky    /// \brief Retrieve the location of the macro name in the definition.
149226633Sdim    SourceLocation getLocation() const { return getSourceRange().getBegin(); }
150205408Srdivacky
151205408Srdivacky    // Implement isa/cast/dyncast/etc.
152205408Srdivacky    static bool classof(const PreprocessedEntity *PE) {
153205408Srdivacky      return PE->getKind() == MacroDefinitionKind;
154205408Srdivacky    }
155205408Srdivacky  };
156226633Sdim
157226633Sdim  /// \brief Records the location of a macro expansion.
158226633Sdim  class MacroExpansion : public PreprocessedEntity {
159226633Sdim    /// \brief The definition of this macro or the name of the macro if it is
160226633Sdim    /// a builtin macro.
161226633Sdim    llvm::PointerUnion<IdentifierInfo *, MacroDefinition *> NameOrDef;
162218893Sdim
163226633Sdim  public:
164226633Sdim    MacroExpansion(IdentifierInfo *BuiltinName, SourceRange Range)
165226633Sdim      : PreprocessedEntity(MacroExpansionKind, Range),
166226633Sdim        NameOrDef(BuiltinName) { }
167226633Sdim
168226633Sdim    MacroExpansion(MacroDefinition *Definition, SourceRange Range)
169226633Sdim      : PreprocessedEntity(MacroExpansionKind, Range),
170226633Sdim        NameOrDef(Definition) { }
171226633Sdim
172226633Sdim    /// \brief True if it is a builtin macro.
173226633Sdim    bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); }
174226633Sdim
175226633Sdim    /// \brief The name of the macro being expanded.
176226633Sdim    const IdentifierInfo *getName() const {
177226633Sdim      if (MacroDefinition *Def = getDefinition())
178226633Sdim        return Def->getName();
179226633Sdim      return NameOrDef.get<IdentifierInfo*>();
180226633Sdim    }
181226633Sdim
182226633Sdim    /// \brief The definition of the macro being expanded. May return null if
183226633Sdim    /// this is a builtin macro.
184226633Sdim    MacroDefinition *getDefinition() const {
185226633Sdim      return NameOrDef.dyn_cast<MacroDefinition *>();
186226633Sdim    }
187226633Sdim
188226633Sdim    // Implement isa/cast/dyncast/etc.
189226633Sdim    static bool classof(const PreprocessedEntity *PE) {
190226633Sdim      return PE->getKind() == MacroExpansionKind;
191226633Sdim    }
192226633Sdim  };
193226633Sdim
194218893Sdim  /// \brief Record the location of an inclusion directive, such as an
195239462Sdim  /// \c \#include or \c \#import statement.
196218893Sdim  class InclusionDirective : public PreprocessingDirective {
197218893Sdim  public:
198218893Sdim    /// \brief The kind of inclusion directives known to the
199218893Sdim    /// preprocessor.
200218893Sdim    enum InclusionKind {
201239462Sdim      /// \brief An \c \#include directive.
202218893Sdim      Include,
203239462Sdim      /// \brief An Objective-C \c \#import directive.
204218893Sdim      Import,
205239462Sdim      /// \brief A GNU \c \#include_next directive.
206218893Sdim      IncludeNext,
207239462Sdim      /// \brief A Clang \c \#__include_macros directive.
208218893Sdim      IncludeMacros
209218893Sdim    };
210218893Sdim
211218893Sdim  private:
212218893Sdim    /// \brief The name of the file that was included, as written in
213218893Sdim    /// the source.
214226633Sdim    StringRef FileName;
215218893Sdim
216218893Sdim    /// \brief Whether the file name was in quotation marks; otherwise, it was
217218893Sdim    /// in angle brackets.
218218893Sdim    unsigned InQuotes : 1;
219218893Sdim
220218893Sdim    /// \brief The kind of inclusion directive we have.
221218893Sdim    ///
222218893Sdim    /// This is a value of type InclusionKind.
223218893Sdim    unsigned Kind : 2;
224218893Sdim
225243830Sdim    /// \brief Whether the inclusion directive was automatically turned into
226243830Sdim    /// a module import.
227243830Sdim    unsigned ImportedModule : 1;
228243830Sdim
229218893Sdim    /// \brief The file that was included.
230218893Sdim    const FileEntry *File;
231218893Sdim
232218893Sdim  public:
233218893Sdim    InclusionDirective(PreprocessingRecord &PPRec,
234226633Sdim                       InclusionKind Kind, StringRef FileName,
235243830Sdim                       bool InQuotes, bool ImportedModule,
236243830Sdim                       const FileEntry *File, SourceRange Range);
237218893Sdim
238218893Sdim    /// \brief Determine what kind of inclusion directive this is.
239218893Sdim    InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); }
240218893Sdim
241218893Sdim    /// \brief Retrieve the included file name as it was written in the source.
242226633Sdim    StringRef getFileName() const { return FileName; }
243218893Sdim
244218893Sdim    /// \brief Determine whether the included file name was written in quotes;
245218893Sdim    /// otherwise, it was written in angle brackets.
246218893Sdim    bool wasInQuotes() const { return InQuotes; }
247243830Sdim
248243830Sdim    /// \brief Determine whether the inclusion directive was automatically
249243830Sdim    /// turned into a module import.
250243830Sdim    bool importedModule() const { return ImportedModule; }
251218893Sdim
252218893Sdim    /// \brief Retrieve the file entry for the actual file that was included
253218893Sdim    /// by this directive.
254218893Sdim    const FileEntry *getFile() const { return File; }
255218893Sdim
256218893Sdim    // Implement isa/cast/dyncast/etc.
257218893Sdim    static bool classof(const PreprocessedEntity *PE) {
258218893Sdim      return PE->getKind() == InclusionDirectiveKind;
259218893Sdim    }
260218893Sdim  };
261205408Srdivacky
262205408Srdivacky  /// \brief An abstract class that should be subclassed by any external source
263205408Srdivacky  /// of preprocessing record entries.
264205408Srdivacky  class ExternalPreprocessingRecordSource {
265205408Srdivacky  public:
266205408Srdivacky    virtual ~ExternalPreprocessingRecordSource();
267205408Srdivacky
268226633Sdim    /// \brief Read a preallocated preprocessed entity from the external source.
269226633Sdim    ///
270226633Sdim    /// \returns null if an error occurred that prevented the preprocessed
271226633Sdim    /// entity from being loaded.
272226633Sdim    virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0;
273226633Sdim
274226633Sdim    /// \brief Returns a pair of [Begin, End) indices of preallocated
275243830Sdim    /// preprocessed entities that \p Range encompasses.
276226633Sdim    virtual std::pair<unsigned, unsigned>
277226633Sdim        findPreprocessedEntitiesInRange(SourceRange Range) = 0;
278234353Sdim
279234353Sdim    /// \brief Optionally returns true or false if the preallocated preprocessed
280243830Sdim    /// entity with index \p Index came from file \p FID.
281249423Sdim    virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index,
282249423Sdim                                                        FileID FID) {
283249423Sdim      return None;
284234353Sdim    }
285205408Srdivacky  };
286205408Srdivacky
287205408Srdivacky  /// \brief A record of the steps taken while preprocessing a source file,
288205408Srdivacky  /// including the various preprocessing directives processed, macros
289224145Sdim  /// expanded, etc.
290205408Srdivacky  class PreprocessingRecord : public PPCallbacks {
291226633Sdim    SourceManager &SourceMgr;
292223017Sdim
293205408Srdivacky    /// \brief Allocator used to store preprocessing objects.
294205408Srdivacky    llvm::BumpPtrAllocator BumpAlloc;
295205408Srdivacky
296205408Srdivacky    /// \brief The set of preprocessed entities in this record, in order they
297205408Srdivacky    /// were seen.
298205408Srdivacky    std::vector<PreprocessedEntity *> PreprocessedEntities;
299205408Srdivacky
300226633Sdim    /// \brief The set of preprocessed entities in this record that have been
301226633Sdim    /// loaded from external sources.
302226633Sdim    ///
303226633Sdim    /// The entries in this vector are loaded lazily from the external source,
304226633Sdim    /// and are referenced by the iterator using negative indices.
305226633Sdim    std::vector<PreprocessedEntity *> LoadedPreprocessedEntities;
306226633Sdim
307226633Sdim    /// \brief Global (loaded or local) ID for a preprocessed entity.
308226633Sdim    /// Negative values are used to indicate preprocessed entities
309226633Sdim    /// loaded from the external source while non-negative values are used to
310226633Sdim    /// indicate preprocessed entities introduced by the current preprocessor.
311243830Sdim    /// Value -1 corresponds to element 0 in the loaded entities vector,
312243830Sdim    /// value -2 corresponds to element 1 in the loaded entities vector, etc.
313243830Sdim    /// Value 0 is an invalid value, the index to local entities is 1-based,
314243830Sdim    /// value 1 corresponds to element 0 in the local entities vector,
315243830Sdim    /// value 2 corresponds to element 1 in the local entities vector, etc.
316243830Sdim    class PPEntityID {
317243830Sdim      int ID;
318243830Sdim      explicit PPEntityID(int ID) : ID(ID) {}
319243830Sdim      friend class PreprocessingRecord;
320243830Sdim    public:
321243830Sdim      PPEntityID() : ID(0) {}
322243830Sdim    };
323226633Sdim
324243830Sdim    static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) {
325243830Sdim      return isLoaded ? PPEntityID(-int(Index)-1) : PPEntityID(Index+1);
326226633Sdim    }
327226633Sdim
328205408Srdivacky    /// \brief Mapping from MacroInfo structures to their definitions.
329249423Sdim    llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions;
330205408Srdivacky
331205408Srdivacky    /// \brief External source of preprocessed entities.
332205408Srdivacky    ExternalPreprocessingRecordSource *ExternalSource;
333226633Sdim
334226633Sdim    /// \brief Retrieve the preprocessed entity at the given ID.
335226633Sdim    PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID);
336226633Sdim
337226633Sdim    /// \brief Retrieve the loaded preprocessed entity at the given index.
338226633Sdim    PreprocessedEntity *getLoadedPreprocessedEntity(unsigned Index);
339205408Srdivacky
340226633Sdim    /// \brief Determine the number of preprocessed entities that were
341226633Sdim    /// loaded (or can be loaded) from an external source.
342226633Sdim    unsigned getNumLoadedPreprocessedEntities() const {
343226633Sdim      return LoadedPreprocessedEntities.size();
344226633Sdim    }
345226633Sdim
346226633Sdim    /// \brief Returns a pair of [Begin, End) indices of local preprocessed
347243830Sdim    /// entities that \p Range encompasses.
348226633Sdim    std::pair<unsigned, unsigned>
349226633Sdim      findLocalPreprocessedEntitiesInRange(SourceRange Range) const;
350226633Sdim    unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const;
351226633Sdim    unsigned findEndLocalPreprocessedEntity(SourceLocation Loc) const;
352226633Sdim
353226633Sdim    /// \brief Allocate space for a new set of loaded preprocessed entities.
354226633Sdim    ///
355226633Sdim    /// \returns The index into the set of loaded preprocessed entities, which
356226633Sdim    /// corresponds to the first newly-allocated entity.
357226633Sdim    unsigned allocateLoadedEntities(unsigned NumEntities);
358226633Sdim
359226633Sdim    /// \brief Register a new macro definition.
360249423Sdim    void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinition *Def);
361205408Srdivacky
362205408Srdivacky  public:
363226633Sdim    /// \brief Construct a new preprocessing record.
364249423Sdim    explicit PreprocessingRecord(SourceManager &SM);
365205408Srdivacky
366205408Srdivacky    /// \brief Allocate memory in the preprocessing record.
367205408Srdivacky    void *Allocate(unsigned Size, unsigned Align = 8) {
368205408Srdivacky      return BumpAlloc.Allocate(Size, Align);
369205408Srdivacky    }
370205408Srdivacky
371205408Srdivacky    /// \brief Deallocate memory in the preprocessing record.
372205408Srdivacky    void Deallocate(void *Ptr) { }
373226633Sdim
374226633Sdim    size_t getTotalMemory() const;
375226633Sdim
376226633Sdim    SourceManager &getSourceManager() const { return SourceMgr; }
377226633Sdim
378205408Srdivacky    // Iteration over the preprocessed entities.
379226633Sdim    class iterator {
380226633Sdim      PreprocessingRecord *Self;
381226633Sdim
382226633Sdim      /// \brief Position within the preprocessed entity sequence.
383226633Sdim      ///
384226633Sdim      /// In a complete iteration, the Position field walks the range [-M, N),
385226633Sdim      /// where negative values are used to indicate preprocessed entities
386226633Sdim      /// loaded from the external source while non-negative values are used to
387226633Sdim      /// indicate preprocessed entities introduced by the current preprocessor.
388226633Sdim      /// However, to provide iteration in source order (for, e.g., chained
389226633Sdim      /// precompiled headers), dereferencing the iterator flips the negative
390226633Sdim      /// values (corresponding to loaded entities), so that position -M
391226633Sdim      /// corresponds to element 0 in the loaded entities vector, position -M+1
392226633Sdim      /// corresponds to element 1 in the loaded entities vector, etc. This
393226633Sdim      /// gives us a reasonably efficient, source-order walk.
394243830Sdim      int Position;
395226633Sdim
396226633Sdim    public:
397226633Sdim      typedef PreprocessedEntity *value_type;
398226633Sdim      typedef value_type&         reference;
399226633Sdim      typedef value_type*         pointer;
400226633Sdim      typedef std::random_access_iterator_tag iterator_category;
401226633Sdim      typedef int                 difference_type;
402226633Sdim
403226633Sdim      iterator() : Self(0), Position(0) { }
404226633Sdim
405243830Sdim      iterator(PreprocessingRecord *Self, int Position)
406226633Sdim        : Self(Self), Position(Position) { }
407226633Sdim
408226633Sdim      value_type operator*() const {
409243830Sdim        bool isLoaded = Position < 0;
410243830Sdim        unsigned Index = isLoaded ?
411243830Sdim            Self->LoadedPreprocessedEntities.size() + Position : Position;
412243830Sdim        PPEntityID ID = Self->getPPEntityID(Index, isLoaded);
413243830Sdim        return Self->getPreprocessedEntity(ID);
414226633Sdim      }
415226633Sdim
416226633Sdim      value_type operator[](difference_type D) {
417226633Sdim        return *(*this + D);
418226633Sdim      }
419226633Sdim
420226633Sdim      iterator &operator++() {
421226633Sdim        ++Position;
422226633Sdim        return *this;
423226633Sdim      }
424226633Sdim
425226633Sdim      iterator operator++(int) {
426226633Sdim        iterator Prev(*this);
427226633Sdim        ++Position;
428226633Sdim        return Prev;
429226633Sdim      }
430218893Sdim
431226633Sdim      iterator &operator--() {
432226633Sdim        --Position;
433226633Sdim        return *this;
434226633Sdim      }
435226633Sdim
436226633Sdim      iterator operator--(int) {
437226633Sdim        iterator Prev(*this);
438226633Sdim        --Position;
439226633Sdim        return Prev;
440226633Sdim      }
441226633Sdim
442226633Sdim      friend bool operator==(const iterator &X, const iterator &Y) {
443226633Sdim        return X.Position == Y.Position;
444226633Sdim      }
445226633Sdim
446226633Sdim      friend bool operator!=(const iterator &X, const iterator &Y) {
447226633Sdim        return X.Position != Y.Position;
448226633Sdim      }
449226633Sdim
450226633Sdim      friend bool operator<(const iterator &X, const iterator &Y) {
451226633Sdim        return X.Position < Y.Position;
452226633Sdim      }
453226633Sdim
454226633Sdim      friend bool operator>(const iterator &X, const iterator &Y) {
455226633Sdim        return X.Position > Y.Position;
456226633Sdim      }
457226633Sdim
458226633Sdim      friend bool operator<=(const iterator &X, const iterator &Y) {
459226633Sdim        return X.Position < Y.Position;
460226633Sdim      }
461226633Sdim
462226633Sdim      friend bool operator>=(const iterator &X, const iterator &Y) {
463226633Sdim        return X.Position > Y.Position;
464226633Sdim      }
465226633Sdim
466226633Sdim      friend iterator& operator+=(iterator &X, difference_type D) {
467226633Sdim        X.Position += D;
468226633Sdim        return X;
469226633Sdim      }
470226633Sdim
471226633Sdim      friend iterator& operator-=(iterator &X, difference_type D) {
472226633Sdim        X.Position -= D;
473226633Sdim        return X;
474226633Sdim      }
475226633Sdim
476226633Sdim      friend iterator operator+(iterator X, difference_type D) {
477226633Sdim        X.Position += D;
478226633Sdim        return X;
479226633Sdim      }
480226633Sdim
481226633Sdim      friend iterator operator+(difference_type D, iterator X) {
482226633Sdim        X.Position += D;
483226633Sdim        return X;
484226633Sdim      }
485226633Sdim
486226633Sdim      friend difference_type operator-(const iterator &X, const iterator &Y) {
487226633Sdim        return X.Position - Y.Position;
488226633Sdim      }
489226633Sdim
490226633Sdim      friend iterator operator-(iterator X, difference_type D) {
491226633Sdim        X.Position -= D;
492226633Sdim        return X;
493226633Sdim      }
494234353Sdim      friend class PreprocessingRecord;
495226633Sdim    };
496226633Sdim    friend class iterator;
497226633Sdim
498226633Sdim    /// \brief Begin iterator for all preprocessed entities.
499226633Sdim    iterator begin() {
500226633Sdim      return iterator(this, -(int)LoadedPreprocessedEntities.size());
501226633Sdim    }
502226633Sdim
503226633Sdim    /// \brief End iterator for all preprocessed entities.
504226633Sdim    iterator end() {
505226633Sdim      return iterator(this, PreprocessedEntities.size());
506226633Sdim    }
507226633Sdim
508226633Sdim    /// \brief Begin iterator for local, non-loaded, preprocessed entities.
509226633Sdim    iterator local_begin() {
510226633Sdim      return iterator(this, 0);
511226633Sdim    }
512226633Sdim
513226633Sdim    /// \brief End iterator for local, non-loaded, preprocessed entities.
514226633Sdim    iterator local_end() {
515226633Sdim      return iterator(this, PreprocessedEntities.size());
516226633Sdim    }
517226633Sdim
518243830Sdim    /// \brief begin/end iterator pair for the given range of loaded
519243830Sdim    /// preprocessed entities.
520243830Sdim    std::pair<iterator, iterator>
521243830Sdim    getIteratorsForLoadedRange(unsigned start, unsigned count) {
522243830Sdim      unsigned end = start + count;
523243830Sdim      assert(end <= LoadedPreprocessedEntities.size());
524243830Sdim      return std::make_pair(
525243830Sdim                   iterator(this, int(start)-LoadedPreprocessedEntities.size()),
526243830Sdim                   iterator(this, int(end)-LoadedPreprocessedEntities.size()));
527243830Sdim    }
528243830Sdim
529226633Sdim    /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
530243830Sdim    /// that source range \p R encompasses.
531234353Sdim    ///
532234353Sdim    /// \param R the range to look for preprocessed entities.
533234353Sdim    ///
534226633Sdim    std::pair<iterator, iterator> getPreprocessedEntitiesInRange(SourceRange R);
535226633Sdim
536243830Sdim    /// \brief Returns true if the preprocessed entity that \p PPEI iterator
537243830Sdim    /// points to is coming from the file \p FID.
538234353Sdim    ///
539234353Sdim    /// Can be used to avoid implicit deserializations of preallocated
540234353Sdim    /// preprocessed entities if we only care about entities of a specific file
541239462Sdim    /// and not from files \#included in the range given at
542234353Sdim    /// \see getPreprocessedEntitiesInRange.
543234353Sdim    bool isEntityInFileID(iterator PPEI, FileID FID);
544234353Sdim
545205408Srdivacky    /// \brief Add a new preprocessed entity to this record.
546234353Sdim    PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity);
547234353Sdim
548205408Srdivacky    /// \brief Set the external source for preprocessed entities.
549226633Sdim    void SetExternalSource(ExternalPreprocessingRecordSource &Source);
550218893Sdim
551218893Sdim    /// \brief Retrieve the external source for preprocessed entities.
552218893Sdim    ExternalPreprocessingRecordSource *getExternalSource() const {
553218893Sdim      return ExternalSource;
554218893Sdim    }
555205408Srdivacky
556205408Srdivacky    /// \brief Retrieve the macro definition that corresponds to the given
557205408Srdivacky    /// \c MacroInfo.
558205408Srdivacky    MacroDefinition *findMacroDefinition(const MacroInfo *MI);
559226633Sdim
560234353Sdim  private:
561249423Sdim    virtual void MacroExpands(const Token &Id, const MacroDirective *MD,
562251662Sdim                              SourceRange Range, const MacroArgs *Args);
563249423Sdim    virtual void MacroDefined(const Token &Id, const MacroDirective *MD);
564249423Sdim    virtual void MacroUndefined(const Token &Id, const MacroDirective *MD);
565218893Sdim    virtual void InclusionDirective(SourceLocation HashLoc,
566218893Sdim                                    const Token &IncludeTok,
567226633Sdim                                    StringRef FileName,
568218893Sdim                                    bool IsAngled,
569243830Sdim                                    CharSourceRange FilenameRange,
570218893Sdim                                    const FileEntry *File,
571226633Sdim                                    StringRef SearchPath,
572243830Sdim                                    StringRef RelativePath,
573243830Sdim                                    const Module *Imported);
574249423Sdim    virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
575249423Sdim                       const MacroDirective *MD);
576249423Sdim    virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
577249423Sdim                        const MacroDirective *MD);
578249423Sdim    /// \brief Hook called whenever the 'defined' operator is seen.
579249423Sdim    virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD);
580226633Sdim
581249423Sdim    void addMacroExpansion(const Token &Id, const MacroInfo *MI,
582249423Sdim                           SourceRange Range);
583249423Sdim
584234353Sdim    /// \brief Cached result of the last \see getPreprocessedEntitiesInRange
585234353Sdim    /// query.
586234353Sdim    struct {
587234353Sdim      SourceRange Range;
588243830Sdim      std::pair<int, int> Result;
589234353Sdim    } CachedRangeQuery;
590234353Sdim
591243830Sdim    std::pair<int, int> getPreprocessedEntitiesInRangeSlow(SourceRange R);
592234353Sdim
593226633Sdim    friend class ASTReader;
594226633Sdim    friend class ASTWriter;
595205408Srdivacky  };
596205408Srdivacky} // end namespace clang
597205408Srdivacky
598205408Srdivackyinline void* operator new(size_t bytes, clang::PreprocessingRecord& PR,
599205408Srdivacky                          unsigned alignment) throw() {
600205408Srdivacky  return PR.Allocate(bytes, alignment);
601205408Srdivacky}
602205408Srdivacky
603205408Srdivackyinline void operator delete(void* ptr, clang::PreprocessingRecord& PR,
604205408Srdivacky                            unsigned) throw() {
605205408Srdivacky  PR.Deallocate(ptr);
606205408Srdivacky}
607205408Srdivacky
608205408Srdivacky#endif // LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
609