Tobias Schlüter - [FORTRAN, fix PR30478] Slightly overhaul ENUM parsing (original) (raw)

This is the mail archive of the gcc-patches@gcc.gnu.orgmailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR30478 is due to the decision to use the normal variable matching code also when matching ENUMERATORs. This leads to the curious situation that something like
ENUM, BIND(C)
INTEGER :: x
END ENUM
will make the compiler choke much later than necessary. Since our enum handling determines the values of the ENUMERATORs during parsing, and due to unforeseen interactions in the error case, this also leads to the additional complication that the machinery which determines the ENUMERATOR values, gets confused, which explains the invalid memory accesses reported in the PR.This patch fixes this by separating the parsing of ENUMERATOR declarations from that of variable declarations. A possible follow-up is to move the determination of the ENUMERATOR values to the resolution stage. I can by no means remember why I didn't insist that this be done when I reviewed the original patch, the only thing I remember is that I thought that there was a good reason not to (besides laziness). If anybody can think of something, please let me know.The diff is against 4.1 because I couldn't get 4.3 to build on the fast Linux boxes I have access to, due to issues with a GMP upgraded by the sysop. My personal old Linux box is currently working its way through the compile, but it will take until tomorrow.Built and tested on i686-linux, I verified with valgrind that that the enum_* testcases stay clear of memory error. Is this ok for 4.3, 4.2 and 4.1 once I manage to build and test this on all three versions? I can split out the cleanups, and only apply them to 4.3, in case they weren't included in Steve's whitespace works.

Cheers,

:ADDPATCH fortran:2007-02-10 Tobias Schl¸ter tobi@gcc.gnu.org

PR fortran/30478

fortran/ * decl.c (create_enum_history, gfc_free_enum_history): Formatting fixes. (add_init_expr_to_sym): Remove ENUM-specific code-path. (variable_decl): Likewise. Formatting fix. (match_attr_spec): Remove ENUM-specific codepath. (gfc_match_enum): Fix typo in error message. (enumerator_decl): New. (gfc_match_enumerator_def): Strip down to code necessary for ENUMs, use enumerator_decl. testsuite/ * gfortran.dg/enum_4.f90: Update expected error message.

2007-02-10 Tobias Schlüter tobi@gcc.gnu.org

PR fortran/30478

fortran/ * decl.c (create_enum_history, gfc_free_enum_history): Formatting fixes. (add_init_expr_to_sym): Remove ENUM-specific code-path. (variable_decl): Likewise. Formatting fix. (match_attr_spec): Remove ENUM-specific codepath. (gfc_match_enum): Fix typo in error message. (enumerator_decl): New. (gfc_match_enumerator_def): Strip down to code necessary for ENUMs, use enumerator_decl. testsuite/ * gfortran.dg/enum_4.f90: Update expected error message.

Index: gcc/fortran/decl.c

--- gcc/fortran/decl.c (revision 121799) +++ gcc/fortran/decl.c (working copy) @@ -758,7 +758,7 @@ gfc_set_constant_character_len (int len, INIT points to its enumerator value. */ static void -create_enum_history(gfc_symbol *sym, gfc_expr *init) +create_enum_history (gfc_symbol *sym, gfc_expr *init) { enumerator_history *new_enum_history; gcc_assert (sym != NULL && init != NULL); @@ -789,7 +789,7 @@ create_enum_history(gfc_symbol sym, gfc / Function to free enum kind history. */ void -gfc_free_enum_history(void) +gfc_free_enum_history (void) { enumerator_history *current = enum_history;
enumerator_history *next;
@@ -911,10 +911,6 @@ add_init_expr_to_sym (const char *name, initp = NULL; } - / Maintain enumerator history. */ - if (gfc_current_state () == COMP_ENUM) - create_enum_history (sym, init);

return SUCCESS; } @@ -1073,14 +1069,6 @@ variable_decl (int elem) if (m == MATCH_NO) as = gfc_copy_array_spec (current_as); - else if (gfc_current_state () == COMP_ENUM) - { - gfc_error ("Enumerator cannot be array at %C"); - gfc_free_enum_history (); - m = MATCH_ERROR; - goto cleanup; - }

char_len = NULL; cl = NULL; @@ -1179,10 +1167,11 @@ variable_decl (int elem) goto cleanup; } - /* An interface body specifies all of the procedure's characteristics and these - shall be consistent with those specified in the procedure definition, except - that the interface may specify a procedure that is not pure if the procedure - is defined to be pure(12.3.2). / + / An interface body specifies all of the procedure's + characteristics and these shall be consistent with those + specified in the procedure definition, except that the interface + may specify a procedure that is not pure if the procedure is + defined to be pure(12.3.2). / if (current_ts.type == BT_DERIVED && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY && current_ts.derived->ns != gfc_current_ns) @@ -1288,30 +1277,6 @@ variable_decl (int elem) } } - / Check if we are parsing an enumeration and if the current enumerator - variable has an initializer or not. If it does not have an - initializer, the initialization value of the previous enumerator - (stored in last_initializer) is incremented by 1 and is used to - initialize the current enumerator. */ - if (gfc_current_state () == COMP_ENUM) - { - if (initializer == NULL) - initializer = gfc_enum_initializer (last_initializer, old_locus);

@@ -2033,12 +1998,6 @@ match_attr_spec (void) if (d == DECL_NONE || d == DECL_COLON) break;
- if (gfc_current_state () == COMP_ENUM) - { - gfc_error ("Enumerator cannot have attributes %C"); - return MATCH_ERROR; - }

   seen[d]++;
   seen_at[d] = gfc_current_locus;

@@ -2057,18 +2016,6 @@ match_attr_spec (void) } } - /* If we are parsing an enumeration and have ensured that no other - attributes are present we can now set the parameter attribute. */ - if (gfc_current_state () == COMP_ENUM) - { - t = gfc_add_flavor (&current_attr, FL_PARAMETER, NULL, NULL); - if (t == FAILURE) - { - m = MATCH_ERROR; - goto cleanup; - } - }

/* No double colon, so assume that we've been looking at something else the whole time. */ if (d == DECL_NONE) @@ -4081,7 +4028,7 @@ gfc_match_enum (void) return m;

if (gfc_notify_std (GFC_STD_F2003, - "New in Fortran 2003: ENUM AND ENUMERATOR at %C") + "New in Fortran 2003: ENUM and ENUMERATOR at %C") == FAILURE) return MATCH_ERROR;

@@ -4089,19 +4036,116 @@ gfc_match_enum (void) }

+/* Match a variable name with an optional initializer. When this

@@ -4113,17 +4157,17 @@ gfc_match_enumerator_def (void) (&current_ts)->type = BT_INTEGER; (&current_ts)->kind = gfc_c_int_kind;

Index: gcc/testsuite/gfortran.dg/enum_4.f90

--- gcc/testsuite/gfortran.dg/enum_4.f90 (revision 121799) +++ gcc/testsuite/gfortran.dg/enum_4.f90 (working copy) @@ -5,12 +5,12 @@ program main implicit none enum, bind (c) enumerator :: red, black = 2

end enum

enum, bind (c)

end ! { dg-error " END ENUM" }

end program main ! { dg-excess-errors "" }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]