Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to the this pointer: GCC vs clang

This is a follow-up of these questions.

Consider the following code:

struct A {
private:
    A* const& this_ref{this};
};

int main() {
    A a{};
    (void)a;
}

If compiled with the -Wextra, both GCC v6.2 and clang v3.9 show a warning.

Anyway, with the slightly modified version shown below they behave differently:

struct A {
    A* const& this_ref{this};
};

int main() {
    A a{};
    (void)a;
}

In this case GCC doesn't give any warning, clang gives the same warning as returned in the previous example.

The warnings are almost the identical.
It follows the one from clang:

3 : warning: binding reference member 'this_ref' to a temporary value [-Wdangling-field]

Which compiler is right?

I would say that GCC is wrong in this case and I were opening an issue, but maybe it's the opposite because of an arcane corner case of the language.

like image 465
skypjack Avatar asked Sep 12 '16 12:09

skypjack


2 Answers

The member declaration

A* const& this_ref{this};

binds a reference to a temporary that only exists during constructor execution (note: this is an rvalue expression).

I'm not sure if this is formally available in that context, but if it is then with any use of that pointer you have serious case of UB.

Re

Which compiler is right?

… a compiler can issue as many diagnostics as it wants. It's not wrong to issue a diagnostic. So per your description, that both accept the code, then either both compilers are right (which I think is most likely), or both are wrong.

like image 195
Cheers and hth. - Alf Avatar answered Oct 16 '22 19:10

Cheers and hth. - Alf


The reason for this warning is IMO this excerpt from standard (12.2.5):

A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.

and since the keyword this is a prvalue expression, during this_ref initialization a temporary will be created and this_ref is bound to that temporary.

But I have doubt whether your reference is actually initialized in ctor-initializer.

If you write:

struct A {
private:
    const int& rr = 1+1;
};

then you will reproduce the exact same problem with gcc, removing private will also remove this warning.

From what I know this pointer might be used in the body of the non-static member function, I have never read that it could be used as argument during default member initialization.

like image 38
marcinj Avatar answered Oct 16 '22 18:10

marcinj