summaryrefslogtreecommitdiffstats
path: root/gcc/fortran/expr.c
diff options
context:
space:
mode:
authorburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2007-01-05 09:08:37 +0000
committerburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2007-01-05 09:08:37 +0000
commit2bec85dcfa9cc6740deec823018c072a605f3b90 (patch)
treef40639a46b029ee6c2ccfe80b9c03b2f7f2cd3fd /gcc/fortran/expr.c
parenta48a3d3d6554978c46de7739f4588a265753f7f9 (diff)
downloadppe42-gcc-2bec85dcfa9cc6740deec823018c072a605f3b90.tar.gz
ppe42-gcc-2bec85dcfa9cc6740deec823018c072a605f3b90.zip
fortran/
2007-01-05 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-01-05 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120472 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/expr.c')
-rw-r--r--gcc/fortran/expr.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 7f6c699de59..7c2069c340b 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -2188,12 +2188,25 @@ try
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 is the component or
+ sub-component of 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 @@ try
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 @@ gfc_check_pointer_assign (gfc_expr * lvalue, gfc_expr * rvalue)
return FAILURE;
}
- attr = gfc_variable_attr (lvalue, NULL);
- if (!attr.pointer)
+
+ /* Check INTENT(IN), unless the object itself is the component or
+ sub-component of 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;
OpenPOWER on IntegriCloud