Different signatures or smart casting?

Dear Ksenia,

Message: 3
Date: Fri, 10 Apr 2015 16:03:18 +0300
From: Ksenia Dolgorukova <der.spiegel.sieht.mich@gmail.com>
To: llvmdev@cs.uiuc.edu
Subject: [LLVMdev] Different signatures or smart casting?
Message-ID:
        <
CALtCODFHh-Y9dreELuiiHt2BXRcmtBSr6LXAzvExhEGoSqPrtw@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8

Hello!
I linked two bitcode files like described below using LTO and find
they are linked fine instead of making an error.
----------
1.bc
----------
...
define i32 @main(i32 %argc, i8** %argv) #0 {
entry:
...
%call = call i32 @_Z1aj(i64 2)
...
}
declare i32 @_Z1aj(i64) #1
...

----------
2.bc
----------
...
define i32 @_Z1aj(i32 %b) #0 {
entry:
...
}
...

----------

In the first file function "_Z1aj" is declared as having i64 argument,
whereas in the second file the function "_Z1aj" is described as having
i32 argument!

Are function signatures different?
How does LLVM cast them?
Could it be a bug?

After playing around a little bit, I found this might actually be a feature
of the C language. And please correct me if I'm wrong. For example, the
following actually gets compiled with clang as well as gcc:

// main.c
#include <stdio.h>

void foo(char c);

int main()
{

    foo(100);
    return 0;
}

// foo.c
#include <stdio.h>
void foo(int c)

{
    printf("The param is %d\n", c);
}

$ gcc hello.c foo.c

Although the declaration and definition for foo has different parameter
types, the foo.c and main.c compiled successfully. I think this might be
the 'feature' of the linker, since C object files exposes function names
only. This won't compiler if you're using clang++ or g++.

The corresponding IR is following:

;; main.ll

declare void @foo(i8 signext) #1

;; foo.ll

define void @foo(i32 %c) #0 {
  ...
}

Not only so, the following C code also compiles with gcc-4.9 and clang-3.5:

// main.c

void foo(char c);

// foo.c
void foo(int c, int d, int e)
{
    printf("The param is %d, %d, %d\n", c, d, e);
}

The running result is:

The param is 100, 911150376, 911150392

The last two numbers, I believe, represents memory on the stack, cause
that's where the C functions are reading parameters from.

Correct me if you found somewhere I was wrong.

Regards,
Kevin

Yes, this is a feature, I think. Furthermore, I looked for it in
Linker source code and run linker with gdb but I cann't find the
moment of signature changing. It's like a magic. When Verifier pass
works on linked code it finds nothing! If signatures were not changed
Verifier must throw an error of parameter mismatching.