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