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 <hyogeol...@gmail.com>
+ * Copyright (c) 2007 Hyogeol Lee <hyogeol...@gmail.com>
+ * Copyright (c) 2015-2017 Kai Wang <kaiwan...@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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to