[clang] 00d7b7d - [clang] Fix visitation of ConceptSpecializationExpr in constrained-parameter
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 17 21:32:44 PDT 2020
Author: Nathan Ridge
Date: 2020-08-18T00:32:34-04:00
New Revision: 00d7b7d014f90aaaacaef6f9c778614b09356bf0
URL: https://github.com/llvm/llvm-project/commit/00d7b7d014f90aaaacaef6f9c778614b09356bf0
DIFF: https://github.com/llvm/llvm-project/commit/00d7b7d014f90aaaacaef6f9c778614b09356bf0.diff
LOG: [clang] Fix visitation of ConceptSpecializationExpr in constrained-parameter
Summary: RecursiveASTVisitor needs to traverse TypeConstraint::ImmediatelyDeclaredConstraint
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D84136
Added:
clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
Modified:
clang-tools-extra/clangd/unittests/FindTargetTests.cpp
clang/include/clang/AST/RecursiveASTVisitor.h
clang/unittests/Tooling/CMakeLists.txt
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 4c655c3338d2..2507932c5cda 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -442,6 +442,28 @@ TEST_F(TargetDeclTest, Concept) {
)cpp";
EXPECT_DECLS("ConceptSpecializationExpr",
{"template <typename T> concept Fooable = true;"});
+
+ // constrained-parameter
+ Code = R"cpp(
+ template <typename T>
+ concept Fooable = true;
+
+ template <[[Fooable]] T>
+ void bar(T t);
+ )cpp";
+ EXPECT_DECLS("ConceptSpecializationExpr",
+ {"template <typename T> concept Fooable = true;"});
+
+ // partial-concept-id
+ Code = R"cpp(
+ template <typename T, typename U>
+ concept Fooable = true;
+
+ template <[[Fooable]]<int> T>
+ void bar(T t);
+ )cpp";
+ EXPECT_DECLS("ConceptSpecializationExpr",
+ {"template <typename T, typename U> concept Fooable = true;"});
}
TEST_F(TargetDeclTest, FunctionTemplate) {
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 3dcfc9fee629..6f07b92f2532 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1777,8 +1777,17 @@ DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
// D is the "T" in something like "template<typename T> class vector;"
if (D->getTypeForDecl())
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
- if (const auto *TC = D->getTypeConstraint())
- TRY_TO(TraverseConceptReference(*TC));
+ if (const auto *TC = D->getTypeConstraint()) {
+ if (Expr *IDC = TC->getImmediatelyDeclaredConstraint()) {
+ TRY_TO(TraverseStmt(IDC));
+ } else {
+ // Avoid traversing the ConceptReference in the TypeCosntraint
+ // if we have an immediately-declared-constraint, otherwise
+ // we'll end up visiting the concept and the arguments in
+ // the TC twice.
+ TRY_TO(TraverseConceptReference(*TC));
+ }
+ }
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
})
diff --git a/clang/unittests/Tooling/CMakeLists.txt b/clang/unittests/Tooling/CMakeLists.txt
index f290c3d2bede..9de330ab73d4 100644
--- a/clang/unittests/Tooling/CMakeLists.txt
+++ b/clang/unittests/Tooling/CMakeLists.txt
@@ -22,6 +22,7 @@ add_clang_unittest(ToolingTests
RecursiveASTVisitorTests/Attr.cpp
RecursiveASTVisitorTests/Callbacks.cpp
RecursiveASTVisitorTests/Class.cpp
+ RecursiveASTVisitorTests/Concept.cpp
RecursiveASTVisitorTests/ConstructExpr.cpp
RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
RecursiveASTVisitorTests/CXXMemberCall.cpp
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
new file mode 100644
index 000000000000..f0f700204dd5
--- /dev/null
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
@@ -0,0 +1,45 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/Concept.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 "clang/AST/ExprConcepts.h"
+
+using namespace clang;
+
+namespace {
+
+struct ConceptVisitor : ExpectedLocationVisitor<ConceptVisitor> {
+ bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
+ ++ConceptSpecializationExprsVisited;
+ return true;
+ }
+ bool TraverseConceptReference(const ConceptReference &R) {
+ ++ConceptReferencesTraversed;
+ return true;
+ }
+
+ int ConceptSpecializationExprsVisited = 0;
+ int ConceptReferencesTraversed = 0;
+};
+
+TEST(RecursiveASTVisitor, ConstrainedParameter) {
+ ConceptVisitor Visitor;
+ EXPECT_TRUE(Visitor.runOver("template <typename T> concept Fooable = true;\n"
+ "template <Fooable T> void bar(T);",
+ ConceptVisitor::Lang_CXX2a));
+ // Check that we visit the "Fooable T" template parameter's TypeConstraint's
+ // ImmediatelyDeclaredConstraint, which is a ConceptSpecializationExpr.
+ EXPECT_EQ(1, Visitor.ConceptSpecializationExprsVisited);
+ // There are two ConceptReference objects in the AST: the base subobject
+ // of the ConceptSpecializationExpr, and the base subobject of the
+ // TypeConstraint itself. To avoid traversing the concept and arguments
+ // multiple times, we only traverse one.
+ EXPECT_EQ(1, Visitor.ConceptReferencesTraversed);
+}
+
+} // end anonymous namespace
More information about the cfe-commits
mailing list