This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, RFA, C++] ICE on ill-formed template_fun(&mem_fun) withintemplate function
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 25 Sep 2005 02:22:09 -0300
- Subject: [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}