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 PreprocessingRecord::PreprocessingRecord(SourceManager &SM, 41 bool IncludeNestedMacroExpansions) 42 : SourceMgr(SM), IncludeNestedMacroExpansions(IncludeNestedMacroExpansions), 43 ExternalSource(0) 44 { 45 } 46 47 /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities 48 /// that source range \arg R encompasses. 49 std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> 50 PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) { 51 if (Range.isInvalid()) 52 return std::make_pair(iterator(this, 0), iterator(this, 0)); 53 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); 54 55 std::pair<unsigned, unsigned> 56 Local = findLocalPreprocessedEntitiesInRange(Range); 57 58 // Check if range spans local entities. 59 if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin())) 60 return std::make_pair(iterator(this, Local.first), 61 iterator(this, Local.second)); 62 63 std::pair<unsigned, unsigned> 64 Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range); 65 66 // Check if range spans local entities. 67 if (Loaded.first == Loaded.second) 68 return std::make_pair(iterator(this, Local.first), 69 iterator(this, Local.second)); 70 71 unsigned TotalLoaded = LoadedPreprocessedEntities.size(); 72 73 // Check if range spans loaded entities. 74 if (Local.first == Local.second) 75 return std::make_pair(iterator(this, int(Loaded.first)-TotalLoaded), 76 iterator(this, int(Loaded.second)-TotalLoaded)); 77 78 // Range spands loaded and local entities. 79 return std::make_pair(iterator(this, int(Loaded.first)-TotalLoaded), 80 iterator(this, Local.second)); 81 } 82 83 std::pair<unsigned, unsigned> 84 PreprocessingRecord::findLocalPreprocessedEntitiesInRange( 85 SourceRange Range) const { 86 if (Range.isInvalid()) 87 return std::make_pair(0,0); 88 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); 89 90 unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin()); 91 unsigned End = findEndLocalPreprocessedEntity(Range.getEnd()); 92 return std::make_pair(Begin, End); 93 } 94 95 namespace { 96 97 template <SourceLocation (SourceRange::*getRangeLoc)() const> 98 struct PPEntityComp { 99 const SourceManager &SM; 100 101 explicit PPEntityComp(const SourceManager &SM) : SM(SM) { } 102 103 bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const { 104 SourceLocation LHS = getLoc(L); 105 SourceLocation RHS = getLoc(R); 106 return SM.isBeforeInTranslationUnit(LHS, RHS); 107 } 108 109 bool operator()(PreprocessedEntity *L, SourceLocation RHS) const { 110 SourceLocation LHS = getLoc(L); 111 return SM.isBeforeInTranslationUnit(LHS, RHS); 112 } 113 114 bool operator()(SourceLocation LHS, PreprocessedEntity *R) const { 115 SourceLocation RHS = getLoc(R); 116 return SM.isBeforeInTranslationUnit(LHS, RHS); 117 } 118 119 SourceLocation getLoc(PreprocessedEntity *PPE) const { 120 SourceRange Range = PPE->getSourceRange(); 121 return (Range.*getRangeLoc)(); 122 } 123 }; 124 125 } 126 127 unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity( 128 SourceLocation Loc) const { 129 if (SourceMgr.isLoadedSourceLocation(Loc)) 130 return 0; 131 132 size_t Count = PreprocessedEntities.size(); 133 size_t Half; 134 std::vector<PreprocessedEntity *>::const_iterator 135 First = PreprocessedEntities.begin(); 136 std::vector<PreprocessedEntity *>::const_iterator I; 137 138 // Do a binary search manually instead of using std::lower_bound because 139 // The end locations of entities may be unordered (when a macro expansion 140 // is inside another macro argument), but for this case it is not important 141 // whether we get the first macro expansion or its containing macro. 142 while (Count > 0) { 143 Half = Count/2; 144 I = First; 145 std::advance(I, Half); 146 if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(), 147 Loc)){ 148 First = I; 149 ++First; 150 Count = Count - Half - 1; 151 } else 152 Count = Half; 153 } 154 155 return First - PreprocessedEntities.begin(); 156 } 157 158 unsigned PreprocessingRecord::findEndLocalPreprocessedEntity( 159 SourceLocation Loc) const { 160 if (SourceMgr.isLoadedSourceLocation(Loc)) 161 return 0; 162 163 std::vector<PreprocessedEntity *>::const_iterator 164 I = std::upper_bound(PreprocessedEntities.begin(), 165 PreprocessedEntities.end(), 166 Loc, 167 PPEntityComp<&SourceRange::getBegin>(SourceMgr)); 168 return I - PreprocessedEntities.begin(); 169 } 170 171 void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) { 172 assert(Entity); 173 SourceLocation BeginLoc = Entity->getSourceRange().getBegin(); 174 175 // Check normal case, this entity begin location is after the previous one. 176 if (PreprocessedEntities.empty() || 177 !SourceMgr.isBeforeInTranslationUnit(BeginLoc, 178 PreprocessedEntities.back()->getSourceRange().getBegin())) { 179 PreprocessedEntities.push_back(Entity); 180 return; 181 } 182 183 // The entity's location is not after the previous one; this can happen rarely 184 // e.g. with "#include MACRO". 185 // Iterate the entities vector in reverse until we find the right place to 186 // insert the new entity. 187 for (std::vector<PreprocessedEntity *>::iterator 188 RI = PreprocessedEntities.end(), Begin = PreprocessedEntities.begin(); 189 RI != Begin; --RI) { 190 std::vector<PreprocessedEntity *>::iterator I = RI; 191 --I; 192 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc, 193 (*I)->getSourceRange().getBegin())) { 194 PreprocessedEntities.insert(RI, Entity); 195 return; 196 } 197 } 198 } 199 200 void PreprocessingRecord::SetExternalSource( 201 ExternalPreprocessingRecordSource &Source) { 202 assert(!ExternalSource && 203 "Preprocessing record already has an external source"); 204 ExternalSource = &Source; 205 } 206 207 unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) { 208 unsigned Result = LoadedPreprocessedEntities.size(); 209 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size() 210 + NumEntities); 211 return Result; 212 } 213 214 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro, 215 PPEntityID PPID) { 216 MacroDefinitions[Macro] = PPID; 217 } 218 219 /// \brief Retrieve the preprocessed entity at the given ID. 220 PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){ 221 if (PPID < 0) { 222 assert(unsigned(-PPID-1) < LoadedPreprocessedEntities.size() && 223 "Out-of bounds loaded preprocessed entity"); 224 return getLoadedPreprocessedEntity(LoadedPreprocessedEntities.size()+PPID); 225 } 226 assert(unsigned(PPID) < PreprocessedEntities.size() && 227 "Out-of bounds local preprocessed entity"); 228 return PreprocessedEntities[PPID]; 229 } 230 231 /// \brief Retrieve the loaded preprocessed entity at the given index. 232 PreprocessedEntity * 233 PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) { 234 assert(Index < LoadedPreprocessedEntities.size() && 235 "Out-of bounds loaded preprocessed entity"); 236 assert(ExternalSource && "No external source to load from"); 237 PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index]; 238 if (!Entity) { 239 Entity = ExternalSource->ReadPreprocessedEntity(Index); 240 if (!Entity) // Failed to load. 241 Entity = new (*this) 242 PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange()); 243 } 244 return Entity; 245 } 246 247 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) { 248 llvm::DenseMap<const MacroInfo *, PPEntityID>::iterator Pos 249 = MacroDefinitions.find(MI); 250 if (Pos == MacroDefinitions.end()) 251 return 0; 252 253 PreprocessedEntity *Entity = getPreprocessedEntity(Pos->second); 254 if (Entity->isInvalid()) 255 return 0; 256 return cast<MacroDefinition>(Entity); 257 } 258 259 void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI, 260 SourceRange Range) { 261 if (!IncludeNestedMacroExpansions && Id.getLocation().isMacroID()) 262 return; 263 264 if (MI->isBuiltinMacro()) 265 addPreprocessedEntity( 266 new (*this) MacroExpansion(Id.getIdentifierInfo(),Range)); 267 else if (MacroDefinition *Def = findMacroDefinition(MI)) 268 addPreprocessedEntity( 269 new (*this) MacroExpansion(Def, Range)); 270 } 271 272 void PreprocessingRecord::MacroDefined(const Token &Id, 273 const MacroInfo *MI) { 274 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); 275 MacroDefinition *Def 276 = new (*this) MacroDefinition(Id.getIdentifierInfo(), R); 277 addPreprocessedEntity(Def); 278 MacroDefinitions[MI] = getPPEntityID(PreprocessedEntities.size()-1, 279 /*isLoaded=*/false); 280 } 281 282 void PreprocessingRecord::MacroUndefined(const Token &Id, 283 const MacroInfo *MI) { 284 llvm::DenseMap<const MacroInfo *, PPEntityID>::iterator Pos 285 = MacroDefinitions.find(MI); 286 if (Pos != MacroDefinitions.end()) 287 MacroDefinitions.erase(Pos); 288 } 289 290 void PreprocessingRecord::InclusionDirective( 291 SourceLocation HashLoc, 292 const clang::Token &IncludeTok, 293 StringRef FileName, 294 bool IsAngled, 295 const FileEntry *File, 296 clang::SourceLocation EndLoc, 297 StringRef SearchPath, 298 StringRef RelativePath) { 299 InclusionDirective::InclusionKind Kind = InclusionDirective::Include; 300 301 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { 302 case tok::pp_include: 303 Kind = InclusionDirective::Include; 304 break; 305 306 case tok::pp_import: 307 Kind = InclusionDirective::Import; 308 break; 309 310 case tok::pp_include_next: 311 Kind = InclusionDirective::IncludeNext; 312 break; 313 314 case tok::pp___include_macros: 315 Kind = InclusionDirective::IncludeMacros; 316 break; 317 318 default: 319 llvm_unreachable("Unknown include directive kind"); 320 return; 321 } 322 323 clang::InclusionDirective *ID 324 = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, 325 File, SourceRange(HashLoc, EndLoc)); 326 addPreprocessedEntity(ID); 327 } 328 329 size_t PreprocessingRecord::getTotalMemory() const { 330 return BumpAlloc.getTotalMemory() 331 + llvm::capacity_in_bytes(MacroDefinitions) 332 + llvm::capacity_in_bytes(PreprocessedEntities) 333 + llvm::capacity_in_bytes(LoadedPreprocessedEntities); 334 } 335