This is an archive of the discontinued LLVM Phabricator instance.

[ObjC] Fix lifetime markers of loop variable in EmitObjCForCollectionStmt
ClosedPublic

Authored by kubamracek on Apr 13 2017, 10:10 AM.

Details

Summary

CodeGenFunction::EmitObjCForCollectionStmt currently emits lifetime markers for the loop variable in an inconsistent way: lifetime.start is emitted before the loop is entered, but lifetime.end is emitted inside the loop:

; entry block
  %u = alloca %1*, align 8
  %1 = bitcast %1** %u to i8*
  call void @llvm.lifetime.start(i64 8, i8* %1) #5
  ...

; loop body
  ...
  %14 = bitcast %1** %u to i8*
  call void @llvm.lifetime.end(i64 8, i8* %14) #5
  ...
  br i1 %21, ... ; loop

; loop ended
  ret void

AddressSanitizer uses these markers to track out-of-scope accesses to local variables, and we get false positives in Obj-C foreach loops (in the 2nd iteration of the loop). The markers of the loop variable need to be either both inside the loop (so that we poison and unpoison the variable in each iteration), or both outside. This patch implements the "both inside" approach and makes EmitObjCForCollectionStmt emit:

; entry block
  %u = alloca %1*, align 8
  ...

; loop body
  %12 = bitcast %1** %u to i8*
  call void @llvm.lifetime.start(i64 8, i8* %12) #5
  ...
  %14 = bitcast %1** %u to i8*
  call void @llvm.lifetime.end(i64 8, i8* %14) #5
  br label %15

; loop ended
  ret void

The test fixups are only changing the order of allocas. There's some related discussion at https://reviews.llvm.org/D18618.

Diff Detail

Repository
rL LLVM

Event Timeline

kubamracek created this revision.Apr 13 2017, 10:10 AM

Note that C++ foreach loops also generate lifetime.start and lifetime.end inside of the loop body.

rjmccall accepted this revision.Apr 13 2017, 4:57 PM

Yes, looks good to me.

This revision is now accepted and ready to land.Apr 13 2017, 4:57 PM
This revision was automatically updated to reflect the committed changes.
kubamracek reopened this revision.Apr 13 2017, 9:45 PM

Reverted because this fails for-in.m by crashing the compiler when compiling:

void t2(NSArray *array) {
  for (NSArray *array in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}}
  }
}
This revision is now accepted and ready to land.Apr 13 2017, 9:45 PM

Trying a different approach: Keeping the loop variable alive for the whole loop by extending ForScope and registering the cleanup function inside EmitAutoVarAlloca.

Those test changes are smaller than I thought they might be; great.

This revision was automatically updated to reflect the committed changes.