sammccall created this revision. sammccall added reviewers: kadircet, massberg. Herald added a project: All. sammccall requested review of this revision. Herald added projects: clang, clang-tools-extra. Herald added a subscriber: cfe-commits.
Most cases handled by adding VisitConceptReference to RecursiveASTVisitor though it is incomplete. Fixes https://github.com/llvm/llvm-project/issues/60702 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D155425 Files: clang-tools-extra/include-cleaner/lib/WalkAST.cpp clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp clang/include/clang/AST/RecursiveASTVisitor.h Index: clang/include/clang/AST/RecursiveASTVisitor.h =================================================================== --- clang/include/clang/AST/RecursiveASTVisitor.h +++ clang/include/clang/AST/RecursiveASTVisitor.h @@ -457,6 +457,9 @@ DEF_TRAVERSE_TMPL_INST(Function) #undef DEF_TRAVERSE_TMPL_INST + // FIXME: we should also provide VisitTypeConstraint. + // FIXME: VisitConceptReference is not yet called in constrained AutoTypeLoc. + bool VisitConceptReference(const ConceptReference *C) { return true; } bool TraverseTypeConstraint(const TypeConstraint *C); bool TraverseConceptRequirement(concepts::Requirement *R); @@ -543,6 +546,7 @@ template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseConceptReferenceHelper( const ConceptReference &C) { + TRY_TO(VisitConceptReference(&C)); TRY_TO(TraverseNestedNameSpecifierLoc(C.getNestedNameSpecifierLoc())); TRY_TO(TraverseDeclarationNameInfo(C.getConceptNameInfo())); if (C.hasExplicitTemplateArgs()) @@ -1356,6 +1360,8 @@ DEF_TRAVERSE_TYPELOC(AutoType, { TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); if (TL.isConstrained()) { + // FIXME: should VisitConceptReference instead. + // We don't store that node in the AST today. TRY_TO(TraverseNestedNameSpecifierLoc(TL.getNestedNameSpecifierLoc())); TRY_TO(TraverseDeclarationNameInfo(TL.getConceptNameInfo())); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) Index: clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp =================================================================== --- clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp +++ clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp @@ -50,7 +50,7 @@ Inputs.ExtraFiles["target.h"] = Target.code().str(); Inputs.ExtraArgs.push_back("-include"); Inputs.ExtraArgs.push_back("target.h"); - Inputs.ExtraArgs.push_back("-std=c++17"); + Inputs.ExtraArgs.push_back("-std=c++20"); TestAST AST(Inputs); const auto &SM = AST.sourceManager(); @@ -510,5 +510,17 @@ testWalk("enum class E : int {};", "enum class ^E : int ;"); } +TEST(WalkAST, Concepts) { + testWalk("template <class> concept $explicit^C = true;", "^C auto x = 1;"); + testWalk("template <class> concept $explicit^C = true;", "bool x = ^C<int>;"); + testWalk("template <class> concept $explicit^C = true;", "void X(^C auto);"); + testWalk("template <class> concept $explicit^C = true;", + "template <^C T> int X;"); + testWalk("template <class> concept $explicit^C = true;", + "template <^C auto T> int X;"); + testWalk("template <class> concept $explicit^C = true;", + "template <class T> requires(^C<T>) int X;"); +} + } // namespace } // namespace clang::include_cleaner Index: clang-tools-extra/include-cleaner/lib/WalkAST.cpp =================================================================== --- clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -249,6 +249,11 @@ return true; } + bool VisitConceptReference(const ConceptReference *CR) { + report(CR->getConceptNameLoc(), CR->getNamedConcept()); + return true; + } + // TypeLoc visitors. void reportType(SourceLocation RefLoc, NamedDecl *ND) { // Reporting explicit references to types nested inside classes can cause @@ -279,6 +284,13 @@ return true; } + bool VisitAutoTypeLoc(AutoTypeLoc ATL) { + // FIXME: RAV should call VisitConceptReference here, but doesn't! + if (ATL.isConstrained()) + report(ATL.getConceptNameLoc(), ATL.getNamedConcept()); + return true; + } + bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { reportType(TL.getTemplateNameLoc(), getMostRelevantTemplatePattern(TL.getTypePtr()));
Index: clang/include/clang/AST/RecursiveASTVisitor.h =================================================================== --- clang/include/clang/AST/RecursiveASTVisitor.h +++ clang/include/clang/AST/RecursiveASTVisitor.h @@ -457,6 +457,9 @@ DEF_TRAVERSE_TMPL_INST(Function) #undef DEF_TRAVERSE_TMPL_INST + // FIXME: we should also provide VisitTypeConstraint. + // FIXME: VisitConceptReference is not yet called in constrained AutoTypeLoc. + bool VisitConceptReference(const ConceptReference *C) { return true; } bool TraverseTypeConstraint(const TypeConstraint *C); bool TraverseConceptRequirement(concepts::Requirement *R); @@ -543,6 +546,7 @@ template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseConceptReferenceHelper( const ConceptReference &C) { + TRY_TO(VisitConceptReference(&C)); TRY_TO(TraverseNestedNameSpecifierLoc(C.getNestedNameSpecifierLoc())); TRY_TO(TraverseDeclarationNameInfo(C.getConceptNameInfo())); if (C.hasExplicitTemplateArgs()) @@ -1356,6 +1360,8 @@ DEF_TRAVERSE_TYPELOC(AutoType, { TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); if (TL.isConstrained()) { + // FIXME: should VisitConceptReference instead. + // We don't store that node in the AST today. TRY_TO(TraverseNestedNameSpecifierLoc(TL.getNestedNameSpecifierLoc())); TRY_TO(TraverseDeclarationNameInfo(TL.getConceptNameInfo())); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) Index: clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp =================================================================== --- clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp +++ clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp @@ -50,7 +50,7 @@ Inputs.ExtraFiles["target.h"] = Target.code().str(); Inputs.ExtraArgs.push_back("-include"); Inputs.ExtraArgs.push_back("target.h"); - Inputs.ExtraArgs.push_back("-std=c++17"); + Inputs.ExtraArgs.push_back("-std=c++20"); TestAST AST(Inputs); const auto &SM = AST.sourceManager(); @@ -510,5 +510,17 @@ testWalk("enum class E : int {};", "enum class ^E : int ;"); } +TEST(WalkAST, Concepts) { + testWalk("template <class> concept $explicit^C = true;", "^C auto x = 1;"); + testWalk("template <class> concept $explicit^C = true;", "bool x = ^C<int>;"); + testWalk("template <class> concept $explicit^C = true;", "void X(^C auto);"); + testWalk("template <class> concept $explicit^C = true;", + "template <^C T> int X;"); + testWalk("template <class> concept $explicit^C = true;", + "template <^C auto T> int X;"); + testWalk("template <class> concept $explicit^C = true;", + "template <class T> requires(^C<T>) int X;"); +} + } // namespace } // namespace clang::include_cleaner Index: clang-tools-extra/include-cleaner/lib/WalkAST.cpp =================================================================== --- clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -249,6 +249,11 @@ return true; } + bool VisitConceptReference(const ConceptReference *CR) { + report(CR->getConceptNameLoc(), CR->getNamedConcept()); + return true; + } + // TypeLoc visitors. void reportType(SourceLocation RefLoc, NamedDecl *ND) { // Reporting explicit references to types nested inside classes can cause @@ -279,6 +284,13 @@ return true; } + bool VisitAutoTypeLoc(AutoTypeLoc ATL) { + // FIXME: RAV should call VisitConceptReference here, but doesn't! + if (ATL.isConstrained()) + report(ATL.getConceptNameLoc(), ATL.getNamedConcept()); + return true; + } + bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { reportType(TL.getTemplateNameLoc(), getMostRelevantTemplatePattern(TL.getTypePtr()));
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits