diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index e88e600ba2b974..b523ad5ef9ff23 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -20,6 +20,7 @@ #include "clang/Lex/ModuleMap.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" @@ -314,6 +315,9 @@ class HeaderSearch { /// whether they were valid or not. llvm::DenseMap LoadedModuleMaps; + // A map of discovered headers with their associated include file name. + llvm::DenseMap> IncludeNames; + /// Uniqued set of framework names, which is used to track which /// headers were included as framework headers. llvm::StringSet FrameworkNames; @@ -823,6 +827,13 @@ class HeaderSearch { /// Retrieve a uniqued framework name. StringRef getUniqueFrameworkName(StringRef Framework); + /// Retrieve the include name for the header. + /// + /// \param File The entry for a given header. + /// \returns The name of how the file was included when the header's location + /// was resolved. + StringRef getIncludeNameForHeader(const FileEntry *File) const; + /// Suggest a path by which the specified file could be found, for use in /// diagnostics to suggest a #include. Returned path will only contain forward /// slashes as separators. MainFile is the absolute path of the file that we diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 14b9a1d7f68be1..5fd853541b6a21 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -1030,8 +1030,11 @@ Optional HeaderSearch::LookupFile( CurDir = It; + const auto FE = &File->getFileEntry(); + IncludeNames[FE] = Filename; + // This file is a system header or C++ unfriendly if the dir is. - HeaderFileInfo &HFI = getFileInfo(&File->getFileEntry()); + HeaderFileInfo &HFI = getFileInfo(FE); HFI.DirInfo = CurDir->getDirCharacteristic(); // If the directory characteristic is User but this framework was @@ -1460,6 +1463,13 @@ StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { return FrameworkNames.insert(Framework).first->first(); } +StringRef HeaderSearch::getIncludeNameForHeader(const FileEntry *File) const { + auto It = IncludeNames.find(File); + if (It == IncludeNames.end()) + return {}; + return It->second; +} + bool HeaderSearch::hasModuleMap(StringRef FileName, const DirectoryEntry *Root, bool IsSystem) { diff --git a/clang/unittests/Lex/HeaderSearchTest.cpp b/clang/unittests/Lex/HeaderSearchTest.cpp index fbb5cb30754a79..87d1c01650987b 100644 --- a/clang/unittests/Lex/HeaderSearchTest.cpp +++ b/clang/unittests/Lex/HeaderSearchTest.cpp @@ -207,6 +207,7 @@ TEST_F(HeaderSearchTest, HeaderFrameworkLookup) { EXPECT_TRUE(FI); EXPECT_TRUE(FI->IsValid); EXPECT_EQ(FI->Framework.str(), "Foo"); + EXPECT_EQ(Search.getIncludeNameForHeader(FE), "Foo/Foo.h"); } // Helper struct with null terminator character to make MemoryBuffer happy. @@ -275,6 +276,7 @@ TEST_F(HeaderSearchTest, HeaderMapFrameworkLookup) { EXPECT_TRUE(FI); EXPECT_TRUE(FI->IsValid); EXPECT_EQ(FI->Framework.str(), "Foo"); + EXPECT_EQ(Search.getIncludeNameForHeader(FE), "Foo/Foo.h"); } } // namespace