warning with conditional operator and printf, is this a bug ?

This is a test case, not sure if its a bug with printf.

This seems strange because both operands are the same type (the one that is
expected).

Thanks in advance.

please CC me, I'm not suscribed to the list.

This is a test case, not sure if its a bug with printf.

I don't believe this is a bug, no.

This seems strange because both operands are the same type (the one that is
expected).

What you're seeing here are the Usual Arithmetic Conversions. [expr] 5\9:

Many binary operators that expect operands of arithmetic or
enumeration type cause conversions and yield
result types in a similar way. The purpose is to yield a common type,
which is also the type of the result.
This pattern is called the usual arithmetic conversions, which are
defined as follows:
  — If either operand is of scoped enumeration type (7.2), no
conversions are performed; if the other
operand does not have the same type, the expression is ill-formed.
  — If either operand is of type long double, the other shall be
converted to long double.
  — Otherwise, if either operand is double, the other shall be
converted to double.
  — Otherwise, if either operand is float, the other shall be
converted to float.
  — Otherwise, the integral promotions (4.5) shall be performed on
both operands.59 Then the following
rules shall be applied to the promoted operands:
       — If both operands have the same type, no further conversion is needed.

and [conv.prom] 4.5\1 says:

A prvalue of an integer type other than bool, char16_t, char32_t, or
wchar_t whose integer conversion
rank (4.13) is less than the rank of int can be converted to a prvalue
of type int if int can represent all
the values of the source type; otherwise, the source prvalue can be
converted to a prvalue of type unsigned
int.

which means your uint16s get promoted to ints at the drop of a hat &
the type of the conditional expression in the printf is actually int,
not uint16_t.

- David

It's a clear false positive in our format checker. Promoting an unsigned value to a wider signed type performs a zero-extend, so the distinction between signed and unsigned formats is irrelevant and either %d or %ud should be acceptable. (The reverse would not be true: we should still warn about using unsigned formats with promoted signed types).

John.

David,

Can you file a bug report and CC me?

I just reported the bug:

http://llvm.org/bugs/show_bug.cgi?id=11313

I added Ted in the CC list as requested.

Thanks for your help!

Thanks so much.

It is not clear to me how you intend to do that: conditional operator
operands are promoted *before* to evaluate the operator. Unless you use
some complex way to track the original type despite the promotions I
don't see any way to avoid this warning.

Also I don't believe it is so clear that it is a false positive: indeed
we are passing an integer argument to an unsigned short format.

Of course if the example was:

unsigned short x;
printf("%d", x);
printf("%u", x);

you argument would be very accurate and agreeable.

The purpose of this warning is to warn about the possible
misformatting of a value or mishandling of varargs. There is no
possibility of that here. Therefore it's a false positive.

It's really quite easy to track the expected range of a value
above and beyond its static type, and we do exactly that for
-Wconversion and -Wsign-compare. Re-using that analysis
here would be simple. It's not quite sufficient because we
should also be diagnosing varargs promotion/size problems,
but it's the right way to catch the misformatting issues.

John.

Hi,

Here's a reason why I think it is clearly a false positive.

<quote>

ISO/IEC 9899:TC3 Commettee Draft - Septemper 7, 2007 W14/N1256

6.5.15 Conditional operator

First semantics paragraph:

"The first operand is evaluated; there is a sequence point after
its evaluation." ... (description about when the second or third
operand are evaluated) ... "the result is the value of the
second or third operand (whichever is evaluated), converted to
the type described below."

Second sematics paragraph:

"If both the second and third operands have arithmetic type, the
result type that would be determined by the usual arithmetic
conversions, were they applied to those two operands, is the
type of the result."

</quote>

Based on this, which I *assume* hasn't changed from the original
ISO/IEC 9899:1999 standard, I can conclude following:

1) There is no a reason to do any arithmetic conversions to the
second or third operand of the conditional operator in this case.
So the result of both operands should be original type, which is
unit16_t for both operands.

2) As what comes for the first operand, I can see that the "Usual
Arithmetic Conversions" rules do apply to it. But since it is
only a sequence point, it is irrelevant in this case (or in any
case, if that matters).

So, according those points, which I concluded, the warning is a
false positive indeed.

Pasi.

1) There is no a reason to do any arithmetic conversions to the
second or third operand of the conditional operator in this case.
So the result of both operands should be original type, which is
unit16_t for both operands.

Sorry, this is the bit I don't follow. "the usual arithmetic
conversion" isn't something that requires a "reason" it's a thing of
its own. I quoted it in my original reply, but applying "the usual
arithmetic conversion" to "uint16_t" should result in "int", unless
I'm missing something.

- David

You're right that formally we have to do a promotion here. It does
not thereby follow that we have to treat an obviously promoted
value as a completely opaque value of the promoted type. Indeed,
we already don't: the language specifies that an unsigned short
must be promoted to int in basically every context, and yet we
manage to not complain about the following, because doing so
would be daft:
  printf("%hu", (uint16_t) x);

The warning exists to serve the user and tell them when they've
likely done something wrong, not to impress them with our
awesome knowledge of the C type system. There are no cases
here where the implicit promotion to int prevents the user's code
from working as obviously intended. Therefore, this is a false
positive.

John.

Well, in this case you are missing that the ellipsis notation doesn't
expect any kind of type for its arguments, and hence there's no need to do any type conversion for results of those expressions.

Those expressions may disagree about the resulting type between each other or with the expected type of printf and that should be warned, but that's not the case here as both resulting types and printf do agree here.

Pasi.

You're right that formally we have to do a promotion here.

Right, sorry - that's all I was getting at. After your reply I've not
made any claims as to what the static analyzer should do, just what's
happening at the language level. To make my point of view on that
clear: if you already have precedent for only finding actual bugs* (or
things that at least might exhibit observable behavior that would
differ from the user's intent), not logical errors, then this clearly
comes under that convention & is a false positive.

I was just trying to explain (perhaps poorly, I'm not sure) to Pasi
the language details going on in this instance.

- David