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