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 "clang/Basic/IdentifierTable.h"
18 #include "llvm/Support/ErrorHandling.h"
19 
20 using namespace clang;
21 
22 ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
23 
24 void PreprocessingRecord::MaybeLoadPreallocatedEntities() const {
25   if (!ExternalSource || LoadedPreallocatedEntities)
26     return;
27 
28   LoadedPreallocatedEntities = true;
29   ExternalSource->ReadPreprocessedEntities();
30 }
31 
32 PreprocessingRecord::PreprocessingRecord()
33   : ExternalSource(0), NumPreallocatedEntities(0),
34     LoadedPreallocatedEntities(false)
35 {
36 }
37 
38 PreprocessingRecord::iterator
39 PreprocessingRecord::begin(bool OnlyLocalEntities) {
40   if (OnlyLocalEntities)
41     return PreprocessedEntities.begin() + NumPreallocatedEntities;
42 
43   MaybeLoadPreallocatedEntities();
44   return PreprocessedEntities.begin();
45 }
46 
47 PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) {
48   if (!OnlyLocalEntities)
49     MaybeLoadPreallocatedEntities();
50 
51   return PreprocessedEntities.end();
52 }
53 
54 PreprocessingRecord::const_iterator
55 PreprocessingRecord::begin(bool OnlyLocalEntities) const {
56   if (OnlyLocalEntities)
57     return PreprocessedEntities.begin() + NumPreallocatedEntities;
58 
59   MaybeLoadPreallocatedEntities();
60   return PreprocessedEntities.begin();
61 }
62 
63 PreprocessingRecord::const_iterator
64 PreprocessingRecord::end(bool OnlyLocalEntities) const {
65   if (!OnlyLocalEntities)
66     MaybeLoadPreallocatedEntities();
67 
68   return PreprocessedEntities.end();
69 }
70 
71 void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
72   PreprocessedEntities.push_back(Entity);
73 }
74 
75 void PreprocessingRecord::SetExternalSource(
76                                     ExternalPreprocessingRecordSource &Source,
77                                             unsigned NumPreallocatedEntities) {
78   assert(!ExternalSource &&
79          "Preprocessing record already has an external source");
80   ExternalSource = &Source;
81   this->NumPreallocatedEntities = NumPreallocatedEntities;
82   PreprocessedEntities.insert(PreprocessedEntities.begin(),
83                               NumPreallocatedEntities, 0);
84 }
85 
86 void PreprocessingRecord::SetPreallocatedEntity(unsigned Index,
87                                                 PreprocessedEntity *Entity) {
88   assert(Index < NumPreallocatedEntities &&"Out-of-bounds preallocated entity");
89   PreprocessedEntities[Index] = Entity;
90 }
91 
92 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
93                                                   MacroDefinition *MD) {
94   MacroDefinitions[Macro] = MD;
95 }
96 
97 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
98   llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
99     = MacroDefinitions.find(MI);
100   if (Pos == MacroDefinitions.end())
101     return 0;
102 
103   return Pos->second;
104 }
105 
106 void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) {
107   if (MacroDefinition *Def = findMacroDefinition(MI))
108     PreprocessedEntities.push_back(
109                        new (*this) MacroInstantiation(Id.getIdentifierInfo(),
110                                                       Id.getLocation(),
111                                                       Def));
112 }
113 
114 void PreprocessingRecord::MacroDefined(const IdentifierInfo *II,
115                                        const MacroInfo *MI) {
116   SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
117   MacroDefinition *Def
118     = new (*this) MacroDefinition(II, MI->getDefinitionLoc(), R);
119   MacroDefinitions[MI] = Def;
120   PreprocessedEntities.push_back(Def);
121 }
122 
123 void PreprocessingRecord::MacroUndefined(SourceLocation Loc,
124                                          const IdentifierInfo *II,
125                                          const MacroInfo *MI) {
126   llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
127     = MacroDefinitions.find(MI);
128   if (Pos != MacroDefinitions.end())
129     MacroDefinitions.erase(Pos);
130 }
131 
132 void PreprocessingRecord::InclusionDirective(SourceLocation HashLoc,
133                                              const clang::Token &IncludeTok,
134                                              llvm::StringRef FileName,
135                                              bool IsAngled,
136                                              const FileEntry *File,
137                                            clang::SourceLocation EndLoc) {
138   InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
139 
140   switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
141   case tok::pp_include:
142     Kind = InclusionDirective::Include;
143     break;
144 
145   case tok::pp_import:
146     Kind = InclusionDirective::Import;
147     break;
148 
149   case tok::pp_include_next:
150     Kind = InclusionDirective::IncludeNext;
151     break;
152 
153   case tok::pp___include_macros:
154     Kind = InclusionDirective::IncludeMacros;
155     break;
156 
157   default:
158     llvm_unreachable("Unknown include directive kind");
159     return;
160   }
161 
162   clang::InclusionDirective *ID
163     = new (*this) clang::InclusionDirective(Kind, FileName, !IsAngled, File,
164                                             SourceRange(HashLoc, EndLoc));
165   PreprocessedEntities.push_back(ID);
166 }
167