diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-03-27 16:47:18 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-03-27 16:47:18 +0000 |
commit | bf7fc9c542f2d7b47aaa5a387bbac5a25005c00e (patch) | |
tree | 420f4fc92dbde3650028a8bc112afc455891bb68 /clang/lib | |
parent | 0afce43be124b77e5efa7907cc150f1d80ac3f1d (diff) | |
download | llvm-bf7fc9c542f2d7b47aaa5a387bbac5a25005c00e.zip llvm-bf7fc9c542f2d7b47aaa5a387bbac5a25005c00e.tar.gz llvm-bf7fc9c542f2d7b47aaa5a387bbac5a25005c00e.tar.bz2 |
<rdar://problem/13509689> Introduce -module-file-info option that provides information about a particular module file.
This option can be useful for end users who want to know why they
ended up with a ton of different variants of the "std" module in their
module cache. This problem should go away over time, as we reduce the
need for module variants, but it will never go away entirely.
llvm-svn: 178148
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Driver/Driver.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Driver/Types.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 125 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendOptions.cpp | 2 | ||||
-rw-r--r-- | clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Serialization/ModuleManager.cpp | 14 |
9 files changed, 163 insertions, 8 deletions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 706409d..29ed5cf 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -126,6 +126,7 @@ const { // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler. } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || + (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || (PhaseArg = DAL.getLastArg(options::OPT__migrate)) || @@ -1170,6 +1171,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, return new MigrateJobAction(Input, types::TY_Remap); } else if (Args.hasArg(options::OPT_emit_ast)) { return new CompileJobAction(Input, types::TY_AST); + } else if (Args.hasArg(options::OPT_module_file_info)) { + return new CompileJobAction(Input, types::TY_ModuleFile); } else if (IsUsingLTO(Args)) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; @@ -1432,7 +1435,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, } // Default to writing to stdout? - if (AtTopLevel && isa<PreprocessJobAction>(JA) && !CCGenDiagnostics) + if (AtTopLevel && !CCGenDiagnostics && + (isa<PreprocessJobAction>(JA) || JA.getType() == types::TY_ModuleFile)) return "-"; // Output to a temporary file? diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index c7e47ad..fa3128bb 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1860,6 +1860,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-S"); } else if (JA.getType() == types::TY_AST) { CmdArgs.push_back("-emit-pch"); + } else if (JA.getType() == types::TY_ModuleFile) { + CmdArgs.push_back("-module-file-info"); } else if (JA.getType() == types::TY_RewrittenObjC) { CmdArgs.push_back("-rewrite-objc"); rewriteKind = RK_NonFragile; @@ -3696,6 +3698,9 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, else if (II.getType() == types::TY_AST) D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString(); + else if (II.getType() == types::TY_ModuleFile) + D.Diag(diag::err_drv_no_module_support) + << getToolChain().getTripleString(); if (types::canTypeBeUserSpecified(II.getType())) { CmdArgs.push_back("-x"); @@ -3826,6 +3831,9 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, else if (II.getType() == types::TY_AST) D.Diag(clang::diag::err_drv_no_ast_support) << getToolChain().getTripleString(); + else if (II.getType() == types::TY_ModuleFile) + D.Diag(diag::err_drv_no_module_support) + << getToolChain().getTripleString(); if (II.isFilename()) CmdArgs.push_back(II.getFilename()); diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index 9665095..7d22596 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -87,7 +87,7 @@ bool types::isAcceptedByClang(ID Id) { case TY_ObjCHeader: case TY_PP_ObjCHeader: case TY_CXXHeader: case TY_PP_CXXHeader: case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: - case TY_AST: + case TY_AST: case TY_ModuleFile: case TY_LLVM_IR: case TY_LLVM_BC: return true; } @@ -164,6 +164,7 @@ types::ID types::lookupTypeForExtension(const char *Ext) { .Case("F90", TY_Fortran) .Case("F95", TY_Fortran) .Case("mii", TY_PP_ObjCXX) + .Case("pcm", TY_ModuleFile) .Default(TY_INVALID); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 2d945b5..0fb8e58 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -644,6 +644,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::InitOnly; break; case OPT_fsyntax_only: Opts.ProgramAction = frontend::ParseSyntaxOnly; break; + case OPT_module_file_info: + Opts.ProgramAction = frontend::ModuleFileInfo; break; case OPT_print_decl_contexts: Opts.ProgramAction = frontend::PrintDeclContext; break; case OPT_print_preamble: @@ -779,7 +781,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, .Case("objective-c-header", IK_ObjC) .Case("c++-header", IK_CXX) .Case("objective-c++-header", IK_ObjCXX) - .Case("ast", IK_AST) + .Cases("ast", "pcm", IK_AST) .Case("ir", IK_LLVM_IR) .Default(IK_None); if (DashX == IK_None) @@ -1465,6 +1467,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, case frontend::GeneratePCH: case frontend::GeneratePTH: case frontend::ParseSyntaxOnly: + case frontend::ModuleFileInfo: case frontend::PluginAction: case frontend::PrintDeclContext: case frontend::RewriteObjC: @@ -1627,6 +1630,8 @@ llvm::APInt ModuleSignature::getAsInteger() const { } std::string CompilerInvocation::getModuleHash() const { + // Note: For QoI reasons, the things we use as a hash here should all be + // dumped via the -module-info flag. using llvm::hash_code; using llvm::hash_value; using llvm::hash_combine; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index f3466f0..5c7567f 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -19,6 +19,7 @@ #include "clang/Lex/Pragma.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/Parser.h" +#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/FileSystem.h" @@ -316,6 +317,130 @@ ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, return new ASTConsumer(); } +ASTConsumer *DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + return new ASTConsumer(); +} + +namespace { + /// \brief AST reader listener that dumps module information for a module + /// file. + class DumpModuleInfoListener : public ASTReaderListener { + llvm::raw_ostream &Out; + + public: + DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { } + +#define DUMP_BOOLEAN(Value, Text) \ + Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n" + + virtual bool ReadFullVersionInformation(StringRef FullVersion) { + Out.indent(2) + << "Generated by " + << (FullVersion == getClangFullRepositoryVersion()? "this" + : "a different") + << " Clang: " << FullVersion << "\n"; + return ASTReaderListener::ReadFullVersionInformation(FullVersion); + } + + virtual bool ReadLanguageOptions(const LangOptions &LangOpts, + bool Complain) { + Out.indent(2) << "Language options:\n"; +#define LANGOPT(Name, Bits, Default, Description) \ + DUMP_BOOLEAN(LangOpts.Name, Description); +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ + Out.indent(4) << Description << ": " \ + << static_cast<unsigned>(LangOpts.get##Name()) << "\n"; +#define VALUE_LANGOPT(Name, Bits, Default, Description) \ + Out.indent(4) << Description << ": " << LangOpts.Name << "\n"; +#define BENIGN_LANGOPT(Name, Bits, Default, Description) +#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) +#include "clang/Basic/LangOptions.def" + return false; + } + + virtual bool ReadTargetOptions(const TargetOptions &TargetOpts, + bool Complain) { + Out.indent(2) << "Target options:\n"; + Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n"; + Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n"; + Out.indent(4) << " ABI: " << TargetOpts.ABI << "\n"; + Out.indent(4) << " C++ ABI: " << TargetOpts.CXXABI << "\n"; + Out.indent(4) << " Linker version: " << TargetOpts.LinkerVersion << "\n"; + + if (!TargetOpts.FeaturesAsWritten.empty()) { + Out.indent(4) << "Target features:\n"; + for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); + I != N; ++I) { + Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n"; + } + } + + return false; + } + + virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, + bool Complain) { + Out.indent(2) << "Header search options:\n"; + Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n"; + DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes, + "Use builtin include directories [-nobuiltininc]"); + DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes, + "Use standard system include directories [-nostdinc]"); + DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes, + "Use standard C++ include directories [-nostdinc++]"); + DUMP_BOOLEAN(HSOpts.UseLibcxx, + "Use libc++ (rather than libstdc++) [-stdlib=]"); + return false; + } + + virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, + bool Complain, + std::string &SuggestedPredefines) { + Out.indent(2) << "Preprocessor options:\n"; + DUMP_BOOLEAN(PPOpts.UsePredefines, + "Uses compiler/target-specific predefines [-undef]"); + DUMP_BOOLEAN(PPOpts.DetailedRecord, + "Uses detailed preprocessing record (for indexing)"); + + if (!PPOpts.Macros.empty()) { + Out.indent(4) << "Predefined macros:\n"; + } + + for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator + I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end(); + I != IEnd; ++I) { + Out.indent(6); + if (I->second) + Out << "-U"; + else + Out << "-D"; + Out << I->first << "\n"; + } + return false; + } +#undef DUMP_BOOLEAN + }; +} + +void DumpModuleInfoAction::ExecuteAction() { + // Set up the output file. + llvm::OwningPtr<llvm::raw_fd_ostream> OutFile; + StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile; + if (!OutputFileName.empty() && OutputFileName != "-") { + std::string ErrorInfo; + OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str().c_str(), + ErrorInfo)); + } + llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs(); + + Out << "Information for module file '" << getCurrentFile() << "':\n"; + DumpModuleInfoListener Listener(Out); + ASTReader::readASTFileControlBlock(getCurrentFile(), + getCompilerInstance().getFileManager(), + Listener); +} + //===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// diff --git a/clang/lib/Frontend/FrontendOptions.cpp b/clang/lib/Frontend/FrontendOptions.cpp index ea4005f..f1823c6 100644 --- a/clang/lib/Frontend/FrontendOptions.cpp +++ b/clang/lib/Frontend/FrontendOptions.cpp @@ -13,7 +13,7 @@ using namespace clang; InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) { return llvm::StringSwitch<InputKind>(Extension) - .Case("ast", IK_AST) + .Cases("ast", "pcm", IK_AST) .Case("c", IK_C) .Cases("S", "s", IK_Asm) .Case("i", IK_PreprocessedC) diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index ad8eb04..b0d76da 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -62,6 +62,7 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) { case GeneratePTH: return new GeneratePTHAction(); case InitOnly: return new InitOnlyAction(); case ParseSyntaxOnly: return new SyntaxOnlyAction(); + case ModuleFileInfo: return new DumpModuleInfoAction(); case PluginAction: { for (FrontendPluginRegistry::iterator it = diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 55e333a..4c2d219 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3487,10 +3487,9 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, if (Record[0] != VERSION_MAJOR) return true; - const std::string &CurBranch = getClangFullRepositoryVersion(); - if (StringRef(CurBranch) != Blob) + if (Listener.ReadFullVersionInformation(Blob)) return true; - + break; } case LANGUAGE_OPTIONS: diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 193a38b..f3d53ad 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -29,7 +29,19 @@ using namespace serialization; ModuleFile *ModuleManager::lookup(StringRef Name) { const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, /*cacheFailure=*/false); - return Modules[Entry]; + if (Entry) + return lookup(Entry); + + return 0; +} + +ModuleFile *ModuleManager::lookup(const FileEntry *File) { + llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known + = Modules.find(File); + if (Known == Modules.end()) + return 0; + + return Known->second; } llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { |