Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 1 | //===- PreprocessingRecord.h - Record of Preprocessing ----------*- C++ -*-===// | 
        
| 2 | // | 
        ||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
        ||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | 
        ||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
        ||
| 6 | // | 
        ||
| 7 | //===----------------------------------------------------------------------===// | 
        ||
| 8 | // | 
        ||
| 9 | //  This file defines the PreprocessingRecord class, which maintains a record | 
        ||
| 10 | //  of what occurred during preprocessing. | 
        ||
| 11 | // | 
        ||
| 12 | //===----------------------------------------------------------------------===// | 
        ||
| 13 | |||
| 14 | #ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H | 
        ||
| 15 | #define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H | 
        ||
| 16 | |||
| 17 | #include "clang/Basic/IdentifierTable.h" | 
        ||
| 18 | #include "clang/Basic/LLVM.h" | 
        ||
| 19 | #include "clang/Basic/SourceLocation.h" | 
        ||
| 20 | #include "clang/Lex/PPCallbacks.h" | 
        ||
| 21 | #include "llvm/ADT/DenseMap.h" | 
        ||
| 22 | #include "llvm/ADT/PointerUnion.h" | 
        ||
| 23 | #include "llvm/ADT/StringRef.h" | 
        ||
| 24 | #include "llvm/ADT/iterator.h" | 
        ||
| 25 | #include "llvm/ADT/iterator_range.h" | 
        ||
| 26 | #include "llvm/Support/Allocator.h" | 
        ||
| 27 | #include "llvm/Support/Compiler.h" | 
        ||
| 28 | #include <cassert> | 
        ||
| 29 | #include <cstddef> | 
        ||
| 30 | #include <iterator> | 
        ||
| 31 | #include <optional> | 
        ||
| 32 | #include <utility> | 
        ||
| 33 | #include <vector> | 
        ||
| 34 | |||
| 35 | namespace clang {  | 
        ||
| 36 | |||
| 37 | class PreprocessingRecord;  | 
        ||
| 38 | |||
| 39 | } // namespace clang  | 
        ||
| 40 | |||
| 41 | /// Allocates memory within a Clang preprocessing record. | 
        ||
| 42 | void *operator new(size_t bytes, clang::PreprocessingRecord &PR,  | 
        ||
| 43 | unsigned alignment = 8) noexcept;  | 
        ||
| 44 | |||
| 45 | /// Frees memory allocated in a Clang preprocessing record. | 
        ||
| 46 | void operator delete(void *ptr, clang::PreprocessingRecord &PR,  | 
        ||
| 47 | unsigned) noexcept;  | 
        ||
| 48 | |||
| 49 | namespace clang {  | 
        ||
| 50 | |||
| 51 | class IdentifierInfo;  | 
        ||
| 52 | class MacroInfo;  | 
        ||
| 53 | class SourceManager;  | 
        ||
| 54 | class Token;  | 
        ||
| 55 | |||
| 56 |   /// Base class that describes a preprocessed entity, which may be a | 
        ||
| 57 |   /// preprocessor directive or macro expansion. | 
        ||
| 58 | class PreprocessedEntity {  | 
        ||
| 59 | public:  | 
        ||
| 60 |     /// The kind of preprocessed entity an object describes. | 
        ||
| 61 | enum EntityKind {  | 
        ||
| 62 |       /// Indicates a problem trying to load the preprocessed entity. | 
        ||
| 63 | InvalidKind,  | 
        ||
| 64 | |||
| 65 |       /// A macro expansion. | 
        ||
| 66 | MacroExpansionKind,  | 
        ||
| 67 | |||
| 68 |       /// \defgroup Preprocessing directives | 
        ||
| 69 |       /// @{ | 
        ||
| 70 | |||
| 71 |       /// A macro definition. | 
        ||
| 72 | MacroDefinitionKind,  | 
        ||
| 73 | |||
| 74 |       /// An inclusion directive, such as \c \#include, \c | 
        ||
| 75 |       /// \#import, or \c \#include_next. | 
        ||
| 76 | InclusionDirectiveKind,  | 
        ||
| 77 | |||
| 78 |       /// @} | 
        ||
| 79 | |||
| 80 |       FirstPreprocessingDirective = MacroDefinitionKind, | 
        ||
| 81 |       LastPreprocessingDirective = InclusionDirectiveKind | 
        ||
| 82 | };  | 
        ||
| 83 | |||
| 84 | private:  | 
        ||
| 85 |     /// The kind of preprocessed entity that this object describes. | 
        ||
| 86 |     EntityKind Kind; | 
        ||
| 87 | |||
| 88 |     /// The source range that covers this preprocessed entity. | 
        ||
| 89 |     SourceRange Range; | 
        ||
| 90 | |||
| 91 | protected:  | 
        ||
| 92 | friend class PreprocessingRecord;  | 
        ||
| 93 | |||
| 94 | PreprocessedEntity(EntityKind Kind, SourceRange Range)  | 
        ||
| 95 | : Kind(Kind), Range(Range) {}  | 
        ||
| 96 | |||
| 97 | public:  | 
        ||
| 98 |     /// Retrieve the kind of preprocessed entity stored in this object. | 
        ||
| 99 | EntityKind getKind() const { return Kind; }  | 
        ||
| 100 | |||
| 101 |     /// Retrieve the source range that covers this entire preprocessed | 
        ||
| 102 |     /// entity. | 
        ||
| 103 | SourceRange getSourceRange() const LLVM_READONLY { return Range; }  | 
        ||
| 104 | |||
| 105 |     /// Returns true if there was a problem loading the preprocessed | 
        ||
| 106 |     /// entity. | 
        ||
| 107 | bool isInvalid() const { return Kind == InvalidKind; }  | 
        ||
| 108 | |||
| 109 |     // Only allow allocation of preprocessed entities using the allocator | 
        ||
| 110 |     // in PreprocessingRecord or by doing a placement new. | 
        ||
| 111 | void *operator new(size_t bytes, PreprocessingRecord &PR,  | 
        ||
| 112 | unsigned alignment = 8) noexcept {  | 
        ||
| 113 | return ::operator new(bytes, PR, alignment);  | 
        ||
| 114 |     } | 
        ||
| 115 | |||
| 116 | void *operator new(size_t bytes, void *mem) noexcept { return mem; }  | 
        ||
| 117 | |||
| 118 | void operator delete(void *ptr, PreprocessingRecord &PR,  | 
        ||
| 119 | unsigned alignment) noexcept {  | 
        ||
| 120 | return ::operator delete(ptr, PR, alignment);  | 
        ||
| 121 |     } | 
        ||
| 122 | |||
| 123 | void operator delete(void *, std::size_t) noexcept {}  | 
        ||
| 124 | void operator delete(void *, void *) noexcept {}  | 
        ||
| 125 | |||
| 126 | private:  | 
        ||
| 127 |     // Make vanilla 'new' and 'delete' illegal for preprocessed entities. | 
        ||
| 128 | void *operator new(size_t bytes) noexcept;  | 
        ||
| 129 | void operator delete(void *data) noexcept;  | 
        ||
| 130 | };  | 
        ||
| 131 | |||
| 132 |   /// Records the presence of a preprocessor directive. | 
        ||
| 133 | class PreprocessingDirective : public PreprocessedEntity {  | 
        ||
| 134 | public:  | 
        ||
| 135 | PreprocessingDirective(EntityKind Kind, SourceRange Range)  | 
        ||
| 136 | : PreprocessedEntity(Kind, Range) {}  | 
        ||
| 137 | |||
| 138 |     // Implement isa/cast/dyncast/etc. | 
        ||
| 139 | static bool classof(const PreprocessedEntity *PD) {  | 
        ||
| 140 | return PD->getKind() >= FirstPreprocessingDirective &&  | 
        ||
| 141 | PD->getKind() <= LastPreprocessingDirective;  | 
        ||
| 142 |     } | 
        ||
| 143 | };  | 
        ||
| 144 | |||
| 145 |   /// Record the location of a macro definition. | 
        ||
| 146 | class MacroDefinitionRecord : public PreprocessingDirective {  | 
        ||
| 147 |     /// The name of the macro being defined. | 
        ||
| 148 | const IdentifierInfo *Name;  | 
        ||
| 149 | |||
| 150 | public:  | 
        ||
| 151 | explicit MacroDefinitionRecord(const IdentifierInfo *Name,  | 
        ||
| 152 |                                    SourceRange Range) | 
        ||
| 153 | : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name) {}  | 
        ||
| 154 | |||
| 155 |     /// Retrieve the name of the macro being defined. | 
        ||
| 156 | const IdentifierInfo *getName() const { return Name; }  | 
        ||
| 157 | |||
| 158 |     /// Retrieve the location of the macro name in the definition. | 
        ||
| 159 | SourceLocation getLocation() const { return getSourceRange().getBegin(); }  | 
        ||
| 160 | |||
| 161 |     // Implement isa/cast/dyncast/etc. | 
        ||
| 162 | static bool classof(const PreprocessedEntity *PE) {  | 
        ||
| 163 | return PE->getKind() == MacroDefinitionKind;  | 
        ||
| 164 |     } | 
        ||
| 165 | };  | 
        ||
| 166 | |||
| 167 |   /// Records the location of a macro expansion. | 
        ||
| 168 | class MacroExpansion : public PreprocessedEntity {  | 
        ||
| 169 |     /// The definition of this macro or the name of the macro if it is | 
        ||
| 170 |     /// a builtin macro. | 
        ||
| 171 | llvm::PointerUnion<IdentifierInfo *, MacroDefinitionRecord *> NameOrDef;  | 
        ||
| 172 | |||
| 173 | public:  | 
        ||
| 174 | MacroExpansion(IdentifierInfo *BuiltinName, SourceRange Range)  | 
        ||
| 175 | : PreprocessedEntity(MacroExpansionKind, Range),  | 
        ||
| 176 | NameOrDef(BuiltinName) {}  | 
        ||
| 177 | |||
| 178 | MacroExpansion(MacroDefinitionRecord *Definition, SourceRange Range)  | 
        ||
| 179 | : PreprocessedEntity(MacroExpansionKind, Range), NameOrDef(Definition) {  | 
        ||
| 180 |     } | 
        ||
| 181 | |||
| 182 |     /// True if it is a builtin macro. | 
        ||
| 183 | bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); }  | 
        ||
| 184 | |||
| 185 |     /// The name of the macro being expanded. | 
        ||
| 186 | const IdentifierInfo *getName() const {  | 
        ||
| 187 | if (MacroDefinitionRecord *Def = getDefinition())  | 
        ||
| 188 | return Def->getName();  | 
        ||
| 189 | return NameOrDef.get<IdentifierInfo *>();  | 
        ||
| 190 |     } | 
        ||
| 191 | |||
| 192 |     /// The definition of the macro being expanded. May return null if | 
        ||
| 193 |     /// this is a builtin macro. | 
        ||
| 194 | MacroDefinitionRecord *getDefinition() const {  | 
        ||
| 195 | return NameOrDef.dyn_cast<MacroDefinitionRecord *>();  | 
        ||
| 196 |     } | 
        ||
| 197 | |||
| 198 |     // Implement isa/cast/dyncast/etc. | 
        ||
| 199 | static bool classof(const PreprocessedEntity *PE) {  | 
        ||
| 200 | return PE->getKind() == MacroExpansionKind;  | 
        ||
| 201 |     } | 
        ||
| 202 | };  | 
        ||
| 203 | |||
| 204 |   /// Record the location of an inclusion directive, such as an | 
        ||
| 205 |   /// \c \#include or \c \#import statement. | 
        ||
| 206 | class InclusionDirective : public PreprocessingDirective {  | 
        ||
| 207 | public:  | 
        ||
| 208 |     /// The kind of inclusion directives known to the | 
        ||
| 209 |     /// preprocessor. | 
        ||
| 210 | enum InclusionKind {  | 
        ||
| 211 |       /// An \c \#include directive. | 
        ||
| 212 | Include,  | 
        ||
| 213 | |||
| 214 |       /// An Objective-C \c \#import directive. | 
        ||
| 215 | Import,  | 
        ||
| 216 | |||
| 217 |       /// A GNU \c \#include_next directive. | 
        ||
| 218 | IncludeNext,  | 
        ||
| 219 | |||
| 220 |       /// A Clang \c \#__include_macros directive. | 
        ||
| 221 | IncludeMacros  | 
        ||
| 222 | };  | 
        ||
| 223 | |||
| 224 | private:  | 
        ||
| 225 |     /// The name of the file that was included, as written in | 
        ||
| 226 |     /// the source. | 
        ||
| 227 |     StringRef FileName; | 
        ||
| 228 | |||
| 229 |     /// Whether the file name was in quotation marks; otherwise, it was | 
        ||
| 230 |     /// in angle brackets. | 
        ||
| 231 | unsigned InQuotes : 1;  | 
        ||
| 232 | |||
| 233 |     /// The kind of inclusion directive we have. | 
        ||
| 234 |     /// | 
        ||
| 235 |     /// This is a value of type InclusionKind. | 
        ||
| 236 | unsigned Kind : 2;  | 
        ||
| 237 | |||
| 238 |     /// Whether the inclusion directive was automatically turned into | 
        ||
| 239 |     /// a module import. | 
        ||
| 240 | unsigned ImportedModule : 1;  | 
        ||
| 241 | |||
| 242 |     /// The file that was included. | 
        ||
| 243 |     OptionalFileEntryRef File; | 
        ||
| 244 | |||
| 245 | public:  | 
        ||
| 246 | InclusionDirective(PreprocessingRecord &PPRec, InclusionKind Kind,  | 
        ||
| 247 | StringRef FileName, bool InQuotes, bool ImportedModule,  | 
        ||
| 248 | OptionalFileEntryRef File, SourceRange Range);  | 
        ||
| 249 | |||
| 250 |     /// Determine what kind of inclusion directive this is. | 
        ||
| 251 | InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); }  | 
        ||
| 252 | |||
| 253 |     /// Retrieve the included file name as it was written in the source. | 
        ||
| 254 | StringRef getFileName() const { return FileName; }  | 
        ||
| 255 | |||
| 256 |     /// Determine whether the included file name was written in quotes; | 
        ||
| 257 |     /// otherwise, it was written in angle brackets. | 
        ||
| 258 | bool wasInQuotes() const { return InQuotes; }  | 
        ||
| 259 | |||
| 260 |     /// Determine whether the inclusion directive was automatically | 
        ||
| 261 |     /// turned into a module import. | 
        ||
| 262 | bool importedModule() const { return ImportedModule; }  | 
        ||
| 263 | |||
| 264 |     /// Retrieve the file entry for the actual file that was included | 
        ||
| 265 |     /// by this directive. | 
        ||
| 266 | OptionalFileEntryRef getFile() const { return File; }  | 
        ||
| 267 | |||
| 268 |     // Implement isa/cast/dyncast/etc. | 
        ||
| 269 | static bool classof(const PreprocessedEntity *PE) {  | 
        ||
| 270 | return PE->getKind() == InclusionDirectiveKind;  | 
        ||
| 271 |     } | 
        ||
| 272 | };  | 
        ||
| 273 | |||
| 274 |   /// An abstract class that should be subclassed by any external source | 
        ||
| 275 |   /// of preprocessing record entries. | 
        ||
| 276 | class ExternalPreprocessingRecordSource {  | 
        ||
| 277 | public:  | 
        ||
| 278 | virtual ~ExternalPreprocessingRecordSource();  | 
        ||
| 279 | |||
| 280 |     /// Read a preallocated preprocessed entity from the external source. | 
        ||
| 281 |     /// | 
        ||
| 282 |     /// \returns null if an error occurred that prevented the preprocessed | 
        ||
| 283 |     /// entity from being loaded. | 
        ||
| 284 | virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0;  | 
        ||
| 285 | |||
| 286 |     /// Returns a pair of [Begin, End) indices of preallocated | 
        ||
| 287 |     /// preprocessed entities that \p Range encompasses. | 
        ||
| 288 | virtual std::pair<unsigned, unsigned>  | 
        ||
| 289 | findPreprocessedEntitiesInRange(SourceRange Range) = 0;  | 
        ||
| 290 | |||
| 291 |     /// Optionally returns true or false if the preallocated preprocessed | 
        ||
| 292 |     /// entity with index \p Index came from file \p FID. | 
        ||
| 293 | virtual std::optional<bool> isPreprocessedEntityInFileID(unsigned Index,  | 
        ||
| 294 | FileID FID) {  | 
        ||
| 295 | return std::nullopt;  | 
        ||
| 296 |     } | 
        ||
| 297 | |||
| 298 |     /// Read a preallocated skipped range from the external source. | 
        ||
| 299 | virtual SourceRange ReadSkippedRange(unsigned Index) = 0;  | 
        ||
| 300 | };  | 
        ||
| 301 | |||
| 302 |   /// A record of the steps taken while preprocessing a source file, | 
        ||
| 303 |   /// including the various preprocessing directives processed, macros | 
        ||
| 304 |   /// expanded, etc. | 
        ||
| 305 | class PreprocessingRecord : public PPCallbacks {  | 
        ||
| 306 | SourceManager &SourceMgr;  | 
        ||
| 307 | |||
| 308 |     /// Allocator used to store preprocessing objects. | 
        ||
| 309 | llvm::BumpPtrAllocator BumpAlloc;  | 
        ||
| 310 | |||
| 311 |     /// The set of preprocessed entities in this record, in order they | 
        ||
| 312 |     /// were seen. | 
        ||
| 313 | std::vector<PreprocessedEntity *> PreprocessedEntities;  | 
        ||
| 314 | |||
| 315 |     /// The set of preprocessed entities in this record that have been | 
        ||
| 316 |     /// loaded from external sources. | 
        ||
| 317 |     /// | 
        ||
| 318 |     /// The entries in this vector are loaded lazily from the external source, | 
        ||
| 319 |     /// and are referenced by the iterator using negative indices. | 
        ||
| 320 | std::vector<PreprocessedEntity *> LoadedPreprocessedEntities;  | 
        ||
| 321 | |||
| 322 |     /// The set of ranges that were skipped by the preprocessor, | 
        ||
| 323 | std::vector<SourceRange> SkippedRanges;  | 
        ||
| 324 | |||
| 325 | bool SkippedRangesAllLoaded = true;  | 
        ||
| 326 | |||
| 327 |     /// Global (loaded or local) ID for a preprocessed entity. | 
        ||
| 328 |     /// Negative values are used to indicate preprocessed entities | 
        ||
| 329 |     /// loaded from the external source while non-negative values are used to | 
        ||
| 330 |     /// indicate preprocessed entities introduced by the current preprocessor. | 
        ||
| 331 |     /// Value -1 corresponds to element 0 in the loaded entities vector, | 
        ||
| 332 |     /// value -2 corresponds to element 1 in the loaded entities vector, etc. | 
        ||
| 333 |     /// Value 0 is an invalid value, the index to local entities is 1-based, | 
        ||
| 334 |     /// value 1 corresponds to element 0 in the local entities vector, | 
        ||
| 335 |     /// value 2 corresponds to element 1 in the local entities vector, etc. | 
        ||
| 336 | class PPEntityID {  | 
        ||
| 337 | friend class PreprocessingRecord;  | 
        ||
| 338 | |||
| 339 | int ID = 0;  | 
        ||
| 340 | |||
| 341 | explicit PPEntityID(int ID) : ID(ID) {}  | 
        ||
| 342 | |||
| 343 | public:  | 
        ||
| 344 | PPEntityID() = default;  | 
        ||
| 345 | };  | 
        ||
| 346 | |||
| 347 | static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) {  | 
        ||
| 348 | return isLoaded ? PPEntityID(-int(Index)-1) : PPEntityID(Index+1);  | 
        ||
| 349 |     } | 
        ||
| 350 | |||
| 351 |     /// Mapping from MacroInfo structures to their definitions. | 
        ||
| 352 | llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *> MacroDefinitions;  | 
        ||
| 353 | |||
| 354 |     /// External source of preprocessed entities. | 
        ||
| 355 | ExternalPreprocessingRecordSource *ExternalSource = nullptr;  | 
        ||
| 356 | |||
| 357 |     /// Retrieve the preprocessed entity at the given ID. | 
        ||
| 358 | PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID);  | 
        ||
| 359 | |||
| 360 |     /// Retrieve the loaded preprocessed entity at the given index. | 
        ||
| 361 | PreprocessedEntity *getLoadedPreprocessedEntity(unsigned Index);  | 
        ||
| 362 | |||
| 363 |     /// Determine the number of preprocessed entities that were | 
        ||
| 364 |     /// loaded (or can be loaded) from an external source. | 
        ||
| 365 | unsigned getNumLoadedPreprocessedEntities() const {  | 
        ||
| 366 | return LoadedPreprocessedEntities.size();  | 
        ||
| 367 |     } | 
        ||
| 368 | |||
| 369 |     /// Returns a pair of [Begin, End) indices of local preprocessed | 
        ||
| 370 |     /// entities that \p Range encompasses. | 
        ||
| 371 | std::pair<unsigned, unsigned>  | 
        ||
| 372 | findLocalPreprocessedEntitiesInRange(SourceRange Range) const;  | 
        ||
| 373 | unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const;  | 
        ||
| 374 | unsigned findEndLocalPreprocessedEntity(SourceLocation Loc) const;  | 
        ||
| 375 | |||
| 376 |     /// Allocate space for a new set of loaded preprocessed entities. | 
        ||
| 377 |     /// | 
        ||
| 378 |     /// \returns The index into the set of loaded preprocessed entities, which | 
        ||
| 379 |     /// corresponds to the first newly-allocated entity. | 
        ||
| 380 | unsigned allocateLoadedEntities(unsigned NumEntities);  | 
        ||
| 381 | |||
| 382 |     /// Allocate space for a new set of loaded preprocessed skipped | 
        ||
| 383 |     /// ranges. | 
        ||
| 384 |     /// | 
        ||
| 385 |     /// \returns The index into the set of loaded preprocessed ranges, which | 
        ||
| 386 |     /// corresponds to the first newly-allocated range. | 
        ||
| 387 | unsigned allocateSkippedRanges(unsigned NumRanges);  | 
        ||
| 388 | |||
| 389 |     /// Ensures that all external skipped ranges have been loaded. | 
        ||
| 390 | void ensureSkippedRangesLoaded();  | 
        ||
| 391 | |||
| 392 |     /// Register a new macro definition. | 
        ||
| 393 | void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinitionRecord *Def);  | 
        ||
| 394 | |||
| 395 | public:  | 
        ||
| 396 |     /// Construct a new preprocessing record. | 
        ||
| 397 | explicit PreprocessingRecord(SourceManager &SM);  | 
        ||
| 398 | |||
| 399 |     /// Allocate memory in the preprocessing record. | 
        ||
| 400 | void *Allocate(unsigned Size, unsigned Align = 8) {  | 
        ||
| 401 | return BumpAlloc.Allocate(Size, Align);  | 
        ||
| 402 |     } | 
        ||
| 403 | |||
| 404 |     /// Deallocate memory in the preprocessing record. | 
        ||
| 405 | void Deallocate(void *Ptr) {}  | 
        ||
| 406 | |||
| 407 | size_t getTotalMemory() const;  | 
        ||
| 408 | |||
| 409 | SourceManager &getSourceManager() const { return SourceMgr; }  | 
        ||
| 410 | |||
| 411 |     /// Iteration over the preprocessed entities. | 
        ||
| 412 |     /// | 
        ||
| 413 |     /// In a complete iteration, the iterator walks the range [-M, N), | 
        ||
| 414 |     /// where negative values are used to indicate preprocessed entities | 
        ||
| 415 |     /// loaded from the external source while non-negative values are used to | 
        ||
| 416 |     /// indicate preprocessed entities introduced by the current preprocessor. | 
        ||
| 417 |     /// However, to provide iteration in source order (for, e.g., chained | 
        ||
| 418 |     /// precompiled headers), dereferencing the iterator flips the negative | 
        ||
| 419 |     /// values (corresponding to loaded entities), so that position -M | 
        ||
| 420 |     /// corresponds to element 0 in the loaded entities vector, position -M+1 | 
        ||
| 421 |     /// corresponds to element 1 in the loaded entities vector, etc. This | 
        ||
| 422 |     /// gives us a reasonably efficient, source-order walk. | 
        ||
| 423 |     /// | 
        ||
| 424 |     /// We define this as a wrapping iterator around an int. The | 
        ||
| 425 |     /// iterator_adaptor_base class forwards the iterator methods to basic | 
        ||
| 426 |     /// integer arithmetic. | 
        ||
| 427 | class iterator : public llvm::iterator_adaptor_base<  | 
        ||
| 428 | iterator, int, std::random_access_iterator_tag,  | 
        ||
| 429 | PreprocessedEntity *, int, PreprocessedEntity *,  | 
        ||
| 430 | PreprocessedEntity *> {  | 
        ||
| 431 | friend class PreprocessingRecord;  | 
        ||
| 432 | |||
| 433 | PreprocessingRecord *Self;  | 
        ||
| 434 | |||
| 435 | iterator(PreprocessingRecord *Self, int Position)  | 
        ||
| 436 | : iterator::iterator_adaptor_base(Position), Self(Self) {}  | 
        ||
| 437 | |||
| 438 | public:  | 
        ||
| 439 | iterator() : iterator(nullptr, 0) {}  | 
        ||
| 440 | |||
| 441 | PreprocessedEntity *operator*() const {  | 
        ||
| 442 | bool isLoaded = this->I < 0;  | 
        ||
| 443 | unsigned Index = isLoaded ?  | 
        ||
| 444 | Self->LoadedPreprocessedEntities.size() + this->I : this->I;  | 
        ||
| 445 | PPEntityID ID = Self->getPPEntityID(Index, isLoaded);  | 
        ||
| 446 | return Self->getPreprocessedEntity(ID);  | 
        ||
| 447 |       } | 
        ||
| 448 | PreprocessedEntity *operator->() const { return **this; }  | 
        ||
| 449 | };  | 
        ||
| 450 | |||
| 451 |     /// Begin iterator for all preprocessed entities. | 
        ||
| 452 | iterator begin() {  | 
        ||
| 453 | return iterator(this, -(int)LoadedPreprocessedEntities.size());  | 
        ||
| 454 |     } | 
        ||
| 455 | |||
| 456 |     /// End iterator for all preprocessed entities. | 
        ||
| 457 | iterator end() {  | 
        ||
| 458 | return iterator(this, PreprocessedEntities.size());  | 
        ||
| 459 |     } | 
        ||
| 460 | |||
| 461 |     /// Begin iterator for local, non-loaded, preprocessed entities. | 
        ||
| 462 | iterator local_begin() {  | 
        ||
| 463 | return iterator(this, 0);  | 
        ||
| 464 |     } | 
        ||
| 465 | |||
| 466 |     /// End iterator for local, non-loaded, preprocessed entities. | 
        ||
| 467 | iterator local_end() {  | 
        ||
| 468 | return iterator(this, PreprocessedEntities.size());  | 
        ||
| 469 |     } | 
        ||
| 470 | |||
| 471 |     /// iterator range for the given range of loaded | 
        ||
| 472 |     /// preprocessed entities. | 
        ||
| 473 | llvm::iterator_range<iterator> getIteratorsForLoadedRange(unsigned start,  | 
        ||
| 474 | unsigned count) {  | 
        ||
| 475 | unsigned end = start + count;  | 
        ||
| 476 | assert(end <= LoadedPreprocessedEntities.size());  | 
        ||
| 477 | return llvm::make_range(  | 
        ||
| 478 | iterator(this, int(start) - LoadedPreprocessedEntities.size()),  | 
        ||
| 479 | iterator(this, int(end) - LoadedPreprocessedEntities.size()));  | 
        ||
| 480 |     } | 
        ||
| 481 | |||
| 482 |     /// Returns a range of preprocessed entities that source range \p R | 
        ||
| 483 |     /// encompasses. | 
        ||
| 484 |     /// | 
        ||
| 485 |     /// \param R the range to look for preprocessed entities. | 
        ||
| 486 | llvm::iterator_range<iterator>  | 
        ||
| 487 | getPreprocessedEntitiesInRange(SourceRange R);  | 
        ||
| 488 | |||
| 489 |     /// Returns true if the preprocessed entity that \p PPEI iterator | 
        ||
| 490 |     /// points to is coming from the file \p FID. | 
        ||
| 491 |     /// | 
        ||
| 492 |     /// Can be used to avoid implicit deserializations of preallocated | 
        ||
| 493 |     /// preprocessed entities if we only care about entities of a specific file | 
        ||
| 494 |     /// and not from files \#included in the range given at | 
        ||
| 495 |     /// \see getPreprocessedEntitiesInRange. | 
        ||
| 496 | bool isEntityInFileID(iterator PPEI, FileID FID);  | 
        ||
| 497 | |||
| 498 |     /// Add a new preprocessed entity to this record. | 
        ||
| 499 | PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity);  | 
        ||
| 500 | |||
| 501 |     /// Set the external source for preprocessed entities. | 
        ||
| 502 | void SetExternalSource(ExternalPreprocessingRecordSource &Source);  | 
        ||
| 503 | |||
| 504 |     /// Retrieve the external source for preprocessed entities. | 
        ||
| 505 | ExternalPreprocessingRecordSource *getExternalSource() const {  | 
        ||
| 506 | return ExternalSource;  | 
        ||
| 507 |     } | 
        ||
| 508 | |||
| 509 |     /// Retrieve the macro definition that corresponds to the given | 
        ||
| 510 |     /// \c MacroInfo. | 
        ||
| 511 | MacroDefinitionRecord *findMacroDefinition(const MacroInfo *MI);  | 
        ||
| 512 | |||
| 513 |     /// Retrieve all ranges that got skipped while preprocessing. | 
        ||
| 514 | const std::vector<SourceRange> &getSkippedRanges() {  | 
        ||
| 515 | ensureSkippedRangesLoaded();  | 
        ||
| 516 | return SkippedRanges;  | 
        ||
| 517 |     } | 
        ||
| 518 | |||
| 519 | private:  | 
        ||
| 520 | friend class ASTReader;  | 
        ||
| 521 | friend class ASTWriter;  | 
        ||
| 522 | |||
| 523 | void MacroExpands(const Token &Id, const MacroDefinition &MD,  | 
        ||
| 524 | SourceRange Range, const MacroArgs *Args) override;  | 
        ||
| 525 | void MacroDefined(const Token &Id, const MacroDirective *MD) override;  | 
        ||
| 526 | void MacroUndefined(const Token &Id, const MacroDefinition &MD,  | 
        ||
| 527 | const MacroDirective *Undef) override;  | 
        ||
| 528 | void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,  | 
        ||
| 529 |                             StringRef FileName, bool IsAngled, | 
        ||
| 530 | CharSourceRange FilenameRange,  | 
        ||
| 531 | OptionalFileEntryRef File, StringRef SearchPath,  | 
        ||
| 532 | StringRef RelativePath, const Module *Imported,  | 
        ||
| 533 | SrcMgr::CharacteristicKind FileType) override;  | 
        ||
| 534 | void Ifdef(SourceLocation Loc, const Token &MacroNameTok,  | 
        ||
| 535 | const MacroDefinition &MD) override;  | 
        ||
| 536 | void Ifndef(SourceLocation Loc, const Token &MacroNameTok,  | 
        ||
| 537 | const MacroDefinition &MD) override;  | 
        ||
| 538 | |||
| 539 | using PPCallbacks::Elifdef;  | 
        ||
| 540 | using PPCallbacks::Elifndef;  | 
        ||
| 541 | void Elifdef(SourceLocation Loc, const Token &MacroNameTok,  | 
        ||
| 542 | const MacroDefinition &MD) override;  | 
        ||
| 543 | void Elifndef(SourceLocation Loc, const Token &MacroNameTok,  | 
        ||
| 544 | const MacroDefinition &MD) override;  | 
        ||
| 545 | |||
| 546 |     /// Hook called whenever the 'defined' operator is seen. | 
        ||
| 547 | void Defined(const Token &MacroNameTok, const MacroDefinition &MD,  | 
        ||
| 548 | SourceRange Range) override;  | 
        ||
| 549 | |||
| 550 | void SourceRangeSkipped(SourceRange Range,  | 
        ||
| 551 | SourceLocation EndifLoc) override;  | 
        ||
| 552 | |||
| 553 | void addMacroExpansion(const Token &Id, const MacroInfo *MI,  | 
        ||
| 554 | SourceRange Range);  | 
        ||
| 555 | |||
| 556 |     /// Cached result of the last \see getPreprocessedEntitiesInRange | 
        ||
| 557 |     /// query. | 
        ||
| 558 | struct {  | 
        ||
| 559 |       SourceRange Range; | 
        ||
| 560 | std::pair<int, int> Result;  | 
        ||
| 561 | } CachedRangeQuery;  | 
        ||
| 562 | |||
| 563 | std::pair<int, int> getPreprocessedEntitiesInRangeSlow(SourceRange R);  | 
        ||
| 564 | };  | 
        ||
| 565 | |||
| 566 | } // namespace clang  | 
        ||
| 567 | |||
| 568 | inline void *operator new(size_t bytes, clang::PreprocessingRecord &PR,  | 
        ||
| 569 | unsigned alignment) noexcept {  | 
        ||
| 570 | return PR.Allocate(bytes, alignment);  | 
        ||
| 571 | } | 
        ||
| 572 | |||
| 573 | inline void operator delete(void *ptr, clang::PreprocessingRecord &PR,  | 
        ||
| 574 | unsigned) noexcept {  | 
        ||
| 575 | PR.Deallocate(ptr);  | 
        ||
| 576 | } | 
        ||
| 577 | |||
| 578 | #endif // LLVM_CLANG_LEX_PREPROCESSINGRECORD_H |