From: Mark Mitchell Date: Tue, 24 Mar 1998 10:25:44 +0000 (+0000) Subject: cplus-dem.c (optable): Add sizeof. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=050367a36dc31833f15828aef52e33a37ef2a952;p=gcc.git cplus-dem.c (optable): Add sizeof. * cplus-dem.c (optable): Add sizeof. (demangle_template_value_parm): New function containing code previously found in demangle_template. (demangle_integral_value): New function which handles complicated integral expressions. (demangle_template): Use them. * error.c (dump_expr): Remove unused variable `l'. * pt.c (for_each_template_parm): New function, created by converting uses_template_parms. (tree_fn_t): New typedef. (uses_template_parms): Use it. (mark_template_parm): New function. (push_template_decl): Check that the argument list of a partial specialization uses all the template parameters. * Make-lang.in (c++filt): Don't delete cxxmain.c after we're done with it; we might want it for debugging. * cp-tree.h (type_unification): Change interface. * class.c (finish_struct_1): Skip nested template types, just like ordinary nested types. (instantiate_type): Use new interface to type_unification. * lex.c (init_lex): Add __sz as opname for sizeof. * method.c (build_overload_scope_ref): New function. (build_overload_int): Handle complex expressions. Set numeric_output_need_bar if necessary. (build_overload_value): Handle non-PARM_DECL nodes; this routine is now used by build_overload_int. Remove some assignments to numeric_output_need_bar. Use build_overload_scope_ref. (build_qualified_name): Note that some template mangled names end with digits, and set numeric_output_need_bar appropriately. Use build_underscore_int. * pt.c (unify): Change interface. (type_unification_real): Likewise. (determine_specialization): Use new interfaces. (tsubst): Deal gracefully with situations in which the argument vector is not fully filled. (fn_type_unification): Use new interfaces. (type_unification): Likewise. Remove NOP_EXPR hack. (type_unification_real): Likewise. (unify): Likewise. Deal with unification of complex expresions. From-SVN: r18795 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fae898a9089..78a37f2f076 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +1998-03-24 Mark Mitchell + + * cplus-dem.c (optable): Add sizeof. + (demangle_template_value_parm): New function containing code + previously found in demangle_template. + (demangle_integral_value): New function which handles complicated + integral expressions. + (demangle_template): Use them. + Tue Mar 24 12:13:18 1998 Kaveh R. Ghazi * Makefile.in (genconfig.o, genflags.o, gencodes.o, genemit.o, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3ebc7f522cc..320bcf6fc60 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,42 @@ +Tue Mar 24 10:23:47 1998 Mark Mitchell + + * error.c (dump_expr): Remove unused variable `l'. + + * pt.c (for_each_template_parm): New function, created by + converting uses_template_parms. + (tree_fn_t): New typedef. + (uses_template_parms): Use it. + (mark_template_parm): New function. + (push_template_decl): Check that the argument list of a partial + specialization uses all the template parameters. + + * Make-lang.in (c++filt): Don't delete cxxmain.c after we're done + with it; we might want it for debugging. + * cp-tree.h (type_unification): Change interface. + * class.c (finish_struct_1): Skip nested template types, just like + ordinary nested types. + (instantiate_type): Use new interface to type_unification. + * lex.c (init_lex): Add __sz as opname for sizeof. + * method.c (build_overload_scope_ref): New function. + (build_overload_int): Handle complex expressions. Set + numeric_output_need_bar if necessary. + (build_overload_value): Handle non-PARM_DECL nodes; this + routine is now used by build_overload_int. Remove some + assignments to numeric_output_need_bar. Use + build_overload_scope_ref. + (build_qualified_name): Note that some template mangled names end + with digits, and set numeric_output_need_bar appropriately. Use + build_underscore_int. + * pt.c (unify): Change interface. + (type_unification_real): Likewise. + (determine_specialization): Use new interfaces. + (tsubst): Deal gracefully with situations in which the argument + vector is not fully filled. + (fn_type_unification): Use new interfaces. + (type_unification): Likewise. Remove NOP_EXPR hack. + (type_unification_real): Likewise. + (unify): Likewise. Deal with unification of complex expresions. + Mon Mar 23 12:24:37 1998 Jason Merrill * pt.c (complete_template_args): Initialize skip properly. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 6490c7e1d66..215bc950a52 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -107,7 +107,6 @@ cxxmain.o: cplus-dem.c demangle.h $(LN_S) $(srcdir)/cplus-dem.c cxxmain.c $(CC) -c -DMAIN $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -DVERSION=\"$(version)\" cxxmain.c - rm -f cxxmain.c $(DEMANGLER_PROG): cxxmain.o underscore.o getopt.o getopt1.o $(LIBDEPS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(LIBS) -o $@ \ diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 3cbf9ea3e68..37f8086db44 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3322,7 +3322,8 @@ finish_struct_1 (t, warn_anon) last_x = x; - if (TREE_CODE (x) == TYPE_DECL) + if (TREE_CODE (x) == TYPE_DECL + || TREE_CODE (x) == TEMPLATE_DECL) continue; /* If we've gotten this far, it's a data member, possibly static, @@ -5174,8 +5175,8 @@ instantiate_type (lhstype, rhs, complain) tree t = make_scratch_vec (n); int i; i = type_unification - (DECL_INNERMOST_TEMPLATE_PARMS (elem), - &TREE_VEC_ELT (t, 0), TYPE_ARG_TYPES (TREE_TYPE (elem)), + (DECL_INNERMOST_TEMPLATE_PARMS (elem), t, + TYPE_ARG_TYPES (TREE_TYPE (elem)), TYPE_ARG_TYPES (lhstype), explicit_targs, 1, 1); if (i == 0) { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0c4cfcd78f8..1d2d2476495 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2463,7 +2463,7 @@ extern tree instantiate_class_template PROTO((tree)); extern tree instantiate_template PROTO((tree, tree)); extern void overload_template_name PROTO((tree)); extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, int, tree)); -extern int type_unification PROTO((tree, tree *, tree, tree, tree, int, int)); +extern int type_unification PROTO((tree, tree, tree, tree, tree, int, int)); struct tinst_level *tinst_for_decl PROTO((void)); extern void mark_decl_instantiated PROTO((tree, int)); extern int more_specialized PROTO((tree, tree, tree)); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 31a38bb52d3..d97ed3804aa 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1533,12 +1533,7 @@ dump_expr (t, nop) } case TEMPLATE_PARM_INDEX: - { - int l = current_template_parms ? - list_length (current_template_parms) : 0; - - dump_decl (TEMPLATE_PARM_DECL (t), -1); - } + dump_decl (TEMPLATE_PARM_DECL (t), -1); break; case IDENTIFIER_NODE: diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 7efaf655c48..2b5059814c5 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -471,6 +471,16 @@ build_underscore_int (i) OB_PUTC ('_'); } +static void +build_overload_scope_ref (value) + tree value; +{ + OB_PUTC2 ('Q', '2'); + numeric_output_need_bar = 0; + build_mangled_name (TREE_OPERAND (value, 0), 0, 0); + build_overload_identifier (TREE_OPERAND (value, 1)); +} + /* Encoding for an INTEGER_CST value. */ static void @@ -479,13 +489,70 @@ build_overload_int (value, in_template) int in_template; { if (in_template && 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. */ { - static int n; - sprintf (digit_buffer, " *%d", n++); - OB_PUTCP (digit_buffer); + if (TREE_CODE (value) == SCOPE_REF) + { + build_overload_scope_ref (value); + return; + } + + OB_PUTC ('E'); + numeric_output_need_bar = 0; + + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value)))) + { + int i; + int operands = tree_code_length[(int) TREE_CODE (value)]; + tree id; + char* name; + + id = ansi_opname [(int) TREE_CODE (value)]; + my_friendly_assert (id != NULL_TREE, 0); + name = IDENTIFIER_POINTER (id); + my_friendly_assert (name[0] == '_' && name[1] == '_', 0); + + for (i = 0; i < operands; ++i) + { + tree operand; + enum tree_code tc; + + /* We just outputted either the `E' or the name of the + operator. */ + numeric_output_need_bar = 0; + + if (i != 0) + /* Skip the leading underscores. */ + OB_PUTCP (name + 2); + + operand = TREE_OPERAND (value, i); + tc = TREE_CODE (operand); + + if (TREE_CODE_CLASS (tc) == 't') + /* We can get here with sizeof, e.g.: + + template void f(A); */ + process_overload_item (operand, 0); + else if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc))) + build_overload_int (operand, in_template); + else + build_overload_value (TREE_TYPE (operand), + operand, + in_template); + } + } + else + { + /* 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. */ + + static int n; + sprintf (digit_buffer, " *%d", n++); + OB_PUTCP (digit_buffer); + } + + OB_PUTC ('W'); + numeric_output_need_bar = 0; return; } @@ -497,12 +564,14 @@ build_overload_int (value, in_template) { /* need to print a DImode value in decimal */ dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value)); + numeric_output_need_bar = 1; return; } /* else fall through to print in smaller mode */ } /* Wordsize or smaller */ icat (TREE_INT_CST_LOW (value)); + numeric_output_need_bar = 1; } @@ -531,8 +600,11 @@ build_overload_value (type, value, in_template) while (TREE_CODE (value) == NON_LVALUE_EXPR || TREE_CODE (value) == NOP_EXPR) value = TREE_OPERAND (value, 0); - my_friendly_assert (TREE_CODE (type) == PARM_DECL, 242); - type = TREE_TYPE (type); + + if (TREE_CODE (type) == PARM_DECL) + type = TREE_TYPE (type); + + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0); if (numeric_output_need_bar) { @@ -569,7 +641,6 @@ build_overload_value (type, value, in_template) case BOOLEAN_TYPE: { build_overload_int (value, in_template); - numeric_output_need_bar = 1; return; } case REAL_TYPE: @@ -672,7 +743,6 @@ build_overload_value (type, value, in_template) { OB_PUTC ('i'); build_overload_int (a3, in_template); - numeric_output_need_bar = 1; return; } } @@ -683,7 +753,6 @@ build_overload_value (type, value, in_template) if (TREE_CODE (value) == INTEGER_CST) { build_overload_int (value, in_template); - numeric_output_need_bar = 1; return; } else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) @@ -707,13 +776,7 @@ build_overload_value (type, value, in_template) return; } else if (TREE_CODE (value) == SCOPE_REF) - { - OB_PUTC2 ('Q', '1'); - numeric_output_need_bar = 0; - build_mangled_name (TREE_OPERAND (value, 0), 0, 0); - build_overload_identifier (TREE_OPERAND (value, 1)); - return; - } + build_overload_scope_ref (value); else my_friendly_abort (71); break; /* not really needed */ @@ -865,7 +928,10 @@ build_qualified_name (decl) if (TREE_CODE (decl) == TYPE_DECL && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling) { - OB_PUTID (DECL_ASSEMBLER_NAME (decl)); + tree id = DECL_ASSEMBLER_NAME (decl); + OB_PUTID (id); + if (isdigit (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1])) + numeric_output_need_bar = 1; return; } @@ -907,11 +973,7 @@ build_qualified_name (decl) if (i > 1) { OB_PUTC ('Q'); - if (i > 9) - OB_PUTC ('_'); - icat (i); - if (i > 9) - OB_PUTC ('_'); + build_underscore_int (i); numeric_output_need_bar = 0; } build_overload_nested_name (decl); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6ea32092644..2e44007b3c5 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -43,6 +43,10 @@ Boston, MA 02111-1307, USA. */ #include #endif +/* The type of functions taking a tree, and some additional data, and + returning an int. */ +typedef int (*tree_fn_t) PROTO((tree, void*)); + extern struct obstack permanent_obstack; extern int lineno; @@ -69,7 +73,7 @@ static tree saved_trees; #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free -static int unify PROTO((tree, tree *, int, tree, tree, int)); +static int unify PROTO((tree, tree, int, tree, tree, int, int*)); static void add_pending_template PROTO((tree)); static int push_tinst_level PROTO((tree)); static tree classtype_mangled_name PROTO((tree)); @@ -81,13 +85,14 @@ static tree get_class_bindings PROTO((tree, tree, tree, tree)); static tree coerce_template_parms PROTO((tree, tree, tree, int, int, int)); static tree tsubst_enum PROTO((tree, tree, tree *)); static tree add_to_template_args PROTO((tree, tree)); +static int type_unification_real PROTO((tree, tree, tree, tree, + int, int, int, int*)); static tree complete_template_args PROTO((tree, tree, int)); -static int type_unification_real PROTO((tree, tree *, tree, tree, - int, int, int)); static void note_template_header PROTO((int)); static tree maybe_fold_nontype_arg PROTO((tree)); static tree convert_nontype_argument PROTO((tree, tree)); static tree get_bindings_overload PROTO((tree, tree, tree)); +static int for_each_template_parm PROTO((tree, tree_fn_t, void*)); /* Do any processing required when DECL (a member template declaration using TEMPLATE_PARAMETERS as its innermost parameter list) is @@ -719,7 +724,7 @@ determine_specialization (template_id, decl, targs_out, /* We allow incomplete unification here, because we are going to check all the functions. */ i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), - &TREE_VEC_ELT (targs, 0), + targs, NULL_TREE, NULL_TREE, targs_in, @@ -1464,7 +1469,46 @@ build_template_decl (decl, parms) return tmpl; } - +struct template_parm_data +{ + int level; + int* parms; +}; + +/* Subroutine of push_template_decl used to see if each template + parameter in a partial specialization is used in the explicit + argument list. If T is of the LEVEL given in DATA (which is + treated as a template_parm_data*), then DATA->PARMS is marked + appropriately. */ + +static int +mark_template_parm (t, data) + tree t; + void* data; +{ + int level; + int idx; + struct template_parm_data* tpd = (struct template_parm_data*) data; + + if (TREE_CODE (t) == TEMPLATE_PARM_INDEX) + { + level = TEMPLATE_PARM_LEVEL (t); + idx = TEMPLATE_PARM_IDX (t); + } + else + { + level = TEMPLATE_TYPE_LEVEL (t); + idx = TEMPLATE_TYPE_IDX (t); + } + + if (level == tpd->level) + tpd->parms[idx] = 1; + + /* Return zero so that for_each_template_parm will continue the + traversal of the tree; we want to mark *every* template parm. */ + return 0; +} + /* Creates a TEMPLATE_DECL for the indicated DECL using the template parameters given by current_template_args, or reuses a previously existing one, if appropriate. Returns the DECL, or an @@ -1529,6 +1573,66 @@ push_template_decl (decl) tree mainargs = CLASSTYPE_TI_ARGS (type); tree spec = DECL_TEMPLATE_SPECIALIZATIONS (maintmpl); + /* We check that each of the template parameters given in the + partial specialization is used in the argument list to the + specialization. For example: + + template struct S; + template struct S; + + The second declaration is OK because `T*' uses the template + parameter T, whereas + + template struct S; + + is no good. Even trickier is: + + template + struct S1 + { + template + struct S2; + template + struct S2; + }; + + The S2 declaration is actually illegal; it is a + full-specialization. Of course, + + template + struct S2; + + or some such would have been OK. */ + int i; + struct template_parm_data tpd; + int ntparms = TREE_VEC_LENGTH (TREE_VALUE (current_template_parms)); + int did_error_intro = 0; + + tpd.level = TREE_INT_CST_HIGH (TREE_PURPOSE (current_template_parms)); + tpd.parms = alloca (sizeof (int) * ntparms); + for (i = 0; i < ntparms; ++i) + tpd.parms[i] = 0; + for (i = 0; i < TREE_VEC_LENGTH (mainargs); ++i) + for_each_template_parm (TREE_VEC_ELT (mainargs, i), + &mark_template_parm, + &tpd); + for (i = 0; i < ntparms; ++i) + if (tpd.parms[i] == 0) + { + /* One of the template parms was not used in the + specialization. */ + if (!did_error_intro) + { + cp_error ("template parameters not used in partial specialization:"); + did_error_intro = 1; + } + + cp_error (" `%D'", + TREE_VALUE (TREE_VEC_ELT + (TREE_VALUE (current_template_parms), + i))); + } + for (; spec; spec = TREE_CHAIN (spec)) { /* purpose: args to main template @@ -2505,6 +2609,8 @@ tree lookup_template_function (fns, arglist) tree fns, arglist; { + tree t; + if (fns == NULL_TREE) { cp_error ("non-template used as template"); @@ -2737,9 +2843,19 @@ lookup_template_class (d1, arglist, in_decl, context) /* Should be defined in parse.h. */ extern int yychar; +/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or + TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA. + If FN returns non-zero, the iteration is terminated, and + for_each_template_parm returns 1. Otherwise, the iteration + continues. If FN never returns a non-zero value, the value + returned by for_each_template_parm is 0. If FN is NULL, it is + considered to be the function which always returns 1. */ + int -uses_template_parms (t) +for_each_template_parm (t, fn, data) tree t; + tree_fn_t fn; + void* data; { if (!t) return 0; @@ -2750,7 +2866,7 @@ uses_template_parms (t) /* We assume that the object must be instantiated in order to build the COMPONENT_REF, so we test only whether the type of the COMPONENT_REF uses template parms. */ - return uses_template_parms (TREE_TYPE (t)); + return for_each_template_parm (TREE_TYPE (t), fn, data); case IDENTIFIER_NODE: if (!IDENTIFIER_TEMPLATE (t)) @@ -2762,49 +2878,52 @@ uses_template_parms (t) { int i = TREE_VEC_LENGTH (t); while (i--) - if (uses_template_parms (TREE_VEC_ELT (t, i))) + if (for_each_template_parm (TREE_VEC_ELT (t, i), fn, data)) return 1; return 0; } case TREE_LIST: - if (uses_template_parms (TREE_PURPOSE (t)) - || uses_template_parms (TREE_VALUE (t))) + if (for_each_template_parm (TREE_PURPOSE (t), fn, data) + || for_each_template_parm (TREE_VALUE (t), fn, data)) return 1; - return uses_template_parms (TREE_CHAIN (t)); + return for_each_template_parm (TREE_CHAIN (t), fn, data); /* constructed type nodes */ case POINTER_TYPE: case REFERENCE_TYPE: - return uses_template_parms (TREE_TYPE (t)); + return for_each_template_parm (TREE_TYPE (t), fn, data); case RECORD_TYPE: if (TYPE_PTRMEMFUNC_FLAG (t)) - return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (t)); + return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE (t), + fn, data); case UNION_TYPE: if (! CLASSTYPE_TEMPLATE_INFO (t)) return 0; - return uses_template_parms (TREE_VALUE (CLASSTYPE_TEMPLATE_INFO (t))); + return for_each_template_parm (TREE_VALUE + (CLASSTYPE_TEMPLATE_INFO (t)), + fn, data); case FUNCTION_TYPE: - if (uses_template_parms (TYPE_ARG_TYPES (t))) + if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data)) return 1; - return uses_template_parms (TREE_TYPE (t)); + return for_each_template_parm (TREE_TYPE (t), fn, data); case ARRAY_TYPE: - if (uses_template_parms (TYPE_DOMAIN (t))) + if (for_each_template_parm (TYPE_DOMAIN (t), fn, data)) return 1; - return uses_template_parms (TREE_TYPE (t)); + return for_each_template_parm (TREE_TYPE (t), fn, data); case OFFSET_TYPE: - if (uses_template_parms (TYPE_OFFSET_BASETYPE (t))) + if (for_each_template_parm (TYPE_OFFSET_BASETYPE (t), fn, data)) return 1; - return uses_template_parms (TREE_TYPE (t)); + return for_each_template_parm (TREE_TYPE (t), fn, data); case METHOD_TYPE: - if (uses_template_parms (TYPE_METHOD_BASETYPE (t))) + if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data)) return 1; - if (uses_template_parms (TYPE_ARG_TYPES (t))) + if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data)) return 1; - return uses_template_parms (TREE_TYPE (t)); + return for_each_template_parm (TREE_TYPE (t), fn, data); /* decl nodes */ case TYPE_DECL: - return uses_template_parms (TREE_TYPE (t)); + return for_each_template_parm (TREE_TYPE (t), fn, data); case TEMPLATE_DECL: /* A template template parameter is encountered */ @@ -2816,7 +2935,7 @@ uses_template_parms (t) return 0; case CONST_DECL: - if (uses_template_parms (DECL_INITIAL (t))) + if (for_each_template_parm (DECL_INITIAL (t), fn, data)) return 1; goto check_type_and_context; @@ -2824,33 +2943,37 @@ uses_template_parms (t) case VAR_DECL: /* ??? What about FIELD_DECLs? */ if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t) - && uses_template_parms (DECL_TI_ARGS (t))) + && for_each_template_parm (DECL_TI_ARGS (t), fn, data)) return 1; /* fall through */ case PARM_DECL: check_type_and_context: - if (uses_template_parms (TREE_TYPE (t))) + if (for_each_template_parm (TREE_TYPE (t), fn, data)) return 1; - if (DECL_CONTEXT (t) && uses_template_parms (DECL_CONTEXT (t))) + if (DECL_CONTEXT (t) + && for_each_template_parm (DECL_CONTEXT (t), fn, data)) return 1; return 0; case CALL_EXPR: - return uses_template_parms (TREE_TYPE (t)); + return for_each_template_parm (TREE_TYPE (t), fn, data); case ADDR_EXPR: - return uses_template_parms (TREE_OPERAND (t, 0)); + return for_each_template_parm (TREE_OPERAND (t, 0), fn, data); /* template parm nodes */ case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: case TEMPLATE_PARM_INDEX: - return 1; + if (fn) + return (*fn)(t, data); + else + return 1; /* simple type nodes */ case INTEGER_TYPE: - if (uses_template_parms (TYPE_MIN_VALUE (t))) + if (for_each_template_parm (TYPE_MIN_VALUE (t), fn, data)) return 1; - return uses_template_parms (TYPE_MAX_VALUE (t)); + return for_each_template_parm (TYPE_MAX_VALUE (t), fn, data); case REAL_TYPE: case COMPLEX_TYPE: @@ -2863,7 +2986,7 @@ uses_template_parms (t) tree v; for (v = TYPE_VALUES (t); v != NULL_TREE; v = TREE_CHAIN (v)) - if (uses_template_parms (TREE_VALUE (v))) + if (for_each_template_parm (TREE_VALUE (v), fn, data)) return 1; } return 0; @@ -2885,12 +3008,13 @@ uses_template_parms (t) return 1; case SCOPE_REF: - return uses_template_parms (TREE_OPERAND (t, 0)); + return for_each_template_parm (TREE_OPERAND (t, 0), fn, data); case CONSTRUCTOR: if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) - return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t))); - return uses_template_parms (TREE_OPERAND (t, 1)); + return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE + (TREE_TYPE (t)), fn, data); + return for_each_template_parm (TREE_OPERAND (t, 1), fn, data); case MODOP_EXPR: case CAST_EXPR: @@ -2905,7 +3029,7 @@ uses_template_parms (t) case SIZEOF_EXPR: case ALIGNOF_EXPR: - return uses_template_parms (TREE_OPERAND (t, 0)); + return for_each_template_parm (TREE_OPERAND (t, 0), fn, data); default: switch (TREE_CODE_CLASS (TREE_CODE (t))) @@ -2917,7 +3041,7 @@ uses_template_parms (t) { int i; for (i = tree_code_length[(int) TREE_CODE (t)]; --i >= 0;) - if (uses_template_parms (TREE_OPERAND (t, i))) + if (for_each_template_parm (TREE_OPERAND (t, i), fn, data)) return 1; return 0; } @@ -2932,6 +3056,13 @@ uses_template_parms (t) } } +int +uses_template_parms (t) + tree t; +{ + return for_each_template_parm (t, 0, 0); +} + static struct tinst_level *current_tinst_level = 0; static struct tinst_level *free_tinst_level = 0; static int tinst_depth = 0; @@ -3549,7 +3680,7 @@ tsubst (t, args, in_decl) r = lookup_template_class (t, argvec, in_decl, context); return cp_build_type_variant (r, TYPE_READONLY (t), - TYPE_VOLATILE (t)); + TYPE_VOLATILE (t)); } /* else fall through */ @@ -3625,7 +3756,8 @@ tsubst (t, args, in_decl) { tree arg = NULL_TREE; - if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) + if (TREE_VEC_ELT (args, 0) != NULL_TREE + && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) { levels = TREE_VEC_LENGTH (args); if (level <= levels) @@ -3678,12 +3810,15 @@ tsubst (t, args, in_decl) } } + if (level == 1) + /* This can happen during the attempted tsubst'ing in + unify. This means that we don't yet have any information + about the template parameter in question. */ + return t; + /* If we get here, we must have been looking at a parm for a - more deeply nested template. */ - my_friendly_assert(level > 1, 0); - - /* Make a new version of this template parameter, but with a - lower level. */ + more deeply nested template. Make a new version of this + template parameter, but with a lower level. */ switch (TREE_CODE (t)) { case TEMPLATE_TYPE_PARM: @@ -5111,7 +5246,7 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type, fn_arg_types); i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn), - &TREE_VEC_ELT (targs, 0), + targs, fn_arg_types, decl_arg_types, explicit_targs, @@ -5147,15 +5282,17 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type, int type_unification (tparms, targs, parms, args, targs_in, strict, allow_incomplete) - tree tparms, *targs, parms, args, targs_in; + tree tparms, targs, parms, args, targs_in; int strict, allow_incomplete; { int ntparms = TREE_VEC_LENGTH (tparms); tree arg; + int* explicit_mask; int i; int r; - bzero ((char *) targs, sizeof (tree) * ntparms); + for (i = 0; i < ntparms; i++) + TREE_VEC_ELT (targs, i) = NULL_TREE; if (targs_in != NULL_TREE) { @@ -5166,34 +5303,38 @@ type_unification (tparms, targs, parms, args, targs_in, if (arg_vec == error_mark_node) return 1; + explicit_mask = alloca (sizeof (int) * TREE_VEC_LENGTH (targs)); + bzero (explicit_mask, sizeof(int) * TREE_VEC_LENGTH (targs)); + for (i = 0; i < TREE_VEC_LENGTH (arg_vec) - && TREE_VEC_ELT (arg_vec, i) != NULL_TREE; + && TREE_VEC_ELT (arg_vec, i) != NULL_TREE; ++i) - /* Insert the template argument. It is encoded as the operands - of NOP_EXPRs so that unify can tell that it is an explicit - arguments. */ - targs[i] = build1 (NOP_EXPR, NULL_TREE, TREE_VEC_ELT (arg_vec, i)); + { + TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (arg_vec, i); + /* Let unify know that this argument was explicit. */ + explicit_mask [i] = 1; + } } - - r = type_unification_real (tparms, targs, parms, args, 0, - strict, allow_incomplete); + else + explicit_mask = 0; - for (i = 0, arg = targs_in; - arg != NULL_TREE; - arg = TREE_CHAIN (arg), ++i) - if (TREE_CODE (targs[i]) == NOP_EXPR) - targs[i] = TREE_OPERAND (targs[i], 0); + r = type_unification_real (tparms, targs, parms, args, 0, + strict, allow_incomplete, explicit_mask); return r; } +/* Like type_unfication. EXPLICIT_MASK, if non-NULL, is an array of + integers, with ones in positions corresponding to arguments in + targs that were provided explicitly, and zeros elsewhere. */ static int type_unification_real (tparms, targs, parms, args, subr, - strict, allow_incomplete) - tree tparms, *targs, parms, args; + strict, allow_incomplete, explicit_mask) + tree tparms, targs, parms, args; int subr, strict, allow_incomplete; + int* explicit_mask; { tree parm, arg; int i; @@ -5267,12 +5408,12 @@ type_unification_real (tparms, targs, parms, args, subr, && TREE_CODE (TREE_VALUE (arg)) == TEMPLATE_DECL) { int ntparms; - tree *targs; + tree targs; /* Have to back unify here */ arg = TREE_VALUE (arg); ntparms = DECL_NTPARMS (arg); - targs = (tree *) alloca (sizeof (tree) * ntparms); + targs = make_scratch_vec (ntparms); parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE); return type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg), @@ -5304,7 +5445,8 @@ type_unification_real (tparms, targs, parms, args, subr, arg = TYPE_MAIN_VARIANT (arg); } - switch (unify (tparms, targs, ntparms, parm, arg, strict)) + switch (unify (tparms, targs, ntparms, parm, arg, strict, + explicit_mask)) { case 0: break; @@ -5323,7 +5465,7 @@ type_unification_real (tparms, targs, parms, args, subr, return 1; if (!subr) for (i = 0; i < ntparms; i++) - if (!targs[i]) + if (TREE_VEC_ELT (targs, i) == NULL_TREE) { if (!allow_incomplete) error ("incomplete type unification"); @@ -5335,11 +5477,13 @@ type_unification_real (tparms, targs, parms, args, subr, /* Tail recursion is your friend. */ static int -unify (tparms, targs, ntparms, parm, arg, strict) - tree tparms, *targs, parm, arg; +unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) + tree tparms, targs, parm, arg; int ntparms, strict; + int* explicit_mask; { int idx; + tree targ; /* I don't think this will do the right thing with respect to types. But the only case I've seen it in so far has been array bounds, where @@ -5372,12 +5516,13 @@ unify (tparms, targs, ntparms, parm, arg, strict) case TEMPLATE_TYPE_PARM: idx = TEMPLATE_TYPE_IDX (parm); + targ = TREE_VEC_ELT (targs, idx); /* Check for mixed types and values. */ if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL) return 1; - if (!strict && targs[idx] != NULL_TREE && - TREE_CODE (targs[idx]) == NOP_EXPR) + if (!strict && targ != NULL_TREE + && explicit_mask && explicit_mask[idx]) /* An explicit template argument. Don't even try to match here; the overload resolution code will manage check to see whether the call is legal. */ @@ -5402,24 +5547,23 @@ unify (tparms, targs, ntparms, parm, arg, strict) } #endif /* Simple cases: Value already set, does match or doesn't. */ - if (targs[idx] == arg - || (targs[idx] - && TREE_CODE (targs[idx]) == NOP_EXPR - && TREE_OPERAND (targs[idx], 0) == arg)) + if (targ == arg || (targ && explicit_mask && explicit_mask[idx])) return 0; - else if (targs[idx]) + else if (targ) return 1; - targs[idx] = arg; + TREE_VEC_ELT (targs, idx) = arg; return 0; case TEMPLATE_TEMPLATE_PARM: idx = TEMPLATE_TYPE_IDX (parm); + targ = TREE_VEC_ELT (targs, idx); + /* Check for mixed types and values. */ if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TEMPLATE_DECL) return 1; - if (!strict && targs[idx] != NULL_TREE && - TREE_CODE (targs[idx]) == NOP_EXPR) + if (!strict && targ != NULL_TREE + && explicit_mask && explicit_mask[idx]) /* An explicit template argument. Don't even try to match here; the overload resolution code will manage check to see whether the call is legal. */ @@ -5465,7 +5609,7 @@ unify (tparms, targs, ntparms, parm, arg, strict) /* This argument can be deduced. */ if (unify (tparms, targs, ntparms, t, - TREE_VEC_ELT (argvec, i), strict)) + TREE_VEC_ELT (argvec, i), strict, explicit_mask)) return 1; } } @@ -5473,21 +5617,19 @@ unify (tparms, targs, ntparms, parm, arg, strict) } /* Simple cases: Value already set, does match or doesn't. */ - if (targs[idx] == arg - || (targs[idx] - && TREE_CODE (targs[idx]) == NOP_EXPR - && TREE_OPERAND (targs[idx], 0) == arg)) + if (targ == arg || (targ && explicit_mask && explicit_mask[idx])) return 0; - else if (targs[idx]) + else if (targ) return 1; - targs[idx] = arg; + TREE_VEC_ELT (targs, idx) = arg; return 0; case TEMPLATE_PARM_INDEX: idx = TEMPLATE_PARM_IDX (parm); - if (targs[idx]) + targ = TREE_VEC_ELT (targs, idx); + if (targ) { - int i = cp_tree_equal (targs[idx], arg); + int i = cp_tree_equal (targ, arg); if (i == 1) return 0; else if (i == 0) @@ -5496,24 +5638,24 @@ unify (tparms, targs, ntparms, parm, arg, strict) my_friendly_abort (42); } - targs[idx] = copy_to_permanent (arg); + TREE_VEC_ELT (targs, idx) = copy_to_permanent (arg); return 0; case POINTER_TYPE: if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg)) return unify (tparms, targs, ntparms, parm, - TYPE_PTRMEMFUNC_FN_TYPE (arg), strict); + TYPE_PTRMEMFUNC_FN_TYPE (arg), strict, explicit_mask); if (TREE_CODE (arg) != POINTER_TYPE) return 1; return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), - strict); + strict, explicit_mask); case REFERENCE_TYPE: if (TREE_CODE (arg) == REFERENCE_TYPE) arg = TREE_TYPE (arg); return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, - strict); + strict, explicit_mask); case ARRAY_TYPE: if (TREE_CODE (arg) != ARRAY_TYPE) @@ -5523,10 +5665,10 @@ unify (tparms, targs, ntparms, parm, arg, strict) return 1; if (TYPE_DOMAIN (parm) != NULL_TREE && unify (tparms, targs, ntparms, TYPE_DOMAIN (parm), - TYPE_DOMAIN (arg), strict) != 0) + TYPE_DOMAIN (arg), strict, explicit_mask) != 0) return 1; return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), - strict); + strict, explicit_mask); case REAL_TYPE: case COMPLEX_TYPE: @@ -5540,11 +5682,11 @@ unify (tparms, targs, ntparms, parm, arg, strict) { if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg) && unify (tparms, targs, ntparms, TYPE_MIN_VALUE (parm), - TYPE_MIN_VALUE (arg), strict)) + TYPE_MIN_VALUE (arg), strict, explicit_mask)) return 1; if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg) && unify (tparms, targs, ntparms, TYPE_MAX_VALUE (parm), - TYPE_MAX_VALUE (arg), strict)) + TYPE_MAX_VALUE (arg), strict, explicit_mask)) return 1; } else if (TREE_CODE (parm) == REAL_TYPE @@ -5565,16 +5707,6 @@ unify (tparms, targs, ntparms, parm, arg, strict) return 1; return !tree_int_cst_equal (parm, arg); - case MINUS_EXPR: - { - tree t1, t2; - t1 = TREE_OPERAND (parm, 0); - t2 = TREE_OPERAND (parm, 1); - return unify (tparms, targs, ntparms, t1, - fold (build (PLUS_EXPR, integer_type_node, arg, t2)), - strict); - } - case TREE_VEC: { int i; @@ -5585,7 +5717,7 @@ unify (tparms, targs, ntparms, parm, arg, strict) for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--) if (unify (tparms, targs, ntparms, TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i), - strict)) + strict, explicit_mask)) return 1; return 0; } @@ -5593,7 +5725,7 @@ unify (tparms, targs, ntparms, parm, arg, strict) case RECORD_TYPE: if (TYPE_PTRMEMFUNC_FLAG (parm)) return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm), - arg, strict); + arg, strict, explicit_mask); /* Allow trivial conversions. */ if (TREE_CODE (arg) != RECORD_TYPE @@ -5614,7 +5746,7 @@ unify (tparms, targs, ntparms, parm, arg, strict) return 1; return unify (tparms, targs, ntparms, CLASSTYPE_TI_ARGS (parm), - CLASSTYPE_TI_ARGS (t), strict); + CLASSTYPE_TI_ARGS (t), strict, explicit_mask); } else if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg)) return 1; @@ -5630,20 +5762,20 @@ unify (tparms, targs, ntparms, parm, arg, strict) return 1; check_args: if (unify (tparms, targs, ntparms, TREE_TYPE (parm), - TREE_TYPE (arg), strict)) + TREE_TYPE (arg), strict, explicit_mask)) return 1; return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm), TYPE_ARG_TYPES (arg), 1, - strict, 0); + strict, 0, explicit_mask); case OFFSET_TYPE: if (TREE_CODE (arg) != OFFSET_TYPE) return 1; if (unify (tparms, targs, ntparms, TYPE_OFFSET_BASETYPE (parm), - TYPE_OFFSET_BASETYPE (arg), strict)) + TYPE_OFFSET_BASETYPE (arg), strict, explicit_mask)) return 1; return unify (tparms, targs, ntparms, TREE_TYPE (parm), - TREE_TYPE (arg), strict); + TREE_TYPE (arg), strict, explicit_mask); case CONST_DECL: if (arg != decl_constant_value (parm)) @@ -5655,8 +5787,65 @@ unify (tparms, targs, ntparms, parm, arg, strict) return 1; default: - sorry ("use of `%s' in template type unification", - tree_code_name [(int) TREE_CODE (parm)]); + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm)))) + { + /* We're looking at an expression. This can happen with + something like: + + template + void foo(S, S); + + If the call looked like: + + foo(S<2>(), S<4>()); + + we would have already matched `I' with `2'. Now, we'd + like to know if `4' matches `I + 2'. So, we substitute + into that expression, and fold constants, in the hope of + figuring it out. */ + tree t = + maybe_fold_nontype_arg (tsubst_expr (parm, targs, NULL_TREE)); + enum tree_code tc = TREE_CODE (t); + + if (tc == MINUS_EXPR + && TREE_CODE (TREE_OPERAND (t, 0)) == TEMPLATE_PARM_INDEX + && TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST) + { + /* We handle this case specially, since it comes up with + arrays. In particular, something like: + + template void f(int (&x)[N]); + + Here, we are trying to unify the range type, which + looks like [0 ... (N - 1)]. */ + tree t1, t2; + t1 = TREE_OPERAND (parm, 0); + t2 = TREE_OPERAND (parm, 1); + + t = maybe_fold_nontype_arg (build (PLUS_EXPR, + integer_type_node, + arg, t2)); + + return unify (tparms, targs, ntparms, t1, t, + strict, explicit_mask); + } + + if (!IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc))) + /* Good, we mangaged to simplify the exression. */ + return unify (tparms, targs, ntparms, t, arg, strict, + explicit_mask); + else + /* Bad, we couldn't simplify this. Assume it doesn't + unify. */ + return 1; + } + else + { + sorry ("use of `%s' in template type unification", + tree_code_name [(int) TREE_CODE (parm)]); + break; + } + return 1; } } @@ -5837,8 +6026,9 @@ get_class_bindings (tparms, parms, args, outer_args) for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) { - switch (unify (tparms, &TREE_VEC_ELT (vec, 0), ntparms, - TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i), 1)) + switch (unify (tparms, vec, ntparms, + TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i), + 1, 0)) { case 0: break; diff --git a/gcc/cplus-dem.c b/gcc/cplus-dem.c index af9244909f7..898ab4bd500 100644 --- a/gcc/cplus-dem.c +++ b/gcc/cplus-dem.c @@ -197,7 +197,8 @@ static const struct optable {"min", "*", DMGL_ANSI} /* ansi */ + {"rm", "->*", DMGL_ANSI}, /* ansi */ + {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */ }; @@ -330,6 +331,10 @@ forget_types PARAMS ((struct work_stuff *)); static void string_prepends PARAMS ((string *, string *)); +static int +demangle_template_value_parm PARAMS ((struct work_stuff*, + const char**, string*)); + /* Translate count to integer, consuming tokens in the process. Conversion terminates on the first non-digit character. Trying to consume something that isn't a count results in @@ -995,6 +1000,270 @@ demangle_template_template_parm (work, mangled, tname) return (success); } +static int +demangle_integral_value (work, mangled, s) + struct work_stuff *work; + const char** mangled; + string* s; +{ + int success; + + if (**mangled == 'E') + { + int need_operator = 0; + + success = 1; + string_appendn (s, "(", 1); + (*mangled)++; + while (success && **mangled != 'W' && **mangled != '\0') + { + if (need_operator) + { + size_t i; + size_t len; + + success = 0; + + len = strlen (*mangled); + + for (i = 0; + i < sizeof (optable) / sizeof (optable [0]); + ++i) + { + size_t l = strlen (optable[i].in); + + if (l <= len + && memcmp (optable[i].in, *mangled, l) == 0) + { + string_appendn (s, " ", 1); + string_append (s, optable[i].out); + string_appendn (s, " ", 1); + success = 1; + (*mangled) += l; + break; + } + } + + if (!success) + break; + } + else + need_operator = 1; + + success = demangle_template_value_parm (work, mangled, s); + } + + if (**mangled != 'W') + success = 0; + else + { + string_appendn (s, ")", 1); + (*mangled)++; + } + } + else if (**mangled == 'Q') + success = demangle_qualified (work, mangled, s, 0, 1); + else + { + success = 0; + + if (**mangled == 'm') + { + string_appendn (s, "-", 1); + (*mangled)++; + } + while (isdigit (**mangled)) + { + string_appendn (s, *mangled, 1); + (*mangled)++; + success = 1; + } + } + + return success; +} + +static int +demangle_template_value_parm (work, mangled, s) + struct work_stuff *work; + const char **mangled; + string* s; +{ + const char *old_p = *mangled; + int is_pointer = 0; + int is_real = 0; + int is_integral = 0; + int is_char = 0; + int is_bool = 0; + int done = 0; + int success = 1; + + while (*old_p && !done) + { + switch (*old_p) + { + case 'P': + case 'p': + case 'R': + done = is_pointer = 1; + break; + case 'C': /* const */ + case 'S': /* explicitly signed [char] */ + case 'U': /* unsigned */ + case 'V': /* volatile */ + case 'F': /* function */ + case 'M': /* member function */ + case 'O': /* ??? */ + case 'J': /* complex */ + old_p++; + continue; + case 'E': /* expression */ + case 'Q': /* qualified name */ + done = is_integral = 1; + break; + case 'T': /* remembered type */ + abort (); + break; + case 'v': /* void */ + abort (); + break; + case 'x': /* long long */ + case 'l': /* long */ + case 'i': /* int */ + case 's': /* short */ + case 'w': /* wchar_t */ + done = is_integral = 1; + break; + case 'b': /* bool */ + done = is_bool = 1; + break; + case 'c': /* char */ + done = is_char = 1; + break; + case 'r': /* long double */ + case 'd': /* double */ + case 'f': /* float */ + done = is_real = 1; + break; + default: + /* it's probably user defined type, let's assume + it's integral, it seems hard to figure out + what it really is */ + done = is_integral = 1; + } + } + if (**mangled == 'Y') + { + /* The next argument is a template parameter. */ + int idx; + + (*mangled)++; + idx = consume_count_with_underscores (mangled); + if (idx == -1 + || (work->tmpl_argvec && idx >= work->ntmpl_args) + || consume_count_with_underscores (mangled) == -1) + return -1; + if (work->tmpl_argvec) + string_append (s, work->tmpl_argvec[idx]); + else + { + char buf[10]; + sprintf(buf, "T%d", idx); + string_append (s, buf); + } + } + else if (is_integral) + success = demangle_integral_value (work, mangled, s); + else if (is_char) + { + char tmp[2]; + int val; + if (**mangled == 'm') + { + string_appendn (s, "-", 1); + (*mangled)++; + } + string_appendn (s, "'", 1); + val = consume_count(mangled); + if (val == 0) + return -1; + tmp[0] = (char)val; + tmp[1] = '\0'; + string_appendn (s, &tmp[0], 1); + string_appendn (s, "'", 1); + } + else if (is_bool) + { + int val = consume_count (mangled); + if (val == 0) + string_appendn (s, "false", 5); + else if (val == 1) + string_appendn (s, "true", 4); + else + success = 0; + } + else if (is_real) + { + if (**mangled == 'm') + { + string_appendn (s, "-", 1); + (*mangled)++; + } + while (isdigit (**mangled)) + { + string_appendn (s, *mangled, 1); + (*mangled)++; + } + if (**mangled == '.') /* fraction */ + { + string_appendn (s, ".", 1); + (*mangled)++; + while (isdigit (**mangled)) + { + string_appendn (s, *mangled, 1); + (*mangled)++; + } + } + if (**mangled == 'e') /* exponent */ + { + string_appendn (s, "e", 1); + (*mangled)++; + while (isdigit (**mangled)) + { + string_appendn (s, *mangled, 1); + (*mangled)++; + } + } + } + else if (is_pointer) + { + int symbol_len = consume_count (mangled); + if (symbol_len == 0) + return -1; + if (symbol_len == 0) + string_appendn (s, "0", 1); + else + { + char *p = xmalloc (symbol_len + 1), *q; + strncpy (p, *mangled, symbol_len); + p [symbol_len] = '\0'; + q = cplus_demangle (p, work->options); + string_appendn (s, "&", 1); + if (q) + { + string_append (s, q); + free (q); + } + else + string_append (s, p); + free (p); + } + *mangled += symbol_len; + } + + return success; +} + static int demangle_template (work, mangled, tname, trawname, is_type) struct work_stuff *work; @@ -1004,18 +1273,10 @@ demangle_template (work, mangled, tname, trawname, is_type) int is_type; { int i; - int is_pointer; - int is_real; - int is_integral; - int is_char; - int is_bool; int r; int need_comma = 0; int success = 0; - int done; - const char *old_p; const char *start; - int symbol_len; int is_java_array = 0; string temp; @@ -1148,13 +1409,7 @@ demangle_template (work, mangled, tname, trawname, is_type) string* s; /* otherwise, value parameter */ - old_p = *mangled; - is_pointer = 0; - is_real = 0; - is_integral = 0; - is_char = 0; - is_bool = 0; - done = 0; + /* temp is initialized in do_type */ success = do_type (work, mangled, &temp); /* @@ -1180,193 +1435,16 @@ demangle_template (work, mangled, tname, trawname, is_type) else s = tname; - while (*old_p && !done) - { - switch (*old_p) - { - case 'P': - case 'p': - case 'R': - done = is_pointer = 1; - break; - case 'C': /* const */ - case 'S': /* explicitly signed [char] */ - case 'U': /* unsigned */ - case 'V': /* volatile */ - case 'F': /* function */ - case 'M': /* member function */ - case 'O': /* ??? */ - case 'J': /* complex */ - old_p++; - continue; - case 'Q': /* qualified name */ - done = is_integral = 1; - break; - case 'T': /* remembered type */ - abort (); - break; - case 'v': /* void */ - abort (); - break; - case 'x': /* long long */ - case 'l': /* long */ - case 'i': /* int */ - case 's': /* short */ - case 'w': /* wchar_t */ - done = is_integral = 1; - break; - case 'b': /* bool */ - done = is_bool = 1; - break; - case 'c': /* char */ - done = is_char = 1; - break; - case 'r': /* long double */ - case 'd': /* double */ - case 'f': /* float */ - done = is_real = 1; - break; - default: - /* it's probably user defined type, let's assume - it's integral, it seems hard to figure out - what it really is */ - done = is_integral = 1; - } - } - if (**mangled == 'Y') - { - /* The next argument is a template parameter. */ - int idx; + success = demangle_template_value_parm (work, mangled, s); - (*mangled)++; - idx = consume_count_with_underscores (mangled); - if (idx == -1 - || (work->tmpl_argvec && idx >= work->ntmpl_args) - || consume_count_with_underscores (mangled) == -1) - { - success = 0; - if (!is_type) - string_delete (s); - break; - } - if (work->tmpl_argvec) - string_append (s, work->tmpl_argvec[idx]); - else - { - char buf[10]; - sprintf(buf, "T%d", idx); - string_append (s, buf); - } - } - else if (is_integral) - { - if (**mangled == 'm') - { - string_appendn (s, "-", 1); - (*mangled)++; - } - while (isdigit (**mangled)) - { - string_appendn (s, *mangled, 1); - (*mangled)++; - } - } - else if (is_char) - { - char tmp[2]; - int val; - if (**mangled == 'm') - { - string_appendn (s, "-", 1); - (*mangled)++; - } - string_appendn (s, "'", 1); - val = consume_count(mangled); - if (val == 0) - { - success = 0; - if (!is_type) - string_delete (s); - break; - } - tmp[0] = (char)val; - tmp[1] = '\0'; - string_appendn (s, &tmp[0], 1); - string_appendn (s, "'", 1); - } - else if (is_bool) - { - int val = consume_count (mangled); - if (val == 0) - string_appendn (s, "false", 5); - else if (val == 1) - string_appendn (s, "true", 4); - else - success = 0; - } - else if (is_real) - { - if (**mangled == 'm') - { - string_appendn (s, "-", 1); - (*mangled)++; - } - while (isdigit (**mangled)) - { - string_appendn (s, *mangled, 1); - (*mangled)++; - } - if (**mangled == '.') /* fraction */ - { - string_appendn (s, ".", 1); - (*mangled)++; - while (isdigit (**mangled)) - { - string_appendn (s, *mangled, 1); - (*mangled)++; - } - } - if (**mangled == 'e') /* exponent */ - { - string_appendn (s, "e", 1); - (*mangled)++; - while (isdigit (**mangled)) - { - string_appendn (s, *mangled, 1); - (*mangled)++; - } - } - } - else if (is_pointer) + if (!success) { - symbol_len = consume_count (mangled); - if (symbol_len == 0) - { - success = 0; - if (!is_type) - string_delete (s); - break; - } - if (symbol_len == 0) - string_appendn (s, "0", 1); - else - { - char *p = xmalloc (symbol_len + 1), *q; - strncpy (p, *mangled, symbol_len); - p [symbol_len] = '\0'; - q = cplus_demangle (p, work->options); - string_appendn (s, "&", 1); - if (q) - { - string_append (s, q); - free (q); - } - else - string_append (s, p); - free (p); - } - *mangled += symbol_len; + if (!is_type) + string_delete (s); + success = 0; + break; } + if (!is_type) { int len = s->p - s->b; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash4.C b/gcc/testsuite/g++.old-deja/g++.pt/crash4.C new file mode 100644 index 00000000000..510d4cdd836 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash4.C @@ -0,0 +1,11 @@ +// Build don't link: + +template +class Tensor +{ +}; + +template +class Tensor<2> : Tensor { // ERROR - template parameters not used +}; + diff --git a/gcc/testsuite/g++.old-deja/g++.pt/expr1.C b/gcc/testsuite/g++.old-deja/g++.pt/expr1.C new file mode 100644 index 00000000000..cdb868770bc --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/expr1.C @@ -0,0 +1,33 @@ +template class vec { + double x[n]; + + public: + vec() { + for (int i=0; i& v) { + for (int i=0; i& v, const double& y) { + for (int i=0; i vec& operator,(const vec& v, const double& y) { + return *(new vec(v, y)); +} + + +int main() { + vec<4> v; + vec<5> w; + w=(v,3.); +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/expr2.C b/gcc/testsuite/g++.old-deja/g++.pt/expr2.C new file mode 100644 index 00000000000..d6e5593b242 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/expr2.C @@ -0,0 +1,12 @@ +// Build don't link: + +template +struct S {}; + +template +void foo(S); + +void bar() +{ + foo(S<3>()); // ERROR - no way to deduce J from this. +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/expr3.C b/gcc/testsuite/g++.old-deja/g++.pt/expr3.C new file mode 100644 index 00000000000..4d77370e186 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/expr3.C @@ -0,0 +1,20 @@ +// Build don't link: + +template +struct S {}; + +template +void foo(S); + +template +void baz(S); + +template +void fun(S, S); + +void bar() +{ + foo<5>(S<4>()); // OK - 4 is 5 - 1. + baz(S()); // OK + fun(S<4>(), S<8>()); // OK - deduce J from first argument. +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/expr4.C b/gcc/testsuite/g++.old-deja/g++.pt/expr4.C new file mode 100644 index 00000000000..13298febe4d --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/expr4.C @@ -0,0 +1,373 @@ +template +class TinyContainer { +public: + + typedef W T_Wrapped; + + TinyContainer() { } + TinyContainer(View data) : m_data(data) { } + + T_Wrapped &unwrap() + { + return *static_cast(this); + } + const T_Wrapped &unwrap() const + { + return *static_cast(this); + } + +protected: + + mutable View m_data; +}; + +template +class TinyBinaryExpr : + public TinyContainer< Op, TinyBinaryExpr > { +public: + + typedef typename Left::T_Return T_Return; + typedef TinyBinaryExpr T_Expr; + + T_Expr makeExpr() const { return *this; } + + TinyBinaryExpr(const Op &op, const Left &left, const Right &right) + : TinyContainer< Op, TinyBinaryExpr >(op), + m_left(left), m_right(right) + { } + + TinyBinaryExpr(const Left &left, const Right &right) + : m_left(left), m_right(right) + { } + + Op op() const { return m_data; } + Left left() const { return m_left; } + Right right() const { return m_right; } + +private: + + Left m_left; + Right m_right; +}; + +struct OpAdd { + + template + static T1 apply(const T1 &l, const T2 &r) + { + return l + r; + } + +}; + +template +inline TinyBinaryExpr +operator+(const TinyContainer& l, const TinyContainer& r) +{ + typedef TinyBinaryExpr ret; + return ret(l.unwrap().makeExpr(), r.unwrap().makeExpr()); +} + + +template +inline +typename T1::T_Return +for_each(const TinyBinaryExpr& node, Functor f) +{ + return Op::apply(for_each(node.left(),f), for_each(node.right(),f)); +} + +template +class DenseDataView + : public TinyContainer< T*, DenseDataView > { +public: + + typedef T T_Return; + typedef DenseDataView T_Expr; + + T_Expr makeExpr() const { return *this; } + + T *beginLoc(unsigned i, unsigned j) const + { return m_data + S1 * i + S2 * j; } + + DenseDataView(T *pData) + : TinyContainer< T*, DenseDataView >(pData) { } + + T &offset(unsigned i, unsigned j) + { + return m_data[S1 * i + S2 * j]; + } + + T offset(unsigned i, unsigned j) const + { + return m_data[S1 * i + S2 * j]; + } + + template + struct Offset { + + static T &apply(DenseDataView &d) + { + return d.m_data[S1 * I + S2 * J]; + } + + static T constApply(const DenseDataView &d) + { + return d.m_data[S1 * I + S2 * J]; + } + + }; + +}; + +template +struct Eval2 { }; + +template +inline T +for_each(const DenseDataView &d, + const Eval2 &e) +{ + return d.offset(I, J); +} + +template +class DenseData + : public TinyContainer< T[Nrows * Ncols], DenseData > { +public: + + typedef T T_Return; + typedef DenseDataView T_Expr; + + T_Expr makeExpr() const { return T_Expr(m_data); } + + T *beginLoc(unsigned i, unsigned j) const + { return &m_data[i + Nrows * j]; } + + T &operator[](unsigned i) + { + return m_data[i]; + } + + T operator[](unsigned i) const + { + return m_data[i]; + } + + T &offset(unsigned i, unsigned j) + { + return m_data[i + Nrows * j]; + } + + T offset(unsigned i, unsigned j) const + { + return m_data[i + Nrows * j]; + } + + template + struct Offset { + + static T &apply(DenseData &d) + { + return d.m_data[I + Nrows * J]; + } + + static T constApply(const DenseData &d) + { + return d.m_data[I + Nrows * J]; + } + + }; + +}; + +template +class DiagonalData { +public: + + T &offset(unsigned i, unsigned j) + { + assert(i == j); + return m_data[i]; + } + + T offset(unsigned i, unsigned j) const + { + return (i == j) ? m_data[i] : T(0); + } + + template + struct Offset { + + static T &apply(DiagonalData &d) + { + assert(I == J); + return d.m_data[I]; + } + + static T constApply(const DiagonalData &d) + { + return (I == J) ? d.m_data[I] : T(0); + } + + }; + +private: + + T m_data[Nrc]; +}; + +template +struct InnerLoop { + + template + static inline void eval(LHS &l, const RHS &r) + { + l.offset(I,J) = for_each(r, Eval2()); + InnerLoop::eval(l, r); + } + +}; + +template +struct InnerLoop { + + template + static inline void eval(LHS &, const RHS &) { } + +}; + +template +struct Loop2 { + + template + static inline void eval(LHS &l, const RHS &r) + { + InnerLoop::eval(l, r); + Loop2::eval(l, r); + } +}; + +template +struct Loop2 { + + template + static inline void eval(LHS &l, const RHS &r) { } + +}; + + +template +class TinyRange { +public: + + static const unsigned b = Begin; + static const unsigned e = End; + static const unsigned s = Stride; + static const unsigned n = (End - Begin) / Stride + 1; + + static unsigned index(unsigned i) + { + return b + s * i; + } +}; + +template +struct Merge { }; + +template +struct Merge > +{ + static const unsigned s2 = Nrows * Range2::s; + typedef + DenseDataView type; +}; + +template +struct Merge > +{ + static const unsigned s1 = S1 * Range1::s; + static const unsigned s2 = S2 * Range2::s; + + typedef + DenseDataView type; +}; + +template > +class TinyMatrix : + public TinyContainer< Data, TinyMatrix > { +public: + + typedef T T_Return; + typedef typename Data::T_Expr T_Expr; + typedef TinyContainer< Data, TinyMatrix > T_Base; + + T_Expr makeExpr() const { return m_data.makeExpr(); } + + TinyMatrix() { } + + TinyMatrix(const T &a0, const T &a1, const T &a2, + const T &a3, const T &a4, const T &a5) + { + m_data[0] = a0; m_data[1] = a1; m_data[2] = a2; + m_data[3] = a3; m_data[4] = a4; m_data[5] = a5; + } + + TinyMatrix(const T &a0, const T &a1) + { + m_data[0] = a0; m_data[1] = a1; + } + + TinyMatrix(const Data &d) : T_Base(d) { } + + T operator()(unsigned i, unsigned j) const + { + return m_data.offset(i, j); + } + + template + TinyMatrix::n, + TinyRange::n, + typename + Merge< TinyRange, TinyRange, Data>::type> + operator()(const TinyRange &r1, const TinyRange &r2) + { + typedef typename + Merge< TinyRange, TinyRange, Data>::type + T_DataType; + typedef TinyMatrix::n, + TinyRange::n, T_DataType> T_RetType; + + return T_RetType(T_DataType(m_data.beginLoc(B1, B2))); + } + + template + void operator=(const TinyContainer &rhs) + { + Loop2<0, 0, Nrows, Ncols>::eval(m_data, rhs.unwrap().makeExpr()); + } + +}; + + +int main() +{ + TinyMatrix a, b(1.0, 2.0, 3.0, 4.0, 5.0, 6.0), + c(0.1, 0.2, 0.3, 0.4, 0.5, 0.6), d(0.01, 0.02, 0.03, 0.04, 0.05, 0.06); + TinyMatrix e, f(17.0, 48.3); + + a = b + c + d; + + a(TinyRange<0,1>(), TinyRange<0,2,2>()); + + a(TinyRange<0,1>(), TinyRange<0,2,2>()) + (TinyRange<0,0>(), TinyRange<0,1>()); + + e = f + a(TinyRange<0,1>(), TinyRange<0,2,2>()) + (TinyRange<0,0>(), TinyRange<0,1>()); +} +