2017-11-02 07:09:49 +08:00
|
|
|
//===- ASTMatchersInternal.cpp - Structural query framework ---------------===//
|
2012-07-06 13:48:52 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2012-07-06 13:48:52 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Implements the base layer of the matcher framework.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/ASTMatchers/ASTMatchersInternal.h"
|
2017-11-02 07:09:49 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/ASTTypeTraits.h"
|
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/AST/DeclTemplate.h"
|
|
|
|
#include "clang/AST/PrettyPrinter.h"
|
|
|
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
|
|
|
#include "clang/Basic/LLVM.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
|
|
|
#include "llvm/ADT/None.h"
|
2014-10-15 22:58:46 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2016-02-23 05:13:02 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2017-11-02 07:09:49 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2014-10-10 03:28:18 +08:00
|
|
|
#include "llvm/Support/ManagedStatic.h"
|
2017-11-02 07:09:49 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <string>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2012-07-06 13:48:52 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace ast_matchers {
|
2018-03-29 09:15:05 +08:00
|
|
|
|
|
|
|
AST_MATCHER_P(ObjCMessageExpr, hasAnySelectorMatcher, std::vector<std::string>,
|
|
|
|
Matches) {
|
|
|
|
std::string SelString = Node.getSelector().getAsString();
|
|
|
|
for (const std::string &S : Matches)
|
|
|
|
if (S == SelString)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-07-06 13:48:52 +08:00
|
|
|
namespace internal {
|
|
|
|
|
2015-07-15 00:50:14 +08:00
|
|
|
bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
|
2014-11-20 23:45:53 +08:00
|
|
|
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
2015-07-15 00:50:14 +08:00
|
|
|
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
|
2014-11-20 23:45:53 +08:00
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
2015-07-15 00:50:14 +08:00
|
|
|
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
|
2014-11-20 23:45:53 +08:00
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
2015-07-15 00:50:14 +08:00
|
|
|
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
|
2014-11-20 23:45:53 +08:00
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
Completely revamp node binding for AST matchers.
This is in preparation for the backwards references to bound
nodes, which will expose a lot more about how matches occur. Main
changes:
- instead of building the tree of bound nodes, we build a "set" of bound
nodes and explode all possible match combinations while running
through the matchers; this will allow us to also implement matchers
that filter down the current set of matches, like "equalsBoundNode"
- take the set of bound nodes at the start of the match into
consideration when doing memoization; as part of that, reevaluated
that memoization gives us benefits that are large enough (it still
does - the effect on common match patterns is up to an order of
magnitude)
- reset the bound nodes when a node does not match, thus never leaking
information from partial sub-matcher matches for failing matchers
Effects:
- we can now correctly "explode" combinatorial matches, for example:
allOf(forEachDescendant(...bind("a")),
forEachDescendant(...bind("b"))) will now trigger matches for all
combinations of matching "a" and "b"s.
- we now never expose bound nodes from partial matches in matchers that
did not match in the end - this fixes a long-standing issue
FIXMEs:
- rename BoundNodesTreeBuilder to BoundNodesBuilder or
BoundNodesSetBuilder, as we don't build a tree any more; this is out
of scope for this change, though
- we're seeing some performance regressions (around 10%), but I expect
some performance tuning will get that back, and it's easily worth
the increase in expressiveness for now
llvm-svn: 184313
2013-06-19 23:42:45 +08:00
|
|
|
void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
|
|
|
|
if (Bindings.empty())
|
|
|
|
Bindings.push_back(BoundNodesMap());
|
2014-10-24 21:29:15 +08:00
|
|
|
for (BoundNodesMap &Binding : Bindings) {
|
|
|
|
ResultVisitor->visitMatch(BoundNodes(Binding));
|
2012-08-29 07:26:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-01 23:08:07 +08:00
|
|
|
namespace {
|
|
|
|
|
2017-11-02 07:09:49 +08:00
|
|
|
using VariadicOperatorFunction = bool (*)(
|
2015-07-15 00:50:14 +08:00
|
|
|
const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
2014-12-01 22:46:14 +08:00
|
|
|
BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
|
|
|
template <VariadicOperatorFunction Func>
|
2014-10-01 23:08:07 +08:00
|
|
|
class VariadicMatcher : public DynMatcherInterface {
|
2014-11-20 23:45:53 +08:00
|
|
|
public:
|
2014-12-01 22:46:14 +08:00
|
|
|
VariadicMatcher(std::vector<DynTypedMatcher> InnerMatchers)
|
|
|
|
: InnerMatchers(std::move(InnerMatchers)) {}
|
2014-10-01 23:08:07 +08:00
|
|
|
|
|
|
|
bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
|
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder) const override {
|
|
|
|
return Func(DynNode, Finder, Builder, InnerMatchers);
|
|
|
|
}
|
|
|
|
|
2014-11-20 23:45:53 +08:00
|
|
|
private:
|
2014-10-01 23:08:07 +08:00
|
|
|
std::vector<DynTypedMatcher> InnerMatchers;
|
|
|
|
};
|
|
|
|
|
|
|
|
class IdDynMatcher : public DynMatcherInterface {
|
2016-07-21 23:06:51 +08:00
|
|
|
public:
|
2014-10-01 23:08:07 +08:00
|
|
|
IdDynMatcher(StringRef ID,
|
2016-07-21 23:06:51 +08:00
|
|
|
IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher)
|
|
|
|
: ID(ID), InnerMatcher(std::move(InnerMatcher)) {}
|
2014-10-01 23:08:07 +08:00
|
|
|
|
|
|
|
bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
|
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder) const override {
|
|
|
|
bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
|
|
|
|
if (Result) Builder->setBinding(ID, DynNode);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2016-07-21 23:06:51 +08:00
|
|
|
private:
|
2014-10-01 23:08:07 +08:00
|
|
|
const std::string ID;
|
|
|
|
const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
|
|
|
|
};
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// A matcher that always returns true.
|
2014-10-10 03:28:18 +08:00
|
|
|
///
|
|
|
|
/// We only ever need one instance of this matcher, so we create a global one
|
|
|
|
/// and reuse it to reduce the overhead of the matcher and increase the chance
|
|
|
|
/// of cache hits.
|
2014-10-24 21:29:21 +08:00
|
|
|
class TrueMatcherImpl : public DynMatcherInterface {
|
|
|
|
public:
|
|
|
|
TrueMatcherImpl() {
|
|
|
|
Retain(); // Reference count will never become zero.
|
|
|
|
}
|
2017-11-02 07:09:49 +08:00
|
|
|
|
2014-10-24 21:29:21 +08:00
|
|
|
bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
|
|
|
|
BoundNodesTreeBuilder *) const override {
|
|
|
|
return true;
|
|
|
|
}
|
2014-10-10 03:28:18 +08:00
|
|
|
};
|
|
|
|
|
2017-11-02 07:09:49 +08:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
|
2014-10-01 23:08:07 +08:00
|
|
|
|
|
|
|
DynTypedMatcher DynTypedMatcher::constructVariadic(
|
2014-11-20 23:45:53 +08:00
|
|
|
DynTypedMatcher::VariadicOperator Op,
|
2015-07-18 00:05:27 +08:00
|
|
|
ast_type_traits::ASTNodeKind SupportedKind,
|
2014-11-17 22:55:49 +08:00
|
|
|
std::vector<DynTypedMatcher> InnerMatchers) {
|
2017-11-02 07:09:49 +08:00
|
|
|
assert(!InnerMatchers.empty() && "Array must not be empty.");
|
2018-10-21 01:53:42 +08:00
|
|
|
assert(llvm::all_of(InnerMatchers,
|
|
|
|
[SupportedKind](const DynTypedMatcher &M) {
|
|
|
|
return M.canConvertTo(SupportedKind);
|
|
|
|
}) &&
|
2015-07-18 00:05:27 +08:00
|
|
|
"InnerMatchers must be convertible to SupportedKind!");
|
2014-10-14 01:38:12 +08:00
|
|
|
|
|
|
|
// We must relax the restrict kind here.
|
|
|
|
// The different operators might deal differently with a mismatch.
|
|
|
|
// Make it the same as SupportedKind, since that is the broadest type we are
|
|
|
|
// allowed to accept.
|
2014-12-01 22:46:14 +08:00
|
|
|
auto RestrictKind = SupportedKind;
|
|
|
|
|
2014-11-20 23:45:53 +08:00
|
|
|
switch (Op) {
|
|
|
|
case VO_AllOf:
|
2014-12-01 22:46:14 +08:00
|
|
|
// In the case of allOf() we must pass all the checks, so making
|
|
|
|
// RestrictKind the most restrictive can save us time. This way we reject
|
|
|
|
// invalid types earlier and we can elide the kind checks inside the
|
|
|
|
// matcher.
|
|
|
|
for (auto &IM : InnerMatchers) {
|
|
|
|
RestrictKind = ast_type_traits::ASTNodeKind::getMostDerivedType(
|
|
|
|
RestrictKind, IM.RestrictKind);
|
|
|
|
}
|
|
|
|
return DynTypedMatcher(
|
|
|
|
SupportedKind, RestrictKind,
|
|
|
|
new VariadicMatcher<AllOfVariadicOperator>(std::move(InnerMatchers)));
|
|
|
|
|
2014-11-20 23:45:53 +08:00
|
|
|
case VO_AnyOf:
|
2014-12-01 22:46:14 +08:00
|
|
|
return DynTypedMatcher(
|
|
|
|
SupportedKind, RestrictKind,
|
|
|
|
new VariadicMatcher<AnyOfVariadicOperator>(std::move(InnerMatchers)));
|
|
|
|
|
2014-11-20 23:45:53 +08:00
|
|
|
case VO_EachOf:
|
2014-12-01 22:46:14 +08:00
|
|
|
return DynTypedMatcher(
|
|
|
|
SupportedKind, RestrictKind,
|
|
|
|
new VariadicMatcher<EachOfVariadicOperator>(std::move(InnerMatchers)));
|
|
|
|
|
2014-11-20 23:45:53 +08:00
|
|
|
case VO_UnaryNot:
|
2014-12-01 22:46:14 +08:00
|
|
|
// FIXME: Implement the Not operator to take a single matcher instead of a
|
|
|
|
// vector.
|
|
|
|
return DynTypedMatcher(
|
|
|
|
SupportedKind, RestrictKind,
|
|
|
|
new VariadicMatcher<NotUnaryOperator>(std::move(InnerMatchers)));
|
2014-11-20 23:45:53 +08:00
|
|
|
}
|
2014-12-01 22:46:14 +08:00
|
|
|
llvm_unreachable("Invalid Op value.");
|
2014-10-01 23:08:07 +08:00
|
|
|
}
|
|
|
|
|
2014-10-10 03:28:18 +08:00
|
|
|
DynTypedMatcher DynTypedMatcher::trueMatcher(
|
|
|
|
ast_type_traits::ASTNodeKind NodeKind) {
|
2014-10-24 21:29:21 +08:00
|
|
|
return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
|
2014-10-10 03:28:18 +08:00
|
|
|
}
|
|
|
|
|
2014-11-25 05:21:09 +08:00
|
|
|
bool DynTypedMatcher::canMatchNodesOfKind(
|
|
|
|
ast_type_traits::ASTNodeKind Kind) const {
|
|
|
|
return RestrictKind.isBaseOf(Kind);
|
|
|
|
}
|
|
|
|
|
2014-10-01 23:08:07 +08:00
|
|
|
DynTypedMatcher DynTypedMatcher::dynCastTo(
|
|
|
|
const ast_type_traits::ASTNodeKind Kind) const {
|
|
|
|
auto Copy = *this;
|
|
|
|
Copy.SupportedKind = Kind;
|
2014-10-06 21:14:30 +08:00
|
|
|
Copy.RestrictKind =
|
|
|
|
ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
|
2014-10-01 23:08:07 +08:00
|
|
|
return Copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
|
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder) const {
|
|
|
|
if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
|
|
|
|
Implementation->dynMatches(DynNode, 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->removeBindings([](const BoundNodesMap &) { return true; });
|
2014-11-25 05:21:09 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DynTypedMatcher::matchesNoKindCheck(
|
|
|
|
const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder) const {
|
|
|
|
assert(RestrictKind.isBaseOf(DynNode.getNodeKind()));
|
|
|
|
if (Implementation->dynMatches(DynNode, 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->removeBindings([](const BoundNodesMap &) { return true; });
|
2014-10-01 23:08:07 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
|
|
|
|
if (!AllowBind) return llvm::None;
|
|
|
|
auto Result = *this;
|
2016-07-21 23:06:51 +08:00
|
|
|
Result.Implementation =
|
|
|
|
new IdDynMatcher(ID, std::move(Result.Implementation));
|
|
|
|
return std::move(Result);
|
2014-10-01 23:08:07 +08:00
|
|
|
}
|
|
|
|
|
2014-09-04 22:13:58 +08:00
|
|
|
bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
|
|
|
|
const auto From = getSupportedKind();
|
|
|
|
auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
|
|
|
|
auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
|
|
|
|
/// Mimic the implicit conversions of Matcher<>.
|
|
|
|
/// - From Matcher<Type> to Matcher<QualType>
|
|
|
|
if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
|
|
|
|
/// - From Matcher<Base> to Matcher<Derived>
|
|
|
|
return From.isBaseOf(To);
|
|
|
|
}
|
|
|
|
|
Completely revamp node binding for AST matchers.
This is in preparation for the backwards references to bound
nodes, which will expose a lot more about how matches occur. Main
changes:
- instead of building the tree of bound nodes, we build a "set" of bound
nodes and explode all possible match combinations while running
through the matchers; this will allow us to also implement matchers
that filter down the current set of matches, like "equalsBoundNode"
- take the set of bound nodes at the start of the match into
consideration when doing memoization; as part of that, reevaluated
that memoization gives us benefits that are large enough (it still
does - the effect on common match patterns is up to an order of
magnitude)
- reset the bound nodes when a node does not match, thus never leaking
information from partial sub-matcher matches for failing matchers
Effects:
- we can now correctly "explode" combinatorial matches, for example:
allOf(forEachDescendant(...bind("a")),
forEachDescendant(...bind("b"))) will now trigger matches for all
combinations of matching "a" and "b"s.
- we now never expose bound nodes from partial matches in matchers that
did not match in the end - this fixes a long-standing issue
FIXMEs:
- rename BoundNodesTreeBuilder to BoundNodesBuilder or
BoundNodesSetBuilder, as we don't build a tree any more; this is out
of scope for this change, though
- we're seeing some performance regressions (around 10%), but I expect
some performance tuning will get that back, and it's easily worth
the increase in expressiveness for now
llvm-svn: 184313
2013-06-19 23:42:45 +08:00
|
|
|
void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
|
2014-10-24 21:29:15 +08:00
|
|
|
Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
|
2012-08-29 07:26:39 +08:00
|
|
|
}
|
|
|
|
|
2015-07-15 00:50:14 +08:00
|
|
|
bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
|
2013-11-22 22:41:48 +08:00
|
|
|
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers) {
|
|
|
|
if (InnerMatchers.size() != 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// The 'unless' matcher will always discard the result:
|
|
|
|
// If the inner matcher doesn't match, unless returns true,
|
|
|
|
// but the inner matcher cannot have bound anything.
|
|
|
|
// If the inner matcher matches, the result is false, and
|
|
|
|
// any possible binding will be discarded.
|
|
|
|
// We still need to hand in all the bound nodes up to this
|
|
|
|
// point so the inner matcher can depend on bound nodes,
|
|
|
|
// and we need to actively discard the bound nodes, otherwise
|
|
|
|
// the inner matcher will reset the bound nodes if it doesn't
|
|
|
|
// match, but this would be inversed by 'unless'.
|
|
|
|
BoundNodesTreeBuilder Discard(*Builder);
|
|
|
|
return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
|
|
|
|
}
|
|
|
|
|
2015-07-15 00:50:14 +08:00
|
|
|
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
|
2013-08-27 23:11:16 +08:00
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
2013-10-29 22:37:15 +08:00
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers) {
|
2013-08-27 23:11:16 +08:00
|
|
|
// allOf leads to one matcher for each alternative in the first
|
|
|
|
// matcher combined with each alternative in the second matcher.
|
|
|
|
// Thus, we can reuse the same Builder.
|
2014-10-24 21:29:15 +08:00
|
|
|
for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
|
2014-12-01 22:46:14 +08:00
|
|
|
if (!InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder))
|
2013-08-27 23:11:16 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-07-15 00:50:14 +08:00
|
|
|
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
|
2013-08-27 23:11:16 +08:00
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
2013-10-29 22:37:15 +08:00
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers) {
|
2013-08-27 23:11:16 +08:00
|
|
|
BoundNodesTreeBuilder Result;
|
|
|
|
bool Matched = false;
|
2014-10-24 21:29:15 +08:00
|
|
|
for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
|
2013-08-27 23:11:16 +08:00
|
|
|
BoundNodesTreeBuilder BuilderInner(*Builder);
|
2014-10-24 21:29:15 +08:00
|
|
|
if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
|
2013-08-27 23:11:16 +08:00
|
|
|
Matched = true;
|
|
|
|
Result.addMatch(BuilderInner);
|
|
|
|
}
|
|
|
|
}
|
2014-08-29 19:22:47 +08:00
|
|
|
*Builder = std::move(Result);
|
2013-08-27 23:11:16 +08:00
|
|
|
return Matched;
|
|
|
|
}
|
|
|
|
|
2015-07-15 00:50:14 +08:00
|
|
|
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
|
2013-08-27 23:11:16 +08:00
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
2013-10-29 22:37:15 +08:00
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers) {
|
2014-10-24 21:29:15 +08:00
|
|
|
for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
|
2013-08-27 23:11:16 +08:00
|
|
|
BoundNodesTreeBuilder Result = *Builder;
|
2014-10-24 21:29:15 +08:00
|
|
|
if (InnerMatcher.matches(DynNode, Finder, &Result)) {
|
2014-08-29 19:22:47 +08:00
|
|
|
*Builder = std::move(Result);
|
2013-08-27 23:11:16 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-03-29 08:51:12 +08:00
|
|
|
inline static
|
|
|
|
std::vector<std::string> vectorFromRefs(ArrayRef<const StringRef *> NameRefs) {
|
2016-02-23 05:13:02 +08:00
|
|
|
std::vector<std::string> Names;
|
|
|
|
for (auto *Name : NameRefs)
|
|
|
|
Names.emplace_back(*Name);
|
2018-03-29 08:51:12 +08:00
|
|
|
return Names;
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs) {
|
|
|
|
std::vector<std::string> Names = vectorFromRefs(NameRefs);
|
|
|
|
return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Names));
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher<ObjCMessageExpr> hasAnySelectorFunc(
|
|
|
|
ArrayRef<const StringRef *> NameRefs) {
|
|
|
|
return hasAnySelectorMatcher(vectorFromRefs(NameRefs));
|
2016-02-23 05:13:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
HasNameMatcher::HasNameMatcher(std::vector<std::string> N)
|
|
|
|
: UseUnqualifiedMatch(std::all_of(
|
|
|
|
N.begin(), N.end(),
|
|
|
|
[](StringRef Name) { return Name.find("::") == Name.npos; })),
|
|
|
|
Names(std::move(N)) {
|
2016-02-23 18:29:04 +08:00
|
|
|
#ifndef NDEBUG
|
2016-02-23 05:13:02 +08:00
|
|
|
for (StringRef Name : Names)
|
|
|
|
assert(!Name.empty());
|
2016-02-23 18:29:04 +08:00
|
|
|
#endif
|
2014-10-15 22:58:46 +08:00
|
|
|
}
|
|
|
|
|
2017-11-02 07:09:49 +08:00
|
|
|
static bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) {
|
2016-02-06 02:29:24 +08:00
|
|
|
StringRef Name = FullName;
|
|
|
|
if (!Name.endswith(Suffix))
|
|
|
|
return false;
|
|
|
|
Name = Name.drop_back(Suffix.size());
|
|
|
|
if (!Name.empty()) {
|
|
|
|
if (!Name.endswith("::"))
|
|
|
|
return false;
|
|
|
|
Name = Name.drop_back(2);
|
2014-10-17 01:50:19 +08:00
|
|
|
}
|
2016-02-06 02:29:24 +08:00
|
|
|
FullName = Name;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-02 07:09:49 +08:00
|
|
|
static StringRef getNodeName(const NamedDecl &Node,
|
|
|
|
llvm::SmallString<128> &Scratch) {
|
2016-02-06 02:29:24 +08:00
|
|
|
// Simple name.
|
|
|
|
if (Node.getIdentifier())
|
2016-02-23 05:13:02 +08:00
|
|
|
return Node.getName();
|
2016-02-06 02:29:24 +08:00
|
|
|
|
2014-10-17 01:50:19 +08:00
|
|
|
if (Node.getDeclName()) {
|
2014-10-15 22:58:46 +08:00
|
|
|
// Name needs to be constructed.
|
2016-02-23 05:13:02 +08:00
|
|
|
Scratch.clear();
|
|
|
|
llvm::raw_svector_ostream OS(Scratch);
|
2014-10-15 22:58:46 +08:00
|
|
|
Node.printName(OS);
|
2016-02-23 05:13:02 +08:00
|
|
|
return OS.str();
|
2014-10-15 22:58:46 +08:00
|
|
|
}
|
2016-02-06 02:29:24 +08:00
|
|
|
|
2016-02-23 05:13:02 +08:00
|
|
|
return "(anonymous)";
|
2014-10-15 22:58:46 +08:00
|
|
|
}
|
|
|
|
|
2017-11-02 07:09:49 +08:00
|
|
|
static StringRef getNodeName(const RecordDecl &Node,
|
|
|
|
llvm::SmallString<128> &Scratch) {
|
2016-02-23 05:13:02 +08:00
|
|
|
if (Node.getIdentifier()) {
|
|
|
|
return Node.getName();
|
|
|
|
}
|
|
|
|
Scratch.clear();
|
|
|
|
return ("(anonymous " + Node.getKindName() + ")").toStringRef(Scratch);
|
|
|
|
}
|
|
|
|
|
2017-11-02 07:09:49 +08:00
|
|
|
static StringRef getNodeName(const NamespaceDecl &Node,
|
|
|
|
llvm::SmallString<128> &Scratch) {
|
2016-02-23 05:13:02 +08:00
|
|
|
return Node.isAnonymousNamespace() ? "(anonymous namespace)" : Node.getName();
|
|
|
|
}
|
|
|
|
|
2017-11-02 07:09:49 +08:00
|
|
|
namespace {
|
2016-02-23 05:13:02 +08:00
|
|
|
|
|
|
|
class PatternSet {
|
|
|
|
public:
|
|
|
|
PatternSet(ArrayRef<std::string> Names) {
|
|
|
|
for (StringRef Name : Names)
|
|
|
|
Patterns.push_back({Name, Name.startswith("::")});
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Consumes the name suffix from each pattern in the set and removes the ones
|
|
|
|
/// that didn't match.
|
|
|
|
/// Return true if there are still any patterns left.
|
|
|
|
bool consumeNameSuffix(StringRef NodeName, bool CanSkip) {
|
|
|
|
for (size_t I = 0; I < Patterns.size();) {
|
2018-03-29 08:51:12 +08:00
|
|
|
if (::clang::ast_matchers::internal::consumeNameSuffix(Patterns[I].P,
|
|
|
|
NodeName) ||
|
2016-02-23 05:13:02 +08:00
|
|
|
CanSkip) {
|
|
|
|
++I;
|
|
|
|
} else {
|
|
|
|
Patterns.erase(Patterns.begin() + I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return !Patterns.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Check if any of the patterns are a match.
|
|
|
|
/// A match will be a pattern that was fully consumed, that also matches the
|
|
|
|
/// 'fully qualified' requirement.
|
|
|
|
bool foundMatch(bool AllowFullyQualified) const {
|
|
|
|
for (auto& P: Patterns)
|
2016-02-23 06:21:58 +08:00
|
|
|
if (P.P.empty() && (AllowFullyQualified || !P.IsFullyQualified))
|
2016-02-23 05:13:02 +08:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
struct Pattern {
|
2016-02-23 06:21:58 +08:00
|
|
|
StringRef P;
|
2016-02-23 05:13:02 +08:00
|
|
|
bool IsFullyQualified;
|
|
|
|
};
|
2017-11-02 07:09:49 +08:00
|
|
|
|
2016-02-23 05:13:02 +08:00
|
|
|
llvm::SmallVector<Pattern, 8> Patterns;
|
|
|
|
};
|
|
|
|
|
2017-11-02 07:09:49 +08:00
|
|
|
} // namespace
|
2016-02-06 02:29:24 +08:00
|
|
|
|
|
|
|
bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
|
|
|
|
assert(UseUnqualifiedMatch);
|
2016-02-23 05:13:02 +08:00
|
|
|
llvm::SmallString<128> Scratch;
|
|
|
|
StringRef NodeName = getNodeName(Node, Scratch);
|
2018-10-21 01:53:42 +08:00
|
|
|
return llvm::any_of(Names, [&](StringRef Name) {
|
2016-02-23 05:13:02 +08:00
|
|
|
return consumeNameSuffix(Name, NodeName) && Name.empty();
|
|
|
|
});
|
2016-02-06 02:29:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool HasNameMatcher::matchesNodeFullFast(const NamedDecl &Node) const {
|
2016-02-23 05:13:02 +08:00
|
|
|
PatternSet Patterns(Names);
|
|
|
|
llvm::SmallString<128> Scratch;
|
|
|
|
|
2016-02-06 02:29:24 +08:00
|
|
|
// This function is copied and adapted from NamedDecl::printQualifiedName()
|
|
|
|
// By matching each part individually we optimize in a couple of ways:
|
|
|
|
// - We can exit early on the first failure.
|
|
|
|
// - We can skip inline/anonymous namespaces without another pass.
|
|
|
|
// - We print one name at a time, reducing the chance of overflowing the
|
|
|
|
// inlined space of the SmallString.
|
|
|
|
|
|
|
|
// First, match the name.
|
2016-02-23 05:13:02 +08:00
|
|
|
if (!Patterns.consumeNameSuffix(getNodeName(Node, Scratch),
|
|
|
|
/*CanSkip=*/false))
|
2016-02-06 02:29:24 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Try to match each declaration context.
|
|
|
|
// We are allowed to skip anonymous and inline namespaces if they don't match.
|
|
|
|
const DeclContext *Ctx = Node.getDeclContext();
|
|
|
|
|
|
|
|
if (Ctx->isFunctionOrMethod())
|
2016-02-23 05:13:02 +08:00
|
|
|
return Patterns.foundMatch(/*AllowFullyQualified=*/false);
|
2016-02-06 02:29:24 +08:00
|
|
|
|
2016-02-23 05:13:02 +08:00
|
|
|
for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) {
|
|
|
|
if (Patterns.foundMatch(/*AllowFullyQualified=*/false))
|
|
|
|
return true;
|
2016-02-06 02:29:24 +08:00
|
|
|
|
2016-02-23 05:13:02 +08:00
|
|
|
if (const auto *ND = dyn_cast<NamespaceDecl>(Ctx)) {
|
|
|
|
// If it matches (or we can skip it), continue.
|
|
|
|
if (Patterns.consumeNameSuffix(getNodeName(*ND, Scratch),
|
|
|
|
/*CanSkip=*/ND->isAnonymousNamespace() ||
|
|
|
|
ND->isInline()))
|
2016-02-06 02:29:24 +08:00
|
|
|
continue;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (const auto *RD = dyn_cast<RecordDecl>(Ctx)) {
|
|
|
|
if (!isa<ClassTemplateSpecializationDecl>(Ctx)) {
|
2016-02-23 05:13:02 +08:00
|
|
|
if (Patterns.consumeNameSuffix(getNodeName(*RD, Scratch),
|
|
|
|
/*CanSkip=*/false))
|
|
|
|
continue;
|
2016-02-06 02:29:24 +08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We don't know how to deal with this DeclContext.
|
|
|
|
// Fallback to the slow version of the code.
|
|
|
|
return matchesNodeFullSlow(Node);
|
|
|
|
}
|
|
|
|
|
2016-02-23 05:13:02 +08:00
|
|
|
return Patterns.foundMatch(/*AllowFullyQualified=*/true);
|
2016-02-06 02:29:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool HasNameMatcher::matchesNodeFullSlow(const NamedDecl &Node) const {
|
|
|
|
const bool SkipUnwrittenCases[] = {false, true};
|
|
|
|
for (bool SkipUnwritten : SkipUnwrittenCases) {
|
|
|
|
llvm::SmallString<128> NodeName = StringRef("::");
|
|
|
|
llvm::raw_svector_ostream OS(NodeName);
|
|
|
|
|
|
|
|
if (SkipUnwritten) {
|
|
|
|
PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
|
|
|
|
Policy.SuppressUnwrittenScope = true;
|
|
|
|
Node.printQualifiedName(OS, Policy);
|
|
|
|
} else {
|
|
|
|
Node.printQualifiedName(OS);
|
|
|
|
}
|
|
|
|
|
|
|
|
const StringRef FullName = OS.str();
|
2014-10-17 01:50:19 +08:00
|
|
|
|
2016-02-23 05:13:02 +08:00
|
|
|
for (const StringRef Pattern : Names) {
|
|
|
|
if (Pattern.startswith("::")) {
|
|
|
|
if (FullName == Pattern)
|
|
|
|
return true;
|
|
|
|
} else if (FullName.endswith(Pattern) &&
|
|
|
|
FullName.drop_back(Pattern.size()).endswith("::")) {
|
2016-02-06 02:29:24 +08:00
|
|
|
return true;
|
2016-02-23 05:13:02 +08:00
|
|
|
}
|
2016-02-06 02:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2014-10-15 22:58:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
|
2016-02-06 02:29:24 +08:00
|
|
|
assert(matchesNodeFullFast(Node) == matchesNodeFullSlow(Node));
|
2014-10-15 22:58:46 +08:00
|
|
|
if (UseUnqualifiedMatch) {
|
2016-02-06 02:29:24 +08:00
|
|
|
assert(matchesNodeUnqualified(Node) == matchesNodeFullFast(Node));
|
2014-10-15 22:58:46 +08:00
|
|
|
return matchesNodeUnqualified(Node);
|
|
|
|
}
|
2016-02-06 02:29:24 +08:00
|
|
|
return matchesNodeFullFast(Node);
|
2014-10-15 22:58:46 +08:00
|
|
|
}
|
|
|
|
|
2012-07-06 13:48:52 +08:00
|
|
|
} // end namespace internal
|
2017-11-16 00:52:12 +08:00
|
|
|
|
2018-07-07 05:36:04 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAutoreleasePoolStmt>
|
|
|
|
autoreleasePoolStmt;
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
|
|
|
|
translationUnitDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
|
|
|
|
typedefNameDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl>
|
|
|
|
typeAliasTemplateDecl;
|
|
|
|
const internal::VariadicAllOfMatcher<Decl> decl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
|
|
|
|
linkageSpecDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
|
|
|
|
namespaceAliasDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> cxxRecordDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl>
|
|
|
|
classTemplateDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl,
|
|
|
|
ClassTemplateSpecializationDecl>
|
|
|
|
classTemplateSpecializationDecl;
|
2018-08-22 19:52:14 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<
|
|
|
|
Decl, ClassTemplatePartialSpecializationDecl>
|
|
|
|
classTemplatePartialSpecializationDecl;
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
|
|
|
|
declaratorDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
|
|
|
|
accessSpecDecl;
|
|
|
|
const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
|
|
|
|
const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
|
|
|
|
const internal::VariadicAllOfMatcher<TemplateName> templateName;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, NonTypeTemplateParmDecl>
|
|
|
|
nonTypeTemplateParmDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl>
|
|
|
|
templateTypeParmDecl;
|
|
|
|
const internal::VariadicAllOfMatcher<QualType> qualType;
|
|
|
|
const internal::VariadicAllOfMatcher<Type> type;
|
|
|
|
const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryExprOrTypeTraitExpr>
|
|
|
|
unaryExprOrTypeTraitExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl>
|
|
|
|
cxxConstructorDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl>
|
|
|
|
cxxDestructorDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl>
|
|
|
|
enumConstantDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
|
|
|
|
cxxConversionDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
|
2018-12-17 20:42:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, IndirectFieldDecl>
|
|
|
|
indirectFieldDecl;
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl>
|
|
|
|
functionTemplateDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
|
|
|
|
const internal::VariadicAllOfMatcher<Stmt> stmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
|
2018-08-13 01:34:36 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedMemberExpr>
|
|
|
|
unresolvedMemberExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDependentScopeMemberExpr>
|
|
|
|
cxxDependentScopeMemberExpr;
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr>
|
|
|
|
cxxMemberCallExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr>
|
|
|
|
objcMessageExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl>
|
|
|
|
objcInterfaceDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl>
|
|
|
|
objcImplementationDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl>
|
|
|
|
objcProtocolDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl>
|
|
|
|
objcCategoryDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl>
|
|
|
|
objcCategoryImplDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl>
|
|
|
|
objcMethodDecl;
|
2018-05-17 06:47:03 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, BlockDecl>
|
|
|
|
blockDecl;
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl> objcIvarDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl>
|
|
|
|
objcPropertyDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt>
|
|
|
|
objcThrowStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt> objcTryStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt>
|
|
|
|
objcCatchStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt>
|
|
|
|
objcFinallyStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups>
|
|
|
|
exprWithCleanups;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStdInitializerListExpr>
|
|
|
|
cxxStdInitializerListExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr>
|
|
|
|
implicitValueInitExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> parenListExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, SubstNonTypeTemplateParmExpr>
|
|
|
|
substNonTypeTemplateParmExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
|
|
|
|
usingDirectiveDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr>
|
|
|
|
unresolvedLookupExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingValueDecl>
|
|
|
|
unresolvedUsingValueDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingTypenameDecl>
|
|
|
|
unresolvedUsingTypenameDecl;
|
2018-11-09 08:41:36 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ConstantExpr> constantExpr;
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr>
|
|
|
|
cxxConstructExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXUnresolvedConstructExpr>
|
|
|
|
cxxUnresolvedConstructExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr>
|
|
|
|
cxxBindTemporaryExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, MaterializeTemporaryExpr>
|
|
|
|
materializeTemporaryExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr>
|
|
|
|
arraySubscriptExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
|
|
|
|
cxxDefaultArgExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
|
|
|
|
cxxOperatorCallExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr;
|
2018-07-28 01:26:11 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCIvarRefExpr> objcIvarRefExpr;
|
2018-12-13 11:35:10 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, BlockExpr> blockExpr;
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt>
|
|
|
|
cxxForRangeStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> addrLabelExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr>
|
|
|
|
cxxBoolLiteral;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral> stringLiteral;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral>
|
|
|
|
characterLiteral;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral>
|
|
|
|
integerLiteral;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral> floatLiteral;
|
2018-08-09 20:18:07 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ImaginaryLiteral> imaginaryLiteral;
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral>
|
|
|
|
userDefinedLiteral;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr>
|
|
|
|
compoundLiteralExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr>
|
|
|
|
cxxNullPtrLiteralExpr;
|
[ASTImporter] Add support for importing ChooseExpr AST nodes.
Summary:
This allows ASTs to be merged when they contain ChooseExpr (the GNU
__builtin_choose_expr construction). This is needed, for example, for
cross-CTU analysis of C code that makes use of __builtin_choose_expr.
The node is already supported in the AST, but it didn't have a matcher
in ASTMatchers. So, this change adds the matcher and adds support to
ASTImporter.
This was originally reviewed and approved in
https://reviews.llvm.org/D58292 and submitted as r354832. It was
reverted in r354839 due to failures on the Windows CI builds.
This version fixes the test failures on Windows, which were caused by
differences in template expansion between versions of clang on different
OSes. The version of clang built with MSVC and running on Windows never
expands the template in the C++ test in ImportExpr.ImportChooseExpr in
clang/unittests/AST/ASTImporter.cpp, but the version on Linux does for
the empty arguments and -fms-compatibility.
So, this version of the patch drops the C++ test for
__builtin_choose_expr, since that version was written to catch
regressions of the logic for isConditionTrue() in the AST import code
for ChooseExpr, and those regressions are also caught by
ASTImporterOptionSpecificTestBase.ImportChooseExpr, which does work on
Windows.
Reviewers: shafik, a_sidorin, martong, aaron.ballman, rnk, a.sidorin
Subscribers: cfe-commits, jdoerfert, rnkovacs, aaron.ballman
Tags: #clang
Differential Revision: https://reviews.llvm.org/D58663
llvm-svn: 354916
2019-02-27 03:26:41 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ChooseExpr> chooseExpr;
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator>
|
|
|
|
binaryOperator;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator> unaryOperator;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator>
|
|
|
|
conditionalOperator;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryConditionalOperator>
|
|
|
|
binaryConditionalOperator;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr>
|
|
|
|
opaqueValueExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl>
|
|
|
|
staticAssertDecl;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr>
|
|
|
|
cxxReinterpretCastExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr>
|
|
|
|
cxxStaticCastExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr>
|
|
|
|
cxxDynamicCastExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr>
|
|
|
|
cxxConstCastExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr>
|
|
|
|
cStyleCastExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr>
|
|
|
|
explicitCastExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr>
|
|
|
|
implicitCastExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr>
|
|
|
|
cxxFunctionalCastExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr>
|
|
|
|
cxxTemporaryObjectExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr>
|
|
|
|
predefinedExpr;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr>
|
|
|
|
designatedInitExpr;
|
|
|
|
const internal::VariadicOperatorMatcherFunc<
|
|
|
|
2, std::numeric_limits<unsigned>::max()>
|
|
|
|
eachOf = {internal::DynTypedMatcher::VO_EachOf};
|
|
|
|
const internal::VariadicOperatorMatcherFunc<
|
|
|
|
2, std::numeric_limits<unsigned>::max()>
|
|
|
|
anyOf = {internal::DynTypedMatcher::VO_AnyOf};
|
|
|
|
const internal::VariadicOperatorMatcherFunc<
|
|
|
|
2, std::numeric_limits<unsigned>::max()>
|
|
|
|
allOf = {internal::DynTypedMatcher::VO_AllOf};
|
|
|
|
const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
|
|
|
|
internal::hasAnyNameFunc>
|
|
|
|
hasAnyName = {};
|
2018-03-29 10:47:28 +08:00
|
|
|
const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>, StringRef,
|
|
|
|
internal::hasAnySelectorFunc>
|
|
|
|
hasAnySelector = {};
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has = {};
|
|
|
|
const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher>
|
|
|
|
hasDescendant = {};
|
|
|
|
const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher> forEach =
|
|
|
|
{};
|
|
|
|
const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher>
|
|
|
|
forEachDescendant = {};
|
|
|
|
const internal::ArgumentAdaptingMatcherFunc<
|
|
|
|
internal::HasParentMatcher,
|
|
|
|
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
|
|
|
|
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
|
|
|
|
hasParent = {};
|
|
|
|
const internal::ArgumentAdaptingMatcherFunc<
|
|
|
|
internal::HasAncestorMatcher,
|
|
|
|
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
|
|
|
|
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
|
|
|
|
hasAncestor = {};
|
|
|
|
const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
|
|
|
|
internal::DynTypedMatcher::VO_UnaryNot};
|
|
|
|
const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
|
|
|
|
const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc>
|
|
|
|
nestedNameSpecifierLoc;
|
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
|
|
|
|
cudaKernelCallExpr;
|
|
|
|
const AstTypeMatcher<BuiltinType> builtinType;
|
|
|
|
const AstTypeMatcher<ArrayType> arrayType;
|
|
|
|
const AstTypeMatcher<ComplexType> complexType;
|
|
|
|
const AstTypeMatcher<ConstantArrayType> constantArrayType;
|
|
|
|
const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType;
|
|
|
|
const AstTypeMatcher<IncompleteArrayType> incompleteArrayType;
|
|
|
|
const AstTypeMatcher<VariableArrayType> variableArrayType;
|
|
|
|
const AstTypeMatcher<AtomicType> atomicType;
|
|
|
|
const AstTypeMatcher<AutoType> autoType;
|
2018-07-23 23:59:27 +08:00
|
|
|
const AstTypeMatcher<DecltypeType> decltypeType;
|
2017-11-16 00:52:12 +08:00
|
|
|
const AstTypeMatcher<FunctionType> functionType;
|
|
|
|
const AstTypeMatcher<FunctionProtoType> functionProtoType;
|
|
|
|
const AstTypeMatcher<ParenType> parenType;
|
|
|
|
const AstTypeMatcher<BlockPointerType> blockPointerType;
|
|
|
|
const AstTypeMatcher<MemberPointerType> memberPointerType;
|
|
|
|
const AstTypeMatcher<PointerType> pointerType;
|
|
|
|
const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType;
|
|
|
|
const AstTypeMatcher<ReferenceType> referenceType;
|
|
|
|
const AstTypeMatcher<LValueReferenceType> lValueReferenceType;
|
|
|
|
const AstTypeMatcher<RValueReferenceType> rValueReferenceType;
|
|
|
|
const AstTypeMatcher<TypedefType> typedefType;
|
|
|
|
const AstTypeMatcher<EnumType> enumType;
|
|
|
|
const AstTypeMatcher<TemplateSpecializationType> templateSpecializationType;
|
|
|
|
const AstTypeMatcher<UnaryTransformType> unaryTransformType;
|
|
|
|
const AstTypeMatcher<RecordType> recordType;
|
|
|
|
const AstTypeMatcher<TagType> tagType;
|
|
|
|
const AstTypeMatcher<ElaboratedType> elaboratedType;
|
|
|
|
const AstTypeMatcher<SubstTemplateTypeParmType> substTemplateTypeParmType;
|
|
|
|
const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType;
|
|
|
|
const AstTypeMatcher<InjectedClassNameType> injectedClassNameType;
|
|
|
|
const AstTypeMatcher<DecayedType> decayedType;
|
2017-11-21 09:09:18 +08:00
|
|
|
AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasElementType,
|
|
|
|
AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType,
|
|
|
|
ComplexType));
|
|
|
|
AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasValueType,
|
|
|
|
AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType));
|
|
|
|
AST_TYPELOC_TRAVERSE_MATCHER_DEF(
|
|
|
|
pointee,
|
|
|
|
AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType,
|
|
|
|
PointerType, ReferenceType));
|
2017-11-16 00:52:12 +08:00
|
|
|
|
2012-07-06 13:48:52 +08:00
|
|
|
} // end namespace ast_matchers
|
|
|
|
} // end namespace clang
|