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 } 191