Blame SOURCES/0010-Allow-mixed-string-length-and-array-specification-in.patch

2985e0
From e4c3d25a9133224535b3142ed31e8a8be1ad356b Mon Sep 17 00:00:00 2001
2985e0
From: Jim MacArthur <jim.macarthur@codethink.co.uk>
2985e0
Date: Wed, 7 Oct 2015 17:04:06 -0400
2985e0
Subject: [PATCH 10/23] Allow mixed string length and array specification in
2985e0
 character declarations.
2985e0
2985e0
---
2985e0
2985e0
        0010-Allow-mixed-string-length-and-array-specification-in.patch
2985e0
2985e0
commit 05124ea7df2ee14620d5c24ffe972db3dcab4f4e
2985e0
Author: Jim MacArthur <jim.macarthur@codethink.co.uk>
2985e0
Date:   Wed Oct 7 17:04:06 2015 -0400
2985e0
2985e0
    Allow mixed string length and array specification in character declarations.
2985e0
    
2985e0
    Test written by: Francisco Redondo Marchena <francisco.marchena@codethink.co.uk>
2985e0
2985e0
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
2985e0
index 6d3d28af127..c90f9de5a78 100644
2985e0
--- a/gcc/fortran/decl.c
2985e0
+++ b/gcc/fortran/decl.c
2985e0
@@ -2264,6 +2264,35 @@ check_function_name (char *name)
2985e0
 }
2985e0
 
2985e0
 
2985e0
+static match
2985e0
+match_character_length_clause (gfc_charlen **cl, bool *cl_deferred, int elem)
2985e0
+{
2985e0
+  gfc_expr* char_len;
2985e0
+  char_len = NULL;
2985e0
+
2985e0
+  match m = match_char_length (&char_len, cl_deferred, false);
2985e0
+  if (m == MATCH_YES)
2985e0
+    {
2985e0
+      *cl = gfc_new_charlen (gfc_current_ns, NULL);
2985e0
+      (*cl)->length = char_len;
2985e0
+    }
2985e0
+  else if (m == MATCH_NO)
2985e0
+    {
2985e0
+      if (elem > 1
2985e0
+	  && (current_ts.u.cl->length == NULL
2985e0
+	      || current_ts.u.cl->length->expr_type != EXPR_CONSTANT))
2985e0
+	{
2985e0
+	  *cl = gfc_new_charlen (gfc_current_ns, NULL);
2985e0
+	  (*cl)->length = gfc_copy_expr (current_ts.u.cl->length);
2985e0
+	}
2985e0
+      else
2985e0
+      *cl = current_ts.u.cl;
2985e0
+
2985e0
+      *cl_deferred = current_ts.deferred;
2985e0
+    }
2985e0
+  return m;
2985e0
+}
2985e0
+
2985e0
 /* Match a variable name with an optional initializer.  When this
2985e0
    subroutine is called, a variable is expected to be parsed next.
2985e0
    Depending on what is happening at the moment, updates either the
2985e0
@@ -2274,7 +2303,7 @@ variable_decl (int elem)
2985e0
 {
2985e0
   char name[GFC_MAX_SYMBOL_LEN + 1];
2985e0
   static unsigned int fill_id = 0;
2985e0
-  gfc_expr *initializer, *char_len;
2985e0
+  gfc_expr *initializer;
2985e0
   gfc_array_spec *as;
2985e0
   gfc_array_spec *cp_as; /* Extra copy for Cray Pointees.  */
2985e0
   gfc_charlen *cl;
2985e0
@@ -2283,6 +2312,7 @@ variable_decl (int elem)
2985e0
   match m;
2985e0
   bool t;
2985e0
   gfc_symbol *sym;
2985e0
+  match cl_match;
2985e0
 
2985e0
   initializer = NULL;
2985e0
   as = NULL;
2985e0
@@ -2335,6 +2365,20 @@ variable_decl (int elem)
2985e0
 
2985e0
   var_locus = gfc_current_locus;
2985e0
 
2985e0
+
2985e0
+  cl = NULL;
2985e0
+  cl_deferred = false;
2985e0
+  cl_match = MATCH_NO;
2985e0
+
2985e0
+  /* Check for a character length clause before an array clause */
2985e0
+  if ((gfc_option.allow_std & GFC_STD_EXTRA_LEGACY)
2985e0
+      && current_ts.type == BT_CHARACTER)
2985e0
+    {
2985e0
+      cl_match = match_character_length_clause (&cl, &cl_deferred, elem);
2985e0
+      if (cl_match == MATCH_ERROR)
2985e0
+	goto cleanup;
2985e0
+    }
2985e0
+
2985e0
   /* Now we could see the optional array spec. or character length.  */
2985e0
   m = gfc_match_array_spec (&as, true, true);
2985e0
   if (m == MATCH_ERROR)
2985e0
@@ -2453,40 +2497,12 @@ variable_decl (int elem)
2985e0
 	}
2985e0
     }
2985e0
 
2985e0
-  char_len = NULL;
2985e0
-  cl = NULL;
2985e0
-  cl_deferred = false;
2985e0
-
2985e0
-  if (current_ts.type == BT_CHARACTER)
2985e0
+  /* Second chance for a character length clause */
2985e0
+  if (cl_match == MATCH_NO && current_ts.type == BT_CHARACTER)
2985e0
     {
2985e0
-      switch (match_char_length (&char_len, &cl_deferred, false))
2985e0
-	{
2985e0
-	case MATCH_YES:
2985e0
-	  cl = gfc_new_charlen (gfc_current_ns, NULL);
2985e0
-
2985e0
-	  cl->length = char_len;
2985e0
-	  break;
2985e0
-
2985e0
-	/* Non-constant lengths need to be copied after the first
2985e0
-	   element.  Also copy assumed lengths.  */
2985e0
-	case MATCH_NO:
2985e0
-	  if (elem > 1
2985e0
-	      && (current_ts.u.cl->length == NULL
2985e0
-		  || current_ts.u.cl->length->expr_type != EXPR_CONSTANT))
2985e0
-	    {
2985e0
-	      cl = gfc_new_charlen (gfc_current_ns, NULL);
2985e0
-	      cl->length = gfc_copy_expr (current_ts.u.cl->length);
2985e0
-	    }
2985e0
-	  else
2985e0
-	    cl = current_ts.u.cl;
2985e0
-
2985e0
-	  cl_deferred = current_ts.deferred;
2985e0
-
2985e0
-	  break;
2985e0
-
2985e0
-	case MATCH_ERROR:
2985e0
-	  goto cleanup;
2985e0
-	}
2985e0
+      m = match_character_length_clause( &cl, &cl_deferred, elem );
2985e0
+      if (m == MATCH_ERROR)
2985e0
+	goto cleanup;
2985e0
     }
2985e0
 
2985e0
   /* The dummy arguments and result of the abreviated form of MODULE
2985e0
diff --git a/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration.f b/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration.f
2985e0
new file mode 100644
2985e0
index 00000000000..69b110edb25
2985e0
--- /dev/null
2985e0
+++ b/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration.f
2985e0
@@ -0,0 +1,10 @@
2985e0
+! { dg-do compile }
2985e0
+! { dg-options "-std=extra-legacy" }
2985e0
+!
2985e0
+! Test character declaration with mixed string length and array specification
2985e0
+!
2985e0
+        PROGRAM character_declaration
2985e0
+          CHARACTER ASPEC_SLENGTH*2 (5) /'01','02','03','04','05'/
2985e0
+          CHARACTER SLENGTH_ASPEC(5)*2 /'01','02','03','04','05'/
2985e0
+          if (ASPEC_SLENGTH(3).NE.SLENGTH_ASPEC(3)) STOP 1
2985e0
+        END