10

When I compile C++ code with Visual C++ 9 with "warning level 4" the following:

while( true ) {
   //loop body with break on certain condition
}

and the following:

for( ; true; ) {
   //same loop body
}

both trigger C4127: conditional expression is constant warning but the following:

for( ; ; ) {
   //same loop body
}

compiles without warning.

Why this difference, especially between the second and the third variant?

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 1
    because there is no any conditional expression in third statement...while it is there in second and third.... how can compiler generate warning regarding conditional expression without having any? – Mihir Mehta Mar 10 '11 at 10:08
  • 1
    I usually end up disabling C4127 with `#pragma warning`, especially when using boost. – Alexandre C. Mar 10 '11 at 10:38
  • Related: http://stackoverflow.com/questions/224421/constant-value-in-conditional-expression – CesarB Dec 02 '12 at 10:44

5 Answers5

10

The reason for warning the user of constant conditional expressions is to help avoid bugs where the expression ends up being constant (for example, due to a typo). In the last case, there is no expression, so there is no risk of it accidentally being constant.

Tal Pressman
  • 7,199
  • 2
  • 30
  • 33
7

The reason is simple, though stupid.

It is important to diagnose infinite loop, but such might not be evident:

while(i >= 0) { --i; } // infinite if i unsigned

while(SOME_MACRO(i)) // err, depends on the expansion of macros

It is a great feature of a compiler to produce a warning for a tautological test, that is a test that turns out to be either always true or always false, because it's not obvious when it comes from a macro expansion or within a dependent context.

It just seems that VC++ pushed a bit too far here, and instead of considering tautological conditions warns for all true or false conditions it can find, even when they are already clearly stated in the code.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
4

The for ( ;; ) construct is the canonical way to intentionally code an "endless" loop. I could imagine the compiler designers didn't want to generate a warning for that.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • 6
    I'd say causation is the other way - it's canonical *because* it doesn't issue a warning on a certain popular compiler series. – Steve Jessop Mar 10 '11 at 10:16
  • I don't think its even canonical if you include compilers other than VS. I don't think gcc warns on this? – jk. Mar 10 '11 at 10:47
  • @jk: You are actually right, GCC does not warn about either of these constructs. I didn't test for this, just speculated. – DevSolar Mar 10 '11 at 12:24
4

No point. After all, the langauge specification says ($6.5.3/2),

Either or both of the condition and the expression can be omitted. A missing condition makes the implied while clause equivalent to while(true).

So for ( ; ; ) is equivalent to while(true) even according to the Standard. Therefore, I don't see any reason why the compiler should give warning in one case but not in the other!

--

If the compiler decides to give warning, then in my opinion, the compiler should give warning when the condition is missing as opposed to when it's present, so that the warning would be interpreted as hint for programmer to mention his intention clearly and explicitly.

I mean, for ( ;; ) is more likely to be a typo than the explicit mention of condition in for ( ;true; ). The latter tells programmer's clear and explicit intent. As Steve says in comment:

For an int value y, char x = y is equivalent to char x = (char)y, but you might want a warning for an implicit narrowing conversion on the first but not the second.

So explicit intention should not receive warning, while implicit intention should receive!

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 3
    Not my downvote, but I think equivalence is a red herring. For another example, according to the standard `if (x = y)` is equivalent to `if ((x = y))`, but GCC warns for the former and not the latter. For an int value y, `char x = y` is equivalent to `char x = (char)y`, but you might want a warning for an implicit narrowing conversion on the first but not the second. – Steve Jessop Mar 10 '11 at 10:18
  • 2
    true but I find the idea that while(true) is likely to be a typo to be unconvincing. imho VS is overly fussy here – jk. Mar 10 '11 at 10:19
  • 2
    @jk: I certainly agree that `while(true)` isn't likely to be a typo. In fact I prefer it, so MSVC annoys me. Rather than a typo, it might be the result of a preprocessor expansion `while(CONDITION)`, where CONDITION is accidentally defined to something always true. At least, I always assumed that's what was going through MS's mind when they invented the warning. IMO the warning should only be issued if there's also no `break` in the loop. Or not at all - accidental infinite loops tend not to be the subtlest bugs once you run the code... – Steve Jessop Mar 10 '11 at 10:23
  • @Steve: I quoted your comment in my post. Hope you don't mind. :-) – Nawaz Mar 10 '11 at 10:28
  • @Steve: undecidable... if you loop is interrupted by an exception, the compiler cannot know that unless it inspects the body of the function calls... which are obviously in another translation unit. – Matthieu M. Mar 10 '11 at 10:39
  • @Mattheiu: OK, but that's just more reason *not* to warn if the code calls out of the TU. It'd be a much more difficult analysis, though, than to do what MS has done. They've decided that loops which cannot terminate in the loop condition are worthy of a warning, except that they've allowed one particular syntax to suppress the warning. So I have one complaint that the syntax they picked is not my favoured syntax, and a separate second complaint that I think the warning is excessive anyway. – Steve Jessop Mar 10 '11 at 11:31
1

Compiler warning are here to help catch potential bugs. Using an always true condition in a while loop is probably an error. For exemple, in the following code, this is probably a bug, and I'd like the compiler to warn me about it:

unsigned int x;
// ...
while (x >= 0) {
    // ...
}

In such a situation, in optimized build the compiler will probably deduce that the condition is always true (since an unsigned integer cannot be smaller than 0). So there is a need for detection of an always true condition in while loop. I think that whoever wrote the detection of such an error didn't special case the while (true) case, as there is a simple way to do a infinite loop with for (;;).

You can read here, how the decision to add a warning or not in Visual Studio, is taken (the exemple are about C# but I suppose that the team has the same rule of thumb for warning in C++).

Sylvain Defresne
  • 42,429
  • 12
  • 75
  • 85