gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / c-exp.y
index 50a2eef98b58614bf41cafada3359167e92bae8f..e7d0a0dc4ad398f514ccb866b1cd6eb27324c3dc 100644 (file)
@@ -54,6 +54,7 @@
 #include "typeprint.h"
 #include "cp-abi.h"
 #include "type-stack.h"
+#include "target-float.h"
 
 #define parse_type(ps) builtin_type (ps->gdbarch ())
 
@@ -174,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 */
 
@@ -185,8 +186,8 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
 
 %type <type_stack> ptr_operator_ts abs_decl direct_abs_decl
 
-%token <typed_val_int> INT
-%token <typed_val_float> FLOAT
+%token <typed_val_int> INT COMPLEX_INT
+%token <typed_val_float> FLOAT COMPLEX_FLOAT
 
 /* Both NAME and TYPENAME tokens represent symbols in the input,
    and both convey their data as strings.
@@ -238,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
 
@@ -775,6 +777,22 @@ exp        :       INT
                          write_exp_elt_opcode (pstate, OP_LONG); }
        ;
 
+exp    :       COMPLEX_INT
+                       {
+                         write_exp_elt_opcode (pstate, OP_LONG);
+                         write_exp_elt_type (pstate, TYPE_TARGET_TYPE ($1.type));
+                         write_exp_elt_longcst (pstate, 0);
+                         write_exp_elt_opcode (pstate, OP_LONG);
+                         write_exp_elt_opcode (pstate, OP_LONG);
+                         write_exp_elt_type (pstate, TYPE_TARGET_TYPE ($1.type));
+                         write_exp_elt_longcst (pstate, (LONGEST) ($1.val));
+                         write_exp_elt_opcode (pstate, OP_LONG);
+                         write_exp_elt_opcode (pstate, OP_COMPLEX);
+                         write_exp_elt_type (pstate, $1.type);
+                         write_exp_elt_opcode (pstate, OP_COMPLEX);
+                       }
+       ;
+
 exp    :       CHAR
                        {
                          struct stoken_vector vec;
@@ -804,6 +822,27 @@ exp        :       FLOAT
                          write_exp_elt_opcode (pstate, OP_FLOAT); }
        ;
 
+exp    :       COMPLEX_FLOAT
+                       {
+                         struct type *underlying
+                           = TYPE_TARGET_TYPE ($1.type);
+
+                         write_exp_elt_opcode (pstate, OP_FLOAT);
+                         write_exp_elt_type (pstate, underlying);
+                         gdb_byte val[16];
+                         target_float_from_host_double (val, underlying, 0);
+                         write_exp_elt_floatcst (pstate, val);
+                         write_exp_elt_opcode (pstate, OP_FLOAT);
+                         write_exp_elt_opcode (pstate, OP_FLOAT);
+                         write_exp_elt_type (pstate, underlying);
+                         write_exp_elt_floatcst (pstate, $1.val);
+                         write_exp_elt_opcode (pstate, OP_FLOAT);
+                         write_exp_elt_opcode (pstate, OP_COMPLEX);
+                         write_exp_elt_type (pstate, $1.type);
+                         write_exp_elt_opcode (pstate, OP_COMPLEX);
+                       }
+       ;
+
 exp    :       variable
        ;
 
@@ -1293,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
@@ -1389,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 (),
+                                                        $2.type->name ()); }
+       |       UNSIGNED
+                       { $$ = lookup_unsigned_typename (pstate->language (),
+                                                        "int"); }
+       |       SIGNED_KEYWORD type_name
+                       { $$ = lookup_signed_typename (pstate->language (),
+                                                      $2.type->name ()); }
+       |       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 (),
@@ -1460,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. */
@@ -1683,13 +1739,14 @@ oper:   OPERATOR NEW
 
                          c_print_type ($2, NULL, &buf, -1, 0,
                                        &type_print_raw_options);
+                         std::string name = std::move (buf.string ());
 
                          /* This also needs canonicalization.  */
-                         std::string canon
-                           = cp_canonicalize_string (buf.c_str ());
-                         if (canon.empty ())
-                           canon = std::move (buf.string ());
-                         $$ = operator_stoken ((" " + canon).c_str ());
+                         gdb::unique_xmalloc_ptr<char> canon
+                           = cp_canonicalize_string (name.c_str ());
+                         if (canon != nullptr)
+                           name = canon.get ();
+                         $$ = operator_stoken ((" " + name).c_str ());
                        }
        ;
 
@@ -1697,12 +1754,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"); }
@@ -1796,10 +1852,10 @@ typename_stoken (const char *type)
 static int
 type_aggregate_p (struct type *type)
 {
-  return (TYPE_CODE (type) == TYPE_CODE_STRUCT
-         || TYPE_CODE (type) == TYPE_CODE_UNION
-         || TYPE_CODE (type) == TYPE_CODE_NAMESPACE
-         || (TYPE_CODE (type) == TYPE_CODE_ENUM
+  return (type->code () == TYPE_CODE_STRUCT
+         || type->code () == TYPE_CODE_UNION
+         || type->code () == TYPE_CODE_NAMESPACE
+         || (type->code () == TYPE_CODE_ENUM
              && TYPE_DECLARED_CLASS (type)));
 }
 
@@ -1814,7 +1870,7 @@ check_parameter_typelist (std::vector<struct type *> *params)
   for (ix = 0; ix < params->size (); ++ix)
     {
       type = (*params)[ix];
-      if (type != NULL && TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
+      if (type != NULL && check_typedef (type)->code () == TYPE_CODE_VOID)
        {
          if (ix == 0)
            {
@@ -1853,7 +1909,10 @@ parse_number (struct parser_state *par_state,
   /* Number of "L" suffixes encountered.  */
   int long_p = 0;
 
-  /* We have found a "L" or "U" suffix.  */
+  /* Imaginary number.  */
+  bool imaginary_p = false;
+
+  /* We have found a "L" or "U" (or "i") suffix.  */
   int found_suffix = 0;
 
   ULONGEST high_bit;
@@ -1866,6 +1925,12 @@ parse_number (struct parser_state *par_state,
 
   if (parsed_float)
     {
+      if (len >= 1 && p[len - 1] == 'i')
+       {
+         imaginary_p = true;
+         --len;
+       }
+
       /* Handle suffixes for decimal floating-point: "df", "dd" or "dl".  */
       if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f')
        {
@@ -1909,7 +1974,12 @@ parse_number (struct parser_state *par_state,
                        putithere->typed_val_float.type,
                        putithere->typed_val_float.val))
         return ERROR;
-      return FLOAT;
+
+      if (imaginary_p)
+       putithere->typed_val_float.type
+         = init_complex_type (nullptr, putithere->typed_val_float.type);
+
+      return imaginary_p ? COMPLEX_FLOAT : FLOAT;
     }
 
   /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
@@ -1958,7 +2028,7 @@ parse_number (struct parser_state *par_state,
       c = *p++;
       if (c >= 'A' && c <= 'Z')
        c += 'a' - 'A';
-      if (c != 'l' && c != 'u')
+      if (c != 'l' && c != 'u' && c != 'i')
        n *= base;
       if (c >= '0' && c <= '9')
        {
@@ -1984,6 +2054,11 @@ parse_number (struct parser_state *par_state,
              unsigned_p = 1;
              found_suffix = 1;
            }
+         else if (c == 'i')
+           {
+             imaginary_p = true;
+             found_suffix = 1;
+           }
          else
            return ERROR;       /* Char not a digit */
        }
@@ -1993,13 +2068,13 @@ parse_number (struct parser_state *par_state,
       /* Portably test for overflow (only works for nonzero values, so make
         a second check for zero).  FIXME: Can't we just make n and prevn
         unsigned and avoid this?  */
-      if (c != 'l' && c != 'u' && (prevn >= n) && n != 0)
+      if (c != 'l' && c != 'u' && c != 'i' && (prevn >= n) && n != 0)
        unsigned_p = 1;         /* Try something unsigned */
 
       /* Portably test for unsigned overflow.
         FIXME: This check is wrong; for example it doesn't find overflow
         on 0x123456789 when LONGEST is 32 bits.  */
-      if (c != 'l' && c != 'u' && n != 0)
+      if (c != 'l' && c != 'u' && c != 'i' && n != 0)
        {       
          if (unsigned_p && prevn >= n)
            error (_("Numeric constant too large."));
@@ -2071,7 +2146,11 @@ parse_number (struct parser_state *par_state,
        putithere->typed_val_int.type = signed_type;
      }
 
-   return INT;
+   if (imaginary_p)
+     putithere->typed_val_int.type
+       = init_complex_type (nullptr, putithere->typed_val_int.type);
+
+   return imaginary_p ? COMPLEX_INT : INT;
 }
 
 /* Temporary obstack used for holding strings.  */
@@ -2411,7 +2490,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},
@@ -2423,6 +2502,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},
@@ -2434,6 +2514,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},
@@ -2580,7 +2663,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
        if ((tokentab2[i].flags & FLAG_CXX) != 0
            && par_state->language ()->la_language != language_cplus)
          break;
-       gdb_assert ((tokentab3[i].flags & FLAG_C) == 0);
+       gdb_assert ((tokentab2[i].flags & FLAG_C) == 0);
 
        pstate->lexptr += 2;
        yylval.opcode = tokentab2[i].opcode;
This page took 0.029379 seconds and 4 git commands to generate.