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