FWIW, a larger part of your matcher also works fine in clang-query:
$ cat /tmp/q.cc
namespace boost {
template <typename T, typename C>
T lexical_cast(const C&) {
return T();
}
}
namespace std {
template
class basic_string {};
using string = basic_string;
}
int g();
long long f(int p);
using namespace boost;
template
void string_as_T() {
boost::lexical_cast(42);
}
int main() {
string_as_Tstd::string();
boost::lexical_caststd::string(24);
}
$ clang-query /tmp/q.cc – -std=c++11
clang-query> m callExpr(hasDeclaration(functionDecl(returns(hasDeclaration(classTemplateSpecializationDecl(hasName(“std::basic_string”),hasTemplateArgument(0,templateArgument().bind(“char_type”))))),hasName(“boost::lexical_cast”),hasParameter(0, hasType(qualType())))),argumentCountIs(1))
Match #1:
/tmp/q.cc:20:3: note: “root” binds here
boost::lexical_cast(42);
^~~~~~~~~~~~~~~~~~~~~~~~~~
Match #2:
/tmp/q.cc:25:3: note: “root” binds here
boost::lexical_caststd::string(24);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 matches.
clang-query> m callExpr(hasDeclaration(functionDecl(returns(hasDeclaration(classTemplateSpecializationDecl(hasName(“std::basic_string”),hasTemplateArgument(0,templateArgument().bind(“char_type”))))),hasName(“boost::lexical_cast”),hasParameter(0, hasType(qualType())))),argumentCountIs(1),unless(isInTemplateInstantiation()))
Match #1:
/tmp/q.cc:25:3: note: “root” binds here
boost::lexical_caststd::string(24);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 match.
clang-query> ^D
(the first matcher lacks the unless(isInTemplateInstantiation())
part, the second one has it, hence it skips the match in a template instantiation).
The only part of your matcher that is missing from this example is has(substTemplateTypeParmType(isStrictlyInteger()))
that needs a locally-defined matcher isStrictlyInteger()
.