Hi Yuao,

Tobias Burnus wrote:
Based on our previous discussion, we
don't need to necessarily handle this in the current patch; I just
wanted to highlight it. I will investigate how the argument-passing
logic works.

Yes, as long as there is a 'sorry' instead of producing wrong code,
it is fine. But I would like to avoid seeing runtime fails.

BTW: When thinking about the item below, I think the following
needs to have a condition:

  /* Match an expression in parentheses.  */
  if (gfc_match_char ('(') != MATCH_YES)
...
  m = match_conditional (&e);
...
  m = gfc_match_char (')');
...
  /* Now we have the expression inside the parentheses, build the
     expression pointing to it. By 7.1.7.2, any expression in
     parentheses shall be treated as a data entity.  */
  *result = gfc_get_parentheses (e);

Namely, if 'e->expr_type == EXPR_CONDITIONAL, the extra parentheses
should not be added.

Otherwise, we cannot later distinguish
  ( cond ? a : b )
from
  ( (cond ? a : b ) )

As actual argument to a procedure, the first one is a variable
while the second one is an expression. Besides using this for
constraint checking (for errors), it matters for:
  lbound(...)

For expressions, the lower array bound is always 1, otherwise
it is the the one of the passed variable, e.g., for
'integer :: a(-5:4)', it would be -5.

* * *

I think something like the following would be useful during
parsing:

+  gfc_gobble_whitespace ();
+  locus saved_loc = gfc_current_locus;
   m = gfc_match_expr (&true_expr);
+  if (m != MATCH_YES && (m = gfc_match (".nil.")) == MATCH_YES)
+    true_expr = gfc_get_..._expr (saved_loc, ... )
   if (m != MATCH_YES)

To parse the .nil.; I think in the first round, we should reject
it unconditionally during resolving.

I am not completely sure how to store it, but I was wondering
whether it should be added to operator (EXPR_OP), which is contrary
to the others does not take any expression. As it should only be
reachable by resolving the conditional operation, it shouldn't
harm elsewhere but needs to be handled everywhere where
conditional is processed. During parsing, it should be parsed after
other options failed while during resolution/dumping, it needs to
be handled before as, e.g., resolve_operator does not know about it
(nor does it need to, IMHO).

* * *

In any case, we later have to handle the three cases:
- accept it for actual arguments to OPTIONAL dummy arguments
- reject it for dummy arguments that are not OPTIONAL
- reject it when not used as actual argument.

I wonder whether we can just reject it unconditionally,
except when explicitly processed as actual argument.
Thus, in resolve_conditional, we could rejected in general.

When processing actual arguments, only expr == EXPR_CONDITIONAL
with either argument being .NIL. makes sense (or the first/second
being again a EXPR_CONDITIONAL). Thus, those could be explicitly
handled for the OPTIONAL check. To mark the .NIL. and to be not
diagnosed, I think we can just set the expr->do_not_resolve_again = 1
in the argument handling - and check for it with a comment in
resolve_conditional, skipping the .NIL. diagnostic only
in that case.

The only caveat is that there are many ways to call procedures
(functions and subroutines, specific or generic, type-bound or
procedure pointers), including intrinsic procedures, which are
resolved slightly differently. - I am not sure how many call paths
remain that need to be checked, hopefully not many!
In several cases, the normal diagnostic will do as not all take
optional arguments, but some – including intrinsic procedures -
do.

In any case, I think we should soon handle .NIL., but first reject
it unconditionally.

Tobias

Reply via email to