Imported Upstream version 4.3 upstream/4.3
authorJinWang An <jinwang.an@samsung.com>
Tue, 3 Aug 2021 07:30:48 +0000 (16:30 +0900)
committerJinWang An <jinwang.an@samsung.com>
Tue, 3 Aug 2021 07:30:48 +0000 (16:30 +0900)
37 files changed:
.clang-format
.github/workflows/build.yaml
.gitignore
.mailmap
CMakeLists.txt
CONTRIBUTING.md
cmake/CIBuildType.cmake
cmake/CcacheVersion.cmake
cmake/GenerateConfigurationFile.cmake
doc/AUTHORS.adoc
doc/MANUAL.adoc
doc/NEWS.adoc
misc/clang-format [new file with mode: 0755]
misc/format-files
src/Args.hpp
src/CacheEntryWriter.cpp
src/Config.cpp
src/Fd.hpp
src/File.hpp
src/MiniTrace.cpp
src/Result.cpp
src/ResultRetriever.cpp
src/Sloppiness.hpp
src/Stat.cpp
src/Win32Util.cpp
src/Win32Util.hpp
src/ZstdCompressor.cpp
src/argprocessing.cpp
src/ccache.cpp
src/compopt.cpp
src/system.hpp
test/CMakeLists.txt
test/suites/base.bash
test/suites/ivfsoverlay.bash [new file with mode: 0644]
test/suites/profiling.bash
unittest/test_Config.cpp
unittest/test_Stat.cpp

index f40eea449a4f67bd99f706a79912da500bbca4b4..c5ffe564b36d545f58c89a85e72b0473f21f2982 100644 (file)
@@ -1,8 +1,9 @@
-# This configuration should work with Clang-Format 6.0 and higher.
+# This configuration should work with Clang-Format 10 and higher.
 ---
 Language: Cpp
 BasedOnStyle: LLVM
 
+AllowAllConstructorInitializersOnNextLine: false
 AllowShortFunctionsOnASingleLine: None
 AlwaysBreakAfterReturnType: AllDefinitions
 AlwaysBreakBeforeMultilineStrings: true
index 662f491d050d0e8edd7c17355cbe6e70d8a2448c..07f2904642f7698c999feca2d7af809e6e27db80 100644 (file)
@@ -267,11 +267,11 @@ jobs:
 
           - name: Clang-Tidy
             os: ubuntu-18.04
-            CC: clang
-            CXX: clang++
+            CC: clang-9
+            CXX: clang++-9
             RUN_TESTS: none
-            CMAKE_PARAMS: -DENABLE_CLANG_TIDY=ON
-            apt_get: libzstd-dev clang-tidy
+            CMAKE_PARAMS: -DENABLE_CLANG_TIDY=ON -DCLANGTIDY=/usr/bin/clang-tidy-9
+            apt_get: libzstd-dev clang-9 clang-tidy-9
 
     steps:
       - name: Get source
index 9b69afd5e29e8e0f1da4b1c88d6bb8221a359c59..74db15fb4e6dc481978e594ea9280439da606569 100644 (file)
@@ -1,6 +1,9 @@
 # Typical build directories
 /build*/
 
+# Downloaded tools
+misc/.clang-format-exe
+
 # Emacs save files
 *~
 
index cc87e37d72856ded9684d7131f872118240cfbbd..7e59d6e6c85eb0ec0e4a7fa1170ebead1a9c50bb 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -4,6 +4,7 @@ Anders F Björklund <anders.f.bjorklund@gmail.com> <anders@psqr.se>
 Andrew Boie <andrew.p.boie@intel.com>
 Arne Hasselbring <arne.hasselbring@googlemail.com>
 Bernhard Bauer <bauerb@chromium.org> <bauerb@google.com>
+Bin Li <bin.li@windriver.com>
 Chiaki Ishikawa <ishikawa@yk.rim.or.jp>
 Clemens Rabe <clemens.rabe@gmail.com> <clemens.rabe@clemensrabe.de>
 Clemens Rabe <clemens.rabe@gmail.com> <crabe@gmx.de>
index fc2ff6657352429bd8bd82ea04500b04fe592175..e186e8128bc4d152f247333420941941d016d284 100644 (file)
@@ -133,7 +133,10 @@ target_link_libraries(ccache PRIVATE standard_settings standard_warnings ccache_
 #
 # Documentation
 #
-add_subdirectory(doc)
+option(ENABLE_DOCUMENTATION "Enable documentation" ON)
+if(ENABLE_DOCUMENTATION)
+  add_subdirectory(doc)
+endif()
 
 #
 # Installation
@@ -176,26 +179,16 @@ endif()
 #
 # Special formatting targets
 #
-find_program(
-  CLANG_FORMAT_EXE
-  NAMES "clang-format"
-  DOC "Path to clang-format executable.")
-mark_as_advanced(CLANG_FORMAT_EXE) # Don't show in CMake UIs
-
-if(NOT CLANG_FORMAT_EXE)
-  message(STATUS "clang-format not found")
-else()
-  add_custom_target(
-    format
-    COMMAND misc/format-files --all
-    COMMENT "Formatting code"
-    USES_TERMINAL
-    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
-
-  add_custom_target(
-    check_format
-    COMMAND misc/format-files --all --check
-    COMMENT "Checking code formatting"
-    USES_TERMINAL
-    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
-endif()
+add_custom_target(
+  format
+  COMMAND misc/format-files --all
+  COMMENT "Formatting code"
+  USES_TERMINAL
+  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+
+add_custom_target(
+  check_format
+  COMMAND misc/format-files --all --check
+  COMMENT "Checking code formatting"
+  USES_TERMINAL
+  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
index cb35bc0bf822dea605cd93a255064408d1f8f80d..ad4b8aa85d248737a51ff1ebd5084cbc9f88273a 100644 (file)
@@ -56,12 +56,12 @@ little.
 
 Source code formatting is defined by `.clang-format` in the root directory. The
 format is loosely based on [LLVM's code formatting
-style](https://llvm.org/docs/CodingStandards.html) with some exceptions. It's
-highly recommended to install
-[Clang-Format](https://clang.llvm.org/docs/ClangFormat.html) 6.0 or newer and
-run `make format` to format changes according to ccache's code style. Or even
-better: set up your editor to run Clang-Format automatically when saving. If you
-don't run Clang-Format then the ccache authors have to do it for you.
+style](https://llvm.org/docs/CodingStandards.html) with some exceptions. Run
+`make format` (or `ninja format` if you use Ninja) to format changes according
+to ccache's code style. Or even better: set up your editor to run
+`<ccache-top-dir>/misc/clang-format` (or any other Clang-Format version 10
+binary) automatically when saving. Newer Clang-Format versions likely also work
+fine.
 
 Please follow these conventions:
 
index e72161414d2c95058c973ebc55b2029c0e7d9b18..8246ecca4ec20aaf7a3f4eb0893b8485fa6876f7 100644 (file)
@@ -1,18 +1,18 @@
 # Add a build type called "CI" which is like RelWithDebInfo but with assertions
 # enabled, i.e. without passing -DNDEBUG to the compiler.
 
-set(CMAKE_CXX_FLAGS_CI ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} CACHE STRING
+set(CMAKE_CXX_FLAGS_CI "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" CACHE STRING
  "Flags used by the C++ compiler during CI builds."
   FORCE)
-set(CMAKE_C_FLAGS_CI ${CMAKE_C_FLAGS_RELWITHDEBINFO} CACHE STRING
+set(CMAKE_C_FLAGS_CI "${CMAKE_C_FLAGS_RELWITHDEBINFO}" CACHE STRING
   "Flags used by the C compiler during CI builds."
   FORCE)
 set(CMAKE_EXE_LINKER_FLAGS_CI
-  ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} CACHE STRING
+  "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING
   "Flags used for linking binaries during CI builds."
   FORCE)
 set(CMAKE_SHARED_LINKER_FLAGS_CI
-  ${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} CACHE STRING
+  "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING
   "Flags used by the shared libraries linker during CI builds."
   FORCE)
 mark_as_advanced(
@@ -25,7 +25,7 @@ set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
   "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel CI."
   FORCE)
 
-string(REGEX REPLACE "[/-]DNDEBUG" "" CMAKE_CXX_FLAGS_CI ${CMAKE_CXX_FLAGS_CI})
-string(REGEX REPLACE "[/-]DNDEBUG" "" CMAKE_C_FLAGS_CI ${CMAKE_C_FLAGS_CI})
-string(STRIP ${CMAKE_CXX_FLAGS_CI} CMAKE_CXX_FLAGS_CI)
-string(STRIP ${CMAKE_C_FLAGS_CI} CMAKE_C_FLAGS_CI)
+string(REGEX REPLACE "[/-]DNDEBUG" "" CMAKE_CXX_FLAGS_CI "${CMAKE_CXX_FLAGS_CI}")
+string(REGEX REPLACE "[/-]DNDEBUG" "" CMAKE_C_FLAGS_CI "${CMAKE_C_FLAGS_CI}")
+string(STRIP "${CMAKE_CXX_FLAGS_CI}" CMAKE_CXX_FLAGS_CI)
+string(STRIP "${CMAKE_C_FLAGS_CI}" CMAKE_C_FLAGS_CI)
index 2568fd57798127c08afdfdca4b89c2c43398681c..c0cbd91094a39ff46d3124c5e8ecf1e04dfb22d1 100644 (file)
@@ -22,7 +22,7 @@
 # CCACHE_VERSION_ORIGIN is set to "archive" in scenario 1 and "git" in scenario
 # 3.
 
-set(version_info "1a07c09dcbba202572c5ab1bc4b736183a318aa7 HEAD, tag: v4.2.1, origin/master, origin/HEAD, master")
+set(version_info "2c13bce2609a02b70c92e84cdd177a6072f44d5e HEAD, tag: v4.3, origin/master, origin/HEAD, master")
 
 if(version_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])[0-9a-f]* (.*)")
   # Scenario 1.
index 6e6b60487119a96e42d9462709aa7af4f32c1aaf..a4605293a1bdc29af2618ab5cc23a5f588d42dd8 100644 (file)
@@ -44,7 +44,7 @@ foreach(func IN ITEMS ${functions})
 endforeach()
 
 include(CheckCSourceCompiles)
-set(CMAKE_REQUIRED_LINK_OPTIONS -pthread)
+set(CMAKE_REQUIRED_FLAGS -pthread)
 check_c_source_compiles(
   [=[
     #include <pthread.h>
@@ -57,7 +57,7 @@ check_c_source_compiles(
   ]=]
   HAVE_PTHREAD_MUTEX_ROBUST)
 check_function_exists(pthread_mutexattr_setpshared HAVE_PTHREAD_MUTEXATTR_SETPSHARED)
-set(CMAKE_REQUIRED_LINK_OPTIONS)
+set(CMAKE_REQUIRED_FLAGS)
 
 include(CheckStructHasMember)
 check_struct_has_member("struct stat" st_ctim sys/stat.h
index ce44c8c8e40dab9b01271541a167f56ec986000c..2a8363a964809cc4b67d8bb0d6c67aa8a228d1dc 100644 (file)
@@ -22,6 +22,7 @@ Ccache is a collective work with contributions from many people, including:
 * Arne Hasselbring
 * Azat Khuzhin
 * Bernhard Bauer
+* Bin Li
 * Björn Jacke
 * Breno Guimaraes
 * Chiaki Ishikawa
@@ -58,6 +59,7 @@ Ccache is a collective work with contributions from many people, including:
 * Jon Petrissans
 * Jørgen P. Tjernø
 * Josh Soref
+* Josh Triplett
 * Justin Lebar
 * Ka Ho Ng
 * Karl Chen
@@ -106,6 +108,8 @@ Ccache is a collective work with contributions from many people, including:
 * Pawel Krysiak
 * Per Nordlöw
 * Peter Budai
+* Peter Steinberger
+* Petr Štetiar
 * Philippe Proulx
 * Philipp Storz
 * Rafael Kitover
index 2b6f0012883c348410369e34221cedb345130f2d..25c34c0dad7c07f0e0d3873f06c534631f23b13f 100644 (file)
@@ -824,6 +824,10 @@ still has to do _some_ preprocessing (like macros).
     mtime is too new. This sloppiness disables that check. See also
     _<<_handling_of_newly_created_header_files,Handling of newly created header
     files>>_.
+*ivfsoverlay*::
+    Ignore the Clang compiler option *-ivfsoverlay* and its argument. This is
+    useful if you use Xcode, which uses a virtual file system (VFS) for things
+    like combining Objective-C and Swift code.
 *locale*::
     Ccache includes the environment variables *LANG*, *LC_ALL*, *LC_CTYPE* and
     *LC_MESSAGES* in the hash by default since they may affect localization of
index 040a68e3a994efd6d4327c1ca3100d2cb61733d2..7d69bd49042564c3d896915de15ecbcb35d45631 100644 (file)
@@ -1,6 +1,55 @@
 Ccache news
 ===========
 
+Ccache 4.3
+----------
+Release date: 2021-05-09
+
+New features
+~~~~~~~~~~~~
+
+- Ccache now ignores the Clang compiler option `-ivfsoverlay` and its argument
+  if you opt in to ``ivfsoverlay sloppiness''. This is useful if you use Xcode,
+  which uses a virtual file system (VFS) for things like combining Objective-C
+  and Swift code.
+
+- When using `-P` in combination with `-E`, ccache now reports this as ``called
+  for preprocessing'' instead of ``unsupported compiler option''.
+
+- Added support for `-specs file.specs` and `--specs file.specs` without an
+  equal sign between the arguments.
+
+
+Bug fixes
+~~~~~~~~~
+
+- "Split dwarf" code paths are now disabled when outputting to `/dev/null`. This
+  avoids an attempt to delete `/dev/null.dwo`.
+
+- Made the `stat`/`lstat` wrapper function for Windows treat pending deletes as
+  missing files.
+
+- Fixed a bug that made ccache process header files redundantly for some
+  relative headers when using Clang.
+
+- The object path in now included in the input hash when using `-fprofile-arcs`
+  (or `--coverage`) since the object file embeds a `.gcda` path based on the
+  object file path.
+
+
+Build improvements
+~~~~~~~~~~~~~~~~~~
+
+- Added an `ENABLE_DOCUMENTATION` build option (default: true) that can be used
+  to disable the build of documentation.
+
+- Fixed detection of pthread features.
+
+- Quote CMake variables expansions to avoid errors when
+  `${CMAKE_C_FLAGS_RELWITHDEBINFO}` or `${CMAKE_CXX_FLAGS_RELWITHDEBINFO}`
+  expands to the empty string.
+
+
 Ccache 4.2.1
 ------------
 Release date: 2021-03-27
@@ -8,9 +57,9 @@ Release date: 2021-03-27
 Bug fixes
 ~~~~~~~~~
 
-- Ccache now only `dup2`s stderr into `$UNCACHED_ERR_FD` for calls to the
-  preprocessor/compiler. This works around a complex bug in interaction with GNU
-  Make, LTO linking and the Linux PTY driver.
+- Ccache now only duplicates the stderr file descriptor into `$UNCACHED_ERR_FD`
+  for calls to the preprocessor/compiler. This works around a complex bug in
+  interaction with GNU Make, LTO linking and the Linux PTY driver.
 
 - Fixed detection of color diagnostics usage when using `-Xclang
   -fcolor-diagnostics` options.
diff --git a/misc/clang-format b/misc/clang-format
new file mode 100755 (executable)
index 0000000..b198be2
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/sh
+#
+# This script executes clang-format in the following order:
+#
+# 1. If environment variable CLANG_FORMAT is set, execute $CLANG_FORMAT.
+# 2. Otherwise, if <ccache-top-dir>/misc/.clang-format-exe exists, execute that
+#    program.
+# 3. Otherwise, download a statically linked clang-format executable, verify its
+#    integrity, place it in <ccache-top-dir>/misc/.clang-format-exe and execute
+#    it.
+
+set -eu
+
+if [ -n "${CLANG_FORMAT:-}" ]; then
+    exec "$CLANG_FORMAT" "$@"
+fi
+
+top_dir="$(dirname "$0")"
+clang_format_exe="$top_dir/.clang-format-exe"
+clang_format_version=10
+url_prefix="https://github.com/muttleyxd/clang-tools-static-binaries/releases/download/master-22538c65/clang-format-${clang_format_version}_"
+
+if [ ! -x "$clang_format_exe" ]; then
+    case "$(uname -s | tr '[:upper:]' '[:lower:]')" in
+        *mingw*|*cygwin*|*msys*)
+            url_suffix=windows-amd64.exe
+            checksum=0b21dfb9041437eebcc44032096e4dfba9ee7b668ee6867ada71ea3541f7b09657ea592a5b1cf659bc9f8072bdc477dfc9da07b3edacb7834b70e68d7a3fc887
+            ;;
+        *darwin*)
+            url_suffix=macosx-amd64
+            checksum=8458753e13d3cbb7949a302beab812bed6d9dd9001c6e9618e5ba2e438233633ae04704a4e150aa2abfbaf103f1df4bc4a77b306012f44b37e543964bd527951
+            ;;
+        *linux*)
+            url_suffix=linux-amd64
+            checksum=3c4aaa90ad83313a1d7b350b30f9ad62578be73241f00f7d6e92838289e0b734fab80dee9dfcbd1546135bdb4e3601cfb2cf6b47360fba0bfc961e5a7cab2015
+            ;;
+        *)
+            echo "Error: Please set CLANG_FORMAT to clang-format version $clang_format_version" >&2
+            exit 1
+            ;;
+    esac
+
+    url="$url_prefix$url_suffix"
+
+    if command -v wget >/dev/null; then
+        wget -qO "$clang_format_exe.tmp" "$url"
+    elif command -v curl >/dev/null; then
+        curl -so "$clang_format_exe.tmp" -L --retry 20 "$url"
+    else
+        echo "Error: Neither wget nor curl found" >&2
+        exit 1
+    fi
+
+    if ! command -v sha512sum >/dev/null; then
+        echo "Warning: sha512sum not found, not verifying clang-format integrity" >&2
+    elif ! echo "$checksum $clang_format_exe.tmp" | sha512sum --status -c; then
+        echo "Error: Bad checksum of downloaded clang-format" >&2
+        exit 1
+    fi
+
+    chmod +x "$clang_format_exe.tmp"
+    mv "$clang_format_exe.tmp" "$clang_format_exe"
+fi
+
+exec "$clang_format_exe" "$@"
index 111705ada475a4a4d0d35bad44336c2b69613420..44340b9f657fcdf0ed73ff274eba25b92a1ea263 100755 (executable)
@@ -27,7 +27,7 @@ if [ -n "$all" ]; then
     exec sh "$0" $check $(git ls-files '*.[ch]' '*.[ch]pp' ':!:src/third_party')
 fi
 
-clang_format=${CLANG_FORMAT:-clang-format}
+clang_format="$(dirname "$0")/clang-format"
 [ -t 1 ] && cf_color="--color=always" || cf_color=""
 
 if [ -n "${VERBOSE:-}" ]; then
index ae428096a56b3643668fd57102c9e8ac8d184f16..48fb77df5cdd3e2a2857d2a2c9b5164c9749bda6 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2020 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2021 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -115,18 +115,14 @@ Args::size() const
   return m_args.size();
 }
 
-// clang-format off
 inline const std::string&
 Args::operator[](size_t i) const
-// clang-format on
 {
   return m_args[i];
 }
 
-// clang-format off
 inline std::string&
 Args::operator[](size_t i)
-// clang-format on
 {
   return m_args[i];
 }
index 8f45adfa9eebf5df101d0d3f4274abe0f3d7c0d5..b9369476731b9344700434edab04f836e0e9ebf8 100644 (file)
@@ -26,10 +26,9 @@ CacheEntryWriter::CacheEntryWriter(FILE* stream,
                                    uint64_t payload_size)
   // clang-format off
   : m_compressor(
-      Compressor::create_from_type(compression_type, stream, compression_level)
-    )
+      Compressor::create_from_type(compression_type, stream, compression_level))
+// clang-format on
 {
-  // clang-format on
   uint8_t header_bytes[15];
   memcpy(header_bytes, magic, 4);
   header_bytes[4] = version;
index 68dc3f5752dffe8d6c50e439cd2005a0c2603c08..9e7092360f887044e34b2c701efd1de52b4890ce 100644 (file)
@@ -275,6 +275,8 @@ parse_sloppiness(const std::string& value)
       result |= SLOPPY_LOCALE;
     } else if (token == "modules") {
       result |= SLOPPY_MODULES;
+    } else if (token == "ivfsoverlay") {
+      result |= SLOPPY_IVFSOVERLAY;
     } // else: ignore unknown value for forward compatibility
     start = value.find_first_not_of(", ", end);
   }
@@ -315,6 +317,9 @@ format_sloppiness(uint32_t sloppiness)
   if (sloppiness & SLOPPY_MODULES) {
     result += "modules, ";
   }
+  if (sloppiness & SLOPPY_IVFSOVERLAY) {
+    result += "ivfsoverlay, ";
+  }
   if (!result.empty()) {
     // Strip last ", ".
     result.resize(result.size() - 2);
index 80bc77eae9026976ee16e6aea11ecfb348e7f136..6316e45cedebdac0d48313755b84b106556708be 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2020 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2021 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -72,10 +72,8 @@ Fd::get() const
   return m_fd;
 }
 
-// clang-format off
 inline int
 Fd::operator*() const
-// clang-format on
 {
   ASSERT(m_fd != -1);
   return m_fd;
index 6f0dd21cdd7ffae60a86ef2223b6f933de661ac8..f8f6c0be48421ad6bfc83dbc70a77dabf5b2a8de 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2020 Joel Rosdahl and other contributors
+// Copyright (C) 2019-2021 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -89,10 +89,8 @@ inline File::operator bool() const
   return m_file;
 }
 
-// clang-format off
 inline FILE*
 File::operator*() const
-// clang-format on
 {
   return m_file;
 }
index bf17397b92d5f04066a74bea56257c84a3cf1deb..0516562f1f0987fa5f6d35770cadd6f8e92c5ca2 100644 (file)
@@ -65,7 +65,8 @@ time_seconds()
 } // namespace
 
 MiniTrace::MiniTrace(const ArgsInfo& args_info)
-  : m_args_info(args_info), m_trace_id(reinterpret_cast<void*>(getpid()))
+  : m_args_info(args_info),
+    m_trace_id(reinterpret_cast<void*>(getpid()))
 {
   TemporaryFile tmp_file(get_system_tmp_dir() + "/ccache-trace");
   m_tmp_trace_file = tmp_file.path;
index b20aa6228acb54b6a9ea6c9bab806c1bf678531d..8408d2a7b7fd3037e8caf45fd853795e8697f638 100644 (file)
@@ -300,7 +300,8 @@ Reader::read_entry(CacheEntryReader& cache_entry_reader,
 }
 
 Writer::Writer(Context& ctx, const std::string& result_path)
-  : m_ctx(ctx), m_result_path(result_path)
+  : m_ctx(ctx),
+    m_result_path(result_path)
 {
 }
 
index 957bbee4929424b81288e70857b2b19157760a9b..0218877c3ab801e65e0f102712a16cc3bea638bf 100644 (file)
@@ -25,7 +25,8 @@
 using Result::FileType;
 
 ResultRetriever::ResultRetriever(Context& ctx, bool rewrite_dependency_target)
-  : m_ctx(ctx), m_rewrite_dependency_target(rewrite_dependency_target)
+  : m_ctx(ctx),
+    m_rewrite_dependency_target(rewrite_dependency_target)
 {
 }
 
index bd2078e9a120b238f11933be33944ce33de09794..62c0508a8e912a8134d762b376ed697371aef872 100644 (file)
@@ -38,4 +38,6 @@ enum Sloppiness {
   SLOPPY_LOCALE = 1 << 8,
   // Allow caching even if -fmodules is used.
   SLOPPY_MODULES = 1 << 9,
+  // Ignore virtual file system (VFS) overlay file.
+  SLOPPY_IVFSOVERLAY = 1 << 10,
 };
index d491682937112bd0e703da72e7566e5cefd3579f..244fd6f5a911f9c33308fecd63c357846b958fd7 100644 (file)
@@ -19,6 +19,8 @@
 #include "Stat.hpp"
 
 #ifdef _WIN32
+#  include "Win32Util.hpp"
+
 #  include "third_party/win32/winerror_to_errno.h"
 #endif
 
@@ -124,6 +126,11 @@ win32_stat_impl(const char* path, bool traverse_links, Stat::stat_t* st)
   }
 
   if (handle == INVALID_HANDLE_VALUE) {
+    if (GetLastError() == ERROR_ACCESS_DENIED
+        && Win32Util::get_last_ntstatus() == STATUS_DELETE_PENDING) {
+      // Treat a 'pending delete' as a nonexistent file.
+      SetLastError(ERROR_FILE_NOT_FOUND);
+    }
     return false;
   }
 
index b259ed0e98d159215fa61c0e9e1118df80863a89..1a9de6a0b71ca88f066db8069c6e0cc8a9fb5417 100644 (file)
 #include <chrono>
 #include <thread>
 
+namespace {
+
+template<typename Proc>
+Proc*
+get_proc_address(HMODULE module, const char* proc_name)
+{
+#if defined __GNUC__
+#  pragma GCC diagnostic push
+#  if __GNUC__ >= 8
+#    pragma GCC diagnostic ignored "-Wcast-function-type"
+#  endif
+#endif
+  return reinterpret_cast<Proc*>(GetProcAddress(module, proc_name));
+#if defined __GNUC__
+#  pragma GCC diagnostic pop
+#endif
+}
+
+} // namespace
+
 namespace Win32Util {
 
 std::string
@@ -97,6 +117,14 @@ argv_to_string(const char* const* argv,
   return result;
 }
 
+NTSTATUS
+get_last_ntstatus()
+{
+  static auto* get_last_ntstatus_fn = get_proc_address<NTSTATUS NTAPI()>(
+    GetModuleHandleA("ntdll.dll"), "RtlGetLastNtStatus");
+  return get_last_ntstatus_fn();
+}
+
 } // namespace Win32Util
 
 // From: https://stackoverflow.com/a/58162122/262458
index d6fc57595a10c8839f13c5971a8ef768d01694a1..0a2f1a133c30ed470d4e23abd7613d6858e7ab57 100644 (file)
@@ -39,4 +39,8 @@ std::string argv_to_string(const char* const* argv,
 // Return the error message corresponding to `error_code`.
 std::string error_message(DWORD error_code);
 
+// Returns the last NTSTATUS code. (These can be more specific than the
+// corresponding Win32 error code.)
+NTSTATUS get_last_ntstatus();
+
 } // namespace Win32Util
index a53cfa2ad86edfdd06c4782f40b14136462e04e1..39f6bb25cc4314aceaa4ce0ac863d455d888538b 100644 (file)
@@ -25,7 +25,8 @@
 #include <algorithm>
 
 ZstdCompressor::ZstdCompressor(FILE* stream, int8_t compression_level)
-  : m_stream(stream), m_zstd_stream(ZSTD_createCStream())
+  : m_stream(stream),
+    m_zstd_stream(ZSTD_createCStream())
 {
   if (compression_level == 0) {
     compression_level = default_compression_level;
index e39c4e54fd062bb403158a47e1c1c37caa2bd215..92b929e09b29f3e3eb3bf4c62160e623503f0222 100644 (file)
@@ -232,6 +232,15 @@ process_arg(Context& ctx,
     return nullopt;
   }
 
+  // Ignore clang -ivfsoverlay <arg> to not detect multiple input files.
+  if (args[i] == "-ivfsoverlay"
+      && !(config.sloppiness() & SLOPPY_IVFSOVERLAY)) {
+    LOG_RAW(
+      "You have to specify \"ivfsoverlay\" sloppiness when using"
+      " -ivfsoverlay to get hits");
+    return Statistic::unsupported_compiler_option;
+  }
+
   // Special case for -E.
   if (args[i] == "-E") {
     return Statistic::called_for_preprocessing;
@@ -618,13 +627,19 @@ process_arg(Context& ctx,
     return nullopt;
   }
 
+  if (args[i] == "-P" || args[i] == "-Wp,-P") {
+    // Avoid passing -P to the preprocessor since it removes preprocessor
+    // information we need.
+    state.compiler_only_args.push_back(args[i]);
+    LOG("{} used; not compiling preprocessed code", args[i]);
+    config.set_run_second_cpp(true);
+    return nullopt;
+  }
+
   if (Util::starts_with(args[i], "-Wp,")) {
-    if (args[i] == "-Wp,-P" || args[i].find(",-P,") != std::string::npos
+    if (args[i].find(",-P,") != std::string::npos
         || Util::ends_with(args[i], ",-P")) {
-      // -P removes preprocessor information in such a way that the object file
-      // from compiling the preprocessed file will not be equal to the object
-      // file produced when compiling without ccache.
-      LOG_RAW("Too hard option -Wp,-P detected");
+      // -P together with other preprocessor options is just too hard.
       return Statistic::unsupported_compiler_option;
     } else if (Util::starts_with(args[i], "-Wp,-MD,")
                && args[i].find(',', 8) == std::string::npos) {
@@ -1107,7 +1122,14 @@ process_args(Context& ctx)
   }
 
   if (args_info.seen_split_dwarf) {
-    args_info.output_dwo = Util::change_extension(args_info.output_obj, ".dwo");
+    if (args_info.output_obj == "/dev/null") {
+      // Outputting to /dev/null -> compiler won't write a .dwo, so just pretend
+      // we haven't seen the -gsplit-dwarf option.
+      args_info.seen_split_dwarf = false;
+    } else {
+      args_info.output_dwo =
+        Util::change_extension(args_info.output_obj, ".dwo");
+    }
   }
 
   // Cope with -o /dev/null.
index 7d39e5bbc273f5cc03efcd6f2fcb72190983ef08..761b9ab437a2f75e39132428ad1bec81663946bd 100644 (file)
@@ -205,7 +205,8 @@ private:
 };
 
 inline Failure::Failure(Statistic statistic, nonstd::optional<int> exit_code)
-  : m_statistic(statistic), m_exit_code(exit_code)
+  : m_statistic(statistic),
+    m_exit_code(exit_code)
 {
 }
 
@@ -398,16 +399,16 @@ do_remember_include_file(Context& ctx,
     return true;
   }
 
-  if (ctx.included_files.find(path) != ctx.included_files.end()) {
-    // Already known include file.
-    return true;
-  }
-
   // Canonicalize path for comparison; Clang uses ./header.h.
   if (Util::starts_with(path, "./")) {
     path.erase(0, 2);
   }
 
+  if (ctx.included_files.find(path) != ctx.included_files.end()) {
+    // Already known include file.
+    return true;
+  }
+
 #ifdef _WIN32
   {
     // stat fails on directories on win32.
@@ -1425,14 +1426,17 @@ hash_common_info(const Context& ctx,
 
   if ((!should_rewrite_dependency_target(ctx.args_info)
        && ctx.args_info.generating_dependencies)
-      || ctx.args_info.seen_split_dwarf) {
-    // The output object file name is part of the .d file, so include the path
-    // in the hash if generating dependencies.
+      || ctx.args_info.seen_split_dwarf || ctx.args_info.profile_arcs) {
+    // If generating dependencies: The output object file name is part of the .d
+    // file, so include the path in the hash.
     //
-    // Object files include a link to the corresponding .dwo file based on the
-    // target object filename when using -gsplit-dwarf, so hashing the object
-    // file path will do it, although just hashing the object file base name
-    // would be enough.
+    // When using -gsplit-dwarf: Object files include a link to the
+    // corresponding .dwo file based on the target object filename, so hashing
+    // the object file path will do it, although just hashing the object file
+    // base name would be enough.
+    //
+    // When using -fprofile-arcs (including implicitly via --coverage): the
+    // object file contains a .gcda path based on the object file path.
     hash.hash_delimiter("object file");
     hash.hash(ctx.args_info.output_obj);
   }
@@ -1652,8 +1656,20 @@ calculate_result_name(Context& ctx,
     }
 
     if (Util::starts_with(args[i], "-specs=")
-        || Util::starts_with(args[i], "--specs=")) {
-      std::string path = args[i].substr(args[i].find('=') + 1);
+        || Util::starts_with(args[i], "--specs=")
+        || (args[i] == "-specs" || args[i] == "--specs")) {
+      std::string path;
+      size_t eq_pos = args[i].find('=');
+      if (eq_pos == std::string::npos) {
+        if (i + 1 >= args.size()) {
+          LOG("missing argument for \"{}\"", args[i]);
+          throw Failure(Statistic::bad_compiler_arguments);
+        }
+        path = args[i + 1];
+        i++;
+      } else {
+        path = args[i].substr(eq_pos + 1);
+      }
       auto st = Stat::stat(path, Stat::OnError::log);
       if (st) {
         // If given an explicit specs file, then hash that file, but don't
index d69f74aa852fcaec45536e4c3f688cb1af5588b4..3ed4f5b5b8acb0ec44558407834cd1b79af3bc41 100644 (file)
@@ -62,6 +62,7 @@ const CompOpt compopts[] = {
   {"--save-temps=cwd", TOO_HARD},
   {"--save-temps=obj", TOO_HARD},
   {"--serialize-diagnostics", TAKES_ARG | TAKES_PATH},
+  {"--specs", TAKES_ARG},
   {"-A", TAKES_ARG},
   {"-B", TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
   {"-D", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
@@ -76,7 +77,6 @@ const CompOpt compopts[] = {
   {"-MM", TOO_HARD},
   {"-MQ", TAKES_ARG},
   {"-MT", TAKES_ARG},
-  {"-P", TOO_HARD},
   {"-U", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
   {"-V", TAKES_ARG},
   {"-Wa,", TAKES_CONCAT_ARG | AFFECTS_COMP},
@@ -116,6 +116,7 @@ const CompOpt compopts[] = {
   {"-iquote", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
   {"-isysroot", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
   {"-isystem", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+  {"-ivfsoverlay", TAKES_ARG},
   {"-iwithprefix", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
   {"-iwithprefixbefore",
    AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
@@ -132,6 +133,7 @@ const CompOpt compopts[] = {
   {"-save-temps", TOO_HARD},
   {"-save-temps=cwd", TOO_HARD},
   {"-save-temps=obj", TOO_HARD},
+  {"-specs", TAKES_ARG},
   {"-stdlib=", AFFECTS_CPP | TAKES_CONCAT_ARG},
   {"-trigraphs", AFFECTS_CPP},
   {"-u", TAKES_ARG | TAKES_CONCAT_ARG},
index 6115c5ba5a214776c70de308ce5307342c3e6c0d..fa4bbf3e37d97ffd5ba39ab4afcd27d168c6c82e 100644 (file)
@@ -158,7 +158,10 @@ const mode_t S_IWUSR = mode_t(_S_IWRITE);
 #  include <io.h>
 #  include <process.h>
 #  define NOMINMAX 1
+#  define WIN32_NO_STATUS
 #  include <windows.h>
+#  undef WIN32_NO_STATUS
+#  include <ntstatus.h>
 #  define mkdir(a, b) _mkdir(a)
 #  define execv(a, b)                                                          \
     do_not_call_execv_on_windows // to protect against incidental use of MinGW
index c33befd075b43c1e6bcbf58fceec3b5881c639e0..ae0df8e8a6f5f34ee92b2b546d4c1ab3eea8a4e8 100644 (file)
@@ -47,6 +47,7 @@ addtest(fileclone)
 addtest(hardlink)
 addtest(inode_cache)
 addtest(input_charset)
+addtest(ivfsoverlay)
 addtest(masquerading)
 addtest(modules)
 addtest(multi_arch)
index 9629a06d3b27a4541f689f2f182696583ed97bd4..37b7755daa86bfe72b4fd993bfcaeaedb673f65d 100644 (file)
@@ -1224,43 +1224,59 @@ EOF
     expect_stat 'files in cache' 0
 
     # -------------------------------------------------------------------------
-    TEST "-P"
+    TEST "-P -c"
 
-    # Check that -P disables ccache. (-P removes preprocessor information in
-    # such a way that the object file from compiling the preprocessed file will
-    # not be equal to the object file produced when compiling without ccache.)
+    $CCACHE_COMPILE -P -c test1.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
 
-    $CCACHE_COMPILE -c -P test1.c
+    $CCACHE_COMPILE -P -c test1.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 1
+    expect_stat 'cache miss' 1
+
+    # -------------------------------------------------------------------------
+    TEST "-P -E"
+
+    $CCACHE_COMPILE -P -E test1.c
     expect_stat 'cache hit (direct)' 0
     expect_stat 'cache hit (preprocessed)' 0
     expect_stat 'cache miss' 0
-    expect_stat 'unsupported compiler option' 1
+    expect_stat 'called for preprocessing' 1
 
     # -------------------------------------------------------------------------
     TEST "-Wp,-P"
 
-    # Check that -Wp,-P disables ccache. (-P removes preprocessor information
-    # in such a way that the object file from compiling the preprocessed file
-    # will not be equal to the object file produced when compiling without
-    # ccache.)
-
     $CCACHE_COMPILE -c -Wp,-P test1.c
     expect_stat 'cache hit (direct)' 0
     expect_stat 'cache hit (preprocessed)' 0
-    expect_stat 'cache miss' 0
-    expect_stat 'unsupported compiler option' 1
+    expect_stat 'cache miss' 1
+
+    $CCACHE_COMPILE -c -Wp,-P test1.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 1
+    expect_stat 'cache miss' 1
+
+    # -------------------------------------------------------------------------
+    TEST "-Wp,-P,-DFOO"
+
+    # Check that -P disables ccache when used in combination with other -Wp,
+    # options. (-P removes preprocessor information in such a way that the
+    # object file from compiling the preprocessed file will not be equal to the
+    # object file produced when compiling without ccache.)
 
     $CCACHE_COMPILE -c -Wp,-P,-DFOO test1.c
     expect_stat 'cache hit (direct)' 0
     expect_stat 'cache hit (preprocessed)' 0
     expect_stat 'cache miss' 0
-    expect_stat 'unsupported compiler option' 2
+    expect_stat 'unsupported compiler option' 1
 
     $CCACHE_COMPILE -c -Wp,-DFOO,-P test1.c
     expect_stat 'cache hit (direct)' 0
     expect_stat 'cache hit (preprocessed)' 0
     expect_stat 'cache miss' 0
-    expect_stat 'unsupported compiler option' 3
+    expect_stat 'unsupported compiler option' 2
 
     # -------------------------------------------------------------------------
     TEST "-Wp,-D"
diff --git a/test/suites/ivfsoverlay.bash b/test/suites/ivfsoverlay.bash
new file mode 100644 (file)
index 0000000..ca88221
--- /dev/null
@@ -0,0 +1,44 @@
+SUITE_ivfsoverlay_PROBE() {
+    if ! $COMPILER_TYPE_CLANG; then
+        echo "-ivfsoverlay not supported by compiler"
+    else
+        touch test.c
+        cat <<EOF >test.yaml
+{"case-sensitive":"false","roots":[],"version":0}
+EOF
+        $COMPILER -ivfsoverlay test.yaml test.c -S || echo "compiler does not support -ivfsoverlay"
+    fi
+}
+
+SUITE_ivfsoverlay_SETUP() {
+    unset CCACHE_NODIRECT
+
+    cat <<EOF >test.yaml
+{"case-sensitive":"false","roots":[],"version":0}
+EOF
+    cat <<EOF >test.c
+// test.c
+int test;
+EOF
+}
+
+SUITE_ivfsoverlay() {
+    # -------------------------------------------------------------------------
+    TEST "without sloppy ivfsoverlay"
+
+    $CCACHE_COMPILE -ivfsoverlay test.yaml -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 0
+    expect_stat 'unsupported compiler option' 1
+
+    # -------------------------------------------------------------------------
+    TEST "with sloppy ivfsoverlay"
+
+    CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS ivfsoverlay" $CCACHE_COMPILE -ivfsoverlay test.yaml -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS ivfsoverlay" $CCACHE_COMPILE -ivfsoverlay test.yaml -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 1
+}
index b7abaa2a53f0e99a2d67a072ba863027e3114e31..dbe36d41f9211bedf600950be5bae854393c92f4 100644 (file)
@@ -128,6 +128,29 @@ SUITE_profiling() {
             rm "$gcno_name"
         done
     done
+
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-arcs for different object file paths"
+
+    mkdir obj1 obj2
+
+    $CCACHE_COMPILE -fprofile-arcs -c test.c -o obj1/test.o
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $CCACHE_COMPILE -fprofile-arcs -c test.c -o obj1/test.o
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 1
+
+    $CCACHE_COMPILE -fprofile-arcs -c test.c -o obj2/test.o
+    expect_different_content obj1/test.o obj2/test.o # different paths to .gcda file
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fprofile-arcs -c test.c -o obj2/test.o
+    expect_different_content obj1/test.o obj2/test.o # different paths to .gcda file
+    expect_stat 'cache hit (direct)' 2
+    expect_stat 'cache miss' 2
 }
 
 merge_profiling_data() {
index fad4ff424be73331d7ed5e248888877926baf290..e509c9cee9932ac551afd08bf3da50ed554866a4 100644 (file)
@@ -128,7 +128,7 @@ TEST_CASE("Config::update_from_file")
     "run_second_cpp = false\n"
     "sloppiness =     time_macros   ,include_file_mtime"
     "  include_file_ctime,file_stat_matches,file_stat_matches_ctime,pch_defines"
-    " ,  no_system_headers,system_headers,clang_index_store\n"
+    " ,  no_system_headers,system_headers,clang_index_store,ivfsoverlay\n"
     "stats = false\n"
     "temporary_dir = ${USER}_foo\n"
     "umask = 777"); // Note: no newline.
@@ -169,7 +169,8 @@ TEST_CASE("Config::update_from_file")
         == (SLOPPY_INCLUDE_FILE_MTIME | SLOPPY_INCLUDE_FILE_CTIME
             | SLOPPY_TIME_MACROS | SLOPPY_FILE_STAT_MATCHES
             | SLOPPY_FILE_STAT_MATCHES_CTIME | SLOPPY_SYSTEM_HEADERS
-            | SLOPPY_PCH_DEFINES | SLOPPY_CLANG_INDEX_STORE));
+            | SLOPPY_PCH_DEFINES | SLOPPY_CLANG_INDEX_STORE
+            | SLOPPY_IVFSOVERLAY));
   CHECK_FALSE(config.stats());
   CHECK(config.temporary_dir() == FMT("{}_foo", user));
   CHECK(config.umask() == 0777);
@@ -402,7 +403,7 @@ TEST_CASE("Config::visit_items")
     "run_second_cpp = false\n"
     "sloppiness = include_file_mtime, include_file_ctime, time_macros,"
     " file_stat_matches, file_stat_matches_ctime, pch_defines, system_headers,"
-    " clang_index_store\n"
+    " clang_index_store, ivfsoverlay\n"
     "stats = false\n"
     "temporary_dir = td\n"
     "umask = 022\n");
@@ -459,7 +460,7 @@ TEST_CASE("Config::visit_items")
     "(test.conf) run_second_cpp = false",
     "(test.conf) sloppiness = include_file_mtime, include_file_ctime,"
     " time_macros, pch_defines, file_stat_matches, file_stat_matches_ctime,"
-    " system_headers, clang_index_store",
+    " system_headers, clang_index_store, ivfsoverlay",
     "(test.conf) stats = false",
     "(test.conf) temporary_dir = td",
     "(test.conf) umask = 022",
index 6f8baa6495537253af292a742ae92aa14cf7da86..e5b6eeb8385fd7fb2e7fa0f7510afb627dd2c66a 100644 (file)
@@ -579,7 +579,7 @@ TEST_CASE("Win32 Pending Delete" * doctest::skip(running_under_wine()))
   // will persist until the handle is closed. Until the file is closed, new
   // handles cannot be created to the file; attempts to do so fail with
   // ERROR_ACCESS_DENIED/STATUS_DELETE_PENDING. Our stat implementation maps
-  // these to EACCES. (Should this be ENOENT?)
+  // these to ENOENT.
   FILE_DISPOSITION_INFO info{};
   info.DeleteFile = TRUE;
   REQUIRE_MESSAGE(SetFileInformationByHandle(
@@ -590,14 +590,14 @@ TEST_CASE("Win32 Pending Delete" * doctest::skip(running_under_wine()))
   {
     auto st = Stat::stat("file");
     CHECK(!st);
-    CHECK(st.error_number() == EACCES);
+    CHECK(st.error_number() == ENOENT);
   }
 
   SUBCASE("lstat file pending delete")
   {
     auto st = Stat::lstat("file");
     CHECK(!st);
-    CHECK(st.error_number() == EACCES);
+    CHECK(st.error_number() == ENOENT);
   }
 }