From 86f437e3f66cab44d5814c49216320bb16ae6ecc Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 17 May 2023 18:05:42 +1200 Subject: Support parsing arbitrary expression in decltype Use parser error recovery to skip to the closing matching `)` and issue a warning that we can't deduce the decltype for the expression (like we already do for any expression which isn't a simple variable or similar). Fixes #1589 Helps #2335 (fixes the decltype-related examples) --- Source/CParse/parser.y | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) (limited to 'Source') diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 7a9cefe7b..cea0fd0e1 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1734,7 +1734,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %type access_specifier; %type base_specifier; %type variadic_opt; -%type type rawtype type_right anon_bitfield_type decltype ; +%type type rawtype type_right anon_bitfield_type decltype decltypeexpr; %type base_list inherit raw_inherit; %type definetype def_args etype default_delete deleted_definition explicit_default; %type expr exprnum exprsimple exprcompound valexpr exprmem callparms callptail; @@ -6224,17 +6224,39 @@ type_right : primitive_type { $$ = $1; } ; -decltype : DECLTYPE LPAREN expr RPAREN { - Node *n = Swig_symbol_clookup($3.val, 0); - if (!n) { - Swig_warning(WARN_CPP11_DECLTYPE, cparse_file, cparse_line, "Unable to deduce decltype for '%s'.\n", $3.val); +decltype : DECLTYPE LPAREN { + $$ = get_raw_text_balanced('(', ')'); + } decltypeexpr { + if ($4) { + $$ = $4; + Delete($3); + } else { + String *expr = $3; + Delitem(expr,0); + Delitem(expr,DOH_END); + Swig_warning(WARN_CPP11_DECLTYPE, cparse_file, cparse_line, "Unable to deduce decltype for '%s'.\n", expr); + $$ = expr; + } + } + ; - $$ = NewStringf("decltype(%s)", $3.val); - } else { - $$ = Getattr(n, "type"); - } - } - ; +decltypeexpr : expr RPAREN { + Node *n = Swig_symbol_clookup($1.val, 0); + if (!n) { + Swig_warning(WARN_CPP11_DECLTYPE, cparse_file, cparse_line, "Unable to deduce decltype for '%s'.\n", $1.val); + + $$ = NewStringf("decltype(%s)", $1.val); + } else { + $$ = Getattr(n, "type"); + } + } + | error RPAREN { + // Avoid a parse error if we can't parse the expression decltype() is applied to. + $$ = 0; + skip_balanced('(',')'); + Clear(scanner_ccode); + } + ; primitive_type : primitive_type_list { if (!$1.type) $1.type = NewString("int"); -- cgit v1.2.1