summaryrefslogtreecommitdiffstats
path: root/include/clang/ASTMatchers
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/ASTMatchers')
-rw-r--r--include/clang/ASTMatchers/ASTMatchFinder.h69
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h337
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h636
-rw-r--r--include/clang/ASTMatchers/ASTMatchersMacros.h17
-rw-r--r--include/clang/ASTMatchers/Dynamic/Diagnostics.h4
-rw-r--r--include/clang/ASTMatchers/Dynamic/Parser.h130
-rw-r--r--include/clang/ASTMatchers/Dynamic/Registry.h51
-rw-r--r--include/clang/ASTMatchers/Dynamic/VariantValue.h184
8 files changed, 951 insertions, 477 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index 8af0546..ce2674e 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -38,10 +38,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Timer.h"
namespace clang {
@@ -102,6 +104,12 @@ public:
///
/// Optionally override to do per translation unit tasks.
virtual void onEndOfTranslationUnit() {}
+
+ /// \brief An id used to group the matchers.
+ ///
+ /// This id is used, for example, for the profiling output.
+ /// It defaults to "<unknown>".
+ virtual StringRef getID() const;
};
/// \brief Called when parsing is finished. Intended for testing only.
@@ -111,7 +119,22 @@ public:
virtual void run() = 0;
};
- MatchFinder();
+ struct MatchFinderOptions {
+ struct Profiling {
+ Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
+ : Records(Records) {}
+
+ /// \brief Per bucket timing information.
+ llvm::StringMap<llvm::TimeRecord> &Records;
+ };
+
+ /// \brief Enables per-check timers.
+ ///
+ /// It prints a report after match.
+ llvm::Optional<Profiling> CheckProfiling;
+ };
+
+ MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
~MatchFinder();
/// \brief Adds a matcher to execute when running over the AST.
@@ -148,7 +171,7 @@ public:
MatchCallback *Action);
/// \brief Creates a clang ASTConsumer that finds all matches.
- clang::ASTConsumer *newASTConsumer();
+ std::unique_ptr<clang::ASTConsumer> newASTConsumer();
/// \brief Calls the registered callbacks on all matches on the given \p Node.
///
@@ -173,11 +196,25 @@ public:
/// Each call to FindAll(...) will call the closure once.
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
-private:
- /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
+ /// \brief For each \c Matcher<> a \c MatchCallback that will be called
/// when it matches.
- std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> >
- MatcherCallbackPairs;
+ struct MatchersByType {
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
+ DeclOrStmt;
+ std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
+ std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
+ NestedNameSpecifier;
+ std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
+ NestedNameSpecifierLoc;
+ std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
+ /// \brief All the callbacks in one container to simplify iteration.
+ std::vector<MatchCallback *> AllCallbacks;
+ };
+
+private:
+ MatchersByType Matchers;
+
+ MatchFinderOptions Options;
/// \brief Called when parsing is done.
ParsingDoneTestCallback *ParsingDone;
@@ -210,16 +247,14 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
///
/// This is useful in combanation with \c match():
/// \code
-/// Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
-/// Node, Context));
+/// const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
+/// Node, Context));
/// \endcode
template <typename NodeT>
-NodeT *
+const NodeT *
selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
- for (SmallVectorImpl<BoundNodes>::const_iterator I = Results.begin(),
- E = Results.end();
- I != E; ++I) {
- if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo))
+ for (const BoundNodes &N : Results) {
+ if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
return Node;
}
return nullptr;
@@ -243,7 +278,7 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
MatchFinder Finder;
Finder.addMatcher(Matcher, &Callback);
Finder.match(Node, Context);
- return Callback.Nodes;
+ return std::move(Callback.Nodes);
}
template <typename MatcherT, typename NodeT>
@@ -255,4 +290,4 @@ match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
} // end namespace ast_matchers
} // end namespace clang
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+#endif
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 1ff4ab3..f002cb9 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -42,9 +42,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
@@ -140,9 +141,97 @@ typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher;
/// \endcode
///
/// Usable as: Any Matcher
-inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>
-anything() {
- return internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>();
+inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
+
+/// \brief Matches typedef declarations.
+///
+/// Given
+/// \code
+/// typedef int X;
+/// \endcode
+/// typedefDecl()
+/// matches "typedef int X"
+const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
+
+/// \brief Matches AST nodes that were expanded within the main-file.
+///
+/// Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
+/// \code
+/// #include <Y.h>
+/// class X {};
+/// \endcode
+/// Y.h:
+/// \code
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
+ TypeLoc)) {
+ auto &SourceManager = Finder->getASTContext().getSourceManager();
+ return SourceManager.isInMainFile(
+ SourceManager.getExpansionLoc(Node.getLocStart()));
+}
+
+/// \brief Matches AST nodes that were expanded within system-header-files.
+///
+/// Example matches Y but not X
+/// (matcher = recordDecl(isExpansionInSystemHeader())
+/// \code
+/// #include <SystemHeader.h>
+/// class X {};
+/// \endcode
+/// SystemHeader.h:
+/// \code
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
+ TypeLoc)) {
+ auto &SourceManager = Finder->getASTContext().getSourceManager();
+ auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+ if (ExpansionLoc.isInvalid()) {
+ return false;
+ }
+ return SourceManager.isInSystemHeader(ExpansionLoc);
+}
+
+/// \brief Matches AST nodes that were expanded within files whose name is
+/// partially matching a given regex.
+///
+/// Example matches Y but not X
+/// (matcher = recordDecl(isExpansionInFileMatching("AST.*"))
+/// \code
+/// #include "ASTMatcher.h"
+/// class X {};
+/// \endcode
+/// ASTMatcher.h:
+/// \code
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
+ TypeLoc),
+ std::string, RegExp) {
+ auto &SourceManager = Finder->getASTContext().getSourceManager();
+ auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+ if (ExpansionLoc.isInvalid()) {
+ return false;
+ }
+ auto FileEntry =
+ SourceManager.getFileEntryForID(SourceManager.getFileID(ExpansionLoc));
+ if (!FileEntry) {
+ return false;
+ }
+
+ auto Filename = FileEntry->getName();
+ llvm::Regex RE(RegExp);
+ return RE.match(Filename);
}
/// \brief Matches declarations.
@@ -156,6 +245,17 @@ anything() {
/// \endcode
const internal::VariadicAllOfMatcher<Decl> decl;
+/// \brief Matches a declaration of a linkage specification.
+///
+/// Given
+/// \code
+/// extern "C" {}
+/// \endcode
+/// linkageSpecDecl()
+/// matches "extern "C" {}"
+const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
+ linkageSpecDecl;
+
/// \brief Matches a declaration of anything that could have a name.
///
/// Example matches \c X, \c S, the anonymous union type, \c i, and \c U;
@@ -263,6 +363,17 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicAllOfMatcher<CXXCtorInitializer> ctorInitializer;
+/// \brief Matches template arguments.
+///
+/// Given
+/// \code
+/// template <typename T> struct C {};
+/// C<int> c;
+/// \endcode
+/// templateArgument()
+/// matches 'int' in C<int>.
+const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+
/// \brief Matches public C++ declarations.
///
/// Given
@@ -441,6 +552,23 @@ AST_POLYMORPHIC_MATCHER_P2(
return InnerMatcher.matches(List[N], Finder, Builder);
}
+/// \brief Matches if the number of template arguments equals \p N.
+///
+/// Given
+/// \code
+/// template<typename T> struct C {};
+/// C<int> c;
+/// \endcode
+/// classTemplateSpecializationDecl(templateArgumentCountIs(1))
+/// matches C<int>.
+AST_POLYMORPHIC_MATCHER_P(
+ templateArgumentCountIs,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl,
+ TemplateSpecializationType),
+ unsigned, N) {
+ return internal::getTemplateSpecializationArgs(Node).size() == N;
+}
+
/// \brief Matches a TemplateArgument that refers to a certain type.
///
/// Given
@@ -497,6 +625,68 @@ AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) {
return false;
}
+/// \brief Matches a TemplateArgument that is an integral value.
+///
+/// Given
+/// \code
+/// template<int T> struct A {};
+/// C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(isIntegral()))
+/// matches the implicit instantiation of C in C<42>
+/// with isIntegral() matching 42.
+AST_MATCHER(TemplateArgument, isIntegral) {
+ return Node.getKind() == TemplateArgument::Integral;
+}
+
+/// \brief Matches a TemplateArgument that referes to an integral type.
+///
+/// Given
+/// \code
+/// template<int T> struct A {};
+/// C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(refersToIntegralType(asString("int"))))
+/// matches the implicit instantiation of C in C<42>.
+AST_MATCHER_P(TemplateArgument, refersToIntegralType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ if (Node.getKind() != TemplateArgument::Integral)
+ return false;
+ return InnerMatcher.matches(Node.getIntegralType(), Finder, Builder);
+}
+
+/// \brief Matches a TemplateArgument of integral type with a given value.
+///
+/// Note that 'Value' is a string as the template argument's value is
+/// an arbitrary precision integer. 'Value' must be euqal to the canonical
+/// representation of that integral value in base 10.
+///
+/// Given
+/// \code
+/// template<int T> struct A {};
+/// C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(equalsIntegralValue("42")))
+/// matches the implicit instantiation of C in C<42>.
+AST_MATCHER_P(TemplateArgument, equalsIntegralValue,
+ std::string, Value) {
+ if (Node.getKind() != TemplateArgument::Integral)
+ return false;
+ return Node.getAsIntegral().toString(10) == Value;
+}
+
+/// \brief Matches any value declaration.
+///
+/// Example matches A, B, C and F
+/// \code
+/// enum X { A, B, C };
+/// void F();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
+
/// \brief Matches C++ constructor declarations.
///
/// Example matches Foo::Foo() and Foo::Foo(int)
@@ -1414,21 +1604,21 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
///
/// Usable as: Any Matcher
const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = {
- internal::EachOfVariadicOperator
+ internal::DynTypedMatcher::VO_EachOf
};
/// \brief Matches if any of the given matchers matches.
///
/// Usable as: Any Matcher
const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = {
- internal::AnyOfVariadicOperator
+ internal::DynTypedMatcher::VO_AnyOf
};
/// \brief Matches if all given matchers match.
///
/// Usable as: Any Matcher
const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = {
- internal::AllOfVariadicOperator
+ internal::DynTypedMatcher::VO_AllOf
};
/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
@@ -1502,16 +1692,8 @@ inline internal::Matcher<Stmt> sizeOfExpr(
/// \code
/// namespace a { namespace b { class X; } }
/// \endcode
-AST_MATCHER_P(NamedDecl, hasName, std::string, Name) {
- assert(!Name.empty());
- const std::string FullNameString = "::" + Node.getQualifiedNameAsString();
- const StringRef FullName = FullNameString;
- const StringRef Pattern = Name;
- if (Pattern.startswith("::")) {
- return FullName == Pattern;
- } else {
- return FullName.endswith(("::" + Pattern).str());
- }
+inline internal::Matcher<NamedDecl> hasName(const std::string &Name) {
+ return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Name));
}
/// \brief Matches NamedDecl nodes whose fully qualified names contain
@@ -1558,7 +1740,7 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
inline internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>
-hasOverloadedOperatorName(const StringRef Name) {
+hasOverloadedOperatorName(StringRef Name) {
return internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>(
@@ -1592,7 +1774,7 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
}
/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
-AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, StringRef, BaseName, 1) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) {
assert(!BaseName.empty());
return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
@@ -1607,8 +1789,8 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
/// \brief Overloaded method as shortcut for
/// \c isSameOrDerivedFrom(hasName(...)).
-AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, StringRef, BaseName,
- 1) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
+ BaseName, 1) {
assert(!BaseName.empty());
return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
@@ -1768,7 +1950,7 @@ const internal::ArgumentAdaptingMatcherFunc<
///
/// Usable as: Any Matcher
const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
- internal::NotUnaryOperator
+ internal::DynTypedMatcher::VO_UnaryNot
};
/// \brief Matches a node if the declaration associated with that node
@@ -1844,7 +2026,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
/// Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x")))))
/// \code
/// class Y { public: void x(); };
-/// void z() { Y y; y.x();
+/// void z() { Y y; y.x(); }
/// \endcode
AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
1) {
@@ -1952,6 +2134,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
/// void a(X b) {
/// X &x = b;
/// const X &y = b;
+/// }
/// };
/// \endcode
AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
@@ -2280,11 +2463,10 @@ AST_MATCHER(CXXCtorInitializer, isWritten) {
AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
CallExpr, CXXConstructExpr),
internal::Matcher<Expr>, InnerMatcher) {
- for (unsigned I = 0; I < Node.getNumArgs(); ++I) {
+ for (const Expr *Arg : Node.arguments()) {
BoundNodesTreeBuilder Result(*Builder);
- if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), Finder,
- &Result)) {
- *Builder = Result;
+ if (InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, &Result)) {
+ *Builder = std::move(Result);
return true;
}
}
@@ -2372,6 +2554,19 @@ AST_MATCHER(FunctionDecl, isExternC) {
return Node.isExternC();
}
+/// \brief Matches deleted function declarations.
+///
+/// Given:
+/// \code
+/// void Func();
+/// void DeletedFunc() = delete;
+/// \endcode
+/// functionDecl(isDeleted())
+/// matches the declaration of DeletedFunc, but not Func.
+AST_MATCHER(FunctionDecl, isDeleted) {
+ return Node.isDeleted();
+}
+
/// \brief Matches the condition expression of an if statement, for loop,
/// or conditional operator.
///
@@ -2953,6 +3148,43 @@ AST_POLYMORPHIC_MATCHER(
TSK_ExplicitInstantiationDefinition);
}
+/// \brief Matches declarations that are template instantiations or are inside
+/// template instantiations.
+///
+/// Given
+/// \code
+/// template<typename T> void A(T t) { T i; }
+/// A(0);
+/// A(0U);
+/// \endcode
+/// functionDecl(isInstantiated())
+/// matches 'A(int) {...};' and 'A(unsigned) {...}'.
+AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
+ auto IsInstantiation = decl(anyOf(recordDecl(isTemplateInstantiation()),
+ functionDecl(isTemplateInstantiation())));
+ return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
+}
+
+/// \brief Matches statements inside of a template instantiation.
+///
+/// Given
+/// \code
+/// int j;
+/// template<typename T> void A(T t) { T i; j += 42;}
+/// A(0);
+/// A(0U);
+/// \endcode
+/// declStmt(isInTemplateInstantiation())
+/// matches 'int i;' and 'unsigned i'.
+/// unless(stmt(isInTemplateInstantiation()))
+/// will NOT match j += 42; as it's shared between the template definition and
+/// instantiation.
+AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
+ return stmt(
+ hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()),
+ functionDecl(isTemplateInstantiation())))));
+}
+
/// \brief Matches explicit template specializations of function, class, or
/// static member variable template instantiations.
///
@@ -2979,6 +3211,18 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
new internal::TypeLocTypeMatcher(InnerMatcher));
}
+/// \brief Matches type \c void.
+///
+/// Given
+/// \code
+/// struct S { void func(); };
+/// \endcode
+/// functionDecl(returns(voidType()))
+/// matches "void func();"
+AST_MATCHER(Type, voidType) {
+ return Node.isVoidType();
+}
+
/// \brief Matches builtin Types.
///
/// Given
@@ -3094,6 +3338,7 @@ AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType);
/// int a[] = { 2, 3 }
/// int b[42];
/// int c[a[0]];
+/// }
/// \endcode
/// variableArrayType()
/// matches "int c[a[0]]"
@@ -3432,8 +3677,9 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
/// \c recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
/// declaration of \c class \c D.
AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
- return InnerMatcher.matches(*Decl::castFromDeclContext(Node.getDeclContext()),
- Finder, Builder);
+ const DeclContext *DC = Node.getDeclContext();
+ if (!DC) return false;
+ return InnerMatcher.matches(*Decl::castFromDeclContext(DC), Finder, Builder);
}
/// \brief Matches nested name specifiers.
@@ -3599,7 +3845,7 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
Result.addMatch(CaseBuilder);
}
}
- *Builder = Result;
+ *Builder = std::move(Result);
return Matched;
}
@@ -3622,7 +3868,7 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
Result.addMatch(InitBuilder);
}
}
- *Builder = Result;
+ *Builder = std::move(Result);
return Matched;
}
@@ -3643,7 +3889,32 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
return InnerMatcher.matches(*Node.getLHS(), Finder, Builder);
}
+/// \brief Matches declaration that has a given attribute.
+///
+/// Given
+/// \code
+/// __attribute__((device)) void f() { ... }
+/// \endcode
+/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+/// f.
+AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
+ for (const auto *Attr : Node.attrs()) {
+ if (Attr->getKind() == AttrKind)
+ return true;
+ }
+ return false;
+}
+
+/// \brief Matches CUDA kernel call expression.
+///
+/// Example matches,
+/// \code
+/// kernel<<<i,j>>>();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
+ CUDAKernelCallExpr;
+
} // end namespace ast_matchers
} // end namespace clang
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#endif
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 94435fd..ebe5cdd 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -32,8 +32,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Decl.h"
@@ -44,6 +44,7 @@
#include "clang/AST/Type.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/VariadicFunction.h"
+#include "llvm/Support/ManagedStatic.h"
#include <map>
#include <string>
#include <vector>
@@ -61,9 +62,8 @@ public:
/// \brief Adds \c Node to the map with key \c ID.
///
/// The node's base type should be in NodeBaseType or it will be unaccessible.
- template <typename T>
- void addNode(StringRef ID, const T* Node) {
- NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node);
+ void addNode(StringRef ID, const ast_type_traits::DynTypedNode& DynNode) {
+ NodeMap[ID] = DynNode;
}
/// \brief Returns the AST node bound to \c ID.
@@ -103,6 +103,16 @@ public:
return NodeMap;
}
+ /// \brief 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;
};
@@ -126,11 +136,12 @@ public:
};
/// \brief Add a binding from an id to a node.
- template <typename T> void setBinding(const std::string &Id, const T *Node) {
+ void setBinding(const std::string &Id,
+ const ast_type_traits::DynTypedNode &DynNode) {
if (Bindings.empty())
Bindings.push_back(BoundNodesMap());
- for (unsigned i = 0, e = Bindings.size(); i != e; ++i)
- Bindings[i].addNode(Id, Node);
+ for (BoundNodesMap &Binding : Bindings)
+ Binding.addNode(Id, DynNode);
}
/// \brief Adds a branch in the tree.
@@ -153,12 +164,38 @@ public:
return Bindings < Other.Bindings;
}
+ /// \brief 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, 16> Bindings;
};
class ASTMatchFinder;
+/// \brief 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 RefCountedBaseVPTR {
+public:
+ /// \brief 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 ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const = 0;
+};
+
/// \brief Generic interface for matchers on an AST node of type T.
///
/// Implement this if your matcher may need to inspect the children or
@@ -167,7 +204,7 @@ class ASTMatchFinder;
/// current node and doesn't care about its children or descendants,
/// implement SingleNodeMatcherInterface instead.
template <typename T>
-class MatcherInterface : public RefCountedBaseVPTR {
+class MatcherInterface : public DynMatcherInterface {
public:
virtual ~MatcherInterface() {}
@@ -178,6 +215,12 @@ public:
virtual bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const = 0;
+
+ bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ return matches(DynNode.getUnchecked<T>(), Finder, Builder);
+ }
};
/// \brief Interface for matchers that only evaluate properties on a single
@@ -199,6 +242,145 @@ private:
}
};
+template <typename> class Matcher;
+
+/// \brief 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:
+ /// \brief Takes ownership of the provided implementation pointer.
+ template <typename T>
+ DynTypedMatcher(MatcherInterface<T> *Implementation)
+ : AllowBind(false),
+ SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()),
+ RestrictKind(SupportedKind), Implementation(Implementation) {}
+
+ /// \brief Construct from a variadic function.
+ enum VariadicOperator {
+ /// \brief Matches nodes for which all provided matchers match.
+ VO_AllOf,
+ /// \brief Matches nodes for which at least one of the provided matchers
+ /// matches.
+ VO_AnyOf,
+ /// \brief Matches nodes for which at least one of the provided matchers
+ /// matches, but doesn't stop at the first match.
+ VO_EachOf,
+ /// \brief 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,
+ std::vector<DynTypedMatcher> InnerMatchers);
+
+ /// \brief Get a "true" matcher for \p NodeKind.
+ ///
+ /// It only checks that the node is of the right kind.
+ static DynTypedMatcher trueMatcher(ast_type_traits::ASTNodeKind NodeKind);
+
+ void setAllowBind(bool AB) { AllowBind = AB; }
+
+ /// \brief 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(ast_type_traits::ASTNodeKind Kind) const;
+
+ /// \brief Return a matcher that points to the same implementation, but
+ /// restricts the node types for \p Kind.
+ DynTypedMatcher dynCastTo(const ast_type_traits::ASTNodeKind Kind) const;
+
+ /// \brief Returns true if the matcher matches the given \c DynNode.
+ bool matches(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const;
+
+ /// \brief 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 ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const;
+
+ /// \brief 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;
+
+ /// \brief 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.
+ typedef std::pair<ast_type_traits::ASTNodeKind, uint64_t> MatcherIDType;
+ 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()));
+ }
+
+ /// \brief Returns the type this matcher works on.
+ ///
+ /// \c matches() will always return false unless the node passed is of this
+ /// or a derived type.
+ ast_type_traits::ASTNodeKind getSupportedKind() const {
+ return SupportedKind;
+ }
+
+ /// \brief 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(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
+ }
+ bool canConvertTo(ast_type_traits::ASTNodeKind To) const;
+
+ /// \brief 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>();
+ }
+
+ /// \brief 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;
+
+private:
+ DynTypedMatcher(ast_type_traits::ASTNodeKind SupportedKind,
+ ast_type_traits::ASTNodeKind RestrictKind,
+ IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
+ : AllowBind(false),
+ SupportedKind(SupportedKind),
+ RestrictKind(RestrictKind),
+ Implementation(std::move(Implementation)) {}
+
+ bool AllowBind;
+ ast_type_traits::ASTNodeKind SupportedKind;
+ /// \brief A potentially stricter node kind.
+ ///
+ /// It allows to perform implicit and dynamic cast of matchers without
+ /// needing to change \c Implementation.
+ ast_type_traits::ASTNodeKind RestrictKind;
+ IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
+};
+
/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
@@ -221,7 +403,10 @@ public:
Matcher(const Matcher<From> &Other,
typename std::enable_if<std::is_base_of<From, T>::value &&
!std::is_same<From, T>::value>::type * = 0)
- : Implementation(new ImplicitCastMatcher<From>(Other)) {}
+ : Implementation(restrictMatcher(Other.Implementation)) {
+ assert(Implementation.getSupportedKind().isSame(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
+ }
/// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>.
///
@@ -233,26 +418,34 @@ public:
std::is_same<TypeT, Type>::value>::type* = 0)
: Implementation(new TypeToQualType<TypeT>(Other)) {}
+ /// \brief 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 {
+ static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call.");
+ return Matcher<To>(Implementation);
+ }
+
/// \brief Forwards the call to the underlying MatcherInterface<T> pointer.
bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- if (Implementation->matches(Node, Finder, Builder))
- return true;
- // Delete all bindings when a matcher does not match.
- // This prevents unexpected exposure of bound nodes in unmatches
- // branches of the match tree.
- *Builder = BoundNodesTreeBuilder();
- return false;
+ return Implementation.matches(ast_type_traits::DynTypedNode::create(Node),
+ Finder, Builder);
}
/// \brief Returns an ID that uniquely identifies the matcher.
- uint64_t getID() const {
- /// FIXME: Document the requirements this imposes on matcher
- /// implementations (no new() implementation_ during a Matches()).
- return reinterpret_cast<uint64_t>(Implementation.get());
+ DynTypedMatcher::MatcherIDType getID() const {
+ return Implementation.getID();
}
+ /// \brief 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 { return Implementation; }
+
/// \brief Allows the conversion of a \c Matcher<Type> to a \c
/// Matcher<QualType>.
///
@@ -276,24 +469,22 @@ public:
};
private:
- /// \brief Allows conversion from Matcher<Base> to Matcher<T> if T
- /// is derived from Base.
- template <typename Base>
- class ImplicitCastMatcher : public MatcherInterface<T> {
- public:
- explicit ImplicitCastMatcher(const Matcher<Base> &From)
- : From(From) {}
+ // For Matcher<T> <=> Matcher<U> conversions.
+ template <typename U> friend class Matcher;
+ // For DynTypedMatcher::unconditionalConvertTo<T>.
+ friend class DynTypedMatcher;
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return From.matches(Node, Finder, Builder);
- }
+ static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) {
+ return Other.dynCastTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
+ }
- private:
- const Matcher<Base> From;
- };
+ explicit Matcher(const DynTypedMatcher &Implementation)
+ : Implementation(restrictMatcher(Implementation)) {
+ assert(this->Implementation.getSupportedKind()
+ .isSame(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
+ }
- IntrusiveRefCntPtr< MatcherInterface<T> > Implementation;
+ DynTypedMatcher Implementation;
}; // class Matcher
/// \brief A convenient helper for creating a Matcher<T> without specifying
@@ -303,153 +494,10 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
return Matcher<T>(Implementation);
}
-template <typename T> class BindableMatcher;
-
-/// \brief 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:
- /// \brief Construct from a \c Matcher<T>. Copies the matcher.
- template <typename T> inline DynTypedMatcher(const Matcher<T> &M);
-
- /// \brief Construct from a bindable \c Matcher<T>. Copies the matcher.
- ///
- /// This version enables \c tryBind() on the \c DynTypedMatcher.
- template <typename T> inline DynTypedMatcher(const BindableMatcher<T> &M);
-
- /// \brief Returns true if the matcher matches the given \c DynNode.
- bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const {
- return Storage->matches(DynNode, Finder, Builder);
- }
-
- /// \brief 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 {
- return Storage->tryBind(ID);
- }
-
- /// \brief Returns a unique \p ID for the matcher.
- uint64_t getID() const { return Storage->getID(); }
-
- /// \brief Returns the type this matcher works on.
- ///
- /// \c matches() will always return false unless the node passed is of this
- /// or a derived type.
- ast_type_traits::ASTNodeKind getSupportedKind() const {
- return Storage->getSupportedKind();
- }
-
- /// \brief 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 getSupportedKind().isBaseOf(
- ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
- }
-
- /// \brief 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>();
- }
-
- /// \brief 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;
-
-private:
- class MatcherStorage : public RefCountedBaseVPTR {
- public:
- MatcherStorage(ast_type_traits::ASTNodeKind SupportedKind, uint64_t ID)
- : SupportedKind(SupportedKind), ID(ID) {}
- virtual ~MatcherStorage();
-
- virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const = 0;
-
- virtual llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const = 0;
-
- ast_type_traits::ASTNodeKind getSupportedKind() const {
- return SupportedKind;
- }
-
- uint64_t getID() const { return ID; }
-
- private:
- const ast_type_traits::ASTNodeKind SupportedKind;
- const uint64_t ID;
- };
-
- /// \brief Typed implementation of \c MatcherStorage.
- template <typename T> class TypedMatcherStorage;
-
- IntrusiveRefCntPtr<const MatcherStorage> Storage;
-};
-
-template <typename T>
-class DynTypedMatcher::TypedMatcherStorage : public MatcherStorage {
-public:
- TypedMatcherStorage(const Matcher<T> &Other, bool AllowBind)
- : MatcherStorage(ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
- Other.getID()),
- InnerMatcher(Other), AllowBind(AllowBind) {}
-
- bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- if (const T *Node = DynNode.get<T>()) {
- return InnerMatcher.matches(*Node, Finder, Builder);
- }
- return false;
- }
-
- llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const override {
- if (!AllowBind)
- return llvm::Optional<DynTypedMatcher>();
- return DynTypedMatcher(BindableMatcher<T>(InnerMatcher).bind(ID));
- }
-
-private:
- const Matcher<T> InnerMatcher;
- const bool AllowBind;
-};
-
-template <typename T>
-inline DynTypedMatcher::DynTypedMatcher(const Matcher<T> &M)
- : Storage(new TypedMatcherStorage<T>(M, false)) {}
-
-template <typename T>
-inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher<T> &M)
- : Storage(new TypedMatcherStorage<T>(M, true)) {}
-
/// \brief Specialization of the conversion functions for QualType.
///
-/// These specializations provide the Matcher<Type>->Matcher<QualType>
+/// This specialization provides the Matcher<Type>->Matcher<QualType>
/// conversion that the static API does.
-template <> inline bool DynTypedMatcher::canConvertTo<QualType>() const {
- const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind();
- return SourceKind.isSame(
- ast_type_traits::ASTNodeKind::getFromNodeKind<Type>()) ||
- SourceKind.isSame(
- ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>());
-}
-
template <>
inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const {
assert(canConvertTo<QualType>());
@@ -470,7 +518,7 @@ bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
for (IteratorT I = Start; I != End; ++I) {
BoundNodesTreeBuilder Result(*Builder);
if (Matcher.matches(*I, Finder, &Result)) {
- *Builder = Result;
+ *Builder = std::move(Result);
return true;
}
}
@@ -486,7 +534,7 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
for (IteratorT I = Start; I != End; ++I) {
BoundNodesTreeBuilder Result(*Builder);
if (Matcher.matches(**I, Finder, &Result)) {
- *Builder = Result;
+ *Builder = std::move(Result);
return true;
}
}
@@ -549,6 +597,33 @@ private:
std::string Name;
};
+/// \brief Matches named declarations with a specific name.
+///
+/// See \c hasName() in ASTMatchers.h for details.
+class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
+ public:
+ explicit HasNameMatcher(StringRef Name);
+
+ bool matchesNode(const NamedDecl &Node) const override;
+
+ private:
+ /// \brief Unqualified match routine.
+ ///
+ /// It is much faster than the full match, but it only works for unqualified
+ /// matches.
+ bool matchesNodeUnqualified(const NamedDecl &Node) const;
+
+ /// \brief 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 matchesNodeFull(const NamedDecl &Node) const;
+
+ const bool UseUnqualifiedMatch;
+ const std::string Name;
+};
+
/// \brief Matches declarations for QualType and CallExpr.
///
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
@@ -973,46 +1048,16 @@ private:
///
/// This is useful when a matcher syntactically requires a child matcher,
/// but the context doesn't care. See for example: anything().
-///
-/// FIXME: Alternatively we could also create a IsAMatcher or something
-/// that checks that a dyn_cast is possible. This is purely needed for the
-/// difference between calling for example:
-/// record()
-/// and
-/// record(SomeMatcher)
-/// In the second case we need the correct type we were dyn_cast'ed to in order
-/// to get the right type for the inner matcher. In the first case we don't need
-/// that, but we use the type conversion anyway and insert a TrueMatcher.
-template <typename T>
-class TrueMatcher : public SingleNodeMatcherInterface<T> {
-public:
- bool matchesNode(const T &Node) const override {
- return true;
- }
-};
-
-/// \brief Matcher<T> that wraps an inner Matcher<T> and binds the matched node
-/// to an ID if the inner matcher matches on the node.
-template <typename T>
-class IdMatcher : public MatcherInterface<T> {
-public:
- /// \brief Creates an IdMatcher that binds to 'ID' if 'InnerMatcher' matches
- /// the node.
- IdMatcher(StringRef ID, const Matcher<T> &InnerMatcher)
- : ID(ID), InnerMatcher(InnerMatcher) {}
+class TrueMatcher {
+ public:
+ typedef AllNodeBaseTypes ReturnTypes;
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- bool Result = InnerMatcher.matches(Node, Finder, Builder);
- if (Result) {
- Builder->setBinding(ID, &Node);
- }
- return Result;
+ template <typename T>
+ operator Matcher<T>() const {
+ return DynTypedMatcher::trueMatcher(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>())
+ .template unconditionalConvertTo<T>();
}
-
-private:
- const std::string ID;
- const Matcher<T> InnerMatcher;
};
/// \brief A Matcher that allows binding the node it matches to an id.
@@ -1031,7 +1076,17 @@ public:
/// The returned matcher is equivalent to this matcher, but will
/// bind the matched node on a match.
Matcher<T> bind(StringRef ID) const {
- return Matcher<T>(new IdMatcher<T>(ID, *this));
+ return DynTypedMatcher(*this)
+ .tryBind(ID)
+ ->template unconditionalConvertTo<T>();
+ }
+
+ /// \brief 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;
}
};
@@ -1089,36 +1144,11 @@ private:
/// \brief VariadicOperatorMatcher related types.
/// @{
-/// \brief Function signature for any variadic operator. It takes the inner
-/// matchers as an array of DynTypedMatcher.
-typedef bool (*VariadicOperatorFunction)(
- const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
-
-/// \brief \c MatcherInterface<T> implementation for an variadic operator.
-template <typename T>
-class VariadicOperatorMatcherInterface : public MatcherInterface<T> {
-public:
- VariadicOperatorMatcherInterface(VariadicOperatorFunction Func,
- std::vector<DynTypedMatcher> InnerMatchers)
- : Func(Func), InnerMatchers(std::move(InnerMatchers)) {}
-
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return Func(ast_type_traits::DynTypedNode::create(Node), Finder, Builder,
- InnerMatchers);
- }
-
-private:
- const VariadicOperatorFunction Func;
- const std::vector<DynTypedMatcher> InnerMatchers;
-};
-
/// \brief "No argument" placeholder to use as template paratemers.
struct VariadicOperatorNoArg {};
-/// \brief Polymorphic matcher object that uses a \c VariadicOperatorFunction
-/// operator.
+/// \brief 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
@@ -1133,7 +1163,8 @@ template <typename P1, typename P2 = VariadicOperatorNoArg,
typename P9 = VariadicOperatorNoArg>
class VariadicOperatorMatcher {
public:
- VariadicOperatorMatcher(VariadicOperatorFunction Func, const P1 &Param1,
+ VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
+ const P1 &Param1,
const P2 &Param2 = VariadicOperatorNoArg(),
const P3 &Param3 = VariadicOperatorNoArg(),
const P4 &Param4 = VariadicOperatorNoArg(),
@@ -1142,7 +1173,7 @@ public:
const P7 &Param7 = VariadicOperatorNoArg(),
const P8 &Param8 = VariadicOperatorNoArg(),
const P9 &Param9 = VariadicOperatorNoArg())
- : Func(Func), Param1(Param1), Param2(Param2), Param3(Param3),
+ : Op(Op), Param1(Param1), Param2(Param2), Param3(Param3),
Param4(Param4), Param5(Param5), Param6(Param6), Param7(Param7),
Param8(Param8), Param9(Param9) {}
@@ -1157,8 +1188,8 @@ public:
addMatcher<T>(Param7, Matchers);
addMatcher<T>(Param8, Matchers);
addMatcher<T>(Param9, Matchers);
- return Matcher<T>(
- new VariadicOperatorMatcherInterface<T>(Func, std::move(Matchers)));
+ return DynTypedMatcher::constructVariadic(Op, std::move(Matchers))
+ .template unconditionalConvertTo<T>();
}
private:
@@ -1173,7 +1204,7 @@ private:
static void addMatcher(VariadicOperatorNoArg,
std::vector<DynTypedMatcher> &Matchers) {}
- const VariadicOperatorFunction Func;
+ const DynTypedMatcher::VariadicOperator Op;
const P1 Param1;
const P2 Param2;
const P3 Param3;
@@ -1191,7 +1222,7 @@ private:
/// It supports 1-9 argument overloaded operator(). More can be added if needed.
template <unsigned MinCount, unsigned MaxCount>
struct VariadicOperatorMatcherFunc {
- VariadicOperatorFunction Func;
+ DynTypedMatcher::VariadicOperator Op;
template <unsigned Count, typename T>
struct EnableIfValidArity
@@ -1200,30 +1231,29 @@ struct VariadicOperatorMatcherFunc {
template <typename M1>
typename EnableIfValidArity<1, VariadicOperatorMatcher<M1> >::type
operator()(const M1 &P1) const {
- return VariadicOperatorMatcher<M1>(Func, P1);
+ return VariadicOperatorMatcher<M1>(Op, P1);
}
template <typename M1, typename M2>
typename EnableIfValidArity<2, VariadicOperatorMatcher<M1, M2> >::type
operator()(const M1 &P1, const M2 &P2) const {
- return VariadicOperatorMatcher<M1, M2>(Func, P1, P2);
+ return VariadicOperatorMatcher<M1, M2>(Op, P1, P2);
}
template <typename M1, typename M2, typename M3>
typename EnableIfValidArity<3, VariadicOperatorMatcher<M1, M2, M3> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3) const {
- return VariadicOperatorMatcher<M1, M2, M3>(Func, P1, P2, P3);
+ return VariadicOperatorMatcher<M1, M2, M3>(Op, P1, P2, P3);
}
template <typename M1, typename M2, typename M3, typename M4>
typename EnableIfValidArity<4, VariadicOperatorMatcher<M1, M2, M3, M4> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) const {
- return VariadicOperatorMatcher<M1, M2, M3, M4>(Func, P1, P2, P3, P4);
+ return VariadicOperatorMatcher<M1, M2, M3, M4>(Op, P1, P2, P3, P4);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5>
typename EnableIfValidArity<
5, VariadicOperatorMatcher<M1, M2, M3, M4, M5> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5) const {
- return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Func, P1, P2, P3, P4,
- P5);
+ return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Op, P1, P2, P3, P4, P5);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6>
@@ -1232,7 +1262,7 @@ struct VariadicOperatorMatcherFunc {
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5, const M6 &P6) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6>(
- Func, P1, P2, P3, P4, P5, P6);
+ Op, P1, P2, P3, P4, P5, P6);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6, typename M7>
@@ -1241,7 +1271,7 @@ struct VariadicOperatorMatcherFunc {
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5, const M6 &P6, const M7 &P7) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7>(
- Func, P1, P2, P3, P4, P5, P6, P7);
+ Op, P1, P2, P3, P4, P5, P6, P7);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6, typename M7, typename M8>
@@ -1250,7 +1280,7 @@ struct VariadicOperatorMatcherFunc {
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8>(
- Func, P1, P2, P3, P4, P5, P6, P7, P8);
+ Op, P1, P2, P3, P4, P5, P6, P7, P8);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6, typename M7, typename M8, typename M9>
@@ -1260,55 +1290,40 @@ struct VariadicOperatorMatcherFunc {
const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8,
const M9 &P9) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9>(
- Func, P1, P2, P3, P4, P5, P6, P7, P8, P9);
+ Op, P1, P2, P3, P4, P5, P6, P7, P8, P9);
}
};
/// @}
-/// \brief Matches nodes that do not match the provided matcher.
-///
-/// Uses the variadic matcher interface, but fails if InnerMatchers.size()!=1.
-bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
- ArrayRef<DynTypedMatcher> InnerMatchers);
-
-/// \brief Matches nodes for which all provided matchers match.
-bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder,
- ArrayRef<DynTypedMatcher> InnerMatchers);
-
-/// \brief Matches nodes for which at least one of the provided matchers
-/// matches, but doesn't stop at the first match.
-bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder,
- ArrayRef<DynTypedMatcher> InnerMatchers);
-
-/// \brief Matches nodes for which at least one of the provided matchers
-/// matches.
-bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder,
- ArrayRef<DynTypedMatcher> InnerMatchers);
-
template <typename T>
inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const {
- return Matcher<T>(new VariadicOperatorMatcherInterface<T>(
- AllOfVariadicOperator, llvm::makeArrayRef(*this)));
+ return Matcher<T>(*this);
}
/// \brief Creates a Matcher<T> that matches if all inner matchers match.
template<typename T>
BindableMatcher<T> makeAllOfComposite(
ArrayRef<const Matcher<T> *> InnerMatchers) {
- std::vector<DynTypedMatcher> DynMatchers;
- for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
- DynMatchers.push_back(*InnerMatchers[i]);
+ // For the size() == 0 case, we return a "true" matcher.
+ if (InnerMatchers.size() == 0) {
+ 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]);
}
- return BindableMatcher<T>(new VariadicOperatorMatcherInterface<T>(
- AllOfVariadicOperator, std::move(DynMatchers)));
+
+ std::vector<DynTypedMatcher> DynMatchers;
+ DynMatchers.reserve(InnerMatchers.size());
+ for (const auto *InnerMatcher : InnerMatchers) {
+ DynMatchers.push_back(*InnerMatcher);
+ }
+ return BindableMatcher<T>(
+ DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
+ std::move(DynMatchers))
+ .template unconditionalConvertTo<T>());
}
/// \brief Creates a Matcher<T> that matches if
@@ -1320,8 +1335,8 @@ BindableMatcher<T> makeAllOfComposite(
template<typename T, typename InnerT>
BindableMatcher<T> makeDynCastAllOfComposite(
ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
- return BindableMatcher<T>(DynTypedMatcher(makeAllOfComposite(InnerMatchers))
- .unconditionalConvertTo<T>());
+ return BindableMatcher<T>(
+ makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
}
/// \brief Matches nodes of type T that have at least one descendant node of
@@ -1606,6 +1621,23 @@ private:
const Matcher<InnerTBase> InnerMatcher;
};
+/// \brief 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.
@@ -1627,7 +1659,7 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
inline ArrayRef<TemplateArgument>
getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
- return ArrayRef<TemplateArgument>(T.getArgs(), T.getNumArgs());
+ return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
}
struct NotEqualsBoundNodePredicate {
@@ -1642,4 +1674,4 @@ struct NotEqualsBoundNodePredicate {
} // end namespace ast_matchers
} // end namespace clang
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
+#endif
diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h
index 563372a..b7888be 100644
--- a/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -34,8 +34,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
+
+/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) {
+/// defines a zero parameter function named DefineMatcher() that returns a
+/// ReturnType object.
+#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \
+ inline ReturnType DefineMatcher##_getInstance(); \
+ inline ReturnType DefineMatcher() { \
+ return internal::MemoizedMatcher< \
+ ReturnType, DefineMatcher##_getInstance>::getInstance(); \
+ } \
+ inline ReturnType DefineMatcher##_getInstance()
/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
/// defines a single-parameter function named DefineMatcher() that returns a
@@ -352,4 +363,4 @@
internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc; \
AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+#endif
diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
index 82a14f1..ef93ac5 100644
--- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h
+++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -12,8 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "clang/Basic/LLVM.h"
diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
index 4045f57..bd006b6 100644
--- a/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -31,8 +31,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
#include "clang/ASTMatchers/Dynamic/Registry.h"
@@ -63,17 +63,6 @@ public:
public:
virtual ~Sema();
- /// \brief Lookup a value by name.
- ///
- /// This can be used in the Sema layer to declare known constants or to
- /// allow to split an expression in pieces.
- ///
- /// \param Name The name of the value to lookup.
- ///
- /// \return The named value. It could be any type that VariantValue
- /// supports. An empty value means that the name is not recognized.
- virtual VariantValue getNamedValue(StringRef Name);
-
/// \brief Process a matcher expression.
///
/// All the arguments passed here have already been processed.
@@ -105,6 +94,29 @@ public:
/// found.
virtual llvm::Optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName) = 0;
+
+ /// \brief Compute the list of completion types for \p Context.
+ ///
+ /// Each element of \p Context represents a matcher invocation, going from
+ /// outermost to innermost. Elements are pairs consisting of a reference to
+ /// the matcher constructor and the index of the next element in the
+ /// argument list of that matcher (or for the last element, the index of
+ /// the completion point in the argument list). An empty list requests
+ /// completion for the root matcher.
+ virtual std::vector<ArgKind> getAcceptedCompletionTypes(
+ llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
+
+ /// \brief Compute the list of completions that match any of
+ /// \p AcceptedTypes.
+ ///
+ /// \param AcceptedTypes All types accepted for this completion.
+ ///
+ /// \return All completions for the specified types.
+ /// Completions should be valid when used in \c lookupMatcherCtor().
+ /// The matcher constructed from the return of \c lookupMatcherCtor()
+ /// should be convertible to some type in \p AcceptedTypes.
+ virtual std::vector<MatcherCompletion>
+ getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes);
};
/// \brief Sema implementation that uses the matcher registry to process the
@@ -121,58 +133,91 @@ public:
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) override;
+
+ std::vector<ArgKind> getAcceptedCompletionTypes(
+ llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) override;
+
+ std::vector<MatcherCompletion>
+ getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override;
};
- /// \brief Parse a matcher expression, creating matchers from the registry.
- ///
- /// This overload creates matchers calling directly into the registry. If the
- /// caller needs more control over how the matchers are created, then it can
- /// use the overload below that takes a Sema.
- ///
- /// \param MatcherCode The matcher expression to parse.
- ///
- /// \return The matcher object constructed, or an empty Optional if an error
- /// occurred.
- /// In that case, \c Error will contain a description of the error.
- /// The caller takes ownership of the DynTypedMatcher object returned.
- static llvm::Optional<DynTypedMatcher>
- parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error);
+ typedef llvm::StringMap<VariantValue> NamedValueMap;
/// \brief Parse a matcher expression.
///
/// \param MatcherCode The matcher expression to parse.
///
/// \param S The Sema instance that will help the parser
- /// construct the matchers.
+ /// construct the matchers. If null, it uses the default registry.
+ ///
+ /// \param NamedValues A map of precomputed named values. This provides
+ /// the dictionary for the <NamedValue> rule of the grammar.
+ /// If null, it is ignored.
+ ///
/// \return The matcher object constructed by the processor, or an empty
/// Optional if an error occurred. In that case, \c Error will contain a
/// description of the error.
/// The caller takes ownership of the DynTypedMatcher object returned.
static llvm::Optional<DynTypedMatcher>
- parseMatcherExpression(StringRef MatcherCode, Sema *S, Diagnostics *Error);
-
- /// \brief Parse an expression, creating matchers from the registry.
- ///
- /// Parses any expression supported by this parser. In general, the
- /// \c parseMatcherExpression function is a better approach to get a matcher
- /// object.
- static bool parseExpression(StringRef Code, VariantValue *Value,
- Diagnostics *Error);
+ parseMatcherExpression(StringRef MatcherCode, Sema *S,
+ const NamedValueMap *NamedValues,
+ Diagnostics *Error);
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Sema *S,
+ Diagnostics *Error) {
+ return parseMatcherExpression(MatcherCode, S, nullptr, Error);
+ }
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error) {
+ return parseMatcherExpression(MatcherCode, nullptr, Error);
+ }
/// \brief Parse an expression.
///
/// Parses any expression supported by this parser. In general, the
/// \c parseMatcherExpression function is a better approach to get a matcher
/// object.
+ ///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers. If null, it uses the default registry.
+ ///
+ /// \param NamedValues A map of precomputed named values. This provides
+ /// the dictionary for the <NamedValue> rule of the grammar.
+ /// If null, it is ignored.
static bool parseExpression(StringRef Code, Sema *S,
+ const NamedValueMap *NamedValues,
VariantValue *Value, Diagnostics *Error);
+ static bool parseExpression(StringRef Code, Sema *S,
+ VariantValue *Value, Diagnostics *Error) {
+ return parseExpression(Code, S, nullptr, Value, Error);
+ }
+ static bool parseExpression(StringRef Code, VariantValue *Value,
+ Diagnostics *Error) {
+ return parseExpression(Code, nullptr, Value, Error);
+ }
/// \brief Complete an expression at the given offset.
///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers. If null, it uses the default registry.
+ ///
+ /// \param NamedValues A map of precomputed named values. This provides
+ /// the dictionary for the <NamedValue> rule of the grammar.
+ /// If null, it is ignored.
+ ///
/// \return The list of completions, which may be empty if there are no
/// available completions or if an error occurred.
static std::vector<MatcherCompletion>
- completeExpression(StringRef Code, unsigned CompletionOffset);
+ completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
+ const NamedValueMap *NamedValues);
+ static std::vector<MatcherCompletion>
+ completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S) {
+ return completeExpression(Code, CompletionOffset, S, nullptr);
+ }
+ static std::vector<MatcherCompletion>
+ completeExpression(StringRef Code, unsigned CompletionOffset) {
+ return completeExpression(Code, CompletionOffset, nullptr);
+ }
private:
class CodeTokenizer;
@@ -180,6 +225,7 @@ private:
struct TokenInfo;
Parser(CodeTokenizer *Tokenizer, Sema *S,
+ const NamedValueMap *NamedValues,
Diagnostics *Error);
bool parseExpressionImpl(VariantValue *Value);
@@ -187,12 +233,16 @@ private:
VariantValue *Value);
bool parseIdentifierPrefixImpl(VariantValue *Value);
- void addCompletion(const TokenInfo &CompToken, StringRef TypedText,
- StringRef Decl);
+ void addCompletion(const TokenInfo &CompToken,
+ const MatcherCompletion &Completion);
void addExpressionCompletions();
+ std::vector<MatcherCompletion>
+ getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes);
+
CodeTokenizer *const Tokenizer;
Sema *const S;
+ const NamedValueMap *const NamedValues;
Diagnostics *const Error;
typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy;
diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h
index faa9254..ad24a8d 100644
--- a/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -14,8 +14,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
@@ -36,8 +36,10 @@ typedef const internal::MatcherDescriptor *MatcherCtor;
struct MatcherCompletion {
MatcherCompletion() {}
- MatcherCompletion(StringRef TypedText, StringRef MatcherDecl)
- : TypedText(TypedText), MatcherDecl(MatcherDecl) {}
+ MatcherCompletion(StringRef TypedText, StringRef MatcherDecl,
+ unsigned Specificity)
+ : TypedText(TypedText), MatcherDecl(MatcherDecl),
+ Specificity(Specificity) {}
/// \brief The text to type to select this matcher.
std::string TypedText;
@@ -45,6 +47,13 @@ struct MatcherCompletion {
/// \brief The "declaration" of the matcher, with type information.
std::string MatcherDecl;
+ /// \brief Value corresponding to the "specificity" of the converted matcher.
+ ///
+ /// Zero specificity indicates that this conversion would produce a trivial
+ /// matcher that will either always or never match.
+ /// Such matchers are excluded from code completion results.
+ unsigned Specificity;
+
bool operator==(const MatcherCompletion &Other) const {
return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl;
}
@@ -58,28 +67,28 @@ public:
/// constructor, or Optional<MatcherCtor>() if not found.
static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName);
- /// \brief Compute the list of completions for \p Context.
+ /// \brief Compute the list of completion types for \p Context.
///
/// Each element of \p Context represents a matcher invocation, going from
- /// outermost to innermost. Elements are pairs consisting of a reference to the
- /// matcher constructor and the index of the next element in the argument list
- /// of that matcher (or for the last element, the index of the completion
- /// point in the argument list). An empty list requests completion for the
- /// root matcher.
+ /// outermost to innermost. Elements are pairs consisting of a reference to
+ /// the matcher constructor and the index of the next element in the
+ /// argument list of that matcher (or for the last element, the index of
+ /// the completion point in the argument list). An empty list requests
+ /// completion for the root matcher.
+ static std::vector<ArgKind> getAcceptedCompletionTypes(
+ llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
+
+ /// \brief Compute the list of completions that match any of
+ /// \p AcceptedTypes.
///
- /// The completions are ordered first by decreasing relevance, then
- /// alphabetically. Relevance is determined by how closely the matcher's
- /// type matches that of the context. For example, if the innermost matcher
- /// takes a FunctionDecl matcher, the FunctionDecl matchers are returned
- /// first, followed by the ValueDecl matchers, then NamedDecl, then Decl, then
- /// polymorphic matchers.
+ /// \param AcceptedTypes All types accepted for this completion.
///
- /// Matchers which are technically convertible to the innermost context but
- /// which would match either all or no nodes are excluded. For example,
- /// namedDecl and varDecl are excluded in a FunctionDecl context, because
- /// those matchers would match respectively all or no nodes in such a context.
+ /// \return All completions for the specified types.
+ /// Completions should be valid when used in \c lookupMatcherCtor().
+ /// The matcher constructed from the return of \c lookupMatcherCtor()
+ /// should be convertible to some type in \p AcceptedTypes.
static std::vector<MatcherCompletion>
- getCompletions(ArrayRef<std::pair<MatcherCtor, unsigned> > Context);
+ getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes);
/// \brief Construct a matcher from the registry.
///
diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
index b25267b..a9bd3d5 100644
--- a/include/clang/ASTMatchers/Dynamic/VariantValue.h
+++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -14,8 +14,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
@@ -29,6 +29,51 @@ namespace clang {
namespace ast_matchers {
namespace dynamic {
+/// \brief Kind identifier.
+///
+/// It supports all types that VariantValue can contain.
+class ArgKind {
+ public:
+ enum Kind {
+ AK_Matcher,
+ AK_Unsigned,
+ AK_String
+ };
+ /// \brief Constructor for non-matcher types.
+ ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
+
+ /// \brief Constructor for matcher types.
+ ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
+ : K(AK_Matcher), MatcherKind(MatcherKind) {}
+
+ Kind getArgKind() const { return K; }
+ ast_type_traits::ASTNodeKind getMatcherKind() const {
+ assert(K == AK_Matcher);
+ return MatcherKind;
+ }
+
+ /// \brief Determines if this type can be converted to \p To.
+ ///
+ /// \param To the requested destination type.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion.
+ bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
+
+ bool operator<(const ArgKind &Other) const {
+ if (K == AK_Matcher && Other.K == AK_Matcher)
+ return MatcherKind < Other.MatcherKind;
+ return K < Other.K;
+ }
+
+ /// \brief String representation of the type.
+ std::string asString() const;
+
+private:
+ Kind K;
+ ast_type_traits::ASTNodeKind MatcherKind;
+};
+
using ast_matchers::internal::DynTypedMatcher;
/// \brief A variant matcher object.
@@ -48,13 +93,28 @@ class VariantMatcher {
/// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
class MatcherOps {
public:
- virtual ~MatcherOps();
- virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
- bool &IsExactMatch) const = 0;
- virtual void constructFrom(const DynTypedMatcher &Matcher) = 0;
- virtual void constructVariadicOperator(
- ast_matchers::internal::VariadicOperatorFunction Func,
- ArrayRef<VariantMatcher> InnerMatchers) = 0;
+ MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
+
+ bool canConstructFrom(const DynTypedMatcher &Matcher,
+ bool &IsExactMatch) const;
+
+ /// \brief Convert \p Matcher the destination type and return it as a new
+ /// DynTypedMatcher.
+ virtual DynTypedMatcher
+ convertMatcher(const DynTypedMatcher &Matcher) const = 0;
+
+ /// \brief Constructs a variadic typed matcher from \p InnerMatchers.
+ /// Will try to convert each inner matcher to the destination type and
+ /// return llvm::None if it fails to do so.
+ llvm::Optional<DynTypedMatcher>
+ constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
+ ArrayRef<VariantMatcher> InnerMatchers) const;
+
+ protected:
+ ~MatcherOps() {}
+
+ private:
+ ast_type_traits::ASTNodeKind NodeKind;
};
/// \brief Payload interface to be specialized by each matcher type.
@@ -65,7 +125,10 @@ class VariantMatcher {
virtual ~Payload();
virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
virtual std::string getTypeAsString() const = 0;
- virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
+ virtual llvm::Optional<DynTypedMatcher>
+ getTypedMatcher(const MatcherOps &Ops) const = 0;
+ virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
+ unsigned *Specificity) const = 0;
};
public:
@@ -84,9 +147,9 @@ public:
/// \brief Creates a 'variadic' operator matcher.
///
/// It will bind to the appropriate type on getTypedMatcher<T>().
- static VariantMatcher VariadicOperatorMatcher(
- ast_matchers::internal::VariadicOperatorFunction Func,
- std::vector<VariantMatcher> Args);
+ static VariantMatcher
+ VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
+ std::vector<VariantMatcher> Args);
/// \brief Makes the matcher the "null" matcher.
void reset();
@@ -111,9 +174,21 @@ public:
/// that can, the result would be ambiguous and false is returned.
template <class T>
bool hasTypedMatcher() const {
- TypedMatcherOps<T> Ops;
- if (Value) Value->makeTypedMatcher(Ops);
- return Ops.hasMatcher();
+ if (!Value) return false;
+ return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue();
+ }
+
+ /// \brief Determines if the contained matcher can be converted to \p Kind.
+ ///
+ /// \param Kind the requested destination type.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion.
+ bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
+ unsigned *Specificity) const {
+ if (Value)
+ return Value->isConvertibleTo(Kind, Specificity);
+ return false;
}
/// \brief Return this matcher as a \c Matcher<T>.
@@ -122,10 +197,9 @@ public:
/// Asserts that \c hasTypedMatcher<T>() is true.
template <class T>
ast_matchers::internal::Matcher<T> getTypedMatcher() const {
- TypedMatcherOps<T> Ops;
- Value->makeTypedMatcher(Ops);
- assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false");
- return Ops.matcher();
+ assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
+ return Value->getTypedMatcher(TypedMatcherOps<T>())
+ ->template convertTo<T>();
}
/// \brief String representation of the type of the value.
@@ -137,51 +211,25 @@ public:
private:
explicit VariantMatcher(Payload *Value) : Value(Value) {}
+ template <typename T> struct TypedMatcherOps;
+
class SinglePayload;
class PolymorphicPayload;
class VariadicOpPayload;
- template <typename T>
- class TypedMatcherOps : public MatcherOps {
- public:
- typedef ast_matchers::internal::Matcher<T> MatcherT;
-
- virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
- bool &IsExactMatch) const {
- IsExactMatch = Matcher.getSupportedKind().isSame(
- ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
- return Matcher.canConvertTo<T>();
- }
-
- virtual void constructFrom(const DynTypedMatcher& Matcher) {
- Out.reset(new MatcherT(Matcher.convertTo<T>()));
- }
-
- virtual void constructVariadicOperator(
- ast_matchers::internal::VariadicOperatorFunction Func,
- ArrayRef<VariantMatcher> InnerMatchers) {
- std::vector<DynTypedMatcher> DynMatchers;
- for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
- // Abort if any of the inner matchers can't be converted to
- // Matcher<T>.
- if (!InnerMatchers[i].hasTypedMatcher<T>()) {
- return;
- }
- DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>());
- }
- Out.reset(new MatcherT(
- new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
- Func, DynMatchers)));
- }
-
- bool hasMatcher() const { return Out.get() != nullptr; }
- const MatcherT &matcher() const { return *Out; }
+ IntrusiveRefCntPtr<const Payload> Value;
+};
- private:
- std::unique_ptr<MatcherT> Out;
- };
+template <typename T>
+struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
+ TypedMatcherOps()
+ : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {}
+ typedef ast_matchers::internal::Matcher<T> MatcherT;
- IntrusiveRefCntPtr<const Payload> Value;
+ DynTypedMatcher
+ convertMatcher(const DynTypedMatcher &Matcher) const override {
+ return DynTypedMatcher(Matcher.convertTo<T>());
+ }
};
/// \brief Variant value class.
@@ -228,6 +276,24 @@ public:
const VariantMatcher &getMatcher() const;
void setMatcher(const VariantMatcher &Matcher);
+ /// \brief Determines if the contained value can be converted to \p Kind.
+ ///
+ /// \param Kind the requested destination type.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion.
+ bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
+
+ /// \brief Determines if the contained value can be converted to any kind
+ /// in \p Kinds.
+ ///
+ /// \param Kinds the requested destination types.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion. It is the maximum specificity of all the possible
+ /// conversions.
+ bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
+
/// \brief String representation of the type of the value.
std::string getTypeAsString() const;
OpenPOWER on IntegriCloud