diff options
-rw-r--r-- | include/clang/Driver/CC1Options.td | 4 | ||||
-rw-r--r-- | include/clang/Frontend/ASTUnit.h | 13 | ||||
-rw-r--r-- | include/clang/Frontend/PCHWriter.h | 3 | ||||
-rw-r--r-- | include/clang/Frontend/PreprocessorOptions.h | 6 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessingRecord.h | 21 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 18 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 18 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 4 | ||||
-rw-r--r-- | lib/Lex/PreprocessingRecord.cpp | 16 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 45 | ||||
-rw-r--r-- | tools/CIndex/CIndex.cpp | 15 |
12 files changed, 93 insertions, 73 deletions
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 1ecd8d6ada..6a4bec1ac8 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -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 //===----------------------------------------------------------------------===// diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 0616d03226..e9a982bb26 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -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 diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 212130e2ea..c05e2436bc 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -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); diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h index 7ba7c5c38d..891359b747 100644 --- a/include/clang/Frontend/PreprocessorOptions.h +++ b/include/clang/Frontend/PreprocessorOptions.h @@ -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)); diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index e673b4a7ca..c00da563a1 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -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, diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index a4910f714f..81fbedcfed 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -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(); diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 1aaa536cb3..935c415243 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -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); } diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 5d399bd944..bb0d308e7b 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -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. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 5798f2f710..d47fcf6f9b 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -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) { diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp index 3e0a03b74f..83268e0134 100644 --- a/lib/Lex/PreprocessingRecord.cpp +++ b/lib/Lex/PreprocessingRecord.cpp @@ -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); -} diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 917a2e7412..d9aaed4a48 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -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)); +} diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index c51ca7f119..f20bb75374 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -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); |