Commit 3e4a3562 by Nathan Sidwell Committed by Nathan Sidwell

PR c++/9978, c++/9708

cp:
	PR c++/9978, c++/9708
	* cp-tree.h (instantiate_template): Add tsubst_flags parameter.
	* call.c (add_template_candidate_real): Adjust
	instantiate_template call.
	* class.c (resolve_address_of_overloaded_function): Likewise.
	* decl.c (build_enumerator): Set TREE_CONSTANT.
	* pt.c (check_instantiated_args): New.
	(push_inline_template_parms_recursive): Set TREE_CONSTANT,
	TREE_READONLY.
	(build_template_parm_index): Copy TREE_CONSTANT, TREE_READONLY.
	(reduce_template_parm_level): Likewise.
	(process_template_parm): Likewise.
	(check_explicit_specialization): Adjust instantiate_template call.
	(convert_template_argument): Don't check non-type argument here.
	(lookup_template_class): Check them here.
	(tsubst_friend_function): Adjust instantiate_template call.
	(instantiate_template): Add tsubst_flags parameter, use it. Check
	instantiated args.
testsuite:
	PR c++/9978, c++/9708
	* g++.dg/ext/vlm1.C: Adjust expected error.
	* g++.dg/ext/vla2.C: New test.
	* g++.dg/template/arg1.C: New test.
	* g++.dg/template/arg2.C: New test.

From-SVN: r64714
parent c8fcf20c
2003-03-22 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9978, c++/9708
* cp-tree.h (instantiate_template): Add tsubst_flags parameter.
* call.c (add_template_candidate_real): Adjust
instantiate_template call.
* class.c (resolve_address_of_overloaded_function): Likewise.
* decl.c (build_enumerator): Set TREE_CONSTANT.
* pt.c (check_instantiated_args): New.
(push_inline_template_parms_recursive): Set TREE_CONSTANT,
TREE_READONLY.
(build_template_parm_index): Copy TREE_CONSTANT, TREE_READONLY.
(reduce_template_parm_level): Likewise.
(process_template_parm): Likewise.
(check_explicit_specialization): Adjust instantiate_template call.
(convert_template_argument): Don't check non-type argument here.
(lookup_template_class): Check them here.
(tsubst_friend_function): Adjust instantiate_template call.
(instantiate_template): Add tsubst_flags parameter, use it. Check
instantiated args.
2003-03-21 Zack Weinberg <zack@codesourcery.com>
* decl.c: Update calls to shadow_warning.
......
......@@ -2275,7 +2275,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
if (i != 0)
return NULL;
fn = instantiate_template (tmpl, targs);
fn = instantiate_template (tmpl, targs, tf_none);
if (fn == error_mark_node)
return NULL;
......
......@@ -5989,7 +5989,8 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
continue;
/* Instantiate the template. */
instantiation = instantiate_template (fn, targs);
instantiation = instantiate_template (fn, targs,
complain ? tf_error : tf_none);
if (instantiation == error_mark_node)
/* Instantiation failed. */
continue;
......
......@@ -4016,7 +4016,7 @@ extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t)
extern tree lookup_template_function (tree, tree);
extern int uses_template_parms (tree);
extern tree instantiate_class_template (tree);
extern tree instantiate_template (tree, tree);
extern tree instantiate_template (tree, tree, tsubst_flags_t);
extern int fn_type_unification (tree, tree, tree, tree, tree, unification_kind_t, int);
extern tree tinst_for_decl (void);
extern void mark_decl_instantiated (tree, int);
......
......@@ -13286,8 +13286,8 @@ build_enumerator (tree name, tree value, tree enumtype)
decl = build_decl (CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;
TREE_READONLY (decl) = 1;
if (context && context == current_class_type)
/* In something like `struct S { enum E { i = 7 }; };' we put `i'
......
......@@ -110,6 +110,7 @@ static tree coerce_template_parms PARAMS ((tree, tree, tree,
static void tsubst_enum PARAMS ((tree, tree, tree));
static tree add_to_template_args PARAMS ((tree, tree));
static tree add_outermost_template_args PARAMS ((tree, tree));
static bool check_instantiated_args PARAMS ((tree, tree, tsubst_flags_t));
static int maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*,
tree*));
static int type_unification_real PARAMS ((tree, tree, tree, tree,
......@@ -429,6 +430,7 @@ push_inline_template_parms_recursive (parmlist, levels)
tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
TREE_TYPE (parm));
DECL_ARTIFICIAL (decl) = 1;
TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = DECL_INITIAL (parm);
SET_DECL_TEMPLATE_PARM_P (decl);
pushdecl (decl);
......@@ -1839,7 +1841,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
targs = new_targs;
}
return instantiate_template (tmpl, targs);
return instantiate_template (tmpl, targs, tf_error);
}
/* If this is a specialization of a member template of a
......@@ -2050,6 +2052,8 @@ build_template_parm_index (index, level, orig_level, decl, type)
TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level;
TEMPLATE_PARM_DECL (t) = decl;
TREE_TYPE (t) = type;
TREE_CONSTANT (t) = TREE_CONSTANT (decl);
TREE_READONLY (t) = TREE_READONLY (decl);
return t;
}
......@@ -2069,20 +2073,21 @@ reduce_template_parm_level (index, type, levels)
|| (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
!= TEMPLATE_PARM_LEVEL (index) - levels))
{
tree decl
= build_decl (TREE_CODE (TEMPLATE_PARM_DECL (index)),
DECL_NAME (TEMPLATE_PARM_DECL (index)),
type);
tree t
= build_template_parm_index (TEMPLATE_PARM_IDX (index),
tree orig_decl = TEMPLATE_PARM_DECL (index);
tree decl, t;
decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
TREE_READONLY (decl) = TREE_READONLY (orig_decl);
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
t = build_template_parm_index (TEMPLATE_PARM_IDX (index),
TEMPLATE_PARM_LEVEL (index) - levels,
TEMPLATE_PARM_ORIG_LEVEL (index),
decl, type);
TEMPLATE_PARM_DESCENDANTS (index) = t;
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
/* Template template parameters need this. */
DECL_TEMPLATE_PARMS (decl)
= DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));
......@@ -2137,10 +2142,11 @@ process_template_parm (list, next)
TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
TREE_READONLY (parm) = TREE_CONSTANT (parm) = 1;
if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
TREE_TYPE (parm) = void_type_node;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
processing_template_decl,
......@@ -3632,39 +3638,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
}
}
else
{
val = groktypename (arg);
if (! processing_template_decl)
{
/* [basic.link]: A name with no linkage (notably, the
name of a class or enumeration declared in a local
scope) shall not be used to declare an entity with
linkage. This implies that names with no linkage
cannot be used as template arguments. */
tree t = no_linkage_check (val);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
pedwarn
("template-argument `%T' uses anonymous type", val);
else
error
("template-argument `%T' uses local type `%T'",
val, t);
return error_mark_node;
}
/* In order to avoid all sorts of complications, we do
not allow variably-modified types as template
arguments. */
if (variably_modified_type_p (val))
{
error ("template-argument `%T' is a variably modified type",
val);
return error_mark_node;
}
}
}
val = groktypename (arg);
}
else
{
......@@ -3704,9 +3678,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
/* Convert all template arguments to their appropriate types, and
return a vector containing the innermost resulting template
arguments. If any error occurs, return error_mark_node. Error and
warning messages are issued under control of COMPLAIN. Some error
messages are issued even if COMPLAIN is zero; for instance, if a
template argument is composed from a local class.
warning messages are issued under control of COMPLAIN.
If REQUIRE_ALL_ARGUMENTS is nonzero, all arguments must be
provided in ARGLIST, or else trailing parameters must have default
......@@ -4207,7 +4179,9 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
arglist2 = coerce_template_parms (parmlist, arglist, template,
complain, /*require_all_args=*/1);
if (arglist2 == error_mark_node)
if (arglist2 == error_mark_node
|| (!processing_template_decl
&& check_instantiated_args (template, arglist2, complain)))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
......@@ -4296,7 +4270,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
template,
complain, /*require_all_args=*/1);
if (arglist == error_mark_node)
if (arglist == error_mark_node
|| (!processing_template_decl
&& check_instantiated_args (template,
INNERMOST_TEMPLATE_ARGS (arglist),
complain)))
/* We were unable to bind the arguments. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
......@@ -4919,7 +4897,7 @@ tsubst_friend_function (decl, args)
tmpl = determine_specialization (template_id, new_friend,
&new_args,
/*need_member_template=*/0);
new_friend = instantiate_template (tmpl, new_args);
new_friend = instantiate_template (tmpl, new_args, tf_error);
goto done;
}
......@@ -8394,18 +8372,78 @@ tsubst_copy_and_build (t, args, complain, in_decl)
}
}
/* Verify that the instantiated ARGS are valid. For type arguments,
make sure that the type's linkage is ok. For non-type arguments,
make sure they are constants if they are integral or enumarations.
Emit an error under control of COMPLAIN, and return TRUE on error. */
static bool
check_instantiated_args (tmpl, args, complain)
tree tmpl, args;
tsubst_flags_t complain;
{
int ix, len = DECL_NTPARMS (tmpl);
bool result = false;
for (ix = 0; ix != len; ix++)
{
tree t = TREE_VEC_ELT (args, ix);
if (TYPE_P (t))
{
/* [basic.link]: A name with no linkage (notably, the name
of a class or enumeration declared in a local scope)
shall not be used to declare an entity with linkage.
This implies that names with no linkage cannot be used as
template arguments. */
tree nt = no_linkage_check (t);
if (nt)
{
if (!(complain & tf_error))
/*OK*/;
else if (TYPE_ANONYMOUS_P (nt))
error ("`%T' uses anonymous type", t);
else
error ("`%T' uses local type `%T'", t, nt);
result = true;
}
/* In order to avoid all sorts of complications, we do not
allow variably-modified types as template arguments. */
else if (variably_modified_type_p (t))
{
if (complain & tf_error)
error ("`%T' is a variably modified type", t);
result = true;
}
}
/* A non-type argument of integral or enumerated type must be a
constant. */
else if (TREE_TYPE (t)
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
&& !TREE_CONSTANT (t))
{
if (complain & tf_error)
error ("integral expression `%E' is not constant", t);
result = true;
}
}
if (result && complain & tf_error)
error (" trying to instantiate `%D'", tmpl);
return result;
}
/* Instantiate the indicated variable or function template TMPL with
the template arguments in TARG_PTR. */
tree
instantiate_template (tmpl, targ_ptr)
instantiate_template (tmpl, targ_ptr, complain)
tree tmpl, targ_ptr;
tsubst_flags_t complain;
{
tree fndecl;
tree gen_tmpl;
tree spec;
int i, len;
tree inner_args;
if (tmpl == error_mark_node)
return error_mark_node;
......@@ -8415,7 +8453,8 @@ instantiate_template (tmpl, targ_ptr)
/* If this function is a clone, handle it specially. */
if (DECL_CLONED_FUNCTION_P (tmpl))
{
tree spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr);
tree spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr,
complain);
tree clone;
/* Look for the clone. */
......@@ -8449,34 +8488,20 @@ instantiate_template (tmpl, targ_ptr)
return spec;
}
len = DECL_NTPARMS (gen_tmpl);
inner_args = INNERMOST_TEMPLATE_ARGS (targ_ptr);
i = len;
while (i--)
{
tree t = TREE_VEC_ELT (inner_args, i);
if (TYPE_P (t))
{
tree nt = target_type (t);
if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt)))
{
error ("type `%T' composed from a local class is not a valid template-argument", t);
error (" trying to instantiate `%D'", gen_tmpl);
return error_mark_node;
}
}
}
if (check_instantiated_args (gen_tmpl, INNERMOST_TEMPLATE_ARGS (targ_ptr),
complain))
return error_mark_node;
/* Make sure that we can see identifiers, and compute access
correctly. The desired FUNCTION_DECL for FNDECL may or may not be
created earlier. Let push_access_scope_real figure that out. */
push_access_scope_real
(gen_tmpl, targ_ptr, tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
tf_error, gen_tmpl));
complain, gen_tmpl));
/* substitute template parameters */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, tf_error, gen_tmpl);
targ_ptr, complain, gen_tmpl);
pop_access_scope (gen_tmpl);
......
2003-03-22 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9978, c++/9708
* g++.dg/ext/vlm1.C: Adjust expected error.
* g++.dg/ext/vla2.C: New test.
* g++.dg/template/arg1.C: New test.
* g++.dg/template/arg2.C: New test.
2003-03-22 Bud Davis <bdavis9659@comcast.net>
* g77.f-torture/execute/select.f: New test.
......
// { dg-do compile }
// { dg-options "" }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 21 Mar 2003 <nathan@codesourcery.com>
// PR 9708. We unified a VLA size as a constant. Then issued bogus
// errors.
template <unsigned int N>
char* begin(char (&a) [N] );
void bar(int i)
{
char d[i] ;
begin(d); // { dg-error "no matching function" "" }
}
......@@ -4,7 +4,7 @@ template <class T> struct A {};
struct B {
static const int s;
A<int[s]> a; // { dg-error "variably modified|no type" }
A<int[s]> a; // { dg-error "variably modified|no type|trying to instantiate" }
};
const int B::s=16;
......
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 21 Mar 2003 <nathan@codesourcery.com>
// PR 9978. We rejected a constant expression.
enum { val = 1 };
template <class T>
struct Bar
{
static const int A = val;
static const int B = A + 1;
};
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 21 Mar 2003 <nathan@codesourcery.com>
// PR 9708. We accepted a local class
template <typename T> class X {};
void fn ()
{
class L {};
X<L> f; // { dg-error "uses local type|trying to instantiate|expected" "" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment