teak-llvm/clang/lib/Lex/PreprocessingRecord.cpp
Douglas Gregor 796d76a663 Extend the preprocessing record and libclang with support for
inclusion directives, keeping track of every #include, #import,
etc. in the translation unit. We keep track of the source location and
kind of the inclusion, how the file name was spelled, and the
underlying file to which the inclusion resolved.

llvm-svn: 116952
2010-10-20 22:00:55 +00:00

167 lines
5.7 KiB
C++

//===--- PreprocessingRecord.cpp - Record of Preprocessing ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PreprocessingRecord class, which maintains a record
// of what occurred during preprocessing, and its helpers.
//
//===----------------------------------------------------------------------===//
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Token.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
void PreprocessingRecord::MaybeLoadPreallocatedEntities() const {
if (!ExternalSource || LoadedPreallocatedEntities)
return;
LoadedPreallocatedEntities = true;
ExternalSource->ReadPreprocessedEntities();
}
PreprocessingRecord::PreprocessingRecord()
: ExternalSource(0), NumPreallocatedEntities(0),
LoadedPreallocatedEntities(false)
{
}
PreprocessingRecord::iterator
PreprocessingRecord::begin(bool OnlyLocalEntities) {
if (OnlyLocalEntities)
return PreprocessedEntities.begin() + NumPreallocatedEntities;
MaybeLoadPreallocatedEntities();
return PreprocessedEntities.begin();
}
PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) {
if (!OnlyLocalEntities)
MaybeLoadPreallocatedEntities();
return PreprocessedEntities.end();
}
PreprocessingRecord::const_iterator
PreprocessingRecord::begin(bool OnlyLocalEntities) const {
if (OnlyLocalEntities)
return PreprocessedEntities.begin() + NumPreallocatedEntities;
MaybeLoadPreallocatedEntities();
return PreprocessedEntities.begin();
}
PreprocessingRecord::const_iterator
PreprocessingRecord::end(bool OnlyLocalEntities) const {
if (!OnlyLocalEntities)
MaybeLoadPreallocatedEntities();
return PreprocessedEntities.end();
}
void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
PreprocessedEntities.push_back(Entity);
}
void PreprocessingRecord::SetExternalSource(
ExternalPreprocessingRecordSource &Source,
unsigned NumPreallocatedEntities) {
assert(!ExternalSource &&
"Preprocessing record already has an external source");
ExternalSource = &Source;
this->NumPreallocatedEntities = NumPreallocatedEntities;
PreprocessedEntities.insert(PreprocessedEntities.begin(),
NumPreallocatedEntities, 0);
}
void PreprocessingRecord::SetPreallocatedEntity(unsigned Index,
PreprocessedEntity *Entity) {
assert(Index < NumPreallocatedEntities &&"Out-of-bounds preallocated entity");
PreprocessedEntities[Index] = Entity;
}
void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
MacroDefinition *MD) {
MacroDefinitions[Macro] = MD;
}
MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
= MacroDefinitions.find(MI);
if (Pos == MacroDefinitions.end())
return 0;
return Pos->second;
}
void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) {
if (MacroDefinition *Def = findMacroDefinition(MI))
PreprocessedEntities.push_back(
new (*this) MacroInstantiation(Id.getIdentifierInfo(),
Id.getLocation(),
Def));
}
void PreprocessingRecord::MacroDefined(const IdentifierInfo *II,
const MacroInfo *MI) {
SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
MacroDefinition *Def
= new (*this) MacroDefinition(II, MI->getDefinitionLoc(), R);
MacroDefinitions[MI] = Def;
PreprocessedEntities.push_back(Def);
}
void PreprocessingRecord::MacroUndefined(SourceLocation Loc,
const IdentifierInfo *II,
const MacroInfo *MI) {
llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
= MacroDefinitions.find(MI);
if (Pos != MacroDefinitions.end())
MacroDefinitions.erase(Pos);
}
void PreprocessingRecord::InclusionDirective(SourceLocation HashLoc,
const clang::Token &IncludeTok,
llvm::StringRef FileName,
bool IsAngled,
const FileEntry *File,
clang::SourceLocation EndLoc) {
InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
case tok::pp_include:
Kind = InclusionDirective::Include;
break;
case tok::pp_import:
Kind = InclusionDirective::Import;
break;
case tok::pp_include_next:
Kind = InclusionDirective::IncludeNext;
break;
case tok::pp___include_macros:
Kind = InclusionDirective::IncludeMacros;
break;
default:
llvm_unreachable("Unknown include directive kind");
return;
}
clang::InclusionDirective *ID
= new (*this) clang::InclusionDirective(Kind, FileName, !IsAngled, File,
SourceRange(HashLoc, EndLoc));
PreprocessedEntities.push_back(ID);
}