diff mbox

[Fortran,OOP] PR 49638: [OOP] length parameter is ignored when overriding type bound character functions with constant length.

Message ID CAKwh3qi-cPiexdr9+gPJwLQELX3u90tLchJ9L81cbkKwtbJQ+g@mail.gmail.com
State New
Headers show

Commit Message

Janus Weil Aug. 13, 2011, 1:12 p.m. UTC
Hi Thomas, hi all,

2011/8/7 Thomas Koenig <tkoenig@netcologne.de>:
> When extending the values of gfc_dep_compare_expr, we will need to go
> through all its uses (making sure we change == -2 to <= -2).

attached is a patch which makes a start with this.

For now, it changes the return value to "-3" for two cases:
1) different expr_types
2) non-identical variables

I tried to take care of all places which are checking for a return
value of "-2" and I hope I missed none.

Any objections or ok for trunk? (Regtested successfully.)

Cheers,
Janus


2011-08-13  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49638
	* dependency.c (gfc_dep_compare_expr): Add new result value "-3".
	(gfc_check_element_vs_section,gfc_check_element_vs_element): Handle
	result value "-3".
        * frontend-passes.c (optimize_comparison): Ditto.
	* interface.c (gfc_check_typebound_override): Ditto.


2011-08-13  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49638
	* gfortran.dg/typebound_override_1.f90: Modified.

Comments

Janus Weil Aug. 19, 2011, 10:05 a.m. UTC | #1
Ping! (Maybe I should have posted the follow-up patch in a separate
thread to make it more visible.)




2011/8/13 Janus Weil <janus@gcc.gnu.org>:
> Hi Thomas, hi all,
>
> 2011/8/7 Thomas Koenig <tkoenig@netcologne.de>:
>> When extending the values of gfc_dep_compare_expr, we will need to go
>> through all its uses (making sure we change == -2 to <= -2).
>
> attached is a patch which makes a start with this.
>
> For now, it changes the return value to "-3" for two cases:
> 1) different expr_types
> 2) non-identical variables
>
> I tried to take care of all places which are checking for a return
> value of "-2" and I hope I missed none.
>
> Any objections or ok for trunk? (Regtested successfully.)
>
> Cheers,
> Janus
>
>
> 2011-08-13  Janus Weil  <janus@gcc.gnu.org>
>
>        PR fortran/49638
>        * dependency.c (gfc_dep_compare_expr): Add new result value "-3".
>        (gfc_check_element_vs_section,gfc_check_element_vs_element): Handle
>        result value "-3".
>        * frontend-passes.c (optimize_comparison): Ditto.
>        * interface.c (gfc_check_typebound_override): Ditto.
>
>
> 2011-08-13  Janus Weil  <janus@gcc.gnu.org>
>
>        PR fortran/49638
>        * gfortran.dg/typebound_override_1.f90: Modified.
>
Mikael Morin Aug. 19, 2011, 11:55 a.m. UTC | #2
On Friday 19 August 2011 12:05:02 Janus Weil wrote:
> Ping! (Maybe I should have posted the follow-up patch in a separate
> thread to make it more visible.)
I saw it, had a quick glance, thought that Thomas would jump on it, and 
forgot. Sorry.

> 
> 2011/8/13 Janus Weil <janus@gcc.gnu.org>:
> > Hi Thomas, hi all,
> > 
> > 2011/8/7 Thomas Koenig <tkoenig@netcologne.de>:
> >> When extending the values of gfc_dep_compare_expr, we will need to go
> >> through all its uses (making sure we change == -2 to <= -2).
> > 
> > attached is a patch which makes a start with this.
> > 
> > For now, it changes the return value to "-3" for two cases:
> > 1) different expr_types
> > 2) non-identical variables
> > 
> > I tried to take care of all places which are checking for a return
> > value of "-2" and I hope I missed none.
> > 
> > Any objections or ok for trunk? (Regtested successfully.)
OK from my side for the code proper.

I have one comment though about this:
+/* Compare two expressions.  Return values:
+   * +1 if e1 > e2
+   * 0 if e1 == e2
+   * -1 if e1 < e2
+   * -2 if the relationship could not be determined
+   * -3 if e1 /= e2, but we cannot tell which one is larger.  */

I think this is misleading, as the function does not always return -3 when 
e1/=e2. There is for example (currently) no special handling for operators.
Here is an attempt at expressing it:
  * -3 in some cases where we could determine that e1 and e2 have different 
data dependencies (and thus are not guaranteed to have always the same value), 
but we cannot tell whether one is greater than the other.

Mikael
Tobias Burnus Aug. 19, 2011, 1:12 p.m. UTC | #3
On 08/19/2011 01:55 PM, Mikael Morin wrote:
> OK from my side for the code proper.
>
> I have one comment though about this:
> +/* Compare two expressions.  Return values:
> +   * +1 if e1>  e2
> +   * 0 if e1 == e2
> +   * -1 if e1<  e2
> +   * -2 if the relationship could not be determined
> +   * -3 if e1 /= e2, but we cannot tell which one is larger.  */
>
> I think this is misleading, as the function does not always return -3 when
> e1/=e2. There is for example (currently) no special handling for operators.
> Here is an attempt at expressing it:
>    * -3 in some cases where we could determine that e1 and e2 have different
> data dependencies (and thus are not guaranteed to have always the same value),
> but we cannot tell whether one is greater than the other.

Besides that issue, I am wondering whether we shouldn't start to use an 
ENUM for those. I think for "<" vs. "==" vs. ">" one can use a number 
(-1, 0, 1) and then compare the result against 0 (>0, == 0 etc.).

However, for 5 values, I think it makes sense to do something else 
otherwise, someone write "... < 0" which not only matches -1 but also -2 
or -3.

I think this does not block the committal but one should think about 
whether one should do it as follow up.

Tobias,
who has not read the patch.
Janus Weil Aug. 19, 2011, 9:54 p.m. UTC | #4
>> > 2011/8/7 Thomas Koenig <tkoenig@netcologne.de>:
>> >> When extending the values of gfc_dep_compare_expr, we will need to go
>> >> through all its uses (making sure we change == -2 to <= -2).
>> >
>> > attached is a patch which makes a start with this.
>> >
>> > For now, it changes the return value to "-3" for two cases:
>> > 1) different expr_types
>> > 2) non-identical variables
>> >
>> > I tried to take care of all places which are checking for a return
>> > value of "-2" and I hope I missed none.
>> >
>> > Any objections or ok for trunk? (Regtested successfully.)
> OK from my side for the code proper.

Thanks for the review.


> I have one comment though about this:
> +/* Compare two expressions.  Return values:
> +   * +1 if e1 > e2
> +   * 0 if e1 == e2
> +   * -1 if e1 < e2
> +   * -2 if the relationship could not be determined
> +   * -3 if e1 /= e2, but we cannot tell which one is larger.  */
>
> I think this is misleading, as the function does not always return -3 when
> e1/=e2.

That's right. However, the same argument applies to the other values
as well: The function does not always return 0 if e1==e2. There could
be cases where the arguments are algebraically equal, but we fail to
detect this (example: A+B+C vs C+B+A). This sort of "uncertainty" was
not introduced by me, but was present before, and is not special to
the value "-3".

Describing the value -2 as "relationship could not be determined" sort
of implies that this can happen. So I would tend to leave the
description as it is.


> There is for example (currently) no special handling for operators.

Well, unfortunately one cannot just return "-3" for non-matching
operators. Just think of cases like A*(B+C) vs A*B+A*C. One could try
to handle such cases in a follow-up patch.

I'll commit the patch (as posted) tomorrow, if Mikael agrees that the
description is ok.

Also I like Tobias' idea of using an enum, but I'll leave it for a follow-up.

Cheers,
Janus
Mikael Morin Aug. 19, 2011, 10:54 p.m. UTC | #5
On Friday 19 August 2011 23:54:45 Janus Weil wrote:
> > I have one comment though about this:
> > +/* Compare two expressions.  Return values:
> > +   * +1 if e1 > e2
> > +   * 0 if e1 == e2
> > +   * -1 if e1 < e2
> > +   * -2 if the relationship could not be determined
> > +   * -3 if e1 /= e2, but we cannot tell which one is larger.  */
> > 
> > I think this is misleading, as the function does not always return -3
> > when e1/=e2.
> 
> That's right. However, the same argument applies to the other values
> as well: The function does not always return 0 if e1==e2. There could
> be cases where the arguments are algebraically equal, but we fail to
> detect this (example: A+B+C vs C+B+A). This sort of "uncertainty" was
> not introduced by me, but was present before, and is not special to
> the value "-3".
> 
> Describing the value -2 as "relationship could not be determined" sort
> of implies that this can happen. So I would tend to leave the
> description as it is.
OK, this comment really bugged me, but it's not that bad on second thought.

> 
> > There is for example (currently) no special handling for operators.
> 
> Well, unfortunately one cannot just return "-3" for non-matching
> operators. Just think of cases like A*(B+C) vs A*B+A*C. 
Ah yes. I was thinking expressions themselves were compared; but only their 
values are. 

> One could try to handle such cases in a follow-up patch.
If you want. I wasn't asking you (or anyone else) to do it. 

> 
> I'll commit the patch (as posted) tomorrow, if Mikael agrees that the
> description is ok.
It's fine. Thanks.

Mikael.
Janus Weil Aug. 20, 2011, 7:29 p.m. UTC | #6
>> > There is for example (currently) no special handling for operators.
>>
>> Well, unfortunately one cannot just return "-3" for non-matching
>> operators. Just think of cases like A*(B+C) vs A*B+A*C.
> Ah yes. I was thinking expressions themselves were compared; but only their
> values are.

I'm not sure I'm getting you right here. Of course we do compare the
expressions themselves. However, for example things like commutativity
of operators are taken into account, meaning we compare "A+B" equal to
"B+A" (A and B being arbitrary expressions).

Taking care of other algebraic transformations (like e.g.
distributivity as mentioned above) will be a bit harder. And the
question is we are even allowed to do it. Earlier in this thread Steve
mentioned restrictions like

Note 7.18.  X*(Y-Z) -> X*Y - X*Z is a forbidden transformation
(there is no noted restriction on Z > 0).



>> I'll commit the patch (as posted) tomorrow, if Mikael agrees that the
>> description is ok.
> It's fine. Thanks.

Committed as r177932. Thanks again for your review and comments.

Cheers,
Janus
Mikael Morin Aug. 20, 2011, 8:27 p.m. UTC | #7
On Saturday 20 August 2011 21:29:21 Janus Weil wrote:
> >> > There is for example (currently) no special handling for operators.
> >> 
> >> Well, unfortunately one cannot just return "-3" for non-matching
> >> operators. Just think of cases like A*(B+C) vs A*B+A*C.
> > 
> > Ah yes. I was thinking expressions themselves were compared; but only
> > their values are.
> 
> I'm not sure I'm getting you right here. Of course we do compare the
> expressions themselves. 
Yes, what I mean is...

> However, for example things like commutativity
> of operators are taken into account, meaning we compare "A+B" equal to
> "B+A" (A and B being arbitrary expressions).
... "A+B" and "B+A" are different expressions, with the same value.
And we return 0 (<=> equality) in that case. So we are interested in same-
value-ness, not same-expression-ness.
And we do compare expressions, because same expresssion ===> same value.
But different expression =/=> different value (as your example shows).

Oh well, nevermind.

Mikael
Thomas Koenig Aug. 21, 2011, 10:01 a.m. UTC | #8
If we really wanted to do this The Right Way, there would be seven
cases to be considered, best expressed as three flags.  I'll call them
CAN_BE_LESS, CAN_BE_EQUAL and CAN_BE_MORE.

Comparing a vs. a+1 would yield CAN_BE_LESS for integers and
CAN_BE_LESS | CAN_BE_EQUAL for floats.

Comparing 3 vs. 4 would yield CAN_BE_LESS.

Comparing a vs. 5 would yield CAN_BE_LESS | CAN_BE_EQUAL | CAN_BE_MORE.

Comparing NaN against anything would yield 0.

And so on...

	Thomas
diff mbox

Patch

Index: gcc/testsuite/gfortran.dg/typebound_override_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_override_1.f90	(revision 177733)
+++ gcc/testsuite/gfortran.dg/typebound_override_1.f90	(working copy)
@@ -23,7 +23,7 @@  module m
      procedure, nopass :: b => b2  ! { dg-error "should have matching result types and ranks" }
      procedure, nopass :: c => c2  ! { dg-warning "Possible character length mismatch" }
      procedure, nopass :: d => d2  ! valid, check for commutativity (+,*)
-     procedure, nopass :: e => e2  ! { dg-warning "Possible character length mismatch" }
+     procedure, nopass :: e => e2  ! { dg-error "Character length mismatch" }
   end type
 
 contains
Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c	(revision 177733)
+++ gcc/fortran/interface.c	(working copy)
@@ -3574,7 +3574,8 @@  gfc_check_typebound_override (gfc_symtree* proc, g
 	  switch (compval)
 	  {
 	    case -1:
-	    case 1:
+	    case  1:
+	    case -3:
 	      gfc_error ("Character length mismatch between '%s' at '%L' and "
 			 "overridden FUNCTION", proc->name, &where);
 	      return FAILURE;
Index: gcc/fortran/frontend-passes.c
===================================================================
--- gcc/fortran/frontend-passes.c	(revision 177733)
+++ gcc/fortran/frontend-passes.c	(working copy)
@@ -682,7 +682,7 @@  optimize_comparison (gfc_expr *e, gfc_intrinsic_op
 	  && op1->ts.type != BT_COMPLEX && op2->ts.type != BT_COMPLEX))
     {
       eq = gfc_dep_compare_expr (op1, op2);
-      if (eq == -2)
+      if (eq <= -2)
 	{
 	  /* Replace A // B < A // C with B < C, and A // B < C // B
 	     with A < C.  */
Index: gcc/fortran/dependency.c
===================================================================
--- gcc/fortran/dependency.c	(revision 177733)
+++ gcc/fortran/dependency.c	(working copy)
@@ -230,8 +230,12 @@  gfc_dep_compare_functions (gfc_expr *e1, gfc_expr
 	return -2;      
 }
 
-/* Compare two values.  Returns 0 if e1 == e2, -1 if e1 < e2, +1 if e1 > e2,
-   and -2 if the relationship could not be determined.  */
+/* Compare two expressions.  Return values:
+   * +1 if e1 > e2
+   * 0 if e1 == e2
+   * -1 if e1 < e2
+   * -2 if the relationship could not be determined
+   * -3 if e1 /= e2, but we cannot tell which one is larger.  */
 
 int
 gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2)
@@ -304,9 +308,9 @@  gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2)
 	  r = gfc_dep_compare_expr (e1->value.op.op2, e2->value.op.op2);
 	  if (l == 0 && r == 0)
 	    return 0;
-	  if (l == 0 && r != -2)
+	  if (l == 0 && r > -2)
 	    return r;
-	  if (l != -2 && r == 0)
+	  if (l > -2 && r == 0)
 	    return l;
 	  if (l == 1 && r == 1)
 	    return 1;
@@ -317,9 +321,9 @@  gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2)
 	  r = gfc_dep_compare_expr (e1->value.op.op2, e2->value.op.op1);
 	  if (l == 0 && r == 0)
 	    return 0;
-	  if (l == 0 && r != -2)
+	  if (l == 0 && r > -2)
 	    return r;
-	  if (l != -2 && r == 0)
+	  if (l > -2 && r == 0)
 	    return l;
 	  if (l == 1 && r == 1)
 	    return 1;
@@ -354,9 +358,9 @@  gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2)
 	  r = gfc_dep_compare_expr (e1->value.op.op2, e2->value.op.op2);
 	  if (l == 0 && r == 0)
 	    return 0;
-	  if (l != -2 && r == 0)
+	  if (l > -2 && r == 0)
 	    return l;
-	  if (l == 0 && r != -2)
+	  if (l == 0 && r > -2)
 	    return -r;
 	  if (l == 1 && r == -1)
 	    return 1;
@@ -375,8 +379,8 @@  gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2)
       l = gfc_dep_compare_expr (e1->value.op.op1, e2->value.op.op1);
       r = gfc_dep_compare_expr (e1->value.op.op2, e2->value.op.op2);
 
-      if (l == -2)
-	return -2;
+      if (l <= -2)
+	return l;
 
       if (l == 0)
 	{
@@ -387,7 +391,7 @@  gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2)
 	  if (e1_left->expr_type == EXPR_CONSTANT
 	      && e2_left->expr_type == EXPR_CONSTANT
 	      && e1_left->value.character.length
-	        != e2_left->value.character.length)
+		 != e2_left->value.character.length)
 	    return -2;
 	  else
 	    return r;
@@ -411,7 +415,7 @@  gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2)
     }
 
   if (e1->expr_type != e2->expr_type)
-    return -2;
+    return -3;
 
   switch (e1->expr_type)
     {
@@ -434,7 +438,7 @@  gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2)
       if (are_identical_variables (e1, e2))
 	return 0;
       else
-	return -2;
+	return -3;
 
     case EXPR_OP:
       /* Intrinsic operators are the same if their operands are the same.  */
@@ -1406,7 +1410,7 @@  gfc_check_element_vs_section( gfc_ref *lref, gfc_r
       if (!start || !end)
 	return GFC_DEP_OVERLAP;
       s = gfc_dep_compare_expr (start, end);
-      if (s == -2)
+      if (s <= -2)
 	return GFC_DEP_OVERLAP;
       /* Assume positive stride.  */
       if (s == -1)
@@ -1553,7 +1557,7 @@  gfc_check_element_vs_element (gfc_ref *lref, gfc_r
   if (contains_forall_index_p (r_start) || contains_forall_index_p (l_start))
     return GFC_DEP_OVERLAP;
 
-  if (i != -2)
+  if (i > -2)
     return GFC_DEP_NODEP;
   return GFC_DEP_EQUAL;
 }