Bug? CXXCtorInitializer::getInit()


I am using CXXCtorInitializer’s method getInit() to retrieve its Init Stmt*.
The CXXCtorInitializer::Init field is described as followed:

“The argument used to initialize the base or member, which may end up constructing an object (when multiple arguments are involved).”

In my usecase I actually want to retrieve the underlying source text, that is represented by Init.

This works fine for simple Initializers using declRefExpr or integerLiterals.

Retrieving the source’s text for the Init expr returns i and 10 for the following CXXCtorInitializer:

SomeConstructor(int i):m_foo(i), m_bar(10){}

I haven’t figured out what exactly is the problem, but as far as I can tell the Init pointer appears faulty in some cases when there is a CXXConstructExpr involved.


struct T {};
struct Foo{
Foo(T t): t0(new T()), t1({}), t2(t){}
T * t0;
T t1;
T t2;

Retrieving the Init and it’s underlying source text returns:
for t0: “new T()” <----- as expected :slight_smile:
for t1: “t1({})” <----- expected: “{}
for t2: “t2(t)” <---- expected: “t

Since the Docu states, the Init gives the *"*argument used to initialize the […] member" I think this might be a bug? Maybe I don’t retrieve the source code correctly, but in any other case it appears to work just fine.

I use the Lexer to get to the Init’s source like this, where expr is cxxCtorInitializer->getInit():

Lexer::getSourceText(CharSourceRange::getCharRange(expr->getSourceRange()), ctxt.getSourceManager(), ctxt.getLangOpts());

So is this expected behavior? If so why? And how can I get to the actual ‘Initializer’ in those cases?

Any help appreciated!

I don’t think there is a bug in this case. The argument of the initialiser is indeed “empty bracket uniform initialiser curly moustache pair” or “DeclRefExpr to the variable named t” in your t1 and t2 case. Because the initialiser expression is the thing between the brackets. The remaining part is an “instruction” (purposefully not saying statement here) that tells the compiler that the given expression should be used to initialise the given variable.

It’s like saying “T t = new T();”. “new T()” is the constructing expression here, not the whole line. The whole line is the one that defines (and equal-initialises) the variable.

However, ‘CXXCtorInitializer’ has a ‘getSourceRange()’ method, per documentation “Determine the source range covering the entire initializer.”. You might have some luck with that.
According to the code, it goes matching the rightmost parenthesis of the initialiser. (And in case you use member-init-expressions in a record, it will use the something like the “= 123812” part.)

Julian Mueller via cfe-dev <cfe-dev@lists.llvm.org> ezt írta (időpont: 2018. dec. 21., P, 11:46):