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:
parent
9eb8a531c0
commit
7d3bec9db5
@ -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
|
||||
|
111
gcc/cp/decl.c
111
gcc/cp/decl.c
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
24
gcc/testsuite/g++.dg/template/typename10.C
Normal file
24
gcc/testsuite/g++.dg/template/typename10.C
Normal 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);
|
||||
};
|
Loading…
Reference in New Issue
Block a user