This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, RFA, C++] ICE on ill-formed template_fun(&mem_fun) withintemplate function


Details on the bug and the fix in the MIME part below.  Tested on
amd64-linux-gnu.  Ok to install?

Red Hat bugzilla #168260 triggered an ICE on an ill-formed construct,
taking the address of a non-static member function using an
unqualified id, within a template function, and passing that as an
argument in a function call requiring overload resolution.  Fixing
that uncovered a number of other situations in which we used to fail
or to handle things differently within templates.

Index: gcc/cp/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* class.c (instantiate_type): Handle NON_DEPENDENT_EXPR.
	* pt.c (resolve_overloaded_unification): Likewise.
	* typeck.c (finish_class_member_access_expr): Accept
	non-template baselinks.  Use looked-up name instead of identifier.
	Handle PSEUDO_DTOR_EXPR.
	* semantics.c (finish_non_static_data_member): Don't mark
	current_class_ptr as used if it's NULL.

Index: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* g++.dg/template/dependent-expr5.C: New test.

Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c.orig
+++ gcc/cp/class.c
@@ -5865,15 +5865,6 @@ instantiate_type (tree lhstype, tree rhs
   if (TREE_CODE (rhs) == BASELINK)
     rhs = BASELINK_FUNCTIONS (rhs);
 
-  /* If we are in a template, and have a NON_DEPENDENT_EXPR, we cannot
-     deduce any type information.  */
-  if (TREE_CODE (rhs) == NON_DEPENDENT_EXPR)
-    {
-      if (flags & tf_error)
-	error ("not enough type information");
-      return error_mark_node;
-    }
-
   /* We don't overwrite rhs if it is an overloaded function.
      Copying it would destroy the tree link.  */
   if (TREE_CODE (rhs) != OVERLOAD)
@@ -5912,6 +5903,9 @@ instantiate_type (tree lhstype, tree rhs
       TREE_TYPE (rhs) = unknown_type_node;
       return instantiate_type (lhstype, rhs, flags);
 
+    case NON_DEPENDENT_EXPR:
+      return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
+
     case COMPONENT_REF:
       {
 	tree member = TREE_OPERAND (rhs, 1);
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c.orig
+++ gcc/cp/pt.c
@@ -9499,6 +9499,9 @@ resolve_overloaded_unification (tree tpa
   int good = 0;
   bool addr_p;
 
+  if (TREE_CODE (arg) == NON_DEPENDENT_EXPR)
+    arg = TREE_OPERAND (arg, 0);
+
   if (TREE_CODE (arg) == ADDR_EXPR)
     {
       arg = TREE_OPERAND (arg, 0);
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c.orig
+++ gcc/cp/semantics.c
@@ -1351,7 +1351,9 @@ finish_non_static_data_member (tree decl
 
       return error_mark_node;
     }
-  TREE_USED (current_class_ptr) = 1;
+  /* This won't be set if we're tsubsting a template.  */
+  if (current_class_ptr)
+    TREE_USED (current_class_ptr) = 1;
   if (processing_template_decl && !qualifying_scope)
     {
       tree type = TREE_TYPE (decl);
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c.orig
+++ gcc/cp/typeck.c
@@ -1904,11 +1904,8 @@ finish_class_member_access_expr (tree ob
     }
 
   if (BASELINK_P (name))
-    {
-      /* A member function that has already been looked up.  */
-      gcc_assert (TREE_CODE (BASELINK_FUNCTIONS (name)) == TEMPLATE_ID_EXPR);
-      member = name;
-    }
+    /* A member function that has already been looked up.  */
+    member = name;
   else
     {
       bool is_template_id = false;
@@ -1979,6 +1976,9 @@ finish_class_member_access_expr (tree ob
 	    }
 	  if (member == error_mark_node)
 	    return error_mark_node;
+
+	  if (TREE_CODE (orig_name) == IDENTIFIER_NODE)
+	    orig_name = member;
 	}
 
       if (is_template_id)
Index: gcc/testsuite/g++.dg/template/dependent-expr5.C
===================================================================
--- /dev/null
+++ gcc/testsuite/g++.dg/template/dependent-expr5.C
@@ -0,0 +1,114 @@
+// { dg-do compile }
+
+// Copyright 2005 Free Software Foundation
+// contributed by Alexandre Oliva <aoliva@redhat.com>
+// inspired in the failure reported in Red Hat bugzilla #168260.
+
+template<class F> void bind(F f) {}
+
+template<class F> void bindm(F f) {}
+template<class F, class T> void bindm(F (T::*f)(void)) {} // { dg-error "note" }
+
+template<class F> void bindn(F f) {}
+template<class F, class T> void bindn(F (*f)(T)) {}
+
+template<class F> void bindb(F f) {}
+template<class F, class T> void bindb(F (*f)(T)) {} // { dg-error "note" }
+template<class F, class T> void bindb(F (T::*f)(void)) {} // { dg-error "note" }
+
+struct foo {
+  static int baist;
+  int bait;
+  void barf ();
+  static void barf (int);
+
+  struct bar {
+    static int baikst;
+    int baikt;
+    void bark ();
+    static void bark (int);
+
+    bar() {
+      bind (&baist);
+      bind (&foo::baist);
+      bind (&bait); // { dg-error "nonstatic data member" }
+      bind (&foo::bait);
+
+      bind (&baikst);
+      bind (&bar::baikst);
+      bind (&baikt); // ok, this->baikt
+      bind (&bar::baikt);
+
+      bind (&barf); // { dg-error "no matching function" }
+      bind (&foo::barf); // { dg-error "no matching function" }
+
+      bindm (&barf); // { dg-error "no matching function" }
+      bindm (&foo::barf);
+
+      bindn (&barf);
+      bindn (&foo::barf);
+
+      bindb (&barf);
+      bindb (&foo::barf); // { dg-error "ambiguous" }
+
+      bind (&bark); // { dg-error "no matching function" }
+      bind (&bar::bark); // { dg-error "no matching function" }
+
+      bindm (&bark); // { dg-error "no matching function" }
+      bindm (&bar::bark);
+
+      bindn (&bark);
+      bindn (&bar::bark);
+
+      bindb (&bark);
+      bindb (&bar::bark); // { dg-error "ambiguous" }
+    }
+  };
+
+  template <typename T>
+  struct barT {
+    static int baikst;
+    int baikt;
+    void bark ();
+    static void bark (int);
+
+    barT() {
+      bind (&baist);
+      bind (&foo::baist);
+      bind (&bait); // { dg-error "nonstatic data member" }
+      bind (&foo::bait);
+
+      bind (&baikst);
+      bind (&barT::baikst);
+      bind (&baikt); // ok, this->baikt
+      bind (&barT::baikt);
+
+      bind (&barf); // { dg-error "no matching function" }
+      bind (&foo::barf); // { dg-error "no matching function" }
+
+      bindm (&barf); // { dg-error "no matching function" }
+      bindm (&foo::barf);
+
+      bindn (&barf);
+      bindn (&foo::barf);
+
+      bindb (&barf);
+      bindb (&foo::barf); // { dg-error "ambiguous" }
+
+      bind (&bark); // { dg-error "no matching function" }
+      bind (&barT::bark); // { dg-error "no matching function" }
+
+      bindm (&bark); // { dg-error "no matching function" }
+      bindm (&barT::bark);
+
+      bindn (&bark);
+      bindn (&barT::bark);
+
+      bindb (&bark);
+      bindb (&barT::bark); // { dg-error "ambiguous" }
+    }
+  };
+
+  bar bard;
+  barT<void> bart;
+} bad;
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]