From 16c2076733beb22a4e1c28a0f24f909aa2a62e55 Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Sun, 5 Sep 2010 11:08:09 +0200 Subject: [PATCH] Avoid preprocessed hits when using precompiled headers 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 | 70 ++++++++++++++++++++++++++++++-------------------------- test.sh | 48 ++++++++++++++++++++++++++------------ 2 files changed, 72 insertions(+), 46 deletions(-) diff --git a/ccache.c b/ccache.c index fffb51864..ba069d3e2 100644 --- 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 or . */ 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 1bd05ad34..8995956d4 100755 --- 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 } ###################################################################### -- 2.47.3