[cfe-dev] Stumped by codegen for std::initializer_list

John McCall rjmccall at apple.com
Mon Feb 6 18:24:28 PST 2012


On Feb 4, 2012, at 7:06 AM, Sebastian Redl wrote:
> I'm kinda stuck at codegenning std::initializer_list and would appreciate if someone more experienced could give advice.
> 
> Basically, if you initialize a std::initializer_list object from an initializer list, like so:
> 
> std::initializer_list<int> il = { 1, 2, 3 };
> 
> we are supposed to create a hidden array int[3], initialize that with the init list, and then have the std::initlist point at the array. The lifetime of this hidden array (and its contained objects) is incorrectly specified at the moment, but is probably supposed to be the same as if it was a temporary that is bound to a reference, that reference being the initializer_list object.
> 
> In other words, for the above, the array has the same lifetime as il (automatic or static), whereas if the initializer_list is a temporary, so is the array:
> 
> void fn1(std::initializer_list<int>);
> fn1({1, 2, 3}); // array (and elements) destroyed at end of full-expression
> 
> void fn2(std::vector<int>);
> fn2({1, 2, 3}); // initializer_list created as an argument for the vector constructor, same lifetime.
> 
> new std::initializer_list<int> {1, 2, 3}; // array destroyed at end of full-expression (evil!)
> 
> 
> My AST for this is just an InitListExpr containing the individual object expressions, wrapped in an ExprWithCleanups if the element type has a destructor (which is the interesting case).
> 
> So far I've tried to modify AggExprEmitter::VisitInitListExpr, marking init lists for std::initializer_list in the AST, and emitting the temporary array. However, I just don't see a way to get the lifetime right in this case.
> My other idea is to modify CodeGenFunction::EmitReferenceBindingToInit to deal with std::initializer_list kind of like with references, but that doesn't seem like a particularly good approach either, and I don't see how I would avoid massive code duplication with the subexpression case.
> 
> So, where and how is the best way to modify CodeGen for this?

Does this apply recursively?  i.e. if you have a std::initializer_list<std::initializer_list<std::string>>, should both levels of array be implicitly extended?

Also, what happens in cases of copy elision of the intiializer_list object?  e.g.
  auto list = (std::initializer_list<std::string>) { "" };

I don't see any great solutions beyond special-casing the emission of local and global variables of std::initializer_list type, unless it's to create a special AST node or something (or a flag?) to mark the special kind of construction (which shouldn't be *too* difficult, since it's a special case of initialization already).  That won't really help with the copy-elision case, though.

John.



More information about the cfe-dev mailing list