[cfe-commits] r160348 - in /cfe/trunk: include/clang/ASTMatchers/ASTMatchers.h include/clang/ASTMatchers/ASTMatchersInternal.h lib/ASTMatchers/ASTMatchFinder.cpp unittests/ASTMatchers/ASTMatchersTest.cpp
Daniel Jasper
djasper at google.com
Tue Jul 17 00:39:28 PDT 2012
Author: djasper
Date: Tue Jul 17 02:39:27 2012
New Revision: 160348
URL: http://llvm.org/viewvc/llvm-project?rev=160348&view=rev
Log:
Make the isDerivedFrom matcher more generic.
It now accepts an arbitrary inner matcher but is fully backwards
compatible.
Modified:
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=160348&r1=160347&r2=160348&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Tue Jul 17 02:39:27 2012
@@ -839,14 +839,11 @@
}
/// \brief Matches C++ classes that are directly or indirectly derived from
-/// the given base class.
+/// a class matching \c Base.
///
/// Note that a class is considered to be also derived from itself.
-/// The parameter specified the name of the base type (either a class or a
-/// typedef), and does not allow structural matches for namespaces or template
-/// type parameters.
///
-/// Example matches X, Y, Z, C (Base == "X")
+/// Example matches X, Y, Z, C (Base == hasName("X"))
/// class X; // A class is considered to be derived from itself
/// class Y : public X {}; // directly derived
/// class Z : public Y {}; // indirectly derived
@@ -854,13 +851,19 @@
/// typedef A B;
/// class C : public B {}; // derived from a typedef of X
///
-/// In the following example, Bar matches isDerivedFrom("X"):
+/// In the following example, Bar matches isDerivedFrom(hasName("X")):
/// class Foo;
/// typedef Foo X;
/// class Bar : public Foo {}; // derived from a type that X is a typedef of
-AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, std::string, Base) {
- assert(!Base.empty());
- return Finder->classIsDerivedFrom(&Node, Base);
+AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
+ internal::Matcher<NamedDecl>, Base) {
+ return Finder->classIsDerivedFrom(&Node, Base, Builder);
+}
+
+/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
+inline internal::Matcher<CXXRecordDecl> isDerivedFrom(StringRef BaseName) {
+ assert(!BaseName.empty());
+ return isDerivedFrom(hasName(BaseName));
}
/// \brief Matches AST nodes that have child AST nodes that match the
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=160348&r1=160347&r2=160348&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Tue Jul 17 02:39:27 2012
@@ -411,11 +411,12 @@
virtual ~ASTMatchFinder() {}
/// \brief Returns true if the given class is directly or indirectly derived
- /// from a base type with the given name.
+ /// from a base type matching \c base.
///
/// A class is considered to be also derived from itself.
virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
- StringRef BaseName) const = 0;
+ const Matcher<NamedDecl> &Base,
+ BoundNodesTreeBuilder *Builder) = 0;
// FIXME: Implement for other base nodes.
virtual bool matchesChildOf(const Decl &DeclNode,
Modified: cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp?rev=160348&r1=160347&r2=160348&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp Tue Jul 17 02:39:27 2012
@@ -27,15 +27,6 @@
namespace internal {
namespace {
-// Returns the value that 'AMap' maps 'Key' to, or NULL if 'Key' is
-// not in 'AMap'.
-template <typename Map>
-static const typename Map::mapped_type *
-find(const Map &AMap, const typename Map::key_type &Key) {
- typename Map::const_iterator It = AMap.find(Key);
- return It == AMap.end() ? NULL : &It->second;
-}
-
// We use memoization to avoid running the same matcher on the same
// AST node twice. This pair is the key for looking up match
// result. It consists of an ID of the MatcherInterface (for
@@ -244,8 +235,7 @@
const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
const Type *CanonicalType = // root of the typedef tree
ActiveASTContext->getCanonicalType(TypeNode);
- TypeToUnqualifiedAliases[CanonicalType].insert(
- DeclNode->getName().str());
+ TypeAliases[CanonicalType].insert(DeclNode);
return true;
}
@@ -289,7 +279,8 @@
}
virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
- StringRef BaseName) const;
+ const Matcher<NamedDecl> &Base,
+ BoundNodesTreeBuilder *Builder);
// Implements ASTMatchFinder::MatchesChildOf.
virtual bool matchesChildOf(const Decl &DeclNode,
@@ -347,16 +338,20 @@
MatchFinder::MatchCallback* Callback;
};
- // Returns true if 'TypeNode' is also known by the name 'Name'. In other
- // words, there is a type (including typedef) with the name 'Name'
- // that is equal to 'TypeNode'.
- bool typeHasAlias(const Type *TypeNode,
- StringRef Name) const {
+ // Returns true if 'TypeNode' has an alias that matches the given matcher.
+ bool typeHasMatchingAlias(const Type *TypeNode,
+ const Matcher<NamedDecl> Matcher,
+ BoundNodesTreeBuilder *Builder) {
const Type *const CanonicalType =
ActiveASTContext->getCanonicalType(TypeNode);
- const std::set<std::string> *UnqualifiedAlias =
- find(TypeToUnqualifiedAliases, CanonicalType);
- return UnqualifiedAlias != NULL && UnqualifiedAlias->count(Name) > 0;
+ const std::set<const TypedefDecl*> &Aliases = TypeAliases[CanonicalType];
+ for (std::set<const TypedefDecl*>::const_iterator
+ It = Aliases.begin(), End = Aliases.end();
+ It != End; ++It) {
+ if (Matcher.matches(**It, this, Builder))
+ return true;
+ }
+ return false;
}
// Matches all registered matchers on the given node and calls the
@@ -380,9 +375,8 @@
MatchFinder::MatchCallback*> > *const Triggers;
ASTContext *ActiveASTContext;
- // Maps a canonical type to the names of its typedefs.
- llvm::DenseMap<const Type*, std::set<std::string> >
- TypeToUnqualifiedAliases;
+ // Maps a canonical type to its TypedefDecls.
+ llvm::DenseMap<const Type*, std::set<const TypedefDecl*> > TypeAliases;
// Maps (matcher, node) -> the match result for memoization.
typedef llvm::DenseMap<UntypedMatchInput, MemoizedMatchResult> MemoizationMap;
@@ -392,39 +386,36 @@
// Returns true if the given class is directly or indirectly derived
// from a base type with the given name. A class is considered to be
// also derived from itself.
-bool
-MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
- StringRef BaseName) const {
- if (Declaration->getName() == BaseName) {
+bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
+ const Matcher<NamedDecl> &Base,
+ BoundNodesTreeBuilder *Builder) {
+ if (Base.matches(*Declaration, this, Builder))
return true;
- }
- if (!Declaration->hasDefinition()) {
+ if (!Declaration->hasDefinition())
return false;
- }
typedef CXXRecordDecl::base_class_const_iterator BaseIterator;
for (BaseIterator It = Declaration->bases_begin(),
End = Declaration->bases_end(); It != End; ++It) {
const Type *TypeNode = It->getType().getTypePtr();
- if (typeHasAlias(TypeNode, BaseName))
+ if (typeHasMatchingAlias(TypeNode, Base, Builder))
return true;
// Type::getAs<...>() drills through typedefs.
if (TypeNode->getAs<DependentNameType>() != NULL ||
- TypeNode->getAs<TemplateTypeParmType>() != NULL) {
+ TypeNode->getAs<TemplateTypeParmType>() != NULL)
// Dependent names and template TypeNode parameters will be matched when
// the template is instantiated.
continue;
- }
CXXRecordDecl *ClassDecl = NULL;
TemplateSpecializationType const *TemplateType =
TypeNode->getAs<TemplateSpecializationType>();
if (TemplateType != NULL) {
- if (TemplateType->getTemplateName().isDependent()) {
+ if (TemplateType->getTemplateName().isDependent())
// Dependent template specializations will be matched when the
// template is instantiated.
continue;
- }
+
// For template specialization types which are specializing a template
// declaration which is an explicit or partial specialization of another
// template declaration, getAsCXXRecordDecl() returns the corresponding
@@ -448,9 +439,8 @@
}
assert(ClassDecl != NULL);
assert(ClassDecl != Declaration);
- if (classIsDerivedFrom(ClassDecl, BaseName)) {
+ if (classIsDerivedFrom(ClassDecl, Base, Builder))
return true;
- }
}
return false;
}
Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=160348&r1=160347&r2=160348&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Tue Jul 17 02:39:27 2012
@@ -245,7 +245,7 @@
variable(
hasName("z_char"),
hasInitializer(hasType(record(isDerivedFrom("Base1"),
- isDerivedFrom("Base2")))))));
+ isDerivedFrom("Base2")))))));
const char *RecursiveTemplateTwoParameters =
"class Base1 {}; class Base2 {};"
@@ -273,7 +273,17 @@
variable(
hasName("z_char"),
hasInitializer(hasType(record(isDerivedFrom("Base1"),
- isDerivedFrom("Base2")))))));
+ isDerivedFrom("Base2")))))));
+ EXPECT_TRUE(matches(
+ "namespace ns { class X {}; class Y : public X {}; }",
+ record(isDerivedFrom("::ns::X"))));
+ EXPECT_TRUE(notMatches(
+ "class X {}; class Y : public X {};",
+ record(isDerivedFrom("::ns::X"))));
+
+ EXPECT_TRUE(matches(
+ "class X {}; class Y : public X {};",
+ record(isDerivedFrom(id("test", record(hasName("X")))))));
}
TEST(AllOf, AllOverloadsWork) {
More information about the cfe-commits
mailing list