Hello world,

the attached patch warns about the dubious pointer assignments (see
test case for details).  I think an unconditional warning is OK
in this case because

- Assigning to a pointer from an obvious non-contiguous target
  is not useful at all, that I can see

- Some language laywer will come up with the fact that it is,
  in fact, legal if the target is empty or has a single
  element only, so a hard error would be a rejects-valid.

However, I can also make this into a warning depending on
-Wall, if this is preferred.

Regresson-tested. OK for trunk?

Regards

        Thomas

2017-08-27  Thomas Koenig  <tkoe...@gcc.gnu.org>

        PR fortran/49232
        * expr.c (gfc_check_pointer_assign): Warn for
        suspicious assignments with contiguous pointers.

2017-08-27  Thomas Koenig  <tkoe...@gcc.gnu.org>

        PR fortran/49232
        * gfortran.dg/contiguous_4.f90: New test.
Index: expr.c
===================================================================
--- expr.c	(Revision 239977)
+++ expr.c	(Arbeitskopie)
@@ -3764,6 +3764,66 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_ex
 	  }
     }
 
+  /* Warn for suspicious assignments like
+
+     pointer, real, dimension(:), contiguous :: p
+     real, dimension(10,10) :: a
+     p => a(:,:,2) or p => a(2:4,:)  */
+
+  if (lhs_attr.contiguous)
+    {
+      gfc_array_ref *ar;
+      int i;
+      bool do_warn;
+      
+      do_warn = false;
+      ar = NULL;
+
+      for (ref = rvalue->ref; ref; ref = ref->next)
+	{
+	  if (ref->type == REF_ARRAY)
+	    {
+	      ar = &ref->u.ar;
+	      break;
+	    }
+	}
+      if (ar && ar->type == AR_SECTION)
+	{
+
+	  for (i = 0; i < ar->dimen; i++)
+	    {
+	      if (ar->dimen_type[i] == DIMEN_RANGE && ar->stride[i]
+		  && (ar->stride[i]->expr_type != EXPR_CONSTANT
+		      || (ar->stride[i]->expr_type == EXPR_CONSTANT
+			  && mpz_cmp_si (ar->stride[i]->value.integer, 1))))
+		{
+		  do_warn = true;
+		  break;
+		}
+	    }
+	  if (!do_warn && ar->dimen > 1)
+	    {
+	      for (i = 0; i < ar->dimen - 1; i++)
+		{
+		  if ((ar->start[i] && ar->as->lower[i]
+		       && gfc_dep_compare_expr (ar->start[i], ar->as->lower[i])
+		       != 0)
+		      || (ar->end[i] && ar->as->upper[i]
+			  && gfc_dep_compare_expr (ar->end[i], ar->as->upper[i])
+			  != 0))
+		    {
+		      do_warn = true;
+		      break;
+		    }
+		}
+	    }
+	}
+      if (do_warn)
+	gfc_warning (0, "Assignment to contiguous pointer from "
+		     "possibly non-contiguous target at %L",
+		     &rvalue->where);
+    }
+
   /* Warn if it is the LHS pointer may lives longer than the RHS target.  */
   if (warn_target_lifetime
       && rvalue->expr_type == EXPR_VARIABLE
! { dg-do compile }
program cont_01_neg
  implicit none
  real, pointer, contiguous :: r(:)
  real, pointer, contiguous :: r2(:,:)
  real, target :: x(45)
  real, target :: x2(5,9)
  integer :: i

  x = (/ (real(i),i=1,45) /)
  x2 = reshape(x,shape(x2))
  r => x(::3)   ! { dg-warning "Assignment to contiguous pointer" }
  r2 => x2(2:,:) ! { dg-warning "Assignment to contiguous pointer" }
  r2 => x2(:,2:3)

end program

Reply via email to