[cfe-dev] MatchFinder returning many duplicate matches

E via cfe-dev cfe-dev at lists.llvm.org
Fri Nov 22 21:36:25 PST 2019

Yes, I'm looking to match the primary template instead of its instantiations.
Agreed, it's bizarre that the isExplicitTemplateSpecialisation() and 
isTemplateInstantiation() don't filter these out.

I also thought about filtering out all templates in the function matcher and then
having a separate matcher for only functionTemplateDecl(). Looks like
there isn't a specific function to filter out templated functions, but perhaps
I could do this by dyn_casting the match result to a functionTemplateDecl() 
and checking if the result is valid. Not a clean solution though.

If someone could take another glance at this I'd appreciate it.


> On Nov 19, 2019, at 22:56, Whisperity <whisperity at gmail.com> wrote:
> If I understand correctly you want to return what's usually referred to as the "primary template"? The program element which is the template itself, not any instantiation:
>     template <int i> f() {}
> There is a big distinction in the language's wording that X-templates are not Xs, only their instantiations are.
> You could try using functionTemplateDecl() for the match. If I understand this correctly, it'll give you the primary templates.
> In case you want, apart from this, the explicit specialisations, there's a predicate isExplicitTemplateSpecialisation() which you used as a filter already. That predicate should apply to the "concrete decl" (as opposed to the template) as explicit specialisations are concrete existing code with no need to instantiate any further.
> From a glance or two I've no idea why your current matcher seems to spew out a lot of nodes still. 
> ;;
> ;; Whisperity.
> On Tue, 19 Nov 2019, 08:56 E via cfe-dev, <cfe-dev at lists.llvm.org> wrote:
> Hello,
> I have a tool that runs over all TUs in a project and matches all function declarations.
> These declarations are then stored in a database for later processing.
> My problem is that the MatchFinder callback returns many duplicates of the same
> function, probably due to the use of templates in the function decl.
> I've provided a sample of duplicate USRs for the from_json function in a test project.
> from_json c:@N at nlohmann@S at adl_serializer>#{n5C#v at FT@>2#T#Tfrom_json#&&t0.0#&t0.1# #S
> from_json c:@N at nlohmann@S at adl_serializer>#{n6C#v at FT@>2#T#Tfrom_json#&&t0.0#&t0.1# #S
> from_json c:@N at nlohmann@S at adl_serializer>#*1C#v at FT@>2#T#Tfrom_json#&&t0.0#&t0.1# #S
> from_json c:@N at nlohmann@S at adl_serializer>#{n7C#v at FT@>2#T#Tfrom_json#&&t0.0#&t0.1# #S
> from_json c:@N at nlohmann@S at adl_serializer>#{n10C#v at FT@>2#T#Tfrom_json#&&t0.0#&t0.1# #S
> from_json c:@N at nlohmann@S at adl_serializer>#{n8C#v at FT@>2#T#Tfrom_json#&&t0.0#&t0.1# #S
> from_json c:@N at nlohmann@S at adl_serializer>#b#v at FT@>2#T#Tfrom_json#&&t0.0#&t0.1# #S
> Based on the USRs, it seems like the MatchFinder considers each template instantiation
> a separate declaration, whereas I'd like it to return a single function decl that is templated.
> Is there a way to eliminate these duplicates during the matching stage?
> I have attached a minimal code example below.
> class FunctionMatcher : public MatchFinder::MatchCallback {
> public:
>     FunctionMatcher() {}
>     DeclarationMatcher matcher = functionDecl(unless(anyOf(isDefinition(),
>                                                         isImplicit(),
>                                                         isInStdNamespace(),
>                                                         isExpansionInSystemHeader(),
>                                                         isTemplateInstantiation(),
>                                                         isExplicitTemplateSpecialization())))
>                                     .bind("function");
>     virtual void run(const MatchFinder::MatchResult& Result) {
>         auto res = Result.Nodes.getNodeAs<clang::FunctionDecl>("function");
>         // Ignore invalid matches
>         if (res == nullptr) {
>             return;
>         }
>         // Print function name and USR
>         llvm::SmallString<128> USR;
>         if (!clang::index::generateUSRForDecl(d, USR)) {
>            printf("%s %s\n", res->getNameAsString().c_str(), USR.str().c_str());
>         }
>     }
> }
> int main() {
>     FunctionMatcher FunctionFinder(&this->index, this->cfg);
>     clang::ast_matchers::MatchFinder         Finder;
>     Finder.addMatcher(FunctionFinder.matcher, &FunctionFinder);
>     auto cmpdb = clang::tooling::CompilationDatabase::loadFromDirectory("test", "err_msg");
>     clang::tooling::ClangTool t(*cmpdb, cmpdb->getAllFiles());
>     t.run(clang::tooling::newFrontendActionFactory(&Finder).get());
> }
> Thanks.
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

More information about the cfe-dev mailing list