public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-3003] analyzer: detect and analyze virtual function calls
@ 2021-08-18 17:41 Ankur saini
  0 siblings, 0 replies; only message in thread
From: Ankur saini @ 2021-08-18 17:41 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:1b34248527472496ca3fe2a07183beac8cf69041

commit r12-3003-g1b34248527472496ca3fe2a07183beac8cf69041
Author: Ankur Saini <arsenic@sourceware.org>
Date:   Sun Aug 15 19:19:07 2021 +0530

    analyzer: detect and analyze virtual function calls
    
    2021-08-15  Ankur Saini  <arsenic@sourceware.org>
    
    gcc/analyzer/ChangeLog:
            PR analyzer/97114
            * region-model.cc (region_model::get_rvalue_1): Add case for
            OBJ_TYPE_REF.
    
    gcc/testsuite/ChangeLog:
            PR analyzer/97114
            * g++.dg/analyzer/vfunc-2.C: New test.
            * g++.dg/analyzer/vfunc-3.C: New test.
            * g++.dg/analyzer/vfunc-4.C: New test.
            * g++.dg/analyzer/vfunc-5.C: New test.

Diff:
---
 gcc/analyzer/region-model.cc            |   5 ++
 gcc/testsuite/g++.dg/analyzer/vfunc-2.C |  44 ++++++++++++++
 gcc/testsuite/g++.dg/analyzer/vfunc-3.C |  32 ++++++++++
 gcc/testsuite/g++.dg/analyzer/vfunc-4.C |  28 +++++++++
 gcc/testsuite/g++.dg/analyzer/vfunc-5.C | 103 ++++++++++++++++++++++++++++++++
 5 files changed, 212 insertions(+)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 2316fbe5041..822e893e899 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -1841,6 +1841,11 @@ region_model::get_rvalue_1 (path_var pv, region_model_context *ctxt) const
 	const region *ref_reg = get_lvalue (pv, ctxt);
 	return get_store_value (ref_reg, ctxt);
       }
+    case OBJ_TYPE_REF:
+      {
+        tree expr = OBJ_TYPE_REF_EXPR (pv.m_tree);
+        return get_rvalue (expr, ctxt);
+      }
     }
 }
 
diff --git a/gcc/testsuite/g++.dg/analyzer/vfunc-2.C b/gcc/testsuite/g++.dg/analyzer/vfunc-2.C
new file mode 100644
index 00000000000..46b68e529e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/vfunc-2.C
@@ -0,0 +1,44 @@
+#include <cstdio>
+#include <cstdlib>
+
+struct A
+{
+    int m_data;
+    A() {m_data = 0;}
+    virtual int deallocate (void) 
+    {
+        return 42;
+    }
+};
+
+struct B: public A
+{
+    int *ptr;
+    int m_data_b;
+    B() {m_data_b = 0;}
+    void allocate ()
+    {
+        ptr = (int*)malloc(sizeof(int));
+    }
+    int deallocate (void) 
+    { 
+        free(ptr);
+        return 0;
+    }
+};
+
+void foo(A *a_ptr)
+{
+    printf("%d\n",a_ptr->deallocate());
+}
+
+void test()
+{
+    B b;
+    A a, *aptr;
+    aptr = &b;
+    b.allocate();
+    foo(aptr);
+    aptr = &a;
+    foo(aptr);
+}
diff --git a/gcc/testsuite/g++.dg/analyzer/vfunc-3.C b/gcc/testsuite/g++.dg/analyzer/vfunc-3.C
new file mode 100644
index 00000000000..03d3cdc73be
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/vfunc-3.C
@@ -0,0 +1,32 @@
+#include <cstdlib>
+
+struct A
+{
+    virtual int foo (void) 
+    {
+        return 42;
+    }
+};
+
+struct B: public A
+{
+    int *ptr;
+    void alloc ()
+    {
+        ptr = (int*)malloc(sizeof(int));
+    }
+    int foo (void) 
+    { 
+        free(ptr); /* { dg-warning "double-'free' of 'b.B::ptr'" } */
+        return 0;
+    }
+};
+
+int test ()
+{
+    struct B b, *bptr=&b;
+    b.alloc ();
+    bptr->foo ();  /* { dg-message "\\(6\\) calling 'B::foo' from 'test'" "event 6" } */
+    /* { dg-message "\\(9\\) returning to 'test' from 'B::foo'" "event 9" { target *-*-* } .-1 } */
+    return bptr->foo ();
+}
diff --git a/gcc/testsuite/g++.dg/analyzer/vfunc-4.C b/gcc/testsuite/g++.dg/analyzer/vfunc-4.C
new file mode 100644
index 00000000000..975108400b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/vfunc-4.C
@@ -0,0 +1,28 @@
+#include "../../gcc.dg/analyzer/analyzer-decls.h"
+
+struct A
+{
+  int m_data;
+  virtual char foo ()
+  {
+    return 'A';
+  }
+};
+
+struct B: public A
+{
+  int m_data_b;
+  char foo ()
+  {
+    return 'B';
+  }
+};
+
+void test()
+{
+  A a, *a_ptr = &a;
+  B b;
+  __analyzer_eval (a_ptr->foo () == 'A'); /* { dg-warning "TRUE" } */
+  a_ptr = &b;
+  __analyzer_eval (a_ptr->foo () == 'B'); /* { dg-warning "TRUE" } */
+}
diff --git a/gcc/testsuite/g++.dg/analyzer/vfunc-5.C b/gcc/testsuite/g++.dg/analyzer/vfunc-5.C
new file mode 100644
index 00000000000..2af84657f67
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/vfunc-5.C
@@ -0,0 +1,103 @@
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fdiagnostics-show-caret" } */
+/* { dg-enable-nn-line-numbers "" } */
+
+#include <cstdlib>
+
+struct Base
+{
+    virtual void allocate ();
+    virtual void deallocate (); 
+};
+
+struct Derived: public Base
+{
+    int *ptr;
+    void allocate ()
+    {
+        ptr = (int*)malloc(sizeof(int));
+    }
+    void deallocate () 
+    { 
+        free(ptr);
+    }
+};
+
+void test()
+{
+    Derived D;
+    Base B, *base_ptr;
+    base_ptr = &D;
+
+    D.allocate();
+    base_ptr->deallocate();
+    int n = *D.ptr;   /* { dg-warning "use after 'free' of 'D.Derived::ptr'" } */
+}
+
+/* use after 'free'  */
+/* { dg-begin-multiline-output "" }
+   NN |     int n = *D.ptr;
+      |         ^
+  'void test()': events 1-2
+    |
+    |   NN | void test()
+    |      |      ^~~~
+    |      |      |
+    |      |      (1) entry to 'test'
+    |......
+    |   NN |     D.allocate();
+    |      |     ~~~~~~~~~~~~
+    |      |               |
+    |      |               (2) calling 'Derived::allocate' from 'test'
+    |
+    +--> 'virtual void Derived::allocate()': events 3-4
+           |
+           |   NN |     void allocate ()
+           |      |          ^~~~~~~~
+           |      |          |
+           |      |          (3) entry to 'Derived::allocate'
+           |   NN |     {
+           |   NN |         ptr = (int*)malloc(sizeof(int));
+           |      |                     ~~~~~~~~~~~~~~~~~~~
+           |      |                           |
+           |      |                           (4) allocated here
+           |
+    <------+
+    |
+  'void test()': events 5-6
+    |
+    |   NN |     D.allocate();
+    |      |     ~~~~~~~~~~^~
+    |      |               |
+    |      |               (5) returning to 'test' from 'Derived::allocate'
+    |   NN |     base_ptr->deallocate();
+    |      |     ~~~~~~~~~~~~~~~~~~~~~~
+    |      |                         |
+    |      |                         (6) calling 'Derived::deallocate' from 'test'
+    |
+    +--> 'virtual void Derived::deallocate()': events 7-8
+           |
+           |   NN |     void deallocate ()
+           |      |          ^~~~~~~~~~
+           |      |          |
+           |      |          (7) entry to 'Derived::deallocate'
+           |   NN |     {
+           |   NN |         free(ptr);
+           |      |         ~~~~~~~~~
+           |      |             |
+           |      |             (8) freed here
+           |
+    <------+
+    |
+  'void test()': events 9-10
+    |
+    |   NN |     base_ptr->deallocate();
+    |      |     ~~~~~~~~~~~~~~~~~~~~^~
+    |      |                         |
+    |      |                         (9) returning to 'test' from 'Derived::deallocate'
+    |   NN |     int n = *D.ptr;
+    |      |         ~                
+    |      |         |
+    |      |         (10) use after 'free' of 'D.Derived::ptr'; freed at (8)
+    |
+   { dg-end-multiline-output "" } */
+


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-08-18 17:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-18 17:41 [gcc r12-3003] analyzer: detect and analyze virtual function calls Ankur saini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).