You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
static int old_char_selector;
-/* When variables aquire types and attributes from a declaration
+/* When variables acquire types and attributes from a declaration
statement, they get them from the following static variables. The
first part of a declaration sets these variables and the second
part copies these into symbol structures. */
}
-/* Special subroutine for finding a symbol. If we're compiling a
- function or subroutine and the parent compilation unit is an
- interface, then check to see if the name we've been given is the
- name of the interface (located in another namespace). If so,
- return that symbol. If not, use gfc_get_symbol(). */
+/* Special subroutine for finding a symbol. Check if the name is found
+ in the current name space. If not, and we're compiling a function or
+ subroutine and the parent compilation unit is an interface, then check
+ to see if the name we've been given is the name of the interface
+ (located in another namespace). */
static int
find_special (const char *name, gfc_symbol ** result)
{
gfc_state_data *s;
+ int i;
+ i = gfc_get_symbol (name, NULL, result);
+ if (i==0)
+ goto end;
+
if (gfc_current_state () != COMP_SUBROUTINE
&& gfc_current_state () != COMP_FUNCTION)
- goto normal;
+ goto end;
s = gfc_state_stack->previous;
if (s == NULL)
- goto normal;
+ goto end;
if (s->state != COMP_INTERFACE)
- goto normal;
+ goto end;
if (s->sym == NULL)
- goto normal; /* Nameless interface */
+ goto end; /* Nameless interface */
if (strcmp (name, s->sym->name) == 0)
{
return 0;
}
-normal:
- return gfc_get_symbol (name, NULL, result);
+end:
+ return i;
}
symbol_attribute attr;
gfc_symbol *sym;
- if (find_special (name, &sym))
+ /* if (find_special (name, &sym)) */
+ if (gfc_get_symbol (name, NULL, &sym))
return FAILURE;
/* Start updating the symbol table. Add basic type attribute
/* Update symbol character length according initializer. */
if (sym->ts.cl->length == NULL)
{
+ /* If there are multiple CHARACTER variables declared on
+ the same line, we don't want them to share the same
+ length. */
+ sym->ts.cl = gfc_get_charlen ();
+ sym->ts.cl->next = gfc_current_ns->cl_list;
+ gfc_current_ns->cl_list = sym->ts.cl;
+
if (init->expr_type == EXPR_CONSTANT)
sym->ts.cl->length =
gfc_int_expr (init->value.character.length);
symbol table or the current interface. */
static match
-variable_decl (void)
+variable_decl (int elem)
{
char name[GFC_MAX_SYMBOL_LEN + 1];
gfc_expr *initializer, *char_len;
cl->length = char_len;
break;
+ /* Non-constant lengths need to be copied after the first
+ element. */
case MATCH_NO:
- cl = current_ts.cl;
+ if (elem > 1 && current_ts.cl->length
+ && current_ts.cl->length->expr_type != EXPR_CONSTANT)
+ {
+ cl = gfc_get_charlen ();
+ cl->next = gfc_current_ns->cl_list;
+ gfc_current_ns->cl_list = cl;
+ cl->length = gfc_copy_expr (current_ts.cl->length);
+ }
+ else
+ cl = current_ts.cl;
+
break;
case MATCH_ERROR:
t = add_init_expr_to_sym (name, &initializer, &var_locus);
else
{
- if (current_ts.type == BT_DERIVED && !initializer)
+ if (current_ts.type == BT_DERIVED && !current_attr.pointer && !initializer)
initializer = gfc_default_initializer (¤t_ts);
t = build_struct (name, cl, &initializer, &as);
}
gfc_clear_ts (ts);
+ if (gfc_match (" byte") == MATCH_YES)
+ {
+ if (gfc_notify_std(GFC_STD_GNU, "Extension: BYTE type at %C")
+ == FAILURE)
+ return MATCH_ERROR;
+
+ if (gfc_validate_kind (BT_INTEGER, 1, true) < 0)
+ {
+ gfc_error ("BYTE type used at %C "
+ "is not available on the target machine");
+ return MATCH_ERROR;
+ }
+
+ ts->type = BT_INTEGER;
+ ts->kind = 1;
+ return MATCH_YES;
+ }
+
if (gfc_match (" integer") == MATCH_YES)
{
ts->type = BT_INTEGER;
goto cleanup;
}
+ if ((d == DECL_PRIVATE || d == DECL_PUBLIC)
+ && gfc_current_state () != COMP_MODULE)
+ {
+ if (d == DECL_PRIVATE)
+ attr = "PRIVATE";
+ else
+ attr = "PUBLIC";
+
+ gfc_error ("%s attribute at %L is not allowed outside of a MODULE",
+ attr, &seen_at[d]);
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
+
switch (d)
{
case DECL_ALLOCATABLE:
{
gfc_symbol *sym;
match m;
+ int elem;
m = match_type_spec (¤t_ts, 0);
if (m != MATCH_YES)
if (m == MATCH_NO && current_ts.type == BT_CHARACTER && old_char_selector)
gfc_match_char (',');
- /* Give the types/attributes to symbols that follow. */
+ /* Give the types/attributes to symbols that follow. Give the element
+ a number so that repeat character length expressions can be copied. */
+ elem = 1;
for (;;)
{
- m = variable_decl ();
+ m = variable_decl (elem++);
if (m == MATCH_ERROR)
goto cleanup;
if (m == MATCH_NO)
return m;
state = gfc_current_state ();
- if (state != COMP_SUBROUTINE
- && state != COMP_FUNCTION)
+ if (state != COMP_SUBROUTINE && state != COMP_FUNCTION)
{
- gfc_error ("ENTRY statement at %C cannot appear within %s",
- gfc_state_name (gfc_current_state ()));
+ switch (state)
+ {
+ case COMP_PROGRAM:
+ gfc_error ("ENTRY statement at %C cannot appear within a PROGRAM");
+ break;
+ case COMP_MODULE:
+ gfc_error ("ENTRY statement at %C cannot appear within a MODULE");
+ break;
+ case COMP_BLOCK_DATA:
+ gfc_error
+ ("ENTRY statement at %C cannot appear within a BLOCK DATA");
+ break;
+ case COMP_INTERFACE:
+ gfc_error
+ ("ENTRY statement at %C cannot appear within an INTERFACE");
+ break;
+ case COMP_DERIVED:
+ gfc_error
+ ("ENTRY statement at %C cannot appear "
+ "within a DERIVED TYPE block");
+ break;
+ case COMP_IF:
+ gfc_error
+ ("ENTRY statement at %C cannot appear within an IF-THEN block");
+ break;
+ case COMP_DO:
+ gfc_error
+ ("ENTRY statement at %C cannot appear within a DO block");
+ break;
+ case COMP_SELECT:
+ gfc_error
+ ("ENTRY statement at %C cannot appear within a SELECT block");
+ break;
+ case COMP_FORALL:
+ gfc_error
+ ("ENTRY statement at %C cannot appear within a FORALL block");
+ break;
+ case COMP_WHERE:
+ gfc_error
+ ("ENTRY statement at %C cannot appear within a WHERE block");
+ break;
+ case COMP_CONTAINS:
+ gfc_error
+ ("ENTRY statement at %C cannot appear "
+ "within a contained subprogram");
+ break;
+ default:
+ gfc_internal_error ("gfc_match_entry(): Bad state");
+ }
return MATCH_ERROR;
}
else
{
/* An entry in a function. */
- m = gfc_match_formal_arglist (entry, 0, 0);
+ m = gfc_match_formal_arglist (entry, 0, 1);
if (m != MATCH_YES)
return MATCH_ERROR;
|| gfc_add_function (&entry->attr, entry->name, NULL) == FAILURE)
return MATCH_ERROR;
- entry->result = proc->result;
-
+ entry->result = entry;
}
else
{
|| gfc_add_function (&entry->attr, result->name,
NULL) == FAILURE)
return MATCH_ERROR;
+
+ entry->result = result;
}
if (proc->attr.recursive && result == NULL)
goto cleanup;
}
+ if (sym->ts.type == BT_CHARACTER
+ && sym->ts.cl != NULL
+ && sym->ts.cl->length != NULL
+ && sym->ts.cl->length->expr_type == EXPR_CONSTANT
+ && init->expr_type == EXPR_CONSTANT
+ && init->ts.type == BT_CHARACTER
+ && init->ts.kind == 1)
+ gfc_set_constant_character_len (
+ mpz_get_si (sym->ts.cl->length->value.integer), init);
+
sym->value = init;
return MATCH_YES;
/* Match a module procedure statement. Note that we have to modify
symbols in the parent's namespace because the current one was there
- to receive symbols that are in a interface's formal argument list. */
+ to receive symbols that are in an interface's formal argument list. */
match
gfc_match_modproc (void)