[clang][deps] Fix module context hash for constant strings
authorBen Langmuir <blangmuir@apple.com>
Wed, 1 Feb 2023 01:56:48 +0000 (17:56 -0800)
committerBen Langmuir <blangmuir@apple.com>
Fri, 3 Feb 2023 23:10:19 +0000 (15:10 -0800)
We were not hashing constant strings in the command-line, only ones that
required allocations. This was causing us to get the same hash across
different flag options.

rdar://101053855

Differential Revision: https://reviews.llvm.org/D143027

clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_b2.json.template [new file with mode: 0644]
clang/test/ClangScanDeps/modules-context-hash.c

index 1130c2b..4ff9e60 100644 (file)
@@ -267,13 +267,12 @@ static std::string getModuleContextHash(const ModuleDeps &MD,
   HashBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR);
 
   // Hash the BuildInvocation without any input files.
-  SmallVector<const char *, 32> DummyArgs;
-  CI.generateCC1CommandLine(DummyArgs, [&](const Twine &Arg) {
-    Scratch.clear();
-    StringRef Str = Arg.toStringRef(Scratch);
-    HashBuilder.add(Str);
-    return "<unused>";
-  });
+  SmallVector<const char *, 32> Args;
+  llvm::BumpPtrAllocator Alloc;
+  llvm::StringSaver Saver(Alloc);
+  CI.generateCC1CommandLine(
+      Args, [&](const Twine &Arg) { return Saver.save(Arg).data(); });
+  HashBuilder.addRange(Args);
 
   // Hash the module dependencies. These paths may differ even if the invocation
   // is identical if they depend on the contents of the files in the TU -- for
diff --git a/clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_b2.json.template b/clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_b2.json.template
new file mode 100644 (file)
index 0000000..adb7b42
--- /dev/null
@@ -0,0 +1,7 @@
+[
+  {
+    "directory": "DIR",
+    "command": "clang -c DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -IDIR/b -o DIR/tu_b.o -fapplication-extension",
+    "file": "DIR/tu.c"
+  }
+]
index 97a8653..3108c92 100644 (file)
@@ -7,15 +7,18 @@
 
 // RUN: sed "s|DIR|%/t|g" %S/Inputs/modules-context-hash/cdb_a.json.template > %t/cdb_a.json
 // RUN: sed "s|DIR|%/t|g" %S/Inputs/modules-context-hash/cdb_b.json.template > %t/cdb_b.json
+// RUN: sed "s|DIR|%/t|g" %S/Inputs/modules-context-hash/cdb_b2.json.template > %t/cdb_b2.json
 
-// We run two separate scans. The context hash for "a" and "b" can differ between
+// We run separate scans. The context hash for "a" and "b" can differ between
 // systems. If we'd scan both Clang invocations in a single run, the order of JSON
 // entities would be non-deterministic. To prevent this, run the scans separately
 // and verify that the context hashes differ with a single FileCheck invocation.
 //
-// RUN: clang-scan-deps -compilation-database %t/cdb_a.json -format experimental-full -j 1 >  %t/result.json
-// RUN: clang-scan-deps -compilation-database %t/cdb_b.json -format experimental-full -j 1 >> %t/result.json
-// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t -check-prefix=CHECK
+// RUN: clang-scan-deps -compilation-database %t/cdb_a.json -format experimental-full -j 1 >  %t/result_a.json
+// RUN: clang-scan-deps -compilation-database %t/cdb_b.json -format experimental-full -j 1 > %t/result_b.json
+// RUN: clang-scan-deps -compilation-database %t/cdb_b2.json -format experimental-full -j 1 > %t/result_b2.json
+// RUN: cat %t/result_a.json %t/result_b.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t -check-prefix=CHECK
+// RUN: cat %t/result_b.json %t/result_b2.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t -check-prefix=FLAG_ONLY
 
 // CHECK:      {
 // CHECK-NEXT:   "modules": [
 // CHECK-NEXT:       ],
 // CHECK-NEXT:       "input-file": "[[PREFIX]]/tu.c"
 // CHECK-NEXT:     }
+
+// B and B2 only differ by -fapplication-extension
+
+// FLAG_ONLY:       "modules": [
+// FLAG_ONLY-NEXT:     {
+// FLAG_ONLY:            "context-hash": "[[HASH_MOD_B1:.*]]"
+// FLAG_ONLY-NOT:        "-fapplication-extension"
+
+// FLAG_ONLY:       "modules": [
+// FLAG_ONLY-NEXT:     {
+// FLAG_ONLY-NOT:        "context-hash": "[[HASH_MOD_B1]]"
+// FLAG_ONLY:            "-fapplication-extension"
+// FLAG_ONLY:       "translation-units": [
+// FLAG_ONLY-NOT:        "context-hash": "[[HASH_MOD_B1]]"