Blame SOURCES/0013-Allow-per-variable-kind-specification.patch

2985e0
From 72d3915eadd1121d8b2f0be04fafc17e9232be81 Mon Sep 17 00:00:00 2001
2985e0
From: Jim MacArthur <jim.macarthur@codethink.co.uk>
2985e0
Date: Thu, 5 Nov 2015 18:57:53 +0000
2985e0
Subject: [PATCH 13/23] Allow per-variable kind specification.
2985e0
2985e0
      INTEGER*4 x*2, y*8
2985e0
2985e0
The per-variable sizes override the kind specified in the type.
2985e0
At the moment, you can follow this with an array specification, so
2985e0
INTEGER x*2(10) is OK, but not the other way round.
2985e0
2985e0
This feature is enabled by the `-std=extra-legacy` compiler flag.
2985e0
---
2985e0
2985e0
    0013-Allow-per-variable-kind-specification.patch
2985e0
2985e0
    Allow per-variable kind specification.
2985e0
    
2985e0
          INTEGER*4 x*2, y*8
2985e0
    
2985e0
    The per-variable sizes override the kind specified in the type.
2985e0
    At the moment, you can follow this with an array specification, so
2985e0
    INTEGER x*2(10) is OK, but not the other way round.
2985e0
    
2985e0
    This feature is enabled by the `-std=extra-legacy` compiler flag.
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 3ad9c2c8b40..faa08d9c4bb 100644
2985e0
--- a/gcc/fortran/decl.c
2985e0
+++ b/gcc/fortran/decl.c
2985e0
@@ -1019,6 +1019,24 @@ syntax:
2985e0
   return MATCH_ERROR;
2985e0
 }
2985e0
 
2985e0
+/* This matches the nonstandard kind given after a variable name, like:
2985e0
+   INTEGER x*2, y*4
2985e0
+   The per-variable kind will override any kind given in the type
2985e0
+   declaration.
2985e0
+*/
2985e0
+
2985e0
+static match
2985e0
+match_per_symbol_kind (int *length)
2985e0
+{
2985e0
+  match m;
2985e0
+
2985e0
+  m = gfc_match_char ('*');
2985e0
+  if (m != MATCH_YES)
2985e0
+    return m;
2985e0
+
2985e0
+  m = gfc_match_small_literal_int (length, NULL);
2985e0
+  return m;
2985e0
+}
2985e0
 
2985e0
 /* Special subroutine for finding a symbol.  Check if the name is found
2985e0
    in the current name space.  If not, and we're compiling a function or
2985e0
@@ -2193,10 +2211,13 @@ variable_decl (int elem)
2985e0
   bool t;
2985e0
   gfc_symbol *sym;
2985e0
   match cl_match;
2985e0
+  match kind_match;
2985e0
+  int overridden_kind;
2985e0
 
2985e0
   initializer = NULL;
2985e0
   as = NULL;
2985e0
   cp_as = NULL;
2985e0
+  kind_match = MATCH_NO;
2985e0
 
2985e0
   /* When we get here, we've just matched a list of attributes and
2985e0
      maybe a type and a double colon.  The next thing we expect to see
2985e0
@@ -2213,12 +2234,20 @@ variable_decl (int elem)
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
+  if (gfc_option.allow_std & GFC_STD_EXTRA_LEGACY)
2985e0
     {
2985e0
-      cl_match = match_character_length_clause (&cl, &cl_deferred, elem);
2985e0
-      if (cl_match == MATCH_ERROR)
2985e0
-	goto cleanup;
2985e0
+      if (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
+      else
2985e0
+	{
2985e0
+	  kind_match = match_per_symbol_kind (&overridden_kind);
2985e0
+	  if (kind_match == MATCH_ERROR)
2985e0
+	    goto cleanup;
2985e0
+	}
2985e0
     }
2985e0
 
2985e0
   /* Now we could see the optional array spec. or character length.  */
2985e0
@@ -2412,6 +2441,13 @@ variable_decl (int elem)
2985e0
       goto cleanup;
2985e0
     }
2985e0
 
2985e0
+  if (kind_match == MATCH_YES)
2985e0
+    {
2985e0
+      gfc_find_symbol (name, gfc_current_ns, 1, &sym);
2985e0
+      /* sym *must* be found at this point */
2985e0
+      sym->ts.kind = overridden_kind;
2985e0
+    }
2985e0
+
2985e0
   if (!check_function_name (name))
2985e0
     {
2985e0
       m = MATCH_ERROR;
2985e0
diff --git a/gcc/testsuite/gfortran.dg/dec_spec_in_variable.f b/gcc/testsuite/gfortran.dg/dec_spec_in_variable.f
2985e0
new file mode 100644
2985e0
index 00000000000..0341a176aca
2985e0
--- /dev/null
2985e0
+++ b/gcc/testsuite/gfortran.dg/dec_spec_in_variable.f
2985e0
@@ -0,0 +1,12 @@
2985e0
+! { dg-do compile }
2985e0
+! { dg-options "-std=extra-legacy" }
2985e0
+!
2985e0
+! Test kind specification in variable not in type
2985e0
+!
2985e0
+        PROGRAM spec_in_var
2985e0
+          INTEGER  ai*1/1/
2985e0
+          REAL ar*4/1.0/
2985e0
+
2985e0
+          if(ai.NE.1) STOP 1
2985e0
+          if(abs(ar - 1.0) > 1.0D-6) STOP 2
2985e0
+        END