MISRA Discussion Forums

Full Version: Definition of "constant expression"
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
For rule 12.4, what definition of "constant expression" is used? If the definition is the one from the ISO C standards, that definition does not make it clear the example
Code:
const uint16_t c = 0xffffu;
uint16_t y = c + 1u;
is compliant because a constant variable, if initialized with a constant expression "can be evaluated during translation rather than runtime".

For the record, different compilers appear to take different approaches as to whether or not a const-qualified variable meets the definition of a "constant expression".
I believe that this rule uses the definition of "constant expression" from the ISO C99 standard Section 6.6. The constraints on constant expressions prohibit the following operators: assignment, increment, decrement, function-call and comma. There's an exception for such operators appearing in an expression that isn't evaluated.

The constraints therefore seem to permit access to objects within constant expressions. However, the Semantics section goes on to list the permitted operands for integer constant expressions. That list does not include objects as being allowed in integer constant expressions so I think that would suggest that "c+1u" where "c" is an object with a const-qualified type isn't a constant expression. Further, using "c+1u" in a context where a constant expression is required gives rise to undefined behaviour because it violates a "shall" or "shall not" appearing outside a Constraints section. See Annex J.2, which states the undefined behaviour w.r.t. constant expressions for confirmation.

Just to complicate matters, I see that the C99 standard Section 6.6 para 10 says that an implementation may accept other forms of constant expression. An implementation that does so would, as as with any extension, have to guarantee that the behaviour of a strictly conforming program isn't changed. Since no strictly conforming program would, by definition, be relying on undefined behaviour it's safe for an extensions to accept objects with const-qualified types in a constant expression. I think this explains why some implementations accept a less strict form of constant expression than is specified in the standard and why it can vary between implementations.

So far as the rule is concerned, I don't know what the MISRA C Working Group guidance would be. I suspect it may be best to stick with the rule as worded, namely that the expression must satisfy the constraints in order for the rule to apply, regardless of whether the implementation is less strict. At least that means that the rule doesn't apply to "c+1u" in either of these sequences:
Code:
const uint16_t c = 0xffffu;
uint16_t y = c + 1u;
and
Code:
uint16_t c = 0xffffu;
uint16_t y = c + 1u;

I'd be interested to know that official view on this, as well as the several other unanswered posts. There hasn't been much by way of official responses in the last few months. Any chance of some comments from MISRA?
Very interesting. One point to remember, however, is the fact "constant expressions" are not equal to "integer constant expressions". If anything, the latter is a subset of the former. How this fact places into the analysis, of course, is unclear.
Yes, the difference between integer constant expressions and constant expressions does seem to need a bit more exploration.

I think I was wrong when I wrote in my previous reply that that rule wouldn't apply to "c+1u" because the expression does satisfy the constraints for a constant expression regardless of whether c has a const-qualified type or not. There's no mention of objects in the constraints, unless I've missed it somehow. And clearly constant expressions must be permitted to contain the names of objects in order to allow "address constant expressions" as in:
Code:
const int *p = &i;
In which case does this rule really apply to all expressions that satisfy the constraints for a constant expression? Or is it intended to apply to those that satisfy the semantics for an integer constant expression, as well as the constant expression constraints?
The MISRA C working group is currently formulating a reply, but because of the Christmas period we will be unlikely to get a quorate response until the new year.
The phrase constant expression appears in italics in the MISRA C:2012 guidelines and therefore refers to an entry with the same name in the C99 standard.

The intention was that this rule should refer to expressions that did not violate either the constraints of constant expressions or exhibit undefined behaviour. The example with "const uint16_t c" was included to re-enforce this point. However, we appreciate that the amplification could have been clearer on this point and that the supporting text is incorrect.

The line
Quote:This rule does not apply to the expression c + 1 in the following compliant example as it accesses an object and therefore does not satisfy the constraints for a constant expression
Should read
Quote:This rule does not apply to the expression c + 1 in the following compliant example as it accesses an object and therefore does not satisfy the semantics for a constant expression

And in the amplification the line
Quote:This rule applies to expressions that satisfy the constraints for a constant expression, whether or not they appear in a context that requires a constant expression.
Should read
Quote:This rule applies to expressions that satisfy the constraints and semantics for a constant expression, whether or not they appear in a context that requires a constant expression.

In practice only the semantics of integer constant expression are important as the other forms of constant expressions will not be involved with unsigned integer wrap-around.
What does "satisfy the semantics" mean in the MISRA reply? I believe that the "semantics" sections of the standard specify the meaning of a code construct rather than specifying a set of conditions that must be met.

Does it perhaps mean that the expression must not contain any undefined behaviour, such as might be caused by violating a "shall" or "shall not" appearing outside of a constraint?

If so, does this still apply even for implementations which provide a well-defined behaviour for something that the standard leaves as undefined? I'm guessing the answer is "yes" but this point, made in the original posting, hasn't been explicitly answered.
In this instance “satisfy the semantics” refers to code that that does not exhibit the undefined behaviour listed in section 6.6 of the C99 standard. In other words such code should treat the “shall” restrictions in section 6.6 as if they were constraints, regardless as to the behaviour of a particular implementation.