From 37f6b6bfd2e1c127fa597f4949f62ecd12fcd187 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sun, 28 Sep 1997 19:59:54 +0000 Subject: [PATCH] cplus-dem.c (demangle_template): Add new parameter. Sun Sep 28 12:00:52 1997 Mark Mitchell * cplus-dem.c (demangle_template): Add new parameter. Handle new template-function mangling. (consume_count_with_underscores): New function. (demangle_signature): Handle new name-mangling scheme. From-SVN: r15780 --- gcc/ChangeLog | 7 ++ gcc/cplus-dem.c | 297 +++++++++++++++++++++++++++++++++++++++--------- gcc/invoke.texi | 32 +++++- 3 files changed, 282 insertions(+), 54 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b326a90796b..34b41b5aa10 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +Sun Sep 28 12:00:52 1997 Mark Mitchell + + * cplus-dem.c (demangle_template): Add new parameter. Handle new + template-function mangling. + (consume_count_with_underscores): New function. + (demangle_signature): Handle new name-mangling scheme. + Sun Sep 28 01:55:04 1997 Philippe De Muyter * flow.c (print_rtl_with_bb): Cast alloca return values for variables diff --git a/gcc/cplus-dem.c b/gcc/cplus-dem.c index 5794a5bb869..055ab0818e5 100644 --- a/gcc/cplus-dem.c +++ b/gcc/cplus-dem.c @@ -102,6 +102,8 @@ struct work_stuff int destructor; int static_type; /* A static member function */ int const_type; /* A const member function */ + char **tmpl_argvec; /* Template function arguments. */ + int ntmpl_args; /* The number of template function arguments. */ }; #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) @@ -222,7 +224,7 @@ demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *)) static int demangle_template PARAMS ((struct work_stuff *work, const char **, string *, - string *)); + string *, int)); static int arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **, @@ -294,6 +296,9 @@ get_count PARAMS ((const char **, int *)); static int consume_count PARAMS ((const char **)); +static int +consume_count_with_underscores PARAMS ((const char**)); + static int demangle_args PARAMS ((struct work_stuff *, const char **, string *)); @@ -336,6 +341,42 @@ consume_count (type) return (count); } + +/* Like consume_count, but for counts that are preceeded and followed + by '_' if they are greater than 10. Also, -1 is returned for + failure, since 0 can be a valid value. */ + +static int +consume_count_with_underscores (mangled) + const char **mangled; +{ + int idx; + + if (**mangled == '_') + { + (*mangled)++; + if (!isdigit (**mangled)) + return -1; + + idx = consume_count (mangled); + if (**mangled != '_') + /* The trailing underscore was missing. */ + return -1; + + (*mangled)++; + } + else + { + if (**mangled < '0' || **mangled > '9') + return -1; + + idx = **mangled - '0'; + (*mangled)++; + } + + return idx; +} + int cplus_demangle_opname (opname, result, options) const char *opname; @@ -580,7 +621,17 @@ mop_up (work, declp, success) { free ((char *) work -> typevec); } - + if (work->tmpl_argvec) + { + int i; + + for (i = 0; i < work->ntmpl_args; i++) + if (work->tmpl_argvec[i]) + free ((char*) work->tmpl_argvec[i]); + + free ((char*) work->tmpl_argvec); + } + /* If demangling was successful, ensure that the demangled string is null terminated and return it. Otherwise, free the demangling decl. */ @@ -635,6 +686,7 @@ demangle_signature (work, mangled, declp) int success = 1; int func_done = 0; int expect_func = 0; + int expect_return_type = 0; const char *oldmangled = NULL; string trawname; string tname; @@ -726,7 +778,7 @@ demangle_signature (work, mangled, declp) { oldmangled = *mangled; } - success = demangle_template (work, mangled, &tname, &trawname); + success = demangle_template (work, mangled, &tname, &trawname, 1); if (success) { remember_type (work, oldmangled, *mangled - oldmangled); @@ -751,14 +803,42 @@ demangle_signature (work, mangled, declp) break; case '_': - /* At the outermost level, we cannot have a return type specified, - so if we run into another '_' at this point we are dealing with - a mangled name that is either bogus, or has been mangled by - some algorithm we don't know how to deal with. So just - reject the entire demangling. */ - success = 0; + if (GNU_DEMANGLING && expect_return_type) + { + /* Read the return type. */ + string return_type; + string_init (&return_type); + + (*mangled)++; + success = do_type (work, mangled, &return_type); + APPEND_BLANK (&return_type); + + string_prepends (declp, &return_type); + string_delete (&return_type); + break; + } + else + /* At the outermost level, we cannot have a return type specified, + so if we run into another '_' at this point we are dealing with + a mangled name that is either bogus, or has been mangled by + some algorithm we don't know how to deal with. So just + reject the entire demangling. */ + success = 0; break; + case 'H': + if (GNU_DEMANGLING) + { + /* A G++ template function. Read the template arguments. */ + success = demangle_template (work, mangled, declp, 0, 0); + expect_return_type = 1; + (*mangled)++; + break; + } + else + /* fall through */ + ; + default: if (AUTO_DEMANGLING || GNU_DEMANGLING) { @@ -785,6 +865,10 @@ demangle_signature (work, mangled, declp) { func_done = 1; success = demangle_args (work, mangled, declp); + /* Since template include the mangling of their return types, + we must set expect_func to 0 so that we don't try do + demangle more arguments the next time we get here. */ + expect_func = 0; } } } @@ -838,11 +922,12 @@ demangle_method_args (work, mangled, declp) #endif static int -demangle_template (work, mangled, tname, trawname) +demangle_template (work, mangled, tname, trawname, is_type) struct work_stuff *work; const char **mangled; string *tname; string *trawname; + int is_type; { int i; int is_pointer; @@ -857,31 +942,43 @@ demangle_template (work, mangled, tname, trawname) const char *old_p; const char *start; int symbol_len; - int is_java_array; + int is_java_array = 0; string temp; (*mangled)++; - start = *mangled; - /* get template name */ - if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r) + if (is_type) { - return (0); - } - if (trawname) - string_appendn (trawname, *mangled, r); - is_java_array = (work -> options & DMGL_JAVA) - && strncmp (*mangled, "JArray1Z", 8) == 0; - if (! is_java_array) - { - string_appendn (tname, *mangled, r); - string_append (tname, "<"); + start = *mangled; + /* get template name */ + if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r) + { + return (0); + } + if (trawname) + string_appendn (trawname, *mangled, r); + is_java_array = (work -> options & DMGL_JAVA) + && strncmp (*mangled, "JArray1Z", 8) == 0; + if (! is_java_array) + { + string_appendn (tname, *mangled, r); + } + *mangled += r; } - *mangled += r; + if (!is_java_array) + string_append (tname, "<"); /* get size of template parameter list */ if (!get_count (mangled, &r)) { return (0); } + if (!is_type) + { + /* Create an array for saving the template argument values. */ + work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *)); + work->ntmpl_args = r; + for (i = 0; i < r; i++) + work->tmpl_argvec[i] = 0; + } for (i = 0; i < r; i++) { if (need_comma) @@ -897,6 +994,15 @@ demangle_template (work, mangled, tname, trawname) if (success) { string_appends (tname, &temp); + + if (!is_type) + { + /* Save the template argument. */ + int len = temp.p - temp.b; + work->tmpl_argvec[i] = xmalloc (len + 1); + memcpy (work->tmpl_argvec[i], temp.b, len); + work->tmpl_argvec[i][len] = '\0'; + } } string_delete(&temp); if (!success) @@ -906,6 +1012,9 @@ demangle_template (work, mangled, tname, trawname) } else { + string param; + string* s; + /* otherwise, value parameter */ old_p = *mangled; is_pointer = 0; @@ -919,7 +1028,7 @@ demangle_template (work, mangled, tname, trawname) /* if (success) { - string_appends (tname, &temp); + string_appends (s, &temp); } */ string_delete(&temp); @@ -928,8 +1037,17 @@ demangle_template (work, mangled, tname, trawname) break; } /* - string_append (tname, "="); + string_append (s, "="); */ + + if (!is_type) + { + s = ¶m; + string_init (s); + } + else + s = tname; + while (*old_p && !done) { switch (*old_p) @@ -983,16 +1101,41 @@ demangle_template (work, mangled, tname, trawname) done = is_integral = 1; } } - if (is_integral) + 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 (tname, "-", 1); + string_appendn (s, "-", 1); (*mangled)++; } while (isdigit (**mangled)) { - string_appendn (tname, *mangled, 1); + string_appendn (s, *mangled, 1); (*mangled)++; } } @@ -1002,28 +1145,30 @@ demangle_template (work, mangled, tname, trawname) int val; if (**mangled == 'm') { - string_appendn (tname, "-", 1); + string_appendn (s, "-", 1); (*mangled)++; } - string_appendn (tname, "'", 1); + 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 (tname, &tmp[0], 1); - string_appendn (tname, "'", 1); + string_appendn (s, &tmp[0], 1); + string_appendn (s, "'", 1); } else if (is_bool) { int val = consume_count (mangled); if (val == 0) - string_appendn (tname, "false", 5); + string_appendn (s, "false", 5); else if (val == 1) - string_appendn (tname, "true", 4); + string_appendn (s, "true", 4); else success = 0; } @@ -1031,31 +1176,31 @@ demangle_template (work, mangled, tname, trawname) { if (**mangled == 'm') { - string_appendn (tname, "-", 1); + string_appendn (s, "-", 1); (*mangled)++; } while (isdigit (**mangled)) { - string_appendn (tname, *mangled, 1); + string_appendn (s, *mangled, 1); (*mangled)++; } if (**mangled == '.') /* fraction */ { - string_appendn (tname, ".", 1); + string_appendn (s, ".", 1); (*mangled)++; while (isdigit (**mangled)) { - string_appendn (tname, *mangled, 1); + string_appendn (s, *mangled, 1); (*mangled)++; } } if (**mangled == 'e') /* exponent */ { - string_appendn (tname, "e", 1); + string_appendn (s, "e", 1); (*mangled)++; while (isdigit (**mangled)) { - string_appendn (tname, *mangled, 1); + string_appendn (s, *mangled, 1); (*mangled)++; } } @@ -1066,28 +1211,40 @@ demangle_template (work, mangled, tname, trawname) if (symbol_len == 0) { success = 0; + if (!is_type) + string_delete (s); break; } if (symbol_len == 0) - string_appendn (tname, "0", 1); + 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 (tname, "&", 1); + string_appendn (s, "&", 1); if (q) { - string_append (tname, q); + string_append (s, q); free (q); } else - string_append (tname, p); + string_append (s, p); free (p); } *mangled += symbol_len; } + if (!is_type) + { + int len = s->p - s->b; + work->tmpl_argvec[i] = xmalloc (len + 1); + memcpy (work->tmpl_argvec[i], s->b, len); + work->tmpl_argvec[i][len] = '\0'; + + string_appends (tname, s); + string_delete (s); + } } need_comma = 1; } @@ -1526,7 +1683,7 @@ gnu_special (work, mangled, declp) success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': - success = demangle_template (work, mangled, declp, 0); + success = demangle_template (work, mangled, declp, 0, 1); break; default: if (isdigit(*mangled[0])) @@ -1571,7 +1728,7 @@ gnu_special (work, mangled, declp) success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': - success = demangle_template (work, mangled, declp, 0); + success = demangle_template (work, mangled, declp, 0, 1); break; default: n = consume_count (mangled); @@ -1623,7 +1780,7 @@ gnu_special (work, mangled, declp) success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': - success = demangle_template (work, mangled, declp, 0); + success = demangle_template (work, mangled, declp, 0, 1); break; default: success = demangle_fund_type (work, mangled, declp); @@ -1825,7 +1982,12 @@ demangle_qualified (work, mangled, result, isfuncname, append) *mangled = *mangled + 1; if (*mangled[0] == 't') { - success = demangle_template(work, mangled, &temp, 0); + success = demangle_template(work, mangled, &temp, 0, 1); + if (!success) break; + } + else if (*mangled[0] == 'X') + { + success = do_type (work, mangled, &temp); if (!success) break; } else @@ -2064,7 +2226,7 @@ do_type (work, mangled, result) { string temp; string_init (&temp); - success = demangle_template (work, mangled, &temp, NULL); + success = demangle_template (work, mangled, &temp, NULL, 1); if (success) { string_prependn (&decl, temp.b, temp.p - temp.b); @@ -2152,6 +2314,37 @@ do_type (work, mangled, result) success = demangle_qualified (work, mangled, result, 0, 1); break; + case 'X': + case 'Y': + /* A template parm. We substitute the corresponding argument. */ + { + int idx; + int lvl; + + (*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; + break; + } + + if (work->tmpl_argvec) + string_append (result, work->tmpl_argvec[idx]); + else + { + char buf[10]; + sprintf(buf, "T%d", idx); + string_append (result, buf); + } + + success = 1; + } + break; + default: success = demangle_fund_type (work, mangled, result); break; @@ -2326,7 +2519,7 @@ demangle_fund_type (work, mangled, result) } break; case 't': - success = demangle_template(work,mangled, result, 0); + success = demangle_template(work,mangled, result, 0, 1); break; default: success = 0; diff --git a/gcc/invoke.texi b/gcc/invoke.texi index 7332f62ddf6..0437f25cbc2 100644 --- a/gcc/invoke.texi +++ b/gcc/invoke.texi @@ -104,8 +104,9 @@ in the following sections. @smallexample -fall-virtual -fdollars-in-identifiers -felide-constructors -fenum-int-equiv -fexternal-templates -ffor-scope -fno-for-scope --fhandle-signatures -fmemoize-lookups -fno-default-inline -fno-gnu-keywords --fnonnull-objects -foperator-names -fstrict-prototype -fthis-is-variable +-fhandle-signatures -fmemoize-lookups -fname-mangling-version-@var{n} +-fno-default-inline -fno-gnu-keywords -fnonnull-objects -fguiding-decls +-foperator-names -fstrict-prototype -fthis-is-variable -ftemplate-depth-@var{n} -nostdinc++ -traditional +e@var{n} @end smallexample @@ -925,11 +926,15 @@ Cause template instantiations to obey @samp{#pragma interface} and to the location of the template definition. @xref{Template Instantiation}, for more information. +This option is deprecated. + @item -falt-external-templates Similar to -fexternal-templates, but template instances are emitted or not according to the place where they are first instantiated. @xref{Template Instantiation}, for more information. +This option is deprecated. + @item -ffor-scope @item -fno-for-scope If -ffor-scope is specified, the scope of variables declared in @@ -952,6 +957,18 @@ words as identifiers. You can use the keywords @code{__classof__}, @code{__typeof__} instead. @samp{-ansi} implies @samp{-fno-gnu-keywords}. +@item -fguiding-decls +Treat a function declaration with the same type as a potential function +template instantiation as though it declares that instantiation, not a +normal function. If a definition is given for the function later in the +translation unit (or another translation unit if the target supports +weak symbols), that definition will be used; otherwise the template will +be instantiated. This behavior reflects the C++ language prior to +September 1996, when guiding declarations were removed. + +This option implies @samp{-fname-mangling-version-0}, and will not work +with other name mangling versions. + @item -fno-implicit-templates Never emit code for templates which are instantiated implicitly (i.e. by use); only emit code for explicit instantiations. @xref{Template @@ -1029,6 +1046,17 @@ overridden with @samp{-fno-strict-prototype}. This flag no longer affects declarations with C++ linkage. +@item -fname-mangling-version-@var{n} +Control the way in which names are mangled. Version 0 is compatible +with versions of g++ before 2.8. Version 1 is the default. Version 1 +will allow correct mangling of function templates. For example, +version 0 mangling does not mangle foo and foo +given this declaration: + +@example +template void foo(T t); +@end example + @item -fno-nonnull-objects Don't assume that a reference is initialized to refer to a valid object. Although the current C++ Working Paper prohibits null references, some -- 2.30.2