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"
79namespace ast_matchers {
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(std::nullopt); }
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();
167 std::enable_if_t<TypeListContainsSuperOf<
168 TypeList<CXXBaseSpecifier, CXXCtorInitializer,
169 CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr,
170 CompoundLiteralExpr, DeclaratorDecl, ObjCPropertyDecl,
171 TemplateArgumentLoc, TypedefNameDecl>,
172 T>::value> * =
nullptr>
173inline TypeSourceInfo *GetTypeSourceInfo(
const T &
Node) {
174 return Node.getTypeSourceInfo();
177 std::enable_if_t<TypeListContainsSuperOf<
178 TypeList<CXXFunctionalCastExpr, ExplicitCastExpr>, T>::value> * =
180inline TypeSourceInfo *GetTypeSourceInfo(
const T &
Node) {
181 return Node.getTypeInfoAsWritten();
183inline TypeSourceInfo *GetTypeSourceInfo(
const BlockDecl &
Node) {
184 return Node.getSignatureAsWritten();
186inline TypeSourceInfo *GetTypeSourceInfo(
const CXXNewExpr &
Node) {
187 return Node.getAllocatedTypeSourceInfo();
189inline TypeSourceInfo *
190GetTypeSourceInfo(
const ClassTemplateSpecializationDecl &
Node) {
191 return Node.getTypeAsWritten();
196inline const FunctionProtoType *
197getFunctionProtoType(
const FunctionProtoType &
Node) {
201inline const FunctionProtoType *getFunctionProtoType(
const FunctionDecl &
Node) {
202 return Node.getType()->getAs<FunctionProtoType>();
207 return Node.getAccess();
211 return Node.getAccessSpecifier();
220 void addNode(StringRef
ID,
const DynTypedNode &DynNode) {
221 NodeMap[std::string(
ID)] = DynNode;
228 template <
typename T>
229 const T *getNodeAs(StringRef
ID)
const {
230 IDToNodeMap::const_iterator It = NodeMap.find(
ID);
231 if (It == NodeMap.end()) {
234 return It->second.get<T>();
238 IDToNodeMap::const_iterator It = NodeMap.find(
ID);
239 if (It == NodeMap.end()) {
246 bool operator<(
const BoundNodesMap &Other)
const {
247 return NodeMap <
Other.NodeMap;
255 using IDToNodeMap = std::map<std::string, DynTypedNode, std::less<>>;
257 const IDToNodeMap &getMap()
const {
263 bool isComparable()
const {
264 for (
const auto &IDAndNode : NodeMap) {
265 if (!IDAndNode.second.getMemoizationData())
279class BoundNodesTreeBuilder {
285 virtual ~Visitor() =
default;
290 virtual void visitMatch(
const BoundNodes& BoundNodesView) = 0;
294 void setBinding(StringRef
Id,
const DynTypedNode &DynNode) {
297 for (BoundNodesMap &Binding :
Bindings)
298 Binding.addNode(
Id, DynNode);
302 void addMatch(
const BoundNodesTreeBuilder &
Bindings);
307 void visitMatches(Visitor* ResultVisitor);
309 template <
typename ExcludePredicate>
310 bool removeBindings(
const ExcludePredicate &Predicate) {
311 llvm::erase_if(
Bindings, Predicate);
316 bool operator<(
const BoundNodesTreeBuilder &Other)
const {
322 bool isComparable()
const {
323 for (
const BoundNodesMap &NodesMap :
Bindings) {
324 if (!NodesMap.isComparable())
331 SmallVector<BoundNodesMap, 1>
Bindings;
341class DynMatcherInterface
342 :
public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
344 virtual ~DynMatcherInterface() =
default;
350 virtual bool dynMatches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
351 BoundNodesTreeBuilder *Builder)
const = 0;
353 virtual std::optional<clang::TraversalKind>
TraversalKind()
const {
366class MatcherInterface :
public DynMatcherInterface {
373 ASTMatchFinder *Finder,
374 BoundNodesTreeBuilder *Builder)
const = 0;
376 bool dynMatches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
377 BoundNodesTreeBuilder *Builder)
const override {
378 return matches(DynNode.getUnchecked<T>(), Finder, Builder);
385class SingleNodeMatcherInterface :
public MatcherInterface<T> {
390 virtual bool matchesNode(
const T &
Node)
const = 0;
396 BoundNodesTreeBuilder * )
const override {
397 return matchesNode(
Node);
401template <
typename>
class Matcher;
410class DynTypedMatcher {
413 template <
typename T>
414 DynTypedMatcher(MatcherInterface<T> *Implementation)
415 : SupportedKind(ASTNodeKind::getFromNodeKind<T>()),
416 RestrictKind(SupportedKind), Implementation(Implementation) {}
419 enum VariadicOperator {
442 static DynTypedMatcher
443 constructVariadic(VariadicOperator Op, ASTNodeKind SupportedKind,
444 std::vector<DynTypedMatcher> InnerMatchers);
446 static DynTypedMatcher
447 constructRestrictedWrapper(
const DynTypedMatcher &InnerMatcher,
448 ASTNodeKind RestrictKind);
453 static DynTypedMatcher trueMatcher(ASTNodeKind NodeKind);
455 void setAllowBind(
bool AB) { AllowBind = AB; }
460 bool canMatchNodesOfKind(ASTNodeKind Kind)
const;
464 DynTypedMatcher dynCastTo(
const ASTNodeKind Kind)
const;
470 DynTypedMatcher withTraversalKind(TraversalKind TK);
473 bool matches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
474 BoundNodesTreeBuilder *Builder)
const;
480 bool matchesNoKindCheck(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
481 BoundNodesTreeBuilder *Builder)
const;
486 std::optional<DynTypedMatcher> tryBind(StringRef
ID)
const;
495 using MatcherIDType = std::pair<ASTNodeKind, uint64_t>;
496 MatcherIDType getID()
const {
499 return std::make_pair(RestrictKind,
500 reinterpret_cast<uint64_t>(Implementation.get()));
507 ASTNodeKind getSupportedKind()
const {
return SupportedKind; }
514 template <
typename T>
bool canConvertTo()
const {
515 return canConvertTo(ASTNodeKind::getFromNodeKind<T>());
517 bool canConvertTo(ASTNodeKind To)
const;
524 template <
typename T> Matcher<T> convertTo()
const {
525 assert(canConvertTo<T>());
526 return unconditionalConvertTo<T>();
533 template <
typename T> Matcher<T> unconditionalConvertTo()
const;
539 std::optional<clang::TraversalKind> getTraversalKind()
const {
540 return Implementation->TraversalKind();
544 DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind,
545 IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
546 : SupportedKind(SupportedKind), RestrictKind(RestrictKind),
547 Implementation(
std::move(Implementation)) {}
549 bool AllowBind =
false;
550 ASTNodeKind SupportedKind;
556 ASTNodeKind RestrictKind;
557 IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
572 explicit Matcher(MatcherInterface<T> *Implementation)
573 : Implementation(Implementation) {}
578 template <
typename From>
579 Matcher(
const Matcher<From> &Other,
580 std::enable_if_t<std::is_base_of<From, T>::value &&
581 !std::is_same<From, T>::value> * =
nullptr)
582 : Implementation(restrictMatcher(
Other.Implementation)) {
583 assert(Implementation.getSupportedKind().isSame(
584 ASTNodeKind::getFromNodeKind<T>()));
590 template <
typename TypeT>
591 Matcher(
const Matcher<TypeT> &Other,
592 std::enable_if_t<std::is_same<T, QualType>::value &&
593 std::is_same<TypeT, Type>::value> * =
nullptr)
594 : Implementation(new TypeToQualType<TypeT>(
Other)) {}
599 template <
typename To> Matcher<To> dynCastTo() const & {
600 static_assert(std::is_base_of<To, T>::value,
"Invalid dynCast call.");
601 return Matcher<To>(Implementation);
604 template <
typename To> Matcher<To> dynCastTo() && {
605 static_assert(std::is_base_of<To, T>::value,
"Invalid dynCast call.");
606 return Matcher<To>(std::move(Implementation));
611 ASTMatchFinder *Finder,
612 BoundNodesTreeBuilder *Builder)
const {
613 return Implementation.matches(DynTypedNode::create(
Node), Finder, Builder);
617 DynTypedMatcher::MatcherIDType getID()
const {
618 return Implementation.getID();
625 operator DynTypedMatcher() const & {
return Implementation; }
627 operator DynTypedMatcher() && {
return std::move(Implementation); }
635 template <
typename TypeT>
636 class TypeToQualType :
public MatcherInterface<QualType> {
637 const DynTypedMatcher InnerMatcher;
640 TypeToQualType(
const Matcher<TypeT> &InnerMatcher)
641 : InnerMatcher(InnerMatcher) {}
643 bool matches(
const QualType &
Node, ASTMatchFinder *Finder,
644 BoundNodesTreeBuilder *Builder)
const override {
647 return this->InnerMatcher.matches(DynTypedNode::create(*
Node), Finder,
651 std::optional<clang::TraversalKind>
TraversalKind()
const override {
652 return this->InnerMatcher.getTraversalKind();
658 template <
typename U>
friend class Matcher;
661 friend class DynTypedMatcher;
663 static DynTypedMatcher restrictMatcher(
const DynTypedMatcher &Other) {
664 return Other.dynCastTo(ASTNodeKind::getFromNodeKind<T>());
667 explicit Matcher(
const DynTypedMatcher &Implementation)
668 : Implementation(restrictMatcher(Implementation)) {
669 assert(this->Implementation.getSupportedKind().isSame(
670 ASTNodeKind::getFromNodeKind<T>()));
673 DynTypedMatcher Implementation;
679inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
680 return Matcher<T>(Implementation);
701class ASTMatchFinder {
713 enum AncestorMatchMode {
721 virtual ~ASTMatchFinder() =
default;
727 virtual bool classIsDerivedFrom(
const CXXRecordDecl *Declaration,
728 const Matcher<NamedDecl> &
Base,
729 BoundNodesTreeBuilder *Builder,
736 virtual bool objcClassIsDerivedFrom(
const ObjCInterfaceDecl *Declaration,
737 const Matcher<NamedDecl> &
Base,
738 BoundNodesTreeBuilder *Builder,
741 template <
typename T>
742 bool matchesChildOf(
const T &
Node,
const DynTypedMatcher &Matcher,
743 BoundNodesTreeBuilder *Builder, BindKind Bind) {
744 static_assert(std::is_base_of<Decl, T>::value ||
745 std::is_base_of<Stmt, T>::value ||
746 std::is_base_of<NestedNameSpecifier, T>::value ||
747 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
748 std::is_base_of<TypeLoc, T>::value ||
749 std::is_base_of<QualType, T>::value ||
750 std::is_base_of<Attr, T>::value,
751 "unsupported type for recursive matching");
752 return matchesChildOf(DynTypedNode::create(
Node), getASTContext(), Matcher,
756 template <
typename T>
757 bool matchesDescendantOf(
const T &
Node,
const DynTypedMatcher &Matcher,
758 BoundNodesTreeBuilder *Builder, BindKind Bind) {
759 static_assert(std::is_base_of<Decl, T>::value ||
760 std::is_base_of<Stmt, T>::value ||
761 std::is_base_of<NestedNameSpecifier, T>::value ||
762 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
763 std::is_base_of<TypeLoc, T>::value ||
764 std::is_base_of<QualType, T>::value ||
765 std::is_base_of<Attr, T>::value,
766 "unsupported type for recursive matching");
767 return matchesDescendantOf(DynTypedNode::create(
Node), getASTContext(),
768 Matcher, Builder, Bind);
772 template <
typename T>
773 bool matchesAncestorOf(
const T &
Node,
const DynTypedMatcher &Matcher,
774 BoundNodesTreeBuilder *Builder,
775 AncestorMatchMode MatchMode) {
776 static_assert(std::is_base_of<Decl, T>::value ||
777 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
778 std::is_base_of<Stmt, T>::value ||
779 std::is_base_of<TypeLoc, T>::value ||
780 std::is_base_of<Attr, T>::value,
781 "type not allowed for recursive matching");
782 return matchesAncestorOf(DynTypedNode::create(
Node), getASTContext(),
783 Matcher, Builder, MatchMode);
786 virtual ASTContext &getASTContext()
const = 0;
788 virtual bool IsMatchingInASTNodeNotSpelledInSource()
const = 0;
790 virtual bool IsMatchingInASTNodeNotAsIs()
const = 0;
792 bool isTraversalIgnoringImplicitNodes()
const;
795 virtual bool matchesChildOf(
const DynTypedNode &
Node, ASTContext &Ctx,
796 const DynTypedMatcher &Matcher,
797 BoundNodesTreeBuilder *Builder,
800 virtual bool matchesDescendantOf(
const DynTypedNode &
Node, ASTContext &Ctx,
801 const DynTypedMatcher &Matcher,
802 BoundNodesTreeBuilder *Builder,
805 virtual bool matchesAncestorOf(
const DynTypedNode &
Node, ASTContext &Ctx,
806 const DynTypedMatcher &Matcher,
807 BoundNodesTreeBuilder *Builder,
808 AncestorMatchMode MatchMode) = 0;
810 friend struct ASTChildrenNotSpelledInSourceScope;
811 virtual bool isMatchingChildrenNotSpelledInSource()
const = 0;
812 virtual void setMatchingChildrenNotSpelledInSource(
bool Set) = 0;
815struct ASTChildrenNotSpelledInSourceScope {
816 ASTChildrenNotSpelledInSourceScope(ASTMatchFinder *
V,
bool B)
817 : MV(
V), MB(
V->isMatchingChildrenNotSpelledInSource()) {
818 V->setMatchingChildrenNotSpelledInSource(B);
820 ~ASTChildrenNotSpelledInSourceScope() {
821 MV->setMatchingChildrenNotSpelledInSource(MB);
834inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>()
const {
835 assert(canConvertTo<QualType>());
836 const ASTNodeKind SourceKind = getSupportedKind();
837 if (SourceKind.isSame(ASTNodeKind::getFromNodeKind<Type>())) {
839 return unconditionalConvertTo<Type>();
841 return unconditionalConvertTo<QualType>();
845template <
typename MatcherT,
typename IteratorT>
846IteratorT matchesFirstInRange(
const MatcherT &Matcher, IteratorT Start,
847 IteratorT End, ASTMatchFinder *Finder,
848 BoundNodesTreeBuilder *Builder) {
849 for (IteratorT I = Start; I != End; ++I) {
850 BoundNodesTreeBuilder
Result(*Builder);
851 if (Matcher.matches(*I, Finder, &
Result)) {
852 *Builder = std::move(
Result);
861template <
typename MatcherT,
typename IteratorT>
862IteratorT matchesFirstInPointerRange(
const MatcherT &Matcher, IteratorT Start,
863 IteratorT End, ASTMatchFinder *Finder,
864 BoundNodesTreeBuilder *Builder) {
865 for (IteratorT I = Start; I != End; ++I) {
866 BoundNodesTreeBuilder
Result(*Builder);
867 if (Matcher.matches(**I, Finder, &
Result)) {
868 *Builder = std::move(
Result);
875template <typename T, std::enable_if_t<!std::is_base_of<FunctionDecl, T>::value>
877inline bool isDefaultedHelper(
const T *) {
880inline bool isDefaultedHelper(
const FunctionDecl *FD) {
881 return FD->isDefaulted();
885template <
typename Ty>
890 template <
typename Inner>
891 static yes& test(Inner *I,
decltype(I->getDecl()) * =
nullptr);
894 static no& test(...);
897 static const bool value =
sizeof(test<Ty>(
nullptr)) ==
sizeof(yes);
904template <
typename T,
typename ArgT>
905class HasOverloadedOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
906 static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
907 std::is_base_of<FunctionDecl, T>::value,
908 "unsupported class for matcher");
909 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
910 "argument type must be std::vector<std::string>");
913 explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names)
914 : SingleNodeMatcherInterface<T>(), Names(
std::move(Names)) {}
916 bool matchesNode(
const T &
Node)
const override {
917 return matchesSpecialized(
Node);
925 bool matchesSpecialized(
const CXXOperatorCallExpr &
Node)
const {
931 bool matchesSpecialized(
const FunctionDecl &
Node)
const {
932 return Node.isOverloadedOperator() &&
937 std::vector<std::string> Names;
943class HasNameMatcher :
public SingleNodeMatcherInterface<NamedDecl> {
945 explicit HasNameMatcher(std::vector<std::string> Names);
947 bool matchesNode(
const NamedDecl &
Node)
const override;
954 bool matchesNodeUnqualified(
const NamedDecl &
Node)
const;
962 bool matchesNodeFullFast(
const NamedDecl &
Node)
const;
969 bool matchesNodeFullSlow(
const NamedDecl &
Node)
const;
971 bool UseUnqualifiedMatch;
972 std::vector<std::string> Names;
977Matcher<NamedDecl>
hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs);
982 ArrayRef<const StringRef *> NameRefs);
988template <
typename T,
typename DeclMatcherT>
989class HasDeclarationMatcher :
public MatcherInterface<T> {
990 static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
991 "instantiated with wrong types");
993 DynTypedMatcher InnerMatcher;
996 explicit HasDeclarationMatcher(
const Matcher<Decl> &InnerMatcher)
997 : InnerMatcher(InnerMatcher) {}
999 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1000 BoundNodesTreeBuilder *Builder)
const override {
1001 return matchesSpecialized(
Node, Finder, Builder);
1006 bool matchesSpecialized(
const QualType &
Node, ASTMatchFinder *Finder,
1007 BoundNodesTreeBuilder *Builder)
const {
1011 return matchesSpecialized(*
Node, Finder, Builder);
1016 bool matchesSpecialized(
const Type &
Node, ASTMatchFinder *Finder,
1017 BoundNodesTreeBuilder *Builder)
const {
1020 if (
const auto *S = dyn_cast<DeducedType>(&
Node)) {
1021 QualType DT = S->getDeducedType();
1022 return !DT.isNull() ? matchesSpecialized(*DT, Finder, Builder) :
false;
1027 if (
const auto *S = dyn_cast<TagType>(&
Node)) {
1028 return matchesDecl(S->getDecl(), Finder, Builder);
1030 if (
const auto *S = dyn_cast<InjectedClassNameType>(&
Node)) {
1031 return matchesDecl(S->getDecl(), Finder, Builder);
1033 if (
const auto *S = dyn_cast<TemplateTypeParmType>(&
Node)) {
1034 return matchesDecl(S->getDecl(), Finder, Builder);
1036 if (
const auto *S = dyn_cast<TypedefType>(&
Node)) {
1037 return matchesDecl(S->getDecl(), Finder, Builder);
1039 if (
const auto *S = dyn_cast<UnresolvedUsingType>(&
Node)) {
1040 return matchesDecl(S->getDecl(), Finder, Builder);
1042 if (
const auto *S = dyn_cast<ObjCObjectType>(&
Node)) {
1043 return matchesDecl(S->getInterface(), Finder, Builder);
1054 if (
const auto *S = dyn_cast<SubstTemplateTypeParmType>(&
Node)) {
1055 return matchesSpecialized(S->getReplacementType(), Finder, Builder);
1061 if (
const auto *S = dyn_cast<TemplateSpecializationType>(&
Node)) {
1062 if (!S->isTypeAlias() && S->isSugared()) {
1069 return matchesSpecialized(*S->desugar(), Finder, Builder);
1073 return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder,
1080 if (
const auto *S = dyn_cast<ElaboratedType>(&
Node)) {
1081 return matchesSpecialized(S->desugar(), Finder, Builder);
1086 if (
const auto *S = dyn_cast<UsingType>(&
Node)) {
1087 return matchesSpecialized(S->desugar(), Finder, Builder);
1094 bool matchesSpecialized(
const DeclRefExpr &
Node, ASTMatchFinder *Finder,
1095 BoundNodesTreeBuilder *Builder)
const {
1096 return matchesDecl(
Node.getDecl(), Finder, Builder);
1101 bool matchesSpecialized(
const CallExpr &
Node, ASTMatchFinder *Finder,
1102 BoundNodesTreeBuilder *Builder)
const {
1103 return matchesDecl(
Node.getCalleeDecl(), Finder, Builder);
1108 bool matchesSpecialized(
const CXXConstructExpr &
Node,
1109 ASTMatchFinder *Finder,
1110 BoundNodesTreeBuilder *Builder)
const {
1111 return matchesDecl(
Node.getConstructor(), Finder, Builder);
1114 bool matchesSpecialized(
const ObjCIvarRefExpr &
Node,
1115 ASTMatchFinder *Finder,
1116 BoundNodesTreeBuilder *Builder)
const {
1117 return matchesDecl(
Node.getDecl(), Finder, Builder);
1122 bool matchesSpecialized(
const CXXNewExpr &
Node,
1123 ASTMatchFinder *Finder,
1124 BoundNodesTreeBuilder *Builder)
const {
1125 return matchesDecl(
Node.getOperatorNew(), Finder, Builder);
1130 bool matchesSpecialized(
const MemberExpr &
Node,
1131 ASTMatchFinder *Finder,
1132 BoundNodesTreeBuilder *Builder)
const {
1133 return matchesDecl(
Node.getMemberDecl(), Finder, Builder);
1138 bool matchesSpecialized(
const AddrLabelExpr &
Node,
1139 ASTMatchFinder *Finder,
1140 BoundNodesTreeBuilder *Builder)
const {
1141 return matchesDecl(
Node.getLabel(), Finder, Builder);
1146 bool matchesSpecialized(
const LabelStmt &
Node, ASTMatchFinder *Finder,
1147 BoundNodesTreeBuilder *Builder)
const {
1148 return matchesDecl(
Node.getDecl(), Finder, Builder);
1153 bool matchesDecl(
const Decl *
Node, ASTMatchFinder *Finder,
1154 BoundNodesTreeBuilder *Builder)
const {
1155 return Node !=
nullptr &&
1156 !(Finder->isTraversalIgnoringImplicitNodes() &&
1157 Node->isImplicit()) &&
1158 this->InnerMatcher.matches(DynTypedNode::create(*
Node), Finder,
1165template <
typename T>
1167 static const bool value =
1168 std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value ||
1169 std::is_same<T, QualType>::value || std::is_same<T, Type>::value ||
1170 std::is_same<T, TypeLoc>::value ||
1171 std::is_same<T, NestedNameSpecifier>::value ||
1172 std::is_same<T, NestedNameSpecifierLoc>::value ||
1173 std::is_same<T, CXXCtorInitializer>::value ||
1174 std::is_same<T, TemplateArgumentLoc>::value ||
1175 std::is_same<T, Attr>::value;
1177template <
typename T>
1178const bool IsBaseType<T>::value;
1183using AllNodeBaseTypes =
1184 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
1185 Type, TypeLoc, CXXCtorInitializer, Attr>;
1191template <
class T>
struct ExtractFunctionArgMeta;
1192template <
class T>
struct ExtractFunctionArgMeta<void(T)> {
1196template <
class T,
class Tuple, std::size_t... I>
1197constexpr T *new_from_tuple_impl(Tuple &&t, std::index_sequence<I...>) {
1198 return new T(std::get<I>(std::forward<Tuple>(t))...);
1201template <
class T,
class Tuple>
constexpr T *new_from_tuple(Tuple &&t) {
1202 return new_from_tuple_impl<T>(
1203 std::forward<Tuple>(t),
1204 std::make_index_sequence<
1205 std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
1209using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
1210using AdaptativeDefaultToTypes =
1211 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
1215using HasDeclarationSupportedTypes =
1216 TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
1217 ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
1218 MemberExpr, QualType, RecordType, TagType,
1219 TemplateSpecializationType, TemplateTypeParmType, TypedefType,
1220 UnresolvedUsingType, ObjCIvarRefExpr>;
1226template <
typename T>
class BindableMatcher :
public Matcher<T> {
1228 explicit BindableMatcher(
const Matcher<T> &M) : Matcher<T>(M) {}
1229 explicit BindableMatcher(MatcherInterface<T> *Implementation)
1230 : Matcher<T>(Implementation) {}
1236 Matcher<T> bind(StringRef
ID)
const {
1237 return DynTypedMatcher(*
this)
1239 ->template unconditionalConvertTo<T>();
1244 operator DynTypedMatcher()
const {
1245 DynTypedMatcher Result =
static_cast<const Matcher<T> &
>(*this);
1246 Result.setAllowBind(
true);
1257 using ReturnTypes = AllNodeBaseTypes;
1259 template <
typename T>
operator Matcher<T>()
const {
1260 return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
1261 .template unconditionalConvertTo<T>();
1266template <
typename T>
1268makeAllOfComposite(ArrayRef<
const Matcher<T> *> InnerMatchers) {
1270 if (InnerMatchers.empty()) {
1271 return BindableMatcher<T>(TrueMatcher());
1275 if (InnerMatchers.size() == 1) {
1276 return BindableMatcher<T>(*InnerMatchers[0]);
1279 using PI = llvm::pointee_iterator<const Matcher<T> *
const *>;
1281 std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
1282 PI(InnerMatchers.end()));
1283 return BindableMatcher<T>(
1284 DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
1285 ASTNodeKind::getFromNodeKind<T>(),
1286 std::move(DynMatchers))
1287 .
template unconditionalConvertTo<T>());
1296template <
typename T,
typename InnerT>
1298makeDynCastAllOfComposite(ArrayRef<
const Matcher<InnerT> *> InnerMatchers) {
1299 return BindableMatcher<T>(
1300 makeAllOfComposite(InnerMatchers).
template dynCastTo<T>());
1314template <
typename SourceT,
typename TargetT>
1315class VariadicDynCastAllOfMatcher
1316 :
public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
1317 makeDynCastAllOfComposite<SourceT, TargetT>> {
1319 VariadicDynCastAllOfMatcher() {}
1332template <
typename T>
1333class VariadicAllOfMatcher
1334 :
public VariadicFunction<BindableMatcher<T>, Matcher<T>,
1335 makeAllOfComposite<T>> {
1337 VariadicAllOfMatcher() {}
1349template <
typename... Ps>
class VariadicOperatorMatcher {
1351 VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
1352 : Op(Op), Params(
std::
forward<Ps>(Params)...) {}
1354 template <
typename T>
operator Matcher<T>() const & {
1355 return DynTypedMatcher::constructVariadic(
1356 Op, ASTNodeKind::getFromNodeKind<T>(),
1357 getMatchers<T>(std::index_sequence_for<Ps...>()))
1358 .template unconditionalConvertTo<T>();
1361 template <
typename T>
operator Matcher<T>() && {
1362 return DynTypedMatcher::constructVariadic(
1363 Op, ASTNodeKind::getFromNodeKind<T>(),
1364 getMatchers<T>(std::index_sequence_for<Ps...>()))
1365 .template unconditionalConvertTo<T>();
1370 template <
typename T, std::size_t... Is>
1371 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>)
const & {
1372 return {Matcher<T>(std::get<Is>(Params))...};
1375 template <
typename T, std::size_t... Is>
1376 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) && {
1377 return {Matcher<T>(std::get<Is>(std::move(Params)))...};
1380 const DynTypedMatcher::VariadicOperator Op;
1381 std::tuple<Ps...> Params;
1386template <
unsigned MinCount,
unsigned MaxCount>
1387struct VariadicOperatorMatcherFunc {
1388 DynTypedMatcher::VariadicOperator Op;
1390 template <
typename... Ms>
1391 VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps)
const {
1392 static_assert(MinCount <=
sizeof...(Ms) &&
sizeof...(Ms) <= MaxCount,
1393 "invalid number of parameters for variadic matcher");
1394 return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
1398template <
typename T,
bool IsBaseOf,
typename Head,
typename Tail>
1399struct GetCladeImpl {
1402template <
typename T,
typename Head,
typename Tail>
1403struct GetCladeImpl<T,
false, Head, Tail>
1404 : GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
1405 typename Tail::head, typename Tail::tail> {};
1407template <
typename T,
typename...
U>
1408struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
1410template <
typename CladeType,
typename... MatcherTypes>
1411struct MapAnyOfMatcherImpl {
1413 template <
typename... InnerMatchers>
1414 BindableMatcher<CladeType>
1415 operator()(InnerMatchers &&... InnerMatcher)
const {
1416 return VariadicAllOfMatcher<CladeType>()(std::apply(
1417 internal::VariadicOperatorMatcherFunc<
1418 0, std::numeric_limits<unsigned>::max()>{
1419 internal::DynTypedMatcher::VO_AnyOf},
1421 [&](
auto... Matcher) {
1422 return std::make_tuple(Matcher(InnerMatcher...)...);
1425 VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
1429template <
typename... MatcherTypes>
1430using MapAnyOfMatcher =
1431 MapAnyOfMatcherImpl<
typename GetClade<MatcherTypes...>::Type,
1434template <
typename... MatcherTypes>
struct MapAnyOfHelper {
1435 using CladeType =
typename GetClade<MatcherTypes...>
::Type;
1437 MapAnyOfMatcher<MatcherTypes...> with;
1439 operator BindableMatcher<CladeType>()
const {
return with(); }
1441 Matcher<CladeType> bind(StringRef
ID)
const {
return with().bind(
ID); }
1444template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1445 typename T,
typename ToTypes>
1446class ArgumentAdaptingMatcherFuncAdaptor {
1448 explicit ArgumentAdaptingMatcherFuncAdaptor(
const Matcher<T> &InnerMatcher)
1449 : InnerMatcher(InnerMatcher) {}
1451 using ReturnTypes = ToTypes;
1453 template <
typename To>
operator Matcher<To>() const & {
1454 return Matcher<To>(
new ArgumentAdapterT<To, T>(InnerMatcher));
1457 template <
typename To>
operator Matcher<To>() && {
1458 return Matcher<To>(
new ArgumentAdapterT<To, T>(std::move(InnerMatcher)));
1462 Matcher<T> InnerMatcher;
1478template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1479 typename FromTypes = AdaptativeDefaultFromTypes,
1480 typename ToTypes = AdaptativeDefaultToTypes>
1481struct ArgumentAdaptingMatcherFunc {
1482 template <
typename T>
1483 static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1484 create(
const Matcher<T> &InnerMatcher) {
1485 return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>(
1489 template <
typename T>
1490 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1491 operator()(
const Matcher<T> &InnerMatcher)
const {
1492 return create(InnerMatcher);
1495 template <
typename... T>
1496 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT,
1497 typename GetClade<T...>
::Type, ToTypes>
1498 operator()(
const MapAnyOfHelper<T...> &InnerMatcher)
const {
1499 return create(InnerMatcher.with());
1503template <
typename T>
class TraversalMatcher :
public MatcherInterface<T> {
1504 DynTypedMatcher InnerMatcher;
1509 const Matcher<T> &InnerMatcher)
1510 : InnerMatcher(InnerMatcher),
Traversal(TK) {}
1512 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1513 BoundNodesTreeBuilder *Builder)
const override {
1514 return this->InnerMatcher.matches(DynTypedNode::create(
Node), Finder,
1518 std::optional<clang::TraversalKind>
TraversalKind()
const override {
1519 if (
auto NestedKind = this->InnerMatcher.getTraversalKind())
1525template <
typename MatcherType>
class TraversalWrapper {
1527 TraversalWrapper(TraversalKind TK,
const MatcherType &InnerMatcher)
1528 : TK(TK), InnerMatcher(InnerMatcher) {}
1530 template <
typename T>
operator Matcher<T>() const & {
1531 return internal::DynTypedMatcher::constructRestrictedWrapper(
1532 new internal::TraversalMatcher<T>(TK, InnerMatcher),
1533 ASTNodeKind::getFromNodeKind<T>())
1534 .template unconditionalConvertTo<T>();
1537 template <
typename T>
operator Matcher<T>() && {
1538 return internal::DynTypedMatcher::constructRestrictedWrapper(
1539 new internal::TraversalMatcher<T>(TK, std::move(InnerMatcher)),
1540 ASTNodeKind::getFromNodeKind<T>())
1541 .template unconditionalConvertTo<T>();
1546 MatcherType InnerMatcher;
1561template <
template <
typename T,
typename... Params>
class MatcherT,
1562 typename ReturnTypesF, typename... ParamTypes>
1563class PolymorphicMatcher {
1565 PolymorphicMatcher(
const ParamTypes &... Params) : Params(Params...) {}
1567 using ReturnTypes =
typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1569 template <
typename T>
operator Matcher<T>() const & {
1570 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1571 "right polymorphic conversion");
1572 return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params));
1575 template <
typename T>
operator Matcher<T>() && {
1576 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1577 "right polymorphic conversion");
1579 new_from_tuple<MatcherT<T, ParamTypes...>>(std::move(Params)));
1583 std::tuple<ParamTypes...> Params;
1590template <
typename T,
typename ChildT>
1591class HasMatcher :
public MatcherInterface<T> {
1592 DynTypedMatcher InnerMatcher;
1595 explicit HasMatcher(
const Matcher<ChildT> &InnerMatcher)
1596 : InnerMatcher(InnerMatcher) {}
1598 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1599 BoundNodesTreeBuilder *Builder)
const override {
1600 return Finder->matchesChildOf(
Node, this->InnerMatcher, Builder,
1601 ASTMatchFinder::BK_First);
1610template <
typename T,
typename ChildT>
1611class ForEachMatcher :
public MatcherInterface<T> {
1612 static_assert(IsBaseType<ChildT>::value,
1613 "for each only accepts base type matcher");
1615 DynTypedMatcher InnerMatcher;
1618 explicit ForEachMatcher(
const Matcher<ChildT> &InnerMatcher)
1619 : InnerMatcher(InnerMatcher) {}
1621 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1622 BoundNodesTreeBuilder *Builder)
const override {
1623 return Finder->matchesChildOf(
1624 Node, this->InnerMatcher, Builder,
1625 ASTMatchFinder::BK_All);
1631template <
typename T>
1632inline Matcher<T> DynTypedMatcher::unconditionalConvertTo()
const {
1633 return Matcher<T>(*
this);
1640template <
typename T,
typename DescendantT>
1641class HasDescendantMatcher :
public MatcherInterface<T> {
1642 static_assert(IsBaseType<DescendantT>::value,
1643 "has descendant only accepts base type matcher");
1645 DynTypedMatcher DescendantMatcher;
1648 explicit HasDescendantMatcher(
const Matcher<DescendantT> &DescendantMatcher)
1649 : DescendantMatcher(DescendantMatcher) {}
1651 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1652 BoundNodesTreeBuilder *Builder)
const override {
1653 return Finder->matchesDescendantOf(
Node, this->DescendantMatcher, Builder,
1654 ASTMatchFinder::BK_First);
1662template <
typename T,
typename ParentT>
1663class HasParentMatcher :
public MatcherInterface<T> {
1664 static_assert(IsBaseType<ParentT>::value,
1665 "has parent only accepts base type matcher");
1667 DynTypedMatcher ParentMatcher;
1670 explicit HasParentMatcher(
const Matcher<ParentT> &ParentMatcher)
1671 : ParentMatcher(ParentMatcher) {}
1673 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1674 BoundNodesTreeBuilder *Builder)
const override {
1675 return Finder->matchesAncestorOf(
Node, this->ParentMatcher, Builder,
1676 ASTMatchFinder::AMM_ParentOnly);
1684template <
typename T,
typename AncestorT>
1685class HasAncestorMatcher :
public MatcherInterface<T> {
1686 static_assert(IsBaseType<AncestorT>::value,
1687 "has ancestor only accepts base type matcher");
1689 DynTypedMatcher AncestorMatcher;
1692 explicit HasAncestorMatcher(
const Matcher<AncestorT> &AncestorMatcher)
1693 : AncestorMatcher(AncestorMatcher) {}
1695 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1696 BoundNodesTreeBuilder *Builder)
const override {
1697 return Finder->matchesAncestorOf(
Node, this->AncestorMatcher, Builder,
1698 ASTMatchFinder::AMM_All);
1708template <
typename T,
typename DescendantT>
1709class ForEachDescendantMatcher :
public MatcherInterface<T> {
1710 static_assert(IsBaseType<DescendantT>::value,
1711 "for each descendant only accepts base type matcher");
1713 DynTypedMatcher DescendantMatcher;
1716 explicit ForEachDescendantMatcher(
1717 const Matcher<DescendantT> &DescendantMatcher)
1718 : DescendantMatcher(DescendantMatcher) {}
1720 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1721 BoundNodesTreeBuilder *Builder)
const override {
1722 return Finder->matchesDescendantOf(
Node, this->DescendantMatcher, Builder,
1723 ASTMatchFinder::BK_All);
1729template <
typename T,
typename ValueT>
1730class ValueEqualsMatcher :
public SingleNodeMatcherInterface<T> {
1731 static_assert(std::is_base_of<CharacterLiteral, T>::value ||
1732 std::is_base_of<CXXBoolLiteralExpr, T>::value ||
1733 std::is_base_of<FloatingLiteral, T>::value ||
1734 std::is_base_of<IntegerLiteral, T>::value,
1735 "the node must have a getValue method");
1738 explicit ValueEqualsMatcher(
const ValueT &ExpectedValue)
1739 : ExpectedValue(ExpectedValue) {}
1741 bool matchesNode(
const T &
Node)
const override {
1742 return Node.getValue() == ExpectedValue;
1746 ValueT ExpectedValue;
1752inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
1753 const FloatingLiteral &
Node)
const {
1754 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1755 return Node.getValue().convertToFloat() == ExpectedValue;
1756 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1757 return Node.getValue().convertToDouble() == ExpectedValue;
1761inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
1762 const FloatingLiteral &
Node)
const {
1763 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1764 return Node.getValue().convertToFloat() == ExpectedValue;
1765 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1766 return Node.getValue().convertToDouble() == ExpectedValue;
1770inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
1771 const FloatingLiteral &
Node)
const {
1772 return ExpectedValue.compare(
Node.getValue()) == llvm::APFloat::cmpEqual;
1777template <
typename TLoc,
typename T>
1778class LocMatcher :
public MatcherInterface<TLoc> {
1779 DynTypedMatcher InnerMatcher;
1782 explicit LocMatcher(
const Matcher<T> &InnerMatcher)
1783 : InnerMatcher(InnerMatcher) {}
1785 bool matches(
const TLoc &
Node, ASTMatchFinder *Finder,
1786 BoundNodesTreeBuilder *Builder)
const override {
1789 return this->InnerMatcher.matches(extract(
Node), Finder, Builder);
1793 static DynTypedNode extract(
const NestedNameSpecifierLoc &Loc) {
1794 return DynTypedNode::create(*Loc.getNestedNameSpecifier());
1802class TypeLocTypeMatcher :
public MatcherInterface<TypeLoc> {
1803 DynTypedMatcher InnerMatcher;
1806 explicit TypeLocTypeMatcher(
const Matcher<QualType> &InnerMatcher)
1807 : InnerMatcher(InnerMatcher) {}
1809 bool matches(
const TypeLoc &
Node, ASTMatchFinder *Finder,
1810 BoundNodesTreeBuilder *Builder)
const override {
1813 return this->InnerMatcher.matches(DynTypedNode::create(
Node.getType()),
1821template <
typename T>
class TypeTraverseMatcher :
public MatcherInterface<T> {
1822 DynTypedMatcher InnerMatcher;
1825 explicit TypeTraverseMatcher(
const Matcher<QualType> &InnerMatcher,
1826 QualType (T::*TraverseFunction)()
const)
1827 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1829 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1830 BoundNodesTreeBuilder *Builder)
const override {
1831 QualType NextNode = (
Node.*TraverseFunction)();
1832 if (NextNode.isNull())
1834 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1839 QualType (T::*TraverseFunction)()
const;
1845template <
typename T>
1846class TypeLocTraverseMatcher :
public MatcherInterface<T> {
1847 DynTypedMatcher InnerMatcher;
1850 explicit TypeLocTraverseMatcher(
const Matcher<TypeLoc> &InnerMatcher,
1851 TypeLoc (T::*TraverseFunction)()
const)
1852 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1854 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1855 BoundNodesTreeBuilder *Builder)
const override {
1856 TypeLoc NextNode = (
Node.*TraverseFunction)();
1859 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1864 TypeLoc (T::*TraverseFunction)()
const;
1873template <
typename InnerTBase,
1874 template <
typename OuterT>
class Getter,
1875 template <
typename OuterT>
class MatcherImpl,
1876 typename ReturnTypesF>
1877class TypeTraversePolymorphicMatcher {
1879 using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
1882 static Self
create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers);
1885 using ReturnTypes =
typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1887 explicit TypeTraversePolymorphicMatcher(
1888 ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers)
1889 : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
1891 template <
typename OuterT>
operator Matcher<OuterT>()
const {
1892 return Matcher<OuterT>(
1893 new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
1897 :
public VariadicFunction<Self, Matcher<InnerTBase>, &Self::create> {
1902 Matcher<InnerTBase> InnerMatcher;
1909template <
typename Matcher, Matcher (*Func)()>
class MemoizedMatcher {
1911 Wrapper() : M(
Func()) {}
1917 static const Matcher &getInstance() {
1918 static llvm::ManagedStatic<Wrapper> Instance;
1926template <
typename InnerTBase,
template <
typename OuterT>
class Getter,
1927 template <
typename OuterT>
class MatcherImpl,
typename ReturnTypesF>
1928TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
1929TypeTraversePolymorphicMatcher<
1930 InnerTBase, Getter, MatcherImpl,
1931 ReturnTypesF>::create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers) {
1932 return Self(InnerMatchers);
1937inline ArrayRef<TemplateArgument>
1938getTemplateSpecializationArgs(
const ClassTemplateSpecializationDecl &D) {
1939 return D.getTemplateArgs().asArray();
1942inline ArrayRef<TemplateArgument>
1943getTemplateSpecializationArgs(
const TemplateSpecializationType &T) {
1944 return T.template_arguments();
1947inline ArrayRef<TemplateArgument>
1948getTemplateSpecializationArgs(
const FunctionDecl &FD) {
1949 if (
const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
1950 return TemplateArgs->asArray();
1951 return ArrayRef<TemplateArgument>();
1954struct NotEqualsBoundNodePredicate {
1955 bool operator()(
const internal::BoundNodesMap &
Nodes)
const {
1963template <
typename Ty,
typename Enable =
void>
struct GetBodyMatcher {
1964 static const Stmt *get(
const Ty &
Node) {
return Node.getBody(); }
1967template <
typename Ty>
1968struct GetBodyMatcher<
1969 Ty,
std::enable_if_t<std::is_base_of<FunctionDecl, Ty>::value>> {
1970 static const Stmt *get(
const Ty &
Node) {
1971 return Node.doesThisDeclarationHaveABody() ?
Node.getBody() :
nullptr;
1975template <
typename NodeType>
1976inline std::optional<BinaryOperatorKind>
1977equivalentBinaryOperator(
const NodeType &
Node) {
1978 return Node.getOpcode();
1982inline std::optional<BinaryOperatorKind>
1983equivalentBinaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
1984 if (
Node.getNumArgs() != 2)
1985 return std::nullopt;
1986 switch (
Node.getOperator()) {
1988 return std::nullopt;
2003 case OO_GreaterGreater:
2013 case OO_GreaterEqual:
2017 case OO_ExclaimEqual:
2032 return BO_MulAssign;
2034 return BO_DivAssign;
2035 case OO_PercentEqual:
2036 return BO_RemAssign;
2038 return BO_AddAssign;
2040 return BO_SubAssign;
2041 case OO_LessLessEqual:
2042 return BO_ShlAssign;
2043 case OO_GreaterGreaterEqual:
2044 return BO_ShrAssign;
2046 return BO_AndAssign;
2048 return BO_XorAssign;
2056template <
typename NodeType>
2057inline std::optional<UnaryOperatorKind>
2058equivalentUnaryOperator(
const NodeType &
Node) {
2059 return Node.getOpcode();
2063inline std::optional<UnaryOperatorKind>
2064equivalentUnaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2065 if (
Node.getNumArgs() != 1 &&
Node.getOperator() != OO_PlusPlus &&
2066 Node.getOperator() != OO_MinusMinus)
2067 return std::nullopt;
2068 switch (
Node.getOperator()) {
2070 return std::nullopt;
2084 const auto *FD =
Node.getDirectCallee();
2086 return std::nullopt;
2087 return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
2089 case OO_MinusMinus: {
2090 const auto *FD =
Node.getDirectCallee();
2092 return std::nullopt;
2093 return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
2100template <
typename NodeType>
inline const Expr *getLHS(
const NodeType &
Node) {
2101 return Node.getLHS();
2105getLHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2106 if (!internal::equivalentBinaryOperator(
Node))
2108 return Node.getArg(0);
2110template <
typename NodeType>
inline const Expr *getRHS(
const NodeType &
Node) {
2111 return Node.getRHS();
2115getRHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2116 if (!internal::equivalentBinaryOperator(
Node))
2118 return Node.getArg(1);
2120template <
typename NodeType>
2121inline const Expr *getSubExpr(
const NodeType &
Node) {
2122 return Node.getSubExpr();
2126getSubExpr<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2127 if (!internal::equivalentUnaryOperator(
Node))
2129 return Node.getArg(0);
2132template <
typename Ty>
2133struct HasSizeMatcher {
2134 static bool hasSize(
const Ty &
Node,
unsigned int N) {
2135 return Node.getSize() == N;
2140inline bool HasSizeMatcher<StringLiteral>::hasSize(
2141 const StringLiteral &
Node,
unsigned int N) {
2142 return Node.getLength() == N;
2145template <
typename Ty>
2146struct GetSourceExpressionMatcher {
2147 static const Expr *get(
const Ty &
Node) {
2148 return Node.getSubExpr();
2153inline const Expr *GetSourceExpressionMatcher<OpaqueValueExpr>::get(
2154 const OpaqueValueExpr &
Node) {
2155 return Node.getSourceExpr();
2158template <
typename Ty>
2159struct CompoundStmtMatcher {
2160 static const CompoundStmt *get(
const Ty &
Node) {
2166inline const CompoundStmt *
2167CompoundStmtMatcher<StmtExpr>::get(
const StmtExpr &
Node) {
2168 return Node.getSubStmt();
2177 const ASTContext &Context);
2179inline std::optional<StringRef> getOpName(
const UnaryOperator &
Node) {
2180 return Node.getOpcodeStr(
Node.getOpcode());
2182inline std::optional<StringRef> getOpName(
const BinaryOperator &
Node) {
2183 return Node.getOpcodeStr();
2185inline StringRef getOpName(
const CXXRewrittenBinaryOperator &
Node) {
2186 return Node.getOpcodeStr();
2188inline std::optional<StringRef> getOpName(
const CXXOperatorCallExpr &
Node) {
2189 auto optBinaryOpcode = equivalentBinaryOperator(
Node);
2190 if (!optBinaryOpcode) {
2191 auto optUnaryOpcode = equivalentUnaryOperator(
Node);
2192 if (!optUnaryOpcode)
2193 return std::nullopt;
2203template <
typename T,
typename ArgT = std::vector<std::
string>>
2204class HasAnyOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
2205 static_assert(std::is_same<T, BinaryOperator>::value ||
2206 std::is_same<T, CXXOperatorCallExpr>::value ||
2207 std::is_same<T, CXXRewrittenBinaryOperator>::value ||
2208 std::is_same<T, UnaryOperator>::value,
2209 "Matcher only supports `BinaryOperator`, `UnaryOperator`, "
2210 "`CXXOperatorCallExpr` and `CXXRewrittenBinaryOperator`");
2211 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
2212 "Matcher ArgT must be std::vector<std::string>");
2215 explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names)
2216 : SingleNodeMatcherInterface<T>(), Names(
std::move(Names)) {}
2218 bool matchesNode(
const T &
Node)
const override {
2219 std::optional<StringRef> OptOpName = getOpName(
Node);
2220 return OptOpName && llvm::is_contained(Names, *OptOpName);
2224 static std::optional<StringRef> getOpName(
const UnaryOperator &
Node) {
2225 return Node.getOpcodeStr(
Node.getOpcode());
2227 static std::optional<StringRef> getOpName(
const BinaryOperator &
Node) {
2228 return Node.getOpcodeStr();
2230 static StringRef getOpName(
const CXXRewrittenBinaryOperator &
Node) {
2231 return Node.getOpcodeStr();
2233 static std::optional<StringRef> getOpName(
const CXXOperatorCallExpr &
Node) {
2234 auto optBinaryOpcode = equivalentBinaryOperator(
Node);
2235 if (!optBinaryOpcode) {
2236 auto optUnaryOpcode = equivalentUnaryOperator(
Node);
2237 if (!optUnaryOpcode)
2238 return std::nullopt;
2239 return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
2241 return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
2244 std::vector<std::string> Names;
2247using HasOpNameMatcher =
2248 PolymorphicMatcher<HasAnyOperatorNameMatcher,
2250 TypeList<BinaryOperator, CXXOperatorCallExpr,
2251 CXXRewrittenBinaryOperator, UnaryOperator>),
2252 std::vector<std::string>>;
2256using HasOverloadOpNameMatcher =
2257 PolymorphicMatcher<HasOverloadedOperatorNameMatcher,
2258 void(TypeList<CXXOperatorCallExpr, FunctionDecl>),
2259 std::vector<std::string>>;
2261HasOverloadOpNameMatcher
2268 const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
2269 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder);
2272 llvm::Regex::RegexFlags Flags,
2276MatchTemplateArgLocAt(
const DeclRefExpr &
Node,
unsigned int Index,
2277 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2278 internal::ASTMatchFinder *Finder,
2279 internal::BoundNodesTreeBuilder *Builder) {
2281 return Index < ArgLocs.size() &&
2282 InnerMatcher.matches(ArgLocs[Index], Finder, Builder);
2286MatchTemplateArgLocAt(
const TemplateSpecializationTypeLoc &
Node,
2288 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2289 internal::ASTMatchFinder *Finder,
2290 internal::BoundNodesTreeBuilder *Builder) {
2291 return !
Node.isNull() && Index <
Node.getNumArgs() &&
2292 InnerMatcher.matches(
Node.getArgLoc(Index), Finder, Builder);
BoundNodesTreeBuilder BoundNodes
BoundNodesTreeBuilder Nodes
DynTypedMatcher::MatcherIDType MatcherID
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.
StringRef getOpcodeStr() const
static StringRef getOpcodeStr(Opcode Op)
getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to,...
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
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::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
bool matches(const til::SExpr *E1, const til::SExpr *E2)
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 char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword.
@ Other
Other implicit parameter.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...