﻿id	summary	reporter	owner	description	type	status	priority	component	version	resolution	keywords	cc
305	Rvalue-to-reference promotion circumvents RAII	mlbrooks		"For background, present-state rvalue-to-reference promotion allows this case:

{{{
int foo() {
    return 42;
}
int & x = foo();
// ... call whatever else
printf(""%d\n"", x); // 42
}}}

Ongoing work to rule out certain cases may consider ruling out this case too.

Perhaps surprisingly, present-state handling does not consider this arrangment to be an instant memory error.  The returned value's lifetime is not limited to the call expression; the value lives in a hoised temporary with lifetime roughly block scope.

As it is, objects like this returned 42, should they have RAII, miss an RAII callback step.  A demo follows.

First, we need an object that logs its RAII calls (included for reproduction, can skip on reading):

{{{
struct Obj { 
    int idCopied;
    int idNotCopied;
};

int nextIdCopied = 1;
int nextIdNotCopied = 1;

ptrdiff_t getRelativeAddr( void * addr ) {
    size_t addrVal = (size_t) addr;
    static size_t refAddr = 0;
    if (refAddr == 0 ) refAddr = addrVal;
    return refAddr - addrVal;
}

void ?{}( Obj & this ) {
    this.idCopied = nextIdCopied;
    this.idNotCopied = nextIdNotCopied;
    nextIdCopied += 1;
    nextIdNotCopied += 1;
    printf(""ctor dflt @%+6zd, $%d, #%d\n"", getRelativeAddr(&this), this.idCopied, this.idNotCopied);
}

void ?{}( Obj & this, Obj src ) {
    this.idCopied = src.idCopied;
    this.idNotCopied = nextIdNotCopied;
    nextIdNotCopied += 1;
    printf(""ctor copy @%+6zd, $%d, #%d:=#%d\n"", getRelativeAddr(&this), this.idCopied, this.idNotCopied, src.idNotCopied);
}

void ^?{}( Obj & this ) {
    printf(""dtor      @%+6zd, $%d, #%d\n"", getRelativeAddr(&this), this.idCopied, this.idNotCopied);
}

void observe( Obj & this ) {
    printf(""observe   @%+6zd, $%d, #%d\n"", getRelativeAddr(&this), this.idCopied, this.idNotCopied);
}

Obj bar() {
    return (Obj){};
}
}}}

Now the real test harness:
{{{
printf(""==== Case 1, baseline\n"");
{
    Obj o1 = bar();
    observe(o1);
}
printf(""==== Case 2, SUT\n"");
{
    Obj & o2 = bar();
    observe(o2);
}
}}}

Output key:
@_ is an address offset from an arbitrary point
$_ is a value carried in an object and kept by all its copies
#_ is like a version number, different for each ctor-defined copy

Actual: Runs with output
{{{
==== Case 1, baseline
ctor dflt @    +0, $1, #1
ctor copy @    +8, $1, #2:=#1
dtor      @    +0, $1, #1
ctor copy @  -136, $1, #3:=#2
dtor      @  -144, $1, #2
observe   @  -136, $1, #3
dtor      @  -136, $1, #3
==== Case 2, SUT
ctor dflt @    +0, $2, #4
ctor copy @    +8, $2, #5:=#4
dtor      @    +0, $2, #4
observe   @  -144, $2, #5
dtor      @  -144, $2, #5
}}}

Expected: Runs with case-1 output as-is, case-2 shows same variable/RAII pattern as case-1;  OR  compile error that returned values cannot be saved in reference variables

Further background:

All copy ctors have the anomaly that the src is just bits at a meaningless address (not even shown in output),
for which no lifecycle-maintence occurs.  Work is in progress to fix it (change copy ctor signature to use const reference for `src` argument).

Baseline has the known anomaly that `#2` shows up at a different address (`dtor @-144`) than where it was created (`ctor @+8`).  It's not desired, but a fix is not coming soon (requires custom ABI or using the Box Pass in more cases).  ""Expected"" outcome statement assumes present-state on this matter.  The good being illustrated is that `observe`, a user's function, sees an address (`#3 @-136`) that got a lifecycle maintenance call (`copy ctor #3 @-136`).
The anomaly is contained to phenomena seen by the RAII routines, meaning it's just a limitation on what kinds of RAII can be used along with returning by value.

Illustration of the issue with rvalue-to-reference promotion:

SUT has an anomaly that `observe`, a user's function, sees an address (`#5 @-144`) never before ""made right"" by lifecycle maintenance.  So, an object that contains references into itself, which normally can be returned by value (provided that its RAII accommodates the baseline anomaly), presents garbage if the returned value is stored in a reference.
"	defect	new	major	cfa-cc	1.0		rvalue reference raii	
