1 // Test -fsanitize-memory-use-after-dtor
2 // RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
3 // RUN: %clang_cc1 -DATTRIBUTE -fsanitize=memory -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ATTR
4 
5 template <class T> class Vector {
6  public:
7   ~Vector() {}
8 };
9 
10 struct No_San {
11   Vector<int> v;
12   No_San() { }
13 #ifdef ATTRIBUTE
14   __attribute__((no_sanitize_memory)) ~No_San() = default;
15 #else
16   ~No_San() = default;
17 #endif
18 };
19 
20 int main() {
21   No_San *ns = new No_San();
22   ns->~No_San();
23   return 0;
24 }
25 
26 // Repressing the sanitization attribute results in no msan
27 // instrumentation of the destructor
28 // CHECK: define {{.*}}No_SanD1Ev{{.*}} [[ATTRIBUTE:#[0-9]+]]
29 // CHECK: call void {{.*}}No_SanD2Ev
30 // CHECK: call void @__sanitizer_dtor_callback
31 // CHECK: ret void
32 
33 // CHECK-ATTR: define {{.*}}No_SanD1Ev{{.*}} [[ATTRIBUTE:#[0-9]+]]
34 // CHECK-ATTR: call void {{.*}}No_SanD2Ev
35 // CHECK-ATTR-NOT: call void @__sanitizer_dtor_callback
36 // CHECK-ATTR: ret void
37 
38 
39 // CHECK: define {{.*}}No_SanD2Ev{{.*}} [[ATTRIBUTE:#[0-9]+]]
40 // CHECK: call void {{.*}}Vector
41 // CHECK: call void @__sanitizer_dtor_callback
42 // CHECK: ret void
43 
44 // CHECK-ATTR: define {{.*}}No_SanD2Ev{{.*}} [[ATTRIBUTE:#[0-9]+]]
45 // CHECK-ATTR: call void {{.*}}Vector
46 // CHECK-ATTR-NOT: call void @__sanitizer_dtor_callback
47 // CHECK-ATTR: ret void
48 
49 // When attribute is repressed, the destructor does not emit any tail calls
50 // CHECK: attributes [[ATTRIBUTE]] = {{.*}} sanitize_memory
51 // CHECK-ATTR-NOT: attributes [[ATTRIBUTE]] = {{.*}} sanitize_memory
52