[clang] [AST] RecursiveASTVisitor: Don't traverse the alias deduction guides in the default mode. (PR #91454)
Haojian Wu via cfe-commits
cfe-commits at lists.llvm.org
Thu May 16 01:18:49 PDT 2024
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.wu at 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.wu at 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
More information about the cfe-commits
mailing list