Add _Complex type support to C parser
authorTom Tromey <tom@tromey.com>
Wed, 1 Apr 2020 20:09:52 +0000 (14:09 -0600)
committerTom Tromey <tromey@adacore.com>
Wed, 1 Apr 2020 20:09:53 +0000 (14:09 -0600)
This changes the C parser to add support for complex types in casts.

gdb/ChangeLog
2020-04-01  Tom Tromey  <tom@tromey.com>

* c-exp.y (FLOAT_KEYWORD, COMPLEX): New tokens.
(scalar_type): New rule, from typebase.
(typebase): Use scalar_type.  Recognize complex types.
(field_name): Handle FLOAT_KEYWORD.
(ident_tokens): Add _Complex and __complex__.

gdb/testsuite/ChangeLog
2020-04-01  Tom Tromey  <tom@tromey.com>

* gdb.base/complex-parts.exp: Add type tests.

gdb/ChangeLog
gdb/c-exp.y
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/complex-parts.exp

index 8ae8b484e56ed8433fcd91861d9a20d1adbcd024..61d30070e374aed0250dd838c5fb068eab337f32 100644 (file)
@@ -1,3 +1,11 @@
+2020-04-01  Tom Tromey  <tom@tromey.com>
+
+       * c-exp.y (FLOAT_KEYWORD, COMPLEX): New tokens.
+       (scalar_type): New rule, from typebase.
+       (typebase): Use scalar_type.  Recognize complex types.
+       (field_name): Handle FLOAT_KEYWORD.
+       (ident_tokens): Add _Complex and __complex__.
+
 2020-04-01  Tom Tromey  <tom@tromey.com>
 
        PR exp/25299:
index c2531b9bffc47f9576751867f81ea15af0ccdb95..feab51a8e2cb356223cf9fea1043403973cabd38 100644 (file)
@@ -175,7 +175,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
 
 %type <voidval> exp exp1 type_exp start variable qualified_name lcurly function_method
 %type <lval> rcurly
-%type <tval> type typebase
+%type <tval> type typebase scalar_type
 %type <tvec> nonempty_typelist func_mod parameter_typelist
 /* %type <bval> block */
 
@@ -239,6 +239,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
    legal basetypes.  */
 %token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD
 %token RESTRICT ATOMIC
+%token FLOAT_KEYWORD COMPLEX
 
 %token <sval> DOLLAR_VARIABLE
 
@@ -1331,20 +1332,11 @@ func_mod:       '(' ')'
 type   :       ptype
        ;
 
-/* Implements (approximately): (type-qualifier)* type-specifier.
+/* A helper production that recognizes scalar types that can validly
+   be used with _Complex.  */
 
-   When type-specifier is only ever a single word, like 'float' then these
-   arrive as pre-built TYPENAME tokens thanks to the classify_name
-   function.  However, when a type-specifier can contain multiple words,
-   for example 'double' can appear as just 'double' or 'long double', and
-   similarly 'long' can appear as just 'long' or in 'long double', then
-   these type-specifiers are parsed into their own tokens in the function
-   lex_one_token and the ident_tokens array.  These separate tokens are all
-   recognised here.  */
-typebase
-       :       TYPENAME
-                       { $$ = $1.type; }
-       |       INT_KEYWORD
+scalar_type:
+               INT_KEYWORD
                        { $$ = lookup_signed_typename (pstate->language (),
                                                       "int"); }
        |       LONG
@@ -1427,11 +1419,49 @@ typebase
                                                "double",
                                                NULL,
                                                0); }
+       |       FLOAT_KEYWORD
+                       { $$ = lookup_typename (pstate->language (),
+                                               "float",
+                                               NULL,
+                                               0); }
        |       LONG DOUBLE_KEYWORD
                        { $$ = lookup_typename (pstate->language (),
                                                "long double",
                                                NULL,
                                                0); }
+       |       UNSIGNED type_name
+                       { $$ = lookup_unsigned_typename (pstate->language (),
+                                                        TYPE_NAME($2.type)); }
+       |       UNSIGNED
+                       { $$ = lookup_unsigned_typename (pstate->language (),
+                                                        "int"); }
+       |       SIGNED_KEYWORD type_name
+                       { $$ = lookup_signed_typename (pstate->language (),
+                                                      TYPE_NAME($2.type)); }
+       |       SIGNED_KEYWORD
+                       { $$ = lookup_signed_typename (pstate->language (),
+                                                      "int"); }
+       ;
+
+/* Implements (approximately): (type-qualifier)* type-specifier.
+
+   When type-specifier is only ever a single word, like 'float' then these
+   arrive as pre-built TYPENAME tokens thanks to the classify_name
+   function.  However, when a type-specifier can contain multiple words,
+   for example 'double' can appear as just 'double' or 'long double', and
+   similarly 'long' can appear as just 'long' or in 'long double', then
+   these type-specifiers are parsed into their own tokens in the function
+   lex_one_token and the ident_tokens array.  These separate tokens are all
+   recognised here.  */
+typebase
+       :       TYPENAME
+                       { $$ = $1.type; }
+       |       scalar_type
+                       { $$ = $1; }
+       |       COMPLEX scalar_type
+                       {
+                         $$ = init_complex_type (nullptr, $2);
+                       }
        |       STRUCT name
                        { $$
                            = lookup_struct (copy_name ($2).c_str (),
@@ -1498,18 +1528,6 @@ typebase
                                                       $2.length);
                          $$ = NULL;
                        }
-       |       UNSIGNED type_name
-                       { $$ = lookup_unsigned_typename (pstate->language (),
-                                                        TYPE_NAME($2.type)); }
-       |       UNSIGNED
-                       { $$ = lookup_unsigned_typename (pstate->language (),
-                                                        "int"); }
-       |       SIGNED_KEYWORD type_name
-                       { $$ = lookup_signed_typename (pstate->language (),
-                                                      TYPE_NAME($2.type)); }
-       |       SIGNED_KEYWORD
-                       { $$ = lookup_signed_typename (pstate->language (),
-                                                      "int"); }
                 /* It appears that this rule for templates is never
                    reduced; template recognition happens by lookahead
                    in the token processing code in yylex. */
@@ -1735,12 +1753,11 @@ oper:   OPERATOR NEW
    match the 'name' rule to appear as fields within a struct.  The example
    that initially motivated this was the RISC-V target which models the
    floating point registers as a union with fields called 'float' and
-   'double'.  The 'float' string becomes a TYPENAME token and can appear
-   anywhere a 'name' can, however 'double' is its own token,
-   DOUBLE_KEYWORD, and doesn't match the 'name' rule.*/
+   'double'.  */
 field_name
        :       name
        |       DOUBLE_KEYWORD { $$ = typename_stoken ("double"); }
+       |       FLOAT_KEYWORD { $$ = typename_stoken ("float"); }
        |       INT_KEYWORD { $$ = typename_stoken ("int"); }
        |       LONG { $$ = typename_stoken ("long"); }
        |       SHORT { $$ = typename_stoken ("short"); }
@@ -2472,7 +2489,7 @@ static const struct token tokentab2[] =
 /* Identifier-like tokens.  Only type-specifiers than can appear in
    multi-word type names (for example 'double' can appear in 'long
    double') need to be listed here.  type-specifiers that are only ever
-   single word (like 'float') are handled by the classify_name function.  */
+   single word (like 'char') are handled by the classify_name function.  */
 static const struct token ident_tokens[] =
   {
     {"unsigned", UNSIGNED, OP_NULL, 0},
@@ -2484,6 +2501,7 @@ static const struct token ident_tokens[] =
     {"_Alignof", ALIGNOF, OP_NULL, 0},
     {"alignof", ALIGNOF, OP_NULL, FLAG_CXX},
     {"double", DOUBLE_KEYWORD, OP_NULL, 0},
+    {"float", FLOAT_KEYWORD, OP_NULL, 0},
     {"false", FALSEKEYWORD, OP_NULL, FLAG_CXX},
     {"class", CLASS, OP_NULL, FLAG_CXX},
     {"union", UNION, OP_NULL, 0},
@@ -2495,6 +2513,9 @@ static const struct token ident_tokens[] =
     {"_Atomic", ATOMIC, OP_NULL, 0},
     {"enum", ENUM, OP_NULL, 0},
     {"long", LONG, OP_NULL, 0},
+    {"_Complex", COMPLEX, OP_NULL, 0},
+    {"__complex__", COMPLEX, OP_NULL, 0},
+
     {"true", TRUEKEYWORD, OP_NULL, FLAG_CXX},
     {"int", INT_KEYWORD, OP_NULL, 0},
     {"new", NEW, OP_NULL, FLAG_CXX},
index 05a542b623207f6bd546d32a8c91d9ad684e6c60..f885b93ecd9de1238ce8aa42dea6d9d7fa49d979 100644 (file)
@@ -1,3 +1,7 @@
+2020-04-01  Tom Tromey  <tom@tromey.com>
+
+       * gdb.base/complex-parts.exp: Add type tests.
+
 2020-04-01  Tom Tromey  <tom@tromey.com>
 
        * gdb.base/complex-parts.exp: Add arithmetic tests.
index 0cf4abf56ec434e5a6aff19dca73235953dd86e5..38aad395ad267035562109db6c4811657aec1451 100644 (file)
@@ -86,3 +86,8 @@ gdb_test "print (5 + 7i) != (8 + 7i)" " = 1"
 gdb_test "print (5 + 7i) != (5 + 92i)" " = 1"
 
 gdb_test "print (20 - 4i) / (3 + 2i)" " = 4 \\+ -4i"
+
+gdb_test "print (_Complex int) 4" " = 4 \\+ 0i"
+gdb_test "print (_Complex float) 4.5" " = 4.5 \\+ 0i"
+gdb_test "ptype __complex__ short" " = _Complex short"
+gdb_test "print (_Complex int) (23.75 + 8.88i)" " = 23 \\+ 8i"