[compiler-rt] c059ede - [msan] Add more specific messages for use-after-destroy

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 30 19:52:51 PDT 2022


Author: Vitaly Buka
Date: 2022-08-30T19:52:32-07:00
New Revision: c059ede28ea8faf0540cedad74bc5698ec59e744

URL: https://github.com/llvm/llvm-project/commit/c059ede28ea8faf0540cedad74bc5698ec59e744
DIFF: https://github.com/llvm/llvm-project/commit/c059ede28ea8faf0540cedad74bc5698ec59e744.diff

LOG: [msan] Add more specific messages for use-after-destroy

Reviewed By: kda, kstoimenov

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

Added: 
    

Modified: 
    clang/lib/CodeGen/CGClass.cpp
    clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
    clang/test/CodeGenCXX/sanitize-dtor-callback.cpp
    clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
    clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp
    clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
    clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp
    clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp
    clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp
    clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp
    compiler-rt/include/sanitizer/msan_interface.h
    compiler-rt/lib/msan/msan.h
    compiler-rt/lib/msan/msan_interceptors.cpp
    compiler-rt/lib/msan/msan_interface_internal.h
    compiler-rt/lib/msan/msan_report.cpp
    compiler-rt/test/msan/dtor-base-access.cpp
    compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp
    compiler-rt/test/msan/use-after-dtor.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 703eff8ac54c5..ec4d8e50a3560 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1649,23 +1649,35 @@ namespace {
     }
   };
 
-  static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
-                                        CharUnits::QuantityType PoisonSize) {
+  static void EmitSanitizerDtorCallback(
+      CodeGenFunction &CGF, StringRef Name, llvm::Value *Ptr,
+      llvm::Optional<CharUnits::QuantityType> PoisonSize = {}) {
     CodeGenFunction::SanitizerScope SanScope(&CGF);
     // Pass in void pointer and size of region as arguments to runtime
     // function
-    llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy),
-                           llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)};
+    SmallVector<llvm::Value *, 2> Args = {
+        CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy)};
+    SmallVector<llvm::Type *, 2> ArgTypes = {CGF.VoidPtrTy};
 
-    llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy};
+    if (PoisonSize.has_value()) {
+      Args.emplace_back(llvm::ConstantInt::get(CGF.SizeTy, *PoisonSize));
+      ArgTypes.emplace_back(CGF.SizeTy);
+    }
 
     llvm::FunctionType *FnType =
         llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
-    llvm::FunctionCallee Fn =
-        CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback");
+    llvm::FunctionCallee Fn = CGF.CGM.CreateRuntimeFunction(FnType, Name);
+
     CGF.EmitNounwindRuntimeCall(Fn, Args);
   }
 
+  static void
+  EmitSanitizerDtorFieldsCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
+                                  CharUnits::QuantityType PoisonSize) {
+    EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_fields", Ptr,
+                              PoisonSize);
+  }
+
   /// Poison base class with a trivial destructor.
   struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {
     const CXXRecordDecl *BaseClass;
@@ -1687,7 +1699,8 @@ namespace {
       if (!BaseSize.isPositive())
         return;
 
-      EmitSanitizerDtorCallback(CGF, Addr.getPointer(), BaseSize.getQuantity());
+      EmitSanitizerDtorFieldsCallback(CGF, Addr.getPointer(),
+                                      BaseSize.getQuantity());
 
       // Prevent the current stack frame from disappearing from the stack trace.
       CGF.CurFn->addFnAttr("disable-tail-calls", "true");
@@ -1735,7 +1748,7 @@ namespace {
       if (!PoisonSize.isPositive())
         return;
 
-      EmitSanitizerDtorCallback(CGF, OffsetPtr, PoisonSize.getQuantity());
+      EmitSanitizerDtorFieldsCallback(CGF, OffsetPtr, PoisonSize.getQuantity());
 
       // Prevent the current stack frame from disappearing from the stack trace.
       CGF.CurFn->addFnAttr("disable-tail-calls", "true");
@@ -1752,15 +1765,13 @@ namespace {
     void Emit(CodeGenFunction &CGF, Flags flags) override {
       assert(Dtor->getParent()->isDynamicClass());
       (void)Dtor;
-      ASTContext &Context = CGF.getContext();
       // Poison vtable and vtable ptr if they exist for this class.
       llvm::Value *VTablePtr = CGF.LoadCXXThis();
 
-      CharUnits::QuantityType PoisonSize =
-          Context.toCharUnitsFromBits(CGF.PointerWidthInBits).getQuantity();
       // Pass in void pointer and size of region as arguments to runtime
       // function
-      EmitSanitizerDtorCallback(CGF, VTablePtr, PoisonSize);
+      EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_vptr",
+                                VTablePtr);
     }
  };
 

diff  --git a/clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp b/clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
index 6629cd8b274ea..94571d449380d 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
@@ -63,22 +63,22 @@ struct Adjacent {
 Adjacent ad;
 
 // CHECK-LABEL: define {{.*}}PackedD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 17{{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}i64 17{{.*}}, !dbg ![[DI1:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: define {{.*}}EmptyD2Ev
 // CHECK: ret void
 
 // CHECK-LABEL: define {{.*}}SimpleD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 1{{.*}}, !dbg ![[DI2:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}i64 1{{.*}}, !dbg ![[DI2:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: define {{.*}}AnonD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 5{{.*}}, !dbg ![[DI3:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}i64 5{{.*}}, !dbg ![[DI3:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: define {{.*}}AdjacentD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 1{{.*}}, !dbg ![[DI4:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}i64 1{{.*}}, !dbg ![[DI4:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: !DIFile{{.*}}cpp

diff  --git a/clang/test/CodeGenCXX/sanitize-dtor-callback.cpp b/clang/test/CodeGenCXX/sanitize-dtor-callback.cpp
index d42008a7ad79c..18c6417001fd9 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-callback.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-callback.cpp
@@ -56,16 +56,16 @@ Defaulted_Non_Trivial def_non_trivial;
 // instrumentation inserted.
 // CHECK-LABEL: define {{.*}}SimpleD2Ev
 // CHECK-NOT: store i{{[0-9]+}} 0, {{.*}}@__msan_param_tls
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI1:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: define {{.*}}InlinedD2Ev
 // CHECK-NOT: store i{{[0-9]+}} 0, {{.*}}@__msan_param_tls
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI2:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI2:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: define {{.*}}Defaulted_Non_TrivialD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI3:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI3:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: !DIFile{{.*}}cpp

diff  --git a/clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp b/clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
index 1a6aa9ed1cdbf..1d5accb8bfd06 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
@@ -49,15 +49,15 @@ Derived d;
 
 // Poison members and vtable ptr.
 // CHECK-LABEL: define {{.*}}BaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI1:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 8{{.*}}, !dbg ![[DI1]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}){{.*}}, !dbg ![[DI1]]
 // CHECK: ret void
 
 // Poison members and destroy non-virtual base.
 // CHECK-LABEL: define {{.*}}DerivedD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI3:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI3:[0-9]+]]
 // CHECK: call void {{.*}}BaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 8{{.*}}, !dbg ![[DI3]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}){{.*}}, !dbg ![[DI3]]
 // CHECK: ret void
 
 // CHECK-LABEL: !DIFile{{.*}}cpp

diff  --git a/clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp b/clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp
index d30bd3ade7495..adbe77fc659bd 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp
@@ -47,7 +47,7 @@ Derived d;
 
 // CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev
 // CHECK: call void {{.*}}ZN11VirtualBaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}){{.*}}, !dbg ![[DI0:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}){{.*}}, !dbg ![[DI0:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev
@@ -61,27 +61,27 @@ Derived d;
 
 // poison 2 ints
 // CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 8){{.*}}, !dbg ![[DI1:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 8){{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}){{.*}}, !dbg ![[DI1]]
 // CHECK: ret void
 
 // poison int and double
 // CHECK-LABEL: define {{.*}}ZN4BaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}{{.*}}, !dbg ![[DI2:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 16){{.*}}, !dbg ![[DI2:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}{{.*}}, !dbg ![[DI2]]
 // CHECK: ret void
 
 // poison int, ignore vector, poison int
 // CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 4){{.*}}, !dbg ![[DI3:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 4){{.*}}, !dbg ![[DI3:[0-9]+]]
 // CHECK: call void {{.*}}ZN6VectorIiED1Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 4){{.*}}, !dbg ![[DI3]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 4){{.*}}, !dbg ![[DI3]]
 // CHECK: call void {{.*}}ZN4BaseD2Ev
 // CHECK: ret void
 
 // poison int
 // CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 4){{.*}}, !dbg ![[DI5:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 4){{.*}}, !dbg ![[DI5:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: !DIFile{{.*}}.cpp

diff  --git a/clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp b/clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
index 3d52e725cc556..5cdf69edb9d04 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
@@ -15,7 +15,7 @@ struct Simple {
 Simple s;
 // Simple internal member is poisoned by compiler-generated dtor
 // CHECK: define {{.*}}SimpleD2Ev{{.*}} [[ATTRIBUTE:#[0-9]+]]
-// CHECK: {{^ *}}call void @__sanitizer_dtor_callback(
+// CHECK: call void @__sanitizer_dtor_callback_fields(
 // CHECK: ret void
 
 // Destructor does not emit any tail calls

diff  --git a/clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp b/clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp
index 5da9405b74067..cfb80f8dbd6cb 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp
@@ -20,8 +20,8 @@ Derived d;
 // Poison members, then poison the trivial base class.
 // CHECK-LABEL: define {{.*}}DerivedD2Ev
 // CHECK: %[[GEP:[0-9a-z]+]] = getelementptr i8, i8* {{.*}}, i64 16
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}%[[GEP]], i64 4{{.*}}, !dbg ![[DI:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 16{{.*}}, !dbg ![[DI]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}%[[GEP]], i64 4{{.*}}, !dbg ![[DI:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 16{{.*}}, !dbg ![[DI]]
 // CHECK: ret void
 
 // CHECK-LABEL: !DIFile{{.*}}cpp

diff  --git a/clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp b/clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp
index eb60f7fa46eb0..e2b19424542bb 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp
@@ -14,7 +14,6 @@ Trivial t;
 
 // CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI:[0-9]+]]
 
+// CHECK-LABEL: !DIFile{{.*}}.cpp
 
-// CHECK-LABEL: !DIFile{{.*}}cpp
-
-// CHECK-DAG: ![[DI]] = {{.*}}line: [[@LINE-28]]
+// CHECK-DAG: ![[DI]] = {{.*}}line: [[@LINE-371]]

diff  --git a/clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp b/clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp
index 063ff7ffdb081..49de930ce84ad 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp
@@ -25,18 +25,18 @@ B b;
 // CHECK-LABEL: define {{.*}}BD1Ev
 // CHECK: call void {{.*}}BD2Ev
 // CHECK: call void {{.*}}AD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}, !dbg ![[DI1:[0-9]+]]
 // CHECK: ret void
 
 // Since no virtual bases, poison vtable ptr here.
 // CHECK-LABEL: define {{.*}}AD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI2:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI2]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI2:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}, !dbg ![[DI2]]
 // CHECK: ret void
 
 // Poison members
 // CHECK-LABEL: define {{.*}}BD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI4:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI4:[0-9]+]]
 // CHECK: ret void
 
 // CHECK-LABEL: !DIFile{{.*}}cpp

diff  --git a/clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp b/clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp
index a0b0631b952b5..7aba27e6b8d19 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -no-opaque-pointers -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++20 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s --implicit-check-not "call void @__sanitizer_dtor_callback"
-// RUN: %clang_cc1 -no-opaque-pointers -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++20 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s --implicit-check-not "call void @__sanitizer_dtor_callback"
+// RUN: %clang_cc1 -no-opaque-pointers -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++20 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s --implicit-check-not "call void @__sanitizer_dtor_callback_fields"
+// RUN: %clang_cc1 -no-opaque-pointers -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++20 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s --implicit-check-not "call void @__sanitizer_dtor_callback_fields"
 
 struct Empty {};
 
@@ -30,7 +30,7 @@ struct Struct {
 static_assert(sizeof(Struct) == 16);
 } // namespace T0
 // CHECK-LABEL: define {{.*}} @_ZN2T06StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
 // CHECK-NEXT:    ret void
 
 namespace empty {
@@ -45,7 +45,7 @@ static_assert(sizeof(Struct) == 24);
 } // namespace T1
 // CHECK-LABEL: define {{.*}} @_ZN5empty2T16StructD2Ev(
 // CHECK:         [[GEP:%.+]] = getelementptr i8, {{.*}}, i64 8{{$}}
-// CHECK:         call void @__sanitizer_dtor_callback(i8* [[GEP]], i64 13)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* [[GEP]], i64 13)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
 // CHECK-NEXT:    ret void
 
@@ -60,10 +60,10 @@ static_assert(sizeof(Struct) == 24);
 } // namespace T2
 // CHECK-LABEL: define {{.*}} @_ZN5empty2T26StructD2Ev(
 // CHECK:         [[GEP1:%.+]] = getelementptr i8, {{.*}}, i64 16{{$}}
-// CHECK:         call void @__sanitizer_dtor_callback(i8* [[GEP1]], i64 5)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* [[GEP1]], i64 5)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
 // CHECK:         [[GEP2:%.+]] = getelementptr i8, {{.*}}, i64 0{{$}}
-// CHECK:         call void @__sanitizer_dtor_callback(i8* [[GEP2]], i64 8)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* [[GEP2]], i64 8)
 // CHECK-NEXT:    ret void
 
 namespace T3 {
@@ -77,10 +77,10 @@ static_assert(sizeof(Struct) == 24);
 } // namespace T3
 // CHECK-LABEL: define {{.*}} @_ZN5empty2T36StructD2Ev(
 // CHECK:         [[GEP1:%.+]] = getelementptr i8, {{.*}}, i64 20{{$}}
-// CHECK:         call void @__sanitizer_dtor_callback(i8* [[GEP1]], i64 1)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* [[GEP1]], i64 1)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
 // CHECK:         [[GEP2:%.+]] = getelementptr i8, {{.*}}, i64 0{{$}}
-// CHECK:         call void @__sanitizer_dtor_callback(i8* [[GEP2]], i64 12)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* [[GEP2]], i64 12)
 // CHECK-NEXT:    ret void
 
 namespace T4 {
@@ -93,7 +93,7 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T4
 // CHECK-LABEL: define {{.*}} @_ZN5empty2T46StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
 // CHECK-NEXT:    ret void
 
 namespace T5 {
@@ -107,7 +107,7 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T5
 // CHECK-LABEL: define {{.*}} @_ZN5empty2T56StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
 // CHECK-NEXT:    ret void
 
@@ -122,7 +122,7 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T6
 // CHECK-LABEL: define {{.*}} @_ZN5empty2T66StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
 // CHECK-NEXT:    ret void
 
@@ -137,9 +137,9 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T7
 // CHECK-LABEL: define {{.*}} @_ZN5empty2T76StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
 // CHECK-NEXT:    ret void
 
 namespace T8 {
@@ -153,8 +153,8 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T8
 // CHECK-LABEL: define {{.*}} @_ZN5empty2T86StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
 // CHECK-NEXT:    ret void
 
 namespace T9 {
@@ -168,8 +168,8 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T9
 // CHECK-LABEL: define {{.*}} @_ZN5empty2T96StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
 // CHECK-NEXT:    ret void
 
 namespace T10 {
@@ -183,8 +183,8 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T10
 // CHECK-LABEL: define {{.*}} @_ZN5empty3T106StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
 // CHECK-NEXT:    ret void
 
 namespace T11 {
@@ -198,7 +198,7 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T11
 // CHECK-LABEL: define {{.*}} @_ZN5empty3T116StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
 // CHECK-NEXT:    ret void
 
 namespace T12 {
@@ -214,7 +214,7 @@ static_assert(sizeof(Struct) == 24);
 } // namespace empty
 // CHECK-LABEL: define {{.*}} @_ZN5empty3T126StructD2Ev(
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
 // CHECK-NEXT:    ret void
 
 namespace empty_non_trivial {
@@ -228,7 +228,7 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T1
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T16StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
 // CHECK-NEXT:    ret void
 
@@ -242,8 +242,8 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T2
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T26StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
 // CHECK-NEXT:    ret void
 
 namespace T3 {
@@ -256,8 +256,8 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T3
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T36StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
 // CHECK-NEXT:    ret void
 
 namespace T4 {
@@ -270,7 +270,7 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T4
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T46StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
 // CHECK-NEXT:    ret void
 
 namespace T5 {
@@ -284,7 +284,7 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T5
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T56StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
 // CHECK:         call void @_ZN15EmptyNonTrivialD1Ev(
 // CHECK-NEXT:    ret void
@@ -300,7 +300,7 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T6
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T66StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
 // CHECK:         call void @_ZN15EmptyNonTrivialD1Ev(
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
 // CHECK-NEXT:    ret void
@@ -316,10 +316,10 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T7
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T76StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
 // CHECK:         call void @_ZN15EmptyNonTrivialD1Ev(
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
 // CHECK-NEXT:    ret void
 
 namespace T8 {
@@ -333,9 +333,9 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T8
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T86StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
 // CHECK:         call void @_ZN15EmptyNonTrivialD1Ev(
 // CHECK-NEXT:    ret void
 
@@ -350,10 +350,10 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T9
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T96StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
 // CHECK:         call void @_ZN15EmptyNonTrivialD1Ev(
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
 // CHECK-NEXT:    ret void
 
 namespace T10 {
@@ -367,9 +367,9 @@ struct Struct {
 static_assert(sizeof(Struct) == 24);
 } // namespace T10
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T106StructD2Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
 // CHECK:         call void @_ZN15EmptyNonTrivialD1Ev(
 // CHECK-NEXT:    ret void
 
@@ -386,7 +386,7 @@ static_assert(sizeof(Struct) == 24);
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T116StructD2Ev(
 // CHECK:         call void @_ZN15EmptyNonTrivialD1Ev(
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
 // CHECK-NEXT:    ret void
 
 namespace T12 {
@@ -402,6 +402,6 @@ static_assert(sizeof(Struct) == 24);
 } // namespace empty_non_trivial
 // CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T126StructD2Ev(
 // CHECK:         call void @_ZN10NonTrivialD1Ev(
-// CHECK:         call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK:         call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
 // CHECK:         call void @_ZN15EmptyNonTrivialD1Ev(
 // CHECK:         ret void

diff  --git a/compiler-rt/include/sanitizer/msan_interface.h b/compiler-rt/include/sanitizer/msan_interface.h
index eeb39fbed8b49..854b12cda36ec 100644
--- a/compiler-rt/include/sanitizer/msan_interface.h
+++ b/compiler-rt/include/sanitizer/msan_interface.h
@@ -92,6 +92,8 @@ extern "C" {
 
   /* Tell MSan about newly destroyed memory. Mark memory as uninitialized. */
   void __sanitizer_dtor_callback(const volatile void* data, size_t size);
+  void __sanitizer_dtor_callback_fields(const volatile void *data, size_t size);
+  void __sanitizer_dtor_callback_vptr(const volatile void *data);
 
   /* This function may be optionally provided by user and should return
      a string containing Msan runtime options. See msan_flags.h for details. */

diff  --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h
index 1a4cc8c0c9756..5dc57fdd22be0 100644
--- a/compiler-rt/lib/msan/msan.h
+++ b/compiler-rt/lib/msan/msan.h
@@ -349,6 +349,8 @@ void UnpoisonThreadLocalState();
 u32 ChainOrigin(u32 id, StackTrace *stack);
 
 const int STACK_TRACE_TAG_POISON = StackTrace::TAG_CUSTOM + 1;
+const int STACK_TRACE_TAG_FIELDS = STACK_TRACE_TAG_POISON + 1;
+const int STACK_TRACE_TAG_VPTR = STACK_TRACE_TAG_FIELDS + 1;
 
 #define GET_MALLOC_STACK_TRACE                                            \
   BufferedStackTrace stack;                                               \

diff  --git a/compiler-rt/lib/msan/msan_interceptors.cpp b/compiler-rt/lib/msan/msan_interceptors.cpp
index c4a9e88655fe0..b3d5484c70a35 100644
--- a/compiler-rt/lib/msan/msan_interceptors.cpp
+++ b/compiler-rt/lib/msan/msan_interceptors.cpp
@@ -944,6 +944,22 @@ void __sanitizer_dtor_callback(const void *data, uptr size) {
   }
 }
 
+void __sanitizer_dtor_callback_fields(const void *data, uptr size) {
+  if (flags()->poison_in_dtor) {
+    GET_MALLOC_STACK_TRACE;
+    stack.tag = STACK_TRACE_TAG_FIELDS;
+    PoisonMemory(data, size, &stack);
+  }
+}
+
+void __sanitizer_dtor_callback_vptr(const void *data) {
+  if (flags()->poison_in_dtor) {
+    GET_MALLOC_STACK_TRACE;
+    stack.tag = STACK_TRACE_TAG_VPTR;
+    PoisonMemory(data, sizeof(void *), &stack);
+  }
+}
+
 template <class Mmap>
 static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
                               int prot, int flags, int fd, OFF64_T offset) {

diff  --git a/compiler-rt/lib/msan/msan_interface_internal.h b/compiler-rt/lib/msan/msan_interface_internal.h
index 535c3fca8b24d..c2eead13c20cf 100644
--- a/compiler-rt/lib/msan/msan_interface_internal.h
+++ b/compiler-rt/lib/msan/msan_interface_internal.h
@@ -162,6 +162,10 @@ void __msan_allocated_memory(const void* data, uptr size);
 // uninitialized.
 SANITIZER_INTERFACE_ATTRIBUTE
 void __sanitizer_dtor_callback(const void* data, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_dtor_callback_fields(const void *data, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_dtor_callback_vptr(const void *data);
 
 SANITIZER_INTERFACE_ATTRIBUTE
 u16 __sanitizer_unaligned_load16(const uu16 *p);

diff  --git a/compiler-rt/lib/msan/msan_report.cpp b/compiler-rt/lib/msan/msan_report.cpp
index c8fc286c782df..d1ef36d9a322a 100644
--- a/compiler-rt/lib/msan/msan_report.cpp
+++ b/compiler-rt/lib/msan/msan_report.cpp
@@ -81,6 +81,13 @@ static void DescribeOrigin(u32 id) {
         Printf("  %sMemory was marked as uninitialized%s\n", d.Origin(),
                d.Default());
         break;
+      case STACK_TRACE_TAG_FIELDS:
+        Printf("  %sMember fields were destroyed%s\n", d.Origin(), d.Default());
+        break;
+      case STACK_TRACE_TAG_VPTR:
+        Printf("  %sVirtual table ptr was destroyed%s\n", d.Origin(),
+               d.Default());
+        break;
       default:
         Printf("  %sUninitialized value was created%s\n", d.Origin(),
                d.Default());

diff  --git a/compiler-rt/test/msan/dtor-base-access.cpp b/compiler-rt/test/msan/dtor-base-access.cpp
index 1e141d5afdb26..e182af280150e 100644
--- a/compiler-rt/test/msan/dtor-base-access.cpp
+++ b/compiler-rt/test/msan/dtor-base-access.cpp
@@ -66,17 +66,17 @@ int main() {
   assert(__msan_test_shadow(&g->d, sizeof(g->d)) == 0);
 
   __msan_print_shadow(&g->tb0, sizeof(g->tb0));
-  // CHECK: Memory was marked as uninitialized
+  // CHECK: Member fields were destroyed
   // CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
   // CHECK: {{#1 0x.* in .*~Derived.*cpp:}}[[@LINE-20]]:
 
   __msan_print_shadow(&g->b, sizeof(g->b));
-  // CHECK: Memory was marked as uninitialized
+  // CHECK: Member fields were destroyed
   // CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
   // CHECK: {{#1 0x.* in .*~Base.*cpp:}}[[@LINE-33]]:
 
   __msan_print_shadow(&g->tb1, sizeof(g->tb1));
-  // CHECK: Memory was marked as uninitialized
+  // CHECK: Member fields were destroyed
   // CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
   // CHECK: {{#1 0x.* in .*~Derived.*cpp:}}[[@LINE-30]]:
 

diff  --git a/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp b/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp
index 7e50c49928e6a..600102cd53a73 100644
--- a/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp
+++ b/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp
@@ -51,8 +51,8 @@ int main() {
   // This fails
 #ifdef CVPTR
   c->A_Foo();
-// CVPTR: Memory was marked as uninitialized
-// CVPTR: {{#0 0x.* in __sanitizer_dtor_callback}}
+// CVPTR: Virtual table ptr was destroyed
+// CVPTR: {{#0 0x.* in __sanitizer_dtor_callback_vptr}}
 // CVPTR: {{#1 0x.* in ~C .*cpp:}}[[@LINE-28]]:
 // CVPTR: {{#2 0x.* in main .*cpp:}}[[@LINE-7]]:
 #endif
@@ -63,16 +63,16 @@ int main() {
   // Both of these fail
 #ifdef EAVPTR
   e->A_Foo();
-// EAVPTR: Memory was marked as uninitialized
-// EAVPTR: {{#0 0x.* in __sanitizer_dtor_callback}}
+// EAVPTR: Virtual table ptr was destroyed
+// EAVPTR: {{#0 0x.* in __sanitizer_dtor_callback_vptr}}
 // EAVPTR: {{#1 0x.* in ~E .*cpp:}}[[@LINE-25]]:
 // EAVPTR: {{#2 0x.* in main .*cpp:}}[[@LINE-7]]:
 #endif
 
 #ifdef EDVPTR
   e->D_Foo();
-// EDVPTR: Memory was marked as uninitialized
-// EDVPTR: {{#0 0x.* in __sanitizer_dtor_callback}}
+// EDVPTR: Virtual table ptr was destroyed
+// EDVPTR: {{#0 0x.* in __sanitizer_dtor_callback_vptr}}
 // EDVPTR: {{#1 0x.* in ~E .*cpp:}}[[@LINE-33]]:
 // EDVPTR: {{#2 0x.* in main .*cpp:}}[[@LINE-15]]:
 #endif

diff  --git a/compiler-rt/test/msan/use-after-dtor.cpp b/compiler-rt/test/msan/use-after-dtor.cpp
index 67582c18bc931..385dc349f4d5c 100644
--- a/compiler-rt/test/msan/use-after-dtor.cpp
+++ b/compiler-rt/test/msan/use-after-dtor.cpp
@@ -32,7 +32,7 @@ int main() {
   // CHECK-UAD: WARNING: MemorySanitizer: use-of-uninitialized-value
   // CHECK-UAD: {{#0 0x.* in main.*use-after-dtor.cpp:}}[[@LINE-3]]
 
-  // CHECK-ORIGINS: Memory was marked as uninitialized
+  // CHECK-ORIGINS: Member fields were destroyed
   // CHECK-ORIGINS: {{#0 0x.* in __sanitizer_dtor_callback}}
   // CHECK-ORIGINS: {{#1 0x.* in .*~Simple.*cpp:}}[[@LINE-18]]:
 


        


More information about the llvm-commits mailing list