This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
(C++) more small fixes
- To: egcs-patches at cygnus dot com
- Subject: (C++) more small fixes
- From: Jason Merrill <jason at cygnus dot com>
- Date: Fri, 4 Dec 1998 11:13:12 -0800
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.
To consolidate the code for checking re-use of template parm names, and to
catch missed cases. Fixes Perennial 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 crash on Perennial Sec14/C14339.cm.
* pt.c (check_explicit_specialization): Complain about specialization
with C linkage.
Fixes Perennial Sec14/C14340.cm.
* lang-options.h: Add -f{no-,}implicit-inline-templates.
I added this option to decl2.c a while back, but forgot to add it here...
* pt.c (convert_nontype_argument): Don't assume that any integer
argument is intended to be a constant-expression.
Fixes Perennial Sec14/7/P14245.C.
Index: call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.123
diff -c -p -r1.123 call.c
*** call.c 1998/11/25 00:28:47 1.123
--- call.c 1998/12/04 19:10:06
*************** check_dtor_name (basetype, name)
*** 347,352 ****
--- 347,355 ----
{
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')
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.277
diff -c -p -r1.277 decl.c
*** decl.c 1998/12/03 16:58:01 1.277
--- decl.c 1998/12/04 19:10:07
*************** pushdecl (x)
*** 3452,3457 ****
--- 3452,3459 ----
}
}
+ check_template_shadow (x);
+
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{
t = push_overloaded_decl (x, 1);
*************** pushdecl (x)
*** 3671,3686 ****
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)
--- 3673,3678 ----
*************** pushdecl_class_level (x)
*** 3816,3822 ****
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
--- 3808,3813 ----
*************** pushdecl_class_level (x)
*** 3831,3847 ****
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);
! }
! }
}
push_class_level_binding (name, x);
--- 3822,3828 ----
icv);
}
! check_template_shadow (x);
}
push_class_level_binding (name, x);
*************** xref_tag (code_type_node, name, globaliz
*** 11842,11860 ****
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);
}
else
{
--- 11823,11831 ----
if (! globalize)
{
! /* 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
{
*************** start_method (declspecs, declarator, att
*** 13783,13788 ****
--- 13754,13761 ----
}
return void_type_node;
}
+
+ check_template_shadow (fndecl);
DECL_THIS_INLINE (fndecl) = 1;
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.161
diff -c -p -r1.161 decl2.c
*** decl2.c 1998/12/02 10:12:18 1.161
--- decl2.c 1998/12/04 19:10:07
*************** grokfield (declarator, declspecs, init,
*** 1642,1659 ****
&& (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);
! }
! }
if (attrlist)
cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
--- 1642,1648 ----
&& (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
value = push_template_decl (value);
! check_template_shadow (value);
if (attrlist)
cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
Index: error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.61
diff -c -p -r1.61 error.c
*** error.c 1998/11/17 12:51:01 1.61
--- error.c 1998/12/04 19:10:08
*************** cp_line_of (t)
*** 1849,1855 ****
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))
t = TREE_TYPE (t);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
--- 1849,1856 ----
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)
! && TYPE_MAIN_DECL (TREE_TYPE (t)))
t = TREE_TYPE (t);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
Index: lang-options.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lang-options.h,v
retrieving revision 1.20
diff -c -p -r1.20 lang-options.h
*** lang-options.h 1998/11/23 03:12:18 1.20
--- lang-options.h 1998/12/04 19:10:08
*************** DEFINE_LANG_NAME ("C++")
*** 63,70 ****
{ "-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", "" },
{ "-finit-priority", "Handle the init_priority attribute" },
{ "-fno-init-priority", "" },
{ "-flabels-ok", "Labels can be used as first class objects" },
--- 63,72 ----
{ "-fno-huge-objects", "" },
{ "-fimplement-inlines", "" },
{ "-fno-implement-inlines", "Export functions even if they can be inlined" },
! { "-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" },
Index: parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.104
diff -c -p -r1.104 parse.y
*** parse.y 1998/11/23 03:16:06 1.104
--- parse.y 1998/12/04 19:10:09
*************** apparent_template_type:
*** 913,922 ****
template_type
| identifier '<' template_arg_list_opt '>'
.finish_template_type
! {
! cp_error ("template class %T was not declared yet", $1);
! $$ = $5;
! }
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
--- 913,919 ----
template_type
| identifier '<' template_arg_list_opt '>'
.finish_template_type
! { $$ = $5; }
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.242
diff -c -p -r1.242 pt.c
*** pt.c 1998/11/29 15:30:30 1.242
--- pt.c 1998/12/04 19:10:10
*************** check_explicit_specialization (declarato
*** 1206,1211 ****
--- 1206,1213 ----
("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)
*************** int decl_template_parm_p (old_decl)
*** 1513,1520 ****
return 0;
}
! /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
ORIG_LEVEL, DECL, and TYPE. */
static tree
--- 1515,1547 ----
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,
ORIG_LEVEL, DECL, and TYPE. */
static tree
*************** convert_nontype_argument (type, expr)
*** 2471,2492 ****
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)
/* If expr is the address of an overloaded function, we
will get the unknown_type_node at this point. */
|| expr_type == unknown_type_node)
--- 2498,2506 ----
Check this first since if expr_type is the unknown_type_node
we would otherwise complain below. */
;
! 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)
*************** convert_nontype_argument (type, expr)
*** 2495,2515 ****
tree e = expr;
STRIP_NOPS (e);
! 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);
-
if (TREE_CODE (referent) == STRING_CST)
{
cp_error ("string literal %E is not a valid template argument",
--- 2509,2535 ----
tree e = expr;
STRIP_NOPS (e);
! if (TREE_CODE (type) == REFERENCE_TYPE
! || TREE_CODE (expr_type) == ARRAY_TYPE)
! referent = e;
! else
{
! 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);
}
if (TREE_CODE (referent) == STRING_CST)
{
cp_error ("string literal %E is not a valid template argument",
*************** convert_nontype_argument (type, expr)
*** 2529,2538 ****
return error_mark_node;
}
}
! else if (TREE_CODE (expr) == VAR_DECL)
{
! if (!TREE_PUBLIC (expr))
! goto bad_argument;
}
else
{
--- 2549,2568 ----
return error_mark_node;
}
}
! 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
{
*************** convert_nontype_argument (type, expr)
*** 2556,2562 ****
expr = digest_init (type, expr, (tree*) 0);
if (TREE_CODE (expr) != INTEGER_CST)
! /* Curiously, some TREE_CONSTNAT integral expressions do not
simplify to integer constants. For example, `3 % 0',
remains a TRUNC_MOD_EXPR. */
goto non_constant;
--- 2586,2592 ----
expr = digest_init (type, expr, (tree*) 0);
if (TREE_CODE (expr) != INTEGER_CST)
! /* Curiously, some TREE_CONSTANT integral expressions do not
simplify to integer constants. For example, `3 % 0',
remains a TRUNC_MOD_EXPR. */
goto non_constant;
*************** lookup_template_class (d1, arglist, in_d
*** 3415,3424 ****
}
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);
}
else if (TREE_CODE (d1) == ENUMERAL_TYPE
|| (TREE_CODE_CLASS (TREE_CODE (d1)) == 't'
--- 3445,3455 ----
}
else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
{
! 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'
*************** lookup_template_class (d1, arglist, in_d
*** 3442,3448 ****
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;
if (context == NULL_TREE)
context = global_namespace;
--- 3473,3482 ----
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)
! {
! cp_error ("`%T' is not a template", d1);
! return error_mark_node;
! }
if (context == NULL_TREE)
context = global_namespace;