aboutsummaryrefslogtreecommitdiff
path: root/gdb/f-exp.y
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2019-01-16 16:42:10 +0000
committerAndrew Burgess <andrew.burgess@embecosm.com>2019-03-06 18:11:31 +0000
commit4d00f5d8f6c4a1c9f334b1abb45b9ce05fb45b0a (patch)
tree24f8cddb29a1036f7f0f23d6a2178f593a2daeef /gdb/f-exp.y
parente454224fa82aa52a1288a3d6a2e26e8d224d732a (diff)
downloadgdb-4d00f5d8f6c4a1c9f334b1abb45b9ce05fb45b0a.zip
gdb-4d00f5d8f6c4a1c9f334b1abb45b9ce05fb45b0a.tar.gz
gdb-4d00f5d8f6c4a1c9f334b1abb45b9ce05fb45b0a.tar.bz2
gdb/fortran: Add Fortran 'kind' intrinsic and keyword
The 'kind' keyword has two uses in Fortran, it is the name of a builtin intrinsic function, and it is also a keyword used to create a type of a specific kind. This commit adds support for using kind as an intrinsic function, and also adds some initial support for using kind to create types of a specific kind. This commit only allows the creation of the type 'character(kind=1)', however, it will be easy enough to extend this in future to support more type kinds. The kind of any expression can be queried using the kind intrinsic function. At the moment the kind returned corresponds to the size of the type, this matches how gfortran handles kinds. However, the correspondence between kind and type size depends on the compiler and/or the specific target, so this might not be correct for everyone. If we want to support different compilers/targets in future the code to compute the kind from a type will need to be updated. gdb/ChangeLog: * expprint.c (dump_subexp_body_standard): Support UNOP_KIND. * f-exp.y: Define 'KIND' token. (exp): New pattern for KIND expressions. (ptype): Handle types with a kind extension. (direct_abs_decl): Extend to spot kind extensions. (f77_keywords): Add 'kind' to the list. (push_kind_type): New function. (convert_to_kind_type): New function. * f-lang.c (evaluate_subexp_f): Support UNOP_KIND. * parse.c (operator_length_standard): Likewise. * parser-defs.h (enum type_pieces): Add tp_kind. * std-operator.def: Add UNOP_KIND. gdb/testsuite/ChangeLog: * gdb.fortran/intrinsics.exp: New file. * gdb.fortran/intrinsics.f90: New file. * gdb.fortran/type-kinds.exp: New file.
Diffstat (limited to 'gdb/f-exp.y')
-rw-r--r--gdb/f-exp.y70
1 files changed, 69 insertions, 1 deletions
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index c223d36..327f137 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -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,
@@ -149,7 +153,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
@@ -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
@@ -530,6 +538,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 +563,8 @@ abs_decl: '*'
direct_abs_decl: '(' abs_decl ')'
{ $$ = $2; }
+ | '(' KIND '=' INT ')'
+ { push_kind_type ($4.val, $4.type); }
| direct_abs_decl func_mod
{ push_type (tp_function); }
| func_mod
@@ -773,6 +790,54 @@ 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;
+ }
+
+ 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 +905,9 @@ 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 }
};
/* Implementation of a dynamically expandable buffer for processing input