|
|
2985e0 |
From 7420e95a0ebb2401d67ad405670fb6a8d33f02da Mon Sep 17 00:00:00 2001
|
|
|
2985e0 |
From: Jim MacArthur <jim.macarthur@codethink.co.uk>
|
|
|
2985e0 |
Date: Thu, 4 Feb 2016 17:18:30 +0000
|
|
|
2985e0 |
Subject: [PATCH 04/23] Allow conversion between Hollerith constants and
|
|
|
2985e0 |
CHARACTER and INTEGER
|
|
|
2985e0 |
|
|
|
2985e0 |
Warnings are raised when this happens.
|
|
|
2985e0 |
|
|
|
2985e0 |
This feature is enabled with the `-std=extra-legacy` compiler flag.
|
|
|
2985e0 |
|
|
|
2985e0 |
0004-Allow-conversion-between-Hollerith-constants-and-CHA.patch
|
|
|
2985e0 |
|
|
|
2985e0 |
diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
|
|
|
2985e0 |
index 8fa305c..fc1be48 100644
|
|
|
2985e0 |
--- a/gcc/fortran/arith.c
|
|
|
2985e0 |
+++ b/gcc/fortran/arith.c
|
|
|
2985e0 |
@@ -2562,6 +2562,34 @@ hollerith2representation (gfc_expr *resu
|
|
|
2985e0 |
}
|
|
|
2985e0 |
|
|
|
2985e0 |
|
|
|
2985e0 |
+/* Helper function to set the representation in a character conversion.
|
|
|
2985e0 |
+ This assumes that the ts.type and ts.kind of the result have already
|
|
|
2985e0 |
+ been set. */
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+static void
|
|
|
2985e0 |
+character2representation (gfc_expr *result, gfc_expr *src)
|
|
|
2985e0 |
+{
|
|
|
93e26d |
+ size_t src_len, result_len;
|
|
|
93e26d |
+ size_t i;
|
|
|
2985e0 |
+ src_len = src->value.character.length;
|
|
|
93e26d |
+ gfc_target_expr_size (result, &result_len);
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ if (src_len > result_len)
|
|
|
2985e0 |
+ gfc_warning (0, "The character constant at %L is too long to convert to %s",
|
|
|
2985e0 |
+ &src->where, gfc_typename(&result->ts));
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ result->representation.string = XCNEWVEC (char, result_len + 1);
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ for (i = 0; i < MIN (result_len, src_len); i++)
|
|
|
2985e0 |
+ result->representation.string[i] = (char) src->value.character.string[i];
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ if (src_len < result_len)
|
|
|
2985e0 |
+ memset (&result->representation.string[src_len], ' ', result_len - src_len);
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ result->representation.string[result_len] = '\0'; /* For debugger */
|
|
|
2985e0 |
+ result->representation.length = result_len;
|
|
|
2985e0 |
+}
|
|
|
2985e0 |
+
|
|
|
2985e0 |
/* Convert Hollerith to integer. The constant will be padded or truncated. */
|
|
|
2985e0 |
|
|
|
2985e0 |
gfc_expr *
|
|
|
2985e0 |
@@ -2577,6 +2605,19 @@ gfc_hollerith2int (gfc_expr *src, int ki
|
|
|
2985e0 |
return result;
|
|
|
2985e0 |
}
|
|
|
2985e0 |
|
|
|
2985e0 |
+/* Convert character to integer. The constant will be padded or truncated. */
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+gfc_expr *
|
|
|
2985e0 |
+gfc_character2int (gfc_expr *src, int kind)
|
|
|
2985e0 |
+{
|
|
|
2985e0 |
+ gfc_expr *result;
|
|
|
2985e0 |
+ result = gfc_get_constant_expr (BT_INTEGER, kind, &src->where);
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ character2representation (result, src);
|
|
|
2985e0 |
+ gfc_interpret_integer (kind, (unsigned char *) result->representation.string,
|
|
|
2985e0 |
+ result->representation.length, result->value.integer);
|
|
|
2985e0 |
+ return result;
|
|
|
2985e0 |
+}
|
|
|
2985e0 |
|
|
|
2985e0 |
/* Convert Hollerith to real. The constant will be padded or truncated. */
|
|
|
2985e0 |
|
|
|
2985e0 |
diff --git a/gcc/fortran/arith.h b/gcc/fortran/arith.h
|
|
|
2985e0 |
index 85aca5b..1f56aea 100644
|
|
|
2985e0 |
--- a/gcc/fortran/arith.h
|
|
|
2985e0 |
+++ b/gcc/fortran/arith.h
|
|
|
2985e0 |
@@ -83,6 +83,7 @@ gfc_expr *gfc_hollerith2complex (gfc_expr *, int);
|
|
|
2985e0 |
gfc_expr *gfc_hollerith2character (gfc_expr *, int);
|
|
|
2985e0 |
gfc_expr *gfc_hollerith2logical (gfc_expr *, int);
|
|
|
2985e0 |
gfc_expr *gfc_character2character (gfc_expr *, int);
|
|
|
2985e0 |
+gfc_expr *gfc_character2int (gfc_expr *, int);
|
|
|
2985e0 |
|
|
|
2985e0 |
#endif /* GFC_ARITH_H */
|
|
|
2985e0 |
|
|
|
2985e0 |
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
|
|
|
2985e0 |
index f304154..ed3d440 100644
|
|
|
2985e0 |
--- a/gcc/fortran/check.c
|
|
|
2985e0 |
+++ b/gcc/fortran/check.c
|
|
|
2985e0 |
@@ -2643,9 +2643,14 @@ gfc_check_index (gfc_expr *string, gfc_expr *substring, gfc_expr *back,
|
|
|
2985e0 |
}
|
|
|
2985e0 |
|
|
|
2985e0 |
|
|
|
2985e0 |
+/* This is the check function for the argument to the INT intrinsic */
|
|
|
2985e0 |
bool
|
|
|
2985e0 |
gfc_check_int (gfc_expr *x, gfc_expr *kind)
|
|
|
2985e0 |
{
|
|
|
2985e0 |
+ if ((gfc_option.allow_std & GFC_STD_EXTRA_LEGACY)
|
|
|
2985e0 |
+ && x->ts.type == BT_CHARACTER)
|
|
|
2985e0 |
+ return true;
|
|
|
2985e0 |
+
|
|
|
2985e0 |
if (!numeric_check (x, 0))
|
|
|
2985e0 |
return false;
|
|
|
2985e0 |
|
|
|
2985e0 |
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
|
|
|
2985e0 |
index 2f60fe8..371f5b8 100644
|
|
|
2985e0 |
--- a/gcc/fortran/intrinsic.c
|
|
|
2985e0 |
+++ b/gcc/fortran/intrinsic.c
|
|
|
2985e0 |
@@ -3928,6 +3928,17 @@ add_conversions (void)
|
|
|
2985e0 |
add_conv (BT_LOGICAL, gfc_logical_kinds[j].kind,
|
|
|
2985e0 |
BT_INTEGER, gfc_integer_kinds[i].kind, GFC_STD_LEGACY);
|
|
|
2985e0 |
}
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ /* Oracle allows character values to be converted to integers,
|
|
|
2985e0 |
+ similar to Hollerith-Integer conversion - the first characters will
|
|
|
2985e0 |
+ be turned into ascii values. */
|
|
|
2985e0 |
+ if (gfc_option.allow_std & GFC_STD_EXTRA_LEGACY)
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ /* Character-Integer conversions. */
|
|
|
2985e0 |
+ for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
|
|
|
2985e0 |
+ add_conv (BT_CHARACTER, gfc_default_character_kind,
|
|
|
2985e0 |
+ BT_INTEGER, gfc_integer_kinds[i].kind, GFC_STD_LEGACY);
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
}
|
|
|
2985e0 |
|
|
|
2985e0 |
|
|
|
2985e0 |
@@ -5008,6 +5019,15 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
|
|
|
2985e0 |
gfc_typename (&from_ts), gfc_typename (ts),
|
|
|
2985e0 |
&expr->where);
|
|
|
2985e0 |
}
|
|
|
2985e0 |
+ else if ((gfc_option.allow_std & GFC_STD_EXTRA_LEGACY)
|
|
|
2985e0 |
+ && from_ts.type == BT_CHARACTER
|
|
|
2985e0 |
+ && ts->type == BT_INTEGER)
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ if (warn_conversion_extra || warn_conversion)
|
|
|
2985e0 |
+ gfc_warning_now (0, "Conversion from %s to %s at %L",
|
|
|
2985e0 |
+ gfc_typename (&from_ts), gfc_typename (ts),
|
|
|
2985e0 |
+ &expr->where);
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
else
|
|
|
2985e0 |
gcc_unreachable ();
|
|
|
2985e0 |
}
|
|
|
2985e0 |
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
|
|
|
2985e0 |
index d09cfa6..07c8c9a 100644
|
|
|
2985e0 |
--- a/gcc/fortran/resolve.c
|
|
|
2985e0 |
+++ b/gcc/fortran/resolve.c
|
|
|
2985e0 |
@@ -3803,6 +3803,30 @@ lookup_uop_fuzzy (const char *op, gfc_symtree *uop)
|
|
|
2985e0 |
return gfc_closest_fuzzy_match (op, candidates);
|
|
|
2985e0 |
}
|
|
|
2985e0 |
|
|
|
2985e0 |
+/* Return true if TYPE is character based, false otherwise. */
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+static int
|
|
|
2985e0 |
+is_character_based (bt type)
|
|
|
2985e0 |
+{
|
|
|
2985e0 |
+ return type == BT_CHARACTER || type == BT_HOLLERITH;
|
|
|
2985e0 |
+}
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+/* If E is a logical, convert it to an integer and issue a warning
|
|
|
2985e0 |
+ for the conversion. */
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+static void
|
|
|
2985e0 |
+convert_logical_to_integer (gfc_expr *e)
|
|
|
2985e0 |
+{
|
|
|
2985e0 |
+ if (e->ts.type == BT_LOGICAL)
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ /* Convert to INTEGER */
|
|
|
2985e0 |
+ gfc_typespec t;
|
|
|
2985e0 |
+ t.type = BT_INTEGER;
|
|
|
2985e0 |
+ t.kind = 1;
|
|
|
2985e0 |
+ gfc_convert_type_warn (e, &t, 2, 1);
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
+}
|
|
|
2985e0 |
+
|
|
|
2985e0 |
|
|
|
2985e0 |
/* Resolve an operator expression node. This can involve replacing the
|
|
|
2985e0 |
operation with a user defined function call. */
|
|
|
2985e0 |
@@ -3976,6 +4000,38 @@ resolve_operator (gfc_expr *e)
|
|
|
2985e0 |
case INTRINSIC_EQ_OS:
|
|
|
2985e0 |
case INTRINSIC_NE:
|
|
|
2985e0 |
case INTRINSIC_NE_OS:
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ if (gfc_option.allow_std & GFC_STD_EXTRA_LEGACY)
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ convert_logical_to_integer (op1);
|
|
|
2985e0 |
+ convert_logical_to_integer (op2);
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ /* If you're comparing hollerith contants to character expresisons,
|
|
|
2985e0 |
+ convert the hollerith constant */
|
|
|
2985e0 |
+ if ((gfc_option.allow_std & GFC_STD_EXTRA_LEGACY)
|
|
|
2985e0 |
+ && is_character_based (op1->ts.type)
|
|
|
2985e0 |
+ && is_character_based (op2->ts.type))
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ gfc_typespec ts;
|
|
|
2985e0 |
+ ts.type = BT_CHARACTER;
|
|
|
2985e0 |
+ ts.kind = op1->ts.kind;
|
|
|
2985e0 |
+ if (op1->ts.type == BT_HOLLERITH)
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ gfc_convert_type_warn (op1, &ts, 2, 1);
|
|
|
2985e0 |
+ gfc_warning (0, "Promoting argument for comparison from HOLLERITH "
|
|
|
2985e0 |
+ "to CHARACTER at %L", &op1->where);
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
+ ts.type = BT_CHARACTER;
|
|
|
2985e0 |
+ ts.kind = op2->ts.kind;
|
|
|
2985e0 |
+ if (op2->ts.type == BT_HOLLERITH)
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ gfc_convert_type_warn (op2, &ts, 2, 1);
|
|
|
2985e0 |
+ gfc_warning (0, "Promoting argument for comparison from HOLLERITH "
|
|
|
2985e0 |
+ "to CHARACTER at %L", &op2->where);
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
+
|
|
|
2985e0 |
if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
|
|
|
2985e0 |
&& op1->ts.kind == op2->ts.kind)
|
|
|
2985e0 |
{
|
|
|
2985e0 |
@@ -3984,6 +4040,29 @@ resolve_operator (gfc_expr *e)
|
|
|
2985e0 |
break;
|
|
|
2985e0 |
}
|
|
|
2985e0 |
|
|
|
2985e0 |
+ /* Numeric to hollerith comparisons */
|
|
|
2985e0 |
+ if ((gfc_option.allow_std & GFC_STD_EXTRA_LEGACY)
|
|
|
2985e0 |
+ && gfc_numeric_ts (&op1->ts)
|
|
|
2985e0 |
+ && (op2->ts.type == BT_HOLLERITH || op2->ts.type == BT_CHARACTER))
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ gfc_warning (0, "Promoting argument for comparison from character type to INTEGER at %L", &op2->where);
|
|
|
2985e0 |
+ gfc_typespec ts;
|
|
|
2985e0 |
+ ts.type = BT_INTEGER;
|
|
|
2985e0 |
+ ts.kind = 4;
|
|
|
2985e0 |
+ gfc_convert_type_warn (op2, &ts, 2, 1);
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ if ((gfc_option.allow_std & GFC_STD_EXTRA_LEGACY)
|
|
|
2985e0 |
+ && gfc_numeric_ts (&op2->ts)
|
|
|
2985e0 |
+ && (op1->ts.type == BT_HOLLERITH || op1->ts.type == BT_CHARACTER))
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ gfc_warning (0, "Promoting argument for comparison from character type to INTEGER at %L", &op1->where);
|
|
|
2985e0 |
+ gfc_typespec ts;
|
|
|
2985e0 |
+ ts.type = BT_INTEGER;
|
|
|
2985e0 |
+ ts.kind = 4;
|
|
|
2985e0 |
+ gfc_convert_type_warn (op1, &ts, 2, 1);
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
+
|
|
|
2985e0 |
if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts))
|
|
|
2985e0 |
{
|
|
|
2985e0 |
gfc_type_convert_binary (e, 1);
|
|
|
2985e0 |
@@ -4188,7 +4267,6 @@ bad_op:
|
|
|
2985e0 |
return false;
|
|
|
2985e0 |
}
|
|
|
2985e0 |
|
|
|
2985e0 |
-
|
|
|
2985e0 |
/************** Array resolution subroutines **************/
|
|
|
2985e0 |
|
|
|
2985e0 |
enum compare_result
|
|
|
2985e0 |
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
|
|
|
2985e0 |
index 3c85c52..e03384c 100644
|
|
|
2985e0 |
--- a/gcc/fortran/simplify.c
|
|
|
2985e0 |
+++ b/gcc/fortran/simplify.c
|
|
|
2985e0 |
@@ -7987,10 +7987,19 @@ gfc_convert_constant (gfc_expr *e, bt type, int kind)
|
|
|
2985e0 |
break;
|
|
|
2985e0 |
|
|
|
2985e0 |
case BT_CHARACTER:
|
|
|
2985e0 |
- if (type == BT_CHARACTER)
|
|
|
2985e0 |
- f = gfc_character2character;
|
|
|
2985e0 |
- else
|
|
|
2985e0 |
- goto oops;
|
|
|
2985e0 |
+ switch (type)
|
|
|
2985e0 |
+ {
|
|
|
2985e0 |
+ case BT_CHARACTER:
|
|
|
2985e0 |
+ f = gfc_character2character;
|
|
|
2985e0 |
+ break;
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ case BT_INTEGER:
|
|
|
2985e0 |
+ f = gfc_character2int;
|
|
|
2985e0 |
+ break;
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ default:
|
|
|
2985e0 |
+ goto oops;
|
|
|
2985e0 |
+ }
|
|
|
2985e0 |
break;
|
|
|
2985e0 |
|
|
|
2985e0 |
default:
|
|
|
2985e0 |
diff --git a/gcc/testsuite/gfortran.dg/hollerith-character-comparison.f90 b/gcc/testsuite/gfortran.dg/hollerith-character-comparison.f90
|
|
|
2985e0 |
new file mode 100644
|
|
|
2985e0 |
index 0000000..9c462b9
|
|
|
2985e0 |
--- /dev/null
|
|
|
2985e0 |
+++ b/gcc/testsuite/gfortran.dg/hollerith-character-comparison.f90
|
|
|
2985e0 |
@@ -0,0 +1,15 @@
|
|
|
2985e0 |
+ ! { dg-options "-std=extra-legacy" }
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ program convert
|
|
|
2985e0 |
+ REAL*4 a
|
|
|
2985e0 |
+ INTEGER*4 b
|
|
|
2985e0 |
+ b = 1000
|
|
|
2985e0 |
+ print *, 4HJMAC.eq.4HJMAC ! { dg-warning "Promoting argument for comparison from HOLLERITH to CHARACTER at" }
|
|
|
2985e0 |
+ print *, 4HJMAC.eq."JMAC" ! { dg-warning "Promoting argument for comparison from HOLLERITH to CHARACTER at" }
|
|
|
2985e0 |
+ print *, 4HJMAC.eq."JMAN" ! { dg-warning "Promoting argument for comparison from HOLLERITH to CHARACTER at" }
|
|
|
2985e0 |
+ print *, "JMAC".eq.4HJMAN ! { dg-warning "Promoting argument for comparison from HOLLERITH to CHARACTER at" }
|
|
|
2985e0 |
+ print *, "AAAA".eq.5HAAAAA ! { dg-warning "Promoting argument for comparison from HOLLERITH to CHARACTER at" }
|
|
|
2985e0 |
+ print *, "BBBBB".eq.5HBBBB ! { dg-warning "Promoting argument for comparison from HOLLERITH to CHARACTER at" }
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ end program
|
|
|
2985e0 |
+
|
|
|
2985e0 |
diff --git a/gcc/testsuite/gfortran.dg/hollerith-int-comparison.f90 b/gcc/testsuite/gfortran.dg/hollerith-int-comparison.f90
|
|
|
2985e0 |
new file mode 100644
|
|
|
2985e0 |
index 0000000..f44c1f8
|
|
|
2985e0 |
--- /dev/null
|
|
|
2985e0 |
+++ b/gcc/testsuite/gfortran.dg/hollerith-int-comparison.f90
|
|
|
2985e0 |
@@ -0,0 +1,11 @@
|
|
|
2985e0 |
+ ! { dg-options "-std=extra-legacy" }
|
|
|
2985e0 |
+
|
|
|
2985e0 |
+ program convert
|
|
|
2985e0 |
+ INTEGER*4 b
|
|
|
2985e0 |
+ b = 5HRIVET ! { dg-warning "Legacy Extension: Hollerith constant|Conversion from HOLLERITH to INTEGER|too long to convert" }
|
|
|
2985e0 |
+ print *, 4HJMAC.eq.400 ! { dg-warning "Legacy Extension: Hollerith constant|Promoting argument for comparison from character|Conversion from HOLLERITH to INTEGER" }
|
|
|
2985e0 |
+ print *, 4HRIVE.eq.1163282770 ! { dg-warning "Legacy Extension: Hollerith constant|Promoting argument for comparison from character|Conversion from HOLLERITH to INTEGER" }
|
|
|
2985e0 |
+ print *, b
|
|
|
2985e0 |
+ print *, 1163282770.eq.4HRIVE ! { dg-warning "Legacy Extension: Hollerith constant|Promoting argument for comparison from character|Conversion from HOLLERITH to INTEGER" }
|
|
|
2985e0 |
+ end program
|
|
|
2985e0 |
+
|