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

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);
+}
-- 
                Dodji

Reply via email to