blob: 34421779c935cbf70f59709972fe642a9c0104b1 [file] [log] [blame]
Douglas Gregor065f8d12010-03-18 17:52:52 +00001//===--- 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"
Douglas Gregor796d76a2010-10-20 22:00:55 +000017#include "clang/Basic/IdentifierTable.h"
18#include "llvm/Support/ErrorHandling.h"
Douglas Gregor065f8d12010-03-18 17:52:52 +000019
20using namespace clang;
21
Douglas Gregoraae92242010-03-19 21:51:54 +000022ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
23
24void PreprocessingRecord::MaybeLoadPreallocatedEntities() const {
25 if (!ExternalSource || LoadedPreallocatedEntities)
26 return;
27
28 LoadedPreallocatedEntities = true;
29 ExternalSource->ReadPreprocessedEntities();
30}
31
32PreprocessingRecord::PreprocessingRecord()
33 : ExternalSource(0), NumPreallocatedEntities(0),
34 LoadedPreallocatedEntities(false)
35{
36}
37
38PreprocessingRecord::iterator
39PreprocessingRecord::begin(bool OnlyLocalEntities) {
40 if (OnlyLocalEntities)
41 return PreprocessedEntities.begin() + NumPreallocatedEntities;
42
43 MaybeLoadPreallocatedEntities();
44 return PreprocessedEntities.begin();
45}
46
47PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) {
48 if (!OnlyLocalEntities)
49 MaybeLoadPreallocatedEntities();
50
51 return PreprocessedEntities.end();
52}
53
54PreprocessingRecord::const_iterator
55PreprocessingRecord::begin(bool OnlyLocalEntities) const {
56 if (OnlyLocalEntities)
57 return PreprocessedEntities.begin() + NumPreallocatedEntities;
58
59 MaybeLoadPreallocatedEntities();
60 return PreprocessedEntities.begin();
61}
62
63PreprocessingRecord::const_iterator
64PreprocessingRecord::end(bool OnlyLocalEntities) const {
65 if (!OnlyLocalEntities)
66 MaybeLoadPreallocatedEntities();
67
68 return PreprocessedEntities.end();
69}
70
Douglas Gregor065f8d12010-03-18 17:52:52 +000071void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
72 PreprocessedEntities.push_back(Entity);
73}
74
Douglas Gregoraae92242010-03-19 21:51:54 +000075void 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
86void PreprocessingRecord::SetPreallocatedEntity(unsigned Index,
87 PreprocessedEntity *Entity) {
88 assert(Index < NumPreallocatedEntities &&"Out-of-bounds preallocated entity");
89 PreprocessedEntities[Index] = Entity;
90}
91
92void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
93 MacroDefinition *MD) {
94 MacroDefinitions[Macro] = MD;
95}
96
Douglas Gregor8aaca672010-03-19 21:58:23 +000097MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
Douglas Gregor7dc87222010-03-19 17:12:43 +000098 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
106void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) {
Douglas Gregor8aaca672010-03-19 21:58:23 +0000107 if (MacroDefinition *Def = findMacroDefinition(MI))
108 PreprocessedEntities.push_back(
Douglas Gregor7dc87222010-03-19 17:12:43 +0000109 new (*this) MacroInstantiation(Id.getIdentifierInfo(),
110 Id.getLocation(),
Douglas Gregor8aaca672010-03-19 21:58:23 +0000111 Def));
Douglas Gregor7dc87222010-03-19 17:12:43 +0000112}
113
114void 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}
Douglas Gregoraae92242010-03-19 21:51:54 +0000122
Benjamin Kramerd05f31d2010-08-07 22:27:00 +0000123void PreprocessingRecord::MacroUndefined(SourceLocation Loc,
124 const IdentifierInfo *II,
Douglas Gregor8aaca672010-03-19 21:58:23 +0000125 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
Douglas Gregor796d76a2010-10-20 22:00:55 +0000132void 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}