user1241335
user1241335

Reputation:

Clang built from source compiles C but not C++ code

I've recently compiled clang on windows (host: x86_64-pc-windows64 ; compiler: i686-pc-mingw32 ; target: i686-pc-mingw32).
The CMakeCache (for the config) can be found: here
My issue is that while clang works fine (for C), clang++ (for C++) will "successfully" compile and link, but the resulting program itself won't run and will exit with an error code 1. Here's a sample below (oh-my-zsh):

➜  bin  cat test.c
#include <stdio.h>

int main()
{
        printf("Hello World!\n");
        return 0;
}
➜  bin  cat test.cpp
#include <iostream>

int main()
{
        std::cout<<"Hello World!"<<std::endl;
        return 0;
}
➜  bin  ./clang++ test.cpp -o a.exe
➜  bin  ./clang test.c -o b.exe
➜  bin  ./a.exe
➜  bin  ./b.exe
Hello World!
➜  bin

as is visible here, b.exe (in C) works fine, but a.exe (C++), while compiled and links, gives no output.
Could anyone hint me unto why this is so, and how can I fix it?
Note: the pre-compiled snapshot of clang for windows (also 32 bit) works fine with my current path configuration.
Note: a.exe (C++, failed) returns non-zero.
DATA:
CLANG VERSIONS: Snap: clang version 3.5 (208017) ; Comp: clang version 3.4 (tags/RELEASE_34/final)
LLVM FILES: snapshot ; compiled ; diff
PREPROCESSING FILES: snapshot ; compiled ; diff
ASM FILES: snapshot ; compiled ; diff
VERBOSE OUTPUT: snapshot ; compiled

Upvotes: 1

Views: 603

Answers (1)

osgx
osgx

Reputation: 94445

You new clang uses different (incorrect) calling convention, not the x86_thiscallcc.

snap.s from good clang:

movl    $__ZStL8__ioinit, %ecx
calll   __ZNSt8ios_base4InitC1Ev

movl    %esp, %ecx
movl    $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, (%ecx)
movl    %eax, %ecx
calll   __ZNSolsEPFRSoS_E

Same code from your custom clang, comp.s:

leal    __ZStL8__ioinit, %eax
movl    %eax, (%esp)
calll   __ZNSt8ios_base4InitC1Ev

movl    %eax, (%esp)
movl    %ecx, 4(%esp)
calll   __ZNSolsEPFRSoS_E

and several other.

In llvm bitcode (*.ll files) right calling convention is marked with x86_thiscallcc in function definitions and after call instruction:

<   call void @_ZNSt8ios_base4InitC1Ev(%"class.std::ios_base::Init"* @_ZStL8__ioinit)
>   call x86_thiscallcc void @_ZNSt8ios_base4InitC1Ev(%"class.std::ios_base::Init"* @_ZStL8__ioinit)

< declare void @_ZNSt8ios_base4InitC1Ev(%"class.std::ios_base::Init"*) #0
> declare x86_thiscallcc void @_ZNSt8ios_base4InitC1Ev(%"class.std::ios_base::Init"*) #0
32c33
< declare void @_ZNSt8ios_base4InitD1Ev(%"class.std::ios_base::Init"*) #0
> declare x86_thiscallcc void @_ZNSt8ios_base4InitD1Ev(%"class.std::ios_base::Init"*) #0

<   call void @_ZNSt8ios_base4InitD1Ev(%"class.std::ios_base::Init"* @_ZStL8__ioinit)
>   call x86_thiscallcc void @_ZNSt8ios_base4InitD1Ev(%"class.std::ios_base::Init"* @_ZStL8__ioinit)

<   %3 = call %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"* %2, %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)* @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
>   %call1 = call x86_thiscallcc %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"* %call, %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)* @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
< declare %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"*, %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)*) #0
> declare x86_thiscallcc %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"*, %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)*) #0

In preprocessed file I see the difference. In snap.E many functions are defined with __attribute__((__cdecl__)) and in comp.E they are defined with just __cdecl__. You should check why the definitions are different after preprocessing. I think, new clang may predefine different set of macro (gcc had -dM -E option to dump predefined, not know how to do this in clang). Or your clang just uses different headers (or different versions of headers, you can list used headers with -H option of clang compilation).

Other way is to check, is __attribute__((__cdecl__)) should be equal to __cdecl__, and does newer version of clang change anything in handling them.

Upvotes: 2

Related Questions