Patchwork C++ PATCH for c++/44778 (4.6 ptrmem regression)

login
register
mail settings
Submitter Jason Merrill
Date July 6, 2010, 7:21 p.m.
Message ID <4C33822E.7060004@redhat.com>
Download mbox | patch
Permalink /patch/58056/
State New
Headers show

Comments

Jason Merrill - July 6, 2010, 7:21 p.m.
Some fallout from the dependent_scope_ref_p change; now that we can get 
a non-dependent SCOPE_REF in build_offset_ref, we need to handle it 
properly.  In this case the qualified-id is not dependent, but when we 
take its address we get a type-dependent pointer to member.

Tested x86_64-pc-linux-gnu, applied to trunk.

Patch

commit 9b53d24ba67dae7b803edbb8d2e46e2600cb41fb
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jul 2 23:48:32 2010 -0400

    	PR c++/44778
    	* init.c (build_offset_ref): If scope isn't dependent,
    	don't exit early.  Look at TYPE_MAIN_VARIANT.
    	* pt.c (tsubst_copy) [OFFSET_REF]: Do substitution.

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index ec7dca9..20f921d 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1507,18 +1507,9 @@  build_offset_ref (tree type, tree member, bool address_p)
   if (TREE_CODE (member) == TEMPLATE_DECL)
     return member;
 
-  if (dependent_type_p (type) || type_dependent_expression_p (member))
-    {
-      tree ref, mem_type = NULL_TREE;
-      if (!dependent_scope_p (type))
-	mem_type = TREE_TYPE (member);
-      ref = build_qualified_name (mem_type, type, member,
+  if (dependent_scope_p (type) || type_dependent_expression_p (member))
+    return build_qualified_name (NULL_TREE, type, member,
 				  /*template_p=*/false);
-      /* Undo convert_from_reference.  */
-      if (TREE_CODE (ref) == INDIRECT_REF)
-	ref = TREE_OPERAND (ref, 0);
-      return ref;
-    }
 
   gcc_assert (TYPE_P (type));
   if (! is_class_type (type, 1))
@@ -1528,6 +1519,7 @@  build_offset_ref (tree type, tree member, bool address_p)
   /* Callers should call mark_used before this point.  */
   gcc_assert (!DECL_P (member) || TREE_USED (member));
 
+  type = TYPE_MAIN_VARIANT (type);
   if (!COMPLETE_OR_OPEN_TYPE_P (complete_type (type)))
     {
       error ("incomplete type %qT does not have member %qD", type, member);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f542b21..80cf7d2 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11309,8 +11309,13 @@  tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       gcc_unreachable ();
 
     case OFFSET_REF:
-      mark_used (TREE_OPERAND (t, 1));
-      return t;
+      r = build2
+	(code, tsubst (TREE_TYPE (t), args, complain, in_decl),
+	 tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+	 tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+      PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
+      mark_used (TREE_OPERAND (r, 1));
+      return r;
 
     case EXPR_PACK_EXPANSION:
       error ("invalid use of pack expansion expression");
diff --git a/gcc/testsuite/g++.dg/template/ptrmem17.C b/gcc/testsuite/g++.dg/template/ptrmem17.C
index a79e3c8..5c5ee3f 100644
--- a/gcc/testsuite/g++.dg/template/ptrmem17.C
+++ b/gcc/testsuite/g++.dg/template/ptrmem17.C
@@ -7,4 +7,4 @@  template<int> struct A
   ~A() { &A::i; } // { dg-error "reference" }
 };
 
-A<0> a; // { dg-message "instantiated" }
+A<0> a;
diff --git a/gcc/testsuite/g++.dg/template/ptrmem22.C b/gcc/testsuite/g++.dg/template/ptrmem22.C
new file mode 100644
index 0000000..762f377
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ptrmem22.C
@@ -0,0 +1,29 @@ 
+// PR c++/44778
+
+enum Healpix_Ordering_Scheme { RING, NEST };
+
+class Healpix_Base
+  {
+  protected:
+    Healpix_Ordering_Scheme scheme_;
+    int nest2ring (int pix) const;
+    int ring2nest (int pix) const;
+
+    typedef int (Healpix_Base::*swapfunc)(int pix) const;
+  };
+
+template<typename T> class Healpix_Map: public Healpix_Base
+  {
+  public:
+    void Import_nograde (const Healpix_Map<T> &orig)
+      {
+        swapfunc swapper = (scheme_ == NEST) ?
+          &Healpix_Map::ring2nest : &Healpix_Map::nest2ring;
+      }
+  };
+
+int main()
+  {
+  Healpix_Map<double> a,b;
+  a.Import_nograde(b);
+  }