Flow of control analysis

Esmond Hart asks:

I code a lot of VB.NET and the bug I make most often is forgetting to return the result of a function call. Daft but true. How I would welcome an option that flagged each End Function statement without a Return statement immediately preceding it. Option EvenStricter maybe.

Well, we’ll actually be doing better than this in Whidbey! One of the major features that we’re implementing in the compiler for Whidbey is “flow of control” analysis. This allows us to track at compile-time the ways in which a method can execute and then give the user warnings based on that analysis. For example, take the following code snippet: (I realize it’s a nonsense function, but my brain is working slowly this morning and I can’t think of anything better.)

Function Test(ByVal Value As Integer) As Integer
Dim c,d As Collection

If Value > 0 Then
c = New Collection()
End If


If Value < 0 Then
Return Value
End If
End Function

In Whidbey the compiler will be able to walk through the function and figure out the ways in which it might be executed, determining the following things:

  • It’s possible that the variable c will be used without having assigned it a value.
  • It’s possible that the function will not explicitly return a value.
  • The local variable d was never used.

Once we’ve determined these things, we’ll give warnings on them. Pretty cool, huh? (Yes, I know, compilers for the C family of languages [and many, many others, I’m sure] have had this for forever, but it’s nice to join the party.)

16 thoughts on “Flow of control analysis”

  1. The "xxx is unused" or "not all paths return a value" always kinda bugged me…I was always like "leave me alone, I know what I’m doing"…most of the time I didn’t though and the compiler was right πŸ™‚

    Anyways, what took so long to implement that in the compiler? is it the sometimes ambiguous nature of VB?

  2. Ummmm. Would Whidbey stop that the function wouldn’t hit an explicit Return when Value >= 0 …? Or that Value = 0 isn’t handled? Or that a Select Case… might be a better alternative?

    I know the code is trivial, but all of the above are common coding errors… Or is it just me?

  3. It wasn’t language issues that stood in the way of providing more warnings, it was mostly a question of when the work could be done. (It’s not a small amount of work.) We definitely will have to work hard to find the right balance between giving people useful warnings and annoying them. We’re looking to beta to help us fine tune it.

    We won’t, unfortunately, be going deeper into questions such as "did you handle all possible values of this variable." Maybe sometime in the future, but that’s beyond the capabilities of the code today.

  4. (It seems there’s a server error when a comment containing unescaped &lt; and &gt; is submitted.)

    We were hoping for this ever since it was clear VB was using the C compiler’s back-end for compilation. Like you say, all those "features" of compiled languages that are (almost) assumed to be there — dead-code removal, simple expression folding, etc — are taught at Uni as solved problems that should be in any (optimising) compiler.

    And I believe that this was missing was another reason why a whole class of people "looked down" on VB.

    In fact, when I saw there was a released version of the C++ compiler that explicitly excluded the optimizer, I hoped that mean it was componentised enough to be imported into VB. (The CL included with the free .NET SDK seems to be the "same" version — no optimize options.)

    Will flow analisys occur during the IDE background compile so that you get wiggly underlines "instantly", or is this sort of thing better left until an explicit compile?

    And does these features reduce the utility of the VB concept of the "functionname" variable? That is, is it still supported equally to Return statements? (IMHO both have good uses.)

    Oh, and following on from that, what about code that does rely on an unassigned "functionname" variable will return Empty?

  5. (I’d noticed the thing about &lt; and &gt; but haven’t had a chance to work on it yet. Sorry about that. It’s part of the protection against HTML script injection.)

    How exactly flow analysis will be surfaced is something we’re talking about now and is something we’ll have to play around with. The most logical thing to say is that you get the warnings just like other errors from the background compiler, but we need to see how well that works. Is it going to be distracting/annoying to type "Dim x As Integer" and hit return and immediately get a warning that x is unused? If not in the background, do we do it on build? Interesting questions and something we’ll have to work out in practical use.

    I believe we track the return function variable the same as the Return statement. If you want to rely on implicit return values, you’ll have to turn that warning off (which you’ll be able to do).

  6. Paul:> "Dim x As Integer" and hit return and immediately get a warning that x is unused? If not in the background, do we do it on build?

    It would be quite irritating if it came immediately. One trick you can play is report the error anyway but use a delay timer in the task-list that controls *when* the error is actually seen by the user. So one can say something like "warn me after X minutes if variables are still unused."

    Also whatever you do, please *don’t* disallow the ability to return values implicitly. I personally rely on this a lot because the compiler generates less code when I do Exit Function, instead of Return X. Code is generated to clean up the stack for *every* Return statement, whereas an all Exit Function statements share stack clean-up code by doing a simple jmp to the end of the routine where clean-up code is located.

    Another simple optimisation you can consider is making Return X be equal to Exit Function, when X is a literal value that is also the default value for the function’s return type.

    Aaaaah, I cant wait for Whidbey!! BTW Paul, since the compilers are now free, why dont you release public beta copies so a lot more people can test-drive them?

  7. I’m not so sure about the warnings being that annoying. With the background compilation always running, it’s not uncommon to get transient errors as you type that clear up when you finish filling out a particular structure. I’m not sure that it will be any worse than that, but we’ll see.

    The return value warnings will only occur when you use the Return statement in a method, so your case seems to be safe.

    As for the beta and how that’s organized, I don’t know much about that and am not involved that much in it, but as we’ve seen with the Community Preview being available on MSDN, things are definitely moving in the direction of more openness for releases.

  8. It wouldn’t be any different than typing:

    Public Enum Test

    End Enum

    and getting the warning that test must contain at least one member. I personally like that much better than having to wait until I build the solution to get the error, like some other languages that I know.

  9. Pingback: Panopticon Central

Leave a Reply