PreprocessingRecord.cpp 6.3 KB

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