Sadly this variant is a C only variant... Anyone know how to do something cunning in C++17? On Fri, May 11, 2018 at 10:48 AM, John Carter <john.carter@xxxxxxxxxxxxx> wrote: > Here's a variant that works even at -O3, the trick seems to be to combine > __builtin_choose_expr with __builtin_constant_p > > https://godbolt.org/g/pQeRvE > > #include <stdlib.h> > > void assertFailure( void) __attribute__((warning("Compile time assertion > failure"))); > > int z(void); > > > int main() > { > int j; > > for( j=0;j<4;j++) { > if( z()) break; > } > > __builtin_choose_expr( __builtin_constant_p(!(j < 4)), > ((!(j < 4)) ? assertFailure() : (void)0), > ((!(j < 4)) ? abort() : (void)0)); > > return 0; > } > > > On Fri, May 11, 2018 at 10:37 AM, Marc Glisse <marc.glisse@xxxxxxxx> > wrote: > >> On Fri, 11 May 2018, John Carter wrote: >> >> Here is an example where gcc's optimizers go, ahhh, strange.... >>> >> >> There is nothing strange about it. You are trying to abuse >> __builtin_constant_p for warnings when it is meant for optimization. Linux >> kernel developers had the same issue. >> >> Try play with the optimizations settings on godbolt. >>> https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(j:1,lang >>> :___c,source:'%23include+%3Cstdlib.h%3E%0A%0Avoid+assertFail >>> ure(+void)+__attribute__((warning(%22Compile+time+assertion+ >>> failure%22)))%3B%0A%0Aint+z(void)%3B%0A%0A%0Aint+main()% >>> 0A%7B%0A+++int+j%3B%0A%0A+++for(++j%3D0%3Bj%3C4%3Bj%2B%2B) >>> +%7B%0A++++++if(+z())+break%3B%0A+++%7D%0A+++%0A+++if(+__ >>> builtin_constant_p(!!(j+%3C+4)))%0A+++%7B%0A++++++if(!!(j+% >>> 3C+4))%0A+++++++++assertFailure()%3B%0A+++%7D%0A+++else%0A++ >>> ++++if(+!!(j+%3C+4))%0A+++++++++abort()%3B%0A+++%0A+++ >>> return+0%3B%0A%7D%0A'),l:'5',n:'0',o:'C+source+%231',t:'0') >>> ),k:50,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compi >>> ler:cg81,filters:(b:'0',binary:'1',commentOnly:'0',demangle: >>> '0',directives:'0',execute:'1',intel:'0',trim:'0'),lang:___ >>> c,libs:!(),options:'-Os+-Wall',source:1),l:'5',n:'0',o:'x86- >>> 64+gcc+8.1+(Editor+%231,+Compiler+%231)+C',t:'0')),k: >>> 50,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4 >>> >>> On -Os it behaves sane, on -O2 or higher it calls assertFailure. >>> >>> #include <stdlib.h> >>> >>> void assertFailure( void) __attribute__((warning("Compile time assertion >>> failure"))); >>> >>> int z(void); >>> >>> >>> int main() >>> { >>> int j; >>> >>> for( j=0;j<4;j++) { >>> if( z()) break; >>> } >>> >>> if( __builtin_constant_p(!(j < 4))) >>> >> >> gcc duplicates this piece of code, one version if we came through "break" >> and one version if the loop completed. For each version, the value of j<4 >> is known at compile-time and optimized as such. For optimization purposes, >> this is perfect. >> >> >> { >>> if(!(j < 4)) >>> assertFailure(); >>> } >>> else >>> if( !(j < 4)) >>> abort(); >>> >>> return 0; >>> } >>> >> >> -- >> Marc Glisse >> > > > > -- > John Carter > Phone : (64)(3) 358 6639 > Tait Electronics > PO Box 1645 Christchurch > New Zealand > > -- John Carter Phone : (64)(3) 358 6639 Tait Electronics PO Box 1645 Christchurch New Zealand -- This Communication is Confidential. We only send and receive email on the basis of the terms set out at www.taitradio.com/email_disclaimer <http://www.taitradio.com/email_disclaimer>