nridge created this revision. nridge added a reviewer: hokein. Herald added a project: clang. Herald added a subscriber: cfe-commits. nridge requested review of this revision.
The patch also adds a templateArgumentLoc() AST matcher. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D85621 Files: clang/include/clang/AST/ASTTypeTraits.h clang/include/clang/ASTMatchers/ASTMatchFinder.h clang/include/clang/ASTMatchers/ASTMatchers.h clang/include/clang/ASTMatchers/ASTMatchersInternal.h clang/lib/AST/ASTTypeTraits.cpp clang/lib/ASTMatchers/ASTMatchFinder.cpp clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -2637,6 +2637,19 @@ std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1))); } +TEST(TemplateArgumentLoc, Matches) { + EXPECT_TRUE(matchAndVerifyResultTrue( + R"cpp( + template <typename A, int B, template <typename> class C> class X {}; + class A {}; + const int B = 42; + template <typename> class C {}; + X<A, B, C> x; + )cpp", + templateArgumentLoc().bind("x"), + std::make_unique<VerifyIdIsBoundTo<TemplateArgumentLoc>>("x", 3))); +} + TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) { // Those matchers cover all the cases where an inner matcher is called // and there is not a 1:1 relationship between the match of the outer Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -734,6 +734,7 @@ accessSpecDecl; const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer; const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; +const internal::VariadicAllOfMatcher<TemplateArgumentLoc> templateArgumentLoc; const internal::VariadicAllOfMatcher<TemplateName> templateName; const internal::VariadicDynCastAllOfMatcher<Decl, NonTypeTemplateParmDecl> nonTypeTemplateParmDecl; Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp =================================================================== --- clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -128,6 +128,9 @@ traverse(*T); else if (const auto *C = DynNode.get<CXXCtorInitializer>()) traverse(*C); + else if (const TemplateArgumentLoc *TALoc = + DynNode.get<TemplateArgumentLoc>()) + traverse(*TALoc); // FIXME: Add other base types after adding tests. // It's OK to always overwrite the bound nodes, as if there was @@ -224,6 +227,10 @@ ScopedIncrement ScopedDepth(&CurrentDepth); return traverse(*CtorInit); } + bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) { + ScopedIncrement ScopedDepth(&CurrentDepth); + return traverse(TAL); + } bool TraverseLambdaExpr(LambdaExpr *Node) { if (Finder->getASTContext().getParentMapContext().getTraversalKind() != TK_IgnoreUnlessSpelledInSource) @@ -304,6 +311,9 @@ return VisitorBase::TraverseConstructorInitializer( const_cast<CXXCtorInitializer *>(&CtorInit)); } + bool baseTraverse(TemplateArgumentLoc TAL) { + return VisitorBase::TraverseTemplateArgumentLoc(TAL); + } // Sets 'Matched' to true if 'Matcher' matches 'Node' and: // 0 < CurrentDepth <= MaxDepth. @@ -447,6 +457,7 @@ bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit); + bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL); // Matches children or descendants of 'Node' with 'BaseMatcher'. bool memoizedMatchesRecursively(const DynTypedNode &Node, ASTContext &Ctx, @@ -557,6 +568,8 @@ match(*N); } else if (auto *N = Node.get<CXXCtorInitializer>()) { match(*N); + } else if (auto *N = Node.get<TemplateArgumentLoc>()) { + match(*N); } } @@ -680,6 +693,9 @@ void matchDispatch(const CXXCtorInitializer *Node) { matchWithoutFilter(*Node, Matchers->CtorInit); } + void matchDispatch(const TemplateArgumentLoc *Node) { + matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc); + } void matchDispatch(const void *) { /* Do nothing. */ } /// @} @@ -1035,6 +1051,11 @@ CtorInit); } +bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) { + match(Loc); + return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc); +} + class MatchASTConsumer : public ASTConsumer { public: MatchASTConsumer(MatchFinder *Finder, @@ -1111,6 +1132,12 @@ Matchers.AllCallbacks.insert(Action); } +void MatchFinder::addMatcher(const TemplateArgumentLocMatcher &NodeMatch, + MatchCallback *Action) { + Matchers.TemplateArgumentLoc.emplace_back(NodeMatch, Action); + Matchers.AllCallbacks.insert(Action); +} + bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action) { if (NodeMatch.canConvertTo<Decl>()) { @@ -1134,6 +1161,9 @@ } else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) { addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action); return true; + } else if (NodeMatch.canConvertTo<TemplateArgumentLoc>()) { + addMatcher(NodeMatch.convertTo<TemplateArgumentLoc>(), Action); + return true; } return false; } Index: clang/lib/AST/ASTTypeTraits.cpp =================================================================== --- clang/lib/AST/ASTTypeTraits.cpp +++ clang/lib/AST/ASTTypeTraits.cpp @@ -23,6 +23,7 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { { NKI_None, "<None>" }, { NKI_None, "TemplateArgument" }, + { NKI_None, "TemplateArgumentLoc" }, { NKI_None, "TemplateName" }, { NKI_None, "NestedNameSpecifierLoc" }, { NKI_None, "QualType" }, @@ -129,6 +130,8 @@ const PrintingPolicy &PP) const { if (const TemplateArgument *TA = get<TemplateArgument>()) TA->print(PP, OS); + else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>()) + TAL->getArgument().print(PP, OS); else if (const TemplateName *TN = get<TemplateName>()) TN->print(OS, PP); else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>()) @@ -175,6 +178,8 @@ return D->getSourceRange(); if (const Stmt *S = get<Stmt>()) return S->getSourceRange(); + if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>()) + return TAL->getSourceRange(); if (const auto *C = get<OMPClause>()) return SourceRange(C->getBeginLoc(), C->getEndLoc()); return SourceRange(); Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -938,14 +938,13 @@ template <typename T> struct IsBaseType { static const bool value = - std::is_same<T, Decl>::value || - std::is_same<T, Stmt>::value || - std::is_same<T, QualType>::value || - std::is_same<T, Type>::value || + std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value || + std::is_same<T, QualType>::value || std::is_same<T, Type>::value || std::is_same<T, TypeLoc>::value || std::is_same<T, NestedNameSpecifier>::value || std::is_same<T, NestedNameSpecifierLoc>::value || - std::is_same<T, CXXCtorInitializer>::value; + std::is_same<T, CXXCtorInitializer>::value || + std::is_same<T, TemplateArgumentLoc>::value; }; template <typename T> const bool IsBaseType<T>::value; Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -145,6 +145,7 @@ using NestedNameSpecifierMatcher = internal::Matcher<NestedNameSpecifier>; using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>; using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>; +using TemplateArgumentLocMatcher = internal::Matcher<TemplateArgumentLoc>; /// @} /// Matches any node. @@ -515,6 +516,18 @@ /// matches 'int' in C<int>. extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; +/// Matches template arguments (with location info). +/// +/// Given +/// \code +/// template <typename T> struct C {}; +/// C<int> c; +/// \endcode +/// templateArgumentLoc() +/// matches 'int' in C<int>. +extern const internal::VariadicAllOfMatcher<TemplateArgumentLoc> + templateArgumentLoc; + /// Matches template name. /// /// Given Index: clang/include/clang/ASTMatchers/ASTMatchFinder.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchFinder.h +++ clang/include/clang/ASTMatchers/ASTMatchFinder.h @@ -159,6 +159,8 @@ MatchCallback *Action); void addMatcher(const CXXCtorInitializerMatcher &NodeMatch, MatchCallback *Action); + void addMatcher(const TemplateArgumentLocMatcher &NodeMatch, + MatchCallback *Action); /// @} /// Adds a matcher to execute when running over the AST. @@ -209,6 +211,8 @@ NestedNameSpecifierLoc; std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc; std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit; + std::vector<std::pair<TemplateArgumentLocMatcher, MatchCallback *>> + TemplateArgumentLoc; /// All the callbacks in one container to simplify iteration. llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks; }; Index: clang/include/clang/AST/ASTTypeTraits.h =================================================================== --- clang/include/clang/AST/ASTTypeTraits.h +++ clang/include/clang/AST/ASTTypeTraits.h @@ -132,6 +132,7 @@ enum NodeKindId { NKI_None, NKI_TemplateArgument, + NKI_TemplateArgumentLoc, NKI_TemplateName, NKI_NestedNameSpecifierLoc, NKI_QualType, @@ -191,6 +192,7 @@ }; KIND_TO_KIND_ID(CXXCtorInitializer) KIND_TO_KIND_ID(TemplateArgument) +KIND_TO_KIND_ID(TemplateArgumentLoc) KIND_TO_KIND_ID(TemplateName) KIND_TO_KIND_ID(NestedNameSpecifier) KIND_TO_KIND_ID(NestedNameSpecifierLoc) @@ -456,12 +458,13 @@ /// Note that we can store \c Decls, \c Stmts, \c Types, /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are /// guaranteed to be unique pointers pointing to dedicated storage in the AST. - /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and - /// \c TemplateArguments on the other hand do not have storage or unique - /// pointers and thus need to be stored by value. + /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs, + /// \c TemplateArguments and \c TemplateArgumentLocs on the other hand do not + /// have storage or unique pointers and thus need to be stored by value. llvm::AlignedCharArrayUnion<const void *, TemplateArgument, - NestedNameSpecifierLoc, QualType, - TypeLoc> Storage; + TemplateArgumentLoc, NestedNameSpecifierLoc, + QualType, TypeLoc> + Storage; }; template <typename T> @@ -496,6 +499,10 @@ struct DynTypedNode::BaseConverter< TemplateArgument, void> : public ValueConverter<TemplateArgument> {}; +template <> +struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void> + : public ValueConverter<TemplateArgumentLoc> {}; + template <> struct DynTypedNode::BaseConverter< TemplateName, void> : public ValueConverter<TemplateName> {};
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits