1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- ASTMatchersInternal.h - Structural query framework -------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // Implements the base layer of the matcher framework.
- //
- // Matchers are methods that return a Matcher<T> which provides a method
- // Matches(...) which is a predicate on an AST node. The Matches method's
- // parameters define the context of the match, which allows matchers to recurse
- // or store the current node as bound to a specific string, so that it can be
- // retrieved later.
- //
- // In general, matchers have two parts:
- // 1. A function Matcher<T> MatcherName(<arguments>) which returns a Matcher<T>
- // based on the arguments and optionally on template type deduction based
- // on the arguments. Matcher<T>s form an implicit reverse hierarchy
- // to clang's AST class hierarchy, meaning that you can use a Matcher<Base>
- // everywhere a Matcher<Derived> is required.
- // 2. An implementation of a class derived from MatcherInterface<T>.
- //
- // The matcher functions are defined in ASTMatchers.h. To make it possible
- // to implement both the matcher function and the implementation of the matcher
- // interface in one place, ASTMatcherMacros.h defines macros that allow
- // implementing a matcher in a single place.
- //
- // This file contains the base classes needed to construct the actual matchers.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
- #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
- #include "clang/AST/ASTTypeTraits.h"
- #include "clang/AST/Decl.h"
- #include "clang/AST/DeclCXX.h"
- #include "clang/AST/DeclFriend.h"
- #include "clang/AST/DeclTemplate.h"
- #include "clang/AST/Expr.h"
- #include "clang/AST/ExprCXX.h"
- #include "clang/AST/ExprObjC.h"
- #include "clang/AST/NestedNameSpecifier.h"
- #include "clang/AST/Stmt.h"
- #include "clang/AST/TemplateName.h"
- #include "clang/AST/Type.h"
- #include "clang/AST/TypeLoc.h"
- #include "clang/Basic/LLVM.h"
- #include "clang/Basic/OperatorKinds.h"
- #include "llvm/ADT/APFloat.h"
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/IntrusiveRefCntPtr.h"
- #include "llvm/ADT/None.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/iterator.h"
- #include "llvm/Support/Casting.h"
- #include "llvm/Support/ManagedStatic.h"
- #include "llvm/Support/Regex.h"
- #include <algorithm>
- #include <cassert>
- #include <cstddef>
- #include <cstdint>
- #include <map>
- #include <memory>
- #include <string>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- namespace clang {
- class ASTContext;
- namespace ast_matchers {
- class BoundNodes;
- namespace internal {
- /// A type-list implementation.
- ///
- /// A "linked list" of types, accessible by using the ::head and ::tail
- /// typedefs.
- template <typename... Ts> struct TypeList {}; // Empty sentinel type list.
- template <typename T1, typename... Ts> struct TypeList<T1, Ts...> {
- /// The first type on the list.
- using head = T1;
- /// A sublist with the tail. ie everything but the head.
- ///
- /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the
- /// end of the list.
- using tail = TypeList<Ts...>;
- };
- /// The empty type list.
- using EmptyTypeList = TypeList<>;
- /// Helper meta-function to determine if some type \c T is present or
- /// a parent type in the list.
- template <typename AnyTypeList, typename T> struct TypeListContainsSuperOf {
- static const bool value =
- std::is_base_of<typename AnyTypeList::head, T>::value ||
- TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value;
- };
- template <typename T> struct TypeListContainsSuperOf<EmptyTypeList, T> {
- static const bool value = false;
- };
- /// Variadic function object.
- ///
- /// Most of the functions below that use VariadicFunction could be implemented
- /// using plain C++11 variadic functions, but the function object allows us to
- /// capture it on the dynamic matcher registry.
- template <typename ResultT, typename ArgT,
- ResultT (*Func)(ArrayRef<const ArgT *>)>
- struct VariadicFunction {
- ResultT operator()() const { return Func(None); }
- template <typename... ArgsT>
- ResultT operator()(const ArgT &Arg1, const ArgsT &... Args) const {
- return Execute(Arg1, static_cast<const ArgT &>(Args)...);
- }
- // We also allow calls with an already created array, in case the caller
- // already had it.
- ResultT operator()(ArrayRef<ArgT> Args) const {
- SmallVector<const ArgT*, 8> InnerArgs;
- for (const ArgT &Arg : Args)
- InnerArgs.push_back(&Arg);
- return Func(InnerArgs);
- }
- private:
- // Trampoline function to allow for implicit conversions to take place
- // before we make the array.
- template <typename... ArgsT> ResultT Execute(const ArgsT &... Args) const {
- const ArgT *const ArgsArray[] = {&Args...};
- return Func(ArrayRef<const ArgT *>(ArgsArray, sizeof...(ArgsT)));
- }
- };
- /// Unifies obtaining the underlying type of a regular node through
- /// `getType` and a TypedefNameDecl node through `getUnderlyingType`.
- inline QualType getUnderlyingType(const Expr &Node) { return Node.getType(); }
- inline QualType getUnderlyingType(const ValueDecl &Node) {
- return Node.getType();
- }
- inline QualType getUnderlyingType(const TypedefNameDecl &Node) {
- return Node.getUnderlyingType();
- }
- inline QualType getUnderlyingType(const FriendDecl &Node) {
- if (const TypeSourceInfo *TSI = Node.getFriendType())
- return TSI->getType();
- return QualType();
- }
- inline QualType getUnderlyingType(const CXXBaseSpecifier &Node) {
- return Node.getType();
- }
- /// Unifies obtaining a `TypeSourceInfo` from different node types.
- template <typename T,
- std::enable_if_t<TypeListContainsSuperOf<
- TypeList<CXXBaseSpecifier, CXXCtorInitializer,
- CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr,
- CompoundLiteralExpr, DeclaratorDecl, ObjCPropertyDecl,
- TemplateArgumentLoc, TypedefNameDecl>,
- T>::value> * = nullptr>
- inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) {
- return Node.getTypeSourceInfo();
- }
- template <typename T,
- std::enable_if_t<TypeListContainsSuperOf<
- TypeList<CXXFunctionalCastExpr, ExplicitCastExpr>, T>::value> * =
- nullptr>
- inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) {
- return Node.getTypeInfoAsWritten();
- }
- inline TypeSourceInfo *GetTypeSourceInfo(const BlockDecl &Node) {
- return Node.getSignatureAsWritten();
- }
- inline TypeSourceInfo *GetTypeSourceInfo(const CXXNewExpr &Node) {
- return Node.getAllocatedTypeSourceInfo();
- }
- inline TypeSourceInfo *
- GetTypeSourceInfo(const ClassTemplateSpecializationDecl &Node) {
- return Node.getTypeAsWritten();
- }
- /// Unifies obtaining the FunctionProtoType pointer from both
- /// FunctionProtoType and FunctionDecl nodes..
- inline const FunctionProtoType *
- getFunctionProtoType(const FunctionProtoType &Node) {
- return &Node;
- }
- inline const FunctionProtoType *getFunctionProtoType(const FunctionDecl &Node) {
- return Node.getType()->getAs<FunctionProtoType>();
- }
- /// Unifies obtaining the access specifier from Decl and CXXBaseSpecifier nodes.
- inline clang::AccessSpecifier getAccessSpecifier(const Decl &Node) {
- return Node.getAccess();
- }
- inline clang::AccessSpecifier getAccessSpecifier(const CXXBaseSpecifier &Node) {
- return Node.getAccessSpecifier();
- }
- /// Internal version of BoundNodes. Holds all the bound nodes.
- class BoundNodesMap {
- public:
- /// Adds \c Node to the map with key \c ID.
- ///
- /// The node's base type should be in NodeBaseType or it will be unaccessible.
- void addNode(StringRef ID, const DynTypedNode &DynNode) {
- NodeMap[std::string(ID)] = DynNode;
- }
- /// Returns the AST node bound to \c ID.
- ///
- /// Returns NULL if there was no node bound to \c ID or if there is a node but
- /// it cannot be converted to the specified type.
- template <typename T>
- const T *getNodeAs(StringRef ID) const {
- IDToNodeMap::const_iterator It = NodeMap.find(ID);
- if (It == NodeMap.end()) {
- return nullptr;
- }
- return It->second.get<T>();
- }
- DynTypedNode getNode(StringRef ID) const {
- IDToNodeMap::const_iterator It = NodeMap.find(ID);
- if (It == NodeMap.end()) {
- return DynTypedNode();
- }
- return It->second;
- }
- /// Imposes an order on BoundNodesMaps.
- bool operator<(const BoundNodesMap &Other) const {
- return NodeMap < Other.NodeMap;
- }
- /// A map from IDs to the bound nodes.
- ///
- /// Note that we're using std::map here, as for memoization:
- /// - we need a comparison operator
- /// - we need an assignment operator
- using IDToNodeMap = std::map<std::string, DynTypedNode, std::less<>>;
- const IDToNodeMap &getMap() const {
- return NodeMap;
- }
- /// Returns \c true if this \c BoundNodesMap can be compared, i.e. all
- /// stored nodes have memoization data.
- bool isComparable() const {
- for (const auto &IDAndNode : NodeMap) {
- if (!IDAndNode.second.getMemoizationData())
- return false;
- }
- return true;
- }
- private:
- IDToNodeMap NodeMap;
- };
- /// Creates BoundNodesTree objects.
- ///
- /// The tree builder is used during the matching process to insert the bound
- /// nodes from the Id matcher.
- class BoundNodesTreeBuilder {
- public:
- /// A visitor interface to visit all BoundNodes results for a
- /// BoundNodesTree.
- class Visitor {
- public:
- virtual ~Visitor() = default;
- /// Called multiple times during a single call to VisitMatches(...).
- ///
- /// 'BoundNodesView' contains the bound nodes for a single match.
- virtual void visitMatch(const BoundNodes& BoundNodesView) = 0;
- };
- /// Add a binding from an id to a node.
- void setBinding(StringRef Id, const DynTypedNode &DynNode) {
- if (Bindings.empty())
- Bindings.emplace_back();
- for (BoundNodesMap &Binding : Bindings)
- Binding.addNode(Id, DynNode);
- }
- /// Adds a branch in the tree.
- void addMatch(const BoundNodesTreeBuilder &Bindings);
- /// Visits all matches that this BoundNodesTree represents.
- ///
- /// The ownership of 'ResultVisitor' remains at the caller.
- void visitMatches(Visitor* ResultVisitor);
- template <typename ExcludePredicate>
- bool removeBindings(const ExcludePredicate &Predicate) {
- llvm::erase_if(Bindings, Predicate);
- return !Bindings.empty();
- }
- /// Imposes an order on BoundNodesTreeBuilders.
- bool operator<(const BoundNodesTreeBuilder &Other) const {
- return Bindings < Other.Bindings;
- }
- /// Returns \c true if this \c BoundNodesTreeBuilder can be compared,
- /// i.e. all stored node maps have memoization data.
- bool isComparable() const {
- for (const BoundNodesMap &NodesMap : Bindings) {
- if (!NodesMap.isComparable())
- return false;
- }
- return true;
- }
- private:
- SmallVector<BoundNodesMap, 1> Bindings;
- };
- class ASTMatchFinder;
- /// Generic interface for all matchers.
- ///
- /// Used by the implementation of Matcher<T> and DynTypedMatcher.
- /// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T>
- /// instead.
- class DynMatcherInterface
- : public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
- public:
- virtual ~DynMatcherInterface() = default;
- /// Returns true if \p DynNode can be matched.
- ///
- /// May bind \p DynNode to an ID via \p Builder, or recurse into
- /// the AST via \p Finder.
- virtual bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const = 0;
- virtual llvm::Optional<clang::TraversalKind> TraversalKind() const {
- return llvm::None;
- }
- };
- /// Generic interface for matchers on an AST node of type T.
- ///
- /// Implement this if your matcher may need to inspect the children or
- /// descendants of the node or bind matched nodes to names. If you are
- /// writing a simple matcher that only inspects properties of the
- /// current node and doesn't care about its children or descendants,
- /// implement SingleNodeMatcherInterface instead.
- template <typename T>
- class MatcherInterface : public DynMatcherInterface {
- public:
- /// Returns true if 'Node' can be matched.
- ///
- /// May bind 'Node' to an ID via 'Builder', or recurse into
- /// the AST via 'Finder'.
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const = 0;
- bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return matches(DynNode.getUnchecked<T>(), Finder, Builder);
- }
- };
- /// Interface for matchers that only evaluate properties on a single
- /// node.
- template <typename T>
- class SingleNodeMatcherInterface : public MatcherInterface<T> {
- public:
- /// Returns true if the matcher matches the provided node.
- ///
- /// A subclass must implement this instead of Matches().
- virtual bool matchesNode(const T &Node) const = 0;
- private:
- /// Implements MatcherInterface::Matches.
- bool matches(const T &Node,
- ASTMatchFinder * /* Finder */,
- BoundNodesTreeBuilder * /* Builder */) const override {
- return matchesNode(Node);
- }
- };
- template <typename> class Matcher;
- /// Matcher that works on a \c DynTypedNode.
- ///
- /// It is constructed from a \c Matcher<T> object and redirects most calls to
- /// underlying matcher.
- /// It checks whether the \c DynTypedNode is convertible into the type of the
- /// underlying matcher and then do the actual match on the actual node, or
- /// return false if it is not convertible.
- class DynTypedMatcher {
- public:
- /// Takes ownership of the provided implementation pointer.
- template <typename T>
- DynTypedMatcher(MatcherInterface<T> *Implementation)
- : SupportedKind(ASTNodeKind::getFromNodeKind<T>()),
- RestrictKind(SupportedKind), Implementation(Implementation) {}
- /// Construct from a variadic function.
- enum VariadicOperator {
- /// Matches nodes for which all provided matchers match.
- VO_AllOf,
- /// Matches nodes for which at least one of the provided matchers
- /// matches.
- VO_AnyOf,
- /// Matches nodes for which at least one of the provided matchers
- /// matches, but doesn't stop at the first match.
- VO_EachOf,
- /// Matches any node but executes all inner matchers to find result
- /// bindings.
- VO_Optionally,
- /// Matches nodes that do not match the provided matcher.
- ///
- /// Uses the variadic matcher interface, but fails if
- /// InnerMatchers.size() != 1.
- VO_UnaryNot
- };
- static DynTypedMatcher
- constructVariadic(VariadicOperator Op, ASTNodeKind SupportedKind,
- std::vector<DynTypedMatcher> InnerMatchers);
- static DynTypedMatcher
- constructRestrictedWrapper(const DynTypedMatcher &InnerMatcher,
- ASTNodeKind RestrictKind);
- /// Get a "true" matcher for \p NodeKind.
- ///
- /// It only checks that the node is of the right kind.
- static DynTypedMatcher trueMatcher(ASTNodeKind NodeKind);
- void setAllowBind(bool AB) { AllowBind = AB; }
- /// Check whether this matcher could ever match a node of kind \p Kind.
- /// \return \c false if this matcher will never match such a node. Otherwise,
- /// return \c true.
- bool canMatchNodesOfKind(ASTNodeKind Kind) const;
- /// Return a matcher that points to the same implementation, but
- /// restricts the node types for \p Kind.
- DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const;
- /// Return a matcher that that points to the same implementation, but sets the
- /// traversal kind.
- ///
- /// If the traversal kind is already set, then \c TK overrides it.
- DynTypedMatcher withTraversalKind(TraversalKind TK);
- /// Returns true if the matcher matches the given \c DynNode.
- bool matches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const;
- /// Same as matches(), but skips the kind check.
- ///
- /// It is faster, but the caller must ensure the node is valid for the
- /// kind of this matcher.
- bool matchesNoKindCheck(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const;
- /// Bind the specified \p ID to the matcher.
- /// \return A new matcher with the \p ID bound to it if this matcher supports
- /// binding. Otherwise, returns an empty \c Optional<>.
- llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const;
- /// Returns a unique \p ID for the matcher.
- ///
- /// Casting a Matcher<T> to Matcher<U> creates a matcher that has the
- /// same \c Implementation pointer, but different \c RestrictKind. We need to
- /// include both in the ID to make it unique.
- ///
- /// \c MatcherIDType supports operator< and provides strict weak ordering.
- using MatcherIDType = std::pair<ASTNodeKind, uint64_t>;
- MatcherIDType getID() const {
- /// FIXME: Document the requirements this imposes on matcher
- /// implementations (no new() implementation_ during a Matches()).
- return std::make_pair(RestrictKind,
- reinterpret_cast<uint64_t>(Implementation.get()));
- }
- /// Returns the type this matcher works on.
- ///
- /// \c matches() will always return false unless the node passed is of this
- /// or a derived type.
- ASTNodeKind getSupportedKind() const { return SupportedKind; }
- /// Returns \c true if the passed \c DynTypedMatcher can be converted
- /// to a \c Matcher<T>.
- ///
- /// This method verifies that the underlying matcher in \c Other can process
- /// nodes of types T.
- template <typename T> bool canConvertTo() const {
- return canConvertTo(ASTNodeKind::getFromNodeKind<T>());
- }
- bool canConvertTo(ASTNodeKind To) const;
- /// Construct a \c Matcher<T> interface around the dynamic matcher.
- ///
- /// This method asserts that \c canConvertTo() is \c true. Callers
- /// should call \c canConvertTo() first to make sure that \c this is
- /// compatible with T.
- template <typename T> Matcher<T> convertTo() const {
- assert(canConvertTo<T>());
- return unconditionalConvertTo<T>();
- }
- /// Same as \c convertTo(), but does not check that the underlying
- /// matcher can handle a value of T.
- ///
- /// If it is not compatible, then this matcher will never match anything.
- template <typename T> Matcher<T> unconditionalConvertTo() const;
- /// Returns the \c TraversalKind respected by calls to `match()`, if any.
- ///
- /// Most matchers will not have a traversal kind set, instead relying on the
- /// surrounding context. For those, \c llvm::None is returned.
- llvm::Optional<clang::TraversalKind> getTraversalKind() const {
- return Implementation->TraversalKind();
- }
- private:
- DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind,
- IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
- : SupportedKind(SupportedKind), RestrictKind(RestrictKind),
- Implementation(std::move(Implementation)) {}
- bool AllowBind = false;
- ASTNodeKind SupportedKind;
- /// A potentially stricter node kind.
- ///
- /// It allows to perform implicit and dynamic cast of matchers without
- /// needing to change \c Implementation.
- ASTNodeKind RestrictKind;
- IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
- };
- /// Wrapper of a MatcherInterface<T> *that allows copying.
- ///
- /// A Matcher<Base> can be used anywhere a Matcher<Derived> is
- /// required. This establishes an is-a relationship which is reverse
- /// to the AST hierarchy. In other words, Matcher<T> is contravariant
- /// with respect to T. The relationship is built via a type conversion
- /// operator rather than a type hierarchy to be able to templatize the
- /// type hierarchy instead of spelling it out.
- template <typename T>
- class Matcher {
- public:
- /// Takes ownership of the provided implementation pointer.
- explicit Matcher(MatcherInterface<T> *Implementation)
- : Implementation(Implementation) {}
- /// Implicitly converts \c Other to a Matcher<T>.
- ///
- /// Requires \c T to be derived from \c From.
- template <typename From>
- Matcher(const Matcher<From> &Other,
- std::enable_if_t<std::is_base_of<From, T>::value &&
- !std::is_same<From, T>::value> * = nullptr)
- : Implementation(restrictMatcher(Other.Implementation)) {
- assert(Implementation.getSupportedKind().isSame(
- ASTNodeKind::getFromNodeKind<T>()));
- }
- /// Implicitly converts \c Matcher<Type> to \c Matcher<QualType>.
- ///
- /// The resulting matcher is not strict, i.e. ignores qualifiers.
- template <typename TypeT>
- Matcher(const Matcher<TypeT> &Other,
- std::enable_if_t<std::is_same<T, QualType>::value &&
- std::is_same<TypeT, Type>::value> * = nullptr)
- : Implementation(new TypeToQualType<TypeT>(Other)) {}
- /// Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the
- /// argument.
- /// \c To must be a base class of \c T.
- template <typename To> Matcher<To> dynCastTo() const LLVM_LVALUE_FUNCTION {
- static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call.");
- return Matcher<To>(Implementation);
- }
- #if LLVM_HAS_RVALUE_REFERENCE_THIS
- template <typename To> Matcher<To> dynCastTo() && {
- static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call.");
- return Matcher<To>(std::move(Implementation));
- }
- #endif
- /// Forwards the call to the underlying MatcherInterface<T> pointer.
- bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return Implementation.matches(DynTypedNode::create(Node), Finder, Builder);
- }
- /// Returns an ID that uniquely identifies the matcher.
- DynTypedMatcher::MatcherIDType getID() const {
- return Implementation.getID();
- }
- /// Extract the dynamic matcher.
- ///
- /// The returned matcher keeps the same restrictions as \c this and remembers
- /// that it is meant to support nodes of type \c T.
- operator DynTypedMatcher() const LLVM_LVALUE_FUNCTION {
- return Implementation;
- }
- #if LLVM_HAS_RVALUE_REFERENCE_THIS
- operator DynTypedMatcher() && { return std::move(Implementation); }
- #endif
- /// Allows the conversion of a \c Matcher<Type> to a \c
- /// Matcher<QualType>.
- ///
- /// Depending on the constructor argument, the matcher is either strict, i.e.
- /// does only matches in the absence of qualifiers, or not, i.e. simply
- /// ignores any qualifiers.
- template <typename TypeT>
- class TypeToQualType : public MatcherInterface<QualType> {
- const DynTypedMatcher InnerMatcher;
- public:
- TypeToQualType(const Matcher<TypeT> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
- bool matches(const QualType &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- if (Node.isNull())
- return false;
- return this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder,
- Builder);
- }
- llvm::Optional<clang::TraversalKind> TraversalKind() const override {
- return this->InnerMatcher.getTraversalKind();
- }
- };
- private:
- // For Matcher<T> <=> Matcher<U> conversions.
- template <typename U> friend class Matcher;
- // For DynTypedMatcher::unconditionalConvertTo<T>.
- friend class DynTypedMatcher;
- static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) {
- return Other.dynCastTo(ASTNodeKind::getFromNodeKind<T>());
- }
- explicit Matcher(const DynTypedMatcher &Implementation)
- : Implementation(restrictMatcher(Implementation)) {
- assert(this->Implementation.getSupportedKind().isSame(
- ASTNodeKind::getFromNodeKind<T>()));
- }
- DynTypedMatcher Implementation;
- }; // class Matcher
- /// A convenient helper for creating a Matcher<T> without specifying
- /// the template type argument.
- template <typename T>
- inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
- return Matcher<T>(Implementation);
- }
- /// Interface that allows matchers to traverse the AST.
- /// FIXME: Find a better name.
- ///
- /// This provides three entry methods for each base node type in the AST:
- /// - \c matchesChildOf:
- /// Matches a matcher on every child node of the given node. Returns true
- /// if at least one child node could be matched.
- /// - \c matchesDescendantOf:
- /// Matches a matcher on all descendant nodes of the given node. Returns true
- /// if at least one descendant matched.
- /// - \c matchesAncestorOf:
- /// Matches a matcher on all ancestors of the given node. Returns true if
- /// at least one ancestor matched.
- ///
- /// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal.
- /// In the future, we want to implement this for all nodes for which it makes
- /// sense. In the case of matchesAncestorOf, we'll want to implement it for
- /// all nodes, as all nodes have ancestors.
- class ASTMatchFinder {
- public:
- /// Defines how bindings are processed on recursive matches.
- enum BindKind {
- /// Stop at the first match and only bind the first match.
- BK_First,
- /// Create results for all combinations of bindings that match.
- BK_All
- };
- /// Defines which ancestors are considered for a match.
- enum AncestorMatchMode {
- /// All ancestors.
- AMM_All,
- /// Direct parent only.
- AMM_ParentOnly
- };
- virtual ~ASTMatchFinder() = default;
- /// Returns true if the given C++ class is directly or indirectly derived
- /// from a base type matching \c base.
- ///
- /// A class is not considered to be derived from itself.
- virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
- const Matcher<NamedDecl> &Base,
- BoundNodesTreeBuilder *Builder,
- bool Directly) = 0;
- /// Returns true if the given Objective-C class is directly or indirectly
- /// derived from a base class matching \c base.
- ///
- /// A class is not considered to be derived from itself.
- virtual bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
- const Matcher<NamedDecl> &Base,
- BoundNodesTreeBuilder *Builder,
- bool Directly) = 0;
- template <typename T>
- bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder, BindKind Bind) {
- static_assert(std::is_base_of<Decl, T>::value ||
- std::is_base_of<Stmt, T>::value ||
- std::is_base_of<NestedNameSpecifier, T>::value ||
- std::is_base_of<NestedNameSpecifierLoc, T>::value ||
- std::is_base_of<TypeLoc, T>::value ||
- std::is_base_of<QualType, T>::value ||
- std::is_base_of<Attr, T>::value,
- "unsupported type for recursive matching");
- return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher,
- Builder, Bind);
- }
- template <typename T>
- bool matchesDescendantOf(const T &Node, const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder, BindKind Bind) {
- static_assert(std::is_base_of<Decl, T>::value ||
- std::is_base_of<Stmt, T>::value ||
- std::is_base_of<NestedNameSpecifier, T>::value ||
- std::is_base_of<NestedNameSpecifierLoc, T>::value ||
- std::is_base_of<TypeLoc, T>::value ||
- std::is_base_of<QualType, T>::value ||
- std::is_base_of<Attr, T>::value,
- "unsupported type for recursive matching");
- return matchesDescendantOf(DynTypedNode::create(Node), getASTContext(),
- Matcher, Builder, Bind);
- }
- // FIXME: Implement support for BindKind.
- template <typename T>
- bool matchesAncestorOf(const T &Node, const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- AncestorMatchMode MatchMode) {
- static_assert(std::is_base_of<Decl, T>::value ||
- std::is_base_of<NestedNameSpecifierLoc, T>::value ||
- std::is_base_of<Stmt, T>::value ||
- std::is_base_of<TypeLoc, T>::value ||
- std::is_base_of<Attr, T>::value,
- "type not allowed for recursive matching");
- return matchesAncestorOf(DynTypedNode::create(Node), getASTContext(),
- Matcher, Builder, MatchMode);
- }
- virtual ASTContext &getASTContext() const = 0;
- virtual bool IsMatchingInASTNodeNotSpelledInSource() const = 0;
- virtual bool IsMatchingInASTNodeNotAsIs() const = 0;
- bool isTraversalIgnoringImplicitNodes() const;
- protected:
- virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
- const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- BindKind Bind) = 0;
- virtual bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx,
- const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- BindKind Bind) = 0;
- virtual bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx,
- const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- AncestorMatchMode MatchMode) = 0;
- private:
- friend struct ASTChildrenNotSpelledInSourceScope;
- virtual bool isMatchingChildrenNotSpelledInSource() const = 0;
- virtual void setMatchingChildrenNotSpelledInSource(bool Set) = 0;
- };
- struct ASTChildrenNotSpelledInSourceScope {
- ASTChildrenNotSpelledInSourceScope(ASTMatchFinder *V, bool B)
- : MV(V), MB(V->isMatchingChildrenNotSpelledInSource()) {
- V->setMatchingChildrenNotSpelledInSource(B);
- }
- ~ASTChildrenNotSpelledInSourceScope() {
- MV->setMatchingChildrenNotSpelledInSource(MB);
- }
- private:
- ASTMatchFinder *MV;
- bool MB;
- };
- /// Specialization of the conversion functions for QualType.
- ///
- /// This specialization provides the Matcher<Type>->Matcher<QualType>
- /// conversion that the static API does.
- template <>
- inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const {
- assert(canConvertTo<QualType>());
- const ASTNodeKind SourceKind = getSupportedKind();
- if (SourceKind.isSame(ASTNodeKind::getFromNodeKind<Type>())) {
- // We support implicit conversion from Matcher<Type> to Matcher<QualType>
- return unconditionalConvertTo<Type>();
- }
- return unconditionalConvertTo<QualType>();
- }
- /// Finds the first node in a range that matches the given matcher.
- template <typename MatcherT, typename IteratorT>
- IteratorT matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
- IteratorT End, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) {
- for (IteratorT I = Start; I != End; ++I) {
- BoundNodesTreeBuilder Result(*Builder);
- if (Matcher.matches(*I, Finder, &Result)) {
- *Builder = std::move(Result);
- return I;
- }
- }
- return End;
- }
- /// Finds the first node in a pointer range that matches the given
- /// matcher.
- template <typename MatcherT, typename IteratorT>
- IteratorT matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
- IteratorT End, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) {
- for (IteratorT I = Start; I != End; ++I) {
- BoundNodesTreeBuilder Result(*Builder);
- if (Matcher.matches(**I, Finder, &Result)) {
- *Builder = std::move(Result);
- return I;
- }
- }
- return End;
- }
- template <typename T, std::enable_if_t<!std::is_base_of<FunctionDecl, T>::value>
- * = nullptr>
- inline bool isDefaultedHelper(const T *) {
- return false;
- }
- inline bool isDefaultedHelper(const FunctionDecl *FD) {
- return FD->isDefaulted();
- }
- // Metafunction to determine if type T has a member called getDecl.
- template <typename Ty>
- class has_getDecl {
- using yes = char[1];
- using no = char[2];
- template <typename Inner>
- static yes& test(Inner *I, decltype(I->getDecl()) * = nullptr);
- template <typename>
- static no& test(...);
- public:
- static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
- };
- /// Matches overloaded operators with a specific name.
- ///
- /// The type argument ArgT is not used by this matcher but is used by
- /// PolymorphicMatcher and should be StringRef.
- template <typename T, typename ArgT>
- class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
- static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
- std::is_base_of<FunctionDecl, T>::value,
- "unsupported class for matcher");
- static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
- "argument type must be std::vector<std::string>");
- public:
- explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names)
- : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
- bool matchesNode(const T &Node) const override {
- return matchesSpecialized(Node);
- }
- private:
- /// CXXOperatorCallExpr exist only for calls to overloaded operators
- /// so this function returns true if the call is to an operator of the given
- /// name.
- bool matchesSpecialized(const CXXOperatorCallExpr &Node) const {
- return llvm::is_contained(Names, getOperatorSpelling(Node.getOperator()));
- }
- /// Returns true only if CXXMethodDecl represents an overloaded
- /// operator and has the given operator name.
- bool matchesSpecialized(const FunctionDecl &Node) const {
- return Node.isOverloadedOperator() &&
- llvm::is_contained(
- Names, getOperatorSpelling(Node.getOverloadedOperator()));
- }
- std::vector<std::string> Names;
- };
- /// Matches named declarations with a specific name.
- ///
- /// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details.
- class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
- public:
- explicit HasNameMatcher(std::vector<std::string> Names);
- bool matchesNode(const NamedDecl &Node) const override;
- private:
- /// Unqualified match routine.
- ///
- /// It is much faster than the full match, but it only works for unqualified
- /// matches.
- bool matchesNodeUnqualified(const NamedDecl &Node) const;
- /// Full match routine
- ///
- /// Fast implementation for the simple case of a named declaration at
- /// namespace or RecordDecl scope.
- /// It is slower than matchesNodeUnqualified, but faster than
- /// matchesNodeFullSlow.
- bool matchesNodeFullFast(const NamedDecl &Node) const;
- /// Full match routine
- ///
- /// It generates the fully qualified name of the declaration (which is
- /// expensive) before trying to match.
- /// It is slower but simple and works on all cases.
- bool matchesNodeFullSlow(const NamedDecl &Node) const;
- bool UseUnqualifiedMatch;
- std::vector<std::string> Names;
- };
- /// Trampoline function to use VariadicFunction<> to construct a
- /// HasNameMatcher.
- Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs);
- /// Trampoline function to use VariadicFunction<> to construct a
- /// hasAnySelector matcher.
- Matcher<ObjCMessageExpr> hasAnySelectorFunc(
- ArrayRef<const StringRef *> NameRefs);
- /// Matches declarations for QualType and CallExpr.
- ///
- /// Type argument DeclMatcherT is required by PolymorphicMatcher but
- /// not actually used.
- template <typename T, typename DeclMatcherT>
- class HasDeclarationMatcher : public MatcherInterface<T> {
- static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
- "instantiated with wrong types");
- DynTypedMatcher InnerMatcher;
- public:
- explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return matchesSpecialized(Node, Finder, Builder);
- }
- private:
- /// Forwards to matching on the underlying type of the QualType.
- bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- if (Node.isNull())
- return false;
- return matchesSpecialized(*Node, Finder, Builder);
- }
- /// Finds the best declaration for a type and returns whether the inner
- /// matcher matches on it.
- bool matchesSpecialized(const Type &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- // DeducedType does not have declarations of its own, so
- // match the deduced type instead.
- if (const auto *S = dyn_cast<DeducedType>(&Node)) {
- QualType DT = S->getDeducedType();
- return !DT.isNull() ? matchesSpecialized(*DT, Finder, Builder) : false;
- }
- // First, for any types that have a declaration, extract the declaration and
- // match on it.
- if (const auto *S = dyn_cast<TagType>(&Node)) {
- return matchesDecl(S->getDecl(), Finder, Builder);
- }
- if (const auto *S = dyn_cast<InjectedClassNameType>(&Node)) {
- return matchesDecl(S->getDecl(), Finder, Builder);
- }
- if (const auto *S = dyn_cast<TemplateTypeParmType>(&Node)) {
- return matchesDecl(S->getDecl(), Finder, Builder);
- }
- if (const auto *S = dyn_cast<TypedefType>(&Node)) {
- return matchesDecl(S->getDecl(), Finder, Builder);
- }
- if (const auto *S = dyn_cast<UnresolvedUsingType>(&Node)) {
- return matchesDecl(S->getDecl(), Finder, Builder);
- }
- if (const auto *S = dyn_cast<ObjCObjectType>(&Node)) {
- return matchesDecl(S->getInterface(), Finder, Builder);
- }
- // A SubstTemplateTypeParmType exists solely to mark a type substitution
- // on the instantiated template. As users usually want to match the
- // template parameter on the uninitialized template, we can always desugar
- // one level without loss of expressivness.
- // For example, given:
- // template<typename T> struct X { T t; } class A {}; X<A> a;
- // The following matcher will match, which otherwise would not:
- // fieldDecl(hasType(pointerType())).
- if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(&Node)) {
- return matchesSpecialized(S->getReplacementType(), Finder, Builder);
- }
- // For template specialization types, we want to match the template
- // declaration, as long as the type is still dependent, and otherwise the
- // declaration of the instantiated tag type.
- if (const auto *S = dyn_cast<TemplateSpecializationType>(&Node)) {
- if (!S->isTypeAlias() && S->isSugared()) {
- // If the template is non-dependent, we want to match the instantiated
- // tag type.
- // For example, given:
- // template<typename T> struct X {}; X<int> a;
- // The following matcher will match, which otherwise would not:
- // templateSpecializationType(hasDeclaration(cxxRecordDecl())).
- return matchesSpecialized(*S->desugar(), Finder, Builder);
- }
- // If the template is dependent or an alias, match the template
- // declaration.
- return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder,
- Builder);
- }
- // FIXME: We desugar elaborated types. This makes the assumption that users
- // do never want to match on whether a type is elaborated - there are
- // arguments for both sides; for now, continue desugaring.
- if (const auto *S = dyn_cast<ElaboratedType>(&Node)) {
- return matchesSpecialized(S->desugar(), Finder, Builder);
- }
- // Similarly types found via using declarations.
- // These are *usually* meaningless sugar, and this matches the historical
- // behavior prior to the introduction of UsingType.
- if (const auto *S = dyn_cast<UsingType>(&Node)) {
- return matchesSpecialized(S->desugar(), Finder, Builder);
- }
- return false;
- }
- /// Extracts the Decl the DeclRefExpr references and returns whether
- /// the inner matcher matches on it.
- bool matchesSpecialized(const DeclRefExpr &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return matchesDecl(Node.getDecl(), Finder, Builder);
- }
- /// Extracts the Decl of the callee of a CallExpr and returns whether
- /// the inner matcher matches on it.
- bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return matchesDecl(Node.getCalleeDecl(), Finder, Builder);
- }
- /// Extracts the Decl of the constructor call and returns whether the
- /// inner matcher matches on it.
- bool matchesSpecialized(const CXXConstructExpr &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return matchesDecl(Node.getConstructor(), Finder, Builder);
- }
- bool matchesSpecialized(const ObjCIvarRefExpr &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return matchesDecl(Node.getDecl(), Finder, Builder);
- }
- /// Extracts the operator new of the new call and returns whether the
- /// inner matcher matches on it.
- bool matchesSpecialized(const CXXNewExpr &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return matchesDecl(Node.getOperatorNew(), Finder, Builder);
- }
- /// Extracts the \c ValueDecl a \c MemberExpr refers to and returns
- /// whether the inner matcher matches on it.
- bool matchesSpecialized(const MemberExpr &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return matchesDecl(Node.getMemberDecl(), Finder, Builder);
- }
- /// Extracts the \c LabelDecl a \c AddrLabelExpr refers to and returns
- /// whether the inner matcher matches on it.
- bool matchesSpecialized(const AddrLabelExpr &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return matchesDecl(Node.getLabel(), Finder, Builder);
- }
- /// Extracts the declaration of a LabelStmt and returns whether the
- /// inner matcher matches on it.
- bool matchesSpecialized(const LabelStmt &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return matchesDecl(Node.getDecl(), Finder, Builder);
- }
- /// Returns whether the inner matcher \c Node. Returns false if \c Node
- /// is \c NULL.
- bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return Node != nullptr &&
- !(Finder->isTraversalIgnoringImplicitNodes() &&
- Node->isImplicit()) &&
- this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder,
- Builder);
- }
- };
- /// IsBaseType<T>::value is true if T is a "base" type in the AST
- /// node class hierarchies.
- template <typename T>
- struct IsBaseType {
- static const bool value =
- std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value ||
- std::is_same<T, QualType>::value || std::is_same<T, Type>::value ||
- std::is_same<T, TypeLoc>::value ||
- std::is_same<T, NestedNameSpecifier>::value ||
- std::is_same<T, NestedNameSpecifierLoc>::value ||
- std::is_same<T, CXXCtorInitializer>::value ||
- std::is_same<T, TemplateArgumentLoc>::value ||
- std::is_same<T, Attr>::value;
- };
- template <typename T>
- const bool IsBaseType<T>::value;
- /// A "type list" that contains all types.
- ///
- /// Useful for matchers like \c anything and \c unless.
- using AllNodeBaseTypes =
- TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
- Type, TypeLoc, CXXCtorInitializer, Attr>;
- /// Helper meta-function to extract the argument out of a function of
- /// type void(Arg).
- ///
- /// See AST_POLYMORPHIC_SUPPORTED_TYPES for details.
- template <class T> struct ExtractFunctionArgMeta;
- template <class T> struct ExtractFunctionArgMeta<void(T)> {
- using type = T;
- };
- template <class T, class Tuple, std::size_t... I>
- constexpr T *new_from_tuple_impl(Tuple &&t, std::index_sequence<I...>) {
- return new T(std::get<I>(std::forward<Tuple>(t))...);
- }
- template <class T, class Tuple> constexpr T *new_from_tuple(Tuple &&t) {
- return new_from_tuple_impl<T>(
- std::forward<Tuple>(t),
- std::make_index_sequence<
- std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
- }
- /// Default type lists for ArgumentAdaptingMatcher matchers.
- using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
- using AdaptativeDefaultToTypes =
- TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
- QualType, Attr>;
- /// All types that are supported by HasDeclarationMatcher above.
- using HasDeclarationSupportedTypes =
- TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
- ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
- MemberExpr, QualType, RecordType, TagType,
- TemplateSpecializationType, TemplateTypeParmType, TypedefType,
- UnresolvedUsingType, ObjCIvarRefExpr>;
- /// A Matcher that allows binding the node it matches to an id.
- ///
- /// BindableMatcher provides a \a bind() method that allows binding the
- /// matched node to an id if the match was successful.
- template <typename T> class BindableMatcher : public Matcher<T> {
- public:
- explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {}
- explicit BindableMatcher(MatcherInterface<T> *Implementation)
- : Matcher<T>(Implementation) {}
- /// Returns a matcher that will bind the matched node on a match.
- ///
- /// The returned matcher is equivalent to this matcher, but will
- /// bind the matched node on a match.
- Matcher<T> bind(StringRef ID) const {
- return DynTypedMatcher(*this)
- .tryBind(ID)
- ->template unconditionalConvertTo<T>();
- }
- /// Same as Matcher<T>'s conversion operator, but enables binding on
- /// the returned matcher.
- operator DynTypedMatcher() const {
- DynTypedMatcher Result = static_cast<const Matcher<T> &>(*this);
- Result.setAllowBind(true);
- return Result;
- }
- };
- /// Matches any instance of the given NodeType.
- ///
- /// This is useful when a matcher syntactically requires a child matcher,
- /// but the context doesn't care. See for example: anything().
- class TrueMatcher {
- public:
- using ReturnTypes = AllNodeBaseTypes;
- template <typename T> operator Matcher<T>() const {
- return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
- .template unconditionalConvertTo<T>();
- }
- };
- /// Creates a Matcher<T> that matches if all inner matchers match.
- template <typename T>
- BindableMatcher<T>
- makeAllOfComposite(ArrayRef<const Matcher<T> *> InnerMatchers) {
- // For the size() == 0 case, we return a "true" matcher.
- if (InnerMatchers.empty()) {
- return BindableMatcher<T>(TrueMatcher());
- }
- // For the size() == 1 case, we simply return that one matcher.
- // No need to wrap it in a variadic operation.
- if (InnerMatchers.size() == 1) {
- return BindableMatcher<T>(*InnerMatchers[0]);
- }
- using PI = llvm::pointee_iterator<const Matcher<T> *const *>;
- std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
- PI(InnerMatchers.end()));
- return BindableMatcher<T>(
- DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
- ASTNodeKind::getFromNodeKind<T>(),
- std::move(DynMatchers))
- .template unconditionalConvertTo<T>());
- }
- /// Creates a Matcher<T> that matches if
- /// T is dyn_cast'able into InnerT and all inner matchers match.
- ///
- /// Returns BindableMatcher, as matchers that use dyn_cast have
- /// the same object both to match on and to run submatchers on,
- /// so there is no ambiguity with what gets bound.
- template <typename T, typename InnerT>
- BindableMatcher<T>
- makeDynCastAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
- return BindableMatcher<T>(
- makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
- }
- /// A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
- /// variadic functor that takes a number of Matcher<TargetT> and returns a
- /// Matcher<SourceT> that matches TargetT nodes that are matched by all of the
- /// given matchers, if SourceT can be dynamically casted into TargetT.
- ///
- /// For example:
- /// const VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> record;
- /// Creates a functor record(...) that creates a Matcher<Decl> given
- /// a variable number of arguments of type Matcher<CXXRecordDecl>.
- /// The returned matcher matches if the given Decl can by dynamically
- /// casted to CXXRecordDecl and all given matchers match.
- template <typename SourceT, typename TargetT>
- class VariadicDynCastAllOfMatcher
- : public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
- makeDynCastAllOfComposite<SourceT, TargetT>> {
- public:
- VariadicDynCastAllOfMatcher() {}
- };
- /// A \c VariadicAllOfMatcher<T> object is a variadic functor that takes
- /// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T
- /// nodes that are matched by all of the given matchers.
- ///
- /// For example:
- /// const VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
- /// Creates a functor nestedNameSpecifier(...) that creates a
- /// \c Matcher<NestedNameSpecifier> given a variable number of arguments of type
- /// \c Matcher<NestedNameSpecifier>.
- /// The returned matcher matches if all given matchers match.
- template <typename T>
- class VariadicAllOfMatcher
- : public VariadicFunction<BindableMatcher<T>, Matcher<T>,
- makeAllOfComposite<T>> {
- public:
- VariadicAllOfMatcher() {}
- };
- /// VariadicOperatorMatcher related types.
- /// @{
- /// Polymorphic matcher object that uses a \c
- /// DynTypedMatcher::VariadicOperator operator.
- ///
- /// Input matchers can have any type (including other polymorphic matcher
- /// types), and the actual Matcher<T> is generated on demand with an implicit
- /// conversion operator.
- template <typename... Ps> class VariadicOperatorMatcher {
- public:
- VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
- : Op(Op), Params(std::forward<Ps>(Params)...) {}
- template <typename T> operator Matcher<T>() const LLVM_LVALUE_FUNCTION {
- return DynTypedMatcher::constructVariadic(
- Op, ASTNodeKind::getFromNodeKind<T>(),
- getMatchers<T>(std::index_sequence_for<Ps...>()))
- .template unconditionalConvertTo<T>();
- }
- #if LLVM_HAS_RVALUE_REFERENCE_THIS
- template <typename T> operator Matcher<T>() && {
- return DynTypedMatcher::constructVariadic(
- Op, ASTNodeKind::getFromNodeKind<T>(),
- getMatchers<T>(std::index_sequence_for<Ps...>()))
- .template unconditionalConvertTo<T>();
- }
- #endif
- private:
- // Helper method to unpack the tuple into a vector.
- template <typename T, std::size_t... Is>
- std::vector<DynTypedMatcher>
- getMatchers(std::index_sequence<Is...>) const LLVM_LVALUE_FUNCTION {
- return {Matcher<T>(std::get<Is>(Params))...};
- }
- #if LLVM_HAS_RVALUE_REFERENCE_THIS
- template <typename T, std::size_t... Is>
- std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) && {
- return {Matcher<T>(std::get<Is>(std::move(Params)))...};
- }
- #endif
- const DynTypedMatcher::VariadicOperator Op;
- std::tuple<Ps...> Params;
- };
- /// Overloaded function object to generate VariadicOperatorMatcher
- /// objects from arbitrary matchers.
- template <unsigned MinCount, unsigned MaxCount>
- struct VariadicOperatorMatcherFunc {
- DynTypedMatcher::VariadicOperator Op;
- template <typename... Ms>
- VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps) const {
- static_assert(MinCount <= sizeof...(Ms) && sizeof...(Ms) <= MaxCount,
- "invalid number of parameters for variadic matcher");
- return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
- }
- };
- template <typename F, typename Tuple, std::size_t... I>
- constexpr auto applyMatcherImpl(F &&f, Tuple &&args,
- std::index_sequence<I...>) {
- return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
- }
- template <typename F, typename Tuple>
- constexpr auto applyMatcher(F &&f, Tuple &&args) {
- return applyMatcherImpl(
- std::forward<F>(f), std::forward<Tuple>(args),
- std::make_index_sequence<
- std::tuple_size<typename std::decay<Tuple>::type>::value>());
- }
- template <typename T, bool IsBaseOf, typename Head, typename Tail>
- struct GetCladeImpl {
- using Type = Head;
- };
- template <typename T, typename Head, typename Tail>
- struct GetCladeImpl<T, false, Head, Tail>
- : GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
- typename Tail::head, typename Tail::tail> {};
- template <typename T, typename... U>
- struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
- template <typename CladeType, typename... MatcherTypes>
- struct MapAnyOfMatcherImpl {
- template <typename... InnerMatchers>
- BindableMatcher<CladeType>
- operator()(InnerMatchers &&... InnerMatcher) const {
- // TODO: Use std::apply from c++17
- return VariadicAllOfMatcher<CladeType>()(applyMatcher(
- internal::VariadicOperatorMatcherFunc<
- 0, std::numeric_limits<unsigned>::max()>{
- internal::DynTypedMatcher::VO_AnyOf},
- applyMatcher(
- [&](auto... Matcher) {
- return std::make_tuple(Matcher(InnerMatcher...)...);
- },
- std::tuple<
- VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
- }
- };
- template <typename... MatcherTypes>
- using MapAnyOfMatcher =
- MapAnyOfMatcherImpl<typename GetClade<MatcherTypes...>::Type,
- MatcherTypes...>;
- template <typename... MatcherTypes> struct MapAnyOfHelper {
- using CladeType = typename GetClade<MatcherTypes...>::Type;
- MapAnyOfMatcher<MatcherTypes...> with;
- operator BindableMatcher<CladeType>() const { return with(); }
- Matcher<CladeType> bind(StringRef ID) const { return with().bind(ID); }
- };
- template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
- typename T, typename ToTypes>
- class ArgumentAdaptingMatcherFuncAdaptor {
- public:
- explicit ArgumentAdaptingMatcherFuncAdaptor(const Matcher<T> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
- using ReturnTypes = ToTypes;
- template <typename To> operator Matcher<To>() const LLVM_LVALUE_FUNCTION {
- return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
- }
- #if LLVM_HAS_RVALUE_REFERENCE_THIS
- template <typename To> operator Matcher<To>() && {
- return Matcher<To>(new ArgumentAdapterT<To, T>(std::move(InnerMatcher)));
- }
- #endif
- private:
- Matcher<T> InnerMatcher;
- };
- /// Converts a \c Matcher<T> to a matcher of desired type \c To by
- /// "adapting" a \c To into a \c T.
- ///
- /// The \c ArgumentAdapterT argument specifies how the adaptation is done.
- ///
- /// For example:
- /// \c ArgumentAdaptingMatcher<HasMatcher, T>(InnerMatcher);
- /// Given that \c InnerMatcher is of type \c Matcher<T>, this returns a matcher
- /// that is convertible into any matcher of type \c To by constructing
- /// \c HasMatcher<To, T>(InnerMatcher).
- ///
- /// If a matcher does not need knowledge about the inner type, prefer to use
- /// PolymorphicMatcher.
- template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
- typename FromTypes = AdaptativeDefaultFromTypes,
- typename ToTypes = AdaptativeDefaultToTypes>
- struct ArgumentAdaptingMatcherFunc {
- template <typename T>
- static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
- create(const Matcher<T> &InnerMatcher) {
- return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>(
- InnerMatcher);
- }
- template <typename T>
- ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
- operator()(const Matcher<T> &InnerMatcher) const {
- return create(InnerMatcher);
- }
- template <typename... T>
- ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT,
- typename GetClade<T...>::Type, ToTypes>
- operator()(const MapAnyOfHelper<T...> &InnerMatcher) const {
- return create(InnerMatcher.with());
- }
- };
- template <typename T> class TraversalMatcher : public MatcherInterface<T> {
- DynTypedMatcher InnerMatcher;
- clang::TraversalKind Traversal;
- public:
- explicit TraversalMatcher(clang::TraversalKind TK,
- const Matcher<T> &InnerMatcher)
- : InnerMatcher(InnerMatcher), Traversal(TK) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return this->InnerMatcher.matches(DynTypedNode::create(Node), Finder,
- Builder);
- }
- llvm::Optional<clang::TraversalKind> TraversalKind() const override {
- if (auto NestedKind = this->InnerMatcher.getTraversalKind())
- return NestedKind;
- return Traversal;
- }
- };
- template <typename MatcherType> class TraversalWrapper {
- public:
- TraversalWrapper(TraversalKind TK, const MatcherType &InnerMatcher)
- : TK(TK), InnerMatcher(InnerMatcher) {}
- template <typename T> operator Matcher<T>() const LLVM_LVALUE_FUNCTION {
- return internal::DynTypedMatcher::constructRestrictedWrapper(
- new internal::TraversalMatcher<T>(TK, InnerMatcher),
- ASTNodeKind::getFromNodeKind<T>())
- .template unconditionalConvertTo<T>();
- }
- #if LLVM_HAS_RVALUE_REFERENCE_THIS
- template <typename T> operator Matcher<T>() && {
- return internal::DynTypedMatcher::constructRestrictedWrapper(
- new internal::TraversalMatcher<T>(TK, std::move(InnerMatcher)),
- ASTNodeKind::getFromNodeKind<T>())
- .template unconditionalConvertTo<T>();
- }
- #endif
- private:
- TraversalKind TK;
- MatcherType InnerMatcher;
- };
- /// A PolymorphicMatcher<MatcherT, P1, ..., PN> object can be
- /// created from N parameters p1, ..., pN (of type P1, ..., PN) and
- /// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN)
- /// can be constructed.
- ///
- /// For example:
- /// - PolymorphicMatcher<IsDefinitionMatcher>()
- /// creates an object that can be used as a Matcher<T> for any type T
- /// where an IsDefinitionMatcher<T>() can be constructed.
- /// - PolymorphicMatcher<ValueEqualsMatcher, int>(42)
- /// creates an object that can be used as a Matcher<T> for any type T
- /// where a ValueEqualsMatcher<T, int>(42) can be constructed.
- template <template <typename T, typename... Params> class MatcherT,
- typename ReturnTypesF, typename... ParamTypes>
- class PolymorphicMatcher {
- public:
- PolymorphicMatcher(const ParamTypes &... Params) : Params(Params...) {}
- using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type;
- template <typename T> operator Matcher<T>() const LLVM_LVALUE_FUNCTION {
- static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
- "right polymorphic conversion");
- return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params));
- }
- #if LLVM_HAS_RVALUE_REFERENCE_THIS
- template <typename T> operator Matcher<T>() && {
- static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
- "right polymorphic conversion");
- return Matcher<T>(
- new_from_tuple<MatcherT<T, ParamTypes...>>(std::move(Params)));
- }
- #endif
- private:
- std::tuple<ParamTypes...> Params;
- };
- /// Matches nodes of type T that have child nodes of type ChildT for
- /// which a specified child matcher matches.
- ///
- /// ChildT must be an AST base type.
- template <typename T, typename ChildT>
- class HasMatcher : public MatcherInterface<T> {
- DynTypedMatcher InnerMatcher;
- public:
- explicit HasMatcher(const Matcher<ChildT> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesChildOf(Node, this->InnerMatcher, Builder,
- ASTMatchFinder::BK_First);
- }
- };
- /// Matches nodes of type T that have child nodes of type ChildT for
- /// which a specified child matcher matches. ChildT must be an AST base
- /// type.
- /// As opposed to the HasMatcher, the ForEachMatcher will produce a match
- /// for each child that matches.
- template <typename T, typename ChildT>
- class ForEachMatcher : public MatcherInterface<T> {
- static_assert(IsBaseType<ChildT>::value,
- "for each only accepts base type matcher");
- DynTypedMatcher InnerMatcher;
- public:
- explicit ForEachMatcher(const Matcher<ChildT> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesChildOf(
- Node, this->InnerMatcher, Builder,
- ASTMatchFinder::BK_All);
- }
- };
- /// @}
- template <typename T>
- inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const {
- return Matcher<T>(*this);
- }
- /// Matches nodes of type T that have at least one descendant node of
- /// type DescendantT for which the given inner matcher matches.
- ///
- /// DescendantT must be an AST base type.
- template <typename T, typename DescendantT>
- class HasDescendantMatcher : public MatcherInterface<T> {
- static_assert(IsBaseType<DescendantT>::value,
- "has descendant only accepts base type matcher");
- DynTypedMatcher DescendantMatcher;
- public:
- explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
- : DescendantMatcher(DescendantMatcher) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
- ASTMatchFinder::BK_First);
- }
- };
- /// Matches nodes of type \c T that have a parent node of type \c ParentT
- /// for which the given inner matcher matches.
- ///
- /// \c ParentT must be an AST base type.
- template <typename T, typename ParentT>
- class HasParentMatcher : public MatcherInterface<T> {
- static_assert(IsBaseType<ParentT>::value,
- "has parent only accepts base type matcher");
- DynTypedMatcher ParentMatcher;
- public:
- explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
- : ParentMatcher(ParentMatcher) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesAncestorOf(Node, this->ParentMatcher, Builder,
- ASTMatchFinder::AMM_ParentOnly);
- }
- };
- /// Matches nodes of type \c T that have at least one ancestor node of
- /// type \c AncestorT for which the given inner matcher matches.
- ///
- /// \c AncestorT must be an AST base type.
- template <typename T, typename AncestorT>
- class HasAncestorMatcher : public MatcherInterface<T> {
- static_assert(IsBaseType<AncestorT>::value,
- "has ancestor only accepts base type matcher");
- DynTypedMatcher AncestorMatcher;
- public:
- explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher)
- : AncestorMatcher(AncestorMatcher) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesAncestorOf(Node, this->AncestorMatcher, Builder,
- ASTMatchFinder::AMM_All);
- }
- };
- /// Matches nodes of type T that have at least one descendant node of
- /// type DescendantT for which the given inner matcher matches.
- ///
- /// DescendantT must be an AST base type.
- /// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will match
- /// for each descendant node that matches instead of only for the first.
- template <typename T, typename DescendantT>
- class ForEachDescendantMatcher : public MatcherInterface<T> {
- static_assert(IsBaseType<DescendantT>::value,
- "for each descendant only accepts base type matcher");
- DynTypedMatcher DescendantMatcher;
- public:
- explicit ForEachDescendantMatcher(
- const Matcher<DescendantT> &DescendantMatcher)
- : DescendantMatcher(DescendantMatcher) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
- ASTMatchFinder::BK_All);
- }
- };
- /// Matches on nodes that have a getValue() method if getValue() equals
- /// the value the ValueEqualsMatcher was constructed with.
- template <typename T, typename ValueT>
- class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> {
- static_assert(std::is_base_of<CharacterLiteral, T>::value ||
- std::is_base_of<CXXBoolLiteralExpr, T>::value ||
- std::is_base_of<FloatingLiteral, T>::value ||
- std::is_base_of<IntegerLiteral, T>::value,
- "the node must have a getValue method");
- public:
- explicit ValueEqualsMatcher(const ValueT &ExpectedValue)
- : ExpectedValue(ExpectedValue) {}
- bool matchesNode(const T &Node) const override {
- return Node.getValue() == ExpectedValue;
- }
- private:
- ValueT ExpectedValue;
- };
- /// Template specializations to easily write matchers for floating point
- /// literals.
- template <>
- inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
- const FloatingLiteral &Node) const {
- if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
- return Node.getValue().convertToFloat() == ExpectedValue;
- if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
- return Node.getValue().convertToDouble() == ExpectedValue;
- return false;
- }
- template <>
- inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
- const FloatingLiteral &Node) const {
- if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
- return Node.getValue().convertToFloat() == ExpectedValue;
- if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
- return Node.getValue().convertToDouble() == ExpectedValue;
- return false;
- }
- template <>
- inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
- const FloatingLiteral &Node) const {
- return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
- }
- /// Matches nodes of type \c TLoc for which the inner
- /// \c Matcher<T> matches.
- template <typename TLoc, typename T>
- class LocMatcher : public MatcherInterface<TLoc> {
- DynTypedMatcher InnerMatcher;
- public:
- explicit LocMatcher(const Matcher<T> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
- bool matches(const TLoc &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- if (!Node)
- return false;
- return this->InnerMatcher.matches(extract(Node), Finder, Builder);
- }
- private:
- static DynTypedNode extract(const NestedNameSpecifierLoc &Loc) {
- return DynTypedNode::create(*Loc.getNestedNameSpecifier());
- }
- };
- /// Matches \c TypeLocs based on an inner matcher matching a certain
- /// \c QualType.
- ///
- /// Used to implement the \c loc() matcher.
- class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> {
- DynTypedMatcher InnerMatcher;
- public:
- explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
- bool matches(const TypeLoc &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- if (!Node)
- return false;
- return this->InnerMatcher.matches(DynTypedNode::create(Node.getType()),
- Finder, Builder);
- }
- };
- /// Matches nodes of type \c T for which the inner matcher matches on a
- /// another node of type \c T that can be reached using a given traverse
- /// function.
- template <typename T> class TypeTraverseMatcher : public MatcherInterface<T> {
- DynTypedMatcher InnerMatcher;
- public:
- explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher,
- QualType (T::*TraverseFunction)() const)
- : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- QualType NextNode = (Node.*TraverseFunction)();
- if (NextNode.isNull())
- return false;
- return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
- Builder);
- }
- private:
- QualType (T::*TraverseFunction)() const;
- };
- /// Matches nodes of type \c T in a ..Loc hierarchy, for which the inner
- /// matcher matches on a another node of type \c T that can be reached using a
- /// given traverse function.
- template <typename T>
- class TypeLocTraverseMatcher : public MatcherInterface<T> {
- DynTypedMatcher InnerMatcher;
- public:
- explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher,
- TypeLoc (T::*TraverseFunction)() const)
- : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- TypeLoc NextNode = (Node.*TraverseFunction)();
- if (!NextNode)
- return false;
- return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
- Builder);
- }
- private:
- TypeLoc (T::*TraverseFunction)() const;
- };
- /// Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where
- /// \c OuterT is any type that is supported by \c Getter.
- ///
- /// \code Getter<OuterT>::value() \endcode returns a
- /// \code InnerTBase (OuterT::*)() \endcode, which is used to adapt a \c OuterT
- /// object into a \c InnerT
- template <typename InnerTBase,
- template <typename OuterT> class Getter,
- template <typename OuterT> class MatcherImpl,
- typename ReturnTypesF>
- class TypeTraversePolymorphicMatcher {
- private:
- using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
- ReturnTypesF>;
- static Self create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers);
- public:
- using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type;
- explicit TypeTraversePolymorphicMatcher(
- ArrayRef<const Matcher<InnerTBase> *> InnerMatchers)
- : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
- template <typename OuterT> operator Matcher<OuterT>() const {
- return Matcher<OuterT>(
- new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
- }
- struct Func
- : public VariadicFunction<Self, Matcher<InnerTBase>, &Self::create> {
- Func() {}
- };
- private:
- Matcher<InnerTBase> InnerMatcher;
- };
- /// A simple memoizer of T(*)() functions.
- ///
- /// It will call the passed 'Func' template parameter at most once.
- /// Used to support AST_MATCHER_FUNCTION() macro.
- template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher {
- struct Wrapper {
- Wrapper() : M(Func()) {}
- Matcher M;
- };
- public:
- static const Matcher &getInstance() {
- static llvm::ManagedStatic<Wrapper> Instance;
- return Instance->M;
- }
- };
- // Define the create() method out of line to silence a GCC warning about
- // the struct "Func" having greater visibility than its base, which comes from
- // using the flag -fvisibility-inlines-hidden.
- template <typename InnerTBase, template <typename OuterT> class Getter,
- template <typename OuterT> class MatcherImpl, typename ReturnTypesF>
- TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
- TypeTraversePolymorphicMatcher<
- InnerTBase, Getter, MatcherImpl,
- ReturnTypesF>::create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers) {
- return Self(InnerMatchers);
- }
- // FIXME: unify ClassTemplateSpecializationDecl and TemplateSpecializationType's
- // APIs for accessing the template argument list.
- inline ArrayRef<TemplateArgument>
- getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
- return D.getTemplateArgs().asArray();
- }
- inline ArrayRef<TemplateArgument>
- getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
- return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
- }
- inline ArrayRef<TemplateArgument>
- getTemplateSpecializationArgs(const FunctionDecl &FD) {
- if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
- return TemplateArgs->asArray();
- return ArrayRef<TemplateArgument>();
- }
- struct NotEqualsBoundNodePredicate {
- bool operator()(const internal::BoundNodesMap &Nodes) const {
- return Nodes.getNode(ID) != Node;
- }
- std::string ID;
- DynTypedNode Node;
- };
- template <typename Ty, typename Enable = void> struct GetBodyMatcher {
- static const Stmt *get(const Ty &Node) { return Node.getBody(); }
- };
- template <typename Ty>
- struct GetBodyMatcher<Ty, typename std::enable_if<
- std::is_base_of<FunctionDecl, Ty>::value>::type> {
- static const Stmt *get(const Ty &Node) {
- return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr;
- }
- };
- template <typename NodeType>
- inline Optional<BinaryOperatorKind>
- equivalentBinaryOperator(const NodeType &Node) {
- return Node.getOpcode();
- }
- template <>
- inline Optional<BinaryOperatorKind>
- equivalentBinaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
- if (Node.getNumArgs() != 2)
- return None;
- switch (Node.getOperator()) {
- default:
- return None;
- case OO_ArrowStar:
- return BO_PtrMemI;
- case OO_Star:
- return BO_Mul;
- case OO_Slash:
- return BO_Div;
- case OO_Percent:
- return BO_Rem;
- case OO_Plus:
- return BO_Add;
- case OO_Minus:
- return BO_Sub;
- case OO_LessLess:
- return BO_Shl;
- case OO_GreaterGreater:
- return BO_Shr;
- case OO_Spaceship:
- return BO_Cmp;
- case OO_Less:
- return BO_LT;
- case OO_Greater:
- return BO_GT;
- case OO_LessEqual:
- return BO_LE;
- case OO_GreaterEqual:
- return BO_GE;
- case OO_EqualEqual:
- return BO_EQ;
- case OO_ExclaimEqual:
- return BO_NE;
- case OO_Amp:
- return BO_And;
- case OO_Caret:
- return BO_Xor;
- case OO_Pipe:
- return BO_Or;
- case OO_AmpAmp:
- return BO_LAnd;
- case OO_PipePipe:
- return BO_LOr;
- case OO_Equal:
- return BO_Assign;
- case OO_StarEqual:
- return BO_MulAssign;
- case OO_SlashEqual:
- return BO_DivAssign;
- case OO_PercentEqual:
- return BO_RemAssign;
- case OO_PlusEqual:
- return BO_AddAssign;
- case OO_MinusEqual:
- return BO_SubAssign;
- case OO_LessLessEqual:
- return BO_ShlAssign;
- case OO_GreaterGreaterEqual:
- return BO_ShrAssign;
- case OO_AmpEqual:
- return BO_AndAssign;
- case OO_CaretEqual:
- return BO_XorAssign;
- case OO_PipeEqual:
- return BO_OrAssign;
- case OO_Comma:
- return BO_Comma;
- }
- }
- template <typename NodeType>
- inline Optional<UnaryOperatorKind>
- equivalentUnaryOperator(const NodeType &Node) {
- return Node.getOpcode();
- }
- template <>
- inline Optional<UnaryOperatorKind>
- equivalentUnaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
- if (Node.getNumArgs() != 1 && Node.getOperator() != OO_PlusPlus &&
- Node.getOperator() != OO_MinusMinus)
- return None;
- switch (Node.getOperator()) {
- default:
- return None;
- case OO_Plus:
- return UO_Plus;
- case OO_Minus:
- return UO_Minus;
- case OO_Amp:
- return UO_AddrOf;
- case OO_Star:
- return UO_Deref;
- case OO_Tilde:
- return UO_Not;
- case OO_Exclaim:
- return UO_LNot;
- case OO_PlusPlus: {
- const auto *FD = Node.getDirectCallee();
- if (!FD)
- return None;
- return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
- }
- case OO_MinusMinus: {
- const auto *FD = Node.getDirectCallee();
- if (!FD)
- return None;
- return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
- }
- case OO_Coawait:
- return UO_Coawait;
- }
- }
- template <typename NodeType> inline const Expr *getLHS(const NodeType &Node) {
- return Node.getLHS();
- }
- template <>
- inline const Expr *
- getLHS<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
- if (!internal::equivalentBinaryOperator(Node))
- return nullptr;
- return Node.getArg(0);
- }
- template <typename NodeType> inline const Expr *getRHS(const NodeType &Node) {
- return Node.getRHS();
- }
- template <>
- inline const Expr *
- getRHS<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
- if (!internal::equivalentBinaryOperator(Node))
- return nullptr;
- return Node.getArg(1);
- }
- template <typename NodeType>
- inline const Expr *getSubExpr(const NodeType &Node) {
- return Node.getSubExpr();
- }
- template <>
- inline const Expr *
- getSubExpr<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
- if (!internal::equivalentUnaryOperator(Node))
- return nullptr;
- return Node.getArg(0);
- }
- template <typename Ty>
- struct HasSizeMatcher {
- static bool hasSize(const Ty &Node, unsigned int N) {
- return Node.getSize() == N;
- }
- };
- template <>
- inline bool HasSizeMatcher<StringLiteral>::hasSize(
- const StringLiteral &Node, unsigned int N) {
- return Node.getLength() == N;
- }
- template <typename Ty>
- struct GetSourceExpressionMatcher {
- static const Expr *get(const Ty &Node) {
- return Node.getSubExpr();
- }
- };
- template <>
- inline const Expr *GetSourceExpressionMatcher<OpaqueValueExpr>::get(
- const OpaqueValueExpr &Node) {
- return Node.getSourceExpr();
- }
- template <typename Ty>
- struct CompoundStmtMatcher {
- static const CompoundStmt *get(const Ty &Node) {
- return &Node;
- }
- };
- template <>
- inline const CompoundStmt *
- CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) {
- return Node.getSubStmt();
- }
- /// If \p Loc is (transitively) expanded from macro \p MacroName, returns the
- /// location (in the chain of expansions) at which \p MacroName was
- /// expanded. Since the macro may have been expanded inside a series of
- /// expansions, that location may itself be a MacroID.
- llvm::Optional<SourceLocation>
- getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
- const ASTContext &Context);
- inline Optional<StringRef> getOpName(const UnaryOperator &Node) {
- return Node.getOpcodeStr(Node.getOpcode());
- }
- inline Optional<StringRef> getOpName(const BinaryOperator &Node) {
- return Node.getOpcodeStr();
- }
- inline StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
- return Node.getOpcodeStr();
- }
- inline Optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
- auto optBinaryOpcode = equivalentBinaryOperator(Node);
- if (!optBinaryOpcode) {
- auto optUnaryOpcode = equivalentUnaryOperator(Node);
- if (!optUnaryOpcode)
- return None;
- return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
- }
- return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
- }
- /// Matches overloaded operators with a specific name.
- ///
- /// The type argument ArgT is not used by this matcher but is used by
- /// PolymorphicMatcher and should be std::vector<std::string>>.
- template <typename T, typename ArgT = std::vector<std::string>>
- class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
- static_assert(std::is_same<T, BinaryOperator>::value ||
- std::is_same<T, CXXOperatorCallExpr>::value ||
- std::is_same<T, CXXRewrittenBinaryOperator>::value ||
- std::is_same<T, UnaryOperator>::value,
- "Matcher only supports `BinaryOperator`, `UnaryOperator`, "
- "`CXXOperatorCallExpr` and `CXXRewrittenBinaryOperator`");
- static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
- "Matcher ArgT must be std::vector<std::string>");
- public:
- explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names)
- : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
- bool matchesNode(const T &Node) const override {
- Optional<StringRef> OptOpName = getOpName(Node);
- return OptOpName && llvm::is_contained(Names, *OptOpName);
- }
- private:
- static Optional<StringRef> getOpName(const UnaryOperator &Node) {
- return Node.getOpcodeStr(Node.getOpcode());
- }
- static Optional<StringRef> getOpName(const BinaryOperator &Node) {
- return Node.getOpcodeStr();
- }
- static StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
- return Node.getOpcodeStr();
- }
- static Optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
- auto optBinaryOpcode = equivalentBinaryOperator(Node);
- if (!optBinaryOpcode) {
- auto optUnaryOpcode = equivalentUnaryOperator(Node);
- if (!optUnaryOpcode)
- return None;
- return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
- }
- return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
- }
- std::vector<std::string> Names;
- };
- using HasOpNameMatcher =
- PolymorphicMatcher<HasAnyOperatorNameMatcher,
- void(
- TypeList<BinaryOperator, CXXOperatorCallExpr,
- CXXRewrittenBinaryOperator, UnaryOperator>),
- std::vector<std::string>>;
- HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs);
- using HasOverloadOpNameMatcher =
- PolymorphicMatcher<HasOverloadedOperatorNameMatcher,
- void(TypeList<CXXOperatorCallExpr, FunctionDecl>),
- std::vector<std::string>>;
- HasOverloadOpNameMatcher
- hasAnyOverloadedOperatorNameFunc(ArrayRef<const StringRef *> NameRefs);
- /// Returns true if \p Node has a base specifier matching \p BaseSpec.
- ///
- /// A class is not considered to be derived from itself.
- bool matchesAnyBase(const CXXRecordDecl &Node,
- const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
- ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder);
- std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex,
- llvm::Regex::RegexFlags Flags,
- StringRef MatcherID);
- inline bool
- MatchTemplateArgLocAt(const DeclRefExpr &Node, unsigned int Index,
- internal::Matcher<TemplateArgumentLoc> InnerMatcher,
- internal::ASTMatchFinder *Finder,
- internal::BoundNodesTreeBuilder *Builder) {
- llvm::ArrayRef<TemplateArgumentLoc> ArgLocs = Node.template_arguments();
- return Index < ArgLocs.size() &&
- InnerMatcher.matches(ArgLocs[Index], Finder, Builder);
- }
- inline bool
- MatchTemplateArgLocAt(const TemplateSpecializationTypeLoc &Node,
- unsigned int Index,
- internal::Matcher<TemplateArgumentLoc> InnerMatcher,
- internal::ASTMatchFinder *Finder,
- internal::BoundNodesTreeBuilder *Builder) {
- return !Node.isNull() && Index < Node.getNumArgs() &&
- InnerMatcher.matches(Node.getArgLoc(Index), Finder, Builder);
- }
- } // namespace internal
- } // namespace ast_matchers
- } // namespace clang
- #endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|