[Mono-bugs] [Bug 358102] New: MCS generates unverifiable code for ternary ? : operator.

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Fri Feb 1 13:55:22 EST 2008


https://bugzilla.novell.com/show_bug.cgi?id=358102


           Summary: MCS generates unverifiable code for ternary ? :
                    operator.
           Product: Mono: Compilers
           Version: unspecified
          Platform: Other
        OS/Version: Other
            Status: NEW
          Severity: Normal
          Priority: P5 - None
         Component: C#
        AssignedTo: mono-bugs at lists.ximian.com
        ReportedBy: rkumpera at novell.com
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---


Created an attachment (id=192839)
 --> (https://bugzilla.novell.com/attachment.cgi?id=192839)
C# code that causes this bug.

When the ternary operator type is an interface type, MCS doesn't explicitly
type it to the required interface. Given the following:

interface ParentA
interface ParentB
class Foo : ParentA, ParentB
class Bar : ParentA, ParentB


ParentB p;
Foo f = new Foo();
Bar b = new Bar();
..
p = args == null ? (ParentB) f : (ParentB) b;
..
p.TestB();


the assignment using the ternary operator will be emit as follow:


ldarg.0

brtrue     LABEL_1



ldloc.1

br         LABEL_2



LABEL_1:
ldloc.2

LABEL_2:

stloc.0

What happens is that the verifier cannot infer that the type on stack before
the stloc.0 is executed is of type ParentB. This happens because the stack
merge algorithm uses only parent types when deciding which is the common type.
This is described in Part III 1.8.1.3 of ECMA 335.

This code compiled with mcs is not verifiable under MS. The MS verifier picks
the first common interface of Foo and Bar, which is wrong, but doesn't use a
full join type of the 2 interfaces.

CSC uses a clever hack to compile such code in a verifiable way. It stores the
intermediate values in a local variable with the expected type. The code looks
like this:

//V_4 type is ParentB
ldarg.0

brtrue  LABEL_1




ldloc.1

stloc.s    V_4

ldloc.s    V_4

br.s       LABEL_2



LABEL_1:
ldloc.2


LABEL_2:
stloc.0


This code works because the stack merge in the stloc.0 between ParentB and Bar
will result in ParentB been selected.

Fixing this is important for Moonlight as it could cause assemblies compiled by
mcs to fail loading under Silverligth.


-- 
Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.


More information about the mono-bugs mailing list