mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-26 14:58:59 -04:00

clients to observe the exact path through which an #included file was located. This is very useful when trying to record and replay inclusion operations without it beind influenced by the aggressive caching done inside the FileManager to avoid redundant system calls and filesystem operations. The work to compute and return this is only done in the presence of callbacks, so it should have no effect on normal compilation. Patch by Manuel Klimek. llvm-svn: 127742
186 lines
6.2 KiB
C++
186 lines
6.2 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() { }
|
|
|
|
|
|
InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
|
|
InclusionKind Kind,
|
|
llvm::StringRef FileName,
|
|
bool InQuotes, const FileEntry *File,
|
|
SourceRange Range)
|
|
: PreprocessingDirective(InclusionDirectiveKind, Range),
|
|
InQuotes(InQuotes), Kind(Kind), File(File)
|
|
{
|
|
char *Memory
|
|
= (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>());
|
|
memcpy(Memory, FileName.data(), FileName.size());
|
|
Memory[FileName.size()] = 0;
|
|
this->FileName = llvm::StringRef(Memory, FileName.size());
|
|
}
|
|
|
|
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 Token &Id,
|
|
const MacroInfo *MI) {
|
|
SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
|
|
MacroDefinition *Def
|
|
= new (*this) MacroDefinition(Id.getIdentifierInfo(),
|
|
MI->getDefinitionLoc(),
|
|
R);
|
|
MacroDefinitions[MI] = Def;
|
|
PreprocessedEntities.push_back(Def);
|
|
}
|
|
|
|
void PreprocessingRecord::MacroUndefined(const Token &Id,
|
|
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,
|
|
const llvm::SmallVectorImpl<char> &RawPath) {
|
|
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(*this, Kind, FileName, !IsAngled,
|
|
File, SourceRange(HashLoc, EndLoc));
|
|
PreprocessedEntities.push_back(ID);
|
|
}
|