svn commit: r367323 - head/contrib/libcxxrt

Dimitry Andric dim at FreeBSD.org
Wed Nov 4 11:13:37 UTC 2020


Author: dim
Date: Wed Nov  4 11:13:36 2020
New Revision: 367323
URL: https://svnweb.freebsd.org/changeset/base/367323

Log:
  Update libcxxrt's private copy of elftoolchain demangler
  
  This updates the private copy of libelftc_dem_gnu3.c in libcxxrt with
  the most recent version from upstream r3877. Similar to r367322, this
  fixes a number of possible assertions, and allows it to correctly
  demangle several names that it could not handle before.
  
  PR:		250702
  MFC after:	3 days

Modified:
  head/contrib/libcxxrt/libelftc_dem_gnu3.c

Modified: head/contrib/libcxxrt/libelftc_dem_gnu3.c
==============================================================================
--- head/contrib/libcxxrt/libelftc_dem_gnu3.c	Wed Nov  4 11:02:05 2020	(r367322)
+++ head/contrib/libcxxrt/libelftc_dem_gnu3.c	Wed Nov  4 11:13:36 2020	(r367323)
@@ -1,5 +1,6 @@
 /*-
- * Copyright (c) 2007, 2008 Hyogeol Lee <hyogeollee at gmail.com>
+ * Copyright (c) 2007 Hyogeol Lee <hyogeollee at gmail.com>
+ * Copyright (c) 2015-2017 Kai Wang <kaiwang27 at gmail.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -54,12 +55,17 @@ struct vector_str {
 };
 
 #define BUFFER_GROWFACTOR	1.618
-#define VECTOR_DEF_CAPACITY	8
+#define BUFFER_GROW(x)		(((x)+0.5)*BUFFER_GROWFACTOR)
+
+#define	ELFTC_FAILURE		0
 #define	ELFTC_ISDIGIT(C) 	(isdigit((C) & 0xFF))
+#define	ELFTC_SUCCESS		1
 
+#define VECTOR_DEF_CAPACITY	8
+
 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 {
@@ -73,35 +79,57 @@ 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
 #define	FLOAT_EXTENED_BYTES	10
 
 #define SIMPLE_HASH(x,y)	(64 * x + y)
+#define DEM_PUSH_STR(d,s)	cpp_demangle_push_str((d), (s), strlen((s)))
+#define VEC_PUSH_STR(d,s)	vector_str_push((d), (s), strlen((s)))
 
 static size_t	get_strlen_sum(const struct vector_str *v);
 static bool	vector_str_grow(struct vector_str *v);
@@ -125,7 +153,7 @@ get_strlen_sum(const struct vector_str *v)
 /**
  * @brief Deallocate resource in vector_str.
  */
-static void
+void
 vector_str_dest(struct vector_str *v)
 {
 	size_t i;
@@ -146,7 +174,7 @@ vector_str_dest(struct vector_str *v)
  * @param l Length of the string.
  * @return -1 at failed, 0 at not found, 1 at found.
  */
-static int
+int
 vector_str_find(const struct vector_str *v, const char *o, size_t l)
 {
 	size_t i;
@@ -169,7 +197,7 @@ vector_str_find(const struct vector_str *v, const char
  * @param l Length of the string.
  * @return NULL at failed or NUL terminated new allocated string.
  */
-static char *
+char *
 vector_str_get_flat(const struct vector_str *v, size_t *l)
 {
 	ssize_t elem_pos, elem_size, rtn_size;
@@ -213,7 +241,7 @@ vector_str_grow(struct vector_str *v)
 
 	assert(v->capacity > 0);
 
-	tmp_cap = v->capacity * BUFFER_GROWFACTOR;
+	tmp_cap = BUFFER_GROW(v->capacity);
 
 	assert(tmp_cap > v->capacity);
 
@@ -235,7 +263,7 @@ vector_str_grow(struct vector_str *v)
  * @brief Initialize vector_str.
  * @return false at failed, true at success.
  */
-static bool
+bool
 vector_str_init(struct vector_str *v)
 {
 
@@ -259,7 +287,7 @@ vector_str_init(struct vector_str *v)
  * @brief Remove last element in vector_str.
  * @return false at failed, true at success.
  */
-static bool
+bool
 vector_str_pop(struct vector_str *v)
 {
 
@@ -281,7 +309,7 @@ vector_str_pop(struct vector_str *v)
  * @brief Push back string to vector.
  * @return false at failed, true at success.
  */
-static bool
+bool
 vector_str_push(struct vector_str *v, const char *str, size_t len)
 {
 
@@ -305,7 +333,7 @@ vector_str_push(struct vector_str *v, const char *str,
  * @brief Push front org vector to det vector.
  * @return false at failed, true at success.
  */
-static bool
+bool
 vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org)
 {
 	size_t i, j, tmp_cap;
@@ -314,7 +342,7 @@ vector_str_push_vector_head(struct vector_str *dst, st
 	if (dst == NULL || org == NULL)
 		return (false);
 
-	tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR;
+	tmp_cap = BUFFER_GROW(dst->size + org->size);
 
 	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
 		return (false);
@@ -342,12 +370,53 @@ vector_str_push_vector_head(struct vector_str *dst, st
 }
 
 /**
+ * @brief Push org vector to the tail of det vector.
+ * @return false at failed, true at success.
+ */
+bool
+vector_str_push_vector(struct vector_str *dst, struct vector_str *org)
+{
+	size_t i, j, tmp_cap;
+	char **tmp_ctn;
+
+	if (dst == NULL || org == NULL)
+		return (false);
+
+	tmp_cap = BUFFER_GROW(dst->size + org->size);
+
+	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
+		return (false);
+
+	for (i = 0; i < dst->size; ++i)
+		tmp_ctn[i] = dst->container[i];
+
+	for (i = 0; i < org->size; ++i)
+		if ((tmp_ctn[i + dst->size] = strdup(org->container[i])) ==
+		    NULL) {
+			for (j = 0; j < i + dst->size; ++j)
+				free(tmp_ctn[j]);
+
+			free(tmp_ctn);
+
+			return (false);
+		}
+
+	free(dst->container);
+
+	dst->container = tmp_ctn;
+	dst->capacity = tmp_cap;
+	dst->size += org->size;
+
+	return (true);
+}
+
+/**
  * @brief Get new allocated flat string from vector between begin and end.
  *
  * If r_len is not NULL, string length will be returned.
  * @return NULL at failed or NUL terminated new allocated string.
  */
-static char *
+char *
 vector_str_substr(const struct vector_str *v, size_t begin, size_t end,
     size_t *r_len)
 {
@@ -387,6 +456,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 *,
@@ -419,16 +489,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 *);
@@ -440,10 +512,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 *,
@@ -460,14 +534,16 @@ char *
 __cxa_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 = NULL;
+	char *rtn;
+	bool has_ret, more_type;
 
-	if (org == NULL)
+	if (org == NULL || (org_len = strlen(org)) < 2)
 		return (NULL);
 
-	org_len = strlen(org);
 	if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) {
 		if ((rtn = malloc(org_len + 19)) == NULL)
 			return (NULL);
@@ -476,52 +552,100 @@ __cxa_demangle_gnu3(const char *org)
 		return (rtn);
 	}
 
-	// Try demangling as a type for short encodings
-	if ((org_len < 2) || (org[0] != '_' || org[1] != 'Z' )) {
-		if (!cpp_demangle_data_init(&ddata, org))
-			return (NULL);
-		if (!cpp_demangle_read_type(&ddata, 0))
-			goto clean;
-		rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
-		goto clean;
-	}
+	if (org[0] != '_' || org[1] != 'Z')
+		return (NULL);
 
-
 	if (!cpp_demangle_data_init(&ddata, org + 2))
 		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 && !vector_str_push(&ddata.output, ")", 1))
+	if (td.paren && !VEC_PUSH_STR(&ddata.output, ")"))
 		goto clean;
-	if (ddata.mem_vat && !vector_str_push(&ddata.output, " volatile", 9))
+	if (ddata.mem_vat && !VEC_PUSH_STR(&ddata.output, " volatile"))
 		goto clean;
-	if (ddata.mem_cst && !vector_str_push(&ddata.output, " const", 6))
+	if (ddata.mem_cst && !VEC_PUSH_STR(&ddata.output, " const"))
 		goto clean;
-	if (ddata.mem_rst && !vector_str_push(&ddata.output, " restrict", 9))
+	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);
@@ -538,7 +662,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);
 }
 
@@ -551,43 +674,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);
 
@@ -632,13 +754,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)
 {
@@ -677,9 +813,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);
@@ -691,18 +829,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 	if (type_str != NULL) {
 		if (!vector_str_init(&subst_v))
 			return (0);
-		if (!vector_str_push(&subst_v, type_str, strlen(type_str)))
+		if (!VEC_PUSH_STR(&subst_v, type_str))
 			goto clean;
 	}
 
+	cv = true;
 	e_idx = 0;
 	while (idx > 0) {
 		switch (v->q_container[idx - 1]) {
 		case TYPE_PTR:
-			if (!cpp_demangle_push_str(ddata, "*", 1))
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, "*"))
 				goto clean;
 			if (type_str != NULL) {
-				if (!vector_str_push(&subst_v, "*", 1))
+				if (!VEC_PUSH_STR(&subst_v, "*"))
 					goto clean;
 				if (!cpp_demangle_push_subst_v(ddata,
 				    &subst_v))
@@ -711,10 +853,13 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_REF:
-			if (!cpp_demangle_push_str(ddata, "&", 1))
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, "&"))
 				goto clean;
 			if (type_str != NULL) {
-				if (!vector_str_push(&subst_v, "&", 1))
+				if (!VEC_PUSH_STR(&subst_v, "&"))
 					goto clean;
 				if (!cpp_demangle_push_subst_v(ddata,
 				    &subst_v))
@@ -722,11 +867,29 @@ 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:
-			if (!cpp_demangle_push_str(ddata, " complex", 8))
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, " complex"))
 				goto clean;
 			if (type_str != NULL) {
-				if (!vector_str_push(&subst_v, " complex", 8))
+				if (!VEC_PUSH_STR(&subst_v, " complex"))
 					goto clean;
 				if (!cpp_demangle_push_subst_v(ddata,
 				    &subst_v))
@@ -735,11 +898,13 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_IMG:
-			if (!cpp_demangle_push_str(ddata, " imaginary", 10))
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, " imaginary"))
 				goto clean;
 			if (type_str != NULL) {
-				if (!vector_str_push(&subst_v, " imaginary",
-				    10))
+				if (!VEC_PUSH_STR(&subst_v, " imaginary"))
 					goto clean;
 				if (!cpp_demangle_push_subst_v(ddata,
 				    &subst_v))
@@ -748,6 +913,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;
@@ -759,14 +927,13 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			snprintf(buf, e_len + 2, " %s",
 			    v->ext_name.container[e_idx]);
 
-			if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) {
+			if (!DEM_PUSH_STR(ddata, buf)) {
 				free(buf);
 				goto clean;
 			}
 
 			if (type_str != NULL) {
-				if (!vector_str_push(&subst_v, buf,
-				    e_len + 1)) {
+				if (!VEC_PUSH_STR(&subst_v, buf)) {
 					free(buf);
 					goto clean;
 				}
@@ -781,11 +948,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_RST:
-			if (!cpp_demangle_push_str(ddata, " restrict", 9))
+			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 (!vector_str_push(&subst_v, " restrict", 9))
+				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;
@@ -793,11 +971,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_VAT:
-			if (!cpp_demangle_push_str(ddata, " volatile", 9))
+			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 (!vector_str_push(&subst_v, " volatile", 9))
+				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;
@@ -805,11 +994,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 			break;
 
 		case TYPE_CST:
-			if (!cpp_demangle_push_str(ddata, " const", 6))
+			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 (!vector_str_push(&subst_v, " const", 6))
+				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;
@@ -817,6 +1017,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;
@@ -827,13 +1030,12 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_d
 				goto clean;
 			snprintf(buf, e_len + 12, " __vector(%s)",
 			    v->ext_name.container[e_idx]);
-			if (!cpp_demangle_push_str(ddata, buf, e_len + 11)) {
+			if (!DEM_PUSH_STR(ddata, buf)) {
 				free(buf);
 				goto clean;
 			}
 			if (type_str != NULL) {
-				if (!vector_str_push(&subst_v, buf,
-				    e_len + 11)) {
+				if (!VEC_PUSH_STR(&subst_v, buf)) {
 					free(buf);
 					goto clean;
 				}
@@ -907,10 +1109,10 @@ 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 (!cpp_demangle_push_str(ddata, "[]", 2))
+		if (!DEM_PUSH_STR(ddata, "[]"))
 			return (0);
 	} else {
 		if (ELFTC_ISDIGIT(*ddata->cur) != 0) {
@@ -923,13 +1125,13 @@ 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 (!cpp_demangle_push_str(ddata, "[", 1))
+			if (!DEM_PUSH_STR(ddata, "["))
 				return (0);
 			if (!cpp_demangle_push_str(ddata, num, num_len))
 				return (0);
-			if (!cpp_demangle_push_str(ddata, "]", 1))
+			if (!DEM_PUSH_STR(ddata, "]"))
 				return (0);
 		} else {
 			p_idx = ddata->output.size;
@@ -953,11 +1155,11 @@ 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);
 			}
-			if (!cpp_demangle_push_str(ddata, "[", 1)) {
+			if (!DEM_PUSH_STR(ddata, "[")) {
 				free(exp);
 				return (0);
 			}
@@ -965,7 +1167,7 @@ cpp_demangle_read_array(struct cpp_demangle_data *ddat
 				free(exp);
 				return (0);
 			}
-			if (!cpp_demangle_push_str(ddata, "]", 1)) {
+			if (!DEM_PUSH_STR(ddata, "]")) {
 				free(exp);
 				return (0);
 			}
@@ -1001,10 +1203,10 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_dat
 		switch (*(++ddata->cur)) {
 		case '0':
 			ddata->cur += 2;
-			return (cpp_demangle_push_str(ddata, "false", 5));
+			return (DEM_PUSH_STR(ddata, "false"));
 		case '1':
 			ddata->cur += 2;
-			return (cpp_demangle_push_str(ddata, "true", 4));
+			return (DEM_PUSH_STR(ddata, "true"));
 		default:
 			return (0);
 		}
@@ -1041,7 +1243,7 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_dat
 	case 'x':
 	case 'y':
 		if (*(++ddata->cur) == 'n') {
-			if (!cpp_demangle_push_str(ddata, "-", 1))
+			if (!DEM_PUSH_STR(ddata, "-"))
 				return (0);
 			++ddata->cur;
 		}
@@ -1070,11 +1272,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);
@@ -1351,8 +1553,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;
 
@@ -1429,8 +1630,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);
@@ -1441,12 +1646,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 (!cpp_demangle_push_str(ddata, "(", 1))
+		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 =
@@ -1458,42 +1694,69 @@ cpp_demangle_read_function(struct cpp_demangle_data *d
 			if (!cpp_demangle_push_str(ddata, class_type,
 			    class_type_len))
 				return (0);
-			if (!cpp_demangle_push_str(ddata, "::*", 3))
+			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 (!cpp_demangle_push_str(ddata, ")(", 2))
-			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 (!cpp_demangle_push_str(ddata, ")", 1))
+		/* 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;
@@ -1515,7 +1778,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 	/* special name */
 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
 	case SIMPLE_HASH('G', 'A'):
-		if (!cpp_demangle_push_str(ddata, "hidden alias for ", 17))
+		if (!DEM_PUSH_STR(ddata, "hidden alias for "))
 			return (0);
 		ddata->cur += 2;
 		if (*ddata->cur == '\0')
@@ -1523,7 +1786,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *d
 		return (cpp_demangle_read_encoding(ddata));
 

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


More information about the svn-src-head mailing list