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