CIL lowers compound assignments such as g += 1 to normal assignments g = g + 1. For C11 programs, this is not a semantics preserving operation (see C11 draft (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf), 6.5.16.2)
In the program below, the assertion holds:
#include <assert.h>
#include <pthread.h>
#include <stdatomic.h>
static _Atomic int g;
void *t1(void *arg)
{
g += 4;
return NULL;
}
int main(void)
{
pthread_t thread;
pthread_create(&thread, NULL, t1, NULL);
g += 4;
pthread_join(thread, NULL);
assert(g == 8);
return 0;
}
CIL transforms the program into something like
#include <assert.h>
#include <pthread.h>
#include <stdatomic.h>
static _Atomic int g;
void *t1(void *arg)
{
g = g + 4;
return NULL;
}
int main(void)
{
pthread_t thread;
pthread_create(&thread, NULL, t1, NULL) ;
g = g+4;
pthread_join(thread, NULL);
assert(g == 8);
return 0;
}
where after the assert g may also be 4, but no race has occurred. For usage within Goblint this is only a precision problem, but more generally I think this could be considered a miscompilation.
CIL lowers compound assignments such as
g += 1to normal assignmentsg = g + 1. For C11 programs, this is not a semantics preserving operation (see C11 draft (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf), 6.5.16.2)In the program below, the assertion holds:
CIL transforms the program into something like
where after the assert
gmay also be4, but no race has occurred. For usage within Goblint this is only a precision problem, but more generally I think this could be considered a miscompilation.