re PR sanitizer/87095 (UndefinedBehaviorSanitizer vptr false positive with virtual...
authorJakub Jelinek <jakub@redhat.com>
Wed, 29 Aug 2018 21:43:18 +0000 (23:43 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 29 Aug 2018 21:43:18 +0000 (23:43 +0200)
PR c++/87095
* decl.c (begin_destructor_body): If current_class_type has
virtual bases and the primary base is nearly empty virtual base,
voidify clearing of vptr and make it conditional on in-charge
argument.

* g++.dg/ubsan/vptr-13.C: New test.

From-SVN: r263967

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ubsan/vptr-13.C [new file with mode: 0644]

index 6ed074eea1a88c170af5a8135712cfeacebf7c1d..6ecd48dfac81569192af33d974c6208ec7d6df35 100644 (file)
@@ -1,3 +1,11 @@
+2018-08-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/87095
+       * decl.c (begin_destructor_body): If current_class_type has
+       virtual bases and the primary base is nearly empty virtual base,
+       voidify clearing of vptr and make it conditional on in-charge
+       argument.
+
 2018-08-29  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/85265
index 7fee3da1f4909238f854db27fd50898013e90d1c..c6711f74177fe4bcb9d5cfa00cf77683907f41af 100644 (file)
@@ -15698,6 +15698,18 @@ begin_destructor_body (void)
            tree stmt = cp_build_modify_expr (input_location, vtbl_ptr,
                                              NOP_EXPR, vtbl,
                                              tf_warning_or_error);
+           /* If the vptr is shared with some virtual nearly empty base,
+              don't clear it if not in charge, the dtor of the virtual
+              nearly empty base will do that later.  */
+           if (CLASSTYPE_VBASECLASSES (current_class_type)
+               && CLASSTYPE_PRIMARY_BINFO (current_class_type)
+               && BINFO_VIRTUAL_P
+                         (CLASSTYPE_PRIMARY_BINFO (current_class_type)))
+             {
+               stmt = convert_to_void (stmt, ICV_STATEMENT,
+                                       tf_warning_or_error);
+               stmt = build_if_in_charge (stmt);
+             }
            finish_decl_cleanup (NULL_TREE, stmt);
          }
        else
index 78bbd7f31e55146a9f14837f8e65cc840b7f5378..e38dab2f8abffe7a404f84555db655eb0930fb98 100644 (file)
@@ -1,3 +1,8 @@
+2018-08-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/87095
+       * g++.dg/ubsan/vptr-13.C: New test.
+
 2018-08-29  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/85265
diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-13.C b/gcc/testsuite/g++.dg/ubsan/vptr-13.C
new file mode 100644 (file)
index 0000000..345581f
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/87095
+// { dg-do run }
+// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" }
+
+struct A
+{
+  virtual ~A () {}
+};
+
+struct B : virtual A {};
+
+struct C : B {};
+
+int
+main ()
+{
+  C c;
+  return 0;
+}