/* Local functions */
-static void f_printchar (int c, struct type *type, struct ui_file * stream);
-static void f_emit_char (int c, struct type *type,
- struct ui_file * stream, int quoter);
-
/* Return the encoding that should be used for the character type
TYPE. */
-static const char *
-f_get_encoding (struct type *type)
+const char *
+f_language::get_encoding (struct type *type)
{
const char *encoding;
return encoding;
}
-/* Print the character C on STREAM as part of the contents of a literal
- string whose delimiter is QUOTER. Note that that format for printing
- characters and strings is language specific.
- FIXME: This is a copy of the same function from c-exp.y. It should
- be replaced with a true F77 version. */
-
-static void
-f_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
-{
- const char *encoding = f_get_encoding (type);
-
- generic_emit_char (c, type, stream, quoter, encoding);
-}
-
-/* Implementation of la_printchar. */
-
-static void
-f_printchar (int c, struct type *type, struct ui_file *stream)
-{
- fputs_filtered ("'", stream);
- LA_EMIT_CHAR (c, type, stream, '\'');
- fputs_filtered ("'", stream);
-}
-
-/* Print the character string STRING, printing at most LENGTH characters.
- Printing stops early if the number hits print_max; repeat counts
- are printed as appropriate. Print ellipses at the end if we
- had to stop before printing LENGTH characters, or if FORCE_ELLIPSES.
- FIXME: This is a copy of the same function from c-exp.y. It should
- be replaced with a true F77 version. */
-
-static void
-f_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
- unsigned int length, const char *encoding, int force_ellipses,
- const struct value_print_options *options)
-{
- const char *type_encoding = f_get_encoding (type);
-
- if (TYPE_LENGTH (type) == 4)
- fputs_filtered ("4_", stream);
-
- if (!encoding || !*encoding)
- encoding = type_encoding;
-
- generic_printstr (stream, type, string, length, encoding,
- force_ellipses, '\'', 0, options);
-}
\f
/* Table of operators and their precedences for printing expressions. */
-static const struct op_print f_op_print_tab[] =
+const struct op_print f_language::op_print_tab[] =
{
{"+", BINOP_ADD, PREC_ADD, 0},
{"+", UNOP_PLUS, PREC_PREFIX, 0},
{NULL, OP_NULL, PREC_REPEAT, 0}
};
\f
-enum f_primitive_types {
- f_primitive_type_character,
- f_primitive_type_logical,
- f_primitive_type_logical_s1,
- f_primitive_type_logical_s2,
- f_primitive_type_logical_s8,
- f_primitive_type_integer,
- f_primitive_type_integer_s2,
- f_primitive_type_real,
- f_primitive_type_real_s8,
- f_primitive_type_real_s16,
- f_primitive_type_complex_s8,
- f_primitive_type_complex_s16,
- f_primitive_type_void,
- nr_f_primitive_types
-};
+
+/* Called from fortran_value_subarray to take a slice of an array or a
+ string. ARRAY is the array or string to be accessed. EXP, POS, and
+ NOSIDE are as for evaluate_subexp_standard. Return a value that is a
+ slice of the array. */
+
+static struct value *
+value_f90_subarray (struct value *array,
+ struct expression *exp, int *pos, enum noside noside)
+{
+ int pc = (*pos) + 1;
+ LONGEST low_bound, high_bound, stride;
+ struct type *range = check_typedef (value_type (array)->index_type ());
+ enum range_flag range_flag
+ = (enum range_flag) longest_to_int (exp->elts[pc].longconst);
+
+ *pos += 3;
+
+ if (range_flag & RANGE_LOW_BOUND_DEFAULT)
+ low_bound = range->bounds ()->low.const_val ();
+ else
+ low_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
+
+ if (range_flag & RANGE_HIGH_BOUND_DEFAULT)
+ high_bound = range->bounds ()->high.const_val ();
+ else
+ high_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
+
+ if (range_flag & RANGE_HAS_STRIDE)
+ stride = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
+ else
+ stride = 1;
+
+ if (stride != 1)
+ error (_("Fortran array strides are not currently supported"));
+
+ return value_slice (array, low_bound, high_bound - low_bound + 1);
+}
+
+/* Helper for skipping all the arguments in an undetermined argument list.
+ This function was designed for use in the OP_F77_UNDETERMINED_ARGLIST
+ case of evaluate_subexp_standard as multiple, but not all, code paths
+ require a generic skip. */
+
+static void
+skip_undetermined_arglist (int nargs, struct expression *exp, int *pos,
+ enum noside noside)
+{
+ for (int i = 0; i < nargs; ++i)
+ evaluate_subexp (nullptr, exp, pos, noside);
+}
+
+/* Return the number of dimensions for a Fortran array or string. */
+
+int
+calc_f77_array_dims (struct type *array_type)
+{
+ int ndimen = 1;
+ struct type *tmp_type;
+
+ if ((array_type->code () == TYPE_CODE_STRING))
+ return 1;
+
+ if ((array_type->code () != TYPE_CODE_ARRAY))
+ error (_("Can't get dimensions for a non-array type"));
+
+ tmp_type = array_type;
+
+ while ((tmp_type = TYPE_TARGET_TYPE (tmp_type)))
+ {
+ if (tmp_type->code () == TYPE_CODE_ARRAY)
+ ++ndimen;
+ }
+ return ndimen;
+}
+
+/* Called from evaluate_subexp_standard to perform array indexing, and
+ sub-range extraction, for Fortran. As well as arrays this function
+ also handles strings as they can be treated like arrays of characters.
+ ARRAY is the array or string being accessed. EXP, POS, and NOSIDE are
+ as for evaluate_subexp_standard, and NARGS is the number of arguments
+ in this access (e.g. 'array (1,2,3)' would be NARGS 3). */
+
+static struct value *
+fortran_value_subarray (struct value *array, struct expression *exp,
+ int *pos, int nargs, enum noside noside)
+{
+ if (exp->elts[*pos].opcode == OP_RANGE)
+ return value_f90_subarray (array, exp, pos, noside);
+
+ if (noside == EVAL_SKIP)
+ {
+ skip_undetermined_arglist (nargs, exp, pos, noside);
+ /* Return the dummy value with the correct type. */
+ return array;
+ }
+
+ LONGEST subscript_array[MAX_FORTRAN_DIMS];
+ int ndimensions = 1;
+ struct type *type = check_typedef (value_type (array));
+
+ if (nargs > MAX_FORTRAN_DIMS)
+ error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS);
+
+ ndimensions = calc_f77_array_dims (type);
+
+ if (nargs != ndimensions)
+ error (_("Wrong number of subscripts"));
+
+ gdb_assert (nargs > 0);
+
+ /* Now that we know we have a legal array subscript expression let us
+ actually find out where this element exists in the array. */
+
+ /* Take array indices left to right. */
+ for (int i = 0; i < nargs; i++)
+ {
+ /* Evaluate each subscript; it must be a legal integer in F77. */
+ value *arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ /* Fill in the subscript array. */
+ subscript_array[i] = value_as_long (arg2);
+ }
+
+ /* Internal type of array is arranged right to left. */
+ for (int i = nargs; i > 0; i--)
+ {
+ struct type *array_type = check_typedef (value_type (array));
+ LONGEST index = subscript_array[i - 1];
+
+ array = value_subscripted_rvalue (array, index,
+ f77_get_lowerbound (array_type));
+ }
+
+ return array;
+}
/* Special expression evaluation cases for Fortran. */
return evaluate_subexp_standard (expect_type, exp, pos, noside);
case UNOP_ABS:
- arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg1 = evaluate_subexp (nullptr, exp, pos, noside);
if (noside == EVAL_SKIP)
return eval_skip_value (exp);
type = value_type (arg1);
error (_("ABS of type %s not supported"), TYPE_SAFE_NAME (type));
case BINOP_MOD:
- arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg1 = evaluate_subexp (nullptr, exp, pos, noside);
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
if (noside == EVAL_SKIP)
return eval_skip_value (exp);
case UNOP_FORTRAN_CEILING:
{
- arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg1 = evaluate_subexp (nullptr, exp, pos, noside);
if (noside == EVAL_SKIP)
return eval_skip_value (exp);
type = value_type (arg1);
case UNOP_FORTRAN_FLOOR:
{
- arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg1 = evaluate_subexp (nullptr, exp, pos, noside);
if (noside == EVAL_SKIP)
return eval_skip_value (exp);
type = value_type (arg1);
case BINOP_FORTRAN_MODULO:
{
- arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg1 = evaluate_subexp (nullptr, exp, pos, noside);
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
if (noside == EVAL_SKIP)
return eval_skip_value (exp);
type = value_type (arg1);
if (type->code () != value_type (arg2)->code ())
error (_("non-matching types for parameters to MODULO ()"));
- /* MODULO(A, P) = A - FLOOR (A / P) * P */
+ /* MODULO(A, P) = A - FLOOR (A / P) * P */
switch (type->code ())
{
case TYPE_CODE_INT:
}
case BINOP_FORTRAN_CMPLX:
- arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg1 = evaluate_subexp (nullptr, exp, pos, noside);
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
if (noside == EVAL_SKIP)
return eval_skip_value (exp);
type = value_type (arg1);
switch (type->code ())
- {
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- case TYPE_CODE_MODULE:
- case TYPE_CODE_FUNC:
- error (_("argument to kind must be an intrinsic type"));
- }
+ {
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_MODULE:
+ case TYPE_CODE_FUNC:
+ error (_("argument to kind must be an intrinsic type"));
+ }
if (!TYPE_TARGET_TYPE (type))
- return value_from_longest (builtin_type (exp->gdbarch)->builtin_int,
+ return value_from_longest (builtin_type (exp->gdbarch)->builtin_int,
TYPE_LENGTH (type));
return value_from_longest (builtin_type (exp->gdbarch)->builtin_int,
TYPE_LENGTH (TYPE_TARGET_TYPE (type)));
+
+
+ case OP_F77_UNDETERMINED_ARGLIST:
+ /* Remember that in F77, functions, substring ops and array subscript
+ operations cannot be disambiguated at parse time. We have made
+ all array subscript operations, substring operations as well as
+ function calls come here and we now have to discover what the heck
+ this thing actually was. If it is a function, we process just as
+ if we got an OP_FUNCALL. */
+ int nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 2;
+
+ /* First determine the type code we are dealing with. */
+ arg1 = evaluate_subexp (nullptr, exp, pos, noside);
+ type = check_typedef (value_type (arg1));
+ enum type_code code = type->code ();
+
+ if (code == TYPE_CODE_PTR)
+ {
+ /* Fortran always passes variable to subroutines as pointer.
+ So we need to look into its target type to see if it is
+ array, string or function. If it is, we need to switch
+ to the target value the original one points to. */
+ struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
+
+ if (target_type->code () == TYPE_CODE_ARRAY
+ || target_type->code () == TYPE_CODE_STRING
+ || target_type->code () == TYPE_CODE_FUNC)
+ {
+ arg1 = value_ind (arg1);
+ type = check_typedef (value_type (arg1));
+ code = type->code ();
+ }
+ }
+
+ switch (code)
+ {
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_STRING:
+ return fortran_value_subarray (arg1, exp, pos, nargs, noside);
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_INTERNAL_FUNCTION:
+ {
+ /* It's a function call. Allocate arg vector, including
+ space for the function to be called in argvec[0] and a
+ termination NULL. */
+ struct value **argvec = (struct value **)
+ alloca (sizeof (struct value *) * (nargs + 2));
+ argvec[0] = arg1;
+ int tem = 1;
+ for (; tem <= nargs; tem++)
+ {
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ /* Arguments in Fortran are passed by address. Coerce the
+ arguments here rather than in value_arg_coerce as
+ otherwise the call to malloc to place the non-lvalue
+ parameters in target memory is hit by this Fortran
+ specific logic. This results in malloc being called
+ with a pointer to an integer followed by an attempt to
+ malloc the arguments to malloc in target memory.
+ Infinite recursion ensues. */
+ if (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC)
+ {
+ bool is_artificial
+ = TYPE_FIELD_ARTIFICIAL (value_type (arg1), tem - 1);
+ argvec[tem] = fortran_argument_convert (argvec[tem],
+ is_artificial);
+ }
+ }
+ argvec[tem] = 0; /* signal end of arglist */
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ return evaluate_subexp_do_call (exp, noside, nargs, argvec, NULL,
+ expect_type);
+ }
+
+ default:
+ error (_("Cannot perform substring on this type"));
+ }
}
/* Should be unreachable. */
return nullptr;
}
-/* Return true if TYPE is a string. */
-
-static bool
-f_is_string_type_p (struct type *type)
-{
- type = check_typedef (type);
- return (type->code () == TYPE_CODE_STRING
- || (type->code () == TYPE_CODE_ARRAY
- && TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_CHAR));
-}
-
/* Special expression lengths for Fortran. */
static void
oplen = 1;
args = 2;
break;
+
+ case OP_F77_UNDETERMINED_ARGLIST:
+ oplen = 3;
+ args = 1 + longest_to_int (exp->elts[pc - 2].longconst);
+ break;
}
*oplenp = oplen;
case BINOP_FORTRAN_MODULO:
print_binop_subexp_f (exp, pos, stream, prec, "MODULO");
return;
+
+ case OP_F77_UNDETERMINED_ARGLIST:
+ (*pos)++;
+ print_subexp_funcall (exp, pos, stream);
+ return;
}
}
case BINOP_FORTRAN_MODULO:
operator_length_f (exp, (elt + 1), &oplen, &nargs);
break;
+
+ case OP_F77_UNDETERMINED_ARGLIST:
+ return dump_subexp_body_funcall (exp, stream, elt + 1);
}
elt += oplen;
return 0;
}
-static const char *f_extensions[] =
-{
- ".f", ".F", ".for", ".FOR", ".ftn", ".FTN", ".fpp", ".FPP",
- ".f90", ".F90", ".f95", ".F95", ".f03", ".F03", ".f08", ".F08",
- NULL
-};
-
/* Expression processing for Fortran. */
-static const struct exp_descriptor exp_descriptor_f =
+const struct exp_descriptor f_language::exp_descriptor_tab =
{
print_subexp_f,
operator_length_f,
evaluate_subexp_f
};
-/* Constant data that describes the Fortran language. */
+/* See language.h. */
-extern const struct language_data f_language_data =
+void
+f_language::language_arch_info (struct gdbarch *gdbarch,
+ struct language_arch_info *lai) const
{
- "fortran",
- "Fortran",
- language_fortran,
- range_check_on,
- case_sensitive_off,
- array_column_major,
- macro_expansion_no,
- f_extensions,
- &exp_descriptor_f,
- f_parse, /* parser */
- null_post_parser,
- f_printchar, /* Print character constant */
- f_printstr, /* function to print string constant */
- f_emit_char, /* Function to print a single character */
- f_print_typedef, /* Print a typedef using appropriate syntax */
- NULL, /* name_of_this */
- false, /* la_store_sym_names_in_linkage_form_p */
- f_op_print_tab, /* expression operators for printing */
- 0, /* arrays are first-class (not c-style) */
- 1, /* String lower bound */
- &default_varobj_ops,
- f_is_string_type_p,
- "(...)" /* la_struct_too_deep_ellipsis */
-};
-
-/* Class representing the Fortran language. */
+ const struct builtin_f_type *builtin = builtin_f_type (gdbarch);
-class f_language : public language_defn
-{
-public:
- f_language ()
- : language_defn (language_fortran, f_language_data)
- { /* Nothing. */ }
-
- /* See language.h. */
- void language_arch_info (struct gdbarch *gdbarch,
- struct language_arch_info *lai) const override
- {
- const struct builtin_f_type *builtin = builtin_f_type (gdbarch);
-
- lai->string_char_type = builtin->builtin_character;
- lai->primitive_type_vector
- = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_f_primitive_types + 1,
- struct type *);
-
- lai->primitive_type_vector [f_primitive_type_character]
- = builtin->builtin_character;
- lai->primitive_type_vector [f_primitive_type_logical]
- = builtin->builtin_logical;
- lai->primitive_type_vector [f_primitive_type_logical_s1]
- = builtin->builtin_logical_s1;
- lai->primitive_type_vector [f_primitive_type_logical_s2]
- = builtin->builtin_logical_s2;
- lai->primitive_type_vector [f_primitive_type_logical_s8]
- = builtin->builtin_logical_s8;
- lai->primitive_type_vector [f_primitive_type_real]
- = builtin->builtin_real;
- lai->primitive_type_vector [f_primitive_type_real_s8]
- = builtin->builtin_real_s8;
- lai->primitive_type_vector [f_primitive_type_real_s16]
- = builtin->builtin_real_s16;
- lai->primitive_type_vector [f_primitive_type_complex_s8]
- = builtin->builtin_complex_s8;
- lai->primitive_type_vector [f_primitive_type_complex_s16]
- = builtin->builtin_complex_s16;
- lai->primitive_type_vector [f_primitive_type_void]
- = builtin->builtin_void;
-
- lai->bool_type_symbol = "logical";
- lai->bool_type_default = builtin->builtin_logical_s2;
- }
-
- /* See language.h. */
- unsigned int search_name_hash (const char *name) const override
- {
- return cp_search_name_hash (name);
- }
-
- /* See language.h. */
-
- char *demangle (const char *mangled, int options) const override
- {
- /* We could support demangling here to provide module namespaces
- also for inferiors with only minimal symbol table (ELF symbols).
- Just the mangling standard is not standardized across compilers
- and there is no DW_AT_producer available for inferiors with only
- the ELF symbols to check the mangling kind. */
- return nullptr;
- }
-
- /* See language.h. */
-
- void print_type (struct type *type, const char *varstring,
- struct ui_file *stream, int show, int level,
- const struct type_print_options *flags) const override
+ /* Helper function to allow shorter lines below. */
+ auto add = [&] (struct type * t)
{
- f_print_type (type, varstring, stream, show, level, flags);
- }
-
- /* See language.h. This just returns default set of word break
- characters but with the modules separator `::' removed. */
-
- const char *word_break_characters (void) const override
- {
- static char *retval;
-
- if (!retval)
- {
- char *s;
-
- retval = xstrdup (language_defn::word_break_characters ());
- s = strchr (retval, ':');
- if (s)
- {
- char *last_char = &s[strlen (s) - 1];
-
- *s = *last_char;
- *last_char = 0;
- }
- }
- return retval;
- }
-
-
- /* See language.h. */
+ lai->add_primitive_type (t);
+ };
+
+ add (builtin->builtin_character);
+ add (builtin->builtin_logical);
+ add (builtin->builtin_logical_s1);
+ add (builtin->builtin_logical_s2);
+ add (builtin->builtin_logical_s8);
+ add (builtin->builtin_real);
+ add (builtin->builtin_real_s8);
+ add (builtin->builtin_real_s16);
+ add (builtin->builtin_complex_s8);
+ add (builtin->builtin_complex_s16);
+ add (builtin->builtin_void);
+
+ lai->set_string_char_type (builtin->builtin_character);
+ lai->set_bool_type (builtin->builtin_logical_s2, "logical");
+}
- void collect_symbol_completion_matches (completion_tracker &tracker,
- complete_symbol_mode mode,
- symbol_name_match_type name_match_type,
- const char *text, const char *word,
- enum type_code code) const override
- {
- /* Consider the modules separator :: as a valid symbol name character
- class. */
- default_collect_symbol_completion_matches_break_on (tracker, mode,
- name_match_type,
- text, word, ":",
- code);
- }
-
- /* See language.h. */
-
- void value_print_inner
- (struct value *val, struct ui_file *stream, int recurse,
- const struct value_print_options *options) const override
- {
- return f_value_print_inner (val, stream, recurse, options);
- }
+/* See language.h. */
- /* See language.h. */
+unsigned int
+f_language::search_name_hash (const char *name) const
+{
+ return cp_search_name_hash (name);
+}
- struct block_symbol lookup_symbol_nonlocal
- (const char *name, const struct block *block,
- const domain_enum domain) const override
- {
- return cp_lookup_symbol_nonlocal (this, name, block, domain);
- }
+/* See language.h. */
-protected:
+struct block_symbol
+f_language::lookup_symbol_nonlocal (const char *name,
+ const struct block *block,
+ const domain_enum domain) const
+{
+ return cp_lookup_symbol_nonlocal (this, name, block, domain);
+}
- /* See language.h. */
+/* See language.h. */
- symbol_name_matcher_ftype *get_symbol_name_matcher_inner
- (const lookup_name_info &lookup_name) const override
- {
- return cp_get_symbol_name_matcher (lookup_name);
- }
-};
+symbol_name_matcher_ftype *
+f_language::get_symbol_name_matcher_inner
+ (const lookup_name_info &lookup_name) const
+{
+ return cp_get_symbol_name_matcher (lookup_name);
+}
/* Single instance of the Fortran language class. */