// c2011-6-5-16-2-ex.c
// original examples and/or notes
// (c) ISO/IEC JTC1 SC22 WG14 N1570, April 12, 2011
// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
// C2011 6.5.16.2 Compound assignment
// compile and output mechanism
// (c) Ogawa Kiyoshi, kaizen@gifu-u.ac.jp, December.xx, 2013
// compile errors and/or warnings
// (c) Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn)
// Target: x86_64-apple-darwin11.4.2 //Thread model: posix
// (c) LLVM 2003-2009 University of Illinois at Urbana-Champaign.
// gcc-4.9 (GCC) 4.9.0 20131229 (experimental)
// Copyright (C) 2013 Free Software Foundation, Inc.
#include <stdio.h>
// Note 113) 2nd
#include <fenv.h>
#include <stdatomic.h>

#pragma STDC FENV_ACCESS ON
/* ... */
typedef  struct{int i;} T1;
typedef T1 T2;

int main(void){
fenv_t fenv;
T1 E1;
T2 E2;
T1 *addr = &E1;
T2 val = E2;
T1 old = *addr;
T1 new;

feholdexcept(&fenv);
for (;;) {
		new = old = val;
		printf("before \n");
		if (atomic_compare_exchange_strong(addr, &old, new))
		printf("after \n"); break;
feclearexcept(FE_ALL_EXCEPT);
}
feupdateenv(&fenv);
// Note 113) 1st
T1 *addr1 = &E1;
T2 val1 = (E2);
T1 old1 = *addr;
T1 new1;
do {
		printf("%d %d %d\n",new1, old1,val1);
} while (!atomic_compare_exchange_strong(addr1, &old1, new1));
	return printf("6.5.16.2 Compound assignment %d \n",addr1->i);
}
// LLVM3.2 can not support this
// warning GCC4.9
//c2011-6-5-16-2-ex.c:18:0: warning: ignoring #pragma STDC FENV_ACCESS [-Wunknown-pragmas]
// #pragma STDC FENV_ACCESS ON
// ^
//c2011-6-5-16-2-ex.c: In function 'main':
//c2011-6-5-16-2-ex.c:47:3: warning: format '%d' expects argument of type 'int', but argument 2 has type 'T1' [-Wformat=]
//   printf("%d %d %d\n",new1, old1,val1);
//   ^
//c2011-6-5-16-2-ex.c:47:3: warning: format '%d' expects argument of type 'int', but argument 3 has type 'T1' [-Wformat=]
//c2011-6-5-16-2-ex.c:47:3: warning: format '%d' expects argument of type 'int', but argument 4 has type 'T2' [-Wformat=]
//c2011-6-5-16-2-ex.c:47:3: warning: format '%d' expects argument of type 'int', but argument 2 has type 'T1' [-Wformat=]
//c2011-6-5-16-2-ex.c:47:3: warning: format '%d' expects argument of type 'int', but argument 3 has type 'T1' [-Wformat=]
//c2011-6-5-16-2-ex.c:47:3: warning: format '%d' expects argument of type 'int', but argument 4 has type 'T2' [-Wformat=]
// output GCC4.9
// before 
//　1131076993 1571724016 34693120
// 6.5.16.2 Compound assignment 1131076993 