https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/91454
>From e560fe2bf2d4bdc07a71682aa4d3a4bee8730b80 Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Wed, 8 May 2024 12:11:10 +0200 Subject: [PATCH 1/2] [AST] RecursiveASTVisitor: Don't traverse the alias deduction guides in default mode. --- clang/include/clang/AST/RecursiveASTVisitor.h | 28 ++++-- .../DeductionGuide.cpp | 89 +++++++++++++++++++ 2 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index f9b145b4e86a5..2517189c95300 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -736,13 +736,27 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { // As a syntax visitor, by default we want to ignore declarations for // implicit declarations (ones not typed explicitly by the user). - if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) { - // For an implicit template type parameter, its type constraints are not - // implicit and are not represented anywhere else. We still need to visit - // them. - if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(D)) - return TraverseTemplateTypeParamDeclConstraints(TTPD); - return true; + if (!getDerived().shouldVisitImplicitCode()) { + if (D->isImplicit()) { + // For an implicit template type parameter, its type constraints are not + // implicit and are not represented anywhere else. We still need to visit + // them. + if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(D)) + return TraverseTemplateTypeParamDeclConstraints(TTPD); + return true; + } + + // Deduction guides for alias templates are always synthesized, so they + // should not be traversed unless shouldVisitImplicitCode() returns true. + // + // It's important to note that checking the implicit bit is not efficient + // for the alias case. For deduction guides synthesized from explicit + // user-defined deduction guides, we must maintain the explicit bit to + // ensure correct overload resolution. + if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) + if (llvm::isa_and_present<TypeAliasTemplateDecl>( + FTD->getDeclName().getCXXDeductionGuideTemplate())) + return true; } switch (D->getKind()) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp new file mode 100644 index 0000000000000..abfdbaea4a615 --- /dev/null +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp @@ -0,0 +1,89 @@ +//===- unittest/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TestVisitor.h" +#include <string> + +using namespace clang; + +namespace { + +class DeductionGuideVisitor + : public ExpectedLocationVisitor<DeductionGuideVisitor> { +public: + DeductionGuideVisitor(bool ShouldVisitImplicitCode) + : ShouldVisitImplicitCode(ShouldVisitImplicitCode) {} + bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { + std::string Storage; + llvm::raw_string_ostream Stream(Storage); + D->print(Stream); + Match(Stream.str(),D->getLocation()); + return true; + } + + bool shouldVisitTemplateInstantiations() const { + return false; + } + + bool shouldVisitImplicitCode() const { + return ShouldVisitImplicitCode; + } + bool ShouldVisitImplicitCode; +}; + +TEST(RecursiveASTVisitor, DeductionGuideNonImplicitMode) { + DeductionGuideVisitor Visitor(/*ShouldVisitImplicitCode*/ false); + // Verify that the synthezied deduction guide for alias is not visited in + // RAV's implicit mode. + Visitor.ExpectMatch("Foo(T) -> Foo<int>", 11, 1); + Visitor.DisallowMatch("Bar(type-parameter-0-0) -> Foo<int>", 14, 1); + EXPECT_TRUE(Visitor.runOver( + R"cpp( +template <typename T> +concept False = true; + +template <typename T> +struct Foo { + Foo(T); +}; + +template<typename T> requires False<T> +Foo(T) -> Foo<int>; + +template <typename U> +using Bar = Foo<U>; +Bar s(1); + )cpp" + , DeductionGuideVisitor::Lang_CXX2a)); +} + +TEST(RecursiveASTVisitor, DeductionGuideImplicitMode) { + DeductionGuideVisitor Visitor(/*ShouldVisitImplicitCode*/ true); + Visitor.ExpectMatch("Foo(T) -> Foo<int>", 11, 1); + Visitor.ExpectMatch("Bar(type-parameter-0-0) -> Foo<int>", 14, 1); + EXPECT_TRUE(Visitor.runOver( + R"cpp( +template <typename T> +concept False = true; + +template <typename T> +struct Foo { + Foo(T); +}; + +template<typename T> requires False<T> +Foo(T) -> Foo<int>; + +template <typename U> +using Bar = Foo<U>; +Bar s(1); + )cpp" + , DeductionGuideVisitor::Lang_CXX2a)); +} + +} // end anonymous namespace >From f449f1f9902031d567f037afc97bccf053abdaaa Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Thu, 16 May 2024 10:18:30 +0200 Subject: [PATCH 2/2] clang-format --- .../DeductionGuide.cpp | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp index abfdbaea4a615..274f275ea66a9 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp @@ -22,17 +22,13 @@ class DeductionGuideVisitor std::string Storage; llvm::raw_string_ostream Stream(Storage); D->print(Stream); - Match(Stream.str(),D->getLocation()); + Match(Stream.str(), D->getLocation()); return true; } - bool shouldVisitTemplateInstantiations() const { - return false; - } + bool shouldVisitTemplateInstantiations() const { return false; } - bool shouldVisitImplicitCode() const { - return ShouldVisitImplicitCode; - } + bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } bool ShouldVisitImplicitCode; }; @@ -43,7 +39,7 @@ TEST(RecursiveASTVisitor, DeductionGuideNonImplicitMode) { Visitor.ExpectMatch("Foo(T) -> Foo<int>", 11, 1); Visitor.DisallowMatch("Bar(type-parameter-0-0) -> Foo<int>", 14, 1); EXPECT_TRUE(Visitor.runOver( - R"cpp( + R"cpp( template <typename T> concept False = true; @@ -58,8 +54,8 @@ Foo(T) -> Foo<int>; template <typename U> using Bar = Foo<U>; Bar s(1); - )cpp" - , DeductionGuideVisitor::Lang_CXX2a)); + )cpp", + DeductionGuideVisitor::Lang_CXX2a)); } TEST(RecursiveASTVisitor, DeductionGuideImplicitMode) { @@ -67,7 +63,7 @@ TEST(RecursiveASTVisitor, DeductionGuideImplicitMode) { Visitor.ExpectMatch("Foo(T) -> Foo<int>", 11, 1); Visitor.ExpectMatch("Bar(type-parameter-0-0) -> Foo<int>", 14, 1); EXPECT_TRUE(Visitor.runOver( - R"cpp( + R"cpp( template <typename T> concept False = true; @@ -82,8 +78,8 @@ Foo(T) -> Foo<int>; template <typename U> using Bar = Foo<U>; Bar s(1); - )cpp" - , DeductionGuideVisitor::Lang_CXX2a)); + )cpp", + DeductionGuideVisitor::Lang_CXX2a)); } } // end anonymous namespace _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits