News for hackers. Stuff that matters.
Re:Const and Optimization in C by nkurz on Monday July 25, 2016 @04:16AM (#12157201)
The C99 specification, in §6.7.3¶5, has one sentence just for this:

  If an attempt is made to modify an object defined with a   
  const-qualified type through use of an lvalue with non-
  const-qualified type, the behavior is undefined.
This is a separate question than whether the compiler can rely on the function prototype, but doesn't his definition of bar() invoke undefined behavior by this rule?

  void foo(const int *readonly_x) {
    int *x = (int *)readonly_x;  // cast away const
    (*x)++;
  }
I naively assumed that in the context of the bar() function, readonly_x is "an object defined with a const-qualified type", and that since the function modifies this "through use of an lvalue with non-const-qualified type", that bar() invokes undefined behavior. Or am I falsely equating "declaring an object" with "defining an object"?

The original x wasn’t const-qualified, so this rule didn’t apply. And there aren’t any rules against casting away const to modify an object that isn’t itself const.

Does the original x matter here, or just the readonly_x variable that is in scope of the function? In the language of the spec, are x and readonly_x the same object? Or two different objects of different types that happen to point to the same address? Is it certain that const-qualifiers on function arguments can be legally be ignored inside that function?

Re:Const and Optimization in C by ynik on Monday July 25, 2016 @04:33AM (#12157256)
`readonly_x` is a non-constant object of type 'pointer to const int'. If `readonly_x` itself was const-qualified, it'd look like this: `const int* const readonly_x`.

This is a distinct object from whatever pointer the caller is passing in. But none of this matters to the special const rule -- that rule is not talking about the pointer object, but about the target object that the pointer is pointing to.

Re:Const and Optimization in C by nkurz on Monday July 25, 2016 @05:00AM (#12157351)
Thanks, that goes a long way toward an explanation. I'm still a bit surprised though that no compilers seem to complain even if we cast away the const from the properly const-qualified version. Here's the snippet I was playing with that tests all the variations: https://godbolt.org/g/aaC4B7

I should have expected it, but if you define the "lying" function where the compiler can see the full definition (and don't specify -fno-inline), the loads are optimized out. It made me wonder though whether some variation of this bug might apply : http://www.playingwithpointers.com/ipo-and-derefinement.html

Re:Const and Optimization in C by nkurz on Monday July 25, 2016 @03:10PM (#12160827)
[Saw a response here, but it disappeared before my reply. Posted here anyway in case it clarifies my first paragraph.]

Did you check out the link? https://godbolt.org/g/aaC4B7

My surprise is that none of clang, gcc, or icc give any warning on this with -Wall -Wextra:

  1  void copy_const(const int * const arg) {
  2    int *copy = (int *)arg;
  3    (*copy)++;
  4  }
I agree that the cast on line 2 is legal and requires no warning. My surprise is that there is no warning for the write on line 3, since I think this is undefined behavior according the quoted part of the spec. Isn't this trying "to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type"?

I realize that the compiler has no obligation to issue a warning here, and in fact is fully entitled to my first-born as soon as it encounters undefined behavior. Still, it seems like it would be a useful place to offer the user a warning just as it does in the case of direct modification:

  1 void write_const(const int * const arg) {
  2   (*arg)++;
  3 }
clang: "error: read-only variable is not assignable"

gcc: "error: increment of read-only location '*arg'"

icc: "error #137: expression must be a modifiable lvalue"

Re:Const and Optimization in C by Too on Tuesday July 26, 2016 @04:41AM (#12164179)
In gcc try -Wcast-qual
Re:Const and Optimization in C by nkurz on Tuesday July 26, 2016 @01:36PM (#12167332)
It's good to know that it exists (and that it's not included in -Wall -Wextra) but it's not quite what I'm looking for. The cast itself is well defined --- it's the subsequent write that is the issue. While it wouldn't be possible to catch all of these, those that are caught are likely genuine bugs.

That said, it looks like -Wcast-qual is also supported by clang and icc. Clang includes it in "-Weverything", which gcc and icc do not support. Even if not ideal for this issue, I'm sure there are cases where it would help to catch bugs.