[clang] 0c42d87 - [clang][cli] Generate and round-trip preprocessor options

Jan Svoboda via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 8 00:35:04 PST 2021


Author: Jan Svoboda
Date: 2021-02-08T09:34:55+01:00
New Revision: 0c42d87ea8e01f369d9cced7427a5ee0cca7574b

URL: https://github.com/llvm/llvm-project/commit/0c42d87ea8e01f369d9cced7427a5ee0cca7574b
DIFF: https://github.com/llvm/llvm-project/commit/0c42d87ea8e01f369d9cced7427a5ee0cca7574b.diff

LOG: [clang][cli] Generate and round-trip preprocessor options

This patch implements generation of remaining preprocessor options and tests it by performing parse-generate-parse round trip.

Reviewed By: dexonsmith

Differential Revision: https://reviews.llvm.org/D95366

Added: 
    

Modified: 
    clang/include/clang/Driver/Options.td
    clang/lib/Frontend/CompilerInvocation.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index cbd501ca2a74..49071a4c56d9 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -258,7 +258,7 @@ class CodeGenOpts<string base>
 class HeaderSearchOpts<string base>
   : KeyPathAndMacro<"HeaderSearchOpts->", base, "HEADER_SEARCH_"> {}
 class PreprocessorOpts<string base>
-  : KeyPathAndMacro<"PreprocessorOpts->", base> {}
+  : KeyPathAndMacro<"PreprocessorOpts->", base, "PREPROCESSOR_"> {}
 class FileSystemOpts<string base>
   : KeyPathAndMacro<"FileSystemOpts.", base> {}
 class AnalyzerOpts<string base>

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index f93f10cf0988..8743da2b80ca 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3122,9 +3122,96 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
   llvm_unreachable("invalid frontend action");
 }
 
-static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
-                                  DiagnosticsEngine &Diags,
-                                  frontend::ActionKind Action) {
+static void GeneratePreprocessorArgs(PreprocessorOptions &Opts,
+                                     SmallVectorImpl<const char *> &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 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
   // "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<PreprocessorOptions>();
+
+  auto Parse = [Action](CompilerInvocation &Res, ArgList &Args,
+                        DiagnosticsEngine &Diags) {
+    return ParsePreprocessorArgsImpl(Res.getPreprocessorOpts(), Args, Diags,
+                                     Action, Res.getFrontendOpts());
+  };
+
+  auto Generate = [&Args](CompilerInvocation &Res,
+                     SmallVectorImpl<const char *> &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 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
       !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 @@ void CompilerInvocation::generateCC1CommandLine(
 #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);


        


More information about the cfe-commits mailing list