summaryrefslogtreecommitdiffstats
path: root/include/clang/ASTMatchers/ASTMatchersInternal.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchersInternal.h')
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h89
1 files changed, 60 insertions, 29 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index b494647..d499091 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -188,8 +188,11 @@ class ASTMatchFinder;
/// Used by the implementation of Matcher<T> and DynTypedMatcher.
/// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T>
/// instead.
-class DynMatcherInterface : public RefCountedBaseVPTR {
+class DynMatcherInterface
+ : public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
public:
+ virtual ~DynMatcherInterface() {}
+
/// \brief Returns true if \p DynNode can be matched.
///
/// May bind \p DynNode to an ID via \p Builder, or recurse into
@@ -209,8 +212,6 @@ public:
template <typename T>
class MatcherInterface : public DynMatcherInterface {
public:
- ~MatcherInterface() override {}
-
/// \brief Returns true if 'Node' can be matched.
///
/// May bind 'Node' to an ID via 'Builder', or recurse into
@@ -281,6 +282,7 @@ public:
};
static DynTypedMatcher
constructVariadic(VariadicOperator Op,
+ ast_type_traits::ASTNodeKind SupportedKind,
std::vector<DynTypedMatcher> InnerMatchers);
/// \brief Get a "true" matcher for \p NodeKind.
@@ -556,22 +558,32 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
return false;
}
-/// \brief Metafunction to determine if type T has a member called getDecl.
+// Metafunction to determine if type T has a member called
+// getDecl.
+#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__clang__)
+// For old versions of MSVC, we use a weird nonstandard __if_exists
+// statement, since before MSVC2015, it was not standards-conformant
+// enough to compile the usual code below.
template <typename T> struct has_getDecl {
- struct Default { int getDecl; };
- struct Derived : T, Default { };
-
- template<typename C, C> struct CheckT;
-
- // If T::getDecl exists, an ambiguity arises and CheckT will
- // not be instantiable. This makes f(...) the only available
- // overload.
- template<typename C>
- static char (&f(CheckT<int Default::*, &C::getDecl>*))[1];
- template<typename C> static char (&f(...))[2];
-
- static bool const value = sizeof(f<Derived>(nullptr)) == 2;
+ __if_exists(T::getDecl) {
+ enum { value = 1 };
+ }
+ __if_not_exists(T::getDecl) {
+ enum { value = 0 };
+ }
};
+#else
+// There is a default template inheriting from "false_type". Then, a
+// partial specialization inherits from "true_type". However, this
+// specialization will only exist when the call to getDecl() isn't an
+// error -- it vanishes by SFINAE when the member doesn't exist.
+template <typename> struct type_sink_to_void { typedef void type; };
+template <typename T, typename = void> struct has_getDecl : std::false_type {};
+template <typename T>
+struct has_getDecl<
+ T, typename type_sink_to_void<decltype(std::declval<T>().getDecl())>::type>
+ : std::true_type {};
+#endif
/// \brief Matches overloaded operators with a specific name.
///
@@ -667,16 +679,30 @@ private:
return matchesDecl(Node.getDecl(), Finder, Builder);
}
- /// \brief Extracts the CXXRecordDecl or EnumDecl of a QualType and returns
- /// whether the inner matcher matches on it.
+ /// \brief Extracts the TagDecl of a QualType and returns whether the inner
+ /// matcher matches on it.
bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- /// FIXME: Add other ways to convert...
if (Node.isNull())
return false;
- if (const EnumType *AsEnum = dyn_cast<EnumType>(Node.getTypePtr()))
- return matchesDecl(AsEnum->getDecl(), Finder, Builder);
- return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder);
+
+ if (auto *TD = Node->getAsTagDecl())
+ return matchesDecl(TD, Finder, Builder);
+ else if (auto *TT = Node->getAs<TypedefType>())
+ return matchesDecl(TT->getDecl(), Finder, Builder);
+ // Do not use getAs<TemplateTypeParmType> instead of the direct dyn_cast.
+ // Calling getAs will return the canonical type, but that type does not
+ // store a TemplateTypeParmDecl. We *need* the uncanonical type, if it is
+ // available, and using dyn_cast ensures that.
+ else if (auto *TTP = dyn_cast<TemplateTypeParmType>(Node.getTypePtr()))
+ return matchesDecl(TTP->getDecl(), Finder, Builder);
+ else if (auto *OCIT = Node->getAs<ObjCInterfaceType>())
+ return matchesDecl(OCIT->getDecl(), Finder, Builder);
+ else if (auto *UUT = Node->getAs<UnresolvedUsingType>())
+ return matchesDecl(UUT->getDecl(), Finder, Builder);
+ else if (auto *ICNT = Node->getAs<InjectedClassNameType>())
+ return matchesDecl(ICNT->getDecl(), Finder, Builder);
+ return false;
}
/// \brief Gets the TemplateDecl from a TemplateSpecializationType
@@ -753,7 +779,7 @@ const bool IsBaseType<T>::value;
/// at least one ancestor matched.
///
/// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal.
-/// In the future, we wan to implement this for all nodes for which it makes
+/// In the future, we want to implement this for all nodes for which it makes
/// sense. In the case of matchesAncestorOf, we'll want to implement it for
/// all nodes, as all nodes have ancestors.
class ASTMatchFinder {
@@ -833,8 +859,10 @@ public:
BoundNodesTreeBuilder *Builder,
AncestorMatchMode MatchMode) {
static_assert(std::is_base_of<Decl, T>::value ||
- std::is_base_of<Stmt, T>::value,
- "only Decl or Stmt allowed for recursive matching");
+ std::is_base_of<NestedNameSpecifierLoc, T>::value ||
+ std::is_base_of<Stmt, T>::value ||
+ std::is_base_of<TypeLoc, T>::value,
+ "type not allowed for recursive matching");
return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node),
Matcher, Builder, MatchMode);
}
@@ -1137,7 +1165,8 @@ public:
template <typename T> operator Matcher<T>() const {
return DynTypedMatcher::constructVariadic(
- Op, getMatchers<T>(llvm::index_sequence_for<Ps...>()))
+ Op, ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
+ getMatchers<T>(llvm::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
@@ -1191,8 +1220,10 @@ BindableMatcher<T> makeAllOfComposite(
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
PI(InnerMatchers.end()));
return BindableMatcher<T>(
- DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
- std::move(DynMatchers))
+ DynTypedMatcher::constructVariadic(
+ DynTypedMatcher::VO_AllOf,
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
+ std::move(DynMatchers))
.template unconditionalConvertTo<T>());
}
OpenPOWER on IntegriCloud