kadircet created this revision. kadircet added a reviewer: sammccall. Herald added subscribers: cfe-commits, usaxena95, arphaman, jkorous, MaskRay, ilya-biryukov. Herald added a project: clang.
This will enable extraction of correct line locations in preamble patch for includes. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D78740 Files: clang-tools-extra/clangd/Headers.cpp clang-tools-extra/clangd/unittests/HeadersTests.cpp Index: clang-tools-extra/clangd/unittests/HeadersTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/HeadersTests.cpp +++ clang-tools-extra/clangd/unittests/HeadersTests.cpp @@ -16,6 +16,7 @@ #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/PreprocessorOptions.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -302,6 +303,29 @@ llvm::None); } +TEST_F(HeadersTest, PresumedLocations) { + FS.Files[MainFile] = R"cpp( +#include "a.h" +// #include "b.h" +// nothing on this line +// #include "c.h" +)cpp"; + std::string HeaderFile = testPath("a.h"); + std::string HeaderContents = llvm::formatv("#line 0 \"{0}\"", MainFile); + HeaderContents += R"cpp( +#line 3 +#include <b.h> +#line 5 +#include <c.h> +#include <d.h>)cpp"; + FS.Files[HeaderFile] = HeaderContents; + + EXPECT_THAT(collectIncludes().MainFileIncludes, + UnorderedElementsAre(AllOf(IncludeLine(1), Written("\"a.h\"")), + AllOf(IncludeLine(2), Written("<b.h>")), + AllOf(IncludeLine(4), Written("<c.h>")), + AllOf(IncludeLine(5), Written("<d.h>")))); +} } // namespace } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/Headers.cpp =================================================================== --- clang-tools-extra/clangd/Headers.cpp +++ clang-tools-extra/clangd/Headers.cpp @@ -35,6 +35,27 @@ llvm::StringRef /*RelativePath*/, const Module * /*Imported*/, SrcMgr::CharacteristicKind FileKind) override { + if (!isInsideMainFile(HashLoc, SM)) { + auto PreLoc = SM.getPresumedLoc(HashLoc); + if (auto FE = SM.getFileManager().getFile(PreLoc.getFilename())) { + if (SM.getFileEntryForID(SM.getMainFileID()) == *FE) { + HashLoc = SM.translateLineCol(SM.getMainFileID(), PreLoc.getLine(), + PreLoc.getColumn()); + PreLoc = SM.getPresumedLoc(FilenameRange.getBegin()); + auto FileNameBegin = SM.translateLineCol( + SM.getMainFileID(), PreLoc.getLine(), PreLoc.getColumn()); + PreLoc = SM.getPresumedLoc(FilenameRange.getEnd()); + // translateLineCol doesn't allow offsetting into a line past its end. + // But FilenameRange can be a charrange and point past the line, as + // the endpoint is exclusive. + auto FileNameEnd = + SM.translateLineCol(SM.getMainFileID(), PreLoc.getLine(), 1) + .getLocWithOffset(PreLoc.getColumn() - 1); + FilenameRange = CharSourceRange({FileNameBegin, FileNameEnd}, + FilenameRange.isTokenRange()); + } + } + } if (isInsideMainFile(HashLoc, SM)) { Out->MainFileIncludes.emplace_back(); auto &Inc = Out->MainFileIncludes.back();
Index: clang-tools-extra/clangd/unittests/HeadersTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/HeadersTests.cpp +++ clang-tools-extra/clangd/unittests/HeadersTests.cpp @@ -16,6 +16,7 @@ #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/PreprocessorOptions.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -302,6 +303,29 @@ llvm::None); } +TEST_F(HeadersTest, PresumedLocations) { + FS.Files[MainFile] = R"cpp( +#include "a.h" +// #include "b.h" +// nothing on this line +// #include "c.h" +)cpp"; + std::string HeaderFile = testPath("a.h"); + std::string HeaderContents = llvm::formatv("#line 0 \"{0}\"", MainFile); + HeaderContents += R"cpp( +#line 3 +#include <b.h> +#line 5 +#include <c.h> +#include <d.h>)cpp"; + FS.Files[HeaderFile] = HeaderContents; + + EXPECT_THAT(collectIncludes().MainFileIncludes, + UnorderedElementsAre(AllOf(IncludeLine(1), Written("\"a.h\"")), + AllOf(IncludeLine(2), Written("<b.h>")), + AllOf(IncludeLine(4), Written("<c.h>")), + AllOf(IncludeLine(5), Written("<d.h>")))); +} } // namespace } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/Headers.cpp =================================================================== --- clang-tools-extra/clangd/Headers.cpp +++ clang-tools-extra/clangd/Headers.cpp @@ -35,6 +35,27 @@ llvm::StringRef /*RelativePath*/, const Module * /*Imported*/, SrcMgr::CharacteristicKind FileKind) override { + if (!isInsideMainFile(HashLoc, SM)) { + auto PreLoc = SM.getPresumedLoc(HashLoc); + if (auto FE = SM.getFileManager().getFile(PreLoc.getFilename())) { + if (SM.getFileEntryForID(SM.getMainFileID()) == *FE) { + HashLoc = SM.translateLineCol(SM.getMainFileID(), PreLoc.getLine(), + PreLoc.getColumn()); + PreLoc = SM.getPresumedLoc(FilenameRange.getBegin()); + auto FileNameBegin = SM.translateLineCol( + SM.getMainFileID(), PreLoc.getLine(), PreLoc.getColumn()); + PreLoc = SM.getPresumedLoc(FilenameRange.getEnd()); + // translateLineCol doesn't allow offsetting into a line past its end. + // But FilenameRange can be a charrange and point past the line, as + // the endpoint is exclusive. + auto FileNameEnd = + SM.translateLineCol(SM.getMainFileID(), PreLoc.getLine(), 1) + .getLocWithOffset(PreLoc.getColumn() - 1); + FilenameRange = CharSourceRange({FileNameBegin, FileNameEnd}, + FilenameRange.isTokenRange()); + } + } + } if (isInsideMainFile(HashLoc, SM)) { Out->MainFileIncludes.emplace_back(); auto &Inc = Out->MainFileIncludes.back();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits