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"
|
2019-12-10 09:03:47 +08:00
|
|
|
#include "clang/AST/ParentMapContext.h"
|
2017-11-02 07:09:49 +08:00
|
|
|
#include "clang/AST/PrettyPrinter.h"
|
|
|
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
|
|
|
#include "clang/Basic/LLVM.h"
|
2020-02-04 05:21:02 +08:00
|
|
|
#include "clang/Lex/Lexer.h"
|
2017-11-02 07:09:49 +08:00
|
|
|
#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) {
|
2020-02-25 09:47:51 +08:00
|
|
|
return llvm::is_contained(Matches, Node.getSelector().getAsString());
|
2018-03-29 09:15:05 +08:00
|
|
|
}
|
|
|
|
|
2012-07-06 13:48:52 +08:00
|
|
|
namespace internal {
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool NotUnaryOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
2014-11-20 23:45:53 +08:00
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool AllOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
2014-11-20 23:45:53 +08:00
|
|
|
BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool EachOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
2014-11-20 23:45:53 +08:00
|
|
|
BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool AnyOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
2014-11-20 23:45:53 +08:00
|
|
|
BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool OptionallyVariadicOperator(const DynTypedNode &DynNode,
|
2020-01-09 03:09:29 +08:00
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers);
|
|
|
|
|
2020-04-29 11:00:49 +08:00
|
|
|
bool matchesAnyBase(const CXXRecordDecl &Node,
|
|
|
|
const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
|
|
|
|
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) {
|
|
|
|
if (!Node.hasDefinition())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CXXBasePaths Paths;
|
|
|
|
Paths.setOrigin(&Node);
|
|
|
|
|
|
|
|
const auto basePredicate =
|
|
|
|
[Finder, Builder, &BaseSpecMatcher](const CXXBaseSpecifier *BaseSpec,
|
|
|
|
CXXBasePath &IgnoredParam) {
|
|
|
|
BoundNodesTreeBuilder Result(*Builder);
|
|
|
|
if (BaseSpecMatcher.matches(*BaseSpec, Finder, Builder)) {
|
|
|
|
*Builder = std::move(Result);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
return Node.lookupInBases(basePredicate, Paths,
|
|
|
|
/*LookupInDependent =*/true);
|
|
|
|
}
|
|
|
|
|
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 (*)(
|
2020-02-13 03:34:13 +08:00
|
|
|
const 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
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
2014-10-01 23:08:07 +08:00
|
|
|
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
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
2014-10-01 23:08:07 +08:00
|
|
|
BoundNodesTreeBuilder *Builder) const override {
|
|
|
|
bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
|
|
|
|
if (Result) Builder->setBinding(ID, DynNode);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
llvm::Optional<clang::TraversalKind> TraversalKind() const override {
|
2020-01-06 04:48:20 +08:00
|
|
|
return InnerMatcher->TraversalKind();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool dynMatches(const DynTypedNode &, ASTMatchFinder *,
|
2014-10-24 21:29:21 +08:00
|
|
|
BoundNodesTreeBuilder *) const override {
|
|
|
|
return true;
|
|
|
|
}
|
2014-10-10 03:28:18 +08:00
|
|
|
};
|
|
|
|
|
2020-05-28 06:04:50 +08:00
|
|
|
/// A matcher that specifies a particular \c TraversalKind.
|
|
|
|
///
|
|
|
|
/// The kind provided to the constructor overrides any kind that may be
|
|
|
|
/// specified by the `InnerMatcher`.
|
|
|
|
class DynTraversalMatcherImpl : public DynMatcherInterface {
|
|
|
|
public:
|
|
|
|
explicit DynTraversalMatcherImpl(
|
|
|
|
clang::TraversalKind TK,
|
|
|
|
IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher)
|
|
|
|
: TK(TK), InnerMatcher(std::move(InnerMatcher)) {}
|
|
|
|
|
|
|
|
bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder) const override {
|
|
|
|
return this->InnerMatcher->dynMatches(DynNode, Finder, Builder);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Optional<clang::TraversalKind> TraversalKind() const override {
|
|
|
|
return TK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
clang::TraversalKind TK;
|
|
|
|
IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
|
|
|
|
};
|
|
|
|
|
2017-11-02 07:09:49 +08:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
|
2014-10-01 23:08:07 +08:00
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
DynTypedMatcher
|
|
|
|
DynTypedMatcher::constructVariadic(DynTypedMatcher::VariadicOperator Op,
|
|
|
|
ASTNodeKind SupportedKind,
|
|
|
|
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) {
|
2020-02-13 03:34:13 +08:00
|
|
|
RestrictKind =
|
|
|
|
ASTNodeKind::getMostDerivedType(RestrictKind, IM.RestrictKind);
|
2014-12-01 22:46:14 +08:00
|
|
|
}
|
|
|
|
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)));
|
|
|
|
|
2020-01-09 03:09:29 +08:00
|
|
|
case VO_Optionally:
|
|
|
|
return DynTypedMatcher(SupportedKind, RestrictKind,
|
|
|
|
new VariadicMatcher<OptionallyVariadicOperator>(
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
DynTypedMatcher
|
|
|
|
DynTypedMatcher::constructRestrictedWrapper(const DynTypedMatcher &InnerMatcher,
|
|
|
|
ASTNodeKind RestrictKind) {
|
2019-05-13 04:09:32 +08:00
|
|
|
DynTypedMatcher Copy = InnerMatcher;
|
|
|
|
Copy.RestrictKind = RestrictKind;
|
|
|
|
return Copy;
|
|
|
|
}
|
|
|
|
|
2020-05-28 06:04:50 +08:00
|
|
|
DynTypedMatcher
|
|
|
|
DynTypedMatcher::withTraversalKind(ast_type_traits::TraversalKind TK) {
|
|
|
|
auto Copy = *this;
|
|
|
|
Copy.Implementation =
|
|
|
|
new DynTraversalMatcherImpl(TK, std::move(Copy.Implementation));
|
|
|
|
return Copy;
|
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
DynTypedMatcher DynTypedMatcher::trueMatcher(ASTNodeKind NodeKind) {
|
2014-10-24 21:29:21 +08:00
|
|
|
return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
|
2014-10-10 03:28:18 +08:00
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool DynTypedMatcher::canMatchNodesOfKind(ASTNodeKind Kind) const {
|
2014-11-25 05:21:09 +08:00
|
|
|
return RestrictKind.isBaseOf(Kind);
|
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
DynTypedMatcher DynTypedMatcher::dynCastTo(const ASTNodeKind Kind) const {
|
2014-10-01 23:08:07 +08:00
|
|
|
auto Copy = *this;
|
|
|
|
Copy.SupportedKind = Kind;
|
2020-02-13 03:34:13 +08:00
|
|
|
Copy.RestrictKind = ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
|
2014-10-01 23:08:07 +08:00
|
|
|
return Copy;
|
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool DynTypedMatcher::matches(const DynTypedNode &DynNode,
|
2014-10-01 23:08:07 +08:00
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder) const {
|
2019-05-13 04:09:32 +08:00
|
|
|
TraversalKindScope RAII(Finder->getASTContext(),
|
|
|
|
Implementation->TraversalKind());
|
|
|
|
|
2019-12-10 09:03:47 +08:00
|
|
|
auto N =
|
|
|
|
Finder->getASTContext().getParentMapContext().traverseIgnored(DynNode);
|
2019-05-13 04:09:32 +08:00
|
|
|
|
|
|
|
if (RestrictKind.isBaseOf(N.getNodeKind()) &&
|
|
|
|
Implementation->dynMatches(N, Finder, Builder)) {
|
2014-10-01 23:08:07 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool DynTypedMatcher::matchesNoKindCheck(const DynTypedNode &DynNode,
|
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder) const {
|
2019-05-13 04:09:32 +08:00
|
|
|
TraversalKindScope raii(Finder->getASTContext(),
|
|
|
|
Implementation->TraversalKind());
|
|
|
|
|
2019-12-10 09:03:47 +08:00
|
|
|
auto N =
|
|
|
|
Finder->getASTContext().getParentMapContext().traverseIgnored(DynNode);
|
2019-05-13 04:09:32 +08:00
|
|
|
|
|
|
|
assert(RestrictKind.isBaseOf(N.getNodeKind()));
|
|
|
|
if (Implementation->dynMatches(N, Finder, Builder)) {
|
2014-11-25 05:21:09 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool DynTypedMatcher::canConvertTo(ASTNodeKind To) const {
|
2014-09-04 22:13:58 +08:00
|
|
|
const auto From = getSupportedKind();
|
2020-02-13 03:34:13 +08:00
|
|
|
auto QualKind = ASTNodeKind::getFromNodeKind<QualType>();
|
|
|
|
auto TypeKind = ASTNodeKind::getFromNodeKind<Type>();
|
2014-09-04 22:13:58 +08:00
|
|
|
/// 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
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool NotUnaryOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
2013-11-22 22:41:48 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool AllOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
2013-08-27 23:11:16 +08:00
|
|
|
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.
|
2020-02-25 09:47:51 +08:00
|
|
|
return llvm::all_of(InnerMatchers, [&](const DynTypedMatcher &InnerMatcher) {
|
|
|
|
return InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder);
|
|
|
|
});
|
2013-08-27 23:11:16 +08:00
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool EachOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
2013-08-27 23:11:16 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool AnyOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
2013-08-27 23:11:16 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-02-13 03:34:13 +08:00
|
|
|
bool OptionallyVariadicOperator(const DynTypedNode &DynNode,
|
2020-01-09 03:09:29 +08:00
|
|
|
ASTMatchFinder *Finder,
|
|
|
|
BoundNodesTreeBuilder *Builder,
|
|
|
|
ArrayRef<DynTypedMatcher> InnerMatchers) {
|
2020-03-04 04:04:08 +08:00
|
|
|
if (InnerMatchers.size() != 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
BoundNodesTreeBuilder Result(*Builder);
|
|
|
|
if (InnerMatchers[0].matches(DynNode, Finder, &Result))
|
2020-02-29 01:45:19 +08:00
|
|
|
*Builder = std::move(Result);
|
2020-01-09 03:09:29 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
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;
|
2020-02-25 09:47:51 +08:00
|
|
|
Names.reserve(NameRefs.size());
|
2016-02-23 05:13:02 +08:00
|
|
|
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) {
|
2020-02-25 09:47:51 +08:00
|
|
|
return internal::Matcher<NamedDecl>(
|
|
|
|
new internal::HasNameMatcher(vectorFromRefs(NameRefs)));
|
2018-03-29 08:51:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Matcher<ObjCMessageExpr> hasAnySelectorFunc(
|
|
|
|
ArrayRef<const StringRef *> NameRefs) {
|
|
|
|
return hasAnySelectorMatcher(vectorFromRefs(NameRefs));
|
2016-02-23 05:13:02 +08:00
|
|
|
}
|
|
|
|
|
2020-02-25 15:51:07 +08:00
|
|
|
HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs) {
|
|
|
|
return HasOpNameMatcher(vectorFromRefs(NameRefs));
|
|
|
|
}
|
|
|
|
|
2020-03-09 19:16:50 +08:00
|
|
|
HasOverloadOpNameMatcher
|
|
|
|
hasAnyOverloadedOperatorNameFunc(ArrayRef<const StringRef *> NameRefs) {
|
|
|
|
return HasOverloadOpNameMatcher(vectorFromRefs(NameRefs));
|
|
|
|
}
|
|
|
|
|
2016-02-23 05:13:02 +08:00
|
|
|
HasNameMatcher::HasNameMatcher(std::vector<std::string> N)
|
2020-02-25 09:47:51 +08:00
|
|
|
: UseUnqualifiedMatch(llvm::all_of(
|
|
|
|
N, [](StringRef Name) { return Name.find("::") == Name.npos; })),
|
2016-02-23 05:13:02 +08:00
|
|
|
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) {
|
2020-02-25 09:47:51 +08:00
|
|
|
Patterns.reserve(Names.size());
|
2016-02-23 05:13:02 +08:00
|
|
|
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 {
|
2020-02-25 09:47:51 +08:00
|
|
|
return llvm::any_of(Patterns, [&](const Pattern &Pattern) {
|
|
|
|
return Pattern.P.empty() &&
|
|
|
|
(AllowFullyQualified || !Pattern.IsFullyQualified);
|
|
|
|
});
|
2016-02-23 05:13:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2020-02-27 06:06:38 +08:00
|
|
|
for (; Ctx; Ctx = Ctx->getParent()) {
|
|
|
|
// Linkage Spec can just be ignored
|
|
|
|
// FIXME: Any other DeclContext kinds that can be safely disregarded
|
|
|
|
if (isa<LinkageSpecDecl>(Ctx))
|
|
|
|
continue;
|
|
|
|
if (!isa<NamedDecl>(Ctx))
|
|
|
|
break;
|
2016-02-23 05:13:02 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-02-04 05:21:02 +08:00
|
|
|
// Checks whether \p Loc points to a token with source text of \p TokenText.
|
|
|
|
static bool isTokenAtLoc(const SourceManager &SM, const LangOptions &LangOpts,
|
|
|
|
StringRef Text, SourceLocation Loc) {
|
|
|
|
llvm::SmallString<16> Buffer;
|
|
|
|
bool Invalid = false;
|
|
|
|
// Since `Loc` may point into an expansion buffer, which has no corresponding
|
|
|
|
// source, we need to look at the spelling location to read the actual source.
|
2020-02-05 01:32:06 +08:00
|
|
|
StringRef TokenText = Lexer::getSpelling(SM.getSpellingLoc(Loc), Buffer, SM,
|
|
|
|
LangOpts, &Invalid);
|
2020-02-04 05:21:02 +08:00
|
|
|
return !Invalid && Text == TokenText;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Optional<SourceLocation>
|
|
|
|
getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
|
|
|
|
const ASTContext &Context) {
|
2020-02-05 01:32:06 +08:00
|
|
|
auto &SM = Context.getSourceManager();
|
|
|
|
const LangOptions &LangOpts = Context.getLangOpts();
|
2020-02-04 05:21:02 +08:00
|
|
|
while (Loc.isMacroID()) {
|
2020-02-05 01:32:06 +08:00
|
|
|
SrcMgr::ExpansionInfo Expansion =
|
|
|
|
SM.getSLocEntry(SM.getFileID(Loc)).getExpansion();
|
2020-02-04 05:21:02 +08:00
|
|
|
if (Expansion.isMacroArgExpansion())
|
|
|
|
// Check macro argument for an expansion of the given macro. For example,
|
|
|
|
// `F(G(3))`, where `MacroName` is `G`.
|
2020-02-05 01:32:06 +08:00
|
|
|
if (llvm::Optional<SourceLocation> ArgLoc = getExpansionLocOfMacro(
|
2020-02-04 05:21:02 +08:00
|
|
|
MacroName, Expansion.getSpellingLoc(), Context))
|
|
|
|
return ArgLoc;
|
|
|
|
Loc = Expansion.getExpansionLocStart();
|
|
|
|
if (isTokenAtLoc(SM, LangOpts, MacroName, Loc))
|
|
|
|
return Loc;
|
|
|
|
}
|
|
|
|
return llvm::None;
|
|
|
|
}
|
|
|
|
|
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;
|
2020-01-29 20:57:27 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, TagDecl> tagDecl;
|
2017-11-16 00:52:12 +08:00
|
|
|
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;
|
2020-01-28 21:12:08 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
|
|
|
|
cxxNoexceptExpr;
|
2017-11-16 00:52:12 +08:00
|
|
|
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;
|
2020-04-06 21:22:35 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, FixedPointLiteral>
|
|
|
|
fixedPointLiteral;
|
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};
|
2020-03-04 04:04:08 +08:00
|
|
|
const internal::VariadicOperatorMatcherFunc<1, 1> optionally = {
|
|
|
|
internal::DynTypedMatcher::VO_Optionally};
|
2017-11-16 00:52:12 +08:00
|
|
|
const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
|
|
|
|
internal::hasAnyNameFunc>
|
|
|
|
hasAnyName = {};
|
2020-02-25 15:51:07 +08:00
|
|
|
|
|
|
|
const internal::VariadicFunction<internal::HasOpNameMatcher, StringRef,
|
|
|
|
internal::hasAnyOperatorNameFunc>
|
|
|
|
hasAnyOperatorName = {};
|
2020-03-09 19:16:50 +08:00
|
|
|
const internal::VariadicFunction<internal::HasOverloadOpNameMatcher, StringRef,
|
|
|
|
internal::hasAnyOverloadedOperatorNameFunc>
|
|
|
|
hasAnyOverloadedOperatorName = {};
|
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;
|
2020-02-03 20:43:26 +08:00
|
|
|
const AstTypeMatcher<DeducedTemplateSpecializationType>
|
|
|
|
deducedTemplateSpecializationType;
|
2017-11-16 00:52:12 +08:00
|
|
|
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
|
|
|
|
2019-03-21 23:33:10 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Stmt, OMPExecutableDirective>
|
|
|
|
ompExecutableDirective;
|
[ASTTypeTraits][ASTMatchers][OpenMP] OMPClause handling
Summary:
`OMPClause` is the base class, it is not descendant from **any**
other class, therefore for it to work with e.g.
`VariadicDynCastAllOfMatcher<>`, it needs to be handled here.
Reviewers: sbenza, bkramer, pcc, klimek, hokein, gribozavr, aaron.ballman, george.karpenkov
Reviewed By: gribozavr, aaron.ballman
Subscribers: guansong, jdoerfert, alexfh, ABataev, cfe-commits
Tags: #openmp, #clang
Differential Revision: https://reviews.llvm.org/D57112
llvm-svn: 356675
2019-03-21 23:33:24 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause>
|
|
|
|
ompDefaultClause;
|
2019-06-20 18:13:58 +08:00
|
|
|
const internal::VariadicDynCastAllOfMatcher<Decl, CXXDeductionGuideDecl>
|
|
|
|
cxxDeductionGuideDecl;
|
2019-03-21 23:33:10 +08:00
|
|
|
|
2012-07-06 13:48:52 +08:00
|
|
|
} // end namespace ast_matchers
|
|
|
|
} // end namespace clang
|