This is an archive of the discontinued LLVM Phabricator instance.

[ObjC][CodeGen] Remove an assert that is no longer correct.
ClosedPublic

Authored by ahatanak on May 6 2016, 9:17 PM.

Details

Summary

The assert was committed in r183967. After r231508 made changes to promote constant temporaries to globals, the assert fires when a std::initializer_list is constructed using Objective-C string literals:

void foo1() {

std::vector<NSString*> strs = {@"a", @"b"};

}

rdar://problem/25504992
rdar://problem/25955179

Diff Detail

Repository
rL LLVM

Event Timeline

ahatanak updated this revision to Diff 56492.May 6 2016, 9:17 PM
ahatanak retitled this revision from to [ObjC][CodeGen] Remove an assert that is no longer correct..
ahatanak updated this object.
ahatanak added reviewers: rjmccall, rsmith, manmanren.
ahatanak added a subscriber: cfe-commits.
manmanren edited edge metadata.May 10 2016, 9:13 AM

After r231508 made changes to promote constant temporaries to globals, the assert fires when a std::initializer_list is constructed using Objective-C string literals.

--> Can you explain the code path after r231508 for your example? Will r231508 change the code path if we start with a global?
r231508 seems to change the behavior constant temporaries only.

Thanks for working on this!
Manman

lib/CodeGen/CGExpr.cpp
364 ↗(On Diff #56492)

Can you add comments here?

ahatanak updated this revision to Diff 57088.May 12 2016, 12:51 PM
ahatanak edited edge metadata.

Add a comment explaining why it is OK to return early if the global variable has an initializer.

After r231508 made changes to promote constant temporaries to globals, the assert fires when a std::initializer_list is constructed using Objective-C string literals.

--> Can you explain the code path after r231508 for your example? Will r231508 change the code path if we start with a global?
r231508 seems to change the behavior constant temporaries only.

I think your question is about the following case where initializer_list is used to initialize a global variable?

const std::vector<NSString*> CfgFiles = {@"Test0", @"Test1", @"Test2", @"Test3"};

This is not different from the case where the vector is declared inside a function. In both cases, a temporary std::initializer_list is created and passed to std::vector's constructor.
r231508 made changes to create a global array of strings (@.ref.tmp in the IR shown below).

@.ref.tmp = private constant [4 x %0*] [%0* bitcast (%struct.NSConstantString_tag* @_unnamed_cfstring_ to %0*), %0* bitcast (%struct.NSConstantString_tag* @_unnamed_cfstring_.2 to %0*), %0* bitcast (%struct.NSConstantString_tag* @_unnamed_cfstring_.4 to %0*), %0* bitcast (%struct.NSConstantString_tag* @_unnamed_cfstring_.6 to %0*)], align 8
...
%agg.tmp = alloca %"class.std::initializer_list", align 8 ; temporary std::initializer_list
%begin_ = getelementptr inbounds %"class.std::initializer_list", %"class.std::initializer_list"* %agg.tmp, i32 0, i32 0
store %0 getelementptr inbounds ([4 x %0*], [4 x %0*]* @.ref.tmp, i64 0, i64 0), %0* %
begin_, align 8, !tbaa !7 ; std::initializer_list holds a pointer to the array.

rjmccall added inline comments.May 12 2016, 3:32 PM
lib/CodeGen/CGExpr.cpp
365 ↗(On Diff #57088)

As we discussed in person, please make the comment address *why* this can ever have an initializer. I think something like this would be ok:

// createReferenceTemporary will promote the temporary to a global
// with a constant initializer if it can.  It can only do this to a value of
// ARC-manageable type if the value is global and therefore "immune"
// to ref-counting operations.  Therefore we have no need to emit either
// a dynamic initialization or a cleanup and we can just return the
// address of the temporary.
ahatanak updated this revision to Diff 57111.May 12 2016, 3:47 PM

Thanks, I updated the comment in the new patch.

rjmccall edited edge metadata.May 12 2016, 3:54 PM

LGTM, thanks.

This revision was automatically updated to reflect the committed changes.