Browse Source

Use FileEntryRef for PPCallbacks::HasInclude

This fixes the issue where a filename dependendency was missing if the file that
was referenced with __has_include() was accessed through a symlink in an earlier run,
if the file manager was reused between runs.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@370081 91177308-0d34-0410-b5e6-96231b3b80d8
Alex Lorenz 6 years ago
parent
commit
32bae3c742

+ 2 - 2
include/clang/Lex/PPCallbacks.h

@@ -307,7 +307,7 @@ public:
   /// Hook called when a '__has_include' or '__has_include_next' directive is
   /// Hook called when a '__has_include' or '__has_include_next' directive is
   /// read.
   /// read.
   virtual void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
   virtual void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
-                          const FileEntry *File,
+                          Optional<FileEntryRef> File,
                           SrcMgr::CharacteristicKind FileType) {}
                           SrcMgr::CharacteristicKind FileType) {}
 
 
   /// Hook called when a source range is skipped.
   /// Hook called when a source range is skipped.
@@ -489,7 +489,7 @@ public:
   }
   }
 
 
   void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
   void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
-                  const FileEntry *File,
+                  Optional<FileEntryRef> File,
                   SrcMgr::CharacteristicKind FileType) override {
                   SrcMgr::CharacteristicKind FileType) override {
     First->HasInclude(Loc, FileName, IsAngled, File, FileType);
     First->HasInclude(Loc, FileName, IsAngled, File, FileType);
     Second->HasInclude(Loc, FileName, IsAngled, File, FileType);
     Second->HasInclude(Loc, FileName, IsAngled, File, FileType);

+ 1 - 1
lib/Frontend/DependencyFile.cpp

@@ -83,7 +83,7 @@ struct DepCollectorPPCallbacks : public PPCallbacks {
   }
   }
 
 
   void HasInclude(SourceLocation Loc, StringRef SpelledFilename, bool IsAngled,
   void HasInclude(SourceLocation Loc, StringRef SpelledFilename, bool IsAngled,
-                  const FileEntry *File,
+                  Optional<FileEntryRef> File,
                   SrcMgr::CharacteristicKind FileType) override {
                   SrcMgr::CharacteristicKind FileType) override {
     if (!File)
     if (!File)
       return;
       return;

+ 1 - 2
lib/Lex/PPMacroExpansion.cpp

@@ -1219,8 +1219,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
     if (File)
     if (File)
       FileType =
       FileType =
           PP.getHeaderSearchInfo().getFileDirFlavor(&File->getFileEntry());
           PP.getHeaderSearchInfo().getFileDirFlavor(&File->getFileEntry());
-    Callbacks->HasInclude(FilenameLoc, Filename, isAngled,
-                          File ? &File->getFileEntry() : nullptr, FileType);
+    Callbacks->HasInclude(FilenameLoc, Filename, isAngled, File, FileType);
   }
   }
 
 
   // Get the result value.  A result of true means the file exists.
   // Get the result value.  A result of true means the file exists.

+ 35 - 0
unittests/Tooling/DependencyScannerTest.cpp

@@ -161,5 +161,40 @@ TEST(DependencyScanner, ScanDepsReuseFilemanagerSkippedFile) {
   EXPECT_EQ(convert_to_slash(Deps[5]), "/root/header.h");
   EXPECT_EQ(convert_to_slash(Deps[5]), "/root/header.h");
 }
 }
 
 
+TEST(DependencyScanner, ScanDepsReuseFilemanagerHasInclude) {
+  std::vector<std::string> Compilation = {"-c", "-E", "-MT", "test.cpp.o"};
+  StringRef CWD = "/root";
+  FixedCompilationDatabase CDB(CWD, Compilation);
+
+  auto VFS = new llvm::vfs::InMemoryFileSystem();
+  VFS->setCurrentWorkingDirectory(CWD);
+  auto Sept = llvm::sys::path::get_separator();
+  std::string HeaderPath = llvm::formatv("{0}root{0}header.h", Sept);
+  std::string SymlinkPath = llvm::formatv("{0}root{0}symlink.h", Sept);
+  std::string TestPath = llvm::formatv("{0}root{0}test.cpp", Sept);
+
+  VFS->addFile(HeaderPath, 0, llvm::MemoryBuffer::getMemBuffer("\n"));
+  VFS->addHardLink(SymlinkPath, HeaderPath);
+  VFS->addFile(
+      TestPath, 0,
+      llvm::MemoryBuffer::getMemBuffer("#if __has_include(\"header.h\") && "
+                                       "__has_include(\"symlink.h\")\n#endif"));
+
+  ClangTool Tool(CDB, {"test.cpp", "test.cpp"},
+                 std::make_shared<PCHContainerOperations>(), VFS);
+  Tool.clearArgumentsAdjusters();
+  std::vector<std::string> Deps;
+  TestDependencyScanningAction Action(Deps);
+  Tool.run(&Action);
+  using llvm::sys::path::convert_to_slash;
+  ASSERT_EQ(Deps.size(), 6u);
+  EXPECT_EQ(convert_to_slash(Deps[0]), "/root/test.cpp");
+  EXPECT_EQ(convert_to_slash(Deps[1]), "/root/header.h");
+  EXPECT_EQ(convert_to_slash(Deps[2]), "/root/symlink.h");
+  EXPECT_EQ(convert_to_slash(Deps[3]), "/root/test.cpp");
+  EXPECT_EQ(convert_to_slash(Deps[4]), "/root/header.h");
+  EXPECT_EQ(convert_to_slash(Deps[5]), "/root/symlink.h");
+}
+
 } // end namespace tooling
 } // end namespace tooling
 } // end namespace clang
 } // end namespace clang