2 * Ported from LLVM's libcxxabi trunk/src/cxa_demangle.cpp
3 * LICENSE.TXT contents is available as ../THIRDPARTYLICENSE
5 * The LLVM Compiler Infrastructure
7 * This file is dual licensed under the MIT and the University of Illinois Open
8 * Source Licenses. See LICENSE.TXT for details.
13 * Copyright 2018 Jason King.
23 #include <sys/isa_defs.h>
24 #include <sys/debug.h>
25 #include "demangle-sys.h"
26 #include "demangle_int.h"
30 #define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
33 #define CPP_QUAL_CONST (1U)
34 #define CPP_QUAL_VOLATILE (2U)
35 #define CPP_QUAL_RESTRICT (4U)
37 typedef struct cpp_db_s
{
38 sysdem_ops_t
*cpp_ops
;
46 boolean_t cpp_parsed_ctor_dtor_cv
;
47 boolean_t cpp_tag_templates
;
48 boolean_t cpp_fix_forward_references
;
49 boolean_t cpp_try_to_parse_template_args
;
56 longjmp(db->cpp_jmp, 1); \
61 #define TOP_L(db) (&(name_top(&(db)->cpp_name)->strp_l))
62 #define RLEN(f, l) ((size_t)((l) - (f)))
63 #define NAMT(db, n) (nlen(db) - n)
65 static inline boolean_t
is_xdigit(int);
67 static boolean_t
nempty(cpp_db_t
*);
68 static size_t nlen(cpp_db_t
*);
69 static void nadd_l(cpp_db_t
*, const char *, size_t);
70 static void njoin(cpp_db_t
*, size_t, const char *);
71 static void nfmt(cpp_db_t
*, const char *, const char *);
73 static void save_top(cpp_db_t
*, size_t);
74 static void sub(cpp_db_t
*, size_t);
76 static boolean_t
tempty(const cpp_db_t
*);
77 static size_t ttlen(const cpp_db_t
*);
79 static void tsub(cpp_db_t
*, size_t);
80 static void tpush(cpp_db_t
*);
81 static void tpop(cpp_db_t
*);
82 static void tsave(cpp_db_t
*, size_t);
84 static boolean_t
db_init(cpp_db_t
*, sysdem_ops_t
*);
85 static void db_fini(cpp_db_t
*);
86 static void dump(cpp_db_t
*, FILE *);
88 static void demangle(const char *, const char *, cpp_db_t
*);
90 static const char *parse_type(const char *, const char *, cpp_db_t
*);
91 static const char *parse_builtin_type(const char *, const char *, cpp_db_t
*);
92 static const char *parse_qual_type(const char *, const char *, cpp_db_t
*);
93 static const char *parse_encoding(const char *, const char *, cpp_db_t
*);
94 static const char *parse_dot_suffix(const char *, const char *, cpp_db_t
*);
95 static const char *parse_block_invoke(const char *, const char *, cpp_db_t
*);
96 static const char *parse_special_name(const char *, const char *, cpp_db_t
*);
97 static const char *parse_name(const char *, const char *, boolean_t
*,
99 static const char *parse_call_offset(const char *, const char *, locale_t
);
100 static const char *parse_number(const char *, const char *, locale_t
);
101 static const char *parse_nested_name(const char *, const char *, boolean_t
*,
103 static const char *parse_local_name(const char *, const char *, boolean_t
*,
105 static const char *parse_unscoped_name(const char *, const char *, cpp_db_t
*);
106 static const char *parse_template_args(const char *, const char *, cpp_db_t
*);
107 static const char *parse_substitution(const char *, const char *, cpp_db_t
*);
108 static const char *parse_discriminator(const char *, const char *, locale_t
);
109 static const char *parse_cv_qualifiers(const char *, const char *, unsigned *);
110 static const char *parse_template_param(const char *, const char *, cpp_db_t
*);
111 static const char *parse_decltype(const char *, const char *, cpp_db_t
*);
112 static const char *parse_template_args(const char *, const char *, cpp_db_t
*);
113 static const char *parse_unqualified_name(const char *, const char *,
115 static const char *parse_template_arg(const char *, const char *, cpp_db_t
*);
116 static const char *parse_expression(const char *, const char *, cpp_db_t
*);
117 static const char *parse_expr_primary(const char *, const char *, cpp_db_t
*);
118 static const char *parse_binary_expr(const char *, const char *,
119 const char *, cpp_db_t
*);
120 static const char *parse_prefix_expr(const char *, const char *,
121 const char *, cpp_db_t
*);
122 static const char *parse_gs(const char *, const char *, cpp_db_t
*);
123 static const char *parse_idx_expr(const char *, const char *, cpp_db_t
*);
124 static const char *parse_mm_expr(const char *, const char *, cpp_db_t
*);
125 static const char *parse_pp_expr(const char *, const char *, cpp_db_t
*);
126 static const char *parse_trinary_expr(const char *, const char *, cpp_db_t
*);
127 static const char *parse_new_expr(const char *, const char *, cpp_db_t
*);
128 static const char *parse_del_expr(const char *, const char *, cpp_db_t
*);
129 static const char *parse_cast_expr(const char *, const char *, cpp_db_t
*);
130 static const char *parse_sizeof_param_pack_expr(const char *, const char *,
132 static const char *parse_typeid_expr(const char *, const char *, cpp_db_t
*);
133 static const char *parse_throw_expr(const char *, const char *, cpp_db_t
*);
134 static const char *parse_dot_star_expr(const char *, const char *, cpp_db_t
*);
135 static const char *parse_dot_expr(const char *, const char *, cpp_db_t
*);
136 static const char *parse_call_expr(const char *, const char *, cpp_db_t
*);
137 static const char *parse_arrow_expr(const char *, const char *, cpp_db_t
*);
138 static const char *parse_conv_expr(const char *, const char *, cpp_db_t
*);
139 static const char *parse_function_param(const char *, const char *, cpp_db_t
*);
140 static const char *parse_base_unresolved_name(const char *, const char *,
142 static const char *parse_unresolved_name(const char *, const char *,
144 static const char *parse_noexcept_expr(const char *, const char *, cpp_db_t
*);
145 static const char *parse_alignof(const char *, const char *, cpp_db_t
*);
146 static const char *parse_sizeof(const char *, const char *, cpp_db_t
*);
147 static const char *parse_unnamed_type_name(const char *, const char *,
149 static const char *parse_ctor_dtor_name(const char *, const char *, cpp_db_t
*);
150 static const char *parse_source_name(const char *, const char *, cpp_db_t
*);
151 static const char *parse_operator_name(const char *, const char *, cpp_db_t
*);
152 static const char *parse_pack_expansion(const char *, const char *, cpp_db_t
*);
153 static const char *parse_unresolved_type(const char *, const char *,
155 static const char *parse_unresolved_qualifier_level(const char *, const char *,
157 static const char *parse_destructor_name(const char *, const char *,
159 static const char *parse_function_type(const char *, const char *, cpp_db_t
*);
160 static const char *parse_array_type(const char *, const char *, cpp_db_t
*);
161 static const char *parse_pointer_to_member_type(const char *, const char *,
163 static const char *parse_vector_type(const char *, const char *, cpp_db_t
*);
165 size_t cpp_name_max_depth
= 1024; /* max depth of name stack */
168 cpp_demangle(const char *src
, sysdem_ops_t
*ops
)
172 size_t srclen
= strlen(src
);
174 if (!db_init(&db
, ops
))
176 if (setjmp(db
.cpp_jmp
) != 0)
180 demangle(src
, src
+ srclen
, &db
);
182 if (errno
== 0 && db
.cpp_fix_forward_references
&&
183 !templ_empty(&db
.cpp_templ
) &&
184 !sub_empty(&db
.cpp_templ
.tpl_items
[0])) {
185 db
.cpp_fix_forward_references
= B_FALSE
;
186 db
.cpp_tag_templates
= B_FALSE
;
187 name_clear(&db
.cpp_name
);
188 sub_clear(&db
.cpp_subs
);
190 if (setjmp(db
.cpp_jmp
) != 0)
193 demangle(src
, src
+ srclen
, &db
);
195 if (db
.cpp_fix_forward_references
) {
212 str_t
*s
= TOP_L(&db
);
213 char *res
= zalloc(ops
, s
->str_len
+ 1);
217 (void) memcpy(res
, s
->str_s
, s
->str_len
);
230 demangle(const char *first
, const char *last
, cpp_db_t
*db
)
232 const char *t
= NULL
;
239 if (first
[0] != '_') {
240 t
= parse_type(first
, last
, db
);
248 if (last
- first
< 4) {
253 if (first
[1] == 'Z') {
254 t
= parse_encoding(first
+ 2, last
, db
);
256 if (t
!= first
+ 2 && t
!= last
&& t
[0] == '.') {
257 t
= parse_dot_suffix(t
, last
, db
);
265 if (first
[1] != '_' || first
[2] != '_' || first
[3] != 'Z')
268 t
= parse_encoding(first
+ 4, last
, db
);
269 if (t
!= first
+ 4 && t
!= last
)
270 t
= parse_block_invoke(t
, last
, db
);
278 parse_dot_suffix(const char *first
, const char *last
, cpp_db_t
*db
)
280 VERIFY3P(first
, <=, last
);
282 if (first
== last
|| first
[0] != '.')
288 nadd_l(db
, first
, RLEN(first
, last
));
289 nfmt(db
, " ({0})", NULL
);
296 * _block_invoke<digit>*
297 * _block_invoke_<digit>+
300 parse_block_invoke(const char *first
, const char *last
, cpp_db_t
*db
)
302 VERIFY3P(first
, <=, last
);
304 if (last
- first
< 13)
307 const char test
[] = "_block_invoke";
308 const char *t
= first
;
310 if (strncmp(first
, test
, sizeof (test
) - 1) != 0)
318 /* need at least one digit */
319 if (t
+ 1 == last
|| !isdigit_l(t
[1], db
->cpp_loc
))
324 while (t
< last
&& isdigit_l(t
[0], db
->cpp_loc
))
331 nfmt(db
, "invocation function for block in {0}", NULL
);
336 * <encoding> ::= <function name><bare-function-type>
341 parse_encoding(const char *first
, const char *last
, cpp_db_t
*db
)
343 VERIFY3P(first
, <=, last
);
348 const char *t
= NULL
;
349 const char *t2
= NULL
;
352 boolean_t tag_templ_save
= db
->cpp_tag_templates
;
354 if (++db
->cpp_depth
> 1)
355 db
->cpp_tag_templates
= B_TRUE
;
357 if (first
[0] == 'G' || first
[0] == 'T') {
358 t
= parse_special_name(first
, last
, db
);
362 boolean_t ends_with_template_args
= B_FALSE
;
363 t
= parse_name(first
, last
, &ends_with_template_args
, db
);
370 if (t
== last
|| t
[0] == 'E' || t
[0] == '.')
373 db
->cpp_tag_templates
= B_FALSE
;
374 if (nempty(db
) || str_length(TOP_L(db
)) == 0)
377 if (!db
->cpp_parsed_ctor_dtor_cv
&& ends_with_template_args
) {
378 t2
= parse_type(t
, last
, db
);
379 if (t2
== t
|| nlen(db
) < 2)
382 str_pair_t
*sp
= name_top(&db
->cpp_name
);
384 if (str_length(&sp
->strp_r
) == 0)
385 (void) str_append(&sp
->strp_l
, " ", 1);
387 nfmt(db
, "{0:L}{1:L}", "{1:R}{0:R}");
391 if (t
== last
|| nempty(db
))
400 t2
= parse_type(t
, last
, db
);
401 if (t2
== t
|| t
== last
)
409 * a bit of a hack, but a template substitution can apparently be
410 * an empty string at the end of an argument list, so avoid
413 if (NAMT(db
, n
) > 1 && str_pair_len(name_top(&db
->cpp_name
)) == 0)
414 name_pop(&db
->cpp_name
, NULL
);
416 njoin(db
, NAMT(db
, n
), ", ");
417 nfmt(db
, "({0})", NULL
);
419 str_t
*s
= TOP_L(db
);
421 if (cv
& CPP_QUAL_CONST
) {
422 CK(str_append(s
, " const", 0));
424 if (cv
& CPP_QUAL_VOLATILE
) {
425 CK(str_append(s
, " volatile", 0));
427 if (cv
& CPP_QUAL_RESTRICT
) {
428 CK(str_append(s
, " restrict", 0));
431 CK(str_append(s
, " &", 0));
434 CK(str_append(s
, " &&", 0));
437 nfmt(db
, "{1:L}{0}{1:R}", NULL
);
440 db
->cpp_tag_templates
= tag_templ_save
;
445 db
->cpp_tag_templates
= tag_templ_save
;
451 * <special-name> ::= TV <type> # virtual table
452 * ::= TT <type> # VTT structure (construction vtable index)
453 * ::= TI <type> # typeinfo structure
454 * ::= TS <type> # typeinfo name (null-terminated byte string)
455 * ::= Tc <call-offset> <call-offset> <base encoding>
456 * # base is the nominal target function of thunk
457 * # first call-offset is 'this' adjustment
458 * # second call-offset is result adjustment
459 * ::= T <call-offset> <base encoding>
460 * # base is the nominal target function of thunk
461 * ::= GV <object name> # Guard variable for one-time init
463 * ::= TW <object name> # Thread-local wrapper
464 * ::= TH <object name> # Thread-local initialization
465 * extension ::= TC <first type> <number> _ <second type>
466 * # construction vtable for second-in-first
467 * extension ::= GR <object name> # reference temporary for object
470 parse_special_name(const char *first
, const char *last
, cpp_db_t
*db
)
472 VERIFY3P(first
, <=, last
);
474 const char *t
= first
;
475 const char *t1
= NULL
;
478 if (last
- first
< 2)
485 nadd_l(db
, "vtable for", 0);
486 t
= parse_type(first
+ 2, last
, db
);
489 nadd_l(db
, "VTT for", 0);
490 t
= parse_type(first
+ 2, last
, db
);
493 nadd_l(db
, "typeinfo for", 0);
494 t
= parse_type(first
+ 2, last
, db
);
497 nadd_l(db
, "typeinfo name for", 0);
498 t
= parse_type(first
+ 2, last
, db
);
501 nadd_l(db
, "covariant return thunk to", 0);
502 t1
= parse_call_offset(first
+ 2, last
, db
->cpp_loc
);
505 t
= parse_call_offset(t1
, last
, db
->cpp_loc
);
508 t1
= parse_encoding(t
, last
, db
);
513 t
= parse_type(first
+ 2, last
, db
);
516 t1
= parse_number(t
, last
, db
->cpp_loc
);
519 t
= parse_type(t1
+ 1, last
, db
);
520 if (t
== t1
+ 1 || nlen(db
) < 2)
522 nfmt(db
, "construction vtable for {0}-in-{1}", NULL
);
525 nadd_l(db
, "thread-local wrapper routine for", 0);
526 t
= parse_name(first
+ 2, last
, NULL
, db
);
529 nadd_l(db
, "thread-local initialization routine for",
531 t
= parse_name(first
+ 2, last
, NULL
, db
);
534 if (first
[1] == 'v') {
535 nadd_l(db
, "virtual thunk to", 0);
537 nadd_l(db
, "non-virtual thunk to", 0);
540 t
= parse_call_offset(first
+ 1, last
, db
->cpp_loc
);
543 t1
= parse_encoding(t
, last
, db
);
553 nadd_l(db
, "guard variable for", 0);
554 t
= parse_name(first
+ 2, last
, NULL
, db
);
557 nadd_l(db
, "reference temporary for", 0);
558 t
= parse_name(first
+ 2, last
, NULL
, db
);
568 size_t amt
= NAMT(db
, n
);
569 if (t
== first
+ 2 || amt
< 2)
577 * <call-offset> ::= h <nv-offset> _
580 * <nv-offset> ::= <offset number>
581 * # non-virtual base override
583 * <v-offset> ::= <offset number> _ <virtual offset number>
584 * # virtual base override, with vcall offset
587 parse_call_offset(const char *first
, const char *last
, locale_t loc
)
589 VERIFY3P(first
, <=, last
);
591 const char *t
= NULL
;
592 const char *t1
= NULL
;
597 if (first
[0] != 'h' && first
[0] != 'v')
600 t
= parse_number(first
+ 1, last
, loc
);
601 if (t
== first
+ 1 || t
== last
|| t
[0] != '_')
610 t1
= parse_number(t
, last
, loc
);
611 if (t
== t1
|| t1
== last
|| t1
[0] != '_')
621 * <name> ::= <nested-name> // N
622 * ::= <local-name> # See Scope Encoding below // Z
623 * ::= <unscoped-template-name> <template-args>
624 * ::= <unscoped-name>
626 * <unscoped-template-name> ::= <unscoped-name>
630 parse_name(const char *first
, const char *last
,
631 boolean_t
*ends_with_template_args
, cpp_db_t
*db
)
633 VERIFY3P(first
, <=, last
);
635 const char *t
= first
;
636 const char *t1
= NULL
;
638 if (last
- first
< 2)
641 /* extension: ignore L here */
647 t1
= parse_nested_name(t
, last
, ends_with_template_args
, db
);
648 return ((t
== t1
) ? first
: t1
);
650 t1
= parse_local_name(t
, last
, ends_with_template_args
, db
);
651 return ((t
== t1
) ? first
: t1
);
656 * <unscoped-name> <template-args>
657 * <substitution> <template-args>
659 t1
= parse_unscoped_name(t
, last
, db
);
661 /* <unscoped-name> */
662 if (t
!= t1
&& t1
[0] != 'I')
666 t1
= parse_substitution(t
, last
, db
);
667 if (t
== t1
|| t1
== last
|| t1
[0] != 'I')
673 t
= parse_template_args(t1
, last
, db
);
674 if (t1
== t
|| nlen(db
) < 2)
677 nfmt(db
, "{1:L}{0}", "{1:R}");
679 if (ends_with_template_args
!= NULL
)
680 *ends_with_template_args
= B_TRUE
;
687 * <local-name> := Z <function encoding> E <entity name> [<discriminator>]
688 * := Z <function encoding> E s [<discriminator>]
689 * := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
693 parse_local_name(const char *first
, const char *last
,
694 boolean_t
*ends_with_template_args
, cpp_db_t
*db
)
696 VERIFY3P(first
, <=, last
);
698 const char *t
= NULL
;
699 const char *t1
= NULL
;
700 const char *t2
= NULL
;
702 if (first
== last
|| first
[0] != 'Z')
705 t
= parse_encoding(first
+ 1, last
, db
);
706 if (t
== first
+ 1 || t
== last
|| t
[0] != 'E')
715 nfmt(db
, "{0:L}::string literal", "{0:R}");
716 return (parse_discriminator(t
, last
, db
->cpp_loc
));
720 t1
= parse_number(t
+ 1, last
, db
->cpp_loc
);
728 t2
= parse_name(t1
, last
, ends_with_template_args
, db
);
732 nfmt(db
, "{1:L}::{0}", "{1:R}");
734 /* parsed, but ignored */
736 t2
= parse_discriminator(t2
, last
, db
->cpp_loc
);
743 * <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
744 * ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
746 * <prefix> ::= <prefix> <unqualified-name>
747 * ::= <template-prefix> <template-args>
748 * ::= <template-param>
752 * ::= <prefix> <data-member-prefix>
755 * <template-prefix> ::= <prefix> <template unqualified-name>
756 * ::= <template-param>
761 parse_nested_name(const char *first
, const char *last
,
762 boolean_t
*ends_with_template_args
, cpp_db_t
*db
)
764 VERIFY3P(first
, <=, last
);
766 if (first
== last
|| first
[0] != 'N')
770 const char *t
= parse_cv_qualifiers(first
+ 1, last
, &cv
);
775 boolean_t more
= B_FALSE
;
787 if (last
- first
< 2 || t
[1] != 't')
789 if (last
- first
== 2)
791 nadd_l(db
, "std", 3);
797 boolean_t pop_subs
= B_FALSE
;
798 boolean_t component_ends_with_template_args
= B_FALSE
;
800 while (t
[0] != 'E' && t
!= last
) {
801 const char *t1
= NULL
;
803 component_ends_with_template_args
= B_FALSE
;
807 if (t
+ 1 != last
&& t
[1] == 't')
810 t1
= parse_substitution(t
, last
, db
);
811 if (t1
== t
|| t1
== last
|| NAMT(db
, n
) != 1)
815 nfmt(db
, "{0}", NULL
);
817 VERIFY3U(nlen(db
), >, 1);
818 nfmt(db
, "{1:L}::{0}", "{1:R}");
828 t1
= parse_template_param(t
, last
, db
);
829 if (t1
== t
|| t1
== last
|| NAMT(db
, n
) != 1)
833 nfmt(db
, "{0}", NULL
);
835 VERIFY3U(nlen(db
), >, 1);
836 nfmt(db
, "{1:L}::{0}", "{1:R}");
846 if (t
+ 1 != last
&& t
[1] != 't' && t
[1] != 'T')
848 t1
= parse_decltype(t
, last
, db
);
849 if (t1
== t
|| t1
== last
|| NAMT(db
, n
) != 1)
853 nfmt(db
, "{0}", NULL
);
855 VERIFY3U(nlen(db
), >, 1);
856 nfmt(db
, "{1:L}::{0}", "{1:R}");
867 * Must have at least one component before
873 t1
= parse_template_args(t
, last
, db
);
874 if (t1
== t
|| t1
== last
)
877 VERIFY3U(nlen(db
), >, 1);
878 nfmt(db
, "{1:L}{0}", "{1:R}");
881 component_ends_with_template_args
= B_TRUE
;
894 t1
= parse_unqualified_name(t
, last
, db
);
895 if (t1
== t
|| t1
== last
|| NAMT(db
, n
) != 1)
899 nfmt(db
, "{0}", NULL
);
901 VERIFY3U(nlen(db
), >, 1);
902 nfmt(db
, "{1:L}::{0}", "{1:R}");
911 /* need to parse at least one thing */
916 if (pop_subs
&& !sub_empty(&db
->cpp_subs
))
917 sub_pop(&db
->cpp_subs
);
919 if (ends_with_template_args
!= NULL
)
920 *ends_with_template_args
= component_ends_with_template_args
;
929 * <template-arg> ::= <type> # type or template
930 * ::= X <expression> E # expression
931 * ::= <expr-primary> # simple expressions
932 * ::= J <template-arg>* E # argument pack
933 * ::= LZ <encoding> E # extension
936 parse_template_arg(const char *first
, const char *last
, cpp_db_t
*db
)
938 VERIFY3P(first
, <=, last
);
940 const char *t
= NULL
;
941 const char *t1
= NULL
;
948 t
= parse_expression(first
+ 1, last
, db
);
949 if (t
== first
+ 1 || t
[0] != 'E')
961 while (t
[0] != 'E') {
962 t1
= parse_template_arg(t
, last
, db
);
973 if (first
+ 1 == last
|| first
[1] != 'Z') {
974 t
= parse_expr_primary(first
, last
, db
);
976 t
= parse_encoding(first
+ 2, last
, db
);
977 if (t
== first
+ 2 || t
== last
|| t
[0] != 'E')
986 t
= parse_type(first
, last
, db
);
994 * <expression> ::= <unary operator-name> <expression>
995 * ::= <binary operator-name> <expression> <expression>
996 * ::= <ternary operator-name> <expression> <expression> <expression>
997 * ::= cl <expression>+ E # call
998 * ::= cv <type> <expression> # conversion with one argument
999 * ::= cv <type> _ <expression>* E # conversion with a different number of arguments
1000 * ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
1001 * ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1002 * ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
1003 * ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1004 * ::= [gs] dl <expression> # delete expression
1005 * ::= [gs] da <expression> # delete[] expression
1006 * ::= pp_ <expression> # prefix ++
1007 * ::= mm_ <expression> # prefix --
1008 * ::= ti <type> # typeid (type)
1009 * ::= te <expression> # typeid (expression)
1010 * ::= dc <type> <expression> # dynamic_cast<type> (expression)
1011 * ::= sc <type> <expression> # static_cast<type> (expression)
1012 * ::= cc <type> <expression> # const_cast<type> (expression)
1013 * ::= rc <type> <expression> # reinterpret_cast<type> (expression)
1014 * ::= st <type> # sizeof (a type)
1015 * ::= sz <expression> # sizeof (an expression)
1016 * ::= at <type> # alignof (a type)
1017 * ::= az <expression> # alignof (an expression)
1018 * ::= nx <expression> # noexcept (expression)
1019 * ::= <template-param>
1020 * ::= <function-param>
1021 * ::= dt <expression> <unresolved-name> # expr.name
1022 * ::= pt <expression> <unresolved-name> # expr->name
1023 * ::= ds <expression> <expression> # expr.*expr
1024 * ::= sZ <template-param> # size of a parameter pack
1025 * ::= sZ <function-param> # size of a function parameter pack
1026 * ::= sp <expression> # pack expansion
1027 * ::= tw <expression> # throw expression
1028 * ::= tr # throw with no operand (rethrow)
1029 * ::= <unresolved-name> # f(p), N::f(p), ::f(p),
1030 * # freestanding dependent name (e.g., T::x),
1031 * # objectless nonstatic member reference
1032 * ::= <expr-primary>
1036 #define PA(cd, arg, fn) { \
1038 .p.parse_expr_arg = fn, \
1039 .fntype = EXPR_ARG, \
1043 #define PN(cd, fn) { \
1045 .p.parse_expr_noarg = fn, \
1046 .fntype = EXPR_NOARG \
1052 const char *(*parse_expr_arg
)(const char *, const char *,
1053 const char *, cpp_db_t
*);
1054 const char *(*parse_expr_noarg
)(const char *, const char *,
1063 PA("aN", "&=", parse_binary_expr
),
1064 PA("aS", "=", parse_binary_expr
),
1065 PA("aa", "&&", parse_binary_expr
),
1066 PA("ad", "&", parse_prefix_expr
),
1067 PA("an", "&", parse_binary_expr
),
1068 PN("at", parse_alignof
),
1069 PN("az", parse_alignof
),
1070 PN("cc", parse_cast_expr
),
1071 PN("cl", parse_call_expr
),
1072 PA("cm", ",", parse_binary_expr
),
1073 PA("co", "~", parse_prefix_expr
),
1074 PN("cv", parse_conv_expr
),
1075 PN("da", parse_del_expr
),
1076 PA("dV", "/=", parse_binary_expr
),
1077 PN("dc", parse_cast_expr
),
1078 PA("de", "*", parse_prefix_expr
),
1079 PN("dl", parse_del_expr
),
1080 PN("dn", parse_unresolved_name
),
1081 PN("ds", parse_dot_star_expr
),
1082 PN("dt", parse_dot_expr
),
1083 PA("dv", "/", parse_binary_expr
),
1084 PA("eO", "^=", parse_binary_expr
),
1085 PA("eo", "^", parse_binary_expr
),
1086 PA("eq", "==", parse_binary_expr
),
1087 PA("ge", ">=", parse_binary_expr
),
1089 PA("gt", ">", parse_binary_expr
),
1090 PN("ix", parse_idx_expr
),
1091 PA("lS", "<<=", parse_binary_expr
),
1092 PA("le", "<=", parse_binary_expr
),
1093 PA("ls", "<<", parse_binary_expr
),
1094 PA("lt", "<", parse_binary_expr
),
1095 PA("mI", "-=", parse_binary_expr
),
1096 PA("mL", "*=", parse_binary_expr
),
1097 PN("mm", parse_mm_expr
),
1098 PA("mi", "-", parse_binary_expr
),
1099 PA("ml", "*", parse_binary_expr
),
1100 PN("na", parse_new_expr
),
1101 PA("ne", "!=", parse_binary_expr
),
1102 PA("ng", "-", parse_prefix_expr
),
1103 PA("nt", "!", parse_prefix_expr
),
1104 PN("nw", parse_new_expr
),
1105 PN("nx", parse_noexcept_expr
),
1106 PA("oR", "|=", parse_binary_expr
),
1107 PN("on", parse_unresolved_name
),
1108 PA("oo", "||", parse_binary_expr
),
1109 PA("or", "|", parse_binary_expr
),
1110 PA("pL", "+=", parse_binary_expr
),
1111 PA("pl", "+", parse_binary_expr
),
1112 PA("pm", "->*", parse_binary_expr
),
1113 PN("pp", parse_pp_expr
),
1114 PA("ps", "+", parse_prefix_expr
),
1115 PN("pt", parse_arrow_expr
),
1116 PN("qu", parse_trinary_expr
),
1117 PA("rM", "%=", parse_binary_expr
),
1118 PA("rS", ">>=", parse_binary_expr
),
1119 PN("rc", parse_cast_expr
),
1120 PA("rm", "%", parse_binary_expr
),
1121 PA("rs", ">>", parse_binary_expr
),
1122 PN("sc", parse_cast_expr
),
1123 PN("sp", parse_pack_expansion
),
1124 PN("sr", parse_unresolved_name
),
1125 PN("st", parse_sizeof
),
1126 PN("sz", parse_sizeof
),
1127 PN("sZ", parse_sizeof_param_pack_expr
),
1128 PN("te", parse_typeid_expr
),
1129 PN("tr", parse_throw_expr
),
1130 PN("tw", parse_throw_expr
)
1136 parse_expression(const char *first
, const char *last
, cpp_db_t
*db
)
1138 VERIFY3P(first
, <=, last
);
1140 if (last
- first
< 2)
1143 for (size_t i
= 0; i
< ARRAY_SIZE(expr_tbl
); i
++) {
1144 if (strncmp(expr_tbl
[i
].code
, first
, 2) != 0)
1146 switch (expr_tbl
[i
].fntype
) {
1148 return (expr_tbl
[i
].p
.parse_expr_arg(first
, last
,
1149 expr_tbl
[i
].val
, db
));
1151 return (expr_tbl
[i
].p
.parse_expr_noarg(first
, last
,
1158 return (parse_expr_primary(first
, last
, db
));
1160 return (parse_template_param(first
, last
, db
));
1162 return (parse_function_param(first
, last
, db
));
1172 return (parse_unresolved_name(first
, last
, db
));
1179 parse_binary_expr(const char *first
, const char *last
, const char *op
,
1182 VERIFY3P(first
, <=, last
);
1184 if (last
- first
< 2)
1187 size_t n
= nlen(db
);
1189 const char *t1
= parse_expression(first
+ 2, last
, db
);
1190 if (t1
== first
+ 2)
1195 const char *t2
= parse_expression(t1
, last
, db
);
1199 if (NAMT(db
, n
) != 3)
1202 VERIFY3U(nlen(db
), >, 2);
1204 nfmt(db
, "({2}) {1} ({0})", NULL
);
1205 if (strcmp(op
, ">") == 0)
1206 nfmt(db
, "({0})", NULL
);
1212 parse_prefix_expr(const char *first
, const char *last
, const char *op
,
1215 VERIFY3P(first
, <=, last
);
1217 if (last
- first
< 2)
1222 const char *t
= parse_expression(first
+ 2, last
, db
);
1223 if (t
== first
+ 2) {
1227 VERIFY3U(nlen(db
), >, 1);
1229 nfmt(db
, "{1}({0})", NULL
);
1234 parse_gs(const char *first
, const char *last
, cpp_db_t
*db
)
1236 VERIFY3P(first
, <=, last
);
1238 const char *t
= NULL
;
1240 if (last
- first
< 4)
1243 if (first
[2] == 'n' && (first
[3] == 'a' || first
[3] == 'w'))
1244 t
= parse_new_expr(first
+ 2, last
, db
);
1245 else if (first
[2] == 'd' && (first
[3] == 'l' || first
[3] == 'a'))
1246 t
= parse_del_expr(first
+ 2, last
, db
);
1253 VERIFY3U(nlen(db
), >, 0);
1255 nfmt(db
, "::{0}", NULL
);
1260 * [gs] nw <expression>* _ <type> E # new (expr-list) type
1261 * [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1262 * [gs] na <expression>* _ <type> E # new[] (expr-list) type
1263 * [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1264 * <initializer> ::= pi <expression>* E # parenthesized initialization
1267 parse_new_expr(const char *first
, const char *last
, cpp_db_t
*db
)
1269 VERIFY3P(first
, <=, last
);
1271 /* note [gs] is already handled by parse_gs() */
1272 if (last
- first
< 3)
1275 VERIFY3U(first
[0], ==, 'n');
1276 VERIFY(first
[1] == 'a' || first
[1] == 'w');
1278 const char *t1
= first
+ 2;
1279 const char *t2
= NULL
;
1280 size_t n
= nlen(db
);
1282 nadd_l(db
, (first
[1] == 'w') ? "new" : "new[]", 0);
1284 while (t1
!= last
&& t1
[0] != '_') {
1285 t2
= parse_expression(t1
, last
, db
);
1286 VERIFY3P(t2
, !=, NULL
);
1294 if (NAMT(db
, n
) > 1) {
1295 njoin(db
, NAMT(db
, n
) - 1, ", ");
1296 nfmt(db
, "({0})", NULL
);
1299 t2
= parse_type(t1
+ 1, last
, db
);
1306 if (t2
[0] != 'p' && t2
[1] != 'i')
1310 const char *t3
= t2
;
1311 size_t n1
= nlen(db
);
1313 while (t2
[0] != 'E' && t2
!= last
) {
1314 t3
= parse_expression(t2
, last
, db
);
1320 if (t3
== last
|| t3
[0] != 'E')
1323 if (NAMT(db
, n1
) > 0) {
1324 njoin(db
, NAMT(db
, n1
), ", ");
1325 nfmt(db
, "({0})", NULL
);
1329 njoin(db
, NAMT(db
, n
), " ");
1334 parse_del_expr(const char *first
, const char *last
, cpp_db_t
*db
)
1336 VERIFY3P(first
, <=, last
);
1338 if (last
- first
< 3)
1341 VERIFY3U(first
[0], ==, 'd');
1342 VERIFY(first
[1] == 'l' || first
[1] == 'a');
1344 size_t n
= nlen(db
);
1345 const char *t
= parse_expression(first
+ 2, last
, db
);
1346 if (t
== first
+ 2 || NAMT(db
, n
) != 1)
1349 nfmt(db
, (first
[1] == 'a') ? "delete[] {0}" : "delete {0}", NULL
);
1354 parse_idx_expr(const char *first
, const char *last
, cpp_db_t
*db
)
1356 VERIFY3P(first
, <=, last
);
1357 VERIFY3U(first
[0], ==, 'i');
1358 VERIFY3U(first
[1], ==, 'x');
1360 size_t n
= nlen(db
);
1361 const char *t1
= parse_expression(first
+ 2, last
, db
);
1362 if (t1
== first
+ 2)
1365 const char *t2
= parse_expression(t1
, last
, db
);
1366 if (t2
== t1
|| NAMT(db
, n
) != 2)
1369 nfmt(db
, "({0})[{1}]", NULL
);
1374 parse_ppmm_expr(const char *first
, const char *last
, const char *fmt
,
1377 VERIFY3P(first
, <=, last
);
1379 if (last
- first
< 3)
1382 const char *t
= NULL
;
1383 size_t n
= nlen(db
);
1385 if (first
[2] == '_') {
1386 t
= parse_binary_expr(first
+ 3, last
, "--", db
);
1392 t
= parse_expression(first
+ 2, last
, db
);
1393 if (t
== first
+ 2 || NAMT(db
, n
) < 1)
1396 nfmt(db
, fmt
, NULL
);
1401 parse_mm_expr(const char *first
, const char *last
, cpp_db_t
*db
)
1403 VERIFY3P(first
, <=, last
);
1404 VERIFY3U(first
[0], ==, 'm');
1405 VERIFY3U(first
[1], ==, 'm');
1407 return (parse_ppmm_expr(first
, last
, "({0})--", db
));
1411 parse_pp_expr(const char *first
, const char *last
, cpp_db_t
*db
)
1413 VERIFY3P(first
, <=, last
);
1415 VERIFY3U(first
[0], ==, 'p');
1416 VERIFY3U(first
[0], ==, 'p');
1418 return (parse_ppmm_expr(first
, last
, "({0})++", db
));
1422 parse_trinary_expr(const char *first
, const char *last
, cpp_db_t
*db
)
1424 VERIFY3P(first
, <=, last
);
1426 const char *t1
, *t2
, *t3
;
1427 size_t n
= nlen(db
);
1429 if (last
- first
< 2)
1432 t1
= parse_expression(first
+ 2, last
, db
);
1433 if (t1
== first
+ 2)
1435 t2
= parse_expression(t1
, last
, db
);
1438 t3
= parse_expression(t2
, last
, db
);
1442 if (NAMT(db
, n
) != 3)
1445 nfmt(db
, "({2}) ? ({1}) : ({0})", NULL
);
1450 parse_noexcept_expr(const char *first
, const char *last
, cpp_db_t
*db
)
1452 VERIFY3P(first
, <=, last
);
1454 if (last
- first
< 2)
1457 size_t n
= nlen(db
);
1458 const char *t
= parse_expression(first
+ 2, last
, db
);
1459 if (t
== first
+ 2 || NAMT(db
, n
) != 1)
1462 nfmt(db
, "noexcept ({0})", NULL
);
1467 * cc <type> <expression> # const_cast<type> (expression)
1468 * dc <type> <expression> # dynamic_cast<type> (expression)
1469 * rc <type> <expression> # reinterpret_cast<type> (expression)
1470 * sc <type> <expression> # static_cast<type> (expression)
1473 parse_cast_expr(const char *first
, const char *last
, cpp_db_t
*db
)
1475 VERIFY3P(first
, <=, last
);
1477 if (last
- first
< 2)
1480 const char *fmt
= NULL
;
1483 fmt
= "const_cast<{1}> ({0})";
1486 fmt
= "dynamic_cast<{1}> ({0})";
1489 fmt
= "reinterpret_cast<{1}> ({0})";
1492 fmt
= "static_cast<{1}> ({0})";
1498 VERIFY3U(first
[1], ==, 'c');
1500 const char *t1
= parse_type(first
+ 2, last
, db
);
1501 if (t1
== first
+ 2)
1504 const char *t2
= parse_expression(t1
, last
, db
);
1508 VERIFY3U(nlen(db
), >, 1);
1510 nfmt(db
, fmt
, NULL
);
1514 /* pt <expression> <expression> # expr->name */
1516 parse_arrow_expr(const char *first
, const char *last
, cpp_db_t
*db
)
1518 VERIFY3P(first
, <=, last
);
1520 if (last
- first
< 4)
1523 size_t n
= nlen(db
);
1525 const char *t1
= parse_expression(first
+ 2, last
, db
);
1526 if (t1
== first
+ 2)
1529 const char *t2
= parse_expression(t1
, last
, db
);
1530 if (t2
== t1
|| NAMT(db
, n
) != 2)
1533 nfmt(db
, "{1}->{0}", NULL
);
1537 /* wrap value in () when necessary */
1539 paren(str_pair_t
*sp
)
1541 str_t
*l
= &sp
->strp_l
;
1542 str_t
*r
= &sp
->strp_r
;
1544 if (str_length(r
) > 1 &&
1545 r
->str_s
[0] == ' ' && r
->str_s
[1] == '[') {
1546 (void) str_append(l
, " (", 2);
1547 (void) str_insert(r
, 0, ")", 1);
1548 } else if (str_length(r
) > 0 && r
->str_s
[0] == '(') {
1549 (void) str_append(l
, "(", 1);
1550 (void) str_insert(r
, 0, ")", 1);
1556 * <type> ::= <builtin-type>
1557 * ::= <function-type>
1558 * ::= <class-enum-type>
1560 * ::= <pointer-to-member-type>
1561 * ::= <template-param>
1562 * ::= <template-template-param> <template-args>
1564 * ::= <substitution>
1565 * ::= <CV-qualifiers> <type>
1566 * ::= P <type> # pointer-to
1567 * ::= R <type> # reference-to
1568 * ::= O <type> # rvalue reference-to (C++0x)
1569 * ::= C <type> # complex pair (C 2000)
1570 * ::= G <type> # imaginary (C 2000)
1571 * ::= Dp <type> # pack expansion (C++0x)
1572 * ::= U <source-name> <type> # vendor extended type qualifier
1573 * extension := U <objc-name> <objc-type> # objc-type<identifier>
1574 * extension := <vector-type> # <vector-type> starts with Dv
1576 * <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1577 * <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1581 parse_type(const char *first
, const char *last
, cpp_db_t
*db
)
1583 VERIFY3P(first
, <=, last
);
1592 return (parse_qual_type(first
, last
, db
));
1595 const char *t
= first
;
1596 const char *t1
= NULL
;
1597 str_pair_t
*sp
= NULL
;
1598 size_t n
= nlen(db
);
1601 t
= parse_builtin_type(first
, last
, db
);
1607 t
= parse_array_type(first
, last
, db
);
1608 if (t
== first
|| NAMT(db
, n
) == 0)
1614 t
= parse_type(first
+ 1, last
, db
);
1615 if (t
== first
+ 1 || NAMT(db
, n
) == 0)
1618 (void) str_append(TOP_L(db
), " complex", 8);
1623 t
= parse_function_type(first
, last
, db
);
1624 if (t
== first
|| NAMT(db
, n
) == 0)
1630 t
= parse_type(first
+ 1, last
, db
);
1631 if (t
== first
+ 1 || NAMT(db
, n
) == 0)
1634 (void) str_append(TOP_L(db
), " imaginary", 10);
1639 t
= parse_pointer_to_member_type(first
, last
, db
);
1640 if (t
== first
|| NAMT(db
, n
) == 0)
1646 t
= parse_type(first
+ 1, last
, db
);
1648 if (t
== first
+ 1 || amt
== 0)
1651 sp
= name_at(&db
->cpp_name
, amt
- 1);
1652 for (size_t i
= 0; i
< amt
; i
++, sp
++) {
1654 if (str_pair_len(sp
) > 0)
1655 (void) str_append(&sp
->strp_l
, "&&", 2);
1662 t
= parse_type(first
+ 1, last
, db
);
1664 if (t
== first
+ 1 || amt
== 0)
1667 sp
= name_at(&db
->cpp_name
, amt
- 1);
1668 for (size_t i
= 0; i
< amt
; i
++, sp
++) {
1669 str_t
*l
= &sp
->strp_l
;
1671 if (str_pair_len(sp
) == 0)
1675 if (first
[1] != 'U' ||
1676 strncmp(l
->str_s
, "objc_object<", 12) != 0) {
1677 (void) str_append(l
, "*", 1);
1679 (void) str_erase(l
, 0, 11);
1680 (void) str_insert(l
, 0, "id", 2);
1687 t
= parse_type(first
+ 1, last
, db
);
1689 if (t
== first
+ 1 || amt
== 0)
1692 sp
= name_at(&db
->cpp_name
, amt
- 1);
1693 for (size_t i
= 0; i
< amt
; i
++, sp
++) {
1694 if (str_length(&sp
->strp_l
) == 0 &&
1695 str_length(&sp
->strp_r
) == 0)
1699 (void) str_append(&sp
->strp_l
, "&", 1);
1706 t
= parse_template_param(first
, last
, db
);
1712 if (!db
->cpp_try_to_parse_template_args
|| amt
!= 1)
1715 t1
= parse_template_args(t
, last
, db
);
1719 nfmt(db
, "{1:L}{0}", "{1:R}");
1724 if (first
+ 1 == last
)
1727 t
= parse_source_name(first
+ 1, last
, db
);
1731 nfmt(db
, "{0}", NULL
);
1733 t1
= parse_type(t
, last
, db
);
1734 if (t1
== t
|| NAMT(db
, n
) < 2)
1737 const str_t
*name
= &name_at(&db
->cpp_name
, 1)->strp_l
;
1739 if (str_length(name
) > 0 &&
1740 strncmp(name
->str_s
, "objcproto", 9) != 0) {
1741 nfmt(db
, "{0} {1}", NULL
);
1743 t
= parse_source_name(name
->str_s
+ 9,
1744 name
->str_s
+ name
->str_len
, db
);
1745 if (t
!= name
->str_s
+ 9) {
1746 nfmt(db
, "{1}<{0}>", NULL
);
1748 str_pair_t save
= {0};
1750 name_pop(&db
->cpp_name
, &save
);
1752 /* get rid of 'objcproto' */
1753 name_pop(&db
->cpp_name
, NULL
);
1754 CK(name_add_str(&db
->cpp_name
, &save
.strp_l
,
1757 nfmt(db
, "{1} {0}", NULL
);
1765 if (first
+ 1 != last
&& first
[1] == 't') {
1766 t
= parse_name(first
, last
, NULL
, db
);
1767 if (t
== first
|| NAMT(db
, n
) == 0)
1774 t
= parse_substitution(first
, last
, db
);
1779 * If the substitution is a <template-param>, it might
1780 * be followed by <template-args>
1782 t1
= parse_template_args(t
, last
, db
);
1786 if (NAMT(db
, n
) < 2)
1789 nfmt(db
, "{1:L}{0}", "{1:R}");
1794 if (first
+ 1 == last
)
1799 t
= parse_type(first
+ 2, last
, db
);
1803 save_top(db
, NAMT(db
, n
));
1808 t
= parse_decltype(first
, last
, db
);
1816 t
= parse_vector_type(first
, last
, db
);
1820 if (NAMT(db
, n
) == 0)
1830 * must check for builtin-types before class-enum-types to avoid
1831 * ambiguities with operator-names
1833 t
= parse_builtin_type(first
, last
, db
);
1837 t
= parse_name(first
, last
, NULL
, db
);
1838 if (t
== first
|| NAMT(db
, n
) == 0)
1846 parse_qual_type(const char *first
, const char *last
, cpp_db_t
*db
)
1848 VERIFY3P(first
, <=, last
);
1850 const char *t
= NULL
;
1851 const char *t1
= NULL
;
1854 t
= parse_cv_qualifiers(first
, last
, &cv
);
1858 size_t n
= nlen(db
);
1859 boolean_t is_func
= !!(t
[0] == 'F');
1861 t1
= parse_type(t
, last
, db
);
1862 size_t amt
= NAMT(db
, n
);
1863 if (t
== t1
|| amt
== 0)
1867 sub_pop(&db
->cpp_subs
);
1869 str_pair_t
*sp
= name_at(&db
->cpp_name
, amt
- 1);
1871 for (size_t i
= 0; i
< amt
; i
++, sp
++) {
1877 if (str_length(s
) == 0)
1881 (void) str_append(s
, " const", 6);
1883 (void) str_append(s
, " volatile", 9);
1885 (void) str_append(s
, " restrict", 9);
1891 size_t pos
= str_length(s
);
1893 if (pos
> 0 && s
->str_s
[pos
- 1] == '&') {
1895 if (s
->str_s
[pos
- 1] == '&')
1900 (void) str_insert(s
, pos
, " const", 6);
1904 (void) str_insert(s
, pos
, " volatile", 9);
1908 (void) str_insert(s
, pos
, " restrict", 9);
1917 * at <type> # alignof (a type)
1918 * az <expression> # alignof (a expression)
1921 parse_alignof(const char *first
, const char *last
, cpp_db_t
*db
)
1923 VERIFY3P(first
, <=, last
);
1925 if (last
- first
< 2)
1928 const char *(*fn
)(const char *, const char *, cpp_db_t
*);
1930 fn
= (first
[1] == 't') ? parse_type
: parse_expression
;
1932 size_t n
= nlen(db
);
1933 const char *t
= fn(first
+ 2, last
, db
);
1934 if (t
== first
+ 2 || NAMT(db
, n
) != 1)
1937 nfmt(db
, "alignof ({0})", NULL
);
1942 * st <type> # sizeof (a type)
1943 * sz <expr> # sizeof (a expression)
1946 parse_sizeof(const char *first
, const char *last
, cpp_db_t
*db
)
1948 VERIFY3P(first
, <=, last
);
1950 if (last
- first
< 2)
1953 VERIFY3U(first
[0], ==, 's');
1955 const char *t
= NULL
;
1956 size_t n
= nlen(db
);
1960 t
= parse_type(first
+ 2, last
, db
);
1963 t
= parse_expression(first
+ 2, last
, db
);
1968 if (t
== first
+ 2 || NAMT(db
, n
) != 1)
1971 nfmt(db
, "sizeof ({0})", NULL
);
1977 * <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
1978 * ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
1979 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter
1980 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
1984 parse_function_param(const char *first
, const char *last
, cpp_db_t
*db
)
1986 VERIFY3P(first
, <=, last
);
1988 if (last
- first
< 3 || first
[0] != 'f')
1991 const char *t1
= first
+ 2;
1992 const char *t2
= NULL
;
1995 if (first
[1] == 'L') {
1996 t2
= parse_number(t1
, last
, db
->cpp_loc
);
1997 if (t2
== last
|| t2
[0] != 'p')
2002 if (first
[1] != 'p')
2005 t1
= parse_cv_qualifiers(t1
, last
, &cv
);
2006 t2
= parse_number(t1
, last
, db
->cpp_loc
);
2007 if (t2
== last
|| t2
[0] != '_')
2011 nadd_l(db
, t1
, (size_t)(t2
- t1
));
2015 nfmt(db
, "fp{0}", NULL
);
2020 * sZ <template-param> # size of a parameter pack
2021 * sZ <function-param> # size of a function parameter pack
2024 parse_sizeof_param_pack_expr(const char *first
, const char *last
, cpp_db_t
*db
)
2026 VERIFY3P(first
, <=, last
);
2028 if (last
- first
< 3)
2031 VERIFY3U(first
[0], ==, 's');
2032 VERIFY3U(first
[1], ==, 'Z');
2034 if (first
[2] != 'T' && first
[2] != 'f')
2037 const char *t
= NULL
;
2038 size_t n
= nlen(db
);
2040 if (first
[2] == 'T')
2041 t
= parse_template_param(first
+ 2, last
, db
);
2043 t
= parse_function_param(first
+ 2, last
, db
);
2048 njoin(db
, NAMT(db
, n
), ", ");
2049 nfmt(db
, "sizeof...({0})", NULL
);
2054 * te <expression> # typeid (expression)
2055 * ti <type> # typeid (type)
2058 parse_typeid_expr(const char *first
, const char *last
, cpp_db_t
*db
)
2060 VERIFY3P(first
, <=, last
);
2062 if (last
- first
< 3)
2065 VERIFY3U(first
[0], ==, 't');
2066 VERIFY(first
[1] == 'e' || first
[1] == 'i');
2068 const char *t
= NULL
;
2069 size_t n
= nlen(db
);
2071 if (first
[1] == 'e')
2072 t
= parse_expression(first
+ 2, last
, db
);
2074 t
= parse_type(first
+ 2, last
, db
);
2076 if (t
== first
+ 2 || NAMT(db
, n
) != 1)
2079 nfmt(db
, "typeid ({0})", NULL
);
2085 * tw <expression> # throw expression
2088 parse_throw_expr(const char *first
, const char *last
, cpp_db_t
*db
)
2090 VERIFY3P(first
, <=, last
);
2092 if (last
- first
< 3)
2095 VERIFY3U(first
[0], ==, 't');
2096 VERIFY(first
[1] == 'w' || first
[1] == 'r');
2098 if (first
[1] == 'r') {
2099 nadd_l(db
, "throw", 0);
2103 size_t n
= nlen(db
);
2104 const char *t
= parse_expression(first
+ 2, last
, db
);
2105 if (t
== first
+ 2 || NAMT(db
, n
) != 1)
2108 nfmt(db
, "throw {0}", NULL
);
2112 /* ds <expression> <expression> # expr.*expr */
2114 parse_dot_star_expr(const char *first
, const char *last
, cpp_db_t
*db
)
2116 VERIFY3P(first
, <=, last
);
2118 if (last
- first
< 3)
2121 VERIFY3U(first
[0], ==, 'd');
2122 VERIFY3U(first
[1], ==, 's');
2124 size_t n
= nlen(db
);
2125 const char *t
= parse_expression(first
+ 2, last
, db
);
2129 const char *t2
= parse_expression(t
, last
, db
);
2130 if (t
== t2
|| NAMT(db
, n
) != 2)
2133 nfmt(db
, "{1}.*{0}", NULL
);
2137 /* dt <expression> <unresolved-name> # expr.name */
2139 parse_dot_expr(const char *first
, const char *last
, cpp_db_t
*db
)
2141 VERIFY3P(first
, <=, last
);
2143 if (last
- first
< 3)
2146 VERIFY3U(first
[0], ==, 'd');
2147 VERIFY3U(first
[1], ==, 't');
2149 const char *t
= parse_expression(first
+ 2, last
, db
);
2153 const char *t1
= parse_unresolved_name(t
, last
, db
);
2157 nfmt(db
, "{1}.{0}", NULL
);
2161 /* cl <expression>+ E # call */
2163 parse_call_expr(const char *first
, const char *last
, cpp_db_t
*db
)
2165 VERIFY3P(first
, <=, last
);
2167 if (last
- first
< 4)
2170 VERIFY3U(first
[0], ==, 'c');
2171 VERIFY3U(first
[1], ==, 'l');
2173 const char *t
= first
+ 2;
2174 const char *t1
= NULL
;
2175 size_t n
= nlen(db
);
2177 for (t
= first
+ 2; t
!= last
&& t
[0] != 'E'; t
= t1
) {
2178 t1
= parse_expression(t
, last
, db
);
2183 size_t amt
= NAMT(db
, n
);
2185 if (t
== last
|| amt
== 0)
2188 njoin(db
, amt
- 1, ", ");
2189 nfmt(db
, "{1}({0})", NULL
);
2191 VERIFY3U(t
[0], ==, 'E');
2197 * cv <type> <expression> # conversion with one argument
2198 * cv <type> _ <expression>* E # conversion with a different number of arguments
2202 parse_conv_expr(const char *first
, const char *last
, cpp_db_t
*db
)
2204 VERIFY3P(first
, <=, last
);
2206 if (last
- first
< 3)
2209 VERIFY3U(first
[0], ==, 'c');
2210 VERIFY3U(first
[1], ==, 'v');
2212 const char *t
= NULL
;
2213 const char *t1
= NULL
;
2214 size_t n
= nlen(db
);
2216 boolean_t try_to_parse_template_args
=
2217 db
->cpp_try_to_parse_template_args
;
2219 db
->cpp_try_to_parse_template_args
= B_FALSE
;
2220 t
= parse_type(first
+ 2, last
, db
);
2221 db
->cpp_try_to_parse_template_args
= try_to_parse_template_args
;
2227 t1
= parse_expression(t
, last
, db
);
2233 size_t n1
= nlen(db
);
2237 while (t
[0] != 'E' && t
!= last
) {
2238 t1
= parse_expression(t
, last
, db
);
2247 njoin(db
, NAMT(db
, n1
), ", ");
2250 if (NAMT(db
, n
) < 2)
2253 nfmt(db
, "({1})({0})", NULL
);
2257 /* <simple-id> ::= <source-name> [ <template-args> ] */
2259 parse_simple_id(const char *first
, const char *last
, cpp_db_t
*db
)
2261 VERIFY3P(first
, <=, last
);
2263 const char *t
= parse_source_name(first
, last
, db
);
2267 const char *t1
= parse_template_args(t
, last
, db
);
2271 nfmt(db
, "{1}{0}", NULL
);
2276 * <unresolved-type> ::= <template-param>
2278 * ::= <substitution>
2281 parse_unresolved_type(const char *first
, const char *last
, cpp_db_t
*db
)
2283 VERIFY3P(first
, <=, last
);
2288 const char *t
= first
;
2289 size_t n
= nlen(db
);
2293 t
= parse_template_param(first
, last
, db
);
2294 if (t
== first
|| NAMT(db
, n
) != 1) {
2295 for (size_t i
= 0; i
< NAMT(db
, n
); i
++)
2296 name_pop(&db
->cpp_name
, NULL
);
2303 t
= parse_decltype(first
, last
, db
);
2304 if (t
== first
|| NAMT(db
, n
) == 0)
2310 t
= parse_substitution(first
, last
, db
);
2314 if (last
- first
< 2 || first
[1] != 't')
2317 t
= parse_unqualified_name(first
+ 2, last
, db
);
2318 if (t
== first
+ 2 || NAMT(db
, n
) == 0)
2321 nfmt(db
, "std::{0:L}", "{0:R}");
2329 /* sp <expression> # pack expansion */
2331 parse_pack_expansion(const char *first
, const char *last
, cpp_db_t
*db
)
2333 VERIFY3P(first
, <=, last
);
2335 if (last
- first
< 3)
2338 VERIFY3U(first
[0], ==, 's');
2339 VERIFY3U(first
[1], ==, 'p');
2341 const char *t
= parse_expression(first
+ 2, last
, db
);
2349 * <unscoped-name> ::= <unqualified-name>
2350 * ::= St <unqualified-name> # ::std::
2351 * extension ::= StL<unqualified-name>
2354 parse_unscoped_name(const char *first
, const char *last
, cpp_db_t
*db
)
2356 VERIFY3P(first
, <=, last
);
2358 if (last
- first
< 2)
2361 const char *t
= first
;
2362 const char *t1
= NULL
;
2363 boolean_t st
= B_FALSE
;
2365 if (first
[0] == 'S' && first
[1] == 't') {
2369 if (first
+ 3 != last
&& first
[2] == 'L')
2373 t1
= parse_unqualified_name(t
, last
, db
);
2378 nfmt(db
, "std::{0}", NULL
);
2384 * <unqualified-name> ::= <operator-name>
2385 * ::= <ctor-dtor-name>
2387 * ::= <unnamed-type-name>
2390 parse_unqualified_name(const char *first
, const char *last
, cpp_db_t
*db
)
2392 VERIFY3P(first
, <=, last
);
2400 return (parse_ctor_dtor_name(first
, last
, db
));
2402 return (parse_unnamed_type_name(first
, last
, db
));
2413 return (parse_source_name(first
, last
, db
));
2415 return (parse_operator_name(first
, last
, db
));
2420 * <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
2421 * ::= <closure-type-name>
2423 * <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2425 * <lambda-sig> ::= <parameter type>+
2426 * # Parameter types or "v" if the lambda has no parameters
2429 parse_unnamed_type_name(const char *first
, const char *last
, cpp_db_t
*db
)
2431 VERIFY3P(first
, <=, last
);
2433 if (last
- first
< 2 || first
[0] != 'U')
2436 if (first
[1] != 't' && first
[1] != 'l')
2439 const char *t1
= first
+ 2;
2440 const char *t2
= NULL
;
2442 if (first
[1] == 't') {
2443 while (t1
!= last
&& t1
[0] != '_' &&
2444 isdigit_l(t1
[0], db
->cpp_loc
))
2450 if (t1
== first
+ 2)
2453 nadd_l(db
, first
+ 2, (size_t)(t1
- first
- 2));
2455 nfmt(db
, "'unnamed{0}'", NULL
);
2459 size_t n
= nlen(db
);
2461 if (first
[2] != 'v') {
2463 t2
= parse_type(t1
, last
, db
);
2467 } while (t1
!= last
&& t1
[0] != 'E');
2469 if (t1
== last
|| NAMT(db
, n
) < 1)
2472 if (NAMT(db
, n
) < 1)
2480 njoin(db
, NAMT(db
, n
), ", ");
2486 while (t2
!= last
&& t2
[0] != '_') {
2487 if (!isdigit_l(*t2
++, db
->cpp_loc
))
2495 nadd_l(db
, t1
, (size_t)(t2
- t1
));
2499 nfmt(db
, "'lambda{0}'({1})", NULL
);
2507 const char *fullname
;
2508 const char *basename
;
2512 "std::basic_string<char, std::char_traits<char>, "
2513 "std::allocator<char> >",
2518 "std::basic_istream<char, std::char_traits<char> >",
2523 "std::basic_ostream<char, std::char_traits<char> >",
2528 "std::basic_iostream<char, std::char_traits<char> >",
2534 basename(cpp_db_t
*db
)
2536 str_t
*s
= TOP_L(db
);
2538 for (size_t i
= 0; i
< ARRAY_SIZE(aliases
); i
++) {
2539 if (str_length(s
) != strlen(aliases
[i
].alias
))
2541 if (strncmp(aliases
[i
].alias
, s
->str_s
, str_length(s
)) != 0)
2544 /* swap out alias for full name */
2545 sysdem_ops_t
*ops
= s
->str_ops
;
2548 str_set(s
, aliases
[i
].fullname
, 0);
2550 nadd_l(db
, aliases
[i
].basename
, 0);
2554 const char *start
= s
->str_s
;
2555 const char *end
= s
->str_s
+ s
->str_len
;
2558 * if name ends with a template i.e. <.....> back up to start
2559 * of outermost template
2563 if (end
[-1] == '>') {
2564 for (; end
> start
; end
--) {
2580 VERIFY3P(end
, >=, start
);
2582 if (end
- start
< 2) {
2587 for (start
= end
- 1; start
> s
->str_s
; start
--) {
2588 if (start
[0] == ':') {
2594 VERIFY3P(end
, >=, start
);
2596 nadd_l(db
, start
, (size_t)(end
- start
));
2600 * <ctor-dtor-name> ::= C1 # complete object constructor
2601 * ::= C2 # base object constructor
2602 * ::= C3 # complete object allocating constructor
2603 * extension ::= C5 # ?
2604 * ::= D0 # deleting destructor
2605 * ::= D1 # complete object destructor
2606 * ::= D2 # base object destructor
2607 * extension ::= D5 # ?
2610 parse_ctor_dtor_name(const char *first
, const char *last
, cpp_db_t
*db
)
2612 VERIFY3P(first
, <=, last
);
2614 if (last
- first
< 2 || nempty(db
) || str_length(TOP_L(db
)) == 0)
2637 (void) str_insert(TOP_L(db
), 0, "~", 1);
2647 db
->cpp_parsed_ctor_dtor_cv
= B_TRUE
;
2652 parse_integer_literal(const char *first
, const char *last
, const char *fmt
,
2655 VERIFY3P(first
, <=, last
);
2657 const char *t
= parse_number(first
, last
, db
->cpp_loc
);
2658 const char *start
= first
;
2660 if (t
== first
|| t
== last
|| t
[0] != 'E')
2663 if (first
[0] == 'n')
2666 nadd_l(db
, start
, (size_t)(t
- start
));
2668 nfmt(db
, "-{0}", NULL
);
2670 nfmt(db
, fmt
, NULL
);
2674 static struct float_data_s
{
2676 size_t mangled_size
;
2677 size_t max_demangled_size
;
2680 { "%af", 8, 24, 'f' }, /* float */
2681 { "%a", 16, 32, 'd' }, /* double */
2682 { "%LaL", 20, 40, 'e' } /* long double */
2686 parse_floating_literal(const char *first
, const char *last
, cpp_db_t
*db
)
2688 VERIFY3P(first
, <=, last
);
2689 VERIFY(first
[0] == 'f' || first
[0] == 'd' || first
[0] == 'e');
2691 const struct float_data_s
*fd
= NULL
;
2693 for (size_t i
= 0; i
< ARRAY_SIZE(float_info
); i
++) {
2694 if (float_info
[i
].type
!= first
[0])
2697 fd
= &float_info
[i
];
2701 if (fd
== NULL
|| (size_t)(last
- first
) < fd
->mangled_size
)
2707 char buf
[sizeof (float)];
2711 char buf
[sizeof (double)];
2715 char buf
[sizeof (long double)];
2719 const char *t
= NULL
;
2733 last
= first
+ fd
->mangled_size
+ 1;
2735 #if defined(_BIG_ENDIAN)
2736 for (t
= first
+ 1; t
!= last
; t
++, e
++) {
2737 if (!is_xdigit(t
[0]))
2740 unsigned d1
= isdigit_l(t
[0], db
->cpp_loc
) ?
2741 t
[0] - '0' : t
[0] - 'a' + 10;
2743 unsigned d0
= isdigit_l(t
[0], db
->cpp_loc
) ?
2744 t
[0] - '0' : t
[0] - 'a' + 10;
2746 *e
= (d1
<< 4) + d0
;
2748 #elif defined(_LITTLE_ENDIAN)
2749 for (t
= last
- 1; t
> first
; t
--, e
++) {
2750 if (!is_xdigit(t
[0]))
2753 unsigned d0
= isdigit_l(t
[0], db
->cpp_loc
) ?
2754 t
[0] - '0' : t
[0] - 'a' + 10;
2756 unsigned d1
= isdigit_l(t
[0], db
->cpp_loc
) ?
2757 t
[0] - '0' : t
[0] - 'a' + 10;
2759 *e
= (d1
<< 4) + d0
;
2763 #error One of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined
2770 str_init(&num
, db
->cpp_ops
);
2772 num
.str_size
= fd
->max_demangled_size
+ 1;
2773 num
.str_s
= zalloc(db
->cpp_ops
, num
.str_size
);
2774 CK(num
.str_s
!= NULL
);
2780 n
= snprintf(num
.str_s
, fd
->max_demangled_size
, fd
->spec
,
2784 n
= snprintf(num
.str_s
, fd
->max_demangled_size
, fd
->spec
,
2788 n
= snprintf(num
.str_s
, fd
->max_demangled_size
, fd
->spec
,
2792 if (n
>= fd
->max_demangled_size
|| n
<= 0) {
2798 (void) name_add_str(&db
->cpp_name
, &num
, NULL
);
2804 * <expr-primary> ::= L <type> <value number> E # integer literal
2805 * ::= L <type> <value float> E # floating literal
2806 * ::= L <string type> E # string literal
2807 * ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
2809 * ::= L <type> <real-part float> _ <imag-part float> E
2810 * # complex floating point
2811 * # literal (C 2000)
2813 * ::= L <mangled-name> E # external name
2819 { 'a', "(signed char){0}" },
2820 { 'c', "(char){0}" },
2821 { 'h', "(unsigned char){0}" },
2826 { 'n', "(__int128){0}" },
2827 { 'o', "(unsigned __int128){0}" },
2828 { 's', "(short){0}" },
2829 { 't', "(unsigned short){0}" },
2830 { 'w', "(wchar_t){0}" },
2836 parse_expr_primary(const char *first
, const char *last
, cpp_db_t
*db
)
2838 VERIFY3P(first
, <=, last
);
2840 if (last
- first
< 4 || first
[0] != 'L')
2843 const char *t
= NULL
;
2845 for (size_t i
= 0; i
< ARRAY_SIZE(int_lits
); i
++) {
2846 if (first
[1] == int_lits
[i
].c
) {
2847 t
= parse_integer_literal(first
+ 2, last
,
2848 int_lits
[i
].fmt
, db
);
2849 return ((t
== first
+ 2) ? first
: t
);
2855 if (first
[3] != 'E')
2860 nadd_l(db
, "false", 5);
2863 nadd_l(db
, "true", 4);
2869 case 'd': /* double */
2870 case 'e': /* long double */
2871 case 'f': /* float */
2872 t
= parse_floating_literal(first
+ 1, last
, db
);
2873 return ((t
== first
+ 1) ? first
: t
);
2877 * Invalid mangled name per
2878 * http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
2884 if (first
[2] != 'Z')
2887 t
= parse_encoding(first
+ 3, last
, db
);
2888 if (t
== first
+ 3 || t
== last
|| t
[0] != 'E')
2894 t
= parse_type(first
+ 1, last
, db
);
2895 if (t
== first
+ 1 || t
== last
)
2902 for (n
= t
; n
!= last
&& isdigit_l(n
[0], db
->cpp_loc
); n
++)
2904 if (n
== last
|| nempty(db
) || n
[0] != 'E')
2909 nadd_l(db
, t
, (size_t)(n
- t
));
2910 nfmt(db
, "({1}){0}", NULL
);
2919 * ::= ad # & (unary)
2926 * ::= cv <type> # (cast)
2928 * ::= de # * (unary)
2939 * ::= li <source-name> # operator ""
2947 * ::= mm # -- (postfix in <expression> context)
2950 * ::= ng # - (unary)
2959 * ::= pp # ++ (postfix in <expression> context)
2960 * ::= ps # + (unary)
2967 * ::= v <digit> <source-name> # vendor extended operator
2973 { "aa", "operator&&" },
2974 { "ad", "operator&" },
2975 { "an", "operator&" },
2976 { "aN", "operator&=" },
2977 { "aS", "operator=" },
2978 { "cl", "operator()" },
2979 { "cm", "operator," },
2980 { "co", "operator~" },
2981 { "da", "operator delete[]" },
2982 { "de", "operator*" },
2983 { "dl", "operator delete" },
2984 { "dv", "operator/" },
2985 { "dV", "operator/=" },
2986 { "eo", "operator^" },
2987 { "eO", "operator^=" },
2988 { "eq", "operator==" },
2989 { "ge", "operator>=" },
2990 { "gt", "operator>" },
2991 { "ix", "operator[]" },
2992 { "le", "operator<=" },
2993 { "ls", "operator<<" },
2994 { "lS", "operator<<=" },
2995 { "lt", "operator<" },
2996 { "mi", "operator-" },
2997 { "mI", "operator-=" },
2998 { "ml", "operator*" },
2999 { "mL", "operator*=" },
3000 { "mm", "operator--" },
3001 { "na", "operator new[]" },
3002 { "ne", "operator!=" },
3003 { "ng", "operator-" },
3004 { "nt", "operator!" },
3005 { "nw", "operator new" },
3006 { "oo", "operator||" },
3007 { "or", "operator|" },
3008 { "oR", "operator|=" },
3009 { "pm", "operator->*" },
3010 { "pl", "operator+" },
3011 { "pL", "operator+=" },
3012 { "pp", "operator++" },
3013 { "ps", "operator+" },
3014 { "pt", "operator->" },
3015 { "qu", "operator?" },
3016 { "rm", "operator%" },
3017 { "rM", "operator%=" },
3018 { "rs", "operator>>" },
3019 { "rS", "operator>>=" }
3023 parse_operator_name(const char *first
, const char *last
, cpp_db_t
*db
)
3025 VERIFY3P(first
, <=, last
);
3027 if (last
- first
< 2)
3030 for (size_t i
= 0; i
< ARRAY_SIZE(op_tbl
); i
++) {
3031 if (strncmp(first
, op_tbl
[i
].code
, 2) != 0)
3034 nadd_l(db
, op_tbl
[i
].op
, 0);
3038 const char *t
= NULL
;
3040 if (first
[0] == 'l' && first
[1] == 'i') {
3041 t
= parse_source_name(first
+ 2, last
, db
);
3042 if (t
== first
+ 2 || nempty(db
))
3045 nfmt(db
, "operator\"\" {0}", NULL
);
3049 if (first
[0] == 'v') {
3050 if (!isdigit_l(first
[1], db
->cpp_loc
))
3053 t
= parse_source_name(first
+ 2, last
, db
);
3057 nfmt(db
, "operator {0}", NULL
);
3061 if (first
[0] != 'c' && first
[1] != 'v')
3064 boolean_t try_to_parse_template_args
=
3065 db
->cpp_try_to_parse_template_args
;
3067 db
->cpp_try_to_parse_template_args
= B_FALSE
;
3068 t
= parse_type(first
+ 2, last
, db
);
3069 db
->cpp_try_to_parse_template_args
= try_to_parse_template_args
;
3071 if (t
== first
+ 2 || nempty(db
))
3074 nfmt(db
, "operator {0}", NULL
);
3075 db
->cpp_parsed_ctor_dtor_cv
= B_TRUE
;
3084 static struct type_tbl_s type_tbl1
[] = {
3085 { 'a', "signed char" },
3089 { 'e', "long double" },
3091 { 'g', "__float128" },
3092 { 'h', "unsigned char" },
3094 { 'j', "unsigned int" },
3096 { 'm', "unsigned long" },
3097 { 'n', "__int128" },
3098 { 'o', "unsigned __int128" },
3100 { 't', "unsigned short" },
3103 { 'x', "long long" },
3104 { 'y', "unsigned long long" },
3108 static struct type_tbl_s type_tbl2
[] = {
3110 { 'c', "decltype(auto)" },
3111 { 'd', "decimal64" },
3112 { 'e', "decimal128" },
3113 { 'f', "decimal32" },
3114 { 'h', "decimal16" },
3115 { 'i', "char32_t" },
3116 { 'n', "std::nullptr_t" },
3121 parse_builtin_type(const char *first
, const char *last
, cpp_db_t
*db
)
3123 VERIFY3P(first
, <=, last
);
3130 for (i
= 0; i
< ARRAY_SIZE(type_tbl1
); i
++) {
3131 if (first
[0] == type_tbl1
[i
].code
) {
3132 nadd_l(db
, type_tbl1
[i
].name
, 0);
3137 if (first
[0] == 'D') {
3138 if (first
+ 1 == last
)
3140 for (i
= 0; i
< ARRAY_SIZE(type_tbl2
); i
++) {
3141 if (first
[1] == type_tbl2
[i
].code
) {
3142 nadd_l(db
, type_tbl2
[i
].name
, 0);
3148 if (first
[0] == 'u') {
3149 const char *t
= parse_source_name(first
+ 1, last
, db
);
3159 parse_base36(const char *first
, const char *last
, size_t *val
, locale_t loc
)
3161 VERIFY3P(first
, <=, last
);
3165 for (t
= first
, *val
= 0; t
!= last
; t
++) {
3166 if (!isdigit_l(t
[0], loc
) && !isupper_l(t
[0], loc
))
3171 if (isdigit_l(t
[0], loc
))
3174 *val
+= t
[0] - 'A' + 10;
3179 static struct type_tbl_s sub_tbl
[] = {
3180 { 'a', "std::allocator" },
3181 { 'b', "std::basic_string" },
3182 { 's', "std::string" },
3183 { 'i', "std::istream" },
3184 { 'o', "std::ostream" },
3185 { 'd', "std::iostream" }
3189 parse_substitution(const char *first
, const char *last
, cpp_db_t
*db
)
3191 VERIFY3P(first
, <=, last
);
3193 if (first
== last
|| last
- first
< 2)
3196 if (first
[0] != 'S')
3199 for (size_t i
= 0; i
< ARRAY_SIZE(sub_tbl
); i
++) {
3200 if (first
[1] == sub_tbl
[i
].code
) {
3201 nadd_l(db
, sub_tbl
[i
].name
, 0);
3206 const char *t
= first
+ 1;
3210 t
= parse_base36(first
+ 1, last
, &n
, db
->cpp_loc
);
3211 if (t
== first
+ 1 || t
[0] != '_')
3215 * S_ == substitution 0,
3216 * S0_ == substituion 1,
3222 if (n
>= sub_len(&db
->cpp_subs
))
3228 VERIFY3U(t
[0], ==, '_');
3234 parse_source_name(const char *first
, const char *last
, cpp_db_t
*db
)
3236 VERIFY3P(first
, <=, last
);
3241 const char *t
= NULL
;
3244 for (t
= first
; t
!= last
&& isdigit_l(t
[0], db
->cpp_loc
); t
++) {
3245 /* make sure we don't overflow */
3257 if (n
== 0 || t
== last
|| t
+ n
> last
||
3258 (uintptr_t)t
+ n
< (uintptr_t)t
)
3261 if (strncmp(t
, "_GLOBAL__N", 10) == 0)
3262 nadd_l(db
, "(anonymous namespace)", 0);
3271 * <vector-type> ::= Dv <positive dimension number> _
3272 * <extended element type>
3273 * ::= Dv [<dimension expression>] _ <element type>
3274 * <extended element type> ::= <element type>
3275 * ::= p # AltiVec vector pixel
3278 parse_vector_type(const char *first
, const char *last
, cpp_db_t
*db
)
3280 VERIFY3P(first
, <=, last
);
3282 if (last
- first
< 3)
3285 VERIFY3U(first
[0], ==, 'D');
3286 VERIFY3U(first
[1], ==, 'v');
3288 const char *t
= first
+ 2;
3289 const char *t1
= NULL
;
3291 if (isdigit_l(first
[2], db
->cpp_loc
) && first
[2] != '0') {
3292 t1
= parse_number(t
, last
, db
->cpp_loc
);
3293 if (t1
== last
|| t1
+ 1 == last
|| t1
[0] != '_')
3296 nadd_l(db
, t
, (size_t)(t1
- t
));
3302 t1
= parse_type(t
, last
, db
);
3306 nfmt(db
, "{0} vector[{1}]", NULL
);
3309 nfmt(db
, "{0} pixel vector[{1}]", NULL
);
3313 if (first
[2] != '_') {
3314 t1
= parse_expression(first
+ 2, last
, db
);
3315 if (first
== last
|| t1
== first
+ 2 || t1
[0] != '_')
3324 t1
= parse_type(t
, last
, db
);
3328 nfmt(db
, "{1:L} vector[{0}]", "{1:R}");
3334 * <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3335 * ::= DT <expression> E # decltype of an expression (C++0x)
3339 parse_decltype(const char *first
, const char *last
, cpp_db_t
*db
)
3341 VERIFY3P(first
, <=, last
);
3343 if (last
- first
< 4)
3346 VERIFY3U(first
[0], ==, 'D');
3348 if (first
[1] != 't' && first
[1] != 'T')
3351 size_t n
= nlen(db
);
3352 const char *t
= parse_expression(first
+ 2, last
, db
);
3353 if (NAMT(db
, n
) != 1 || t
== first
+ 2 || t
== last
|| t
[0] != 'E')
3356 nfmt(db
, "decltype({0})", NULL
);
3363 * <array-type> ::= A <positive dimension number> _ <element type>
3364 * ::= A [<dimension expression>] _ <element type>
3367 parse_array_type(const char *first
, const char *last
, cpp_db_t
*db
)
3369 VERIFY3P(first
, <=, last
);
3370 VERIFY3U(first
[0], ==, 'A');
3372 if (last
- first
< 3)
3375 const char *t
= first
+ 1;
3376 const char *t1
= NULL
;
3377 size_t n
= nlen(db
);
3380 if (isdigit_l(t
[0], db
->cpp_loc
) && t
[0] != '0') {
3381 t1
= parse_number(t
, last
, db
->cpp_loc
);
3385 nadd_l(db
, t
, (size_t)(t1
- t
));
3387 t1
= parse_expression(t
, last
, db
);
3388 if (t1
== last
|| t
== t1
)
3400 VERIFY3U(t
[0], ==, '_');
3402 t1
= parse_type(t
+ 1, last
, db
);
3403 if (t1
== t
+ 1 || NAMT(db
, n
) != 2)
3407 * if we have " [xxx]" already, want new result to be
3410 str_t
*r
= &name_top(&db
->cpp_name
)->strp_r
;
3411 if (r
->str_len
> 1 && r
->str_s
[0] == ' ' && r
->str_s
[1] == '[')
3412 (void) str_erase(r
, 0, 1);
3414 nfmt(db
, "{0:L}", " [{1}]{0:R}");
3418 /* <pointer-to-member-type> ::= M <class type> <member type> */
3420 parse_pointer_to_member_type(const char *first
, const char *last
, cpp_db_t
*db
)
3422 VERIFY3P(first
, <=, last
);
3424 if (last
- first
< 3)
3427 VERIFY3U(first
[0], ==, 'M');
3429 const char *t1
= first
+ 1;
3430 const char *t2
= NULL
;
3431 size_t n
= nlen(db
);
3433 t2
= parse_type(t1
, last
, db
);
3438 t2
= parse_type(t1
, last
, db
);
3442 if (NAMT(db
, n
) != 2)
3445 str_pair_t
*func
= name_top(&db
->cpp_name
);
3447 if (str_length(&func
->strp_r
) > 0 && func
->strp_r
.str_s
[0] == '(')
3448 nfmt(db
, "{0:L}({1}::*", "){0:R}");
3450 nfmt(db
, "{0:L} {1}::*", "{0:R}");
3458 * extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3459 * ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3460 * ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3461 * # A::x, N::y, A<T>::z; "gs" means leading "::"
3462 * ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3463 * extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3464 * # T::N::x /decltype(p)::N::x
3465 * (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3469 parse_unresolved_name(const char *first
, const char *last
, cpp_db_t
*db
)
3471 VERIFY3P(first
, <=, last
);
3473 if (last
- first
< 2)
3476 const char *t
= first
;
3477 const char *t2
= NULL
;
3478 boolean_t global
= B_FALSE
;
3481 if (t
[0] == 'g' && t
[1] == 's') {
3488 t2
= parse_base_unresolved_name(t
, last
, db
);
3494 (void) str_insert(TOP_L(db
), 0, "::", 2);
3499 if (t
[0] != 's' || t
[1] != 'r' || last
- t
< 2)
3505 t2
= parse_unresolved_type(t
, last
, db
);
3506 if (t2
== t
|| t2
== last
)
3510 t2
= parse_template_args(t
, last
, db
);
3512 if (NAMT(db
, n
) < 2 || t2
== last
)
3515 nfmt(db
, "{1:L}{0}", "{1:R}");
3519 VERIFY3U(NAMT(db
, n
), ==, 1);
3521 while (t
[0] != 'E') {
3522 size_t nn
= nlen(db
);
3523 t2
= parse_unresolved_qualifier_level(t
, last
, db
);
3524 if (t
== t2
|| t
== last
|| NAMT(db
, nn
) != 1)
3533 t2
= parse_base_unresolved_name(t
, last
, db
);
3534 if (t
== t2
|| NAMT(db
, n
) < 2)
3537 njoin(db
, NAMT(db
, n
), "::");
3543 t2
= parse_unresolved_type(t
, last
, db
);
3546 t2
= parse_template_args(t
, last
, db
);
3548 nfmt(db
, "{1:L}{0}", "{1:R}");
3551 t2
= parse_base_unresolved_name(t
, last
, db
);
3552 if (t
== t2
|| nlen(db
) < 2)
3555 nfmt(db
, "{1:L}::{0}", "{1:R}");
3559 t2
= parse_unresolved_qualifier_level(t
, last
, db
);
3560 if (t2
== t
|| t2
== last
)
3564 if (global
&& nlen(db
) > 0)
3565 nfmt(db
, "::{0:L}", "{0:R}");
3567 while (t
[0] != 'E') {
3568 t2
= parse_unresolved_qualifier_level(t
, last
, db
);
3569 if (t
== t2
|| t
== last
|| nlen(db
) < 2)
3578 t2
= parse_base_unresolved_name(t
, last
, db
);
3579 if (t
== t2
|| nlen(db
) < 2)
3582 njoin(db
, NAMT(db
, n
), "::");
3586 /* <unresolved-qualifier-level> ::= <simple-id> */
3588 parse_unresolved_qualifier_level(const char *first
, const char *last
,
3591 VERIFY3P(first
, <=, last
);
3592 return (parse_simple_id(first
, last
, db
));
3597 * <base-unresolved-name> ::= <simple-id> # unresolved name
3598 * extension ::= <operator-name> # unresolved operator-function-id
3599 * extension ::= <operator-name> <template-args> # unresolved operator template-id
3600 * ::= on <operator-name> # unresolved operator-function-id
3601 * ::= on <operator-name> <template-args> # unresolved operator template-id
3602 * ::= dn <destructor-name> # destructor or pseudo-destructor;
3603 * # e.g. ~X or ~X<N-1>
3607 parse_base_unresolved_name(const char *first
, const char *last
, cpp_db_t
*db
)
3609 VERIFY3P(first
, <=, last
);
3611 if (last
- first
< 2)
3614 const char *t
= NULL
;
3615 const char *t1
= NULL
;
3617 if ((first
[0] != 'o' && first
[0] != 'd') || first
[1] != 'n') {
3618 t
= parse_simple_id(first
, last
, db
);
3622 t
= parse_operator_name(first
, last
, db
);
3626 t1
= parse_template_args(t
, last
, db
);
3630 nfmt(db
, "{1:L}{0}", "{1:R}");
3636 if (first
[0] == 'd') {
3637 t
= parse_destructor_name(first
+ 2, last
, db
);
3638 return ((t
!= first
+ 2) ? t
: first
);
3641 t
= parse_operator_name(first
+ 2, last
, db
);
3645 t1
= parse_template_args(t
, last
, db
);
3647 nfmt(db
, "{1:L}{0}", "{1:R}");
3652 * <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3653 * ::= <simple-id> # e.g., ~A<2*N>
3656 parse_destructor_name(const char *first
, const char *last
, cpp_db_t
*db
)
3658 VERIFY3P(first
, <=, last
);
3663 const char *t
= parse_unresolved_type(first
, last
, db
);
3666 t
= parse_simple_id(first
, last
, db
);
3671 nfmt(db
, "~{0:L}", "{0:R}");
3676 * <ref-qualifier> ::= R # & ref-qualifier
3677 * <ref-qualifier> ::= O # && ref-qualifier
3679 * <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
3682 parse_function_type(const char *first
, const char *last
, cpp_db_t
*db
)
3684 VERIFY3P(first
, <=, last
);
3686 if (last
- first
< 2)
3689 VERIFY3U(first
[0], ==, 'F');
3691 const char *t
= first
+ 1;
3697 const char *t1
= parse_type(t
, last
, db
);
3701 size_t n
= nlen(db
);
3706 while (t
!= last
&& t
[0] != 'E') {
3712 if (t
[0] == 'R' && t
+ 1 != last
&& t
[1] == 'E') {
3718 if (t
[0] == 'O' && t
+ 1 != last
&& t
[1] == 'E') {
3725 t1
= parse_type(t
, last
, db
);
3726 if (t1
== t
|| t
== last
)
3735 njoin(db
, NAMT(db
, n
), ", ");
3736 nfmt(db
, "({0})", NULL
);
3740 nfmt(db
, "{0} &", NULL
);
3743 nfmt(db
, "{0} &&", NULL
);
3747 nfmt(db
, "{1:L} ", "{0}{1:R}");
3754 * <template-param> ::= T_ # first template parameter
3755 * ::= T <parameter-2 non-negative number> _
3758 parse_template_param(const char *first
, const char *last
, cpp_db_t
*db
)
3760 VERIFY3P(first
, <=, last
);
3762 if (last
- first
< 2 || first
[0] != 'T')
3765 const char *t
= first
+ 1;
3768 while (t
!= last
&& t
[0] != '_') {
3769 if (!isdigit_l(t
[0], db
->cpp_loc
))
3780 VERIFY3U(t
[0], ==, '_');
3788 if (first
[1] != '_')
3797 if (idx
>= ttlen(db
)) {
3798 nadd_l(db
, first
, (size_t)(t
- first
));
3799 db
->cpp_fix_forward_references
= B_TRUE
;
3808 * <template-args> ::= I <template-arg>* E
3809 * extension, the abi says <template-arg>+
3812 parse_template_args(const char *first
, const char *last
, cpp_db_t
*db
)
3814 VERIFY3P(first
, <=, last
);
3816 if (last
- first
< 2 || first
[0] != 'I')
3819 if (db
->cpp_tag_templates
)
3820 sub_clear(templ_top(&db
->cpp_templ
));
3822 const char *t
= first
+ 1;
3823 size_t n
= nlen(db
);
3825 while (t
[0] != 'E') {
3826 if (db
->cpp_tag_templates
)
3829 size_t n1
= nlen(db
);
3830 const char *t1
= parse_template_arg(t
, last
, db
);
3832 if (db
->cpp_tag_templates
)
3835 if (t1
== t
|| t
== last
)
3838 if (db
->cpp_tag_templates
)
3839 tsave(db
, NAMT(db
, n1
));
3845 * ugly, but if the last thing pushed was an empty string,
3846 * get rid of it so we dont get "<..., >"
3848 if (NAMT(db
, n
) > 1 &&
3849 str_pair_len(name_top(&db
->cpp_name
)) == 0)
3850 name_pop(&db
->cpp_name
, NULL
);
3852 njoin(db
, NAMT(db
, n
), ", ");
3854 VERIFY3U(nlen(db
), >, 0);
3856 /* make sure we don't bitshift ourselves into oblivion */
3857 str_t
*top
= TOP_L(db
);
3858 if (str_length(top
) > 0 &&
3859 top
->str_s
[top
->str_len
- 1] == '>')
3860 nfmt(db
, "<{0} >", NULL
);
3862 nfmt(db
, "<{0}>", NULL
);
3869 * <discriminator> := _ <non-negative number> # when number < 10
3870 * := __ <non-negative number> _ # when number >= 10
3871 * extension := decimal-digit+ # at the end of string
3874 parse_discriminator(const char *first
, const char *last
, locale_t loc
)
3876 VERIFY3P(first
, <=, last
);
3878 const char *t
= NULL
;
3883 if (isdigit_l(first
[0], loc
)) {
3884 for (t
= first
; t
!= last
&& isdigit_l(t
[0], loc
); t
++)
3887 /* not at the end of the string */
3892 } else if (first
[0] != '_' || first
+ 1 == last
) {
3897 if (isdigit_l(t
[0], loc
))
3900 if (t
[0] != '_' || t
+ 1 == last
)
3903 for (t
++; t
!= last
&& isdigit_l(t
[0], loc
); t
++)
3905 if (t
== last
|| t
[0] != '_')
3911 /* <CV-qualifiers> ::= [r] [V] [K] */
3913 parse_cv_qualifiers(const char *first
, const char *last
, unsigned *cv
)
3915 VERIFY3P(first
, <=, last
);
3921 if (first
[0] == 'r') {
3922 *cv
|= CPP_QUAL_RESTRICT
;
3925 if (first
!= last
&& first
[0] == 'V') {
3926 *cv
|= CPP_QUAL_VOLATILE
;
3929 if (first
!= last
&& first
[0] == 'K') {
3930 *cv
|= CPP_QUAL_CONST
;
3938 * <number> ::= [n] <non-negative decimal integer>
3941 parse_number(const char *first
, const char *last
, locale_t loc
)
3943 VERIFY3P(first
, <=, last
);
3945 const char *t
= first
;
3947 if (first
== last
|| (first
[0] != 'n' && !isdigit_l(first
[0], loc
)))
3956 while (isdigit_l(t
[0], loc
))
3963 * Like isxdigit(3C), except we can only accept lower case letters as
3964 * that's only what is allowed when [de]mangling floating point constants into
3965 * their hex representation.
3967 static inline boolean_t
3970 if ((c
>= '0' && c
<= '9') || (c
>= 'a' && c
<= 'f'))
3976 nempty(cpp_db_t
*db
)
3978 return (name_empty(&db
->cpp_name
));
3984 return (name_len(&db
->cpp_name
));
3988 nadd_l(cpp_db_t
*db
, const char *s
, size_t len
)
3990 CK(name_add(&db
->cpp_name
, s
, len
, NULL
, 0));
3994 njoin(cpp_db_t
*db
, size_t amt
, const char *sep
)
3996 name_t
*nm
= &db
->cpp_name
;
3998 CK(name_join(nm
, amt
, sep
));
4002 nfmt(cpp_db_t
*db
, const char *fmt_l
, const char *fmt_r
)
4004 CK(name_fmt(&db
->cpp_name
, fmt_l
, fmt_r
));
4008 save_top(cpp_db_t
*db
, size_t amt
)
4010 CK(sub_save(&db
->cpp_subs
, &db
->cpp_name
, amt
));
4014 sub(cpp_db_t
*db
, size_t n
)
4016 CK(sub_substitute(&db
->cpp_subs
, n
, &db
->cpp_name
));
4020 tempty(const cpp_db_t
*db
)
4022 return (templ_empty(&db
->cpp_templ
) ? B_TRUE
: B_FALSE
);
4026 ttlen(const cpp_db_t
*db
)
4028 return (templ_top_len(&db
->cpp_templ
));
4032 tsub(cpp_db_t
*db
, size_t n
)
4034 CK(templ_sub(&db
->cpp_templ
, n
, &db
->cpp_name
));
4040 CK(templ_push(&db
->cpp_templ
));
4046 templ_pop(&db
->cpp_templ
);
4050 tsave(cpp_db_t
*db
, size_t amt
)
4052 CK(templ_save(&db
->cpp_name
, amt
, &db
->cpp_templ
));
4056 db_init(cpp_db_t
*db
, sysdem_ops_t
*ops
)
4058 (void) memset(db
, 0, sizeof (*db
));
4060 name_init(&db
->cpp_name
, ops
);
4061 sub_init(&db
->cpp_subs
, ops
);
4062 templ_init(&db
->cpp_templ
, ops
);
4063 db
->cpp_tag_templates
= B_TRUE
;
4064 db
->cpp_try_to_parse_template_args
= B_TRUE
;
4066 db
->cpp_loc
= newlocale(LC_CTYPE_MASK
, "C", 0);
4067 return ((db
->cpp_loc
!= NULL
) ? B_TRUE
: B_FALSE
);
4071 db_fini(cpp_db_t
*db
)
4073 name_fini(&db
->cpp_name
);
4074 sub_fini(&db
->cpp_subs
);
4075 templ_fini(&db
->cpp_templ
);
4076 freelocale(db
->cpp_loc
);
4077 (void) memset(db
, 0, sizeof (*db
));
4081 print_sp(const str_pair_t
*sp
, FILE *out
)
4083 (void) fprintf(out
, "{%.*s#%.*s}",
4084 (int)sp
->strp_l
.str_len
, sp
->strp_l
.str_s
,
4085 (int)sp
->strp_r
.str_len
, sp
->strp_r
.str_s
);
4089 print_name(const name_t
*n
, FILE *out
)
4091 const str_pair_t
*sp
= name_top((name_t
*)n
);
4094 (void) fprintf(out
, "Name:\n");
4096 if (name_len(n
) == 0)
4099 for (i
= 0; i
< n
->nm_len
; i
++, sp
--) {
4100 (void) fprintf(out
, " [%02zu] ", i
);
4102 (void) fputc('\n', out
);
4105 (void) fputc('\n', out
);
4108 /* Print a base-36 number (for substitutions) */
4110 base36(char *buf
, size_t val
)
4112 char tmp
[16] = { 0 };
4122 size_t r
= val
% 36;
4127 *p
++ = r
- 10 + 'A';
4140 print_sub(const sub_t
*sub
, FILE *out
)
4142 const name_t
*n
= sub
->sub_items
;
4144 (void) fprintf(out
, "Substitutions:\n");
4146 if (sub
->sub_len
== 0)
4149 for (size_t i
= 0; i
< sub
->sub_len
; i
++, n
++) {
4152 (void) fprintf(out
, "%-4s", "S_");
4154 char buf
[16] = { 0 };
4155 char buf2
[16] = { 0 };
4157 (void) snprintf(buf
, sizeof (buf
), "S%s_",
4159 (void) fprintf(out
, "%-4s", buf
);
4161 (void) fprintf(out
, " = ");
4163 (void) fputc('{', out
);
4164 for (size_t j
= 0; j
< n
->nm_len
; j
++) {
4166 (void) fputc(' ', out
);
4167 print_sp(&n
->nm_items
[j
], out
);
4169 (void) fputc('}', out
);
4171 (void) fputc('\n', out
);
4173 (void) fputc('\n', out
);
4177 print_templ(const templ_t
*tpl
, FILE *out
)
4180 (void) fprintf(out
, "Template\n");
4182 const sub_t
*s
= templ_top((templ_t
*)tpl
);
4184 for (size_t i
= 0; i
< s
->sub_len
; i
++) {
4185 char buf
[16] = { 0 };
4188 (void) snprintf(buf
, sizeof (buf
), "%s", "T_");
4190 (void) snprintf(buf
, sizeof (buf
), "T%zu_", i
- 1);
4192 (void) fprintf(out
, " %-4s = ", buf
);
4194 (void) fputc('{', out
);
4196 const name_t
*n
= &s
->sub_items
[i
];
4197 for (size_t j
= 0; j
< n
->nm_len
; j
++) {
4198 const str_pair_t
*sp
= &n
->nm_items
[j
];
4201 (void) fputc(' ', out
);
4203 (void) fprintf(out
, "{%.*s#%.*s}",
4204 (int)sp
->strp_l
.str_len
, sp
->strp_l
.str_s
,
4205 (int)sp
->strp_r
.str_len
, sp
->strp_r
.str_s
);
4207 (void) fprintf(out
, "}\n");
4209 (void) fprintf(out
, "\n");
4213 dump(cpp_db_t
*db
, FILE *out
)
4215 print_name(&db
->cpp_name
, out
);
4216 print_sub(&db
->cpp_subs
, out
);
4217 print_templ(&db
->cpp_templ
, out
);