
CXTranslationUnit_NestedMacroInstantiations, which indicates whether we want to see "nested" macro instantiations (e.g., those that occur inside other macro instantiations) within the detailed preprocessing record. Many clients (e.g., those that only care about visible tokens) don't care about this information, and in code that uses preprocessor metaprogramming, this information can have a very high cost. Addresses <rdar://problem/9389320>. llvm-svn: 130990
191 lines
6.4 KiB
C++
191 lines
6.4 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(bool IncludeNestedMacroInstantiations)
|
|
: IncludeNestedMacroInstantiations(IncludeNestedMacroInstantiations),
|
|
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 (!IncludeNestedMacroInstantiations && Id.getLocation().isMacroID())
|
|
return;
|
|
|
|
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,
|
|
llvm::StringRef SearchPath,
|
|
llvm::StringRef RelativePath) {
|
|
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);
|
|
}
|