Commit f3400fe2 by Jason Merrill Committed by Jason Merrill

pt.c (check_template_shadow): New fn.

	* pt.c (check_template_shadow): New fn.
	* decl2.c (grokfield): Use it.
	* decl.c (pushdecl): Likewise.
	(pushdecl_class_level): Likewise.
	(start_method): Likewise.
	(xref_tag): Don't try to use 't' if we're defining.
Fixes Sec14/7/C14387.cm.
	* call.c (check_dtor_name): Just return an error_mark_node.
	* pt.c (lookup_template_class): Complain about using non-template here.
	* parse.y (apparent_template_type): Not here.
Fixes Sec14/C14339.cm.
	* pt.c (check_explicit_specialization): Complain about specialization
	with C linkage.
Fixes Sec14/C14340.cm.
	* lang-options.h: Add -f{no-,}implicit-inline-templates.
	* pt.c (convert_nontype_argument): Don't assume that any integer
	argument is intended to be a constant-expression.
Fixes Sec14/7/P14245.C.

From-SVN: r24086
parent 2ec10ea9
1998-12-04 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (check_template_shadow): New fn.
* decl2.c (grokfield): Use it.
* decl.c (pushdecl): Likewise.
(pushdecl_class_level): Likewise.
(start_method): Likewise.
(xref_tag): Don't try to use 't' if we're defining.
* call.c (check_dtor_name): Just return an error_mark_node.
* pt.c (lookup_template_class): Complain about using non-template here.
* parse.y (apparent_template_type): Not here.
* pt.c (check_explicit_specialization): Complain about specialization
with C linkage.
* lang-options.h: Add -f{no-,}implicit-inline-templates.
* pt.c (convert_nontype_argument): Don't assume that any integer
argument is intended to be a constant-expression.
1998-12-03 Mark Mitchell <mark@markmitchell.com> 1998-12-03 Mark Mitchell <mark@markmitchell.com>
* class.c (handle_using_decl): Fix comment. Don't lookup * class.c (handle_using_decl): Fix comment. Don't lookup
...@@ -1416,7 +1437,6 @@ Tue Oct 6 07:57:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> ...@@ -1416,7 +1437,6 @@ Tue Oct 6 07:57:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* decl2.c (merge_functions): Remove duplicates. * decl2.c (merge_functions): Remove duplicates.
* decl2.c: Add -f{no-,}implicit-inline-templates. * decl2.c: Add -f{no-,}implicit-inline-templates.
(lang_decode_option): Unset it if -frepo.
(import_export_decl): Check it. (import_export_decl): Check it.
* decl.c (lookup_name_real): Template parms also take precedence * decl.c (lookup_name_real): Template parms also take precedence
......
...@@ -347,6 +347,9 @@ check_dtor_name (basetype, name) ...@@ -347,6 +347,9 @@ check_dtor_name (basetype, name)
{ {
name = TREE_OPERAND (name, 0); name = TREE_OPERAND (name, 0);
if (name == error_mark_node)
return error_mark_node;
if (TREE_CODE (name) == TYPE_DECL) if (TREE_CODE (name) == TYPE_DECL)
name = TREE_TYPE (name); name = TREE_TYPE (name);
else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
......
...@@ -3452,6 +3452,8 @@ pushdecl (x) ...@@ -3452,6 +3452,8 @@ pushdecl (x)
} }
} }
check_template_shadow (x);
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x)) if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{ {
t = push_overloaded_decl (x, 1); t = push_overloaded_decl (x, 1);
...@@ -3671,16 +3673,6 @@ pushdecl (x) ...@@ -3671,16 +3673,6 @@ pushdecl (x)
if (warnstring) if (warnstring)
warning (warnstring, IDENTIFIER_POINTER (name)); warning (warnstring, IDENTIFIER_POINTER (name));
} }
/* Check to see if decl redeclares a template parameter. */
if (oldlocal && (current_class_type || current_function_decl)
&& current_template_parms)
{
if (decl_template_parm_p (oldlocal))
{
cp_error ("re-using name of template parameter `%T' in this scope", name);
cp_error_at (" previously declared here `%#D'", oldlocal);
}
}
} }
if (TREE_CODE (x) == FUNCTION_DECL) if (TREE_CODE (x) == FUNCTION_DECL)
...@@ -3816,7 +3808,6 @@ pushdecl_class_level (x) ...@@ -3816,7 +3808,6 @@ pushdecl_class_level (x)
Types, enums, and static vars are checked here; other Types, enums, and static vars are checked here; other
members are checked in finish_struct. */ members are checked in finish_struct. */
tree icv = IDENTIFIER_CLASS_VALUE (name); tree icv = IDENTIFIER_CLASS_VALUE (name);
tree ilv = IDENTIFIER_LOCAL_VALUE (name);
if (icv && icv != x if (icv && icv != x
&& flag_optional_diags && flag_optional_diags
...@@ -3831,17 +3822,7 @@ pushdecl_class_level (x) ...@@ -3831,17 +3822,7 @@ pushdecl_class_level (x)
icv); icv);
} }
/* Check to see if decl redeclares a template parameter. */ check_template_shadow (x);
if (ilv && ! decls_match (ilv, x)
&& (current_class_type || current_function_decl)
&& current_template_parms)
{
if (decl_template_parm_p (ilv))
{
cp_error ("re-using name of template parameter `%T' in this scope", name);
cp_error_at (" previously declared here `%#D'", ilv);
}
}
} }
push_class_level_binding (name, x); push_class_level_binding (name, x);
...@@ -11842,16 +11823,6 @@ xref_tag (code_type_node, name, globalize) ...@@ -11842,16 +11823,6 @@ xref_tag (code_type_node, name, globalize)
if (! globalize) if (! globalize)
{ {
if (t && (TREE_CODE (t) == TEMPLATE_TYPE_PARM
|| TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM))
{
cp_error ("redeclaration of template type-parameter `%T'", name);
cp_error_at (" previously declared here `%#D'",
TEMPLATE_TYPE_DECL (t));
}
if (t && TYPE_CONTEXT (t) && got_type)
ref = t;
else
/* If we know we are defining this tag, only look it up in /* If we know we are defining this tag, only look it up in
this scope and don't try to find it as a type. */ this scope and don't try to find it as a type. */
ref = lookup_tag (code, name, b, 1); ref = lookup_tag (code, name, b, 1);
...@@ -13784,6 +13755,8 @@ start_method (declspecs, declarator, attrlist) ...@@ -13784,6 +13755,8 @@ start_method (declspecs, declarator, attrlist)
return void_type_node; return void_type_node;
} }
check_template_shadow (fndecl);
DECL_THIS_INLINE (fndecl) = 1; DECL_THIS_INLINE (fndecl) = 1;
if (flag_default_inline) if (flag_default_inline)
......
...@@ -1642,18 +1642,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist) ...@@ -1642,18 +1642,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
&& (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL)) && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
value = push_template_decl (value); value = push_template_decl (value);
/* Check to see if a field redeclares a template parameter. */ check_template_shadow (value);
if (current_template_parms
&& TREE_CODE (declarator) == IDENTIFIER_NODE
&& IDENTIFIER_LOCAL_VALUE (declarator))
{
tree olddecl = IDENTIFIER_LOCAL_VALUE (declarator);
if (decl_template_parm_p (olddecl))
{
cp_error ("redeclaration of template parameter `%T'", declarator);
cp_error_at (" previously declared here `%#D'", olddecl);
}
}
if (attrlist) if (attrlist)
cplus_decl_attributes (value, TREE_PURPOSE (attrlist), cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
......
...@@ -1849,7 +1849,8 @@ cp_line_of (t) ...@@ -1849,7 +1849,8 @@ cp_line_of (t)
int line = 0; int line = 0;
if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t)) if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
line = DECL_SOURCE_LINE (DECL_CONTEXT (t)); line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)) if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
&& TYPE_MAIN_DECL (TREE_TYPE (t)))
t = TREE_TYPE (t); t = TREE_TYPE (t);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
......
...@@ -63,8 +63,10 @@ DEFINE_LANG_NAME ("C++") ...@@ -63,8 +63,10 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-huge-objects", "" }, { "-fno-huge-objects", "" },
{ "-fimplement-inlines", "" }, { "-fimplement-inlines", "" },
{ "-fno-implement-inlines", "Export functions even if they can be inlined" }, { "-fno-implement-inlines", "Export functions even if they can be inlined" },
{ "-fimplicit-templates", "Emit implicit template instatiations when used" }, { "-fimplicit-templates", "" },
{ "-fno-implicit-templates", "" }, { "-fno-implicit-templates", "Only emit explicit template instatiations" },
{ "-fimplicit-inline-templates", "" },
{ "-fno-implicit-inline-templates", "Only emit explicit instatiations of inline templates" },
{ "-finit-priority", "Handle the init_priority attribute" }, { "-finit-priority", "Handle the init_priority attribute" },
{ "-fno-init-priority", "" }, { "-fno-init-priority", "" },
{ "-flabels-ok", "Labels can be used as first class objects" }, { "-flabels-ok", "Labels can be used as first class objects" },
......
...@@ -913,10 +913,7 @@ apparent_template_type: ...@@ -913,10 +913,7 @@ apparent_template_type:
template_type template_type
| identifier '<' template_arg_list_opt '>' | identifier '<' template_arg_list_opt '>'
.finish_template_type .finish_template_type
{ { $$ = $5; }
cp_error ("template class %T was not declared yet", $1);
$$ = $5;
}
self_template_type: self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket SELFNAME '<' template_arg_list_opt template_close_bracket
......
...@@ -1206,6 +1206,8 @@ check_explicit_specialization (declarator, decl, template_count, flags) ...@@ -1206,6 +1206,8 @@ check_explicit_specialization (declarator, decl, template_count, flags)
("default argument specified in explicit specialization"); ("default argument specified in explicit specialization");
break; break;
} }
if (current_lang_name == lang_name_c)
cp_error ("template specialization with C linkage");
} }
if (specialization || member_specialization || explicit_instantiation) if (specialization || member_specialization || explicit_instantiation)
...@@ -1513,8 +1515,33 @@ int decl_template_parm_p (old_decl) ...@@ -1513,8 +1515,33 @@ int decl_template_parm_p (old_decl)
return 0; return 0;
} }
/* Complain if DECL shadows a template parameter.
[temp.local]: A template-parameter shall not be redeclared within its
scope (including nested scopes). */
void
check_template_shadow (decl)
tree decl;
{
if (current_template_parms
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)))
{
tree olddecl = IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl));
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL, /* We check for decl != olddecl to avoid bogus errors for using a
name inside a class. We check TPFI to avoid duplicate errors for
inline member templates. */
if (decl != olddecl && decl_template_parm_p (olddecl)
&& ! TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
{
cp_error_at ("declaration of `%#D'", decl);
cp_error_at (" shadows template parm `%#D'", olddecl);
}
}
}
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
ORIG_LEVEL, DECL, and TYPE. */ ORIG_LEVEL, DECL, and TYPE. */
static tree static tree
...@@ -2471,22 +2498,9 @@ convert_nontype_argument (type, expr) ...@@ -2471,22 +2498,9 @@ convert_nontype_argument (type, expr)
Check this first since if expr_type is the unknown_type_node Check this first since if expr_type is the unknown_type_node
we would otherwise complain below. */ we would otherwise complain below. */
; ;
else if (INTEGRAL_TYPE_P (expr_type)
|| TYPE_PTRMEM_P (expr_type)
|| TYPE_PTRMEMFUNC_P (expr_type)
/* The next two are g++ extensions. */
|| TREE_CODE (expr_type) == REAL_TYPE
|| TREE_CODE (expr_type) == COMPLEX_TYPE)
{
if (! TREE_CONSTANT (expr))
{
non_constant:
cp_error ("non-constant `%E' cannot be used as template argument",
expr);
return NULL_TREE;
}
}
else if (TYPE_PTR_P (expr_type) else if (TYPE_PTR_P (expr_type)
|| TREE_CODE (expr_type) == ARRAY_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE
/* If expr is the address of an overloaded function, we /* If expr is the address of an overloaded function, we
will get the unknown_type_node at this point. */ will get the unknown_type_node at this point. */
|| expr_type == unknown_type_node) || expr_type == unknown_type_node)
...@@ -2495,6 +2509,11 @@ convert_nontype_argument (type, expr) ...@@ -2495,6 +2509,11 @@ convert_nontype_argument (type, expr)
tree e = expr; tree e = expr;
STRIP_NOPS (e); STRIP_NOPS (e);
if (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (expr_type) == ARRAY_TYPE)
referent = e;
else
{
if (TREE_CODE (e) != ADDR_EXPR) if (TREE_CODE (e) != ADDR_EXPR)
{ {
bad_argument: bad_argument:
...@@ -2509,6 +2528,7 @@ convert_nontype_argument (type, expr) ...@@ -2509,6 +2528,7 @@ convert_nontype_argument (type, expr)
referent = TREE_OPERAND (e, 0); referent = TREE_OPERAND (e, 0);
STRIP_NOPS (referent); STRIP_NOPS (referent);
}
if (TREE_CODE (referent) == STRING_CST) if (TREE_CODE (referent) == STRING_CST)
{ {
...@@ -2529,10 +2549,20 @@ convert_nontype_argument (type, expr) ...@@ -2529,10 +2549,20 @@ convert_nontype_argument (type, expr)
return error_mark_node; return error_mark_node;
} }
} }
else if (TREE_CODE (expr) == VAR_DECL) else if (INTEGRAL_TYPE_P (expr_type)
|| TYPE_PTRMEM_P (expr_type)
|| TYPE_PTRMEMFUNC_P (expr_type)
/* The next two are g++ extensions. */
|| TREE_CODE (expr_type) == REAL_TYPE
|| TREE_CODE (expr_type) == COMPLEX_TYPE)
{ {
if (!TREE_PUBLIC (expr)) if (! TREE_CONSTANT (expr))
goto bad_argument; {
non_constant:
cp_error ("non-constant `%E' cannot be used as template argument",
expr);
return NULL_TREE;
}
} }
else else
{ {
...@@ -2556,7 +2586,7 @@ convert_nontype_argument (type, expr) ...@@ -2556,7 +2586,7 @@ convert_nontype_argument (type, expr)
expr = digest_init (type, expr, (tree*) 0); expr = digest_init (type, expr, (tree*) 0);
if (TREE_CODE (expr) != INTEGER_CST) if (TREE_CODE (expr) != INTEGER_CST)
/* Curiously, some TREE_CONSTNAT integral expressions do not /* Curiously, some TREE_CONSTANT integral expressions do not
simplify to integer constants. For example, `3 % 0', simplify to integer constants. For example, `3 % 0',
remains a TRUNC_MOD_EXPR. */ remains a TRUNC_MOD_EXPR. */
goto non_constant; goto non_constant;
...@@ -3415,11 +3445,12 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope) ...@@ -3415,11 +3445,12 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
} }
else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1))) else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
{ {
if (CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d1)) == NULL_TREE) if (CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d1)))
return error_mark_node; {
template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1)); template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
d1 = DECL_NAME (template); d1 = DECL_NAME (template);
} }
}
else if (TREE_CODE (d1) == ENUMERAL_TYPE else if (TREE_CODE (d1) == ENUMERAL_TYPE
|| (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' || (TREE_CODE_CLASS (TREE_CODE (d1)) == 't'
&& IS_AGGR_TYPE (d1))) && IS_AGGR_TYPE (d1)))
...@@ -3442,7 +3473,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope) ...@@ -3442,7 +3473,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
We don't want to do that, but we have to deal with the situation, so We don't want to do that, but we have to deal with the situation, so
let's give them some syntax errors to chew on instead of a crash. */ let's give them some syntax errors to chew on instead of a crash. */
if (! template) if (! template)
{
cp_error ("`%T' is not a template", d1);
return error_mark_node; return error_mark_node;
}
if (context == NULL_TREE) if (context == NULL_TREE)
context = global_namespace; context = global_namespace;
......
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