diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-03-19 16:15:56 +0000 | 
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-03-19 16:15:56 +0000 | 
| commit | 7f6d60dcc2cea9975c125fe6750ecc39af6a6fb0 (patch) | |
| tree | be9ba62d824d411415b67cc23233856110c3bdff /clang | |
| parent | 45a967cd628f44cdb8e3430ccddbd8c8c6a3b1af (diff) | |
| download | bcm5719-llvm-7f6d60dcc2cea9975c125fe6750ecc39af6a6fb0.tar.gz bcm5719-llvm-7f6d60dcc2cea9975c125fe6750ecc39af6a6fb0.zip  | |
Optionally store a PreprocessingRecord in the preprocessor itself, and
tie its creation to a CC1 flag -detailed-preprocessing-record.
llvm-svn: 98963
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Driver/CC1Options.td | 4 | ||||
| -rw-r--r-- | clang/include/clang/Frontend/ASTUnit.h | 13 | ||||
| -rw-r--r-- | clang/include/clang/Frontend/PCHWriter.h | 3 | ||||
| -rw-r--r-- | clang/include/clang/Frontend/PreprocessorOptions.h | 6 | ||||
| -rw-r--r-- | clang/include/clang/Lex/PreprocessingRecord.h | 21 | ||||
| -rw-r--r-- | clang/include/clang/Lex/Preprocessor.h | 18 | ||||
| -rw-r--r-- | clang/lib/Frontend/ASTUnit.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Lex/PreprocessingRecord.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Lex/Preprocessor.cpp | 45 | ||||
| -rw-r--r-- | clang/tools/CIndex/CIndex.cpp | 15 | 
12 files changed, 93 insertions, 73 deletions
diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 1ecd8d6adaf..6a4bec1ac85 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/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/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 0616d03226a..e9a982bb260 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/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/clang/include/clang/Frontend/PCHWriter.h b/clang/include/clang/Frontend/PCHWriter.h index 212130e2ea6..c05e2436bcb 100644 --- a/clang/include/clang/Frontend/PCHWriter.h +++ b/clang/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/clang/include/clang/Frontend/PreprocessorOptions.h b/clang/include/clang/Frontend/PreprocessorOptions.h index 7ba7c5c38da..891359b7478 100644 --- a/clang/include/clang/Frontend/PreprocessorOptions.h +++ b/clang/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/clang/include/clang/Lex/PreprocessingRecord.h b/clang/include/clang/Lex/PreprocessingRecord.h index e673b4a7caa..c00da563a18 100644 --- a/clang/include/clang/Lex/PreprocessingRecord.h +++ b/clang/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/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index a4910f714fd..81fbedcfedd 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/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/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 1aaa536cb34..935c4152437 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/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/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 5d399bd944e..bb0d308e7b4 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/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/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 5798f2f7100..d47fcf6f9b7 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/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/clang/lib/Lex/PreprocessingRecord.cpp b/clang/lib/Lex/PreprocessingRecord.cpp index 3e0a03b74f8..83268e0134a 100644 --- a/clang/lib/Lex/PreprocessingRecord.cpp +++ b/clang/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/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 917a2e7412f..d9aaed4a485 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/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/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp index c51ca7f1190..f20bb753747 100644 --- a/clang/tools/CIndex/CIndex.cpp +++ b/clang/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);  | 

