[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

Conrad Poelman via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 8 14:15:45 PST 2019


poelmanc added a comment.

In D69238#1736365 <https://reviews.llvm.org/D69238#1736365>, @NoQ wrote:

> I suspect that it's not just the source range, but the whole AST for the initializer is different, due to C++17 mandatory copy elision in the equals-initializer syntax. Like, before C++17 it was a temporary constructor, a temporary materialization (ironic!), and a copy constructor, but in C++17 and after it's a single direct constructor which looks exactly like the old temporary constructor (except not being a `CXXTemporaryObjectExpr`). You're most likely talking about //different construct-expressions// in different language modes.
>
> That said, it should probably be possible to change the source range anyway somehow.


Thanks to all the encouragement here, I spent a few more hours stepping through code and have found a one-line change to clang\lib\Sema\SemaInit.cpp:8053 that fixes this bug! Change:

  SourceLocation Loc = CurInit.get()->getBeginLoc();

to

  SourceLocation Loc = Kind.getLocation();

For `SK_UserConversion`, `CurInit` is set at SemaInit.cpp:7899 to `Args[0]`, i.e. the first argument to the constructor, which is `""` in this case. By changing `Loc` to `Kind.getLocation()`, the `BuildCXXConstructExpr` at SemaInit.cpp:8064 gets created with a SourceRange spanning `a = ""`. With just that change, the SourceRange for an expression like `std::string a = ""` becomes consistent across C++11/14/17/2a and `readability-redundant-string-init` tests pass in all C++ modes (so we can throw away my 70 lines of manual parsing code.)

I have no experience with the clang parsing code so I don't know what other effects this change might have or who else we might want to check with before committing this. Should I change my "diff" here to just that?

> Also i don't see any tests for multiple declarations in a single `DeclStmt`, i.e.
> 
>   string A = "a", B = "";
> 
> 
> ... - which source range do you expect to have if you warn on `B`?

For that example I'd expect the warning source range to cover `B = ""`. `readability-redundant-string-init.cpp` does include tests almost like that: `std::string a = "", b = "", c = "";` warns on 3 separate source ranges, while `std::string d = "u", e = "u", f = "u";` doesn't warn at all. I'm happy to add a line that has some of each. I just added `std::string g = "u", h = "", i = "uuu", j = "", k;` and confirmed that it warns and fixes correctly (in C++11/14 mode it should pass already; in C++17/2a mode it works correctly with the current patch.)


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238





More information about the cfe-commits mailing list