forked from OSchip/llvm-project
Optionally store a PreprocessingRecord in the preprocessor itself, and
tie its creation to a CC1 flag -detailed-preprocessing-record. llvm-svn: 98963
This commit is contained in:
parent
45a967cd62
commit
7f6d60dcc2
|
@ -448,7 +448,9 @@ def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">,
|
|||
HelpText<"Undefine the specified macro">;
|
||||
def undef : Flag<"-undef">, MetaVarName<"<macro>">,
|
||||
HelpText<"undef all system defines">;
|
||||
|
||||
def detailed_preprocessing_record : Flag<"-detailed-preprocessing-record">,
|
||||
HelpText<"include a detailed record of preprocessing actions">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Preprocessed Output Options
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -54,7 +54,6 @@ class ASTUnit {
|
|||
llvm::OwningPtr<TargetInfo> Target;
|
||||
llvm::OwningPtr<Preprocessor> PP;
|
||||
llvm::OwningPtr<ASTContext> Ctx;
|
||||
llvm::OwningPtr<PreprocessingRecord> Preprocessing;
|
||||
|
||||
/// Optional owned invocation, just used to make the invocation used in
|
||||
/// LoadFromCommandLine available.
|
||||
|
@ -137,12 +136,6 @@ public:
|
|||
const ASTContext &getASTContext() const { return *Ctx.get(); }
|
||||
ASTContext &getASTContext() { return *Ctx.get(); }
|
||||
|
||||
const PreprocessingRecord &getPreprocessingRecord() const {
|
||||
return *Preprocessing.get();
|
||||
}
|
||||
PreprocessingRecord &getPreprocessingRecord() { return *Preprocessing.get(); }
|
||||
bool hasPreprocessingRecord() { return Preprocessing.get() != 0; }
|
||||
|
||||
const FileManager &getFileManager() const { return FileMgr; }
|
||||
FileManager &getFileManager() { return FileMgr; }
|
||||
|
||||
|
@ -212,8 +205,7 @@ public:
|
|||
static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI,
|
||||
Diagnostic &Diags,
|
||||
bool OnlyLocalDecls = false,
|
||||
bool CaptureDiagnostics = false,
|
||||
bool WantPreprocessingRecord = false);
|
||||
bool CaptureDiagnostics = false);
|
||||
|
||||
/// LoadFromCommandLine - Create an ASTUnit from a vector of command line
|
||||
/// arguments, which must specify exactly one source file.
|
||||
|
@ -236,8 +228,7 @@ public:
|
|||
bool OnlyLocalDecls = false,
|
||||
RemappedFile *RemappedFiles = 0,
|
||||
unsigned NumRemappedFiles = 0,
|
||||
bool CaptureDiagnostics = false,
|
||||
bool WantPreprocessingRecord = false);
|
||||
bool CaptureDiagnostics = false);
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
|
|
@ -234,6 +234,9 @@ public:
|
|||
///
|
||||
/// \param isysroot if non-NULL, write a relocatable PCH file whose headers
|
||||
/// are relative to the given system root.
|
||||
///
|
||||
/// \param PPRec Record of the preprocessing actions that occurred while
|
||||
/// preprocessing this file, e.g., macro instantiations
|
||||
void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||
const char* isysroot);
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ public:
|
|||
unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler
|
||||
/// and target specific predefines.
|
||||
|
||||
unsigned DetailedRecord : 1; /// Whether we should maintain a detailed
|
||||
/// record of all macro definitions and
|
||||
/// instantiations.
|
||||
|
||||
/// The implicit PCH included at the start of the translation unit, or empty.
|
||||
std::string ImplicitPCHInclude;
|
||||
|
||||
|
@ -77,7 +81,7 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
PreprocessorOptions() : UsePredefines(true) {}
|
||||
PreprocessorOptions() : UsePredefines(true), DetailedRecord(false) {}
|
||||
|
||||
void addMacroDef(llvm::StringRef Name) {
|
||||
Macros.push_back(std::make_pair(Name, false));
|
||||
|
|
|
@ -14,10 +14,7 @@
|
|||
#ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
|
||||
#define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
|
||||
|
||||
#include "clang/Lex/PPCallbacks.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <vector>
|
||||
|
||||
|
@ -206,24 +203,6 @@ namespace clang {
|
|||
/// \brief Add a new preprocessed entity to this record.
|
||||
void addPreprocessedEntity(PreprocessedEntity *Entity);
|
||||
};
|
||||
|
||||
/// \brief Preprocessor callback action used to populate a preprocessing
|
||||
/// record.
|
||||
class PopulatePreprocessingRecord : public PPCallbacks {
|
||||
/// \brief The preprocessing record this action will populate.
|
||||
PreprocessingRecord &Record;
|
||||
|
||||
/// \brief Mapping from MacroInfo structures to their definitions.
|
||||
llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions;
|
||||
|
||||
public:
|
||||
explicit PopulatePreprocessingRecord(PreprocessingRecord &Record)
|
||||
: Record(Record) { }
|
||||
|
||||
virtual void MacroExpands(const Token &Id, const MacroInfo* MI);
|
||||
virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
inline void* operator new(size_t bytes, clang::PreprocessingRecord& PR,
|
||||
|
|
|
@ -43,7 +43,8 @@ class ScratchBuffer;
|
|||
class TargetInfo;
|
||||
class PPCallbacks;
|
||||
class DirectoryLookup;
|
||||
|
||||
class PreprocessingRecord;
|
||||
|
||||
/// Preprocessor - This object engages in a tight little dance with the lexer to
|
||||
/// efficiently preprocess tokens. Lexers know only about tokens within a
|
||||
/// single source file, and don't know anything about preprocessor-level issues
|
||||
|
@ -209,6 +210,13 @@ class Preprocessor {
|
|||
unsigned NumCachedTokenLexers;
|
||||
TokenLexer *TokenLexerCache[TokenLexerCacheSize];
|
||||
|
||||
/// \brief A record of the macro definitions and instantiations that
|
||||
/// occurred during preprocessing.
|
||||
///
|
||||
/// This is an optional side structure that can be enabled with
|
||||
/// \c createPreprocessingRecord() prior to preprocessing.
|
||||
llvm::OwningPtr<PreprocessingRecord> Record;
|
||||
|
||||
private: // Cached tokens state.
|
||||
typedef llvm::SmallVector<Token, 1> CachedTokensTy;
|
||||
|
||||
|
@ -348,6 +356,14 @@ public:
|
|||
/// It is an error to remove a handler that has not been registered.
|
||||
void RemoveCommentHandler(CommentHandler *Handler);
|
||||
|
||||
/// \brief Retrieve the preprocessing record, or NULL if there is no
|
||||
/// preprocessing record.
|
||||
PreprocessingRecord *getPreprocessingRecord() const { return Record.get(); }
|
||||
|
||||
/// \brief Create a new preprocessing record, which will keep track of
|
||||
/// all macro expansions, macro definitions, etc.
|
||||
void createPreprocessingRecord();
|
||||
|
||||
/// EnterMainSourceFile - Enter the specified FileID as the main source file,
|
||||
/// which implicitly adds the builtin defines etc.
|
||||
bool EnterMainSourceFile();
|
||||
|
|
|
@ -278,8 +278,7 @@ public:
|
|||
ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
|
||||
Diagnostic &Diags,
|
||||
bool OnlyLocalDecls,
|
||||
bool CaptureDiagnostics,
|
||||
bool WantPreprocessingRecord) {
|
||||
bool CaptureDiagnostics) {
|
||||
// Create the compiler instance to use for building the AST.
|
||||
CompilerInstance Clang;
|
||||
llvm::OwningPtr<ASTUnit> AST;
|
||||
|
@ -329,15 +328,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
|
|||
// Create the preprocessor.
|
||||
Clang.createPreprocessor();
|
||||
|
||||
// If the ASTUnit was requested to store information about preprocessing,
|
||||
// create storage for that information and attach an appropriate callback to
|
||||
// populate that storage.
|
||||
if (WantPreprocessingRecord) {
|
||||
AST->Preprocessing.reset(new PreprocessingRecord);
|
||||
Clang.getPreprocessor().addPPCallbacks(
|
||||
new PopulatePreprocessingRecord(*AST->Preprocessing));
|
||||
}
|
||||
|
||||
Act.reset(new TopLevelDeclTrackerAction(*AST));
|
||||
if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
|
||||
/*IsAST=*/false))
|
||||
|
@ -377,8 +367,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
|
|||
bool OnlyLocalDecls,
|
||||
RemappedFile *RemappedFiles,
|
||||
unsigned NumRemappedFiles,
|
||||
bool CaptureDiagnostics,
|
||||
bool WantPreprocessingRecord) {
|
||||
bool CaptureDiagnostics) {
|
||||
llvm::SmallVector<const char *, 16> Args;
|
||||
Args.push_back("<clang>"); // FIXME: Remove dummy argument.
|
||||
Args.insert(Args.end(), ArgBegin, ArgEnd);
|
||||
|
@ -430,6 +419,5 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
|
|||
|
||||
CI->getFrontendOpts().DisableFree = true;
|
||||
return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
|
||||
CaptureDiagnostics,
|
||||
WantPreprocessingRecord);
|
||||
CaptureDiagnostics);
|
||||
}
|
||||
|
|
|
@ -224,6 +224,9 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags,
|
|||
PP->setPTHManager(PTHMgr);
|
||||
}
|
||||
|
||||
if (PPOpts.DetailedRecord)
|
||||
PP->createPreprocessingRecord();
|
||||
|
||||
InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
|
||||
|
||||
// Handle generating dependencies, if requested.
|
||||
|
|
|
@ -575,6 +575,8 @@ static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
|
|||
}
|
||||
if (!Opts.UsePredefines)
|
||||
Res.push_back("-undef");
|
||||
if (Opts.DetailedRecord)
|
||||
Res.push_back("-detailed-preprocessing-record");
|
||||
if (!Opts.ImplicitPCHInclude.empty()) {
|
||||
Res.push_back("-include-pch");
|
||||
Res.push_back(Opts.ImplicitPCHInclude);
|
||||
|
@ -1232,7 +1234,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
|
|||
else
|
||||
Opts.TokenCache = Opts.ImplicitPTHInclude;
|
||||
Opts.UsePredefines = !Args.hasArg(OPT_undef);
|
||||
|
||||
Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
|
||||
// Add macros from the command line.
|
||||
for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U),
|
||||
ie = Args.filtered_end(); it != ie; ++it) {
|
||||
|
|
|
@ -21,19 +21,3 @@ void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
|
|||
PreprocessedEntities.push_back(Entity);
|
||||
}
|
||||
|
||||
void PopulatePreprocessingRecord::MacroExpands(const Token &Id,
|
||||
const MacroInfo* MI) {
|
||||
Record.addPreprocessedEntity(
|
||||
new (Record) MacroInstantiation(Id.getIdentifierInfo(),
|
||||
Id.getLocation(),
|
||||
MacroDefinitions[MI]));
|
||||
}
|
||||
|
||||
void PopulatePreprocessingRecord::MacroDefined(const IdentifierInfo *II,
|
||||
const MacroInfo *MI) {
|
||||
SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
|
||||
MacroDefinition *Def
|
||||
= new (Record) MacroDefinition(II, MI->getDefinitionLoc(), R);
|
||||
MacroDefinitions[MI] = Def;
|
||||
Record.addPreprocessedEntity(Def);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/MacroInfo.h"
|
||||
#include "clang/Lex/Pragma.h"
|
||||
#include "clang/Lex/PreprocessingRecord.h"
|
||||
#include "clang/Lex/ScratchBuffer.h"
|
||||
#include "clang/Lex/LexDiagnostic.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
|
@ -627,3 +628,47 @@ bool Preprocessor::HandleComment(Token &result, SourceRange Comment) {
|
|||
}
|
||||
|
||||
CommentHandler::~CommentHandler() { }
|
||||
|
||||
namespace {
|
||||
/// \brief Preprocessor callback action used to populate a preprocessing
|
||||
/// record.
|
||||
class PopulatePreprocessingRecord : public PPCallbacks {
|
||||
/// \brief The preprocessing record this action will populate.
|
||||
PreprocessingRecord &Record;
|
||||
|
||||
/// \brief Mapping from MacroInfo structures to their definitions.
|
||||
llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions;
|
||||
|
||||
public:
|
||||
explicit PopulatePreprocessingRecord(PreprocessingRecord &Record)
|
||||
: Record(Record) { }
|
||||
|
||||
virtual void MacroExpands(const Token &Id, const MacroInfo* MI);
|
||||
virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
|
||||
};
|
||||
}
|
||||
|
||||
void PopulatePreprocessingRecord::MacroExpands(const Token &Id,
|
||||
const MacroInfo* MI) {
|
||||
Record.addPreprocessedEntity(
|
||||
new (Record) MacroInstantiation(Id.getIdentifierInfo(),
|
||||
Id.getLocation(),
|
||||
MacroDefinitions[MI]));
|
||||
}
|
||||
|
||||
void PopulatePreprocessingRecord::MacroDefined(const IdentifierInfo *II,
|
||||
const MacroInfo *MI) {
|
||||
SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
|
||||
MacroDefinition *Def
|
||||
= new (Record) MacroDefinition(II, MI->getDefinitionLoc(), R);
|
||||
MacroDefinitions[MI] = Def;
|
||||
Record.addPreprocessedEntity(Def);
|
||||
}
|
||||
|
||||
void Preprocessor::createPreprocessingRecord() {
|
||||
if (Record)
|
||||
return;
|
||||
|
||||
Record.reset(new PreprocessingRecord);
|
||||
addPPCallbacks(new PopulatePreprocessingRecord(*Record));
|
||||
}
|
||||
|
|
|
@ -430,11 +430,11 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
|
|||
return true;
|
||||
|
||||
// Walk the preprocessing record.
|
||||
if (CXXUnit->hasPreprocessingRecord()) {
|
||||
if (PreprocessingRecord *PPRec
|
||||
= CXXUnit->getPreprocessor().getPreprocessingRecord()) {
|
||||
// FIXME: Once we have the ability to deserialize a preprocessing record,
|
||||
// do so.
|
||||
PreprocessingRecord &PPRec = CXXUnit->getPreprocessingRecord();
|
||||
for (PreprocessingRecord::iterator E = PPRec.begin(), EEnd = PPRec.end();
|
||||
for (PreprocessingRecord::iterator E = PPRec->begin(),EEnd = PPRec->end();
|
||||
E != EEnd; ++E) {
|
||||
if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
|
||||
if (Visit(MakeMacroInstantiationCursor(MI, CXXUnit)))
|
||||
|
@ -1014,7 +1014,8 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
|
|||
Args.push_back(source_filename);
|
||||
Args.insert(Args.end(), command_line_args,
|
||||
command_line_args + num_command_line_args);
|
||||
|
||||
Args.push_back("-Xclang");
|
||||
Args.push_back("-detailed-preprocessing-record");
|
||||
unsigned NumErrors = Diags->getNumErrors();
|
||||
|
||||
#ifdef USE_CRASHTRACER
|
||||
|
@ -1028,8 +1029,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
|
|||
CXXIdx->getOnlyLocalDecls(),
|
||||
RemappedFiles.data(),
|
||||
RemappedFiles.size(),
|
||||
/*CaptureDiagnostics=*/true,
|
||||
/*WantPreprocessingRecord=*/true));
|
||||
/*CaptureDiagnostics=*/true));
|
||||
|
||||
// FIXME: Until we have broader testing, just drop the entire AST if we
|
||||
// encountered an error.
|
||||
|
@ -1114,6 +1114,9 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
|
|||
TemporaryFiles.push_back(DiagnosticsFile);
|
||||
argv.push_back("-fdiagnostics-binary");
|
||||
|
||||
argv.push_back("-Xclang");
|
||||
argv.push_back("-detailed-preprocessing-record");
|
||||
|
||||
// Add the null terminator.
|
||||
argv.push_back(NULL);
|
||||
|
||||
|
|
Loading…
Reference in New Issue