units of the actual argument up to the end of the array. */
static unsigned long
-get_expr_storage_size (gfc_expr *e, bool *size_known)
+get_expr_storage_size (gfc_expr *e, bool *size_known, long int *charlen)
{
int i;
long int strlen, elements;
gfc_ref *ref;
*size_known = false;
+ *charlen = -1;
if (e == NULL)
return 0;
strlen = e->value.character.length;
else
return 0;
+ *charlen = strlen;
}
else
strlen = 1; /* Length per element. */
gfc_formal_arglist *f;
int i, n, na;
unsigned long actual_size, formal_size;
+ long int charlen;
bool full_array = false;
gfc_array_ref *actual_arr_ref;
gfc_array_spec *fas, *aas;
if (a->expr->expr_type == EXPR_NULL && a->expr->ts.type == BT_UNKNOWN)
goto skip_size_check;
- actual_size = get_expr_storage_size (a->expr, &actual_size_known);
+ actual_size = get_expr_storage_size (a->expr, &actual_size_known, &charlen);
formal_size = get_sym_storage_size (f->sym, &formal_size_known);
+ /* If the formal is a scalar character variable, use the charlen of the
+ actual. */
+ if (actual_size_known && formal_size_known && charlen >= 0
+ && a->expr->ts.type == BT_CHARACTER
+ && f->sym->attr.flavor != FL_PROCEDURE
+ && !f->sym->attr.dimension)
+ actual_size = charlen;
+
if (actual_size_known && formal_size_known
&& actual_size != formal_size
&& a->expr->ts.type == BT_CHARACTER
--- /dev/null
+! { dg-do compile }
+! { dg-additional-options "-std=f2018 -Wcharacter-truncation" }
+!
+! PR fortran/125393 - checking of passed character length
+
+module test
+ implicit none
+contains
+
+ subroutine a(string)
+ character(len=2) string
+ end subroutine a
+
+ subroutine b
+ character(len=2) :: s1
+ character(len=2), dimension(2) :: s2
+ character(len=1) :: s3(2)
+ character(len=4) :: s4
+ call a(s1)
+ call a(s1(1:2))
+ call a(s2(1)) ! This gave a bogus warning
+ call a(s2(1)(1:2))
+ call a(s3(1)) ! { dg-error "Character length of actual argument shorter" }
+ call a(s4(1:2))
+ call a(c1()) ! { dg-error "Character length of actual argument shorter" }
+ call a(c2())
+ call a(c3()) ! { dg-warning "Character length of actual argument longer" }
+ end subroutine b
+
+ function c1 ()
+ character(len=1) :: c1
+ c1 = "a"
+ end function c1
+
+ function c2 ()
+ character(len=2) :: c2
+ c2 = "ab"
+ end function c2
+
+ function c3 ()
+ character(len=3) :: c3
+ c3 = "abc"
+ end function c3
+
+end module test