diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1445,6 +1445,8 @@ def fmodule_name : Separate<["-"], "fmodule-name">, Alias; def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">, Flags<[CC1Option]>, Alias; +def fsystem_module : Flag<["-"], "fsystem-module">, Flags<[CC1Option]>, + HelpText<"Build this module as a system module. Only used with -emit-module">; def fmodule_map_file : Joined<["-"], "fmodule-map-file=">, Group, Flags<[DriverOption,CC1Option]>, MetaVarName<"">, HelpText<"Load this module map file">; diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -297,6 +297,9 @@ /// Should a temporary file be used during compilation. unsigned UseTemporary : 1; + /// When using -emit-module, treat the modulemap as a system module. + unsigned IsSystemModule : 1; + CodeCompleteOptions CodeCompleteOpts; /// Specifies the output format of the AST. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1905,6 +1905,11 @@ Opts.ModulesEmbedAllFiles = Args.hasArg(OPT_fmodules_embed_all_files); Opts.IncludeTimestamps = !Args.hasArg(OPT_fno_pch_timestamp); Opts.UseTemporary = !Args.hasArg(OPT_fno_temp_file); + Opts.IsSystemModule = Args.hasArg(OPT_fsystem_module); + + if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule) + Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module" + << "-emit-module"; Opts.CodeCompleteOpts.IncludeMacros = Args.hasArg(OPT_code_completion_macros); @@ -2061,12 +2066,16 @@ DashX = IK; } + bool IsSystem = false; + // The -emit-module action implicitly takes a module map. if (Opts.ProgramAction == frontend::GenerateModule && - IK.getFormat() == InputKind::Source) + IK.getFormat() == InputKind::Source) { IK = IK.withFormat(InputKind::ModuleMap); + IsSystem = Opts.IsSystemModule; + } - Opts.Inputs.emplace_back(std::move(Inputs[i]), IK); + Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem); } return DashX; diff --git a/clang/test/Modules/fsystem-module.m b/clang/test/Modules/fsystem-module.m new file mode 100644 --- /dev/null +++ b/clang/test/Modules/fsystem-module.m @@ -0,0 +1,19 @@ +// RUN: rm -rf %t +// RUN: rm -rf %t-saved +// RUN: mkdir %t-saved + +// -fsystem-module requires -emit-module +// RUN: not %clang_cc1 -fsyntax-only -fsystem-module %s 2>&1 | grep "-emit-module" + +// RUN: not %clang_cc1 -fmodules -I %S/Inputs \ +// RUN: -emit-module -fmodule-name=warning -pedantic -Werror \ +// RUN: %S/Inputs/module.map -o %t-saved/warning.pcm + +// RUN: %clang_cc1 -fmodules -I %S/Inputs \ +// RUN: -emit-module -fmodule-name=warning -pedantic -Werror \ +// RUN: %S/Inputs/module.map -o %t-saved/warning-system.pcm -fsystem-module + +// RUN: not %clang_cc1 -fmodules -I %S/Inputs \ +// RUN: -emit-module -fmodule-name=warning -pedantic -Werror \ +// RUN: %S/Inputs/module.map -o %t-saved/warning-system.pcm -fsystem-module \ +// RUN: -Wsystem-headers