]> granicus.if.org Git - clang/commitdiff
[Tooling] add a Heuristic field indicating that a CompileCommand was guessed.
authorSam McCall <sam.mccall@gmail.com>
Fri, 5 Apr 2019 15:22:20 +0000 (15:22 +0000)
committerSam McCall <sam.mccall@gmail.com>
Fri, 5 Apr 2019 15:22:20 +0000 (15:22 +0000)
Summary:
Use cases:
 - a tool that dumps the heuristic used for each header in a project can
   be used to evaluate changes to the heuristic
 - we want to expose this information to users in clangd as it affects
   accuracy/reliability of editor features
 - express interpolation tests more directly

Reviewers: ilya-biryukov, klimek

Subscribers: ioeric, kadircet, cfe-commits

Tags: #clang

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@357770 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Tooling/CompilationDatabase.h
lib/Tooling/InterpolatingCompilationDatabase.cpp
unittests/Tooling/CompilationDatabaseTest.cpp

index 984e8666c18fb476cbcf5f9b5ca2c094777b42e7..01f6e679a05965890d13af98c3e080b2efe47c34 100644 (file)
@@ -59,9 +59,15 @@ struct CompileCommand {
   /// The output file associated with the command.
   std::string Output;
 
+  /// If this compile command was guessed rather than read from an authoritative
+  /// source, a short human-readable explanation.
+  /// e.g. "inferred from foo/bar.h".
+  std::string Heuristic;
+
   friend bool operator==(const CompileCommand &LHS, const CompileCommand &RHS) {
     return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
-           LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output;
+           LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output &&
+           LHS.Heuristic == RHS.Heuristic;
   }
 
   friend bool operator!=(const CompileCommand &LHS, const CompileCommand &RHS) {
index 82ae6b62617b5c02854e5da56e9a548c98d3d5f3..5124340892f33c77df61dc5dee69a817562cc31f 100644 (file)
@@ -226,6 +226,7 @@ struct TransferableCommand {
           LangStandard::getLangStandardForKind(Std).getName()).str());
     }
     Result.CommandLine.push_back(Filename);
+    Result.Heuristic = "inferred from " + Cmd.Filename;
     return Result;
   }
 
index 83fceba802fc326c789feed877565f3e9c442043..4e27df71d87e961930838c42873f2e6da987dc58 100644 (file)
@@ -673,6 +673,27 @@ protected:
     return llvm::join(Results[0].CommandLine, " ");
   }
 
+  // Parse the file whose command was used out of the Heuristic string.
+  std::string getProxy(llvm::StringRef F) {
+    auto Results =
+        inferMissingCompileCommands(llvm::make_unique<MemCDB>(Entries))
+            ->getCompileCommands(path(F));
+    if (Results.empty())
+      return "none";
+    StringRef Proxy = Results.front().Heuristic;
+    if (!Proxy.consume_front("inferred from "))
+      return "";
+    // We have a proxy file, convert back to a unix relative path.
+    // This is a bit messy, but we do need to test these strings somehow...
+    llvm::SmallString<32> TempDir;
+    llvm::sys::path::system_temp_directory(false, TempDir);
+    Proxy.consume_front(TempDir);
+    Proxy.consume_front(llvm::sys::path::get_separator());
+    llvm::SmallString<32> Result = Proxy;
+    llvm::sys::path::native(Result, llvm::sys::path::Style::posix);
+    return Result.str();
+  }
+
   MemCDB::EntryMap Entries;
 };
 
@@ -682,18 +703,16 @@ TEST_F(InterpolateTest, Nearby) {
   add("an/other/foo.cpp");
 
   // great: dir and name both match (prefix or full, case insensitive)
-  EXPECT_EQ(getCommand("dir/f.cpp"), "clang -D dir/foo.cpp");
-  EXPECT_EQ(getCommand("dir/FOO.cpp"), "clang -D dir/foo.cpp");
+  EXPECT_EQ(getProxy("dir/f.cpp"), "dir/foo.cpp");
+  EXPECT_EQ(getProxy("dir/FOO.cpp"), "dir/foo.cpp");
   // no name match. prefer matching dir, break ties by alpha
-  EXPECT_EQ(getCommand("dir/a.cpp"), "clang -D dir/bar.cpp");
+  EXPECT_EQ(getProxy("dir/a.cpp"), "dir/bar.cpp");
   // an exact name match beats one segment of directory match
-  EXPECT_EQ(getCommand("some/other/bar.h"),
-            "clang -D dir/bar.cpp -x c++-header");
+  EXPECT_EQ(getProxy("some/other/bar.h"), "dir/bar.cpp");
   // two segments of directory match beat a prefix name match
-  EXPECT_EQ(getCommand("an/other/b.cpp"), "clang -D an/other/foo.cpp");
+  EXPECT_EQ(getProxy("an/other/b.cpp"), "an/other/foo.cpp");
   // if nothing matches at all, we still get the closest alpha match
-  EXPECT_EQ(getCommand("below/some/obscure/path.cpp"),
-            "clang -D an/other/foo.cpp");
+  EXPECT_EQ(getProxy("below/some/obscure/path.cpp"), "an/other/foo.cpp");
 }
 
 TEST_F(InterpolateTest, Language) {
@@ -727,7 +746,7 @@ TEST_F(InterpolateTest, Case) {
   add("FOO/BAR/BAZ/SHOUT.cc");
   add("foo/bar/baz/quiet.cc");
   // Case mismatches are completely ignored, so we choose the name match.
-  EXPECT_EQ(getCommand("foo/bar/baz/shout.C"), "clang -D FOO/BAR/BAZ/SHOUT.cc");
+  EXPECT_EQ(getProxy("foo/bar/baz/shout.C"), "FOO/BAR/BAZ/SHOUT.cc");
 }
 
 TEST_F(InterpolateTest, Aliasing) {