Description
Bug Description
Consider the following C code:
const unsigned short mask = 0;
mask+mask;
~mask;
The types of mask+mask
and ~mask
are int
because of integer promotion, I can confirm this with a _Static_assert
and gcc. However, if I parse this with Eclipse CDT and call getExpressionType()
on the two expressions, I wrongly get const unsigned short
.
The same problem also exists if the variable is declared volatile
instead of const
or with other qualifiers.
Code Analysis
Binary Expression
CASTBinaryExpression::getExpressionType()
first removes typedefs and then calls this:
Typedefs are removed again, but qualifiers are kept. However,
isArithmeticOrUnscopedEnum()
only checks for IBasicType
or IEnumeration
and returns false
for all other types including the CQualifierType
that is passed. Then CASTBinaryExpression
produces the type of the first operand as expression type.
Unary Expression
For arithmetic unary expressions, CASTUnaryExpression::getExpressionType()
also removes typedefs and then calls this:
The same problem as above exists, just with
isIntegralOrUnscopedEnum()
.
Side Note: Ternary Operator
Notably, this problem does not exist for the ternary operator, although arithmetic conversion including integer promotion is also applied here. This is because CASTConditionalExpression
removes qualifiers before calling CArithmeticConversion
:
This was added in df6ebf0 for bug 495423.
Potential Fix
I guess that at some point before the final call to ArithmeticConversion::promote(IType, Domain)
a call needs to be inserted that removes qualifiers. However, I do now know at which level this is expected to be, i.e., inside the CAST*Expression
or in ArithmeticConversion
. I also do not know how this applies to C++ (for which ArithmeticConversion
is used as well). At least, for C code only binary expressions, unary expressions, and the ternary operator trigger calls to promote()
, so there should be no unwanted side effects.