[cfe-dev] MatchFinder returning many duplicate matches

E via cfe-dev cfe-dev at lists.llvm.org
Mon Nov 18 23:56:08 PST 2019


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.





More information about the cfe-dev mailing list