Bug 2677 - weirdness w/ternary operator (a?b:c)
: weirdness w/ternary operator (a?b:c)
Status: RESOLVED FIXED
: Pike
Compiler
: 7.2
: All Other
: P3 (normal) normal
: ---
Assigned To:
:
:
: 2589
  Show dependency treegraph
 
Reported: 2002-01-13 11:58 CET by
Modified: 2002-05-14 18:13 CET (History)
Scrum Prio:
In scrum?: ---
Story included in sprints:
Unplanned in sprints:


Attachments


Description From 2002-01-13 11:58:08 CET
From: "Robert J. Budzynski" <Robert.Budzynski@fuw.edu.pl>
Subject: weirdness w/ternary operator (a?b:c)
To: pike@roxen.com
Date: Sun Jan 13 02:12:14 2002 +0100

Pike v7.2 release 234 running Hilfe v2.0 (Incremental Pike Frontend)
> mixed foo(mixed x){return x?(write("FOO\n"),"FOO"):werror("BAR\n");}
> foo(1);
FOO
Result: 1
> foo(0);
BAR
Result: 0
> mixed fooo(mixed x){return
x?(write("FOO\n"),"FOO"):(werror("BAR\n"),"BAR");}
> fooo(0);
BAR
Result: "BAR"
> fooo(1);
FOO
Result: "FOO"

Note that while fooo() works correctly, the return value of foo(1) is
bogus. Pike is getting confused when the third arg of the ternary operator
(the `c' in a?b:c) is a call to a function of return type void.
------- Comment #1 From 2002-02-14 15:32:08 CET -------
The reason seems to be due to stacklevel adjustments.
The return value "FOO" is removed in an attempt to adjust the stacklevel to the
same as for the werror (ie zero).

Note the pop_n_elems(1) below:

---   7: byte(1)
---   7: byte(1)
---   7: entry
---   7: function start
---   7: label(0)
---   7: local(0)
---   7: branch if zero(2)
---   7: mark
---   7: string(0)
---   7: apply(1)
---   7: pop
---   7: string(1)
---   7: pop_n_elems(1)
---   7: return
---   7: label(2)
---   7: string(2)
---   7: call builtin 1(2)
---   7: nop
---   7: return
---   7: push int(0)
---   7: return
------- Comment #2 From 2002-02-14 15:52:15 CET -------
Fixed in Pike 7.3:

Pike v7.3 release 14 running Hilfe v2.0 (Incremental Pike Frontend)
> mixed foo(mixed x){return x?(write("FOO\n"),"FOO"):werror("BAR\n");}
-:1:The arguments to ?: may not be void.
------- Comment #3 From 2002-02-28 13:24:31 CET -------
The fix is bad for three reasons (ordered from least to most subjective):

1.  The error can kick in for if statements too. I've encountered that in this
    case:

    int main (int x)
    {
      if (x) // The arguments to ?: may not be void.
    x = 1;
      else
    foo: break foo;
    }

    (This is added to the test suite.)

2.  This new restriction breaks compatibility; it should at least be made
    dependent on compat_version.

3.  The ?: in itself should not have this restriction. For instance there's no
    semantic problem writing

    x?(write("FOO\n"),"FOO"):werror("BAR\n");

    as a statement. (It's conceivable that this can occur as a result of macro
    expansions.)

    A better way to fix it would be to let the ?: expression have void as
result
    type when either operand is void (unless perhaps when the test is constant
    and the void operand can be optimized away), and then fix the check in the
    return statement so that the type of the expression isn't void (at least
    when the function return type isn't void).
------- Comment #4 From 2002-04-07 15:18:26 CET -------
Added to bug 2589, since it blocks green AutoBuild.
------- Comment #5 From 2002-05-09 17:19:47 CET -------
Fixed in Pike 7.3.
------- Comment #6 From 2002-05-14 17:15:39 CET -------
Hmm... Still triggered by the following code:

Pike v7.3 release 45 running Hilfe v3.4 (Incremental Pike Frontend)
> void foo(mixed x){return x?werror("FOO\n"):werror("BAR\n");}
> foo(0);
BAR
(1) Result: 0
> foo(1);
FOO
(2) Result: 1
------- Comment #7 From 2002-05-14 18:14:20 CET -------
The latter problem wasn't in ?:, but in return of void expressions:

Pike v7.3 release 45 running Hilfe v3.4 (Incremental Pike Frontend)
> void foo(mixed x){return werror("FOO\n");}
> foo(0);
FOO
(1) Result: 0
> foo(1);
FOO
(2) Result: 1



Fixed:

Pike v7.3 release 45 running Hilfe v3.4 (Incremental Pike Frontend)
> void foo(mixed x){return x?werror("FOO\n"):werror("BAR\n");}
Compiler Warning: 1:Returning a void expression. Converted to zero.
Compiler Error: 1:Wrong return type.
Compiler Error: 1:Expected: void
Compiler Error: 1:Got     : zero
> int foo(mixed x){return x?werror("FOO\n"):werror("BAR\n");}
> foo(0);
BAR
(1) Result: 0
> foo(1);
FOO
(2) Result: 0
> void foo(mixed x){return werror("FOO\n");}
Compiler Warning: 1:Returning a void expression. Converted to zero.
Compiler Error: 1:Wrong return type.
Compiler Error: 1:Expected: void
Compiler Error: 1:Got     : zero
> int foo(mixed x){return werror("FOO\n");}
> foo(0);
FOO
(3) Result: 0
> foo(1);
FOO
(4) Result: 0

Note

You need to log in before you can comment on or make changes to this bug.