Initializer expression SourceRange differs between c++14 and c++17, affecting clang-tidy

When parsing a named declaration with an equals sign with clang -std c++11/14, clang builds an initializer expression whose SourceRange covers from the variable name through the end of the initial value:

std::string foo = “bar”;

^~~~~~~~~~~

When parsing the same code with clang -std c++17/2x, the initializer expression’s SourceRange only includes the initial value itself, and not the variable name or the equals sign:

std::string foo = “bar”;

^~~~~

If the string is initialized using parentheses rather than an equals sign, in all of c++11/14/17/2x the initializer expression’s SourceRange includes the variable name and both parentheses:

std::string foo(“bar”);

^~~~~~~~~~

This difference has broken clang-tidy’s readability-remove-redundant-string for c++17 and c++2x, as described in at reviews.llvm.org/D69238. Is this SourceRange difference intentional, and if not does anyone have thoughts on how to make the SourceRange consistent across C++ standards? Thanks!

– Conrad

P.S. I’ve tried stepping through clang-tidy parsing the std::string a = “”; line in clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp with -std=c++11 and again with -std=c++17. In both cases Sema::AddInitializerToDecl seems to create a correct InitializationKind with the Locations[0] properly pointing to the start of the variable name. I’m not sure how or where that gets translated to the expression’s SourceRange later on in some way that presumably differs between c++11 and c++17. If this SourceRange difference is unintentional and needs to be tracked down and fixed, any tips on where to look would be appreciated.