1 //===--- PreprocessingRecord.cpp - Record of Preprocessing ------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements the PreprocessingRecord class, which maintains a record
11 //  of what occurred during preprocessing, and its helpers.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "clang/Lex/PreprocessingRecord.h"
15 #include "clang/Lex/MacroInfo.h"
16 #include "clang/Lex/Token.h"
17 
18 using namespace clang;
19 
20 ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
21 
22 void PreprocessingRecord::MaybeLoadPreallocatedEntities() const {
23   if (!ExternalSource || LoadedPreallocatedEntities)
24     return;
25 
26   LoadedPreallocatedEntities = true;
27   ExternalSource->ReadPreprocessedEntities();
28 }
29 
30 PreprocessingRecord::PreprocessingRecord()
31   : ExternalSource(0), NumPreallocatedEntities(0),
32     LoadedPreallocatedEntities(false)
33 {
34 }
35 
36 PreprocessingRecord::iterator
37 PreprocessingRecord::begin(bool OnlyLocalEntities) {
38   if (OnlyLocalEntities)
39     return PreprocessedEntities.begin() + NumPreallocatedEntities;
40 
41   MaybeLoadPreallocatedEntities();
42   return PreprocessedEntities.begin();
43 }
44 
45 PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) {
46   if (!OnlyLocalEntities)
47     MaybeLoadPreallocatedEntities();
48 
49   return PreprocessedEntities.end();
50 }
51 
52 PreprocessingRecord::const_iterator
53 PreprocessingRecord::begin(bool OnlyLocalEntities) const {
54   if (OnlyLocalEntities)
55     return PreprocessedEntities.begin() + NumPreallocatedEntities;
56 
57   MaybeLoadPreallocatedEntities();
58   return PreprocessedEntities.begin();
59 }
60 
61 PreprocessingRecord::const_iterator
62 PreprocessingRecord::end(bool OnlyLocalEntities) const {
63   if (!OnlyLocalEntities)
64     MaybeLoadPreallocatedEntities();
65 
66   return PreprocessedEntities.end();
67 }
68 
69 void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
70   PreprocessedEntities.push_back(Entity);
71 }
72 
73 void PreprocessingRecord::SetExternalSource(
74                                     ExternalPreprocessingRecordSource &Source,
75                                             unsigned NumPreallocatedEntities) {
76   assert(!ExternalSource &&
77          "Preprocessing record already has an external source");
78   ExternalSource = &Source;
79   this->NumPreallocatedEntities = NumPreallocatedEntities;
80   PreprocessedEntities.insert(PreprocessedEntities.begin(),
81                               NumPreallocatedEntities, 0);
82 }
83 
84 void PreprocessingRecord::SetPreallocatedEntity(unsigned Index,
85                                                 PreprocessedEntity *Entity) {
86   assert(Index < NumPreallocatedEntities &&"Out-of-bounds preallocated entity");
87   PreprocessedEntities[Index] = Entity;
88 }
89 
90 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
91                                                   MacroDefinition *MD) {
92   MacroDefinitions[Macro] = MD;
93 }
94 
95 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
96   llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
97     = MacroDefinitions.find(MI);
98   if (Pos == MacroDefinitions.end())
99     return 0;
100 
101   return Pos->second;
102 }
103 
104 void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) {
105   if (MacroDefinition *Def = findMacroDefinition(MI))
106     PreprocessedEntities.push_back(
107                        new (*this) MacroInstantiation(Id.getIdentifierInfo(),
108                                                       Id.getLocation(),
109                                                       Def));
110 }
111 
112 void PreprocessingRecord::MacroDefined(const IdentifierInfo *II,
113                                        const MacroInfo *MI) {
114   SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
115   MacroDefinition *Def
116     = new (*this) MacroDefinition(II, MI->getDefinitionLoc(), R);
117   MacroDefinitions[MI] = Def;
118   PreprocessedEntities.push_back(Def);
119 }
120 
121 void PreprocessingRecord::MacroUndefined(const IdentifierInfo *II,
122                                          const MacroInfo *MI) {
123   llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
124     = MacroDefinitions.find(MI);
125   if (Pos != MacroDefinitions.end())
126     MacroDefinitions.erase(Pos);
127 }
128 
129