1

I'm trying to match unnecessary calls to c_str() when calling functions that are happy to take the std::string directly so that I can remove the unnecessary call so that I can write a clang-tidy check to automatically turn statements like:

fmt::print("{} {}", s1.c_str(), s2.c_str());

into

fmt::print("{} {}", s1, s2);

Whilst I've been able to come up with a matcher that matches the entire statement, it would be more convenient if I could bind all the c_str calls individually. I've tried

auto StringType = hasUnqualifiedDesugaredType(recordType(hasDeclaration(cxxRecordDecl(
                      hasName("::std::basic_string")))));
auto PrintCall = hasName("::fmt::print");
StatementMatcher CStrMatcher = traverse(                                                                                                                                                                                                                              
      TK_AsIs, callExpr(callee(functionDecl(PrintCall)),                                                                                                                                                                                                                
                        hasAnyArgument(cxxMemberCallExpr(                                                                                                                                                                                                               
                                            callee(cxxMethodDecl(hasName("c_str"))),                                                                                                                                                                                    
                                            on(hasType(StringType))).bind("c_str")))                                                                                                                                                                                    
      );                                                                                                                                                                                                                                                                

but I only get a single match no matter how many arguments call c_str. Is there a way to iterate over the separate argument matches that I've bound, or do I need to iterate over all the arguments (whether they matched or not) myself in the check member?

Mike Crowe
  • 642
  • 6
  • 18

0 Answers0