From 8405874a0e2db1806332ead2dcf3e9ec563075aa Mon Sep 17 00:00:00 2001 From: Mark Eggleston Date: Thu, 19 Dec 2019 15:13:25 +0000 Subject: [PATCH] Prevent conversion of character data in array constructors. Fix for PR fortran/92896 [10 Regression] [DEC] ICE in reduce_unary, at fortran/arith.c:1283. This was caused by an unintended side affect of "Allow CHARACTER literals in assignments and data statements" (revision 277975). If the conversion occurs in a array constructor it is rejected. From-SVN: r279583 --- gcc/fortran/ChangeLog | 14 ++++++++++++++ gcc/fortran/array.c | 7 ++++--- gcc/fortran/gfortran.h | 3 ++- gcc/fortran/intrinsic.c | 15 +++++++++++++-- gcc/testsuite/ChangeLog | 5 +++++ .../no_char_conversion_in_array_constructor.f90 | 10 ++++++++++ 6 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/no_char_conversion_in_array_constructor.f90 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index b780450a63a..7a71c70a6e9 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,17 @@ +2019-12-19 Mark Eggleston + + PR fortran/92896 + * array.c (walk_array_constructor): Replace call to gfc_convert_type + with call to gfc_convert_type_warn with new argument set to true. + (check_element_type): Replace call to cfg_convert_type with call to + gfc_convert_type_warn with new argument set to true. + * gfortran.h: Add argument "array" to gfc_convert_type_warn default + value set to false. + *intrinsic.c (gfc_convert_type_warn): Update description of arguments. + Add new argument to argument list. Add check for conversion to numeric + or logical from character and array set to true, i.e. if conversion + from character is in an array constructor reject it, goto bad. + 2019-12-19 Jakub Jelinek PR fortran/92977 diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c index 1834d2f98a0..bfd461252d8 100644 --- a/gcc/fortran/array.c +++ b/gcc/fortran/array.c @@ -1185,9 +1185,10 @@ walk_array_constructor (gfc_typespec *ts, gfc_constructor_base head) if (m == MATCH_ERROR) return m; } - else if (!gfc_convert_type (e, ts, 1) && e->ts.type != BT_UNKNOWN) + else if (!gfc_convert_type_warn (e, ts, 1, 1, true) + && e->ts.type != BT_UNKNOWN) return MATCH_ERROR; - } + } return MATCH_YES; } @@ -1386,7 +1387,7 @@ check_element_type (gfc_expr *expr, bool convert) return 0; if (convert) - return gfc_convert_type(expr, &constructor_ts, 1) ? 0 : 1; + return gfc_convert_type_warn (expr, &constructor_ts, 1, 1, true) ? 0 : 1; gfc_error ("Element in %s array constructor at %L is %s", gfc_typename (&constructor_ts), &expr->where, diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 3907d1407ac..a266edb8ed8 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -3189,7 +3189,8 @@ void gfc_intrinsic_done_1 (void); char gfc_type_letter (bt, bool logical_equals_int = false); gfc_symbol * gfc_get_intrinsic_sub_symbol (const char *); bool gfc_convert_type (gfc_expr *, gfc_typespec *, int); -bool gfc_convert_type_warn (gfc_expr *, gfc_typespec *, int, int); +bool gfc_convert_type_warn (gfc_expr *, gfc_typespec *, int, int, + bool array = false); bool gfc_convert_chartype (gfc_expr *, gfc_typespec *); int gfc_generic_intrinsic (const char *); int gfc_specific_intrinsic (const char *); diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c index 76b53bb7117..c913f5ab152 100644 --- a/gcc/fortran/intrinsic.c +++ b/gcc/fortran/intrinsic.c @@ -5096,10 +5096,15 @@ gfc_convert_type (gfc_expr *expr, gfc_typespec *ts, int eflag) 1 Generate a gfc_error() 2 Generate a gfc_internal_error(). - 'wflag' controls the warning related to conversion. */ + 'wflag' controls the warning related to conversion. + + 'array' indicates whether the conversion is in an array constructor. + Non-standard conversion from character to numeric not allowed if true. +*/ bool -gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag) +gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag, + bool array) { gfc_intrinsic_sym *sym; gfc_typespec from_ts; @@ -5142,6 +5147,12 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag) && gfc_compare_types (&expr->ts, ts)) return true; + /* If array is true then conversion is in an array constructor where + non-standard conversion is not allowed. */ + if (array && from_ts.type == BT_CHARACTER + && (gfc_numeric_ts (ts) || ts->type == BT_LOGICAL)) + goto bad; + sym = find_conv (&expr->ts, ts); if (sym == NULL) goto bad; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bbca1aa5b16..4e75067e9ce 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-12-19 Mark Eggleston + + PR fortran/92896 + * gfortran.dg/no_char_conversion_in_array_constructor.f90: New test. + 2019-12-19 Richard Sandiford * gcc.target/aarch64/sve/mixed_size_9.c: New test. diff --git a/gcc/testsuite/gfortran.dg/no_char_conversion_in_array_constructor.f90 b/gcc/testsuite/gfortran.dg/no_char_conversion_in_array_constructor.f90 new file mode 100644 index 00000000000..7dc4624b8b1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/no_char_conversion_in_array_constructor.f90 @@ -0,0 +1,10 @@ +! { dg-do compile } +! { dg-options "-fdec-char-conversions" } + +program p + print *, -[integer :: 1, [integer(8) :: '2']] ! { dg-error "Cannot convert" } + print *, -[real :: 1, [real(8) :: '2']] ! { dg-error "Cannot convert" } + print *, -[complex :: 1, [complex(8) :: '2']] ! { dg-error "Cannot convert" } + print *, [logical :: 1, [logical(8) :: '2']] ! { dg-error "Cannot convert" } +end +