re PR c++/27787 (Qualified lookup fails to find inherited class template)

cp/
	PR c++/27787
	* decl.c (make_typename_type): Only try and resolve it when
	context is not dependent.  Refactor.
	* decl2.c (check_classfn): Push to class scope before looking for
	the function.
testsuite/
	PR c++/27787
	* g++.dg/template/typename10.C: New.
	* g++.dg/template/lookup4.C: Remove bogus error marker.

From-SVN: r116409
This commit is contained in:
Nathan Sidwell 2006-08-25 16:56:07 +00:00 committed by Nathan Sidwell
parent 9eb8a531c0
commit 7d3bec9db5
6 changed files with 104 additions and 68 deletions

View File

@ -1,3 +1,11 @@
2006-08-25 Nathan Sidwell <nathan@codesourcery.com>
PR c++/27787
* decl.c (make_typename_type): Only try and resolve it when
context is not dependent. Refactor.
* decl2.c (check_classfn): Push to class scope before looking for
the function.
2006-08-24 Danny Smith <dannysmith@users.sourceforge.net>
PR driver/28528

View File

@ -2779,6 +2779,8 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
tsubst_flags_t complain)
{
tree fullname;
tree t;
bool want_template;
if (name == error_mark_node
|| context == NULL_TREE
@ -2816,73 +2818,60 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
gcc_assert (TYPE_P (context));
if (!dependent_type_p (context)
|| currently_open_class (context))
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
{
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
error ("no class template named %q#T in %q#T",
name, context);
return error_mark_node;
}
/* When the CONTEXT is a dependent type, NAME could refer to a
dependent base class of CONTEXT. So we cannot peek inside it,
even if CONTEXT is a currently open scope. */
if (dependent_type_p (context))
return build_typename_type (context, name, fullname, tag_type);
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
NULL_TREE, context,
/*entering_scope=*/0,
tf_warning_or_error | tf_user);
}
else
{
tree t;
if (!IS_AGGR_TYPE (context))
{
if (complain & tf_error)
error ("no type named %q#T in %q#T", name, context);
return error_mark_node;
}
t = lookup_field (context, name, 0, true);
if (t)
{
if (TREE_CODE (t) != TYPE_DECL)
{
if (complain & tf_error)
error ("no type named %q#T in %q#T", name, context);
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), t);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
return t;
}
}
}
/* If the CONTEXT is not a template type, then either the field is
there now or its never going to be. */
if (!dependent_type_p (context))
if (!IS_AGGR_TYPE (context))
{
if (complain & tf_error)
error ("no type named %q#T in %q#T", name, context);
error ("%q#T is not a class", context);
return error_mark_node;
}
want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
/* We should only set WANT_TYPE when we're a nested typename type.
Then we can give better diagnostics if we find a non-type. */
t = lookup_field (context, name, 0, /*want_type=*/true);
if (!t)
{
if (complain & tf_error)
error (want_template ? "no class template named %q#T in %q#T"
: "no type named %q#T in %q#T", name, context);
return error_mark_node;
}
if (want_template && !DECL_CLASS_TEMPLATE_P (t))
{
if (complain & tf_error)
error ("%<typename %T::%D%> names %q#T, which is not a class template",
context, name, t);
return error_mark_node;
}
if (!want_template && TREE_CODE (t) != TYPE_DECL)
{
if (complain & tf_error)
error ("%<typename %T::%D%> names %q#T, which is not a type",
context, name, t);
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), t);
return build_typename_type (context, name, fullname, tag_type);
if (want_template)
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
NULL_TREE, context,
/*entering_scope=*/0,
tf_warning_or_error | tf_user);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
return t;
}
/* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name

View File

@ -553,7 +553,8 @@ check_classfn (tree ctype, tree function, tree template_parms)
{
int ix;
bool is_template;
tree pushed_scope;
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
&& DECL_TEMPLATE_SPECIALIZATION (function))
@ -583,16 +584,18 @@ check_classfn (tree ctype, tree function, tree template_parms)
/* OK, is this a definition of a member template? */
is_template = (template_parms != NULL_TREE);
/* We must enter the scope here, because conversion operators are
named by target type, and type equivalence relies on typenames
resolving within the scope of CTYPE. */
pushed_scope = push_scope (ctype);
ix = class_method_index_for_fn (complete_type (ctype), function);
if (ix >= 0)
{
VEC(tree,gc) *methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl = 0;
bool is_conv_op;
tree pushed_scope;
const char *format = NULL;
pushed_scope = push_scope (ctype);
for (fndecls = VEC_index (tree, methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
@ -631,10 +634,13 @@ check_classfn (tree ctype, tree function, tree template_parms)
== DECL_TI_TEMPLATE (fndecl))))
break;
}
if (pushed_scope)
pop_scope (pushed_scope);
if (fndecls)
return OVL_CURRENT (fndecls);
{
if (pushed_scope)
pop_scope (pushed_scope);
return OVL_CURRENT (fndecls);
}
error ("prototype for %q#D does not match any in class %qT",
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
@ -682,6 +688,9 @@ check_classfn (tree ctype, tree function, tree template_parms)
properly within the class. */
if (COMPLETE_TYPE_P (ctype))
add_method (ctype, function, NULL_TREE);
if (pushed_scope)
pop_scope (pushed_scope);
return NULL_TREE;
}

View File

@ -1,3 +1,9 @@
2006-08-25 Nathan Sidwell <nathan@codesourcery.com>
PR c++/27787
* g++.dg/template/typename10.C: New.
* g++.dg/template/lookup4.C: Remove bogus error marker.
2006-08-25 Richard Guenther <rguenther@suse.de>
PR testsuite/28829

View File

@ -2,5 +2,5 @@
template <class T> struct Base {};
template <class T> struct Derived: public Base<T> {
typename Derived::template Base<double>* p1; // { dg-error "" }
typename Derived::template Base<double>* p1;
};

View File

@ -0,0 +1,24 @@
// { dg-do compile }
// Copyright (C) 2006 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 25 Aug 2006 <nathan@codesourcery.com>
// Origin: Tobias Schwinger <tschwinger@neoscientists.org>
// PR 27787. Too eager to resolve a typename
template<typename X>
struct x
{
template<typename Y>
struct y
{
typedef Y type;
};
};
template<typename A>
struct a : x<A>
{
template<typename B>
typename a::template y<B>::type f(B);
};