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({}); }
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 {
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;
678inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
679 return Matcher<T>(Implementation);
700class ASTMatchFinder {
712 enum AncestorMatchMode {
720 virtual ~ASTMatchFinder() =
default;
726 virtual bool classIsDerivedFrom(
const CXXRecordDecl *Declaration,
727 const Matcher<NamedDecl> &
Base,
728 BoundNodesTreeBuilder *Builder,
735 virtual bool objcClassIsDerivedFrom(
const ObjCInterfaceDecl *Declaration,
736 const Matcher<NamedDecl> &
Base,
737 BoundNodesTreeBuilder *Builder,
740 template <
typename T>
741 bool matchesChildOf(
const T &
Node,
const DynTypedMatcher &Matcher,
742 BoundNodesTreeBuilder *Builder, BindKind Bind) {
743 static_assert(std::is_base_of<Decl, T>::value ||
744 std::is_base_of<Stmt, T>::value ||
745 std::is_base_of<NestedNameSpecifier, T>::value ||
746 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
747 std::is_base_of<TypeLoc, T>::value ||
748 std::is_base_of<QualType, T>::value ||
749 std::is_base_of<Attr, T>::value,
750 "unsupported type for recursive matching");
751 return matchesChildOf(DynTypedNode::create(
Node), getASTContext(), Matcher,
755 template <
typename T>
756 bool matchesDescendantOf(
const T &
Node,
const DynTypedMatcher &Matcher,
757 BoundNodesTreeBuilder *Builder, BindKind Bind) {
758 static_assert(std::is_base_of<Decl, T>::value ||
759 std::is_base_of<Stmt, T>::value ||
760 std::is_base_of<NestedNameSpecifier, T>::value ||
761 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
762 std::is_base_of<TypeLoc, T>::value ||
763 std::is_base_of<QualType, T>::value ||
764 std::is_base_of<Attr, T>::value,
765 "unsupported type for recursive matching");
766 return matchesDescendantOf(DynTypedNode::create(
Node), getASTContext(),
767 Matcher, Builder, Bind);
771 template <
typename T>
772 bool matchesAncestorOf(
const T &
Node,
const DynTypedMatcher &Matcher,
773 BoundNodesTreeBuilder *Builder,
774 AncestorMatchMode MatchMode) {
775 static_assert(std::is_base_of<Decl, T>::value ||
776 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
777 std::is_base_of<Stmt, T>::value ||
778 std::is_base_of<TypeLoc, T>::value ||
779 std::is_base_of<Attr, T>::value,
780 "type not allowed for recursive matching");
781 return matchesAncestorOf(DynTypedNode::create(
Node), getASTContext(),
782 Matcher, Builder, MatchMode);
785 virtual ASTContext &getASTContext()
const = 0;
787 virtual bool IsMatchingInASTNodeNotSpelledInSource()
const = 0;
789 virtual bool IsMatchingInASTNodeNotAsIs()
const = 0;
791 bool isTraversalIgnoringImplicitNodes()
const;
794 virtual bool matchesChildOf(
const DynTypedNode &
Node, ASTContext &Ctx,
795 const DynTypedMatcher &Matcher,
796 BoundNodesTreeBuilder *Builder,
799 virtual bool matchesDescendantOf(
const DynTypedNode &
Node, ASTContext &Ctx,
800 const DynTypedMatcher &Matcher,
801 BoundNodesTreeBuilder *Builder,
804 virtual bool matchesAncestorOf(
const DynTypedNode &
Node, ASTContext &Ctx,
805 const DynTypedMatcher &Matcher,
806 BoundNodesTreeBuilder *Builder,
807 AncestorMatchMode MatchMode) = 0;
809 friend struct ASTChildrenNotSpelledInSourceScope;
810 virtual bool isMatchingChildrenNotSpelledInSource()
const = 0;
811 virtual void setMatchingChildrenNotSpelledInSource(
bool Set) = 0;
814struct ASTChildrenNotSpelledInSourceScope {
815 ASTChildrenNotSpelledInSourceScope(ASTMatchFinder *
V,
bool B)
816 : MV(
V), MB(
V->isMatchingChildrenNotSpelledInSource()) {
817 V->setMatchingChildrenNotSpelledInSource(B);
819 ~ASTChildrenNotSpelledInSourceScope() {
820 MV->setMatchingChildrenNotSpelledInSource(MB);
833inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>()
const {
834 assert(canConvertTo<QualType>());
835 const ASTNodeKind SourceKind = getSupportedKind();
836 if (SourceKind.isSame(ASTNodeKind::getFromNodeKind<Type>())) {
838 return unconditionalConvertTo<Type>();
840 return unconditionalConvertTo<QualType>();
844template <
typename MatcherT,
typename IteratorT>
845IteratorT matchesFirstInRange(
const MatcherT &Matcher, IteratorT Start,
846 IteratorT End, ASTMatchFinder *Finder,
847 BoundNodesTreeBuilder *Builder) {
848 for (IteratorT I = Start; I != End; ++I) {
849 BoundNodesTreeBuilder
Result(*Builder);
850 if (Matcher.matches(*I, Finder, &
Result)) {
851 *Builder = std::move(
Result);
860template <
typename MatcherT,
typename IteratorT>
861IteratorT matchesFirstInPointerRange(
const MatcherT &Matcher, IteratorT Start,
862 IteratorT End, ASTMatchFinder *Finder,
863 BoundNodesTreeBuilder *Builder) {
864 for (IteratorT I = Start; I != End; ++I) {
865 BoundNodesTreeBuilder
Result(*Builder);
866 if (Matcher.matches(**I, Finder, &
Result)) {
867 *Builder = std::move(
Result);
874template <typename T, std::enable_if_t<!std::is_base_of<FunctionDecl, T>::value>
876inline bool isDefaultedHelper(
const T *) {
879inline bool isDefaultedHelper(
const FunctionDecl *FD) {
880 return FD->isDefaulted();
884template <
typename Ty>
889 template <
typename Inner>
890 static yes& test(Inner *I,
decltype(I->getDecl()) * =
nullptr);
893 static no& test(...);
896 static const bool value =
sizeof(test<Ty>(
nullptr)) ==
sizeof(yes);
903template <
typename T,
typename ArgT>
904class HasOverloadedOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
905 static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
906 std::is_base_of<FunctionDecl, T>::value,
907 "unsupported class for matcher");
908 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
909 "argument type must be std::vector<std::string>");
912 explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names)
913 : SingleNodeMatcherInterface<
T>(), Names(
std::move(Names)) {}
915 bool matchesNode(
const T &
Node)
const override {
916 return matchesSpecialized(
Node);
924 bool matchesSpecialized(
const CXXOperatorCallExpr &
Node)
const {
930 bool matchesSpecialized(
const FunctionDecl &
Node)
const {
931 return Node.isOverloadedOperator() &&
936 std::vector<std::string> Names;
942class HasNameMatcher :
public SingleNodeMatcherInterface<NamedDecl> {
944 explicit HasNameMatcher(std::vector<std::string> Names);
946 bool matchesNode(
const NamedDecl &
Node)
const override;
953 bool matchesNodeUnqualified(
const NamedDecl &
Node)
const;
961 bool matchesNodeFullFast(
const NamedDecl &
Node)
const;
968 bool matchesNodeFullSlow(
const NamedDecl &
Node)
const;
970 bool UseUnqualifiedMatch;
971 std::vector<std::string> Names;
976Matcher<NamedDecl>
hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs);
981 ArrayRef<const StringRef *> NameRefs);
987template <
typename T,
typename DeclMatcherT>
988class HasDeclarationMatcher :
public MatcherInterface<T> {
989 static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
990 "instantiated with wrong types");
992 DynTypedMatcher InnerMatcher;
995 explicit HasDeclarationMatcher(
const Matcher<Decl> &InnerMatcher)
996 : InnerMatcher(InnerMatcher) {}
998 bool matches(
const T &
Node, ASTMatchFinder *Finder,
999 BoundNodesTreeBuilder *Builder)
const override {
1000 return matchesSpecialized(
Node, Finder, Builder);
1005 bool matchesSpecialized(
const QualType &
Node, ASTMatchFinder *Finder,
1006 BoundNodesTreeBuilder *Builder)
const {
1010 return matchesSpecialized(*
Node, Finder, Builder);
1015 bool matchesSpecialized(
const Type &
Node, ASTMatchFinder *Finder,
1016 BoundNodesTreeBuilder *Builder)
const {
1019 if (
const auto *S = dyn_cast<DeducedType>(&
Node)) {
1020 QualType DT = S->getDeducedType();
1021 return !DT.isNull() ? matchesSpecialized(*DT, Finder, Builder) :
false;
1026 if (
const auto *S = dyn_cast<TagType>(&
Node)) {
1027 return matchesDecl(S->getDecl(), Finder, Builder);
1029 if (
const auto *S = dyn_cast<InjectedClassNameType>(&
Node)) {
1030 return matchesDecl(S->getDecl(), Finder, Builder);
1032 if (
const auto *S = dyn_cast<TemplateTypeParmType>(&
Node)) {
1033 return matchesDecl(S->getDecl(), Finder, Builder);
1035 if (
const auto *S = dyn_cast<TypedefType>(&
Node)) {
1036 return matchesDecl(S->getDecl(), Finder, Builder);
1038 if (
const auto *S = dyn_cast<UnresolvedUsingType>(&
Node)) {
1039 return matchesDecl(S->getDecl(), Finder, Builder);
1041 if (
const auto *S = dyn_cast<ObjCObjectType>(&
Node)) {
1042 return matchesDecl(S->getInterface(), Finder, Builder);
1053 if (
const auto *S = dyn_cast<SubstTemplateTypeParmType>(&
Node)) {
1054 return matchesSpecialized(S->getReplacementType(), Finder, Builder);
1060 if (
const auto *S = dyn_cast<TemplateSpecializationType>(&
Node)) {
1061 if (!S->isTypeAlias() && S->isSugared()) {
1068 return matchesSpecialized(*S->desugar(), Finder, Builder);
1072 return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder,
1079 if (
const auto *S = dyn_cast<ElaboratedType>(&
Node)) {
1080 return matchesSpecialized(S->desugar(), Finder, Builder);
1085 if (
const auto *S = dyn_cast<UsingType>(&
Node)) {
1086 return matchesSpecialized(S->desugar(), Finder, Builder);
1093 bool matchesSpecialized(
const DeclRefExpr &
Node, ASTMatchFinder *Finder,
1094 BoundNodesTreeBuilder *Builder)
const {
1095 return matchesDecl(
Node.getDecl(), Finder, Builder);
1100 bool matchesSpecialized(
const CallExpr &
Node, ASTMatchFinder *Finder,
1101 BoundNodesTreeBuilder *Builder)
const {
1102 return matchesDecl(
Node.getCalleeDecl(), Finder, Builder);
1107 bool matchesSpecialized(
const CXXConstructExpr &
Node,
1108 ASTMatchFinder *Finder,
1109 BoundNodesTreeBuilder *Builder)
const {
1110 return matchesDecl(
Node.getConstructor(), Finder, Builder);
1113 bool matchesSpecialized(
const ObjCIvarRefExpr &
Node,
1114 ASTMatchFinder *Finder,
1115 BoundNodesTreeBuilder *Builder)
const {
1116 return matchesDecl(
Node.getDecl(), Finder, Builder);
1119 bool matchesSpecialized(
const ObjCInterfaceDecl &
Node, ASTMatchFinder *Finder,
1120 BoundNodesTreeBuilder *Builder)
const {
1121 return matchesDecl(
Node.getCanonicalDecl(), Finder, Builder);
1126 bool matchesSpecialized(
const CXXNewExpr &
Node,
1127 ASTMatchFinder *Finder,
1128 BoundNodesTreeBuilder *Builder)
const {
1129 return matchesDecl(
Node.getOperatorNew(), Finder, Builder);
1134 bool matchesSpecialized(
const MemberExpr &
Node,
1135 ASTMatchFinder *Finder,
1136 BoundNodesTreeBuilder *Builder)
const {
1137 return matchesDecl(
Node.getMemberDecl(), Finder, Builder);
1142 bool matchesSpecialized(
const AddrLabelExpr &
Node,
1143 ASTMatchFinder *Finder,
1144 BoundNodesTreeBuilder *Builder)
const {
1145 return matchesDecl(
Node.getLabel(), Finder, Builder);
1150 bool matchesSpecialized(
const LabelStmt &
Node, ASTMatchFinder *Finder,
1151 BoundNodesTreeBuilder *Builder)
const {
1152 return matchesDecl(
Node.getDecl(), Finder, Builder);
1157 bool matchesDecl(
const Decl *
Node, ASTMatchFinder *Finder,
1158 BoundNodesTreeBuilder *Builder)
const {
1159 return Node !=
nullptr &&
1160 !(Finder->isTraversalIgnoringImplicitNodes() &&
1161 Node->isImplicit()) &&
1162 this->InnerMatcher.matches(DynTypedNode::create(*
Node), Finder,
1169template <
typename T>
1171 static const bool value =
1172 std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value ||
1173 std::is_same<T, QualType>::value || std::is_same<T, Type>::value ||
1174 std::is_same<T, TypeLoc>::value ||
1175 std::is_same<T, NestedNameSpecifier>::value ||
1176 std::is_same<T, NestedNameSpecifierLoc>::value ||
1177 std::is_same<T, CXXCtorInitializer>::value ||
1178 std::is_same<T, TemplateArgumentLoc>::value ||
1179 std::is_same<T, Attr>::value;
1181template <
typename T>
1182const bool IsBaseType<T>::value;
1187using AllNodeBaseTypes =
1188 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
1189 Type, TypeLoc, CXXCtorInitializer, Attr>;
1195template <
class T>
struct ExtractFunctionArgMeta;
1196template <
class T>
struct ExtractFunctionArgMeta<void(
T)> {
1200template <
class T,
class Tuple, std::size_t... I>
1201constexpr T *new_from_tuple_impl(Tuple &&t, std::index_sequence<I...>) {
1202 return new T(std::get<I>(std::forward<Tuple>(t))...);
1205template <
class T,
class Tuple>
constexpr T *new_from_tuple(Tuple &&t) {
1206 return new_from_tuple_impl<T>(
1207 std::forward<Tuple>(t),
1208 std::make_index_sequence<
1209 std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
1213using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
1214using AdaptativeDefaultToTypes =
1215 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
1219using HasDeclarationSupportedTypes =
1220 TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
1221 ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
1222 MemberExpr, QualType, RecordType, TagType,
1223 TemplateSpecializationType, TemplateTypeParmType, TypedefType,
1224 UnresolvedUsingType, ObjCIvarRefExpr, ObjCInterfaceDecl>;
1230template <
typename T>
class BindableMatcher :
public Matcher<T> {
1232 explicit BindableMatcher(
const Matcher<T> &M) : Matcher<
T>(M) {}
1233 explicit BindableMatcher(MatcherInterface<T> *Implementation)
1234 : Matcher<
T>(Implementation) {}
1240 Matcher<T> bind(StringRef
ID)
const {
1241 return DynTypedMatcher(*
this)
1243 ->template unconditionalConvertTo<T>();
1248 operator DynTypedMatcher()
const {
1249 DynTypedMatcher Result =
static_cast<const Matcher<T> &
>(*this);
1250 Result.setAllowBind(
true);
1261 using ReturnTypes = AllNodeBaseTypes;
1263 template <
typename T>
operator Matcher<T>()
const {
1264 return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
1265 .template unconditionalConvertTo<T>();
1270template <
typename T>
1272makeAllOfComposite(ArrayRef<
const Matcher<T> *> InnerMatchers) {
1274 if (InnerMatchers.empty()) {
1275 return BindableMatcher<T>(TrueMatcher());
1279 if (InnerMatchers.size() == 1) {
1280 return BindableMatcher<T>(*InnerMatchers[0]);
1283 using PI = llvm::pointee_iterator<const Matcher<T> *
const *>;
1285 std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
1286 PI(InnerMatchers.end()));
1287 return BindableMatcher<T>(
1288 DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
1289 ASTNodeKind::getFromNodeKind<T>(),
1290 std::move(DynMatchers))
1291 .
template unconditionalConvertTo<T>());
1300template <
typename T,
typename InnerT>
1302makeDynCastAllOfComposite(ArrayRef<
const Matcher<InnerT> *> InnerMatchers) {
1303 return BindableMatcher<T>(
1304 makeAllOfComposite(InnerMatchers).
template dynCastTo<T>());
1318template <
typename SourceT,
typename TargetT>
1319class VariadicDynCastAllOfMatcher
1320 :
public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
1321 makeDynCastAllOfComposite<SourceT, TargetT>> {
1323 VariadicDynCastAllOfMatcher() {}
1336template <
typename T>
1337class VariadicAllOfMatcher
1338 :
public VariadicFunction<BindableMatcher<T>, Matcher<T>,
1339 makeAllOfComposite<T>> {
1341 VariadicAllOfMatcher() {}
1353template <
typename... Ps>
class VariadicOperatorMatcher {
1355 VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
1356 : Op(Op), Params(
std::
forward<Ps>(Params)...) {}
1358 template <
typename T>
operator Matcher<T>() const & {
1359 return DynTypedMatcher::constructVariadic(
1360 Op, ASTNodeKind::getFromNodeKind<T>(),
1361 getMatchers<T>(std::index_sequence_for<Ps...>()))
1362 .template unconditionalConvertTo<T>();
1365 template <
typename T>
operator Matcher<T>() && {
1366 return DynTypedMatcher::constructVariadic(
1367 Op, ASTNodeKind::getFromNodeKind<T>(),
1368 getMatchers<T>(std::index_sequence_for<Ps...>()))
1369 .template unconditionalConvertTo<T>();
1374 template <
typename T, std::size_t... Is>
1375 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>)
const & {
1376 return {Matcher<T>(std::get<Is>(Params))...};
1379 template <
typename T, std::size_t... Is>
1380 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) && {
1381 return {Matcher<T>(std::get<Is>(std::move(Params)))...};
1384 const DynTypedMatcher::VariadicOperator Op;
1385 std::tuple<Ps...> Params;
1390template <
unsigned MinCount,
unsigned MaxCount>
1391struct VariadicOperatorMatcherFunc {
1392 DynTypedMatcher::VariadicOperator Op;
1394 template <
typename... Ms>
1395 VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps)
const {
1396 static_assert(MinCount <=
sizeof...(Ms) &&
sizeof...(Ms) <= MaxCount,
1397 "invalid number of parameters for variadic matcher");
1398 return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
1402template <
typename T,
bool IsBaseOf,
typename Head,
typename Tail>
1403struct GetCladeImpl {
1406template <
typename T,
typename Head,
typename Tail>
1407struct GetCladeImpl<
T,
false, Head, Tail>
1408 : GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
1409 typename Tail::head, typename Tail::tail> {};
1411template <
typename T,
typename...
U>
1412struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
1414template <
typename CladeType,
typename... MatcherTypes>
1415struct MapAnyOfMatcherImpl {
1417 template <
typename... InnerMatchers>
1418 BindableMatcher<CladeType>
1419 operator()(InnerMatchers &&... InnerMatcher)
const {
1420 return VariadicAllOfMatcher<CladeType>()(std::apply(
1421 internal::VariadicOperatorMatcherFunc<
1422 0, std::numeric_limits<unsigned>::max()>{
1423 internal::DynTypedMatcher::VO_AnyOf},
1425 [&](
auto... Matcher) {
1426 return std::make_tuple(Matcher(InnerMatcher...)...);
1429 VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
1433template <
typename... MatcherTypes>
1434using MapAnyOfMatcher =
1435 MapAnyOfMatcherImpl<
typename GetClade<MatcherTypes...>::Type,
1438template <
typename... MatcherTypes>
struct MapAnyOfHelper {
1439 using CladeType =
typename GetClade<MatcherTypes...>
::Type;
1441 MapAnyOfMatcher<MatcherTypes...> with;
1443 operator BindableMatcher<CladeType>()
const {
return with(); }
1445 Matcher<CladeType> bind(StringRef
ID)
const {
return with().bind(
ID); }
1448template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1449 typename T,
typename ToTypes>
1450class ArgumentAdaptingMatcherFuncAdaptor {
1452 explicit ArgumentAdaptingMatcherFuncAdaptor(
const Matcher<T> &InnerMatcher)
1453 : InnerMatcher(InnerMatcher) {}
1455 using ReturnTypes = ToTypes;
1457 template <
typename To>
operator Matcher<To>() const & {
1458 return Matcher<To>(
new ArgumentAdapterT<To, T>(InnerMatcher));
1461 template <
typename To>
operator Matcher<To>() && {
1462 return Matcher<To>(
new ArgumentAdapterT<To, T>(std::move(InnerMatcher)));
1466 Matcher<T> InnerMatcher;
1482template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1483 typename FromTypes = AdaptativeDefaultFromTypes,
1484 typename ToTypes = AdaptativeDefaultToTypes>
1485struct ArgumentAdaptingMatcherFunc {
1486 template <
typename T>
1487 static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1488 create(
const Matcher<T> &InnerMatcher) {
1489 return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>(
1493 template <
typename T>
1494 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1495 operator()(
const Matcher<T> &InnerMatcher)
const {
1496 return create(InnerMatcher);
1499 template <
typename...
T>
1500 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT,
1501 typename GetClade<
T...>
::Type, ToTypes>
1502 operator()(
const MapAnyOfHelper<T...> &InnerMatcher)
const {
1503 return create(InnerMatcher.with());
1507template <
typename T>
class TraversalMatcher :
public MatcherInterface<T> {
1508 DynTypedMatcher InnerMatcher;
1513 const Matcher<T> &InnerMatcher)
1514 : InnerMatcher(InnerMatcher),
Traversal(TK) {}
1516 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1517 BoundNodesTreeBuilder *Builder)
const override {
1518 return this->InnerMatcher.matches(DynTypedNode::create(
Node), Finder,
1522 std::optional<clang::TraversalKind>
TraversalKind()
const override {
1523 if (
auto NestedKind = this->InnerMatcher.getTraversalKind())
1529template <
typename MatcherType>
class TraversalWrapper {
1531 TraversalWrapper(TraversalKind TK,
const MatcherType &InnerMatcher)
1532 : TK(TK), InnerMatcher(InnerMatcher) {}
1534 template <
typename T>
operator Matcher<T>() const & {
1535 return internal::DynTypedMatcher::constructRestrictedWrapper(
1536 new internal::TraversalMatcher<T>(TK, InnerMatcher),
1537 ASTNodeKind::getFromNodeKind<T>())
1538 .template unconditionalConvertTo<T>();
1541 template <
typename T>
operator Matcher<T>() && {
1542 return internal::DynTypedMatcher::constructRestrictedWrapper(
1543 new internal::TraversalMatcher<T>(TK, std::move(InnerMatcher)),
1544 ASTNodeKind::getFromNodeKind<T>())
1545 .template unconditionalConvertTo<T>();
1550 MatcherType InnerMatcher;
1565template <
template <
typename T,
typename... Params>
class MatcherT,
1566 typename ReturnTypesF, typename... ParamTypes>
1567class PolymorphicMatcher {
1569 PolymorphicMatcher(
const ParamTypes &... Params) : Params(Params...) {}
1571 using ReturnTypes =
typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1573 template <
typename T>
operator Matcher<T>() const & {
1574 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1575 "right polymorphic conversion");
1576 return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params));
1579 template <
typename T>
operator Matcher<T>() && {
1580 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1581 "right polymorphic conversion");
1583 new_from_tuple<MatcherT<T, ParamTypes...>>(std::move(Params)));
1587 std::tuple<ParamTypes...> Params;
1594template <
typename T,
typename ChildT>
1595class HasMatcher :
public MatcherInterface<T> {
1596 DynTypedMatcher InnerMatcher;
1599 explicit HasMatcher(
const Matcher<ChildT> &InnerMatcher)
1600 : InnerMatcher(InnerMatcher) {}
1602 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1603 BoundNodesTreeBuilder *Builder)
const override {
1604 return Finder->matchesChildOf(
Node, this->InnerMatcher, Builder,
1605 ASTMatchFinder::BK_First);
1614template <
typename T,
typename ChildT>
1615class ForEachMatcher :
public MatcherInterface<T> {
1616 static_assert(IsBaseType<ChildT>::value,
1617 "for each only accepts base type matcher");
1619 DynTypedMatcher InnerMatcher;
1622 explicit ForEachMatcher(
const Matcher<ChildT> &InnerMatcher)
1623 : InnerMatcher(InnerMatcher) {}
1625 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1626 BoundNodesTreeBuilder *Builder)
const override {
1627 return Finder->matchesChildOf(
1628 Node, this->InnerMatcher, Builder,
1629 ASTMatchFinder::BK_All);
1635template <
typename T>
1636inline Matcher<T> DynTypedMatcher::unconditionalConvertTo()
const {
1637 return Matcher<T>(*
this);
1644template <
typename T,
typename DescendantT>
1645class HasDescendantMatcher :
public MatcherInterface<T> {
1646 static_assert(IsBaseType<DescendantT>::value,
1647 "has descendant only accepts base type matcher");
1649 DynTypedMatcher DescendantMatcher;
1652 explicit HasDescendantMatcher(
const Matcher<DescendantT> &DescendantMatcher)
1653 : DescendantMatcher(DescendantMatcher) {}
1655 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1656 BoundNodesTreeBuilder *Builder)
const override {
1657 return Finder->matchesDescendantOf(
Node, this->DescendantMatcher, Builder,
1658 ASTMatchFinder::BK_First);
1666template <
typename T,
typename ParentT>
1667class HasParentMatcher :
public MatcherInterface<T> {
1668 static_assert(IsBaseType<ParentT>::value,
1669 "has parent only accepts base type matcher");
1671 DynTypedMatcher ParentMatcher;
1674 explicit HasParentMatcher(
const Matcher<ParentT> &ParentMatcher)
1675 : ParentMatcher(ParentMatcher) {}
1677 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1678 BoundNodesTreeBuilder *Builder)
const override {
1679 return Finder->matchesAncestorOf(
Node, this->ParentMatcher, Builder,
1680 ASTMatchFinder::AMM_ParentOnly);
1688template <
typename T,
typename AncestorT>
1689class HasAncestorMatcher :
public MatcherInterface<T> {
1690 static_assert(IsBaseType<AncestorT>::value,
1691 "has ancestor only accepts base type matcher");
1693 DynTypedMatcher AncestorMatcher;
1696 explicit HasAncestorMatcher(
const Matcher<AncestorT> &AncestorMatcher)
1697 : AncestorMatcher(AncestorMatcher) {}
1699 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1700 BoundNodesTreeBuilder *Builder)
const override {
1701 return Finder->matchesAncestorOf(
Node, this->AncestorMatcher, Builder,
1702 ASTMatchFinder::AMM_All);
1712template <
typename T,
typename DescendantT>
1713class ForEachDescendantMatcher :
public MatcherInterface<T> {
1714 static_assert(IsBaseType<DescendantT>::value,
1715 "for each descendant only accepts base type matcher");
1717 DynTypedMatcher DescendantMatcher;
1720 explicit ForEachDescendantMatcher(
1721 const Matcher<DescendantT> &DescendantMatcher)
1722 : DescendantMatcher(DescendantMatcher) {}
1724 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1725 BoundNodesTreeBuilder *Builder)
const override {
1726 return Finder->matchesDescendantOf(
Node, this->DescendantMatcher, Builder,
1727 ASTMatchFinder::BK_All);
1733template <
typename T,
typename ValueT>
1734class ValueEqualsMatcher :
public SingleNodeMatcherInterface<T> {
1735 static_assert(std::is_base_of<CharacterLiteral, T>::value ||
1736 std::is_base_of<CXXBoolLiteralExpr, T>::value ||
1737 std::is_base_of<FloatingLiteral, T>::value ||
1738 std::is_base_of<IntegerLiteral, T>::value,
1739 "the node must have a getValue method");
1742 explicit ValueEqualsMatcher(
const ValueT &ExpectedValue)
1743 : ExpectedValue(ExpectedValue) {}
1745 bool matchesNode(
const T &
Node)
const override {
1746 return Node.getValue() == ExpectedValue;
1750 ValueT ExpectedValue;
1756inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
1757 const FloatingLiteral &
Node)
const {
1758 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1759 return Node.getValue().convertToFloat() == ExpectedValue;
1760 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1761 return Node.getValue().convertToDouble() == ExpectedValue;
1765inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
1766 const FloatingLiteral &
Node)
const {
1767 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1768 return Node.getValue().convertToFloat() == ExpectedValue;
1769 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1770 return Node.getValue().convertToDouble() == ExpectedValue;
1774inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
1775 const FloatingLiteral &
Node)
const {
1776 return ExpectedValue.compare(
Node.getValue()) == llvm::APFloat::cmpEqual;
1781template <
typename TLoc,
typename T>
1782class LocMatcher :
public MatcherInterface<TLoc> {
1783 DynTypedMatcher InnerMatcher;
1786 explicit LocMatcher(
const Matcher<T> &InnerMatcher)
1787 : InnerMatcher(InnerMatcher) {}
1789 bool matches(
const TLoc &
Node, ASTMatchFinder *Finder,
1790 BoundNodesTreeBuilder *Builder)
const override {
1793 return this->InnerMatcher.matches(extract(
Node), Finder, Builder);
1798 return DynTypedNode::create(*
Loc.getNestedNameSpecifier());
1806class TypeLocTypeMatcher :
public MatcherInterface<TypeLoc> {
1807 DynTypedMatcher InnerMatcher;
1810 explicit TypeLocTypeMatcher(
const Matcher<QualType> &InnerMatcher)
1811 : InnerMatcher(InnerMatcher) {}
1813 bool matches(
const TypeLoc &
Node, ASTMatchFinder *Finder,
1814 BoundNodesTreeBuilder *Builder)
const override {
1817 return this->InnerMatcher.matches(DynTypedNode::create(
Node.getType()),
1825template <
typename T>
class TypeTraverseMatcher :
public MatcherInterface<T> {
1826 DynTypedMatcher InnerMatcher;
1829 explicit TypeTraverseMatcher(
const Matcher<QualType> &InnerMatcher,
1830 QualType (T::*TraverseFunction)()
const)
1831 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1833 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1834 BoundNodesTreeBuilder *Builder)
const override {
1835 QualType NextNode = (
Node.*TraverseFunction)();
1836 if (NextNode.isNull())
1838 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1843 QualType (T::*TraverseFunction)()
const;
1849template <
typename T>
1850class TypeLocTraverseMatcher :
public MatcherInterface<T> {
1851 DynTypedMatcher InnerMatcher;
1854 explicit TypeLocTraverseMatcher(
const Matcher<TypeLoc> &InnerMatcher,
1855 TypeLoc (T::*TraverseFunction)()
const)
1856 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1858 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1859 BoundNodesTreeBuilder *Builder)
const override {
1860 TypeLoc NextNode = (
Node.*TraverseFunction)();
1863 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1868 TypeLoc (T::*TraverseFunction)()
const;
1877template <
typename InnerTBase,
1878 template <
typename OuterT>
class Getter,
1879 template <
typename OuterT>
class MatcherImpl,
1880 typename ReturnTypesF>
1881class TypeTraversePolymorphicMatcher {
1883 using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
1886 static Self
create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers);
1889 using ReturnTypes =
typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1891 explicit TypeTraversePolymorphicMatcher(
1892 ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers)
1893 : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
1895 template <
typename OuterT>
operator Matcher<OuterT>()
const {
1896 return Matcher<OuterT>(
1897 new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
1901 :
public VariadicFunction<Self, Matcher<InnerTBase>, &Self::create> {
1906 Matcher<InnerTBase> InnerMatcher;
1913template <
typename Matcher, Matcher (*Func)()>
class MemoizedMatcher {
1915 Wrapper() : M(
Func()) {}
1921 static const Matcher &getInstance() {
1922 static llvm::ManagedStatic<Wrapper> Instance;
1930template <
typename InnerTBase,
template <
typename OuterT>
class Getter,
1931 template <
typename OuterT>
class MatcherImpl,
typename ReturnTypesF>
1932TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
1933TypeTraversePolymorphicMatcher<
1934 InnerTBase, Getter, MatcherImpl,
1935 ReturnTypesF>::create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers) {
1936 return Self(InnerMatchers);
1941inline ArrayRef<TemplateArgument>
1942getTemplateSpecializationArgs(
const ClassTemplateSpecializationDecl &
D) {
1943 return D.getTemplateArgs().asArray();
1946inline ArrayRef<TemplateArgument>
1947getTemplateSpecializationArgs(
const VarTemplateSpecializationDecl &
D) {
1948 return D.getTemplateArgs().asArray();
1951inline ArrayRef<TemplateArgument>
1952getTemplateSpecializationArgs(
const TemplateSpecializationType &
T) {
1953 return T.template_arguments();
1956inline ArrayRef<TemplateArgument>
1957getTemplateSpecializationArgs(
const FunctionDecl &FD) {
1958 if (
const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
1959 return TemplateArgs->asArray();
1963inline ArrayRef<TemplateArgumentLoc>
1964getTemplateArgsWritten(
const ClassTemplateSpecializationDecl &
D) {
1965 if (
const ASTTemplateArgumentListInfo *Args =
D.getTemplateArgsAsWritten())
1966 return Args->arguments();
1970inline ArrayRef<TemplateArgumentLoc>
1971getTemplateArgsWritten(
const VarTemplateSpecializationDecl &
D) {
1972 if (
const ASTTemplateArgumentListInfo *Args =
D.getTemplateArgsAsWritten())
1973 return Args->arguments();
1977inline ArrayRef<TemplateArgumentLoc>
1978getTemplateArgsWritten(
const FunctionDecl &FD) {
1979 if (
const auto *Args = FD.getTemplateSpecializationArgsAsWritten())
1980 return Args->arguments();
1984inline ArrayRef<TemplateArgumentLoc>
1985getTemplateArgsWritten(
const DeclRefExpr &DRE) {
1986 if (
const auto *Args = DRE.getTemplateArgs())
1987 return {Args, DRE.getNumTemplateArgs()};
1991inline SmallVector<TemplateArgumentLoc>
1992getTemplateArgsWritten(
const TemplateSpecializationTypeLoc &
T) {
1993 SmallVector<TemplateArgumentLoc> Args;
1995 Args.reserve(
T.getNumArgs());
1996 for (
unsigned I = 0; I <
T.getNumArgs(); ++I)
1997 Args.emplace_back(
T.getArgLoc(I));
2002struct NotEqualsBoundNodePredicate {
2003 bool operator()(
const internal::BoundNodesMap &
Nodes)
const {
2011template <
typename Ty,
typename Enable =
void>
struct GetBodyMatcher {
2012 static const Stmt *get(
const Ty &
Node) {
return Node.getBody(); }
2015template <
typename Ty>
2016struct GetBodyMatcher<
2017 Ty,
std::
enable_if_t<std::is_base_of<FunctionDecl, Ty>::value>> {
2018 static const Stmt *get(
const Ty &
Node) {
2019 return Node.doesThisDeclarationHaveABody() ?
Node.getBody() :
nullptr;
2023template <
typename NodeType>
2024inline std::optional<BinaryOperatorKind>
2025equivalentBinaryOperator(
const NodeType &
Node) {
2026 return Node.getOpcode();
2030inline std::optional<BinaryOperatorKind>
2031equivalentBinaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2032 if (
Node.getNumArgs() != 2)
2033 return std::nullopt;
2034 switch (
Node.getOperator()) {
2036 return std::nullopt;
2051 case OO_GreaterGreater:
2061 case OO_GreaterEqual:
2065 case OO_ExclaimEqual:
2080 return BO_MulAssign;
2082 return BO_DivAssign;
2083 case OO_PercentEqual:
2084 return BO_RemAssign;
2086 return BO_AddAssign;
2088 return BO_SubAssign;
2089 case OO_LessLessEqual:
2090 return BO_ShlAssign;
2091 case OO_GreaterGreaterEqual:
2092 return BO_ShrAssign;
2094 return BO_AndAssign;
2096 return BO_XorAssign;
2104template <
typename NodeType>
2105inline std::optional<UnaryOperatorKind>
2106equivalentUnaryOperator(
const NodeType &
Node) {
2107 return Node.getOpcode();
2111inline std::optional<UnaryOperatorKind>
2112equivalentUnaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2113 if (
Node.getNumArgs() != 1 &&
Node.getOperator() != OO_PlusPlus &&
2114 Node.getOperator() != OO_MinusMinus)
2115 return std::nullopt;
2116 switch (
Node.getOperator()) {
2118 return std::nullopt;
2132 const auto *FD =
Node.getDirectCallee();
2134 return std::nullopt;
2135 return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
2137 case OO_MinusMinus: {
2138 const auto *FD =
Node.getDirectCallee();
2140 return std::nullopt;
2141 return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
2148template <
typename NodeType>
inline const Expr *getLHS(
const NodeType &
Node) {
2149 return Node.getLHS();
2153getLHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2154 if (!internal::equivalentBinaryOperator(
Node))
2156 return Node.getArg(0);
2158template <
typename NodeType>
inline const Expr *getRHS(
const NodeType &
Node) {
2159 return Node.getRHS();
2163getRHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2164 if (!internal::equivalentBinaryOperator(
Node))
2166 return Node.getArg(1);
2168template <
typename NodeType>
2169inline const Expr *getSubExpr(
const NodeType &
Node) {
2170 return Node.getSubExpr();
2174getSubExpr<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2175 if (!internal::equivalentUnaryOperator(
Node))
2177 return Node.getArg(0);
2180template <
typename Ty>
2181struct HasSizeMatcher {
2182 static bool hasSize(
const Ty &
Node,
unsigned int N) {
2183 return Node.getSize() == N;
2188inline bool HasSizeMatcher<StringLiteral>::hasSize(
2189 const StringLiteral &
Node,
unsigned int N) {
2190 return Node.getLength() == N;
2193template <
typename Ty>
2194struct GetSourceExpressionMatcher {
2195 static const Expr *get(
const Ty &
Node) {
2196 return Node.getSubExpr();
2201inline const Expr *GetSourceExpressionMatcher<OpaqueValueExpr>::get(
2202 const OpaqueValueExpr &
Node) {
2203 return Node.getSourceExpr();
2206template <
typename Ty>
2207struct CompoundStmtMatcher {
2208 static const CompoundStmt *get(
const Ty &
Node) {
2214inline const CompoundStmt *
2215CompoundStmtMatcher<StmtExpr>::get(
const StmtExpr &
Node) {
2216 return Node.getSubStmt();
2225 const ASTContext &Context);
2227inline std::optional<StringRef> getOpName(
const UnaryOperator &
Node) {
2228 return Node.getOpcodeStr(
Node.getOpcode());
2230inline std::optional<StringRef> getOpName(
const BinaryOperator &
Node) {
2231 return Node.getOpcodeStr();
2233inline StringRef getOpName(
const CXXRewrittenBinaryOperator &
Node) {
2234 return Node.getOpcodeStr();
2236inline std::optional<StringRef> getOpName(
const CXXOperatorCallExpr &
Node) {
2237 auto optBinaryOpcode = equivalentBinaryOperator(
Node);
2238 if (!optBinaryOpcode) {
2239 auto optUnaryOpcode = equivalentUnaryOperator(
Node);
2240 if (!optUnaryOpcode)
2241 return std::nullopt;
2246inline StringRef getOpName(
const CXXFoldExpr &
Node) {
2254template <
typename T,
typename ArgT = std::vector<std::
string>>
2255class HasAnyOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
2256 static_assert(std::is_same<T, BinaryOperator>::value ||
2257 std::is_same<T, CXXOperatorCallExpr>::value ||
2258 std::is_same<T, CXXRewrittenBinaryOperator>::value ||
2259 std::is_same<T, UnaryOperator>::value,
2260 "Matcher only supports `BinaryOperator`, `UnaryOperator`, "
2261 "`CXXOperatorCallExpr` and `CXXRewrittenBinaryOperator`");
2262 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
2263 "Matcher ArgT must be std::vector<std::string>");
2266 explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names)
2267 : SingleNodeMatcherInterface<
T>(), Names(
std::move(Names)) {}
2269 bool matchesNode(
const T &
Node)
const override {
2270 std::optional<StringRef> OptOpName = getOpName(
Node);
2271 return OptOpName && llvm::is_contained(Names, *OptOpName);
2275 static std::optional<StringRef> getOpName(
const UnaryOperator &
Node) {
2276 return Node.getOpcodeStr(
Node.getOpcode());
2278 static std::optional<StringRef> getOpName(
const BinaryOperator &
Node) {
2279 return Node.getOpcodeStr();
2281 static StringRef getOpName(
const CXXRewrittenBinaryOperator &
Node) {
2282 return Node.getOpcodeStr();
2284 static std::optional<StringRef> getOpName(
const CXXOperatorCallExpr &
Node) {
2285 auto optBinaryOpcode = equivalentBinaryOperator(
Node);
2286 if (!optBinaryOpcode) {
2287 auto optUnaryOpcode = equivalentUnaryOperator(
Node);
2288 if (!optUnaryOpcode)
2289 return std::nullopt;
2290 return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
2292 return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
2295 std::vector<std::string> Names;
2298using HasOpNameMatcher =
2299 PolymorphicMatcher<HasAnyOperatorNameMatcher,
2301 TypeList<BinaryOperator, CXXOperatorCallExpr,
2302 CXXRewrittenBinaryOperator, UnaryOperator>),
2303 std::vector<std::string>>;
2307using HasOverloadOpNameMatcher =
2308 PolymorphicMatcher<HasOverloadedOperatorNameMatcher,
2309 void(TypeList<CXXOperatorCallExpr, FunctionDecl>),
2310 std::vector<std::string>>;
2312HasOverloadOpNameMatcher
2319 const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
2320 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder);
2323 llvm::Regex::RegexFlags Flags,
2327MatchTemplateArgLocAt(
const DeclRefExpr &
Node,
unsigned int Index,
2328 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2329 internal::ASTMatchFinder *Finder,
2330 internal::BoundNodesTreeBuilder *Builder) {
2332 return Index < ArgLocs.size() &&
2333 InnerMatcher.matches(ArgLocs[Index], Finder, Builder);
2337MatchTemplateArgLocAt(
const TemplateSpecializationTypeLoc &
Node,
2339 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2340 internal::ASTMatchFinder *Finder,
2341 internal::BoundNodesTreeBuilder *Builder) {
2342 return !
Node.isNull() && Index <
Node.getNumArgs() &&
2343 InnerMatcher.matches(
Node.getArgLoc(Index), Finder, Builder);
BoundNodesTreeBuilder BoundNodes
BoundNodesTreeBuilder Nodes
DynTypedMatcher::MatcherIDType MatcherID
enum clang::sema::@1718::IndirectLocalPathEntry::EntryKind Kind
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)
The JSON file list parser is used to communicate input to InstallAPI.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
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
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...
typename enable_if< B, T >::Type enable_if_t