1 //===--- PreprocessingRecord.cpp - Record of Preprocessing ------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the PreprocessingRecord class, which maintains a record
11 // of what occurred during preprocessing, and its helpers.
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"
20 using namespace clang;
22 ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
25 InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
27 llvm::StringRef FileName,
28 bool InQuotes, const FileEntry *File,
30 : PreprocessingDirective(InclusionDirectiveKind, Range),
31 InQuotes(InQuotes), Kind(Kind), File(File)
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 = llvm::StringRef(Memory, FileName.size());
40 void PreprocessingRecord::MaybeLoadPreallocatedEntities() const {
41 if (!ExternalSource || LoadedPreallocatedEntities)
44 LoadedPreallocatedEntities = true;
45 ExternalSource->ReadPreprocessedEntities();
48 PreprocessingRecord::PreprocessingRecord(bool IncludeNestedMacroExpansions)
49 : IncludeNestedMacroExpansions(IncludeNestedMacroExpansions),
50 ExternalSource(0), NumPreallocatedEntities(0),
51 LoadedPreallocatedEntities(false)
55 PreprocessingRecord::iterator
56 PreprocessingRecord::begin(bool OnlyLocalEntities) {
57 if (OnlyLocalEntities)
58 return PreprocessedEntities.begin() + NumPreallocatedEntities;
60 MaybeLoadPreallocatedEntities();
61 return PreprocessedEntities.begin();
64 PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) {
65 if (!OnlyLocalEntities)
66 MaybeLoadPreallocatedEntities();
68 return PreprocessedEntities.end();
71 PreprocessingRecord::const_iterator
72 PreprocessingRecord::begin(bool OnlyLocalEntities) const {
73 if (OnlyLocalEntities)
74 return PreprocessedEntities.begin() + NumPreallocatedEntities;
76 MaybeLoadPreallocatedEntities();
77 return PreprocessedEntities.begin();
80 PreprocessingRecord::const_iterator
81 PreprocessingRecord::end(bool OnlyLocalEntities) const {
82 if (!OnlyLocalEntities)
83 MaybeLoadPreallocatedEntities();
85 return PreprocessedEntities.end();
88 void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
89 PreprocessedEntities.push_back(Entity);
92 void PreprocessingRecord::SetExternalSource(
93 ExternalPreprocessingRecordSource &Source,
94 unsigned NumPreallocatedEntities) {
95 assert(!ExternalSource &&
96 "Preprocessing record already has an external source");
97 ExternalSource = &Source;
98 this->NumPreallocatedEntities = NumPreallocatedEntities;
99 PreprocessedEntities.insert(PreprocessedEntities.begin(),
100 NumPreallocatedEntities, 0);
103 void PreprocessingRecord::SetPreallocatedEntity(unsigned Index,
104 PreprocessedEntity *Entity) {
105 assert(Index < NumPreallocatedEntities &&"Out-of-bounds preallocated entity");
106 PreprocessedEntities[Index] = Entity;
109 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
110 MacroDefinition *MD) {
111 MacroDefinitions[Macro] = MD;
114 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
115 llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
116 = MacroDefinitions.find(MI);
117 if (Pos == MacroDefinitions.end())
123 void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) {
124 if (!IncludeNestedMacroExpansions && Id.getLocation().isMacroID())
127 if (MacroDefinition *Def = findMacroDefinition(MI))
128 PreprocessedEntities.push_back(
129 new (*this) MacroExpansion(Id.getIdentifierInfo(),
130 Id.getLocation(), Def));
133 void PreprocessingRecord::MacroDefined(const Token &Id,
134 const MacroInfo *MI) {
135 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
137 = new (*this) MacroDefinition(Id.getIdentifierInfo(),
138 MI->getDefinitionLoc(),
140 MacroDefinitions[MI] = Def;
141 PreprocessedEntities.push_back(Def);
144 void PreprocessingRecord::MacroUndefined(const Token &Id,
145 const MacroInfo *MI) {
146 llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
147 = MacroDefinitions.find(MI);
148 if (Pos != MacroDefinitions.end())
149 MacroDefinitions.erase(Pos);
152 void PreprocessingRecord::InclusionDirective(
153 SourceLocation HashLoc,
154 const clang::Token &IncludeTok,
155 llvm::StringRef FileName,
157 const FileEntry *File,
158 clang::SourceLocation EndLoc,
159 llvm::StringRef SearchPath,
160 llvm::StringRef RelativePath) {
161 InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
163 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
164 case tok::pp_include:
165 Kind = InclusionDirective::Include;
169 Kind = InclusionDirective::Import;
172 case tok::pp_include_next:
173 Kind = InclusionDirective::IncludeNext;
176 case tok::pp___include_macros:
177 Kind = InclusionDirective::IncludeMacros;
181 llvm_unreachable("Unknown include directive kind");
185 clang::InclusionDirective *ID
186 = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
187 File, SourceRange(HashLoc, EndLoc));
188 PreprocessedEntities.push_back(ID);