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>
* 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>
* decl2.c (merge_functions): Remove duplicates.
* decl2.c: Add -f{no-,}implicit-inline-templates.
(lang_decode_option): Unset it if -frepo.
(import_export_decl): Check it.
* decl.c (lookup_name_real): Template parms also take precedence
......
......@@ -347,6 +347,9 @@ check_dtor_name (basetype, name)
{
name = TREE_OPERAND (name, 0);
if (name == error_mark_node)
return error_mark_node;
if (TREE_CODE (name) == TYPE_DECL)
name = TREE_TYPE (name);
else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
......
......@@ -3452,6 +3452,8 @@ pushdecl (x)
}
}
check_template_shadow (x);
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{
t = push_overloaded_decl (x, 1);
......@@ -3671,16 +3673,6 @@ pushdecl (x)
if (warnstring)
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)
......@@ -3816,7 +3808,6 @@ pushdecl_class_level (x)
Types, enums, and static vars are checked here; other
members are checked in finish_struct. */
tree icv = IDENTIFIER_CLASS_VALUE (name);
tree ilv = IDENTIFIER_LOCAL_VALUE (name);
if (icv && icv != x
&& flag_optional_diags
......@@ -3831,17 +3822,7 @@ pushdecl_class_level (x)
icv);
}
/* Check to see if decl redeclares a template parameter. */
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);
}
}
check_template_shadow (x);
}
push_class_level_binding (name, x);
......@@ -11842,19 +11823,9 @@ xref_tag (code_type_node, name, 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
this scope and don't try to find it as a type. */
ref = lookup_tag (code, name, b, 1);
/* 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. */
ref = lookup_tag (code, name, b, 1);
}
else
{
......@@ -13784,6 +13755,8 @@ start_method (declspecs, declarator, attrlist)
return void_type_node;
}
check_template_shadow (fndecl);
DECL_THIS_INLINE (fndecl) = 1;
if (flag_default_inline)
......
......@@ -1642,18 +1642,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
&& (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
value = push_template_decl (value);
/* Check to see if a field redeclares a template parameter. */
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);
}
}
check_template_shadow (value);
if (attrlist)
cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
......
......@@ -1849,7 +1849,8 @@ cp_line_of (t)
int line = 0;
if (TREE_CODE (t) == PARM_DECL && 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);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
......
......@@ -63,8 +63,10 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-huge-objects", "" },
{ "-fimplement-inlines", "" },
{ "-fno-implement-inlines", "Export functions even if they can be inlined" },
{ "-fimplicit-templates", "Emit implicit template instatiations when used" },
{ "-fno-implicit-templates", "" },
{ "-fimplicit-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" },
{ "-fno-init-priority", "" },
{ "-flabels-ok", "Labels can be used as first class objects" },
......
......@@ -913,10 +913,7 @@ apparent_template_type:
template_type
| identifier '<' template_arg_list_opt '>'
.finish_template_type
{
cp_error ("template class %T was not declared yet", $1);
$$ = $5;
}
{ $$ = $5; }
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
......
......@@ -1206,6 +1206,8 @@ check_explicit_specialization (declarator, decl, template_count, flags)
("default argument specified in explicit specialization");
break;
}
if (current_lang_name == lang_name_c)
cp_error ("template specialization with C linkage");
}
if (specialization || member_specialization || explicit_instantiation)
......@@ -1513,8 +1515,33 @@ int decl_template_parm_p (old_decl)
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));
/* 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,
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
ORIG_LEVEL, DECL, and TYPE. */
static tree
......@@ -2471,22 +2498,9 @@ convert_nontype_argument (type, expr)
Check this first since if expr_type is the unknown_type_node
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
will get the unknown_type_node at this point. */
|| expr_type == unknown_type_node)
......@@ -2495,21 +2509,27 @@ convert_nontype_argument (type, expr)
tree e = expr;
STRIP_NOPS (e);
if (TREE_CODE (e) != ADDR_EXPR)
if (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (expr_type) == ARRAY_TYPE)
referent = e;
else
{
bad_argument:
cp_error ("`%E' is not a valid template argument", expr);
error ("it must be %s%s with external linkage",
TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
? "a pointer to " : "",
TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == FUNCTION_TYPE
? "a function" : "an object");
return NULL_TREE;
if (TREE_CODE (e) != ADDR_EXPR)
{
bad_argument:
cp_error ("`%E' is not a valid template argument", expr);
error ("it must be %s%s with external linkage",
TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
? "a pointer to " : "",
TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == FUNCTION_TYPE
? "a function" : "an object");
return NULL_TREE;
}
referent = TREE_OPERAND (e, 0);
STRIP_NOPS (referent);
}
referent = TREE_OPERAND (e, 0);
STRIP_NOPS (referent);
if (TREE_CODE (referent) == STRING_CST)
{
cp_error ("string literal %E is not a valid template argument",
......@@ -2529,10 +2549,20 @@ convert_nontype_argument (type, expr)
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))
goto bad_argument;
if (! TREE_CONSTANT (expr))
{
non_constant:
cp_error ("non-constant `%E' cannot be used as template argument",
expr);
return NULL_TREE;
}
}
else
{
......@@ -2556,7 +2586,7 @@ convert_nontype_argument (type, expr)
expr = digest_init (type, expr, (tree*) 0);
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',
remains a TRUNC_MOD_EXPR. */
goto non_constant;
......@@ -3415,10 +3445,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
}
else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
{
if (CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d1)) == NULL_TREE)
return error_mark_node;
template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
d1 = DECL_NAME (template);
if (CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d1)))
{
template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
d1 = DECL_NAME (template);
}
}
else if (TREE_CODE (d1) == ENUMERAL_TYPE
|| (TREE_CODE_CLASS (TREE_CODE (d1)) == 't'
......@@ -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
let's give them some syntax errors to chew on instead of a crash. */
if (! template)
return error_mark_node;
{
cp_error ("`%T' is not a template", d1);
return error_mark_node;
}
if (context == NULL_TREE)
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