Author: emaste
Date: Wed Jul  5 16:39:29 2017
New Revision: 320685
URL: https://svnweb.freebsd.org/changeset/base/320685

Log:
  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
  
  Also r320663 libelftc: bump version, tracking import in r320343

Modified:
  stable/11/contrib/elftoolchain/elfdump/elfdump.c
  stable/11/contrib/elftoolchain/libelftc/_libelftc.h
  stable/11/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
  stable/11/contrib/elftoolchain/libelftc/libelftc_vstr.c
  stable/11/lib/libelftc/elftc_version.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/contrib/elftoolchain/elfdump/elfdump.c
==============================================================================
--- stable/11/contrib/elftoolchain/elfdump/elfdump.c    Wed Jul  5 16:21:26 
2017        (r320684)
+++ stable/11/contrib/elftoolchain/elfdump/elfdump.c    Wed Jul  5 16:39:29 
2017        (r320685)
@@ -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: stable/11/contrib/elftoolchain/libelftc/_libelftc.h
==============================================================================
--- stable/11/contrib/elftoolchain/libelftc/_libelftc.h Wed Jul  5 16:21:26 
2017        (r320684)
+++ stable/11/contrib/elftoolchain/libelftc/_libelftc.h Wed Jul  5 16:39:29 
2017        (r320685)
@@ -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: stable/11/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
==============================================================================
--- stable/11/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c Wed Jul  5 
16:21:26 2017        (r320684)
+++ stable/11/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c Wed Jul  5 
16:39:29 2017        (r320685)
@@ -1,5 +1,6 @@
 /*-
  * 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
@@ -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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to