]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Don’t pass -Werror and compilation-only options to the preprocessor
authorJoel Rosdahl <joel@rosdahl.net>
Fri, 19 Jul 2019 07:22:04 +0000 (09:22 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Fri, 19 Jul 2019 07:33:37 +0000 (09:33 +0200)
Clang emits warnings when it sees unused options, so when ccache runs
the Clang preprocessor separately, options that are not used by the
preprocessor will produce warnings. This means that the user may get
warnings which would not be present when not using ccache. And if
-Werror is present then the preprocessing step fails, which needless to
say is not optimal.

To work around this:

* Options known to have the above mentioned problem are not passed to
  the preprocessor.
* In addition, -Werror is also not passed to the preprocessor so that
  options not properly marked as “compiler only” will only trigger
  warnings, not errors.

Fixes #312.

src/ccache.c
src/compopt.c
src/compopt.h
unittest/test_argument_processing.c

index 75e74310be0414b40bbbdf5f77c67b741ff4f93b..ca3b961ab671c2ea5ca5c5756425ab3da62b1e6c 100644 (file)
@@ -2513,9 +2513,11 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
        // used as a temporary data structure to loop over.
        struct args *expanded_args = args_copy(args);
 
-       // common_args essentially contains all original arguments except those that
-       // only should be passed to the preprocessor (if run_second_cpp is false) and
-       // except dependency options (like -MD and friends).
+       // common_args contains all original arguments except:
+       // * those that never should be passed to the preprocessor,
+       // * those that only should be passed to the preprocessor (if run_second_cpp
+       //   is false), and
+       // * dependency options (like -MD and friends).
        struct args *common_args = args_init(0, NULL);
 
        // cpp_args contains arguments that were not added to common_args, i.e. those
@@ -2523,12 +2525,15 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
        // If run_second_cpp is true, they will be passed to the compiler as well.
        struct args *cpp_args = args_init(0, NULL);
 
-       // dep_args contains dependency options like -MD. They only passed to the
+       // dep_args contains dependency options like -MD. They are only passed to the
        // preprocessor, never to the compiler.
        struct args *dep_args = args_init(0, NULL);
 
-       bool found_color_diagnostics = false;
+       // compiler_only_args contains arguments that should only be passed to the
+       // compiler, not the preprocessor.
+       struct args *compiler_only_args = args_init(0, NULL);
 
+       bool found_color_diagnostics = false;
        bool found_directives_only = false;
        bool found_rewrite_includes = false;
 
@@ -2662,6 +2667,26 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
                        continue;
                }
 
+               // Handle options that should not be passed to the preprocessor.
+               if (compopt_affects_comp(argv[i])) {
+                       args_add(compiler_only_args, argv[i]);
+                       if (compopt_takes_arg(argv[i])) {
+                               if (i == argc - 1) {
+                                       cc_log("Missing argument to %s", argv[i]);
+                                       stats_update(STATS_ARGS);
+                                       result = false;
+                                       goto out;
+                               }
+                               args_add(compiler_only_args, argv[i + 1]);
+                               ++i;
+                       }
+                       continue;
+               }
+               if (compopt_prefix_affects_comp(argv[i])) {
+                       args_add(compiler_only_args, argv[i]);
+                       continue;
+               }
+
                if (str_eq(argv[i], "-fpch-preprocess")
                    || str_eq(argv[i], "-emit-pch")
                    || str_eq(argv[i], "-emit-pth")) {
@@ -3498,6 +3523,8 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
        }
 
        *compiler_args = args_copy(common_args);
+       args_extend(*compiler_args, compiler_only_args);
+
        if (conf->run_second_cpp) {
                args_extend(*compiler_args, cpp_args);
        } else if (found_directives_only || found_rewrite_includes) {
index 8940cfcd826e16dda601a685dd76dfb217949aba..413a1b37a17e1defcc416ea045003ddd04b73666 100644 (file)
 #include "ccache.h"
 #include "compopt.h"
 
+// The option it too hard to handle at all.
 #define TOO_HARD         (1 << 0)
+
+// The option it too hard for the direct mode.
 #define TOO_HARD_DIRECT  (1 << 1)
+
+// The option takes a separate argument, e.g. "-D FOO=1".
 #define TAKES_ARG        (1 << 2)
+
+// The option takes a concatenated argument, e.g. "-DFOO=1".
 #define TAKES_CONCAT_ARG (1 << 3)
+
+// The argument to the option is a path that may be rewritten if base_dir is
+// used.
 #define TAKES_PATH       (1 << 4)
+
+// The option only affects preprocessing; not passed to the compiler if
+// run_second_cpp is false.
 #define AFFECTS_CPP      (1 << 5)
 
+// The option only affects compilation; not passed to the preprocesor.
+#define AFFECTS_COMP (1 << 6)
+
 struct compopt {
        const char *name;
        int type;
@@ -56,14 +72,20 @@ static const struct compopt compopts[] = {
        {"-P",              TOO_HARD},
        {"-U",              AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
        {"-V",              TAKES_ARG},
-       {"-Xassembler",     TAKES_ARG},
+       {"-Wa,",            TAKES_CONCAT_ARG | AFFECTS_COMP},
+       {"-Werror",         AFFECTS_COMP}, // don't exit with error when preprocessing
+       {"-Wl,",            TAKES_CONCAT_ARG | AFFECTS_COMP},
+       {"-Xassembler",     TAKES_ARG | TAKES_CONCAT_ARG | AFFECTS_COMP},
        {"-Xclang",         TAKES_ARG},
-       {"-Xlinker",        TAKES_ARG},
+       {"-Xlinker",        TAKES_ARG | TAKES_CONCAT_ARG | AFFECTS_COMP},
        {"-Xpreprocessor",  AFFECTS_CPP | TOO_HARD_DIRECT | TAKES_ARG},
+       {"-all_load",       AFFECTS_COMP},
        {"-analyze",        TOO_HARD}, // clang
        {"-arch",           TAKES_ARG},
        {"-aux-info",       TAKES_ARG},
        {"-b",              TAKES_ARG},
+       {"-bind_at_load",   AFFECTS_COMP},
+       {"-bundle",         AFFECTS_COMP},
        {"-ccbin",          AFFECTS_CPP | TAKES_ARG}, // nvcc
        {"-fmodules",       TOO_HARD},
        {"-fno-working-directory", AFFECTS_CPP},
@@ -87,9 +109,14 @@ static const struct compopt compopts[] = {
        {"-iwithprefixbefore",
         AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
        {"-ldir",           AFFECTS_CPP | TAKES_ARG}, // nvcc
+       {"-nolibc",         AFFECTS_COMP},
        {"-nostdinc",       AFFECTS_CPP},
        {"-nostdinc++",     AFFECTS_CPP},
        {"-odir",           AFFECTS_CPP | TAKES_ARG}, // nvcc
+       {"-pie",            AFFECTS_COMP},
+       {"-prebind",        AFFECTS_COMP},
+       {"-preload",        AFFECTS_COMP},
+       {"-rdynamic",       AFFECTS_COMP},
        {"-remap",          AFFECTS_CPP},
        {"-save-temps",     TOO_HARD},
        {"-save-temps=cwd", TOO_HARD},
@@ -172,6 +199,13 @@ compopt_affects_cpp(const char *option)
        return co && (co->type & AFFECTS_CPP);
 }
 
+bool
+compopt_affects_comp(const char *option)
+{
+       const struct compopt *co = find(option);
+       return co && (co->type & AFFECTS_COMP);
+}
+
 bool
 compopt_too_hard(const char *option)
 {
@@ -216,3 +250,13 @@ compopt_prefix_affects_cpp(const char *option)
        const struct compopt *co = find_prefix(option);
        return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_CPP);
 }
+
+// Determines if the prefix of the option matches any option and affects the
+// preprocessor.
+bool
+compopt_prefix_affects_comp(const char *option)
+{
+       // Prefix options have to take concatenated args.
+       const struct compopt *co = find_prefix(option);
+       return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_COMP);
+}
index d72639fe4d261f9a0eeb714093f679878feba581..4f1f760e9b86b4c70149412cc86d66a64d9187bf 100644 (file)
@@ -5,11 +5,13 @@
 
 bool compopt_short(bool (*fn)(const char *option), const char *option);
 bool compopt_affects_cpp(const char *option);
+bool compopt_affects_comp(const char *option);
 bool compopt_too_hard(const char *option);
 bool compopt_too_hard_for_direct_mode(const char *option);
 bool compopt_takes_path(const char *option);
 bool compopt_takes_arg(const char *option);
 bool compopt_takes_concat_arg(const char *option);
 bool compopt_prefix_affects_cpp(const char *option);
+bool compopt_prefix_affects_comp(const char *option);
 
 #endif // CCACHE_COMPOPT_H
index 8d40a511f5203e8b654e717856019ae1670ee7ec..7974f8a7660e8394802b5dc9bb57b5c3bab37203 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2010-2018 Joel Rosdahl
+// Copyright (C) 2010-2019 Joel Rosdahl
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by the Free
@@ -494,4 +494,22 @@ TEST(debug_flag_order_with_known_option_last)
        args_free(orig);
 }
 
+TEST(options_not_to_be_passed_to_the_preprocesor)
+{
+       struct args *orig = args_init_from_string(
+               "cc -Wa,foo foo.c -g -Xlinker fie -Xlinker,fum -c -Werror");
+       struct args *exp_cpp = args_init_from_string("cc -g");
+       struct args *exp_cc = args_init_from_string(
+               "cc -g -Wa,foo -Xlinker fie -Xlinker,fum -Werror -c");
+       struct args *act_cpp = NULL;
+       struct args *act_cc = NULL;
+
+       create_file("foo.c", "");
+       CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+       CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+       CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+       args_free(orig);
+}
+
 TEST_SUITE_END