c++clangabstract-syntax-treeclang-query

Get classes with at least two same access specifiers with ASTMatcher


I need to catch cases in C++ code when there are two or more similar access specifiers in the class. Let's say there are two classes

class A{
public:
    int b;
public:
    int a;
}

class B{
public:
    int a;
}

How to match class A (because it has two 'public's) but not class B with ASTMatcher?


Solution

  • This matcher grabs the 'public' declaration:

    accessSpecDecl(
      isPublic(),
      hasAncestor(cxxRecordDecl().bind("crd"))).bind("asd")
    

    In the callback class, you can track the number of hits the matcher gets for a given struct declaration, for example with a std::map<string,int>:

    struct report_public : public MatchCallback{
      using map_t = std::map<string,int>;
      using map_it = map_t::iterator;
    
      map_t count;
    
      void run(MatchResult const & result){
        AccessSpecDecl const * asd = result.Nodes.getNodeAs<AccessSpecDecl>("asd");
        CXXRecordDecl const * crd = result.Nodes.getNodeAs<CXXRecordDecl>("crd");
        if(asd && crd){
          string const struct_name = crd->getNameAsString();
          map_it it = count.find(struct_name);
          if(it != count.end()) count[struct_name]++;
          else count[struct_name] = 1;
        }
        else { /* error handling */}
        return;
      } // run
    }; // report_public