re PR fortran/27122 (binary operator functions should require intent(in))
2006-04-21 Paul Thomas <pault@gcc.gnu.org>
PR fortran/27122
* resolve.c (resolve_function): Remove general restriction on auto
character length function interfaces.
(gfc_resolve_uops): Check restrictions on defined operator
procedures.
(resolve_types): Call the check for defined operators.
PR fortran/27113
* trans-array.c (gfc_trans_array_constructor_subarray): Remove
redundant gfc_todo_error.
(get_array_ctor_var_strlen): Remove typo in enum.
2006-04-21 Paul Thomas <pault@gcc.gnu.org>
PR fortran/27122
* gfortran.dg/defined_operators_1.f90: New test.
* gfortran.dg/assumed_charlen_function_1.f90: Add new error and
remove old ones associated, incorrectly, with Note 5.46.
PR fortran/27113
* gfortran.dg/character_array_constructor_1.f90: New test.
From-SVN: r113133
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index c954717..003f931 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,17 @@
+2006-04-21 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/27122
+ * resolve.c (resolve_function): Remove general restriction on auto
+ character length function interfaces.
+ (gfc_resolve_uops): Check restrictions on defined operator
+ procedures.
+ (resolve_types): Call the check for defined operators.
+
+ PR fortran/27113
+ * trans-array.c (gfc_trans_array_constructor_subarray): Remove
+ redundant gfc_todo_error.
+ (get_array_ctor_var_strlen): Remove typo in enum.
+
2006-04-18 Bernhard Fischer <aldot@gcc.gnu.org>
* parse.c (next_free): Use consistent error string between
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index f7acb73..fce2322 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -1237,28 +1237,16 @@
need_full_assumed_size--;
if (sym && sym->ts.type == BT_CHARACTER
- && sym->ts.cl && sym->ts.cl->length == NULL)
+ && sym->ts.cl
+ && sym->ts.cl->length == NULL
+ && !sym->attr.dummy
+ && !sym->attr.contained)
{
- if (sym->attr.if_source == IFSRC_IFBODY)
- {
- /* This follows from a slightly odd requirement at 5.1.1.5 in the
- standard that allows assumed character length functions to be
- declared in interfaces but not used. Picking up the symbol here,
- rather than resolve_symbol, accomplishes that. */
- gfc_error ("Function '%s' can be declared in an interface to "
- "return CHARACTER(*) but cannot be used at %L",
- sym->name, &expr->where);
- return FAILURE;
- }
-
/* Internal procedures are taken care of in resolve_contained_fntype. */
- if (!sym->attr.dummy && !sym->attr.contained)
- {
- gfc_error ("Function '%s' is declared CHARACTER(*) and cannot "
- "be used at %L since it is not a dummy argument",
- sym->name, &expr->where);
- return FAILURE;
- }
+ gfc_error ("Function '%s' is declared CHARACTER(*) and cannot "
+ "be used at %L since it is not a dummy argument",
+ sym->name, &expr->where);
+ return FAILURE;
}
/* See if function is already resolved. */
@@ -6105,6 +6093,68 @@
}
}
+/* 12.3.2.1.1 Defined operators. */
+
+static void
+gfc_resolve_uops(gfc_symtree *symtree)
+{
+ gfc_interface *itr;
+ gfc_symbol *sym;
+ gfc_formal_arglist *formal;
+
+ if (symtree == NULL)
+ return;
+
+ gfc_resolve_uops (symtree->left);
+ gfc_resolve_uops (symtree->right);
+
+ for (itr = symtree->n.uop->operator; itr; itr = itr->next)
+ {
+ sym = itr->sym;
+ if (!sym->attr.function)
+ gfc_error("User operator procedure '%s' at %L must be a FUNCTION",
+ sym->name, &sym->declared_at);
+
+ if (sym->ts.type == BT_CHARACTER
+ && !(sym->ts.cl && sym->ts.cl->length)
+ && !(sym->result && sym->result->ts.cl && sym->result->ts.cl->length))
+ gfc_error("User operator procedure '%s' at %L cannot be assumed character "
+ "length", sym->name, &sym->declared_at);
+
+ formal = sym->formal;
+ if (!formal || !formal->sym)
+ {
+ gfc_error("User operator procedure '%s' at %L must have at least "
+ "one argument", sym->name, &sym->declared_at);
+ continue;
+ }
+
+ if (formal->sym->attr.intent != INTENT_IN)
+ gfc_error ("First argument of operator interface at %L must be "
+ "INTENT(IN)", &sym->declared_at);
+
+ if (formal->sym->attr.optional)
+ gfc_error ("First argument of operator interface at %L cannot be "
+ "optional", &sym->declared_at);
+
+ formal = formal->next;
+ if (!formal || !formal->sym)
+ continue;
+
+ if (formal->sym->attr.intent != INTENT_IN)
+ gfc_error ("Second argument of operator interface at %L must be "
+ "INTENT(IN)", &sym->declared_at);
+
+ if (formal->sym->attr.optional)
+ gfc_error ("Second argument of operator interface at %L cannot be "
+ "optional", &sym->declared_at);
+
+ if (formal->next)
+ gfc_error ("Operator interface at %L must have, at most, two "
+ "arguments", &sym->declared_at);
+ }
+}
+
/* Examine all of the expressions associated with a program unit,
assign types to all intermediate expressions, make sure that all
@@ -6164,6 +6214,9 @@
/* Warn about unused labels. */
if (gfc_option.warn_unused_labels)
warn_unused_label (ns->st_labels);
+
+ gfc_resolve_uops (ns->uop_root);
+
}
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 0157e62..fcd2223 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -1035,9 +1035,6 @@
gfc_copy_loopinfo_to_se (&se, &loop);
se.ss = ss;
- if (expr->ts.type == BT_CHARACTER)
- gfc_todo_error ("character arrays in constructors");
-
gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
gcc_assert (se.ss == gfc_ss_terminator);
@@ -1311,7 +1308,7 @@
/* Array references don't change the string length. */
break;
- case COMPONENT_REF:
+ case REF_COMPONENT:
/* Use the length of the component. */
ts = &ref->u.c.component->ts;
break;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bbc744f..bc315da 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2006-04-21 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/27122
+ * gfortran.dg/defined_operators_1.f90: New test.
+ * gfortran.dg/assumed_charlen_function_1.f90: Add new error and
+ remove old ones associated, incorrectly, with Note 5.46.
+
+ PR fortran/27113
+ * gfortran.dg/character_array_constructor_1.f90: New test.
+
2006-04-20 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/20060419-1.c: New test.
diff --git a/gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90 b/gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90
index e10fd70..a28934e25 100644
--- a/gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90
@@ -17,7 +17,7 @@
MODULE INTEGER_SETS
INTERFACE OPERATOR (.IN.)
- FUNCTION ELEMENT(X,A)
+ FUNCTION ELEMENT(X,A) ! { dg-error "cannot be assumed character length" }
USE M1
CHARACTER(LEN=*) :: ELEMENT
INTEGER, INTENT(IN) :: X
@@ -59,7 +59,6 @@
not_OK = ch
end function not_OK
- use INTEGER_SETS
use m1
character(4) :: answer
@@ -74,11 +73,8 @@
end function ext
end interface
- answer = i.IN.z ! { dg-error "cannot be used|Operands of user operator" }
- answer = ext (2) ! { dg-error "but cannot be used" }
-
answer = not_OK ("unOK") ! { dg-error "since it is not a dummy" }
END
-! { dg-final { cleanup-modules "M1 INTEGER_SETS" } }
+! { dg-final { cleanup-modules "M1" } }
diff --git a/gcc/testsuite/gfortran.dg/character_array_constructor_1.f90 b/gcc/testsuite/gfortran.dg/character_array_constructor_1.f90
new file mode 100644
index 0000000..ac0f7e3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/character_array_constructor_1.f90
@@ -0,0 +1,47 @@
+! { dg-do run }
+! Tests the fix for PR27113, in which character structure
+! components would produce the TODO compilation error "complex
+! character array constructors".
+!
+! Test based on part of tonto-2.2;
+! Contributed by Paul Thomas <pault@gcc.gnu.org>
+!
+ type BASIS_TYPE
+ character(len=8) :: label
+ end type
+
+ type(BASIS_TYPE), dimension(:), pointer :: ptr
+ character(8), dimension(2) :: carray
+
+ allocate (ptr(2))
+ ptr(1)%label = "Label 1"
+ ptr(2)%label = "Label 2"
+
+! This is the original bug
+ call read_library_data_((/ptr%label/))
+
+ carray(1) = "Label 3"
+ carray(2) = "Label 4"
+
+! Mix a character array with the character component of a derived type pointer array.
+ call read_library_data_((/carray, ptr%label/))
+
+! Finally, add a constant (character(8)).
+ call read_library_data_((/carray, ptr%label, "Label 5 "/))
+
+contains
+
+ subroutine read_library_data_ (chr)
+ character(*), dimension(:) :: chr
+ character(len = len(chr)) :: tmp
+ if (size(chr,1) == 2) then
+ if (any (chr .ne. (/"Label 1", "Label 2"/))) call abort ()
+ elseif (size(chr,1) == 4) then
+ if (any (chr .ne. (/"Label 3", "Label 4","Label 1", "Label 2"/))) call abort ()
+ elseif (size(chr,1) == 5) then
+ if (any (chr .ne. (/"Label 3", "Label 4","Label 1", "Label 2", "Label 5"/))) &
+ call abort ()
+ end if
+ end subroutine read_library_data_
+
+end
diff --git a/gcc/testsuite/gfortran.dg/defined_operators_1.f90 b/gcc/testsuite/gfortran.dg/defined_operators_1.f90
new file mode 100644
index 0000000..f7688b8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/defined_operators_1.f90
@@ -0,0 +1,56 @@
+! { dg-do compile }
+! { dg-options "-std=legacy" }
+! Tests the fix for PR27122, in which the requirements of 12.3.2.1.1
+! for defined operators were not enforced.
+!
+! Based on PR test by Thomas Koenig <tkoenig@gcc.gnu.org>
+!
+module mymod
+ interface operator (.foo.)
+ module procedure foo_0 ! { dg-error "must have at least one argument" }
+ module procedure foo_1 ! { dg-error "must be INTENT" }
+ module procedure foo_2 ! { dg-error "cannot be optional" }
+ module procedure foo_3 ! { dg-error "must have, at most, two arguments" }
+ module procedure foo_1_OK
+ module procedure foo_2_OK
+ function foo_chr (chr) ! { dg-error "cannot be assumed character length" }
+ character(*) :: foo_chr
+ character(*), intent(in) :: chr
+ end function foo_chr
+ subroutine bad_foo (chr) ! { dg-error "must be a FUNCTION" }
+ character(*), intent(in) :: chr
+ end subroutine bad_foo
+ end interface
+contains
+ function foo_0 ()
+ integer :: foo_1
+ foo_0 = 1
+ end function foo_0
+ function foo_1 (a)
+ integer :: foo_1
+ integer :: a
+ foo_1 = 1
+ end function foo_1
+ function foo_1_OK (a)
+ integer :: foo_1_OK
+ integer, intent (in) :: a
+ foo_1_OK = 1
+ end function foo_1_OK
+ function foo_2 (a, b)
+ integer :: foo_2
+ integer, intent(in) :: a
+ integer, intent(in), optional :: b
+ foo_2 = 2 * a + b
+ end function foo_2
+ function foo_2_OK (a, b)
+ real :: foo_2_OK
+ real, intent(in) :: a
+ real, intent(in) :: b
+ foo_2_OK = 2.0 * a + b
+ end function foo_2_OK
+ function foo_3 (a, b, c)
+ integer :: foo_3
+ integer, intent(in) :: a, b, c
+ foo_3 = a + 3 * b - c
+ end function foo_3
+end module mymod