File indexing completed on 2026-05-10 08:36:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
0035 #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
0036
0037 #include "clang/AST/ASTTypeTraits.h"
0038 #include "clang/AST/Decl.h"
0039 #include "clang/AST/DeclCXX.h"
0040 #include "clang/AST/DeclFriend.h"
0041 #include "clang/AST/DeclTemplate.h"
0042 #include "clang/AST/Expr.h"
0043 #include "clang/AST/ExprCXX.h"
0044 #include "clang/AST/ExprObjC.h"
0045 #include "clang/AST/NestedNameSpecifier.h"
0046 #include "clang/AST/Stmt.h"
0047 #include "clang/AST/TemplateName.h"
0048 #include "clang/AST/Type.h"
0049 #include "clang/AST/TypeLoc.h"
0050 #include "clang/Basic/LLVM.h"
0051 #include "clang/Basic/OperatorKinds.h"
0052 #include "llvm/ADT/APFloat.h"
0053 #include "llvm/ADT/ArrayRef.h"
0054 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0055 #include "llvm/ADT/STLExtras.h"
0056 #include "llvm/ADT/SmallVector.h"
0057 #include "llvm/ADT/StringRef.h"
0058 #include "llvm/ADT/iterator.h"
0059 #include "llvm/Support/Casting.h"
0060 #include "llvm/Support/ManagedStatic.h"
0061 #include "llvm/Support/Regex.h"
0062 #include <algorithm>
0063 #include <cassert>
0064 #include <cstddef>
0065 #include <cstdint>
0066 #include <map>
0067 #include <memory>
0068 #include <optional>
0069 #include <string>
0070 #include <tuple>
0071 #include <type_traits>
0072 #include <utility>
0073 #include <vector>
0074
0075 namespace clang {
0076
0077 class ASTContext;
0078
0079 namespace ast_matchers {
0080
0081 class BoundNodes;
0082
0083 namespace internal {
0084
0085
0086
0087
0088
0089 template <typename... Ts> struct TypeList {};
0090
0091 template <typename T1, typename... Ts> struct TypeList<T1, Ts...> {
0092
0093 using head = T1;
0094
0095
0096
0097
0098
0099 using tail = TypeList<Ts...>;
0100 };
0101
0102
0103 using EmptyTypeList = TypeList<>;
0104
0105
0106
0107 template <typename AnyTypeList, typename T> struct TypeListContainsSuperOf {
0108 static const bool value =
0109 std::is_base_of<typename AnyTypeList::head, T>::value ||
0110 TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value;
0111 };
0112 template <typename T> struct TypeListContainsSuperOf<EmptyTypeList, T> {
0113 static const bool value = false;
0114 };
0115
0116
0117
0118
0119
0120
0121 template <typename ResultT, typename ArgT,
0122 ResultT (*Func)(ArrayRef<const ArgT *>)>
0123 struct VariadicFunction {
0124 ResultT operator()() const { return Func({}); }
0125
0126 template <typename... ArgsT>
0127 ResultT operator()(const ArgT &Arg1, const ArgsT &... Args) const {
0128 return Execute(Arg1, static_cast<const ArgT &>(Args)...);
0129 }
0130
0131
0132
0133 ResultT operator()(ArrayRef<ArgT> Args) const {
0134 return Func(llvm::to_vector<8>(llvm::make_pointer_range(Args)));
0135 }
0136
0137 private:
0138
0139
0140 template <typename... ArgsT> ResultT Execute(const ArgsT &... Args) const {
0141 const ArgT *const ArgsArray[] = {&Args...};
0142 return Func(ArrayRef<const ArgT *>(ArgsArray, sizeof...(ArgsT)));
0143 }
0144 };
0145
0146
0147
0148 inline QualType getUnderlyingType(const Expr &Node) { return Node.getType(); }
0149
0150 inline QualType getUnderlyingType(const ValueDecl &Node) {
0151 return Node.getType();
0152 }
0153 inline QualType getUnderlyingType(const TypedefNameDecl &Node) {
0154 return Node.getUnderlyingType();
0155 }
0156 inline QualType getUnderlyingType(const FriendDecl &Node) {
0157 if (const TypeSourceInfo *TSI = Node.getFriendType())
0158 return TSI->getType();
0159 return QualType();
0160 }
0161 inline QualType getUnderlyingType(const CXXBaseSpecifier &Node) {
0162 return Node.getType();
0163 }
0164 inline QualType getUnderlyingType(const ObjCInterfaceDecl &Node) {
0165 return Node.getTypeForDecl()->getPointeeType();
0166 }
0167
0168
0169 template <typename T,
0170 std::enable_if_t<TypeListContainsSuperOf<
0171 TypeList<CXXBaseSpecifier, CXXCtorInitializer,
0172 CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr,
0173 CompoundLiteralExpr, DeclaratorDecl, ObjCPropertyDecl,
0174 TemplateArgumentLoc, TypedefNameDecl>,
0175 T>::value> * = nullptr>
0176 inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) {
0177 return Node.getTypeSourceInfo();
0178 }
0179 template <typename T,
0180 std::enable_if_t<TypeListContainsSuperOf<
0181 TypeList<CXXFunctionalCastExpr, ExplicitCastExpr>, T>::value> * =
0182 nullptr>
0183 inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) {
0184 return Node.getTypeInfoAsWritten();
0185 }
0186 inline TypeSourceInfo *GetTypeSourceInfo(const BlockDecl &Node) {
0187 return Node.getSignatureAsWritten();
0188 }
0189 inline TypeSourceInfo *GetTypeSourceInfo(const CXXNewExpr &Node) {
0190 return Node.getAllocatedTypeSourceInfo();
0191 }
0192
0193
0194
0195 inline const FunctionProtoType *
0196 getFunctionProtoType(const FunctionProtoType &Node) {
0197 return &Node;
0198 }
0199
0200 inline const FunctionProtoType *getFunctionProtoType(const FunctionDecl &Node) {
0201 return Node.getType()->getAs<FunctionProtoType>();
0202 }
0203
0204
0205 inline clang::AccessSpecifier getAccessSpecifier(const Decl &Node) {
0206 return Node.getAccess();
0207 }
0208
0209 inline clang::AccessSpecifier getAccessSpecifier(const CXXBaseSpecifier &Node) {
0210 return Node.getAccessSpecifier();
0211 }
0212
0213
0214 class BoundNodesMap {
0215 public:
0216
0217
0218
0219 void addNode(StringRef ID, const DynTypedNode &DynNode) {
0220 NodeMap[std::string(ID)] = DynNode;
0221 }
0222
0223
0224
0225
0226
0227 template <typename T>
0228 const T *getNodeAs(StringRef ID) const {
0229 IDToNodeMap::const_iterator It = NodeMap.find(ID);
0230 if (It == NodeMap.end()) {
0231 return nullptr;
0232 }
0233 return It->second.get<T>();
0234 }
0235
0236 DynTypedNode getNode(StringRef ID) const {
0237 IDToNodeMap::const_iterator It = NodeMap.find(ID);
0238 if (It == NodeMap.end()) {
0239 return DynTypedNode();
0240 }
0241 return It->second;
0242 }
0243
0244
0245 bool operator<(const BoundNodesMap &Other) const {
0246 return NodeMap < Other.NodeMap;
0247 }
0248
0249
0250
0251
0252
0253
0254 using IDToNodeMap = std::map<std::string, DynTypedNode, std::less<>>;
0255
0256 const IDToNodeMap &getMap() const {
0257 return NodeMap;
0258 }
0259
0260
0261
0262 bool isComparable() const {
0263 for (const auto &IDAndNode : NodeMap) {
0264 if (!IDAndNode.second.getMemoizationData())
0265 return false;
0266 }
0267 return true;
0268 }
0269
0270 private:
0271 IDToNodeMap NodeMap;
0272 };
0273
0274
0275
0276
0277
0278 class BoundNodesTreeBuilder {
0279 public:
0280
0281
0282 class Visitor {
0283 public:
0284 virtual ~Visitor() = default;
0285
0286
0287
0288
0289 virtual void visitMatch(const BoundNodes& BoundNodesView) = 0;
0290 };
0291
0292
0293 void setBinding(StringRef Id, const DynTypedNode &DynNode) {
0294 if (Bindings.empty())
0295 Bindings.emplace_back();
0296 for (BoundNodesMap &Binding : Bindings)
0297 Binding.addNode(Id, DynNode);
0298 }
0299
0300
0301 void addMatch(const BoundNodesTreeBuilder &Bindings);
0302
0303
0304
0305
0306 void visitMatches(Visitor* ResultVisitor);
0307
0308 template <typename ExcludePredicate>
0309 bool removeBindings(const ExcludePredicate &Predicate) {
0310 llvm::erase_if(Bindings, Predicate);
0311 return !Bindings.empty();
0312 }
0313
0314
0315 bool operator<(const BoundNodesTreeBuilder &Other) const {
0316 return Bindings < Other.Bindings;
0317 }
0318
0319
0320
0321 bool isComparable() const {
0322 for (const BoundNodesMap &NodesMap : Bindings) {
0323 if (!NodesMap.isComparable())
0324 return false;
0325 }
0326 return true;
0327 }
0328
0329 private:
0330 SmallVector<BoundNodesMap, 1> Bindings;
0331 };
0332
0333 class ASTMatchFinder;
0334
0335
0336
0337
0338
0339
0340 class DynMatcherInterface
0341 : public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
0342 public:
0343 virtual ~DynMatcherInterface() = default;
0344
0345
0346
0347
0348
0349 virtual bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
0350 BoundNodesTreeBuilder *Builder) const = 0;
0351
0352 virtual std::optional<clang::TraversalKind> TraversalKind() const {
0353 return std::nullopt;
0354 }
0355 };
0356
0357
0358
0359
0360
0361
0362
0363
0364 template <typename T>
0365 class MatcherInterface : public DynMatcherInterface {
0366 public:
0367
0368
0369
0370
0371 virtual bool matches(const T &Node,
0372 ASTMatchFinder *Finder,
0373 BoundNodesTreeBuilder *Builder) const = 0;
0374
0375 bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
0376 BoundNodesTreeBuilder *Builder) const override {
0377 return matches(DynNode.getUnchecked<T>(), Finder, Builder);
0378 }
0379 };
0380
0381
0382
0383 template <typename T>
0384 class SingleNodeMatcherInterface : public MatcherInterface<T> {
0385 public:
0386
0387
0388
0389 virtual bool matchesNode(const T &Node) const = 0;
0390
0391 private:
0392
0393 bool matches(const T &Node,
0394 ASTMatchFinder * ,
0395 BoundNodesTreeBuilder * ) const override {
0396 return matchesNode(Node);
0397 }
0398 };
0399
0400 template <typename> class Matcher;
0401
0402
0403
0404
0405
0406
0407
0408
0409 class DynTypedMatcher {
0410 public:
0411
0412 template <typename T>
0413 DynTypedMatcher(MatcherInterface<T> *Implementation)
0414 : SupportedKind(ASTNodeKind::getFromNodeKind<T>()),
0415 RestrictKind(SupportedKind), Implementation(Implementation) {}
0416
0417
0418 enum VariadicOperator {
0419
0420 VO_AllOf,
0421
0422
0423
0424 VO_AnyOf,
0425
0426
0427
0428 VO_EachOf,
0429
0430
0431
0432 VO_Optionally,
0433
0434
0435
0436
0437
0438 VO_UnaryNot
0439 };
0440
0441 static DynTypedMatcher
0442 constructVariadic(VariadicOperator Op, ASTNodeKind SupportedKind,
0443 std::vector<DynTypedMatcher> InnerMatchers);
0444
0445 static DynTypedMatcher
0446 constructRestrictedWrapper(const DynTypedMatcher &InnerMatcher,
0447 ASTNodeKind RestrictKind);
0448
0449
0450
0451
0452 static DynTypedMatcher trueMatcher(ASTNodeKind NodeKind);
0453
0454 void setAllowBind(bool AB) { AllowBind = AB; }
0455
0456
0457
0458
0459 bool canMatchNodesOfKind(ASTNodeKind Kind) const;
0460
0461
0462
0463 DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const;
0464
0465
0466
0467
0468
0469 DynTypedMatcher withTraversalKind(TraversalKind TK);
0470
0471
0472 bool matches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
0473 BoundNodesTreeBuilder *Builder) const;
0474
0475
0476
0477
0478
0479 bool matchesNoKindCheck(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
0480 BoundNodesTreeBuilder *Builder) const;
0481
0482
0483
0484
0485 std::optional<DynTypedMatcher> tryBind(StringRef ID) const;
0486
0487
0488
0489
0490
0491
0492
0493
0494 using MatcherIDType = std::pair<ASTNodeKind, uint64_t>;
0495 MatcherIDType getID() const {
0496
0497
0498 return std::make_pair(RestrictKind,
0499 reinterpret_cast<uint64_t>(Implementation.get()));
0500 }
0501
0502
0503
0504
0505
0506 ASTNodeKind getSupportedKind() const { return SupportedKind; }
0507
0508
0509
0510
0511
0512
0513 template <typename T> bool canConvertTo() const {
0514 return canConvertTo(ASTNodeKind::getFromNodeKind<T>());
0515 }
0516 bool canConvertTo(ASTNodeKind To) const;
0517
0518
0519
0520
0521
0522
0523 template <typename T> Matcher<T> convertTo() const {
0524 assert(canConvertTo<T>());
0525 return unconditionalConvertTo<T>();
0526 }
0527
0528
0529
0530
0531
0532 template <typename T> Matcher<T> unconditionalConvertTo() const;
0533
0534
0535
0536
0537
0538 std::optional<clang::TraversalKind> getTraversalKind() const {
0539 return Implementation->TraversalKind();
0540 }
0541
0542 private:
0543 DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind,
0544 IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
0545 : SupportedKind(SupportedKind), RestrictKind(RestrictKind),
0546 Implementation(std::move(Implementation)) {}
0547
0548 bool AllowBind = false;
0549 ASTNodeKind SupportedKind;
0550
0551
0552
0553
0554
0555 ASTNodeKind RestrictKind;
0556 IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
0557 };
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567 template <typename T>
0568 class Matcher {
0569 public:
0570
0571 explicit Matcher(MatcherInterface<T> *Implementation)
0572 : Implementation(Implementation) {}
0573
0574
0575
0576
0577 template <typename From>
0578 Matcher(const Matcher<From> &Other,
0579 std::enable_if_t<std::is_base_of<From, T>::value &&
0580 !std::is_same<From, T>::value> * = nullptr)
0581 : Implementation(restrictMatcher(Other.Implementation)) {
0582 assert(Implementation.getSupportedKind().isSame(
0583 ASTNodeKind::getFromNodeKind<T>()));
0584 }
0585
0586
0587
0588
0589 template <typename TypeT>
0590 Matcher(const Matcher<TypeT> &Other,
0591 std::enable_if_t<std::is_same<T, QualType>::value &&
0592 std::is_same<TypeT, Type>::value> * = nullptr)
0593 : Implementation(new TypeToQualType<TypeT>(Other)) {}
0594
0595
0596
0597
0598 template <typename To> Matcher<To> dynCastTo() const & {
0599 static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call.");
0600 return Matcher<To>(Implementation);
0601 }
0602
0603 template <typename To> Matcher<To> dynCastTo() && {
0604 static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call.");
0605 return Matcher<To>(std::move(Implementation));
0606 }
0607
0608
0609 bool matches(const T &Node,
0610 ASTMatchFinder *Finder,
0611 BoundNodesTreeBuilder *Builder) const {
0612 return Implementation.matches(DynTypedNode::create(Node), Finder, Builder);
0613 }
0614
0615
0616 DynTypedMatcher::MatcherIDType getID() const {
0617 return Implementation.getID();
0618 }
0619
0620
0621
0622
0623
0624 operator DynTypedMatcher() const & { return Implementation; }
0625
0626 operator DynTypedMatcher() && { return std::move(Implementation); }
0627
0628
0629
0630
0631
0632
0633
0634 template <typename TypeT>
0635 class TypeToQualType : public MatcherInterface<QualType> {
0636 const DynTypedMatcher InnerMatcher;
0637
0638 public:
0639 TypeToQualType(const Matcher<TypeT> &InnerMatcher)
0640 : InnerMatcher(InnerMatcher) {}
0641
0642 bool matches(const QualType &Node, ASTMatchFinder *Finder,
0643 BoundNodesTreeBuilder *Builder) const override {
0644 if (Node.isNull())
0645 return false;
0646 return this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder,
0647 Builder);
0648 }
0649
0650 std::optional<clang::TraversalKind> TraversalKind() const override {
0651 return this->InnerMatcher.getTraversalKind();
0652 }
0653 };
0654
0655 private:
0656
0657 template <typename U> friend class Matcher;
0658
0659
0660 friend class DynTypedMatcher;
0661
0662 static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) {
0663 return Other.dynCastTo(ASTNodeKind::getFromNodeKind<T>());
0664 }
0665
0666 explicit Matcher(const DynTypedMatcher &Implementation)
0667 : Implementation(restrictMatcher(Implementation)) {
0668 assert(this->Implementation.getSupportedKind().isSame(
0669 ASTNodeKind::getFromNodeKind<T>()));
0670 }
0671
0672 DynTypedMatcher Implementation;
0673 };
0674
0675
0676
0677 template <typename T>
0678 inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
0679 return Matcher<T>(Implementation);
0680 }
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700 class ASTMatchFinder {
0701 public:
0702
0703 enum BindKind {
0704
0705 BK_First,
0706
0707
0708 BK_All
0709 };
0710
0711
0712 enum AncestorMatchMode {
0713
0714 AMM_All,
0715
0716
0717 AMM_ParentOnly
0718 };
0719
0720 virtual ~ASTMatchFinder() = default;
0721
0722
0723
0724
0725
0726 virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
0727 const Matcher<NamedDecl> &Base,
0728 BoundNodesTreeBuilder *Builder,
0729 bool Directly) = 0;
0730
0731
0732
0733
0734
0735 virtual bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
0736 const Matcher<NamedDecl> &Base,
0737 BoundNodesTreeBuilder *Builder,
0738 bool Directly) = 0;
0739
0740 template <typename T>
0741 bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher,
0742 BoundNodesTreeBuilder *Builder, BindKind Bind) {
0743 static_assert(std::is_base_of<Decl, T>::value ||
0744 std::is_base_of<Stmt, T>::value ||
0745 std::is_base_of<NestedNameSpecifier, T>::value ||
0746 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
0747 std::is_base_of<TypeLoc, T>::value ||
0748 std::is_base_of<QualType, T>::value ||
0749 std::is_base_of<Attr, T>::value,
0750 "unsupported type for recursive matching");
0751 return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher,
0752 Builder, Bind);
0753 }
0754
0755 template <typename T>
0756 bool matchesDescendantOf(const T &Node, const DynTypedMatcher &Matcher,
0757 BoundNodesTreeBuilder *Builder, BindKind Bind) {
0758 static_assert(std::is_base_of<Decl, T>::value ||
0759 std::is_base_of<Stmt, T>::value ||
0760 std::is_base_of<NestedNameSpecifier, T>::value ||
0761 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
0762 std::is_base_of<TypeLoc, T>::value ||
0763 std::is_base_of<QualType, T>::value ||
0764 std::is_base_of<Attr, T>::value,
0765 "unsupported type for recursive matching");
0766 return matchesDescendantOf(DynTypedNode::create(Node), getASTContext(),
0767 Matcher, Builder, Bind);
0768 }
0769
0770
0771 template <typename T>
0772 bool matchesAncestorOf(const T &Node, const DynTypedMatcher &Matcher,
0773 BoundNodesTreeBuilder *Builder,
0774 AncestorMatchMode MatchMode) {
0775 static_assert(std::is_base_of<Decl, T>::value ||
0776 std::is_base_of<NestedNameSpecifierLoc, T>::value ||
0777 std::is_base_of<Stmt, T>::value ||
0778 std::is_base_of<TypeLoc, T>::value ||
0779 std::is_base_of<Attr, T>::value,
0780 "type not allowed for recursive matching");
0781 return matchesAncestorOf(DynTypedNode::create(Node), getASTContext(),
0782 Matcher, Builder, MatchMode);
0783 }
0784
0785 virtual ASTContext &getASTContext() const = 0;
0786
0787 virtual bool IsMatchingInASTNodeNotSpelledInSource() const = 0;
0788
0789 virtual bool IsMatchingInASTNodeNotAsIs() const = 0;
0790
0791 bool isTraversalIgnoringImplicitNodes() const;
0792
0793 protected:
0794 virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
0795 const DynTypedMatcher &Matcher,
0796 BoundNodesTreeBuilder *Builder,
0797 BindKind Bind) = 0;
0798
0799 virtual bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx,
0800 const DynTypedMatcher &Matcher,
0801 BoundNodesTreeBuilder *Builder,
0802 BindKind Bind) = 0;
0803
0804 virtual bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx,
0805 const DynTypedMatcher &Matcher,
0806 BoundNodesTreeBuilder *Builder,
0807 AncestorMatchMode MatchMode) = 0;
0808 private:
0809 friend struct ASTChildrenNotSpelledInSourceScope;
0810 virtual bool isMatchingChildrenNotSpelledInSource() const = 0;
0811 virtual void setMatchingChildrenNotSpelledInSource(bool Set) = 0;
0812 };
0813
0814 struct ASTChildrenNotSpelledInSourceScope {
0815 ASTChildrenNotSpelledInSourceScope(ASTMatchFinder *V, bool B)
0816 : MV(V), MB(V->isMatchingChildrenNotSpelledInSource()) {
0817 V->setMatchingChildrenNotSpelledInSource(B);
0818 }
0819 ~ASTChildrenNotSpelledInSourceScope() {
0820 MV->setMatchingChildrenNotSpelledInSource(MB);
0821 }
0822
0823 private:
0824 ASTMatchFinder *MV;
0825 bool MB;
0826 };
0827
0828
0829
0830
0831
0832 template <>
0833 inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const {
0834 assert(canConvertTo<QualType>());
0835 const ASTNodeKind SourceKind = getSupportedKind();
0836 if (SourceKind.isSame(ASTNodeKind::getFromNodeKind<Type>())) {
0837
0838 return unconditionalConvertTo<Type>();
0839 }
0840 return unconditionalConvertTo<QualType>();
0841 }
0842
0843
0844 template <typename MatcherT, typename IteratorT>
0845 IteratorT matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
0846 IteratorT End, ASTMatchFinder *Finder,
0847 BoundNodesTreeBuilder *Builder) {
0848 for (IteratorT I = Start; I != End; ++I) {
0849 BoundNodesTreeBuilder Result(*Builder);
0850 if (Matcher.matches(*I, Finder, &Result)) {
0851 *Builder = std::move(Result);
0852 return I;
0853 }
0854 }
0855 return End;
0856 }
0857
0858
0859
0860 template <typename MatcherT, typename IteratorT>
0861 IteratorT matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
0862 IteratorT End, ASTMatchFinder *Finder,
0863 BoundNodesTreeBuilder *Builder) {
0864 for (IteratorT I = Start; I != End; ++I) {
0865 BoundNodesTreeBuilder Result(*Builder);
0866 if (Matcher.matches(**I, Finder, &Result)) {
0867 *Builder = std::move(Result);
0868 return I;
0869 }
0870 }
0871 return End;
0872 }
0873
0874 template <typename T, std::enable_if_t<!std::is_base_of<FunctionDecl, T>::value>
0875 * = nullptr>
0876 inline bool isDefaultedHelper(const T *) {
0877 return false;
0878 }
0879 inline bool isDefaultedHelper(const FunctionDecl *FD) {
0880 return FD->isDefaulted();
0881 }
0882
0883
0884 template <typename Ty>
0885 class has_getDecl {
0886 using yes = char[1];
0887 using no = char[2];
0888
0889 template <typename Inner>
0890 static yes& test(Inner *I, decltype(I->getDecl()) * = nullptr);
0891
0892 template <typename>
0893 static no& test(...);
0894
0895 public:
0896 static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
0897 };
0898
0899
0900
0901
0902
0903 template <typename T, typename ArgT>
0904 class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
0905 static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
0906 std::is_base_of<FunctionDecl, T>::value,
0907 "unsupported class for matcher");
0908 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
0909 "argument type must be std::vector<std::string>");
0910
0911 public:
0912 explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names)
0913 : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
0914
0915 bool matchesNode(const T &Node) const override {
0916 return matchesSpecialized(Node);
0917 }
0918
0919 private:
0920
0921
0922
0923
0924 bool matchesSpecialized(const CXXOperatorCallExpr &Node) const {
0925 return llvm::is_contained(Names, getOperatorSpelling(Node.getOperator()));
0926 }
0927
0928
0929
0930 bool matchesSpecialized(const FunctionDecl &Node) const {
0931 return Node.isOverloadedOperator() &&
0932 llvm::is_contained(
0933 Names, getOperatorSpelling(Node.getOverloadedOperator()));
0934 }
0935
0936 std::vector<std::string> Names;
0937 };
0938
0939
0940
0941
0942 class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
0943 public:
0944 explicit HasNameMatcher(std::vector<std::string> Names);
0945
0946 bool matchesNode(const NamedDecl &Node) const override;
0947
0948 private:
0949
0950
0951
0952
0953 bool matchesNodeUnqualified(const NamedDecl &Node) const;
0954
0955
0956
0957
0958
0959
0960
0961 bool matchesNodeFullFast(const NamedDecl &Node) const;
0962
0963
0964
0965
0966
0967
0968 bool matchesNodeFullSlow(const NamedDecl &Node) const;
0969
0970 bool UseUnqualifiedMatch;
0971 std::vector<std::string> Names;
0972 };
0973
0974
0975
0976 Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs);
0977
0978
0979
0980 Matcher<ObjCMessageExpr> hasAnySelectorFunc(
0981 ArrayRef<const StringRef *> NameRefs);
0982
0983
0984
0985
0986
0987 template <typename T, typename DeclMatcherT>
0988 class HasDeclarationMatcher : public MatcherInterface<T> {
0989 static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
0990 "instantiated with wrong types");
0991
0992 DynTypedMatcher InnerMatcher;
0993
0994 public:
0995 explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
0996 : InnerMatcher(InnerMatcher) {}
0997
0998 bool matches(const T &Node, ASTMatchFinder *Finder,
0999 BoundNodesTreeBuilder *Builder) const override {
1000 return matchesSpecialized(Node, Finder, Builder);
1001 }
1002
1003 private:
1004
1005 bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
1006 BoundNodesTreeBuilder *Builder) const {
1007 if (Node.isNull())
1008 return false;
1009
1010 return matchesSpecialized(*Node, Finder, Builder);
1011 }
1012
1013
1014
1015 bool matchesSpecialized(const Type &Node, ASTMatchFinder *Finder,
1016 BoundNodesTreeBuilder *Builder) const {
1017
1018
1019 if (const auto *S = dyn_cast<DeducedType>(&Node)) {
1020 QualType DT = S->getDeducedType();
1021 return !DT.isNull() ? matchesSpecialized(*DT, Finder, Builder) : false;
1022 }
1023
1024
1025
1026 if (const auto *S = dyn_cast<TagType>(&Node)) {
1027 return matchesDecl(S->getDecl(), Finder, Builder);
1028 }
1029 if (const auto *S = dyn_cast<InjectedClassNameType>(&Node)) {
1030 return matchesDecl(S->getDecl(), Finder, Builder);
1031 }
1032 if (const auto *S = dyn_cast<TemplateTypeParmType>(&Node)) {
1033 return matchesDecl(S->getDecl(), Finder, Builder);
1034 }
1035 if (const auto *S = dyn_cast<TypedefType>(&Node)) {
1036 return matchesDecl(S->getDecl(), Finder, Builder);
1037 }
1038 if (const auto *S = dyn_cast<UnresolvedUsingType>(&Node)) {
1039 return matchesDecl(S->getDecl(), Finder, Builder);
1040 }
1041 if (const auto *S = dyn_cast<ObjCObjectType>(&Node)) {
1042 return matchesDecl(S->getInterface(), Finder, Builder);
1043 }
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053 if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(&Node)) {
1054 return matchesSpecialized(S->getReplacementType(), Finder, Builder);
1055 }
1056
1057
1058
1059
1060 if (const auto *S = dyn_cast<TemplateSpecializationType>(&Node)) {
1061 if (!S->isTypeAlias() && S->isSugared()) {
1062
1063
1064
1065
1066
1067
1068 return matchesSpecialized(*S->desugar(), Finder, Builder);
1069 }
1070
1071
1072 return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder,
1073 Builder);
1074 }
1075
1076
1077
1078
1079 if (const auto *S = dyn_cast<ElaboratedType>(&Node)) {
1080 return matchesSpecialized(S->desugar(), Finder, Builder);
1081 }
1082
1083
1084
1085 if (const auto *S = dyn_cast<UsingType>(&Node)) {
1086 return matchesSpecialized(S->desugar(), Finder, Builder);
1087 }
1088 return false;
1089 }
1090
1091
1092
1093 bool matchesSpecialized(const DeclRefExpr &Node, ASTMatchFinder *Finder,
1094 BoundNodesTreeBuilder *Builder) const {
1095 return matchesDecl(Node.getDecl(), Finder, Builder);
1096 }
1097
1098
1099
1100 bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder,
1101 BoundNodesTreeBuilder *Builder) const {
1102 return matchesDecl(Node.getCalleeDecl(), Finder, Builder);
1103 }
1104
1105
1106
1107 bool matchesSpecialized(const CXXConstructExpr &Node,
1108 ASTMatchFinder *Finder,
1109 BoundNodesTreeBuilder *Builder) const {
1110 return matchesDecl(Node.getConstructor(), Finder, Builder);
1111 }
1112
1113 bool matchesSpecialized(const ObjCIvarRefExpr &Node,
1114 ASTMatchFinder *Finder,
1115 BoundNodesTreeBuilder *Builder) const {
1116 return matchesDecl(Node.getDecl(), Finder, Builder);
1117 }
1118
1119 bool matchesSpecialized(const ObjCInterfaceDecl &Node, ASTMatchFinder *Finder,
1120 BoundNodesTreeBuilder *Builder) const {
1121 return matchesDecl(Node.getCanonicalDecl(), Finder, Builder);
1122 }
1123
1124
1125
1126 bool matchesSpecialized(const CXXNewExpr &Node,
1127 ASTMatchFinder *Finder,
1128 BoundNodesTreeBuilder *Builder) const {
1129 return matchesDecl(Node.getOperatorNew(), Finder, Builder);
1130 }
1131
1132
1133
1134 bool matchesSpecialized(const MemberExpr &Node,
1135 ASTMatchFinder *Finder,
1136 BoundNodesTreeBuilder *Builder) const {
1137 return matchesDecl(Node.getMemberDecl(), Finder, Builder);
1138 }
1139
1140
1141
1142 bool matchesSpecialized(const AddrLabelExpr &Node,
1143 ASTMatchFinder *Finder,
1144 BoundNodesTreeBuilder *Builder) const {
1145 return matchesDecl(Node.getLabel(), Finder, Builder);
1146 }
1147
1148
1149
1150 bool matchesSpecialized(const LabelStmt &Node, ASTMatchFinder *Finder,
1151 BoundNodesTreeBuilder *Builder) const {
1152 return matchesDecl(Node.getDecl(), Finder, Builder);
1153 }
1154
1155
1156
1157 bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
1158 BoundNodesTreeBuilder *Builder) const {
1159 return Node != nullptr &&
1160 !(Finder->isTraversalIgnoringImplicitNodes() &&
1161 Node->isImplicit()) &&
1162 this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder,
1163 Builder);
1164 }
1165 };
1166
1167
1168
1169 template <typename T>
1170 struct IsBaseType {
1171 static const bool value =
1172 std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value ||
1173 std::is_same<T, QualType>::value || std::is_same<T, Type>::value ||
1174 std::is_same<T, TypeLoc>::value ||
1175 std::is_same<T, NestedNameSpecifier>::value ||
1176 std::is_same<T, NestedNameSpecifierLoc>::value ||
1177 std::is_same<T, CXXCtorInitializer>::value ||
1178 std::is_same<T, TemplateArgumentLoc>::value ||
1179 std::is_same<T, Attr>::value;
1180 };
1181 template <typename T>
1182 const bool IsBaseType<T>::value;
1183
1184
1185
1186
1187 using AllNodeBaseTypes =
1188 TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
1189 Type, TypeLoc, CXXCtorInitializer, Attr>;
1190
1191
1192
1193
1194
1195 template <class T> struct ExtractFunctionArgMeta;
1196 template <class T> struct ExtractFunctionArgMeta<void(T)> {
1197 using type = T;
1198 };
1199
1200 template <class T, class Tuple, std::size_t... I>
1201 constexpr T *new_from_tuple_impl(Tuple &&t, std::index_sequence<I...>) {
1202 return new T(std::get<I>(std::forward<Tuple>(t))...);
1203 }
1204
1205 template <class T, class Tuple> constexpr T *new_from_tuple(Tuple &&t) {
1206 return new_from_tuple_impl<T>(
1207 std::forward<Tuple>(t),
1208 std::make_index_sequence<
1209 std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
1210 }
1211
1212
1213 using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
1214 using AdaptativeDefaultToTypes =
1215 TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
1216 QualType, Attr>;
1217
1218
1219 using HasDeclarationSupportedTypes =
1220 TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
1221 ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
1222 MemberExpr, QualType, RecordType, TagType,
1223 TemplateSpecializationType, TemplateTypeParmType, TypedefType,
1224 UnresolvedUsingType, ObjCIvarRefExpr, ObjCInterfaceDecl>;
1225
1226
1227
1228
1229
1230 template <typename T> class BindableMatcher : public Matcher<T> {
1231 public:
1232 explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {}
1233 explicit BindableMatcher(MatcherInterface<T> *Implementation)
1234 : Matcher<T>(Implementation) {}
1235
1236
1237
1238
1239
1240 Matcher<T> bind(StringRef ID) const {
1241 return DynTypedMatcher(*this)
1242 .tryBind(ID)
1243 ->template unconditionalConvertTo<T>();
1244 }
1245
1246
1247
1248 operator DynTypedMatcher() const {
1249 DynTypedMatcher Result = static_cast<const Matcher<T> &>(*this);
1250 Result.setAllowBind(true);
1251 return Result;
1252 }
1253 };
1254
1255
1256
1257
1258
1259 class TrueMatcher {
1260 public:
1261 using ReturnTypes = AllNodeBaseTypes;
1262
1263 template <typename T> operator Matcher<T>() const {
1264 return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
1265 .template unconditionalConvertTo<T>();
1266 }
1267 };
1268
1269
1270 template <typename T>
1271 BindableMatcher<T>
1272 makeAllOfComposite(ArrayRef<const Matcher<T> *> InnerMatchers) {
1273
1274 if (InnerMatchers.empty()) {
1275 return BindableMatcher<T>(TrueMatcher());
1276 }
1277
1278
1279 if (InnerMatchers.size() == 1) {
1280 return BindableMatcher<T>(*InnerMatchers[0]);
1281 }
1282
1283 using PI = llvm::pointee_iterator<const Matcher<T> *const *>;
1284
1285 std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
1286 PI(InnerMatchers.end()));
1287 return BindableMatcher<T>(
1288 DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
1289 ASTNodeKind::getFromNodeKind<T>(),
1290 std::move(DynMatchers))
1291 .template unconditionalConvertTo<T>());
1292 }
1293
1294
1295
1296
1297
1298
1299
1300 template <typename T, typename InnerT>
1301 BindableMatcher<T>
1302 makeDynCastAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
1303 return BindableMatcher<T>(
1304 makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
1305 }
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318 template <typename SourceT, typename TargetT>
1319 class VariadicDynCastAllOfMatcher
1320 : public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
1321 makeDynCastAllOfComposite<SourceT, TargetT>> {
1322 public:
1323 VariadicDynCastAllOfMatcher() {}
1324 };
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336 template <typename T>
1337 class VariadicAllOfMatcher
1338 : public VariadicFunction<BindableMatcher<T>, Matcher<T>,
1339 makeAllOfComposite<T>> {
1340 public:
1341 VariadicAllOfMatcher() {}
1342 };
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353 template <typename... Ps> class VariadicOperatorMatcher {
1354 public:
1355 VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
1356 : Op(Op), Params(std::forward<Ps>(Params)...) {}
1357
1358 template <typename T> operator Matcher<T>() const & {
1359 return DynTypedMatcher::constructVariadic(
1360 Op, ASTNodeKind::getFromNodeKind<T>(),
1361 getMatchers<T>(std::index_sequence_for<Ps...>()))
1362 .template unconditionalConvertTo<T>();
1363 }
1364
1365 template <typename T> operator Matcher<T>() && {
1366 return DynTypedMatcher::constructVariadic(
1367 Op, ASTNodeKind::getFromNodeKind<T>(),
1368 getMatchers<T>(std::index_sequence_for<Ps...>()))
1369 .template unconditionalConvertTo<T>();
1370 }
1371
1372 private:
1373
1374 template <typename T, std::size_t... Is>
1375 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) const & {
1376 return {Matcher<T>(std::get<Is>(Params))...};
1377 }
1378
1379 template <typename T, std::size_t... Is>
1380 std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) && {
1381 return {Matcher<T>(std::get<Is>(std::move(Params)))...};
1382 }
1383
1384 const DynTypedMatcher::VariadicOperator Op;
1385 std::tuple<Ps...> Params;
1386 };
1387
1388
1389
1390 template <unsigned MinCount, unsigned MaxCount>
1391 struct VariadicOperatorMatcherFunc {
1392 DynTypedMatcher::VariadicOperator Op;
1393
1394 template <typename... Ms>
1395 VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps) const {
1396 static_assert(MinCount <= sizeof...(Ms) && sizeof...(Ms) <= MaxCount,
1397 "invalid number of parameters for variadic matcher");
1398 return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
1399 }
1400 };
1401
1402 template <typename T, bool IsBaseOf, typename Head, typename Tail>
1403 struct GetCladeImpl {
1404 using Type = Head;
1405 };
1406 template <typename T, typename Head, typename Tail>
1407 struct GetCladeImpl<T, false, Head, Tail>
1408 : GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
1409 typename Tail::head, typename Tail::tail> {};
1410
1411 template <typename T, typename... U>
1412 struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
1413
1414 template <typename CladeType, typename... MatcherTypes>
1415 struct MapAnyOfMatcherImpl {
1416
1417 template <typename... InnerMatchers>
1418 BindableMatcher<CladeType>
1419 operator()(InnerMatchers &&... InnerMatcher) const {
1420 return VariadicAllOfMatcher<CladeType>()(std::apply(
1421 internal::VariadicOperatorMatcherFunc<
1422 0, std::numeric_limits<unsigned>::max()>{
1423 internal::DynTypedMatcher::VO_AnyOf},
1424 std::apply(
1425 [&](auto... Matcher) {
1426 return std::make_tuple(Matcher(InnerMatcher...)...);
1427 },
1428 std::tuple<
1429 VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
1430 }
1431 };
1432
1433 template <typename... MatcherTypes>
1434 using MapAnyOfMatcher =
1435 MapAnyOfMatcherImpl<typename GetClade<MatcherTypes...>::Type,
1436 MatcherTypes...>;
1437
1438 template <typename... MatcherTypes> struct MapAnyOfHelper {
1439 using CladeType = typename GetClade<MatcherTypes...>::Type;
1440
1441 MapAnyOfMatcher<MatcherTypes...> with;
1442
1443 operator BindableMatcher<CladeType>() const { return with(); }
1444
1445 Matcher<CladeType> bind(StringRef ID) const { return with().bind(ID); }
1446 };
1447
1448 template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
1449 typename T, typename ToTypes>
1450 class ArgumentAdaptingMatcherFuncAdaptor {
1451 public:
1452 explicit ArgumentAdaptingMatcherFuncAdaptor(const Matcher<T> &InnerMatcher)
1453 : InnerMatcher(InnerMatcher) {}
1454
1455 using ReturnTypes = ToTypes;
1456
1457 template <typename To> operator Matcher<To>() const & {
1458 return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
1459 }
1460
1461 template <typename To> operator Matcher<To>() && {
1462 return Matcher<To>(new ArgumentAdapterT<To, T>(std::move(InnerMatcher)));
1463 }
1464
1465 private:
1466 Matcher<T> InnerMatcher;
1467 };
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482 template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
1483 typename FromTypes = AdaptativeDefaultFromTypes,
1484 typename ToTypes = AdaptativeDefaultToTypes>
1485 struct ArgumentAdaptingMatcherFunc {
1486 template <typename T>
1487 static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1488 create(const Matcher<T> &InnerMatcher) {
1489 return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>(
1490 InnerMatcher);
1491 }
1492
1493 template <typename T>
1494 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
1495 operator()(const Matcher<T> &InnerMatcher) const {
1496 return create(InnerMatcher);
1497 }
1498
1499 template <typename... T>
1500 ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT,
1501 typename GetClade<T...>::Type, ToTypes>
1502 operator()(const MapAnyOfHelper<T...> &InnerMatcher) const {
1503 return create(InnerMatcher.with());
1504 }
1505 };
1506
1507 template <typename T> class TraversalMatcher : public MatcherInterface<T> {
1508 DynTypedMatcher InnerMatcher;
1509 clang::TraversalKind Traversal;
1510
1511 public:
1512 explicit TraversalMatcher(clang::TraversalKind TK,
1513 const Matcher<T> &InnerMatcher)
1514 : InnerMatcher(InnerMatcher), Traversal(TK) {}
1515
1516 bool matches(const T &Node, ASTMatchFinder *Finder,
1517 BoundNodesTreeBuilder *Builder) const override {
1518 return this->InnerMatcher.matches(DynTypedNode::create(Node), Finder,
1519 Builder);
1520 }
1521
1522 std::optional<clang::TraversalKind> TraversalKind() const override {
1523 if (auto NestedKind = this->InnerMatcher.getTraversalKind())
1524 return NestedKind;
1525 return Traversal;
1526 }
1527 };
1528
1529 template <typename MatcherType> class TraversalWrapper {
1530 public:
1531 TraversalWrapper(TraversalKind TK, const MatcherType &InnerMatcher)
1532 : TK(TK), InnerMatcher(InnerMatcher) {}
1533
1534 template <typename T> operator Matcher<T>() const & {
1535 return internal::DynTypedMatcher::constructRestrictedWrapper(
1536 new internal::TraversalMatcher<T>(TK, InnerMatcher),
1537 ASTNodeKind::getFromNodeKind<T>())
1538 .template unconditionalConvertTo<T>();
1539 }
1540
1541 template <typename T> operator Matcher<T>() && {
1542 return internal::DynTypedMatcher::constructRestrictedWrapper(
1543 new internal::TraversalMatcher<T>(TK, std::move(InnerMatcher)),
1544 ASTNodeKind::getFromNodeKind<T>())
1545 .template unconditionalConvertTo<T>();
1546 }
1547
1548 private:
1549 TraversalKind TK;
1550 MatcherType InnerMatcher;
1551 };
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565 template <template <typename T, typename... Params> class MatcherT,
1566 typename ReturnTypesF, typename... ParamTypes>
1567 class PolymorphicMatcher {
1568 public:
1569 PolymorphicMatcher(const ParamTypes &... Params) : Params(Params...) {}
1570
1571 using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1572
1573 template <typename T> operator Matcher<T>() const & {
1574 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1575 "right polymorphic conversion");
1576 return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params));
1577 }
1578
1579 template <typename T> operator Matcher<T>() && {
1580 static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
1581 "right polymorphic conversion");
1582 return Matcher<T>(
1583 new_from_tuple<MatcherT<T, ParamTypes...>>(std::move(Params)));
1584 }
1585
1586 private:
1587 std::tuple<ParamTypes...> Params;
1588 };
1589
1590
1591
1592
1593
1594 template <typename T, typename ChildT>
1595 class HasMatcher : public MatcherInterface<T> {
1596 DynTypedMatcher InnerMatcher;
1597
1598 public:
1599 explicit HasMatcher(const Matcher<ChildT> &InnerMatcher)
1600 : InnerMatcher(InnerMatcher) {}
1601
1602 bool matches(const T &Node, ASTMatchFinder *Finder,
1603 BoundNodesTreeBuilder *Builder) const override {
1604 return Finder->matchesChildOf(Node, this->InnerMatcher, Builder,
1605 ASTMatchFinder::BK_First);
1606 }
1607 };
1608
1609
1610
1611
1612
1613
1614 template <typename T, typename ChildT>
1615 class ForEachMatcher : public MatcherInterface<T> {
1616 static_assert(IsBaseType<ChildT>::value,
1617 "for each only accepts base type matcher");
1618
1619 DynTypedMatcher InnerMatcher;
1620
1621 public:
1622 explicit ForEachMatcher(const Matcher<ChildT> &InnerMatcher)
1623 : InnerMatcher(InnerMatcher) {}
1624
1625 bool matches(const T &Node, ASTMatchFinder *Finder,
1626 BoundNodesTreeBuilder *Builder) const override {
1627 return Finder->matchesChildOf(
1628 Node, this->InnerMatcher, Builder,
1629 ASTMatchFinder::BK_All);
1630 }
1631 };
1632
1633
1634
1635 template <typename T>
1636 inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const {
1637 return Matcher<T>(*this);
1638 }
1639
1640
1641
1642
1643
1644 template <typename T, typename DescendantT>
1645 class HasDescendantMatcher : public MatcherInterface<T> {
1646 static_assert(IsBaseType<DescendantT>::value,
1647 "has descendant only accepts base type matcher");
1648
1649 DynTypedMatcher DescendantMatcher;
1650
1651 public:
1652 explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
1653 : DescendantMatcher(DescendantMatcher) {}
1654
1655 bool matches(const T &Node, ASTMatchFinder *Finder,
1656 BoundNodesTreeBuilder *Builder) const override {
1657 return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
1658 ASTMatchFinder::BK_First);
1659 }
1660 };
1661
1662
1663
1664
1665
1666 template <typename T, typename ParentT>
1667 class HasParentMatcher : public MatcherInterface<T> {
1668 static_assert(IsBaseType<ParentT>::value,
1669 "has parent only accepts base type matcher");
1670
1671 DynTypedMatcher ParentMatcher;
1672
1673 public:
1674 explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
1675 : ParentMatcher(ParentMatcher) {}
1676
1677 bool matches(const T &Node, ASTMatchFinder *Finder,
1678 BoundNodesTreeBuilder *Builder) const override {
1679 return Finder->matchesAncestorOf(Node, this->ParentMatcher, Builder,
1680 ASTMatchFinder::AMM_ParentOnly);
1681 }
1682 };
1683
1684
1685
1686
1687
1688 template <typename T, typename AncestorT>
1689 class HasAncestorMatcher : public MatcherInterface<T> {
1690 static_assert(IsBaseType<AncestorT>::value,
1691 "has ancestor only accepts base type matcher");
1692
1693 DynTypedMatcher AncestorMatcher;
1694
1695 public:
1696 explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher)
1697 : AncestorMatcher(AncestorMatcher) {}
1698
1699 bool matches(const T &Node, ASTMatchFinder *Finder,
1700 BoundNodesTreeBuilder *Builder) const override {
1701 return Finder->matchesAncestorOf(Node, this->AncestorMatcher, Builder,
1702 ASTMatchFinder::AMM_All);
1703 }
1704 };
1705
1706
1707
1708
1709
1710
1711
1712 template <typename T, typename DescendantT>
1713 class ForEachDescendantMatcher : public MatcherInterface<T> {
1714 static_assert(IsBaseType<DescendantT>::value,
1715 "for each descendant only accepts base type matcher");
1716
1717 DynTypedMatcher DescendantMatcher;
1718
1719 public:
1720 explicit ForEachDescendantMatcher(
1721 const Matcher<DescendantT> &DescendantMatcher)
1722 : DescendantMatcher(DescendantMatcher) {}
1723
1724 bool matches(const T &Node, ASTMatchFinder *Finder,
1725 BoundNodesTreeBuilder *Builder) const override {
1726 return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
1727 ASTMatchFinder::BK_All);
1728 }
1729 };
1730
1731
1732
1733 template <typename T, typename ValueT>
1734 class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> {
1735 static_assert(std::is_base_of<CharacterLiteral, T>::value ||
1736 std::is_base_of<CXXBoolLiteralExpr, T>::value ||
1737 std::is_base_of<FloatingLiteral, T>::value ||
1738 std::is_base_of<IntegerLiteral, T>::value,
1739 "the node must have a getValue method");
1740
1741 public:
1742 explicit ValueEqualsMatcher(const ValueT &ExpectedValue)
1743 : ExpectedValue(ExpectedValue) {}
1744
1745 bool matchesNode(const T &Node) const override {
1746 return Node.getValue() == ExpectedValue;
1747 }
1748
1749 private:
1750 ValueT ExpectedValue;
1751 };
1752
1753
1754
1755 template <>
1756 inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
1757 const FloatingLiteral &Node) const {
1758 if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1759 return Node.getValue().convertToFloat() == ExpectedValue;
1760 if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1761 return Node.getValue().convertToDouble() == ExpectedValue;
1762 return false;
1763 }
1764 template <>
1765 inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
1766 const FloatingLiteral &Node) const {
1767 if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
1768 return Node.getValue().convertToFloat() == ExpectedValue;
1769 if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
1770 return Node.getValue().convertToDouble() == ExpectedValue;
1771 return false;
1772 }
1773 template <>
1774 inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
1775 const FloatingLiteral &Node) const {
1776 return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
1777 }
1778
1779
1780
1781 template <typename TLoc, typename T>
1782 class LocMatcher : public MatcherInterface<TLoc> {
1783 DynTypedMatcher InnerMatcher;
1784
1785 public:
1786 explicit LocMatcher(const Matcher<T> &InnerMatcher)
1787 : InnerMatcher(InnerMatcher) {}
1788
1789 bool matches(const TLoc &Node, ASTMatchFinder *Finder,
1790 BoundNodesTreeBuilder *Builder) const override {
1791 if (!Node)
1792 return false;
1793 return this->InnerMatcher.matches(extract(Node), Finder, Builder);
1794 }
1795
1796 private:
1797 static DynTypedNode extract(const NestedNameSpecifierLoc &Loc) {
1798 return DynTypedNode::create(*Loc.getNestedNameSpecifier());
1799 }
1800 };
1801
1802
1803
1804
1805
1806 class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> {
1807 Matcher<QualType> InnerMatcher;
1808
1809 public:
1810 explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher)
1811 : InnerMatcher(InnerMatcher) {}
1812
1813 bool matches(const TypeLoc &Node, ASTMatchFinder *Finder,
1814 BoundNodesTreeBuilder *Builder) const override {
1815 if (!Node)
1816 return false;
1817 return this->InnerMatcher.matches(Node.getType(), Finder, Builder);
1818 }
1819 };
1820
1821
1822
1823
1824 template <typename T> class TypeTraverseMatcher : public MatcherInterface<T> {
1825 DynTypedMatcher InnerMatcher;
1826
1827 public:
1828 explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher,
1829 QualType (T::*TraverseFunction)() const)
1830 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1831
1832 bool matches(const T &Node, ASTMatchFinder *Finder,
1833 BoundNodesTreeBuilder *Builder) const override {
1834 QualType NextNode = (Node.*TraverseFunction)();
1835 if (NextNode.isNull())
1836 return false;
1837 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1838 Builder);
1839 }
1840
1841 private:
1842 QualType (T::*TraverseFunction)() const;
1843 };
1844
1845
1846
1847
1848 template <typename T>
1849 class TypeLocTraverseMatcher : public MatcherInterface<T> {
1850 DynTypedMatcher InnerMatcher;
1851
1852 public:
1853 explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher,
1854 TypeLoc (T::*TraverseFunction)() const)
1855 : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
1856
1857 bool matches(const T &Node, ASTMatchFinder *Finder,
1858 BoundNodesTreeBuilder *Builder) const override {
1859 TypeLoc NextNode = (Node.*TraverseFunction)();
1860 if (!NextNode)
1861 return false;
1862 return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
1863 Builder);
1864 }
1865
1866 private:
1867 TypeLoc (T::*TraverseFunction)() const;
1868 };
1869
1870
1871
1872
1873
1874
1875
1876 template <typename InnerTBase,
1877 template <typename OuterT> class Getter,
1878 template <typename OuterT> class MatcherImpl,
1879 typename ReturnTypesF>
1880 class TypeTraversePolymorphicMatcher {
1881 private:
1882 using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
1883 ReturnTypesF>;
1884
1885 static Self create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers);
1886
1887 public:
1888 using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type;
1889
1890 explicit TypeTraversePolymorphicMatcher(
1891 ArrayRef<const Matcher<InnerTBase> *> InnerMatchers)
1892 : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
1893
1894 template <typename OuterT> operator Matcher<OuterT>() const {
1895 return Matcher<OuterT>(
1896 new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
1897 }
1898
1899 struct Func
1900 : public VariadicFunction<Self, Matcher<InnerTBase>, &Self::create> {
1901 Func() {}
1902 };
1903
1904 private:
1905 Matcher<InnerTBase> InnerMatcher;
1906 };
1907
1908
1909
1910
1911
1912 template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher {
1913 struct Wrapper {
1914 Wrapper() : M(Func()) {}
1915
1916 Matcher M;
1917 };
1918
1919 public:
1920 static const Matcher &getInstance() {
1921 static llvm::ManagedStatic<Wrapper> Instance;
1922 return Instance->M;
1923 }
1924 };
1925
1926
1927
1928
1929 template <typename InnerTBase, template <typename OuterT> class Getter,
1930 template <typename OuterT> class MatcherImpl, typename ReturnTypesF>
1931 TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
1932 TypeTraversePolymorphicMatcher<
1933 InnerTBase, Getter, MatcherImpl,
1934 ReturnTypesF>::create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers) {
1935 return Self(InnerMatchers);
1936 }
1937
1938
1939
1940 inline ArrayRef<TemplateArgument>
1941 getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
1942 return D.getTemplateArgs().asArray();
1943 }
1944
1945 inline ArrayRef<TemplateArgument>
1946 getTemplateSpecializationArgs(const VarTemplateSpecializationDecl &D) {
1947 return D.getTemplateArgs().asArray();
1948 }
1949
1950 inline ArrayRef<TemplateArgument>
1951 getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
1952 return T.template_arguments();
1953 }
1954
1955 inline ArrayRef<TemplateArgument>
1956 getTemplateSpecializationArgs(const FunctionDecl &FD) {
1957 if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
1958 return TemplateArgs->asArray();
1959 return {};
1960 }
1961
1962 inline ArrayRef<TemplateArgumentLoc>
1963 getTemplateArgsWritten(const ClassTemplateSpecializationDecl &D) {
1964 if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
1965 return Args->arguments();
1966 return {};
1967 }
1968
1969 inline ArrayRef<TemplateArgumentLoc>
1970 getTemplateArgsWritten(const VarTemplateSpecializationDecl &D) {
1971 if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
1972 return Args->arguments();
1973 return {};
1974 }
1975
1976 inline ArrayRef<TemplateArgumentLoc>
1977 getTemplateArgsWritten(const FunctionDecl &FD) {
1978 if (const auto *Args = FD.getTemplateSpecializationArgsAsWritten())
1979 return Args->arguments();
1980 return {};
1981 }
1982
1983 inline ArrayRef<TemplateArgumentLoc>
1984 getTemplateArgsWritten(const DeclRefExpr &DRE) {
1985 if (const auto *Args = DRE.getTemplateArgs())
1986 return {Args, DRE.getNumTemplateArgs()};
1987 return {};
1988 }
1989
1990 inline SmallVector<TemplateArgumentLoc>
1991 getTemplateArgsWritten(const TemplateSpecializationTypeLoc &T) {
1992 SmallVector<TemplateArgumentLoc> Args;
1993 if (!T.isNull()) {
1994 Args.reserve(T.getNumArgs());
1995 for (unsigned I = 0; I < T.getNumArgs(); ++I)
1996 Args.emplace_back(T.getArgLoc(I));
1997 }
1998 return Args;
1999 }
2000
2001 struct NotEqualsBoundNodePredicate {
2002 bool operator()(const internal::BoundNodesMap &Nodes) const {
2003 return Nodes.getNode(ID) != Node;
2004 }
2005
2006 std::string ID;
2007 DynTypedNode Node;
2008 };
2009
2010 template <typename Ty, typename Enable = void> struct GetBodyMatcher {
2011 static const Stmt *get(const Ty &Node) { return Node.getBody(); }
2012 };
2013
2014 template <typename Ty>
2015 struct GetBodyMatcher<
2016 Ty, std::enable_if_t<std::is_base_of<FunctionDecl, Ty>::value>> {
2017 static const Stmt *get(const Ty &Node) {
2018 return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr;
2019 }
2020 };
2021
2022 template <typename NodeType>
2023 inline std::optional<BinaryOperatorKind>
2024 equivalentBinaryOperator(const NodeType &Node) {
2025 return Node.getOpcode();
2026 }
2027
2028 template <>
2029 inline std::optional<BinaryOperatorKind>
2030 equivalentBinaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
2031 if (Node.getNumArgs() != 2)
2032 return std::nullopt;
2033 switch (Node.getOperator()) {
2034 default:
2035 return std::nullopt;
2036 case OO_ArrowStar:
2037 return BO_PtrMemI;
2038 case OO_Star:
2039 return BO_Mul;
2040 case OO_Slash:
2041 return BO_Div;
2042 case OO_Percent:
2043 return BO_Rem;
2044 case OO_Plus:
2045 return BO_Add;
2046 case OO_Minus:
2047 return BO_Sub;
2048 case OO_LessLess:
2049 return BO_Shl;
2050 case OO_GreaterGreater:
2051 return BO_Shr;
2052 case OO_Spaceship:
2053 return BO_Cmp;
2054 case OO_Less:
2055 return BO_LT;
2056 case OO_Greater:
2057 return BO_GT;
2058 case OO_LessEqual:
2059 return BO_LE;
2060 case OO_GreaterEqual:
2061 return BO_GE;
2062 case OO_EqualEqual:
2063 return BO_EQ;
2064 case OO_ExclaimEqual:
2065 return BO_NE;
2066 case OO_Amp:
2067 return BO_And;
2068 case OO_Caret:
2069 return BO_Xor;
2070 case OO_Pipe:
2071 return BO_Or;
2072 case OO_AmpAmp:
2073 return BO_LAnd;
2074 case OO_PipePipe:
2075 return BO_LOr;
2076 case OO_Equal:
2077 return BO_Assign;
2078 case OO_StarEqual:
2079 return BO_MulAssign;
2080 case OO_SlashEqual:
2081 return BO_DivAssign;
2082 case OO_PercentEqual:
2083 return BO_RemAssign;
2084 case OO_PlusEqual:
2085 return BO_AddAssign;
2086 case OO_MinusEqual:
2087 return BO_SubAssign;
2088 case OO_LessLessEqual:
2089 return BO_ShlAssign;
2090 case OO_GreaterGreaterEqual:
2091 return BO_ShrAssign;
2092 case OO_AmpEqual:
2093 return BO_AndAssign;
2094 case OO_CaretEqual:
2095 return BO_XorAssign;
2096 case OO_PipeEqual:
2097 return BO_OrAssign;
2098 case OO_Comma:
2099 return BO_Comma;
2100 }
2101 }
2102
2103 template <typename NodeType>
2104 inline std::optional<UnaryOperatorKind>
2105 equivalentUnaryOperator(const NodeType &Node) {
2106 return Node.getOpcode();
2107 }
2108
2109 template <>
2110 inline std::optional<UnaryOperatorKind>
2111 equivalentUnaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
2112 if (Node.getNumArgs() != 1 && Node.getOperator() != OO_PlusPlus &&
2113 Node.getOperator() != OO_MinusMinus)
2114 return std::nullopt;
2115 switch (Node.getOperator()) {
2116 default:
2117 return std::nullopt;
2118 case OO_Plus:
2119 return UO_Plus;
2120 case OO_Minus:
2121 return UO_Minus;
2122 case OO_Amp:
2123 return UO_AddrOf;
2124 case OO_Star:
2125 return UO_Deref;
2126 case OO_Tilde:
2127 return UO_Not;
2128 case OO_Exclaim:
2129 return UO_LNot;
2130 case OO_PlusPlus: {
2131 const auto *FD = Node.getDirectCallee();
2132 if (!FD)
2133 return std::nullopt;
2134 return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
2135 }
2136 case OO_MinusMinus: {
2137 const auto *FD = Node.getDirectCallee();
2138 if (!FD)
2139 return std::nullopt;
2140 return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
2141 }
2142 case OO_Coawait:
2143 return UO_Coawait;
2144 }
2145 }
2146
2147 template <typename NodeType> inline const Expr *getLHS(const NodeType &Node) {
2148 return Node.getLHS();
2149 }
2150 template <>
2151 inline const Expr *
2152 getLHS<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
2153 if (!internal::equivalentBinaryOperator(Node))
2154 return nullptr;
2155 return Node.getArg(0);
2156 }
2157 template <typename NodeType> inline const Expr *getRHS(const NodeType &Node) {
2158 return Node.getRHS();
2159 }
2160 template <>
2161 inline const Expr *
2162 getRHS<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
2163 if (!internal::equivalentBinaryOperator(Node))
2164 return nullptr;
2165 return Node.getArg(1);
2166 }
2167 template <typename NodeType>
2168 inline const Expr *getSubExpr(const NodeType &Node) {
2169 return Node.getSubExpr();
2170 }
2171 template <>
2172 inline const Expr *
2173 getSubExpr<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
2174 if (!internal::equivalentUnaryOperator(Node))
2175 return nullptr;
2176 return Node.getArg(0);
2177 }
2178
2179 template <typename Ty>
2180 struct HasSizeMatcher {
2181 static bool hasSize(const Ty &Node, unsigned int N) {
2182 return Node.getSize() == N;
2183 }
2184 };
2185
2186 template <>
2187 inline bool HasSizeMatcher<StringLiteral>::hasSize(
2188 const StringLiteral &Node, unsigned int N) {
2189 return Node.getLength() == N;
2190 }
2191
2192 template <typename Ty>
2193 struct GetSourceExpressionMatcher {
2194 static const Expr *get(const Ty &Node) {
2195 return Node.getSubExpr();
2196 }
2197 };
2198
2199 template <>
2200 inline const Expr *GetSourceExpressionMatcher<OpaqueValueExpr>::get(
2201 const OpaqueValueExpr &Node) {
2202 return Node.getSourceExpr();
2203 }
2204
2205 template <typename Ty>
2206 struct CompoundStmtMatcher {
2207 static const CompoundStmt *get(const Ty &Node) {
2208 return &Node;
2209 }
2210 };
2211
2212 template <>
2213 inline const CompoundStmt *
2214 CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) {
2215 return Node.getSubStmt();
2216 }
2217
2218
2219
2220
2221
2222 std::optional<SourceLocation> getExpansionLocOfMacro(StringRef MacroName,
2223 SourceLocation Loc,
2224 const ASTContext &Context);
2225
2226 inline std::optional<StringRef> getOpName(const UnaryOperator &Node) {
2227 return Node.getOpcodeStr(Node.getOpcode());
2228 }
2229 inline std::optional<StringRef> getOpName(const BinaryOperator &Node) {
2230 return Node.getOpcodeStr();
2231 }
2232 inline StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
2233 return Node.getOpcodeStr();
2234 }
2235 inline std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
2236 auto optBinaryOpcode = equivalentBinaryOperator(Node);
2237 if (!optBinaryOpcode) {
2238 auto optUnaryOpcode = equivalentUnaryOperator(Node);
2239 if (!optUnaryOpcode)
2240 return std::nullopt;
2241 return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
2242 }
2243 return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
2244 }
2245 inline StringRef getOpName(const CXXFoldExpr &Node) {
2246 return BinaryOperator::getOpcodeStr(Node.getOperator());
2247 }
2248
2249
2250
2251
2252
2253 template <typename T, typename ArgT = std::vector<std::string>>
2254 class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
2255 static_assert(std::is_same<T, BinaryOperator>::value ||
2256 std::is_same<T, CXXOperatorCallExpr>::value ||
2257 std::is_same<T, CXXRewrittenBinaryOperator>::value ||
2258 std::is_same<T, UnaryOperator>::value,
2259 "Matcher only supports `BinaryOperator`, `UnaryOperator`, "
2260 "`CXXOperatorCallExpr` and `CXXRewrittenBinaryOperator`");
2261 static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
2262 "Matcher ArgT must be std::vector<std::string>");
2263
2264 public:
2265 explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names)
2266 : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
2267
2268 bool matchesNode(const T &Node) const override {
2269 std::optional<StringRef> OptOpName = getOpName(Node);
2270 return OptOpName && llvm::is_contained(Names, *OptOpName);
2271 }
2272
2273 private:
2274 static std::optional<StringRef> getOpName(const UnaryOperator &Node) {
2275 return Node.getOpcodeStr(Node.getOpcode());
2276 }
2277 static std::optional<StringRef> getOpName(const BinaryOperator &Node) {
2278 return Node.getOpcodeStr();
2279 }
2280 static StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
2281 return Node.getOpcodeStr();
2282 }
2283 static std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
2284 auto optBinaryOpcode = equivalentBinaryOperator(Node);
2285 if (!optBinaryOpcode) {
2286 auto optUnaryOpcode = equivalentUnaryOperator(Node);
2287 if (!optUnaryOpcode)
2288 return std::nullopt;
2289 return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
2290 }
2291 return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
2292 }
2293
2294 std::vector<std::string> Names;
2295 };
2296
2297 using HasOpNameMatcher =
2298 PolymorphicMatcher<HasAnyOperatorNameMatcher,
2299 void(
2300 TypeList<BinaryOperator, CXXOperatorCallExpr,
2301 CXXRewrittenBinaryOperator, UnaryOperator>),
2302 std::vector<std::string>>;
2303
2304 HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs);
2305
2306 using HasOverloadOpNameMatcher =
2307 PolymorphicMatcher<HasOverloadedOperatorNameMatcher,
2308 void(TypeList<CXXOperatorCallExpr, FunctionDecl>),
2309 std::vector<std::string>>;
2310
2311 HasOverloadOpNameMatcher
2312 hasAnyOverloadedOperatorNameFunc(ArrayRef<const StringRef *> NameRefs);
2313
2314
2315
2316
2317 bool matchesAnyBase(const CXXRecordDecl &Node,
2318 const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
2319 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder);
2320
2321 std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex,
2322 llvm::Regex::RegexFlags Flags,
2323 StringRef MatcherID);
2324
2325 inline bool
2326 MatchTemplateArgLocAt(const DeclRefExpr &Node, unsigned int Index,
2327 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2328 internal::ASTMatchFinder *Finder,
2329 internal::BoundNodesTreeBuilder *Builder) {
2330 llvm::ArrayRef<TemplateArgumentLoc> ArgLocs = Node.template_arguments();
2331 return Index < ArgLocs.size() &&
2332 InnerMatcher.matches(ArgLocs[Index], Finder, Builder);
2333 }
2334
2335 inline bool
2336 MatchTemplateArgLocAt(const TemplateSpecializationTypeLoc &Node,
2337 unsigned int Index,
2338 internal::Matcher<TemplateArgumentLoc> InnerMatcher,
2339 internal::ASTMatchFinder *Finder,
2340 internal::BoundNodesTreeBuilder *Builder) {
2341 return !Node.isNull() && Index < Node.getNumArgs() &&
2342 InnerMatcher.matches(Node.getArgLoc(Index), Finder, Builder);
2343 }
2344
2345 inline std::string getDependentName(const DependentScopeDeclRefExpr &node) {
2346 return node.getDeclName().getAsString();
2347 }
2348
2349 inline std::string getDependentName(const DependentNameType &node) {
2350 return node.getIdentifier()->getName().str();
2351 }
2352
2353 }
2354
2355 }
2356
2357 }
2358
2359 #endif