The Following Code Causes Segfault in Clang
If your are looking for code to break a C compiler, you can try my tool Quest https://github.com/lindig/quest. It tries to to generate code that shows that a C compiler handles parameter passing wrong. I usually run it in a loop, like here on Mac OS X 10.9.4 witch gcc:
This means the tool found C code where parameter passing is not compiled properly. It took about 10 seconds to find this. The test case is pretty small::quest $ gcc --version Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) Target: x86_64-apple-darwin13.3.0 Thread model: posix :quest $ while true; do > ./main.native -test gcc -n 1 > foo.c > gcc -O2 -o foo foo.c > ./foo || break > echo -n . > done ................................................................ ................................................................ ................................................. Assertion failed: (b32 == b43), function callee_b0f, file foo.c, line 128. Abort trap: 6
The generated code that where the assertion checks that parameters are received correctly looks like this::quest $ wc foo.c 140 444 3485 foo.cstatic union bt8 * callee_b0f(struct bt4 *bp7, double *bp8, struct bt6 bp9, float bp10, struct bt7 bp11, double bp12, short int bp13, ...) { va_list ap; typedef int bd0; typedef struct bt0 bd1; typedef int bd2; typedef union bt3 bd3; bd0 b41; bd1 b42; bd2 b43; bd3 b44; /* seed: 2040 */ va_start(ap, bp13); QUEST_ASSERT(b34 == bp7); QUEST_ASSERT(b35 == bp8); QUEST_ASSERT(b36.b24.b18 == bp9.b24.b18); QUEST_ASSERT(b36.b24.b19 == bp9.b24.b19); QUEST_ASSERT(b36.b24.b20 == bp9.b24.b20); QUEST_ASSERT(b36.b24.b21 == bp9.b24.b21); QUEST_ASSERT(b36.b24.b22 == bp9.b24.b22); QUEST_ASSERT(b36.b24.b23 == bp9.b24.b23); QUEST_ASSERT(b36.b25 == bp9.b25); QUEST_ASSERT(b36.b26 == bp9.b26); QUEST_ASSERT(b37 == bp10); QUEST_ASSERT(b38.b27 == bp11.b27); QUEST_ASSERT(b39 == bp12); QUEST_ASSERT(b40 == bp13); b41 = va_arg(ap, bd0); b42 = va_arg(ap, bd1); b43 = va_arg(ap, bd2); b44 = va_arg(ap, bd3); QUEST_ASSERT(b30 == b41); QUEST_ASSERT(b31.b0 == b42.b0); QUEST_ASSERT(b32 == b43); QUEST_ASSERT(b33.b10.b1 == b44.b10.b1); va_end(ap); return b29; }While we're at segfaulting compiler's, here's what I found just a few days ago:
(This is legal C -- look it up. Don't argue with me over the practical relevance of this please)python -S -c 'print("void f(){} int main(){return (" + "*"*10**7 + "f)();}")' | gcc -xc -Hmm...
Not quite so unreachable...Unable to find instantiation of declaration! UNREACHABLE executed at SemaTemplateInstantiateDecl.cpp:4384!https://gist.github.com/cwgreene/d689f010619310dbbc77
https://github.com/llvm-mirror/clang/blob/b310439121c875937d...
Something I found last week that crashes with clang-503.0.40:
template<class T> class foo { public: ~ foo() { } foo &operator = (const foo &rhs) { foo::~foo(); new (this) foo (rhs); return *this; } }; int main(int argc, char * argv[]) { foo<int> a, b; b = a; }Is there some legitimate reason to want to have A's destructor called twice on a single instance?
Something tells me C++ isn't the best thing to implement a compiler with.