Title
Self-references in trivially copyable objects as function return values
Status
open
Section
6.7.7 [class.temporary]
Submitter
Richard Smith

Created on 2018-02-16.00:00:00 last changed 1 month ago

Messages

Date: 2024-02-28.22:48:17

Suggested resolution:

When an object of class type X is passed to or returned from a function, if X has at least one eligible copy or move constructor (11.4.4 [special]), each such constructor is trivial, and the destructor of X is either trivial or deleted, implementations are permitted to create a temporary object to hold the function parameter or result object. The temporary object is constructed from the function argument or return value, respectively, and the function's parameter or return object is initialized as if by using the eligible trivial constructor to copy the temporary (even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object). The temporary object may occupy the storage that the parameter or return object is going to occupy, but pointers that pointed to the temporary object become invalid pointer values (6.8.4 [basic.compound]) when the parameter or return object is constructed and do not point to the parameter or return object.
Date: 2018-02-16.00:00:00

Consider:

  struct A {
    A *children;
    long long arr[100];

    A() : children() {}
    A(int) : children(this) {}
  };

  __attribute__((noinline))
  A Foo() {
    return A(0);   // #1
  }

  A x[3] = {};

  void Bar(int n) {
    A a = Foo();
    for (int i = 0; i < n; i++) {
      a.children[i].children = x;     // #2
    }
  }

  int main() {
    Bar(3);
    return x[0].children || !x[1].children || !x[2].children;
  }

It ought to be valid to hoist the load of a.children out of the loop. However, guaranteed copy elision is required to apply to #1, making the A objects in Foo and Bar be the same object. An additional temporary copy can be made per 6.7.7 [class.temporary] paragraph 3, but that does not cause the children member of the a variable to become invalid.

History
Date User Action Args
2024-02-28 22:48:17adminsetmessages: + msg7623
2018-02-16 00:00:00admincreate