34#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
35#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
52#include "llvm/ADT/APFloat.h"
53#include "llvm/ADT/ArrayRef.h"
54#include "llvm/ADT/IntrusiveRefCntPtr.h"
55#include "llvm/ADT/STLExtras.h"
56#include "llvm/ADT/SmallVector.h"
57#include "llvm/ADT/StringRef.h"
58#include "llvm/ADT/iterator.h"
59#include "llvm/Support/Casting.h"
60#include "llvm/Support/ManagedStatic.h"
61#include "llvm/Support/Regex.h"
79namespace ast_matchers {
89template <
typename... Ts>
struct TypeList {};
91template <
typename T1,
typename... Ts>
struct TypeList<T1, Ts...> {
99 using tail = TypeList<Ts...>;
103using EmptyTypeList = TypeList<>;
107template <
typename AnyTypeList,
typename T>
struct TypeListContainsSuperOf {
108 static const bool value =
109 std::is_base_of<typename AnyTypeList::head, T>::value ||
110 TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value;
112template <
typename T>
struct TypeListContainsSuperOf<EmptyTypeList,
T> {
113 static const bool value =
false;
121template <
typename ResultT,
typename ArgT,
122 ResultT (*
Func)(ArrayRef<const ArgT *>)>
123struct VariadicFunction {
124 ResultT operator()()
const {
return Func(std::nullopt); }
126 template <
typename... ArgsT>
127 ResultT operator()(
const ArgT &Arg1,
const ArgsT &... Args)
const {
128 return Execute(Arg1,
static_cast<const ArgT &
>(Args)...);
133 ResultT operator()(ArrayRef<ArgT> Args)
const {
134 return Func(llvm::to_vector<8>(llvm::make_pointer_range(Args)));
140 template <
typename... ArgsT> ResultT Execute(
const ArgsT &... Args)
const {
141 const ArgT *
const ArgsArray[] = {&Args...};
142 return Func(ArrayRef<const ArgT *>(ArgsArray,
sizeof...(ArgsT)));
151 return Node.getType();
154 return Node.getUnderlyingType();
157 if (
const TypeSourceInfo *TSI =
Node.getFriendType())
158 return TSI->getType();
162 return Node.getType();
167 std::enable_if_t<TypeListContainsSuperOf<
168 TypeList<CXXBaseSpecifier, CXXCtorInitializer,
169 CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr,
170 CompoundLiteralExpr, DeclaratorDecl, ObjCPropertyDecl,
171 TemplateArgumentLoc, TypedefNameDecl>,
172 T>::value> * =
nullptr>
173inline TypeSourceInfo *GetTypeSourceInfo(
const T &
Node) {
174 return Node.getTypeSourceInfo();
177 std::enable_if_t<TypeListContainsSuperOf<
178 TypeList<CXXFunctionalCastExpr, ExplicitCastExpr>,
T>::value> * =
180inline TypeSourceInfo *GetTypeSourceInfo(
const T &
Node) {
181 return Node.getTypeInfoAsWritten();
183inline TypeSourceInfo *GetTypeSourceInfo(
const BlockDecl &
Node) {
184 return Node.getSignatureAsWritten();
186inline TypeSourceInfo *GetTypeSourceInfo(
const CXXNewExpr &
Node) {
187 return Node.getAllocatedTypeSourceInfo();
192inline const FunctionProtoType *
193getFunctionProtoType(
const FunctionProtoType &
Node) {
197inline const FunctionProtoType *getFunctionProtoType(
const FunctionDecl &
Node) {
198 return Node.getType()->getAs<FunctionProtoType>();
203 return Node.getAccess();
207 return Node.getAccessSpecifier();
216 void addNode(StringRef
ID,
const DynTypedNode &DynNode) {
217 NodeMap[std::string(
ID)] = DynNode;
224 template <
typename T>
225 const T *getNodeAs(StringRef
ID)
const {
226 IDToNodeMap::const_iterator It = NodeMap.find(
ID);
227 if (It == NodeMap.end()) {
230 return It->second.get<
T>();
234 IDToNodeMap::const_iterator It = NodeMap.find(
ID);
235 if (It == NodeMap.end()) {
242 bool operator<(
const BoundNodesMap &Other)
const {
243 return NodeMap <
Other.NodeMap;
251 using IDToNodeMap = std::map<std::string, DynTypedNode, std::less<>>;
253 const IDToNodeMap &getMap()
const {
259 bool isComparable()
const {
260 for (
const auto &IDAndNode : NodeMap) {
261 if (!IDAndNode.second.getMemoizationData())
275class BoundNodesTreeBuilder {
281 virtual ~Visitor() =
default;
286 virtual void visitMatch(
const BoundNodes& BoundNodesView) = 0;
290 void setBinding(StringRef
Id,
const DynTypedNode &DynNode) {
293 for (BoundNodesMap &Binding :
Bindings)
294 Binding.addNode(
Id, DynNode);
298 void addMatch(
const BoundNodesTreeBuilder &
Bindings);
303 void visitMatches(Visitor* ResultVisitor);
305 template <
typename ExcludePredicate>
306 bool removeBindings(
const ExcludePredicate &Predicate) {
307 llvm::erase_if(
Bindings, Predicate);
312 bool operator<(
const BoundNodesTreeBuilder &Other)
const {
318 bool isComparable()
const {
319 for (
const BoundNodesMap &NodesMap :
Bindings) {
320 if (!NodesMap.isComparable())
327 SmallVector<BoundNodesMap, 1>
Bindings;
337class DynMatcherInterface
338 :
public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
340 virtual ~DynMatcherInterface() =
default;
346 virtual bool dynMatches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
347 BoundNodesTreeBuilder *Builder)
const = 0;
349 virtual std::optional<clang::TraversalKind>
TraversalKind()
const {
362class MatcherInterface :
public DynMatcherInterface {
369 ASTMatchFinder *Finder,
370 BoundNodesTreeBuilder *Builder)
const = 0;
372 bool dynMatches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
373 BoundNodesTreeBuilder *Builder)
const override {
374 return matches(DynNode.getUnchecked<T>(), Finder, Builder);
381class SingleNodeMatcherInterface :
public MatcherInterface<T> {
386 virtual bool matchesNode(
const T &
Node)
const = 0;
392 BoundNodesTreeBuilder * )
const override {
393 return matchesNode(
Node);
397template <
typename>
class Matcher;
406class DynTypedMatcher {
409 template <
typename T>
410 DynTypedMatcher(MatcherInterface<T> *Implementation)
411 : SupportedKind(ASTNodeKind::getFromNodeKind<
T>()),
412 RestrictKind(SupportedKind), Implementation(Implementation) {}
415 enum VariadicOperator {
438 static DynTypedMatcher
439 constructVariadic(VariadicOperator Op, ASTNodeKind SupportedKind,
440 std::vector<DynTypedMatcher> InnerMatchers);
442 static DynTypedMatcher
443 constructRestrictedWrapper(
const DynTypedMatcher &InnerMatcher,
444 ASTNodeKind RestrictKind);
449 static DynTypedMatcher trueMatcher(ASTNodeKind NodeKind);
451 void setAllowBind(
bool AB) { AllowBind = AB; }
456 bool canMatchNodesOfKind(ASTNodeKind
Kind)
const;
460 DynTypedMatcher dynCastTo(
const ASTNodeKind
Kind)
const;
466 DynTypedMatcher withTraversalKind(TraversalKind TK);
469 bool matches(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
470 BoundNodesTreeBuilder *Builder)
const;
476 bool matchesNoKindCheck(
const DynTypedNode &DynNode, ASTMatchFinder *Finder,
477 BoundNodesTreeBuilder *Builder)
const;
482 std::optional<DynTypedMatcher> tryBind(StringRef
ID)
const;
491 using MatcherIDType = std::pair<ASTNodeKind, uint64_t>;
492 MatcherIDType getID()
const {
495 return std::make_pair(RestrictKind,
496 reinterpret_cast<uint64_t>(Implementation.get()));
503 ASTNodeKind getSupportedKind()
const {
return SupportedKind; }
510 template <
typename T>
bool canConvertTo()
const {
511 return canConvertTo(ASTNodeKind::getFromNodeKind<T>());
513 bool canConvertTo(ASTNodeKind To)
const;
520 template <
typename T> Matcher<T> convertTo()
const {
521 assert(canConvertTo<T>());
522 return unconditionalConvertTo<T>();
529 template <
typename T> Matcher<T> unconditionalConvertTo()
const;
535 std::optional<clang::TraversalKind> getTraversalKind()
const {
536 return Implementation->TraversalKind();
540 DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind,
541 IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
542 : SupportedKind(SupportedKind), RestrictKind(RestrictKind),
543 Implementation(
std::move(Implementation)) {}
545 bool AllowBind =
false;
546 ASTNodeKind SupportedKind;
552 ASTNodeKind RestrictKind;
553 IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
568 explicit Matcher(MatcherInterface<T> *Implementation)
569 : Implementation(Implementation) {}
574 template <
typename From>
575 Matcher(
const Matcher<From> &Other,
576 std::enable_if_t<std::is_base_of<From, T>::value &&
577 !std::is_same<From, T>::value> * =
nullptr)
578 : Implementation(restrictMatcher(
Other.Implementation)) {
579 assert(Implementation.getSupportedKind().isSame(
580 ASTNodeKind::getFromNodeKind<T>()));
586 template <
typename TypeT>
587 Matcher(
const Matcher<TypeT> &Other,
588 std::enable_if_t<std::is_same<T, QualType>::value &&
589 std::is_same<TypeT, Type>::value> * =
nullptr)
590 : Implementation(new TypeToQualType<TypeT>(
Other)) {}
595 template <
typename To> Matcher<To> dynCastTo() const & {
596 static_assert(std::is_base_of<To, T>::value,
"Invalid dynCast call.");
597 return Matcher<To>(Implementation);
600 template <
typename To> Matcher<To> dynCastTo() && {
601 static_assert(std::is_base_of<To, T>::value,
"Invalid dynCast call.");
602 return Matcher<To>(std::move(Implementation));
607 ASTMatchFinder *Finder,
608 BoundNodesTreeBuilder *Builder)
const {
609 return Implementation.matches(DynTypedNode::create(
Node), Finder, Builder);
613 DynTypedMatcher::MatcherIDType getID()
const {
614 return Implementation.getID();
621 operator DynTypedMatcher() const & {
return Implementation; }
623 operator DynTypedMatcher() && {
return std::move(Implementation); }
631 template <
typename TypeT>
632 class TypeToQualType :
public MatcherInterface<QualType> {
633 const DynTypedMatcher InnerMatcher;
636 TypeToQualType(
const Matcher<TypeT> &InnerMatcher)
637 : InnerMatcher(InnerMatcher) {}
639 bool matches(
const QualType &
Node, ASTMatchFinder *Finder,
640 BoundNodesTreeBuilder *Builder)
const override {
643 return this->InnerMatcher.matches(DynTypedNode::create(*
Node), Finder,
647 std::optional<clang::TraversalKind>
TraversalKind()
const override {
648 return this->InnerMatcher.getTraversalKind();
654 template <
typename U>
friend class Matcher;
657 friend class DynTypedMatcher;
659 static DynTypedMatcher restrictMatcher(
const DynTypedMatcher &Other) {
660 return Other.dynCastTo(ASTNodeKind::getFromNodeKind<T>());
663 explicit Matcher(
const DynTypedMatcher &Implementation)
664 : Implementation(restrictMatcher(Implementation)) {
665 assert(this->Implementation.getSupportedKind().isSame(
666 ASTNodeKind::getFromNodeKind<T>()));
669 DynTypedMatcher Implementation;
675inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
676 return Matcher<T>(Implementation);
697class ASTMatchFinder {
709 enum AncestorMatchMode {
717 virtual ~ASTMatchFinder() =
default;
723 virtual bool classIsDerivedFrom(
const CXXRecordDecl *Declaration,
724 const Matcher<NamedDecl> &
Base,
725 BoundNodesTreeBuilder *Builder,
732 virtual bool objcClassIsDerivedFrom(
const ObjCInterfaceDecl *Declaration,
733 const Matcher<NamedDecl> &
Base,
734 BoundNodesTreeBuilder *Builder,
737 template <
typename T>
738 bool matchesChildOf(
const T &
Node,
const DynTypedMatcher &Matcher,
739 BoundNodesTreeBuilder *Builder, BindKind Bind) {
740 static_assert(std::is_base_of<Decl, T>::value ||
741 std::is_base_of<Stmt, T>::value ||
742 std::is_base_of<NestedNameSpecifier, T>::value ||
743 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
744 std::is_base_of<TypeLoc, T>::value ||
745 std::is_base_of<QualType, T>::value ||
746 std::is_base_of<Attr, T>::value,
747 "unsupported type for recursive matching");
748 return matchesChildOf(DynTypedNode::create(
Node), getASTContext(), Matcher,
752 template <
typename T>
753 bool matchesDescendantOf(
const T &
Node,
const DynTypedMatcher &Matcher,
754 BoundNodesTreeBuilder *Builder, BindKind Bind) {
755 static_assert(std::is_base_of<Decl, T>::value ||
756 std::is_base_of<Stmt, T>::value ||
757 std::is_base_of<NestedNameSpecifier, T>::value ||
758 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
759 std::is_base_of<TypeLoc, T>::value ||
760 std::is_base_of<QualType, T>::value ||
761 std::is_base_of<Attr, T>::value,
762 "unsupported type for recursive matching");
763 return matchesDescendantOf(DynTypedNode::create(
Node), getASTContext(),
764 Matcher, Builder, Bind);
768 template <
typename T>
769 bool matchesAncestorOf(
const T &
Node,
const DynTypedMatcher &Matcher,
770 BoundNodesTreeBuilder *Builder,
771 AncestorMatchMode MatchMode) {
772 static_assert(std::is_base_of<Decl, T>::value ||
773 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
774 std::is_base_of<Stmt, T>::value ||
775 std::is_base_of<TypeLoc, T>::value ||
776 std::is_base_of<Attr, T>::value,
777 "type not allowed for recursive matching");
778 return matchesAncestorOf(DynTypedNode::create(
Node), getASTContext(),
779 Matcher, Builder, MatchMode);
782 virtual ASTContext &getASTContext()
const = 0;
784 virtual bool IsMatchingInASTNodeNotSpelledInSource()
const = 0;
786 virtual bool IsMatchingInASTNodeNotAsIs()
const = 0;
788 bool isTraversalIgnoringImplicitNodes()
const;
791 virtual bool matchesChildOf(
const DynTypedNode &
Node, ASTContext &Ctx,
792 const DynTypedMatcher &Matcher,
793 BoundNodesTreeBuilder *Builder,
796 virtual bool matchesDescendantOf(
const DynTypedNode &
Node, ASTContext &Ctx,
797 const DynTypedMatcher &Matcher,
798 BoundNodesTreeBuilder *Builder,
801 virtual bool matchesAncestorOf(
const DynTypedNode &
Node, ASTContext &Ctx,
802 const DynTypedMatcher &Matcher,
803 BoundNodesTreeBuilder *Builder,
804 AncestorMatchMode MatchMode) = 0;
806 friend struct ASTChildrenNotSpelledInSourceScope;
807 virtual bool isMatchingChildrenNotSpelledInSource()
const = 0;
808 virtual void setMatchingChildrenNotSpelledInSource(
bool Set) = 0;
811struct ASTChildrenNotSpelledInSourceScope {
812 ASTChildrenNotSpelledInSourceScope(ASTMatchFinder *
V,
bool B)
813 : MV(
V), MB(
V->isMatchingChildrenNotSpelledInSource()) {
814 V->setMatchingChildrenNotSpelledInSource(B);
816 ~ASTChildrenNotSpelledInSourceScope() {
817 MV->setMatchingChildrenNotSpelledInSource(MB);
830inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>()
const {
831 assert(canConvertTo<QualType>());
832 const ASTNodeKind SourceKind = getSupportedKind();
833 if (SourceKind.isSame(ASTNodeKind::getFromNodeKind<Type>())) {
835 return unconditionalConvertTo<Type>();
837 return unconditionalConvertTo<QualType>();
841template <
typename MatcherT,
typename IteratorT>
842IteratorT matchesFirstInRange(
const MatcherT &Matcher, IteratorT Start,
843 IteratorT End, ASTMatchFinder *Finder,
844 BoundNodesTreeBuilder *Builder) {
845 for (IteratorT I = Start; I != End; ++I) {
846 BoundNodesTreeBuilder
Result(*Builder);
847 if (Matcher.matches(*I, Finder, &
Result)) {
848 *Builder = std::move(
Result);
857template <
typename MatcherT,
typename IteratorT>
858IteratorT matchesFirstInPointerRange(
const MatcherT &Matcher, IteratorT Start,
859 IteratorT End, ASTMatchFinder *Finder,
860 BoundNodesTreeBuilder *Builder) {
861 for (IteratorT I = Start; I != End; ++I) {
862 BoundNodesTreeBuilder
Result(*Builder);
863 if (Matcher.matches(**I, Finder, &
Result)) {
864 *Builder = std::move(
Result);
871template <typename T, std::enable_if_t<!std::is_base_of<FunctionDecl, T>::value>
873inline bool isDefaultedHelper(
const T *) {
876inline bool isDefaultedHelper(
const FunctionDecl *FD) {
877 return FD->isDefaulted();
881template <
typename Ty>
886 template <
typename Inner>
887 static yes& test(Inner *I,
decltype(I->getDecl()) * =
nullptr);
890 static no& test(...);
893 static const bool value =
sizeof(test<Ty>(
nullptr)) ==
sizeof(yes);
900template <
typename T,
typename ArgT>
901class HasOverloadedOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
902 static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
903 std::is_base_of<FunctionDecl, T>::value,
904 "unsupported class for matcher");
905 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
906 "argument type must be std::vector<std::string>");
909 explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names)
910 : SingleNodeMatcherInterface<
T>(), Names(
std::move(Names)) {}
912 bool matchesNode(
const T &
Node)
const override {
913 return matchesSpecialized(
Node);
921 bool matchesSpecialized(
const CXXOperatorCallExpr &
Node)
const {
927 bool matchesSpecialized(
const FunctionDecl &
Node)
const {
928 return Node.isOverloadedOperator() &&
933 std::vector<std::string> Names;
939class HasNameMatcher :
public SingleNodeMatcherInterface<NamedDecl> {
941 explicit HasNameMatcher(std::vector<std::string> Names);
943 bool matchesNode(
const NamedDecl &
Node)
const override;
950 bool matchesNodeUnqualified(
const NamedDecl &
Node)
const;
958 bool matchesNodeFullFast(
const NamedDecl &
Node)
const;
965 bool matchesNodeFullSlow(
const NamedDecl &
Node)
const;
967 bool UseUnqualifiedMatch;
968 std::vector<std::string> Names;
973Matcher<NamedDecl>
hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs);
978 ArrayRef<const StringRef *> NameRefs);
984template <
typename T,
typename DeclMatcherT>
985class HasDeclarationMatcher :
public MatcherInterface<T> {
986 static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
987 "instantiated with wrong types");
989 DynTypedMatcher InnerMatcher;
992 explicit HasDeclarationMatcher(
const Matcher<Decl> &InnerMatcher)
993 : InnerMatcher(InnerMatcher) {}
995 bool matches(
const T &
Node, ASTMatchFinder *Finder,
996 BoundNodesTreeBuilder *Builder)
const override {
997 return matchesSpecialized(
Node, Finder, Builder);
1002 bool matchesSpecialized(
const QualType &
Node, ASTMatchFinder *Finder,
1003 BoundNodesTreeBuilder *Builder)
const {
1007 return matchesSpecialized(*
Node, Finder, Builder);
1012 bool matchesSpecialized(
const Type &
Node, ASTMatchFinder *Finder,
1013 BoundNodesTreeBuilder *Builder)
const {
1016 if (
const auto *S = dyn_cast<DeducedType>(&
Node)) {
1017 QualType DT = S->getDeducedType();
1018 return !DT.isNull() ? matchesSpecialized(*DT, Finder, Builder) :
false;
1023 if (
const auto *S = dyn_cast<TagType>(&
Node)) {
1024 return matchesDecl(S->getDecl(), Finder, Builder);
1026 if (
const auto *S = dyn_cast<InjectedClassNameType>(&
Node)) {
1027 return matchesDecl(S->getDecl(), Finder, Builder);
1029 if (
const auto *S = dyn_cast<TemplateTypeParmType>(&
Node)) {
1030 return matchesDecl(S->getDecl(), Finder, Builder);
1032 if (
const auto *S = dyn_cast<TypedefType>(&
Node)) {
1033 return matchesDecl(S->getDecl(), Finder, Builder);
1035 if (
const auto *S = dyn_cast<UnresolvedUsingType>(&
Node)) {
1036 return matchesDecl(S->getDecl(), Finder, Builder);
1038 if (
const auto *S = dyn_cast<ObjCObjectType>(&
Node)) {
1039 return matchesDecl(S->getInterface(), Finder, Builder);
1050 if (
const auto *S = dyn_cast<SubstTemplateTypeParmType>(&
Node)) {
1051 return matchesSpecialized(S->getReplacementType(), Finder, Builder);
1057 if (
const auto *S = dyn_cast<TemplateSpecializationType>(&
Node)) {
1058 if (!S->isTypeAlias() && S->isSugared()) {
1065 return matchesSpecialized(*S->desugar(), Finder, Builder);
1069 return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder,
1076 if (
const auto *S = dyn_cast<ElaboratedType>(&
Node)) {
1077 return matchesSpecialized(S->desugar(), Finder, Builder);
1082 if (
const auto *S = dyn_cast<UsingType>(&
Node)) {
1083 return matchesSpecialized(S->desugar(), Finder, Builder);
1090 bool matchesSpecialized(
const DeclRefExpr &
Node, ASTMatchFinder *Finder,
1091 BoundNodesTreeBuilder *Builder)
const {
1092 return matchesDecl(
Node.getDecl(), Finder, Builder);
1097 bool matchesSpecialized(
const CallExpr &
Node, ASTMatchFinder *Finder,
1098 BoundNodesTreeBuilder *Builder)
const {
1099 return matchesDecl(
Node.getCalleeDecl(), Finder, Builder);
1104 bool matchesSpecialized(
const CXXConstructExpr &
Node,
1105 ASTMatchFinder *Finder,
1106 BoundNodesTreeBuilder *Builder)
const {
1107 return matchesDecl(
Node.getConstructor(), Finder, Builder);
1110 bool matchesSpecialized(
const ObjCIvarRefExpr &
Node,
1111 ASTMatchFinder *Finder,
1112 BoundNodesTreeBuilder *Builder)
const {
1113 return matchesDecl(
Node.getDecl(), Finder, Builder);
1118 bool matchesSpecialized(
const CXXNewExpr &
Node,
1119 ASTMatchFinder *Finder,
1120 BoundNodesTreeBuilder *Builder)
const {
1121 return matchesDecl(
Node.getOperatorNew(), Finder, Builder);
1126 bool matchesSpecialized(
const MemberExpr &
Node,
1127 ASTMatchFinder *Finder,
1128 BoundNodesTreeBuilder *Builder)
const {
1129 return matchesDecl(
Node.getMemberDecl(), Finder, Builder);
1134 bool matchesSpecialized(
const AddrLabelExpr &
Node,
1135 ASTMatchFinder *Finder,
1136 BoundNodesTreeBuilder *Builder)
const {
1137 return matchesDecl(
Node.getLabel(), Finder, Builder);
1142 bool matchesSpecialized(
const LabelStmt &
Node, ASTMatchFinder *Finder,
1143 BoundNodesTreeBuilder *Builder)
const {
1144 return matchesDecl(
Node.getDecl(), Finder, Builder);
1149 bool matchesDecl(
const Decl *
Node, ASTMatchFinder *Finder,
1150 BoundNodesTreeBuilder *Builder)
const {
1151 return Node !=
nullptr &&
1152 !(Finder->isTraversalIgnoringImplicitNodes() &&
1153 Node->isImplicit()) &&
1154 this->InnerMatcher.matches(DynTypedNode::create(*
Node), Finder,
1161template <
typename T>
1163 static const bool value =
1164 std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value ||
1165 std::is_same<T, QualType>::value || std::is_same<T, Type>::value ||
1166 std::is_same<T, TypeLoc>::value ||
1167 std::is_same<T, NestedNameSpecifier>::value ||
1168 std::is_same<T, NestedNameSpecifierLoc>::value ||
1169 std::is_same<T, CXXCtorInitializer>::value ||
1170 std::is_same<T, TemplateArgumentLoc>::value ||
1171 std::is_same<T, Attr>::value;
1173template <
typename T>
1174const bool IsBaseType<T>::value;
1179using AllNodeBaseTypes =
1180 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
1181 Type, TypeLoc, CXXCtorInitializer, Attr>;
1187template <
class T>
struct ExtractFunctionArgMeta;
1188template <
class T>
struct ExtractFunctionArgMeta<void(
T)> {
1192template <
class T,
class Tuple, std::size_t... I>
1193constexpr T *new_from_tuple_impl(Tuple &&t, std::index_sequence<I...>) {
1194 return new T(std::get<I>(std::forward<Tuple>(t))...);
1197template <
class T,
class Tuple>
constexpr T *new_from_tuple(Tuple &&t) {
1198 return new_from_tuple_impl<T>(
1199 std::forward<Tuple>(t),
1200 std::make_index_sequence<
1201 std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
1205using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
1206using AdaptativeDefaultToTypes =
1207 TypeList<
Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
1211using HasDeclarationSupportedTypes =
1212 TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
1213 ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
1214 MemberExpr, QualType, RecordType, TagType,
1215 TemplateSpecializationType, TemplateTypeParmType, TypedefType,
1216 UnresolvedUsingType, ObjCIvarRefExpr>;
1222template <
typename T>
class BindableMatcher :
public Matcher<T> {
1224 explicit BindableMatcher(
const Matcher<T> &M) : Matcher<
T>(M) {}
1225 explicit BindableMatcher(MatcherInterface<T> *Implementation)
1226 : Matcher<
T>(Implementation) {}
1232 Matcher<T> bind(StringRef
ID)
const {
1233 return DynTypedMatcher(*
this)
1235 ->template unconditionalConvertTo<T>();
1240 operator DynTypedMatcher()
const {
1241 DynTypedMatcher Result =
static_cast<const Matcher<T> &
>(*this);
1242 Result.setAllowBind(
true);
1253 using ReturnTypes = AllNodeBaseTypes;
1255 template <
typename T>
operator Matcher<T>()
const {
1256 return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
1257 .template unconditionalConvertTo<T>();
1262template <
typename T>
1264makeAllOfComposite(ArrayRef<
const Matcher<T> *> InnerMatchers) {
1266 if (InnerMatchers.empty()) {
1267 return BindableMatcher<T>(TrueMatcher());
1271 if (InnerMatchers.size() == 1) {
1272 return BindableMatcher<T>(*InnerMatchers[0]);
1275 using PI = llvm::pointee_iterator<const Matcher<T> *
const *>;
1277 std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
1278 PI(InnerMatchers.end()));
1279 return BindableMatcher<T>(
1280 DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
1281 ASTNodeKind::getFromNodeKind<T>(),
1282 std::move(DynMatchers))
1283 .
template unconditionalConvertTo<T>());
1292template <
typename T,
typename InnerT>
1294makeDynCastAllOfComposite(ArrayRef<
const Matcher<InnerT> *> InnerMatchers) {
1295 return BindableMatcher<T>(
1296 makeAllOfComposite(InnerMatchers).
template dynCastTo<T>());
1310template <
typename SourceT,
typename TargetT>
1311class VariadicDynCastAllOfMatcher
1312 :
public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
1313 makeDynCastAllOfComposite<SourceT, TargetT>> {
1315 VariadicDynCastAllOfMatcher() {}
1328template <
typename T>
1329class VariadicAllOfMatcher
1330 :
public VariadicFunction<BindableMatcher<T>, Matcher<T>,
1331 makeAllOfComposite<T>> {
1333 VariadicAllOfMatcher() {}
1345template <
typename... Ps>
class VariadicOperatorMatcher {
1347 VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
1348 : Op(Op), Params(
std::
forward<Ps>(Params)...) {}
1350 template <
typename T>
operator Matcher<T>() const & {
1351 return DynTypedMatcher::constructVariadic(
1352 Op, ASTNodeKind::getFromNodeKind<T>(),
1353 getMatchers<T>(std::index_sequence_for<Ps...>()))
1354 .template unconditionalConvertTo<T>();
1357 template <
typename T>
operator Matcher<T>() && {
1358 return DynTypedMatcher::constructVariadic(
1359 Op, ASTNodeKind::getFromNodeKind<T>(),
1360 getMatchers<T>(std::index_sequence_for<Ps...>()))
1361 .template unconditionalConvertTo<T>();
1366 template <
typename T, std::size_t... Is>
1367 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>)
const & {
1368 return {Matcher<T>(std::get<Is>(Params))...};
1371 template <
typename T, std::size_t... Is>
1372 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) && {
1373 return {Matcher<T>(std::get<Is>(std::move(Params)))...};
1376 const DynTypedMatcher::VariadicOperator Op;
1377 std::tuple<Ps...> Params;
1382template <
unsigned MinCount,
unsigned MaxCount>
1383struct VariadicOperatorMatcherFunc {
1384 DynTypedMatcher::VariadicOperator Op;
1386 template <
typename... Ms>
1387 VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps)
const {
1388 static_assert(MinCount <=
sizeof...(Ms) &&
sizeof...(Ms) <= MaxCount,
1389 "invalid number of parameters for variadic matcher");
1390 return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
1394template <
typename T,
bool IsBaseOf,
typename Head,
typename Tail>
1395struct GetCladeImpl {
1398template <
typename T,
typename Head,
typename Tail>
1399struct GetCladeImpl<
T,
false, Head, Tail>
1400 : GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
1401 typename Tail::head, typename Tail::tail> {};
1403template <
typename T,
typename...
U>
1404struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
1406template <
typename CladeType,
typename... MatcherTypes>
1407struct MapAnyOfMatcherImpl {
1409 template <
typename... InnerMatchers>
1410 BindableMatcher<CladeType>
1411 operator()(InnerMatchers &&... InnerMatcher)
const {
1412 return VariadicAllOfMatcher<CladeType>()(std::apply(
1413 internal::VariadicOperatorMatcherFunc<
1414 0, std::numeric_limits<unsigned>::max()>{
1415 internal::DynTypedMatcher::VO_AnyOf},
1417 [&](
auto... Matcher) {
1418 return std::make_tuple(Matcher(InnerMatcher...)...);
1421 VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
1425template <
typename... MatcherTypes>
1426using MapAnyOfMatcher =
1427 MapAnyOfMatcherImpl<
typename GetClade<MatcherTypes...>::Type,
1430template <
typename... MatcherTypes>
struct MapAnyOfHelper {
1431 using CladeType =
typename GetClade<MatcherTypes...>
::Type;
1433 MapAnyOfMatcher<MatcherTypes...> with;
1435 operator BindableMatcher<CladeType>()
const {
return with(); }
1437 Matcher<CladeType> bind(StringRef
ID)
const {
return with().bind(
ID); }
1440template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1441 typename T,
typename ToTypes>
1442class ArgumentAdaptingMatcherFuncAdaptor {
1444 explicit ArgumentAdaptingMatcherFuncAdaptor(
const Matcher<T> &InnerMatcher)
1445 : InnerMatcher(InnerMatcher) {}
1447 using ReturnTypes = ToTypes;
1449 template <
typename To>
operator Matcher<To>() const & {
1450 return Matcher<To>(
new ArgumentAdapterT<To, T>(InnerMatcher));
1453 template <
typename To>
operator Matcher<To>() && {
1454 return Matcher<To>(
new ArgumentAdapterT<To, T>(std::move(InnerMatcher)));
1458 Matcher<T> InnerMatcher;
1474template <
template <
typename ToArg,
typename FromArg>
class ArgumentAdapterT,
1475 typename FromTypes = AdaptativeDefaultFromTypes,
1476 typename ToTypes = AdaptativeDefaultToTypes>
1477struct ArgumentAdaptingMatcherFunc {
1478 template <
typename T>
1479 static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1480 create(
const Matcher<T> &InnerMatcher) {
1481 return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>(
1485 template <
typename T>
1486 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1487 operator()(
const Matcher<T> &InnerMatcher)
const {
1488 return create(InnerMatcher);
1491 template <
typename...
T>
1492 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT,
1493 typename GetClade<
T...>
::Type, ToTypes>
1494 operator()(
const MapAnyOfHelper<T...> &InnerMatcher)
const {
1495 return create(InnerMatcher.with());
1499template <
typename T>
class TraversalMatcher :
public MatcherInterface<T> {
1500 DynTypedMatcher InnerMatcher;
1505 const Matcher<T> &InnerMatcher)
1506 : InnerMatcher(InnerMatcher),
Traversal(TK) {}
1508 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1509 BoundNodesTreeBuilder *Builder)
const override {
1510 return this->InnerMatcher.matches(DynTypedNode::create(
Node), Finder,
1514 std::optional<clang::TraversalKind>
TraversalKind()
const override {
1515 if (
auto NestedKind = this->InnerMatcher.getTraversalKind())
1521template <
typename MatcherType>
class TraversalWrapper {
1523 TraversalWrapper(TraversalKind TK,
const MatcherType &InnerMatcher)
1524 : TK(TK), InnerMatcher(InnerMatcher) {}
1526 template <
typename T>
operator Matcher<T>() const & {
1527 return internal::DynTypedMatcher::constructRestrictedWrapper(
1528 new internal::TraversalMatcher<T>(TK, InnerMatcher),
1529 ASTNodeKind::getFromNodeKind<T>())
1530 .template unconditionalConvertTo<T>();
1533 template <
typename T>
operator Matcher<T>() && {
1534 return internal::DynTypedMatcher::constructRestrictedWrapper(
1535 new internal::TraversalMatcher<T>(TK, std::move(InnerMatcher)),
1536 ASTNodeKind::getFromNodeKind<T>())
1537 .template unconditionalConvertTo<T>();
1542 MatcherType InnerMatcher;
1557template <
template <
typename T,
typename... Params>
class MatcherT,
1558 typename ReturnTypesF, typename... ParamTypes>
1559class PolymorphicMatcher {
1561 PolymorphicMatcher(
const ParamTypes &... Params) : Params(Params...) {}
1563 using ReturnTypes =
typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1565 template <
typename T>
operator Matcher<T>() const & {
1566 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1567 "right polymorphic conversion");
1568 return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params));
1571 template <
typename T>
operator Matcher<T>() && {
1572 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1573 "right polymorphic conversion");
1575 new_from_tuple<MatcherT<T, ParamTypes...>>(std::move(Params)));
1579 std::tuple<ParamTypes...> Params;
1586template <
typename T,
typename ChildT>
1587class HasMatcher :
public MatcherInterface<T> {
1588 DynTypedMatcher InnerMatcher;
1591 explicit HasMatcher(
const Matcher<ChildT> &InnerMatcher)
1592 : InnerMatcher(InnerMatcher) {}
1594 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1595 BoundNodesTreeBuilder *Builder)
const override {
1596 return Finder->matchesChildOf(
Node, this->InnerMatcher, Builder,
1597 ASTMatchFinder::BK_First);
1606template <
typename T,
typename ChildT>
1607class ForEachMatcher :
public MatcherInterface<T> {
1608 static_assert(IsBaseType<ChildT>::value,
1609 "for each only accepts base type matcher");
1611 DynTypedMatcher InnerMatcher;
1614 explicit ForEachMatcher(
const Matcher<ChildT> &InnerMatcher)
1615 : InnerMatcher(InnerMatcher) {}
1617 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1618 BoundNodesTreeBuilder *Builder)
const override {
1619 return Finder->matchesChildOf(
1620 Node, this->InnerMatcher, Builder,
1621 ASTMatchFinder::BK_All);
1627template <
typename T>
1628inline Matcher<T> DynTypedMatcher::unconditionalConvertTo()
const {
1629 return Matcher<T>(*
this);
1636template <
typename T,
typename DescendantT>
1637class HasDescendantMatcher :
public MatcherInterface<T> {
1638 static_assert(IsBaseType<DescendantT>::value,
1639 "has descendant only accepts base type matcher");
1641 DynTypedMatcher DescendantMatcher;
1644 explicit HasDescendantMatcher(
const Matcher<DescendantT> &DescendantMatcher)
1645 : DescendantMatcher(DescendantMatcher) {}
1647 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1648 BoundNodesTreeBuilder *Builder)
const override {
1649 return Finder->matchesDescendantOf(
Node, this->DescendantMatcher, Builder,
1650 ASTMatchFinder::BK_First);
1658template <
typename T,
typename ParentT>
1659class HasParentMatcher :
public MatcherInterface<T> {
1660 static_assert(IsBaseType<ParentT>::value,
1661 "has parent only accepts base type matcher");
1663 DynTypedMatcher ParentMatcher;
1666 explicit HasParentMatcher(
const Matcher<ParentT> &ParentMatcher)
1667 : ParentMatcher(ParentMatcher) {}
1669 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1670 BoundNodesTreeBuilder *Builder)
const override {
1671 return Finder->matchesAncestorOf(
Node, this->ParentMatcher, Builder,
1672 ASTMatchFinder::AMM_ParentOnly);
1680template <
typename T,
typename AncestorT>
1681class HasAncestorMatcher :
public MatcherInterface<T> {
1682 static_assert(IsBaseType<AncestorT>::value,
1683 "has ancestor only accepts base type matcher");
1685 DynTypedMatcher AncestorMatcher;
1688 explicit HasAncestorMatcher(
const Matcher<AncestorT> &AncestorMatcher)
1689 : AncestorMatcher(AncestorMatcher) {}
1691 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1692 BoundNodesTreeBuilder *Builder)
const override {
1693 return Finder->matchesAncestorOf(
Node, this->AncestorMatcher, Builder,
1694 ASTMatchFinder::AMM_All);
1704template <
typename T,
typename DescendantT>
1705class ForEachDescendantMatcher :
public MatcherInterface<T> {
1706 static_assert(IsBaseType<DescendantT>::value,
1707 "for each descendant only accepts base type matcher");
1709 DynTypedMatcher DescendantMatcher;
1712 explicit ForEachDescendantMatcher(
1713 const Matcher<DescendantT> &DescendantMatcher)
1714 : DescendantMatcher(DescendantMatcher) {}
1716 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1717 BoundNodesTreeBuilder *Builder)
const override {
1718 return Finder->matchesDescendantOf(
Node, this->DescendantMatcher, Builder,
1719 ASTMatchFinder::BK_All);
1725template <
typename T,
typename ValueT>
1726class ValueEqualsMatcher :
public SingleNodeMatcherInterface<T> {
1727 static_assert(std::is_base_of<CharacterLiteral, T>::value ||
1728 std::is_base_of<CXXBoolLiteralExpr, T>::value ||
1729 std::is_base_of<FloatingLiteral, T>::value ||
1730 std::is_base_of<IntegerLiteral, T>::value,
1731 "the node must have a getValue method");
1734 explicit ValueEqualsMatcher(
const ValueT &ExpectedValue)
1735 : ExpectedValue(ExpectedValue) {}
1737 bool matchesNode(
const T &
Node)
const override {
1738 return Node.getValue() == ExpectedValue;
1742 ValueT ExpectedValue;
1748inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
1749 const FloatingLiteral &
Node)
const {
1750 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1751 return Node.getValue().convertToFloat() == ExpectedValue;
1752 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1753 return Node.getValue().convertToDouble() == ExpectedValue;
1757inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
1758 const FloatingLiteral &
Node)
const {
1759 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1760 return Node.getValue().convertToFloat() == ExpectedValue;
1761 if ((&
Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1762 return Node.getValue().convertToDouble() == ExpectedValue;
1766inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
1767 const FloatingLiteral &
Node)
const {
1768 return ExpectedValue.compare(
Node.getValue()) == llvm::APFloat::cmpEqual;
1773template <
typename TLoc,
typename T>
1774class LocMatcher :
public MatcherInterface<TLoc> {
1775 DynTypedMatcher InnerMatcher;
1778 explicit LocMatcher(
const Matcher<T> &InnerMatcher)
1779 : InnerMatcher(InnerMatcher) {}
1781 bool matches(
const TLoc &
Node, ASTMatchFinder *Finder,
1782 BoundNodesTreeBuilder *Builder)
const override {
1785 return this->InnerMatcher.matches(extract(
Node), Finder, Builder);
1790 return DynTypedNode::create(*
Loc.getNestedNameSpecifier());
1798class TypeLocTypeMatcher :
public MatcherInterface<TypeLoc> {
1799 DynTypedMatcher InnerMatcher;
1802 explicit TypeLocTypeMatcher(
const Matcher<QualType> &InnerMatcher)
1803 : InnerMatcher(InnerMatcher) {}
1805 bool matches(
const TypeLoc &
Node, ASTMatchFinder *Finder,
1806 BoundNodesTreeBuilder *Builder)
const override {
1809 return this->InnerMatcher.matches(DynTypedNode::create(
Node.getType()),
1817template <
typename T>
class TypeTraverseMatcher :
public MatcherInterface<T> {
1818 DynTypedMatcher InnerMatcher;
1821 explicit TypeTraverseMatcher(
const Matcher<QualType> &InnerMatcher,
1822 QualType (T::*TraverseFunction)()
const)
1823 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1825 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1826 BoundNodesTreeBuilder *Builder)
const override {
1827 QualType NextNode = (
Node.*TraverseFunction)();
1828 if (NextNode.isNull())
1830 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1835 QualType (T::*TraverseFunction)()
const;
1841template <
typename T>
1842class TypeLocTraverseMatcher :
public MatcherInterface<T> {
1843 DynTypedMatcher InnerMatcher;
1846 explicit TypeLocTraverseMatcher(
const Matcher<TypeLoc> &InnerMatcher,
1847 TypeLoc (T::*TraverseFunction)()
const)
1848 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1850 bool matches(
const T &
Node, ASTMatchFinder *Finder,
1851 BoundNodesTreeBuilder *Builder)
const override {
1852 TypeLoc NextNode = (
Node.*TraverseFunction)();
1855 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1860 TypeLoc (T::*TraverseFunction)()
const;
1869template <
typename InnerTBase,
1870 template <
typename OuterT>
class Getter,
1871 template <
typename OuterT>
class MatcherImpl,
1872 typename ReturnTypesF>
1873class TypeTraversePolymorphicMatcher {
1875 using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
1878 static Self
create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers);
1881 using ReturnTypes =
typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1883 explicit TypeTraversePolymorphicMatcher(
1884 ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers)
1885 : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
1887 template <
typename OuterT>
operator Matcher<OuterT>()
const {
1888 return Matcher<OuterT>(
1889 new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
1893 :
public VariadicFunction<Self, Matcher<InnerTBase>, &Self::create> {
1898 Matcher<InnerTBase> InnerMatcher;
1905template <
typename Matcher, Matcher (*Func)()>
class MemoizedMatcher {
1907 Wrapper() : M(
Func()) {}
1913 static const Matcher &getInstance() {
1914 static llvm::ManagedStatic<Wrapper> Instance;
1922template <
typename InnerTBase,
template <
typename OuterT>
class Getter,
1923 template <
typename OuterT>
class MatcherImpl,
typename ReturnTypesF>
1924TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
1925TypeTraversePolymorphicMatcher<
1926 InnerTBase, Getter, MatcherImpl,
1927 ReturnTypesF>::create(ArrayRef<
const Matcher<InnerTBase> *> InnerMatchers) {
1928 return Self(InnerMatchers);
1933inline ArrayRef<TemplateArgument>
1934getTemplateSpecializationArgs(
const ClassTemplateSpecializationDecl &
D) {
1935 return D.getTemplateArgs().asArray();
1938inline ArrayRef<TemplateArgument>
1939getTemplateSpecializationArgs(
const VarTemplateSpecializationDecl &
D) {
1940 return D.getTemplateArgs().asArray();
1943inline ArrayRef<TemplateArgument>
1944getTemplateSpecializationArgs(
const TemplateSpecializationType &
T) {
1945 return T.template_arguments();
1948inline ArrayRef<TemplateArgument>
1949getTemplateSpecializationArgs(
const FunctionDecl &FD) {
1950 if (
const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
1951 return TemplateArgs->asArray();
1952 return std::nullopt;
1955inline ArrayRef<TemplateArgumentLoc>
1956getTemplateArgsWritten(
const ClassTemplateSpecializationDecl &
D) {
1957 if (
const ASTTemplateArgumentListInfo *Args =
D.getTemplateArgsAsWritten())
1958 return Args->arguments();
1959 return std::nullopt;
1962inline ArrayRef<TemplateArgumentLoc>
1963getTemplateArgsWritten(
const VarTemplateSpecializationDecl &
D) {
1964 if (
const ASTTemplateArgumentListInfo *Args =
D.getTemplateArgsAsWritten())
1965 return Args->arguments();
1966 return std::nullopt;
1969inline ArrayRef<TemplateArgumentLoc>
1970getTemplateArgsWritten(
const FunctionDecl &FD) {
1971 if (
const auto *Args = FD.getTemplateSpecializationArgsAsWritten())
1972 return Args->arguments();
1973 return std::nullopt;
1976inline ArrayRef<TemplateArgumentLoc>
1977getTemplateArgsWritten(
const DeclRefExpr &DRE) {
1978 if (
const auto *Args = DRE.getTemplateArgs())
1979 return {Args, DRE.getNumTemplateArgs()};
1980 return std::nullopt;
1983inline SmallVector<TemplateArgumentLoc>
1984getTemplateArgsWritten(
const TemplateSpecializationTypeLoc &
T) {
1985 SmallVector<TemplateArgumentLoc> Args;
1987 Args.reserve(
T.getNumArgs());
1988 for (
unsigned I = 0; I <
T.getNumArgs(); ++I)
1989 Args.emplace_back(
T.getArgLoc(I));
1994struct NotEqualsBoundNodePredicate {
1995 bool operator()(
const internal::BoundNodesMap &
Nodes)
const {
2003template <
typename Ty,
typename Enable =
void>
struct GetBodyMatcher {
2004 static const Stmt *get(
const Ty &
Node) {
return Node.getBody(); }
2007template <
typename Ty>
2008struct GetBodyMatcher<
2009 Ty,
std::enable_if_t<std::is_base_of<FunctionDecl, Ty>::value>> {
2010 static const Stmt *get(
const Ty &
Node) {
2011 return Node.doesThisDeclarationHaveABody() ?
Node.getBody() :
nullptr;
2015template <
typename NodeType>
2016inline std::optional<BinaryOperatorKind>
2017equivalentBinaryOperator(
const NodeType &
Node) {
2018 return Node.getOpcode();
2022inline std::optional<BinaryOperatorKind>
2023equivalentBinaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2024 if (
Node.getNumArgs() != 2)
2025 return std::nullopt;
2026 switch (
Node.getOperator()) {
2028 return std::nullopt;
2043 case OO_GreaterGreater:
2053 case OO_GreaterEqual:
2057 case OO_ExclaimEqual:
2072 return BO_MulAssign;
2074 return BO_DivAssign;
2075 case OO_PercentEqual:
2076 return BO_RemAssign;
2078 return BO_AddAssign;
2080 return BO_SubAssign;
2081 case OO_LessLessEqual:
2082 return BO_ShlAssign;
2083 case OO_GreaterGreaterEqual:
2084 return BO_ShrAssign;
2086 return BO_AndAssign;
2088 return BO_XorAssign;
2096template <
typename NodeType>
2097inline std::optional<UnaryOperatorKind>
2098equivalentUnaryOperator(
const NodeType &
Node) {
2099 return Node.getOpcode();
2103inline std::optional<UnaryOperatorKind>
2104equivalentUnaryOperator<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2105 if (
Node.getNumArgs() != 1 &&
Node.getOperator() != OO_PlusPlus &&
2106 Node.getOperator() != OO_MinusMinus)
2107 return std::nullopt;
2108 switch (
Node.getOperator()) {
2110 return std::nullopt;
2124 const auto *FD =
Node.getDirectCallee();
2126 return std::nullopt;
2127 return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
2129 case OO_MinusMinus: {
2130 const auto *FD =
Node.getDirectCallee();
2132 return std::nullopt;
2133 return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
2140template <
typename NodeType>
inline const Expr *getLHS(
const NodeType &
Node) {
2141 return Node.getLHS();
2145getLHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2146 if (!internal::equivalentBinaryOperator(
Node))
2148 return Node.getArg(0);
2150template <
typename NodeType>
inline const Expr *getRHS(
const NodeType &
Node) {
2151 return Node.getRHS();
2155getRHS<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2156 if (!internal::equivalentBinaryOperator(
Node))
2158 return Node.getArg(1);
2160template <
typename NodeType>
2161inline const Expr *getSubExpr(
const NodeType &
Node) {
2162 return Node.getSubExpr();
2166getSubExpr<CXXOperatorCallExpr>(
const CXXOperatorCallExpr &
Node) {
2167 if (!internal::equivalentUnaryOperator(
Node))
2169 return Node.getArg(0);
2172template <
typename Ty>
2173struct HasSizeMatcher {
2174 static bool hasSize(
const Ty &
Node,
unsigned int N) {
2175 return Node.getSize() == N;
2180inline bool HasSizeMatcher<StringLiteral>::hasSize(
2181 const StringLiteral &
Node,
unsigned int N) {
2182 return Node.getLength() == N;
2185template <
typename Ty>
2186struct GetSourceExpressionMatcher {
2187 static const Expr *get(
const Ty &
Node) {
2188 return Node.getSubExpr();
2193inline const Expr *GetSourceExpressionMatcher<OpaqueValueExpr>::get(
2194 const OpaqueValueExpr &
Node) {
2195 return Node.getSourceExpr();
2198template <
typename Ty>
2199struct CompoundStmtMatcher {
2200 static const CompoundStmt *get(
const Ty &
Node) {
2206inline const CompoundStmt *
2207CompoundStmtMatcher<StmtExpr>::get(
const StmtExpr &
Node) {
2208 return Node.getSubStmt();
2217 const ASTContext &Context);
2219inline std::optional<StringRef> getOpName(
const UnaryOperator &
Node) {
2220 return Node.getOpcodeStr(
Node.getOpcode());
2222inline std::optional<StringRef> getOpName(
const BinaryOperator &
Node) {
2223 return Node.getOpcodeStr();
2225inline StringRef getOpName(
const CXXRewrittenBinaryOperator &
Node) {
2226 return Node.getOpcodeStr();
2228inline std::optional<StringRef> getOpName(
const CXXOperatorCallExpr &
Node) {
2229 auto optBinaryOpcode = equivalentBinaryOperator(
Node);
2230 if (!optBinaryOpcode) {
2231 auto optUnaryOpcode = equivalentUnaryOperator(
Node);
2232 if (!optUnaryOpcode)
2233 return std::nullopt;
2238inline StringRef getOpName(
const CXXFoldExpr &
Node) {
2246template <
typename T,
typename ArgT = std::vector<std::
string>>
2247class HasAnyOperatorNameMatcher :
public SingleNodeMatcherInterface<T> {
2248 static_assert(std::is_same<T, BinaryOperator>::value ||
2249 std::is_same<T, CXXOperatorCallExpr>::value ||
2250 std::is_same<T, CXXRewrittenBinaryOperator>::value ||
2251 std::is_same<T, UnaryOperator>::value,
2252 "Matcher only supports `BinaryOperator`, `UnaryOperator`, "
2253 "`CXXOperatorCallExpr` and `CXXRewrittenBinaryOperator`");
2254 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
2255 "Matcher ArgT must be std::vector<std::string>");
2258 explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names)
2259 : SingleNodeMatcherInterface<
T>(), Names(
std::move(Names)) {}
2261 bool matchesNode(
const T &
Node)
const override {
2262 std::optional<StringRef> OptOpName = getOpName(
Node);
2263 return OptOpName && llvm::is_contained(Names, *OptOpName);
2267 static std::optional<StringRef> getOpName(
const UnaryOperator &
Node) {
2268 return Node.getOpcodeStr(
Node.getOpcode());
2270 static std::optional<StringRef> getOpName(
const BinaryOperator &
Node) {
2271 return Node.getOpcodeStr();
2273 static StringRef getOpName(
const CXXRewrittenBinaryOperator &
Node) {
2274 return Node.getOpcodeStr();
2276 static std::optional<StringRef> getOpName(
const CXXOperatorCallExpr &
Node) {
2277 auto optBinaryOpcode = equivalentBinaryOperator(
Node);
2278 if (!optBinaryOpcode) {
2279 auto optUnaryOpcode = equivalentUnaryOperator(
Node);
2280 if (!optUnaryOpcode)
2281 return std::nullopt;
2282 return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
2284 return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
2287 std::vector<std::string> Names;
2290using HasOpNameMatcher =
2291 PolymorphicMatcher<HasAnyOperatorNameMatcher,
2293 TypeList<BinaryOperator, CXXOperatorCallExpr,
2294 CXXRewrittenBinaryOperator, UnaryOperator>),
2295 std::vector<std::string>>;
2299using HasOverloadOpNameMatcher =
2300 PolymorphicMatcher<HasOverloadedOperatorNameMatcher,
2301 void(TypeList<CXXOperatorCallExpr, FunctionDecl>),
2302 std::vector<std::string>>;
2304HasOverloadOpNameMatcher
2311 const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
2312 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder);
2315 llvm::Regex::RegexFlags Flags,
2319MatchTemplateArgLocAt(
const DeclRefExpr &
Node,
unsigned int Index,
2320 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2321 internal::ASTMatchFinder *Finder,
2322 internal::BoundNodesTreeBuilder *Builder) {
2324 return Index < ArgLocs.size() &&
2325 InnerMatcher.matches(ArgLocs[Index], Finder, Builder);
2329MatchTemplateArgLocAt(
const TemplateSpecializationTypeLoc &
Node,
2331 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2332 internal::ASTMatchFinder *Finder,
2333 internal::BoundNodesTreeBuilder *Builder) {
2334 return !
Node.isNull() && Index <
Node.getNumArgs() &&
2335 InnerMatcher.matches(
Node.getArgLoc(Index), Finder, Builder);
BoundNodesTreeBuilder BoundNodes
BoundNodesTreeBuilder Nodes
DynTypedMatcher::MatcherIDType MatcherID
enum clang::sema::@1655::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...