The AST for explicit template instantiations is slightly different
from the source code (see note below): there is no AST node for explicit template
instantiations, so regular ast matchers like typeLoc can't find the
type which is referenced in template arguments of an explicit template
instantiations.
Our workaround is to record all declarations referenced from template arguments
of explicit template instantiations and the instantiation source location of
instantiations, and assumes that the using-decl is used when the using-decl's
source location is before the instantiation source location.
While the workaround avoids false positives, it may introduce true negatives.
but this case rarely happens and users won't get bothered by true positives (No
warning message is print by the check).
Note:
// NamespaceDecl 0x7f875981e798 </tmp/t.cc:1:1, line:3:1> line:1:11 ns // | `-CXXRecordDecl 0x7f875a02f400 <line:2:1, col:10> col:7 referenced class A definition // | `-CXXRecordDecl 0x7f875a02f520 <col:1, col:7> col:7 implicit class A // |-FunctionTemplateDecl 0x7f875a02f768 <line:4:1, line:6:1> line:5:6 test // | |-TemplateTypeParmDecl 0x7f875a02f5b8 <line:4:10, col:16> col:16 class T // | |-FunctionDecl 0x7f875a02f6c0 <line:5:1, line:6:1> line:5:6 test 'void (void)' // | | `-CompoundStmt 0x7f875a02f7f8 <col:13, line:6:1> // | `-FunctionDecl 0x7f875a02f9d0 <line:5:1, line:6:1> line:5:6 test 'void (void)' // | |-TemplateArgument type 'class ns::A' // | `-CompoundStmt 0x7f875a02f7f8 <col:13, line:6:1> // |-UsingDecl 0x7f875a02f830 <line:7:1, col:11> col:11 ns::A // `-UsingShadowDecl 0x7f875a02f880 <col:11> col:11 implicit CXXRecord 0x7f875a02f400 'A' // `-RecordType 0x7f875a02f4a0 'class ns::A' // `-CXXRecord 0x7f875a02f400 'A' namespace ns { class A {}; } template<class T> void test() { } using ns::A; template void test<A>();