Patchwork PR c++/48574

login
register
mail settings
Submitter Dodji Seketeli
Date April 13, 2011, 1:40 p.m.
Message ID <m3lizeb77i.fsf@redhat.com>
Download mbox | patch
Permalink /patch/91012/
State New
Headers show

Comments

Dodji Seketeli - April 13, 2011, 1:40 p.m.
Hello,

Consider this short code snippet:

    struct A
    {
      virtual void foo();
    };

    template <typename T>
    void
    bar(T x)
    {
      A &b = *x;
      b.foo();
    }

When we look at b.foo() during the parsing (in
cp_parser_postfix_expression), 'b.foo()' is (rightfully) considered
non-dependent.  So we go on an build the method call expression.  Then
build_new_method_call wants to know the determine the dynamic type of
'b' and uses fixed_type_or_null for that.

fixed_type_or_null goes to look into the initializer of the reference
variable 'b', which is dependent; and it crashes while trying to poke at
the type of the INDIRECT_REF '*x', which has no type yet (because it's
dependent).

The patch below makes fixed_type_or_null consider that it cannot
determine the dynamic type of a reference variable if its initializer is
dependent.

Tested on x86_64-unknown-linux-gnu against trunk.

gcc/cp/

	* class.c (fixed_type_or_null): We cannot determine the dynamic
	type of a reference variable if its initializer is dependent.

gcc/testsuite/

	* g++.dg/template/dependent-expr7.C: New test case.
---
 gcc/cp/class.c                                  |    8 ++++++++
 gcc/testsuite/g++.dg/template/dependent-expr7.C |   22 ++++++++++++++++++++++
 2 files changed, 30 insertions(+), 0 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/dependent-expr7.C
Jason Merrill - April 13, 2011, 2:17 p.m.
On 04/13/2011 09:40 AM, Dodji Seketeli wrote:
> +	      if (type_dependent_expression_p (DECL_INITIAL (instance)))
> +		{
> +		  /* The initializer is type dependent so we cannot
> +		     determine the dynamic type of this reference.   */
> +		  if (nonnull)
> +		    *nonnull = 0;
> +		  return NULL_TREE;
> +		}

*nonnull should still be true in this case; even if we don't know what 
the reference refers to, we can still assume that it refers to 
something.  Otherwise OK.

Jason

Patch

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b6aebae..d40c11c 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5944,6 +5944,14 @@  fixed_type_or_null (tree instance, int *nonnull, int *cdtorp)
 	      tree type;
 	      void **slot;
 
+	      if (type_dependent_expression_p (DECL_INITIAL (instance)))
+		{
+		  /* The initializer is type dependent so we cannot
+		     determine the dynamic type of this reference.   */
+		  if (nonnull)
+		    *nonnull = 0;
+		  return NULL_TREE;
+		}
 	      slot = htab_find_slot (ht, instance, INSERT);
 	      *slot = instance;
 	      type = RECUR (DECL_INITIAL (instance));
diff --git a/gcc/testsuite/g++.dg/template/dependent-expr7.C b/gcc/testsuite/g++.dg/template/dependent-expr7.C
new file mode 100644
index 0000000..b246820
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-expr7.C
@@ -0,0 +1,22 @@ 
+// Origin PR c++/48574
+// { dg-do compile }
+
+struct A
+{
+  virtual void foo();
+};
+
+template <typename T>
+void
+bar(T x)
+{
+  A &b = *x;
+  b.foo ();
+}
+
+void
+foo()
+{
+  A a;
+  bar(&a);
+}