From ec25526966761fb80b027fc17431911f91a95ee6 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Sat, 2 Mar 1996 01:49:15 +0000 Subject: [PATCH] 84th Cygnus<->FSF merge From-SVN: r11399 --- gcc/cp/ChangeLog | 75 ++++++++++++++++++++++++++++++++++++++++++++++ gcc/cp/class.c | 32 ++++++++++++-------- gcc/cp/cp-tree.def | 6 ++-- gcc/cp/decl.c | 42 ++++++++++++++++++++++---- gcc/cp/error.c | 6 +++- gcc/cp/method.c | 3 +- gcc/cp/parse.y | 23 ++++++++++++-- gcc/cp/pt.c | 37 ++++++++++++++++------- gcc/cp/tree.c | 4 +++ 9 files changed, 192 insertions(+), 36 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 49b3e9a83f60..471bd9b2a1c2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,80 @@ +Fri Mar 1 13:09:33 1996 Jason Merrill + + * pt.c (instantiate_class_template): If we don't have a pattern + yet, that's OK. + (coerce_template_parms): If we see a local class, bail. + + * decl.c (grok_reference_init): Make sure there's a type before + checking its code. + + * pt.c (do_function_instantiation): Avoid crashing on invalid decls. + (push_template_decl): Ditto. + + * parse.y (named_class_head): Set + CLASSTYPE_TEMPLATE_SPECIALIZATION here if we have basetypes. + + * decl.c (xref_tag): Diagnose redeclaration of template + type-parameter name. + + * error.c (dump_type): Handle anonymous template type parms. + + * pt.c (instantiate_template): Use TYPE_MAIN_DECL instead of + TYPE_STUB_DECL. + (coerce_template_parms): Ditto. + +Thu Feb 29 16:26:01 1996 Mike Stump + + * class.c (instantiate_type, case {ARRAY,INDIRECT}_REF, + case ADDR_EXPR): Don't modify rhs if a subinstantiation fails. + +Thu Feb 29 08:20:25 1996 Jason Merrill + + * pt.c (instantiate_template): Take the MAIN_VARIANT of the type + before trying to get its STUB_DECL. + (coerce_template_parms): Ditto. + + * parse.y (template_type_parm): If they didn't use 'class', + pretend they did after giving an error. + + * pt.c (coerce_template_parms): Diagnose use of local class. + + * decl.c (grok_reference_init): Use instantiate_type. + + * error.c (dump_expr): Handle TEMPLATE_DECLs. + + * parse.y (named_class_head): Diagnose mismatching types and tags. + + * decl.c (pushdecl): Type decls and class templates clash with + artificial type decls, not hide them. + + * decl.c (redeclaration_error_message): Diagnose redefinition of + templates properly. + (duplicate_decls): Diagnose disallowed overloads for template + functions, too. + + * decl.c (start_decl): Call complete_type before checking for a + destructor. + + * pt.c (tsubst): Use tsubst_expr on the elts of a VEC. + + * decl.c (xref_tag): A TEMPLATE_TYPE_PARM is a match. + Wed Feb 28 09:28:44 1996 Jason Merrill + * decl.c (grok_op_properties): Don't check for operator++(int) in + a template. + + * tree.c (perm_manip): Return a copy of variable and function + decls with external linkage. + + * tree.def: Change some of the min tree codes to type "1". + * pt.c (uses_template_parms): Handle 'e's, return 1 for LOOKUP_EXPRs. + * method.c (build_overload_int): Emit something arbitrary for + anything but an INTEGER_CST if we're in a template. + + * decl.c (cp_finish_decl): Call complete_type before deciding + whether or not to lay out the decl. + * lex.c (do_identifier): Check for DECL_INITIAL before using it. Tue Feb 27 16:35:32 1996 Jason Merrill diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4bceaa16310d..e5ce5baa224e 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4842,9 +4842,12 @@ root_lang_context_p () /* Type instantiation routines. */ -/* This function will instantiate the type of the expression given - in RHS to match the type of LHSTYPE. If LHSTYPE is NULL_TREE, - or other errors exist, the TREE_TYPE of RHS will be ERROR_MARK_NODE. +/* This function will instantiate the type of the expression given in + RHS to match the type of LHSTYPE. If errors exist, then return + error_mark_node. If only complain is COMPLAIN is set. If we are + not complaining, never modify rhs, as overload resolution wants to + try many possible instantiations, in hopes that at least one will + work. This function is used in build_modify_expr, convert_arguments, build_c_cast, and compute_conversion_costs. */ @@ -4880,14 +4883,18 @@ instantiate_type (lhstype, rhs, complain) case INDIRECT_REF: case ARRAY_REF: - TREE_TYPE (rhs) = lhstype; - lhstype = build_pointer_type (lhstype); - TREE_OPERAND (rhs, 0) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); - if (TREE_OPERAND (rhs, 0) == error_mark_node) - return error_mark_node; + { + tree new_rhs; - return rhs; + new_rhs = instantiate_type (build_pointer_type (lhstype), + TREE_OPERAND (rhs, 0), complain); + if (new_rhs == error_mark_node) + return error_mark_node; + + TREE_TYPE (rhs) = lhstype; + TREE_OPERAND (rhs, 0) = new_rhs; + return rhs; + } case NOP_EXPR: rhs = copy_node (TREE_OPERAND (rhs, 0)); @@ -5262,13 +5269,12 @@ instantiate_type (lhstype, rhs, complain) error ("type for resolving address of overloaded function must be pointer type"); return error_mark_node; } - TREE_TYPE (rhs) = lhstype; - lhstype = TREE_TYPE (lhstype); { - tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); + tree fn = instantiate_type (TREE_TYPE (lhstype), TREE_OPERAND (rhs, 0), complain); if (fn == error_mark_node) return error_mark_node; mark_addressable (fn); + TREE_TYPE (rhs) = lhstype; TREE_OPERAND (rhs, 0) = fn; TREE_CONSTANT (rhs) = staticp (fn); } diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 51edcb00a07c..d965783188a8 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -116,9 +116,9 @@ DEFTREECODE (USING_DECL, "using_decl", "d", 0) DEFTREECODE (LOOKUP_EXPR, "lookup_expr", "e", 2) DEFTREECODE (MODOP_EXPR, "modop_expr", "e", 3) -DEFTREECODE (CAST_EXPR, "cast_expr", "e", 1) -DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", "e", 1) -DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", "e", 1) +DEFTREECODE (CAST_EXPR, "cast_expr", "1", 1) +DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", "1", 1) +DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", "1", 1) DEFTREECODE (ARROW_EXPR, "arrow_expr", "e", 1) DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", "e", 2) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2dd92e566109..8d1d8cda336b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2501,6 +2501,14 @@ duplicate_decls (newdecl, olddecl) cp_error_at ("conflicts with previous declaration `%#D'", olddecl); } + else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL + && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL + && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))), + TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))), 3)) + { + cp_error ("new declaration `%#D'", newdecl); + cp_error_at ("ambiguates old declaration `%#D'", olddecl); + } return 0; } if (TREE_CODE (newdecl) == FUNCTION_DECL) @@ -3044,8 +3052,15 @@ pushdecl (x) } else if (TREE_CODE (t) != TREE_CODE (x)) { - if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)) - || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))) + if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t) + && TREE_CODE (x) != TYPE_DECL + && ! (TREE_CODE (x) == TEMPLATE_DECL + && TREE_CODE (DECL_TEMPLATE_RESULT (x)) == TYPE_DECL)) + || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x) + && TREE_CODE (t) != TYPE_DECL + && ! (TREE_CODE (t) == TEMPLATE_DECL + && (TREE_CODE (DECL_TEMPLATE_RESULT (t)) + == TYPE_DECL)))) { /* We do nothing special here, because C++ does such nasty things with TYPE_DECLs. Instead, just let the TYPE_DECL @@ -3714,7 +3729,12 @@ redeclaration_error_message (newdecl, olddecl) } else if (TREE_CODE (newdecl) == TEMPLATE_DECL) { - if (DECL_INITIAL (olddecl) && DECL_INITIAL (newdecl)) + if ((TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL + && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) + && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl))) + || (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL + && TYPE_SIZE (TREE_TYPE (newdecl)) + && TYPE_SIZE (TREE_TYPE (olddecl)))) return "redefinition of `%#D'"; return 0; } @@ -5737,7 +5757,7 @@ start_decl (declarator, declspecs, initialized, raises) /* Don't lose if destructors must be executed at file-level. */ if (! current_template_parms && TREE_STATIC (decl) - && TYPE_NEEDS_DESTRUCTOR (type) + && TYPE_NEEDS_DESTRUCTOR (complete_type (type)) && !TREE_PERMANENT (decl)) { push_obstacks (&permanent_obstack, &permanent_obstack); @@ -6029,6 +6049,10 @@ grok_reference_init (decl, type, init, cleanupp) return; } + if (TREE_TYPE (init) && TREE_CODE (TREE_TYPE (init)) == UNKNOWN_TYPE) + /* decay_conversion is probably wrong for references to functions. */ + init = decay_conversion (instantiate_type (TREE_TYPE (type), init, 1)); + if (TREE_CODE (init) == TREE_LIST) init = build_compound_expr (init); @@ -6417,7 +6441,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) if (TREE_CODE (decl) == VAR_DECL) { if (DECL_SIZE (decl) == NULL_TREE - && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE) + && TYPE_SIZE (complete_type (TREE_TYPE (decl))) != NULL_TREE) layout_decl (decl, 0); if (TREE_STATIC (decl) && DECL_SIZE (decl) == NULL_TREE) @@ -10152,6 +10176,7 @@ grok_op_properties (decl, virtualp, friendp) { if ((name == ansi_opname[(int) POSTINCREMENT_EXPR] || name == ansi_opname[(int) POSTDECREMENT_EXPR]) + && ! current_template_parms && TREE_VALUE (TREE_CHAIN (argtypes)) != integer_type_node) { if (methodp) @@ -10259,11 +10284,16 @@ xref_tag (code_type_node, name, binfo, globalize) } else t = IDENTIFIER_TYPE_VALUE (name); - if (t && TREE_CODE (t) != code) + if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM) t = NULL_TREE; if (! globalize) { + if (pedantic && t && TREE_CODE (t) == TEMPLATE_TYPE_PARM) + { + cp_pedwarn ("redeclaration of template type-parameter `%T'", name); + cp_pedwarn_at (" previously declared here", t); + } /* 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. */ if (t && TYPE_CONTEXT(t) && TREE_MANGLED (name)) diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 3c1d9a2e959b..99f72fba9dfa 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -209,7 +209,10 @@ dump_type (t, v) break; case TEMPLATE_TYPE_PARM: - OB_PUTID (TYPE_IDENTIFIER (t)); + if (TYPE_IDENTIFIER (t)) + OB_PUTID (TYPE_IDENTIFIER (t)); + else + OB_PUTS ("{anonymous template type parm}"); break; /* This is not always necessary for pointers and such, but doing this @@ -941,6 +944,7 @@ dump_expr (t, nop) case FIELD_DECL: case CONST_DECL: case FUNCTION_DECL: + case TEMPLATE_DECL: dump_decl (t, -1); break; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 5156121ffb74..6b45ff4008e6 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -364,7 +364,8 @@ build_overload_int (value) OB_PUTC ('_'); return; } - else if (uses_template_parms (value)) + else if (current_template_parms + && TREE_CODE (value) != INTEGER_CST) /* We don't ever want this output, but it's inconvenient not to be able to build the string. This should cause assembler errors we'll notice. */ diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index be782b7eb9e9..c53bef3b6be6 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -427,7 +427,10 @@ template_type_parm: if (TREE_PURPOSE ($$) == signature_type_node) sorry ("signature as template type parameter"); else if (TREE_PURPOSE ($$) != class_type_node) - pedwarn ("template type parameters must use the keyword `class'"); + { + pedwarn ("template type parameters must use the keyword `class'"); + TREE_PURPOSE ($$) = class_type_node; + } } | aggr identifier { $$ = build_tree_list ($1, $2); goto ttpa; } @@ -2129,8 +2132,24 @@ named_class_head: | named_complex_class_head_sans_basetype maybe_base_class_list { $$ = TREE_TYPE ($1); + if (TREE_INT_CST_LOW (current_aggr) == union_type + && TREE_CODE ($$) != UNION_TYPE) + cp_pedwarn ("`union' tag used in declaring `%#T'", $$); + else if (TREE_CODE ($$) == UNION_TYPE + && TREE_INT_CST_LOW (current_aggr) != union_type) + cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$); if ($2) - xref_basetypes (current_aggr, $1, $$, $2); + { + if (IS_AGGR_TYPE ($$) && CLASSTYPE_USE_TEMPLATE ($$)) + { + if (CLASSTYPE_IMPLICIT_INSTANTIATION ($$) + && TYPE_SIZE ($$) == NULL_TREE) + SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$); + else if (CLASSTYPE_TEMPLATE_INSTANTIATION ($$)) + cp_error ("specialization after instantiation of `%T'", $$); + } + xref_basetypes (current_aggr, $1, $$, $2); + } } ; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5a30c9a2301a..02e2822144e4 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -253,6 +253,8 @@ push_template_decl (decl) CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info; DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl)); } + else if (! DECL_LANG_SPECIFIC (decl)) + cp_error ("template declaration of `%#D'", decl); else DECL_TEMPLATE_INFO (decl) = info; } @@ -352,12 +354,24 @@ coerce_template_parms (parms, arglist, in_decl) continue; } if (is_type) - val = groktypename (arg); + { + val = groktypename (arg); + if (! current_template_parms) + { + tree t = target_type (val); + if (IS_AGGR_TYPE (t) + && decl_function_context (TYPE_MAIN_DECL (t))) + { + cp_error ("type `%T' composed from a local class is not a valid template-argument", val); + return error_mark_node; + } + } + } else { tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0), TREE_VEC_LENGTH (vec), in_decl); - if (current_template_parms && uses_template_parms (arg)) + if (current_template_parms) val = arg; else val = digest_init (t, arg, (tree *) 0); @@ -844,6 +858,7 @@ uses_template_parms (t) /* NOTREACHED */ return 0; + case LOOKUP_EXPR: case TYPENAME_TYPE: return 1; @@ -857,7 +872,7 @@ uses_template_parms (t) { case '1': case '2': - case '3': + case 'e': case '<': { int i; @@ -980,11 +995,7 @@ instantiate_class_template (type) pattern = TREE_TYPE (template); if (TYPE_SIZE (pattern) == NULL_TREE) - { - cp_error_at ("no definition available for `%#D'", template); - cp_error (" trying to instantiate `%#T'", type); - return error_mark_node; - } + return type; TYPE_BEING_DEFINED (type) = 1; @@ -1608,7 +1619,7 @@ tsubst (t, args, nargs, in_decl) for (i = 0; i < len; i++) { - elts[i] = tsubst_copy (TREE_VEC_ELT (t, i), args, nargs, in_decl); + elts[i] = tsubst_expr (TREE_VEC_ELT (t, i), args, nargs, in_decl); if (elts[i] != TREE_VEC_ELT (t, i)) need_new = 1; } @@ -2287,7 +2298,7 @@ instantiate_template (tmpl, targ_ptr) if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') { tree nt = target_type (t); - if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_STUB_DECL (nt))) + if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt))) { cp_error ("type `%T' composed from a local class is not a valid template-argument", t); cp_error (" trying to instantiate `%D'", tmpl); @@ -2696,6 +2707,12 @@ do_function_instantiation (declspecs, declarator, storage) tree result = NULL_TREE; int extern_p = 0; + if (! DECL_LANG_SPECIFIC (decl)) + { + cp_error ("explicit instantiation of non-template `%#D'", decl); + return; + } + /* If we've already seen this template instance, use it. */ if (name = DECL_ASSEMBLER_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index e5eb64749e5e..8fbd59bcc9c3 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1625,6 +1625,10 @@ perm_manip (t) { if (TREE_PERMANENT (t)) return t; + /* Support `void f () { extern int i; A<&i> a; }' */ + if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL) + && TREE_PUBLIC (t)) + return copy_node (t); return NULL_TREE; } -- 2.43.5