aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/gcc/fortran/primary.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/gcc/fortran/primary.c')
-rw-r--r--gcc-4.8.1/gcc/fortran/primary.c3328
1 files changed, 0 insertions, 3328 deletions
diff --git a/gcc-4.8.1/gcc/fortran/primary.c b/gcc-4.8.1/gcc/fortran/primary.c
deleted file mode 100644
index d14922416..000000000
--- a/gcc-4.8.1/gcc/fortran/primary.c
+++ /dev/null
@@ -1,3328 +0,0 @@
-/* Primary expression subroutines
- Copyright (C) 2000-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "flags.h"
-#include "gfortran.h"
-#include "arith.h"
-#include "match.h"
-#include "parse.h"
-#include "constructor.h"
-
-int matching_actual_arglist = 0;
-
-/* Matches a kind-parameter expression, which is either a named
- symbolic constant or a nonnegative integer constant. If
- successful, sets the kind value to the correct integer.
- The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
- symbol like e.g. 'c_int'. */
-
-static match
-match_kind_param (int *kind, int *is_iso_c)
-{
- char name[GFC_MAX_SYMBOL_LEN + 1];
- gfc_symbol *sym;
- const char *p;
- match m;
-
- *is_iso_c = 0;
-
- m = gfc_match_small_literal_int (kind, NULL);
- if (m != MATCH_NO)
- return m;
-
- m = gfc_match_name (name);
- if (m != MATCH_YES)
- return m;
-
- if (gfc_find_symbol (name, NULL, 1, &sym))
- return MATCH_ERROR;
-
- if (sym == NULL)
- return MATCH_NO;
-
- *is_iso_c = sym->attr.is_iso_c;
-
- if (sym->attr.flavor != FL_PARAMETER)
- return MATCH_NO;
-
- if (sym->value == NULL)
- return MATCH_NO;
-
- p = gfc_extract_int (sym->value, kind);
- if (p != NULL)
- return MATCH_NO;
-
- gfc_set_sym_referenced (sym);
-
- if (*kind < 0)
- return MATCH_NO;
-
- return MATCH_YES;
-}
-
-
-/* Get a trailing kind-specification for non-character variables.
- Returns:
- * the integer kind value or
- * -1 if an error was generated,
- * -2 if no kind was found.
- The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
- symbol like e.g. 'c_int'. */
-
-static int
-get_kind (int *is_iso_c)
-{
- int kind;
- match m;
-
- *is_iso_c = 0;
-
- if (gfc_match_char ('_') != MATCH_YES)
- return -2;
-
- m = match_kind_param (&kind, is_iso_c);
- if (m == MATCH_NO)
- gfc_error ("Missing kind-parameter at %C");
-
- return (m == MATCH_YES) ? kind : -1;
-}
-
-
-/* Given a character and a radix, see if the character is a valid
- digit in that radix. */
-
-int
-gfc_check_digit (char c, int radix)
-{
- int r;
-
- switch (radix)
- {
- case 2:
- r = ('0' <= c && c <= '1');
- break;
-
- case 8:
- r = ('0' <= c && c <= '7');
- break;
-
- case 10:
- r = ('0' <= c && c <= '9');
- break;
-
- case 16:
- r = ISXDIGIT (c);
- break;
-
- default:
- gfc_internal_error ("gfc_check_digit(): bad radix");
- }
-
- return r;
-}
-
-
-/* Match the digit string part of an integer if signflag is not set,
- the signed digit string part if signflag is set. If the buffer
- is NULL, we just count characters for the resolution pass. Returns
- the number of characters matched, -1 for no match. */
-
-static int
-match_digits (int signflag, int radix, char *buffer)
-{
- locus old_loc;
- int length;
- char c;
-
- length = 0;
- c = gfc_next_ascii_char ();
-
- if (signflag && (c == '+' || c == '-'))
- {
- if (buffer != NULL)
- *buffer++ = c;
- gfc_gobble_whitespace ();
- c = gfc_next_ascii_char ();
- length++;
- }
-
- if (!gfc_check_digit (c, radix))
- return -1;
-
- length++;
- if (buffer != NULL)
- *buffer++ = c;
-
- for (;;)
- {
- old_loc = gfc_current_locus;
- c = gfc_next_ascii_char ();
-
- if (!gfc_check_digit (c, radix))
- break;
-
- if (buffer != NULL)
- *buffer++ = c;
- length++;
- }
-
- gfc_current_locus = old_loc;
-
- return length;
-}
-
-
-/* Match an integer (digit string and optional kind).
- A sign will be accepted if signflag is set. */
-
-static match
-match_integer_constant (gfc_expr **result, int signflag)
-{
- int length, kind, is_iso_c;
- locus old_loc;
- char *buffer;
- gfc_expr *e;
-
- old_loc = gfc_current_locus;
- gfc_gobble_whitespace ();
-
- length = match_digits (signflag, 10, NULL);
- gfc_current_locus = old_loc;
- if (length == -1)
- return MATCH_NO;
-
- buffer = (char *) alloca (length + 1);
- memset (buffer, '\0', length + 1);
-
- gfc_gobble_whitespace ();
-
- match_digits (signflag, 10, buffer);
-
- kind = get_kind (&is_iso_c);
- if (kind == -2)
- kind = gfc_default_integer_kind;
- if (kind == -1)
- return MATCH_ERROR;
-
- if (kind == 4 && gfc_option.flag_integer4_kind == 8)
- kind = 8;
-
- if (gfc_validate_kind (BT_INTEGER, kind, true) < 0)
- {
- gfc_error ("Integer kind %d at %C not available", kind);
- return MATCH_ERROR;
- }
-
- e = gfc_convert_integer (buffer, kind, 10, &gfc_current_locus);
- e->ts.is_c_interop = is_iso_c;
-
- if (gfc_range_check (e) != ARITH_OK)
- {
- gfc_error ("Integer too big for its kind at %C. This check can be "
- "disabled with the option -fno-range-check");
-
- gfc_free_expr (e);
- return MATCH_ERROR;
- }
-
- *result = e;
- return MATCH_YES;
-}
-
-
-/* Match a Hollerith constant. */
-
-static match
-match_hollerith_constant (gfc_expr **result)
-{
- locus old_loc;
- gfc_expr *e = NULL;
- const char *msg;
- int num, pad;
- int i;
-
- old_loc = gfc_current_locus;
- gfc_gobble_whitespace ();
-
- if (match_integer_constant (&e, 0) == MATCH_YES
- && gfc_match_char ('h') == MATCH_YES)
- {
- if (gfc_notify_std (GFC_STD_LEGACY, "Hollerith constant "
- "at %C") == FAILURE)
- goto cleanup;
-
- msg = gfc_extract_int (e, &num);
- if (msg != NULL)
- {
- gfc_error (msg);
- goto cleanup;
- }
- if (num == 0)
- {
- gfc_error ("Invalid Hollerith constant: %L must contain at least "
- "one character", &old_loc);
- goto cleanup;
- }
- if (e->ts.kind != gfc_default_integer_kind)
- {
- gfc_error ("Invalid Hollerith constant: Integer kind at %L "
- "should be default", &old_loc);
- goto cleanup;
- }
- else
- {
- gfc_free_expr (e);
- e = gfc_get_constant_expr (BT_HOLLERITH, gfc_default_character_kind,
- &gfc_current_locus);
-
- /* Calculate padding needed to fit default integer memory. */
- pad = gfc_default_integer_kind - (num % gfc_default_integer_kind);
-
- e->representation.string = XCNEWVEC (char, num + pad + 1);
-
- for (i = 0; i < num; i++)
- {
- gfc_char_t c = gfc_next_char_literal (INSTRING_WARN);
- if (! gfc_wide_fits_in_byte (c))
- {
- gfc_error ("Invalid Hollerith constant at %L contains a "
- "wide character", &old_loc);
- goto cleanup;
- }
-
- e->representation.string[i] = (unsigned char) c;
- }
-
- /* Now pad with blanks and end with a null char. */
- for (i = 0; i < pad; i++)
- e->representation.string[num + i] = ' ';
-
- e->representation.string[num + i] = '\0';
- e->representation.length = num + pad;
- e->ts.u.pad = pad;
-
- *result = e;
- return MATCH_YES;
- }
- }
-
- gfc_free_expr (e);
- gfc_current_locus = old_loc;
- return MATCH_NO;
-
-cleanup:
- gfc_free_expr (e);
- return MATCH_ERROR;
-}
-
-
-/* Match a binary, octal or hexadecimal constant that can be found in
- a DATA statement. The standard permits b'010...', o'73...', and
- z'a1...' where b, o, and z can be capital letters. This function
- also accepts postfixed forms of the constants: '01...'b, '73...'o,
- and 'a1...'z. An additional extension is the use of x for z. */
-
-static match
-match_boz_constant (gfc_expr **result)
-{
- int radix, length, x_hex, kind;
- locus old_loc, start_loc;
- char *buffer, post, delim;
- gfc_expr *e;
-
- start_loc = old_loc = gfc_current_locus;
- gfc_gobble_whitespace ();
-
- x_hex = 0;
- switch (post = gfc_next_ascii_char ())
- {
- case 'b':
- radix = 2;
- post = 0;
- break;
- case 'o':
- radix = 8;
- post = 0;
- break;
- case 'x':
- x_hex = 1;
- /* Fall through. */
- case 'z':
- radix = 16;
- post = 0;
- break;
- case '\'':
- /* Fall through. */
- case '\"':
- delim = post;
- post = 1;
- radix = 16; /* Set to accept any valid digit string. */
- break;
- default:
- goto backup;
- }
-
- /* No whitespace allowed here. */
-
- if (post == 0)
- delim = gfc_next_ascii_char ();
-
- if (delim != '\'' && delim != '\"')
- goto backup;
-
- if (x_hex
- && (gfc_notify_std (GFC_STD_GNU, "Hexadecimal "
- "constant at %C uses non-standard syntax")
- == FAILURE))
- return MATCH_ERROR;
-
- old_loc = gfc_current_locus;
-
- length = match_digits (0, radix, NULL);
- if (length == -1)
- {
- gfc_error ("Empty set of digits in BOZ constant at %C");
- return MATCH_ERROR;
- }
-
- if (gfc_next_ascii_char () != delim)
- {
- gfc_error ("Illegal character in BOZ constant at %C");
- return MATCH_ERROR;
- }
-
- if (post == 1)
- {
- switch (gfc_next_ascii_char ())
- {
- case 'b':
- radix = 2;
- break;
- case 'o':
- radix = 8;
- break;
- case 'x':
- /* Fall through. */
- case 'z':
- radix = 16;
- break;
- default:
- goto backup;
- }
-
- if (gfc_notify_std (GFC_STD_GNU, "BOZ constant "
- "at %C uses non-standard postfix syntax")
- == FAILURE)
- return MATCH_ERROR;
- }
-
- gfc_current_locus = old_loc;
-
- buffer = (char *) alloca (length + 1);
- memset (buffer, '\0', length + 1);
-
- match_digits (0, radix, buffer);
- gfc_next_ascii_char (); /* Eat delimiter. */
- if (post == 1)
- gfc_next_ascii_char (); /* Eat postfixed b, o, z, or x. */
-
- /* In section 5.2.5 and following C567 in the Fortran 2003 standard, we find
- "If a data-stmt-constant is a boz-literal-constant, the corresponding
- variable shall be of type integer. The boz-literal-constant is treated
- as if it were an int-literal-constant with a kind-param that specifies
- the representation method with the largest decimal exponent range
- supported by the processor." */
-
- kind = gfc_max_integer_kind;
- e = gfc_convert_integer (buffer, kind, radix, &gfc_current_locus);
-
- /* Mark as boz variable. */
- e->is_boz = 1;
-
- if (gfc_range_check (e) != ARITH_OK)
- {
- gfc_error ("Integer too big for integer kind %i at %C", kind);
- gfc_free_expr (e);
- return MATCH_ERROR;
- }
-
- if (!gfc_in_match_data ()
- && (gfc_notify_std (GFC_STD_F2003, "BOZ used outside a DATA "
- "statement at %C")
- == FAILURE))
- return MATCH_ERROR;
-
- *result = e;
- return MATCH_YES;
-
-backup:
- gfc_current_locus = start_loc;
- return MATCH_NO;
-}
-
-
-/* Match a real constant of some sort. Allow a signed constant if signflag
- is nonzero. */
-
-static match
-match_real_constant (gfc_expr **result, int signflag)
-{
- int kind, count, seen_dp, seen_digits, is_iso_c;
- locus old_loc, temp_loc;
- char *p, *buffer, c, exp_char;
- gfc_expr *e;
- bool negate;
-
- old_loc = gfc_current_locus;
- gfc_gobble_whitespace ();
-
- e = NULL;
-
- count = 0;
- seen_dp = 0;
- seen_digits = 0;
- exp_char = ' ';
- negate = FALSE;
-
- c = gfc_next_ascii_char ();
- if (signflag && (c == '+' || c == '-'))
- {
- if (c == '-')
- negate = TRUE;
-
- gfc_gobble_whitespace ();
- c = gfc_next_ascii_char ();
- }
-
- /* Scan significand. */
- for (;; c = gfc_next_ascii_char (), count++)
- {
- if (c == '.')
- {
- if (seen_dp)
- goto done;
-
- /* Check to see if "." goes with a following operator like
- ".eq.". */
- temp_loc = gfc_current_locus;
- c = gfc_next_ascii_char ();
-
- if (c == 'e' || c == 'd' || c == 'q')
- {
- c = gfc_next_ascii_char ();
- if (c == '.')
- goto done; /* Operator named .e. or .d. */
- }
-
- if (ISALPHA (c))
- goto done; /* Distinguish 1.e9 from 1.eq.2 */
-
- gfc_current_locus = temp_loc;
- seen_dp = 1;
- continue;
- }
-
- if (ISDIGIT (c))
- {
- seen_digits = 1;
- continue;
- }
-
- break;
- }
-
- if (!seen_digits || (c != 'e' && c != 'd' && c != 'q'))
- goto done;
- exp_char = c;
-
-
- if (c == 'q')
- {
- if (gfc_notify_std (GFC_STD_GNU, "exponent-letter 'q' in "
- "real-literal-constant at %C") == FAILURE)
- return MATCH_ERROR;
- else if (gfc_option.warn_real_q_constant)
- gfc_warning("Extension: exponent-letter 'q' in real-literal-constant "
- "at %C");
- }
-
- /* Scan exponent. */
- c = gfc_next_ascii_char ();
- count++;
-
- if (c == '+' || c == '-')
- { /* optional sign */
- c = gfc_next_ascii_char ();
- count++;
- }
-
- if (!ISDIGIT (c))
- {
- gfc_error ("Missing exponent in real number at %C");
- return MATCH_ERROR;
- }
-
- while (ISDIGIT (c))
- {
- c = gfc_next_ascii_char ();
- count++;
- }
-
-done:
- /* Check that we have a numeric constant. */
- if (!seen_digits || (!seen_dp && exp_char == ' '))
- {
- gfc_current_locus = old_loc;
- return MATCH_NO;
- }
-
- /* Convert the number. */
- gfc_current_locus = old_loc;
- gfc_gobble_whitespace ();
-
- buffer = (char *) alloca (count + 1);
- memset (buffer, '\0', count + 1);
-
- p = buffer;
- c = gfc_next_ascii_char ();
- if (c == '+' || c == '-')
- {
- gfc_gobble_whitespace ();
- c = gfc_next_ascii_char ();
- }
-
- /* Hack for mpfr_set_str(). */
- for (;;)
- {
- if (c == 'd' || c == 'q')
- *p = 'e';
- else
- *p = c;
- p++;
- if (--count == 0)
- break;
-
- c = gfc_next_ascii_char ();
- }
-
- kind = get_kind (&is_iso_c);
- if (kind == -1)
- goto cleanup;
-
- switch (exp_char)
- {
- case 'd':
- if (kind != -2)
- {
- gfc_error ("Real number at %C has a 'd' exponent and an explicit "
- "kind");
- goto cleanup;
- }
- kind = gfc_default_double_kind;
-
- if (kind == 4)
- {
- if (gfc_option.flag_real4_kind == 8)
- kind = 8;
- if (gfc_option.flag_real4_kind == 10)
- kind = 10;
- if (gfc_option.flag_real4_kind == 16)
- kind = 16;
- }
-
- if (kind == 8)
- {
- if (gfc_option.flag_real8_kind == 4)
- kind = 4;
- if (gfc_option.flag_real8_kind == 10)
- kind = 10;
- if (gfc_option.flag_real8_kind == 16)
- kind = 16;
- }
- break;
-
- case 'q':
- if (kind != -2)
- {
- gfc_error ("Real number at %C has a 'q' exponent and an explicit "
- "kind");
- goto cleanup;
- }
-
- /* The maximum possible real kind type parameter is 16. First, try
- that for the kind, then fallback to trying kind=10 (Intel 80 bit)
- extended precision. If neither value works, just given up. */
- kind = 16;
- if (gfc_validate_kind (BT_REAL, kind, true) < 0)
- {
- kind = 10;
- if (gfc_validate_kind (BT_REAL, kind, true) < 0)
- {
- gfc_error ("Invalid exponent-letter 'q' in "
- "real-literal-constant at %C");
- goto cleanup;
- }
- }
- break;
-
- default:
- if (kind == -2)
- kind = gfc_default_real_kind;
-
- if (kind == 4)
- {
- if (gfc_option.flag_real4_kind == 8)
- kind = 8;
- if (gfc_option.flag_real4_kind == 10)
- kind = 10;
- if (gfc_option.flag_real4_kind == 16)
- kind = 16;
- }
-
- if (kind == 8)
- {
- if (gfc_option.flag_real8_kind == 4)
- kind = 4;
- if (gfc_option.flag_real8_kind == 10)
- kind = 10;
- if (gfc_option.flag_real8_kind == 16)
- kind = 16;
- }
-
- if (gfc_validate_kind (BT_REAL, kind, true) < 0)
- {
- gfc_error ("Invalid real kind %d at %C", kind);
- goto cleanup;
- }
- }
-
- e = gfc_convert_real (buffer, kind, &gfc_current_locus);
- if (negate)
- mpfr_neg (e->value.real, e->value.real, GFC_RND_MODE);
- e->ts.is_c_interop = is_iso_c;
-
- switch (gfc_range_check (e))
- {
- case ARITH_OK:
- break;
- case ARITH_OVERFLOW:
- gfc_error ("Real constant overflows its kind at %C");
- goto cleanup;
-
- case ARITH_UNDERFLOW:
- if (gfc_option.warn_underflow)
- gfc_warning ("Real constant underflows its kind at %C");
- mpfr_set_ui (e->value.real, 0, GFC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("gfc_range_check() returned bad value");
- }
-
- *result = e;
- return MATCH_YES;
-
-cleanup:
- gfc_free_expr (e);
- return MATCH_ERROR;
-}
-
-
-/* Match a substring reference. */
-
-static match
-match_substring (gfc_charlen *cl, int init, gfc_ref **result)
-{
- gfc_expr *start, *end;
- locus old_loc;
- gfc_ref *ref;
- match m;
-
- start = NULL;
- end = NULL;
-
- old_loc = gfc_current_locus;
-
- m = gfc_match_char ('(');
- if (m != MATCH_YES)
- return MATCH_NO;
-
- if (gfc_match_char (':') != MATCH_YES)
- {
- if (init)
- m = gfc_match_init_expr (&start);
- else
- m = gfc_match_expr (&start);
-
- if (m != MATCH_YES)
- {
- m = MATCH_NO;
- goto cleanup;
- }
-
- m = gfc_match_char (':');
- if (m != MATCH_YES)
- goto cleanup;
- }
-
- if (gfc_match_char (')') != MATCH_YES)
- {
- if (init)
- m = gfc_match_init_expr (&end);
- else
- m = gfc_match_expr (&end);
-
- if (m == MATCH_NO)
- goto syntax;
- if (m == MATCH_ERROR)
- goto cleanup;
-
- m = gfc_match_char (')');
- if (m == MATCH_NO)
- goto syntax;
- }
-
- /* Optimize away the (:) reference. */
- if (start == NULL && end == NULL)
- ref = NULL;
- else
- {
- ref = gfc_get_ref ();
-
- ref->type = REF_SUBSTRING;
- if (start == NULL)
- start = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
- ref->u.ss.start = start;
- if (end == NULL && cl)
- end = gfc_copy_expr (cl->length);
- ref->u.ss.end = end;
- ref->u.ss.length = cl;
- }
-
- *result = ref;
- return MATCH_YES;
-
-syntax:
- gfc_error ("Syntax error in SUBSTRING specification at %C");
- m = MATCH_ERROR;
-
-cleanup:
- gfc_free_expr (start);
- gfc_free_expr (end);
-
- gfc_current_locus = old_loc;
- return m;
-}
-
-
-/* Reads the next character of a string constant, taking care to
- return doubled delimiters on the input as a single instance of
- the delimiter.
-
- Special return values for "ret" argument are:
- -1 End of the string, as determined by the delimiter
- -2 Unterminated string detected
-
- Backslash codes are also expanded at this time. */
-
-static gfc_char_t
-next_string_char (gfc_char_t delimiter, int *ret)
-{
- locus old_locus;
- gfc_char_t c;
-
- c = gfc_next_char_literal (INSTRING_WARN);
- *ret = 0;
-
- if (c == '\n')
- {
- *ret = -2;
- return 0;
- }
-
- if (gfc_option.flag_backslash && c == '\\')
- {
- old_locus = gfc_current_locus;
-
- if (gfc_match_special_char (&c) == MATCH_NO)
- gfc_current_locus = old_locus;
-
- if (!(gfc_option.allow_std & GFC_STD_GNU) && !inhibit_warnings)
- gfc_warning ("Extension: backslash character at %C");
- }
-
- if (c != delimiter)
- return c;
-
- old_locus = gfc_current_locus;
- c = gfc_next_char_literal (NONSTRING);
-
- if (c == delimiter)
- return c;
- gfc_current_locus = old_locus;
-
- *ret = -1;
- return 0;
-}
-
-
-/* Special case of gfc_match_name() that matches a parameter kind name
- before a string constant. This takes case of the weird but legal
- case of:
-
- kind_____'string'
-
- where kind____ is a parameter. gfc_match_name() will happily slurp
- up all the underscores, which leads to problems. If we return
- MATCH_YES, the parse pointer points to the final underscore, which
- is not part of the name. We never return MATCH_ERROR-- errors in
- the name will be detected later. */
-
-static match
-match_charkind_name (char *name)
-{
- locus old_loc;
- char c, peek;
- int len;
-
- gfc_gobble_whitespace ();
- c = gfc_next_ascii_char ();
- if (!ISALPHA (c))
- return MATCH_NO;
-
- *name++ = c;
- len = 1;
-
- for (;;)
- {
- old_loc = gfc_current_locus;
- c = gfc_next_ascii_char ();
-
- if (c == '_')
- {
- peek = gfc_peek_ascii_char ();
-
- if (peek == '\'' || peek == '\"')
- {
- gfc_current_locus = old_loc;
- *name = '\0';
- return MATCH_YES;
- }
- }
-
- if (!ISALNUM (c)
- && c != '_'
- && (c != '$' || !gfc_option.flag_dollar_ok))
- break;
-
- *name++ = c;
- if (++len > GFC_MAX_SYMBOL_LEN)
- break;
- }
-
- return MATCH_NO;
-}
-
-
-/* See if the current input matches a character constant. Lots of
- contortions have to be done to match the kind parameter which comes
- before the actual string. The main consideration is that we don't
- want to error out too quickly. For example, we don't actually do
- any validation of the kinds until we have actually seen a legal
- delimiter. Using match_kind_param() generates errors too quickly. */
-
-static match
-match_string_constant (gfc_expr **result)
-{
- char name[GFC_MAX_SYMBOL_LEN + 1], peek;
- int i, kind, length, warn_ampersand, ret;
- locus old_locus, start_locus;
- gfc_symbol *sym;
- gfc_expr *e;
- const char *q;
- match m;
- gfc_char_t c, delimiter, *p;
-
- old_locus = gfc_current_locus;
-
- gfc_gobble_whitespace ();
-
- c = gfc_next_char ();
- if (c == '\'' || c == '"')
- {
- kind = gfc_default_character_kind;
- start_locus = gfc_current_locus;
- goto got_delim;
- }
-
- if (gfc_wide_is_digit (c))
- {
- kind = 0;
-
- while (gfc_wide_is_digit (c))
- {
- kind = kind * 10 + c - '0';
- if (kind > 9999999)
- goto no_match;
- c = gfc_next_char ();
- }
-
- }
- else
- {
- gfc_current_locus = old_locus;
-
- m = match_charkind_name (name);
- if (m != MATCH_YES)
- goto no_match;
-
- if (gfc_find_symbol (name, NULL, 1, &sym)
- || sym == NULL
- || sym->attr.flavor != FL_PARAMETER)
- goto no_match;
-
- kind = -1;
- c = gfc_next_char ();
- }
-
- if (c == ' ')
- {
- gfc_gobble_whitespace ();
- c = gfc_next_char ();
- }
-
- if (c != '_')
- goto no_match;
-
- gfc_gobble_whitespace ();
-
- c = gfc_next_char ();
- if (c != '\'' && c != '"')
- goto no_match;
-
- start_locus = gfc_current_locus;
-
- if (kind == -1)
- {
- q = gfc_extract_int (sym->value, &kind);
- if (q != NULL)
- {
- gfc_error (q);
- return MATCH_ERROR;
- }
- gfc_set_sym_referenced (sym);
- }
-
- if (gfc_validate_kind (BT_CHARACTER, kind, true) < 0)
- {
- gfc_error ("Invalid kind %d for CHARACTER constant at %C", kind);
- return MATCH_ERROR;
- }
-
-got_delim:
- /* Scan the string into a block of memory by first figuring out how
- long it is, allocating the structure, then re-reading it. This
- isn't particularly efficient, but string constants aren't that
- common in most code. TODO: Use obstacks? */
-
- delimiter = c;
- length = 0;
-
- for (;;)
- {
- c = next_string_char (delimiter, &ret);
- if (ret == -1)
- break;
- if (ret == -2)
- {
- gfc_current_locus = start_locus;
- gfc_error ("Unterminated character constant beginning at %C");
- return MATCH_ERROR;
- }
-
- length++;
- }
-
- /* Peek at the next character to see if it is a b, o, z, or x for the
- postfixed BOZ literal constants. */
- peek = gfc_peek_ascii_char ();
- if (peek == 'b' || peek == 'o' || peek =='z' || peek == 'x')
- goto no_match;
-
- e = gfc_get_character_expr (kind, &start_locus, NULL, length);
-
- gfc_current_locus = start_locus;
-
- /* We disable the warning for the following loop as the warning has already
- been printed in the loop above. */
- warn_ampersand = gfc_option.warn_ampersand;
- gfc_option.warn_ampersand = 0;
-
- p = e->value.character.string;
- for (i = 0; i < length; i++)
- {
- c = next_string_char (delimiter, &ret);
-
- if (!gfc_check_character_range (c, kind))
- {
- gfc_free_expr (e);
- gfc_error ("Character '%s' in string at %C is not representable "
- "in character kind %d", gfc_print_wide_char (c), kind);
- return MATCH_ERROR;
- }
-
- *p++ = c;
- }
-
- *p = '\0'; /* TODO: C-style string is for development/debug purposes. */
- gfc_option.warn_ampersand = warn_ampersand;
-
- next_string_char (delimiter, &ret);
- if (ret != -1)
- gfc_internal_error ("match_string_constant(): Delimiter not found");
-
- if (match_substring (NULL, 0, &e->ref) != MATCH_NO)
- e->expr_type = EXPR_SUBSTRING;
-
- *result = e;
-
- return MATCH_YES;
-
-no_match:
- gfc_current_locus = old_locus;
- return MATCH_NO;
-}
-
-
-/* Match a .true. or .false. Returns 1 if a .true. was found,
- 0 if a .false. was found, and -1 otherwise. */
-static int
-match_logical_constant_string (void)
-{
- locus orig_loc = gfc_current_locus;
-
- gfc_gobble_whitespace ();
- if (gfc_next_ascii_char () == '.')
- {
- char ch = gfc_next_ascii_char ();
- if (ch == 'f')
- {
- if (gfc_next_ascii_char () == 'a'
- && gfc_next_ascii_char () == 'l'
- && gfc_next_ascii_char () == 's'
- && gfc_next_ascii_char () == 'e'
- && gfc_next_ascii_char () == '.')
- /* Matched ".false.". */
- return 0;
- }
- else if (ch == 't')
- {
- if (gfc_next_ascii_char () == 'r'
- && gfc_next_ascii_char () == 'u'
- && gfc_next_ascii_char () == 'e'
- && gfc_next_ascii_char () == '.')
- /* Matched ".true.". */
- return 1;
- }
- }
- gfc_current_locus = orig_loc;
- return -1;
-}
-
-/* Match a .true. or .false. */
-
-static match
-match_logical_constant (gfc_expr **result)
-{
- gfc_expr *e;
- int i, kind, is_iso_c;
-
- i = match_logical_constant_string ();
- if (i == -1)
- return MATCH_NO;
-
- kind = get_kind (&is_iso_c);
- if (kind == -1)
- return MATCH_ERROR;
- if (kind == -2)
- kind = gfc_default_logical_kind;
-
- if (gfc_validate_kind (BT_LOGICAL, kind, true) < 0)
- {
- gfc_error ("Bad kind for logical constant at %C");
- return MATCH_ERROR;
- }
-
- e = gfc_get_logical_expr (kind, &gfc_current_locus, i);
- e->ts.is_c_interop = is_iso_c;
-
- *result = e;
- return MATCH_YES;
-}
-
-
-/* Match a real or imaginary part of a complex constant that is a
- symbolic constant. */
-
-static match
-match_sym_complex_part (gfc_expr **result)
-{
- char name[GFC_MAX_SYMBOL_LEN + 1];
- gfc_symbol *sym;
- gfc_expr *e;
- match m;
-
- m = gfc_match_name (name);
- if (m != MATCH_YES)
- return m;
-
- if (gfc_find_symbol (name, NULL, 1, &sym) || sym == NULL)
- return MATCH_NO;
-
- if (sym->attr.flavor != FL_PARAMETER)
- {
- gfc_error ("Expected PARAMETER symbol in complex constant at %C");
- return MATCH_ERROR;
- }
-
- if (!gfc_numeric_ts (&sym->value->ts))
- {
- gfc_error ("Numeric PARAMETER required in complex constant at %C");
- return MATCH_ERROR;
- }
-
- if (sym->value->rank != 0)
- {
- gfc_error ("Scalar PARAMETER required in complex constant at %C");
- return MATCH_ERROR;
- }
-
- if (gfc_notify_std (GFC_STD_F2003, "PARAMETER symbol in "
- "complex constant at %C") == FAILURE)
- return MATCH_ERROR;
-
- switch (sym->value->ts.type)
- {
- case BT_REAL:
- e = gfc_copy_expr (sym->value);
- break;
-
- case BT_COMPLEX:
- e = gfc_complex2real (sym->value, sym->value->ts.kind);
- if (e == NULL)
- goto error;
- break;
-
- case BT_INTEGER:
- e = gfc_int2real (sym->value, gfc_default_real_kind);
- if (e == NULL)
- goto error;
- break;
-
- default:
- gfc_internal_error ("gfc_match_sym_complex_part(): Bad type");
- }
-
- *result = e; /* e is a scalar, real, constant expression. */
- return MATCH_YES;
-
-error:
- gfc_error ("Error converting PARAMETER constant in complex constant at %C");
- return MATCH_ERROR;
-}
-
-
-/* Match a real or imaginary part of a complex number. */
-
-static match
-match_complex_part (gfc_expr **result)
-{
- match m;
-
- m = match_sym_complex_part (result);
- if (m != MATCH_NO)
- return m;
-
- m = match_real_constant (result, 1);
- if (m != MATCH_NO)
- return m;
-
- return match_integer_constant (result, 1);
-}
-
-
-/* Try to match a complex constant. */
-
-static match
-match_complex_constant (gfc_expr **result)
-{
- gfc_expr *e, *real, *imag;
- gfc_error_buf old_error;
- gfc_typespec target;
- locus old_loc;
- int kind;
- match m;
-
- old_loc = gfc_current_locus;
- real = imag = e = NULL;
-
- m = gfc_match_char ('(');
- if (m != MATCH_YES)
- return m;
-
- gfc_push_error (&old_error);
-
- m = match_complex_part (&real);
- if (m == MATCH_NO)
- {
- gfc_free_error (&old_error);
- goto cleanup;
- }
-
- if (gfc_match_char (',') == MATCH_NO)
- {
- gfc_pop_error (&old_error);
- m = MATCH_NO;
- goto cleanup;
- }
-
- /* If m is error, then something was wrong with the real part and we
- assume we have a complex constant because we've seen the ','. An
- ambiguous case here is the start of an iterator list of some
- sort. These sort of lists are matched prior to coming here. */
-
- if (m == MATCH_ERROR)
- {
- gfc_free_error (&old_error);
- goto cleanup;
- }
- gfc_pop_error (&old_error);
-
- m = match_complex_part (&imag);
- if (m == MATCH_NO)
- goto syntax;
- if (m == MATCH_ERROR)
- goto cleanup;
-
- m = gfc_match_char (')');
- if (m == MATCH_NO)
- {
- /* Give the matcher for implied do-loops a chance to run. This
- yields a much saner error message for (/ (i, 4=i, 6) /). */
- if (gfc_peek_ascii_char () == '=')
- {
- m = MATCH_ERROR;
- goto cleanup;
- }
- else
- goto syntax;
- }
-
- if (m == MATCH_ERROR)
- goto cleanup;
-
- /* Decide on the kind of this complex number. */
- if (real->ts.type == BT_REAL)
- {
- if (imag->ts.type == BT_REAL)
- kind = gfc_kind_max (real, imag);
- else
- kind = real->ts.kind;
- }
- else
- {
- if (imag->ts.type == BT_REAL)
- kind = imag->ts.kind;
- else
- kind = gfc_default_real_kind;
- }
- gfc_clear_ts (&target);
- target.type = BT_REAL;
- target.kind = kind;
-
- if (real->ts.type != BT_REAL || kind != real->ts.kind)
- gfc_convert_type (real, &target, 2);
- if (imag->ts.type != BT_REAL || kind != imag->ts.kind)
- gfc_convert_type (imag, &target, 2);
-
- e = gfc_convert_complex (real, imag, kind);
- e->where = gfc_current_locus;
-
- gfc_free_expr (real);
- gfc_free_expr (imag);
-
- *result = e;
- return MATCH_YES;
-
-syntax:
- gfc_error ("Syntax error in COMPLEX constant at %C");
- m = MATCH_ERROR;
-
-cleanup:
- gfc_free_expr (e);
- gfc_free_expr (real);
- gfc_free_expr (imag);
- gfc_current_locus = old_loc;
-
- return m;
-}
-
-
-/* Match constants in any of several forms. Returns nonzero for a
- match, zero for no match. */
-
-match
-gfc_match_literal_constant (gfc_expr **result, int signflag)
-{
- match m;
-
- m = match_complex_constant (result);
- if (m != MATCH_NO)
- return m;
-
- m = match_string_constant (result);
- if (m != MATCH_NO)
- return m;
-
- m = match_boz_constant (result);
- if (m != MATCH_NO)
- return m;
-
- m = match_real_constant (result, signflag);
- if (m != MATCH_NO)
- return m;
-
- m = match_hollerith_constant (result);
- if (m != MATCH_NO)
- return m;
-
- m = match_integer_constant (result, signflag);
- if (m != MATCH_NO)
- return m;
-
- m = match_logical_constant (result);
- if (m != MATCH_NO)
- return m;
-
- return MATCH_NO;
-}
-
-
-/* This checks if a symbol is the return value of an encompassing function.
- Function nesting can be maximally two levels deep, but we may have
- additional local namespaces like BLOCK etc. */
-
-bool
-gfc_is_function_return_value (gfc_symbol *sym, gfc_namespace *ns)
-{
- if (!sym->attr.function || (sym->result != sym))
- return false;
- while (ns)
- {
- if (ns->proc_name == sym)
- return true;
- ns = ns->parent;
- }
- return false;
-}
-
-
-/* Match a single actual argument value. An actual argument is
- usually an expression, but can also be a procedure name. If the
- argument is a single name, it is not always possible to tell
- whether the name is a dummy procedure or not. We treat these cases
- by creating an argument that looks like a dummy procedure and
- fixing things later during resolution. */
-
-static match
-match_actual_arg (gfc_expr **result)
-{
- char name[GFC_MAX_SYMBOL_LEN + 1];
- gfc_symtree *symtree;
- locus where, w;
- gfc_expr *e;
- char c;
-
- gfc_gobble_whitespace ();
- where = gfc_current_locus;
-
- switch (gfc_match_name (name))
- {
- case MATCH_ERROR:
- return MATCH_ERROR;
-
- case MATCH_NO:
- break;
-
- case MATCH_YES:
- w = gfc_current_locus;
- gfc_gobble_whitespace ();
- c = gfc_next_ascii_char ();
- gfc_current_locus = w;
-
- if (c != ',' && c != ')')
- break;
-
- if (gfc_find_sym_tree (name, NULL, 1, &symtree))
- break;
- /* Handle error elsewhere. */
-
- /* Eliminate a couple of common cases where we know we don't
- have a function argument. */
- if (symtree == NULL)
- {
- gfc_get_sym_tree (name, NULL, &symtree, false);
- gfc_set_sym_referenced (symtree->n.sym);
- }
- else
- {
- gfc_symbol *sym;
-
- sym = symtree->n.sym;
- gfc_set_sym_referenced (sym);
- if (sym->attr.flavor != FL_PROCEDURE
- && sym->attr.flavor != FL_UNKNOWN)
- break;
-
- if (sym->attr.in_common && !sym->attr.proc_pointer)
- {
- if (gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name,
- &sym->declared_at) == FAILURE)
- return MATCH_ERROR;
- break;
- }
-
- /* If the symbol is a function with itself as the result and
- is being defined, then we have a variable. */
- if (sym->attr.function && sym->result == sym)
- {
- if (gfc_is_function_return_value (sym, gfc_current_ns))
- break;
-
- if (sym->attr.entry
- && (sym->ns == gfc_current_ns
- || sym->ns == gfc_current_ns->parent))
- {
- gfc_entry_list *el = NULL;
-
- for (el = sym->ns->entries; el; el = el->next)
- if (sym == el->sym)
- break;
-
- if (el)
- break;
- }
- }
- }
-
- e = gfc_get_expr (); /* Leave it unknown for now */
- e->symtree = symtree;
- e->expr_type = EXPR_VARIABLE;
- e->ts.type = BT_PROCEDURE;
- e->where = where;
-
- *result = e;
- return MATCH_YES;
- }
-
- gfc_current_locus = where;
- return gfc_match_expr (result);
-}
-
-
-/* Match a keyword argument. */
-
-static match
-match_keyword_arg (gfc_actual_arglist *actual, gfc_actual_arglist *base)
-{
- char name[GFC_MAX_SYMBOL_LEN + 1];
- gfc_actual_arglist *a;
- locus name_locus;
- match m;
-
- name_locus = gfc_current_locus;
- m = gfc_match_name (name);
-
- if (m != MATCH_YES)
- goto cleanup;
- if (gfc_match_char ('=') != MATCH_YES)
- {
- m = MATCH_NO;
- goto cleanup;
- }
-
- m = match_actual_arg (&actual->expr);
- if (m != MATCH_YES)
- goto cleanup;
-
- /* Make sure this name has not appeared yet. */
-
- if (name[0] != '\0')
- {
- for (a = base; a; a = a->next)
- if (a->name != NULL && strcmp (a->name, name) == 0)
- {
- gfc_error ("Keyword '%s' at %C has already appeared in the "
- "current argument list", name);
- return MATCH_ERROR;
- }
- }
-
- actual->name = gfc_get_string (name);
- return MATCH_YES;
-
-cleanup:
- gfc_current_locus = name_locus;
- return m;
-}
-
-
-/* Match an argument list function, such as %VAL. */
-
-static match
-match_arg_list_function (gfc_actual_arglist *result)
-{
- char name[GFC_MAX_SYMBOL_LEN + 1];
- locus old_locus;
- match m;
-
- old_locus = gfc_current_locus;
-
- if (gfc_match_char ('%') != MATCH_YES)
- {
- m = MATCH_NO;
- goto cleanup;
- }
-
- m = gfc_match ("%n (", name);
- if (m != MATCH_YES)
- goto cleanup;
-
- if (name[0] != '\0')
- {
- switch (name[0])
- {
- case 'l':
- if (strncmp (name, "loc", 3) == 0)
- {
- result->name = "%LOC";
- break;
- }
- case 'r':
- if (strncmp (name, "ref", 3) == 0)
- {
- result->name = "%REF";
- break;
- }
- case 'v':
- if (strncmp (name, "val", 3) == 0)
- {
- result->name = "%VAL";
- break;
- }
- default:
- m = MATCH_ERROR;
- goto cleanup;
- }
- }
-
- if (gfc_notify_std (GFC_STD_GNU, "argument list "
- "function at %C") == FAILURE)
- {
- m = MATCH_ERROR;
- goto cleanup;
- }
-
- m = match_actual_arg (&result->expr);
- if (m != MATCH_YES)
- goto cleanup;
-
- if (gfc_match_char (')') != MATCH_YES)
- {
- m = MATCH_NO;
- goto cleanup;
- }
-
- return MATCH_YES;
-
-cleanup:
- gfc_current_locus = old_locus;
- return m;
-}
-
-
-/* Matches an actual argument list of a function or subroutine, from
- the opening parenthesis to the closing parenthesis. The argument
- list is assumed to allow keyword arguments because we don't know if
- the symbol associated with the procedure has an implicit interface
- or not. We make sure keywords are unique. If sub_flag is set,
- we're matching the argument list of a subroutine. */
-
-match
-gfc_match_actual_arglist (int sub_flag, gfc_actual_arglist **argp)
-{
- gfc_actual_arglist *head, *tail;
- int seen_keyword;
- gfc_st_label *label;
- locus old_loc;
- match m;
-
- *argp = tail = NULL;
- old_loc = gfc_current_locus;
-
- seen_keyword = 0;
-
- if (gfc_match_char ('(') == MATCH_NO)
- return (sub_flag) ? MATCH_YES : MATCH_NO;
-
- if (gfc_match_char (')') == MATCH_YES)
- return MATCH_YES;
- head = NULL;
-
- matching_actual_arglist++;
-
- for (;;)
- {
- if (head == NULL)
- head = tail = gfc_get_actual_arglist ();
- else
- {
- tail->next = gfc_get_actual_arglist ();
- tail = tail->next;
- }
-
- if (sub_flag && gfc_match_char ('*') == MATCH_YES)
- {
- m = gfc_match_st_label (&label);
- if (m == MATCH_NO)
- gfc_error ("Expected alternate return label at %C");
- if (m != MATCH_YES)
- goto cleanup;
-
- tail->label = label;
- goto next;
- }
-
- /* After the first keyword argument is seen, the following
- arguments must also have keywords. */
- if (seen_keyword)
- {
- m = match_keyword_arg (tail, head);
-
- if (m == MATCH_ERROR)
- goto cleanup;
- if (m == MATCH_NO)
- {
- gfc_error ("Missing keyword name in actual argument list at %C");
- goto cleanup;
- }
-
- }
- else
- {
- /* Try an argument list function, like %VAL. */
- m = match_arg_list_function (tail);
- if (m == MATCH_ERROR)
- goto cleanup;
-
- /* See if we have the first keyword argument. */
- if (m == MATCH_NO)
- {
- m = match_keyword_arg (tail, head);
- if (m == MATCH_YES)
- seen_keyword = 1;
- if (m == MATCH_ERROR)
- goto cleanup;
- }
-
- if (m == MATCH_NO)
- {
- /* Try for a non-keyword argument. */
- m = match_actual_arg (&tail->expr);
- if (m == MATCH_ERROR)
- goto cleanup;
- if (m == MATCH_NO)
- goto syntax;
- }
- }
-
-
- next:
- if (gfc_match_char (')') == MATCH_YES)
- break;
- if (gfc_match_char (',') != MATCH_YES)
- goto syntax;
- }
-
- *argp = head;
- matching_actual_arglist--;
- return MATCH_YES;
-
-syntax:
- gfc_error ("Syntax error in argument list at %C");
-
-cleanup:
- gfc_free_actual_arglist (head);
- gfc_current_locus = old_loc;
- matching_actual_arglist--;
- return MATCH_ERROR;
-}
-
-
-/* Used by gfc_match_varspec() to extend the reference list by one
- element. */
-
-static gfc_ref *
-extend_ref (gfc_expr *primary, gfc_ref *tail)
-{
- if (primary->ref == NULL)
- primary->ref = tail = gfc_get_ref ();
- else
- {
- if (tail == NULL)
- gfc_internal_error ("extend_ref(): Bad tail");
- tail->next = gfc_get_ref ();
- tail = tail->next;
- }
-
- return tail;
-}
-
-
-/* Match any additional specifications associated with the current
- variable like member references or substrings. If equiv_flag is
- set we only match stuff that is allowed inside an EQUIVALENCE
- statement. sub_flag tells whether we expect a type-bound procedure found
- to be a subroutine as part of CALL or a FUNCTION. For procedure pointer
- components, 'ppc_arg' determines whether the PPC may be called (with an
- argument list), or whether it may just be referred to as a pointer. */
-
-match
-gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
- bool ppc_arg)
-{
- char name[GFC_MAX_SYMBOL_LEN + 1];
- gfc_ref *substring, *tail;
- gfc_component *component;
- gfc_symbol *sym = primary->symtree->n.sym;
- match m;
- bool unknown;
-
- tail = NULL;
-
- gfc_gobble_whitespace ();
-
- if (gfc_peek_ascii_char () == '[')
- {
- if ((sym->ts.type != BT_CLASS && sym->attr.dimension)
- || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
- && CLASS_DATA (sym)->attr.dimension))
- {
- gfc_error ("Array section designator, e.g. '(:)', is required "
- "besides the coarray designator '[...]' at %C");
- return MATCH_ERROR;
- }
- if ((sym->ts.type != BT_CLASS && !sym->attr.codimension)
- || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
- && !CLASS_DATA (sym)->attr.codimension))
- {
- gfc_error ("Coarray designator at %C but '%s' is not a coarray",
- sym->name);
- return MATCH_ERROR;
- }
- }
-
- /* For associate names, we may not yet know whether they are arrays or not.
- Thus if we have one and parentheses follow, we have to assume that it
- actually is one for now. The final decision will be made at
- resolution time, of course. */
- if (sym->assoc && gfc_peek_ascii_char () == '(')
- sym->attr.dimension = 1;
-
- if ((equiv_flag && gfc_peek_ascii_char () == '(')
- || gfc_peek_ascii_char () == '[' || sym->attr.codimension
- || (sym->attr.dimension && sym->ts.type != BT_CLASS
- && !sym->attr.proc_pointer && !gfc_is_proc_ptr_comp (primary)
- && !(gfc_matching_procptr_assignment
- && sym->attr.flavor == FL_PROCEDURE))
- || (sym->ts.type == BT_CLASS && sym->attr.class_ok
- && (CLASS_DATA (sym)->attr.dimension
- || CLASS_DATA (sym)->attr.codimension)))
- {
- gfc_array_spec *as;
-
- tail = extend_ref (primary, tail);
- tail->type = REF_ARRAY;
-
- /* In EQUIVALENCE, we don't know yet whether we are seeing
- an array, character variable or array of character
- variables. We'll leave the decision till resolve time. */
-
- if (equiv_flag)
- as = NULL;
- else if (sym->ts.type == BT_CLASS && CLASS_DATA (sym))
- as = CLASS_DATA (sym)->as;
- else
- as = sym->as;
-
- m = gfc_match_array_ref (&tail->u.ar, as, equiv_flag,
- as ? as->corank : 0);
- if (m != MATCH_YES)
- return m;
-
- gfc_gobble_whitespace ();
- if (equiv_flag && gfc_peek_ascii_char () == '(')
- {
- tail = extend_ref (primary, tail);
- tail->type = REF_ARRAY;
-
- m = gfc_match_array_ref (&tail->u.ar, NULL, equiv_flag, 0);
- if (m != MATCH_YES)
- return m;
- }
- }
-
- primary->ts = sym->ts;
-
- if (equiv_flag)
- return MATCH_YES;
-
- if (sym->ts.type == BT_UNKNOWN && gfc_peek_ascii_char () == '%'
- && gfc_get_default_type (sym->name, sym->ns)->type == BT_DERIVED)
- gfc_set_default_type (sym, 0, sym->ns);
-
- if (sym->ts.type == BT_UNKNOWN && gfc_match_char ('%') == MATCH_YES)
- {
- gfc_error ("Symbol '%s' at %C has no IMPLICIT type", sym->name);
- return MATCH_ERROR;
- }
- else if ((sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
- && gfc_match_char ('%') == MATCH_YES)
- {
- gfc_error ("Unexpected '%%' for nonderived-type variable '%s' at %C",
- sym->name);
- return MATCH_ERROR;
- }
-
- if ((sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
- || gfc_match_char ('%') != MATCH_YES)
- goto check_substring;
-
- sym = sym->ts.u.derived;
-
- for (;;)
- {
- gfc_try t;
- gfc_symtree *tbp;
-
- m = gfc_match_name (name);
- if (m == MATCH_NO)
- gfc_error ("Expected structure component name at %C");
- if (m != MATCH_YES)
- return MATCH_ERROR;
-
- if (sym->f2k_derived)
- tbp = gfc_find_typebound_proc (sym, &t, name, false, &gfc_current_locus);
- else
- tbp = NULL;
-
- if (tbp)
- {
- gfc_symbol* tbp_sym;
-
- if (t == FAILURE)
- return MATCH_ERROR;
-
- gcc_assert (!tail || !tail->next);
- gcc_assert (primary->expr_type == EXPR_VARIABLE
- || (primary->expr_type == EXPR_STRUCTURE
- && primary->symtree && primary->symtree->n.sym
- && primary->symtree->n.sym->attr.flavor));
-
- if (tbp->n.tb->is_generic)
- tbp_sym = NULL;
- else
- tbp_sym = tbp->n.tb->u.specific->n.sym;
-
- primary->expr_type = EXPR_COMPCALL;
- primary->value.compcall.tbp = tbp->n.tb;
- primary->value.compcall.name = tbp->name;
- primary->value.compcall.ignore_pass = 0;
- primary->value.compcall.assign = 0;
- primary->value.compcall.base_object = NULL;
- gcc_assert (primary->symtree->n.sym->attr.referenced);
- if (tbp_sym)
- primary->ts = tbp_sym->ts;
- else
- gfc_clear_ts (&primary->ts);
-
- m = gfc_match_actual_arglist (tbp->n.tb->subroutine,
- &primary->value.compcall.actual);
- if (m == MATCH_ERROR)
- return MATCH_ERROR;
- if (m == MATCH_NO)
- {
- if (sub_flag)
- primary->value.compcall.actual = NULL;
- else
- {
- gfc_error ("Expected argument list at %C");
- return MATCH_ERROR;
- }
- }
-
- break;
- }
-
- component = gfc_find_component (sym, name, false, false);
- if (component == NULL)
- return MATCH_ERROR;
-
- tail = extend_ref (primary, tail);
- tail->type = REF_COMPONENT;
-
- tail->u.c.component = component;
- tail->u.c.sym = sym;
-
- primary->ts = component->ts;
-
- if (component->attr.proc_pointer && ppc_arg)
- {
- /* Procedure pointer component call: Look for argument list. */
- m = gfc_match_actual_arglist (sub_flag,
- &primary->value.compcall.actual);
- if (m == MATCH_ERROR)
- return MATCH_ERROR;
-
- if (m == MATCH_NO && !gfc_matching_ptr_assignment
- && !gfc_matching_procptr_assignment && !matching_actual_arglist)
- {
- gfc_error ("Procedure pointer component '%s' requires an "
- "argument list at %C", component->name);
- return MATCH_ERROR;
- }
-
- if (m == MATCH_YES)
- primary->expr_type = EXPR_PPC;
-
- break;
- }
-
- if (component->as != NULL && !component->attr.proc_pointer)
- {
- tail = extend_ref (primary, tail);
- tail->type = REF_ARRAY;
-
- m = gfc_match_array_ref (&tail->u.ar, component->as, equiv_flag,
- component->as->corank);
- if (m != MATCH_YES)
- return m;
- }
- else if (component->ts.type == BT_CLASS
- && CLASS_DATA (component)->as != NULL
- && !component->attr.proc_pointer)
- {
- tail = extend_ref (primary, tail);
- tail->type = REF_ARRAY;
-
- m = gfc_match_array_ref (&tail->u.ar, CLASS_DATA (component)->as,
- equiv_flag,
- CLASS_DATA (component)->as->corank);
- if (m != MATCH_YES)
- return m;
- }
-
- if ((component->ts.type != BT_DERIVED && component->ts.type != BT_CLASS)
- || gfc_match_char ('%') != MATCH_YES)
- break;
-
- sym = component->ts.u.derived;
- }
-
-check_substring:
- unknown = false;
- if (primary->ts.type == BT_UNKNOWN && sym->attr.flavor != FL_DERIVED)
- {
- if (gfc_get_default_type (sym->name, sym->ns)->type == BT_CHARACTER)
- {
- gfc_set_default_type (sym, 0, sym->ns);
- primary->ts = sym->ts;
- unknown = true;
- }
- }
-
- if (primary->ts.type == BT_CHARACTER)
- {
- switch (match_substring (primary->ts.u.cl, equiv_flag, &substring))
- {
- case MATCH_YES:
- if (tail == NULL)
- primary->ref = substring;
- else
- tail->next = substring;
-
- if (primary->expr_type == EXPR_CONSTANT)
- primary->expr_type = EXPR_SUBSTRING;
-
- if (substring)
- primary->ts.u.cl = NULL;
-
- break;
-
- case MATCH_NO:
- if (unknown)
- {
- gfc_clear_ts (&primary->ts);
- gfc_clear_ts (&sym->ts);
- }
- break;
-
- case MATCH_ERROR:
- return MATCH_ERROR;
- }
- }
-
- /* F2008, C727. */
- if (primary->expr_type == EXPR_PPC && gfc_is_coindexed (primary))
- {
- gfc_error ("Coindexed procedure-pointer component at %C");
- return MATCH_ERROR;
- }
-
- return MATCH_YES;
-}
-
-
-/* Given an expression that is a variable, figure out what the
- ultimate variable's type and attribute is, traversing the reference
- structures if necessary.
-
- This subroutine is trickier than it looks. We start at the base
- symbol and store the attribute. Component references load a
- completely new attribute.
-
- A couple of rules come into play. Subobjects of targets are always
- targets themselves. If we see a component that goes through a
- pointer, then the expression must also be a target, since the
- pointer is associated with something (if it isn't core will soon be
- dumped). If we see a full part or section of an array, the
- expression is also an array.
-
- We can have at most one full array reference. */
-
-symbol_attribute
-gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
-{
- int dimension, pointer, allocatable, target;
- symbol_attribute attr;
- gfc_ref *ref;
- gfc_symbol *sym;
- gfc_component *comp;
-
- if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION)
- gfc_internal_error ("gfc_variable_attr(): Expression isn't a variable");
-
- sym = expr->symtree->n.sym;
- attr = sym->attr;
-
- if (sym->ts.type == BT_CLASS && sym->attr.class_ok)
- {
- dimension = CLASS_DATA (sym)->attr.dimension;
- pointer = CLASS_DATA (sym)->attr.class_pointer;
- allocatable = CLASS_DATA (sym)->attr.allocatable;
- }
- else
- {
- dimension = attr.dimension;
- pointer = attr.pointer;
- allocatable = attr.allocatable;
- }
-
- target = attr.target;
- if (pointer || attr.proc_pointer)
- target = 1;
-
- if (ts != NULL && expr->ts.type == BT_UNKNOWN)
- *ts = sym->ts;
-
- for (ref = expr->ref; ref; ref = ref->next)
- switch (ref->type)
- {
- case REF_ARRAY:
-
- switch (ref->u.ar.type)
- {
- case AR_FULL:
- dimension = 1;
- break;
-
- case AR_SECTION:
- allocatable = pointer = 0;
- dimension = 1;
- break;
-
- case AR_ELEMENT:
- /* Handle coarrays. */
- if (ref->u.ar.dimen > 0)
- allocatable = pointer = 0;
- break;
-
- case AR_UNKNOWN:
- gfc_internal_error ("gfc_variable_attr(): Bad array reference");
- }
-
- break;
-
- case REF_COMPONENT:
- comp = ref->u.c.component;
- attr = comp->attr;
- if (ts != NULL)
- {
- *ts = comp->ts;
- /* Don't set the string length if a substring reference
- follows. */
- if (ts->type == BT_CHARACTER
- && ref->next && ref->next->type == REF_SUBSTRING)
- ts->u.cl = NULL;
- }
-
- if (comp->ts.type == BT_CLASS)
- {
- pointer = CLASS_DATA (comp)->attr.class_pointer;
- allocatable = CLASS_DATA (comp)->attr.allocatable;
- }
- else
- {
- pointer = comp->attr.pointer;
- allocatable = comp->attr.allocatable;
- }
- if (pointer || attr.proc_pointer)
- target = 1;
-
- break;
-
- case REF_SUBSTRING:
- allocatable = pointer = 0;
- break;
- }
-
- attr.dimension = dimension;
- attr.pointer = pointer;
- attr.allocatable = allocatable;
- attr.target = target;
- attr.save = sym->attr.save;
-
- return attr;
-}
-
-
-/* Return the attribute from a general expression. */
-
-symbol_attribute
-gfc_expr_attr (gfc_expr *e)
-{
- symbol_attribute attr;
-
- switch (e->expr_type)
- {
- case EXPR_VARIABLE:
- attr = gfc_variable_attr (e, NULL);
- break;
-
- case EXPR_FUNCTION:
- gfc_clear_attr (&attr);
-
- if (e->value.function.esym != NULL)
- {
- gfc_symbol *sym = e->value.function.esym->result;
- attr = sym->attr;
- if (sym->ts.type == BT_CLASS)
- {
- attr.dimension = CLASS_DATA (sym)->attr.dimension;
- attr.pointer = CLASS_DATA (sym)->attr.class_pointer;
- attr.allocatable = CLASS_DATA (sym)->attr.allocatable;
- }
- }
- else
- attr = gfc_variable_attr (e, NULL);
-
- /* TODO: NULL() returns pointers. May have to take care of this
- here. */
-
- break;
-
- default:
- gfc_clear_attr (&attr);
- break;
- }
-
- return attr;
-}
-
-
-/* Match a structure constructor. The initial symbol has already been
- seen. */
-
-typedef struct gfc_structure_ctor_component
-{
- char* name;
- gfc_expr* val;
- locus where;
- struct gfc_structure_ctor_component* next;
-}
-gfc_structure_ctor_component;
-
-#define gfc_get_structure_ctor_component() XCNEW (gfc_structure_ctor_component)
-
-static void
-gfc_free_structure_ctor_component (gfc_structure_ctor_component *comp)
-{
- free (comp->name);
- gfc_free_expr (comp->val);
- free (comp);
-}
-
-
-/* Translate the component list into the actual constructor by sorting it in
- the order required; this also checks along the way that each and every
- component actually has an initializer and handles default initializers
- for components without explicit value given. */
-static gfc_try
-build_actual_constructor (gfc_structure_ctor_component **comp_head,
- gfc_constructor_base *ctor_head, gfc_symbol *sym)
-{
- gfc_structure_ctor_component *comp_iter;
- gfc_component *comp;
-
- for (comp = sym->components; comp; comp = comp->next)
- {
- gfc_structure_ctor_component **next_ptr;
- gfc_expr *value = NULL;
-
- /* Try to find the initializer for the current component by name. */
- next_ptr = comp_head;
- for (comp_iter = *comp_head; comp_iter; comp_iter = comp_iter->next)
- {
- if (!strcmp (comp_iter->name, comp->name))
- break;
- next_ptr = &comp_iter->next;
- }
-
- /* If an extension, try building the parent derived type by building
- a value expression for the parent derived type and calling self. */
- if (!comp_iter && comp == sym->components && sym->attr.extension)
- {
- value = gfc_get_structure_constructor_expr (comp->ts.type,
- comp->ts.kind,
- &gfc_current_locus);
- value->ts = comp->ts;
-
- if (build_actual_constructor (comp_head, &value->value.constructor,
- comp->ts.u.derived) == FAILURE)
- {
- gfc_free_expr (value);
- return FAILURE;
- }
-
- gfc_constructor_append_expr (ctor_head, value, NULL);
- continue;
- }
-
- /* If it was not found, try the default initializer if there's any;
- otherwise, it's an error. */
- if (!comp_iter)
- {
- if (comp->initializer)
- {
- if (gfc_notify_std (GFC_STD_F2003, "Structure"
- " constructor with missing optional arguments"
- " at %C") == FAILURE)
- return FAILURE;
- value = gfc_copy_expr (comp->initializer);
- }
- else
- {
- gfc_error ("No initializer for component '%s' given in the"
- " structure constructor at %C!", comp->name);
- return FAILURE;
- }
- }
- else
- value = comp_iter->val;
-
- /* Add the value to the constructor chain built. */
- gfc_constructor_append_expr (ctor_head, value, NULL);
-
- /* Remove the entry from the component list. We don't want the expression
- value to be free'd, so set it to NULL. */
- if (comp_iter)
- {
- *next_ptr = comp_iter->next;
- comp_iter->val = NULL;
- gfc_free_structure_ctor_component (comp_iter);
- }
- }
- return SUCCESS;
-}
-
-
-gfc_try
-gfc_convert_to_structure_constructor (gfc_expr *e, gfc_symbol *sym, gfc_expr **cexpr,
- gfc_actual_arglist **arglist,
- bool parent)
-{
- gfc_actual_arglist *actual;
- gfc_structure_ctor_component *comp_tail, *comp_head, *comp_iter;
- gfc_constructor_base ctor_head = NULL;
- gfc_component *comp; /* Is set NULL when named component is first seen */
- const char* last_name = NULL;
- locus old_locus;
- gfc_expr *expr;
-
- expr = parent ? *cexpr : e;
- old_locus = gfc_current_locus;
- if (parent)
- ; /* gfc_current_locus = *arglist->expr ? ->where;*/
- else
- gfc_current_locus = expr->where;
-
- comp_tail = comp_head = NULL;
-
- if (!parent && sym->attr.abstract)
- {
- gfc_error ("Can't construct ABSTRACT type '%s' at %L",
- sym->name, &expr->where);
- goto cleanup;
- }
-
- comp = sym->components;
- actual = parent ? *arglist : expr->value.function.actual;
- for ( ; actual; )
- {
- gfc_component *this_comp = NULL;
-
- if (!comp_head)
- comp_tail = comp_head = gfc_get_structure_ctor_component ();
- else
- {
- comp_tail->next = gfc_get_structure_ctor_component ();
- comp_tail = comp_tail->next;
- }
- if (actual->name)
- {
- if (gfc_notify_std (GFC_STD_F2003, "Structure"
- " constructor with named arguments at %C")
- == FAILURE)
- goto cleanup;
-
- comp_tail->name = xstrdup (actual->name);
- last_name = comp_tail->name;
- comp = NULL;
- }
- else
- {
- /* Components without name are not allowed after the first named
- component initializer! */
- if (!comp)
- {
- if (last_name)
- gfc_error ("Component initializer without name after component"
- " named %s at %L!", last_name,
- actual->expr ? &actual->expr->where
- : &gfc_current_locus);
- else
- gfc_error ("Too many components in structure constructor at "
- "%L!", actual->expr ? &actual->expr->where
- : &gfc_current_locus);
- goto cleanup;
- }
-
- comp_tail->name = xstrdup (comp->name);
- }
-
- /* Find the current component in the structure definition and check
- its access is not private. */
- if (comp)
- this_comp = gfc_find_component (sym, comp->name, false, false);
- else
- {
- this_comp = gfc_find_component (sym, (const char *)comp_tail->name,
- false, false);
- comp = NULL; /* Reset needed! */
- }
-
- /* Here we can check if a component name is given which does not
- correspond to any component of the defined structure. */
- if (!this_comp)
- goto cleanup;
-
- comp_tail->val = actual->expr;
- if (actual->expr != NULL)
- comp_tail->where = actual->expr->where;
- actual->expr = NULL;
-
- /* Check if this component is already given a value. */
- for (comp_iter = comp_head; comp_iter != comp_tail;
- comp_iter = comp_iter->next)
- {
- gcc_assert (comp_iter);
- if (!strcmp (comp_iter->name, comp_tail->name))
- {
- gfc_error ("Component '%s' is initialized twice in the structure"
- " constructor at %L!", comp_tail->name,
- comp_tail->val ? &comp_tail->where
- : &gfc_current_locus);
- goto cleanup;
- }
- }
-
- /* F2008, R457/C725, for PURE C1283. */
- if (this_comp->attr.pointer && comp_tail->val
- && gfc_is_coindexed (comp_tail->val))
- {
- gfc_error ("Coindexed expression to pointer component '%s' in "
- "structure constructor at %L!", comp_tail->name,
- &comp_tail->where);
- goto cleanup;
- }
-
- /* If not explicitly a parent constructor, gather up the components
- and build one. */
- if (comp && comp == sym->components
- && sym->attr.extension
- && comp_tail->val
- && (comp_tail->val->ts.type != BT_DERIVED
- ||
- comp_tail->val->ts.u.derived != this_comp->ts.u.derived))
- {
- gfc_try m;
- gfc_actual_arglist *arg_null = NULL;
-
- actual->expr = comp_tail->val;
- comp_tail->val = NULL;
-
- m = gfc_convert_to_structure_constructor (NULL,
- comp->ts.u.derived, &comp_tail->val,
- comp->ts.u.derived->attr.zero_comp
- ? &arg_null : &actual, true);
- if (m == FAILURE)
- goto cleanup;
-
- if (comp->ts.u.derived->attr.zero_comp)
- {
- comp = comp->next;
- continue;
- }
- }
-
- if (comp)
- comp = comp->next;
- if (parent && !comp)
- break;
-
- actual = actual->next;
- }
-
- if (build_actual_constructor (&comp_head, &ctor_head, sym) == FAILURE)
- goto cleanup;
-
- /* No component should be left, as this should have caused an error in the
- loop constructing the component-list (name that does not correspond to any
- component in the structure definition). */
- if (comp_head && sym->attr.extension)
- {
- for (comp_iter = comp_head; comp_iter; comp_iter = comp_iter->next)
- {
- gfc_error ("component '%s' at %L has already been set by a "
- "parent derived type constructor", comp_iter->name,
- &comp_iter->where);
- }
- goto cleanup;
- }
- else
- gcc_assert (!comp_head);
-
- if (parent)
- {
- expr = gfc_get_structure_constructor_expr (BT_DERIVED, 0, &gfc_current_locus);
- expr->ts.u.derived = sym;
- expr->value.constructor = ctor_head;
- *cexpr = expr;
- }
- else
- {
- expr->ts.u.derived = sym;
- expr->ts.kind = 0;
- expr->ts.type = BT_DERIVED;
- expr->value.constructor = ctor_head;
- expr->expr_type = EXPR_STRUCTURE;
- }
-
- gfc_current_locus = old_locus;
- if (parent)
- *arglist = actual;
- return SUCCESS;
-
- cleanup:
- gfc_current_locus = old_locus;
-
- for (comp_iter = comp_head; comp_iter; )
- {
- gfc_structure_ctor_component *next = comp_iter->next;
- gfc_free_structure_ctor_component (comp_iter);
- comp_iter = next;
- }
- gfc_constructor_free (ctor_head);
-
- return FAILURE;
-}
-
-
-match
-gfc_match_structure_constructor (gfc_symbol *sym, gfc_expr **result)
-{
- match m;
- gfc_expr *e;
- gfc_symtree *symtree;
-
- gfc_get_sym_tree (sym->name, NULL, &symtree, false); /* Can't fail */
-
- e = gfc_get_expr ();
- e->symtree = symtree;
- e->expr_type = EXPR_FUNCTION;
-
- gcc_assert (sym->attr.flavor == FL_DERIVED
- && symtree->n.sym->attr.flavor == FL_PROCEDURE);
- e->value.function.esym = sym;
- e->symtree->n.sym->attr.generic = 1;
-
- m = gfc_match_actual_arglist (0, &e->value.function.actual);
- if (m != MATCH_YES)
- {
- gfc_free_expr (e);
- return m;
- }
-
- if (gfc_convert_to_structure_constructor (e, sym, NULL, NULL, false)
- != SUCCESS)
- {
- gfc_free_expr (e);
- return MATCH_ERROR;
- }
-
- *result = e;
- return MATCH_YES;
-}
-
-
-/* If the symbol is an implicit do loop index and implicitly typed,
- it should not be host associated. Provide a symtree from the
- current namespace. */
-static match
-check_for_implicit_index (gfc_symtree **st, gfc_symbol **sym)
-{
- if ((*sym)->attr.flavor == FL_VARIABLE
- && (*sym)->ns != gfc_current_ns
- && (*sym)->attr.implied_index
- && (*sym)->attr.implicit_type
- && !(*sym)->attr.use_assoc)
- {
- int i;
- i = gfc_get_sym_tree ((*sym)->name, NULL, st, false);
- if (i)
- return MATCH_ERROR;
- *sym = (*st)->n.sym;
- }
- return MATCH_YES;
-}
-
-
-/* Procedure pointer as function result: Replace the function symbol by the
- auto-generated hidden result variable named "ppr@". */
-
-static gfc_try
-replace_hidden_procptr_result (gfc_symbol **sym, gfc_symtree **st)
-{
- /* Check for procedure pointer result variable. */
- if ((*sym)->attr.function && !(*sym)->attr.external
- && (*sym)->result && (*sym)->result != *sym
- && (*sym)->result->attr.proc_pointer
- && (*sym) == gfc_current_ns->proc_name
- && (*sym) == (*sym)->result->ns->proc_name
- && strcmp ("ppr@", (*sym)->result->name) == 0)
- {
- /* Automatic replacement with "hidden" result variable. */
- (*sym)->result->attr.referenced = (*sym)->attr.referenced;
- *sym = (*sym)->result;
- *st = gfc_find_symtree ((*sym)->ns->sym_root, (*sym)->name);
- return SUCCESS;
- }
- return FAILURE;
-}
-
-
-/* Matches a variable name followed by anything that might follow it--
- array reference, argument list of a function, etc. */
-
-match
-gfc_match_rvalue (gfc_expr **result)
-{
- gfc_actual_arglist *actual_arglist;
- char name[GFC_MAX_SYMBOL_LEN + 1], argname[GFC_MAX_SYMBOL_LEN + 1];
- gfc_state_data *st;
- gfc_symbol *sym;
- gfc_symtree *symtree;
- locus where, old_loc;
- gfc_expr *e;
- match m, m2;
- int i;
- gfc_typespec *ts;
- bool implicit_char;
- gfc_ref *ref;
-
- m = gfc_match_name (name);
- if (m != MATCH_YES)
- return m;
-
- if (gfc_find_state (COMP_INTERFACE) == SUCCESS
- && !gfc_current_ns->has_import_set)
- i = gfc_get_sym_tree (name, NULL, &symtree, false);
- else
- i = gfc_get_ha_sym_tree (name, &symtree);
-
- if (i)
- return MATCH_ERROR;
-
- sym = symtree->n.sym;
- e = NULL;
- where = gfc_current_locus;
-
- replace_hidden_procptr_result (&sym, &symtree);
-
- /* If this is an implicit do loop index and implicitly typed,
- it should not be host associated. */
- m = check_for_implicit_index (&symtree, &sym);
- if (m != MATCH_YES)
- return m;
-
- gfc_set_sym_referenced (sym);
- sym->attr.implied_index = 0;
-
- if (sym->attr.function && sym->result == sym)
- {
- /* See if this is a directly recursive function call. */
- gfc_gobble_whitespace ();
- if (sym->attr.recursive
- && gfc_peek_ascii_char () == '('
- && gfc_current_ns->proc_name == sym
- && !sym->attr.dimension)
- {
- gfc_error ("'%s' at %C is the name of a recursive function "
- "and so refers to the result variable. Use an "
- "explicit RESULT variable for direct recursion "
- "(12.5.2.1)", sym->name);
- return MATCH_ERROR;
- }
-
- if (gfc_is_function_return_value (sym, gfc_current_ns))
- goto variable;
-
- if (sym->attr.entry
- && (sym->ns == gfc_current_ns
- || sym->ns == gfc_current_ns->parent))
- {
- gfc_entry_list *el = NULL;
-
- for (el = sym->ns->entries; el; el = el->next)
- if (sym == el->sym)
- goto variable;
- }
- }
-
- if (gfc_matching_procptr_assignment)
- goto procptr0;
-
- if (sym->attr.function || sym->attr.external || sym->attr.intrinsic)
- goto function0;
-
- if (sym->attr.generic)
- goto generic_function;
-
- switch (sym->attr.flavor)
- {
- case FL_VARIABLE:
- variable:
- e = gfc_get_expr ();
-
- e->expr_type = EXPR_VARIABLE;
- e->symtree = symtree;
-
- m = gfc_match_varspec (e, 0, false, true);
- break;
-
- case FL_PARAMETER:
- /* A statement of the form "REAL, parameter :: a(0:10) = 1" will
- end up here. Unfortunately, sym->value->expr_type is set to
- EXPR_CONSTANT, and so the if () branch would be followed without
- the !sym->as check. */
- if (sym->value && sym->value->expr_type != EXPR_ARRAY && !sym->as)
- e = gfc_copy_expr (sym->value);
- else
- {
- e = gfc_get_expr ();
- e->expr_type = EXPR_VARIABLE;
- }
-
- e->symtree = symtree;
- m = gfc_match_varspec (e, 0, false, true);
-
- if (sym->ts.is_c_interop || sym->ts.is_iso_c)
- break;
-
- /* Variable array references to derived type parameters cause
- all sorts of headaches in simplification. Treating such
- expressions as variable works just fine for all array
- references. */
- if (sym->value && sym->ts.type == BT_DERIVED && e->ref)
- {
- for (ref = e->ref; ref; ref = ref->next)
- if (ref->type == REF_ARRAY)
- break;
-
- if (ref == NULL || ref->u.ar.type == AR_FULL)
- break;
-
- ref = e->ref;
- e->ref = NULL;
- gfc_free_expr (e);
- e = gfc_get_expr ();
- e->expr_type = EXPR_VARIABLE;
- e->symtree = symtree;
- e->ref = ref;
- }
-
- break;
-
- case FL_DERIVED:
- sym = gfc_use_derived (sym);
- if (sym == NULL)
- m = MATCH_ERROR;
- else
- goto generic_function;
- break;
-
- /* If we're here, then the name is known to be the name of a
- procedure, yet it is not sure to be the name of a function. */
- case FL_PROCEDURE:
-
- /* Procedure Pointer Assignments. */
- procptr0:
- if (gfc_matching_procptr_assignment)
- {
- gfc_gobble_whitespace ();
- if (!sym->attr.dimension && gfc_peek_ascii_char () == '(')
- /* Parse functions returning a procptr. */
- goto function0;
-
- e = gfc_get_expr ();
- e->expr_type = EXPR_VARIABLE;
- e->symtree = symtree;
- m = gfc_match_varspec (e, 0, false, true);
- if (!e->ref && sym->attr.flavor == FL_UNKNOWN
- && sym->ts.type == BT_UNKNOWN
- && gfc_add_flavor (&sym->attr, FL_PROCEDURE,
- sym->name, NULL) == FAILURE)
- {
- m = MATCH_ERROR;
- break;
- }
- break;
- }
-
- if (sym->attr.subroutine)
- {
- gfc_error ("Unexpected use of subroutine name '%s' at %C",
- sym->name);
- m = MATCH_ERROR;
- break;
- }
-
- /* At this point, the name has to be a non-statement function.
- If the name is the same as the current function being
- compiled, then we have a variable reference (to the function
- result) if the name is non-recursive. */
-
- st = gfc_enclosing_unit (NULL);
-
- if (st != NULL && st->state == COMP_FUNCTION
- && st->sym == sym
- && !sym->attr.recursive)
- {
- e = gfc_get_expr ();
- e->symtree = symtree;
- e->expr_type = EXPR_VARIABLE;
-
- m = gfc_match_varspec (e, 0, false, true);
- break;
- }
-
- /* Match a function reference. */
- function0:
- m = gfc_match_actual_arglist (0, &actual_arglist);
- if (m == MATCH_NO)
- {
- if (sym->attr.proc == PROC_ST_FUNCTION)
- gfc_error ("Statement function '%s' requires argument list at %C",
- sym->name);
- else
- gfc_error ("Function '%s' requires an argument list at %C",
- sym->name);
-
- m = MATCH_ERROR;
- break;
- }
-
- if (m != MATCH_YES)
- {
- m = MATCH_ERROR;
- break;
- }
-
- gfc_get_ha_sym_tree (name, &symtree); /* Can't fail */
- sym = symtree->n.sym;
-
- replace_hidden_procptr_result (&sym, &symtree);
-
- e = gfc_get_expr ();
- e->symtree = symtree;
- e->expr_type = EXPR_FUNCTION;
- e->value.function.actual = actual_arglist;
- e->where = gfc_current_locus;
-
- if (sym->ts.type == BT_CLASS && sym->attr.class_ok
- && CLASS_DATA (sym)->as)
- e->rank = CLASS_DATA (sym)->as->rank;
- else if (sym->as != NULL)
- e->rank = sym->as->rank;
-
- if (!sym->attr.function
- && gfc_add_function (&sym->attr, sym->name, NULL) == FAILURE)
- {
- m = MATCH_ERROR;
- break;
- }
-
- /* Check here for the existence of at least one argument for the
- iso_c_binding functions C_LOC, C_FUNLOC, and C_ASSOCIATED. The
- argument(s) given will be checked in gfc_iso_c_func_interface,
- during resolution of the function call. */
- if (sym->attr.is_iso_c == 1
- && (sym->from_intmod == INTMOD_ISO_C_BINDING
- && (sym->intmod_sym_id == ISOCBINDING_LOC
- || sym->intmod_sym_id == ISOCBINDING_FUNLOC
- || sym->intmod_sym_id == ISOCBINDING_ASSOCIATED)))
- {
- /* make sure we were given a param */
- if (actual_arglist == NULL)
- {
- gfc_error ("Missing argument to '%s' at %C", sym->name);
- m = MATCH_ERROR;
- break;
- }
- }
-
- if (sym->result == NULL)
- sym->result = sym;
-
- m = MATCH_YES;
- break;
-
- case FL_UNKNOWN:
-
- /* Special case for derived type variables that get their types
- via an IMPLICIT statement. This can't wait for the
- resolution phase. */
-
- if (gfc_peek_ascii_char () == '%'
- && sym->ts.type == BT_UNKNOWN
- && gfc_get_default_type (sym->name, sym->ns)->type == BT_DERIVED)
- gfc_set_default_type (sym, 0, sym->ns);
-
- /* If the symbol has a (co)dimension attribute, the expression is a
- variable. */
-
- if (sym->attr.dimension || sym->attr.codimension)
- {
- if (gfc_add_flavor (&sym->attr, FL_VARIABLE,
- sym->name, NULL) == FAILURE)
- {
- m = MATCH_ERROR;
- break;
- }
-
- e = gfc_get_expr ();
- e->symtree = symtree;
- e->expr_type = EXPR_VARIABLE;
- m = gfc_match_varspec (e, 0, false, true);
- break;
- }
-
- if (sym->ts.type == BT_CLASS && sym->attr.class_ok
- && (CLASS_DATA (sym)->attr.dimension
- || CLASS_DATA (sym)->attr.codimension))
- {
- if (gfc_add_flavor (&sym->attr, FL_VARIABLE,
- sym->name, NULL) == FAILURE)
- {
- m = MATCH_ERROR;
- break;
- }
-
- e = gfc_get_expr ();
- e->symtree = symtree;
- e->expr_type = EXPR_VARIABLE;
- m = gfc_match_varspec (e, 0, false, true);
- break;
- }
-
- /* Name is not an array, so we peek to see if a '(' implies a
- function call or a substring reference. Otherwise the
- variable is just a scalar. */
-
- gfc_gobble_whitespace ();
- if (gfc_peek_ascii_char () != '(')
- {
- /* Assume a scalar variable */
- e = gfc_get_expr ();
- e->symtree = symtree;
- e->expr_type = EXPR_VARIABLE;
-
- if (gfc_add_flavor (&sym->attr, FL_VARIABLE,
- sym->name, NULL) == FAILURE)
- {
- m = MATCH_ERROR;
- break;
- }
-
- /*FIXME:??? gfc_match_varspec does set this for us: */
- e->ts = sym->ts;
- m = gfc_match_varspec (e, 0, false, true);
- break;
- }
-
- /* See if this is a function reference with a keyword argument
- as first argument. We do this because otherwise a spurious
- symbol would end up in the symbol table. */
-
- old_loc = gfc_current_locus;
- m2 = gfc_match (" ( %n =", argname);
- gfc_current_locus = old_loc;
-
- e = gfc_get_expr ();
- e->symtree = symtree;
-
- if (m2 != MATCH_YES)
- {
- /* Try to figure out whether we're dealing with a character type.
- We're peeking ahead here, because we don't want to call
- match_substring if we're dealing with an implicitly typed
- non-character variable. */
- implicit_char = false;
- if (sym->ts.type == BT_UNKNOWN)
- {
- ts = gfc_get_default_type (sym->name, NULL);
- if (ts->type == BT_CHARACTER)
- implicit_char = true;
- }
-
- /* See if this could possibly be a substring reference of a name
- that we're not sure is a variable yet. */
-
- if ((implicit_char || sym->ts.type == BT_CHARACTER)
- && match_substring (sym->ts.u.cl, 0, &e->ref) == MATCH_YES)
- {
-
- e->expr_type = EXPR_VARIABLE;
-
- if (sym->attr.flavor != FL_VARIABLE
- && gfc_add_flavor (&sym->attr, FL_VARIABLE,
- sym->name, NULL) == FAILURE)
- {
- m = MATCH_ERROR;
- break;
- }
-
- if (sym->ts.type == BT_UNKNOWN
- && gfc_set_default_type (sym, 1, NULL) == FAILURE)
- {
- m = MATCH_ERROR;
- break;
- }
-
- e->ts = sym->ts;
- if (e->ref)
- e->ts.u.cl = NULL;
- m = MATCH_YES;
- break;
- }
- }
-
- /* Give up, assume we have a function. */
-
- gfc_get_sym_tree (name, NULL, &symtree, false); /* Can't fail */
- sym = symtree->n.sym;
- e->expr_type = EXPR_FUNCTION;
-
- if (!sym->attr.function
- && gfc_add_function (&sym->attr, sym->name, NULL) == FAILURE)
- {
- m = MATCH_ERROR;
- break;
- }
-
- sym->result = sym;
-
- m = gfc_match_actual_arglist (0, &e->value.function.actual);
- if (m == MATCH_NO)
- gfc_error ("Missing argument list in function '%s' at %C", sym->name);
-
- if (m != MATCH_YES)
- {
- m = MATCH_ERROR;
- break;
- }
-
- /* If our new function returns a character, array or structure
- type, it might have subsequent references. */
-
- m = gfc_match_varspec (e, 0, false, true);
- if (m == MATCH_NO)
- m = MATCH_YES;
-
- break;
-
- generic_function:
- gfc_get_sym_tree (name, NULL, &symtree, false); /* Can't fail */
-
- e = gfc_get_expr ();
- e->symtree = symtree;
- e->expr_type = EXPR_FUNCTION;
-
- if (sym->attr.flavor == FL_DERIVED)
- {
- e->value.function.esym = sym;
- e->symtree->n.sym->attr.generic = 1;
- }
-
- m = gfc_match_actual_arglist (0, &e->value.function.actual);
- break;
-
- default:
- gfc_error ("Symbol at %C is not appropriate for an expression");
- return MATCH_ERROR;
- }
-
- if (m == MATCH_YES)
- {
- e->where = where;
- *result = e;
- }
- else
- gfc_free_expr (e);
-
- return m;
-}
-
-
-/* Match a variable, i.e. something that can be assigned to. This
- starts as a symbol, can be a structure component or an array
- reference. It can be a function if the function doesn't have a
- separate RESULT variable. If the symbol has not been previously
- seen, we assume it is a variable.
-
- This function is called by two interface functions:
- gfc_match_variable, which has host_flag = 1, and
- gfc_match_equiv_variable, with host_flag = 0, to restrict the
- match of the symbol to the local scope. */
-
-static match
-match_variable (gfc_expr **result, int equiv_flag, int host_flag)
-{
- gfc_symbol *sym;
- gfc_symtree *st;
- gfc_expr *expr;
- locus where;
- match m;
-
- /* Since nothing has any business being an lvalue in a module
- specification block, an interface block or a contains section,
- we force the changed_symbols mechanism to work by setting
- host_flag to 0. This prevents valid symbols that have the name
- of keywords, such as 'end', being turned into variables by
- failed matching to assignments for, e.g., END INTERFACE. */
- if (gfc_current_state () == COMP_MODULE
- || gfc_current_state () == COMP_INTERFACE
- || gfc_current_state () == COMP_CONTAINS)
- host_flag = 0;
-
- where = gfc_current_locus;
- m = gfc_match_sym_tree (&st, host_flag);
- if (m != MATCH_YES)
- return m;
-
- sym = st->n.sym;
-
- /* If this is an implicit do loop index and implicitly typed,
- it should not be host associated. */
- m = check_for_implicit_index (&st, &sym);
- if (m != MATCH_YES)
- return m;
-
- sym->attr.implied_index = 0;
-
- gfc_set_sym_referenced (sym);
- switch (sym->attr.flavor)
- {
- case FL_VARIABLE:
- /* Everything is alright. */
- break;
-
- case FL_UNKNOWN:
- {
- sym_flavor flavor = FL_UNKNOWN;
-
- gfc_gobble_whitespace ();
-
- if (sym->attr.external || sym->attr.procedure
- || sym->attr.function || sym->attr.subroutine)
- flavor = FL_PROCEDURE;
-
- /* If it is not a procedure, is not typed and is host associated,
- we cannot give it a flavor yet. */
- else if (sym->ns == gfc_current_ns->parent
- && sym->ts.type == BT_UNKNOWN)
- break;
-
- /* These are definitive indicators that this is a variable. */
- else if (gfc_peek_ascii_char () != '(' || sym->ts.type != BT_UNKNOWN
- || sym->attr.pointer || sym->as != NULL)
- flavor = FL_VARIABLE;
-
- if (flavor != FL_UNKNOWN
- && gfc_add_flavor (&sym->attr, flavor, sym->name, NULL) == FAILURE)
- return MATCH_ERROR;
- }
- break;
-
- case FL_PARAMETER:
- if (equiv_flag)
- {
- gfc_error ("Named constant at %C in an EQUIVALENCE");
- return MATCH_ERROR;
- }
- /* Otherwise this is checked for and an error given in the
- variable definition context checks. */
- break;
-
- case FL_PROCEDURE:
- /* Check for a nonrecursive function result variable. */
- if (sym->attr.function
- && !sym->attr.external
- && sym->result == sym
- && (gfc_is_function_return_value (sym, gfc_current_ns)
- || (sym->attr.entry
- && sym->ns == gfc_current_ns)
- || (sym->attr.entry
- && sym->ns == gfc_current_ns->parent)))
- {
- /* If a function result is a derived type, then the derived
- type may still have to be resolved. */
-
- if (sym->ts.type == BT_DERIVED
- && gfc_use_derived (sym->ts.u.derived) == NULL)
- return MATCH_ERROR;
- break;
- }
-
- if (sym->attr.proc_pointer
- || replace_hidden_procptr_result (&sym, &st) == SUCCESS)
- break;
-
- /* Fall through to error */
-
- default:
- gfc_error ("'%s' at %C is not a variable", sym->name);
- return MATCH_ERROR;
- }
-
- /* Special case for derived type variables that get their types
- via an IMPLICIT statement. This can't wait for the
- resolution phase. */
-
- {
- gfc_namespace * implicit_ns;
-
- if (gfc_current_ns->proc_name == sym)
- implicit_ns = gfc_current_ns;
- else
- implicit_ns = sym->ns;
-
- if (gfc_peek_ascii_char () == '%'
- && sym->ts.type == BT_UNKNOWN
- && gfc_get_default_type (sym->name, implicit_ns)->type == BT_DERIVED)
- gfc_set_default_type (sym, 0, implicit_ns);
- }
-
- expr = gfc_get_expr ();
-
- expr->expr_type = EXPR_VARIABLE;
- expr->symtree = st;
- expr->ts = sym->ts;
- expr->where = where;
-
- /* Now see if we have to do more. */
- m = gfc_match_varspec (expr, equiv_flag, false, false);
- if (m != MATCH_YES)
- {
- gfc_free_expr (expr);
- return m;
- }
-
- *result = expr;
- return MATCH_YES;
-}
-
-
-match
-gfc_match_variable (gfc_expr **result, int equiv_flag)
-{
- return match_variable (result, equiv_flag, 1);
-}
-
-
-match
-gfc_match_equiv_variable (gfc_expr **result)
-{
- return match_variable (result, 1, 0);
-}
-