missing code from IL

P

p3john

Hi all,
Not sure if this is the correct newsgroup for this, but I'm in a jamb and
need some input.

I came across a problem that I think is related to the C# compiler in Visual
Studio 2008. The behavior is described by by Kathleen Dollard
(http://www.gendotnet.com/Home/TechnicalPapers/VisualBasic90CompilerBug/tabid/652/Default.aspx) - however my project environment is different.

Here's the gist: I have an assembly with a class in it, I write pages of
code and compile it.
Part of my code says something like:
if ( customer.ReturnPayment )
{
// do cool stuff here
}
if ( customer.RequiresCreditApproval )
{
// do other even cooler stuff here
}

That second IF statement never makes it to the compiled assembly. I can tell
this because I do 2 things that demonstrate the bug (if it's a bug). First, I
set a breakpoint inside the first IF statement (breakpoint on "do cool
stuff"), second I run the app in the debugger.

As soon as the debugger starts the breakpoint moves to the second IF
statement.

I dissassemble the assembly using Reflector, the first IF statement not
there; thus the breakpoint issue.

Now, if I change the Target Framework of my project from .Net Framework 2.0
to 3.5 - everything works fine.
Unfortunately, I cannot use 3.5 yet - minimum system requires for
application specify 2.0.

I need a solution or at least an reason as to *why* this happens, any ideas?

-John
 
B

Ben Voigt [C++ MVP]

p3john said:
Hi all,
Not sure if this is the correct newsgroup for this, but I'm in a jamb and
need some input.

I came across a problem that I think is related to the C# compiler in
Visual
Studio 2008. The behavior is described by by Kathleen Dollard
(http://www.gendotnet.com/Home/TechnicalPapers/VisualBasic90CompilerBug/tabid/652/Default.aspx)
- however my project environment is different.

Here's the gist: I have an assembly with a class in it, I write pages of
code and compile it.
Part of my code says something like:
if ( customer.ReturnPayment )
{
// do cool stuff here
}
if ( customer.RequiresCreditApproval )
{
// do other even cooler stuff here
}

That second IF statement never makes it to the compiled assembly. I can
tell
this because I do 2 things that demonstrate the bug (if it's a bug).
First, I
set a breakpoint inside the first IF statement (breakpoint on "do cool
stuff"), second I run the app in the debugger.

As soon as the debugger starts the breakpoint moves to the second IF
statement.

I dissassemble the assembly using Reflector, the first IF statement not
there; thus the breakpoint issue.

Does it happen in both debug and release mode, or only release? Is there
any possibility that the condition could never be true?
 
M

Marc Gravell

Part of my code says something like:

Unfortunately, I suspect that this is one of those occasions where the
*exact* details matter. While I don't preclude a compiler bug, it
seems prudent to at least verify local causes first.

As Ben notes, if the condition never possibly being true would be a
possible cause - the following doesn't get included, for example (yes
this is a trivial example) - just the naked method signature:

static void Main()
{
if (false)
{
Console.WriteLine("Hi");
}
}

Have you got any conditional constants, for example. Anything funny
(target-wise) in your project files?
And perhaps more importantly - even if it compiles, are there any
compiler warnings? (the above raises a warning)

Marc
 
P

p3john

Ben, Marc,
Thanks for the replies.

I know the condition is true at least once. It is part of a while loop.

I have no funky targets in the project but did not think to check the
warnings... I'll do that and post back if anything shakes out of that.

Why wouldn't that could be included in the assembly? The property is a
boolean and I do not see how the compiler would know that the condition would
never be true - I can see the point that if the condition is never true then
why bother outputting it.
 
M

Marc Gravell

Well, I don't know how far the compiler will probe into methods
(usually "not very", since that is usually the job of the JIT), but
*if* the property is in the same assembly and isn't virtual (or on an
interface) then I guess that *in theory* it could see obvious "always
true" / "always false" conditions and optimise-away the code-block.
For instance, using "is" on a type that clearly isn't compatible, or
is alwas compatible; or if it performs an obvious test against
constants; etc.

I don't suppose you'd care to post the property?

Marc
 
P

p3john

I can post a bit of it, though I need to be careful as it is considered
proprietary:

The property is on an object that is literally just a bunch of properties
and I use the object as a DTO. For brevity I've stripped the other properties.

internal class TaxTrustReportEntity : ITaxTrustReportEntity
{
..
..
..

private double _amountOfEarningsFromInsurancePayments;
public double AmountOfEarningsFromInsurancePayments
{
get
{
return _amountOfEarningsFromInsurancePayments;
}
set
{
_amountOfEarningsFromInsurancePayments = value;
}
}

..
..
..
}
__________

Here's how that property is used on that object: That object is created and
populated by a "calculator" that uses a loop and makes several calculations,
assigning the values of the calculations to the object.
At the end of the loop there is a validation that says this:

if(taxReportEntity.AmountOfEarningsFromInsurancePayments < 0)
{
paymentsWithIns = 0;
earningsOnIns = 0;
}
else
{
paymentsWithIns = paymentsToTrust;
}

Simple stuff, just update the values of some variables based on the property
value.
It is the first branch (the true portion) of the IF statement that does not
make it to IL.

-John
 
M

Marc Gravell

But note: to investigate it properly, I suspect that MS would need
something reproducable.

Marc
 
P

p3john

Thanks Marc,
I'll log it and see what happens. I was pretty sure it was a bug but wanted
to run it by the community first in case I was overlooking something.
 
L

Lasse Vågsæther Karlsen

p3john said:
if(taxReportEntity.AmountOfEarningsFromInsurancePayments < 0)
{
paymentsWithIns = 0;
earningsOnIns = 0;
}
else
{
paymentsWithIns = paymentsToTrust;
}

I am assuming here that your code is exactly as posted, or a close
variation of this. If you have method class or whatnot inside this, then
I guess this whole post doesn't apply.

Anyway, just a thought, but could it be possible that the compiler has
determined that those two assignments are unnecessary, either because:

1. the compiler determines that the variables already has those values
2. the compiler determines that the variables are unused throughout the
rest of their scope
(3. are there other similar cases?)

If either of these are true, it could possibly lead to the whole branch
being optimized away, since the code in that branch does nothing "useful".

Basically, perhaps the compiler is rewriting this code to be:

if(!(taxReportEntity.AmountOfEarningsFromInsurancePayments < 0))
{
paymentsWithIns = paymentsToTrust;
}

I do not know if the compiler is capable of doing this optimization
though, I guess someone more into the compiler system would perhaps know
that.

But, I would assume that the warnings you mentioned would contain
information about either of these cases, at least the part relating to
the assignments.

Did you check out your warnings and see if anything popped up?
 
L

Lasse Vågsæther Karlsen

variation of this. If you have method class or whatnot inside this, then

I don't really know what a "method class" is. I'm assuming I meant
"method call". :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top