Sync config, include and libiberty with GCC

config/

2020-06-24  H.J. Lu  <hongjiu.lu@intel.com>

	Sync with GCC
	2020-05-29  H.J. Lu  <hjl.tools@gmail.com>

	PR bootstrap/95413
	* cet.m4: Replace save_CFLAGS and save_LDFLAGS with
	cet_save_CFLAGS and cet_save_LDFLAGS.

include/

2020-06-24  H.J. Lu  <hongjiu.lu@intel.com>

	Sync with GCC
	2020-06-23  Nick Alcock  <nick.alcock@oracle.com>

	* libiberty.h (bsearch_r): New.

	2020-04-17  Martin Liska  <mliska@suse.cz>
		    Jonathan Yong <10walls@gmail.com>

	PR gcov-profile/94570
	* filenames.h (defined): Do not define HAVE_DOS_BASED_FILE_SYSTEM
	for CYGWIN.

libiberty/

2020-06-23  Nick Alcock  <nick.alcock@oracle.com>

	* bsearch_r.c: New file.
	* Makefile.in (CFILES): Add bsearch_r.c.
	(REQUIRED_OFILES): Add bsearch_r.o.
	* functions.texi: Regenerate.

2020-05-29  H.J. Lu  <hjl.tools@gmail.com>

	PR bootstrap/95413
	* configure: Regenerated.

2020-05-15  Iain Buclaw  <ibuclaw@gdcproject.org>

	* d-demangle.c (dlang_attributes): Add @live attribute.
	* testsuite/d-demangle-expected: Add new tests.

2020-05-14  Rainer Schuetze  <r.sagitario@gmx.de>
	    Iain Buclaw  <ibuclaw@gdcproject.org>

	* d-demangle.c (enum dlang_symbol_kinds): Remove enum.
	(struct dlang_info): New struct
	(dlang_decode_backref): New function.
	(dlang_backref): New function.
	(dlang_symbol_backref): New function.
	(dlang_type_backref): New function.
	(dlang_symbol_name_p): New function.
	(dlang_function_type_noreturn): New function.
	(dlang_function_type): Add 'info' parameter.  Decode function type
	with dlang_function_type_noreturn.
	(dlang_function_args): Add 'info' parameter.
	(dlang_type): Add 'info' parameter.  Handle back referenced types.
	(dlang_identifier): Replace 'kind' parameter with 'info'.  Handle back
	referenced symbols.  Split off decoding of plain identifiers to...
	(dlang_lname): ...here.
	(dlang_parse_mangle): Replace 'kind' parameter with 'info'.  Decode
	function type and return with dlang_type.
	(dlang_parse_qualified): Replace 'kind' parameter with 'info', add
	'suffix_modifier' parameter.  Decode function type with
	dlang_function_type_noreturn.
	(dlang_parse_tuple): Add 'info' parameter.
	(dlang_template_symbol_param): New function.
	(dlang_template_args): Add 'info' parameter.  Decode symbol parameter
	with dlang_template_symbol_param.  Handle back referenced values, and
	externally mangled parameters.
	(dlang_parse_template): Add 'info' parameter.
	(dlang_demangle_init_info): New function.
	(dlang_demangle): Initialize and pass 'info' parameter.
	* testsuite/d-demangle-expected: Add new tests.
This commit is contained in:
H.J. Lu 2020-06-24 12:27:57 -07:00
parent 221db974e6
commit 727b7b1864
12 changed files with 819 additions and 286 deletions

View File

@ -1,3 +1,12 @@
2020-06-24 H.J. Lu <hongjiu.lu@intel.com>
Sync with GCC
2020-05-29 H.J. Lu <hjl.tools@gmail.com>
PR bootstrap/95413
* cet.m4: Replace save_CFLAGS and save_LDFLAGS with
cet_save_CFLAGS and cet_save_LDFLAGS.
2020-05-16 H.J. Lu <hongjiu.lu@intel.com> 2020-05-16 H.J. Lu <hongjiu.lu@intel.com>
Sync with GCC Sync with GCC

View File

@ -7,13 +7,14 @@ GCC_ENABLE(cet, auto, ,[enable Intel CET in target libraries],
permit yes|no|auto) permit yes|no|auto)
AC_MSG_CHECKING([for CET support]) AC_MSG_CHECKING([for CET support])
# NB: Avoid nested save_CFLAGS and save_LDFLAGS.
case "$host" in case "$host" in
i[[34567]]86-*-linux* | x86_64-*-linux*) i[[34567]]86-*-linux* | x86_64-*-linux*)
case "$enable_cet" in case "$enable_cet" in
auto) auto)
# Check if target supports multi-byte NOPs # Check if target supports multi-byte NOPs
# and if assembler supports CET insn. # and if assembler supports CET insn.
save_CFLAGS="$CFLAGS" cet_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fcf-protection" CFLAGS="$CFLAGS -fcf-protection"
AC_COMPILE_IFELSE( AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM( [AC_LANG_PROGRAM(
@ -27,7 +28,7 @@ asm ("setssbsy");
])], ])],
[enable_cet=yes], [enable_cet=yes],
[enable_cet=no]) [enable_cet=no])
CFLAGS="$save_CFLAGS" CFLAGS="$cet_save_CFLAGS"
;; ;;
yes) yes)
# Check if assembler supports CET. # Check if assembler supports CET.
@ -64,7 +65,7 @@ AC_MSG_CHECKING([for CET support])
case "$host" in case "$host" in
i[[34567]]86-*-linux* | x86_64-*-linux*) i[[34567]]86-*-linux* | x86_64-*-linux*)
may_have_cet=yes may_have_cet=yes
save_CFLAGS="$CFLAGS" cet_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fcf-protection" CFLAGS="$CFLAGS -fcf-protection"
case "$enable_cet" in case "$enable_cet" in
auto) auto)
@ -93,7 +94,7 @@ asm ("setssbsy");
[AC_MSG_ERROR([assembler with CET support is required for --enable-cet])]) [AC_MSG_ERROR([assembler with CET support is required for --enable-cet])])
;; ;;
esac esac
CFLAGS="$save_CFLAGS" CFLAGS="$cet_save_CFLAGS"
;; ;;
*) *)
may_have_cet=no may_have_cet=no
@ -101,9 +102,9 @@ asm ("setssbsy");
;; ;;
esac esac
save_CFLAGS="$CFLAGS" cet_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fcf-protection=none" CFLAGS="$CFLAGS -fcf-protection=none"
save_LDFLAGS="$LDFLAGS" cet_save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -Wl,-z,ibt,-z,shstk" LDFLAGS="$LDFLAGS -Wl,-z,ibt,-z,shstk"
if test x$may_have_cet = xyes; then if test x$may_have_cet = xyes; then
# Check whether -fcf-protection=none -Wl,-z,ibt,-z,shstk work. # Check whether -fcf-protection=none -Wl,-z,ibt,-z,shstk work.
@ -159,6 +160,6 @@ if test x$enable_cet = xyes; then
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
CFLAGS="$save_CFLAGS" CFLAGS="$cet_save_CFLAGS"
LDFLAGS="$save_LDFLAGS" LDFLAGS="$cet_save_LDFLAGS"
]) ])

View File

@ -1,3 +1,17 @@
2020-06-24 H.J. Lu <hongjiu.lu@intel.com>
Sync with GCC
2020-06-23 Nick Alcock <nick.alcock@oracle.com>
* libiberty.h (bsearch_r): New.
2020-04-17 Martin Liska <mliska@suse.cz>
Jonathan Yong <10walls@gmail.com>
PR gcov-profile/94570
* filenames.h (defined): Do not define HAVE_DOS_BASED_FILE_SYSTEM
for CYGWIN.
2020-06-22 Alex Coplan <alex.coplan@arm.com> 2020-06-22 Alex Coplan <alex.coplan@arm.com>
* opcode/aarch64.h (AARCH64_FEATURE_SHA2): Normalize. * opcode/aarch64.h (AARCH64_FEATURE_SHA2): Normalize.

View File

@ -32,7 +32,8 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
extern "C" { extern "C" {
#endif #endif
#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__) #if defined(__MSDOS__) || (defined(_WIN32) && ! defined(__CYGWIN__)) || \
defined(__OS2__)
# ifndef HAVE_DOS_BASED_FILE_SYSTEM # ifndef HAVE_DOS_BASED_FILE_SYSTEM
# define HAVE_DOS_BASED_FILE_SYSTEM 1 # define HAVE_DOS_BASED_FILE_SYSTEM 1
# endif # endif

View File

@ -641,6 +641,13 @@ extern int pexecute (const char *, char * const *, const char *,
extern int pwait (int, int *, int); extern int pwait (int, int *, int);
/* Like bsearch, but takes and passes on an argument like qsort_r. */
extern void *bsearch_r (register const void *, const void *,
size_t, register size_t,
register int (*)(const void *, const void *, void *),
void *);
#if defined(HAVE_DECL_ASPRINTF) && !HAVE_DECL_ASPRINTF #if defined(HAVE_DECL_ASPRINTF) && !HAVE_DECL_ASPRINTF
/* Like sprintf but provides a pointer to malloc'd storage, which must /* Like sprintf but provides a pointer to malloc'd storage, which must
be freed by the caller. */ be freed by the caller. */

View File

@ -1,3 +1,53 @@
2020-06-23 Nick Alcock <nick.alcock@oracle.com>
* bsearch_r.c: New file.
* Makefile.in (CFILES): Add bsearch_r.c.
(REQUIRED_OFILES): Add bsearch_r.o.
* functions.texi: Regenerate.
2020-05-29 H.J. Lu <hjl.tools@gmail.com>
PR bootstrap/95413
* configure: Regenerated.
2020-05-15 Iain Buclaw <ibuclaw@gdcproject.org>
* d-demangle.c (dlang_attributes): Add @live attribute.
* testsuite/d-demangle-expected: Add new tests.
2020-05-14 Rainer Schuetze <r.sagitario@gmx.de>
Iain Buclaw <ibuclaw@gdcproject.org>
* d-demangle.c (enum dlang_symbol_kinds): Remove enum.
(struct dlang_info): New struct
(dlang_decode_backref): New function.
(dlang_backref): New function.
(dlang_symbol_backref): New function.
(dlang_type_backref): New function.
(dlang_symbol_name_p): New function.
(dlang_function_type_noreturn): New function.
(dlang_function_type): Add 'info' parameter. Decode function type
with dlang_function_type_noreturn.
(dlang_function_args): Add 'info' parameter.
(dlang_type): Add 'info' parameter. Handle back referenced types.
(dlang_identifier): Replace 'kind' parameter with 'info'. Handle back
referenced symbols. Split off decoding of plain identifiers to...
(dlang_lname): ...here.
(dlang_parse_mangle): Replace 'kind' parameter with 'info'. Decode
function type and return with dlang_type.
(dlang_parse_qualified): Replace 'kind' parameter with 'info', add
'suffix_modifier' parameter. Decode function type with
dlang_function_type_noreturn.
(dlang_parse_tuple): Add 'info' parameter.
(dlang_template_symbol_param): New function.
(dlang_template_args): Add 'info' parameter. Decode symbol parameter
with dlang_template_symbol_param. Handle back referenced values, and
externally mangled parameters.
(dlang_parse_template): Add 'info' parameter.
(dlang_demangle_init_info): New function.
(dlang_demangle): Initialize and pass 'info' parameter.
* testsuite/d-demangle-expected: Add new tests.
2020-05-12 H.J. Lu <hongjiu.lu@intel.com> 2020-05-12 H.J. Lu <hongjiu.lu@intel.com>
PR bootstrap/94998 PR bootstrap/94998

View File

@ -124,7 +124,7 @@ COMPILE.c = $(CC) -c @DEFS@ $(CFLAGS) $(CPPFLAGS) -I. -I$(INCDIR) \
# CONFIGURED_OFILES and funcs in configure.ac. Also run "make maint-deps" # CONFIGURED_OFILES and funcs in configure.ac. Also run "make maint-deps"
# to build the new rules. # to build the new rules.
CFILES = alloca.c argv.c asprintf.c atexit.c \ CFILES = alloca.c argv.c asprintf.c atexit.c \
basename.c bcmp.c bcopy.c bsearch.c bzero.c \ basename.c bcmp.c bcopy.c bsearch.c bsearch_r.c bzero.c \
calloc.c choose-temp.c clock.c concat.c cp-demangle.c \ calloc.c choose-temp.c clock.c concat.c cp-demangle.c \
cp-demint.c cplus-dem.c crc32.c \ cp-demint.c cplus-dem.c crc32.c \
d-demangle.c dwarfnames.c dyn-string.c \ d-demangle.c dwarfnames.c dyn-string.c \
@ -168,6 +168,7 @@ REQUIRED_OFILES = \
./regex.$(objext) ./cplus-dem.$(objext) ./cp-demangle.$(objext) \ ./regex.$(objext) ./cplus-dem.$(objext) ./cp-demangle.$(objext) \
./md5.$(objext) ./sha1.$(objext) ./alloca.$(objext) \ ./md5.$(objext) ./sha1.$(objext) ./alloca.$(objext) \
./argv.$(objext) \ ./argv.$(objext) \
./bsearch_r.$(objext) \
./choose-temp.$(objext) ./concat.$(objext) \ ./choose-temp.$(objext) ./concat.$(objext) \
./cp-demint.$(objext) ./crc32.$(objext) ./d-demangle.$(objext) \ ./cp-demint.$(objext) ./crc32.$(objext) ./d-demangle.$(objext) \
./dwarfnames.$(objext) ./dyn-string.$(objext) \ ./dwarfnames.$(objext) ./dyn-string.$(objext) \
@ -601,6 +602,15 @@ $(CONFIGURED_OFILES): stamp-picdir stamp-noasandir
else true; fi else true; fi
$(COMPILE.c) $(srcdir)/bsearch.c $(OUTPUT_OPTION) $(COMPILE.c) $(srcdir)/bsearch.c $(OUTPUT_OPTION)
./bsearch_r.$(objext): $(srcdir)/bsearch_r.c config.h $(INCDIR)/ansidecl.h
if [ x"$(PICFLAG)" != x ]; then \
$(COMPILE.c) $(PICFLAG) $(srcdir)/bsearch_r.c -o pic/$@; \
else true; fi
if [ x"$(NOASANFLAG)" != x ]; then \
$(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/bsearch_r.c -o noasan/$@; \
else true; fi
$(COMPILE.c) $(srcdir)/bsearch_r.c $(OUTPUT_OPTION)
./bzero.$(objext): $(srcdir)/bzero.c ./bzero.$(objext): $(srcdir)/bzero.c
if [ x"$(PICFLAG)" != x ]; then \ if [ x"$(PICFLAG)" != x ]; then \
$(COMPILE.c) $(PICFLAG) $(srcdir)/bzero.c -o pic/$@; \ $(COMPILE.c) $(PICFLAG) $(srcdir)/bzero.c -o pic/$@; \

93
libiberty/bsearch_r.c Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. [rescinded 22 July 1999]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
@deftypefn Supplemental void* bsearch_r (const void *@var{key}, @
const void *@var{base}, size_t @var{nmemb}, size_t @var{size}, @
int (*@var{compar})(const void *, const void *, void *), void *@var{arg})
Performs a search over an array of @var{nmemb} elements pointed to by
@var{base} for a member that matches the object pointed to by @var{key}.
The size of each member is specified by @var{size}. The array contents
should be sorted in ascending order according to the @var{compar}
comparison function. This routine should take three arguments: the first
two point to the @var{key} and to an array member, and the last is passed
down unchanged from @code{bsearch_r}'s last argument. It should return an
integer less than, equal to, or greater than zero if the @var{key} object
is respectively less than, matching, or greater than the array member.
@end deftypefn
*/
#include "config.h"
#include "ansidecl.h"
#include <sys/types.h> /* size_t */
#include <stdio.h>
/*
* Perform a binary search.
*
* The code below is a bit sneaky. After a comparison fails, we
* divide the work in half by moving either left or right. If lim
* is odd, moving left simply involves halving lim: e.g., when lim
* is 5 we look at item 2, so we change lim to 2 so that we will
* look at items 0 & 1. If lim is even, the same applies. If lim
* is odd, moving right again involes halving lim, this time moving
* the base up one item past p: e.g., when lim is 5 we change base
* to item 3 and make lim 2 so that we will look at items 3 and 4.
* If lim is even, however, we have to shrink it by one before
* halving: e.g., when lim is 4, we still looked at item 2, so we
* have to make lim 3, then halve, obtaining 1, so that we will only
* look at item 3.
*/
void *
bsearch_r (register const void *key, const void *base0,
size_t nmemb, register size_t size,
register int (*compar)(const void *, const void *, void *),
void *arg)
{
register const char *base = (const char *) base0;
register int lim, cmp;
register const void *p;
for (lim = nmemb; lim != 0; lim >>= 1) {
p = base + (lim >> 1) * size;
cmp = (*compar)(key, p, arg);
if (cmp == 0)
return (void *)p;
if (cmp > 0) { /* key > p: move right */
base = (const char *)p + size;
lim--;
} /* else move left */
}
return (NULL);
}

12
libiberty/configure vendored
View File

@ -5286,7 +5286,7 @@ $as_echo_n "checking for CET support... " >&6; }
case "$host" in case "$host" in
i[34567]86-*-linux* | x86_64-*-linux*) i[34567]86-*-linux* | x86_64-*-linux*)
may_have_cet=yes may_have_cet=yes
save_CFLAGS="$CFLAGS" cet_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fcf-protection" CFLAGS="$CFLAGS -fcf-protection"
case "$enable_cet" in case "$enable_cet" in
auto) auto)
@ -5337,7 +5337,7 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
;; ;;
esac esac
CFLAGS="$save_CFLAGS" CFLAGS="$cet_save_CFLAGS"
;; ;;
*) *)
may_have_cet=no may_have_cet=no
@ -5345,9 +5345,9 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
;; ;;
esac esac
save_CFLAGS="$CFLAGS" cet_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fcf-protection=none" CFLAGS="$CFLAGS -fcf-protection=none"
save_LDFLAGS="$LDFLAGS" cet_save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -Wl,-z,ibt,-z,shstk" LDFLAGS="$LDFLAGS -Wl,-z,ibt,-z,shstk"
if test x$may_have_cet = xyes; then if test x$may_have_cet = xyes; then
# Check whether -fcf-protection=none -Wl,-z,ibt,-z,shstk work. # Check whether -fcf-protection=none -Wl,-z,ibt,-z,shstk work.
@ -5438,8 +5438,8 @@ else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; } $as_echo "no" >&6; }
fi fi
CFLAGS="$save_CFLAGS" CFLAGS="$cet_save_CFLAGS"
LDFLAGS="$save_LDFLAGS" LDFLAGS="$cet_save_LDFLAGS"

View File

@ -160,37 +160,42 @@ string_prepend (string *p, const char *s)
} }
} }
/* What kinds of symbol we could be parsing. */ /* Demangle information structure we pass around. */
enum dlang_symbol_kinds struct dlang_info
{ {
/* Top-level symbol, needs it's type checked. */ /* The string we are demangling. */
dlang_top_level, const char *s;
/* Function symbol, needs it's type checked. */ /* The index of the last back reference. */
dlang_function, int last_backref;
/* Strongly typed name, such as for classes, structs and enums. */
dlang_type_name,
/* Template identifier. */
dlang_template_ident,
/* Template symbol parameter. */
dlang_template_param
}; };
/* Prototypes for forward referenced functions */ /* Pass as the LEN to dlang_parse_template if symbol length is not known. */
static const char *dlang_function_args (string *, const char *); enum { TEMPLATE_LENGTH_UNKNOWN = -1 };
static const char *dlang_type (string *, const char *); /* Prototypes for forward referenced functions */
static const char *dlang_function_type (string *, const char *,
struct dlang_info *);
static const char *dlang_function_args (string *, const char *,
struct dlang_info *);
static const char *dlang_type (string *, const char *, struct dlang_info *);
static const char *dlang_value (string *, const char *, const char *, char); static const char *dlang_value (string *, const char *, const char *, char);
static const char *dlang_parse_qualified (string *, const char *, static const char *dlang_parse_qualified (string *, const char *,
enum dlang_symbol_kinds); struct dlang_info *, int);
static const char *dlang_parse_mangle (string *, const char *, static const char *dlang_parse_mangle (string *, const char *,
enum dlang_symbol_kinds); struct dlang_info *);
static const char *dlang_parse_tuple (string *, const char *); static const char *dlang_parse_tuple (string *, const char *,
struct dlang_info *);
static const char *dlang_parse_template (string *, const char *, long); static const char *dlang_parse_template (string *, const char *,
struct dlang_info *, long);
static const char *dlang_lname (string *, const char *, long);
/* Extract the number from MANGLED, and assign the result to RET. /* Extract the number from MANGLED, and assign the result to RET.
@ -267,6 +272,175 @@ dlang_call_convention_p (const char *mangled)
} }
} }
/* Extract the back reference position from MANGLED, and assign the result
to RET. Return the remaining string on success or NULL on failure. */
static const char *
dlang_decode_backref (const char *mangled, long *ret)
{
/* Return NULL if trying to extract something that isn't a digit. */
if (mangled == NULL || !ISALPHA (*mangled))
return NULL;
/* Any identifier or non-basic type that has been emitted to the mangled
symbol before will not be emitted again, but is referenced by a special
sequence encoding the relative position of the original occurrence in the
mangled symbol name.
Numbers in back references are encoded with base 26 by upper case letters
A-Z for higher digits but lower case letters a-z for the last digit.
NumberBackRef:
[a-z]
[A-Z] NumberBackRef
^
*/
(*ret) = 0;
while (ISALPHA (*mangled))
{
(*ret) *= 26;
/* If an overflow occured when multiplying by 26, the result
will not be a multiple of 26. */
if ((*ret % 26) != 0)
return NULL;
if (mangled[0] >= 'a' && mangled[0] <= 'z')
{
(*ret) += mangled[0] - 'a';
return mangled + 1;
}
(*ret) += mangled[0] - 'A';
mangled++;
}
return NULL;
}
/* Extract the symbol pointed at by the back reference and assign the result
to RET. Return the remaining string on success or NULL on failure. */
static const char *
dlang_backref (const char *mangled, const char **ret, struct dlang_info *info)
{
(*ret) = NULL;
if (mangled == NULL || *mangled != 'Q')
return NULL;
/* Position of 'Q'. */
const char *qpos = mangled;
long refpos;
mangled++;
mangled = dlang_decode_backref (mangled, &refpos);
if (mangled == NULL)
return NULL;
if (refpos <= 0 || refpos > qpos - info->s)
return NULL;
/* Set the position of the back reference. */
(*ret) = qpos - refpos;
return mangled;
}
/* Demangle a back referenced symbol from MANGLED and append it to DECL.
Return the remaining string on success or NULL on failure. */
static const char *
dlang_symbol_backref (string *decl, const char *mangled,
struct dlang_info *info)
{
/* An identifier back reference always points to a digit 0 to 9.
IdentifierBackRef:
Q NumberBackRef
^
*/
const char *backref;
long len;
/* Get position of the back reference. */
mangled = dlang_backref (mangled, &backref, info);
/* Must point to a simple identifier. */
backref = dlang_number (backref, &len);
if (backref == NULL)
return NULL;
backref = dlang_lname (decl, backref, len);
if (backref == NULL)
return NULL;
return mangled;
}
/* Demangle a back referenced type from MANGLED and append it to DECL.
IS_FUNCTION is 1 if the back referenced type is expected to be a function.
Return the remaining string on success or NULL on failure. */
static const char *
dlang_type_backref (string *decl, const char *mangled, struct dlang_info *info,
int is_function)
{
/* A type back reference always points to a letter.
TypeBackRef:
Q NumberBackRef
^
*/
const char *backref;
/* If we appear to be moving backwards through the mangle string, then
bail as this may be a recursive back reference. */
if (mangled - info->s >= info->last_backref)
return NULL;
int save_refpos = info->last_backref;
info->last_backref = mangled - info->s;
/* Get position of the back reference. */
mangled = dlang_backref (mangled, &backref, info);
/* Must point to a type. */
if (is_function)
backref = dlang_function_type (decl, backref, info);
else
backref = dlang_type (decl, backref, info);
info->last_backref = save_refpos;
if (backref == NULL)
return NULL;
return mangled;
}
/* Extract the beginning of a symbol name from MANGLED and
return 1 on success or 0 on failure. */
static int
dlang_symbol_name_p (const char *mangled, struct dlang_info *info)
{
long ret;
const char *qref = mangled;
if (ISDIGIT (*mangled))
return 1;
if (mangled[0] == '_' && mangled[1] == '_'
&& (mangled[2] == 'T' || mangled[2] == 'U'))
return 1;
if (*mangled != 'Q')
return 0;
mangled = dlang_decode_backref (mangled + 1, &ret);
if (mangled == NULL || ret <= 0 || ret > qref - info->s)
return 0;
return ISDIGIT (qref[-ret]);
}
/* Demangle the calling convention from MANGLED and append it to DECL. /* Demangle the calling convention from MANGLED and append it to DECL.
Return the remaining string on success or NULL on failure. */ Return the remaining string on success or NULL on failure. */
static const char * static const char *
@ -404,6 +578,10 @@ dlang_attributes (string *decl, const char *mangled)
mangled++; mangled++;
string_append (decl, "scope "); string_append (decl, "scope ");
continue; continue;
case 'm': /* @live */
mangled++;
string_append (decl, "@live ");
continue;
default: /* unknown attribute */ default: /* unknown attribute */
return NULL; return NULL;
@ -414,13 +592,39 @@ dlang_attributes (string *decl, const char *mangled)
return mangled; return mangled;
} }
/* Demangle the function type from MANGLED without the return type.
The arguments are appended to ARGS, the calling convention is appended
to CALL and attributes are appended to ATTR. Any of these can be NULL
to throw the information away. Return the remaining string on success
or NULL on failure. */
static const char *
dlang_function_type_noreturn (string *args, string *call, string *attr,
const char *mangled, struct dlang_info *info)
{
string dump;
string_init (&dump);
/* Skip over calling convention and attributes. */
mangled = dlang_call_convention (call ? call : &dump, mangled);
mangled = dlang_attributes (attr ? attr : &dump, mangled);
if (args)
string_append (args, "(");
mangled = dlang_function_args (args ? args : &dump, mangled, info);
if (args)
string_append (args, ")");
string_delete (&dump);
return mangled;
}
/* Demangle the function type from MANGLED and append it to DECL. /* Demangle the function type from MANGLED and append it to DECL.
Return the remaining string on success or NULL on failure. */ Return the remaining string on success or NULL on failure. */
static const char * static const char *
dlang_function_type (string *decl, const char *mangled) dlang_function_type (string *decl, const char *mangled, struct dlang_info *info)
{ {
string attr, args, type; string attr, args, type;
size_t szattr, szargs, sztype;
if (mangled == NULL || *mangled == '\0') if (mangled == NULL || *mangled == '\0')
return NULL; return NULL;
@ -435,27 +639,16 @@ dlang_function_type (string *decl, const char *mangled)
string_init (&args); string_init (&args);
string_init (&type); string_init (&type);
/* Function call convention. */ mangled = dlang_function_type_noreturn (&args, decl, &attr, mangled, info);
mangled = dlang_call_convention (decl, mangled);
/* Function attributes. */
mangled = dlang_attributes (&attr, mangled);
szattr = string_length (&attr);
/* Function arguments. */
mangled = dlang_function_args (&args, mangled);
szargs = string_length (&args);
/* Function return type. */ /* Function return type. */
mangled = dlang_type (&type, mangled); mangled = dlang_type (&type, mangled, info);
sztype = string_length (&type);
/* Append to decl in order. */ /* Append to decl in order. */
string_appendn (decl, type.b, sztype); string_appendn (decl, type.b, string_length (&type));
string_append (decl, "("); string_appendn (decl, args.b, string_length (&args));
string_appendn (decl, args.b, szargs); string_append (decl, " ");
string_append (decl, ") "); string_appendn (decl, attr.b, string_length (&attr));
string_appendn (decl, attr.b, szattr);
string_delete (&attr); string_delete (&attr);
string_delete (&args); string_delete (&args);
@ -466,7 +659,7 @@ dlang_function_type (string *decl, const char *mangled)
/* Demangle the argument list from MANGLED and append it to DECL. /* Demangle the argument list from MANGLED and append it to DECL.
Return the remaining string on success or NULL on failure. */ Return the remaining string on success or NULL on failure. */
static const char * static const char *
dlang_function_args (string *decl, const char *mangled) dlang_function_args (string *decl, const char *mangled, struct dlang_info *info)
{ {
size_t n = 0; size_t n = 0;
@ -519,7 +712,7 @@ dlang_function_args (string *decl, const char *mangled)
string_append (decl, "lazy "); string_append (decl, "lazy ");
break; break;
} }
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
} }
return mangled; return mangled;
@ -528,7 +721,7 @@ dlang_function_args (string *decl, const char *mangled)
/* Demangle the type from MANGLED and append it to DECL. /* Demangle the type from MANGLED and append it to DECL.
Return the remaining string on success or NULL on failure. */ Return the remaining string on success or NULL on failure. */
static const char * static const char *
dlang_type (string *decl, const char *mangled) dlang_type (string *decl, const char *mangled, struct dlang_info *info)
{ {
if (mangled == NULL || *mangled == '\0') if (mangled == NULL || *mangled == '\0')
return NULL; return NULL;
@ -538,19 +731,19 @@ dlang_type (string *decl, const char *mangled)
case 'O': /* shared(T) */ case 'O': /* shared(T) */
mangled++; mangled++;
string_append (decl, "shared("); string_append (decl, "shared(");
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
string_append (decl, ")"); string_append (decl, ")");
return mangled; return mangled;
case 'x': /* const(T) */ case 'x': /* const(T) */
mangled++; mangled++;
string_append (decl, "const("); string_append (decl, "const(");
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
string_append (decl, ")"); string_append (decl, ")");
return mangled; return mangled;
case 'y': /* immutable(T) */ case 'y': /* immutable(T) */
mangled++; mangled++;
string_append (decl, "immutable("); string_append (decl, "immutable(");
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
string_append (decl, ")"); string_append (decl, ")");
return mangled; return mangled;
case 'N': case 'N':
@ -559,7 +752,7 @@ dlang_type (string *decl, const char *mangled)
{ {
mangled++; mangled++;
string_append (decl, "inout("); string_append (decl, "inout(");
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
string_append (decl, ")"); string_append (decl, ")");
return mangled; return mangled;
} }
@ -567,7 +760,7 @@ dlang_type (string *decl, const char *mangled)
{ {
mangled++; mangled++;
string_append (decl, "__vector("); string_append (decl, "__vector(");
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
string_append (decl, ")"); string_append (decl, ")");
return mangled; return mangled;
} }
@ -575,7 +768,7 @@ dlang_type (string *decl, const char *mangled)
return NULL; return NULL;
case 'A': /* dynamic array (T[]) */ case 'A': /* dynamic array (T[]) */
mangled++; mangled++;
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
string_append (decl, "[]"); string_append (decl, "[]");
return mangled; return mangled;
case 'G': /* static array (T[N]) */ case 'G': /* static array (T[N]) */
@ -590,7 +783,7 @@ dlang_type (string *decl, const char *mangled)
num++; num++;
mangled++; mangled++;
} }
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
string_append (decl, "["); string_append (decl, "[");
string_appendn (decl, numptr, num); string_appendn (decl, numptr, num);
string_append (decl, "]"); string_append (decl, "]");
@ -603,10 +796,10 @@ dlang_type (string *decl, const char *mangled)
mangled++; mangled++;
string_init (&type); string_init (&type);
mangled = dlang_type (&type, mangled); mangled = dlang_type (&type, mangled, info);
sztype = string_length (&type); sztype = string_length (&type);
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
string_append (decl, "["); string_append (decl, "[");
string_appendn (decl, type.b, sztype); string_appendn (decl, type.b, sztype);
string_append (decl, "]"); string_append (decl, "]");
@ -618,7 +811,7 @@ dlang_type (string *decl, const char *mangled)
mangled++; mangled++;
if (!dlang_call_convention_p (mangled)) if (!dlang_call_convention_p (mangled))
{ {
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
string_append (decl, "*"); string_append (decl, "*");
return mangled; return mangled;
} }
@ -630,7 +823,7 @@ dlang_type (string *decl, const char *mangled)
case 'R': /* function T (C++) */ case 'R': /* function T (C++) */
case 'Y': /* function T (Objective-C) */ case 'Y': /* function T (Objective-C) */
/* Function pointer types don't include the trailing asterisk. */ /* Function pointer types don't include the trailing asterisk. */
mangled = dlang_function_type (decl, mangled); mangled = dlang_function_type (decl, mangled, info);
string_append (decl, "function"); string_append (decl, "function");
return mangled; return mangled;
case 'I': /* ident T */ case 'I': /* ident T */
@ -639,7 +832,7 @@ dlang_type (string *decl, const char *mangled)
case 'E': /* enum T */ case 'E': /* enum T */
case 'T': /* typedef T */ case 'T': /* typedef T */
mangled++; mangled++;
return dlang_parse_qualified (decl, mangled, dlang_type_name); return dlang_parse_qualified (decl, mangled, info, 0);
case 'D': /* delegate T */ case 'D': /* delegate T */
{ {
string mods; string mods;
@ -650,7 +843,12 @@ dlang_type (string *decl, const char *mangled)
mangled = dlang_type_modifiers (&mods, mangled); mangled = dlang_type_modifiers (&mods, mangled);
szmods = string_length (&mods); szmods = string_length (&mods);
mangled = dlang_function_type (decl, mangled); /* Back referenced function type. */
if (*mangled == 'Q')
mangled = dlang_type_backref (decl, mangled, info, 1);
else
mangled = dlang_function_type (decl, mangled, info);
string_append (decl, "delegate"); string_append (decl, "delegate");
string_appendn (decl, mods.b, szmods); string_appendn (decl, mods.b, szmods);
@ -659,7 +857,7 @@ dlang_type (string *decl, const char *mangled)
} }
case 'B': /* tuple T */ case 'B': /* tuple T */
mangled++; mangled++;
return dlang_parse_tuple (decl, mangled); return dlang_parse_tuple (decl, mangled, info);
/* Basic types */ /* Basic types */
case 'n': case 'n':
@ -773,6 +971,10 @@ dlang_type (string *decl, const char *mangled)
} }
return NULL; return NULL;
/* Back referenced type. */
case 'Q':
return dlang_type_backref (decl, mangled, info, 0);
default: /* unhandled */ default: /* unhandled */
return NULL; return NULL;
} }
@ -781,69 +983,45 @@ dlang_type (string *decl, const char *mangled)
/* Extract the identifier from MANGLED and append it to DECL. /* Extract the identifier from MANGLED and append it to DECL.
Return the remaining string on success or NULL on failure. */ Return the remaining string on success or NULL on failure. */
static const char * static const char *
dlang_identifier (string *decl, const char *mangled, dlang_identifier (string *decl, const char *mangled, struct dlang_info *info)
enum dlang_symbol_kinds kind)
{ {
long len; long len;
if (mangled == NULL || *mangled == '\0')
return NULL;
if (*mangled == 'Q')
return dlang_symbol_backref (decl, mangled, info);
/* May be a template instance without a length prefix. */
if (mangled[0] == '_' && mangled[1] == '_'
&& (mangled[2] == 'T' || mangled[2] == 'U'))
return dlang_parse_template (decl, mangled, info, TEMPLATE_LENGTH_UNKNOWN);
const char *endptr = dlang_number (mangled, &len); const char *endptr = dlang_number (mangled, &len);
if (endptr == NULL || len == 0) if (endptr == NULL || len == 0)
return NULL; return NULL;
/* In template parameter symbols, the first character of the mangled
name can be a digit. This causes ambiguity issues because the
digits of the two numbers are adjacent. */
if (kind == dlang_template_param)
{
long psize = len;
const char *pend;
int saved = string_length (decl);
/* Work backwards until a match is found. */
for (pend = endptr; endptr != NULL; pend--)
{
mangled = pend;
/* Reached the beginning of the pointer to the name length,
try parsing the entire symbol. */
if (psize == 0)
{
psize = len;
pend = endptr;
endptr = NULL;
}
/* Check whether template parameter is a function with a valid
return type or an untyped identifier. */
if (ISDIGIT (*mangled))
mangled = dlang_parse_qualified (decl, mangled,
dlang_template_ident);
else if (strncmp (mangled, "_D", 2) == 0)
mangled = dlang_parse_mangle (decl, mangled, dlang_function);
/* Check for name length mismatch. */
if (mangled && (mangled - pend) == psize)
return mangled;
psize /= 10;
string_setlength (decl, saved);
}
/* No match on any combinations. */
return NULL;
}
else
{
if (strlen (endptr) < (size_t) len) if (strlen (endptr) < (size_t) len)
return NULL; return NULL;
mangled = endptr; mangled = endptr;
/* May be a template instance. */ /* May be a template instance with a length prefix. */
if (len >= 5 && mangled[0] == '_' && mangled[1] == '_' if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
&& (mangled[2] == 'T' || mangled[2] == 'U')) && (mangled[2] == 'T' || mangled[2] == 'U'))
return dlang_parse_template (decl, mangled, len); return dlang_parse_template (decl, mangled, info, len);
return dlang_lname (decl, mangled, len);
}
/* Extract the plain identifier from MANGLED and prepend/append it to DECL
with special treatment for some magic compiler generted symbols.
Return the remaining string on success or NULL on failure. */
static const char *
dlang_lname (string *decl, const char *mangled, long len)
{
switch (len) switch (len)
{ {
case 6: case 6:
@ -925,7 +1103,6 @@ dlang_identifier (string *decl, const char *mangled,
string_appendn (decl, mangled, len); string_appendn (decl, mangled, len);
mangled += len; mangled += len;
}
return mangled; return mangled;
} }
@ -1347,22 +1524,22 @@ dlang_value (string *decl, const char *mangled, const char *name, char type)
/* Extract and demangle the symbol in MANGLED and append it to DECL. /* Extract and demangle the symbol in MANGLED and append it to DECL.
Returns the remaining signature on success or NULL on failure. */ Returns the remaining signature on success or NULL on failure. */
static const char * static const char *
dlang_parse_mangle (string *decl, const char *mangled, dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info)
enum dlang_symbol_kinds kind)
{ {
/* A D mangled symbol is comprised of both scope and type information. /* A D mangled symbol is comprised of both scope and type information.
MangleName: MangleName:
_D QualifiedName Type _D QualifiedName Type
_D QualifiedName M Type
_D QualifiedName Z _D QualifiedName Z
^ ^
The caller should have guaranteed that the start pointer is at the The caller should have guaranteed that the start pointer is at the
above location. above location.
Note that type is never a function type, but only the return type of
a function or the type of a variable.
*/ */
mangled += 2; mangled += 2;
mangled = dlang_parse_qualified (decl, mangled, dlang_top_level); mangled = dlang_parse_qualified (decl, mangled, info, 1);
if (mangled != NULL) if (mangled != NULL)
{ {
@ -1371,68 +1548,40 @@ dlang_parse_mangle (string *decl, const char *mangled,
mangled++; mangled++;
else else
{ {
string mods; /* Discard the declaration or return type. */
int saved; string type;
/* Skip over 'this' parameter. */ string_init (&type);
if (*mangled == 'M') mangled = dlang_type (&type, mangled, info);
mangled++; string_delete (&type);
/* Save the type modifiers for appending at the end if needed. */
string_init (&mods);
mangled = dlang_type_modifiers (&mods, mangled);
if (mangled && dlang_call_convention_p (mangled))
{
/* Skip over calling convention and attributes. */
saved = string_length (decl);
mangled = dlang_call_convention (decl, mangled);
mangled = dlang_attributes (decl, mangled);
string_setlength (decl, saved);
string_append (decl, "(");
mangled = dlang_function_args (decl, mangled);
string_append (decl, ")");
/* Add any const/immutable/shared modifier. */
string_appendn (decl, mods.b, string_length (&mods));
} }
/* Consume the decl type of symbol. */
saved = string_length (decl);
mangled = dlang_type (decl, mangled);
string_setlength (decl, saved);
string_delete (&mods);
}
}
/* Check that the entire symbol was successfully demangled. */
if (kind == dlang_top_level)
{
if (mangled == NULL || *mangled != '\0')
return NULL;
} }
return mangled; return mangled;
} }
/* Extract and demangle the qualified symbol in MANGLED and append it to DECL. /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
Returns the remaining signature on success or NULL on failure. */ Returns the remaining signature on success or NULL on failure. */
static const char * static const char *
dlang_parse_qualified (string *decl, const char *mangled, dlang_parse_qualified (string *decl, const char *mangled,
enum dlang_symbol_kinds kind) struct dlang_info *info, int suffix_modifiers)
{ {
/* Qualified names are identifiers separated by their encoded length. /* Qualified names are identifiers separated by their encoded length.
Nested functions also encode their argument types without specifying Nested functions also encode their argument types without specifying
what they return. what they return.
QualifiedName: QualifiedName:
SymbolName SymbolFunctionName
SymbolName QualifiedName SymbolFunctionName QualifiedName
SymbolName TypeFunctionNoReturn QualifiedName
SymbolName M TypeModifiers TypeFunctionNoReturn QualifiedName
^ ^
SymbolFunctionName:
SymbolName
SymbolName TypeFunctionNoReturn
SymbolName M TypeFunctionNoReturn
SymbolName M TypeModifiers TypeFunctionNoReturn
The start pointer should be at the above location. The start pointer should be at the above location.
*/ */
size_t n = 0; size_t n = 0;
@ -1445,49 +1594,45 @@ dlang_parse_qualified (string *decl, const char *mangled,
while (*mangled == '0') while (*mangled == '0')
mangled++; mangled++;
mangled = dlang_identifier (decl, mangled, kind); mangled = dlang_identifier (decl, mangled, info);
/* Consume the encoded arguments. However if this is not followed by the /* Consume the encoded arguments. However if this is not followed by the
next encoded length, then this is not a continuation of a qualified next encoded length or mangle type, then this is not a continuation of
name, in which case we backtrack and return the current unconsumed a qualified name, in which case we backtrack and return the current
position of the mangled decl. */ unconsumed position of the mangled decl. */
if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled))) if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
{ {
string mods;
const char *start = mangled; const char *start = mangled;
int saved = string_length (decl); int saved = string_length (decl);
/* Save the type modifiers for appending at the end if needed. */
string_init (&mods);
/* Skip over 'this' parameter and type modifiers. */ /* Skip over 'this' parameter and type modifiers. */
if (*mangled == 'M') if (*mangled == 'M')
{ {
mangled++; mangled++;
mangled = dlang_type_modifiers (decl, mangled); mangled = dlang_type_modifiers (&mods, mangled);
string_setlength (decl, saved); string_setlength (decl, saved);
} }
/* The rule we expect to match in the mangled string is: mangled = dlang_function_type_noreturn (decl, NULL, NULL,
mangled, info);
if (suffix_modifiers)
string_appendn (decl, mods.b, string_length (&mods));
TypeFunctionNoReturn: if (mangled == NULL || *mangled == '\0')
CallConvention FuncAttrs Arguments ArgClose
The calling convention and function attributes are not included
in the demangled string. */
mangled = dlang_call_convention (decl, mangled);
mangled = dlang_attributes (decl, mangled);
string_setlength (decl, saved);
string_append (decl, "(");
mangled = dlang_function_args (decl, mangled);
string_append (decl, ")");
if (mangled == NULL || !ISDIGIT (*mangled))
{ {
/* Did not match the rule we were looking for. */ /* Did not match the rule we were looking for. */
mangled = start; mangled = start;
string_setlength (decl, saved); string_setlength (decl, saved);
} }
string_delete (&mods);
} }
} }
while (mangled && ISDIGIT (*mangled)); while (mangled && dlang_symbol_name_p (mangled, info));
return mangled; return mangled;
} }
@ -1495,7 +1640,7 @@ dlang_parse_qualified (string *decl, const char *mangled,
/* Demangle the tuple from MANGLED and append it to DECL. /* Demangle the tuple from MANGLED and append it to DECL.
Return the remaining string on success or NULL on failure. */ Return the remaining string on success or NULL on failure. */
static const char * static const char *
dlang_parse_tuple (string *decl, const char *mangled) dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info)
{ {
long elements; long elements;
@ -1507,7 +1652,7 @@ dlang_parse_tuple (string *decl, const char *mangled)
while (elements--) while (elements--)
{ {
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
if (mangled == NULL) if (mangled == NULL)
return NULL; return NULL;
@ -1519,10 +1664,71 @@ dlang_parse_tuple (string *decl, const char *mangled)
return mangled; return mangled;
} }
/* Demangle the template symbol parameter from MANGLED and append it to DECL.
Return the remaining string on success or NULL on failure. */
static const char *
dlang_template_symbol_param (string *decl, const char *mangled,
struct dlang_info *info)
{
if (strncmp (mangled, "_D", 2) == 0
&& dlang_symbol_name_p (mangled + 2, info))
return dlang_parse_mangle (decl, mangled, info);
if (*mangled == 'Q')
return dlang_parse_qualified (decl, mangled, info, 0);
long len;
const char *endptr = dlang_number (mangled, &len);
if (endptr == NULL || len == 0)
return NULL;
/* In template parameter symbols generated by the frontend up to 2.076,
the symbol length is encoded and the first character of the mangled
name can be a digit. This causes ambiguity issues because the digits
of the two numbers are adjacent. */
long psize = len;
const char *pend;
int saved = string_length (decl);
/* Work backwards until a match is found. */
for (pend = endptr; endptr != NULL; pend--)
{
mangled = pend;
/* Reached the beginning of the pointer to the name length,
try parsing the entire symbol. */
if (psize == 0)
{
psize = len;
pend = endptr;
endptr = NULL;
}
/* Check whether template parameter is a function with a valid
return type or an untyped identifier. */
if (dlang_symbol_name_p (mangled, info))
mangled = dlang_parse_qualified (decl, mangled, info, 0);
else if (strncmp (mangled, "_D", 2) == 0
&& dlang_symbol_name_p (mangled + 2, info))
mangled = dlang_parse_mangle (decl, mangled, info);
/* Check for name length mismatch. */
if (mangled && (endptr == NULL || (mangled - pend) == psize))
return mangled;
psize /= 10;
string_setlength (decl, saved);
}
/* No match on any combinations. */
return NULL;
}
/* Demangle the argument list from MANGLED and append it to DECL. /* Demangle the argument list from MANGLED and append it to DECL.
Return the remaining string on success or NULL on failure. */ Return the remaining string on success or NULL on failure. */
static const char * static const char *
dlang_template_args (string *decl, const char *mangled) dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
{ {
size_t n = 0; size_t n = 0;
@ -1546,11 +1752,11 @@ dlang_template_args (string *decl, const char *mangled)
{ {
case 'S': /* Symbol parameter. */ case 'S': /* Symbol parameter. */
mangled++; mangled++;
mangled = dlang_identifier (decl, mangled, dlang_template_param); mangled = dlang_template_symbol_param (decl, mangled, info);
break; break;
case 'T': /* Type parameter. */ case 'T': /* Type parameter. */
mangled++; mangled++;
mangled = dlang_type (decl, mangled); mangled = dlang_type (decl, mangled, info);
break; break;
case 'V': /* Value parameter. */ case 'V': /* Value parameter. */
{ {
@ -1561,10 +1767,20 @@ dlang_template_args (string *decl, const char *mangled)
mangled++; mangled++;
type = *mangled; type = *mangled;
if (type == 'Q')
{
/* Value type is a back reference, peek at the real type. */
const char *backref;
if (dlang_backref (mangled, &backref, info) == NULL)
return NULL;
type = *backref;
}
/* In the few instances where the type is actually desired in /* In the few instances where the type is actually desired in
the output, it should precede the value from dlang_value. */ the output, it should precede the value from dlang_value. */
string_init (&name); string_init (&name);
mangled = dlang_type (&name, mangled); mangled = dlang_type (&name, mangled, info);
string_need (&name, 1); string_need (&name, 1);
*(name.p) = '\0'; *(name.p) = '\0';
@ -1572,7 +1788,20 @@ dlang_template_args (string *decl, const char *mangled)
string_delete (&name); string_delete (&name);
break; break;
} }
case 'X': /* Externally mangled parameter. */
{
long len;
const char *endptr;
mangled++;
endptr = dlang_number (mangled, &len);
if (endptr == NULL || strlen (endptr) < (size_t) len)
return NULL;
string_appendn (decl, endptr, len);
mangled = endptr + len;
break;
}
default: default:
return NULL; return NULL;
} }
@ -1582,12 +1811,14 @@ dlang_template_args (string *decl, const char *mangled)
} }
/* Extract and demangle the template symbol in MANGLED, expected to /* Extract and demangle the template symbol in MANGLED, expected to
be made up of LEN characters, and append it to DECL. be made up of LEN characters (-1 if unknown), and append it to DECL.
Returns the remaining signature on success or NULL on failure. */ Returns the remaining signature on success or NULL on failure. */
static const char * static const char *
dlang_parse_template (string *decl, const char *mangled, long len) dlang_parse_template (string *decl, const char *mangled,
struct dlang_info *info, long len)
{ {
const char *start = mangled; const char *start = mangled;
string args;
/* Template instance names have the types and values of its parameters /* Template instance names have the types and values of its parameters
encoded into it. encoded into it.
@ -1601,26 +1832,40 @@ dlang_parse_template (string *decl, const char *mangled, long len)
*/ */
/* Template symbol. */ /* Template symbol. */
if (!ISDIGIT (mangled[3]) || mangled[3] == '0') if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0')
return NULL; return NULL;
mangled += 3; mangled += 3;
/* Template identifier. */ /* Template identifier. */
mangled = dlang_identifier (decl, mangled, dlang_template_ident); mangled = dlang_identifier (decl, mangled, info);
/* Template arguments. */ /* Template arguments. */
string_init (&args);
mangled = dlang_template_args (&args, mangled, info);
string_append (decl, "!("); string_append (decl, "!(");
mangled = dlang_template_args (decl, mangled); string_appendn (decl, args.b, string_length (&args));
string_append (decl, ")"); string_append (decl, ")");
string_delete (&args);
/* Check for template name length mismatch. */ /* Check for template name length mismatch. */
if (mangled && (mangled - start) != len) if (len != TEMPLATE_LENGTH_UNKNOWN && mangled && (mangled - start) != len)
return NULL; return NULL;
return mangled; return mangled;
} }
/* Initialize the information structure we use to pass around information. */
static void
dlang_demangle_init_info (const char *mangled, int last_backref,
struct dlang_info *info)
{
info->s = mangled;
info->last_backref = last_backref;
}
/* Extract and demangle the symbol in MANGLED. Returns the demangled /* Extract and demangle the symbol in MANGLED. Returns the demangled
signature on success or NULL on failure. */ signature on success or NULL on failure. */
@ -1644,7 +1889,13 @@ dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
} }
else else
{ {
if (dlang_parse_mangle (&decl, mangled, dlang_top_level) == NULL) struct dlang_info info;
dlang_demangle_init_info (mangled, strlen (mangled), &info);
mangled = dlang_parse_mangle (&decl, mangled, &info);
/* Check that the entire symbol was successfully demangled. */
if (mangled == NULL || *mangled != '\0')
string_delete (&decl); string_delete (&decl);
} }

View File

@ -84,6 +84,23 @@ is respectively less than, matching, or greater than the array member.
@end deftypefn @end deftypefn
@c bsearch_r.c:33
@deftypefn Supplemental void* bsearch_r (const void *@var{key}, @
const void *@var{base}, size_t @var{nmemb}, size_t @var{size}, @
int (*@var{compar})(const void *, const void *, void *), void *@var{arg})
Performs a search over an array of @var{nmemb} elements pointed to by
@var{base} for a member that matches the object pointed to by @var{key}.
The size of each member is specified by @var{size}. The array contents
should be sorted in ascending order according to the @var{compar}
comparison function. This routine should take three arguments: the first
two point to the @var{key} and to an array member, and the last is passed
down unchanged from @code{bsearch_r}'s last argument. It should return an
integer less than, equal to, or greater than zero if the @var{key} object
is respectively less than, matching, or greater than the array member.
@end deftypefn
@c argv.c:138 @c argv.c:138
@deftypefn Extension char** buildargv (char *@var{sp}) @deftypefn Extension char** buildargv (char *@var{sp})
@ -175,7 +192,7 @@ Concatenate zero or more of strings and return the result in freshly
@end deftypefn @end deftypefn
@c argv.c:487 @c argv.c:495
@deftypefn Extension int countargv (char * const *@var{argv}) @deftypefn Extension int countargv (char * const *@var{argv})
Return the number of elements in @var{argv}. Return the number of elements in @var{argv}.
@ -240,7 +257,7 @@ symbolic name or message.
@end deftypefn @end deftypefn
@c argv.c:344 @c argv.c:352
@deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp}) @deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
The @var{argcp} and @code{argvp} arguments are pointers to the usual The @var{argcp} and @code{argvp} arguments are pointers to the usual

View File

@ -462,6 +462,10 @@ _D8demangle4testFDFNiZaZv
demangle.test(char() @nogc delegate) demangle.test(char() @nogc delegate)
# #
--format=dlang --format=dlang
_D8demangle4testFDFNmZaZv
demangle.test(char() @live delegate)
#
--format=dlang
_D8demangle4testFDFNaNbZaZv _D8demangle4testFDFNaNbZaZv
demangle.test(char() pure nothrow delegate) demangle.test(char() pure nothrow delegate)
# #
@ -538,6 +542,10 @@ _D8demangle4testFPFNiZaZv
demangle.test(char() @nogc function) demangle.test(char() @nogc function)
# #
--format=dlang --format=dlang
_D8demangle4testFPFNmZaZv
demangle.test(char() @live function)
#
--format=dlang
_D8demangle4testFPFNaNbZaZv _D8demangle4testFPFNaNbZaZv
demangle.test(char() pure nothrow function) demangle.test(char() pure nothrow function)
# #
@ -1326,3 +1334,75 @@ _D1_B699999999961*
--format=dlang --format=dlang
_D5__T1fVHacA6666666666_ _D5__T1fVHacA6666666666_
_D5__T1fVHacA6666666666_ _D5__T1fVHacA6666666666_
#
--format=dlang
_D3std5range15__T4iotaTtTtTtZ4iotaFtttZ6Result7opIndexMNgFNaNbNiNfmZNgt
std.range.iota!(ushort, ushort, ushort).iota(ushort, ushort, ushort).Result.opIndex(ulong) inout
#
--format=dlang
_D3std6format77__T6getNthVAyaa13_696e7465676572207769647468S233std6traits10isIntegralTiTkTkZ6getNthFNaNfkkkZi
std.format.getNth!("integer width", std.traits.isIntegral, int, uint, uint).getNth(uint, uint, uint)
#
--format=dlang
_D3std11parallelism42__T16RoundRobinBufferTDFKAaZvTDxFNaNdNeZbZ16RoundRobinBuffer5primeMFZv
std.parallelism.RoundRobinBuffer!(void(ref char[]) delegate, bool() pure @property @trusted delegate const).RoundRobinBuffer.prime()
#
--format=dlang
_D4core4stdc5errnoQgFZi
core.stdc.errno.errno()
#
--format=dlang
_D4testFS10structnameQnZb
test(structname, structname)
#
--format=dlang
_D3std11parallelism__T4TaskS8unittest3cmpTAyaTQeZQBb6__dtorMFNfZv
std.parallelism.Task!(unittest.cmp, immutable(char)[], immutable(char)[]).Task.~this()
#
--format=dlang
_D13testexpansion44__T1sTS13testexpansion8__T1sTiZ1sFiZ6ResultZ1sFS13testexpansion8__T1sTiZ1sFiZ6ResultZ6Result3fooMFNaNfZv
testexpansion.s!(testexpansion.s!(int).s(int).Result).s(testexpansion.s!(int).s(int).Result).Result.foo()
#
--format=dlang
_D13testexpansion__T1sTSQw__TQjTiZQoFiZ6ResultZQBbFQBcZQq3fooMFNaNfZv
testexpansion.s!(testexpansion.s!(int).s(int).Result).s(testexpansion.s!(int).s(int).Result).Result.foo()
#
--format=dlang
_D3std4conv__T7enumRepTyAaTEQBa12experimental9allocator15building_blocks15stats_collector7OptionsVQCti64ZQDnyQDh
std.conv.enumRep!(immutable(char[]), std.experimental.allocator.building_blocks.stats_collector.Options, 64).enumRep
#
--format=dlang
_D3std12experimental9allocator6common__T10reallocateTSQCaQBzQBo15building_blocks17kernighan_ritchie__T8KRRegionTSQEhQEgQDvQCh14null_allocator13NullAllocatorZQCdZQErFNaNbNiKQEpKAvmZb
std.experimental.allocator.common.reallocate!(std.experimental.allocator.building_blocks.kernighan_ritchie.KRRegion!(std.experimental.allocator.building_blocks.null_allocator.NullAllocator).KRRegion).reallocate(ref std.experimental.allocator.building_blocks.kernighan_ritchie.KRRegion!(std.experimental.allocator.building_blocks.null_allocator.NullAllocator).KRRegion, ref void[], ulong)
#
--format=dlang
_D3std9exception__T11doesPointToTASQBh5regex8internal2ir10NamedGroupTQBkTvZQCeFNaNbNiNeKxASQDlQCeQCbQBvQBvKxQtZb
std.exception.doesPointTo!(std.regex.internal.ir.NamedGroup[], std.regex.internal.ir.NamedGroup[], void).doesPointTo(ref const(std.regex.internal.ir.NamedGroup[]), ref const(std.regex.internal.ir.NamedGroup[]))
#
--format=dlang
_D3std9algorithm9iteration__T14SplitterResultS_DQBu3uni7isWhiteFNaNbNiNfwZbTAyaZQBz9__xtoHashFNbNeKxSQDvQDuQDn__TQDgS_DQEnQCtQCsQCnTQCeZQEdZm
std.algorithm.iteration.SplitterResult!(std.uni.isWhite(dchar), immutable(char)[]).SplitterResult.__xtoHash(ref const(std.algorithm.iteration.SplitterResult!(std.uni.isWhite, immutable(char)[]).SplitterResult))
#
--format=dlang
_D3std8typecons__T7TypedefTCQBaQz19__unittestL6513_208FNfZ7MyClassVQBonVAyanZQCh6__ctorMFNaNbNcNiNfQCuZSQDyQDx__TQDrTQDmVQDqnVQCcnZQEj
std.typecons.Typedef!(std.typecons.__unittestL6513_208().MyClass, null, null).Typedef.this(std.typecons.__unittestL6513_208().MyClass)
#
--format=dlang
_D3std6getopt__TQkTAyaTDFNaNbNiNfQoZvTQtTDQsZQBnFNfKAQBiQBlQBkQBrQyZSQCpQCo12GetoptResult
std.getopt.getopt!(immutable(char)[], void(immutable(char)[]) pure nothrow @nogc @safe delegate, immutable(char)[], void(immutable(char)[]) pure nothrow @nogc @safe delegate).getopt(ref immutable(char)[][], immutable(char)[], void(immutable(char)[]) pure nothrow @nogc @safe delegate, immutable(char)[], void(immutable(char)[]) pure nothrow @nogc @safe delegate)
#
--format=dlang
_D3std5regex8internal9kickstart__T7ShiftOrTaZQl11ShiftThread__T3setS_DQCqQCpQCmQCg__TQBzTaZQCfQBv10setInvMaskMFNaNbNiNfkkZvZQCjMFNaNfwZv
std.regex.internal.kickstart.ShiftOr!(char).ShiftOr.ShiftThread.set!(std.regex.internal.kickstart.ShiftOr!(char).ShiftOr.ShiftThread.setInvMask(uint, uint)).set(dchar)
#
--format=dlang
_D3std5stdio4File__T8lockImplX10LockFileExTykZQBaMFmmykZi
std.stdio.File.lockImpl!(LockFileEx, immutable(uint)).lockImpl(ulong, ulong, immutable(uint))
#
--format=dlang
_D3std9algorithm9iteration__T12FilterResultSQBq8typecons__T5TupleTiVAyaa1_61TiVQla1_62TiVQva1_63ZQBm__T6renameVHiQBtA2i0a1_63i2a1_61ZQBeMFNcZ9__lambda1TAiZQEw9__xtoHashFNbNeKxSQGsQGrQGk__TQGdSQHiQFs__TQFmTiVQFja1_61TiVQFua1_62TiVQGfa1_63ZQGx__TQFlVQFhA2i0a1_63i2a1_61ZQGjMFNcZQFfTQEyZQJvZm
std.algorithm.iteration.FilterResult!(std.typecons.Tuple!(int, "a", int, "b", int, "c").Tuple.rename!([0:"c", 2:"a"]).rename().__lambda1, int[]).FilterResult.__xtoHash(ref const(std.algorithm.iteration.FilterResult!(std.typecons.Tuple!(int, "a", int, "b", int, "c").Tuple.rename!([0:"c", 2:"a"]).rename().__lambda1, int[]).FilterResult))
#
--format=dlang
_D3std3uni__T6toCaseS_DQvQt12toLowerIndexFNaNbNiNewZtVii1043S_DQCjQCi10toLowerTabFNaNbNiNemZwSQDo5ascii7toLowerTAyaZQDzFNaNeQmZ14__foreachbody2MFNaNeKmKwZ14__foreachbody3MFNaNeKwZi
std.uni.toCase!(std.uni.toLowerIndex(dchar), 1043, std.uni.toLowerTab(ulong), std.ascii.toLower, immutable(char)[]).toCase(immutable(char)[]).__foreachbody2(ref ulong, ref dchar).__foreachbody3(ref dchar)