]> 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 09:01:01 +0000 (11:01 +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.

(cherry picked from commit 5d8585b588fb9f81e741b765603053e4cadcf1ac)

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

index 1051ac8e3e5a96bdb35ae5f760b336ed73edc793..e4fc54fcc626409704b5b14c5bd24c1bf5bf75bd 100644 (file)
@@ -2322,9 +2322,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
@@ -2332,12 +2334,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;
 
@@ -2471,6 +2476,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")) {
@@ -3299,6 +3324,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 a3bd7b521fac40eff64bd39378bb39a4c2d02a4c..63204d4f03986d344c38b5b89aebf433461b56a6 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;
@@ -58,14 +74,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},
@@ -89,9 +111,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},
@@ -174,6 +201,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)
 {
@@ -218,3 +252,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 c81ac773368606804040613040f09046d71ce611..4c37aab1a999f22159327f31717b029d484b3615 100644 (file)
 
 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 17585d653b51d87c62f2547e7f9364cf0a02a79d..9d426ad5805d862fdd88b868dfa0b0cc113684c7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2010-2018 Joel Rosdahl and other contributors
+// Copyright (C) 2010-2019 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -496,4 +496,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