From e7333b691a8ec1d1bfb0e8ea1c8702a869e87232 Mon Sep 17 00:00:00 2001
From: Janus Weil <janus@gcc.gnu.org>
Date: Fri, 31 May 2013 10:09:09 +0200
Subject: re PR fortran/54190 (TYPE(*)/assumed-rank: Type/rank check too
 relaxed for dummy procedure)

2013-05-31  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/54190
	PR fortran/57217
	* gfortran.h (gfc_terminal_width): Remove prototype.
	* error.c (get_terminal_width): Moved here from misc.c. Renamed.
	Try to determine terminal width from environment variable.
	* interface.c (compare_type, compare_rank): New functions. Fix assumed
	type/rank handling.
	(compare_type_rank, check_dummy_characteristics,
	check_result_characteristics, gfc_compare_interfaces): Use them.
	(symbol_rank): Slightly modified and moved.
	* misc.c (gfc_terminal_width): Moved to error.c.


2013-05-31  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/54190
	PR fortran/57217
	* gfortran.dg/dummy_procedure_5.f90: Modified error message.
	* gfortran.dg/interface_26.f90: Ditto.
	* gfortran.dg/proc_ptr_11.f90: Ditto.
	* gfortran.dg/proc_ptr_15.f90: Ditto.
	* gfortran.dg/proc_ptr_comp_20.f90: Ditto.
	* gfortran.dg/proc_ptr_comp_33.f90: Ditto.
	* gfortran.dg/proc_ptr_result_5.f90: Ditto.
	* gfortran.dg/typebound_override_1.f90: Ditto.
	* gfortran.dg/typebound_override_4.f90: Ditto.
	* gfortran.dg/typebound_proc_6.f03: Ditto.
	* gfortran.dg/assumed_type_7.f90: New test.
	* gfortran.dg/typebound_override_5.f90: New test.
	* gfortran.dg/typebound_override_6.f90: New test.
	* gfortran.dg/typebound_override_7.f90: New test.

From-SVN: r199475
---
 gcc/fortran/ChangeLog   |  14 +++++++
 gcc/fortran/error.c     |  17 +++++++-
 gcc/fortran/gfortran.h  |   1 -
 gcc/fortran/interface.c | 106 +++++++++++++++++++++++++++++++++---------------
 gcc/fortran/misc.c      |   9 ----
 5 files changed, 103 insertions(+), 44 deletions(-)

(limited to 'gcc/fortran')

diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index af467b6..db8d1d0 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,17 @@
+2013-05-31  Janus Weil  <janus@gcc.gnu.org>
+
+	PR fortran/54190
+	PR fortran/57217
+	* gfortran.h (gfc_terminal_width): Remove prototype.
+	* error.c (get_terminal_width): Moved here from misc.c. Renamed.
+	Try to determine terminal width from environment variable.
+	* interface.c (compare_type, compare_rank): New functions. Fix assumed
+	type/rank handling.
+	(compare_type_rank, check_dummy_characteristics,
+	check_result_characteristics, gfc_compare_interfaces): Use them.
+	(symbol_rank): Slightly modified and moved.
+	* misc.c (gfc_terminal_width): Moved to error.c.
+
 2013-05-30  Janus Weil  <janus@gcc.gnu.org>
 
 	PR fortran/54189
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index 60b2093..ee0dea0 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -59,12 +59,27 @@ gfc_pop_suppress_errors (void)
 }
 
 
+static int
+get_terminal_width (void)
+{
+  const char *p = getenv ("COLUMNS");
+  if (p)
+    {
+      int value = atoi (p);
+      if (value > 0)
+	return value;
+    }
+  /* Use a reasonable default.  */
+  return 80;
+}
+
+
 /* Per-file error initialization.  */
 
 void
 gfc_error_init_1 (void)
 {
-  terminal_width = gfc_terminal_width ();
+  terminal_width = get_terminal_width ();
   errors = 0;
   warnings = 0;
   buffer_flag = 0;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 27662f7..14da0af 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2436,7 +2436,6 @@ void gfc_start_source_files (void);
 void gfc_end_source_files (void);
 
 /* misc.c */
-int gfc_terminal_width (void);
 void gfc_clear_ts (gfc_typespec *);
 FILE *gfc_open_file (const char *);
 const char *gfc_basic_typename (bt);
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index adc4e63..f06ecfe 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -508,18 +508,23 @@ gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2)
 }
 
 
-/* Given two symbols that are formal arguments, compare their ranks
-   and types.  Returns nonzero if they have the same rank and type,
-   zero otherwise.  */
+static int
+compare_type (gfc_symbol *s1, gfc_symbol *s2)
+{
+  if (s2->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
+    return 1;
+
+  return gfc_compare_types (&s1->ts, &s2->ts) || s2->ts.type == BT_ASSUMED;
+}
+
 
 static int
-compare_type_rank (gfc_symbol *s1, gfc_symbol *s2)
+compare_rank (gfc_symbol *s1, gfc_symbol *s2)
 {
   gfc_array_spec *as1, *as2;
   int r1, r2;
 
-  if (s1->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK)
-      || s2->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
+  if (s2->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
     return 1;
 
   as1 = (s1->ts.type == BT_CLASS) ? CLASS_DATA (s1)->as : s1->as;
@@ -528,13 +533,21 @@ compare_type_rank (gfc_symbol *s1, gfc_symbol *s2)
   r1 = as1 ? as1->rank : 0;
   r2 = as2 ? as2->rank : 0;
 
-  if (r1 != r2
-      && (!as1 || as1->type != AS_ASSUMED_RANK)
-      && (!as2 || as2->type != AS_ASSUMED_RANK))
+  if (r1 != r2 && (!as2 || as2->type != AS_ASSUMED_RANK))
     return 0;			/* Ranks differ.  */
 
-  return gfc_compare_types (&s1->ts, &s2->ts)
-	 || s1->ts.type == BT_ASSUMED || s2->ts.type == BT_ASSUMED;
+  return 1;
+}
+
+
+/* Given two symbols that are formal arguments, compare their ranks
+   and types.  Returns nonzero if they have the same rank and type,
+   zero otherwise.  */
+
+static int
+compare_type_rank (gfc_symbol *s1, gfc_symbol *s2)
+{
+  return compare_type (s1, s2) && compare_rank (s1, s2);
 }
 
 
@@ -1019,6 +1032,15 @@ generic_correspondence (gfc_formal_arglist *f1, gfc_formal_arglist *f2,
 }
 
 
+static int
+symbol_rank (gfc_symbol *sym)
+{
+  gfc_array_spec *as;
+  as = (sym->ts.type == BT_CLASS) ? CLASS_DATA (sym)->as : sym->as;
+  return as ? as->rank : 0;
+}
+
+
 /* Check if the characteristics of two dummy arguments match,
    cf. F08:12.3.2.  */
 
@@ -1030,12 +1052,20 @@ check_dummy_characteristics (gfc_symbol *s1, gfc_symbol *s2,
     return s1 == s2 ? true : false;
 
   /* Check type and rank.  */
-  if (type_must_agree &&
-      (!compare_type_rank (s1, s2) || !compare_type_rank (s2, s1)))
+  if (type_must_agree)
     {
-      snprintf (errmsg, err_len, "Type/rank mismatch in argument '%s'",
-		s1->name);
-      return false;
+      if (!compare_type (s1, s2) || !compare_type (s2, s1))
+	{
+	  snprintf (errmsg, err_len, "Type mismatch in argument '%s' (%s/%s)",
+		    s1->name, gfc_typename (&s1->ts), gfc_typename (&s2->ts));
+	  return false;
+	}
+      if (!compare_rank (s1, s2))
+	{
+	  snprintf (errmsg, err_len, "Rank mismatch in argument '%s' (%i/%i)",
+		    s1->name, symbol_rank (s1), symbol_rank (s2));
+	  return false;
+	}
     }
 
   /* Check INTENT.  */
@@ -1203,9 +1233,16 @@ check_result_characteristics (gfc_symbol *s1, gfc_symbol *s2,
     return true;
 
   /* Check type and rank.  */
-  if (!compare_type_rank (r1, r2))
+  if (!compare_type (r1, r2))
+    {
+      snprintf (errmsg, err_len, "Type mismatch in function result (%s/%s)",
+		gfc_typename (&r1->ts), gfc_typename (&r2->ts));
+      return false;
+    }
+  if (!compare_rank (r1, r2))
     {
-      snprintf (errmsg, err_len, "Type/rank mismatch in function result");
+      snprintf (errmsg, err_len, "Rank mismatch in function result (%i/%i)",
+		symbol_rank (r1), symbol_rank (r2));
       return false;
     }
 
@@ -1437,13 +1474,26 @@ gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, const char *name2,
 					      errmsg, err_len))
 	      return 0;
 	  }
-	else if (!compare_type_rank (f2->sym, f1->sym))
+	else
 	  {
 	    /* Only check type and rank.  */
-	    if (errmsg != NULL)
-	      snprintf (errmsg, err_len, "Type/rank mismatch in argument '%s'",
-			f1->sym->name);
-	    return 0;
+	    if (!compare_type (f2->sym, f1->sym))
+	      {
+		if (errmsg != NULL)
+		  snprintf (errmsg, err_len, "Type mismatch in argument '%s' "
+			    "(%s/%s)", f1->sym->name,
+			    gfc_typename (&f1->sym->ts),
+			    gfc_typename (&f2->sym->ts));
+		return 0;
+	      }
+	    if (!compare_rank (f2->sym, f1->sym))
+	      {
+		if (errmsg != NULL)
+		  snprintf (errmsg, err_len, "Rank mismatch in argument '%s' "
+			    "(%i/%i)", f1->sym->name, symbol_rank (f1->sym),
+			    symbol_rank (f2->sym));
+		return 0;
+	      }
 	  }
 next:
 	f1 = f1->next;
@@ -1746,16 +1796,6 @@ done:
 }
 
 
-static int
-symbol_rank (gfc_symbol *sym)
-{
-  if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->as)
-    return CLASS_DATA (sym)->as->rank;
-
-  return (sym->as == NULL) ? 0 : sym->as->rank;
-}
-
-
 /* Given a symbol of a formal argument list and an expression, if the
    formal argument is allocatable, check that the actual argument is
    allocatable. Returns nonzero if compatible, zero if not compatible.  */
diff --git a/gcc/fortran/misc.c b/gcc/fortran/misc.c
index cce599b..9b8f31f 100644
--- a/gcc/fortran/misc.c
+++ b/gcc/fortran/misc.c
@@ -24,15 +24,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gfortran.h"
 
 
-/* Get terminal width.  */
-
-int
-gfc_terminal_width (void)
-{
-  return 80;
-}
-
-
 /* Initialize a typespec to unknown.  */
 
 void
-- 
cgit v1.1