﻿id	summary	reporter	owner	description	type	status	priority	component	version	resolution	keywords	cc
291	Cannot Lift Reference Initialization	ajbeach		"The initial symptom of this error is a problem in the box pass. But that is because of a floating node, which you can catch with the invariant check, revealing that it comes from Fix Init.

Here is code to reproduce the error:
{{{
int var = 4;

int & getVar() {
    return var;
}

int & ref = getVar();
}}}

There are various ways this can cause errors, but the root cause seems to be fairly consistent. That is reference initializers cannot be hoisted into the `__global_init__` function. This decision is made inside the resolver even though the actual lifting happens later.

The decision is communicated from the resolver to the hoisting pass (Fix Global Init, part of Fix Init) by wrapping the initializer in a ConstructorInit. There are two sets of fields on the ConstructorInit, ctor/dtor for a managed type and init for an unmanaged type.

At least that appears to be the intent, a lone Init couldn't be hoisted to an assignment as is, but also that entire option isn't used here so that is just a guess at what the intent is. The result is that only constructors are hoisted.

On a very basic level, all non-constant expressions need to be hoisted, because C will not evaluate them at the global scope. All functions are not constant, hence all constructors are not constant and do need to be hoisted. However, some non-constructor initializers also need to be lifted.

Original issue was discovered with the following example. This has the issue with a non-constant expressions but also some polymorphic code that is not specialized outside of a function and a temporary value that is lost with no block to insert it into.
{{{
#include <stdlib.hfa>

struct S {
    int x;
};

S & s = (*malloc()){ 2 };
}}}"	defect	new	major	cfa-cc	1.0			
