PATCH for complex expressions in templates
Mark Mitchell
mmitchell@usa.net
Thu Mar 19 13:09:00 GMT 1998
Jason --
Here's a patch that fixes the following problems:
o Incorrect mangling of template functions like:
template <int I>
void f(vec<N - 1>);
o Failure to unify with some examples of such templates, such
as
template <int I>
void f(vec<N>, vec<N+1>);
o A mishandling of member template classes in finish_struct_1.
All regression tests are OK, plus the quite nasty code in the test
cases at the bottom of the patch now works.
Is this OK?
--
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available
1998-03-19 Mark Mitchell <mmitchell@usa.net>
* 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.
Thu Mar 19 11:10:47 1998 Mark Mitchell <mmitchell@usa.net>
* 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.
* 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.
Index: cplus-dem.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cplus-dem.c,v
retrieving revision 1.12
diff -c -p -r1.12 cplus-dem.c
*** cplus-dem.c 1998/03/19 00:09:47 1.12
--- cplus-dem.c 1998/03/19 19:02:38
*************** static const struct optable
*** 197,203 ****
{"min", "<?", 0}, /* old */
{"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
{"nop", "", 0}, /* old (for operator=) */
! {"rm", "->*", DMGL_ANSI} /* ansi */
};
--- 197,204 ----
{"min", "<?", 0}, /* old */
{"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
{"nop", "", 0}, /* old (for operator=) */
! {"rm", "->*", DMGL_ANSI}, /* ansi */
! {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */
};
*************** forget_types PARAMS ((struct work_stuff
*** 330,335 ****
--- 331,340 ----
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
*************** demangle_template_template_parm (work, m
*** 996,1001 ****
--- 1001,1270 ----
}
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;
const char **mangled;
*************** demangle_template (work, mangled, tname,
*** 1004,1021 ****
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;
--- 1273,1282 ----
*************** demangle_template (work, mangled, tname,
*** 1148,1160 ****
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);
/*
--- 1409,1415 ----
string* s;
/* otherwise, value parameter */
!
/* temp is initialized in do_type */
success = do_type (work, mangled, &temp);
/*
*************** demangle_template (work, mangled, tname,
*** 1180,1372 ****
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;
! (*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)
{
! 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)
{
int len = s->p - s->b;
--- 1435,1450 ----
else
s = tname;
! success = demangle_template_value_parm (work, mangled, s);
! if (!success)
{
! if (!is_type)
! string_delete (s);
! success = 0;
! break;
}
+
if (!is_type)
{
int len = s->p - s->b;
Index: cp/Make-lang.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Make-lang.in,v
retrieving revision 1.11
diff -c -p -r1.11 Make-lang.in
*** Make-lang.in 1998/03/18 10:52:00 1.11
--- Make-lang.in 1998/03/19 19:02:43
*************** cxxmain.o: cplus-dem.c demangle.h
*** 107,113 ****
$(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 $@ \
--- 107,112 ----
Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.28
diff -c -p -r1.28 class.c
*** class.c 1998/03/17 00:03:35 1.28
--- class.c 1998/03/19 19:02:59
*************** finish_struct_1 (t, warn_anon)
*** 3322,3328 ****
last_x = x;
! if (TREE_CODE (x) == TYPE_DECL)
continue;
/* If we've gotten this far, it's a data member, possibly static,
--- 3322,3329 ----
last_x = x;
! 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,
*************** instantiate_type (lhstype, rhs, complain
*** 5174,5181 ****
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)),
TYPE_ARG_TYPES (lhstype), explicit_targs, 1, 1);
if (i == 0)
{
--- 5175,5182 ----
tree t = make_scratch_vec (n);
int i;
i = type_unification
! (DECL_INNERMOST_TEMPLATE_PARMS (elem), t,
! TYPE_ARG_TYPES (TREE_TYPE (elem)),
TYPE_ARG_TYPES (lhstype), explicit_targs, 1, 1);
if (i == 0)
{
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.43
diff -c -p -r1.43 cp-tree.h
*** cp-tree.h 1998/03/18 10:51:54 1.43
--- cp-tree.h 1998/03/19 19:03:10
*************** extern tree instantiate_class_template
*** 2463,2469 ****
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));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
extern int more_specialized PROTO((tree, tree, tree));
--- 2463,2469 ----
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));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
extern int more_specialized PROTO((tree, tree, tree));
Index: cp/gxxint.texi
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/gxxint.texi,v
retrieving revision 1.7
diff -c -p -r1.7 gxxint.texi
*** gxxint.texi 1998/03/04 12:12:59 1.7
--- gxxint.texi 1998/03/19 19:03:17
*************** Indicates a C++ array type.
*** 1746,1751 ****
--- 1746,1754 ----
Encodes the C++ @code{bool} type,
and the Java @code{boolean} type.
+ @item B
+ Used for squangling.
+
@item c
Encodes the C++ @code{char} type, and the Java @code{byte} type.
*************** Encodes the C++ and Java @code{double} t
*** 1760,1765 ****
--- 1763,1771 ----
@item e
Indicates extra unknown arguments @code{...}.
+ @item E
+ Indicates the opening parenthesis of an expression.
+
@item f
Encodes the C++ and Java @code{float} types.
*************** Encodes the C++ and Java @code{int} type
*** 1775,1780 ****
--- 1781,1789 ----
@item J
Indicates a complex type.
+ @item K
+ Used for squangling.
+
@item l
Encodes the C++ @code{long} type.
*************** A modified for a @code{const} type or me
*** 1820,1825 ****
--- 1829,1837 ----
@item w
Encodes the C++ @code{wchar_t} type, and the Java @code{char} types.
+
+ @item W
+ Indicates the closing parenthesis of an expression.
@item x
Encodes the GNU C++ @code{long long} type, and the Java @code{long} type.
Index: cp/method.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/method.c,v
retrieving revision 1.35
diff -c -p -r1.35 method.c
*** method.c 1998/03/06 22:24:29 1.35
--- method.c 1998/03/19 19:03:33
*************** build_underscore_int (i)
*** 471,476 ****
--- 471,486 ----
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
*************** build_overload_int (value, in_template)
*** 479,491 ****
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);
return;
}
--- 489,571 ----
int in_template;
{
if (in_template && TREE_CODE (value) != INTEGER_CST)
! {
! if (TREE_CODE (value) == SCOPE_REF)
! {
! build_overload_scope_ref (value);
! return;
! }
!
! OB_PUTC ('E');
! numeric_output_need_bar = 0;
!
! switch (TREE_CODE_CLASS (TREE_CODE (value)))
! {
! case '1':
! case '2':
! case 'e':
! {
! int i;
! int operands;
! tree id;
! char* name;
!
! if (TREE_CODE_CLASS (TREE_CODE (value)) == 1)
! operands = 1;
! else if (TREE_CODE_CLASS (TREE_CODE (value)) == 2)
! operands = 2;
! else
! operands = tree_code_length[(int) TREE_CODE (value)];
!
! if (TREE_CODE (value) == SIZEOF_EXPR)
! name = "__sz";
! else
! {
! 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;
!
! if (i != 0)
! /* Skip the leading underscores. */
! OB_PUTCP (name + 2);
!
! operand = TREE_OPERAND (value, i);
!
! if (TREE_CODE_CLASS (TREE_CODE (operand)) == 't')
! /* We can get here with sizeof, e.g.:
!
! template <class T> void f(A<sizeof(T)>); */
! process_overload_item (operand, 0);
! else
! build_overload_value (TREE_TYPE (operand),
! operand,
! in_template);
! }
! }
! break;
!
! default:
! {
! /* 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);
! }
! break;
! }
!
! OB_PUTC ('W');
! numeric_output_need_bar = 0;
return;
}
*************** build_overload_int (value, in_template)
*** 497,508 ****
--- 577,590 ----
{
/* 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;
}
*************** build_overload_value (type, value, in_te
*** 531,538 ****
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 (numeric_output_need_bar)
{
--- 613,623 ----
while (TREE_CODE (value) == NON_LVALUE_EXPR
|| TREE_CODE (value) == NOP_EXPR)
value = TREE_OPERAND (value, 0);
!
! 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)
{
*************** build_overload_value (type, value, in_te
*** 569,575 ****
case BOOLEAN_TYPE:
{
build_overload_int (value, in_template);
- numeric_output_need_bar = 1;
return;
}
case REAL_TYPE:
--- 654,659 ----
*************** build_overload_value (type, value, in_te
*** 672,678 ****
{
OB_PUTC ('i');
build_overload_int (a3, in_template);
- numeric_output_need_bar = 1;
return;
}
}
--- 756,761 ----
*************** build_overload_value (type, value, in_te
*** 683,689 ****
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)
--- 766,771 ----
*************** build_overload_value (type, value, in_te
*** 707,719 ****
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;
! }
else
my_friendly_abort (71);
break; /* not really needed */
--- 789,795 ----
return;
}
else if (TREE_CODE (value) == SCOPE_REF)
! build_overload_scope_ref (value);
else
my_friendly_abort (71);
break; /* not really needed */
*************** build_qualified_name (decl)
*** 865,871 ****
if (TREE_CODE (decl) == TYPE_DECL
&& DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling)
{
! OB_PUTID (DECL_ASSEMBLER_NAME (decl));
return;
}
--- 941,950 ----
if (TREE_CODE (decl) == TYPE_DECL
&& DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling)
{
! tree id = DECL_ASSEMBLER_NAME (decl);
! OB_PUTID (id);
! if (isdigit (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1]))
! numeric_output_need_bar = 1;
return;
}
*************** build_qualified_name (decl)
*** 907,917 ****
if (i > 1)
{
OB_PUTC ('Q');
! if (i > 9)
! OB_PUTC ('_');
! icat (i);
! if (i > 9)
! OB_PUTC ('_');
numeric_output_need_bar = 0;
}
build_overload_nested_name (decl);
--- 986,992 ----
if (i > 1)
{
OB_PUTC ('Q');
! build_underscore_int (i);
numeric_output_need_bar = 0;
}
build_overload_nested_name (decl);
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.98
diff -c -p -r1.98 pt.c
*** pt.c 1998/03/19 09:08:52 1.98
--- pt.c 1998/03/19 19:03:50
*************** static tree saved_trees;
*** 69,75 ****
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
! static int unify PROTO((tree, tree *, int, tree, tree, int));
static void add_pending_template PROTO((tree));
static int push_tinst_level PROTO((tree));
static tree classtype_mangled_name PROTO((tree));
--- 69,75 ----
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
! 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));
*************** static tree get_class_bindings PROTO((tr
*** 81,88 ****
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));
static void note_template_header PROTO((int));
static tree maybe_fold_nontype_arg PROTO((tree));
static tree convert_nontype_argument PROTO((tree, tree));
--- 81,88 ----
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 void note_template_header PROTO((int));
static tree maybe_fold_nontype_arg PROTO((tree));
static tree convert_nontype_argument PROTO((tree, tree));
*************** determine_specialization (template_id, d
*** 621,627 ****
/* 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),
NULL_TREE,
NULL_TREE,
targs_in,
--- 621,627 ----
/* We allow incomplete unification here, because we are going to
check all the functions. */
i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
! targs,
NULL_TREE,
NULL_TREE,
targs_in,
*************** tsubst (t, args, in_decl)
*** 3527,3533 ****
{
tree arg = NULL_TREE;
! if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
{
levels = TREE_VEC_LENGTH (args);
if (level <= levels)
--- 3531,3538 ----
{
tree arg = NULL_TREE;
! 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)
*************** tsubst (t, args, in_decl)
*** 3580,3585 ****
--- 3585,3596 ----
}
}
+ 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);
*************** fn_type_unification (fn, explicit_targs,
*** 5017,5023 ****
fn_arg_types);
i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
! &TREE_VEC_ELT (targs, 0),
fn_arg_types,
decl_arg_types,
explicit_targs,
--- 5028,5034 ----
fn_arg_types);
i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
! targs,
fn_arg_types,
decl_arg_types,
explicit_targs,
*************** fn_type_unification (fn, explicit_targs,
*** 5053,5067 ****
int
type_unification (tparms, targs, parms, args, targs_in,
strict, allow_incomplete)
! tree tparms, *targs, parms, args, targs_in;
int strict, allow_incomplete;
{
int ntparms = TREE_VEC_LENGTH (tparms);
tree arg;
int i;
int r;
! bzero ((char *) targs, sizeof (tree) * ntparms);
if (targs_in != NULL_TREE)
{
--- 5064,5080 ----
int
type_unification (tparms, targs, parms, args, targs_in,
strict, allow_incomplete)
! 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;
! for (i = 0; i < ntparms; i++)
! TREE_VEC_ELT (targs, i) = NULL_TREE;
if (targs_in != NULL_TREE)
{
*************** type_unification (tparms, targs, parms,
*** 5072,5105 ****
if (arg_vec == error_mark_node)
return 1;
for (i = 0;
i < TREE_VEC_LENGTH (arg_vec)
! && 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));
}
!
! r = type_unification_real (tparms, targs, parms, args, 0,
! strict, allow_incomplete);
! 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);
return r;
}
static int
type_unification_real (tparms, targs, parms, args, subr,
! strict, allow_incomplete)
! tree tparms, *targs, parms, args;
int subr, strict, allow_incomplete;
{
tree parm, arg;
int i;
--- 5085,5122 ----
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;
++i)
! {
! TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (arg_vec, i);
! /* Let unify know that this argument was explicit. */
! explicit_mask [i] = 1;
! }
}
! else
! explicit_mask = 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, explicit_mask)
! tree tparms, targs, parms, args;
int subr, strict, allow_incomplete;
+ int* explicit_mask;
{
tree parm, arg;
int i;
*************** type_unification_real (tparms, targs, pa
*** 5173,5184 ****
&& TREE_CODE (TREE_VALUE (arg)) == TEMPLATE_DECL)
{
int ntparms;
! tree *targs;
/* Have to back unify here */
arg = TREE_VALUE (arg);
ntparms = DECL_NTPARMS (arg);
! targs = (tree *) alloca (sizeof (tree) * ntparms);
parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE);
return
type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
--- 5190,5201 ----
&& TREE_CODE (TREE_VALUE (arg)) == TEMPLATE_DECL)
{
int ntparms;
! tree targs;
/* Have to back unify here */
arg = TREE_VALUE (arg);
ntparms = DECL_NTPARMS (arg);
! targs = make_scratch_vec (ntparms);
parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE);
return
type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
*************** type_unification_real (tparms, targs, pa
*** 5210,5216 ****
arg = TYPE_MAIN_VARIANT (arg);
}
! switch (unify (tparms, targs, ntparms, parm, arg, strict))
{
case 0:
break;
--- 5227,5234 ----
arg = TYPE_MAIN_VARIANT (arg);
}
! switch (unify (tparms, targs, ntparms, parm, arg, strict,
! explicit_mask))
{
case 0:
break;
*************** type_unification_real (tparms, targs, pa
*** 5229,5235 ****
return 1;
if (!subr)
for (i = 0; i < ntparms; i++)
! if (!targs[i])
{
if (!allow_incomplete)
error ("incomplete type unification");
--- 5247,5253 ----
return 1;
if (!subr)
for (i = 0; i < ntparms; i++)
! if (TREE_VEC_ELT (targs, i) == NULL_TREE)
{
if (!allow_incomplete)
error ("incomplete type unification");
*************** type_unification_real (tparms, targs, pa
*** 5241,5251 ****
/* Tail recursion is your friend. */
static int
! unify (tparms, targs, ntparms, parm, arg, strict)
! tree tparms, *targs, parm, arg;
int ntparms, strict;
{
int idx;
/* 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
--- 5259,5271 ----
/* Tail recursion is your friend. */
static int
! 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
*************** unify (tparms, targs, ntparms, parm, arg
*** 5278,5289 ****
case TEMPLATE_TYPE_PARM:
idx = TEMPLATE_TYPE_IDX (parm);
/* 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)
/* 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. */
--- 5298,5310 ----
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 && 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. */
*************** unify (tparms, targs, ntparms, parm, arg
*** 5308,5331 ****
}
#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))
return 0;
! else if (targs[idx])
return 1;
! targs[idx] = arg;
return 0;
case TEMPLATE_TEMPLATE_PARM:
idx = TEMPLATE_TYPE_IDX (parm);
/* 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)
/* 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. */
--- 5329,5351 ----
}
#endif
/* Simple cases: Value already set, does match or doesn't. */
! if (targ == arg || (targ && explicit_mask && explicit_mask[idx]))
return 0;
! else if (targ)
return 1;
! 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 && 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. */
*************** unify (tparms, targs, ntparms, parm, arg
*** 5371,5377 ****
/* This argument can be deduced. */
if (unify (tparms, targs, ntparms, t,
! TREE_VEC_ELT (argvec, i), strict))
return 1;
}
}
--- 5391,5397 ----
/* This argument can be deduced. */
if (unify (tparms, targs, ntparms, t,
! TREE_VEC_ELT (argvec, i), strict, explicit_mask))
return 1;
}
}
*************** unify (tparms, targs, ntparms, parm, arg
*** 5379,5399 ****
}
/* 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))
return 0;
! else if (targs[idx])
return 1;
! targs[idx] = arg;
return 0;
case TEMPLATE_PARM_INDEX:
idx = TEMPLATE_PARM_IDX (parm);
! if (targs[idx])
{
! int i = cp_tree_equal (targs[idx], arg);
if (i == 1)
return 0;
else if (i == 0)
--- 5399,5417 ----
}
/* Simple cases: Value already set, does match or doesn't. */
! if (targ == arg || (targ && explicit_mask && explicit_mask[idx]))
return 0;
! else if (targ)
return 1;
! TREE_VEC_ELT (targs, idx) = arg;
return 0;
case TEMPLATE_PARM_INDEX:
idx = TEMPLATE_PARM_IDX (parm);
! targ = TREE_VEC_ELT (targs, idx);
! if (targ)
{
! int i = cp_tree_equal (targ, arg);
if (i == 1)
return 0;
else if (i == 0)
*************** unify (tparms, targs, ntparms, parm, arg
*** 5402,5425 ****
my_friendly_abort (42);
}
! 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);
if (TREE_CODE (arg) != POINTER_TYPE)
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
! strict);
case REFERENCE_TYPE:
if (TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg,
! strict);
case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE)
--- 5420,5443 ----
my_friendly_abort (42);
}
! 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, explicit_mask);
if (TREE_CODE (arg) != POINTER_TYPE)
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
! 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, explicit_mask);
case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE)
*************** unify (tparms, targs, ntparms, parm, arg
*** 5429,5438 ****
return 1;
if (TYPE_DOMAIN (parm) != NULL_TREE
&& unify (tparms, targs, ntparms, TYPE_DOMAIN (parm),
! TYPE_DOMAIN (arg), strict) != 0)
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
! strict);
case REAL_TYPE:
case COMPLEX_TYPE:
--- 5447,5456 ----
return 1;
if (TYPE_DOMAIN (parm) != NULL_TREE
&& unify (tparms, targs, ntparms, TYPE_DOMAIN (parm),
! TYPE_DOMAIN (arg), strict, explicit_mask) != 0)
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
! strict, explicit_mask);
case REAL_TYPE:
case COMPLEX_TYPE:
*************** unify (tparms, targs, ntparms, parm, arg
*** 5446,5456 ****
{
if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
&& unify (tparms, targs, ntparms, TYPE_MIN_VALUE (parm),
! TYPE_MIN_VALUE (arg), strict))
return 1;
if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
&& unify (tparms, targs, ntparms, TYPE_MAX_VALUE (parm),
! TYPE_MAX_VALUE (arg), strict))
return 1;
}
else if (TREE_CODE (parm) == REAL_TYPE
--- 5464,5474 ----
{
if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
&& unify (tparms, targs, ntparms, TYPE_MIN_VALUE (parm),
! 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, explicit_mask))
return 1;
}
else if (TREE_CODE (parm) == REAL_TYPE
*************** unify (tparms, targs, ntparms, parm, arg
*** 5471,5486 ****
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;
--- 5489,5494 ----
*************** unify (tparms, targs, ntparms, parm, arg
*** 5491,5497 ****
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))
return 1;
return 0;
}
--- 5499,5505 ----
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, explicit_mask))
return 1;
return 0;
}
*************** unify (tparms, targs, ntparms, parm, arg
*** 5499,5505 ****
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm))
return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm),
! arg, strict);
/* Allow trivial conversions. */
if (TREE_CODE (arg) != RECORD_TYPE
--- 5507,5513 ----
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm))
return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm),
! arg, strict, explicit_mask);
/* Allow trivial conversions. */
if (TREE_CODE (arg) != RECORD_TYPE
*************** unify (tparms, targs, ntparms, parm, arg
*** 5520,5526 ****
return 1;
return unify (tparms, targs, ntparms, CLASSTYPE_TI_ARGS (parm),
! CLASSTYPE_TI_ARGS (t), strict);
}
else if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg))
return 1;
--- 5528,5534 ----
return 1;
return unify (tparms, targs, ntparms, CLASSTYPE_TI_ARGS (parm),
! CLASSTYPE_TI_ARGS (t), strict, explicit_mask);
}
else if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg))
return 1;
*************** unify (tparms, targs, ntparms, parm, arg
*** 5536,5555 ****
return 1;
check_args:
if (unify (tparms, targs, ntparms, TREE_TYPE (parm),
! TREE_TYPE (arg), strict))
return 1;
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
TYPE_ARG_TYPES (arg), 1,
! strict, 0);
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))
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm),
! TREE_TYPE (arg), strict);
case CONST_DECL:
if (arg != decl_constant_value (parm))
--- 5544,5563 ----
return 1;
check_args:
if (unify (tparms, targs, ntparms, TREE_TYPE (parm),
! 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, 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, explicit_mask))
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm),
! TREE_TYPE (arg), strict, explicit_mask);
case CONST_DECL:
if (arg != decl_constant_value (parm))
*************** unify (tparms, targs, ntparms, parm, arg
*** 5561,5568 ****
return 1;
default:
! sorry ("use of `%s' in template type unification",
! tree_code_name [(int) TREE_CODE (parm)]);
return 1;
}
}
--- 5569,5624 ----
return 1;
default:
! if (TREE_CODE_CLASS (TREE_CODE (parm)) == 'e'
! || TREE_CODE_CLASS (TREE_CODE (parm)) == '1'
! || TREE_CODE_CLASS (TREE_CODE (parm)) == '2')
! {
! 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 <int N> 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 (TREE_CODE_CLASS (tc) != 'e'
! && TREE_CODE_CLASS (tc) != '1'
! && TREE_CODE_CLASS (tc) != '2')
! /* 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;
}
}
*************** get_class_bindings (tparms, parms, args,
*** 5720,5727 ****
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))
{
case 0:
break;
--- 5776,5784 ----
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
! switch (unify (tparms, vec, ntparms,
! TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i),
! 1, 0))
{
case 0:
break;
Index: testsuite/g++.old-deja/g++.pt/expr1.C
===================================================================
RCS file: expr1.C
diff -N expr1.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- expr1.C Thu Mar 19 11:04:11 1998
***************
*** 0 ****
--- 1,33 ----
+ template <int n> class vec {
+ double x[n];
+
+ public:
+ vec() {
+ for (int i=0; i<n-1; ++i) x[i]=0;
+ }
+
+ vec(const vec<n>& v) {
+ for (int i=0; i<n; ++i) x[i]=v(i);
+ }
+
+ vec(const vec<n-1>& v, const double& y) {
+ for (int i=0; i<n-1; ++i) x[i]=v(i);
+ x[n-1]=y;
+ }
+
+ inline double operator()(const int i) const {
+ return x[i];
+ }
+ };
+
+
+ template <int n> vec<n + 1>& operator,(const vec<n>& v, const double& y) {
+ return *(new vec<n + 1>(v, y));
+ }
+
+
+ int main() {
+ vec<4> v;
+ vec<5> w;
+ w=(v,3.);
+ }
Index: testsuite/g++.old-deja/g++.pt/expr2.C
===================================================================
RCS file: expr2.C
diff -N expr2.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- expr2.C Thu Mar 19 11:04:11 1998
***************
*** 0 ****
--- 1,12 ----
+ // Build don't link:
+
+ template <int I>
+ struct S {};
+
+ template <int J>
+ void foo(S<J + 2>);
+
+ void bar()
+ {
+ foo(S<3>()); // ERROR - no way to deduce J from this.
+ }
Index: testsuite/g++.old-deja/g++.pt/expr3.C
===================================================================
RCS file: expr3.C
diff -N expr3.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- expr3.C Thu Mar 19 11:04:11 1998
***************
*** 0 ****
--- 1,20 ----
+ // Build don't link:
+
+ template <int I>
+ struct S {};
+
+ template <int J>
+ void foo(S<J - 1>);
+
+ template <class T>
+ void baz(S<sizeof(T)>);
+
+ template <int J>
+ void fun(S<J>, S<J * 2>);
+
+ void bar()
+ {
+ foo<5>(S<4>()); // OK - 4 is 5 - 1.
+ baz<int>(S<sizeof(int)>()); // OK
+ fun(S<4>(), S<8>()); // OK - deduce J from first argument.
+ }
Index: testsuite/g++.old-deja/g++.pt/expr4.C
===================================================================
RCS file: expr4.C
diff -N expr4.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- expr4.C Thu Mar 19 11:04:11 1998
***************
*** 0 ****
--- 1,373 ----
+ template<class View, class W>
+ class TinyContainer {
+ public:
+
+ typedef W T_Wrapped;
+
+ TinyContainer() { }
+ TinyContainer(View data) : m_data(data) { }
+
+ T_Wrapped &unwrap()
+ {
+ return *static_cast<T_Wrapped *>(this);
+ }
+ const T_Wrapped &unwrap() const
+ {
+ return *static_cast<const T_Wrapped *>(this);
+ }
+
+ protected:
+
+ mutable View m_data;
+ };
+
+ template<class Op, class Left, class Right>
+ class TinyBinaryExpr :
+ public TinyContainer< Op, TinyBinaryExpr<Op, Left, Right> > {
+ public:
+
+ typedef typename Left::T_Return T_Return;
+ typedef TinyBinaryExpr<Op, Left, Right> T_Expr;
+
+ T_Expr makeExpr() const { return *this; }
+
+ TinyBinaryExpr(const Op &op, const Left &left, const Right &right)
+ : TinyContainer< Op, TinyBinaryExpr<Op, Left, Right> >(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<class T1, class T2>
+ static T1 apply(const T1 &l, const T2 &r)
+ {
+ return l + r;
+ }
+
+ };
+
+ template<class V1, class T1, class V2, class T2>
+ inline TinyBinaryExpr<OpAdd, typename T1::T_Expr, typename T2::T_Expr>
+ operator+(const TinyContainer<V1,T1>& l, const TinyContainer<V2,T2>& r)
+ {
+ typedef TinyBinaryExpr<OpAdd, typename T1::T_Expr, typename T2::T_Expr> ret;
+ return ret(l.unwrap().makeExpr(), r.unwrap().makeExpr());
+ }
+
+
+ template<class Op, class T1, class T2, class Functor>
+ inline
+ typename T1::T_Return
+ for_each(const TinyBinaryExpr<Op,T1,T2>& node, Functor f)
+ {
+ return Op::apply(for_each(node.left(),f), for_each(node.right(),f));
+ }
+
+ template<class T, unsigned Nrows, unsigned Ncols, unsigned S1, unsigned S2>
+ class DenseDataView
+ : public TinyContainer< T*, DenseDataView<T, Nrows, Ncols, S1, S2> > {
+ public:
+
+ typedef T T_Return;
+ typedef DenseDataView<T, Nrows, Ncols, S1, S2> 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<T, Nrows, Ncols, S1, S2> >(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<unsigned I, unsigned J>
+ struct Offset {
+
+ static T &apply(DenseDataView<T, Nrows, Ncols, S1, S2> &d)
+ {
+ return d.m_data[S1 * I + S2 * J];
+ }
+
+ static T constApply(const DenseDataView<T, Nrows, Ncols, S1, S2> &d)
+ {
+ return d.m_data[S1 * I + S2 * J];
+ }
+
+ };
+
+ };
+
+ template<unsigned I, unsigned J>
+ struct Eval2 { };
+
+ template<class T, unsigned Nrows, unsigned Ncols, unsigned S1, unsigned S2,
+ unsigned I, unsigned J>
+ inline T
+ for_each(const DenseDataView<T, Nrows, Ncols, S1, S2> &d,
+ const Eval2<I,J> &e)
+ {
+ return d.offset(I, J);
+ }
+
+ template<class T, unsigned Nrows, unsigned Ncols>
+ class DenseData
+ : public TinyContainer< T[Nrows * Ncols], DenseData<T, Nrows, Ncols> > {
+ public:
+
+ typedef T T_Return;
+ typedef DenseDataView<T, Nrows, Ncols, 1, Nrows> 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<unsigned I, unsigned J>
+ struct Offset {
+
+ static T &apply(DenseData<T, Nrows, Ncols> &d)
+ {
+ return d.m_data[I + Nrows * J];
+ }
+
+ static T constApply(const DenseData<T, Nrows, Ncols> &d)
+ {
+ return d.m_data[I + Nrows * J];
+ }
+
+ };
+
+ };
+
+ template<class T, unsigned Nrc>
+ 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<unsigned I, unsigned J>
+ struct Offset {
+
+ static T &apply(DiagonalData<T,Nrc> &d)
+ {
+ assert(I == J);
+ return d.m_data[I];
+ }
+
+ static T constApply(const DiagonalData<T,Nrc> &d)
+ {
+ return (I == J) ? d.m_data[I] : T(0);
+ }
+
+ };
+
+ private:
+
+ T m_data[Nrc];
+ };
+
+ template<unsigned I, unsigned J, unsigned C1>
+ struct InnerLoop {
+
+ template<class LHS, class RHS>
+ static inline void eval(LHS &l, const RHS &r)
+ {
+ l.offset(I,J) = for_each(r, Eval2<I,J>());
+ InnerLoop<I + 1, J, C1 - 1>::eval(l, r);
+ }
+
+ };
+
+ template<unsigned I, unsigned J>
+ struct InnerLoop<I, J, 0> {
+
+ template<class LHS, class RHS>
+ static inline void eval(LHS &, const RHS &) { }
+
+ };
+
+ template<unsigned I, unsigned J, unsigned C1, unsigned C2>
+ struct Loop2 {
+
+ template<class LHS, class RHS>
+ static inline void eval(LHS &l, const RHS &r)
+ {
+ InnerLoop<I, J, C1>::eval(l, r);
+ Loop2<I, J + 1, C1, C2 - 1>::eval(l, r);
+ }
+ };
+
+ template<unsigned I, unsigned J, unsigned C1>
+ struct Loop2<I, J, C1, 0> {
+
+ template<class LHS, class RHS>
+ static inline void eval(LHS &l, const RHS &r) { }
+
+ };
+
+
+ template<unsigned Begin, unsigned End, unsigned Stride = 1>
+ 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<class Range1, class Range2, class Data>
+ struct Merge { };
+
+ template<class Range1, class Range2, class T, unsigned Nrows, unsigned Ncols>
+ struct Merge<Range1, Range2, DenseData<T, Nrows, Ncols> >
+ {
+ static const unsigned s2 = Nrows * Range2::s;
+ typedef
+ DenseDataView<T, Range1::n, Range2::n, Range1::s, s2> type;
+ };
+
+ template<class Range1, class Range2, class T, unsigned Nrows, unsigned Ncols,
+ unsigned S1, unsigned S2>
+ struct Merge<Range1, Range2, DenseDataView<T, Nrows, Ncols, S1, S2> >
+ {
+ static const unsigned s1 = S1 * Range1::s;
+ static const unsigned s2 = S2 * Range2::s;
+
+ typedef
+ DenseDataView<T, Range1::n, Range2::n, s1, s2> type;
+ };
+
+ template<class T, unsigned Nrows, unsigned Ncols,
+ class Data = DenseData<T, Nrows, Ncols> >
+ class TinyMatrix :
+ public TinyContainer< Data, TinyMatrix<T, Nrows, Ncols, Data> > {
+ public:
+
+ typedef T T_Return;
+ typedef typename Data::T_Expr T_Expr;
+ typedef TinyContainer< Data, TinyMatrix<T, Nrows, Ncols, Data> > 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<unsigned B1, unsigned E1, unsigned S1,
+ unsigned B2, unsigned E2, unsigned S2>
+ TinyMatrix<T, TinyRange<B1, E1, S1>::n,
+ TinyRange<B2, E2, S2>::n,
+ typename
+ Merge< TinyRange<B1, E1, S1>, TinyRange<B2, E2, S2>, Data>::type>
+ operator()(const TinyRange<B1, E1, S1> &r1, const TinyRange<B2, E2, S2> &r2)
+ {
+ typedef typename
+ Merge< TinyRange<B1, E1, S1>, TinyRange<B2, E2, S2>, Data>::type
+ T_DataType;
+ typedef TinyMatrix<T, TinyRange<B1, E1, S1>::n,
+ TinyRange<B2, E2, S2>::n, T_DataType> T_RetType;
+
+ return T_RetType(T_DataType(m_data.beginLoc(B1, B2)));
+ }
+
+ template<class V1, class T1>
+ void operator=(const TinyContainer<V1, T1> &rhs)
+ {
+ Loop2<0, 0, Nrows, Ncols>::eval(m_data, rhs.unwrap().makeExpr());
+ }
+
+ };
+
+
+ int main()
+ {
+ TinyMatrix<double, 2, 3> 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<double, 1, 2> 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>());
+ }
+
cvs server: Diffing testsuite/g++.old-deja/g++.rfg
cvs server: Diffing testsuite/g++.old-deja/g++.robertl
cvs server: Diffing testsuite/g77.f-torture
cvs server: Diffing testsuite/g77.f-torture/compile
cvs server: Diffing testsuite/g77.f-torture/execute
cvs server: Diffing testsuite/gcc.c-torture
cvs server: Diffing testsuite/gcc.c-torture/code_quality
cvs server: Diffing testsuite/gcc.c-torture/compat
cvs server: Diffing testsuite/gcc.c-torture/compile
cvs server: Diffing testsuite/gcc.c-torture/execute
cvs server: Diffing testsuite/gcc.c-torture/execute/ieee
cvs server: Diffing testsuite/gcc.c-torture/noncompile
cvs server: Diffing testsuite/gcc.c-torture/special
cvs server: Diffing testsuite/gcc.c-torture/unsorted
cvs server: Diffing testsuite/gcc.dg
cvs server: Diffing testsuite/gcc.failure
cvs server: Diffing testsuite/gcc.misc-tests
cvs server: Diffing testsuite/lib
More information about the Gcc-bugs
mailing list