aboutsummaryrefslogtreecommitdiff
path: root/unittests/ASTMatchers
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
commit676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch)
tree02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /unittests/ASTMatchers
parentc7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff)
Notes
Diffstat (limited to 'unittests/ASTMatchers')
-rw-r--r--unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp99
-rw-r--r--unittests/ASTMatchers/ASTMatchersNodeTest.cpp70
-rw-r--r--unittests/ASTMatchers/ASTMatchersTraversalTest.cpp67
-rw-r--r--unittests/ASTMatchers/CMakeLists.txt1
-rw-r--r--unittests/ASTMatchers/Dynamic/CMakeLists.txt1
-rw-r--r--unittests/ASTMatchers/Dynamic/ParserTest.cpp57
-rw-r--r--unittests/ASTMatchers/Dynamic/RegistryTest.cpp3
7 files changed, 285 insertions, 13 deletions
diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 1e7b10e99e71..fb17d100c518 100644
--- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -667,6 +667,14 @@ TEST(Matcher, VarDecl_Storage) {
EXPECT_TRUE(matches("void f() { static int X; }", M));
}
+TEST(Matcher, VarDecl_IsStaticLocal) {
+ auto M = varDecl(isStaticLocal());
+ EXPECT_TRUE(matches("void f() { static int X; }", M));
+ EXPECT_TRUE(notMatches("static int X;", M));
+ EXPECT_TRUE(notMatches("void f() { int X; }", M));
+ EXPECT_TRUE(notMatches("int X;", M));
+}
+
TEST(Matcher, VarDecl_StorageDuration) {
std::string T =
"void f() { int x; static int y; } int a;static int b;extern int c;";
@@ -765,6 +773,11 @@ TEST(IsArrow, MatchesMemberVariablesViaArrow) {
memberExpr(isArrow())));
EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } int y; };",
memberExpr(isArrow())));
+ EXPECT_TRUE(matches("template <class T> class Y { void x() { this->m; } };",
+ cxxDependentScopeMemberExpr(isArrow())));
+ EXPECT_TRUE(
+ notMatches("template <class T> class Y { void x() { (*this).m; } };",
+ cxxDependentScopeMemberExpr(isArrow())));
}
TEST(IsArrow, MatchesStaticMemberVariablesViaArrow) {
@@ -783,6 +796,14 @@ TEST(IsArrow, MatchesMemberCallsViaArrow) {
memberExpr(isArrow())));
EXPECT_TRUE(notMatches("class Y { void x() { Y y; y.x(); } };",
memberExpr(isArrow())));
+ EXPECT_TRUE(
+ matches("class Y { template <class T> void x() { this->x<T>(); } };",
+ unresolvedMemberExpr(isArrow())));
+ EXPECT_TRUE(matches("class Y { template <class T> void x() { x<T>(); } };",
+ unresolvedMemberExpr(isArrow())));
+ EXPECT_TRUE(
+ notMatches("class Y { template <class T> void x() { (*this).x<T>(); } };",
+ unresolvedMemberExpr(isArrow())));
}
TEST(ConversionDeclaration, IsExplicit) {
@@ -1365,6 +1386,10 @@ TEST(ObjCIvarRefExprMatcher, IvarExpr) {
hasDeclaration(namedDecl(hasName("y"))))));
}
+TEST(BlockExprMatcher, BlockExpr) {
+ EXPECT_TRUE(matchesObjC("void f() { ^{}(); }", blockExpr()));
+}
+
TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) {
EXPECT_TRUE(matches("void f() { }",
compoundStmt(statementCountIs(0))));
@@ -1517,6 +1542,26 @@ TEST(HasObjectExpression, MatchesBaseOfVariable) {
"struct X { int m; }; void f(X* x) { x->m; }",
memberExpr(hasObjectExpression(
hasType(pointsTo(recordDecl(hasName("X"))))))));
+ EXPECT_TRUE(matches("template <class T> struct X { void f() { T t; t.m; } };",
+ cxxDependentScopeMemberExpr(hasObjectExpression(
+ declRefExpr(to(namedDecl(hasName("t"))))))));
+ EXPECT_TRUE(
+ matches("template <class T> struct X { void f() { T t; t->m; } };",
+ cxxDependentScopeMemberExpr(hasObjectExpression(
+ declRefExpr(to(namedDecl(hasName("t"))))))));
+}
+
+TEST(HasObjectExpression, MatchesBaseOfMemberFunc) {
+ EXPECT_TRUE(matches(
+ "struct X { void f(); }; void g(X x) { x.f(); }",
+ memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches("struct X { template <class T> void f(); };"
+ "template <class T> void g(X x) { x.f<T>(); }",
+ unresolvedMemberExpr(hasObjectExpression(
+ hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches("template <class T> void f(T t) { t.g(); }",
+ cxxDependentScopeMemberExpr(hasObjectExpression(
+ declRefExpr(to(namedDecl(hasName("t"))))))));
}
TEST(HasObjectExpression,
@@ -1748,6 +1793,48 @@ TEST(IsInTemplateInstantiation, Sharing) {
Matcher));
}
+TEST(IsInstantiationDependent, MatchesNonValueTypeDependent) {
+ EXPECT_TRUE(matches(
+ "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }",
+ expr(isInstantiationDependent())));
+}
+
+TEST(IsInstantiationDependent, MatchesValueDependent) {
+ EXPECT_TRUE(matches("template<int T> int f() { return T; }",
+ expr(isInstantiationDependent())));
+}
+
+TEST(IsInstantiationDependent, MatchesTypeDependent) {
+ EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
+ expr(isInstantiationDependent())));
+}
+
+TEST(IsTypeDependent, MatchesTypeDependent) {
+ EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
+ expr(isTypeDependent())));
+}
+
+TEST(IsTypeDependent, NotMatchesValueDependent) {
+ EXPECT_TRUE(notMatches("template<int T> int f() { return T; }",
+ expr(isTypeDependent())));
+}
+
+TEST(IsValueDependent, MatchesValueDependent) {
+ EXPECT_TRUE(matches("template<int T> int f() { return T; }",
+ expr(isValueDependent())));
+}
+
+TEST(IsValueDependent, MatchesTypeDependent) {
+ EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
+ expr(isValueDependent())));
+}
+
+TEST(IsValueDependent, MatchesInstantiationDependent) {
+ EXPECT_TRUE(matches(
+ "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }",
+ expr(isValueDependent())));
+}
+
TEST(IsExplicitTemplateSpecialization,
DoesNotMatchPrimaryTemplate) {
EXPECT_TRUE(notMatches(
@@ -2168,6 +2255,18 @@ TEST(IsAssignmentOperator, Basic) {
notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
}
+TEST(HasInit, Basic) {
+ EXPECT_TRUE(
+ matches("int x{0};",
+ initListExpr(hasInit(0, expr()))));
+ EXPECT_FALSE(
+ matches("int x{0};",
+ initListExpr(hasInit(1, expr()))));
+ EXPECT_FALSE(
+ matches("int x;",
+ initListExpr(hasInit(0, expr()))));
+}
+
TEST(Matcher, isMain) {
EXPECT_TRUE(
matches("int main() {}", functionDecl(isMain())));
diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index e521940983b2..1bd4e09e7761 100644
--- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -27,7 +27,7 @@ TEST(Finder, DynamicOnlyAcceptsSomeMatchers) {
nullptr));
// Do not accept non-toplevel matchers.
- EXPECT_FALSE(Finder.addDynamicMatcher(isArrow(), nullptr));
+ EXPECT_FALSE(Finder.addDynamicMatcher(isMain(), nullptr));
EXPECT_FALSE(Finder.addDynamicMatcher(hasName("x"), nullptr));
}
@@ -199,6 +199,40 @@ TEST(Matcher, UnresolvedLookupExpr) {
"-fno-delayed-template-parsing"));
}
+TEST(Matcher, ADLCall) {
+ StatementMatcher ADLMatch = callExpr(usesADL());
+ StatementMatcher ADLMatchOper = cxxOperatorCallExpr(usesADL());
+ auto NS_Str = R"cpp(
+ namespace NS {
+ struct X {};
+ void f(X);
+ void operator+(X, X);
+ }
+ struct MyX {};
+ void f(...);
+ void operator+(MyX, MyX);
+)cpp";
+
+ auto MkStr = [&](std::string Body) -> std::string {
+ std::string S = NS_Str;
+ S += "void test_fn() { " + Body + " }";
+ return S;
+ };
+
+ EXPECT_TRUE(matches(MkStr("NS::X x; f(x);"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("NS::X x; NS::f(x);"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("MyX x; f(x);"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("NS::X x; using NS::f; f(x);"), ADLMatch));
+
+ // Operator call expressions
+ EXPECT_TRUE(matches(MkStr("NS::X x; x + x;"), ADLMatch));
+ EXPECT_TRUE(matches(MkStr("NS::X x; x + x;"), ADLMatchOper));
+ EXPECT_TRUE(notMatches(MkStr("MyX x; x + x;"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("MyX x; x + x;"), ADLMatchOper));
+ EXPECT_TRUE(matches(MkStr("NS::X x; operator+(x, x);"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("NS::X x; NS::operator+(x, x);"), ADLMatch));
+}
+
TEST(Matcher, Call) {
// FIXME: Do we want to overload Call() to directly take
// Matcher<Decl>, too?
@@ -422,10 +456,17 @@ TEST(UnaryExprOrTypeTraitExpr, MatchesSizeOfAndAlignOf) {
TEST(MemberExpression, DoesNotMatchClasses) {
EXPECT_TRUE(notMatches("class Y { void x() {} };", memberExpr()));
+ EXPECT_TRUE(notMatches("class Y { void x() {} };", unresolvedMemberExpr()));
+ EXPECT_TRUE(
+ notMatches("class Y { void x() {} };", cxxDependentScopeMemberExpr()));
}
TEST(MemberExpression, MatchesMemberFunctionCall) {
EXPECT_TRUE(matches("class Y { void x() { x(); } };", memberExpr()));
+ EXPECT_TRUE(matches("class Y { template <class T> void x() { x<T>(); } };",
+ unresolvedMemberExpr()));
+ EXPECT_TRUE(matches("template <class T> void x() { T t; t.f(); }",
+ cxxDependentScopeMemberExpr()));
}
TEST(MemberExpression, MatchesVariable) {
@@ -435,6 +476,13 @@ TEST(MemberExpression, MatchesVariable) {
matches("class Y { void x() { y; } int y; };", memberExpr()));
EXPECT_TRUE(
matches("class Y { void x() { Y y; y.y; } int y; };", memberExpr()));
+ EXPECT_TRUE(matches("template <class T>"
+ "class X : T { void f() { this->T::v; } };",
+ cxxDependentScopeMemberExpr()));
+ EXPECT_TRUE(matches("template <class T> class X : T { void f() { T::v; } };",
+ cxxDependentScopeMemberExpr()));
+ EXPECT_TRUE(matches("template <class T> void x() { T t; t.v; }",
+ cxxDependentScopeMemberExpr()));
}
TEST(MemberExpression, MatchesStaticVariable) {
@@ -746,23 +794,23 @@ TEST(Matcher, Initializers) {
has(
designatedInitExpr(
designatorCountIs(2),
- has(floatLiteral(
+ hasDescendant(floatLiteral(
equals(1.0))),
- has(integerLiteral(
+ hasDescendant(integerLiteral(
equals(2))))),
has(
designatedInitExpr(
designatorCountIs(2),
- has(floatLiteral(
+ hasDescendant(floatLiteral(
equals(2.0))),
- has(integerLiteral(
+ hasDescendant(integerLiteral(
equals(2))))),
has(
designatedInitExpr(
designatorCountIs(2),
- has(floatLiteral(
+ hasDescendant(floatLiteral(
equals(1.0))),
- has(integerLiteral(
+ hasDescendant(integerLiteral(
equals(0)))))
)))));
}
@@ -1133,6 +1181,14 @@ TEST(ParenExpression, SimpleCases) {
parenExpr()));
}
+TEST(ParenExpression, IgnoringParens) {
+ EXPECT_FALSE(matches("const char* str = (\"my-string\");",
+ implicitCastExpr(hasSourceExpression(stringLiteral()))));
+ EXPECT_TRUE(matches(
+ "const char* str = (\"my-string\");",
+ implicitCastExpr(hasSourceExpression(ignoringParens(stringLiteral())))));
+}
+
TEST(TypeMatching, MatchesTypes) {
EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
}
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 3b8f362101a6..5f6ecc0d0b8b 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -406,9 +406,22 @@ TEST(Matcher, AnyArgument) {
auto HasArgumentY = hasAnyArgument(
ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));
StatementMatcher CallArgumentY = callExpr(HasArgumentY);
+ StatementMatcher CtorArgumentY = cxxConstructExpr(HasArgumentY);
+ StatementMatcher UnresolvedCtorArgumentY =
+ cxxUnresolvedConstructExpr(HasArgumentY);
StatementMatcher ObjCCallArgumentY = objcMessageExpr(HasArgumentY);
EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY));
EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY));
+ EXPECT_TRUE(matches("struct Y { Y(int, int); };"
+ "void x() { int y; (void)Y(1, y); }",
+ CtorArgumentY));
+ EXPECT_TRUE(matches("struct Y { Y(int, int); };"
+ "void x() { int y; (void)Y(y, 42); }",
+ CtorArgumentY));
+ EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(1, y); }",
+ UnresolvedCtorArgumentY));
+ EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(y, 42); }",
+ UnresolvedCtorArgumentY));
EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end "
"void x(I* i) { int y; [i f:y]; }",
ObjCCallArgumentY));
@@ -416,6 +429,12 @@ TEST(Matcher, AnyArgument) {
"void x(I* i) { int z; [i f:z]; }",
ObjCCallArgumentY));
EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));
+ EXPECT_TRUE(notMatches("struct Y { Y(int, int); };"
+ "void x() { int y; (void)Y(1, 2); }",
+ CtorArgumentY));
+ EXPECT_TRUE(notMatches("template <class Y>"
+ "void x() { int y; (void)Y(1, 2); }",
+ UnresolvedCtorArgumentY));
StatementMatcher ImplicitCastedArgument = callExpr(
hasAnyArgument(implicitCastExpr()));
@@ -1302,6 +1321,45 @@ TEST(IgnoringImplicit, MatchesImplicit) {
varDecl(has(ignoringImplicit(cxxConstructExpr())))));
}
+TEST(IgnoringImplicit, MatchesNestedImplicit) {
+ StringRef Code = R"(
+
+struct OtherType;
+
+struct SomeType
+{
+ SomeType() {}
+ SomeType(const OtherType&) {}
+ SomeType& operator=(OtherType const&) { return *this; }
+};
+
+struct OtherType
+{
+ OtherType() {}
+ ~OtherType() {}
+};
+
+OtherType something()
+{
+ return {};
+}
+
+int main()
+{
+ SomeType i = something();
+}
+)";
+ EXPECT_TRUE(matches(Code, varDecl(
+ hasName("i"),
+ hasInitializer(exprWithCleanups(has(
+ cxxConstructExpr(has(expr(ignoringImplicit(cxxConstructExpr(
+ has(expr(ignoringImplicit(callExpr())))
+ )))))
+ )))
+ )
+ ));
+}
+
TEST(IgnoringImplicit, DoesNotMatchIncorrectly) {
EXPECT_TRUE(
notMatches("class C {}; C a = C();", varDecl(has(cxxConstructExpr()))));
@@ -1516,13 +1574,16 @@ TEST(SwitchCase, MatchesEachCase) {
ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt()))))));
EXPECT_TRUE(matches("void x() { switch(42) { case 1+1: case 4:; } }",
switchStmt(forEachSwitchCase(
- caseStmt(hasCaseConstant(integerLiteral()))))));
+ caseStmt(hasCaseConstant(
+ constantExpr(has(integerLiteral()))))))));
EXPECT_TRUE(notMatches("void x() { switch(42) { case 1+1: case 2+2:; } }",
switchStmt(forEachSwitchCase(
- caseStmt(hasCaseConstant(integerLiteral()))))));
+ caseStmt(hasCaseConstant(
+ constantExpr(has(integerLiteral()))))))));
EXPECT_TRUE(notMatches("void x() { switch(42) { case 1 ... 2:; } }",
switchStmt(forEachSwitchCase(
- caseStmt(hasCaseConstant(integerLiteral()))))));
+ caseStmt(hasCaseConstant(
+ constantExpr(has(integerLiteral()))))))));
EXPECT_TRUE(matchAndVerifyResultTrue(
"void x() { switch (42) { case 1: case 2: case 3: default:; } }",
switchStmt(forEachSwitchCase(caseStmt().bind("x"))),
diff --git a/unittests/ASTMatchers/CMakeLists.txt b/unittests/ASTMatchers/CMakeLists.txt
index ae1aecf503cc..4e44c795f894 100644
--- a/unittests/ASTMatchers/CMakeLists.txt
+++ b/unittests/ASTMatchers/CMakeLists.txt
@@ -24,6 +24,7 @@ target_link_libraries(ASTMatchersTests
clangASTMatchers
clangBasic
clangFrontend
+ clangSerialization
clangTooling
)
diff --git a/unittests/ASTMatchers/Dynamic/CMakeLists.txt b/unittests/ASTMatchers/Dynamic/CMakeLists.txt
index 0fd96e97cff0..07742caef658 100644
--- a/unittests/ASTMatchers/Dynamic/CMakeLists.txt
+++ b/unittests/ASTMatchers/Dynamic/CMakeLists.txt
@@ -15,5 +15,6 @@ target_link_libraries(DynamicASTMatchersTests
clangBasic
clangDynamicASTMatchers
clangFrontend
+ clangSerialization
clangTooling
)
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
index d670e3129b80..9e891069c862 100644
--- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -148,8 +148,8 @@ TEST(ParserTest, ParseMatcher) {
const uint64_t ExpectedBar = Sema.expectMatcher("Bar");
const uint64_t ExpectedBaz = Sema.expectMatcher("Baz");
Sema.parse(" Foo ( Bar ( 17), Baz( \n \"B A,Z\") ) .bind( \"Yo!\") ");
- for (size_t i = 0, e = Sema.Errors.size(); i != e; ++i) {
- EXPECT_EQ("", Sema.Errors[i]);
+ for (const auto &E : Sema.Errors) {
+ EXPECT_EQ("", E);
}
EXPECT_NE(ExpectedFoo, ExpectedBar);
@@ -181,6 +181,21 @@ TEST(ParserTest, ParseMatcher) {
EXPECT_EQ("Yo!", Foo.BoundID);
}
+TEST(ParserTest, ParseComment) {
+ MockSema Sema;
+ Sema.expectMatcher("Foo");
+ Sema.parse(" Foo() # Bar() ");
+ for (const auto &E : Sema.Errors) {
+ EXPECT_EQ("", E);
+ }
+
+ EXPECT_EQ(1ULL, Sema.Matchers.size());
+
+ Sema.parse("Foo(#) ");
+
+ EXPECT_EQ("1:4: Error parsing matcher. Found end-of-code while looking for ')'.", Sema.Errors[1]);
+}
+
using ast_matchers::internal::Matcher;
Parser::NamedValueMap getTestNamedValues() {
@@ -359,6 +374,44 @@ TEST(ParserTest, CompletionNamedValues) {
Comps[2].MatcherDecl);
}
+TEST(ParserTest, ParseBindOnLet) {
+
+ auto NamedValues = getTestNamedValues();
+
+ Diagnostics Error;
+
+ {
+ llvm::Optional<DynTypedMatcher> TopLevelLetBinding(
+ Parser::parseMatcherExpression("hasParamA.bind(\"parmABinding\")",
+ nullptr, &NamedValues, &Error));
+ EXPECT_EQ("", Error.toStringFull());
+ auto M = TopLevelLetBinding->unconditionalConvertTo<Decl>();
+
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "void foo(int a);", M,
+ llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+ EXPECT_TRUE(matchAndVerifyResultFalse(
+ "void foo(int b);", M,
+ llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+ }
+
+ {
+ llvm::Optional<DynTypedMatcher> NestedLetBinding(
+ Parser::parseMatcherExpression(
+ "functionDecl(hasParamA.bind(\"parmABinding\"))", nullptr,
+ &NamedValues, &Error));
+ EXPECT_EQ("", Error.toStringFull());
+ auto M = NestedLetBinding->unconditionalConvertTo<Decl>();
+
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "void foo(int a);", M,
+ llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+ EXPECT_TRUE(matchAndVerifyResultFalse(
+ "void foo(int b);", M,
+ llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+ }
+}
+
} // end anonymous namespace
} // end namespace dynamic
} // end namespace ast_matchers
diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
index aae229bd045a..1ca394d8d8c3 100644
--- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -440,7 +440,8 @@ TEST_F(RegistryTest, Errors) {
Error.get()).isNull());
EXPECT_EQ("Incorrect type for arg 1. "
"(Expected = Matcher<CXXRecordDecl>) != "
- "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
+ "(Actual = Matcher<CXXRecordDecl>&Matcher"
+ "<MemberExpr|UnresolvedMemberExpr|CXXDependentScopeMemberExpr>)",
Error->toString());
}