[Patch, fortran] PR27996 and PR29978 - warnings and errors on character lengths
Paul Thomas
paulthomas2@wanadoo.fr
Wed Jan 3 20:33:00 GMT 2007
Ping!
> Tobias,
>> When I try to bootstrap with your patch, I get an ICE with
>> libgfortran/generated/misc_specifics.F90.
>> Reduced test case:
>>
> This is now fixed in the attached. Also, your other comments have
> been acted upon. Furthermore, I have bootstratpped and regtested on
> ia64/FC5.
>
> I think that it is now OK for trunk and, after the usual delay, for
> 4.1. OK with you?
>
> Paul
>
> ------------------------------------------------------------------------
>
> 2006-11-30 Paul Thomas <pault@gcc.gnu.org>
>
> PR fortran/27996
> PR fortran/27998
> * decl.c (gfc_set_constant_character_len): Add boolean arg to
> flag array constructor resolution. Warn if string is being
> truncated. Standard dependent error if string is padded. Set
> new arg to false for all three calls to
> gfc_set_constant_character_len.
> * match.h : Add boolean arg to prototype for
> gfc_set_constant_character_len.
> * gfortran.h : Add warn_character_truncation to gfc_options.
> * options.c (set_Wall): Set warn_character_truncation if -Wall
> is set.
> * resolve.c (resolve_code): Warn if rhs string in character
> assignment has to be truncated.
> * array.c (gfc_resolve_character_array_constructor): Set new
> argument to true for call to gfc_set_constant_character_len.
>
> 2006-11-29 Paul Thomas <pault@gcc.gnu.org>
>
> PR fortran/27996
> PR fortran/27998
> * gfortran.dg/char_length_1.f90: New test.
>
> ------------------------------------------------------------------------
>
> Index: gcc/fortran/decl.c
> ===================================================================
> *** gcc/fortran/decl.c (revision 120260)
> --- gcc/fortran/decl.c (working copy)
> *************** build_sym (const char *name, gfc_charlen
> *** 743,749 ****
> truncated. */
>
> void
> ! gfc_set_constant_character_len (int len, gfc_expr * expr)
> {
> char * s;
> int slen;
> --- 743,749 ----
> truncated. */
>
> void
> ! gfc_set_constant_character_len (int len, gfc_expr * expr, bool array)
> {
> char * s;
> int slen;
> *************** gfc_set_constant_character_len (int len,
> *** 758,763 ****
> --- 758,775 ----
> memcpy (s, expr->value.character.string, MIN (len, slen));
> if (len > slen)
> memset (&s[slen], ' ', len - slen);
> +
> + if (gfc_option.warn_character_truncation && slen > len)
> + gfc_warning_now ("CHARACTER expression at %L is being truncated "
> + "(%d/%d)", &expr->where, slen, len);
> +
> + /* Apply the standard by 'hand' otherwise it gets cleared for
> + initializers. */
> + if (array && slen < len && !(gfc_option.allow_std & GFC_STD_GNU))
> + gfc_error_now ("The CHARACTER elements of the array constructor "
> + "at %L must have the same length (%d/%d)",
> + &expr->where, slen, len);
> +
> s[len] = '\0';
> gfc_free (expr->value.character.string);
> expr->value.character.string = s;
> *************** add_init_expr_to_sym (const char *name,
> *** 909,921 ****
> gfc_constructor * p;
>
> if (init->expr_type == EXPR_CONSTANT)
> ! gfc_set_constant_character_len (len, init);
> else if (init->expr_type == EXPR_ARRAY)
> {
> gfc_free_expr (init->ts.cl->length);
> init->ts.cl->length = gfc_copy_expr (sym->ts.cl->length);
> for (p = init->value.constructor; p; p = p->next)
> ! gfc_set_constant_character_len (len, p->expr);
> }
> }
> }
> --- 921,933 ----
> gfc_constructor * p;
>
> if (init->expr_type == EXPR_CONSTANT)
> ! gfc_set_constant_character_len (len, init, false);
> else if (init->expr_type == EXPR_ARRAY)
> {
> gfc_free_expr (init->ts.cl->length);
> init->ts.cl->length = gfc_copy_expr (sym->ts.cl->length);
> for (p = init->value.constructor; p; p = p->next)
> ! gfc_set_constant_character_len (len, p->expr, false);
> }
> }
> }
> *************** do_parm (void)
> *** 4025,4031 ****
> && init->ts.type == BT_CHARACTER
> && init->ts.kind == 1)
> gfc_set_constant_character_len (
> ! mpz_get_si (sym->ts.cl->length->value.integer), init);
>
> sym->value = init;
> return MATCH_YES;
> --- 4037,4043 ----
> && init->ts.type == BT_CHARACTER
> && init->ts.kind == 1)
> gfc_set_constant_character_len (
> ! mpz_get_si (sym->ts.cl->length->value.integer), init, false);
>
> sym->value = init;
> return MATCH_YES;
> Index: gcc/fortran/array.c
> ===================================================================
> *** gcc/fortran/array.c (revision 120260)
> --- gcc/fortran/array.c (working copy)
> *************** got_charlen:
> *** 1587,1593 ****
> /* Update the element constructors. */
> for (p = expr->value.constructor; p; p = p->next)
> if (p->expr->expr_type == EXPR_CONSTANT)
> ! gfc_set_constant_character_len (max_length, p->expr);
> }
> }
> }
> --- 1587,1593 ----
> /* Update the element constructors. */
> for (p = expr->value.constructor; p; p = p->next)
> if (p->expr->expr_type == EXPR_CONSTANT)
> ! gfc_set_constant_character_len (max_length, p->expr, true);
> }
> }
> }
> Index: gcc/fortran/gfortran.h
> ===================================================================
> *** gcc/fortran/gfortran.h (revision 120260)
> --- gcc/fortran/gfortran.h (working copy)
> *************** typedef struct
> *** 1637,1642 ****
> --- 1637,1643 ----
> int warn_surprising;
> int warn_tabs;
> int warn_underflow;
> + int warn_character_truncation;
> int max_errors;
>
> int flag_all_intrinsics;
> Index: gcc/fortran/resolve.c
> ===================================================================
> *** gcc/fortran/resolve.c (revision 120260)
> --- gcc/fortran/resolve.c (working copy)
> *************** resolve_code (gfc_code * code, gfc_names
> *** 4966,4971 ****
> --- 4966,4993 ----
> goto call;
> }
>
> + if (code->expr->ts.type == BT_CHARACTER
> + && gfc_option.warn_character_truncation)
> + {
> + int llen = 0, rlen = 0;
> + gfc_symbol *sym;
> + sym = code->expr->symtree->n.sym;
> + if (sym->ts.cl->length->expr_type == EXPR_CONSTANT)
> + llen = mpz_get_si (sym->ts.cl->length->value.integer);
> +
> + if (code->expr2->expr_type == EXPR_CONSTANT)
> + rlen = code->expr2->value.character.length;
> +
> + else if (code->expr2->ts.cl != NULL
> + && code->expr2->ts.cl->length != NULL
> + && code->expr2->ts.cl->length->expr_type == EXPR_CONSTANT)
> + rlen = mpz_get_si (code->expr2->ts.cl->length->value.integer);
> +
> + if (rlen && llen && rlen > llen)
> + gfc_warning_now ("rhs of CHARACTER assignment at %L will "
> + "be truncated (%d/%d)", &code->loc, rlen, llen);
> + }
> +
> if (gfc_pure (NULL))
> {
> if (gfc_impure_variable (code->expr->symtree->n.sym))
> Index: gcc/fortran/match.h
> ===================================================================
> *** gcc/fortran/match.h (revision 120260)
> --- gcc/fortran/match.h (working copy)
> *************** match gfc_match_derived_decl (void);
> *** 130,136 ****
> match gfc_match_implicit_none (void);
> match gfc_match_implicit (void);
>
> ! void gfc_set_constant_character_len (int, gfc_expr *);
>
> /* Matchers for attribute declarations */
> match gfc_match_allocatable (void);
> --- 130,136 ----
> match gfc_match_implicit_none (void);
> match gfc_match_implicit (void);
>
> ! void gfc_set_constant_character_len (int, gfc_expr *, bool);
>
> /* Matchers for attribute declarations */
> match gfc_match_allocatable (void);
> Index: gcc/fortran/options.c
> ===================================================================
> *** gcc/fortran/options.c (revision 120260)
> --- gcc/fortran/options.c (working copy)
> *************** set_Wall (void)
> *** 309,314 ****
> --- 309,315 ----
> gfc_option.warn_surprising = 1;
> gfc_option.warn_tabs = 0;
> gfc_option.warn_underflow = 1;
> + gfc_option.warn_character_truncation = 1;
>
> set_Wunused (1);
> warn_return_type = 1;
> Index: gcc/testsuite/gfortran.dg/char_length_1.f90
> ===================================================================
> *** gcc/testsuite/gfortran.dg/char_length_1.f90 (revision 0)
> --- gcc/testsuite/gfortran.dg/char_length_1.f90 (revision 0)
> ***************
> *** 0 ****
> --- 1,18 ----
> + ! { dg-do compile }
> + ! { dg-options "-Wall -std=f2003" }
> + ! Tests the patch for PR27996 and PR27998, in which warnings
> + ! or errors were not emitted when the length of character
> + ! constants was changed silently.
> + !
> + ! Contributed by Tobias Burnus <tobias.burnus@physik.fu-berlin.de>
> + !
> + program test
> + character(10) :: a(3)
> + character(10) :: b(3)= &
> + (/ 'Takata ', 'Tanaka', 'Hayashi' /) ! { dg-error "same length" }
> + character(4) :: c = "abcde" ! { dg-warning "being truncated" }
> + a = (/ 'Takata', 'Tanaka ', 'Hayashi' /) ! { dg-error "same length" }
> + a = (/ 'Takata ', 'Tanaka ', 'Hayashi' /)
> + b = "abc"
> + c = "abcdefg" ! { dg-warning "will be truncated" }
> + end program test
>
More information about the Fortran
mailing list