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 void PreprocessingRecord::MaybeLoadPreallocatedEntities() const { 25 if (!ExternalSource || LoadedPreallocatedEntities) 26 return; 27 28 LoadedPreallocatedEntities = true; 29 ExternalSource->ReadPreprocessedEntities(); 30 } 31 32 PreprocessingRecord::PreprocessingRecord() 33 : ExternalSource(0), NumPreallocatedEntities(0), 34 LoadedPreallocatedEntities(false) 35 { 36 } 37 38 PreprocessingRecord::iterator 39 PreprocessingRecord::begin(bool OnlyLocalEntities) { 40 if (OnlyLocalEntities) 41 return PreprocessedEntities.begin() + NumPreallocatedEntities; 42 43 MaybeLoadPreallocatedEntities(); 44 return PreprocessedEntities.begin(); 45 } 46 47 PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) { 48 if (!OnlyLocalEntities) 49 MaybeLoadPreallocatedEntities(); 50 51 return PreprocessedEntities.end(); 52 } 53 54 PreprocessingRecord::const_iterator 55 PreprocessingRecord::begin(bool OnlyLocalEntities) const { 56 if (OnlyLocalEntities) 57 return PreprocessedEntities.begin() + NumPreallocatedEntities; 58 59 MaybeLoadPreallocatedEntities(); 60 return PreprocessedEntities.begin(); 61 } 62 63 PreprocessingRecord::const_iterator 64 PreprocessingRecord::end(bool OnlyLocalEntities) const { 65 if (!OnlyLocalEntities) 66 MaybeLoadPreallocatedEntities(); 67 68 return PreprocessedEntities.end(); 69 } 70 71 void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) { 72 PreprocessedEntities.push_back(Entity); 73 } 74 75 void PreprocessingRecord::SetExternalSource( 76 ExternalPreprocessingRecordSource &Source, 77 unsigned NumPreallocatedEntities) { 78 assert(!ExternalSource && 79 "Preprocessing record already has an external source"); 80 ExternalSource = &Source; 81 this->NumPreallocatedEntities = NumPreallocatedEntities; 82 PreprocessedEntities.insert(PreprocessedEntities.begin(), 83 NumPreallocatedEntities, 0); 84 } 85 86 void PreprocessingRecord::SetPreallocatedEntity(unsigned Index, 87 PreprocessedEntity *Entity) { 88 assert(Index < NumPreallocatedEntities &&"Out-of-bounds preallocated entity"); 89 PreprocessedEntities[Index] = Entity; 90 } 91 92 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro, 93 MacroDefinition *MD) { 94 MacroDefinitions[Macro] = MD; 95 } 96 97 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) { 98 llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos 99 = MacroDefinitions.find(MI); 100 if (Pos == MacroDefinitions.end()) 101 return 0; 102 103 return Pos->second; 104 } 105 106 void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) { 107 if (MacroDefinition *Def = findMacroDefinition(MI)) 108 PreprocessedEntities.push_back( 109 new (*this) MacroInstantiation(Id.getIdentifierInfo(), 110 Id.getLocation(), 111 Def)); 112 } 113 114 void PreprocessingRecord::MacroDefined(const IdentifierInfo *II, 115 const MacroInfo *MI) { 116 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); 117 MacroDefinition *Def 118 = new (*this) MacroDefinition(II, MI->getDefinitionLoc(), R); 119 MacroDefinitions[MI] = Def; 120 PreprocessedEntities.push_back(Def); 121 } 122 123 void PreprocessingRecord::MacroUndefined(SourceLocation Loc, 124 const IdentifierInfo *II, 125 const MacroInfo *MI) { 126 llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos 127 = MacroDefinitions.find(MI); 128 if (Pos != MacroDefinitions.end()) 129 MacroDefinitions.erase(Pos); 130 } 131 132 void PreprocessingRecord::InclusionDirective(SourceLocation HashLoc, 133 const clang::Token &IncludeTok, 134 llvm::StringRef FileName, 135 bool IsAngled, 136 const FileEntry *File, 137 clang::SourceLocation EndLoc) { 138 InclusionDirective::InclusionKind Kind = InclusionDirective::Include; 139 140 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { 141 case tok::pp_include: 142 Kind = InclusionDirective::Include; 143 break; 144 145 case tok::pp_import: 146 Kind = InclusionDirective::Import; 147 break; 148 149 case tok::pp_include_next: 150 Kind = InclusionDirective::IncludeNext; 151 break; 152 153 case tok::pp___include_macros: 154 Kind = InclusionDirective::IncludeMacros; 155 break; 156 157 default: 158 llvm_unreachable("Unknown include directive kind"); 159 return; 160 } 161 162 clang::InclusionDirective *ID 163 = new (*this) clang::InclusionDirective(Kind, FileName, !IsAngled, File, 164 SourceRange(HashLoc, EndLoc)); 165 PreprocessedEntities.push_back(ID); 166 } 167