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/None.h"
56 #include "llvm/ADT/Optional.h"
57 #include "llvm/ADT/STLExtras.h"
58 #include "llvm/ADT/SmallVector.h"
59 #include "llvm/ADT/StringRef.h"
60 #include "llvm/ADT/iterator.h"
61 #include "llvm/Support/Casting.h"
62 #include "llvm/Support/ManagedStatic.h"
63 #include "llvm/Support/Regex.h"
72 #include <type_traits>
80 namespace ast_matchers {
90 template <
typename... Ts>
struct TypeList {};
92 template <
typename T1,
typename... Ts>
struct TypeList<T1, Ts...> {
100 using tail = TypeList<Ts...>;
104 using EmptyTypeList = TypeList<>;
108 template <
typename AnyTypeList,
typename T>
struct TypeListContainsSuperOf {
109 static const bool value =
110 std::is_base_of<typename AnyTypeList::head, T>::value ||
111 TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value;
113 template <
typename T>
struct TypeListContainsSuperOf<EmptyTypeList, T> {
114 static const bool value =
false;
122 template <
typename ResultT,
typename ArgT,
123 ResultT (*Func)(ArrayRef<const ArgT *>)>
124 struct VariadicFunction {
125 ResultT operator()()
const {
return Func(None); }
127 template <
typename... ArgsT>
128 ResultT operator()(
const ArgT &Arg1,
const ArgsT &... Args)
const {
129 return Execute(Arg1,
static_cast<const ArgT &
>(Args)...);
134 ResultT operator()(ArrayRef<ArgT> Args)
const {
135 return Func(llvm::to_vector<8>(llvm::make_pointer_range(Args)));
141 template <
typename... ArgsT> ResultT Execute(
const ArgsT &... Args)
const {
142 const ArgT *
const ArgsArray[] = {&Args...};
143 return Func(ArrayRef<const ArgT *>(ArgsArray,
sizeof...(ArgsT)));
152 return Node.getType();
155 return Node.getUnderlyingType();
158 if (
const TypeSourceInfo *TSI =
Node.getFriendType())
159 return TSI->getType();
163 return Node.getType();
167 template <
typename T,
168 std::enable_if_t<TypeListContainsSuperOf<
169 TypeList<CXXBaseSpecifier, CXXCtorInitializer,
170 CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr,
171 CompoundLiteralExpr, DeclaratorDecl, ObjCPropertyDecl,
172 TemplateArgumentLoc, TypedefNameDecl>,
173 T>::value> * =
nullptr>
174 inline TypeSourceInfo *GetTypeSourceInfo(
const T &
Node) {
175 return Node.getTypeSourceInfo();
177 template <
typename T,
178 std::enable_if_t<TypeListContainsSuperOf<
179 TypeList<CXXFunctionalCastExpr, ExplicitCastExpr>, T>::value> * =
181 inline TypeSourceInfo *GetTypeSourceInfo(
const T &
Node) {
182 return Node.getTypeInfoAsWritten();
184 inline TypeSourceInfo *GetTypeSourceInfo(
const BlockDecl &
Node) {
185 return Node.getSignatureAsWritten();
187 inline TypeSourceInfo *GetTypeSourceInfo(
const CXXNewExpr &
Node) {
188 return Node.getAllocatedTypeSourceInfo();
190 inline TypeSourceInfo *
191 GetTypeSourceInfo(
const ClassTemplateSpecializationDecl &
Node) {
192 return Node.getTypeAsWritten();
197 inline const FunctionProtoType *
198 getFunctionProtoType(
const FunctionProtoType &
Node) {
202 inline const FunctionProtoType *getFunctionProtoType(
const FunctionDecl &
Node) {
203 return Node.getType()->getAs<FunctionProtoType>();
208 return Node.getAccess();
212 return Node.getAccessSpecifier();
216 class BoundNodesMap {
229 template <
typename T>
230 const T *getNodeAs(StringRef
ID)
const {
231 IDToNodeMap::const_iterator It = NodeMap.find(
ID);
232 if (It == NodeMap.end()) {
235 return It->second.get<T>();
239 IDToNodeMap::const_iterator It = NodeMap.find(
ID);
240 if (It == NodeMap.end()) {
247 bool operator<(
const BoundNodesMap &Other)
const {
248 return NodeMap < Other.NodeMap;
256 using IDToNodeMap = std::map<std::string, DynTypedNode, std::less<>>;
258 const IDToNodeMap &getMap()
const {
264 bool isComparable()
const {
265 for (
const auto &IDAndNode : NodeMap) {
266 if (!IDAndNode.second.getMemoizationData())
280 class BoundNodesTreeBuilder {
286 virtual ~Visitor() =
default;
291 virtual void visitMatch(
const BoundNodes& BoundNodesView) = 0;
298 for (BoundNodesMap &Binding :
Bindings)
299 Binding.addNode(
Id, DynNode);
303 void addMatch(
const BoundNodesTreeBuilder &
Bindings);
308 void visitMatches(Visitor* ResultVisitor);
310 template <
typename ExcludePredicate>
311 bool removeBindings(
const ExcludePredicate &Predicate) {
312 llvm::erase_if(
Bindings, Predicate);
317 bool operator<(
const BoundNodesTreeBuilder &Other)
const {
323 bool isComparable()
const {
324 for (
const BoundNodesMap &NodesMap :
Bindings) {
325 if (!NodesMap.isComparable())
332 SmallVector<BoundNodesMap, 1>
Bindings;
335 class ASTMatchFinder;
342 class DynMatcherInterface
343 :
public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
345 virtual ~DynMatcherInterface() =
default;
351 virtual bool dynMatches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
352 BoundNodesTreeBuilder *Builder)
const = 0;
366 template <
typename T>
367 class MatcherInterface :
public DynMatcherInterface {
374 ASTMatchFinder *Finder,
375 BoundNodesTreeBuilder *Builder)
const = 0;
377 bool dynMatches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
378 BoundNodesTreeBuilder *Builder)
const override {
379 return matches(DynNode.getUnchecked<T>(), Finder, Builder);
385 template <
typename T>
386 class SingleNodeMatcherInterface :
public MatcherInterface<T> {
391 virtual bool matchesNode(
const T &
Node)
const = 0;
397 BoundNodesTreeBuilder * )
const override {
398 return matchesNode(
Node);
402 template <
typename>
class Matcher;
411 class DynTypedMatcher {
414 template <
typename T>
415 DynTypedMatcher(MatcherInterface<T> *Implementation)
416 : SupportedKind(ASTNodeKind::getFromNodeKind<T>()),
417 RestrictKind(SupportedKind), Implementation(Implementation) {}
420 enum VariadicOperator {
443 static DynTypedMatcher
444 constructVariadic(VariadicOperator Op, ASTNodeKind SupportedKind,
445 std::vector<DynTypedMatcher> InnerMatchers);
447 static DynTypedMatcher
448 constructRestrictedWrapper(
const DynTypedMatcher &InnerMatcher,
449 ASTNodeKind RestrictKind);
454 static DynTypedMatcher trueMatcher(ASTNodeKind
NodeKind);
456 void setAllowBind(
bool AB) { AllowBind = AB; }
461 bool canMatchNodesOfKind(ASTNodeKind
Kind)
const;
465 DynTypedMatcher dynCastTo(
const ASTNodeKind
Kind)
const;
475 BoundNodesTreeBuilder *Builder)
const;
481 bool matchesNoKindCheck(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
482 BoundNodesTreeBuilder *Builder)
const;
496 using MatcherIDType = std::pair<ASTNodeKind, uint64_t>;
497 MatcherIDType getID()
const {
500 return std::make_pair(RestrictKind,
501 reinterpret_cast<uint64_t>(Implementation.get()));
508 ASTNodeKind getSupportedKind()
const {
return SupportedKind; }
515 template <
typename T>
bool canConvertTo()
const {
516 return canConvertTo(ASTNodeKind::getFromNodeKind<T>());
518 bool canConvertTo(ASTNodeKind To)
const;
525 template <
typename T> Matcher<T> convertTo()
const {
526 assert(canConvertTo<T>());
527 return unconditionalConvertTo<T>();
534 template <
typename T> Matcher<T> unconditionalConvertTo()
const;
541 return Implementation->TraversalKind();
545 DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind,
546 IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
547 : SupportedKind(SupportedKind), RestrictKind(RestrictKind),
548 Implementation(
std::move(Implementation)) {}
550 bool AllowBind =
false;
551 ASTNodeKind SupportedKind;
557 ASTNodeKind RestrictKind;
558 IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
569 template <
typename T>
573 explicit Matcher(MatcherInterface<T> *Implementation)
574 : Implementation(Implementation) {}
579 template <
typename From>
580 Matcher(
const Matcher<From> &Other,
581 std::enable_if_t<std::is_base_of<From, T>::value &&
582 !std::is_same<From, T>::value> * =
nullptr)
583 : Implementation(restrictMatcher(Other.Implementation)) {
584 assert(Implementation.getSupportedKind().isSame(
585 ASTNodeKind::getFromNodeKind<T>()));
591 template <
typename TypeT>
592 Matcher(
const Matcher<TypeT> &Other,
593 std::enable_if_t<std::is_same<T, QualType>::value &&
594 std::is_same<TypeT, Type>::value> * =
nullptr)
595 : Implementation(new TypeToQualType<TypeT>(Other)) {}
600 template <
typename To> Matcher<To> dynCastTo() const & {
601 static_assert(std::is_base_of<To, T>::value,
"Invalid dynCast call.");
602 return Matcher<To>(Implementation);
605 template <
typename To> Matcher<To> dynCastTo() && {
606 static_assert(std::is_base_of<To, T>::value,
"Invalid dynCast call.");
607 return Matcher<To>(std::move(Implementation));
612 ASTMatchFinder *Finder,
613 BoundNodesTreeBuilder *Builder)
const {
618 DynTypedMatcher::MatcherIDType getID()
const {
619 return Implementation.getID();
626 operator DynTypedMatcher() const & {
return Implementation; }
628 operator DynTypedMatcher() && {
return std::move(Implementation); }
636 template <
typename TypeT>
637 class TypeToQualType :
public MatcherInterface<QualType> {
638 const DynTypedMatcher InnerMatcher;
641 TypeToQualType(
const Matcher<TypeT> &InnerMatcher)
642 : InnerMatcher(InnerMatcher) {}
644 bool matches(
const QualType &
Node, ASTMatchFinder *Finder,
645 BoundNodesTreeBuilder *Builder)
const override {
653 return this->InnerMatcher.getTraversalKind();
659 template <
typename U>
friend class Matcher;
662 friend class DynTypedMatcher;
664 static DynTypedMatcher restrictMatcher(
const DynTypedMatcher &Other) {
665 return Other.dynCastTo(ASTNodeKind::getFromNodeKind<T>());
668 explicit Matcher(
const DynTypedMatcher &Implementation)
669 : Implementation(restrictMatcher(Implementation)) {
670 assert(this->Implementation.getSupportedKind().isSame(
671 ASTNodeKind::getFromNodeKind<T>()));
674 DynTypedMatcher Implementation;
679 template <
typename T>
680 inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
681 return Matcher<T>(Implementation);
702 class ASTMatchFinder {
714 enum AncestorMatchMode {
722 virtual ~ASTMatchFinder() =
default;
728 virtual bool classIsDerivedFrom(
const CXXRecordDecl *Declaration,
729 const Matcher<NamedDecl> &
Base,
730 BoundNodesTreeBuilder *Builder,
737 virtual bool objcClassIsDerivedFrom(
const ObjCInterfaceDecl *Declaration,
738 const Matcher<NamedDecl> &
Base,
739 BoundNodesTreeBuilder *Builder,
742 template <
typename T>
743 bool matchesChildOf(
const T &
Node,
const DynTypedMatcher &Matcher,
744 BoundNodesTreeBuilder *Builder, BindKind Bind) {
745 static_assert(std::is_base_of<Decl, T>::value ||
746 std::is_base_of<Stmt, T>::value ||
747 std::is_base_of<NestedNameSpecifier, T>::value ||
748 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
749 std::is_base_of<TypeLoc, T>::value ||
750 std::is_base_of<QualType, T>::value ||
751 std::is_base_of<Attr, T>::value,
752 "unsupported type for recursive matching");
757 template <
typename T>
758 bool matchesDescendantOf(
const T &
Node,
const DynTypedMatcher &Matcher,
759 BoundNodesTreeBuilder *Builder, BindKind Bind) {
760 static_assert(std::is_base_of<Decl, T>::value ||
761 std::is_base_of<Stmt, T>::value ||
762 std::is_base_of<NestedNameSpecifier, T>::value ||
763 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
764 std::is_base_of<TypeLoc, T>::value ||
765 std::is_base_of<QualType, T>::value ||
766 std::is_base_of<Attr, T>::value,
767 "unsupported type for recursive matching");
769 Matcher, Builder, Bind);
773 template <
typename T>
774 bool matchesAncestorOf(
const T &
Node,
const DynTypedMatcher &Matcher,
775 BoundNodesTreeBuilder *Builder,
776 AncestorMatchMode MatchMode) {
777 static_assert(std::is_base_of<Decl, T>::value ||
778 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
779 std::is_base_of<Stmt, T>::value ||
780 std::is_base_of<TypeLoc, T>::value ||
781 std::is_base_of<Attr, T>::value,
782 "type not allowed for recursive matching");
784 Matcher, Builder, MatchMode);
787 virtual ASTContext &getASTContext()
const = 0;
789 virtual bool IsMatchingInASTNodeNotSpelledInSource()
const = 0;
791 virtual bool IsMatchingInASTNodeNotAsIs()
const = 0;
793 bool isTraversalIgnoringImplicitNodes()
const;
797 const DynTypedMatcher &Matcher,
798 BoundNodesTreeBuilder *Builder,
802 const DynTypedMatcher &Matcher,
803 BoundNodesTreeBuilder *Builder,
807 const DynTypedMatcher &Matcher,
808 BoundNodesTreeBuilder *Builder,
809 AncestorMatchMode MatchMode) = 0;
811 friend struct ASTChildrenNotSpelledInSourceScope;
812 virtual bool isMatchingChildrenNotSpelledInSource()
const = 0;
813 virtual void setMatchingChildrenNotSpelledInSource(
bool Set) = 0;
816 struct ASTChildrenNotSpelledInSourceScope {
817 ASTChildrenNotSpelledInSourceScope(ASTMatchFinder *
V,
bool B)
818 : MV(
V), MB(
V->isMatchingChildrenNotSpelledInSource()) {
819 V->setMatchingChildrenNotSpelledInSource(B);
821 ~ASTChildrenNotSpelledInSourceScope() {
822 MV->setMatchingChildrenNotSpelledInSource(MB);
835 inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>()
const {
836 assert(canConvertTo<QualType>());
837 const ASTNodeKind SourceKind = getSupportedKind();
838 if (SourceKind.isSame(ASTNodeKind::getFromNodeKind<Type>())) {
840 return unconditionalConvertTo<Type>();
842 return unconditionalConvertTo<QualType>();
846 template <
typename MatcherT,
typename IteratorT>
847 IteratorT matchesFirstInRange(
const MatcherT &Matcher, IteratorT Start,
848 IteratorT
End, ASTMatchFinder *Finder,
849 BoundNodesTreeBuilder *Builder) {
850 for (IteratorT I = Start; I !=
End; ++I) {
851 BoundNodesTreeBuilder Result(*Builder);
852 if (Matcher.matches(*I, Finder, &Result)) {
853 *Builder = std::move(Result);
862 template <
typename MatcherT,
typename IteratorT>
863 IteratorT matchesFirstInPointerRange(
const MatcherT &Matcher, IteratorT Start,
864 IteratorT
End, ASTMatchFinder *Finder,
865 BoundNodesTreeBuilder *Builder) {
866 for (IteratorT I = Start; I !=
End; ++I) {
867 BoundNodesTreeBuilder Result(*Builder);
868 if (Matcher.matches(**I, Finder, &Result)) {
869 *Builder = std::move(Result);
876 template <typename T, std::enable_if_t<!std::is_base_of<FunctionDecl, T>::value>
878 inline bool isDefaultedHelper(
const T *) {
881 inline bool isDefaultedHelper(
const FunctionDecl *FD) {
882 return FD->isDefaulted();
886 template <
typename Ty>
891 template <
typename Inner>
892 static yes& test(Inner *I, decltype(I->getDecl()) * =
nullptr);
895 static no& test(...);
898 static const bool value =
sizeof(test<Ty>(
nullptr)) ==
sizeof(yes);
905 template <
typename T,
typename ArgT>
906 class HasOverloadedOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
907 static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
908 std::is_base_of<FunctionDecl, T>::value,
909 "unsupported class for matcher");
910 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
911 "argument type must be std::vector<std::string>");
914 explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names)
915 : SingleNodeMatcherInterface<T>(), Names(
std::move(Names)) {}
917 bool matchesNode(
const T &
Node)
const override {
918 return matchesSpecialized(
Node);
926 bool matchesSpecialized(
const CXXOperatorCallExpr &
Node)
const {
932 bool matchesSpecialized(
const FunctionDecl &
Node)
const {
933 return Node.isOverloadedOperator() &&
938 std::vector<std::string> Names;
944 class HasNameMatcher :
public SingleNodeMatcherInterface<NamedDecl> {
946 explicit HasNameMatcher(std::vector<std::string> Names);
948 bool matchesNode(
const NamedDecl &
Node)
const override;
955 bool matchesNodeUnqualified(
const NamedDecl &
Node)
const;
963 bool matchesNodeFullFast(
const NamedDecl &
Node)
const;
970 bool matchesNodeFullSlow(
const NamedDecl &
Node)
const;
972 bool UseUnqualifiedMatch;
973 std::vector<std::string> Names;
978 Matcher<NamedDecl>
hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs);
983 ArrayRef<const StringRef *> NameRefs);
989 template <
typename T,
typename DeclMatcherT>
990 class HasDeclarationMatcher :
public MatcherInterface<T> {
991 static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
992 "instantiated with wrong types");
994 DynTypedMatcher InnerMatcher;
997 explicit HasDeclarationMatcher(
const Matcher<Decl> &InnerMatcher)
998 : InnerMatcher(InnerMatcher) {}
1000 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1001 BoundNodesTreeBuilder *Builder)
const override {
1002 return matchesSpecialized(
Node, Finder, Builder);
1007 bool matchesSpecialized(
const QualType &
Node, ASTMatchFinder *Finder,
1008 BoundNodesTreeBuilder *Builder)
const {
1012 return matchesSpecialized(*
Node, Finder, Builder);
1017 bool matchesSpecialized(
const Type &
Node, ASTMatchFinder *Finder,
1018 BoundNodesTreeBuilder *Builder)
const {
1021 if (
const auto *S = dyn_cast<DeducedType>(&
Node)) {
1022 QualType DT = S->getDeducedType();
1023 return !DT.isNull() ? matchesSpecialized(*DT, Finder, Builder) :
false;
1028 if (
const auto *S = dyn_cast<TagType>(&
Node)) {
1029 return matchesDecl(S->getDecl(), Finder, Builder);
1031 if (
const auto *S = dyn_cast<InjectedClassNameType>(&
Node)) {
1032 return matchesDecl(S->getDecl(), Finder, Builder);
1034 if (
const auto *S = dyn_cast<TemplateTypeParmType>(&
Node)) {
1035 return matchesDecl(S->getDecl(), Finder, Builder);
1037 if (
const auto *S = dyn_cast<TypedefType>(&
Node)) {
1038 return matchesDecl(S->getDecl(), Finder, Builder);
1040 if (
const auto *S = dyn_cast<UnresolvedUsingType>(&
Node)) {
1041 return matchesDecl(S->getDecl(), Finder, Builder);
1043 if (
const auto *S = dyn_cast<ObjCObjectType>(&
Node)) {
1044 return matchesDecl(S->getInterface(), Finder, Builder);
1055 if (
const auto *S = dyn_cast<SubstTemplateTypeParmType>(&
Node)) {
1056 return matchesSpecialized(S->getReplacementType(), Finder, Builder);
1062 if (
const auto *S = dyn_cast<TemplateSpecializationType>(&
Node)) {
1063 if (!S->isTypeAlias() && S->isSugared()) {
1070 return matchesSpecialized(*S->desugar(), Finder, Builder);
1074 return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder,
1081 if (
const auto *S = dyn_cast<ElaboratedType>(&
Node)) {
1082 return matchesSpecialized(S->desugar(), Finder, Builder);
1087 if (
const auto *S = dyn_cast<UsingType>(&
Node)) {
1088 return matchesSpecialized(S->desugar(), Finder, Builder);
1095 bool matchesSpecialized(
const DeclRefExpr &
Node, ASTMatchFinder *Finder,
1096 BoundNodesTreeBuilder *Builder)
const {
1097 return matchesDecl(
Node.getDecl(), Finder, Builder);
1102 bool matchesSpecialized(
const CallExpr &
Node, ASTMatchFinder *Finder,
1103 BoundNodesTreeBuilder *Builder)
const {
1104 return matchesDecl(
Node.getCalleeDecl(), Finder, Builder);
1109 bool matchesSpecialized(
const CXXConstructExpr &
Node,
1110 ASTMatchFinder *Finder,
1111 BoundNodesTreeBuilder *Builder)
const {
1112 return matchesDecl(
Node.getConstructor(), Finder, Builder);
1115 bool matchesSpecialized(
const ObjCIvarRefExpr &
Node,
1116 ASTMatchFinder *Finder,
1117 BoundNodesTreeBuilder *Builder)
const {
1118 return matchesDecl(
Node.getDecl(), Finder, Builder);
1123 bool matchesSpecialized(
const CXXNewExpr &
Node,
1124 ASTMatchFinder *Finder,
1125 BoundNodesTreeBuilder *Builder)
const {
1126 return matchesDecl(
Node.getOperatorNew(), Finder, Builder);
1131 bool matchesSpecialized(
const MemberExpr &
Node,
1132 ASTMatchFinder *Finder,
1133 BoundNodesTreeBuilder *Builder)
const {
1134 return matchesDecl(
Node.getMemberDecl(), Finder, Builder);
1139 bool matchesSpecialized(
const AddrLabelExpr &
Node,
1140 ASTMatchFinder *Finder,
1141 BoundNodesTreeBuilder *Builder)
const {
1142 return matchesDecl(
Node.getLabel(), Finder, Builder);
1147 bool matchesSpecialized(
const LabelStmt &
Node, ASTMatchFinder *Finder,
1148 BoundNodesTreeBuilder *Builder)
const {
1149 return matchesDecl(
Node.getDecl(), Finder, Builder);
1154 bool matchesDecl(
const Decl *
Node, ASTMatchFinder *Finder,
1155 BoundNodesTreeBuilder *Builder)
const {
1156 return Node !=
nullptr &&
1157 !(Finder->isTraversalIgnoringImplicitNodes() &&
1158 Node->isImplicit()) &&
1166 template <
typename T>
1168 static const bool value =
1169 std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value ||
1170 std::is_same<T, QualType>::value || std::is_same<T, Type>::value ||
1171 std::is_same<T, TypeLoc>::value ||
1172 std::is_same<T, NestedNameSpecifier>::value ||
1173 std::is_same<T, NestedNameSpecifierLoc>::value ||
1174 std::is_same<T, CXXCtorInitializer>::value ||
1175 std::is_same<T, TemplateArgumentLoc>::value ||
1176 std::is_same<T, Attr>::value;
1178 template <
typename T>
1179 const bool IsBaseType<T>::value;
1184 using AllNodeBaseTypes =
1185 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
1186 Type, TypeLoc, CXXCtorInitializer, Attr>;
1192 template <
class T>
struct ExtractFunctionArgMeta;
1193 template <
class T>
struct ExtractFunctionArgMeta<void(T)> {
1198 constexpr T *new_from_tuple_impl(Tuple &&t, std::index_sequence<I...>) {
1199 return new T(std::get<I>(std::forward<Tuple>(t))...);
1202 template <
class T,
class Tuple> constexpr T *new_from_tuple(Tuple &&t) {
1203 return new_from_tuple_impl<T>(
1204 std::forward<Tuple>(t),
1205 std::make_index_sequence<
1206 std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
1210 using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
1211 using AdaptativeDefaultToTypes =
1212 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
1216 using HasDeclarationSupportedTypes =
1217 TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
1218 ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
1219 MemberExpr, QualType, RecordType, TagType,
1220 TemplateSpecializationType, TemplateTypeParmType, TypedefType,
1221 UnresolvedUsingType, ObjCIvarRefExpr>;
1227 template <
typename T>
class BindableMatcher :
public Matcher<T> {
1229 explicit BindableMatcher(
const Matcher<T> &M) : Matcher<T>(M) {}
1230 explicit BindableMatcher(MatcherInterface<T> *Implementation)
1231 : Matcher<T>(Implementation) {}
1237 Matcher<T> bind(StringRef
ID)
const {
1238 return DynTypedMatcher(*
this)
1240 ->template unconditionalConvertTo<T>();
1245 operator DynTypedMatcher()
const {
1246 DynTypedMatcher Result =
static_cast<const Matcher<T> &
>(*this);
1247 Result.setAllowBind(
true);
1258 using ReturnTypes = AllNodeBaseTypes;
1260 template <
typename T>
operator Matcher<T>()
const {
1261 return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
1262 .template unconditionalConvertTo<T>();
1267 template <
typename T>
1269 makeAllOfComposite(ArrayRef<
const Matcher<T> *> InnerMatchers) {
1271 if (InnerMatchers.empty()) {
1272 return BindableMatcher<T>(TrueMatcher());
1276 if (InnerMatchers.size() == 1) {
1277 return BindableMatcher<T>(*InnerMatchers[0]);
1280 using PI = llvm::pointee_iterator<const Matcher<T> *
const *>;
1282 std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
1283 PI(InnerMatchers.end()));
1284 return BindableMatcher<T>(
1285 DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
1286 ASTNodeKind::getFromNodeKind<T>(),
1287 std::move(DynMatchers))
1288 .
template unconditionalConvertTo<T>());
1297 template <
typename T,
typename InnerT>
1299 makeDynCastAllOfComposite(ArrayRef<
const Matcher<InnerT> *> InnerMatchers) {
1300 return BindableMatcher<T>(
1301 makeAllOfComposite(InnerMatchers).
template dynCastTo<T>());
1315 template <
typename SourceT,
typename TargetT>
1316 class VariadicDynCastAllOfMatcher
1317 :
public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
1318 makeDynCastAllOfComposite<SourceT, TargetT>> {
1320 VariadicDynCastAllOfMatcher() {}
1333 template <
typename T>
1334 class VariadicAllOfMatcher
1335 :
public VariadicFunction<BindableMatcher<T>, Matcher<T>,
1336 makeAllOfComposite<T>> {
1338 VariadicAllOfMatcher() {}
1350 template <
typename... Ps>
class VariadicOperatorMatcher {
1352 VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
1353 : Op(Op), Params(
std::forward<Ps>(Params)...) {}
1355 template <
typename T>
operator Matcher<T>() const & {
1356 return DynTypedMatcher::constructVariadic(
1357 Op, ASTNodeKind::getFromNodeKind<T>(),
1358 getMatchers<T>(std::index_sequence_for<Ps...>()))
1359 .template unconditionalConvertTo<T>();
1362 template <
typename T>
operator Matcher<T>() && {
1363 return DynTypedMatcher::constructVariadic(
1364 Op, ASTNodeKind::getFromNodeKind<T>(),
1365 getMatchers<T>(std::index_sequence_for<Ps...>()))
1366 .template unconditionalConvertTo<T>();
1372 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>)
const & {
1373 return {Matcher<T>(std::get<Is>(Params))...};
1377 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) && {
1378 return {Matcher<T>(std::get<Is>(std::move(Params)))...};
1381 const DynTypedMatcher::VariadicOperator Op;
1382 std::tuple<Ps...> Params;
1387 template <
unsigned MinCount,
unsigned MaxCount>
1388 struct VariadicOperatorMatcherFunc {
1389 DynTypedMatcher::VariadicOperator Op;
1391 template <
typename... Ms>
1392 VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps)
const {
1393 static_assert(MinCount <=
sizeof...(Ms) &&
sizeof...(Ms) <= MaxCount,
1394 "invalid number of parameters for variadic matcher");
1395 return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
1399 template <
typename F,
typename Tuple,
std::size_t... I>
1400 constexpr
auto applyMatcherImpl(F &&f, Tuple &&args,
1401 std::index_sequence<I...>) {
1402 return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
1405 template <
typename F,
typename Tuple>
1406 constexpr
auto applyMatcher(F &&f, Tuple &&args) {
1407 return applyMatcherImpl(
1408 std::forward<F>(f), std::forward<Tuple>(args),
1409 std::make_index_sequence<
1413 template <
typename T,
bool IsBaseOf,
typename Head,
typename Tail>
1414 struct GetCladeImpl {
1417 template <
typename T,
typename Head,
typename Tail>
1418 struct GetCladeImpl<T,
false, Head, Tail>
1419 : GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
1420 typename Tail::head, typename Tail::tail> {};
1422 template <
typename T,
typename...
U>
1423 struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
1425 template <
typename CladeType,
typename... MatcherTypes>
1426 struct MapAnyOfMatcherImpl {
1428 template <
typename... InnerMatchers>
1429 BindableMatcher<CladeType>
1430 operator()(InnerMatchers &&... InnerMatcher)
const {
1432 return VariadicAllOfMatcher<CladeType>()(applyMatcher(
1433 internal::VariadicOperatorMatcherFunc<
1435 internal::DynTypedMatcher::VO_AnyOf},
1437 [&](
auto... Matcher) {
1438 return std::make_tuple(Matcher(InnerMatcher...)...);
1441 VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
1445 template <
typename... MatcherTypes>
1446 using MapAnyOfMatcher =
1447 MapAnyOfMatcherImpl<
typename GetClade<MatcherTypes...>::Type,
1450 template <
typename... MatcherTypes>
struct MapAnyOfHelper {
1451 using CladeType =
typename GetClade<MatcherTypes...>::Type;
1453 MapAnyOfMatcher<MatcherTypes...> with;
1455 operator BindableMatcher<CladeType>()
const {
return with(); }
1457 Matcher<CladeType> bind(StringRef
ID)
const {
return with().bind(
ID); }
1460 template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1461 typename T,
typename ToTypes>
1462 class ArgumentAdaptingMatcherFuncAdaptor {
1464 explicit ArgumentAdaptingMatcherFuncAdaptor(
const Matcher<T> &InnerMatcher)
1465 : InnerMatcher(InnerMatcher) {}
1467 using ReturnTypes = ToTypes;
1469 template <
typename To>
operator Matcher<To>() const & {
1470 return Matcher<To>(
new ArgumentAdapterT<To, T>(InnerMatcher));
1473 template <
typename To>
operator Matcher<To>() && {
1474 return Matcher<To>(
new ArgumentAdapterT<To, T>(std::move(InnerMatcher)));
1478 Matcher<T> InnerMatcher;
1494 template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1495 typename FromTypes = AdaptativeDefaultFromTypes,
1496 typename ToTypes = AdaptativeDefaultToTypes>
1497 struct ArgumentAdaptingMatcherFunc {
1498 template <
typename T>
1499 static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1500 create(
const Matcher<T> &InnerMatcher) {
1501 return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>(
1505 template <
typename T>
1506 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1507 operator()(
const Matcher<T> &InnerMatcher)
const {
1508 return create(InnerMatcher);
1511 template <
typename... T>
1512 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT,
1513 typename GetClade<T...>::Type, ToTypes>
1514 operator()(
const MapAnyOfHelper<T...> &InnerMatcher)
const {
1515 return create(InnerMatcher.with());
1519 template <
typename T>
class TraversalMatcher :
public MatcherInterface<T> {
1520 DynTypedMatcher InnerMatcher;
1525 const Matcher<T> &InnerMatcher)
1526 : InnerMatcher(InnerMatcher),
Traversal(TK) {}
1528 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1529 BoundNodesTreeBuilder *Builder)
const override {
1535 if (
auto NestedKind = this->InnerMatcher.getTraversalKind())
1541 template <
typename MatcherType>
class TraversalWrapper {
1543 TraversalWrapper(
TraversalKind TK,
const MatcherType &InnerMatcher)
1544 : TK(TK), InnerMatcher(InnerMatcher) {}
1546 template <
typename T>
operator Matcher<T>() const & {
1547 return internal::DynTypedMatcher::constructRestrictedWrapper(
1548 new internal::TraversalMatcher<T>(TK, InnerMatcher),
1549 ASTNodeKind::getFromNodeKind<T>())
1550 .template unconditionalConvertTo<T>();
1553 template <
typename T>
operator Matcher<T>() && {
1554 return internal::DynTypedMatcher::constructRestrictedWrapper(
1555 new internal::TraversalMatcher<T>(TK, std::move(InnerMatcher)),
1556 ASTNodeKind::getFromNodeKind<T>())
1557 .template unconditionalConvertTo<T>();
1562 MatcherType InnerMatcher;
1577 template <
template <
typename T,
typename... Params>
class MatcherT,
1578 typename ReturnTypesF, typename... ParamTypes>
1579 class PolymorphicMatcher {
1581 PolymorphicMatcher(
const ParamTypes &... Params) : Params(Params...) {}
1585 template <
typename T>
operator Matcher<T>() const & {
1586 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1587 "right polymorphic conversion");
1588 return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params));
1591 template <
typename T>
operator Matcher<T>() && {
1592 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1593 "right polymorphic conversion");
1595 new_from_tuple<MatcherT<T, ParamTypes...>>(std::move(Params)));
1599 std::tuple<ParamTypes...> Params;
1606 template <
typename T,
typename ChildT>
1607 class HasMatcher :
public MatcherInterface<T> {
1608 DynTypedMatcher InnerMatcher;
1611 explicit HasMatcher(
const Matcher<ChildT> &InnerMatcher)
1612 : InnerMatcher(InnerMatcher) {}
1614 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1615 BoundNodesTreeBuilder *Builder)
const override {
1616 return Finder->matchesChildOf(
Node, this->InnerMatcher, Builder,
1617 ASTMatchFinder::BK_First);
1626 template <
typename T,
typename ChildT>
1627 class ForEachMatcher :
public MatcherInterface<T> {
1628 static_assert(IsBaseType<ChildT>::value,
1629 "for each only accepts base type matcher");
1631 DynTypedMatcher InnerMatcher;
1634 explicit ForEachMatcher(
const Matcher<ChildT> &InnerMatcher)
1635 : InnerMatcher(InnerMatcher) {}
1637 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1638 BoundNodesTreeBuilder *Builder)
const override {
1639 return Finder->matchesChildOf(
1640 Node, this->InnerMatcher, Builder,
1641 ASTMatchFinder::BK_All);
1647 template <
typename T>
1648 inline Matcher<T> DynTypedMatcher::unconditionalConvertTo()
const {
1649 return Matcher<T>(*
this);
1656 template <
typename T,
typename DescendantT>
1657 class HasDescendantMatcher :
public MatcherInterface<T> {
1658 static_assert(IsBaseType<DescendantT>::value,
1659 "has descendant only accepts base type matcher");
1661 DynTypedMatcher DescendantMatcher;
1664 explicit HasDescendantMatcher(
const Matcher<DescendantT> &DescendantMatcher)
1665 : DescendantMatcher(DescendantMatcher) {}
1667 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1668 BoundNodesTreeBuilder *Builder)
const override {
1669 return Finder->matchesDescendantOf(
Node, this->DescendantMatcher, Builder,
1670 ASTMatchFinder::BK_First);
1678 template <
typename T,
typename ParentT>
1679 class HasParentMatcher :
public MatcherInterface<T> {
1680 static_assert(IsBaseType<ParentT>::value,
1681 "has parent only accepts base type matcher");
1683 DynTypedMatcher ParentMatcher;
1686 explicit HasParentMatcher(
const Matcher<ParentT> &ParentMatcher)
1687 : ParentMatcher(ParentMatcher) {}
1689 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1690 BoundNodesTreeBuilder *Builder)
const override {
1691 return Finder->matchesAncestorOf(
Node, this->ParentMatcher, Builder,
1692 ASTMatchFinder::AMM_ParentOnly);
1700 template <
typename T,
typename AncestorT>
1701 class HasAncestorMatcher :
public MatcherInterface<T> {
1702 static_assert(IsBaseType<AncestorT>::value,
1703 "has ancestor only accepts base type matcher");
1705 DynTypedMatcher AncestorMatcher;
1708 explicit HasAncestorMatcher(
const Matcher<AncestorT> &AncestorMatcher)
1709 : AncestorMatcher(AncestorMatcher) {}
1711 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1712 BoundNodesTreeBuilder *Builder)
const override {
1713 return Finder->matchesAncestorOf(
Node, this->AncestorMatcher, Builder,
1714 ASTMatchFinder::AMM_All);
1724 template <
typename T,
typename DescendantT>
1725 class ForEachDescendantMatcher :
public MatcherInterface<T> {
1726 static_assert(IsBaseType<DescendantT>::value,
1727 "for each descendant only accepts base type matcher");
1729 DynTypedMatcher DescendantMatcher;
1732 explicit ForEachDescendantMatcher(
1733 const Matcher<DescendantT> &DescendantMatcher)
1734 : DescendantMatcher(DescendantMatcher) {}
1736 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1737 BoundNodesTreeBuilder *Builder)
const override {
1738 return Finder->matchesDescendantOf(
Node, this->DescendantMatcher, Builder,
1739 ASTMatchFinder::BK_All);
1745 template <
typename T,
typename ValueT>
1746 class ValueEqualsMatcher :
public SingleNodeMatcherInterface<T> {
1747 static_assert(std::is_base_of<CharacterLiteral, T>::value ||
1748 std::is_base_of<CXXBoolLiteralExpr, T>::value ||
1749 std::is_base_of<FloatingLiteral, T>::value ||
1750 std::is_base_of<IntegerLiteral, T>::value,
1751 "the node must have a getValue method");
1754 explicit ValueEqualsMatcher(
const ValueT &ExpectedValue)
1755 : ExpectedValue(ExpectedValue) {}
1757 bool matchesNode(
const T &
Node)
const override {
1758 return Node.getValue() == ExpectedValue;
1762 ValueT ExpectedValue;
1768 inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
1769 const FloatingLiteral &
Node)
const {
1770 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1771 return Node.getValue().convertToFloat() == ExpectedValue;
1772 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1773 return Node.getValue().convertToDouble() == ExpectedValue;
1777 inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
1778 const FloatingLiteral &
Node)
const {
1779 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1780 return Node.getValue().convertToFloat() == ExpectedValue;
1781 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1782 return Node.getValue().convertToDouble() == ExpectedValue;
1786 inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
1787 const FloatingLiteral &
Node)
const {
1788 return ExpectedValue.compare(
Node.getValue()) == llvm::APFloat::cmpEqual;
1793 template <
typename TLoc,
typename T>
1794 class LocMatcher :
public MatcherInterface<TLoc> {
1795 DynTypedMatcher InnerMatcher;
1798 explicit LocMatcher(
const Matcher<T> &InnerMatcher)
1799 : InnerMatcher(InnerMatcher) {}
1801 bool matches(
const TLoc &
Node, ASTMatchFinder *Finder,
1802 BoundNodesTreeBuilder *Builder)
const override {
1805 return this->InnerMatcher.matches(extract(
Node), Finder, Builder);
1809 static DynTypedNode extract(
const NestedNameSpecifierLoc &Loc) {
1818 class TypeLocTypeMatcher :
public MatcherInterface<TypeLoc> {
1819 DynTypedMatcher InnerMatcher;
1822 explicit TypeLocTypeMatcher(
const Matcher<QualType> &InnerMatcher)
1823 : InnerMatcher(InnerMatcher) {}
1825 bool matches(
const TypeLoc &
Node, ASTMatchFinder *Finder,
1826 BoundNodesTreeBuilder *Builder)
const override {
1837 template <
typename T>
class TypeTraverseMatcher :
public MatcherInterface<T> {
1838 DynTypedMatcher InnerMatcher;
1841 explicit TypeTraverseMatcher(
const Matcher<QualType> &InnerMatcher,
1842 QualType (T::*TraverseFunction)()
const)
1843 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1845 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1846 BoundNodesTreeBuilder *Builder)
const override {
1847 QualType NextNode = (
Node.*TraverseFunction)();
1848 if (NextNode.isNull())
1855 QualType (T::*TraverseFunction)()
const;
1861 template <
typename T>
1862 class TypeLocTraverseMatcher :
public MatcherInterface<T> {
1863 DynTypedMatcher InnerMatcher;
1866 explicit TypeLocTraverseMatcher(
const Matcher<TypeLoc> &InnerMatcher,
1867 TypeLoc (T::*TraverseFunction)()
const)
1868 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1870 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1871 BoundNodesTreeBuilder *Builder)
const override {
1872 TypeLoc NextNode = (
Node.*TraverseFunction)();
1880 TypeLoc (T::*TraverseFunction)()
const;
1889 template <
typename InnerTBase,
1890 template <
typename OuterT>
class Getter,
1891 template <
typename OuterT>
class MatcherImpl,
1892 typename ReturnTypesF>
1893 class TypeTraversePolymorphicMatcher {
1895 using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
1898 static Self
create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers);
1903 explicit TypeTraversePolymorphicMatcher(
1904 ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers)
1905 : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
1907 template <
typename OuterT>
operator Matcher<OuterT>()
const {
1908 return Matcher<OuterT>(
1909 new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
1913 :
public VariadicFunction<Self, Matcher<InnerTBase>, &Self::create> {
1918 Matcher<InnerTBase> InnerMatcher;
1925 template <
typename Matcher, Matcher (*Func)()>
class MemoizedMatcher {
1927 Wrapper() : M(Func()) {}
1933 static const Matcher &getInstance() {
1934 static llvm::ManagedStatic<Wrapper> Instance;
1942 template <
typename InnerTBase,
template <
typename OuterT>
class Getter,
1943 template <
typename OuterT>
class MatcherImpl,
typename ReturnTypesF>
1944 TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
1945 TypeTraversePolymorphicMatcher<
1946 InnerTBase, Getter, MatcherImpl,
1947 ReturnTypesF>
::create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers) {
1948 return Self(InnerMatchers);
1953 inline ArrayRef<TemplateArgument>
1954 getTemplateSpecializationArgs(
const ClassTemplateSpecializationDecl &D) {
1955 return D.getTemplateArgs().asArray();
1958 inline ArrayRef<TemplateArgument>
1959 getTemplateSpecializationArgs(
const TemplateSpecializationType &T) {
1960 return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
1963 inline ArrayRef<TemplateArgument>
1964 getTemplateSpecializationArgs(
const FunctionDecl &FD) {
1965 if (
const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
1966 return TemplateArgs->asArray();
1967 return ArrayRef<TemplateArgument>();
1970 struct NotEqualsBoundNodePredicate {
1971 bool operator()(
const internal::BoundNodesMap &
Nodes)
const {
1979 template <
typename Ty,
typename Enable =
void>
struct GetBodyMatcher {
1980 static const Stmt *get(
const Ty &
Node) {
return Node.getBody(); }
1983 template <
typename Ty>
1984 struct GetBodyMatcher<Ty, typename
std::enable_if<
1985 std::is_base_of<FunctionDecl, Ty>::value>
::type> {
1986 static const Stmt *get(
const Ty &
Node) {
1987 return Node.doesThisDeclarationHaveABody() ?
Node.getBody() :
nullptr;
1991 template <
typename NodeType>
1993 equivalentBinaryOperator(
const NodeType &
Node) {
1994 return Node.getOpcode();
1999 equivalentBinaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2000 if (
Node.getNumArgs() != 2)
2002 switch (
Node.getOperator()) {
2019 case OO_GreaterGreater:
2029 case OO_GreaterEqual:
2033 case OO_ExclaimEqual:
2048 return BO_MulAssign;
2050 return BO_DivAssign;
2051 case OO_PercentEqual:
2052 return BO_RemAssign;
2054 return BO_AddAssign;
2056 return BO_SubAssign;
2057 case OO_LessLessEqual:
2058 return BO_ShlAssign;
2059 case OO_GreaterGreaterEqual:
2060 return BO_ShrAssign;
2062 return BO_AndAssign;
2064 return BO_XorAssign;
2072 template <
typename NodeType>
2074 equivalentUnaryOperator(
const NodeType &
Node) {
2075 return Node.getOpcode();
2080 equivalentUnaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2081 if (
Node.getNumArgs() != 1 &&
Node.getOperator() != OO_PlusPlus &&
2082 Node.getOperator() != OO_MinusMinus)
2084 switch (
Node.getOperator()) {
2100 const auto *FD =
Node.getDirectCallee();
2103 return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
2105 case OO_MinusMinus: {
2106 const auto *FD =
Node.getDirectCallee();
2109 return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
2116 template <
typename NodeType>
inline const Expr *getLHS(
const NodeType &
Node) {
2117 return Node.getLHS();
2121 getLHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2122 if (!internal::equivalentBinaryOperator(
Node))
2124 return Node.getArg(0);
2126 template <
typename NodeType>
inline const Expr *getRHS(
const NodeType &
Node) {
2127 return Node.getRHS();
2131 getRHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2132 if (!internal::equivalentBinaryOperator(
Node))
2134 return Node.getArg(1);
2136 template <
typename NodeType>
2137 inline const Expr *getSubExpr(
const NodeType &
Node) {
2138 return Node.getSubExpr();
2142 getSubExpr<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2143 if (!internal::equivalentUnaryOperator(
Node))
2145 return Node.getArg(0);
2148 template <
typename Ty>
2149 struct HasSizeMatcher {
2150 static bool hasSize(
const Ty &
Node,
unsigned int N) {
2151 return Node.getSize() == N;
2156 inline bool HasSizeMatcher<StringLiteral>::hasSize(
2157 const StringLiteral &
Node,
unsigned int N) {
2158 return Node.getLength() == N;
2161 template <
typename Ty>
2162 struct GetSourceExpressionMatcher {
2163 static const Expr *get(
const Ty &
Node) {
2164 return Node.getSubExpr();
2169 inline const Expr *GetSourceExpressionMatcher<OpaqueValueExpr>::get(
2170 const OpaqueValueExpr &
Node) {
2171 return Node.getSourceExpr();
2174 template <
typename Ty>
2175 struct CompoundStmtMatcher {
2176 static const CompoundStmt *get(
const Ty &
Node) {
2182 inline const CompoundStmt *
2183 CompoundStmtMatcher<StmtExpr>::get(
const StmtExpr &
Node) {
2184 return Node.getSubStmt();
2193 const ASTContext &Context);
2196 return Node.getOpcodeStr(
Node.getOpcode());
2199 return Node.getOpcodeStr();
2201 inline StringRef getOpName(
const CXXRewrittenBinaryOperator &
Node) {
2202 return Node.getOpcodeStr();
2205 auto optBinaryOpcode = equivalentBinaryOperator(
Node);
2206 if (!optBinaryOpcode) {
2207 auto optUnaryOpcode = equivalentUnaryOperator(
Node);
2208 if (!optUnaryOpcode)
2219 template <
typename T,
typename ArgT = std::vector<std::
string>>
2220 class HasAnyOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
2221 static_assert(std::is_same<T, BinaryOperator>::value ||
2222 std::is_same<T, CXXOperatorCallExpr>::value ||
2223 std::is_same<T, CXXRewrittenBinaryOperator>::value ||
2224 std::is_same<T, UnaryOperator>::value,
2225 "Matcher only supports `BinaryOperator`, `UnaryOperator`, "
2226 "`CXXOperatorCallExpr` and `CXXRewrittenBinaryOperator`");
2227 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
2228 "Matcher ArgT must be std::vector<std::string>");
2231 explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names)
2232 : SingleNodeMatcherInterface<T>(), Names(
std::move(Names)) {}
2234 bool matchesNode(
const T &
Node)
const override {
2236 return OptOpName && llvm::is_contained(Names, *OptOpName);
2241 return Node.getOpcodeStr(
Node.getOpcode());
2244 return Node.getOpcodeStr();
2246 static StringRef getOpName(
const CXXRewrittenBinaryOperator &
Node) {
2247 return Node.getOpcodeStr();
2250 auto optBinaryOpcode = equivalentBinaryOperator(
Node);
2251 if (!optBinaryOpcode) {
2252 auto optUnaryOpcode = equivalentUnaryOperator(
Node);
2253 if (!optUnaryOpcode)
2260 std::vector<std::string> Names;
2263 using HasOpNameMatcher =
2264 PolymorphicMatcher<HasAnyOperatorNameMatcher,
2266 TypeList<BinaryOperator, CXXOperatorCallExpr,
2267 CXXRewrittenBinaryOperator, UnaryOperator>),
2268 std::vector<std::string>>;
2272 using HasOverloadOpNameMatcher =
2273 PolymorphicMatcher<HasOverloadedOperatorNameMatcher,
2274 void(TypeList<CXXOperatorCallExpr, FunctionDecl>),
2275 std::vector<std::string>>;
2277 HasOverloadOpNameMatcher
2284 const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
2285 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder);
2288 llvm::Regex::RegexFlags Flags,
2292 MatchTemplateArgLocAt(
const DeclRefExpr &
Node,
unsigned int Index,
2293 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2294 internal::ASTMatchFinder *Finder,
2295 internal::BoundNodesTreeBuilder *Builder) {
2297 return Index < ArgLocs.size() &&
2298 InnerMatcher.matches(ArgLocs[Index], Finder, Builder);
2302 MatchTemplateArgLocAt(
const TemplateSpecializationTypeLoc &
Node,
2304 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2305 internal::ASTMatchFinder *Finder,
2306 internal::BoundNodesTreeBuilder *Builder) {
2307 return !
Node.isNull() && Index <
Node.getNumArgs() &&
2308 InnerMatcher.matches(
Node.getArgLoc(Index), Finder, Builder);
2317 #endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H