aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog19
-rw-r--r--gcc/fortran/decl.c180
-rw-r--r--gcc/fortran/primary.c5
3 files changed, 135 insertions, 69 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index ea90d12b116..ef28e189c8d 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,22 @@
+2007-02-15 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/30799
+ * primary.c (match_logical_constant): Return MATCH_ERROR on invalid
+ kind.
+
+2007-02-15 Tobias Schlueter <tobi@gcc.gnu.org>
+
+ PR fortran/30478
+ * 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.
+
2007-02-13 Release Manager
* GCC 4.1.2 released.
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index e69ae3cbe28..df362014668 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -758,7 +758,7 @@ gfc_set_constant_character_len (int len, gfc_expr * expr)
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_expr *init)
/* 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;
@@ -805,7 +805,7 @@ gfc_free_enum_history(void)
}
-/* Function called by variable_decl() that adds an initialization
+/* Function called by variabl_decl() that adds an initialization
expression to a symbol. */
static try
@@ -911,10 +911,6 @@ add_init_expr_to_sym (const char *name, gfc_expr ** initp,
*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);
-
- if (initializer == NULL || initializer->ts.type != BT_INTEGER)
- {
- gfc_error("ENUMERATOR %L not initialized with integer expression",
- &var_locus);
- m = MATCH_ERROR;
- gfc_free_enum_history ();
- goto cleanup;
- }
-
- /* Store this current initializer, for the next enumerator
- variable to be parsed. */
- last_initializer = initializer;
- }
-
/* Add the initializer. Note that it is fine if initializer is
NULL here, because we sometimes also need to check if a
declaration *must* have an initialization expression. */
@@ -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
+ subroutine is called, a variable is expected to be parsed next.
+ Depending on what is happening at the moment, updates either the
+ symbol table or the current interface. */
+
+static match
+enumerator_decl (void)
+{
+ char name[GFC_MAX_SYMBOL_LEN + 1];
+ gfc_expr *initializer;
+ gfc_array_spec *as = NULL;
+ gfc_symbol *sym;
+ locus var_locus;
+ match m;
+ try t;
+ locus old_locus;
+
+ initializer = NULL;
+ old_locus = gfc_current_locus;
+
+ /* When we get here, we've just matched a list of attributes and
+ maybe a type and a double colon. The next thing we expect to see
+ is the name of the symbol. */
+ m = gfc_match_name (name);
+ if (m != MATCH_YES)
+ goto cleanup;
+
+ var_locus = gfc_current_locus;
+
+ /* OK, we've successfully matched the declaration. Now put the
+ symbol in the current namespace. If we fail to create the symbol,
+ bail out. */
+ if (build_sym (name, NULL, &as, &var_locus) == FAILURE)
+ {
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
+
+ /* The double colon must be present in order to have initializers.
+ Otherwise the statement is ambiguous with an assignment statement. */
+ if (colon_seen)
+ {
+ if (gfc_match_char ('=') == MATCH_YES)
+ {
+ m = gfc_match_init_expr (&initializer);
+ if (m == MATCH_NO)
+ {
+ gfc_error ("Expected an initialization expression at %C");
+ m = MATCH_ERROR;
+ }
+
+ if (m != MATCH_YES)
+ goto cleanup;
+ }
+ }
+
+ /* If we do 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 (initializer == NULL)
+ initializer = gfc_enum_initializer (last_initializer, old_locus);
+
+ if (initializer == NULL || initializer->ts.type != BT_INTEGER)
+ {
+ gfc_error("ENUMERATOR %L not initialized with integer expression",
+ &var_locus);
+ m = MATCH_ERROR;
+ gfc_free_enum_history ();
+ goto cleanup;
+ }
+
+ /* Store this current initializer, for the next enumerator variable
+ to be parsed. add_init_expr_to_sym() zeros initializer, so we
+ use last_initializer below. */
+ last_initializer = initializer;
+ t = add_init_expr_to_sym (name, &initializer, &var_locus);
+
+ /* Maintain enumerator history. */
+ gfc_find_symbol (name, NULL, 0, &sym);
+ create_enum_history (sym, last_initializer);
+
+ return (t == SUCCESS) ? MATCH_YES : MATCH_ERROR;
+
+cleanup:
+ /* Free stuff up and return. */
+ gfc_free_expr (initializer);
+
+ return m;
+}
+
+
/* Match the enumerator definition statement. */
match
gfc_match_enumerator_def (void)
{
match m;
- int elem;
+ try t;
gfc_clear_ts (&current_ts);
m = gfc_match (" enumerator");
if (m != MATCH_YES)
return m;
+
+ m = gfc_match (" :: ");
+ if (m == MATCH_ERROR)
+ return m;
+
+ colon_seen = (m == MATCH_YES);
if (gfc_current_state () != COMP_ENUM)
{
@@ -4113,17 +4157,17 @@ gfc_match_enumerator_def (void)
(&current_ts)->type = BT_INTEGER;
(&current_ts)->kind = gfc_c_int_kind;
- m = match_attr_spec ();
- if (m == MATCH_ERROR)
+ gfc_clear_attr (&current_attr);
+ t = gfc_add_flavor (&current_attr, FL_PARAMETER, NULL, NULL);
+ if (t == FAILURE)
{
- m = MATCH_NO;
+ m = MATCH_ERROR;
goto cleanup;
}
- elem = 1;
for (;;)
{
- m = variable_decl (elem++);
+ m = enumerator_decl ();
if (m == MATCH_ERROR)
goto cleanup;
if (m == MATCH_NO)
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 182cb4c47e8..e5bdd79c74e 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -1039,7 +1039,10 @@ match_logical_constant (gfc_expr ** result)
kind = gfc_default_logical_kind;
if (gfc_validate_kind (BT_LOGICAL, kind, true) < 0)
- gfc_error ("Bad kind for logical constant at %C");
+ {
+ gfc_error ("Bad kind for logical constant at %C");
+ return MATCH_ERROR;
+ }
e = gfc_get_expr ();