On Thu, Apr 27, 2017 at 6:49 PM, Richard Smith via cfe-commits <cfe-commits@lists.llvm.org> wrote: > Author: rsmith > Date: Thu Apr 27 20:49:42 2017 > New Revision: 301610 > > URL: http://llvm.org/viewvc/llvm-project?rev=301610&view=rev > Log: > Move functionality for handling module maps as inputs from the -emit-module > action to the general FrontendAction infrastructure. > > This permits applying -E, -ast-dump, -fsyntax-only, and so on to a module map > compilation. (The -E form is not currently especially useful yet as there's no > good way to take the output and use it to actually build a module.)
Yay! This is awesome Richard!! > In order to support this, -cc1 now accepts -x <lang>-module-map in all cases > where it accepts -x <lang> for a language we can parse (not ir/ast). And for > uniformity, we also accept -x <lang>-header for all such languages (we used > to reject for cuda and renderscript), and -x <lang>-cpp-output for all such > languages (we used to reject for c, cl, and renderscript). > > (None of these new alternatives are accepted by the driver yet, so no > user-visible changes.) > > Added: > cfe/trunk/test/Modules/preprocess-module.cpp > Modified: > cfe/trunk/include/clang/Frontend/FrontendActions.h > cfe/trunk/include/clang/Frontend/FrontendOptions.h > cfe/trunk/lib/Frontend/CompilerInstance.cpp > cfe/trunk/lib/Frontend/CompilerInvocation.cpp > cfe/trunk/lib/Frontend/FrontendAction.cpp > cfe/trunk/lib/Frontend/FrontendActions.cpp > cfe/trunk/lib/Frontend/FrontendOptions.cpp > > Modified: cfe/trunk/include/clang/Frontend/FrontendActions.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendActions.h?rev=301610&r1=301609&r2=301610&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Frontend/FrontendActions.h (original) > +++ cfe/trunk/include/clang/Frontend/FrontendActions.h Thu Apr 27 20:49:42 > 2017 > @@ -99,8 +99,6 @@ class GenerateModuleAction : public ASTF > CreateOutputFile(CompilerInstance &CI, StringRef InFile) = 0; > > protected: > - bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) > override; > - > std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, > StringRef InFile) override; > > @@ -112,20 +110,11 @@ protected: > }; > > class GenerateModuleFromModuleMapAction : public GenerateModuleAction { > - clang::Module *Module = nullptr; > - const FileEntry *ModuleMapForUniquing = nullptr; > - bool IsSystem = false; > - > private: > bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) > override; > > std::unique_ptr<raw_pwrite_stream> > CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; > - > -public: > - GenerateModuleFromModuleMapAction() {} > - GenerateModuleFromModuleMapAction(const FileEntry *ModuleMap, bool > IsSystem) > - : ModuleMapForUniquing(ModuleMap), IsSystem(IsSystem) {} > }; > > class GenerateModuleInterfaceAction : public GenerateModuleAction { > > Modified: cfe/trunk/include/clang/Frontend/FrontendOptions.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendOptions.h?rev=301610&r1=301609&r2=301610&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Frontend/FrontendOptions.h (original) > +++ cfe/trunk/include/clang/Frontend/FrontendOptions.h Thu Apr 27 20:49:42 > 2017 > @@ -23,6 +23,7 @@ class MemoryBuffer; > } > > namespace clang { > +class FileEntry; > > namespace frontend { > enum ActionKind { > @@ -100,9 +101,8 @@ public: > Precompiled > }; > > - constexpr InputKind(Language L = Unknown, bool PP = false) > - : Lang(L), Fmt(Source), Preprocessed(PP) {} > - constexpr InputKind(Language L, Format F, bool PP = false) > + constexpr InputKind(Language L = Unknown, Format F = Source, > + bool PP = false) > : Lang(L), Fmt(F), Preprocessed(PP) {} > > Language getLanguage() const { return static_cast<Language>(Lang); } > @@ -118,6 +118,9 @@ public: > InputKind getPreprocessed() const { > return InputKind(getLanguage(), getFormat(), true); > } > + InputKind withFormat(Format F) const { > + return InputKind(getLanguage(), F, isPreprocessed()); > + } > }; > > /// \brief An input file for the front end. > @@ -256,6 +259,10 @@ public: > /// The input files and their types. > std::vector<FrontendInputFile> Inputs; > > + /// When the input is a module map, the original module map file from which > + /// that map was inferred, if any (for umbrella modules). > + std::string OriginalModuleMap; > + > /// The output file, if any. > std::string OutputFile; > > > Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=301610&r1=301609&r2=301610&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original) > +++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Thu Apr 27 20:49:42 2017 > @@ -1080,6 +1080,8 @@ static bool compileModuleImpl(CompilerIn > FrontendOpts.DisableFree = false; > FrontendOpts.GenerateGlobalModuleIndex = false; > FrontendOpts.BuildingImplicitModule = true; > + FrontendOpts.OriginalModuleMap = > + ModMap.getModuleMapFileForUniquing(Module)->getName(); > // Force implicitly-built modules to hash the content of the module file. > HSOpts.ModulesHashContent = true; > FrontendOpts.Inputs.clear(); > @@ -1129,11 +1131,12 @@ static bool compileModuleImpl(CompilerIn > if (const FileEntry *ModuleMapFile = > ModMap.getContainingModuleMapFile(Module)) { > // Use the module map where this module resides. > - FrontendOpts.Inputs.emplace_back(ModuleMapFile->getName(), IK); > + FrontendOpts.Inputs.emplace_back(ModuleMapFile->getName(), IK, > + +Module->IsSystem); > } else { > SmallString<128> FakeModuleMapFile(Module->Directory->getName()); > llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map"); > - FrontendOpts.Inputs.emplace_back(FakeModuleMapFile, IK); > + FrontendOpts.Inputs.emplace_back(FakeModuleMapFile, IK, > +Module->IsSystem); > > llvm::raw_string_ostream OS(InferredModuleMapContent); > Module->print(OS); > @@ -1146,11 +1149,6 @@ static bool compileModuleImpl(CompilerIn > SourceMgr.overrideFileContents(ModuleMapFile, > std::move(ModuleMapBuffer)); > } > > - // Construct a module-generating action. Passing through the module map is > - // safe because the FileManager is shared between the compiler instances. > - GenerateModuleFromModuleMapAction CreateModuleAction( > - ModMap.getModuleMapFileForUniquing(Module), Module->IsSystem); > - > ImportingInstance.getDiagnostics().Report(ImportLoc, > diag::remark_module_build) > << Module->Name << ModuleFileName; > @@ -1159,8 +1157,12 @@ static bool compileModuleImpl(CompilerIn > // thread so that we get a stack large enough. > const unsigned ThreadStackSize = 8 << 20; > llvm::CrashRecoveryContext CRC; > - CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(CreateModuleAction); > }, > - ThreadStackSize); > + CRC.RunSafelyOnThread( > + [&]() { > + GenerateModuleFromModuleMapAction Action; > + Instance.ExecuteAction(Action); > + }, > + ThreadStackSize); > > ImportingInstance.getDiagnostics().Report(ImportLoc, > diag::remark_module_build_done) > > Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=301610&r1=301609&r2=301610&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original) > +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Thu Apr 27 20:49:42 2017 > @@ -1350,30 +1350,51 @@ static InputKind ParseFrontendArgs(Front > InputKind DashX(InputKind::Unknown); > if (const Arg *A = Args.getLastArg(OPT_x)) { > StringRef XValue = A->getValue(); > + > + // Parse suffixes: '<lang>(-header|[-module-map][-cpp-output])'. > + // FIXME: Supporting '<lang>-header-cpp-output' would be useful. > + bool Preprocessed = XValue.consume_back("-cpp-output"); > + bool ModuleMap = XValue.consume_back("-module-map"); > + IsHeaderFile = > + !Preprocessed && !ModuleMap && XValue.consume_back("-header"); > + > + // Principal languages. > DashX = llvm::StringSwitch<InputKind>(XValue) > - .Cases("c", "c-header", "cpp-output", InputKind::C) > - .Cases("cl", "cl-header", InputKind::OpenCL) > - .Cases("cuda", "cuda-cpp-output", InputKind::CUDA) > - .Cases("c++", "c++-header", "c++-cpp-output", InputKind::CXX) > - .Cases("objective-c", "objective-c-header", > - "objective-c-cpp-output", "objc-cpp-output", > - InputKind::ObjC) > - .Cases("objective-c++", "objective-c++-header", > - "objective-c++-cpp-output", "objc++-cpp-output", > - InputKind::ObjCXX) > - .Case("renderscript", InputKind::RenderScript) > - .Case("assembler-with-cpp", InputKind::Asm) > - .Cases("ast", "pcm", > - InputKind(InputKind::Unknown, InputKind::Precompiled)) > - .Case("ir", InputKind::LLVM_IR) > - .Default(InputKind::Unknown); > + .Case("c", InputKind::C) > + .Case("cl", InputKind::OpenCL) > + .Case("cuda", InputKind::CUDA) > + .Case("c++", InputKind::CXX) > + .Case("objective-c", InputKind::ObjC) > + .Case("objective-c++", InputKind::ObjCXX) > + .Case("renderscript", InputKind::RenderScript) > + .Default(InputKind::Unknown); > + > + // "objc[++]-cpp-output" is an acceptable synonym for > + // "objective-c[++]-cpp-output". > + if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap) > + DashX = llvm::StringSwitch<InputKind>(XValue) > + .Case("objc", InputKind::ObjC) > + .Case("objc++", InputKind::ObjCXX) > + .Default(InputKind::Unknown); > + > + // Some special cases cannot be combined with suffixes. > + if (DashX.isUnknown() && !Preprocessed && !ModuleMap && !IsHeaderFile) > + DashX = llvm::StringSwitch<InputKind>(XValue) > + .Case("cpp-output", > InputKind(InputKind::C).getPreprocessed()) > + .Case("assembler-with-cpp", InputKind::Asm) > + .Cases("ast", "pcm", > + InputKind(InputKind::Unknown, > InputKind::Precompiled)) > + .Case("ir", InputKind::LLVM_IR) > + .Default(InputKind::Unknown); > + > if (DashX.isUnknown()) > Diags.Report(diag::err_drv_invalid_value) > << A->getAsString(Args) << A->getValue(); > > - if (XValue.endswith("cpp-output")) > + if (Preprocessed) > DashX = DashX.getPreprocessed(); > - IsHeaderFile = XValue.endswith("-header"); > + if (ModuleMap) > + DashX = DashX.withFormat(InputKind::ModuleMap); > } > > // '-' is the default input if none is given. > @@ -1393,6 +1414,12 @@ static InputKind ParseFrontendArgs(Front > if (i == 0) > DashX = IK; > } > + > + // The -emit-module action implicitly takes a module map. > + if (Opts.ProgramAction == frontend::GenerateModule && > + IK.getFormat() == InputKind::Source) > + IK = IK.withFormat(InputKind::ModuleMap); > + > Opts.Inputs.emplace_back(std::move(Inputs[i]), IK); > } > > > Modified: cfe/trunk/lib/Frontend/FrontendAction.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendAction.cpp?rev=301610&r1=301609&r2=301610&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/FrontendAction.cpp (original) > +++ cfe/trunk/lib/Frontend/FrontendAction.cpp Thu Apr 27 20:49:42 2017 > @@ -224,6 +224,231 @@ static bool ReadOriginalFileName(Compile > return true; > } > > +static SmallVectorImpl<char> & > +operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) { > + Includes.append(RHS.begin(), RHS.end()); > + return Includes; > +} > + > +static void addHeaderInclude(StringRef HeaderName, > + SmallVectorImpl<char> &Includes, > + const LangOptions &LangOpts, > + bool IsExternC) { > + if (IsExternC && LangOpts.CPlusPlus) > + Includes += "extern \"C\" {\n"; > + if (LangOpts.ObjC1) > + Includes += "#import \""; > + else > + Includes += "#include \""; > + > + Includes += HeaderName; > + > + Includes += "\"\n"; > + if (IsExternC && LangOpts.CPlusPlus) > + Includes += "}\n"; > +} > + > +/// \brief Collect the set of header includes needed to construct the given > +/// module and update the TopHeaders file set of the module. > +/// > +/// \param Module The module we're collecting includes from. > +/// > +/// \param Includes Will be augmented with the set of \#includes or \#imports > +/// needed to load all of the named headers. > +static std::error_code > +collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager > &FileMgr, > + ModuleMap &ModMap, clang::Module *Module, > + SmallVectorImpl<char> &Includes) { > + // Don't collect any headers for unavailable modules. > + if (!Module->isAvailable()) > + return std::error_code(); > + > + // Add includes for each of these headers. > + for (auto HK : {Module::HK_Normal, Module::HK_Private}) { > + for (Module::Header &H : Module->Headers[HK]) { > + Module->addTopHeader(H.Entry); > + // Use the path as specified in the module map file. We'll look for > this > + // file relative to the module build directory (the directory > containing > + // the module map file) so this will find the same file that we found > + // while parsing the module map. > + addHeaderInclude(H.NameAsWritten, Includes, LangOpts, > Module->IsExternC); > + } > + } > + // Note that Module->PrivateHeaders will not be a TopHeader. > + > + if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) { > + Module->addTopHeader(UmbrellaHeader.Entry); > + if (Module->Parent) > + // Include the umbrella header for submodules. > + addHeaderInclude(UmbrellaHeader.NameAsWritten, Includes, LangOpts, > + Module->IsExternC); > + } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) { > + // Add all of the headers we find in this subdirectory. > + std::error_code EC; > + SmallString<128> DirNative; > + llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative); > + > + vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); > + for (vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End; > + Dir != End && !EC; Dir.increment(EC)) { > + // Check whether this entry has an extension typically associated with > + // headers. > + if > (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->getName())) > + .Cases(".h", ".H", ".hh", ".hpp", true) > + .Default(false)) > + continue; > + > + const FileEntry *Header = FileMgr.getFile(Dir->getName()); > + // FIXME: This shouldn't happen unless there is a file system race. Is > + // that worth diagnosing? > + if (!Header) > + continue; > + > + // If this header is marked 'unavailable' in this module, don't include > + // it. > + if (ModMap.isHeaderUnavailableInModule(Header, Module)) > + continue; > + > + // Compute the relative path from the directory to this file. > + SmallVector<StringRef, 16> Components; > + auto PathIt = llvm::sys::path::rbegin(Dir->getName()); > + for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt) > + Components.push_back(*PathIt); > + SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten); > + for (auto It = Components.rbegin(), End = Components.rend(); It != End; > + ++It) > + llvm::sys::path::append(RelativeHeader, *It); > + > + // Include this header as part of the umbrella directory. > + Module->addTopHeader(Header); > + addHeaderInclude(RelativeHeader, Includes, LangOpts, > Module->IsExternC); > + } > + > + if (EC) > + return EC; > + } > + > + // Recurse into submodules. > + for (clang::Module::submodule_iterator Sub = Module->submodule_begin(), > + SubEnd = Module->submodule_end(); > + Sub != SubEnd; ++Sub) > + if (std::error_code Err = collectModuleHeaderIncludes( > + LangOpts, FileMgr, ModMap, *Sub, Includes)) > + return Err; > + > + return std::error_code(); > +} > + > +/// Parse a module map and compute the corresponding real input buffer that > +/// should be used to build the module described by that module map and the > +/// current module name. > +static std::unique_ptr<llvm::MemoryBuffer> > +getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename, > + bool IsSystem) { > + // Find the module map file. > + const FileEntry *ModuleMap = > + CI.getFileManager().getFile(Filename, /*openFile*/true); > + if (!ModuleMap) { > + CI.getDiagnostics().Report(diag::err_module_map_not_found) > + << Filename; > + return nullptr; > + } > + > + // Find the module map file from which it was generated, if different. > + const FileEntry *OriginalModuleMap = ModuleMap; > + StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap; > + if (!OriginalModuleMapName.empty()) { > + OriginalModuleMap = CI.getFileManager().getFile(OriginalModuleMapName, > + /*openFile*/ true); > + if (!OriginalModuleMap) { > + CI.getDiagnostics().Report(diag::err_module_map_not_found) > + << OriginalModuleMapName; > + return nullptr; > + } > + } > + > + // Parse the module map file. > + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); > + if (HS.loadModuleMapFile(ModuleMap, IsSystem)) > + return nullptr; > + > + if (CI.getLangOpts().CurrentModule.empty()) { > + CI.getDiagnostics().Report(diag::err_missing_module_name); > + > + // FIXME: Eventually, we could consider asking whether there was just > + // a single module described in the module map, and use that as a > + // default. Then it would be fairly trivial to just "compile" a module > + // map with a single module (the common case). > + return nullptr; > + } > + > + // If we're being run from the command-line, the module build stack will > not > + // have been filled in yet, so complete it now in order to allow us to > detect > + // module cycles. > + SourceManager &SourceMgr = CI.getSourceManager(); > + if (SourceMgr.getModuleBuildStack().empty()) > + SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule, > + FullSourceLoc(SourceLocation(), > SourceMgr)); > + > + // Dig out the module definition. > + Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, > + /*AllowSearch=*/false); > + if (!M) { > + CI.getDiagnostics().Report(diag::err_missing_module) > + << CI.getLangOpts().CurrentModule << Filename; > + > + return nullptr; > + } > + > + // Check whether we can build this module at all. > + clang::Module::Requirement Requirement; > + clang::Module::UnresolvedHeaderDirective MissingHeader; > + if (!M->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement, > + MissingHeader)) { > + if (MissingHeader.FileNameLoc.isValid()) { > + CI.getDiagnostics().Report(MissingHeader.FileNameLoc, > + diag::err_module_header_missing) > + << MissingHeader.IsUmbrella << MissingHeader.FileName; > + } else { > + CI.getDiagnostics().Report(diag::err_module_unavailable) > + << M->getFullModuleName() << Requirement.second << Requirement.first; > + } > + > + return nullptr; > + } > + > + if (OriginalModuleMap != ModuleMap) { > + M->IsInferred = true; > + HS.getModuleMap().setInferredModuleAllowedBy(M, OriginalModuleMap); > + } > + > + FileManager &FileMgr = CI.getFileManager(); > + > + // Collect the set of #includes we need to build the module. > + SmallString<256> HeaderContents; > + std::error_code Err = std::error_code(); > + if (Module::Header UmbrellaHeader = M->getUmbrellaHeader()) > + addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents, > + CI.getLangOpts(), M->IsExternC); > + Err = collectModuleHeaderIncludes( > + CI.getLangOpts(), FileMgr, > + CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M, > + HeaderContents); > + > + if (Err) { > + CI.getDiagnostics().Report(diag::err_module_cannot_create_includes) > + << M->getFullModuleName() << Err.message(); > + return nullptr; > + } > + > + // Inform the preprocessor that includes from within the input buffer > should > + // be resolved relative to the build directory of the module map file. > + CI.getPreprocessor().setMainFileDir(M->Directory); > + > + return llvm::MemoryBuffer::getMemBufferCopy( > + HeaderContents, Module::getModuleInputBufferName()); > +} > + > bool FrontendAction::BeginSourceFile(CompilerInstance &CI, > const FrontendInputFile &Input) { > assert(!Instance && "Already processing a source file!"); > @@ -232,6 +457,7 @@ bool FrontendAction::BeginSourceFile(Com > setCompilerInstance(&CI); > > StringRef InputFile = Input.getFile(); > + FrontendInputFile FileToProcess = Input; > bool HasBegunSourceFile = false; > if (!BeginInvocation(CI)) > goto failure; > @@ -297,6 +523,17 @@ bool FrontendAction::BeginSourceFile(Com > if (!CI.hasSourceManager()) > CI.createSourceManager(CI.getFileManager()); > > + // Set up embedding for any specified files. Do this before we load any > + // source files, including the primary module map for the compilation. > + for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) { > + if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true)) > + CI.getSourceManager().setFileIsTransient(FE); > + else > + CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << > F; > + } > + if (CI.getFrontendOpts().ModulesEmbedAllFiles) > + CI.getSourceManager().setAllFilesAreTransient(true); > + > // IR files bypass the rest of initialization. > if (Input.getKind().getLanguage() == InputKind::LLVM_IR) { > assert(hasIRSupport() && > @@ -360,13 +597,34 @@ bool FrontendAction::BeginSourceFile(Com > &CI.getPreprocessor()); > HasBegunSourceFile = true; > > + // For module map files, we first parse the module map and synthesize a > + // "<module-includes>" buffer before more conventional processing. > + if (Input.getKind().getFormat() == InputKind::ModuleMap) { > + CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap); > + > + auto Buffer = getInputBufferForModuleMap(CI, InputFile, > Input.isSystem()); > + if (!Buffer) > + goto failure; > + > + Module *CurrentModule = > + CI.getPreprocessor().getHeaderSearchInfo().lookupModule( > + CI.getLangOpts().CurrentModule, > + /*AllowSearch=*/false); > + assert(CurrentModule && "no module info for current module"); > + > + // The input that we end up processing is the generated buffer, not the > + // module map file itself. > + FileToProcess = FrontendInputFile( > + Buffer.release(), Input.getKind().withFormat(InputKind::Source), > + CurrentModule->IsSystem); > + } > + > // Initialize the action. > if (!BeginSourceFileAction(CI, InputFile)) > goto failure; > > - // Initialize the main file entry. It is important that this occurs after > - // BeginSourceFileAction, which may change CurrentInput during module > builds. > - if (!CI.InitializeSourceManager(CurrentInput)) > + // Initialize the main file entry. > + if (!CI.InitializeSourceManager(FileToProcess)) > goto failure; > > // Create the AST context and consumer unless this is a preprocessor only > @@ -498,6 +756,7 @@ bool FrontendAction::BeginSourceFile(Com > if (HasBegunSourceFile) > CI.getDiagnosticClient().EndSourceFile(); > CI.clearOutputFiles(/*EraseFiles=*/true); > + CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); > setCurrentInput(FrontendInputFile()); > setCompilerInstance(nullptr); > return false; > @@ -580,6 +839,7 @@ void FrontendAction::EndSourceFile() { > > setCompilerInstance(nullptr); > setCurrentInput(FrontendInputFile()); > + CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); > } > > bool FrontendAction::shouldEraseOutputFiles() { > > Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=301610&r1=301609&r2=301610&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/FrontendActions.cpp (original) > +++ cfe/trunk/lib/Frontend/FrontendActions.cpp Thu Apr 27 20:49:42 2017 > @@ -164,242 +164,9 @@ GenerateModuleAction::CreateASTConsumer( > return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); > } > > -bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, > - StringRef Filename) { > - // Set up embedding for any specified files. Do this before we load any > - // source files, including the primary module map for the compilation. > - for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) { > - if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true)) > - CI.getSourceManager().setFileIsTransient(FE); > - else > - CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << > F; > - } > - if (CI.getFrontendOpts().ModulesEmbedAllFiles) > - CI.getSourceManager().setAllFilesAreTransient(true); > - > - return true; > -} > - > - > -static SmallVectorImpl<char> & > -operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) { > - Includes.append(RHS.begin(), RHS.end()); > - return Includes; > -} > - > -static void addHeaderInclude(StringRef HeaderName, > - SmallVectorImpl<char> &Includes, > - const LangOptions &LangOpts, > - bool IsExternC) { > - if (IsExternC && LangOpts.CPlusPlus) > - Includes += "extern \"C\" {\n"; > - if (LangOpts.ObjC1) > - Includes += "#import \""; > - else > - Includes += "#include \""; > - > - Includes += HeaderName; > - > - Includes += "\"\n"; > - if (IsExternC && LangOpts.CPlusPlus) > - Includes += "}\n"; > -} > - > -/// \brief Collect the set of header includes needed to construct the given > -/// module and update the TopHeaders file set of the module. > -/// > -/// \param Module The module we're collecting includes from. > -/// > -/// \param Includes Will be augmented with the set of \#includes or \#imports > -/// needed to load all of the named headers. > -static std::error_code > -collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager > &FileMgr, > - ModuleMap &ModMap, clang::Module *Module, > - SmallVectorImpl<char> &Includes) { > - // Don't collect any headers for unavailable modules. > - if (!Module->isAvailable()) > - return std::error_code(); > - > - // Add includes for each of these headers. > - for (auto HK : {Module::HK_Normal, Module::HK_Private}) { > - for (Module::Header &H : Module->Headers[HK]) { > - Module->addTopHeader(H.Entry); > - // Use the path as specified in the module map file. We'll look for > this > - // file relative to the module build directory (the directory > containing > - // the module map file) so this will find the same file that we found > - // while parsing the module map. > - addHeaderInclude(H.NameAsWritten, Includes, LangOpts, > Module->IsExternC); > - } > - } > - // Note that Module->PrivateHeaders will not be a TopHeader. > - > - if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) { > - Module->addTopHeader(UmbrellaHeader.Entry); > - if (Module->Parent) > - // Include the umbrella header for submodules. > - addHeaderInclude(UmbrellaHeader.NameAsWritten, Includes, LangOpts, > - Module->IsExternC); > - } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) { > - // Add all of the headers we find in this subdirectory. > - std::error_code EC; > - SmallString<128> DirNative; > - llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative); > - > - vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); > - for (vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End; > - Dir != End && !EC; Dir.increment(EC)) { > - // Check whether this entry has an extension typically associated with > - // headers. > - if > (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->getName())) > - .Cases(".h", ".H", ".hh", ".hpp", true) > - .Default(false)) > - continue; > - > - const FileEntry *Header = FileMgr.getFile(Dir->getName()); > - // FIXME: This shouldn't happen unless there is a file system race. Is > - // that worth diagnosing? > - if (!Header) > - continue; > - > - // If this header is marked 'unavailable' in this module, don't include > - // it. > - if (ModMap.isHeaderUnavailableInModule(Header, Module)) > - continue; > - > - // Compute the relative path from the directory to this file. > - SmallVector<StringRef, 16> Components; > - auto PathIt = llvm::sys::path::rbegin(Dir->getName()); > - for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt) > - Components.push_back(*PathIt); > - SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten); > - for (auto It = Components.rbegin(), End = Components.rend(); It != End; > - ++It) > - llvm::sys::path::append(RelativeHeader, *It); > - > - // Include this header as part of the umbrella directory. > - Module->addTopHeader(Header); > - addHeaderInclude(RelativeHeader, Includes, LangOpts, > Module->IsExternC); > - } > - > - if (EC) > - return EC; > - } > - > - // Recurse into submodules. > - for (clang::Module::submodule_iterator Sub = Module->submodule_begin(), > - SubEnd = Module->submodule_end(); > - Sub != SubEnd; ++Sub) > - if (std::error_code Err = collectModuleHeaderIncludes( > - LangOpts, FileMgr, ModMap, *Sub, Includes)) > - return Err; > - > - return std::error_code(); > -} > - > bool GenerateModuleFromModuleMapAction::BeginSourceFileAction( > CompilerInstance &CI, StringRef Filename) { > - CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap); > - > - if (!GenerateModuleAction::BeginSourceFileAction(CI, Filename)) > - return false; > - > - // Find the module map file. > - const FileEntry *ModuleMap = > - CI.getFileManager().getFile(Filename, /*openFile*/true); > - if (!ModuleMap) { > - CI.getDiagnostics().Report(diag::err_module_map_not_found) > - << Filename; > - return false; > - } > - > - // Parse the module map file. > - HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); > - if (HS.loadModuleMapFile(ModuleMap, IsSystem)) > - return false; > - > - if (CI.getLangOpts().CurrentModule.empty()) { > - CI.getDiagnostics().Report(diag::err_missing_module_name); > - > - // FIXME: Eventually, we could consider asking whether there was just > - // a single module described in the module map, and use that as a > - // default. Then it would be fairly trivial to just "compile" a module > - // map with a single module (the common case). > - return false; > - } > - > - // If we're being run from the command-line, the module build stack will > not > - // have been filled in yet, so complete it now in order to allow us to > detect > - // module cycles. > - SourceManager &SourceMgr = CI.getSourceManager(); > - if (SourceMgr.getModuleBuildStack().empty()) > - SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule, > - FullSourceLoc(SourceLocation(), > SourceMgr)); > - > - // Dig out the module definition. > - Module = HS.lookupModule(CI.getLangOpts().CurrentModule, > - /*AllowSearch=*/false); > - if (!Module) { > - CI.getDiagnostics().Report(diag::err_missing_module) > - << CI.getLangOpts().CurrentModule << Filename; > - > - return false; > - } > - > - // Check whether we can build this module at all. > - clang::Module::Requirement Requirement; > - clang::Module::UnresolvedHeaderDirective MissingHeader; > - if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement, > - MissingHeader)) { > - if (MissingHeader.FileNameLoc.isValid()) { > - CI.getDiagnostics().Report(MissingHeader.FileNameLoc, > - diag::err_module_header_missing) > - << MissingHeader.IsUmbrella << MissingHeader.FileName; > - } else { > - CI.getDiagnostics().Report(diag::err_module_unavailable) > - << Module->getFullModuleName() > - << Requirement.second << Requirement.first; > - } > - > - return false; > - } > - > - if (ModuleMapForUniquing && ModuleMapForUniquing != ModuleMap) { > - Module->IsInferred = true; > - HS.getModuleMap().setInferredModuleAllowedBy(Module, > ModuleMapForUniquing); > - } else { > - ModuleMapForUniquing = ModuleMap; > - } > - > - FileManager &FileMgr = CI.getFileManager(); > - > - // Collect the set of #includes we need to build the module. > - SmallString<256> HeaderContents; > - std::error_code Err = std::error_code(); > - if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) > - addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents, > - CI.getLangOpts(), Module->IsExternC); > - Err = collectModuleHeaderIncludes( > - CI.getLangOpts(), FileMgr, > - CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), Module, > - HeaderContents); > - > - if (Err) { > - CI.getDiagnostics().Report(diag::err_module_cannot_create_includes) > - << Module->getFullModuleName() << Err.message(); > - return false; > - } > - > - // Inform the preprocessor that includes from within the input buffer > should > - // be resolved relative to the build directory of the module map file. > - CI.getPreprocessor().setMainFileDir(Module->Directory); > - > - std::unique_ptr<llvm::MemoryBuffer> InputBuffer = > - llvm::MemoryBuffer::getMemBufferCopy(HeaderContents, > - > Module::getModuleInputBufferName()); > - // Ownership of InputBuffer will be transferred to the SourceManager. > - setCurrentInput(FrontendInputFile(InputBuffer.release(), > getCurrentFileKind(), > - Module->IsSystem)); > - return true; > + return GenerateModuleAction::BeginSourceFileAction(CI, Filename); > } > > std::unique_ptr<raw_pwrite_stream> > @@ -408,10 +175,13 @@ GenerateModuleFromModuleMapAction::Creat > // If no output file was provided, figure out where this module would go > // in the module cache. > if (CI.getFrontendOpts().OutputFile.empty()) { > + StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap; > + if (ModuleMapFile.empty()) > + ModuleMapFile = InFile; > + > HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); > CI.getFrontendOpts().OutputFile = > - HS.getModuleFileName(CI.getLangOpts().CurrentModule, > - ModuleMapForUniquing->getName(), > + HS.getModuleFileName(CI.getLangOpts().CurrentModule, ModuleMapFile, > /*UsePrebuiltPath=*/false); > } > > > Modified: cfe/trunk/lib/Frontend/FrontendOptions.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendOptions.cpp?rev=301610&r1=301609&r2=301610&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/FrontendOptions.cpp (original) > +++ cfe/trunk/lib/Frontend/FrontendOptions.cpp Thu Apr 27 20:49:42 2017 > @@ -16,17 +16,17 @@ InputKind FrontendOptions::getInputKindF > .Cases("ast", "pcm", InputKind(InputKind::Unknown, > InputKind::Precompiled)) > .Case("c", InputKind::C) > .Cases("S", "s", InputKind::Asm) > - .Case("i", InputKind(InputKind::C, true)) > - .Case("ii", InputKind(InputKind::CXX, true)) > - .Case("cui", InputKind(InputKind::CUDA, true)) > + .Case("i", InputKind(InputKind::C).getPreprocessed()) > + .Case("ii", InputKind(InputKind::CXX).getPreprocessed()) > + .Case("cui", InputKind(InputKind::CUDA).getPreprocessed()) > .Case("m", InputKind::ObjC) > - .Case("mi", InputKind(InputKind::ObjC, true)) > + .Case("mi", InputKind(InputKind::ObjC).getPreprocessed()) > .Cases("mm", "M", InputKind::ObjCXX) > - .Case("mii", InputKind(InputKind::ObjCXX, true)) > + .Case("mii", InputKind(InputKind::ObjCXX).getPreprocessed()) > .Cases("C", "cc", "cp", InputKind::CXX) > .Cases("cpp", "CPP", "c++", "cxx", "hpp", InputKind::CXX) > .Case("cppm", InputKind::CXX) > - .Case("iim", InputKind(InputKind::CXX, true)) > + .Case("iim", InputKind(InputKind::CXX).getPreprocessed()) > .Case("cl", InputKind::OpenCL) > .Case("cu", InputKind::CUDA) > .Cases("ll", "bc", InputKind::LLVM_IR) > > Added: cfe/trunk/test/Modules/preprocess-module.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/preprocess-module.cpp?rev=301610&view=auto > ============================================================================== > --- cfe/trunk/test/Modules/preprocess-module.cpp (added) > +++ cfe/trunk/test/Modules/preprocess-module.cpp Thu Apr 27 20:49:42 2017 > @@ -0,0 +1,12 @@ > +// RUN: rm -rf %t > + > +// RUN: not %clang_cc1 -fmodules -fmodule-name=file -I%S/Inputs/preprocess > -x c++-module-map %S/Inputs/preprocess/module.modulemap -E 2>&1 | FileCheck > %s --check-prefix=MISSING-FWD > +// MISSING-FWD: module 'fwd' is needed > + > +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodules-cache-path=%t > -I%S/Inputs/preprocess -x c++-module-map > %S/Inputs/preprocess/module.modulemap -E | FileCheck %s > +// CHECK: # 1 "<module-includes>" > +// CHECK: # 1 "{{.*}}file.h" 1 > +// CHECK: struct __FILE; > +// CHECK: #include "fwd.h" /* clang -E: implicit import for module fwd */ > +// CHECK: typedef struct __FILE FILE; > +// CHECK: # 2 "<module-includes>" 2 > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits -- Bruno Cardoso Lopes http://www.brunocardoso.cc _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits