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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits