Clang++
I just came across this fun bug.
#include <iostream> #include <string> #include <sstream> #include <fstream> std::stringstream prog; constexpr unsigned c_strlen( char const* str, unsigned count = 0 ) { return ('\0' == str[0]) ? count : c_strlen(str+1, count+1); } template < char t_c, char... tt_c > struct rec_eval { static void eval() { rec_eval<t_c>::eval(); rec_eval < tt_c... > :: eval (); } }; template < char t_c > struct rec_eval < t_c > { static void eval() { switch(t_c) { case '+': prog<<"++t[i];"; break; case '-': prog<<"--t[i];"; break; case '>': prog<<"++i;"; break; case '<': prog<<"--i;"; break; case '[': prog<<"while(t[i]){"; break; case ']': prog<<"}"; break; case '.': prog<<"putc(t[i],stdout);"; break; case ',': prog<<"t[i]=getchar();"; break; } } }; template < char... tt_c > struct exploded_string { static void eval() { rec_eval < tt_c... > :: eval(); } }; template < typename T_StrProvider, unsigned t_len, char... tt_c > struct explode_impl { using result = typename explode_impl < T_StrProvider, t_len-1, T_StrProvider::str()[t_len-1], tt_c... > :: result; }; template < typename T_StrProvider, char... tt_c > struct explode_impl < T_StrProvider, 0, tt_c... > { using result = exploded_string < tt_c... >; }; template < typename T_StrProvider > using explode = typename explode_impl < T_StrProvider, c_strlen(T_StrProvider::str()) > :: result; int main(int argc, char** argv) { if(argc < 2) return 1; prog << "#include <stdio.h>\n#include <stdlib.h>\nint main(){unsigned char* t=calloc("; prog << (1 << sizeof(unsigned short)); prog << ",sizeof(unsigned short));unsigned short i=0;"; struct my_str_provider { constexpr static char const* str() { return "++++[>+++++<-]>+++[[>+>+<<-]>++++++[<+>-]+++++++++[<++++++++++>-]>[<+>-]<-]+++>+++++++++[<+++++++++>-]>++++++[<++++++++>-]<--[>+>+<<-]>>[<<+>>-]<-->>++++[<++++++++>-]++++++++++>+++++++++[>+++++++++++<-]>[[>+>+>+<<<-]>[<+>-]>>[[>+>+<<-]>>[<<+>>-]<[<->-[<->-[<->-[<->-[<->-[<->-[<->-[<->-[<->-[<<<+>---------->->[-]]]]]]]]]]]<]<<[>>++++++++++++[<++++<++++>>-]<<[.[-]>]<<]>[<++++++[>++++++++<-]>.[-]]<<<<<.<<<<<.[<]>>>>>>>>>.<<<<<..>>>>>>>>.>>>>>>>.[>]>[>+>+<<-]>[<+>-]>[-[[-]+++++++++[<+++++++++++++>-]<--.[-]>]]<<<<<.[<]>>>>>>>>>.>>>>>>>>>.[>]<<.<<<<<.<<<..[<]>>>>>>.[>]<<.[<]>>>>>>>>>.>.[>]<<.[<]>>>>.>>>>>>>>>>>>.>>>.[>]<<.[<]>.[>]<<<<<<.<<<<<<<<<<<..[>]<<<.>.[>]>[>+>+>+<<<-]>[<+>-]>>[[>+>+<<-]>>[<<+>>-]<[<->-[<->-[<->-[<->-[<->-[<->-[<->-[<->-[<->-[<<<+>---------->->[-]]]]]]]]]]]<]<<[>>++++++++++++[<++++<++++>>-]<<[.[-]>]<<]>[<++++++[>++++++++<-]>.[-]]<<<<<.<<<<<.[<]>>>>>>>>>.<<<<<..>>>>>>>>.>>>>>>>.[>]>[>+>+<<-]>[<+>-]>[-[[-]+++++++++[<+++++++++++++>-]<--.[-]>]]<<<<<.[<]>>>>>>>>>.>>>>>>>>>.[>]<<.<<<<<.<<<..[<]>>>>>>.[>]<<<<.>>>.<<<<.<.<<<<<<<<<<.>>>>>>.[>]<<.[<]>>>>>>>>>.>.>>>>>>>>>.[>]<<.<<<<<<<.[<]>>>>>>>>>.[<]>.>>>>>>>>>.[>]<<.<<<<.<<<<<<<<<<<<<.[>]<<<<<<<<<.[>]<<.[<]>>>>>>>>.[>]<<<<<<.[<]>>>>>..[>]<<.<<<<<<<<<<<<.[<]>>>>.[>]<<.<<<<.[<]>>>>>>.>>>.<<<<<<.>>>>>>>.>>>>>>>>>>.[>]<<<.>.>>>-[>+>+>+<<<-]>[<+>-]>>[[>+>+<<-]>>[<<+>>-]<[<->-[<->-[<->-[<->-[<->-[<->-[<->-[<->-[<->-[<<<+>---------->->[-]]]]]]]]]]]<]<<[>>++++++++++++[<++++<++++>>-]<<[.[-]>]<<]>[<++++++[>++++++++<-]>.[-]]<<[>+>+<<-]>[<+>-]+>[<->[-]]<[-<<<[<]>>>>>>>>>>.<.[>]<<.[<]>>>>>>>>>>>.<<.<<<.[>]<<<<<<<<<<.[>]>>]<<<<.<<<<<.[<]>>>>>>>>>.<<<<<..>>>>>>>>.>>>>>>>.[>]>[>+>+<<-]>[<+>-]+>[<->-[<+>[-]]]<[++++++++[>+++++++++++++<-]>--.[-]<]<<<<.[<]>>>>>>>>>.>>>>>>>>>.[>]<<.<<<<<.<<<..[<]>>>>>>.[>]<<.[<]>>>>>>>>>.>.[>]<<.[<]>>>>.>>>>>>>>>>>>.>>>.[>]<<.[<]>.[>]<<<<<<.<<<<<<<<<<<..[>]<<<<.>>>..>>]"; } }; auto my_str = explode < my_str_provider >{}; my_str.eval(); prog << "}"; std::ofstream ofs(argv[1]); if(!ofs) return 2; ofs << prog.str() << std::endl; ofs.close(); return 0; }
The goal is to translate Brainfuck into C, using template meta-programming to do most of the work. This code works for smaller Brainfuck programs, such as Hello World, but when I tried to run it with 99 Bottles...
$ clang++ -std=c++11 -fconstexpr-depth=1000 bf_static.cpp clang: error: unable to execute command: Segmentation fault (core dumped) clang: error: clang frontend command failed due to signal (use -v to see invocation) clang version 3.5.2 (tags/RELEASE_352/final) Target: i386-pc-windows-cygnus Thread model: posix clang: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script. clang: note: diagnostic msg: ******************** PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT: Preprocessed source(s) and associated run script(s) are located at: clang: note: diagnostic msg: /tmp/bf_static-afa982.cpp clang: note: diagnostic msg: /tmp/bf_static-afa982.sh clang: note: diagnostic msg: ********************
It will successfully compile in GCC (after about 2 minutes), but linking it causes another issue...
/usr/lib/gcc/i686-pc-cygwin/4.9.3/../../../../i686-pc-cygwin/bin/as: /tmp/cc0W7cJu.o: section .eh_frame$_ZN8rec_eval<giant mangled name removed>: string table overflow at offset 10004228 /tmp/cc3JeiMp.s: Assembler messages: /tmp/cc3JeiMp.s: Fatal error: can't close /tmp/cc0W7cJu.o: File too big
Oops.