This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch, Fortran] PR fortran/38137: Runtime check for stringlengths to MERGE
- From: Daniel Kraft <d at domob dot eu>
- To: Fortran List <fortran at gcc dot gnu dot org>, gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 17 Dec 2008 09:24:12 +0100
- Subject: [Patch, Fortran] PR fortran/38137: Runtime check for stringlengths to MERGE
Hi all,
this patch adds a runtime check (when -fbounds-check is enabled) that
the arguments to MERGE have the same string length; currently this is
only checked at compile-time when possible. The patch should be
straight forward, if I didn't mess up some of the tree stuff.
I'm not sure if other intrinsics are affected as well, but check.c does
compile-time checks for same string lengths only for MERGE. But feel
free to suggest others and I can add both compile-time and runtime
checks for them :)
Regression test running at the moment on GNU/Linux-x86-32. Ok for trunk
if no regressions? I believe this is can go in for 4.4 without problems
(but can hold on until 4.5 too if you want).
Yours,
Daniel
--
Done: Arc-Bar-Cav-Rog-Sam-Tou-Val-Wiz
To go: Hea-Kni-Mon-Pri-Ran
2008-12-17 Daniel Kraft <d@domob.eu>
PR fortran/38137
* trans-intrinsic.c (conv_same_strlen_check): New method.
(gfc_conv_intrinsic_merge): Call it here to actually do the check.
2008-12-17 Daniel Kraft <d@domob.eu>
PR fortran/38137
* gfortran.dg/merge_char_3.f90: New test.
Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c (revision 142781)
+++ gcc/fortran/trans-intrinsic.c (working copy)
@@ -746,6 +746,36 @@ gfc_conv_intrinsic_lib_function (gfc_se
se->expr = build_call_array (rettype, fndecl, num_args, args);
}
+
+/* If bounds-checking is enabled, create code to verify at runtime that the
+ string lengths for both expressions are the same (needed for e.g. MERGE).
+ If bounds-checking is not enabled, does nothing. */
+
+static void
+conv_same_strlen_check (const char* intr_name, locus* where, tree a, tree b,
+ stmtblock_t* target)
+{
+ tree cond;
+ tree name;
+
+ /* If bounds-checking is disabled, do nothing. */
+ if (!flag_bounds_check)
+ return;
+
+ /* Compare the two string lengths. */
+ cond = fold_build2 (NE_EXPR, boolean_type_node, a, b);
+
+ /* Output the runtime-check. */
+ name = gfc_build_cstring_const (intr_name);
+ name = gfc_build_addr_expr (pchar_type_node, name);
+ gfc_trans_runtime_check (true, false, cond, target, where,
+ "Unequal character lengths (%ld/%ld) for arguments"
+ " to %s",
+ fold_convert (long_integer_type_node, a),
+ fold_convert (long_integer_type_node, b), name);
+}
+
+
/* The EXPONENT(s) intrinsic function is translated into
int ret;
frexp (s, &ret);
@@ -3026,7 +3056,7 @@ gfc_conv_intrinsic_merge (gfc_se * se, g
tree fsource;
tree mask;
tree type;
- tree len;
+ tree len, len2;
tree *args;
unsigned int num_args;
@@ -3047,9 +3077,12 @@ gfc_conv_intrinsic_merge (gfc_se * se, g
also have to set the string length for the result. */
len = args[0];
tsource = args[1];
+ len2 = args[2];
fsource = args[3];
mask = args[4];
+ conv_same_strlen_check ("MERGE", &expr->where, len, len2, &se->post);
+
se->string_length = len;
}
type = TREE_TYPE (tsource);
Index: gcc/testsuite/gfortran.dg/merge_char_3.f90
===================================================================
--- gcc/testsuite/gfortran.dg/merge_char_3.f90 (revision 0)
+++ gcc/testsuite/gfortran.dg/merge_char_3.f90 (revision 0)
@@ -0,0 +1,19 @@
+! { dg-do run }
+! { dg-options "-fbounds-check" }
+! { dg-shouldfail "Unequal character lengths" }
+
+! PR fortran/38137
+! Test that -fbounds-check detects unequal character lengths to MERGE
+! at runtime.
+
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+
+subroutine foo(a)
+implicit none
+character(len=*) :: a
+character(len=3) :: b
+print *, merge(a,b,.true.) ! Unequal character lengths
+end subroutine foo
+
+call foo("ab")
+end