]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Avoid preprocessed hits when using precompiled headers
authorJoel Rosdahl <joel@rosdahl.net>
Sun, 5 Sep 2010 09:08:09 +0000 (11:08 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Sun, 5 Sep 2010 09:45:10 +0000 (11:45 +0200)
Otherwise, we would get a false hit if the PCH has changed (but the rest of
the source has not) since the preprocessed output doesn't include the PCH
content.

The PCH content is now also included in the preprocessor output hash to
avoid several manifest entries (where the PCH hash differs) pointing to the
same object file.

ccache.c
test.sh

index fffb5186432986e36dd848de5ffd73d03019f7b8..ba069d3e2d1225ce903addce8eea7b671672d87f 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -278,10 +278,11 @@ get_path_in_cache(const char *name, const char *suffix)
 
 /*
  * This function hashes an include file and stores the path and hash in the
- * global included_files variable. Takes over ownership of path.
+ * global included_files variable. If the include file is a PCH, cpp_hash is
+ * also updated. Takes over ownership of path.
  */
 static void
-remember_include_file(char *path, size_t path_len)
+remember_include_file(char *path, size_t path_len, struct mdfour *cpp_hash)
 {
        struct file_hash *h;
        struct mdfour fhash;
@@ -290,10 +291,6 @@ remember_include_file(char *path, size_t path_len)
        size_t size;
        int result;
 
-       if (!included_files) {
-               goto ignore;
-       }
-
        if (path_len >= 2 && (path[0] == '<' && path[path_len - 1] == '>')) {
                /* Typically <built-in> or <command-line>. */
                goto ignore;
@@ -328,29 +325,36 @@ remember_include_file(char *path, size_t path_len)
        hash_start(&fhash);
 
        if (is_precompiled_header(path)) {
-               hash_file(&fhash, path);
-       } else {
-               if (st.st_size > 0) {
-                       if (!read_file(path, st.st_size, &source, &size)) {
+               hash_file2(&fhash, cpp_hash, path);
+       }
+
+       if (enable_direct) {
+               if (!is_precompiled_header(path)) {
+                       if (st.st_size > 0) {
+                               if (!read_file(path, st.st_size, &source, &size)) {
+                                       goto failure;
+                               }
+                       } else {
+                               source = x_strdup("");
+                               size = 0;
+                       }
+
+                       result = hash_source_code_string(&fhash, source, size, path);
+                       if (result & HASH_SOURCE_CODE_ERROR
+                           || result & HASH_SOURCE_CODE_FOUND_TIME) {
                                goto failure;
                        }
-               } else {
-                       source = x_strdup("");
-                       size = 0;
                }
 
-               result = hash_source_code_string(&fhash, source, size, path);
-               if (result & HASH_SOURCE_CODE_ERROR
-                   || result & HASH_SOURCE_CODE_FOUND_TIME) {
-                       goto failure;
-               }
+               h = x_malloc(sizeof(*h));
+               hash_result_as_bytes(&fhash, h->hash);
+               h->size = fhash.totalN;
+               hashtable_insert(included_files, path, h);
+       } else {
+               free(path);
        }
 
        free(source);
-       h = x_malloc(sizeof(*h));
-       hash_result_as_bytes(&fhash, h->hash);
-       h->size = fhash.totalN;
-       hashtable_insert(included_files, path, h);
        return;
 
 failure:
@@ -400,9 +404,7 @@ process_preprocessed_file(struct mdfour *hash, const char *path)
                return false;
        }
 
-       if (enable_direct) {
-               included_files = create_hashtable(1000, hash_from_string, strings_equal);
-       }
+       included_files = create_hashtable(1000, hash_from_string, strings_equal);
 
        /* Bytes between p and q are pending to be hashed. */
        end = data + size;
@@ -458,11 +460,7 @@ process_preprocessed_file(struct mdfour *hash, const char *path)
                        path = x_strndup(p, q - p);
                        path = make_relative_path(path);
                        hash_string(hash, path);
-                       if (enable_direct) {
-                               remember_include_file(path, q - p);
-                       } else {
-                               free(path);
-                       }
+                       remember_include_file(path, q - p, hash);
                        p = q;
                } else {
                        q++;
@@ -1875,8 +1873,16 @@ ccache(int argc, char *argv[])
                put_object_in_manifest = true;
        }
 
-       /* if we can return from cache at this point then do */
-       from_cache(FROMCACHE_CPP_MODE, put_object_in_manifest);
+       if (using_precompiled_header) {
+               /*
+                * We must avoid a preprocessed hit when using a PCH. Otherwise, we would
+                * get a false hit if the PCH has changed (but the rest of the source has
+                * not) since the preprocessed output doesn't include the PCH content.
+                */
+       } else {
+               /* if we can return from cache at this point then do */
+               from_cache(FROMCACHE_CPP_MODE, put_object_in_manifest);
+       }
 
        if (getenv("CCACHE_READONLY")) {
                cc_log("Read-only mode; running real compiler");
diff --git a/test.sh b/test.sh
index 1bd05ad346e18b811d82bbf173da996b1397ed34..8995956d461989416a901616159c9e45e46dc335 100755 (executable)
--- a/test.sh
+++ b/test.sh
@@ -1669,16 +1669,35 @@ EOF
     rm -f pch.h
     backdate pch.h.gch
 
-    testname="no -fpch-preprocess"
-    $CCACHE -z >/dev/null
+    testname="preprocessor mode"
+    $CCACHE -Cz >/dev/null
+    CCACHE_NODIRECT=1 CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+    checkstat 'cache hit (direct)' 0
+    checkstat 'cache hit (preprocessed)' 0
+    checkstat 'cache miss' 0
+    checkstat "can't use precompiled header" 1
+
+    testname="no -fpch-preprocess, #include"
+    $CCACHE -Cz >/dev/null
     $CCACHE $COMPILER -c pch.c 2>/dev/null
     checkstat 'cache hit (direct)' 0
     checkstat 'cache hit (preprocessed)' 0
     checkstat 'cache miss' 0
+    # Preprocessor error because GCC can't find the real include file when
+    # trying to preprocess:
     checkstat 'preprocessor error' 1
 
-    testname="no -fpch-preprocess, using -include"
-    $CCACHE -z >/dev/null
+    testname="no -fpch-preprocess, -include, no sloppy time macros"
+    $CCACHE -Cz >/dev/null
+    $CCACHE $COMPILER -c -include pch.h pch2.c 2>/dev/null
+    checkstat 'cache hit (direct)' 0
+    checkstat 'cache hit (preprocessed)' 0
+    checkstat 'cache miss' 0
+    # Must enable sloppy time macros:
+    checkstat "can't use precompiled header" 1
+
+    testname="no -fpch-preprocess, -include"
+    $CCACHE -Cz >/dev/null
     CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -include pch.h pch2.c 2>/dev/null
     checkstat 'cache hit (direct)' 0
     checkstat 'cache hit (preprocessed)' 0
@@ -1688,16 +1707,16 @@ EOF
     checkstat 'cache hit (preprocessed)' 0
     checkstat 'cache miss' 1
 
-    testname="-fpch-preprocess, no sloppy time macros"
-    $CCACHE -z >/dev/null
+    testname="-fpch-preprocess, #include, no sloppy time macros"
+    $CCACHE -Cz >/dev/null
     $CCACHE $COMPILER -c -fpch-preprocess pch.c
     checkstat 'cache hit (direct)' 0
     checkstat 'cache hit (preprocessed)' 0
-    checkstat 'cache miss' 0
+    # Must enable sloppy time macros:
     checkstat "can't use precompiled header" 1
 
-    testname="-fpch-preprocess, sloppy time macros"
-    $CCACHE -zC >/dev/null
+    testname="-fpch-preprocess, #include, sloppy time macros"
+    $CCACHE -Cz >/dev/null
     CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
     checkstat 'cache hit (direct)' 0
     checkstat 'cache hit (preprocessed)' 0
@@ -1707,14 +1726,15 @@ EOF
     checkstat 'cache hit (preprocessed)' 0
     checkstat 'cache miss' 1
 
-    testname="-fpch-preprocess, file changed, direct mode"
-    $CCACHE -z >/dev/null
+    testname="-fpch-preprocess, #include, file changed"
     echo "updated" >>pch.h.gch # GCC seems to cope with this...
     backdate pch.h.gch
     CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
-    checkstat 'cache hit (direct)' 0
-    checkstat 'cache hit (preprocessed)' 1
-    checkstat 'cache miss' 0
+    checkstat 'cache hit (direct)' 1
+    # Shouldnt' get a preprocessed hit since the preprocessed output doesn't
+    # include the PCH header:
+    checkstat 'cache hit (preprocessed)' 0
+    checkstat 'cache miss' 2
 }
 
 ######################################################################