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 @@ -258,7 +258,7 @@ class HeaderSearchOpts : KeyPathAndMacro<"HeaderSearchOpts->", base, "HEADER_SEARCH_"> {} class PreprocessorOpts - : KeyPathAndMacro<"PreprocessorOpts->", base> {} + : KeyPathAndMacro<"PreprocessorOpts->", base, "PREPROCESSOR_"> {} class FileSystemOpts : KeyPathAndMacro<"FileSystemOpts.", base> {} class AnalyzerOpts 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 @@ -3122,9 +3122,96 @@ llvm_unreachable("invalid frontend action"); } -static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, - DiagnosticsEngine &Diags, - frontend::ActionKind Action) { +static void GeneratePreprocessorArgs(PreprocessorOptions &Opts, + SmallVectorImpl &Args, + CompilerInvocation::StringAllocator SA, + const LangOptions &LangOpts, + const FrontendOptions &FrontendOpts, + const CodeGenOptions &CodeGenOpts) { + PreprocessorOptions *PreprocessorOpts = &Opts; + +#define PREPROCESSOR_OPTION_WITH_MARSHALLING( \ + PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \ + DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \ + MERGER, EXTRACTOR, TABLE_INDEX) \ + GENERATE_OPTION_WITH_MARSHALLING( \ + Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \ + IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX) +#include "clang/Driver/Options.inc" +#undef PREPROCESSOR_OPTION_WITH_MARSHALLING + + if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate) + GenerateArg(Args, OPT_pch_through_hdrstop_use, SA); + + for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn) + GenerateArg(Args, OPT_error_on_deserialized_pch_decl, D, SA); + + for (const auto &MP : Opts.MacroPrefixMap) + GenerateArg(Args, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second, SA); + + if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false)) + GenerateArg(Args, OPT_preamble_bytes_EQ, + Twine(Opts.PrecompiledPreambleBytes.first) + "," + + (Opts.PrecompiledPreambleBytes.second ? "1" : "0"), + SA); + + for (const auto &M : Opts.Macros) { + // Don't generate __CET__ macro definitions. They are implied by the + // -fcf-protection option that is generated elsewhere. + if (M.first == "__CET__=1" && !M.second && + !CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch) + continue; + if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn && + !CodeGenOpts.CFProtectionBranch) + continue; + if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn && + CodeGenOpts.CFProtectionBranch) + continue; + + GenerateArg(Args, M.second ? OPT_U : OPT_D, M.first, SA); + } + + for (const auto &I : Opts.Includes) { + // Don't generate OpenCL includes. They are implied by other flags that are + // generated elsewhere. + if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader && + ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") || + I == "opencl-c.h")) + continue; + + GenerateArg(Args, OPT_include, I, SA); + } + + for (const auto &CI : Opts.ChainedIncludes) + GenerateArg(Args, OPT_chain_include, CI, SA); + + for (const auto &RF : Opts.RemappedFiles) + GenerateArg(Args, OPT_remap_file, RF.first + ";" + RF.second, SA); + + // Don't handle LexEditorPlaceholders. It is implied by the action that is + // generated elsewhere. +} + +static bool ParsePreprocessorArgsImpl(PreprocessorOptions &Opts, ArgList &Args, + DiagnosticsEngine &Diags, + frontend::ActionKind Action, + const FrontendOptions &FrontendOpts) { + PreprocessorOptions *PreprocessorOpts = &Opts; + bool Success = true; + +#define PREPROCESSOR_OPTION_WITH_MARSHALLING( \ + PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \ + DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \ + MERGER, EXTRACTOR, TABLE_INDEX) \ + PARSE_OPTION_WITH_MARSHALLING(Args, Diags, Success, ID, FLAGS, PARAM, \ + SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \ + IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \ + MERGER, TABLE_INDEX) +#include "clang/Driver/Options.inc" +#undef PREPROCESSOR_OPTION_WITH_MARSHALLING + Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) || Args.hasArg(OPT_pch_through_hdrstop_use); @@ -3195,6 +3282,48 @@ // "editor placeholder in source file" error in PP only mode. if (isStrictlyPreprocessorAction(Action)) Opts.LexEditorPlaceholders = false; + + return Success; +} + +static bool ParsePreprocessorArgs(CompilerInvocation &Res, + PreprocessorOptions &Opts, ArgList &Args, + DiagnosticsEngine &Diags, + frontend::ActionKind Action, + FrontendOptions &FrontendOpts) { + auto DummyOpts = std::make_shared(); + + auto Parse = [Action](CompilerInvocation &Res, ArgList &Args, + DiagnosticsEngine &Diags) { + return ParsePreprocessorArgsImpl(Res.getPreprocessorOpts(), Args, Diags, + Action, Res.getFrontendOpts()); + }; + + auto Generate = [&Args](CompilerInvocation &Res, + SmallVectorImpl &GeneratedArgs, + CompilerInvocation::StringAllocator SA) { + GeneratePreprocessorArgs(Res.getPreprocessorOpts(), GeneratedArgs, SA, + *Res.getLangOpts(), Res.getFrontendOpts(), + Res.getCodeGenOpts()); + // The ParsePreprocessorArgs function queries the -fcf-protection option, + // which means that it won't be directly copied during argument generation. + // The GeneratePreprocessorArgs function isn't responsible for generating it + // either. This would cause -fcf-protection to get forgotten during + // round-trip and the __CET__ macros wouldn't get deduced during second call + // to ParsePreprocessorArgs. Let's fix this by generating -fcf-protection + // here. + // TODO: Remove this once we're doing one big round-trip instead of many + // small ones. + if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) + GenerateArg(GeneratedArgs, OPT_fcf_protection_EQ, A->getValue(), SA); + }; + + auto Swap = [&DummyOpts](CompilerInvocation &Res) { + std::swap(Res.PreprocessorOpts, DummyOpts); + }; + + return RoundTrip(Parse, Generate, Swap, Res, Args, Diags, + "PreprocessorOptions"); } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, @@ -3322,8 +3451,9 @@ !LangOpts.Sanitize.has(SanitizerKind::Memory) && !LangOpts.Sanitize.has(SanitizerKind::KernelMemory); - ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags, - Res.getFrontendOpts().ProgramAction); + ParsePreprocessorArgs(Res, Res.getPreprocessorOpts(), Args, Diags, + Res.getFrontendOpts().ProgramAction, + Res.getFrontendOpts()); ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Res.getFrontendOpts().ProgramAction); @@ -3483,6 +3613,8 @@ #undef DIAG_OPTION_WITH_MARSHALLING #undef OPTION_WITH_MARSHALLING + GeneratePreprocessorArgs(*PreprocessorOpts, Args, SA, *LangOpts, + FrontendOpts, CodeGenOpts); GenerateAnalyzerArgs(*AnalyzerOpts, Args, SA); GenerateHeaderSearchArgs(*HeaderSearchOpts, Args, SA); GenerateLangArgs(*LangOpts, Args, SA);