]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / clang / lib / Lex / PreprocessingRecord.cpp
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 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/Capacity.h"
19
20 using namespace clang;
21
22 ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
23
24
25 InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
26                                        InclusionKind Kind, 
27                                        StringRef FileName, 
28                                        bool InQuotes, const FileEntry *File, 
29                                        SourceRange Range)
30   : PreprocessingDirective(InclusionDirectiveKind, Range), 
31     InQuotes(InQuotes), Kind(Kind), File(File) 
32
33   char *Memory 
34     = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>());
35   memcpy(Memory, FileName.data(), FileName.size());
36   Memory[FileName.size()] = 0;
37   this->FileName = StringRef(Memory, FileName.size());
38 }
39
40 PreprocessingRecord::PreprocessingRecord(SourceManager &SM,
41                                          bool IncludeNestedMacroExpansions)
42   : SourceMgr(SM), IncludeNestedMacroExpansions(IncludeNestedMacroExpansions),
43     ExternalSource(0)
44 {
45 }
46
47 /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
48 /// that source range \arg R encompasses.
49 std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
50 PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
51   if (Range.isInvalid())
52     return std::make_pair(iterator(this, 0), iterator(this, 0));
53   assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
54
55   std::pair<unsigned, unsigned>
56     Local = findLocalPreprocessedEntitiesInRange(Range);
57
58   // Check if range spans local entities.
59   if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
60     return std::make_pair(iterator(this, Local.first),
61                           iterator(this, Local.second));
62
63   std::pair<unsigned, unsigned>
64     Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
65
66   // Check if range spans local entities.
67   if (Loaded.first == Loaded.second)
68     return std::make_pair(iterator(this, Local.first),
69                           iterator(this, Local.second));
70
71   unsigned TotalLoaded = LoadedPreprocessedEntities.size();
72
73   // Check if range spans loaded entities.
74   if (Local.first == Local.second)
75     return std::make_pair(iterator(this, int(Loaded.first)-TotalLoaded),
76                           iterator(this, int(Loaded.second)-TotalLoaded));
77
78   // Range spands loaded and local entities.
79   return std::make_pair(iterator(this, int(Loaded.first)-TotalLoaded),
80                         iterator(this, Local.second));
81 }
82
83 std::pair<unsigned, unsigned>
84 PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
85                                                       SourceRange Range) const {
86   if (Range.isInvalid())
87     return std::make_pair(0,0);
88   assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
89
90   unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
91   unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
92   return std::make_pair(Begin, End);
93 }
94
95 namespace {
96
97 template <SourceLocation (SourceRange::*getRangeLoc)() const>
98 struct PPEntityComp {
99   const SourceManager &SM;
100
101   explicit PPEntityComp(const SourceManager &SM) : SM(SM) { }
102
103   bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
104     SourceLocation LHS = getLoc(L);
105     SourceLocation RHS = getLoc(R);
106     return SM.isBeforeInTranslationUnit(LHS, RHS);
107   }
108
109   bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
110     SourceLocation LHS = getLoc(L);
111     return SM.isBeforeInTranslationUnit(LHS, RHS);
112   }
113
114   bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
115     SourceLocation RHS = getLoc(R);
116     return SM.isBeforeInTranslationUnit(LHS, RHS);
117   }
118
119   SourceLocation getLoc(PreprocessedEntity *PPE) const {
120     SourceRange Range = PPE->getSourceRange();
121     return (Range.*getRangeLoc)();
122   }
123 };
124
125 }
126
127 unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
128                                                      SourceLocation Loc) const {
129   if (SourceMgr.isLoadedSourceLocation(Loc))
130     return 0;
131
132   size_t Count = PreprocessedEntities.size();
133   size_t Half;
134   std::vector<PreprocessedEntity *>::const_iterator
135     First = PreprocessedEntities.begin();
136   std::vector<PreprocessedEntity *>::const_iterator I;
137
138   // Do a binary search manually instead of using std::lower_bound because
139   // The end locations of entities may be unordered (when a macro expansion
140   // is inside another macro argument), but for this case it is not important
141   // whether we get the first macro expansion or its containing macro.
142   while (Count > 0) {
143     Half = Count/2;
144     I = First;
145     std::advance(I, Half);
146     if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
147                                             Loc)){
148       First = I;
149       ++First;
150       Count = Count - Half - 1;
151     } else
152       Count = Half;
153   }
154
155   return First - PreprocessedEntities.begin();
156 }
157
158 unsigned PreprocessingRecord::findEndLocalPreprocessedEntity(
159                                                      SourceLocation Loc) const {
160   if (SourceMgr.isLoadedSourceLocation(Loc))
161     return 0;
162
163   std::vector<PreprocessedEntity *>::const_iterator
164   I = std::upper_bound(PreprocessedEntities.begin(),
165                        PreprocessedEntities.end(),
166                        Loc,
167                        PPEntityComp<&SourceRange::getBegin>(SourceMgr));
168   return I - PreprocessedEntities.begin();
169 }
170
171 void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
172   assert(Entity);
173   SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
174   
175   // Check normal case, this entity begin location is after the previous one.
176   if (PreprocessedEntities.empty() ||
177       !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
178                    PreprocessedEntities.back()->getSourceRange().getBegin())) {
179     PreprocessedEntities.push_back(Entity);
180     return;
181   }
182
183   // The entity's location is not after the previous one; this can happen rarely
184   // e.g. with "#include MACRO".
185   // Iterate the entities vector in reverse until we find the right place to
186   // insert the new entity.
187   for (std::vector<PreprocessedEntity *>::iterator
188          RI = PreprocessedEntities.end(), Begin = PreprocessedEntities.begin();
189        RI != Begin; --RI) {
190     std::vector<PreprocessedEntity *>::iterator I = RI;
191     --I;
192     if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
193                                            (*I)->getSourceRange().getBegin())) {
194       PreprocessedEntities.insert(RI, Entity);
195       return;
196     }
197   }
198 }
199
200 void PreprocessingRecord::SetExternalSource(
201                                     ExternalPreprocessingRecordSource &Source) {
202   assert(!ExternalSource &&
203          "Preprocessing record already has an external source");
204   ExternalSource = &Source;
205 }
206
207 unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
208   unsigned Result = LoadedPreprocessedEntities.size();
209   LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size() 
210                                     + NumEntities);
211   return Result;
212 }
213
214 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
215                                                   PPEntityID PPID) {
216   MacroDefinitions[Macro] = PPID;
217 }
218
219 /// \brief Retrieve the preprocessed entity at the given ID.
220 PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
221   if (PPID < 0) {
222     assert(unsigned(-PPID-1) < LoadedPreprocessedEntities.size() &&
223            "Out-of bounds loaded preprocessed entity");
224     return getLoadedPreprocessedEntity(LoadedPreprocessedEntities.size()+PPID);
225   }
226   assert(unsigned(PPID) < PreprocessedEntities.size() &&
227          "Out-of bounds local preprocessed entity");
228   return PreprocessedEntities[PPID];
229 }
230
231 /// \brief Retrieve the loaded preprocessed entity at the given index.
232 PreprocessedEntity *
233 PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
234   assert(Index < LoadedPreprocessedEntities.size() && 
235          "Out-of bounds loaded preprocessed entity");
236   assert(ExternalSource && "No external source to load from");
237   PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
238   if (!Entity) {
239     Entity = ExternalSource->ReadPreprocessedEntity(Index);
240     if (!Entity) // Failed to load.
241       Entity = new (*this)
242          PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
243   }
244   return Entity;
245 }
246
247 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
248   llvm::DenseMap<const MacroInfo *, PPEntityID>::iterator Pos
249     = MacroDefinitions.find(MI);
250   if (Pos == MacroDefinitions.end())
251     return 0;
252   
253   PreprocessedEntity *Entity = getPreprocessedEntity(Pos->second);
254   if (Entity->isInvalid())
255     return 0;
256   return cast<MacroDefinition>(Entity);
257 }
258
259 void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI,
260                                        SourceRange Range) {
261   if (!IncludeNestedMacroExpansions && Id.getLocation().isMacroID())
262     return;
263
264   if (MI->isBuiltinMacro())
265     addPreprocessedEntity(
266                       new (*this) MacroExpansion(Id.getIdentifierInfo(),Range));
267   else if (MacroDefinition *Def = findMacroDefinition(MI))
268     addPreprocessedEntity(
269                        new (*this) MacroExpansion(Def, Range));
270 }
271
272 void PreprocessingRecord::MacroDefined(const Token &Id,
273                                        const MacroInfo *MI) {
274   SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
275   MacroDefinition *Def
276       = new (*this) MacroDefinition(Id.getIdentifierInfo(), R);
277   addPreprocessedEntity(Def);
278   MacroDefinitions[MI] = getPPEntityID(PreprocessedEntities.size()-1,
279                                        /*isLoaded=*/false);
280 }
281
282 void PreprocessingRecord::MacroUndefined(const Token &Id,
283                                          const MacroInfo *MI) {
284   llvm::DenseMap<const MacroInfo *, PPEntityID>::iterator Pos
285     = MacroDefinitions.find(MI);
286   if (Pos != MacroDefinitions.end())
287     MacroDefinitions.erase(Pos);
288 }
289
290 void PreprocessingRecord::InclusionDirective(
291     SourceLocation HashLoc,
292     const clang::Token &IncludeTok,
293     StringRef FileName,
294     bool IsAngled,
295     const FileEntry *File,
296     clang::SourceLocation EndLoc,
297     StringRef SearchPath,
298     StringRef RelativePath) {
299   InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
300   
301   switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
302   case tok::pp_include: 
303     Kind = InclusionDirective::Include; 
304     break;
305     
306   case tok::pp_import: 
307     Kind = InclusionDirective::Import; 
308     break;
309     
310   case tok::pp_include_next: 
311     Kind = InclusionDirective::IncludeNext; 
312     break;
313     
314   case tok::pp___include_macros: 
315     Kind = InclusionDirective::IncludeMacros;
316     break;
317     
318   default:
319     llvm_unreachable("Unknown include directive kind");
320     return;
321   }
322   
323   clang::InclusionDirective *ID
324     = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, 
325                                             File, SourceRange(HashLoc, EndLoc));
326   addPreprocessedEntity(ID);
327 }
328
329 size_t PreprocessingRecord::getTotalMemory() const {
330   return BumpAlloc.getTotalMemory()
331     + llvm::capacity_in_bytes(MacroDefinitions)
332     + llvm::capacity_in_bytes(PreprocessedEntities)
333     + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
334 }