teak-llvm/clang/test/CodeGenCXX/lifetime-asan.cpp
Richard Smith aa140bf164 Avoid creating conditional cleanup blocks that contain only @llvm.lifetime.end calls
When a non-extended temporary object is created in a conditional branch, the
lifetime of that temporary ends outside the conditional (at the end of the
full-expression). If we're inserting lifetime markers, this means we could end
up generating

  if (some_cond) {
    lifetime.start(&tmp);
    Tmp::Tmp(&tmp);
  }
  // ...
  if (some_cond) {
    lifetime.end(&tmp);
  }

... for a full-expression containing a subexpression of the form `some_cond ?
Tmp().x : 0`. This patch moves the lifetime start for such a temporary out of
the conditional branch so that we don't need to generate an additional basic
block to hold the lifetime end marker.

This is disabled if we want precise lifetime markers (for asan's
stack-use-after-scope checks) or of the temporary has a non-trivial destructor
(in which case we'd generate an extra basic block anyway to hold the destructor
call).

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

llvm-svn: 338945
2018-08-04 01:25:06 +00:00

43 lines
1.3 KiB
C++

// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - -fno-exceptions -O0 %s | FileCheck %s -check-prefixes=CHECK,CHECK-O0 --implicit-check-not=llvm.lifetime
// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - -fno-exceptions -O0 \
// RUN: -fsanitize=address -fsanitize-address-use-after-scope %s | \
// RUN: FileCheck %s -check-prefixes=CHECK,CHECK-ASAN-USE-AFTER-SCOPE
extern int bar(char *A, int n);
struct X { X(); ~X(); int *p; };
struct Y { Y(); int *p; };
extern "C" void a(), b(), c(), d();
// CHECK-LABEL: @_Z3foo
void foo(int n) {
// CHECK: call void @a()
a();
// CHECK: call void @b()
// CHECK-ASAN-USE-AFTER-SCOPE: store i1 false
// CHECK-ASAN-USE-AFTER-SCOPE: store i1 false
// CHECK: br i1
//
// CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.start
// CHECK-ASAN-USE-AFTER-SCOPE: store i1 true
// CHECK: call void @_ZN1XC
// CHECK: br label
//
// CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.start
// CHECK-ASAN-USE-AFTER-SCOPE: store i1 true
// CHECK: call void @_ZN1YC
// CHECK: br label
//
// CHECK: call void @c()
// CHECK-ASAN-USE-AFTER-SCOPE: br i1
// CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.end
// CHECK-ASAN-USE-AFTER-SCOPE: br i1
// CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.end
b(), (n ? X().p : Y().p), c();
// CHECK: call void @d()
d();
}