From 954d77b98dd69c6bcf808e3dac871171d4832bad Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Thu, 21 Oct 2021 13:28:05 +0200 Subject: [PATCH] [clang][deps] Ensure reported context hash is strict One of main goals of the dependency scanner is to be strict about module compatibility. This is achieved through strict context hash. This patch ensures that strict context hash is enabled not only during the scan itself (and its minimized implicit build), but also when actually reporting the dependency. Reviewed By: dexonsmith Differential Revision: https://reviews.llvm.org/D111720 --- .../DependencyScanning/ModuleDepCollector.cpp | 8 ++ .../Inputs/modules-context-hash/a/dep.h | 0 .../Inputs/modules-context-hash/b/dep.h | 0 .../Inputs/modules-context-hash/cdb.json.template | 12 +++ .../Inputs/modules-context-hash/mod.h | 1 + .../Inputs/modules-context-hash/module.modulemap | 1 + .../ClangScanDeps/Inputs/modules-context-hash/tu.c | 1 + clang/test/ClangScanDeps/modules-context-hash.c | 89 ++++++++++++++++++++++ 8 files changed, 112 insertions(+) create mode 100644 clang/test/ClangScanDeps/Inputs/modules-context-hash/a/dep.h create mode 100644 clang/test/ClangScanDeps/Inputs/modules-context-hash/b/dep.h create mode 100644 clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb.json.template create mode 100644 clang/test/ClangScanDeps/Inputs/modules-context-hash/mod.h create mode 100644 clang/test/ClangScanDeps/Inputs/modules-context-hash/module.modulemap create mode 100644 clang/test/ClangScanDeps/Inputs/modules-context-hash/tu.c create mode 100644 clang/test/ClangScanDeps/modules-context-hash.c diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index 919c7d1..8144f25 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -55,6 +55,14 @@ CompilerInvocation ModuleDepCollector::makeInvocationForModuleBuildWithoutPaths( Optimize(CI); + // The original invocation probably didn't have strict context hash enabled. + // We will use the context hash of this invocation to distinguish between + // multiple incompatible versions of the same module and will use it when + // reporting dependencies to the clients. Let's make sure we're using + // **strict** context hash in order to prevent accidental sharing of + // incompatible modules (e.g. with differences in search paths). + CI.getHeaderSearchOpts().ModulesStrictContextHash = true; + return CI; } diff --git a/clang/test/ClangScanDeps/Inputs/modules-context-hash/a/dep.h b/clang/test/ClangScanDeps/Inputs/modules-context-hash/a/dep.h new file mode 100644 index 0000000..e69de29 diff --git a/clang/test/ClangScanDeps/Inputs/modules-context-hash/b/dep.h b/clang/test/ClangScanDeps/Inputs/modules-context-hash/b/dep.h new file mode 100644 index 0000000..e69de29 diff --git a/clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb.json.template b/clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb.json.template new file mode 100644 index 0000000..81f7084 --- /dev/null +++ b/clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb.json.template @@ -0,0 +1,12 @@ +[ + { + "directory": "DIR", + "command": "clang -c DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -IDIR/a -o DIR/tu_a.o", + "file": "DIR/tu.c" + }, + { + "directory": "DIR", + "command": "clang -c DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -IDIR/b -o DIR/tu_b.o", + "file": "DIR/tu.c" + } +] diff --git a/clang/test/ClangScanDeps/Inputs/modules-context-hash/mod.h b/clang/test/ClangScanDeps/Inputs/modules-context-hash/mod.h new file mode 100644 index 0000000..075cfb1 --- /dev/null +++ b/clang/test/ClangScanDeps/Inputs/modules-context-hash/mod.h @@ -0,0 +1 @@ +#include "dep.h" diff --git a/clang/test/ClangScanDeps/Inputs/modules-context-hash/module.modulemap b/clang/test/ClangScanDeps/Inputs/modules-context-hash/module.modulemap new file mode 100644 index 0000000..03cbffa --- /dev/null +++ b/clang/test/ClangScanDeps/Inputs/modules-context-hash/module.modulemap @@ -0,0 +1 @@ +module mod { header "mod.h" } diff --git a/clang/test/ClangScanDeps/Inputs/modules-context-hash/tu.c b/clang/test/ClangScanDeps/Inputs/modules-context-hash/tu.c new file mode 100644 index 0000000..01f1458 --- /dev/null +++ b/clang/test/ClangScanDeps/Inputs/modules-context-hash/tu.c @@ -0,0 +1 @@ +#include "mod.h" diff --git a/clang/test/ClangScanDeps/modules-context-hash.c b/clang/test/ClangScanDeps/modules-context-hash.c new file mode 100644 index 0000000..0b9a3e0 --- /dev/null +++ b/clang/test/ClangScanDeps/modules-context-hash.c @@ -0,0 +1,89 @@ +// RUN: rm -rf %t && mkdir %t +// RUN: cp -r %S/Inputs/modules-context-hash/* %t + +// Check that the scanner reports the same module as distinct dependencies when +// a single translation unit gets compiled with multiple command-lines that +// produce different **strict** context hashes. + +// RUN: sed "s|DIR|%/t|g" %S/Inputs/modules-context-hash/cdb.json.template > %t/cdb.json +// RUN: echo -%t > %t/result.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -j 1 >> %t/result.json +// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck %s -check-prefix=CHECK + +// CHECK: -[[PREFIX:.*]] +// CHECK-NEXT: { +// CHECK-NEXT: "modules": [ +// CHECK-NEXT: { +// CHECK-NEXT: "clang-module-deps": [], +// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "command-line": [ +// CHECK-NEXT: "-cc1" +// CHECK: "-emit-module" +// CHECK: "-I" +// CHECK: "[[PREFIX]]/a" +// CHECK: "-fmodule-name=mod" +// CHECK: ], +// CHECK-NEXT: "context-hash": "[[HASH_MOD_A:.*]]", +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/a/dep.h", +// CHECK-NEXT: "[[PREFIX]]/mod.h", +// CHECK-NEXT: "[[PREFIX]]/module.modulemap" +// CHECK-NEXT: ], +// CHECK-NEXT: "name": "mod" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "clang-module-deps": [], +// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "command-line": [ +// CHECK-NEXT: "-cc1" +// CHECK: "-emit-module" +// CHECK: "-I" +// CHECK: "[[PREFIX]]/b" +// CHECK: "-fmodule-name=mod" +// CHECK: ], +// CHECK-NEXT: "context-hash": "[[HASH_MOD_B:.*]]", +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/b/dep.h", +// CHECK-NEXT: "[[PREFIX]]/mod.h", +// CHECK-NEXT: "[[PREFIX]]/module.modulemap" +// CHECK-NEXT: ], +// CHECK-NEXT: "name": "mod" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "translation-units": [ +// CHECK-NEXT: { +// CHECK-NEXT: "clang-context-hash": "{{.*}}", +// CHECK-NEXT: "clang-module-deps": [ +// CHECK-NEXT: { +// CHECK-NEXT: "context-hash": "[[HASH_MOD_A]]", +// CHECK-NEXT: "module-name": "mod" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "command-line": [ +// CHECK-NEXT: "-fno-implicit-modules", +// CHECK-NEXT: "-fno-implicit-module-maps" +// CHECK-NEXT: ], +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/tu.c" +// CHECK-NEXT: ], +// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "clang-context-hash": "{{.*}}", +// CHECK-NEXT: "clang-module-deps": [ +// CHECK-NEXT: { +// CHECK-NEXT: "context-hash": "[[HASH_MOD_B]]", +// CHECK-NEXT: "module-name": "mod" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "command-line": [ +// CHECK-NEXT: "-fno-implicit-modules", +// CHECK-NEXT: "-fno-implicit-module-maps" +// CHECK-NEXT: ], +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/tu.c" +// CHECK-NEXT: ], +// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } -- 2.7.4