PR fortran/36517, fortran/36492
authorDaniel Kraft <d@domob.eu>
Wed, 18 Jun 2008 13:53:32 +0000 (15:53 +0200)
committerDaniel Kraft <domob@gcc.gnu.org>
Wed, 18 Jun 2008 13:53:32 +0000 (15:53 +0200)
2008-06-18  Daniel Kraft  <d@domob.eu>

PR fortran/36517, fortran/36492
* gfortran.dg/array_constructor_25.f03:  New test.
* gfortran.dg/array_constructor_26.f03:  New test.
* gfortran.dg/array_constructor_27.f03:  New test.
* gfortran.dg/array_constructor_28.f03:  New test.
* gfortran.dg/array_constructor_29.f03:  New test.
* gfortran.dg/array_constructor_30.f03:  New test.
* gfortran.dg/array_constructor_type_19.f03:  New test.
* gfortran.dg/array_constructor_type_20.f03:  New test.
* gfortran.dg/array_constructor_type_21.f03:  New test.

2008-06-18  Daniel Kraft  <d@domob.eu>

PR fortran/36517, fortran/36492
* array.c (gfc_resolve_character_array_constructor):  Call
gfc_set_constant_character_len with changed length-chec argument.
* decl.c (gfc_set_constant_character_len):  Changed array argument to
be a generic length-checking argument that can be used for correct
checking with typespec and in special cases where the should-be length
is different from the target length.
(build_struct):  Call gfc_set_constant_character_len with changed length
checking argument and introduced additional checks for exceptional
conditions on invalid code.
(add_init_expr_to_sym), (do_parm):  Call gfc_set_constant_character_len
with changed argument.
* match.h (gfc_set_constant_character_len):  Changed third argument to
int for the should-be length rather than bool.

From-SVN: r136894

14 files changed:
gcc/fortran/ChangeLog
gcc/fortran/array.c
gcc/fortran/decl.c
gcc/fortran/match.h
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/array_constructor_25.f03 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/array_constructor_26.f03 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/array_constructor_27.f03 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/array_constructor_28.f03 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/array_constructor_29.f03 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/array_constructor_30.f03 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/array_constructor_type_19.f03 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/array_constructor_type_20.f03 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/array_constructor_type_21.f03 [new file with mode: 0644]

index e83c3cb0c959f8c32890bc9ed8789b6910c5b082..6362039389877bd9fd45939f06a45b30d11f51db 100644 (file)
@@ -1,3 +1,20 @@
+2008-06-18  Daniel Kraft  <d@domob.eu>
+
+       PR fortran/36517, fortran/36492
+       * array.c (gfc_resolve_character_array_constructor):  Call
+       gfc_set_constant_character_len with changed length-chec argument.
+       * decl.c (gfc_set_constant_character_len):  Changed array argument to
+       be a generic length-checking argument that can be used for correct
+       checking with typespec and in special cases where the should-be length
+       is different from the target length.
+       (build_struct):  Call gfc_set_constant_character_len with changed length
+       checking argument and introduced additional checks for exceptional
+       conditions on invalid code.
+       (add_init_expr_to_sym), (do_parm):  Call gfc_set_constant_character_len
+       with changed argument.
+       * match.h (gfc_set_constant_character_len):  Changed third argument to
+       int for the should-be length rather than bool.
+
 2008-06-17  Daniel Kraft  <d@domob.eu>
 
        PR fortran/36112
index 73b78c3f2fcebe08ec65cd200165637ba85a92b4..a34695e42419607ee6596aaf7aa5e31ce9d57bf0 100644 (file)
@@ -1680,25 +1680,29 @@ got_charlen:
         (without typespec) all elements are verified to have the same length
         anyway.  */
       if (found_length != -1)
-        for (p = expr->value.constructor; p; p = p->next)
-          if (p->expr->expr_type == EXPR_CONSTANT)
-            {
-              gfc_expr *cl = NULL;
-              int current_length = -1;
-
-              if (p->expr->ts.cl && p->expr->ts.cl->length)
-              {
-                cl = p->expr->ts.cl->length;
-                gfc_extract_int (cl, &current_length);
-              }
-
-              /* If gfc_extract_int above set current_length, we implicitly
-                 know the type is BT_INTEGER and it's EXPR_CONSTANT.  */
-
-              if (! cl
-                  || (current_length != -1 && current_length < found_length))
-                gfc_set_constant_character_len (found_length, p->expr, true);
-            }
+       for (p = expr->value.constructor; p; p = p->next)
+         if (p->expr->expr_type == EXPR_CONSTANT)
+           {
+             gfc_expr *cl = NULL;
+             int current_length = -1;
+             bool has_ts;
+
+             if (p->expr->ts.cl && p->expr->ts.cl->length)
+             {
+               cl = p->expr->ts.cl->length;
+               gfc_extract_int (cl, &current_length);
+             }
+
+             /* If gfc_extract_int above set current_length, we implicitly
+                know the type is BT_INTEGER and it's EXPR_CONSTANT.  */
+
+             has_ts = (expr->ts.cl && expr->ts.cl->length_from_typespec);
+
+             if (! cl
+                 || (current_length != -1 && current_length < found_length))
+               gfc_set_constant_character_len (found_length, p->expr,
+                                               has_ts ? -1 : found_length);
+           }
     }
 
   return SUCCESS;
index a1c7d5aa44e4bb906aa7544b754c405becbe7c38..57db93fd8e1e289590aa1e390468945f2fc3b44e 100644 (file)
@@ -1084,10 +1084,12 @@ build_sym (const char *name, gfc_charlen *cl,
 
 
 /* Set character constant to the given length. The constant will be padded or
-   truncated.  */
+   truncated.  If we're inside an array constructor without a typespec, we
+   additionally check that all elements have the same length; check_len -1
+   means no checking.  */
 
 void
-gfc_set_constant_character_len (int len, gfc_expr *expr, bool array)
+gfc_set_constant_character_len (int len, gfc_expr *expr, int check_len)
 {
   gfc_char_t *s;
   int slen;
@@ -1110,10 +1112,11 @@ gfc_set_constant_character_len (int len, gfc_expr *expr, bool array)
 
       /* Apply the standard by 'hand' otherwise it gets cleared for
         initializers.  */
-      if (array && slen < len && !(gfc_option.allow_std & GFC_STD_GNU))
+      if (check_len != -1 && slen != check_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);
+                       &expr->where, slen, check_len);
 
       s[len] = '\0';
       gfc_free (expr->value.character.string);
@@ -1269,7 +1272,7 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
              gfc_constructor * p;
 
              if (init->expr_type == EXPR_CONSTANT)
-               gfc_set_constant_character_len (len, init, false);
+               gfc_set_constant_character_len (len, init, -1);
              else if (init->expr_type == EXPR_ARRAY)
                {
                  /* Build a new charlen to prevent simplification from
@@ -1280,7 +1283,7 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
                  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);
+                   gfc_set_constant_character_len (len, p->expr, -1);
                }
            }
        }
@@ -1402,19 +1405,48 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
 
   /* Should this ever get more complicated, combine with similar section
      in add_init_expr_to_sym into a separate function.  */
-  if (c->ts.type == BT_CHARACTER && !c->pointer && c->initializer)
+  if (c->ts.type == BT_CHARACTER && !c->pointer && c->initializer && c->ts.cl
+      && c->ts.cl->length && c->ts.cl->length->expr_type == EXPR_CONSTANT)
     {
-      int len = mpz_get_si (c->ts.cl->length->value.integer);
+      int len;
+
+      gcc_assert (c->ts.cl && c->ts.cl->length);
+      gcc_assert (c->ts.cl->length->expr_type == EXPR_CONSTANT);
+      gcc_assert (c->ts.cl->length->ts.type == BT_INTEGER);
+
+      len = mpz_get_si (c->ts.cl->length->value.integer);
 
       if (c->initializer->expr_type == EXPR_CONSTANT)
-       gfc_set_constant_character_len (len, c->initializer, false);
+       gfc_set_constant_character_len (len, c->initializer, -1);
       else if (mpz_cmp (c->ts.cl->length->value.integer,
                        c->initializer->ts.cl->length->value.integer))
        {
+         bool has_ts;
          gfc_constructor *ctor = c->initializer->value.constructor;
-         for (;ctor ; ctor = ctor->next)
-           if (ctor->expr->expr_type == EXPR_CONSTANT)
-             gfc_set_constant_character_len (len, ctor->expr, true);
+
+         bool first = true;
+         int first_len;
+
+         has_ts = (c->initializer->ts.cl
+                   && c->initializer->ts.cl->length_from_typespec);
+
+         for (; ctor; ctor = ctor->next)
+           {
+             /* Remember the length of the first element for checking that
+                all elements *in the constructor* have the same length.  This
+                need not be the length of the LHS!  */
+             if (first)
+               {
+                 gcc_assert (ctor->expr->expr_type == EXPR_CONSTANT);
+                 gcc_assert (ctor->expr->ts.type == BT_CHARACTER);
+                 first_len = ctor->expr->value.character.length;
+                 first = false;
+               }
+
+             if (ctor->expr->expr_type == EXPR_CONSTANT)
+               gfc_set_constant_character_len (len, ctor->expr,
+                                               has_ts ? -1 : first_len);
+           }
        }
     }
 
@@ -5822,7 +5854,7 @@ do_parm (void)
       && init->expr_type == EXPR_CONSTANT
       && init->ts.type == BT_CHARACTER)
     gfc_set_constant_character_len (
-      mpz_get_si (sym->ts.cl->length->value.integer), init, false);
+      mpz_get_si (sym->ts.cl->length->value.integer), init, -1);
   else if (sym->ts.type == BT_CHARACTER && sym->ts.cl != NULL
           && sym->ts.cl->length == NULL)
        {
index 5ee91fb62dec8aff731c35a6bc09960fbe147dce..cf30b2730dc143854318104eb9030d36c5c0a541 100644 (file)
@@ -147,7 +147,7 @@ match gfc_match_final_decl (void);
 match gfc_match_implicit_none (void);
 match gfc_match_implicit (void);
 
-void gfc_set_constant_character_len (int, gfc_expr *, bool);
+void gfc_set_constant_character_len (int, gfc_expr *, int);
 
 /* Matchers for attribute declarations.  */
 match gfc_match_allocatable (void);
index 8b2d63c2979c8feb3538884375c9d35f16b09948..ff03e2f966802e86fe206c6c76e2edcd231b5bc1 100644 (file)
@@ -1,3 +1,16 @@
+2008-06-18  Daniel Kraft  <d@domob.eu>
+
+       PR fortran/36517, fortran/36492
+       * gfortran.dg/array_constructor_25.f03:  New test.
+       * gfortran.dg/array_constructor_26.f03:  New test.
+       * gfortran.dg/array_constructor_27.f03:  New test.
+       * gfortran.dg/array_constructor_28.f03:  New test.
+       * gfortran.dg/array_constructor_29.f03:  New test.
+       * gfortran.dg/array_constructor_30.f03:  New test.
+       * gfortran.dg/array_constructor_type_19.f03:  New test.
+       * gfortran.dg/array_constructor_type_20.f03:  New test.
+       * gfortran.dg/array_constructor_type_21.f03:  New test.
+
 2008-06-17  Daniel Kraft  <d@domob.eu>
 
        PR fortran/36112
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_25.f03 b/gcc/testsuite/gfortran.dg/array_constructor_25.f03
new file mode 100644 (file)
index 0000000..b187468
--- /dev/null
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-options "-std=f2003" }
+
+! PR fortran/36492
+! Check for incorrect error message with -std=f2003.
+! Reduced test based on the one from comment #4, PR 36492.
+
+type t
+  character (2) :: arr (1) = [ "a" ]
+end type t
+
+end
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_26.f03 b/gcc/testsuite/gfortran.dg/array_constructor_26.f03
new file mode 100644 (file)
index 0000000..a226f6a
--- /dev/null
@@ -0,0 +1,18 @@
+! { dg-do compile }
+
+! PR fortran/36492
+! Check for incorrect error message with -std=f2003.
+! Test from comment #4, PR 36492 causing ICE.
+
+MODULE WinData
+  IMPLICIT NONE
+  INTEGER (1), PARAMETER :: MAXFLD = 25_1, MAXHED = 5_1, MAXCHR = 80_1
+  integer :: i
+  TYPE TWindowData
+    CHARACTER (MAX_FLD_HED, 1) :: DWFdHd(MAXFLD) = [(" ", i = 1, MAXFLD)]
+    ! { dg-error "no IMPLICIT type" "" { target *-*-* } 12 }
+    ! { dg-error "specification expression" "" { target *-*-* } 12 }
+  END TYPE TWindowData
+END MODULE WinData
+
+! { dg-final { cleanup-modules "WinData" } }
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_27.f03 b/gcc/testsuite/gfortran.dg/array_constructor_27.f03
new file mode 100644 (file)
index 0000000..6cd4d62
--- /dev/null
@@ -0,0 +1,15 @@
+! { dg-do compile }
+
+! PR fortran/36492
+! Check for incorrect error message with -std=f2003.
+! Reduced test triggering the ICE mentioned in comment #4, PR 36492.
+
+implicit none
+
+type t
+  character (a) :: arr (1) = [ "a" ]
+  ! { dg-error "no IMPLICIT type" "" { target *-*-* } 10 }
+  ! { dg-error "specification expression" "" { target *-*-* } 10 }
+end type t
+
+end
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_28.f03 b/gcc/testsuite/gfortran.dg/array_constructor_28.f03
new file mode 100644 (file)
index 0000000..382e49a
--- /dev/null
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "-std=f2003" }
+
+! PR fortran/36492
+! Check that the error is still emitted for really incorrect constructor.
+
+type t
+  character (2) :: arr (2) = [ "a", "ab" ] ! { dg-error "Different CHARACTER" }
+end type t
+
+end
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_29.f03 b/gcc/testsuite/gfortran.dg/array_constructor_29.f03
new file mode 100644 (file)
index 0000000..03534fa
--- /dev/null
@@ -0,0 +1,13 @@
+! { dg-do compile }
+
+! PR fortran/36492
+! Similar to the ICE-test, but now test it works for real constants.
+
+implicit none
+
+integer, parameter :: a = 42
+type t
+  character (a) :: arr (1) = [ "a" ]
+end type t
+
+end
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_30.f03 b/gcc/testsuite/gfortran.dg/array_constructor_30.f03
new file mode 100644 (file)
index 0000000..587ce03
--- /dev/null
@@ -0,0 +1,16 @@
+! { dg-do compile }
+
+! PR fortran/36492
+! Similar to the ICE-test, but now test for complaint about constant
+! specification expression.
+
+implicit none
+
+integer :: a = 42
+type t
+  character (a) :: arr (1) = [ "a" ]
+  ! { dg-error "in the expression" "" { target *-*-* } 11 }
+  ! { dg-error "specification expression" "" { target *-*-* } 11 }
+end type t
+
+end
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_type_19.f03 b/gcc/testsuite/gfortran.dg/array_constructor_type_19.f03
new file mode 100644 (file)
index 0000000..f3c8fd5
--- /dev/null
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! { dg-options "-std=f2003" }
+
+! PR fortran/36517
+! Check for incorrect error message with -std=f2003.
+! This is the test of comment #1, PR 36517.
+
+print *, [ character(len=2) :: 'a', 'bb' ]
+end
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_type_20.f03 b/gcc/testsuite/gfortran.dg/array_constructor_type_20.f03
new file mode 100644 (file)
index 0000000..9702669
--- /dev/null
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "-std=f2003" }
+
+! PR fortran/36517
+! Check for incorrect error message with -std=f2003.
+! This is the original test from PR 36517.
+
+CHARACTER (len=*) MY_STRING(1:3)
+PARAMETER ( MY_STRING = (/ CHARACTER (len=3) :: "AC", "B", "C" /) )
+CHARACTER (len=*), PARAMETER :: str(2) = [ CHARACTER (len=3) :: 'A', 'cc' ]
+END
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_type_21.f03 b/gcc/testsuite/gfortran.dg/array_constructor_type_21.f03
new file mode 100644 (file)
index 0000000..41e4da3
--- /dev/null
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "-std=f2003" }
+
+! PR fortran/36492
+! Check that it works with a typespec even for not-the-same-length elements.
+
+type t
+  character (1) :: arr (2) = [ character(len=2) :: "a", "ab" ]
+end type t
+
+end