This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: [PATCH, Fortran] ABSTRACT INTERFACE
Hi Tobias,
To start with the most important:
Is the attached patch ok for the trunk? Regression tested on
x86_64-unknown-linux-gnu.
Tobias Schlüter wrote:
>> + case INTERFACE_ABSTRACT:
>> gfc_error ("Missing generic specification in USE statement at
>> %C");
> Please add a test for this error. In general all error messages
> should be tested.
I think this is impossible. gfc_match_interface has difficulties
returning INTERFACE_NAMELESS as gfc_match_name() [essentially] either
gives an error or matches an (existing or nonexisting) name. But
INTERFACE_ABSTRACT is *never* returned. However, it is needed in
module.c since if not all enum possibilities have a "case..:" in the
switch() block, the compiler bails out with an error.
As compensation I add a test case for -std=f95 ;-)
>> + match ("abstract interface", gfc_match_abstract_interface,
>> ST_INTERFACE);
> This should probably be "abstract% interface" (i.e. with an obligatory
> blank).
I think I'm not alone forgetting that Fortran ignores at many places
spaces; while they are here required ...
>> + gfc_error ("Name of ABSTRACT INTERFACE at %C cannot be the same
>> as "
>> + "an intrinsic type: %s",gfc_new_block->name);
> You're missing some intrinsic types there.
... they are optional for "double precision" and "double complex".
Thanks for reminding and spotting these!
> I take it that there is no way of using this feature by itself?
Not really. ABSTRACT INTERFACEs only make sense as "name" in
PROCEDURE([name]).
PROCEDURE (without pointers) acts as extended version of the EXTERNAL
statement:
- PROCEDURE() or PROCEDURE(REAL) etc. do the same as EXTERNAL (except
that bind(C) is allowed)
- PROCEDURE(abstract interface name) saves the typing of several
interfaces for functions which have the same interface
- PROCEDURE(existing procedure) does the same if one has already an
interface or use/host associated function with the needed interface
(The real fun of PROCEDURE starts with (procedure) POINTER, e.g.
type t
procedure(), pointer, pass(x_this) :: p => null
type(t), pointer :: next => null
end type t
where call mytype%p() calls the procedure with "mytype" as argument to
"x_this=".)
Tobias
2007-08-18 Tobias Burnus <burnus@net-b.de>
* gfortran.h: Add declaration for gfc_is_intrinsic_typename.
* symbol.c: Add function gfc_is_intrinsic_typename.
* parse.c (decode_statement): Check for space in ABSTRACT INTERFACE.
(parse_interface): Use gfc_is_intrinsic_typename.
* decl.c (gfc_match_derived_decl): Ditto.
2007-08-18 Tobias Burnus <burnus@net-b.de>
* gfortran.dg/interface_abstract_2.f90: New.
* gfortran.dg/interface_abstract_1.f90: Fix typo.
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h (revision 127612)
+++ gcc/fortran/gfortran.h (working copy)
@@ -2056,6 +2059,7 @@ try gfc_add_new_implicit_range (int, int
try gfc_merge_new_implicit (gfc_typespec *);
void gfc_set_implicit_none (void);
void gfc_check_function_type (gfc_namespace *);
+bool gfc_is_intrinsic_typename (const char *, const char *);
gfc_typespec *gfc_get_default_type (gfc_symbol *, gfc_namespace *);
try gfc_set_default_type (gfc_symbol *, int, gfc_namespace *);
Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c (revision 127612)
+++ gcc/fortran/symbol.c (working copy)
@@ -2909,6 +2910,29 @@ gfc_traverse_ns (gfc_namespace *ns, void
}
+/* Tests whether name is the name of an intrinsic type. If it is
+ the passed error_message is printed and TRUE is returned.
+ The error message must to contain a single %s for the name. */
+
+bool
+gfc_is_intrinsic_typename (const char *name, const char *error_message)
+{
+ if (strcmp (name, "integer") == 0
+ || strcmp (name, "real") == 0
+ || strcmp (name, "character") == 0
+ || strcmp (name, "logical") == 0
+ || strcmp (name, "complex") == 0
+ || strcmp (name, "doubleprecision") == 0
+ || strcmp (name, "doublecomplex") == 0)
+ {
+ gfc_error (error_message, name);
+ return true;
+ }
+
+ return false;
+}
+
+
/* Return TRUE if the symbol is an automatic variable. */
static bool
Index: gcc/fortran/parse.c
===================================================================
--- gcc/fortran/parse.c (revision 127612)
+++ gcc/fortran/parse.c (working copy)
@@ -172,7 +172,8 @@ decode_statement (void)
switch (c)
{
case 'a':
- match ("abstract interface", gfc_match_abstract_interface, ST_INTERFACE);
+ match ("abstract% interface", gfc_match_abstract_interface,
+ ST_INTERFACE);
match ("allocate", gfc_match_allocate, ST_ALLOCATE);
match ("allocatable", gfc_match_allocatable, ST_ATTR_DECL);
match ("assign", gfc_match_assign, ST_LABEL_ASSIGNMENT);
@@ -1799,13 +1805,11 @@ loop:
if (current_interface.type == INTERFACE_ABSTRACT)
{
gfc_new_block->attr.abstract = 1;
- if (!strcmp(gfc_new_block->name,"integer")
- || !strcmp(gfc_new_block->name,"real")
- || !strcmp(gfc_new_block->name,"complex")
- || !strcmp(gfc_new_block->name,"character")
- || !strcmp(gfc_new_block->name,"logical"))
- gfc_error ("Name of ABSTRACT INTERFACE at %C cannot be the same as "
- "an intrinsic type: %s",gfc_new_block->name);
+
+ /* Print an error if it has the name of an intrinsic type. */
+ gfc_is_intrinsic_typename (gfc_new_block->name,
+ "Name '%s' of ABSTRACT INTERFACE at %C "
+ "cannot be the same as an intrinsic type");
}
push_state (&s2, new_state, gfc_new_block);
Index: gcc/fortran/decl.c
===================================================================
--- gcc/fortran/decl.c (revision 127612)
+++ gcc/fortran/decl.c (working copy)
@@ -5472,18 +5618,9 @@ gfc_match_derived_decl (void)
'double {precision,complex}' types don't get past the name
matcher, unless they're written as a single word or in fixed
form. */
- if (strcmp (name, "integer") == 0
- || strcmp (name, "real") == 0
- || strcmp (name, "character") == 0
- || strcmp (name, "logical") == 0
- || strcmp (name, "complex") == 0
- || strcmp (name, "doubleprecision") == 0
- || strcmp (name, "doublecomplex") == 0)
- {
- gfc_error ("Type name '%s' at %C cannot be the same as an intrinsic "
- "type", name);
- return MATCH_ERROR;
- }
+ if (gfc_is_intrinsic_typename (name, "Type name '%s' at %C cannot be the "
+ "same as an intrinsic type"))
+ return MATCH_ERROR;
if (gfc_get_symbol (name, NULL, &sym))
return MATCH_ERROR;
Index: gcc/testsuite/gfortran.dg/interface_abstract_2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/interface_abstract_2.f90 (revision 0)
+++ gcc/testsuite/gfortran.dg/interface_abstract_2.f90 (revision 0)
@@ -0,0 +1,7 @@
+! { dg-do compile }
+! { dg-options "-std=f95" }
+abstract interface ! { dg-error "Fortran 2003: ABSTRACT INTERFACE" }
+ subroutine two()
+ end subroutine two
+end interface ! { dg-error "Expecting END PROGRAM statement" }
+end
Index: gcc/testsuite/gfortran.dg/interface_abstract_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/interface_abstract_1.f90 (revision 127614)
+++ gcc/testsuite/gfortran.dg/interface_abstract_1.f90 (working copy)
@@ -9,7 +9,7 @@ abstract interface
end subroutine two
subroutine three() bind(C,name="three") ! { dg-error "NAME not allowed on BIND.C. for ABSTRACT INTERFACE" }
end subroutine three ! { dg-error "Expecting END INTERFACE statement" }
- subroutine real() ! { dg-error "cannot be be the same as an intrinsic type" }
+ subroutine real() ! { dg-error "cannot be the same as an intrinsic type" }
end subroutine real
end interface
end