16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/Support/ManagedStatic.h"
21 namespace ast_matchers {
44 void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
46 Bindings.push_back(BoundNodesMap());
47 for (BoundNodesMap &Binding : Bindings) {
48 ResultVisitor->visitMatch(
BoundNodes(Binding));
54 typedef bool (*VariadicOperatorFunction)(
55 const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *
Finder,
58 template <VariadicOperatorFunction Func>
59 class VariadicMatcher :
public DynMatcherInterface {
62 : InnerMatchers(std::move(InnerMatchers)) {}
64 bool dynMatches(
const ast_type_traits::DynTypedNode &DynNode,
65 ASTMatchFinder *Finder,
66 BoundNodesTreeBuilder *Builder)
const override {
74 class IdDynMatcher :
public DynMatcherInterface {
76 IdDynMatcher(StringRef
ID,
77 const IntrusiveRefCntPtr<DynMatcherInterface> &
InnerMatcher)
80 bool dynMatches(
const ast_type_traits::DynTypedNode &DynNode,
81 ASTMatchFinder *Finder,
82 BoundNodesTreeBuilder *Builder)
const override {
83 bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
84 if (Result) Builder->setBinding(ID, DynNode);
98 class TrueMatcherImpl :
public DynMatcherInterface {
103 bool dynMatches(
const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
104 BoundNodesTreeBuilder *)
const override {
108 static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
112 DynTypedMatcher DynTypedMatcher::constructVariadic(
113 DynTypedMatcher::VariadicOperator Op,
114 ast_type_traits::ASTNodeKind SupportedKind,
116 assert(InnerMatchers.size() > 0 &&
"Array must not be empty.");
117 assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
118 [SupportedKind](
const DynTypedMatcher &M) {
119 return M.canConvertTo(SupportedKind);
121 "InnerMatchers must be convertible to SupportedKind!");
127 auto RestrictKind = SupportedKind;
135 for (
auto &IM : InnerMatchers) {
137 RestrictKind, IM.RestrictKind);
139 return DynTypedMatcher(
140 SupportedKind, RestrictKind,
141 new VariadicMatcher<AllOfVariadicOperator>(std::move(InnerMatchers)));
144 return DynTypedMatcher(
145 SupportedKind, RestrictKind,
146 new VariadicMatcher<AnyOfVariadicOperator>(std::move(InnerMatchers)));
149 return DynTypedMatcher(
150 SupportedKind, RestrictKind,
151 new VariadicMatcher<EachOfVariadicOperator>(std::move(InnerMatchers)));
156 return DynTypedMatcher(
157 SupportedKind, RestrictKind,
158 new VariadicMatcher<NotUnaryOperator>(std::move(InnerMatchers)));
160 llvm_unreachable(
"Invalid Op value.");
163 DynTypedMatcher DynTypedMatcher::trueMatcher(
164 ast_type_traits::ASTNodeKind NodeKind) {
165 return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
168 bool DynTypedMatcher::canMatchNodesOfKind(
169 ast_type_traits::ASTNodeKind
Kind)
const {
170 return RestrictKind.isBaseOf(Kind);
173 DynTypedMatcher DynTypedMatcher::dynCastTo(
174 const ast_type_traits::ASTNodeKind Kind)
const {
176 Copy.SupportedKind =
Kind;
183 ASTMatchFinder *Finder,
184 BoundNodesTreeBuilder *Builder)
const {
185 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
186 Implementation->dynMatches(DynNode, Finder, Builder)) {
192 Builder->removeBindings([](
const BoundNodesMap &) {
return true; });
196 bool DynTypedMatcher::matchesNoKindCheck(
197 const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
198 BoundNodesTreeBuilder *Builder)
const {
199 assert(RestrictKind.isBaseOf(DynNode.getNodeKind()));
200 if (Implementation->dynMatches(DynNode, Finder, Builder)) {
206 Builder->removeBindings([](
const BoundNodesMap &) {
return true; });
213 Result.Implementation =
new IdDynMatcher(ID, Result.Implementation);
217 bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To)
const {
218 const auto From = getSupportedKind();
219 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
220 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
223 if (From.isSame(TypeKind) && To.isSame(QualKind))
return true;
225 return From.isBaseOf(To);
228 void BoundNodesTreeBuilder::addMatch(
const BoundNodesTreeBuilder &Other) {
229 Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
233 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
235 if (InnerMatchers.size() != 1)
248 BoundNodesTreeBuilder Discard(*Builder);
249 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
253 ASTMatchFinder *Finder,
254 BoundNodesTreeBuilder *Builder,
259 for (
const DynTypedMatcher &InnerMatcher : InnerMatchers) {
260 if (!InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder))
267 ASTMatchFinder *Finder,
268 BoundNodesTreeBuilder *Builder,
270 BoundNodesTreeBuilder Result;
271 bool Matched =
false;
272 for (
const DynTypedMatcher &InnerMatcher : InnerMatchers) {
273 BoundNodesTreeBuilder BuilderInner(*Builder);
274 if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
276 Result.addMatch(BuilderInner);
279 *Builder = std::move(Result);
284 ASTMatchFinder *Finder,
285 BoundNodesTreeBuilder *Builder,
287 for (
const DynTypedMatcher &InnerMatcher : InnerMatchers) {
288 BoundNodesTreeBuilder Result = *
Builder;
289 if (InnerMatcher.matches(DynNode, Finder, &Result)) {
290 *Builder = std::move(Result);
298 std::vector<std::string>
Names;
299 for (
auto *
Name : NameRefs)
300 Names.emplace_back(*
Name);
301 return internal::Matcher<NamedDecl>(
302 new internal::HasNameMatcher(std::move(Names)));
305 HasNameMatcher::HasNameMatcher(std::vector<std::string> N)
306 : UseUnqualifiedMatch(std::all_of(
308 [](StringRef
Name) {
return Name.find(
"::") ==
Name.npos; })),
312 assert(!
Name.empty());
318 bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) {
319 StringRef
Name = FullName;
320 if (!Name.endswith(Suffix))
322 Name = Name.drop_back(Suffix.size());
324 if (!Name.endswith(
"::"))
326 Name = Name.drop_back(2);
334 if (Node.getIdentifier())
337 if (Node.getDeclName()) {
340 llvm::raw_svector_ostream OS(Scratch);
345 return "(anonymous)";
349 if (Node.getIdentifier()) {
350 return Node.getName();
353 return (
"(anonymous " + Node.getKindName() +
")").toStringRef(Scratch);
356 StringRef getNodeName(
const NamespaceDecl &Node,
358 return Node.isAnonymousNamespace() ?
"(anonymous namespace)" : Node.getName();
364 PatternSet(ArrayRef<std::string>
Names) {
365 for (StringRef Name : Names)
372 bool consumeNameSuffix(StringRef NodeName,
bool CanSkip) {
374 if (internal::consumeNameSuffix(
Patterns[
I].
P, NodeName) ||
387 bool foundMatch(
bool AllowFullyQualified)
const {
389 if (P.P.empty() && (AllowFullyQualified || !P.IsFullyQualified))
404 bool HasNameMatcher::matchesNodeUnqualified(
const NamedDecl &Node)
const {
405 assert(UseUnqualifiedMatch);
407 StringRef NodeName = getNodeName(Node, Scratch);
408 return std::any_of(Names.begin(), Names.end(), [&](StringRef
Name) {
409 return consumeNameSuffix(Name, NodeName) && Name.empty();
413 bool HasNameMatcher::matchesNodeFullFast(
const NamedDecl &Node)
const {
425 if (!
Patterns.consumeNameSuffix(getNodeName(Node, Scratch),
431 const DeclContext *Ctx = Node.getDeclContext();
433 if (Ctx->isFunctionOrMethod())
436 for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) {
440 if (
const auto *ND = dyn_cast<NamespaceDecl>(Ctx)) {
442 if (
Patterns.consumeNameSuffix(getNodeName(*ND, Scratch),
443 ND->isAnonymousNamespace() ||
448 if (
const auto *RD = dyn_cast<RecordDecl>(Ctx)) {
449 if (!isa<ClassTemplateSpecializationDecl>(Ctx)) {
450 if (
Patterns.consumeNameSuffix(getNodeName(*RD, Scratch),
460 return matchesNodeFullSlow(Node);
466 bool HasNameMatcher::matchesNodeFullSlow(
const NamedDecl &Node)
const {
467 const bool SkipUnwrittenCases[] = {
false,
true};
468 for (
bool SkipUnwritten : SkipUnwrittenCases) {
470 llvm::raw_svector_ostream OS(NodeName);
473 PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
474 Policy.SuppressUnwrittenScope =
true;
475 Node.printQualifiedName(OS, Policy);
477 Node.printQualifiedName(OS);
480 const StringRef FullName = OS.str();
482 for (
const StringRef Pattern : Names) {
483 if (Pattern.startswith(
"::")) {
484 if (FullName == Pattern)
486 }
else if (FullName.endswith(Pattern) &&
487 FullName.drop_back(Pattern.size()).endswith(
"::")) {
496 bool HasNameMatcher::matchesNode(
const NamedDecl &Node)
const {
497 assert(matchesNodeFullFast(Node) == matchesNodeFullSlow(Node));
498 if (UseUnqualifiedMatch) {
499 assert(matchesNodeUnqualified(Node) == matchesNodeFullFast(Node));
500 return matchesNodeUnqualified(Node);
502 return matchesNodeFullFast(Node);
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
llvm::SmallVector< Pattern, 8 > Patterns
bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
std::vector< DynTypedMatcher > InnerMatchers
const IntrusiveRefCntPtr< DynMatcherInterface > InnerMatcher
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
detail::InMemoryDirectory::const_iterator I
StringRef getName() const
Return the actual identifier string.
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
Matcher< NamedDecl > hasAnyNameFunc(ArrayRef< const StringRef * > NameRefs)
static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2)
Return the most derived type between Kind1 and Kind2.
The result type of a method or function.
ASTMatchFinder *const Finder
BoundNodesTreeBuilder BoundNodes
ast_type_traits::DynTypedNode Node
A dynamically typed AST node container.
BoundNodesTreeBuilder *const Builder
bool matches(const til::SExpr *E1, const til::SExpr *E2)