mikecrowe added inline comments.

================
Comment at: 
clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp:188
+                              callee(functionDecl(hasName("::std::format")))),
+                        hasAnyArgument(materializeTemporaryExpr(
+                            has(StringCStrCallExpr))))),
----------------
njames93 wrote:
> mikecrowe wrote:
> > njames93 wrote:
> > > The limitation about only transforming the first argument can be 
> > > alleviated by using the `forEachArgumentWithParam` matcher
> > Thanks for the hint. I did try to overcome this limitation but failed to 
> > find `forEachArgumentWithParam`.
> > 
> > I think that I've managed to make `forEachArgumentWithParam` work, but only 
> > if I lose the `materializeTemporaryExpr`. I hope that's not essential. I've 
> > ended up with:
> > 
> > ```C++
> >   Finder->addMatcher(                                                       
> >                                                                             
> >                                                    
> >     traverse(TK_AsIs,                                                       
> >                                                                             
> >                                                    
> >              callExpr(callee(functionDecl(hasAnyName("::std::print", 
> > "::std::format"))),                                                         
> >                                                           
> >                       forEachArgumentWithParam(StringCStrCallExpr, 
> > parmVarDecl()))),                                                           
> >                                                             
> >     this);                                                                  
> >                                                                             
> >                                                    
> > ```
> > I suspect that there's something better than the `parmVarDecl()` second 
> > parameter to `forEachArgumentWithParam` though.
> `parmVarDecl` is exactly what you need here.
> 
> My understanding of the temporary expressions isn't perfect, but from what I 
> can gather, we shouldn't need temporaries when calling the `.c_str()`method 
> for all but the first argument.
> 
> This does highlight an issue with your test code though.
> `std::format` and `std::print` take a `std::format_string` as the first 
> argument, but in your tests you have it as `const char *`
> Anyway I think this means the first argument in real world code would result 
> in a `materializeTemporaryExpr`
> See [[ https://en.cppreference.com/w/cpp/utility/format/basic_format_string | 
> here ]]
I mentioned that I'd failed to use a genuine type for the first parameter in my 
commit message. However, I've now tried again, and I think that I've got 
something working that is much closer to that required by the standard.

I tried to come up with something that I could call `c_str()` on to pass as the 
first argument, but couldn't come up with anything that g++ thought was a 
constant expression. I tried:
```
consteval std::string f()                                                       
                                                                                
                                             {                                  
                                                                                
                                                                                
          
    return {"Hi {}"};                                                           
                                                                                
                                             
}                                                                               
                                                                                
                                             

    std::puts(std::format(f().c_str(), get().c_str());                          
                                                                                
                                             
```
but g++ still claims:
```
format.cpp:22:28: error: 
‘std::string{std::__cxx11::basic_string<char>::_Alloc_hider{((char*)(&<anonymous>.std::__cxx11::basic_string<char>::<anonymous>.std::__cxx11::basic_string<char>::<unnamed
 union>::_M_local_buf))}, 5, std::__cxx11::basic_string<char>::<unnamed 
union>{char [16]{'H', 'i', ' ', '{', '}', 0, '\000', '\000', '\000', '\000', 
'\000', '\000', '\000', '\000', '\000', '\000'}}}’ is not a constant expression
   22 |     std::puts(std::format(f().c_str(), get().c_str());
      |                           ~^~
```
So I think that the risk of inadvertently removing `c_str()` from the first 
argument is low, given that such a call appears not to be legal anyway. Even if 
there does turn out to be a way to do so, I think that removing the `c_str()` 
call probably ought to be expected to work too.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143342/new/

https://reviews.llvm.org/D143342

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to