]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
Copy the v4l2 header unchanged from the vendor branch.
[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()
49   : ExternalSource(0), NumPreallocatedEntities(0), 
50     LoadedPreallocatedEntities(false)
51 {
52 }
53
54 PreprocessingRecord::iterator 
55 PreprocessingRecord::begin(bool OnlyLocalEntities) {
56   if (OnlyLocalEntities)
57     return PreprocessedEntities.begin() + NumPreallocatedEntities;
58   
59   MaybeLoadPreallocatedEntities();
60   return PreprocessedEntities.begin();
61 }
62
63 PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) {
64   if (!OnlyLocalEntities)
65     MaybeLoadPreallocatedEntities();
66   
67   return PreprocessedEntities.end();
68 }
69
70 PreprocessingRecord::const_iterator 
71 PreprocessingRecord::begin(bool OnlyLocalEntities) const {
72   if (OnlyLocalEntities)
73     return PreprocessedEntities.begin() + NumPreallocatedEntities;
74   
75   MaybeLoadPreallocatedEntities();
76   return PreprocessedEntities.begin();
77 }
78
79 PreprocessingRecord::const_iterator 
80 PreprocessingRecord::end(bool OnlyLocalEntities) const {
81   if (!OnlyLocalEntities)
82     MaybeLoadPreallocatedEntities();
83   
84   return PreprocessedEntities.end();
85 }
86
87 void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
88   PreprocessedEntities.push_back(Entity);
89 }
90
91 void 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
102 void PreprocessingRecord::SetPreallocatedEntity(unsigned Index, 
103                                                 PreprocessedEntity *Entity) {
104   assert(Index < NumPreallocatedEntities &&"Out-of-bounds preallocated entity");
105   PreprocessedEntities[Index] = Entity;
106 }
107
108 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro, 
109                                                   MacroDefinition *MD) {
110   MacroDefinitions[Macro] = MD;
111 }
112
113 MacroDefinition *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
122 void 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
130 void 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
141 void 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
149 void PreprocessingRecord::InclusionDirective(
150     SourceLocation HashLoc,
151     const clang::Token &IncludeTok,
152     llvm::StringRef FileName,
153     bool IsAngled,
154     const FileEntry *File,
155     clang::SourceLocation EndLoc,
156     llvm::StringRef SearchPath,
157     llvm::StringRef RelativePath) {
158   InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
159   
160   switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
161   case tok::pp_include: 
162     Kind = InclusionDirective::Include; 
163     break;
164     
165   case tok::pp_import: 
166     Kind = InclusionDirective::Import; 
167     break;
168     
169   case tok::pp_include_next: 
170     Kind = InclusionDirective::IncludeNext; 
171     break;
172     
173   case tok::pp___include_macros: 
174     Kind = InclusionDirective::IncludeMacros;
175     break;
176     
177   default:
178     llvm_unreachable("Unknown include directive kind");
179     return;
180   }
181   
182   clang::InclusionDirective *ID
183     = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, 
184                                             File, SourceRange(HashLoc, EndLoc));
185   PreprocessedEntities.push_back(ID);
186 }