hokein created this revision. hokein added a reviewer: kadircet. Herald added a project: All. hokein requested review of this revision. Herald added a project: clang-tools-extra.
By special-casing them at the moment. The tooling stdlib lib doesn't support these symbols (most important one is std::move). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D143906 Files: clang-tools-extra/include-cleaner/lib/FindHeaders.cpp clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
Index: clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp =================================================================== --- clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp +++ clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp @@ -278,25 +278,31 @@ class HeadersForSymbolTest : public FindHeadersTest { protected: - llvm::SmallVector<Header> headersForFoo() { + llvm::SmallVector<Header> headersFor(llvm::StringRef Name) { struct Visitor : public RecursiveASTVisitor<Visitor> { const NamedDecl *Out = nullptr; + llvm::StringRef Name; + Visitor(llvm::StringRef Name) : Name(Name) {} bool VisitNamedDecl(const NamedDecl *ND) { - if (ND->getName() == "foo") { + if (auto *TD = ND->getDescribedTemplate()) + ND = TD; + + if (ND->getName() == Name) { EXPECT_TRUE(Out == nullptr || Out == ND->getCanonicalDecl()) - << "Found multiple matches for foo."; + << "Found multiple matches for " << Name << "."; Out = cast<NamedDecl>(ND->getCanonicalDecl()); } return true; } }; - Visitor V; + Visitor V(Name); V.TraverseDecl(AST->context().getTranslationUnitDecl()); if (!V.Out) - ADD_FAILURE() << "Couldn't find any decls named foo."; + ADD_FAILURE() << "Couldn't find any decls named " << Name << "."; assert(V.Out); return headersForSymbol(*V.Out, AST->sourceManager(), &PI); } + llvm::SmallVector<Header> headersForFoo() { return headersFor("foo"); } }; TEST_F(HeadersForSymbolTest, Deduplicates) { @@ -430,5 +436,54 @@ EXPECT_THAT(headersForFoo(), ElementsAre(Header(StringRef("\"public.h\"")), physicalHeader("foo.h"))); } + +TEST_F(HeadersForSymbolTest, AmbiguousStdSymbols) { + struct { + llvm::StringRef Code; + llvm::StringRef Name; + + llvm::StringRef ExpectedHeader; + } TestCases[] = { + { + R"cpp( + namespace std { + template <typename InputIt, typename OutputIt> + constexpr OutputIt move(InputIt first, InputIt last, OutputIt dest); + })cpp", + "move", + "<algorithm>", + }, + { + R"cpp( + namespace std { + template<typename T> constexpr T move(T&& t) noexcept; + })cpp", + "move", + "<utility>", + }, + { + R"cpp( + namespace std { + template<class ForwardIt, class T> + ForwardIt remove(ForwardIt first, ForwardIt last, const T& value); + })cpp", + "remove", + "<algorithm>", + }, + { + "namespace std { int remove(const char*); }", + "remove", + "<cstdio>", + }, + }; + + for (const auto &T : TestCases) { + Inputs.Code = T.Code; + buildAST(); + EXPECT_THAT(headersFor(T.Name), + UnorderedElementsAre(Header(T.ExpectedHeader))); + } +} + } // namespace } // namespace clang::include_cleaner Index: clang-tools-extra/include-cleaner/lib/FindHeaders.cpp =================================================================== --- clang-tools-extra/include-cleaner/lib/FindHeaders.cpp +++ clang-tools-extra/include-cleaner/lib/FindHeaders.cpp @@ -82,6 +82,36 @@ llvm_unreachable("unhandled Symbol kind!"); } +// Special-case the ambiguous standard library symbols (e.g. std::move) which +// are not supported by the tooling stdlib lib. +llvm::SmallVector<Header> specialStandardSymbols(const Symbol &S) { + if (S.kind() != Symbol::Declaration || !S.declaration().isInStdNamespace()) + return {}; + + const auto *FD = S.declaration().getAsFunction(); + if (!FD) + return {}; + + llvm::StringRef FName = FD->getName(); + if (FName == "move") { + if (FD->getNumParams() == 1) + // move(T&& t) + return {Header("<utility>")}; + if (FD->getNumParams() == 3) + // move(InputIt first, InputIt last, OutputIt dest); + return {Header("<algorithm>")}; + } + if (FName == "remove") { + if (FD->getNumParams() == 1) + // remove(const char*); + return {Header("<cstdio>")}; + if (FD->getNumParams() == 3) + // remove(ForwardIt first, ForwardIt last, const T& value); + return {Header("<algorithm>")}; + } + return {}; +} + } // namespace llvm::SmallVector<Hinted<Header>> findHeaders(const SymbolLocation &Loc, @@ -141,6 +171,9 @@ llvm::SmallVector<Header> headersForSymbol(const Symbol &S, const SourceManager &SM, const PragmaIncludes *PI) { + if (auto Headers = specialStandardSymbols(S); !Headers.empty()) + return Headers; + // Get headers for all the locations providing Symbol. Same header can be // reached through different traversals, deduplicate those into a single // Header by merging their hints.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits