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(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