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 void PreprocessingRecord::MaybeLoadPreallocatedEntities() const {
41   if (!ExternalSource || LoadedPreallocatedEntities)
42     return;
43 
44   LoadedPreallocatedEntities = true;
45   ExternalSource->ReadPreprocessedEntities();
46 }
47 
48 PreprocessingRecord::PreprocessingRecord(bool IncludeNestedMacroExpansions)
49   : IncludeNestedMacroExpansions(IncludeNestedMacroExpansions),
50     ExternalSource(0), LoadedPreallocatedEntities(false)
51 {
52 }
53 
54 PreprocessingRecord::iterator
55 PreprocessingRecord::begin(bool OnlyLocalEntities) {
56   if (OnlyLocalEntities)
57     return iterator(this, 0);
58 
59   MaybeLoadPreallocatedEntities();
60   return iterator(this, -(int)LoadedPreprocessedEntities.size());
61 }
62 
63 PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) {
64   if (!OnlyLocalEntities)
65     MaybeLoadPreallocatedEntities();
66 
67   return iterator(this, PreprocessedEntities.size());
68 }
69 
70 void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
71   PreprocessedEntities.push_back(Entity);
72 }
73 
74 void PreprocessingRecord::SetExternalSource(
75                                     ExternalPreprocessingRecordSource &Source) {
76   assert(!ExternalSource &&
77          "Preprocessing record already has an external source");
78   ExternalSource = &Source;
79 }
80 
81 unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
82   unsigned Result = LoadedPreprocessedEntities.size();
83   LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
84                                     + NumEntities);
85   return Result;
86 }
87 
88 void
89 PreprocessingRecord::setLoadedPreallocatedEntity(unsigned Index,
90                                                  PreprocessedEntity *Entity) {
91   assert(Index < LoadedPreprocessedEntities.size() &&
92          "Out-of-bounds preallocated entity");
93   LoadedPreprocessedEntities[Index] = Entity;
94 }
95 
96 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
97                                                   MacroDefinition *MD) {
98   MacroDefinitions[Macro] = MD;
99 }
100 
101 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
102   llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
103     = MacroDefinitions.find(MI);
104   if (Pos == MacroDefinitions.end())
105     return 0;
106 
107   return Pos->second;
108 }
109 
110 void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI,
111                                        SourceRange Range) {
112   if (!IncludeNestedMacroExpansions && Id.getLocation().isMacroID())
113     return;
114 
115   if (MI->isBuiltinMacro())
116     PreprocessedEntities.push_back(
117                       new (*this) MacroExpansion(Id.getIdentifierInfo(),Range));
118   else if (MacroDefinition *Def = findMacroDefinition(MI))
119     PreprocessedEntities.push_back(
120                        new (*this) MacroExpansion(Def, Range));
121 }
122 
123 void PreprocessingRecord::MacroDefined(const Token &Id,
124                                        const MacroInfo *MI) {
125   SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
126   MacroDefinition *Def
127       = new (*this) MacroDefinition(Id.getIdentifierInfo(),
128                                     MI->getDefinitionLoc(),
129                                     R);
130   MacroDefinitions[MI] = Def;
131   PreprocessedEntities.push_back(Def);
132 }
133 
134 void PreprocessingRecord::MacroUndefined(const Token &Id,
135                                          const MacroInfo *MI) {
136   llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
137     = MacroDefinitions.find(MI);
138   if (Pos != MacroDefinitions.end())
139     MacroDefinitions.erase(Pos);
140 }
141 
142 void PreprocessingRecord::InclusionDirective(
143     SourceLocation HashLoc,
144     const clang::Token &IncludeTok,
145     StringRef FileName,
146     bool IsAngled,
147     const FileEntry *File,
148     clang::SourceLocation EndLoc,
149     StringRef SearchPath,
150     StringRef RelativePath) {
151   InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
152 
153   switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
154   case tok::pp_include:
155     Kind = InclusionDirective::Include;
156     break;
157 
158   case tok::pp_import:
159     Kind = InclusionDirective::Import;
160     break;
161 
162   case tok::pp_include_next:
163     Kind = InclusionDirective::IncludeNext;
164     break;
165 
166   case tok::pp___include_macros:
167     Kind = InclusionDirective::IncludeMacros;
168     break;
169 
170   default:
171     llvm_unreachable("Unknown include directive kind");
172     return;
173   }
174 
175   clang::InclusionDirective *ID
176     = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
177                                             File, SourceRange(HashLoc, EndLoc));
178   PreprocessedEntities.push_back(ID);
179 }
180 
181 size_t PreprocessingRecord::getTotalMemory() const {
182   return BumpAlloc.getTotalMemory()
183     + llvm::capacity_in_bytes(MacroDefinitions)
184     + llvm::capacity_in_bytes(PreprocessedEntities)
185     + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
186 }
187