]> granicus.if.org Git - clang/commitdiff
[ObjC] Fix lifetime markers of loop variable in EmitObjCForCollectionStmt
authorKuba Mracek <mracek@apple.com>
Fri, 14 Apr 2017 00:32:43 +0000 (00:32 +0000)
committerKuba Mracek <mracek@apple.com>
Fri, 14 Apr 2017 00:32:43 +0000 (00:32 +0000)
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.  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.

Differential Revision: https://reviews.llvm.org/D32029

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300287 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGObjC.cpp
test/CodeGenObjC/arc-foreach.m
test/CodeGenObjC/arc-ternary-op.m

index 929bda9099b9dc3327c678265dfeb2be2a7e6bab..50252d5a44b91abb10e62e06e82c0a86bc3ad8ac 100644 (file)
@@ -1469,11 +1469,6 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
   if (DI)
     DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
 
-  // The local variable comes into scope immediately.
-  AutoVarEmission variable = AutoVarEmission::invalid();
-  if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement()))
-    variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl()));
-
   JumpDest LoopEnd = getJumpDestInCurrentScope("forcoll.end");
 
   // Fast enumeration state.
@@ -1625,8 +1620,10 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
   bool elementIsVariable;
   LValue elementLValue;
   QualType elementType;
+  AutoVarEmission variable = AutoVarEmission::invalid();
   if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
     // Initialize the variable, in case it's a __block variable or something.
+    variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl()));
     EmitAutoVarInit(variable);
 
     const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
index db150e88a59f59f0572713af82d53dc11b7907d5..be2586433fcdf5aa655b60c4fb763e1977754298 100644 (file)
@@ -24,9 +24,9 @@ void test0(NSArray *array) {
 
 // CHECK-LP64-LABEL:    define void @test0(
 // CHECK-LP64:      [[ARRAY:%.*]] = alloca [[ARRAY_T:%.*]]*,
-// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*,
 // CHECK-LP64-NEXT: [[STATE:%.*]] = alloca [[STATE_T:%.*]],
 // CHECK-LP64-NEXT: [[BUFFER:%.*]] = alloca [16 x i8*], align 8
+// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*,
 // CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
 
 // Initialize 'array'.
@@ -97,9 +97,9 @@ void test1(NSArray *array) {
 
 // CHECK-LP64-LABEL:    define void @test1(
 // CHECK-LP64:      alloca [[ARRAY_T:%.*]]*,
-// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*,
 // CHECK-LP64-NEXT: [[STATE:%.*]] = alloca [[STATE_T:%.*]],
 // CHECK-LP64-NEXT: alloca [16 x i8*], align 8
+// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*,
 // CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
 
 // CHECK-LP64:      [[T0:%.*]] = getelementptr inbounds [[STATE_T]], [[STATE_T]]* [[STATE]], i32 0, i32 1
@@ -160,7 +160,7 @@ void test3(NSArray *array) {
 
   // CHECK-LP64-LABEL:    define void @test3(
   // CHECK-LP64:      [[ARRAY:%.*]] = alloca [[ARRAY_T]]*, align 8
-  // CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*, align 8
+  // CHECK-LP64:      [[X:%.*]] = alloca i8*, align 8
   // CHECK-LP64:      [[T0:%.*]] = load i8*, i8** [[X]], align 8
   // CHECK-LP64-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null
   // CHECK-LP64-NEXT: br i1 [[T1]],
index 3488d2c5387a4e435121fc9d1d533f2b90f0a0e9..8d2672a327d36c7a328cee1c99ae691ff0dcf45a 100644 (file)
@@ -120,9 +120,9 @@ void test2(int cond) {
 
   // CHECK-LABEL:    define void @test2(
   // CHECK:      [[COND:%.*]] = alloca i32,
-  // CHECK:      alloca i8*
   // CHECK:      [[CLEANUP_SAVE:%.*]] = alloca i8*
   // CHECK:      [[RUN_CLEANUP:%.*]] = alloca i1
+  // CHECK:      alloca i8*
   //   Evaluate condition; cleanup disabled by default.
   // CHECK:      [[T0:%.*]] = load i32, i32* [[COND]],
   // CHECK-NEXT: icmp ne i32 [[T0]], 0