diff options
author | Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2015-08-07 15:02:15 +0000 |
---|---|---|
committer | François-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2015-08-07 15:02:15 +0000 |
commit | 0e360db97091f31bf8a16ec50e99b31ebe6c52e1 (patch) | |
tree | 8a5b785abc55fa5c397eb33f2c98ba742798a57c /gcc/fortran | |
parent | a044d2b1b6c85f88451e83649977ad908011b1f4 (diff) | |
download | gcc-0e360db97091f31bf8a16ec50e99b31ebe6c52e1.zip gcc-0e360db97091f31bf8a16ec50e99b31ebe6c52e1.tar.gz gcc-0e360db97091f31bf8a16ec50e99b31ebe6c52e1.tar.bz2 |
re PR fortran/64104 ([F2003][IEEE] Allow IEEE functions in specification expressions)
PR fortran/64104
* expr.c (gfc_check_init_expr): Allow some IEEE functions in
constant expressions.
(external_spec_function): Allow some IEEE functions in specification
expressions.
* simplify.c (gfc_simplify_ieee_selected_real_kind): Remove.
(simplify_ieee_selected_real_kind, simplify_ieee_support,
matches_ieee_function_name, gfc_simplify_ieee_functions): New
functions.
* gfortran.h (gfc_simplify_ieee_selected_real_kind): Remove
prototype.
(gfc_simplify_ieee_functions): Add prototype.
* gfortran.dg/ieee/ieee_8.f90: New test.
From-SVN: r226723
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/fortran/expr.c | 37 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 3 | ||||
-rw-r--r-- | gcc/fortran/simplify.c | 73 |
4 files changed, 106 insertions, 22 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 86afcf0..b071f87 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,18 @@ +2015-08-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/64104 + * expr.c (gfc_check_init_expr): Allow some IEEE functions in + constant expressions. + (external_spec_function): Allow some IEEE functions in specification + expressions. + * simplify.c (gfc_simplify_ieee_selected_real_kind): Remove. + (simplify_ieee_selected_real_kind, simplify_ieee_support, + matches_ieee_function_name, gfc_simplify_ieee_functions): New + functions. + * gfortran.h (gfc_simplify_ieee_selected_real_kind): Remove + prototype. + (gfc_simplify_ieee_functions): Add prototype. + 2015-08-06 Mikael Morin <mikael@gcc.gnu.org> * trans.h (gfc_trans_scalar_assign): Remove fourth argument. diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 9e5a804f..1d6f310 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -2474,13 +2474,14 @@ gfc_check_init_expr (gfc_expr *e) gfc_intrinsic_sym* isym; gfc_symbol* sym = e->symtree->n.sym; - /* Special case for IEEE_SELECTED_REAL_KIND from the intrinsic - module IEEE_ARITHMETIC, which is allowed in initialization - expressions. */ - if (!strcmp(sym->name, "ieee_selected_real_kind") - && sym->from_intmod == INTMOD_IEEE_ARITHMETIC) + /* Simplify here the intrinsics from the IEEE_ARITHMETIC and + IEEE_EXCEPTIONS modules. */ + int mod = sym->from_intmod; + if (mod == INTMOD_NONE && sym->generic) + mod = sym->generic->sym->from_intmod; + if (mod == INTMOD_IEEE_ARITHMETIC || mod == INTMOD_IEEE_EXCEPTIONS) { - gfc_expr *new_expr = gfc_simplify_ieee_selected_real_kind (e); + gfc_expr *new_expr = gfc_simplify_ieee_functions (e); if (new_expr) { gfc_replace_expr (e, new_expr); @@ -2738,6 +2739,29 @@ external_spec_function (gfc_expr *e) f = e->value.function.esym; + /* IEEE functions allowed are "a reference to a transformational function + from the intrinsic module IEEE_ARITHMETIC or IEEE_EXCEPTIONS", and + "inquiry function from the intrinsic modules IEEE_ARITHMETIC and + IEEE_EXCEPTIONS". */ + if (f->from_intmod == INTMOD_IEEE_ARITHMETIC + || f->from_intmod == INTMOD_IEEE_EXCEPTIONS) + { + if (!strcmp (f->name, "ieee_selected_real_kind") + || !strcmp (f->name, "ieee_support_rounding") + || !strcmp (f->name, "ieee_support_flag") + || !strcmp (f->name, "ieee_support_halting") + || !strcmp (f->name, "ieee_support_datatype") + || !strcmp (f->name, "ieee_support_denormal") + || !strcmp (f->name, "ieee_support_divide") + || !strcmp (f->name, "ieee_support_inf") + || !strcmp (f->name, "ieee_support_io") + || !strcmp (f->name, "ieee_support_nan") + || !strcmp (f->name, "ieee_support_sqrt") + || !strcmp (f->name, "ieee_support_standard") + || !strcmp (f->name, "ieee_support_underflow_control")) + goto function_allowed; + } + if (f->attr.proc == PROC_ST_FUNCTION) { gfc_error ("Specification function %qs at %L cannot be a statement " @@ -2766,6 +2790,7 @@ external_spec_function (gfc_expr *e) return false; } +function_allowed: return restricted_args (e->value.function.actual); } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 69de5ad..5a0c369 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2881,8 +2881,6 @@ gfc_formal_arglist *gfc_sym_get_dummy_args (gfc_symbol *); /* intrinsic.c -- true if working in an init-expr, false otherwise. */ extern bool gfc_init_expr_flag; -gfc_expr *gfc_simplify_ieee_selected_real_kind (gfc_expr *); - /* Given a symbol that we have decided is intrinsic, mark it as such by placing it into a special module that is otherwise impossible to read or write. */ @@ -3245,6 +3243,7 @@ int gfc_code_walker (gfc_code **, walk_code_fn_t, walk_expr_fn_t, void *); /* simplify.c */ void gfc_convert_mpz_to_signed (mpz_t, int); +gfc_expr *gfc_simplify_ieee_functions (gfc_expr *); /* trans-array.c */ diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index f0fdfbd..124558e 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -5553,20 +5553,6 @@ gfc_simplify_selected_real_kind (gfc_expr *p, gfc_expr *q, gfc_expr *rdx) gfc_expr * -gfc_simplify_ieee_selected_real_kind (gfc_expr *expr) -{ - gfc_actual_arglist *arg = expr->value.function.actual; - gfc_expr *p = arg->expr, *q = arg->next->expr, - *rdx = arg->next->next->expr; - - /* Currently, if IEEE is supported and this module is built, it means - all our floating-point types conform to IEEE. Hence, we simply handle - IEEE_SELECTED_REAL_KIND like SELECTED_REAL_KIND. */ - return gfc_simplify_selected_real_kind (p, q, rdx); -} - - -gfc_expr * gfc_simplify_set_exponent (gfc_expr *x, gfc_expr *i) { gfc_expr *result; @@ -6955,3 +6941,62 @@ gfc_simplify_compiler_version (void) return gfc_get_character_expr (gfc_default_character_kind, &gfc_current_locus, buffer, len); } + +/* Simplification routines for intrinsics of IEEE modules. */ + +gfc_expr * +simplify_ieee_selected_real_kind (gfc_expr *expr) +{ + gfc_actual_arglist *arg = expr->value.function.actual; + gfc_expr *p = arg->expr, *q = arg->next->expr, + *rdx = arg->next->next->expr; + + /* Currently, if IEEE is supported and this module is built, it means + all our floating-point types conform to IEEE. Hence, we simply handle + IEEE_SELECTED_REAL_KIND like SELECTED_REAL_KIND. */ + return gfc_simplify_selected_real_kind (p, q, rdx); +} + +gfc_expr * +simplify_ieee_support (gfc_expr *expr) +{ + /* We consider that if the IEEE modules are loaded, we have full support + for flags, halting and rounding, which are the three functions + (IEEE_SUPPORT_{FLAG,HALTING,ROUNDING}) allowed in constant + expressions. One day, we will need libgfortran to detect support and + communicate it back to us, allowing for partial support. */ + + return gfc_get_logical_expr (gfc_default_logical_kind, &expr->where, + true); +} + +bool +matches_ieee_function_name (gfc_symbol *sym, const char *name) +{ + int n = strlen(name); + + if (!strncmp(sym->name, name, n)) + return true; + + /* If a generic was used and renamed, we need more work to find out. + Compare the specific name. */ + if (sym->generic && !strncmp(sym->generic->sym->name, name, n)) + return true; + + return false; +} + +gfc_expr * +gfc_simplify_ieee_functions (gfc_expr *expr) +{ + gfc_symbol* sym = expr->symtree->n.sym; + + if (matches_ieee_function_name(sym, "ieee_selected_real_kind")) + return simplify_ieee_selected_real_kind (expr); + else if (matches_ieee_function_name(sym, "ieee_support_flag") + || matches_ieee_function_name(sym, "ieee_support_halting") + || matches_ieee_function_name(sym, "ieee_support_rounding")) + return simplify_ieee_support (expr); + else + return NULL; +} |