34#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
35#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
52#include "llvm/ADT/APFloat.h"
53#include "llvm/ADT/ArrayRef.h"
54#include "llvm/ADT/IntrusiveRefCntPtr.h"
55#include "llvm/ADT/STLExtras.h"
56#include "llvm/ADT/SmallVector.h"
57#include "llvm/ADT/StringRef.h"
58#include "llvm/ADT/iterator.h"
59#include "llvm/Support/Casting.h"
60#include "llvm/Support/ManagedStatic.h"
61#include "llvm/Support/Regex.h"
89template <
typename... Ts>
struct TypeList {};
91template <
typename T1,
typename... Ts>
struct TypeList<T1, Ts...> {
99 using tail = TypeList<Ts...>;
103using EmptyTypeList = TypeList<>;
107template <
typename AnyTypeList,
typename T>
struct TypeListContainsSuperOf {
108 static const bool value =
109 std::is_base_of<typename AnyTypeList::head, T>::value ||
110 TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value;
112template <
typename T>
struct TypeListContainsSuperOf<EmptyTypeList,
T> {
113 static const bool value =
false;
121template <
typename ResultT,
typename ArgT,
122 ResultT (*
Func)(ArrayRef<const ArgT *>)>
123struct VariadicFunction {
124 ResultT operator()()
const {
return Func({}); }
126 template <
typename... ArgsT>
127 ResultT operator()(
const ArgT &Arg1,
const ArgsT &... Args)
const {
128 return Execute(Arg1,
static_cast<const ArgT &
>(Args)...);
133 ResultT operator()(ArrayRef<ArgT> Args)
const {
134 return Func(llvm::to_vector<8>(llvm::make_pointer_range(Args)));
140 template <
typename... ArgsT> ResultT Execute(
const ArgsT &... Args)
const {
141 const ArgT *
const ArgsArray[] = {&Args...};
142 return Func(ArrayRef<const ArgT *>(ArgsArray,
sizeof...(ArgsT)));
151 return Node.getType();
154 return Node.getUnderlyingType();
157 if (
const TypeSourceInfo *TSI = Node.getFriendType())
158 return TSI->getType();
162 return Node.getType();
165 return Node.getTypeForDecl()->getPointeeType();
170 std::enable_if_t<TypeListContainsSuperOf<
171 TypeList<CXXBaseSpecifier, CXXCtorInitializer,
172 CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr,
173 CompoundLiteralExpr, DeclaratorDecl, ObjCPropertyDecl,
174 TemplateArgumentLoc, TypedefNameDecl>,
175 T>::value> * =
nullptr>
176inline TypeSourceInfo *GetTypeSourceInfo(
const T &Node) {
177 return Node.getTypeSourceInfo();
180 std::enable_if_t<TypeListContainsSuperOf<
181 TypeList<CXXFunctionalCastExpr, ExplicitCastExpr>,
T>::value> * =
183inline TypeSourceInfo *GetTypeSourceInfo(
const T &Node) {
184 return Node.getTypeInfoAsWritten();
186inline TypeSourceInfo *GetTypeSourceInfo(
const BlockDecl &Node) {
187 return Node.getSignatureAsWritten();
189inline TypeSourceInfo *GetTypeSourceInfo(
const CXXNewExpr &Node) {
190 return Node.getAllocatedTypeSourceInfo();
195inline const FunctionProtoType *
196getFunctionProtoType(
const FunctionProtoType &Node) {
200inline const FunctionProtoType *getFunctionProtoType(
const FunctionDecl &Node) {
201 return Node.getType()->getAs<FunctionProtoType>();
206 return Node.getAccess();
210 return Node.getAccessSpecifier();
219 void addNode(StringRef ID,
const DynTypedNode &DynNode) {
220 NodeMap[std::string(ID)] = DynNode;
227 template <
typename T>
228 const T *getNodeAs(StringRef ID)
const {
229 IDToNodeMap::const_iterator It = NodeMap.find(ID);
230 if (It == NodeMap.end()) {
233 return It->second.get<
T>();
237 IDToNodeMap::const_iterator It = NodeMap.find(ID);
238 if (It == NodeMap.end()) {
245 bool operator<(
const BoundNodesMap &Other)
const {
246 return NodeMap <
Other.NodeMap;
254 using IDToNodeMap = std::map<std::string, DynTypedNode, std::less<>>;
256 const IDToNodeMap &getMap()
const {
262 bool isComparable()
const {
263 for (
const auto &IDAndNode : NodeMap) {
264 if (!IDAndNode.second.getMemoizationData())
278class BoundNodesTreeBuilder {
284 virtual ~Visitor() =
default;
289 virtual void visitMatch(
const BoundNodes& BoundNodesView) = 0;
293 void setBinding(StringRef Id,
const DynTypedNode &DynNode) {
296 for (BoundNodesMap &Binding :
Bindings)
297 Binding.addNode(Id, DynNode);
301 void addMatch(
const BoundNodesTreeBuilder &
Bindings);
306 void visitMatches(Visitor* ResultVisitor);
308 template <
typename ExcludePredicate>
309 bool removeBindings(
const ExcludePredicate &Predicate) {
310 llvm::erase_if(
Bindings, Predicate);
315 bool operator<(
const BoundNodesTreeBuilder &Other)
const {
321 bool isComparable()
const {
322 for (
const BoundNodesMap &NodesMap :
Bindings) {
323 if (!NodesMap.isComparable())
330 SmallVector<BoundNodesMap, 1>
Bindings;
340class DynMatcherInterface
341 :
public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
343 virtual ~DynMatcherInterface() =
default;
349 virtual bool dynMatches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
350 BoundNodesTreeBuilder *Builder)
const = 0;
352 virtual std::optional<clang::TraversalKind>
TraversalKind()
const {
365class MatcherInterface :
public DynMatcherInterface {
371 virtual bool matches(
const T &Node,
372 ASTMatchFinder *Finder,
373 BoundNodesTreeBuilder *Builder)
const = 0;
375 bool dynMatches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
376 BoundNodesTreeBuilder *Builder)
const override {
377 return matches(DynNode.getUnchecked<T>(), Finder, Builder);
384class SingleNodeMatcherInterface :
public MatcherInterface<T> {
389 virtual bool matchesNode(
const T &Node)
const = 0;
395 BoundNodesTreeBuilder * )
const override {
396 return matchesNode(Node);
400template <
typename>
class Matcher;
409class DynTypedMatcher {
412 template <
typename T>
413 DynTypedMatcher(MatcherInterface<T> *Implementation)
414 : SupportedKind(ASTNodeKind::getFromNodeKind<
T>()),
415 RestrictKind(SupportedKind), Implementation(Implementation) {}
418 enum VariadicOperator {
441 static DynTypedMatcher
442 constructVariadic(VariadicOperator Op, ASTNodeKind SupportedKind,
443 std::vector<DynTypedMatcher> InnerMatchers);
445 static DynTypedMatcher
446 constructRestrictedWrapper(
const DynTypedMatcher &InnerMatcher,
447 ASTNodeKind RestrictKind);
452 static DynTypedMatcher trueMatcher(ASTNodeKind NodeKind);
454 void setAllowBind(
bool AB) { AllowBind = AB; }
459 bool canMatchNodesOfKind(ASTNodeKind Kind)
const;
463 DynTypedMatcher dynCastTo(
const ASTNodeKind Kind)
const;
469 DynTypedMatcher withTraversalKind(TraversalKind TK);
472 bool matches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
473 BoundNodesTreeBuilder *Builder)
const;
479 bool matchesNoKindCheck(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
480 BoundNodesTreeBuilder *Builder)
const;
485 std::optional<DynTypedMatcher> tryBind(StringRef ID)
const;
494 using MatcherIDType = std::pair<ASTNodeKind, uint64_t>;
495 MatcherIDType getID()
const {
498 return std::make_pair(RestrictKind,
499 reinterpret_cast<uint64_t>(Implementation.get()));
506 ASTNodeKind getSupportedKind()
const {
return SupportedKind; }
513 template <
typename T>
bool canConvertTo()
const {
514 return canConvertTo(ASTNodeKind::getFromNodeKind<T>());
516 bool canConvertTo(ASTNodeKind To)
const;
523 template <
typename T> Matcher<T> convertTo()
const {
524 assert(canConvertTo<T>());
525 return unconditionalConvertTo<T>();
532 template <
typename T> Matcher<T> unconditionalConvertTo()
const;
538 std::optional<clang::TraversalKind> getTraversalKind()
const {
539 return Implementation->TraversalKind();
543 DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind,
544 IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
545 : SupportedKind(SupportedKind), RestrictKind(RestrictKind),
546 Implementation(std::move(Implementation)) {}
548 bool AllowBind =
false;
549 ASTNodeKind SupportedKind;
555 ASTNodeKind RestrictKind;
556 IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
571 explicit Matcher(MatcherInterface<T> *Implementation)
572 : Implementation(Implementation) {}
577 template <
typename From>
578 Matcher(
const Matcher<From> &Other,
579 std::enable_if_t<std::is_base_of<From, T>::value &&
580 !std::is_same<From, T>::value> * =
nullptr)
581 : Implementation(restrictMatcher(
Other.Implementation)) {
582 assert(Implementation.getSupportedKind().isSame(
583 ASTNodeKind::getFromNodeKind<T>()));
589 template <
typename TypeT>
590 Matcher(
const Matcher<TypeT> &Other,
591 std::enable_if_t<std::is_same<T, QualType>::value &&
592 std::is_same<TypeT, Type>::value> * =
nullptr)
593 : Implementation(new TypeToQualType<TypeT>(
Other)) {}
598 template <
typename To> Matcher<To> dynCastTo() const & {
599 static_assert(std::is_base_of<To, T>::value,
"Invalid dynCast call.");
600 return Matcher<To>(Implementation);
603 template <
typename To> Matcher<To> dynCastTo() && {
604 static_assert(std::is_base_of<To, T>::value,
"Invalid dynCast call.");
605 return Matcher<To>(std::move(Implementation));
610 ASTMatchFinder *Finder,
611 BoundNodesTreeBuilder *Builder)
const {
612 return Implementation.matches(DynTypedNode::create(Node), Finder, Builder);
616 DynTypedMatcher::MatcherIDType getID()
const {
617 return Implementation.getID();
624 operator DynTypedMatcher() const & {
return Implementation; }
626 operator DynTypedMatcher() && {
return std::move(Implementation); }
634 template <
typename TypeT>
635 class TypeToQualType :
public MatcherInterface<QualType> {
636 const DynTypedMatcher InnerMatcher;
639 TypeToQualType(
const Matcher<TypeT> &InnerMatcher)
640 : InnerMatcher(InnerMatcher) {}
642 bool matches(
const QualType &Node, ASTMatchFinder *Finder,
643 BoundNodesTreeBuilder *Builder)
const override {
646 return this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder,
650 std::optional<clang::TraversalKind>
TraversalKind()
const override {
651 return this->InnerMatcher.getTraversalKind();
657 template <
typename U>
friend class Matcher;
660 friend class DynTypedMatcher;
662 static DynTypedMatcher restrictMatcher(
const DynTypedMatcher &Other) {
663 return Other.dynCastTo(ASTNodeKind::getFromNodeKind<T>());
666 explicit Matcher(
const DynTypedMatcher &Implementation)
667 : Implementation(restrictMatcher(Implementation)) {
668 assert(this->Implementation.getSupportedKind().isSame(
669 ASTNodeKind::getFromNodeKind<T>()));
672 DynTypedMatcher Implementation;
676template <
typename T> Matcher(MatcherInterface<T> *) -> Matcher<T>;
681 "Use CTAD constructor instead, 'makeMatcher' will be removed in LLVM 23.")]]
682inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
683 return Matcher<T>(Implementation);
704class ASTMatchFinder {
716 enum AncestorMatchMode {
724 virtual ~ASTMatchFinder() =
default;
730 virtual bool classIsDerivedFrom(
const CXXRecordDecl *Declaration,
731 const Matcher<NamedDecl> &Base,
732 BoundNodesTreeBuilder *Builder,
739 virtual bool objcClassIsDerivedFrom(
const ObjCInterfaceDecl *Declaration,
740 const Matcher<NamedDecl> &Base,
741 BoundNodesTreeBuilder *Builder,
744 template <
typename T>
745 bool matchesChildOf(
const T &Node,
const DynTypedMatcher &Matcher,
746 BoundNodesTreeBuilder *Builder, BindKind Bind) {
747 static_assert(std::is_base_of<Decl, T>::value ||
748 std::is_base_of<Stmt, T>::value ||
749 std::is_base_of<NestedNameSpecifier, T>::value ||
750 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
751 std::is_base_of<TypeLoc, T>::value ||
752 std::is_base_of<QualType, T>::value ||
753 std::is_base_of<Attr, T>::value,
754 "unsupported type for recursive matching");
755 return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher,
759 template <
typename T>
760 bool matchesDescendantOf(
const T &Node,
const DynTypedMatcher &Matcher,
761 BoundNodesTreeBuilder *Builder, BindKind Bind) {
762 static_assert(std::is_base_of<Decl, T>::value ||
763 std::is_base_of<Stmt, T>::value ||
764 std::is_base_of<NestedNameSpecifier, T>::value ||
765 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
766 std::is_base_of<TypeLoc, T>::value ||
767 std::is_base_of<QualType, T>::value ||
768 std::is_base_of<Attr, T>::value,
769 "unsupported type for recursive matching");
770 return matchesDescendantOf(DynTypedNode::create(Node), getASTContext(),
771 Matcher, Builder, Bind);
775 template <
typename T>
776 bool matchesAncestorOf(
const T &Node,
const DynTypedMatcher &Matcher,
777 BoundNodesTreeBuilder *Builder,
778 AncestorMatchMode MatchMode) {
779 static_assert(std::is_base_of<Decl, T>::value ||
780 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
781 std::is_base_of<Stmt, T>::value ||
782 std::is_base_of<TypeLoc, T>::value ||
783 std::is_base_of<Attr, T>::value,
784 "type not allowed for recursive matching");
785 return matchesAncestorOf(DynTypedNode::create(Node), getASTContext(),
786 Matcher, Builder, MatchMode);
789 virtual ASTContext &getASTContext()
const = 0;
791 virtual bool IsMatchingInASTNodeNotSpelledInSource()
const = 0;
793 virtual bool IsMatchingInASTNodeNotAsIs()
const = 0;
795 bool isTraversalIgnoringImplicitNodes()
const;
798 virtual bool matchesChildOf(
const DynTypedNode &Node, ASTContext &Ctx,
799 const DynTypedMatcher &Matcher,
800 BoundNodesTreeBuilder *Builder,
803 virtual bool matchesDescendantOf(
const DynTypedNode &Node, ASTContext &Ctx,
804 const DynTypedMatcher &Matcher,
805 BoundNodesTreeBuilder *Builder,
808 virtual bool matchesAncestorOf(
const DynTypedNode &Node, ASTContext &Ctx,
809 const DynTypedMatcher &Matcher,
810 BoundNodesTreeBuilder *Builder,
811 AncestorMatchMode MatchMode) = 0;
813 friend struct ASTChildrenNotSpelledInSourceScope;
814 virtual bool isMatchingChildrenNotSpelledInSource()
const = 0;
815 virtual void setMatchingChildrenNotSpelledInSource(
bool Set) = 0;
818struct ASTChildrenNotSpelledInSourceScope {
819 ASTChildrenNotSpelledInSourceScope(ASTMatchFinder *
V,
bool B)
820 : MV(
V), MB(
V->isMatchingChildrenNotSpelledInSource()) {
821 V->setMatchingChildrenNotSpelledInSource(B);
823 ~ASTChildrenNotSpelledInSourceScope() {
824 MV->setMatchingChildrenNotSpelledInSource(MB);
837inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>()
const {
838 assert(canConvertTo<QualType>());
839 const ASTNodeKind SourceKind = getSupportedKind();
842 return unconditionalConvertTo<Type>();
844 return unconditionalConvertTo<QualType>();
848template <
typename MatcherT,
typename IteratorT>
849IteratorT matchesFirstInRange(
const MatcherT &Matcher, IteratorT Start,
850 IteratorT End, ASTMatchFinder *Finder,
851 BoundNodesTreeBuilder *Builder) {
852 for (IteratorT I = Start; I != End; ++I) {
853 BoundNodesTreeBuilder
Result(*Builder);
854 if (Matcher.matches(*I, Finder, &
Result)) {
855 *Builder = std::move(
Result);
864template <
typename MatcherT,
typename IteratorT>
865IteratorT matchesFirstInPointerRange(
const MatcherT &Matcher, IteratorT Start,
866 IteratorT End, ASTMatchFinder *Finder,
867 BoundNodesTreeBuilder *Builder) {
868 for (IteratorT I = Start; I != End; ++I) {
869 BoundNodesTreeBuilder
Result(*Builder);
870 if (Matcher.matches(**I, Finder, &
Result)) {
871 *Builder = std::move(
Result);
878template <
typename T>
inline bool isDefaultedHelper(
const T *FD) {
879 if constexpr (std::is_base_of_v<FunctionDecl, T>)
880 return FD->isDefaulted();
886using check_has_getDecl =
decltype(std::declval<T &>().getDecl());
889static constexpr bool has_getDecl =
890 llvm::is_detected<check_has_getDecl, T>::value;
896template <
typename T,
typename ArgT>
897class HasOverloadedOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
898 static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
899 std::is_base_of<FunctionDecl, T>::value,
900 "unsupported class for matcher");
901 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
902 "argument type must be std::vector<std::string>");
905 explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names)
906 : SingleNodeMatcherInterface<
T>(), Names(std::move(Names)) {}
908 bool matchesNode(
const T &Node)
const override {
909 return matchesSpecialized(Node);
917 bool matchesSpecialized(
const CXXOperatorCallExpr &Node)
const {
923 bool matchesSpecialized(
const FunctionDecl &Node)
const {
924 return Node.isOverloadedOperator() &&
929 std::vector<std::string> Names;
935class HasNameMatcher :
public SingleNodeMatcherInterface<NamedDecl> {
937 explicit HasNameMatcher(std::vector<std::string> Names);
939 bool matchesNode(
const NamedDecl &Node)
const override;
946 bool matchesNodeUnqualified(
const NamedDecl &Node)
const;
954 bool matchesNodeFullFast(
const NamedDecl &Node)
const;
961 bool matchesNodeFullSlow(
const NamedDecl &Node)
const;
963 bool UseUnqualifiedMatch;
964 std::vector<std::string> Names;
969Matcher<NamedDecl>
hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs);
974 ArrayRef<const StringRef *> NameRefs);
980template <
typename T,
typename DeclMatcherT>
981class HasDeclarationMatcher :
public MatcherInterface<T> {
982 static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
983 "instantiated with wrong types");
985 DynTypedMatcher InnerMatcher;
988 explicit HasDeclarationMatcher(
const Matcher<Decl> &InnerMatcher)
989 : InnerMatcher(InnerMatcher) {}
991 bool matches(
const T &Node, ASTMatchFinder *Finder,
992 BoundNodesTreeBuilder *Builder)
const override {
993 return matchesSpecialized(Node, Finder, Builder);
998 bool matchesSpecialized(
const QualType &Node, ASTMatchFinder *Finder,
999 BoundNodesTreeBuilder *Builder)
const {
1003 return matchesSpecialized(*Node, Finder, Builder);
1008 bool matchesSpecialized(
const Type &Node, ASTMatchFinder *Finder,
1009 BoundNodesTreeBuilder *Builder)
const {
1012 if (
const auto *S = dyn_cast<DeducedType>(&Node)) {
1013 QualType DT = S->getDeducedType();
1014 return !DT.isNull() ? matchesSpecialized(*DT, Finder, Builder) :
false;
1019 if (
const auto *S = dyn_cast<TagType>(&Node)) {
1020 return matchesDecl(S->getOriginalDecl(), Finder, Builder);
1022 if (
const auto *S = dyn_cast<TemplateTypeParmType>(&Node)) {
1023 return matchesDecl(S->getDecl(), Finder, Builder);
1025 if (
const auto *S = dyn_cast<TypedefType>(&Node)) {
1026 return matchesDecl(S->getDecl(), Finder, Builder);
1028 if (
const auto *S = dyn_cast<UnresolvedUsingType>(&Node)) {
1029 return matchesDecl(S->getDecl(), Finder, Builder);
1031 if (
const auto *S = dyn_cast<UsingType>(&Node)) {
1032 return matchesDecl(S->getDecl(), Finder, Builder);
1034 if (
const auto *S = dyn_cast<ObjCObjectType>(&Node)) {
1035 return matchesDecl(S->getInterface(), Finder, Builder);
1046 if (
const auto *S = dyn_cast<SubstTemplateTypeParmType>(&Node)) {
1047 return matchesSpecialized(S->getReplacementType(), Finder, Builder);
1053 if (
const auto *S = dyn_cast<TemplateSpecializationType>(&Node)) {
1054 if (!S->isTypeAlias() && S->isSugared()) {
1061 return matchesSpecialized(*S->desugar(), Finder, Builder);
1065 return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder,
1072 if (
const auto *S = dyn_cast<UsingType>(&Node)) {
1073 return matchesSpecialized(S->desugar(), Finder, Builder);
1080 bool matchesSpecialized(
const DeclRefExpr &Node, ASTMatchFinder *Finder,
1081 BoundNodesTreeBuilder *Builder)
const {
1082 return matchesDecl(Node.getDecl(), Finder, Builder);
1087 bool matchesSpecialized(
const CallExpr &Node, ASTMatchFinder *Finder,
1088 BoundNodesTreeBuilder *Builder)
const {
1089 return matchesDecl(Node.getCalleeDecl(), Finder, Builder);
1094 bool matchesSpecialized(
const CXXConstructExpr &Node,
1095 ASTMatchFinder *Finder,
1096 BoundNodesTreeBuilder *Builder)
const {
1097 return matchesDecl(Node.getConstructor(), Finder, Builder);
1100 bool matchesSpecialized(
const ObjCIvarRefExpr &Node,
1101 ASTMatchFinder *Finder,
1102 BoundNodesTreeBuilder *Builder)
const {
1103 return matchesDecl(Node.getDecl(), Finder, Builder);
1106 bool matchesSpecialized(
const ObjCInterfaceDecl &Node, ASTMatchFinder *Finder,
1107 BoundNodesTreeBuilder *Builder)
const {
1108 return matchesDecl(Node.getCanonicalDecl(), Finder, Builder);
1113 bool matchesSpecialized(
const CXXNewExpr &Node,
1114 ASTMatchFinder *Finder,
1115 BoundNodesTreeBuilder *Builder)
const {
1116 return matchesDecl(Node.getOperatorNew(), Finder, Builder);
1121 bool matchesSpecialized(
const MemberExpr &Node,
1122 ASTMatchFinder *Finder,
1123 BoundNodesTreeBuilder *Builder)
const {
1124 return matchesDecl(Node.getMemberDecl(), Finder, Builder);
1129 bool matchesSpecialized(
const AddrLabelExpr &Node,
1130 ASTMatchFinder *Finder,
1131 BoundNodesTreeBuilder *Builder)
const {
1132 return matchesDecl(Node.getLabel(), Finder, Builder);
1137 bool matchesSpecialized(
const LabelStmt &Node, ASTMatchFinder *Finder,
1138 BoundNodesTreeBuilder *Builder)
const {
1139 return matchesDecl(Node.getDecl(), Finder, Builder);
1144 bool matchesDecl(
const Decl *Node, ASTMatchFinder *Finder,
1145 BoundNodesTreeBuilder *Builder)
const {
1146 return Node !=
nullptr &&
1147 !(Finder->isTraversalIgnoringImplicitNodes() &&
1148 Node->isImplicit()) &&
1149 this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder,
1156template <
typename T>
1158 static const bool value =
1159 std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value ||
1160 std::is_same<T, QualType>::value || std::is_same<T, Type>::value ||
1161 std::is_same<T, TypeLoc>::value ||
1162 std::is_same<T, NestedNameSpecifier>::value ||
1163 std::is_same<T, NestedNameSpecifierLoc>::value ||
1164 std::is_same<T, CXXCtorInitializer>::value ||
1165 std::is_same<T, TemplateArgumentLoc>::value ||
1166 std::is_same<T, Attr>::value;
1168template <
typename T>
1169const bool IsBaseType<T>::value;
1174using AllNodeBaseTypes =
1175 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
1176 Type, TypeLoc, CXXCtorInitializer, Attr>;
1182template <
class T>
struct ExtractFunctionArgMeta;
1183template <
class T>
struct ExtractFunctionArgMeta<void(
T)> {
1187template <
class T,
class Tuple, std::size_t... I>
1188constexpr T *new_from_tuple_impl(Tuple &&t, std::index_sequence<I...>) {
1189 return new T(std::get<I>(std::forward<Tuple>(t))...);
1192template <
class T,
class Tuple>
constexpr T *new_from_tuple(Tuple &&t) {
1193 return new_from_tuple_impl<T>(
1194 std::forward<Tuple>(t),
1195 std::make_index_sequence<
1196 std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
1200using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
1201using AdaptativeDefaultToTypes =
1202 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
1206using HasDeclarationSupportedTypes =
1207 TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
1208 InjectedClassNameType, LabelStmt, AddrLabelExpr, MemberExpr,
1209 QualType, RecordType, TagType, UsingType,
1210 TemplateSpecializationType, TemplateTypeParmType, TypedefType,
1211 UnresolvedUsingType, ObjCIvarRefExpr, ObjCInterfaceDecl>;
1217template <
typename T>
class BindableMatcher :
public Matcher<T> {
1219 explicit BindableMatcher(
const Matcher<T> &M) : Matcher<
T>(M) {}
1220 explicit BindableMatcher(MatcherInterface<T> *Implementation)
1221 : Matcher<
T>(Implementation) {}
1227 Matcher<T> bind(StringRef ID)
const {
1228 return DynTypedMatcher(*
this)
1230 ->template unconditionalConvertTo<T>();
1235 operator DynTypedMatcher()
const {
1236 DynTypedMatcher
Result =
static_cast<const Matcher<T> &
>(*this);
1237 Result.setAllowBind(
true);
1248 using ReturnTypes = AllNodeBaseTypes;
1250 template <
typename T>
operator Matcher<T>()
const {
1251 return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
1252 .template unconditionalConvertTo<T>();
1257template <
typename T>
1259makeAllOfComposite(ArrayRef<
const Matcher<T> *> InnerMatchers) {
1261 if (InnerMatchers.empty()) {
1262 return BindableMatcher<T>(TrueMatcher());
1266 if (InnerMatchers.size() == 1) {
1267 return BindableMatcher<T>(*InnerMatchers[0]);
1270 using PI = llvm::pointee_iterator<const Matcher<T> *
const *>;
1272 std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
1273 PI(InnerMatchers.end()));
1274 return BindableMatcher<T>(
1275 DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
1277 std::move(DynMatchers))
1278 .
template unconditionalConvertTo<T>());
1287template <
typename T,
typename InnerT>
1289makeDynCastAllOfComposite(ArrayRef<
const Matcher<InnerT> *> InnerMatchers) {
1290 return BindableMatcher<T>(
1291 makeAllOfComposite(InnerMatchers).
template dynCastTo<T>());
1305template <
typename SourceT,
typename TargetT>
1306class VariadicDynCastAllOfMatcher
1307 :
public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
1308 makeDynCastAllOfComposite<SourceT, TargetT>> {
1310 VariadicDynCastAllOfMatcher() {}
1323template <
typename T>
1324class VariadicAllOfMatcher
1325 :
public VariadicFunction<BindableMatcher<T>, Matcher<T>,
1326 makeAllOfComposite<T>> {
1328 VariadicAllOfMatcher() {}
1340template <
typename... Ps>
class VariadicOperatorMatcher {
1342 VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
1343 : Op(Op), Params(std::forward<Ps>(Params)...) {}
1345 template <
typename T>
operator Matcher<T>() const & {
1346 return DynTypedMatcher::constructVariadic(
1347 Op, ASTNodeKind::getFromNodeKind<T>(),
1348 getMatchers<T>(std::index_sequence_for<Ps...>()))
1349 .template unconditionalConvertTo<T>();
1352 template <
typename T>
operator Matcher<T>() && {
1353 return DynTypedMatcher::constructVariadic(
1354 Op, ASTNodeKind::getFromNodeKind<T>(),
1355 getMatchers<T>(std::index_sequence_for<Ps...>()))
1356 .template unconditionalConvertTo<T>();
1361 template <
typename T, std::size_t... Is>
1362 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>)
const & {
1363 return {Matcher<T>(std::get<Is>(Params))...};
1366 template <
typename T, std::size_t... Is>
1367 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) && {
1368 return {Matcher<T>(std::get<Is>(std::move(Params)))...};
1371 const DynTypedMatcher::VariadicOperator Op;
1372 std::tuple<Ps...> Params;
1377template <
unsigned MinCount,
unsigned MaxCount>
1378struct VariadicOperatorMatcherFunc {
1379 DynTypedMatcher::VariadicOperator Op;
1381 template <
typename... Ms>
1382 VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps)
const {
1383 static_assert(MinCount <=
sizeof...(Ms) &&
sizeof...(Ms) <= MaxCount,
1384 "invalid number of parameters for variadic matcher");
1385 return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
1389template <
typename T,
bool IsBaseOf,
typename Head,
typename Tail>
1390struct GetCladeImpl {
1393template <
typename T,
typename Head,
typename Tail>
1394struct GetCladeImpl<
T,
false, Head, Tail>
1395 : GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
1396 typename Tail::head, typename Tail::tail> {};
1398template <
typename T,
typename... U>
1399struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
1401template <
typename CladeType,
typename... MatcherTypes>
1402struct MapAnyOfMatcherImpl {
1404 template <
typename... InnerMatchers>
1405 BindableMatcher<CladeType>
1406 operator()(InnerMatchers &&... InnerMatcher)
const {
1407 return VariadicAllOfMatcher<CladeType>()(std::apply(
1408 internal::VariadicOperatorMatcherFunc<
1409 0, std::numeric_limits<unsigned>::max()>{
1410 internal::DynTypedMatcher::VO_AnyOf},
1412 [&](
auto... Matcher) {
1413 return std::make_tuple(Matcher(InnerMatcher...)...);
1416 VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
1420template <
typename... MatcherTypes>
1421using MapAnyOfMatcher =
1422 MapAnyOfMatcherImpl<
typename GetClade<MatcherTypes...>
::Type,
1425template <
typename... MatcherTypes>
struct MapAnyOfHelper {
1426 using CladeType =
typename GetClade<MatcherTypes...>::Type;
1428 MapAnyOfMatcher<MatcherTypes...> with;
1430 operator BindableMatcher<CladeType>()
const {
return with(); }
1432 Matcher<CladeType> bind(StringRef ID)
const {
return with().bind(ID); }
1435template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1436 typename T,
typename ToTypes>
1437class ArgumentAdaptingMatcherFuncAdaptor {
1439 explicit ArgumentAdaptingMatcherFuncAdaptor(
const Matcher<T> &InnerMatcher)
1440 : InnerMatcher(InnerMatcher) {}
1442 using ReturnTypes = ToTypes;
1444 template <
typename To>
operator Matcher<To>() const & {
1445 return Matcher<To>(
new ArgumentAdapterT<To, T>(InnerMatcher));
1448 template <
typename To>
operator Matcher<To>() && {
1449 return Matcher<To>(
new ArgumentAdapterT<To, T>(std::move(InnerMatcher)));
1453 Matcher<T> InnerMatcher;
1469template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1470 typename FromTypes = AdaptativeDefaultFromTypes,
1471 typename ToTypes = AdaptativeDefaultToTypes>
1472struct ArgumentAdaptingMatcherFunc {
1473 template <
typename T>
1474 static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1475 create(
const Matcher<T> &InnerMatcher) {
1476 return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>(
1480 template <
typename T>
1481 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1482 operator()(
const Matcher<T> &InnerMatcher)
const {
1483 return create(InnerMatcher);
1486 template <
typename...
T>
1487 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT,
1488 typename GetClade<
T...>::Type, ToTypes>
1489 operator()(
const MapAnyOfHelper<T...> &InnerMatcher)
const {
1490 return create(InnerMatcher.with());
1494template <
typename T>
class TraversalMatcher :
public MatcherInterface<T> {
1495 DynTypedMatcher InnerMatcher;
1500 const Matcher<T> &InnerMatcher)
1501 : InnerMatcher(InnerMatcher), Traversal(TK) {}
1503 bool matches(
const T &Node, ASTMatchFinder *Finder,
1504 BoundNodesTreeBuilder *Builder)
const override {
1505 return this->InnerMatcher.matches(DynTypedNode::create(Node), Finder,
1509 std::optional<clang::TraversalKind>
TraversalKind()
const override {
1510 if (
auto NestedKind = this->InnerMatcher.getTraversalKind())
1516template <
typename MatcherType>
class TraversalWrapper {
1518 TraversalWrapper(TraversalKind TK,
const MatcherType &InnerMatcher)
1519 : TK(TK), InnerMatcher(InnerMatcher) {}
1521 template <
typename T>
operator Matcher<T>() const & {
1522 return internal::DynTypedMatcher::constructRestrictedWrapper(
1523 new internal::TraversalMatcher<T>(TK, InnerMatcher),
1524 ASTNodeKind::getFromNodeKind<T>())
1525 .template unconditionalConvertTo<T>();
1528 template <
typename T>
operator Matcher<T>() && {
1529 return internal::DynTypedMatcher::constructRestrictedWrapper(
1530 new internal::TraversalMatcher<T>(TK, std::move(InnerMatcher)),
1531 ASTNodeKind::getFromNodeKind<T>())
1532 .template unconditionalConvertTo<T>();
1537 MatcherType InnerMatcher;
1552template <
template <
typename T,
typename... Params>
class MatcherT,
1553 typename ReturnTypesF, typename... ParamTypes>
1554class PolymorphicMatcher {
1556 PolymorphicMatcher(
const ParamTypes &... Params) : Params(Params...) {}
1558 using ReturnTypes =
typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1560 template <
typename T>
operator Matcher<T>() const & {
1561 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1562 "right polymorphic conversion");
1563 return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params));
1566 template <
typename T>
operator Matcher<T>() && {
1567 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1568 "right polymorphic conversion");
1570 new_from_tuple<MatcherT<T, ParamTypes...>>(std::move(Params)));
1574 std::tuple<ParamTypes...> Params;
1581template <
typename T,
typename ChildT>
1582class HasMatcher :
public MatcherInterface<T> {
1583 DynTypedMatcher InnerMatcher;
1586 explicit HasMatcher(
const Matcher<ChildT> &InnerMatcher)
1587 : InnerMatcher(InnerMatcher) {}
1589 bool matches(
const T &Node, ASTMatchFinder *Finder,
1590 BoundNodesTreeBuilder *Builder)
const override {
1591 return Finder->matchesChildOf(Node, this->InnerMatcher, Builder,
1592 ASTMatchFinder::BK_First);
1601template <
typename T,
typename ChildT>
1602class ForEachMatcher :
public MatcherInterface<T> {
1603 static_assert(IsBaseType<ChildT>::value,
1604 "for each only accepts base type matcher");
1606 DynTypedMatcher InnerMatcher;
1609 explicit ForEachMatcher(
const Matcher<ChildT> &InnerMatcher)
1610 : InnerMatcher(InnerMatcher) {}
1612 bool matches(
const T &Node, ASTMatchFinder *Finder,
1613 BoundNodesTreeBuilder *Builder)
const override {
1614 return Finder->matchesChildOf(
1615 Node, this->InnerMatcher, Builder,
1616 ASTMatchFinder::BK_All);
1622template <
typename T>
1623inline Matcher<T> DynTypedMatcher::unconditionalConvertTo()
const {
1624 return Matcher<T>(*
this);
1631template <
typename T,
typename DescendantT>
1632class HasDescendantMatcher :
public MatcherInterface<T> {
1633 static_assert(IsBaseType<DescendantT>::value,
1634 "has descendant only accepts base type matcher");
1636 DynTypedMatcher DescendantMatcher;
1639 explicit HasDescendantMatcher(
const Matcher<DescendantT> &DescendantMatcher)
1640 : DescendantMatcher(DescendantMatcher) {}
1642 bool matches(
const T &Node, ASTMatchFinder *Finder,
1643 BoundNodesTreeBuilder *Builder)
const override {
1644 return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
1645 ASTMatchFinder::BK_First);
1653template <
typename T,
typename ParentT>
1654class HasParentMatcher :
public MatcherInterface<T> {
1655 static_assert(IsBaseType<ParentT>::value,
1656 "has parent only accepts base type matcher");
1658 DynTypedMatcher ParentMatcher;
1661 explicit HasParentMatcher(
const Matcher<ParentT> &ParentMatcher)
1662 : ParentMatcher(ParentMatcher) {}
1664 bool matches(
const T &Node, ASTMatchFinder *Finder,
1665 BoundNodesTreeBuilder *Builder)
const override {
1666 return Finder->matchesAncestorOf(Node, this->ParentMatcher, Builder,
1667 ASTMatchFinder::AMM_ParentOnly);
1675template <
typename T,
typename AncestorT>
1676class HasAncestorMatcher :
public MatcherInterface<T> {
1677 static_assert(IsBaseType<AncestorT>::value,
1678 "has ancestor only accepts base type matcher");
1680 DynTypedMatcher AncestorMatcher;
1683 explicit HasAncestorMatcher(
const Matcher<AncestorT> &AncestorMatcher)
1684 : AncestorMatcher(AncestorMatcher) {}
1686 bool matches(
const T &Node, ASTMatchFinder *Finder,
1687 BoundNodesTreeBuilder *Builder)
const override {
1688 return Finder->matchesAncestorOf(Node, this->AncestorMatcher, Builder,
1689 ASTMatchFinder::AMM_All);
1699template <
typename T,
typename DescendantT>
1700class ForEachDescendantMatcher :
public MatcherInterface<T> {
1701 static_assert(IsBaseType<DescendantT>::value,
1702 "for each descendant only accepts base type matcher");
1704 DynTypedMatcher DescendantMatcher;
1707 explicit ForEachDescendantMatcher(
1708 const Matcher<DescendantT> &DescendantMatcher)
1709 : DescendantMatcher(DescendantMatcher) {}
1711 bool matches(
const T &Node, ASTMatchFinder *Finder,
1712 BoundNodesTreeBuilder *Builder)
const override {
1713 return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
1714 ASTMatchFinder::BK_All);
1720template <
typename T,
typename ValueT>
1721class ValueEqualsMatcher :
public SingleNodeMatcherInterface<T> {
1722 static_assert(std::is_base_of<CharacterLiteral, T>::value ||
1723 std::is_base_of<CXXBoolLiteralExpr, T>::value ||
1724 std::is_base_of<FloatingLiteral, T>::value ||
1725 std::is_base_of<IntegerLiteral, T>::value ||
1726 std::is_base_of<FixedPointLiteral, T>::value,
1727 "the node must have a getValue method");
1730 explicit ValueEqualsMatcher(
const ValueT &ExpectedValue)
1731 : ExpectedValue(ExpectedValue) {}
1733 bool matchesNode(
const T &Node)
const override {
1734 return Node.getValue() == ExpectedValue;
1738 ValueT ExpectedValue;
1744inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
1745 const FloatingLiteral &Node)
const {
1746 if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1747 return Node.getValue().convertToFloat() == ExpectedValue;
1748 if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1749 return Node.getValue().convertToDouble() == ExpectedValue;
1753inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
1754 const FloatingLiteral &Node)
const {
1755 if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1756 return Node.getValue().convertToFloat() == ExpectedValue;
1757 if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1758 return Node.getValue().convertToDouble() == ExpectedValue;
1762inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
1763 const FloatingLiteral &Node)
const {
1764 return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
1769template <
typename TLoc,
typename T>
1770class LocMatcher :
public MatcherInterface<TLoc> {
1771 DynTypedMatcher InnerMatcher;
1774 explicit LocMatcher(
const Matcher<T> &InnerMatcher)
1775 : InnerMatcher(InnerMatcher) {}
1777 bool matches(
const TLoc &Node, ASTMatchFinder *Finder,
1778 BoundNodesTreeBuilder *Builder)
const override {
1781 return this->InnerMatcher.matches(extract(Node), Finder, Builder);
1785 static DynTypedNode extract(
const NestedNameSpecifierLoc &Loc) {
1786 return DynTypedNode::create(Loc.getNestedNameSpecifier());
1794class TypeLocTypeMatcher :
public MatcherInterface<TypeLoc> {
1795 Matcher<QualType> InnerMatcher;
1798 explicit TypeLocTypeMatcher(
const Matcher<QualType> &InnerMatcher)
1799 : InnerMatcher(InnerMatcher) {}
1801 bool matches(
const TypeLoc &Node, ASTMatchFinder *Finder,
1802 BoundNodesTreeBuilder *Builder)
const override {
1805 return this->InnerMatcher.matches(Node.getType(), Finder, Builder);
1812template <
typename T>
class TypeTraverseMatcher :
public MatcherInterface<T> {
1813 DynTypedMatcher InnerMatcher;
1816 explicit TypeTraverseMatcher(
const Matcher<QualType> &InnerMatcher,
1817 QualType (T::*TraverseFunction)()
const)
1818 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1820 bool matches(
const T &Node, ASTMatchFinder *Finder,
1821 BoundNodesTreeBuilder *Builder)
const override {
1822 QualType NextNode = (Node.*TraverseFunction)();
1823 if (NextNode.isNull())
1825 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1830 QualType (T::*TraverseFunction)()
const;
1836template <
typename T>
1837class TypeLocTraverseMatcher :
public MatcherInterface<T> {
1838 DynTypedMatcher InnerMatcher;
1841 explicit TypeLocTraverseMatcher(
const Matcher<TypeLoc> &InnerMatcher,
1842 TypeLoc (T::*TraverseFunction)()
const)
1843 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1845 bool matches(
const T &Node, ASTMatchFinder *Finder,
1846 BoundNodesTreeBuilder *Builder)
const override {
1847 TypeLoc NextNode = (Node.*TraverseFunction)();
1850 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1855 TypeLoc (T::*TraverseFunction)()
const;
1864template <
typename InnerTBase,
1865 template <
typename OuterT>
class Getter,
1866 template <
typename OuterT>
class MatcherImpl,
1867 typename ReturnTypesF>
1868class TypeTraversePolymorphicMatcher {
1870 using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
1873 static Self create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers);
1876 using ReturnTypes =
typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1878 explicit TypeTraversePolymorphicMatcher(
1879 ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers)
1880 : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
1882 template <
typename OuterT>
operator Matcher<OuterT>()
const {
1883 return Matcher<OuterT>(
1884 new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
1888 :
public VariadicFunction<Self, Matcher<InnerTBase>, &Self::create> {
1893 Matcher<InnerTBase> InnerMatcher;
1900template <
typename Matcher, Matcher (*Func)()>
class MemoizedMatcher {
1902 Wrapper() : M(
Func()) {}
1908 static const Matcher &getInstance() {
1909 static llvm::ManagedStatic<Wrapper> Instance;
1917template <
typename InnerTBase,
template <
typename OuterT>
class Getter,
1918 template <
typename OuterT>
class MatcherImpl,
typename ReturnTypesF>
1919TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
1920TypeTraversePolymorphicMatcher<
1921 InnerTBase, Getter, MatcherImpl,
1922 ReturnTypesF>::create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers) {
1923 return Self(InnerMatchers);
1928inline ArrayRef<TemplateArgument>
1929getTemplateSpecializationArgs(
const ClassTemplateSpecializationDecl &D) {
1930 return D.getTemplateArgs().asArray();
1933inline ArrayRef<TemplateArgument>
1934getTemplateSpecializationArgs(
const VarTemplateSpecializationDecl &D) {
1935 return D.getTemplateArgs().asArray();
1938inline ArrayRef<TemplateArgument>
1939getTemplateSpecializationArgs(
const TemplateSpecializationType &
T) {
1940 return T.template_arguments();
1943inline ArrayRef<TemplateArgument>
1944getTemplateSpecializationArgs(
const FunctionDecl &FD) {
1945 if (
const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
1946 return TemplateArgs->asArray();
1950inline ArrayRef<TemplateArgumentLoc>
1951getTemplateArgsWritten(
const ClassTemplateSpecializationDecl &D) {
1952 if (
const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
1953 return Args->arguments();
1957inline ArrayRef<TemplateArgumentLoc>
1958getTemplateArgsWritten(
const VarTemplateSpecializationDecl &D) {
1959 if (
const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
1960 return Args->arguments();
1964inline ArrayRef<TemplateArgumentLoc>
1965getTemplateArgsWritten(
const FunctionDecl &FD) {
1966 if (
const auto *Args = FD.getTemplateSpecializationArgsAsWritten())
1967 return Args->arguments();
1971inline ArrayRef<TemplateArgumentLoc>
1972getTemplateArgsWritten(
const DeclRefExpr &DRE) {
1973 if (
const auto *Args = DRE.getTemplateArgs())
1974 return {Args, DRE.getNumTemplateArgs()};
1978inline SmallVector<TemplateArgumentLoc>
1979getTemplateArgsWritten(
const TemplateSpecializationTypeLoc &
T) {
1980 SmallVector<TemplateArgumentLoc> Args;
1982 Args.reserve(
T.getNumArgs());
1983 for (
unsigned I = 0; I <
T.getNumArgs(); ++I)
1984 Args.emplace_back(
T.getArgLoc(I));
1989struct NotEqualsBoundNodePredicate {
1990 bool operator()(
const internal::BoundNodesMap &Nodes)
const {
1991 return Nodes.getNode(ID) != Node;
1998template <
typename Ty,
typename Enable =
void>
struct GetBodyMatcher {
1999 static const Stmt *get(
const Ty &Node) {
return Node.getBody(); }
2002template <
typename Ty>
2003struct GetBodyMatcher<
2004 Ty, std::
enable_if_t<std::is_base_of<FunctionDecl, Ty>::value>> {
2005 static const Stmt *get(
const Ty &Node) {
2006 return Node.doesThisDeclarationHaveABody() ? Node.getBody() :
nullptr;
2010template <
typename NodeType>
2011inline std::optional<BinaryOperatorKind>
2012equivalentBinaryOperator(
const NodeType &Node) {
2013 return Node.getOpcode();
2017inline std::optional<BinaryOperatorKind>
2018equivalentBinaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &Node) {
2019 if (Node.getNumArgs() != 2)
2020 return std::nullopt;
2021 switch (Node.getOperator()) {
2023 return std::nullopt;
2038 case OO_GreaterGreater:
2048 case OO_GreaterEqual:
2052 case OO_ExclaimEqual:
2067 return BO_MulAssign;
2069 return BO_DivAssign;
2070 case OO_PercentEqual:
2071 return BO_RemAssign;
2073 return BO_AddAssign;
2075 return BO_SubAssign;
2076 case OO_LessLessEqual:
2077 return BO_ShlAssign;
2078 case OO_GreaterGreaterEqual:
2079 return BO_ShrAssign;
2081 return BO_AndAssign;
2083 return BO_XorAssign;
2091template <
typename NodeType>
2092inline std::optional<UnaryOperatorKind>
2093equivalentUnaryOperator(
const NodeType &Node) {
2094 return Node.getOpcode();
2098inline std::optional<UnaryOperatorKind>
2099equivalentUnaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &Node) {
2100 if (Node.getNumArgs() != 1 && Node.getOperator() != OO_PlusPlus &&
2101 Node.getOperator() != OO_MinusMinus)
2102 return std::nullopt;
2103 switch (Node.getOperator()) {
2105 return std::nullopt;
2119 const auto *FD = Node.getDirectCallee();
2121 return std::nullopt;
2122 return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
2124 case OO_MinusMinus: {
2125 const auto *FD = Node.getDirectCallee();
2127 return std::nullopt;
2128 return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
2135template <
typename NodeType>
inline const Expr *getLHS(
const NodeType &Node) {
2136 return Node.getLHS();
2140getLHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &Node) {
2141 if (!internal::equivalentBinaryOperator(Node))
2143 return Node.getArg(0);
2145template <
typename NodeType>
inline const Expr *getRHS(
const NodeType &Node) {
2146 return Node.getRHS();
2150getRHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &Node) {
2151 if (!internal::equivalentBinaryOperator(Node))
2153 return Node.getArg(1);
2155template <
typename NodeType>
2156inline const Expr *getSubExpr(
const NodeType &Node) {
2157 return Node.getSubExpr();
2161getSubExpr<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &Node) {
2162 if (!internal::equivalentUnaryOperator(Node) &&
2163 Node.getOperator() != OO_Arrow) {
2166 return Node.getArg(0);
2169template <
typename Ty>
2170struct HasSizeMatcher {
2171 static bool hasSize(
const Ty &Node,
unsigned int N) {
2172 return Node.getSize() == N;
2177inline bool HasSizeMatcher<StringLiteral>::hasSize(
2178 const StringLiteral &Node,
unsigned int N) {
2179 return Node.getLength() == N;
2182template <
typename Ty>
2183struct GetSourceExpressionMatcher {
2184 static const Expr *get(
const Ty &Node) {
2185 return Node.getSubExpr();
2190inline const Expr *GetSourceExpressionMatcher<OpaqueValueExpr>::get(
2191 const OpaqueValueExpr &Node) {
2192 return Node.getSourceExpr();
2195template <
typename Ty>
2196struct CompoundStmtMatcher {
2204CompoundStmtMatcher<StmtExpr>::get(
const StmtExpr &Node) {
2205 return Node.getSubStmt();
2214 const ASTContext &Context);
2216inline std::optional<StringRef> getOpName(
const UnaryOperator &Node) {
2217 return Node.getOpcodeStr(Node.getOpcode());
2219inline std::optional<StringRef> getOpName(
const BinaryOperator &Node) {
2220 return Node.getOpcodeStr();
2222inline StringRef getOpName(
const CXXRewrittenBinaryOperator &Node) {
2223 return Node.getOpcodeStr();
2225inline std::optional<StringRef> getOpName(
const CXXOperatorCallExpr &Node) {
2228 return std::nullopt;
2230inline StringRef getOpName(
const CXXFoldExpr &Node) {
2238template <
typename T,
typename ArgT = std::vector<std::
string>>
2239class HasAnyOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
2240 static_assert(std::is_same<T, BinaryOperator>::value ||
2241 std::is_same<T, CXXOperatorCallExpr>::value ||
2242 std::is_same<T, CXXRewrittenBinaryOperator>::value ||
2243 std::is_same<T, UnaryOperator>::value,
2244 "Matcher only supports `BinaryOperator`, `UnaryOperator`, "
2245 "`CXXOperatorCallExpr` and `CXXRewrittenBinaryOperator`");
2246 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
2247 "Matcher ArgT must be std::vector<std::string>");
2250 explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names)
2251 : SingleNodeMatcherInterface<
T>(), Names(std::move(Names)) {}
2253 bool matchesNode(
const T &Node)
const override {
2254 std::optional<StringRef> OptOpName = getOpName(Node);
2255 return OptOpName && llvm::is_contained(Names, *OptOpName);
2259 static std::optional<StringRef> getOpName(
const UnaryOperator &Node) {
2260 return Node.getOpcodeStr(Node.getOpcode());
2262 static std::optional<StringRef> getOpName(
const BinaryOperator &Node) {
2263 return Node.getOpcodeStr();
2265 static StringRef getOpName(
const CXXRewrittenBinaryOperator &Node) {
2266 return Node.getOpcodeStr();
2268 static std::optional<StringRef> getOpName(
const CXXOperatorCallExpr &Node) {
2271 return std::nullopt;
2274 std::vector<std::string> Names;
2277using HasOpNameMatcher =
2278 PolymorphicMatcher<HasAnyOperatorNameMatcher,
2280 TypeList<BinaryOperator, CXXOperatorCallExpr,
2281 CXXRewrittenBinaryOperator, UnaryOperator>),
2282 std::vector<std::string>>;
2286using HasOverloadOpNameMatcher =
2287 PolymorphicMatcher<HasOverloadedOperatorNameMatcher,
2288 void(TypeList<CXXOperatorCallExpr, FunctionDecl>),
2289 std::vector<std::string>>;
2291HasOverloadOpNameMatcher
2298 const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
2299 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder);
2302 llvm::Regex::RegexFlags Flags,
2303 StringRef MatcherID);
2306MatchTemplateArgLocAt(
const DeclRefExpr &Node,
unsigned int Index,
2307 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2308 internal::ASTMatchFinder *Finder,
2309 internal::BoundNodesTreeBuilder *Builder) {
2310 llvm::ArrayRef<TemplateArgumentLoc> ArgLocs = Node.template_arguments();
2311 return Index < ArgLocs.size() &&
2312 InnerMatcher.matches(ArgLocs[Index], Finder, Builder);
2316MatchTemplateArgLocAt(
const TemplateSpecializationTypeLoc &Node,
2318 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2319 internal::ASTMatchFinder *Finder,
2320 internal::BoundNodesTreeBuilder *Builder) {
2321 return !Node.isNull() && Index < Node.getNumArgs() &&
2322 InnerMatcher.matches(Node.getArgLoc(Index), Finder, Builder);
2325inline std::string getDependentName(
const DependentScopeDeclRefExpr &node) {
2326 return node.getDeclName().getAsString();
2329inline std::string getDependentName(
const DependentNameType &node) {
2330 return node.getIdentifier()->getName().str();
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines an enumeration for C++ overloaded operators.
static Expected< DynTypedNode > getNode(const ast_matchers::BoundNodes &Nodes, StringRef ID)
static QualType getUnderlyingType(const SubRegion *R)
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
static constexpr ASTNodeKind getFromNodeKind()
Construct an identifier for T.
StringRef getOpcodeStr() const
Maps string IDs to AST nodes matched by parts of a matcher.
HasOverloadOpNameMatcher hasAnyOverloadedOperatorNameFunc(ArrayRef< const StringRef * > NameRefs)
std::shared_ptr< llvm::Regex > createAndVerifyRegex(StringRef Regex, llvm::Regex::RegexFlags Flags, StringRef MatcherID)
Matcher< ObjCMessageExpr > hasAnySelectorFunc(ArrayRef< const StringRef * > NameRefs)
Matcher< NamedDecl > hasAnyNameFunc(ArrayRef< const StringRef * > NameRefs)
HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef< const StringRef * > NameRefs)
std::optional< SourceLocation > getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc, const ASTContext &Context)
bool matchesAnyBase(const CXXRecordDecl &Node, const Matcher< CXXBaseSpecifier > &BaseSpecMatcher, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder)
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
DynTypedNode DynTypedNode
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions &DiagOpts, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
bool matches(const til::SExpr *E1, const til::SExpr *E2)
The JSON file list parser is used to communicate input to InstallAPI.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
TraversalKind
Defines how we descend a level in the AST when we pass through expressions.
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ Type
The name was classified as a type.
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword.
@ Other
Other implicit parameter.
typename enable_if< B, T >::Type enable_if_t