forked from OSchip/llvm-project
[ObjC] Fix lifetime markers of loop variable in EmitObjCForCollectionStmt
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 llvm-svn: 300287
This commit is contained in:
parent
c7b9ecaa63
commit
8f56846d4f
clang
|
@ -1469,11 +1469,6 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
||||||
if (DI)
|
if (DI)
|
||||||
DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
|
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");
|
JumpDest LoopEnd = getJumpDestInCurrentScope("forcoll.end");
|
||||||
|
|
||||||
// Fast enumeration state.
|
// Fast enumeration state.
|
||||||
|
@ -1625,8 +1620,10 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
||||||
bool elementIsVariable;
|
bool elementIsVariable;
|
||||||
LValue elementLValue;
|
LValue elementLValue;
|
||||||
QualType elementType;
|
QualType elementType;
|
||||||
|
AutoVarEmission variable = AutoVarEmission::invalid();
|
||||||
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
|
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
|
||||||
// Initialize the variable, in case it's a __block variable or something.
|
// Initialize the variable, in case it's a __block variable or something.
|
||||||
|
variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl()));
|
||||||
EmitAutoVarInit(variable);
|
EmitAutoVarInit(variable);
|
||||||
|
|
||||||
const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
|
const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
|
||||||
|
|
|
@ -24,9 +24,9 @@ void test0(NSArray *array) {
|
||||||
|
|
||||||
// CHECK-LP64-LABEL: define void @test0(
|
// CHECK-LP64-LABEL: define void @test0(
|
||||||
// CHECK-LP64: [[ARRAY:%.*]] = alloca [[ARRAY_T:%.*]]*,
|
// CHECK-LP64: [[ARRAY:%.*]] = alloca [[ARRAY_T:%.*]]*,
|
||||||
// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*,
|
|
||||||
// CHECK-LP64-NEXT: [[STATE:%.*]] = alloca [[STATE_T:%.*]],
|
// CHECK-LP64-NEXT: [[STATE:%.*]] = alloca [[STATE_T:%.*]],
|
||||||
// CHECK-LP64-NEXT: [[BUFFER:%.*]] = alloca [16 x i8*], align 8
|
// CHECK-LP64-NEXT: [[BUFFER:%.*]] = alloca [16 x i8*], align 8
|
||||||
|
// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*,
|
||||||
// CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
|
// CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
|
||||||
|
|
||||||
// Initialize 'array'.
|
// Initialize 'array'.
|
||||||
|
@ -97,9 +97,9 @@ void test1(NSArray *array) {
|
||||||
|
|
||||||
// CHECK-LP64-LABEL: define void @test1(
|
// CHECK-LP64-LABEL: define void @test1(
|
||||||
// CHECK-LP64: alloca [[ARRAY_T:%.*]]*,
|
// CHECK-LP64: alloca [[ARRAY_T:%.*]]*,
|
||||||
// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*,
|
|
||||||
// CHECK-LP64-NEXT: [[STATE:%.*]] = alloca [[STATE_T:%.*]],
|
// CHECK-LP64-NEXT: [[STATE:%.*]] = alloca [[STATE_T:%.*]],
|
||||||
// CHECK-LP64-NEXT: alloca [16 x i8*], align 8
|
// CHECK-LP64-NEXT: alloca [16 x i8*], align 8
|
||||||
|
// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*,
|
||||||
// CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
|
// CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
|
||||||
|
|
||||||
// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[STATE_T]], [[STATE_T]]* [[STATE]], i32 0, i32 1
|
// 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-LABEL: define void @test3(
|
||||||
// CHECK-LP64: [[ARRAY:%.*]] = alloca [[ARRAY_T]]*, align 8
|
// 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: [[T0:%.*]] = load i8*, i8** [[X]], align 8
|
||||||
// CHECK-LP64-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null
|
// CHECK-LP64-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null
|
||||||
// CHECK-LP64-NEXT: br i1 [[T1]],
|
// CHECK-LP64-NEXT: br i1 [[T1]],
|
||||||
|
|
|
@ -120,9 +120,9 @@ void test2(int cond) {
|
||||||
|
|
||||||
// CHECK-LABEL: define void @test2(
|
// CHECK-LABEL: define void @test2(
|
||||||
// CHECK: [[COND:%.*]] = alloca i32,
|
// CHECK: [[COND:%.*]] = alloca i32,
|
||||||
// CHECK: alloca i8*
|
|
||||||
// CHECK: [[CLEANUP_SAVE:%.*]] = alloca i8*
|
// CHECK: [[CLEANUP_SAVE:%.*]] = alloca i8*
|
||||||
// CHECK: [[RUN_CLEANUP:%.*]] = alloca i1
|
// CHECK: [[RUN_CLEANUP:%.*]] = alloca i1
|
||||||
|
// CHECK: alloca i8*
|
||||||
// Evaluate condition; cleanup disabled by default.
|
// Evaluate condition; cleanup disabled by default.
|
||||||
// CHECK: [[T0:%.*]] = load i32, i32* [[COND]],
|
// CHECK: [[T0:%.*]] = load i32, i32* [[COND]],
|
||||||
// CHECK-NEXT: icmp ne i32 [[T0]], 0
|
// CHECK-NEXT: icmp ne i32 [[T0]], 0
|
||||||
|
|
Loading…
Reference in New Issue