Bug 14511 - [tree-ssa] "pure virtual method called" error when calling a method on a static_casted object
Summary: [tree-ssa] "pure virtual method called" error when calling a method on a stat...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: tree-ssa
: P2 critical
Target Milestone: tree-ssa
Assignee: Diego Novillo
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2004-03-10 07:03 UTC by Brian Ryner
Modified: 2004-03-17 19:45 UTC (History)
1 user (show)

See Also:
Host: i686-pc-linux-gnu
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2004-03-10 19:01:17


Attachments
testcase (141 bytes, text/plain)
2004-03-10 07:04 UTC, Brian Ryner
Details
Patch to mark VA_ARG_EXPR operands volatile as they are created (997 bytes, patch)
2004-03-15 21:35 UTC, Diego Novillo
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Brian Ryner 2004-03-10 07:03:24 UTC
On a tree-ssa build pulled today, I get "pure virtual method called" (and
execution aborts) if I attempt to call a method on a static_casted pointer.  I
believe this regressed within the past few weeks.  The error occurs with -O2,
but not with -O.  gcc build details:

$ c++ -v
Reading specs from /usr/gcc-ssa/lib/gcc/i686-pc-linux-gnu/3.5-tree-ssa/specs
Configured with: ../gcc/configure --prefix=/usr/gcc-ssa --enable-shared
--enable-threads=posix --with-system-zlib --enable-__cxa_atexit
--host=i686-pc-linux-gnu --enable-languages=c,c++ --disable-checking
Thread model: posix
gcc version 3.5-tree-ssa 20040309 (merged 20040307)
Comment 1 Brian Ryner 2004-03-10 07:04:30 UTC
Created attachment 5891 [details]
testcase

testcase output:

$ c++ -O2 -o test_virt_cast test_virt_cast.cpp
$ ./test_virt_cast
pure virtual method called
terminate called without an active exception
Aborted
Comment 2 Andrew Pinski 2004-03-10 14:37:59 UTC
Confirmed, this is an aliasing problem (I think caused by the C++ front-end).
Comment 3 Andrew Pinski 2004-03-10 19:01:16 UTC
The issue I think is that the structs are not marked as they can alias each other.
Comment 4 Diego Novillo 2004-03-15 21:35:33 UTC
Created attachment 5927 [details]
Patch to mark VA_ARG_EXPR operands volatile as they are created
Comment 5 Diego Novillo 2004-03-15 21:36:20 UTC
dammit!  Bugzilla tricked me again and I attached a patch to the wrong case.  
Please disregard
Comment 6 Diego Novillo 2004-03-17 19:28:08 UTC
Subject: Re:  [tree-ssa] "pure virtual method
	called" error when calling a method on a static_casted object

On Wed, 2004-03-10 at 14:01, pinskia at gcc dot gnu dot org wrote:
> ------- Additional Comments From pinskia at gcc dot gnu dot org  2004-03-10 19:01 -------
> The issue I think is that the structs are not marked as they can alias each other.
>
Indeed.  The problem occurs when we replace the RHS of (3) with
&_ZTV4IFoo<D1485>[2]

     1.   this<D1553>_6->_vptr.IFoo<D1483> = &_ZTV4IFoo<D1485>[2];
     2.   this<D1550>_4->_vptr.IFoo<D1511> = &_ZTV3Bar<D1512>[2];
     3.   T.3<D1532>_10 = this<D1553>_6->_vptr.IFoo<D1483>;
     4.   T.4<D1533>_11 = *T.3<D1532>_10;
     5.   #   VUSE <_ZTV4IFoo_1>;
     6.   #   VUSE <_ZTV3Bar_2>;
     7.   T.4_11 (this<D1553>_6);

The alias pass was not computing type aliases properly for this<D1553>
and this<D1550> for two reasons:

      * Variables _ZTV4IFoo<D1485> and _ZTV3Bar<D1512 are read-only, so
        they were being ignored.  However, ignoring them meant that the
        alias sets for this<D1553> and this<D1550> were not being
        populated, therefore the two memory tags were not found to
        conflict, allowing DOM to propagate (1) into (3).
      * The sub-type checking in may_alias_p was not computing the right
        pointer-to type for ARRAY_TYPEs.

Bootstrapped and tested on x86, x86-64 and ia64.


Diego.


	* tree-ssa-alias.c (compute_flow_insensitive_aliasing): Do not
	ignore read-only variables.
	(may_alias_p): Fix pointer-to-var calculation when 'var' is an
	array.

testsuite/ChangeLog.tree-ssa:

	* g++.dg/tree-ssa/20040317-1.C: New test.

Index: tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-alias.c,v
retrieving revision 1.1.2.12
diff -d -c -p -d -u -p -r1.1.2.12 tree-ssa-alias.c
--- tree-ssa-alias.c	16 Mar 2004 22:31:55 -0000	1.1.2.12
+++ tree-ssa-alias.c	17 Mar 2004 19:17:31 -0000
@@ -797,10 +797,6 @@ compute_flow_insensitive_aliasing (struc
 	  if (!tag_stored_p && !var_stored_p)
 	    continue;
 	     
-	  /* Skip memory tags which are written if the variable is readonly.  */
-	  if (tag_stored_p && TREE_READONLY (var))
-	    continue;
-
 	  if (may_alias_p (p_map->var, p_map->set, var, v_map->set))
 	    {
 	      size_t num_tag_refs = ai->num_references[tag_ann->uid];
@@ -1337,7 +1333,12 @@ may_alias_p (tree ptr, HOST_WIDE_INT mem
       if (AGGREGATE_TYPE_P (TREE_TYPE (mem))
 	  || AGGREGATE_TYPE_P (TREE_TYPE (var)))
 	{
-	  tree ptr_to_var = TYPE_POINTER_TO (TREE_TYPE (var));
+	  tree ptr_to_var;
+	  
+	  if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
+	    ptr_to_var = TYPE_POINTER_TO (TREE_TYPE (TREE_TYPE (var)));
+	  else
+	    ptr_to_var = TYPE_POINTER_TO (TREE_TYPE (var));
 
 	  /* If no pointer-to VAR exists, then MEM can't alias VAR.  */
 	  if (ptr_to_var == NULL_TREE)
Index: testsuite/g++.dg/tree-ssa/20040317-1.C
===================================================================
RCS file: testsuite/g++.dg/tree-ssa/20040317-1.C
diff -N testsuite/g++.dg/tree-ssa/20040317-1.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/g++.dg/tree-ssa/20040317-1.C	17 Mar 2004 19:17:31 -0000
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+/* Test provided by Brian Ryner in PR 14511.  The alias analyzer was
+   not handling structures containing arrays properly.  In this case,
+   the static cast was introducing two assignments of the form
+
+	  this_6->_vptr.IFoo = &_ZTV4IFoo[2];
+	  this_4->_vptr.IFoo = &_ZTV3Bar[2];
+
+   which were not considered to alias each other because the alias
+   analyzer was not computing a proper pointer to array elements.
+   Another related bug was the type based alias analyzer not computing
+   alias relations to _ZTV4IFoo and _ZTV3Bar.  Since those variables
+   are read-only, it was disregarding alias information for them.
+   So, the memory tags for the two 'this' variables were not being
+   marked as aliased with these variables.  Resulting in the two
+   assignments not aliasing each other.
+
+   This was causing the optimizers to generate a call to the virtual
+   method Foo() instead of the overloaded version.  */
+
+struct IFoo
+{
+  virtual void Foo() = 0;
+};
+
+struct Bar : IFoo
+{
+  void Foo() { }
+};
+
+int main(int argc, char **argv)
+{
+  Bar* b = new Bar();
+  static_cast<IFoo*>(b)->Foo();
+  return 0;
+}

Comment 8 Diego Novillo 2004-03-17 19:45:45 UTC
Fixed.