Blame SOURCES/0016-Allow-calls-to-intrinsics-with-smaller-types-than-sp.patch

2985e0
From 109b1eeba24e5091bf3bdb6caedf7101a9dcaa6a Mon Sep 17 00:00:00 2001
2985e0
From: Jim MacArthur <jim.macarthur@codethink.co.uk>
2985e0
Date: Wed, 18 Nov 2015 11:50:41 +0000
2985e0
Subject: [PATCH 16/23] Allow calls to intrinsics with smaller types than
2985e0
 specified
2985e0
2985e0
This feature is enabled by the `-std=extra-legacy` compiler flag.
2985e0
---
2985e0
2985e0
    0016-Allow-calls-to-intrinsics-with-smaller-types-than-sp.patch
2985e0
2985e0
diff -Nrup a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
2985e0
--- a/gcc/fortran/gfortran.h	2018-06-05 11:59:14.269337049 -0600
2985e0
+++ b/gcc/fortran/gfortran.h	2018-06-05 11:59:52.830081690 -0600
2985e0
@@ -656,6 +656,13 @@ enum gfc_param_spec_type
2985e0
   SPEC_DEFERRED
2985e0
 };
2985e0
 
2985e0
+enum match_type
2985e0
+{
2985e0
+  MATCH_EXACT,
2985e0
+  MATCH_PROMOTABLE,
2985e0
+  MATCH_INVALID
2985e0
+};
2985e0
+
2985e0
 /************************* Structures *****************************/
2985e0
 
2985e0
 /* Used for keeping things in balanced binary trees.  */
2985e0
@@ -3251,7 +3253,7 @@ bool gfc_add_interface (gfc_symbol *);
2985e0
 gfc_interface *gfc_current_interface_head (void);
2985e0
 void gfc_set_current_interface_head (gfc_interface *);
2985e0
 gfc_symtree* gfc_find_sym_in_symtree (gfc_symbol*);
2985e0
-bool gfc_arglist_matches_symbol (gfc_actual_arglist**, gfc_symbol*);
2985e0
+bool gfc_arglist_matches_symbol (gfc_actual_arglist**, gfc_symbol*, enum match_type mtype);
2985e0
 bool gfc_check_operator_interface (gfc_symbol*, gfc_intrinsic_op, locus);
2985e0
 bool gfc_has_vector_subscript (gfc_expr*);
2985e0
 gfc_intrinsic_op gfc_equivalent_op (gfc_intrinsic_op);
2985e0
diff -Nrup a/gcc/fortran/interface.c b/gcc/fortran/interface.c
2985e0
--- a/gcc/fortran/interface.c	2018-03-03 06:51:39.000000000 -0700
2985e0
+++ b/gcc/fortran/interface.c	2018-06-05 12:01:11.218559539 -0600
2985e0
@@ -682,7 +682,7 @@ gfc_compare_derived_types (gfc_symbol *d
2985e0
 /* Compare two typespecs, recursively if necessary.  */
2985e0
 
2985e0
 bool
2985e0
-gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2)
2985e0
+gfc_compare_types_generic (gfc_typespec *ts1, gfc_typespec *ts2, enum match_type mtype)
2985e0
 {
2985e0
   /* See if one of the typespecs is a BT_VOID, which is what is being used
2985e0
      to allow the funcs like c_f_pointer to accept any pointer type.
2985e0
@@ -721,12 +721,23 @@ gfc_compare_types (gfc_typespec *ts1, gf
2985e0
     return compare_union_types (ts1->u.derived, ts2->u.derived);
2985e0
 
2985e0
   if (ts1->type != BT_DERIVED && ts1->type != BT_CLASS)
2985e0
-    return (ts1->kind == ts2->kind);
2985e0
+    {
2985e0
+    if (mtype == MATCH_PROMOTABLE)
2985e0
+      return (ts1->kind >= ts2->kind);
2985e0
+    else
2985e0
+      return (ts1->kind == ts2->kind);
2985e0
+    }
2985e0
+
2985e0
 
2985e0
   /* Compare derived types.  */
2985e0
   return gfc_type_compatible (ts1, ts2);
2985e0
 }
2985e0
 
2985e0
+bool
2985e0
+gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2)
2985e0
+{
2985e0
+  return gfc_compare_types_generic (ts1, ts2, MATCH_EXACT);
2985e0
+}
2985e0
 
2985e0
 static bool
2985e0
 compare_type (gfc_symbol *s1, gfc_symbol *s2)
2985e0
@@ -743,7 +754,9 @@ compare_type (gfc_symbol *s1, gfc_symbol
93e26d
   return compare_type (s1, s2);
2985e0
 }
2985e0
 
2985e0
-
2985e0
+/* Given two symbols that are formal arguments, compare their ranks
2985e0
+   and types.  Returns nonzero if they have the same rank and type,
2985e0
+   zero otherwise.  */
2985e0
 static bool
2985e0
 compare_rank (gfc_symbol *s1, gfc_symbol *s2)
2985e0
 {
2985e0
@@ -2150,7 +2163,7 @@ argument_rank_mismatch (const char *name
2985e0
 
2985e0
 static bool
2985e0
 compare_parameter (gfc_symbol *formal, gfc_expr *actual,
2985e0
-		   int ranks_must_agree, int is_elemental, locus *where)
2985e0
+                   int ranks_must_agree, int is_elemental, locus *where, enum match_type mtype)
2985e0
 {
2985e0
   gfc_ref *ref;
2985e0
   bool rank_check, is_pointer;
2985e0
@@ -2242,7 +2255,7 @@ compare_parameter (gfc_symbol *formal, g
2985e0
       && actual->ts.type != BT_HOLLERITH
2985e0
       && formal->ts.type != BT_ASSUMED
2985e0
       && !(formal->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
2985e0
-      && !gfc_compare_types (&formal->ts, &actual->ts)
2985e0
+      && !gfc_compare_types_generic (&formal->ts, &actual->ts, mtype)
2985e0
       && !(formal->ts.type == BT_DERIVED && actual->ts.type == BT_CLASS
2985e0
 	   && gfc_compare_derived_types (formal->ts.u.derived,
2985e0
 					 CLASS_DATA (actual)->ts.u.derived)))
2985e0
@@ -2792,7 +2805,8 @@ is_procptr_result (gfc_expr *expr)
2985e0
 static bool
2985e0
 compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
2985e0
 	 	       int ranks_must_agree, int is_elemental,
2985e0
-		       bool in_statement_function, locus *where)
2985e0
+		       bool in_statement_function, locus *where,
2985e0
+		       enum match_type mtype)
2985e0
 {
2985e0
   gfc_actual_arglist **new_arg, *a, *actual;
2985e0
   gfc_formal_arglist *f;
2985e0
@@ -2918,7 +2932,7 @@ compare_actual_formal (gfc_actual_arglis
2985e0
 	}
2985e0
 
2985e0
       if (!compare_parameter (f->sym, a->expr, ranks_must_agree,
2985e0
-			      is_elemental, where))
2985e0
+			      is_elemental, where, mtype))
2985e0
 	return false;
2985e0
 
2985e0
       /* TS 29113, 6.3p2.  */
2985e0
@@ -3666,7 +3680,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_
2985e0
   /* For a statement function, check that types and type parameters of actual
2985e0
      arguments and dummy arguments match.  */
2985e0
   if (!compare_actual_formal (ap, dummy_args, 0, sym->attr.elemental,
2985e0
-			      sym->attr.proc == PROC_ST_FUNCTION, where))
2985e0
+			      sym->attr.proc == PROC_ST_FUNCTION, where, MATCH_PROMOTABLE))
2985e0
     return false;
2985e0
  
2985e0
   if (!check_intents (dummy_args, *ap))
2985e0
@@ -3715,7 +3730,7 @@ gfc_ppc_use (gfc_component *comp, gfc_ac
2985e0
     }
2985e0
 
2985e0
   if (!compare_actual_formal (ap, comp->ts.interface->formal, 0,
2985e0
-			      comp->attr.elemental, false, where))
2985e0
+			      comp->attr.elemental, false, where, MATCH_EXACT))
2985e0
     return;
2985e0
 
2985e0
   check_intents (comp->ts.interface->formal, *ap);
2985e0
@@ -3729,7 +3744,7 @@ gfc_ppc_use (gfc_component *comp, gfc_ac
2985e0
    GENERIC resolution.  */
2985e0
 
2985e0
 bool
2985e0
-gfc_arglist_matches_symbol (gfc_actual_arglist** args, gfc_symbol* sym)
2985e0
+gfc_arglist_matches_symbol (gfc_actual_arglist** args, gfc_symbol* sym, enum match_type mtype)
2985e0
 {
2985e0
   gfc_formal_arglist *dummy_args;
2985e0
   bool r;
2985e0
@@ -3740,7 +3755,7 @@ gfc_arglist_matches_symbol (gfc_actual_a
2985e0
   dummy_args = gfc_sym_get_dummy_args (sym);
2985e0
 
2985e0
   r = !sym->attr.elemental;
2985e0
-  if (compare_actual_formal (args, dummy_args, r, !r, false, NULL))
2985e0
+  if (compare_actual_formal (args, dummy_args, r, !r, false, NULL, mtype))
2985e0
     {
2985e0
       check_intents (dummy_args, *args);
2985e0
       if (warn_aliasing)
2985e0
@@ -3766,7 +3781,8 @@ gfc_search_interface (gfc_interface *int
2985e0
   locus null_expr_loc;
2985e0
   gfc_actual_arglist *a;
2985e0
   bool has_null_arg = false;
2985e0
-
2985e0
+  enum match_type mtypes[] = { MATCH_EXACT, MATCH_PROMOTABLE };
2985e0
+  int i;
2985e0
   for (a = *ap; a; a = a->next)
2985e0
     if (a->expr && a->expr->expr_type == EXPR_NULL
2985e0
 	&& a->expr->ts.type == BT_UNKNOWN)
2985e0
@@ -3776,38 +3792,43 @@ gfc_search_interface (gfc_interface *int
2985e0
 	break;
2985e0
       }
2985e0
 
2985e0
-  for (; intr; intr = intr->next)
2985e0
+  for (i=0; i<2; i++)
2985e0
     {
2985e0
+      for (; intr; intr = intr->next)
2985e0
+	{
2985e0
+	  if (intr->sym->attr.flavor == FL_DERIVED)
2985e0
+	    continue;
2985e0
       if (gfc_fl_struct (intr->sym->attr.flavor))
2985e0
 	continue;
2985e0
-      if (sub_flag && intr->sym->attr.function)
2985e0
-	continue;
2985e0
-      if (!sub_flag && intr->sym->attr.subroutine)
2985e0
+	  if (sub_flag && intr->sym->attr.function)
2985e0
+	    continue;
2985e0
+	  if (!sub_flag && intr->sym->attr.subroutine)
2985e0
 	continue;
2985e0
 
2985e0
-      if (gfc_arglist_matches_symbol (ap, intr->sym))
2985e0
-	{
2985e0
-	  if (has_null_arg && null_sym)
2985e0
-	    {
2985e0
-	      gfc_error ("MOLD= required in NULL() argument at %L: Ambiguity "
2985e0
-			 "between specific functions %s and %s",
2985e0
-			 &null_expr_loc, null_sym->name, intr->sym->name);
2985e0
-	      return NULL;
2985e0
-	    }
2985e0
-	  else if (has_null_arg)
2985e0
+	  if (gfc_arglist_matches_symbol (ap, intr->sym, mtypes[i]))
2985e0
 	    {
2985e0
-	      null_sym = intr->sym;
2985e0
-	      continue;
2985e0
-	    }
2985e0
+	      if (has_null_arg && null_sym)
2985e0
+		{
2985e0
+		  gfc_error ("MOLD= required in NULL() argument at %L: Ambiguity "
2985e0
+			     "between specific functions %s and %s",
2985e0
+			     &null_expr_loc, null_sym->name, intr->sym->name);
2985e0
+		  return NULL;
2985e0
+		}
2985e0
+	      else if (has_null_arg)
2985e0
+		{
2985e0
+		  null_sym = intr->sym;
2985e0
+		  continue;
2985e0
+		}
2985e0
 
2985e0
-	  /* Satisfy 12.4.4.1 such that an elemental match has lower
2985e0
-	     weight than a non-elemental match.  */
2985e0
-	  if (intr->sym->attr.elemental)
2985e0
-	    {
2985e0
-	      elem_sym = intr->sym;
2985e0
-	      continue;
2985e0
+	      /* Satisfy 12.4.4.1 such that an elemental match has lower
2985e0
+		 weight than a non-elemental match.  */
2985e0
+	      if (intr->sym->attr.elemental)
2985e0
+		{
2985e0
+		  elem_sym = intr->sym;
2985e0
+		  continue;
2985e0
+		}
2985e0
+	      return intr->sym;
2985e0
 	    }
2985e0
-	  return intr->sym;
2985e0
 	}
2985e0
     }
2985e0
 
2985e0
@@ -3942,7 +3963,7 @@ matching_typebound_op (gfc_expr** tb_bas
2985e0
 
2985e0
 		/* Check if this arglist matches the formal.  */
2985e0
 		argcopy = gfc_copy_actual_arglist (args);
2985e0
-		matches = gfc_arglist_matches_symbol (&argcopy, target);
2985e0
+		matches = gfc_arglist_matches_symbol (&argcopy, target, MATCH_EXACT);
2985e0
 		gfc_free_actual_arglist (argcopy);
2985e0
 
2985e0
 		/* Return if we found a match.  */
2985e0
diff -Nrup a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
2985e0
--- a/gcc/fortran/intrinsic.c	2018-06-05 11:59:14.278336990 -0600
2985e0
+++ b/gcc/fortran/intrinsic.c	2018-06-05 11:59:52.831081683 -0600
2985e0
@@ -4229,6 +4229,16 @@ check_arglist (gfc_actual_arglist **ap,
2985e0
       if (ts.kind == 0)
2985e0
 	ts.kind = actual->expr->ts.kind;
2985e0
 
2985e0
+      /* ts.kind is the argument spec. actual is what was passed. */
2985e0
+
2985e0
+      if (actual->expr->ts.kind < ts.kind
2985e0
+	  && ts.type == BT_INTEGER)
2985e0
+	{
2985e0
+	  /* If it was OK to overwrite ts.kind in the previous case, it
2985e0
+	     should be fine here... */
2985e0
+	  ts.kind = actual->expr->ts.kind;
2985e0
+	}
2985e0
+
2985e0
       if (!gfc_compare_types (&ts, &actual->expr->ts))
2985e0
 	{
2985e0
 	  if (error_flag)
2985e0
diff -Nrup a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
2985e0
--- a/gcc/fortran/resolve.c	2018-06-05 11:59:14.291336904 -0600
2985e0
+++ b/gcc/fortran/resolve.c	2018-06-05 11:59:52.833081670 -0600
2985e0
@@ -6055,7 +6055,7 @@ resolve_typebound_generic_call (gfc_expr
2985e0
 				  && gfc_sym_get_dummy_args (target) == NULL);
2985e0
 
2985e0
 	  /* Check if this arglist matches the formal.  */
2985e0
-	  matches = gfc_arglist_matches_symbol (&args, target);
2985e0
+	  matches = gfc_arglist_matches_symbol (&args, target, MATCH_EXACT);
2985e0
 
2985e0
 	  /* Clean up and break out of the loop if we've found it.  */
2985e0
 	  gfc_free_actual_arglist (args);