Fix buffer overflow regression due to minsym malloc-ed instead of obstack-ed.
[deliverable/binutils-gdb.git] / gdb / f-exp.y
index c223d366db3484a4ac1766ff854a773c120529e9..f99c26d326e47dc97777445c0992b1de8c59f2df 100644 (file)
@@ -78,6 +78,10 @@ static void growbuf_by_size (int);
 
 static int match_string_literal (void);
 
+static void push_kind_type (LONGEST val, struct type *type);
+
+static struct type *convert_to_kind_type (struct type *basetype, int kind);
+
 %}
 
 /* Although the yacc "value" of an expression is not used,
@@ -101,7 +105,6 @@ static int match_string_literal (void);
     struct ttype tsym;
     struct symtoken ssym;
     int voidval;
-    struct block *bval;
     enum exp_opcode opcode;
     struct internalvar *ivar;
 
@@ -149,7 +152,7 @@ static int parse_number (struct parser_state *, const char *, int,
 
 %token <ssym> NAME_OR_INT 
 
-%token  SIZEOF 
+%token SIZEOF KIND
 %token ERROR
 
 /* Special type cases, put in to allow the parser to distinguish different
@@ -164,6 +167,7 @@ static int parse_number (struct parser_state *, const char *, int,
 %token <voidval> DOLLAR_VARIABLE
 
 %token <opcode> ASSIGN_MODIFY
+%token <opcode> UNOP_INTRINSIC
 
 %left ','
 %left ABOVE_COMMA
@@ -228,6 +232,10 @@ exp        :       SIZEOF exp       %prec UNARY
                        { write_exp_elt_opcode (pstate, UNOP_SIZEOF); }
        ;
 
+exp    :       KIND '(' exp ')'       %prec UNARY
+                       { write_exp_elt_opcode (pstate, UNOP_KIND); }
+       ;
+
 /* No more explicit array operators, we treat everything in F77 as 
    a function call.  The disambiguation as to whether we are 
    doing a subscript operation or a function call is done 
@@ -244,6 +252,10 @@ exp        :       exp '('
                                              OP_F77_UNDETERMINED_ARGLIST); }
        ;
 
+exp    :       UNOP_INTRINSIC '(' exp ')'
+                       { write_exp_elt_opcode (pstate, $1); }
+       ;
+
 arglist        :
        ;
 
@@ -530,6 +542,13 @@ ptype      :       typebase
                      case tp_function:
                        follow_type = lookup_function_type (follow_type);
                        break;
+                     case tp_kind:
+                       {
+                         int kind_val = pop_type_int ();
+                         follow_type
+                           = convert_to_kind_type (follow_type, kind_val);
+                       }
+                       break;
                      }
                  $$ = follow_type;
                }
@@ -548,6 +567,10 @@ abs_decl:  '*'
 
 direct_abs_decl: '(' abs_decl ')'
                        { $$ = $2; }
+       |       '(' KIND '=' INT ')'
+                       { push_kind_type ($4.val, $4.type); }
+       |       '*' INT
+                       { push_kind_type ($2.val, $2.type); }
        |       direct_abs_decl func_mod
                        { push_type (tp_function); }
        |       func_mod
@@ -773,6 +796,92 @@ parse_number (struct parser_state *par_state,
   return INT;
 }
 
+/* Called to setup the type stack when we encounter a '(kind=N)' type
+   modifier, performs some bounds checking on 'N' and then pushes this to
+   the type stack followed by the 'tp_kind' marker.  */
+static void
+push_kind_type (LONGEST val, struct type *type)
+{
+  int ival;
+
+  if (TYPE_UNSIGNED (type))
+    {
+      ULONGEST uval = static_cast <ULONGEST> (val);
+      if (uval > INT_MAX)
+       error (_("kind value out of range"));
+      ival = static_cast <int> (uval);
+    }
+  else
+    {
+      if (val > INT_MAX || val < 0)
+       error (_("kind value out of range"));
+      ival = static_cast <int> (val);
+    }
+
+  push_type_int (ival);
+  push_type (tp_kind);
+}
+
+/* Called when a type has a '(kind=N)' modifier after it, for example
+   'character(kind=1)'.  The BASETYPE is the type described by 'character'
+   in our example, and KIND is the integer '1'.  This function returns a
+   new type that represents the basetype of a specific kind.  */
+static struct type *
+convert_to_kind_type (struct type *basetype, int kind)
+{
+  if (basetype == parse_f_type (pstate)->builtin_character)
+    {
+      /* Character of kind 1 is a special case, this is the same as the
+        base character type.  */
+      if (kind == 1)
+       return parse_f_type (pstate)->builtin_character;
+    }
+  else if (basetype == parse_f_type (pstate)->builtin_complex_s8)
+    {
+      if (kind == 4)
+       return parse_f_type (pstate)->builtin_complex_s8;
+      else if (kind == 8)
+       return parse_f_type (pstate)->builtin_complex_s16;
+      else if (kind == 16)
+       return parse_f_type (pstate)->builtin_complex_s32;
+    }
+  else if (basetype == parse_f_type (pstate)->builtin_real)
+    {
+      if (kind == 4)
+       return parse_f_type (pstate)->builtin_real;
+      else if (kind == 8)
+       return parse_f_type (pstate)->builtin_real_s8;
+      else if (kind == 16)
+       return parse_f_type (pstate)->builtin_real_s16;
+    }
+  else if (basetype == parse_f_type (pstate)->builtin_logical)
+    {
+      if (kind == 1)
+       return parse_f_type (pstate)->builtin_logical_s1;
+      else if (kind == 2)
+       return parse_f_type (pstate)->builtin_logical_s2;
+      else if (kind == 4)
+       return parse_f_type (pstate)->builtin_logical;
+      else if (kind == 8)
+       return parse_f_type (pstate)->builtin_logical_s8;
+    }
+  else if (basetype == parse_f_type (pstate)->builtin_integer)
+    {
+      if (kind == 2)
+       return parse_f_type (pstate)->builtin_integer_s2;
+      else if (kind == 4)
+       return parse_f_type (pstate)->builtin_integer;
+      else if (kind == 8)
+       return parse_f_type (pstate)->builtin_integer_s8;
+    }
+
+  error (_("unsupported kind %d for type %s"),
+        kind, TYPE_SAFE_NAME (basetype));
+
+  /* Should never get here.  */
+  return nullptr;
+}
+
 struct token
 {
   /* The string to match against.  */
@@ -840,6 +949,10 @@ static const struct token f77_keywords[] =
   { "sizeof", SIZEOF, BINOP_END, true },
   { "real_8", REAL_S8_KEYWORD, BINOP_END, true },
   { "real", REAL_KEYWORD, BINOP_END, true },
+  /* The following correspond to actual functions in Fortran and are case
+     insensitive.  */
+  { "kind", KIND, BINOP_END, false },
+  { "abs", UNOP_INTRINSIC, UNOP_ABS, false }
 };
 
 /* Implementation of a dynamically expandable buffer for processing input
This page took 0.026832 seconds and 4 git commands to generate.