Link to this pointer: GCC vs clang

This is a continuation of these questions .

Consider the following code:

struct A { private: A* const& this_ref{this}; }; int main() { A a{}; (void)a; } 

If compiled with -Wextra , GCC v6.2 and clang v3.9. 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 does not give any warning, clang gives the same warning as in the previous example.

The warnings are almost identical.
He follows someone from clang:

3: warning: bind reference element 'this_ref' to temporary value [-Wdangling-field]

Which compiler is right?

I would say that GCC is wrong in this case, and I open the problem, but, possibly, on the contrary, because of the secret corner of the language.

+7
c ++ gcc language-lawyer clang this-pointer
source share
3 answers

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

The temporary binding to the reference element in the ctor-initializer constructor (12.6.2) is preserved until the constructor outputs.

and since the keyword is a prvalue expression , during the initialization of this_ref , a temporary this_ref is created and this_ref tied to this temporary character.

But I have doubts whether your link is really initialized in ctor-initializer .

If you write:

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

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

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

+1
source share

Member Announcement

 A* const& this_ref{this}; 

binds a temporary reference that exists only when the constructor is executed (note: this is an rvalue expression).

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

Re

" Which compiler is right?

& hellip; the compiler can produce as many diagnostic tools as it wants. Incorrect diagnosis. Therefore, in your description that both accept the code, then either both compilers are right (which, I think, most likely), or both are incorrect.

+2
source share

this prvalue and the temporary object will be created when the reference is bound to prvalue, so you will bind the reference element to the temporary element in the default element initiator .

And the binding of the reference element to the temporary element initializer by default is poorly formed, which is explicitly specified in the standard.

$ 12.6.2 / 11 Initialization of the bases and members [Class.base.init] :

A temporary expression bound to a reference element by default, the initializer member is poorly formed. [Example:

 struct A { A() = default; // OK A(int v) : v(v) { } // OK const int& v = 42; // OK }; A a1; // error: ill-formed binding of temporary to reference A a2(1); // OK, unfortunately 

- end of example]

And look at CWG 1696 , this applies to C ++ 14.

+1
source share

All Articles