* [patches,fortran] Add POINTER INTENT(*) support (PR29624)
@ 2006-12-12 11:20 Tobias Burnus
2006-12-17 22:13 ` Tobias Burnus
0 siblings, 1 reply; 7+ messages in thread
From: Tobias Burnus @ 2006-12-12 11:20 UTC (permalink / raw)
To: 'fortran@gcc.gnu.org', gcc-patches
[-- Attachment #1: Type: text/plain, Size: 922 bytes --]
:ADDPATCH fortran:
The standard can be found at
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29624#c0
In a nutshell: With intent(in) the pointer dummy argument's association
shall not be changed, the target may.
Thanks to Tobias S. for pointing out that I was looking at the wrong
thing in terms of attributes.
Quick remark to compound structures:
- If the last subobject is a pointer & its association is changed, I
check whether somewhere higher up in the hierarchy is already a pointer,
because then the subobject is a target of that one. => Modification allowed.
- If the last subobject is a pointer & its value target value is changed
=> Modification always allowed
- If the last subobject is a nonpointer: Check whether somewhere higher
up in the hierarchy is already a pointer, because then the subobject is
a target of that one. => Modification allowed.
Regression tested on x86_64-unknown-linux-gnu.
Tobias
[-- Attachment #2: pointer-intent.diff --]
[-- Type: text/x-patch, Size: 21996 bytes --]
fortran/
2006-12-12 Tobias Burnus <burnus@net-b.de>
PR fortran/29624
* interface.c (compare_parameter_intent): New function.
(check_intents): Support pointer intents.
* symbol.c (check_conflict): Support pointer intents,
better conflict_std message.
* expr.c (gfc_check_assign,gfc_check_pointer_assign):
Support pointer intents.
* resolve.c (resolve_deallocate_expr,resolve_allocate_expr):
Support pointer intents.
testsuite/
2006-12-12 Tobias Burnus <burnus@net-b.de>
PR fortran/29624
* gfortran.dg/allocatable_dummy_2.f90: Update dg-error.
* gfortran.dg/protected_4.f90: Add pointer intent check.
* gfortran.dg/protected_6.f90: Add pointer intent check.
* gfortran.dg/pointer_intent_1.f90: New test.
* gfortran.dg/pointer_intent_2.f90: New test.
* gfortran.dg/pointer_intent_3.f90: New test.
Index: gcc/fortran/interface.c
===================================================================
*** gcc/fortran/interface.c (Revision 119747)
--- gcc/fortran/interface.c (Arbeitskopie)
*************** check_some_aliasing (gfc_formal_arglist
*** 1648,1653 ****
--- 1648,1675 ----
}
+ /* Given a symbol of a formal argument list and an expression, see if
+ their intents are compatible. Returns nonzero if compatible,
+ zero if not compatible. */
+
+ static int
+ compare_parameter_intent (gfc_symbol * formal, gfc_expr * actual)
+ {
+ if (actual->symtree->n.sym->attr.pointer
+ && !formal->attr.pointer)
+ return 1;
+
+ if (actual->symtree->n.sym->attr.intent != INTENT_IN)
+ return 1;
+
+ if (formal->attr.intent == INTENT_INOUT
+ || formal->attr.intent == INTENT_OUT)
+ return 0;
+
+ return 1;
+ }
+
+
/* Given formal and actual argument lists that correspond to one
another, check that they are compatible in the sense that intents
are not mismatched. */
*************** check_some_aliasing (gfc_formal_arglist
*** 1655,1661 ****
static try
check_intents (gfc_formal_arglist * f, gfc_actual_arglist * a)
{
! sym_intent a_intent, f_intent;
for (;; f = f->next, a = a->next)
{
--- 1677,1683 ----
static try
check_intents (gfc_formal_arglist * f, gfc_actual_arglist * a)
{
! sym_intent f_intent;
for (;; f = f->next, a = a->next)
{
*************** check_intents (gfc_formal_arglist * f, g
*** 1667,1678 ****
if (a->expr == NULL || a->expr->expr_type != EXPR_VARIABLE)
continue;
- a_intent = a->expr->symtree->n.sym->attr.intent;
f_intent = f->sym->attr.intent;
! if (a_intent == INTENT_IN
! && (f_intent == INTENT_INOUT
! || f_intent == INTENT_OUT))
{
gfc_error ("Procedure argument at %L is INTENT(IN) while interface "
--- 1689,1697 ----
if (a->expr == NULL || a->expr->expr_type != EXPR_VARIABLE)
continue;
f_intent = f->sym->attr.intent;
! if (!compare_parameter_intent(f->sym, a->expr))
{
gfc_error ("Procedure argument at %L is INTENT(IN) while interface "
Index: gcc/fortran/symbol.c
===================================================================
*** gcc/fortran/symbol.c (Revision 119747)
--- gcc/fortran/symbol.c (Arbeitskopie)
*************** check_conflict (symbol_attribute * attr,
*** 288,294 ****
{
a1 = pointer;
a2 = intent;
! goto conflict;
}
/* Check for attributes not allowed in a BLOCK DATA. */
--- 288,295 ----
{
a1 = pointer;
a2 = intent;
! standard = GFC_STD_F2003;
! goto conflict_std;
}
/* Check for attributes not allowed in a BLOCK DATA. */
*************** conflict:
*** 571,584 ****
conflict_std:
if (name == NULL)
{
! return gfc_notify_std (standard, "In the selected standard, %s attribute "
! "conflicts with %s attribute at %L", a1, a2,
! where);
}
else
{
! return gfc_notify_std (standard, "In the selected standard, %s attribute "
! "conflicts with %s attribute in '%s' at %L",
a1, a2, name, where);
}
}
--- 572,589 ----
conflict_std:
if (name == NULL)
{
! return gfc_notify_std (standard, "%s: %s attribute with %s attribute "
! "at %L",
! (standard == GFC_STD_F2003)
! ? "Fortran 2003" : "Not in the selected standard",
! a1, a2, where);
}
else
{
! return gfc_notify_std (standard, "%s: %s attribute with %s attribute "
! "in '%s' at %L",
! (standard == GFC_STD_F2003)
! ? "Fortran 2003" : "Not in the selected standard",
a1, a2, name, where);
}
}
Index: gcc/fortran/expr.c
===================================================================
*** gcc/fortran/expr.c (Revision 119747)
--- gcc/fortran/expr.c (Arbeitskopie)
*************** try
*** 2188,2199 ****
gfc_check_assign (gfc_expr * lvalue, gfc_expr * rvalue, int conform)
{
gfc_symbol *sym;
sym = lvalue->symtree->n.sym;
! if (sym->attr.intent == INTENT_IN)
{
! gfc_error ("Can't assign to INTENT(IN) variable '%s' at %L",
sym->name, &lvalue->where);
return FAILURE;
}
--- 2188,2212 ----
gfc_check_assign (gfc_expr * lvalue, gfc_expr * rvalue, int conform)
{
gfc_symbol *sym;
+ gfc_ref *ref;
+ int has_pointer;
sym = lvalue->symtree->n.sym;
! /* Check INTENT(IN), unless the object itself of higher up in the
! hierarchy is a pointer. */
! has_pointer = sym->attr.pointer;
!
! for (ref = lvalue->ref; ref; ref = ref->next)
! if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
! {
! has_pointer = 1;
! break;
! }
!
! if (!has_pointer && sym->attr.intent == INTENT_IN)
{
! gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L",
sym->name, &lvalue->where);
return FAILURE;
}
*************** try
*** 2318,2324 ****
--- 2331,2339 ----
gfc_check_pointer_assign (gfc_expr * lvalue, gfc_expr * rvalue)
{
symbol_attribute attr;
+ gfc_ref *ref;
int is_pure;
+ int pointer, check_intent_in;
if (lvalue->symtree->n.sym->ts.type == BT_UNKNOWN)
{
*************** gfc_check_pointer_assign (gfc_expr * lva
*** 2336,2343 ****
return FAILURE;
}
! attr = gfc_variable_attr (lvalue, NULL);
! if (!attr.pointer)
{
gfc_error ("Pointer assignment to non-POINTER at %L", &lvalue->where);
return FAILURE;
--- 2351,2379 ----
return FAILURE;
}
!
! /* Check INTENT(IN), unless the object itself of higher up in the
! hierarchy is a pointer. */
! check_intent_in = 1;
! pointer = lvalue->symtree->n.sym->attr.pointer;
!
! for (ref = lvalue->ref; ref; ref = ref->next)
! {
! if (pointer)
! check_intent_in = 0;
!
! if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
! pointer = 1;
! }
!
! if (check_intent_in && lvalue->symtree->n.sym->attr.intent == INTENT_IN)
! {
! gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L",
! lvalue->symtree->n.sym->name, &lvalue->where);
! return FAILURE;
! }
!
! if (!pointer)
{
gfc_error ("Pointer assignment to non-POINTER at %L", &lvalue->where);
return FAILURE;
Index: gcc/fortran/resolve.c
===================================================================
*** gcc/fortran/resolve.c (Revision 119747)
--- gcc/fortran/resolve.c (Arbeitskopie)
*************** derived_inaccessible (gfc_symbol *sym)
*** 3317,3365 ****
static try
resolve_deallocate_expr (gfc_expr * e)
{
! symbol_attribute attr;
! int allocatable;
gfc_ref *ref;
if (gfc_resolve_expr (e) == FAILURE)
return FAILURE;
- attr = gfc_expr_attr (e);
- if (attr.pointer)
- return SUCCESS;
-
if (e->expr_type != EXPR_VARIABLE)
goto bad;
allocatable = e->symtree->n.sym->attr.allocatable;
for (ref = e->ref; ref; ref = ref->next)
! switch (ref->type)
! {
! case REF_ARRAY:
! if (ref->u.ar.type != AR_FULL)
! allocatable = 0;
! break;
! case REF_COMPONENT:
! allocatable = (ref->u.c.component->as != NULL
! && ref->u.c.component->as->type == AS_DEFERRED);
! break;
! case REF_SUBSTRING:
! allocatable = 0;
! break;
! }
! if (allocatable == 0)
{
bad:
gfc_error ("Expression in DEALLOCATE statement at %L must be "
"ALLOCATABLE or a POINTER", &e->where);
}
! if (e->symtree->n.sym->attr.intent == INTENT_IN)
{
! gfc_error ("Can't deallocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
--- 3317,3372 ----
static try
resolve_deallocate_expr (gfc_expr * e)
{
! int allocatable, pointer, check_intent_in;
gfc_ref *ref;
+ /* Check INTENT(IN), unless an object higher up in the
+ hierarchy is a pointer. */
+ check_intent_in = 1;
+
if (gfc_resolve_expr (e) == FAILURE)
return FAILURE;
if (e->expr_type != EXPR_VARIABLE)
goto bad;
allocatable = e->symtree->n.sym->attr.allocatable;
+ pointer = e->symtree->n.sym->attr.pointer;
for (ref = e->ref; ref; ref = ref->next)
! {
! if (pointer)
! check_intent_in = 0;
! switch (ref->type)
! {
! case REF_ARRAY:
! if (ref->u.ar.type != AR_FULL)
! allocatable = 0;
! break;
! case REF_COMPONENT:
! allocatable = (ref->u.c.component->as != NULL
! && ref->u.c.component->as->type == AS_DEFERRED);
! pointer = ref->u.c.component->pointer;
! break;
! case REF_SUBSTRING:
! allocatable = 0;
! break;
! }
! }
!
! if (allocatable == 0 && pointer == 0)
{
bad:
gfc_error ("Expression in DEALLOCATE statement at %L must be "
"ALLOCATABLE or a POINTER", &e->where);
}
! if (check_intent_in
! && e->symtree->n.sym->attr.intent == INTENT_IN)
{
! gfc_error ("Cannot deallocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
*************** expr_to_initialize (gfc_expr * e)
*** 3481,3487 ****
static try
resolve_allocate_expr (gfc_expr * e, gfc_code * code)
{
! int i, pointer, allocatable, dimension;
symbol_attribute attr;
gfc_ref *ref, *ref2;
gfc_array_ref *ar;
--- 3488,3494 ----
static try
resolve_allocate_expr (gfc_expr * e, gfc_code * code)
{
! int i, pointer, allocatable, dimension, check_intent_in;
symbol_attribute attr;
gfc_ref *ref, *ref2;
gfc_array_ref *ar;
*************** resolve_allocate_expr (gfc_expr * e, gfc
*** 3490,3495 ****
--- 3497,3506 ----
gfc_symbol *sym;
gfc_alloc *a;
+ /* Check INTENT(IN), unless an object higher up in the
+ hierarchy is a pointer. */
+ check_intent_in = 1;
+
if (gfc_resolve_expr (e) == FAILURE)
return FAILURE;
*************** resolve_allocate_expr (gfc_expr * e, gfc
*** 3527,3552 ****
}
for (ref = e->ref; ref; ref2 = ref, ref = ref->next)
! switch (ref->type)
! {
! case REF_ARRAY:
! if (ref->next != NULL)
! pointer = 0;
! break;
!
! case REF_COMPONENT:
! allocatable = (ref->u.c.component->as != NULL
! && ref->u.c.component->as->type == AS_DEFERRED);
!
! pointer = ref->u.c.component->pointer;
! dimension = ref->u.c.component->dimension;
! break;
! case REF_SUBSTRING:
! allocatable = 0;
! pointer = 0;
! break;
! }
}
if (allocatable == 0 && pointer == 0)
--- 3538,3568 ----
}
for (ref = e->ref; ref; ref2 = ref, ref = ref->next)
! {
! if (pointer)
! check_intent_in = 0;
! switch (ref->type)
! {
! case REF_ARRAY:
! if (ref->next != NULL)
! pointer = 0;
! break;
!
! case REF_COMPONENT:
! allocatable = (ref->u.c.component->as != NULL
! && ref->u.c.component->as->type == AS_DEFERRED);
!
! pointer = ref->u.c.component->pointer;
! dimension = ref->u.c.component->dimension;
! break;
!
! case REF_SUBSTRING:
! allocatable = 0;
! pointer = 0;
! break;
! }
! }
}
if (allocatable == 0 && pointer == 0)
*************** resolve_allocate_expr (gfc_expr * e, gfc
*** 3556,3564 ****
return FAILURE;
}
! if (e->symtree->n.sym->attr.intent == INTENT_IN)
{
! gfc_error ("Can't allocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
--- 3572,3581 ----
return FAILURE;
}
! if (check_intent_in
! && e->symtree->n.sym->attr.intent == INTENT_IN)
{
! gfc_error ("Cannot allocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
Index: gcc/testsuite/gfortran.dg/protected_4.f90
===================================================================
*** gcc/testsuite/gfortran.dg/protected_4.f90 (Revision 119747)
--- gcc/testsuite/gfortran.dg/protected_4.f90 (Arbeitskopie)
*************** program main
*** 21,26 ****
--- 21,27 ----
use protmod
implicit none
integer :: j
+ logical :: asgnd
protected :: j ! { dg-error "only allowed in specification part of a module" }
a = 43 ! { dg-error "Assigning to PROTECTED variable" }
ap => null() ! { dg-error "Assigning to PROTECTED variable" }
*************** program main
*** 30,35 ****
--- 31,38 ----
allocate(ap) ! { dg-error "Assigning to PROTECTED variable" }
ap = 73 ! { dg-error "Assigning to PROTECTED variable" }
call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" }
+ call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" }
+ asgnd = pointer_check(ap)
contains
subroutine increment(a1,a3)
integer, intent(inout) :: a1, a3
*************** contains
*** 37,45 ****
a3 = a3 + 1
end subroutine increment
subroutine pointer_assignments(p)
! integer, pointer :: p ! with [pointer] intent(out)
! p => null() ! this is invalid
end subroutine pointer_assignments
end program main
module test
--- 40,53 ----
a3 = a3 + 1
end subroutine increment
subroutine pointer_assignments(p)
! integer, pointer,intent(out) :: p
! p => null()
end subroutine pointer_assignments
+ function pointer_check(p)
+ integer, pointer,intent(in) :: p
+ logical :: pointer_check
+ pointer_check = associated(p)
+ end function pointer_check
end program main
module test
Index: gcc/testsuite/gfortran.dg/protected_6.f90
===================================================================
*** gcc/testsuite/gfortran.dg/protected_6.f90 (Revision 119747)
--- gcc/testsuite/gfortran.dg/protected_6.f90 (Arbeitskopie)
*************** program main
*** 27,32 ****
--- 27,33 ----
allocate(ap) ! { dg-error "Assigning to PROTECTED variable" }
ap = 73 ! { dg-error "Assigning to PROTECTED variable" }
call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" }
+ call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" }
contains
subroutine increment(a1,a3)
integer, intent(inout) :: a1, a3
*************** contains
*** 34,41 ****
a3 = a3 + 1
end subroutine increment
subroutine pointer_assignments(p)
! integer, pointer :: p ! with [pointer] intent(out)
! p => null() ! this is invalid
end subroutine pointer_assignments
end program main
--- 35,42 ----
a3 = a3 + 1
end subroutine increment
subroutine pointer_assignments(p)
! integer, pointer,intent (inout) :: p
! p => null()
end subroutine pointer_assignments
end program main
Index: gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90
===================================================================
*** gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 (Revision 119747)
--- gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 (Arbeitskopie)
*************** contains
*** 16,28 ****
subroutine init2(x)
integer, allocatable, intent(in) :: x(:)
! allocate(x(3)) ! { dg-error "Can't allocate" }
end subroutine init2
subroutine kill(x)
integer, allocatable, intent(in) :: x(:)
! deallocate(x) ! { dg-error "Can't deallocate" }
end subroutine kill
end program alloc_dummy
--- 16,28 ----
subroutine init2(x)
integer, allocatable, intent(in) :: x(:)
! allocate(x(3)) ! { dg-error "Cannot allocate" }
end subroutine init2
subroutine kill(x)
integer, allocatable, intent(in) :: x(:)
! deallocate(x) ! { dg-error "Cannot deallocate" }
end subroutine kill
end program alloc_dummy
Index: gcc/testsuite/gfortran.dg/pointer_intent_1.f90
===================================================================
*** gcc/testsuite/gfortran.dg/pointer_intent_1.f90 (Revision 0)
--- gcc/testsuite/gfortran.dg/pointer_intent_1.f90 (Revision 0)
***************
*** 0 ****
--- 1,71 ----
+ ! { dg-run }
+ ! { dg-options "-std=f2003 -fall-intrinsics" }
+ ! Pointer intent test
+ ! PR fortran/29624
+ !
+ ! Valid program
+ program test
+ implicit none
+ type myT
+ integer :: x
+ integer, pointer :: point
+ end type myT
+ integer, pointer :: p
+ type(myT), pointer :: t
+ type(myT) :: t2
+ allocate(p,t)
+ allocate(t%point)
+ t%point = 55
+ p = 33
+ call a(p,t)
+ deallocate(p)
+ nullify(p)
+ call a(p,t)
+ call nonpointer(t2)
+ contains
+ subroutine a(p,t)
+ integer, pointer,intent(in) :: p
+ type(myT), pointer, intent(in) :: t
+ integer, pointer :: tmp
+ if(.not.associated(p)) return
+ if(p /= 33) call abort()
+ p = 7
+ if (associated(t)) then
+ ! allocating is valid as we don't change the status
+ ! of the pointer "t", only of it's target
+ t%x = -15
+ if(.not.associated(t%point)) call abort()
+ if(t%point /= 55) call abort()
+ nullify(t%point)
+ allocate(tmp)
+ t%point => tmp
+ deallocate(t%point)
+ t%point => null(t%point)
+ tmp => null(tmp)
+ allocate(t%point)
+ t%point = 27
+ if(t%point /= 27) call abort()
+ if(t%x /= -15) call abort()
+ call foo(t)
+ if(t%x /= 32) call abort()
+ if(t%point /= -98) call abort()
+ end if
+ call b(p)
+ if(p /= 5) call abort()
+ end subroutine
+ subroutine b(v)
+ integer, intent(out) :: v
+ v = 5
+ end subroutine b
+ subroutine foo(comp)
+ type(myT), intent(inout) :: comp
+ if(comp%x /= -15) call abort()
+ !if(comp%point /= 27) call abort()
+ comp%x = 32
+ comp%point = -98
+ end subroutine foo
+ subroutine nonpointer(t)
+ type(myT), intent(in) :: t
+ t%point = 7
+ end subroutine nonpointer
+ end program
Index: gcc/testsuite/gfortran.dg/pointer_intent_2.f90
===================================================================
*** gcc/testsuite/gfortran.dg/pointer_intent_2.f90 (Revision 0)
--- gcc/testsuite/gfortran.dg/pointer_intent_2.f90 (Revision 0)
***************
*** 0 ****
--- 1,19 ----
+ ! { dg-compile }
+ ! { dg-options "-std=f95" }
+ ! { dg-shouldfail "Fortran 2003 feature with -std=f95" }
+ !
+ ! Pointer intent test
+ ! PR fortran/29624
+ !
+ ! Fortran 2003 features in Fortran 95
+ program test
+ implicit none
+ integer, pointer :: p
+ allocate(p)
+ p = 33
+ call a(p) ! { dg-error "Type/rank mismatch in argument" }
+ contains
+ subroutine a(p)! { dg-error "has no IMPLICIT type" }
+ integer, pointer,intent(in) :: p ! { dg-error "POINTER attribute with INTENT attribute" }
+ end subroutine
+ end program
Index: gcc/testsuite/gfortran.dg/pointer_intent_3.f90
===================================================================
*** gcc/testsuite/gfortran.dg/pointer_intent_3.f90 (Revision 0)
--- gcc/testsuite/gfortran.dg/pointer_intent_3.f90 (Revision 0)
***************
*** 0 ****
--- 1,41 ----
+ ! { dg-compile }
+ ! { dg-options "-std=f2003 -fall-intrinsics" }
+ ! { dg-shouldfail "Invalid code" }
+ !
+ ! Pointer intent test
+ ! PR fortran/29624
+ !
+ ! Valid program
+ program test
+ implicit none
+ type myT
+ integer :: j = 5
+ integer, pointer :: jp => null()
+ end type myT
+ integer, pointer :: p
+ type(myT) :: t
+ call a(p)
+ call b(t)
+ contains
+ subroutine a(p)
+ integer, pointer,intent(in) :: p
+ p => null(p)! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ nullify(p) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ allocate(p) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" }
+ call c(p) ! { dg-error "is INTENT\\(IN\\) while interface specifies INTENT\\(INOUT\\)" }
+ deallocate(p) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" }
+ end subroutine
+ subroutine c(p)
+ integer, pointer, intent(inout) :: p
+ nullify(p)
+ end subroutine c
+ subroutine b(t)
+ type(myT),intent(in) :: t
+ t%jp = 5
+ t%jp => null(t%jp) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ nullify(t%jp) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ t%j = 7 ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ allocate(t%jp) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" }
+ deallocate(t%jp) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" }
+ end subroutine b
+ end program
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patches,fortran] Add POINTER INTENT(*) support (PR29624)
2006-12-12 11:20 [patches,fortran] Add POINTER INTENT(*) support (PR29624) Tobias Burnus
@ 2006-12-17 22:13 ` Tobias Burnus
2006-12-27 11:24 ` Tobias Burnus
0 siblings, 1 reply; 7+ messages in thread
From: Tobias Burnus @ 2006-12-17 22:13 UTC (permalink / raw)
To: Tobias Burnus; +Cc: 'fortran@gcc.gnu.org', gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1409 bytes --]
Hi,
modified patch; the change in resolve_deallocate_exp caused the
following regression:
deallocate(pointerToArray(0))
was accepted, which provoked later an ICE. With the following change
(interdiff) this it detected. I added also a check to the test suite to
make sure this does not happen again.
Regression tested on x86_64-unknown-linux-gnu.
Tobias
INTERDIFF:
diff -u gcc/fortran/resolve.c gcc/fortran/resolve.c
--- gcc/fortran/resolve.c (Arbeitskopie)
+++ gcc/fortran/resolve.c (Arbeitskopie)
@@ -3317,6 +3317,7 @@
static try
resolve_deallocate_expr (gfc_expr * e)
{
+ symbol_attribute attr;
int allocatable, pointer, check_intent_in;
gfc_ref *ref;
@@ -3356,7 +3357,9 @@
}
}
- if (allocatable == 0 && pointer == 0)
+ attr = gfc_expr_attr (e);
+
+ if (allocatable == 0 && attr.pointer == 0)
{
bad:
gfc_error ("Expression in DEALLOCATE statement at %L must be "
only in patch2:
unchanged:
--- gcc/testsuite/gfortran.dg/alloc_alloc_expr_1.f90 (Revision 119989)
+++ gcc/testsuite/gfortran.dg/alloc_alloc_expr_1.f90 (Arbeitskopie)
@@ -24,6 +24,8 @@
ALLOCATE(PTR,ALLOCS(PTR)) ! { dg-error "same ALLOCATE statement" }
- print *, 'This program has three errors', PTR, ALLOC(1)
+ deallocate(ALLOCS(1)) ! { dg-error "must be ALLOCATABLE or a POINTER" }
+
+ print *, 'This program has four errors', PTR, ALLOC(1)
end program fc011
[-- Attachment #2: pointer-intent2.diff --]
[-- Type: text/x-patch, Size: 18574 bytes --]
fortran/
2006-12-12 Tobias Burnus <burnus@net-b.de>
PR fortran/29624
* interface.c (compare_parameter_intent): New function.
(check_intents): Support pointer intents.
* symbol.c (check_conflict): Support pointer intents,
better conflict_std message.
* expr.c (gfc_check_assign,gfc_check_pointer_assign):
Support pointer intents.
* resolve.c (resolve_deallocate_expr,resolve_allocate_expr):
Support pointer intents.
testsuite/
2006-12-12 Tobias Burnus <burnus@net-b.de>
PR fortran/29624
* gfortran.dg/alloc_alloc_expr_1.f90: Add check for
invalid deallocate.
* gfortran.dg/allocatable_dummy_2.f90: Update dg-error.
* gfortran.dg/protected_4.f90: Add pointer intent check.
* gfortran.dg/protected_6.f90: Add pointer intent check.
* gfortran.dg/pointer_intent_1.f90: New test.
* gfortran.dg/pointer_intent_2.f90: New test.
* gfortran.dg/pointer_intent_3.f90: New test.
Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c (Revision 119993)
+++ gcc/fortran/interface.c (Arbeitskopie)
@@ -1648,6 +1648,28 @@
}
+/* Given a symbol of a formal argument list and an expression, see if
+ their intents are compatible. Returns nonzero if compatible,
+ zero if not compatible. */
+
+static int
+compare_parameter_intent (gfc_symbol * formal, gfc_expr * actual)
+{
+ if (actual->symtree->n.sym->attr.pointer
+ && !formal->attr.pointer)
+ return 1;
+
+ if (actual->symtree->n.sym->attr.intent != INTENT_IN)
+ return 1;
+
+ if (formal->attr.intent == INTENT_INOUT
+ || formal->attr.intent == INTENT_OUT)
+ return 0;
+
+ return 1;
+}
+
+
/* Given formal and actual argument lists that correspond to one
another, check that they are compatible in the sense that intents
are not mismatched. */
@@ -1655,7 +1677,7 @@
static try
check_intents (gfc_formal_arglist * f, gfc_actual_arglist * a)
{
- sym_intent a_intent, f_intent;
+ sym_intent f_intent;
for (;; f = f->next, a = a->next)
{
@@ -1667,12 +1689,9 @@
if (a->expr == NULL || a->expr->expr_type != EXPR_VARIABLE)
continue;
- a_intent = a->expr->symtree->n.sym->attr.intent;
f_intent = f->sym->attr.intent;
- if (a_intent == INTENT_IN
- && (f_intent == INTENT_INOUT
- || f_intent == INTENT_OUT))
+ if (!compare_parameter_intent(f->sym, a->expr))
{
gfc_error ("Procedure argument at %L is INTENT(IN) while interface "
Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c (Revision 119993)
+++ gcc/fortran/symbol.c (Arbeitskopie)
@@ -288,7 +288,8 @@
{
a1 = pointer;
a2 = intent;
- goto conflict;
+ standard = GFC_STD_F2003;
+ goto conflict_std;
}
/* Check for attributes not allowed in a BLOCK DATA. */
@@ -571,14 +572,18 @@
conflict_std:
if (name == NULL)
{
- return gfc_notify_std (standard, "In the selected standard, %s attribute "
- "conflicts with %s attribute at %L", a1, a2,
- where);
+ return gfc_notify_std (standard, "%s: %s attribute with %s attribute "
+ "at %L",
+ (standard == GFC_STD_F2003)
+ ? "Fortran 2003" : "Not in the selected standard",
+ a1, a2, where);
}
else
{
- return gfc_notify_std (standard, "In the selected standard, %s attribute "
- "conflicts with %s attribute in '%s' at %L",
+ return gfc_notify_std (standard, "%s: %s attribute with %s attribute "
+ "in '%s' at %L",
+ (standard == GFC_STD_F2003)
+ ? "Fortran 2003" : "Not in the selected standard",
a1, a2, name, where);
}
}
Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c (Revision 119993)
+++ gcc/fortran/expr.c (Arbeitskopie)
@@ -2188,12 +2188,25 @@
gfc_check_assign (gfc_expr * lvalue, gfc_expr * rvalue, int conform)
{
gfc_symbol *sym;
+ gfc_ref *ref;
+ int has_pointer;
sym = lvalue->symtree->n.sym;
- if (sym->attr.intent == INTENT_IN)
+ /* Check INTENT(IN), unless the object itself of higher up in the
+ hierarchy is a pointer. */
+ has_pointer = sym->attr.pointer;
+
+ for (ref = lvalue->ref; ref; ref = ref->next)
+ if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
+ {
+ has_pointer = 1;
+ break;
+ }
+
+ if (!has_pointer && sym->attr.intent == INTENT_IN)
{
- gfc_error ("Can't assign to INTENT(IN) variable '%s' at %L",
+ gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L",
sym->name, &lvalue->where);
return FAILURE;
}
@@ -2318,7 +2331,9 @@
gfc_check_pointer_assign (gfc_expr * lvalue, gfc_expr * rvalue)
{
symbol_attribute attr;
+ gfc_ref *ref;
int is_pure;
+ int pointer, check_intent_in;
if (lvalue->symtree->n.sym->ts.type == BT_UNKNOWN)
{
@@ -2336,8 +2351,29 @@
return FAILURE;
}
- attr = gfc_variable_attr (lvalue, NULL);
- if (!attr.pointer)
+
+ /* Check INTENT(IN), unless the object itself of higher up in the
+ hierarchy is a pointer. */
+ check_intent_in = 1;
+ pointer = lvalue->symtree->n.sym->attr.pointer;
+
+ for (ref = lvalue->ref; ref; ref = ref->next)
+ {
+ if (pointer)
+ check_intent_in = 0;
+
+ if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
+ pointer = 1;
+ }
+
+ if (check_intent_in && lvalue->symtree->n.sym->attr.intent == INTENT_IN)
+ {
+ gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L",
+ lvalue->symtree->n.sym->name, &lvalue->where);
+ return FAILURE;
+ }
+
+ if (!pointer)
{
gfc_error ("Pointer assignment to non-POINTER at %L", &lvalue->where);
return FAILURE;
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c (Revision 119993)
+++ gcc/fortran/resolve.c (Arbeitskopie)
@@ -3318,48 +3318,58 @@
resolve_deallocate_expr (gfc_expr * e)
{
symbol_attribute attr;
- int allocatable;
+ int allocatable, pointer, check_intent_in;
gfc_ref *ref;
+ /* Check INTENT(IN), unless an object higher up in the
+ hierarchy is a pointer. */
+ check_intent_in = 1;
+
if (gfc_resolve_expr (e) == FAILURE)
return FAILURE;
- attr = gfc_expr_attr (e);
- if (attr.pointer)
- return SUCCESS;
-
if (e->expr_type != EXPR_VARIABLE)
goto bad;
allocatable = e->symtree->n.sym->attr.allocatable;
+ pointer = e->symtree->n.sym->attr.pointer;
for (ref = e->ref; ref; ref = ref->next)
- switch (ref->type)
- {
- case REF_ARRAY:
- if (ref->u.ar.type != AR_FULL)
- allocatable = 0;
- break;
+ {
+ if (pointer)
+ check_intent_in = 0;
- case REF_COMPONENT:
- allocatable = (ref->u.c.component->as != NULL
- && ref->u.c.component->as->type == AS_DEFERRED);
- break;
+ switch (ref->type)
+ {
+ case REF_ARRAY:
+ if (ref->u.ar.type != AR_FULL)
+ allocatable = 0;
+ break;
- case REF_SUBSTRING:
- allocatable = 0;
- break;
- }
+ case REF_COMPONENT:
+ allocatable = (ref->u.c.component->as != NULL
+ && ref->u.c.component->as->type == AS_DEFERRED);
+ pointer = ref->u.c.component->pointer;
+ break;
+
+ case REF_SUBSTRING:
+ allocatable = 0;
+ break;
+ }
+ }
- if (allocatable == 0)
+ attr = gfc_expr_attr (e);
+
+ if (allocatable == 0 && attr.pointer == 0)
{
bad:
gfc_error ("Expression in DEALLOCATE statement at %L must be "
"ALLOCATABLE or a POINTER", &e->where);
}
- if (e->symtree->n.sym->attr.intent == INTENT_IN)
+ if (check_intent_in
+ && e->symtree->n.sym->attr.intent == INTENT_IN)
{
- gfc_error ("Can't deallocate INTENT(IN) variable '%s' at %L",
+ gfc_error ("Cannot deallocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
@@ -3481,7 +3491,7 @@
static try
resolve_allocate_expr (gfc_expr * e, gfc_code * code)
{
- int i, pointer, allocatable, dimension;
+ int i, pointer, allocatable, dimension, check_intent_in;
symbol_attribute attr;
gfc_ref *ref, *ref2;
gfc_array_ref *ar;
@@ -3490,6 +3500,10 @@
gfc_symbol *sym;
gfc_alloc *a;
+ /* Check INTENT(IN), unless an object higher up in the
+ hierarchy is a pointer. */
+ check_intent_in = 1;
+
if (gfc_resolve_expr (e) == FAILURE)
return FAILURE;
@@ -3527,26 +3541,31 @@
}
for (ref = e->ref; ref; ref2 = ref, ref = ref->next)
- switch (ref->type)
- {
- case REF_ARRAY:
- if (ref->next != NULL)
- pointer = 0;
- break;
-
- case REF_COMPONENT:
- allocatable = (ref->u.c.component->as != NULL
- && ref->u.c.component->as->type == AS_DEFERRED);
-
- pointer = ref->u.c.component->pointer;
- dimension = ref->u.c.component->dimension;
- break;
+ {
+ if (pointer)
+ check_intent_in = 0;
- case REF_SUBSTRING:
- allocatable = 0;
- pointer = 0;
- break;
- }
+ switch (ref->type)
+ {
+ case REF_ARRAY:
+ if (ref->next != NULL)
+ pointer = 0;
+ break;
+
+ case REF_COMPONENT:
+ allocatable = (ref->u.c.component->as != NULL
+ && ref->u.c.component->as->type == AS_DEFERRED);
+
+ pointer = ref->u.c.component->pointer;
+ dimension = ref->u.c.component->dimension;
+ break;
+
+ case REF_SUBSTRING:
+ allocatable = 0;
+ pointer = 0;
+ break;
+ }
+ }
}
if (allocatable == 0 && pointer == 0)
@@ -3556,9 +3575,10 @@
return FAILURE;
}
- if (e->symtree->n.sym->attr.intent == INTENT_IN)
+ if (check_intent_in
+ && e->symtree->n.sym->attr.intent == INTENT_IN)
{
- gfc_error ("Can't allocate INTENT(IN) variable '%s' at %L",
+ gfc_error ("Cannot allocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
Index: gcc/testsuite/gfortran.dg/protected_4.f90
===================================================================
--- gcc/testsuite/gfortran.dg/protected_4.f90 (Revision 119989)
+++ gcc/testsuite/gfortran.dg/protected_4.f90 (Arbeitskopie)
@@ -21,6 +21,7 @@
use protmod
implicit none
integer :: j
+ logical :: asgnd
protected :: j ! { dg-error "only allowed in specification part of a module" }
a = 43 ! { dg-error "Assigning to PROTECTED variable" }
ap => null() ! { dg-error "Assigning to PROTECTED variable" }
@@ -30,6 +31,8 @@
allocate(ap) ! { dg-error "Assigning to PROTECTED variable" }
ap = 73 ! { dg-error "Assigning to PROTECTED variable" }
call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" }
+ call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" }
+ asgnd = pointer_check(ap)
contains
subroutine increment(a1,a3)
integer, intent(inout) :: a1, a3
@@ -37,9 +40,14 @@
a3 = a3 + 1
end subroutine increment
subroutine pointer_assignments(p)
- integer, pointer :: p ! with [pointer] intent(out)
- p => null() ! this is invalid
+ integer, pointer,intent(out) :: p
+ p => null()
end subroutine pointer_assignments
+ function pointer_check(p)
+ integer, pointer,intent(in) :: p
+ logical :: pointer_check
+ pointer_check = associated(p)
+ end function pointer_check
end program main
module test
Index: gcc/testsuite/gfortran.dg/protected_6.f90
===================================================================
--- gcc/testsuite/gfortran.dg/protected_6.f90 (Revision 119989)
+++ gcc/testsuite/gfortran.dg/protected_6.f90 (Arbeitskopie)
@@ -27,6 +27,7 @@
allocate(ap) ! { dg-error "Assigning to PROTECTED variable" }
ap = 73 ! { dg-error "Assigning to PROTECTED variable" }
call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" }
+ call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" }
contains
subroutine increment(a1,a3)
integer, intent(inout) :: a1, a3
@@ -34,8 +35,8 @@
a3 = a3 + 1
end subroutine increment
subroutine pointer_assignments(p)
- integer, pointer :: p ! with [pointer] intent(out)
- p => null() ! this is invalid
+ integer, pointer,intent (inout) :: p
+ p => null()
end subroutine pointer_assignments
end program main
Index: gcc/testsuite/gfortran.dg/alloc_alloc_expr_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/alloc_alloc_expr_1.f90 (Revision 119989)
+++ gcc/testsuite/gfortran.dg/alloc_alloc_expr_1.f90 (Arbeitskopie)
@@ -24,6 +24,8 @@
ALLOCATE(PTR,ALLOCS(PTR)) ! { dg-error "same ALLOCATE statement" }
- print *, 'This program has three errors', PTR, ALLOC(1)
+ deallocate(ALLOCS(1)) ! { dg-error "must be ALLOCATABLE or a POINTER" }
+
+ print *, 'This program has four errors', PTR, ALLOC(1)
end program fc011
Index: gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 (Revision 119989)
+++ gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 (Arbeitskopie)
@@ -16,13 +16,13 @@
subroutine init2(x)
integer, allocatable, intent(in) :: x(:)
- allocate(x(3)) ! { dg-error "Can't allocate" }
+ allocate(x(3)) ! { dg-error "Cannot allocate" }
end subroutine init2
subroutine kill(x)
integer, allocatable, intent(in) :: x(:)
- deallocate(x) ! { dg-error "Can't deallocate" }
+ deallocate(x) ! { dg-error "Cannot deallocate" }
end subroutine kill
end program alloc_dummy
Index: gcc/testsuite/gfortran.dg/pointer_intent_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pointer_intent_1.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/pointer_intent_1.f90 (Revision 0)
@@ -0,0 +1,71 @@
+! { dg-run }
+! { dg-options "-std=f2003 -fall-intrinsics" }
+! Pointer intent test
+! PR fortran/29624
+!
+! Valid program
+program test
+ implicit none
+ type myT
+ integer :: x
+ integer, pointer :: point
+ end type myT
+ integer, pointer :: p
+ type(myT), pointer :: t
+ type(myT) :: t2
+ allocate(p,t)
+ allocate(t%point)
+ t%point = 55
+ p = 33
+ call a(p,t)
+ deallocate(p)
+ nullify(p)
+ call a(p,t)
+ call nonpointer(t2)
+contains
+ subroutine a(p,t)
+ integer, pointer,intent(in) :: p
+ type(myT), pointer, intent(in) :: t
+ integer, pointer :: tmp
+ if(.not.associated(p)) return
+ if(p /= 33) call abort()
+ p = 7
+ if (associated(t)) then
+ ! allocating is valid as we don't change the status
+ ! of the pointer "t", only of it's target
+ t%x = -15
+ if(.not.associated(t%point)) call abort()
+ if(t%point /= 55) call abort()
+ nullify(t%point)
+ allocate(tmp)
+ t%point => tmp
+ deallocate(t%point)
+ t%point => null(t%point)
+ tmp => null(tmp)
+ allocate(t%point)
+ t%point = 27
+ if(t%point /= 27) call abort()
+ if(t%x /= -15) call abort()
+ call foo(t)
+ if(t%x /= 32) call abort()
+ if(t%point /= -98) call abort()
+ end if
+ call b(p)
+ if(p /= 5) call abort()
+ end subroutine
+ subroutine b(v)
+ integer, intent(out) :: v
+ v = 5
+ end subroutine b
+ subroutine foo(comp)
+ type(myT), intent(inout) :: comp
+ if(comp%x /= -15) call abort()
+ !if(comp%point /= 27) call abort()
+ comp%x = 32
+ comp%point = -98
+ end subroutine foo
+ subroutine nonpointer(t)
+ type(myT), intent(in) :: t
+ t%point = 7
+ end subroutine nonpointer
+end program
Index: gcc/testsuite/gfortran.dg/pointer_intent_2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pointer_intent_2.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/pointer_intent_2.f90 (Revision 0)
@@ -0,0 +1,19 @@
+! { dg-compile }
+! { dg-options "-std=f95" }
+! { dg-shouldfail "Fortran 2003 feature with -std=f95" }
+!
+! Pointer intent test
+! PR fortran/29624
+!
+! Fortran 2003 features in Fortran 95
+program test
+ implicit none
+ integer, pointer :: p
+ allocate(p)
+ p = 33
+ call a(p) ! { dg-error "Type/rank mismatch in argument" }
+contains
+ subroutine a(p)! { dg-error "has no IMPLICIT type" }
+ integer, pointer,intent(in) :: p ! { dg-error "POINTER attribute with INTENT attribute" }
+ end subroutine
+end program
Index: gcc/testsuite/gfortran.dg/pointer_intent_3.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pointer_intent_3.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/pointer_intent_3.f90 (Revision 0)
@@ -0,0 +1,41 @@
+! { dg-compile }
+! { dg-options "-std=f2003 -fall-intrinsics" }
+! { dg-shouldfail "Invalid code" }
+!
+! Pointer intent test
+! PR fortran/29624
+!
+! Valid program
+program test
+ implicit none
+ type myT
+ integer :: j = 5
+ integer, pointer :: jp => null()
+ end type myT
+ integer, pointer :: p
+ type(myT) :: t
+ call a(p)
+ call b(t)
+contains
+ subroutine a(p)
+ integer, pointer,intent(in) :: p
+ p => null(p)! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ nullify(p) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ allocate(p) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" }
+ call c(p) ! { dg-error "is INTENT\\(IN\\) while interface specifies INTENT\\(INOUT\\)" }
+ deallocate(p) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" }
+ end subroutine
+ subroutine c(p)
+ integer, pointer, intent(inout) :: p
+ nullify(p)
+ end subroutine c
+ subroutine b(t)
+ type(myT),intent(in) :: t
+ t%jp = 5
+ t%jp => null(t%jp) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ nullify(t%jp) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ t%j = 7 ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ allocate(t%jp) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" }
+ deallocate(t%jp) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" }
+ end subroutine b
+end program
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patches,fortran] Add POINTER INTENT(*) support (PR29624)
2006-12-17 22:13 ` Tobias Burnus
@ 2006-12-27 11:24 ` Tobias Burnus
2006-12-27 16:04 ` Paul Thomas
0 siblings, 1 reply; 7+ messages in thread
From: Tobias Burnus @ 2006-12-27 11:24 UTC (permalink / raw)
Cc: 'fortran@gcc.gnu.org', gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1405 bytes --]
* PING *
Tobias
PS: Somewhat late I wish Merry Christmas and - still in time - a happy
New Year to all!
Tobias Burnus wrote:
>> The standard can be found at
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29624#c0
>>
>> In a nutshell: With intent(in) the pointer dummy argument's association
>> shall not be changed, the target may.
>>
>> Thanks to Tobias S. for pointing out that I was looking at the wrong
>> thing in terms of attributes.
>>
>> Quick remark to compound structures:
>> - If the last subobject is a pointer & its association is changed, I
>> check whether somewhere higher up in the hierarchy is already a pointer,
>> because then the subobject is a target of that one. => Modification allowed.
>> - If the last subobject is a pointer & its value target value is changed
>> => Modification always allowed
>> - If the last subobject is a nonpointer: Check whether somewhere higher
>> up in the hierarchy is already a pointer, because then the subobject is
>> a target of that one. => Modification allowed.
>
> modified patch; the change in resolve_deallocate_exp caused the following regression:
>
> deallocate(pointerToArray(0))
>
> was accepted, which provoked later an ICE. With the following change
> (interdiff) this it detected. I added also a check to the test suite to
> make sure this does not happen again.
>
> Regression tested on x86_64-unknown-linux-gnu.
>
> Tobias
>
[-- Attachment #2: pointer-intent2.diff --]
[-- Type: text/x-patch, Size: 18574 bytes --]
fortran/
2006-12-12 Tobias Burnus <burnus@net-b.de>
PR fortran/29624
* interface.c (compare_parameter_intent): New function.
(check_intents): Support pointer intents.
* symbol.c (check_conflict): Support pointer intents,
better conflict_std message.
* expr.c (gfc_check_assign,gfc_check_pointer_assign):
Support pointer intents.
* resolve.c (resolve_deallocate_expr,resolve_allocate_expr):
Support pointer intents.
testsuite/
2006-12-12 Tobias Burnus <burnus@net-b.de>
PR fortran/29624
* gfortran.dg/alloc_alloc_expr_1.f90: Add check for
invalid deallocate.
* gfortran.dg/allocatable_dummy_2.f90: Update dg-error.
* gfortran.dg/protected_4.f90: Add pointer intent check.
* gfortran.dg/protected_6.f90: Add pointer intent check.
* gfortran.dg/pointer_intent_1.f90: New test.
* gfortran.dg/pointer_intent_2.f90: New test.
* gfortran.dg/pointer_intent_3.f90: New test.
Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c (Revision 119993)
+++ gcc/fortran/interface.c (Arbeitskopie)
@@ -1648,6 +1648,28 @@
}
+/* Given a symbol of a formal argument list and an expression, see if
+ their intents are compatible. Returns nonzero if compatible,
+ zero if not compatible. */
+
+static int
+compare_parameter_intent (gfc_symbol * formal, gfc_expr * actual)
+{
+ if (actual->symtree->n.sym->attr.pointer
+ && !formal->attr.pointer)
+ return 1;
+
+ if (actual->symtree->n.sym->attr.intent != INTENT_IN)
+ return 1;
+
+ if (formal->attr.intent == INTENT_INOUT
+ || formal->attr.intent == INTENT_OUT)
+ return 0;
+
+ return 1;
+}
+
+
/* Given formal and actual argument lists that correspond to one
another, check that they are compatible in the sense that intents
are not mismatched. */
@@ -1655,7 +1677,7 @@
static try
check_intents (gfc_formal_arglist * f, gfc_actual_arglist * a)
{
- sym_intent a_intent, f_intent;
+ sym_intent f_intent;
for (;; f = f->next, a = a->next)
{
@@ -1667,12 +1689,9 @@
if (a->expr == NULL || a->expr->expr_type != EXPR_VARIABLE)
continue;
- a_intent = a->expr->symtree->n.sym->attr.intent;
f_intent = f->sym->attr.intent;
- if (a_intent == INTENT_IN
- && (f_intent == INTENT_INOUT
- || f_intent == INTENT_OUT))
+ if (!compare_parameter_intent(f->sym, a->expr))
{
gfc_error ("Procedure argument at %L is INTENT(IN) while interface "
Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c (Revision 119993)
+++ gcc/fortran/symbol.c (Arbeitskopie)
@@ -288,7 +288,8 @@
{
a1 = pointer;
a2 = intent;
- goto conflict;
+ standard = GFC_STD_F2003;
+ goto conflict_std;
}
/* Check for attributes not allowed in a BLOCK DATA. */
@@ -571,14 +572,18 @@
conflict_std:
if (name == NULL)
{
- return gfc_notify_std (standard, "In the selected standard, %s attribute "
- "conflicts with %s attribute at %L", a1, a2,
- where);
+ return gfc_notify_std (standard, "%s: %s attribute with %s attribute "
+ "at %L",
+ (standard == GFC_STD_F2003)
+ ? "Fortran 2003" : "Not in the selected standard",
+ a1, a2, where);
}
else
{
- return gfc_notify_std (standard, "In the selected standard, %s attribute "
- "conflicts with %s attribute in '%s' at %L",
+ return gfc_notify_std (standard, "%s: %s attribute with %s attribute "
+ "in '%s' at %L",
+ (standard == GFC_STD_F2003)
+ ? "Fortran 2003" : "Not in the selected standard",
a1, a2, name, where);
}
}
Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c (Revision 119993)
+++ gcc/fortran/expr.c (Arbeitskopie)
@@ -2188,12 +2188,25 @@
gfc_check_assign (gfc_expr * lvalue, gfc_expr * rvalue, int conform)
{
gfc_symbol *sym;
+ gfc_ref *ref;
+ int has_pointer;
sym = lvalue->symtree->n.sym;
- if (sym->attr.intent == INTENT_IN)
+ /* Check INTENT(IN), unless the object itself of higher up in the
+ hierarchy is a pointer. */
+ has_pointer = sym->attr.pointer;
+
+ for (ref = lvalue->ref; ref; ref = ref->next)
+ if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
+ {
+ has_pointer = 1;
+ break;
+ }
+
+ if (!has_pointer && sym->attr.intent == INTENT_IN)
{
- gfc_error ("Can't assign to INTENT(IN) variable '%s' at %L",
+ gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L",
sym->name, &lvalue->where);
return FAILURE;
}
@@ -2318,7 +2331,9 @@
gfc_check_pointer_assign (gfc_expr * lvalue, gfc_expr * rvalue)
{
symbol_attribute attr;
+ gfc_ref *ref;
int is_pure;
+ int pointer, check_intent_in;
if (lvalue->symtree->n.sym->ts.type == BT_UNKNOWN)
{
@@ -2336,8 +2351,29 @@
return FAILURE;
}
- attr = gfc_variable_attr (lvalue, NULL);
- if (!attr.pointer)
+
+ /* Check INTENT(IN), unless the object itself of higher up in the
+ hierarchy is a pointer. */
+ check_intent_in = 1;
+ pointer = lvalue->symtree->n.sym->attr.pointer;
+
+ for (ref = lvalue->ref; ref; ref = ref->next)
+ {
+ if (pointer)
+ check_intent_in = 0;
+
+ if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
+ pointer = 1;
+ }
+
+ if (check_intent_in && lvalue->symtree->n.sym->attr.intent == INTENT_IN)
+ {
+ gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L",
+ lvalue->symtree->n.sym->name, &lvalue->where);
+ return FAILURE;
+ }
+
+ if (!pointer)
{
gfc_error ("Pointer assignment to non-POINTER at %L", &lvalue->where);
return FAILURE;
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c (Revision 119993)
+++ gcc/fortran/resolve.c (Arbeitskopie)
@@ -3318,48 +3318,58 @@
resolve_deallocate_expr (gfc_expr * e)
{
symbol_attribute attr;
- int allocatable;
+ int allocatable, pointer, check_intent_in;
gfc_ref *ref;
+ /* Check INTENT(IN), unless an object higher up in the
+ hierarchy is a pointer. */
+ check_intent_in = 1;
+
if (gfc_resolve_expr (e) == FAILURE)
return FAILURE;
- attr = gfc_expr_attr (e);
- if (attr.pointer)
- return SUCCESS;
-
if (e->expr_type != EXPR_VARIABLE)
goto bad;
allocatable = e->symtree->n.sym->attr.allocatable;
+ pointer = e->symtree->n.sym->attr.pointer;
for (ref = e->ref; ref; ref = ref->next)
- switch (ref->type)
- {
- case REF_ARRAY:
- if (ref->u.ar.type != AR_FULL)
- allocatable = 0;
- break;
+ {
+ if (pointer)
+ check_intent_in = 0;
- case REF_COMPONENT:
- allocatable = (ref->u.c.component->as != NULL
- && ref->u.c.component->as->type == AS_DEFERRED);
- break;
+ switch (ref->type)
+ {
+ case REF_ARRAY:
+ if (ref->u.ar.type != AR_FULL)
+ allocatable = 0;
+ break;
- case REF_SUBSTRING:
- allocatable = 0;
- break;
- }
+ case REF_COMPONENT:
+ allocatable = (ref->u.c.component->as != NULL
+ && ref->u.c.component->as->type == AS_DEFERRED);
+ pointer = ref->u.c.component->pointer;
+ break;
+
+ case REF_SUBSTRING:
+ allocatable = 0;
+ break;
+ }
+ }
- if (allocatable == 0)
+ attr = gfc_expr_attr (e);
+
+ if (allocatable == 0 && attr.pointer == 0)
{
bad:
gfc_error ("Expression in DEALLOCATE statement at %L must be "
"ALLOCATABLE or a POINTER", &e->where);
}
- if (e->symtree->n.sym->attr.intent == INTENT_IN)
+ if (check_intent_in
+ && e->symtree->n.sym->attr.intent == INTENT_IN)
{
- gfc_error ("Can't deallocate INTENT(IN) variable '%s' at %L",
+ gfc_error ("Cannot deallocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
@@ -3481,7 +3491,7 @@
static try
resolve_allocate_expr (gfc_expr * e, gfc_code * code)
{
- int i, pointer, allocatable, dimension;
+ int i, pointer, allocatable, dimension, check_intent_in;
symbol_attribute attr;
gfc_ref *ref, *ref2;
gfc_array_ref *ar;
@@ -3490,6 +3500,10 @@
gfc_symbol *sym;
gfc_alloc *a;
+ /* Check INTENT(IN), unless an object higher up in the
+ hierarchy is a pointer. */
+ check_intent_in = 1;
+
if (gfc_resolve_expr (e) == FAILURE)
return FAILURE;
@@ -3527,26 +3541,31 @@
}
for (ref = e->ref; ref; ref2 = ref, ref = ref->next)
- switch (ref->type)
- {
- case REF_ARRAY:
- if (ref->next != NULL)
- pointer = 0;
- break;
-
- case REF_COMPONENT:
- allocatable = (ref->u.c.component->as != NULL
- && ref->u.c.component->as->type == AS_DEFERRED);
-
- pointer = ref->u.c.component->pointer;
- dimension = ref->u.c.component->dimension;
- break;
+ {
+ if (pointer)
+ check_intent_in = 0;
- case REF_SUBSTRING:
- allocatable = 0;
- pointer = 0;
- break;
- }
+ switch (ref->type)
+ {
+ case REF_ARRAY:
+ if (ref->next != NULL)
+ pointer = 0;
+ break;
+
+ case REF_COMPONENT:
+ allocatable = (ref->u.c.component->as != NULL
+ && ref->u.c.component->as->type == AS_DEFERRED);
+
+ pointer = ref->u.c.component->pointer;
+ dimension = ref->u.c.component->dimension;
+ break;
+
+ case REF_SUBSTRING:
+ allocatable = 0;
+ pointer = 0;
+ break;
+ }
+ }
}
if (allocatable == 0 && pointer == 0)
@@ -3556,9 +3575,10 @@
return FAILURE;
}
- if (e->symtree->n.sym->attr.intent == INTENT_IN)
+ if (check_intent_in
+ && e->symtree->n.sym->attr.intent == INTENT_IN)
{
- gfc_error ("Can't allocate INTENT(IN) variable '%s' at %L",
+ gfc_error ("Cannot allocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
Index: gcc/testsuite/gfortran.dg/protected_4.f90
===================================================================
--- gcc/testsuite/gfortran.dg/protected_4.f90 (Revision 119989)
+++ gcc/testsuite/gfortran.dg/protected_4.f90 (Arbeitskopie)
@@ -21,6 +21,7 @@
use protmod
implicit none
integer :: j
+ logical :: asgnd
protected :: j ! { dg-error "only allowed in specification part of a module" }
a = 43 ! { dg-error "Assigning to PROTECTED variable" }
ap => null() ! { dg-error "Assigning to PROTECTED variable" }
@@ -30,6 +31,8 @@
allocate(ap) ! { dg-error "Assigning to PROTECTED variable" }
ap = 73 ! { dg-error "Assigning to PROTECTED variable" }
call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" }
+ call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" }
+ asgnd = pointer_check(ap)
contains
subroutine increment(a1,a3)
integer, intent(inout) :: a1, a3
@@ -37,9 +40,14 @@
a3 = a3 + 1
end subroutine increment
subroutine pointer_assignments(p)
- integer, pointer :: p ! with [pointer] intent(out)
- p => null() ! this is invalid
+ integer, pointer,intent(out) :: p
+ p => null()
end subroutine pointer_assignments
+ function pointer_check(p)
+ integer, pointer,intent(in) :: p
+ logical :: pointer_check
+ pointer_check = associated(p)
+ end function pointer_check
end program main
module test
Index: gcc/testsuite/gfortran.dg/protected_6.f90
===================================================================
--- gcc/testsuite/gfortran.dg/protected_6.f90 (Revision 119989)
+++ gcc/testsuite/gfortran.dg/protected_6.f90 (Arbeitskopie)
@@ -27,6 +27,7 @@
allocate(ap) ! { dg-error "Assigning to PROTECTED variable" }
ap = 73 ! { dg-error "Assigning to PROTECTED variable" }
call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" }
+ call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" }
contains
subroutine increment(a1,a3)
integer, intent(inout) :: a1, a3
@@ -34,8 +35,8 @@
a3 = a3 + 1
end subroutine increment
subroutine pointer_assignments(p)
- integer, pointer :: p ! with [pointer] intent(out)
- p => null() ! this is invalid
+ integer, pointer,intent (inout) :: p
+ p => null()
end subroutine pointer_assignments
end program main
Index: gcc/testsuite/gfortran.dg/alloc_alloc_expr_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/alloc_alloc_expr_1.f90 (Revision 119989)
+++ gcc/testsuite/gfortran.dg/alloc_alloc_expr_1.f90 (Arbeitskopie)
@@ -24,6 +24,8 @@
ALLOCATE(PTR,ALLOCS(PTR)) ! { dg-error "same ALLOCATE statement" }
- print *, 'This program has three errors', PTR, ALLOC(1)
+ deallocate(ALLOCS(1)) ! { dg-error "must be ALLOCATABLE or a POINTER" }
+
+ print *, 'This program has four errors', PTR, ALLOC(1)
end program fc011
Index: gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 (Revision 119989)
+++ gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 (Arbeitskopie)
@@ -16,13 +16,13 @@
subroutine init2(x)
integer, allocatable, intent(in) :: x(:)
- allocate(x(3)) ! { dg-error "Can't allocate" }
+ allocate(x(3)) ! { dg-error "Cannot allocate" }
end subroutine init2
subroutine kill(x)
integer, allocatable, intent(in) :: x(:)
- deallocate(x) ! { dg-error "Can't deallocate" }
+ deallocate(x) ! { dg-error "Cannot deallocate" }
end subroutine kill
end program alloc_dummy
Index: gcc/testsuite/gfortran.dg/pointer_intent_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pointer_intent_1.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/pointer_intent_1.f90 (Revision 0)
@@ -0,0 +1,71 @@
+! { dg-run }
+! { dg-options "-std=f2003 -fall-intrinsics" }
+! Pointer intent test
+! PR fortran/29624
+!
+! Valid program
+program test
+ implicit none
+ type myT
+ integer :: x
+ integer, pointer :: point
+ end type myT
+ integer, pointer :: p
+ type(myT), pointer :: t
+ type(myT) :: t2
+ allocate(p,t)
+ allocate(t%point)
+ t%point = 55
+ p = 33
+ call a(p,t)
+ deallocate(p)
+ nullify(p)
+ call a(p,t)
+ call nonpointer(t2)
+contains
+ subroutine a(p,t)
+ integer, pointer,intent(in) :: p
+ type(myT), pointer, intent(in) :: t
+ integer, pointer :: tmp
+ if(.not.associated(p)) return
+ if(p /= 33) call abort()
+ p = 7
+ if (associated(t)) then
+ ! allocating is valid as we don't change the status
+ ! of the pointer "t", only of it's target
+ t%x = -15
+ if(.not.associated(t%point)) call abort()
+ if(t%point /= 55) call abort()
+ nullify(t%point)
+ allocate(tmp)
+ t%point => tmp
+ deallocate(t%point)
+ t%point => null(t%point)
+ tmp => null(tmp)
+ allocate(t%point)
+ t%point = 27
+ if(t%point /= 27) call abort()
+ if(t%x /= -15) call abort()
+ call foo(t)
+ if(t%x /= 32) call abort()
+ if(t%point /= -98) call abort()
+ end if
+ call b(p)
+ if(p /= 5) call abort()
+ end subroutine
+ subroutine b(v)
+ integer, intent(out) :: v
+ v = 5
+ end subroutine b
+ subroutine foo(comp)
+ type(myT), intent(inout) :: comp
+ if(comp%x /= -15) call abort()
+ !if(comp%point /= 27) call abort()
+ comp%x = 32
+ comp%point = -98
+ end subroutine foo
+ subroutine nonpointer(t)
+ type(myT), intent(in) :: t
+ t%point = 7
+ end subroutine nonpointer
+end program
Index: gcc/testsuite/gfortran.dg/pointer_intent_2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pointer_intent_2.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/pointer_intent_2.f90 (Revision 0)
@@ -0,0 +1,19 @@
+! { dg-compile }
+! { dg-options "-std=f95" }
+! { dg-shouldfail "Fortran 2003 feature with -std=f95" }
+!
+! Pointer intent test
+! PR fortran/29624
+!
+! Fortran 2003 features in Fortran 95
+program test
+ implicit none
+ integer, pointer :: p
+ allocate(p)
+ p = 33
+ call a(p) ! { dg-error "Type/rank mismatch in argument" }
+contains
+ subroutine a(p)! { dg-error "has no IMPLICIT type" }
+ integer, pointer,intent(in) :: p ! { dg-error "POINTER attribute with INTENT attribute" }
+ end subroutine
+end program
Index: gcc/testsuite/gfortran.dg/pointer_intent_3.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pointer_intent_3.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/pointer_intent_3.f90 (Revision 0)
@@ -0,0 +1,41 @@
+! { dg-compile }
+! { dg-options "-std=f2003 -fall-intrinsics" }
+! { dg-shouldfail "Invalid code" }
+!
+! Pointer intent test
+! PR fortran/29624
+!
+! Valid program
+program test
+ implicit none
+ type myT
+ integer :: j = 5
+ integer, pointer :: jp => null()
+ end type myT
+ integer, pointer :: p
+ type(myT) :: t
+ call a(p)
+ call b(t)
+contains
+ subroutine a(p)
+ integer, pointer,intent(in) :: p
+ p => null(p)! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ nullify(p) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ allocate(p) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" }
+ call c(p) ! { dg-error "is INTENT\\(IN\\) while interface specifies INTENT\\(INOUT\\)" }
+ deallocate(p) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" }
+ end subroutine
+ subroutine c(p)
+ integer, pointer, intent(inout) :: p
+ nullify(p)
+ end subroutine c
+ subroutine b(t)
+ type(myT),intent(in) :: t
+ t%jp = 5
+ t%jp => null(t%jp) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ nullify(t%jp) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ t%j = 7 ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+ allocate(t%jp) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" }
+ deallocate(t%jp) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" }
+ end subroutine b
+end program
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patches,fortran] Add POINTER INTENT(*) support (PR29624)
2006-12-27 11:24 ` Tobias Burnus
@ 2006-12-27 16:04 ` Paul Thomas
2007-01-04 19:49 ` Tobias Burnus
0 siblings, 1 reply; 7+ messages in thread
From: Paul Thomas @ 2006-12-27 16:04 UTC (permalink / raw)
To: Tobias Burnus; +Cc: 'fortran@gcc.gnu.org', gcc-patches
Tobias,
>> Regression tested on x86_64-unknown-linux-gnu.
>>
OK with a couple of questions/niggles....
>>
>> +/* Given a symbol of a formal argument list and an expression, see if
>> + their intents are compatible. Returns nonzero if compatible,
>> + zero if not compatible. */
>> +
>>
"Given a symbol of a formal argument list and an expression, return
non-zero if their intents are compatible, zero otherwise." is a bit more
concise.
>> - return gfc_notify_std (standard, "In the selected standard, %s attribute "
>> - "conflicts with %s attribute at %L", a1, a2,
>> - where);
>> + return gfc_notify_std (standard, "%s: %s attribute with %s attribute "
>> + "at %L",
>> + (standard == GFC_STD_F2003)
>> + ? "Fortran 2003" : "Not in the selected standard",
>> + a1, a2, where);
>>
Is the language support OK with this? I seem to recall that we had some
problems with computed messages.
>> + /* Check INTENT(IN), unless the object itself of higher up in the
>> + hierarchy is a pointer. */
>>
Not only is the symtax a bit odd but I think that , "unless the object
itself is the component or sub-component of a pointer." is clearer.
>> +
>> + /* Check INTENT(IN), unless the object itself of higher up in the
>> + hierarchy is a pointer. */
>>
ditto
>>
>> + /* Check INTENT(IN), unless an object higher up in the
>> + hierarchy is a pointer. */
>>
ditto**2
Thanks!
Paul
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patches,fortran] Add POINTER INTENT(*) support (PR29624)
2006-12-27 16:04 ` Paul Thomas
@ 2007-01-04 19:49 ` Tobias Burnus
2007-01-04 20:51 ` Brooks Moses
0 siblings, 1 reply; 7+ messages in thread
From: Tobias Burnus @ 2007-01-04 19:49 UTC (permalink / raw)
To: Paul Thomas; +Cc: 'fortran@gcc.gnu.org', gcc-patches
Hi,
Paul Thomas wrote:
> OK with a couple of questions/niggles....
>>> + return gfc_notify_std (standard, "%s: %s attribute with %s
>>> attribute "
>>> + "at %L",
>>> + (standard == GFC_STD_F2003)
>>> + ? "Fortran 2003" : "Not in the
>>> selected standard",
>>> + a1, a2, where);
> Is the language support OK with this? I seem to recall that we had
> some problems with computed messages.
I don't know. As (standard == GFC_STD_F2003) is currently always true
and the translation of "Fortran 2003" does not depend on the context, it
should be ok, except that the translator does not know what the first
"%s:" means.
Due to the colon, it should be also ok for "Not in the selected
standard", which makes it effectively two sentences.
But I'm not a specialist for l18n/i10n.
(Really problematic are strings like
"There are %s items missing", (x?"one" : "two")
as the translation of "one" is context dependent, e.g. French
"un"/"une", German "ein"/"eine"/"eins")
I'll submit it tomorrow as above, unless someone objects or has a better
suggestion.
>>> + /* Check INTENT(IN), unless the object itself of higher up in the
>>> + hierarchy is a pointer. */
>>>
> Not only is the symtax a bit odd but I think that , "unless the object
> itself is the component or sub-component of a pointer." is clearer.
(I should have re-read the comments, the syntax is odd indeed; even with
"or" it is barely decipherable.)
> Thanks!
Thanks for reviewing the patch!
Tobias
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patches,fortran] Add POINTER INTENT(*) support (PR29624)
2007-01-04 19:49 ` Tobias Burnus
@ 2007-01-04 20:51 ` Brooks Moses
2007-01-05 9:17 ` Tobias Burnus
0 siblings, 1 reply; 7+ messages in thread
From: Brooks Moses @ 2007-01-04 20:51 UTC (permalink / raw)
To: gcc-patches; +Cc: fortran
Tobias Burnus wrote:
>>>> + return gfc_notify_std (standard, "%s: %s attribute with %s
>>>> attribute "
>>>> + "at %L",
>>>> + (standard == GFC_STD_F2003)
>>>> + ? "Fortran 2003" : "Not in the
>>>> selected standard",
>>>> + a1, a2, where);
>> Is the language support OK with this? I seem to recall that we had
>> some problems with computed messages.
>
> I don't know. As (standard == GFC_STD_F2003) is currently always true
> and the translation of "Fortran 2003" does not depend on the context, it
> should be ok, except that the translator does not know what the first
> "%s:" means.
> Due to the colon, it should be also ok for "Not in the selected
> standard", which makes it effectively two sentences.
[...]
> I'll submit it tomorrow as above, unless someone objects or has a better
> suggestion.
I would almost suggest it would be clearer to do something like:
--------------------------------------------------------------------
if (standard == GFC_STD_F2003) {
return gfc_notify_std (standard, "Fortran 2003: %s attribute with %s "
"attribute at %L",
a1, a2, where);
} else {
return gfc_notify_std (standard, "Not in the selected standard: %s "
"attribute with %s attribute at %L",
a1, a2, where);
}
--------------------------------------------------------------------
However, I think a much more appropriate thing to do is to modify
gfc_notify_std to handle this sort of thing correctly automatically, so
that we could just do this:
return gfc_notify_std (standard,
"%s attribute with %s attribute at %L",
a1, a2, where);
For now, though, I would think that just using the "Fortran 2003:"
version in all cases should be sufficient -- if something gets flagged
in an error message as "Fortran 2003", it should be sufficiently clear
that it's not in the Fortran 95 standard.
- Brooks
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patches,fortran] Add POINTER INTENT(*) support (PR29624)
2007-01-04 20:51 ` Brooks Moses
@ 2007-01-05 9:17 ` Tobias Burnus
0 siblings, 0 replies; 7+ messages in thread
From: Tobias Burnus @ 2007-01-05 9:17 UTC (permalink / raw)
Cc: fortran, gcc-patches
Brooks Moses wrote:
> However, I think a much more appropriate thing to do is to modify
> gfc_notify_std to handle this sort of thing correctly automatically
Good idea!
> For now, though, I would think that just using the "Fortran 2003:"
> version in all cases should be sufficient -- if something gets flagged
> in an error message as "Fortran 2003", it should be sufficiently clear
> that it's not in the Fortran 95 standard.
I use now the "Fortran 2003: %s ..." alternative. (Checked in as r120472.)
Thanks,
Tobias
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2007-01-05 9:17 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-12 11:20 [patches,fortran] Add POINTER INTENT(*) support (PR29624) Tobias Burnus
2006-12-17 22:13 ` Tobias Burnus
2006-12-27 11:24 ` Tobias Burnus
2006-12-27 16:04 ` Paul Thomas
2007-01-04 19:49 ` Tobias Burnus
2007-01-04 20:51 ` Brooks Moses
2007-01-05 9:17 ` Tobias Burnus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).