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