Index: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp @@ -443,17 +443,22 @@ for (const std::vector &Arg : ArgsKinds) { if (&Arg != &ArgsKinds[0]) OS << ", "; - // This currently assumes that a matcher may not overload a - // non-matcher, and all non-matcher overloads have identical - // arguments. - if (Arg[0].getArgKind() == ArgKind::AK_Matcher) { - std::set MatcherKinds; - std::transform(Arg.begin(), Arg.end(), - std::inserter(MatcherKinds, MatcherKinds.end()), - std::mem_fun_ref(&ArgKind::getMatcherKind)); + + bool FirstArgKind = true; + std::set MatcherKinds; + // Two steps. First all non-matchers, then matchers only. + for (const ArgKind &AK : Arg) { + if (AK.getArgKind() == ArgKind::AK_Matcher) { + MatcherKinds.insert(AK.getMatcherKind()); + } else { + if (!FirstArgKind) OS << "|"; + FirstArgKind = false; + OS << AK.asString(); + } + } + if (!MatcherKinds.empty()) { + if (!FirstArgKind) OS << "|"; OS << "Matcher<" << MatcherKinds << ">"; - } else { - OS << Arg[0].asString(); } } } Index: cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp =================================================================== --- cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -438,10 +438,18 @@ TEST_F(RegistryTest, Completion) { CompVector Comps = getCompletions(); + // Overloaded EXPECT_TRUE(hasCompletion( Comps, "hasParent(", "Matcher hasParent(Matcher)")); + // Variadic. EXPECT_TRUE(hasCompletion(Comps, "whileStmt(", "Matcher whileStmt(Matcher...)")); + // Polymorphic. + EXPECT_TRUE(hasCompletion( + Comps, "hasDescendant(", + "Matcher " + "hasDescendant(Matcher)")); CompVector WhileComps = getCompletions("whileStmt", 0); @@ -470,6 +478,12 @@ hasCompletion(NamedDeclComps, "isPublic()", "Matcher isPublic()")); EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"", "Matcher hasName(string)")); + + // Heterogeneous overloads. + Comps = getCompletions("classTemplateSpecializationDecl", 0); + EXPECT_TRUE(hasCompletion( + Comps, "isSameOrDerivedFrom(", + "Matcher isSameOrDerivedFrom(string|Matcher)")); } TEST_F(RegistryTest, HasArgs) {