diff options
author | Daniel Jasper <djasper@google.com> | 2012-10-29 10:14:44 +0000 |
---|---|---|
committer | Daniel Jasper <djasper@google.com> | 2012-10-29 10:14:44 +0000 |
commit | a267cf6f87dc695143d65fc61ec1744564f55932 (patch) | |
tree | 661316203482135d919275dad31ffbc60568df7e /unittests/ASTMatchers/ASTMatchersTest.cpp | |
parent | b201e93f018fc9e5b964053a85685d38cec6f841 (diff) |
Implement has(), hasDescendant(), forEach() and forEachDescendant() for
Types, QualTypes and TypeLocs.
Review: http://llvm-reviews.chandlerc.com/D83
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166917 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/ASTMatchers/ASTMatchersTest.cpp')
-rw-r--r-- | unittests/ASTMatchers/ASTMatchersTest.cpp | 165 |
1 files changed, 113 insertions, 52 deletions
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 689c91f476..2602e87840 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -555,6 +555,114 @@ TEST(DeclarationMatcher, HasDescendant) { "};", ZDescendantClassXDescendantClassY)); } +// Implements a run method that returns whether BoundNodes contains a +// Decl bound to Id that can be dynamically cast to T. +// Optionally checks that the check succeeded a specific number of times. +template <typename T> +class VerifyIdIsBoundTo : public BoundNodesCallback { +public: + // Create an object that checks that a node of type \c T was bound to \c Id. + // Does not check for a certain number of matches. + explicit VerifyIdIsBoundTo(llvm::StringRef Id) + : Id(Id), ExpectedCount(-1), Count(0) {} + + // Create an object that checks that a node of type \c T was bound to \c Id. + // Checks that there were exactly \c ExpectedCount matches. + VerifyIdIsBoundTo(llvm::StringRef Id, int ExpectedCount) + : Id(Id), ExpectedCount(ExpectedCount), Count(0) {} + + // Create an object that checks that a node of type \c T was bound to \c Id. + // Checks that there was exactly one match with the name \c ExpectedName. + // Note that \c T must be a NamedDecl for this to work. + VerifyIdIsBoundTo(llvm::StringRef Id, llvm::StringRef ExpectedName) + : Id(Id), ExpectedCount(1), Count(0), ExpectedName(ExpectedName) {} + + ~VerifyIdIsBoundTo() { + if (ExpectedCount != -1) + EXPECT_EQ(ExpectedCount, Count); + if (!ExpectedName.empty()) + EXPECT_EQ(ExpectedName, Name); + } + + virtual bool run(const BoundNodes *Nodes) { + if (Nodes->getNodeAs<T>(Id)) { + ++Count; + if (const NamedDecl *Named = Nodes->getNodeAs<NamedDecl>(Id)) { + Name = Named->getNameAsString(); + } else if (const NestedNameSpecifier *NNS = + Nodes->getNodeAs<NestedNameSpecifier>(Id)) { + llvm::raw_string_ostream OS(Name); + NNS->print(OS, PrintingPolicy(LangOptions())); + } + return true; + } + return false; + } + +private: + const std::string Id; + const int ExpectedCount; + int Count; + const std::string ExpectedName; + std::string Name; +}; + +TEST(HasDescendant, MatchesDescendantTypes) { + EXPECT_TRUE(matches("void f() { int i = 3; }", + decl(hasDescendant(loc(builtinType()))))); + EXPECT_TRUE(matches("void f() { int i = 3; }", + stmt(hasDescendant(builtinType())))); + + EXPECT_TRUE(matches("void f() { int i = 3; }", + stmt(hasDescendant(loc(builtinType()))))); + EXPECT_TRUE(matches("void f() { int i = 3; }", + stmt(hasDescendant(qualType(builtinType()))))); + + EXPECT_TRUE(notMatches("void f() { float f = 2.0f; }", + stmt(hasDescendant(isInteger())))); + + EXPECT_TRUE(matchAndVerifyResultTrue( + "void f() { int a; float c; int d; int e; }", + functionDecl(forEachDescendant( + varDecl(hasDescendant(isInteger())).bind("x"))), + new VerifyIdIsBoundTo<Decl>("x", 3))); +} + +TEST(HasDescendant, MatchesDescendantsOfTypes) { + EXPECT_TRUE(matches("void f() { int*** i; }", + qualType(hasDescendant(builtinType())))); + EXPECT_TRUE(matches("void f() { int*** i; }", + qualType(hasDescendant( + pointerType(pointee(builtinType())))))); + EXPECT_TRUE(matches("void f() { int*** i; }", + typeLoc(hasDescendant(builtinTypeLoc())))); + + EXPECT_TRUE(matchAndVerifyResultTrue( + "void f() { int*** i; }", + qualType(asString("int ***"), forEachDescendant(pointerType().bind("x"))), + new VerifyIdIsBoundTo<Type>("x", 2))); +} + +TEST(Has, MatchesChildrenOfTypes) { + EXPECT_TRUE(matches("int i;", + varDecl(hasName("i"), has(isInteger())))); + EXPECT_TRUE(notMatches("int** i;", + varDecl(hasName("i"), has(isInteger())))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int (*f)(float, int);", + qualType(functionType(), forEach(qualType(isInteger()).bind("x"))), + new VerifyIdIsBoundTo<QualType>("x", 2))); +} + +TEST(Has, MatchesChildTypes) { + EXPECT_TRUE(matches( + "int* i;", + varDecl(hasName("i"), hasType(qualType(has(builtinType())))))); + EXPECT_TRUE(notMatches( + "int* i;", + varDecl(hasName("i"), hasType(qualType(has(pointerType())))))); +} + TEST(Enum, DoesNotMatchClasses) { EXPECT_TRUE(notMatches("class X {};", enumDecl(hasName("X")))); } @@ -613,58 +721,6 @@ TEST(TypeMatcher, MatchesClassType) { matches("class A { public: A *a; class B {}; };", TypeAHasClassB)); } -// Implements a run method that returns whether BoundNodes contains a -// Decl bound to Id that can be dynamically cast to T. -// Optionally checks that the check succeeded a specific number of times. -template <typename T> -class VerifyIdIsBoundTo : public BoundNodesCallback { -public: - // Create an object that checks that a node of type \c T was bound to \c Id. - // Does not check for a certain number of matches. - explicit VerifyIdIsBoundTo(llvm::StringRef Id) - : Id(Id), ExpectedCount(-1), Count(0) {} - - // Create an object that checks that a node of type \c T was bound to \c Id. - // Checks that there were exactly \c ExpectedCount matches. - VerifyIdIsBoundTo(llvm::StringRef Id, int ExpectedCount) - : Id(Id), ExpectedCount(ExpectedCount), Count(0) {} - - // Create an object that checks that a node of type \c T was bound to \c Id. - // Checks that there was exactly one match with the name \c ExpectedName. - // Note that \c T must be a NamedDecl for this to work. - VerifyIdIsBoundTo(llvm::StringRef Id, llvm::StringRef ExpectedName) - : Id(Id), ExpectedCount(1), Count(0), ExpectedName(ExpectedName) {} - - ~VerifyIdIsBoundTo() { - if (ExpectedCount != -1) - EXPECT_EQ(ExpectedCount, Count); - if (!ExpectedName.empty()) - EXPECT_EQ(ExpectedName, Name); - } - - virtual bool run(const BoundNodes *Nodes) { - if (Nodes->getNodeAs<T>(Id)) { - ++Count; - if (const NamedDecl *Named = Nodes->getNodeAs<NamedDecl>(Id)) { - Name = Named->getNameAsString(); - } else if (const NestedNameSpecifier *NNS = - Nodes->getNodeAs<NestedNameSpecifier>(Id)) { - llvm::raw_string_ostream OS(Name); - NNS->print(OS, PrintingPolicy(LangOptions())); - } - return true; - } - return false; - } - -private: - const std::string Id; - const int ExpectedCount; - int Count; - const std::string ExpectedName; - std::string Name; -}; - TEST(Matcher, BindMatchedNodes) { DeclarationMatcher ClassX = has(recordDecl(hasName("::X")).bind("x")); @@ -3018,6 +3074,11 @@ TEST(TypeMatching, MatchesAutoTypes) { autoType(hasDeducedType(isInteger())))); } +TEST(TypeMatching, MatchesFunctionTypes) { + EXPECT_TRUE(matches("int (*f)(int);", functionType())); + EXPECT_TRUE(matches("void f(int i) {}", functionType())); +} + TEST(TypeMatching, PointerTypes) { // FIXME: Reactive when these tests can be more specific (not matching // implicit code on certain platforms), likely when we have hasDescendant for |