Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Jun 2017 22:39:28 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r320343 - in head/contrib/elftoolchain: elfdump libelftc
Message-ID:  <201706252239.v5PMdS2N052163@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Sun Jun 25 22:39:28 2017
New Revision: 320343
URL: https://svnweb.freebsd.org/changeset/base/320343

Log:
  Update to ELF Tool Chain snapshot at r3561
  
  This update is primarily bug fixes in C++ symbol demangling, including:
  
  - rvalue reference
  - builtin type auto and decltype(auto)
  - revamped support for function return types
  - formatting fixes
  - omit void when its the only param
  - ref-qualifiers and others in function types
  - type qualifiers in pointer-to-member function types
  - incorrect handling regarding CV-qualifiers in function types
  - ref-qualifier found in nested-name
  - properly handle <name> ::= <substitute><template-args>
  - make sure that nested function name is not a substitute candidate
  - correctly handle expression in template args
  - skip unknown substitution abbreviations
  
  MFC after:	4 days

Modified:
  head/contrib/elftoolchain/elfdump/elfdump.c
  head/contrib/elftoolchain/libelftc/_libelftc.h
  head/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
  head/contrib/elftoolchain/libelftc/libelftc_vstr.c
Directory Properties:
  head/contrib/elftoolchain/   (props changed)
  head/contrib/elftoolchain/elfdump/   (props changed)

Modified: head/contrib/elftoolchain/elfdump/elfdump.c
==============================================================================
--- head/contrib/elftoolchain/elfdump/elfdump.c	Sun Jun 25 22:19:34 2017	(r320342)
+++ head/contrib/elftoolchain/elfdump/elfdump.c	Sun Jun 25 22:39:28 2017	(r320343)
@@ -50,7 +50,7 @@
 
 #include "_elftc.h"
 
-ELFTC_VCSID("$Id: elfdump.c 3497 2016-10-17 20:57:22Z emaste $");
+ELFTC_VCSID("$Id: elfdump.c 3521 2017-06-04 20:07:09Z jkoshy $");
 
 #if defined(ELFTC_NEED_ELF_NOTE_DEFINITION)
 #include "native-elf-format.h"
@@ -2226,8 +2226,8 @@ elf_print_svr4_hash64(struct elfdump *ed, struct secti
 	uint64_t	*buf;
 	uint64_t	*bucket, *chain;
 	uint64_t	 nbucket, nchain;
-	uint64_t	*bl, *c, maxl, total;
-	uint64_t	 i, j;
+	uint64_t	*bl, *c, j, maxl, total;
+	size_t		 i;
 	int		 elferr, first;
 	char		 idx[10];
 

Modified: head/contrib/elftoolchain/libelftc/_libelftc.h
==============================================================================
--- head/contrib/elftoolchain/libelftc/_libelftc.h	Sun Jun 25 22:19:34 2017	(r320342)
+++ head/contrib/elftoolchain/libelftc/_libelftc.h	Sun Jun 25 22:39:28 2017	(r320343)
@@ -24,7 +24,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $Id: _libelftc.h 3174 2015-03-27 17:13:41Z emaste $
+ * $Id: _libelftc.h 3531 2017-06-05 05:08:43Z kaiwang27 $
  */
 
 #ifndef	__LIBELFTC_H_
@@ -82,6 +82,8 @@ bool	vector_str_init(struct vector_str *_vs);
 bool	vector_str_pop(struct vector_str *_vs);
 bool	vector_str_push(struct vector_str *_vs, const char *_str,
     size_t _len);
+bool	vector_str_push_vector(struct vector_str *_dst,
+    struct vector_str *_org);
 bool	vector_str_push_vector_head(struct vector_str *_dst,
     struct vector_str *_org);
 char	*vector_str_substr(const struct vector_str *_vs, size_t _begin,

Modified: head/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
==============================================================================
--- head/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c	Sun Jun 25 22:19:34 2017	(r320342)
+++ head/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c	Sun Jun 25 22:39:28 2017	(r320343)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
+ * Copyright (c) 2015-2017 Kai Wang <kaiwang27@gmail.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,7 +37,7 @@
 
 #include "_libelftc.h"
 
-ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3512 2016-12-29 07:04:19Z kaiwang27 $");
+ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3560 2017-06-25 00:28:23Z kaiwang27 $");
 
 /**
  * @file cpp_demangle.c
@@ -50,7 +51,7 @@ ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3512 2016-12-29 
 
 enum type_qualifier {
 	TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
-	TYPE_CST, TYPE_VEC
+	TYPE_CST, TYPE_VEC, TYPE_RREF
 };
 
 struct vector_type_qualifier {
@@ -64,29 +65,49 @@ enum read_cmd {
 	READ_TYPE, READ_FUNC, READ_PTRMEM
 };
 
+struct read_cmd_item {
+	enum read_cmd cmd;
+	void *data;
+};
+
 struct vector_read_cmd {
 	size_t size, capacity;
-	enum read_cmd *r_container;
+	struct read_cmd_item *r_container;
 };
 
+enum push_qualifier {
+	PUSH_ALL_QUALIFIER,
+	PUSH_CV_QUALIFIER,
+	PUSH_NON_CV_QUALIFIER,
+};
+
 struct cpp_demangle_data {
 	struct vector_str	 output;	/* output string vector */
-	struct vector_str	 output_tmp;
 	struct vector_str	 subst;		/* substitution string vector */
 	struct vector_str	 tmpl;
 	struct vector_str	 class_type;
+	struct vector_str	*cur_output;	/* ptr to current output vec */
 	struct vector_read_cmd	 cmd;
-	bool			 paren;		/* parenthesis opened */
-	bool			 pfirst;	/* first element of parameter */
 	bool			 mem_rst;	/* restrict member function */
 	bool			 mem_vat;	/* volatile member function */
 	bool			 mem_cst;	/* const member function */
+	bool			 mem_ref;	/* lvalue-ref member func */
+	bool			 mem_rref;	/* rvalue-ref member func */
+	bool			 is_tmpl;	/* template args */
+	bool			 is_functype;	/* function type */
+	bool			 ref_qualifier; /* ref qualifier */
+	enum type_qualifier	 ref_qualifier_type; /* ref qualifier type */
+	enum push_qualifier	 push_qualifier; /* which qualifiers to push */
 	int			 func_type;
 	const char		*cur;		/* current mangled name ptr */
 	const char		*last_sname;	/* last source name */
-	int			 push_head;
 };
 
+struct type_delimit {
+	bool paren;
+	bool firstp;
+};
+
 #define	CPP_DEMANGLE_TRY_LIMIT	128
 #define	FLOAT_SPRINTF_TRY_LIMIT	5
 #define	FLOAT_QUADRUPLE_BYTES	16
@@ -105,6 +126,7 @@ static int	cpp_demangle_push_fp(struct cpp_demangle_da
 		    char *(*)(const char *, size_t));
 static int	cpp_demangle_push_str(struct cpp_demangle_data *, const char *,
 		    size_t);
+static int	cpp_demangle_pop_str(struct cpp_demangle_data *);
 static int	cpp_demangle_push_subst(struct cpp_demangle_data *,
 		    const char *, size_t);
 static int	cpp_demangle_push_subst_v(struct cpp_demangle_data *,
@@ -137,16 +159,18 @@ static int	cpp_demangle_read_number_as_string(struct c
 static int	cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
 static int	cpp_demangle_read_offset(struct cpp_demangle_data *);
 static int	cpp_demangle_read_offset_number(struct cpp_demangle_data *);
-static int	cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *);
+static int	cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *,
+		    struct vector_type_qualifier *);
 static int	cpp_demangle_read_sname(struct cpp_demangle_data *);
 static int	cpp_demangle_read_subst(struct cpp_demangle_data *);
 static int	cpp_demangle_read_subst_std(struct cpp_demangle_data *);
 static int	cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *,
-		    const char *, size_t);
+		    const char *);
 static int	cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
 static int	cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
 static int	cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
-static int	cpp_demangle_read_type(struct cpp_demangle_data *, int);
+static int	cpp_demangle_read_type(struct cpp_demangle_data *,
+		    struct type_delimit *);
 static int	cpp_demangle_read_type_flat(struct cpp_demangle_data *,
 		    char **);
 static int	cpp_demangle_read_uqname(struct cpp_demangle_data *);
@@ -158,10 +182,12 @@ static char	*decode_fp_to_float80(const char *, size_t
 static char	*decode_fp_to_long_double(const char *, size_t);
 static int	hex_to_dec(char);
 static void	vector_read_cmd_dest(struct vector_read_cmd *);
-static int	vector_read_cmd_find(struct vector_read_cmd *, enum read_cmd);
+static struct read_cmd_item *vector_read_cmd_find(struct vector_read_cmd *,
+		    enum read_cmd);
 static int	vector_read_cmd_init(struct vector_read_cmd *);
 static int	vector_read_cmd_pop(struct vector_read_cmd *);
-static int	vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd);
+static int	vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd,
+		    void *);
 static void	vector_type_qualifier_dest(struct vector_type_qualifier *);
 static int	vector_type_qualifier_init(struct vector_type_qualifier *);
 static int	vector_type_qualifier_push(struct vector_type_qualifier *,
@@ -178,9 +204,12 @@ char *
 cpp_demangle_gnu3(const char *org)
 {
 	struct cpp_demangle_data ddata;
+	struct vector_str ret_type;
+	struct type_delimit td;
 	ssize_t org_len;
 	unsigned int limit;
 	char *rtn;
+	bool has_ret, more_type;
 
 	if (org == NULL || (org_len = strlen(org)) < 2)
 		return (NULL);
@@ -200,26 +229,75 @@ cpp_demangle_gnu3(const char *org)
 		return (NULL);
 
 	rtn = NULL;
+	has_ret = more_type = false;
 
 	if (!cpp_demangle_read_encoding(&ddata))
 		goto clean;
 
+	/*
+	 * Pop function name from substitution candidate list.
+	 */
+	if (*ddata.cur != 0 && ddata.subst.size >= 1) {
+		if (!vector_str_pop(&ddata.subst))
+			goto clean;
+	}
+
+	td.paren = false;
+	td.firstp = true;
 	limit = 0;
+
+	/*
+	 * The first type is a return type if we just demangled template
+	 * args. (the template args is right next to the function name,
+	 * which means it's a template function)
+	 */
+	if (ddata.is_tmpl) {
+		ddata.is_tmpl = false;
+		if (!vector_str_init(&ret_type))
+			goto clean;
+		ddata.cur_output = &ret_type;
+		has_ret = true;
+	}
+
 	while (*ddata.cur != '\0') {
 		/*
 		 * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4
 		 */
 		if (*ddata.cur == '@' && *(ddata.cur + 1) == '@')
 			break;
-		if (!cpp_demangle_read_type(&ddata, 1))
-			goto clean;
+
+		if (has_ret) {
+			/* Read return type */
+			if (!cpp_demangle_read_type(&ddata, NULL))
+				goto clean;
+		} else {
+			/* Read function arg type */
+			if (!cpp_demangle_read_type(&ddata, &td))
+				goto clean;
+		}
+
+		if (has_ret) {
+			/* Push return type to the beginning */
+			if (!VEC_PUSH_STR(&ret_type, " "))
+				goto clean;
+			if (!vector_str_push_vector_head(&ddata.output,
+			    &ret_type))
+				goto clean;
+			ddata.cur_output = &ddata.output;
+			vector_str_dest(&ret_type);
+			has_ret = false;
+			more_type = true;
+		} else if (more_type)
+			more_type = false;
 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
 			goto clean;
 	}
+	if (more_type)
+		goto clean;
 
 	if (ddata.output.size == 0)
 		goto clean;
-	if (ddata.paren && !VEC_PUSH_STR(&ddata.output, ")"))
+	if (td.paren && !VEC_PUSH_STR(&ddata.output, ")"))
 		goto clean;
 	if (ddata.mem_vat && !VEC_PUSH_STR(&ddata.output, " volatile"))
 		goto clean;
@@ -227,10 +305,17 @@ cpp_demangle_gnu3(const char *org)
 		goto clean;
 	if (ddata.mem_rst && !VEC_PUSH_STR(&ddata.output, " restrict"))
 		goto clean;
+	if (ddata.mem_ref && !VEC_PUSH_STR(&ddata.output, " &"))
+		goto clean;
+	if (ddata.mem_rref && !VEC_PUSH_STR(&ddata.output, " &&"))
+		goto clean;
 
 	rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
 
 clean:
+	if (has_ret)
+		vector_str_dest(&ret_type);
+
 	cpp_demangle_data_dest(&ddata);
 
 	return (rtn);
@@ -247,7 +332,6 @@ cpp_demangle_data_dest(struct cpp_demangle_data *d)
 	vector_str_dest(&d->class_type);
 	vector_str_dest(&d->tmpl);
 	vector_str_dest(&d->subst);
-	vector_str_dest(&d->output_tmp);
 	vector_str_dest(&d->output);
 }
 
@@ -260,43 +344,42 @@ cpp_demangle_data_init(struct cpp_demangle_data *d, co
 
 	if (!vector_str_init(&d->output))
 		return (0);
-	if (!vector_str_init(&d->output_tmp))
-		goto clean1;
 	if (!vector_str_init(&d->subst))
-		goto clean2;
+		goto clean1;
 	if (!vector_str_init(&d->tmpl))
-		goto clean3;
+		goto clean2;
 	if (!vector_str_init(&d->class_type))
-		goto clean4;
+		goto clean3;
 	if (!vector_read_cmd_init(&d->cmd))
-		goto clean5;
+		goto clean4;
 
 	assert(d->output.container != NULL);
-	assert(d->output_tmp.container != NULL);
 	assert(d->subst.container != NULL);
 	assert(d->tmpl.container != NULL);
 	assert(d->class_type.container != NULL);
 
-	d->paren = false;
-	d->pfirst = false;
 	d->mem_rst = false;
 	d->mem_vat = false;
 	d->mem_cst = false;
+	d->mem_ref = false;
+	d->mem_rref = false;
+	d->is_tmpl = false;
+	d->is_functype = false;
+	d->ref_qualifier = false;
+	d->push_qualifier = PUSH_ALL_QUALIFIER;
 	d->func_type = 0;
 	d->cur = cur;
+	d->cur_output = &d->output;
 	d->last_sname = NULL;
-	d->push_head = 0;
 
 	return (1);
 
-clean5:
-	vector_str_dest(&d->class_type);
 clean4:
-	vector_str_dest(&d->tmpl);
+	vector_str_dest(&d->class_type);
 clean3:
-	vector_str_dest(&d->subst);
+	vector_str_dest(&d->tmpl);
 clean2:
-	vector_str_dest(&d->output_tmp);
+	vector_str_dest(&d->subst);
 clean1:
 	vector_str_dest(&d->output);
 
@@ -341,13 +424,27 @@ cpp_demangle_push_str(struct cpp_demangle_data *ddata,
 	if (ddata == NULL || str == NULL || len == 0)
 		return (0);
 
-	if (ddata->push_head > 0)
-		return (vector_str_push(&ddata->output_tmp, str, len));
+	/*
+	 * is_tmpl is used to check if the type (function arg) is right next
+	 * to template args, and should always be cleared whenever new string
+	 * pushed.
+	 */
+	ddata->is_tmpl = false;
 
-	return (vector_str_push(&ddata->output, str, len));
+	return (vector_str_push(ddata->cur_output, str, len));
 }
 
 static int
+cpp_demangle_pop_str(struct cpp_demangle_data *ddata)
+{
+
+	if (ddata == NULL)
+		return (0);
+
+	return (vector_str_pop(ddata->cur_output));
+}
+
+static int
 cpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str,
     size_t len)
 {
@@ -386,9 +483,11 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
     struct vector_type_qualifier *v, const char *type_str)
 {
 	struct vector_str subst_v;
+	enum type_qualifier t;
 	size_t idx, e_idx, e_len;
-	int rtn;
 	char *buf;
+	int rtn;
+	bool cv;
 
 	if (ddata == NULL || v == NULL)
 		return (0);
@@ -404,10 +503,14 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			goto clean;
 	}
 
+	cv = true;
 	e_idx = 0;
 	while (idx > 0) {
 		switch (v->q_container[idx - 1]) {
 		case TYPE_PTR:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
 			if (!DEM_PUSH_STR(ddata, "*"))
 				goto clean;
 			if (type_str != NULL) {
@@ -420,6 +523,9 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_REF:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
 			if (!DEM_PUSH_STR(ddata, "&"))
 				goto clean;
 			if (type_str != NULL) {
@@ -431,7 +537,25 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			}
 			break;
 
+		case TYPE_RREF:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, "&&"))
+				goto clean;
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, "&&"))
+					goto clean;
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v))
+					goto clean;
+			}
+			break;
+
 		case TYPE_CMX:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
 			if (!DEM_PUSH_STR(ddata, " complex"))
 				goto clean;
 			if (type_str != NULL) {
@@ -444,6 +568,9 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_IMG:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
 			if (!DEM_PUSH_STR(ddata, " imaginary"))
 				goto clean;
 			if (type_str != NULL) {
@@ -457,6 +584,9 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_EXT:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
 			if (v->ext_name.size == 0 ||
 			    e_idx > v->ext_name.size - 1)
 				goto clean;
@@ -489,11 +619,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_RST:
+			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
+			    cv)
+				break;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
+				break;
 			if (!DEM_PUSH_STR(ddata, " restrict"))
 				goto clean;
 			if (type_str != NULL) {
 				if (!VEC_PUSH_STR(&subst_v, " restrict"))
 					goto clean;
+				if (idx - 1 > 0) {
+					t = v->q_container[idx - 2];
+					if (t == TYPE_RST || t == TYPE_VAT ||
+					    t == TYPE_CST)
+						break;
+				}
 				if (!cpp_demangle_push_subst_v(ddata,
 				    &subst_v))
 					goto clean;
@@ -501,11 +642,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_VAT:
+			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
+			    cv)
+				break;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
+				break;
 			if (!DEM_PUSH_STR(ddata, " volatile"))
 				goto clean;
 			if (type_str != NULL) {
 				if (!VEC_PUSH_STR(&subst_v, " volatile"))
 					goto clean;
+				if (idx - 1 > 0) {
+					t = v->q_container[idx - 2];
+					if (t == TYPE_RST || t == TYPE_VAT ||
+					    t == TYPE_CST)
+						break;
+				}
 				if (!cpp_demangle_push_subst_v(ddata,
 				    &subst_v))
 					goto clean;
@@ -513,11 +665,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_CST:
+			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
+			    cv)
+				break;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
+				break;
 			if (!DEM_PUSH_STR(ddata, " const"))
 				goto clean;
 			if (type_str != NULL) {
 				if (!VEC_PUSH_STR(&subst_v, " const"))
 					goto clean;
+				if (idx - 1 > 0) {
+					t = v->q_container[idx - 2];
+					if (t == TYPE_RST || t == TYPE_VAT ||
+					    t == TYPE_CST)
+						break;
+				}
 				if (!cpp_demangle_push_subst_v(ddata,
 				    &subst_v))
 					goto clean;
@@ -525,6 +688,9 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_VEC:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
 			if (v->ext_name.size == 0 ||
 			    e_idx > v->ext_name.size - 1)
 				goto clean;
@@ -614,7 +780,7 @@ cpp_demangle_read_array(struct cpp_demangle_data *ddat
 		if (*(++ddata->cur) == '\0')
 			return (0);
 
-		if (!cpp_demangle_read_type(ddata, 0))
+		if (!cpp_demangle_read_type(ddata, NULL))
 			return (0);
 
 		if (!DEM_PUSH_STR(ddata, "[]"))
@@ -630,7 +796,7 @@ cpp_demangle_read_array(struct cpp_demangle_data *ddat
 			assert(num_len > 0);
 			if (*(++ddata->cur) == '\0')
 				return (0);
-			if (!cpp_demangle_read_type(ddata, 0))
+			if (!cpp_demangle_read_type(ddata, NULL))
 				return (0);
 			if (!DEM_PUSH_STR(ddata, "["))
 				return (0);
@@ -660,7 +826,7 @@ cpp_demangle_read_array(struct cpp_demangle_data *ddat
 				free(exp);
 				return (0);
 			}
-			if (!cpp_demangle_read_type(ddata, 0)) {
+			if (!cpp_demangle_read_type(ddata, NULL)) {
 				free(exp);
 				return (0);
 			}
@@ -777,11 +943,11 @@ cpp_demangle_read_expression(struct cpp_demangle_data 
 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
 	case SIMPLE_HASH('s', 't'):
 		ddata->cur += 2;
-		return (cpp_demangle_read_type(ddata, 0));
+		return (cpp_demangle_read_type(ddata, NULL));
 
 	case SIMPLE_HASH('s', 'r'):
 		ddata->cur += 2;
-		if (!cpp_demangle_read_type(ddata, 0))
+		if (!cpp_demangle_read_type(ddata, NULL))
 			return (0);
 		if (!cpp_demangle_read_uqname(ddata))
 			return (0);
@@ -1058,8 +1224,7 @@ cpp_demangle_read_expression_flat(struct cpp_demangle_
 	size_t i, p_idx, idx, exp_len;
 	char *exp;
 
-	output = ddata->push_head > 0 ? &ddata->output_tmp :
-	    &ddata->output;
+	output = &ddata->output;
 
 	p_idx = output->size;
 
@@ -1136,8 +1301,12 @@ static int
 cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
     struct vector_type_qualifier *v)
 {
+	struct type_delimit td;
+	struct read_cmd_item *rc;
 	size_t class_type_size, class_type_len, limit;
 	const char *class_type;
+	int i;
+	bool paren, non_cv_qualifier;
 
 	if (ddata == NULL || *ddata->cur != 'F' || v == NULL)
 		return (0);
@@ -1148,12 +1317,43 @@ cpp_demangle_read_function(struct cpp_demangle_data *d
 			*ext_c = 1;
 		++ddata->cur;
 	}
-	if (!cpp_demangle_read_type(ddata, 0))
+
+	/* Return type */
+	if (!cpp_demangle_read_type(ddata, NULL))
 		return (0);
+
 	if (*ddata->cur != 'E') {
-		if (!DEM_PUSH_STR(ddata, "("))
+		if (!DEM_PUSH_STR(ddata, " "))
 			return (0);
-		if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM)) {
+
+		non_cv_qualifier = false;
+		if (v->size > 0) {
+			for (i = 0; (size_t) i < v->size; i++) {
+				if (v->q_container[i] != TYPE_RST &&
+				    v->q_container[i] != TYPE_VAT &&
+				    v->q_container[i] != TYPE_CST) {
+					non_cv_qualifier = true;
+					break;
+				}
+			}
+		}
+
+		paren = false;
+		rc = vector_read_cmd_find(&ddata->cmd, READ_PTRMEM);
+		if (non_cv_qualifier || rc != NULL) {
+			if (!DEM_PUSH_STR(ddata, "("))
+				return (0);
+			paren = true;
+		}
+
+		/* Push non-cv qualifiers. */
+		ddata->push_qualifier = PUSH_NON_CV_QUALIFIER;
+		if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
+			return (0);
+
+		if (rc) {
+			if (non_cv_qualifier && !DEM_PUSH_STR(ddata, " "))
+				return (0);
 			if ((class_type_size = ddata->class_type.size) == 0)
 				return (0);
 			class_type =
@@ -1167,40 +1367,67 @@ cpp_demangle_read_function(struct cpp_demangle_data *d
 				return (0);
 			if (!DEM_PUSH_STR(ddata, "::*"))
 				return (0);
+			/* Push pointer-to-member qualifiers. */
+			ddata->push_qualifier = PUSH_ALL_QUALIFIER;
+			if (!cpp_demangle_push_type_qualifier(ddata, rc->data,
+			    NULL))
+				return (0);
 			++ddata->func_type;
-		} else {
-			if (!cpp_demangle_push_type_qualifier(ddata, v,
-			    (const char *) NULL))
+		}
+
+		if (paren) {
+			if (!DEM_PUSH_STR(ddata, ")"))
 				return (0);
-			vector_type_qualifier_dest(v);
-			if (!vector_type_qualifier_init(v))
-				return (0);
+			paren = false;
 		}
 
-		if (!DEM_PUSH_STR(ddata, ")("))
-			return (0);
-
+		td.paren = false;
+		td.firstp = true;
 		limit = 0;
+		ddata->is_functype = true;
 		for (;;) {
-			if (!cpp_demangle_read_type(ddata, 0))
+			if (!cpp_demangle_read_type(ddata, &td))
 				return (0);
 			if (*ddata->cur == 'E')
 				break;
 			if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
 				return (0);
 		}
-
-		if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM) == 1) {
-			if (!cpp_demangle_push_type_qualifier(ddata, v,
-			    (const char *) NULL))
+		ddata->is_functype = false;
+		if (td.paren) {
+			if (!DEM_PUSH_STR(ddata, ")"))
 				return (0);
-			vector_type_qualifier_dest(v);
-			if (!vector_type_qualifier_init(v))
-				return (0);
+			td.paren = false;
 		}
 
-		if (!DEM_PUSH_STR(ddata, ")"))
+		/* Push CV qualifiers. */
+		ddata->push_qualifier = PUSH_CV_QUALIFIER;
+		if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
 			return (0);
+
+		ddata->push_qualifier = PUSH_ALL_QUALIFIER;
+
+		/* Release type qualifier vector. */
+		vector_type_qualifier_dest(v);
+		if (!vector_type_qualifier_init(v))
+			return (0);
+
+		/* Push ref-qualifiers. */
+		if (ddata->ref_qualifier) {
+			switch (ddata->ref_qualifier_type) {
+			case TYPE_REF:
+				if (!DEM_PUSH_STR(ddata, " &"))
+					return (0);
+				break;
+			case TYPE_RREF:
+				if (!DEM_PUSH_STR(ddata, " &&"))
+					return (0);
+				break;
+			default:
+				return (0);
+			}
+			ddata->ref_qualifier = false;
+		}
 	}
 
 	++ddata->cur;
@@ -1306,7 +1533,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 			goto clean3;
 		if (*ddata->cur++ != '_')
 			goto clean3;
-		if (!cpp_demangle_read_type(ddata, 0))
+		if (!cpp_demangle_read_type(ddata, NULL))
 			goto clean3;
 		if (!DEM_PUSH_STR(ddata, "-in-"))
 			goto clean3;
@@ -1328,7 +1555,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 		ddata->cur += 2;
 		if (*ddata->cur == '\0')
 			return (0);
-		return (cpp_demangle_read_type(ddata, 0));
+		return (cpp_demangle_read_type(ddata, NULL));
 
 	case SIMPLE_HASH('T', 'h'):
 		/* virtual function non-virtual override thunk */
@@ -1358,7 +1585,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 		ddata->cur += 2;
 		if (*ddata->cur == '\0')
 			return (0);
-		return (cpp_demangle_read_type(ddata, 0));
+		return (cpp_demangle_read_type(ddata, NULL));
 
 	case SIMPLE_HASH('T', 'J'):
 		/* java class */
@@ -1367,7 +1594,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 		ddata->cur += 2;
 		if (*ddata->cur == '\0')
 			return (0);
-		return (cpp_demangle_read_type(ddata, 0));
+		return (cpp_demangle_read_type(ddata, NULL));
 
 	case SIMPLE_HASH('T', 'S'):
 		/* RTTI name (NTBS) */
@@ -1376,7 +1603,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 		ddata->cur += 2;
 		if (*ddata->cur == '\0')
 			return (0);
-		return (cpp_demangle_read_type(ddata, 0));
+		return (cpp_demangle_read_type(ddata, NULL));
 
 	case SIMPLE_HASH('T', 'T'):
 		/* VTT table */
@@ -1385,7 +1612,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 		ddata->cur += 2;
 		if (*ddata->cur == '\0')
 			return (0);
-		return (cpp_demangle_read_type(ddata, 0));
+		return (cpp_demangle_read_type(ddata, NULL));
 
 	case SIMPLE_HASH('T', 'v'):
 		/* virtual function virtual override thunk */
@@ -1406,7 +1633,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 		ddata->cur += 2;
 		if (*ddata->cur == '\0')
 			return (0);
-		return (cpp_demangle_read_type(ddata, 0));
+		return (cpp_demangle_read_type(ddata, NULL));
 
 	case SIMPLE_HASH('T', 'W'):
 		/* TLS wrapper function */
@@ -1424,30 +1651,74 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 static int
 cpp_demangle_read_local_name(struct cpp_demangle_data *ddata)
 {
+	struct vector_str local_name;
+	struct type_delimit td;
 	size_t limit;
+	bool  more_type;
 
 	if (ddata == NULL)
 		return (0);
 	if (*(++ddata->cur) == '\0')
 		return (0);
-	if (!cpp_demangle_read_encoding(ddata))
+
+	vector_str_init(&local_name);
+	ddata->cur_output = &local_name;
+
+	if (!cpp_demangle_read_encoding(ddata)) {
+		vector_str_dest(&local_name);
 		return (0);
+	}
 
+	ddata->cur_output = &ddata->output;
+
+	td.paren = false;
+	td.firstp = true;
+	more_type = false;
 	limit = 0;
-	for (;;) {
-		if (!cpp_demangle_read_type(ddata, 1))
+
+	/*
+	 * The first type is a return type if we just demangled template
+	 * args. (the template args is right next to the function name,
+	 * which means it's a template function)
+	 */
+	if (ddata->is_tmpl) {
+		ddata->is_tmpl = false;
+
+		/* Read return type */
+		if (!cpp_demangle_read_type(ddata, NULL)) {
+			vector_str_dest(&local_name);
 			return (0);
+		}
+
+		more_type = true;
+	}
+
+	/* Now we can push the name after possible return type is handled. */
+	if (!vector_str_push_vector(&ddata->output, &local_name)) {
+		vector_str_dest(&local_name);
+		return (0);
+	}
+	vector_str_dest(&local_name);
+
+	while (*ddata->cur != '\0') {
+		if (!cpp_demangle_read_type(ddata, &td))
+			return (0);
+		if (more_type)
+			more_type = false;
 		if (*ddata->cur == 'E')
 			break;
 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
 			return (0);
 	}
+	if (more_type)
+		return (0);
+
 	if (*(++ddata->cur) == '\0')
 		return (0);
-	if (ddata->paren == true) {
+	if (td.paren == true) {
 		if (!DEM_PUSH_STR(ddata, ")"))
 			return (0);
-		ddata->paren = false;
+		td.paren = false;
 	}
 	if (*ddata->cur == 's')
 		++ddata->cur;
@@ -1477,7 +1748,7 @@ cpp_demangle_read_name(struct cpp_demangle_data *ddata
 	if (ddata == NULL || *ddata->cur == '\0')
 		return (0);
 
-	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
+	output = ddata->cur_output;
 
 	subst_str = NULL;
 
@@ -1539,8 +1810,7 @@ cpp_demangle_read_name_flat(struct cpp_demangle_data *
 	size_t i, p_idx, idx, name_len;
 	char *name;
 
-	output = ddata->push_head > 0 ? &ddata->output_tmp :
-	    &ddata->output;
+	output = ddata->cur_output;
 
 	p_idx = output->size;
 
@@ -1577,8 +1847,7 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data
 	if (*(++ddata->cur) == '\0')
 		return (0);
 
-	while (*ddata->cur == 'r' || *ddata->cur == 'V' ||
-	    *ddata->cur == 'K') {
+	do {
 		switch (*ddata->cur) {
 		case 'r':
 			ddata->mem_rst = true;
@@ -1589,11 +1858,19 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data
 		case 'K':
 			ddata->mem_cst = true;
 			break;
+		case 'R':
+			ddata->mem_ref = true;
+			break;
+		case 'O':
+			ddata->mem_rref = true;
+			break;
+		default:
+			goto next;
 		}
-		++ddata->cur;
-	}
+	} while (*(++ddata->cur));
 
-	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
+next:
+	output = ddata->cur_output;
 	if (!vector_str_init(&v))
 		return (0);
 
@@ -1619,6 +1896,8 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data
 				goto clean;
 		}
 
+		if (p_idx == output->size)
+			goto next_comp;
 		if ((subst_str = vector_str_substr(output, p_idx,
 		    output->size - 1, &subst_str_len)) == NULL)
 			goto clean;
@@ -1630,10 +1909,12 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data
 
 		if (!cpp_demangle_push_subst_v(ddata, &v))
 			goto clean;
+
+	next_comp:
 		if (*ddata->cur == 'E')
 			break;
-		else if (*ddata->cur != 'I' &&
-		    *ddata->cur != 'C' && *ddata->cur != 'D') {
+		else if (*ddata->cur != 'I' && *ddata->cur != 'C' &&
+		    *ddata->cur != 'D' && p_idx != output->size) {
 			if (!DEM_PUSH_STR(ddata, "::"))
 				goto clean;
 			if (!VEC_PUSH_STR(&v, "::"))
@@ -1776,7 +2057,8 @@ cpp_demangle_read_offset_number(struct cpp_demangle_da
 }
 
 static int
-cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata)
+cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata,
+    struct vector_type_qualifier *v)
 {
 	size_t class_type_len, i, idx, p_idx;
 	int p_func_type, rtn;
@@ -1786,7 +2068,7 @@ cpp_demangle_read_pointer_to_member(struct cpp_demangl
 		return (0);
 
 	p_idx = ddata->output.size;
-	if (!cpp_demangle_read_type(ddata, 0))
+	if (!cpp_demangle_read_type(ddata, NULL))
 		return (0);
 
 	if ((class_type = vector_str_substr(&ddata->output, p_idx,
@@ -1799,14 +2081,14 @@ cpp_demangle_read_pointer_to_member(struct cpp_demangl
 		if (!vector_str_pop(&ddata->output))
 			goto clean1;
 
-	if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM))
+	if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM, v))
 		goto clean1;
 
 	if (!vector_str_push(&ddata->class_type, class_type, class_type_len))
 		goto clean2;
 
 	p_func_type = ddata->func_type;
-	if (!cpp_demangle_read_type(ddata, 0))
+	if (!cpp_demangle_read_type(ddata, NULL))
 		goto clean3;
 
 	if (p_func_type == ddata->func_type) {
@@ -1828,6 +2110,10 @@ clean2:
 clean1:
 	free(class_type);
 
+	vector_type_qualifier_dest(v);
+	if (!vector_type_qualifier_init(v))
+		return (0);
+
 	return (rtn);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706252239.v5PMdS2N052163>