Skip to content
Prev 5859 / 21307 Next

[Bioc-devel] evaluation of C post-increments changed in GCC 4.8.2

Hi Robert,

Please, always always _always_ compile with -Wall on. The compiler
should complain almost always when it encounters code like this.
Although I don't have gcc installed, I would be quite surprised if
even slightly older versions did not warn on this.

For reference:

kevin at Kevins-MacBook-Pro:~$ clang -v
clang version 3.5.0 (trunk 209154)
Target: x86_64-apple-darwin13.2.0
Thread model: posix

kevin at Kevins-MacBook-Pro:~$ clang test.c -Wall
test.c:9:23: warning: unsequenced modification and access to 'p' [-Wunsequenced]
            while ((*p++=tolower(*p)));
                      ^           ~
test.c:9:39: warning: while loop has empty body [-Wempty-body]
            while ((*p++=tolower(*p)));
                                      ^
test.c:9:39: note: put the semicolon on a separate line to silence this warning
2 warnings generated.


kevin at Kevins-MacBook-Pro:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc/4.8.3/libexec/gcc/x86_64-apple-darwin13.2.0/4.8.3/lto-wrapper
Target: x86_64-apple-darwin13.2.0
Configured with: ../configure --build=x86_64-apple-darwin13.2.0
--prefix=/usr/local/Cellar/gcc/4.8.3
--enable-languages=c,c++,objc,obj-c++,fortran
--with-gmp=/usr/local/opt/gmp --with-mpfr=/usr/local/opt/mpfr
--with-mpc=/usr/local/opt/libmpc --with-cloog=/usr/local/opt/cloog
--with-isl=/usr/local/opt/isl --with-system-zlib
--enable-version-specific-runtime-libs --enable-libstdcxx-time=yes
--enable-stage1-checking --enable-checking=release --enable-lto
--disable-werror --enable-plugin --disable-nls --enable-multilib
Thread model: posix
gcc version 4.8.3 (GCC)

kevin at Kevins-MacBook-Pro:~$ gcc test.c -Wall
test.c: In function 'main':
test.c:9:23: warning: operation on 'p' may be undefined [-Wsequence-point]
             while ((*p++=tolower(*p)));
                       ^

In your particular example, the compiler doesn't know (and the C
standard leaves undefined) the order in which the expression is
evaluated. Do we increment *p first? Or call tolower(*p) first? It's
tempting to think that "post-increment is just executed at the end of
an expression", or maybe that "expressions are evaluated from left to
right", but this is incorrect -- the order in which these expressions
are evaluated (which both modify the value of *p) is undefined, and so
the compiler can choose one of the possible orderings (and it exploits
this to make optimizations where possible). However, as I noted above,
the compiler will warn you if you use -Wall.

It's easy to enforce this by having a local Makevars file, e.g. at
~/.R/Makevars, containing

    CFLAGS=-g -O3 -Wall -pedantic
    CXXFLAGS=-g -O3 -Wall -pedantic

Cheers,
Kevin
On Thu, Jun 12, 2014 at 8:45 AM, Robert Castelo <robert.castelo at upf.edu> wrote: