Two identical systems but clang gives warning on only one

Well, sort of identical. I have some old threaded C code that I was tinkering with. I put it on my personal server and it compiles and runs just great. I have an old notebook where I installed FreeBSD from scratch, put the same server and everything else on it--identical to what's on the VPS. 12.0-RELEASE p8. I compile the exact same code with the same version of clang but I get a warning:
Code:
warning: cast to 'void *' from smaller integer type 'int'
It comes from this line:
Code:
    for (i = 1; i < THREAD_COUNT; i++)
        pthread_create(&id[i], NULL, doit, (void*)i);
at the point (void*)i

The program works as it should on my notebook but I don't understand why there is a warning on one system but not the other. It sounds familiar, as if I've had this issue years ago, and there was a configuration somewhere that I was unaware of and now have forgotten.

So my question is not how to fix the code but why the long running system on a VPS does not give me the same warning that the new install on my notebook does?
 
The obvious explanation would be either -Wno-int-to-void-pointer-cast or -m32 flag. How did you verify that compilation flags are identical in both cases?
 
I don't know that the flags are the same except I would not have made changes to a plain install on this server.

What I mean is, I'm doing just this:
Code:
clang -I /usr/local/include -L /usr/local/lib -lpthread main.c
 
Can you reproduce that behavior with this code?
Code:
int main() {
  int   foo = 0;
  void* bar = (void*)foo;
  return 0;
}

If you can, then maybe try clang -v for more verbose output. (You don't have to post it here.)
 
Same warning on the notebook but not on the server. Also, with clang -v, same output on both.

EDIT: No! clang -v does show a difference.

EDIT2: I'm betting the server is confounding things. clang -v shows this:
Code:
-m elf_i386_fbsd
So now I have to investigate why the server has that set.
 
Do you have the exact same version of FreeBSD running on both?

Can you mount (or copy) the installation from one system onto the other and then run diff -rq dir1 dir2.
 
You mentioned both servers are CPU amd64 and version 12p8. But one of your clang is i386 ? What is the exact output of uname -a and clang -v from your machines ? The -m elf_i386_fbsd seems like linker flag.
Also is there a particular reason why thread_id is typecasted to int ? When it comes to pointers to int stdint(7) has generic type intptr_t which can be handy.
 
You mentioned both servers are CPU amd64 and version 12p8.
Yes they are.
But one of your clang is i386 ?
I said clang -v shows -m elf_i386_fbsd as one of the fields in the output. I don't know why and need to find out.
Also is there a particular reason why thread_id is typecasted to int ?
This is old code I had found years ago and I just started looking at it today. It compiled and works as intended but I haven't spent any time understanding it.
 
Looking at your code snippets again I'm a bit confused. You mentioned it works on one machine and not the other. But if i is defined as int i then this:
C:
pthread_create(&id[i], NULL, doit, (void*)i);
Should be really defined as
C:
pthread_create(&id[i], NULL, doit, (void*)&i);
As you need a pointer to an arg.
 
Aha! Somehow, and I think I know how, the linker on my VPS is the GNU linker and not from llvm.

A while back, I was doing more tinkering and found I filled the disk trying to have both gcc and llvm. I have a feeling I deinstalled llvm and this is the situation I'm in.

I'll try and fix this in the morning.
 
Not really, it's the argument to the caller supplied callback
Hm, I'm not really in the position to say yes or no here. My reply here is out of curiosity. Though I do understand that if callback function knows what to expect it can dealt with it. But shouldn't it be, according to standard at least, that if function argument defines to pass a pointer (be it void) pointer should be passed ?

I think this is where the original OP's warning is coming from - he's trying to pass int as void* - hence the size issue. He could also use (void*)(intptr_t)i which would probably silenced the warning.

EDIT: I'm attaching also the short example. bar() function being what I'd expect it should be like.

C:
#include <stdio.h>
#include <stdint.h>

void foo(void* d) {
        printf ("foo: %x\n", (int)(intptr_t)d);
}

void bar(void* d) {
        printf("bar: %x\n", *((int*)d));
}

int main() {
        int a = 0xcafec0de;

        printf ("a: %x\n", a);
        foo((void*)(intptr_t)a);
        bar(&a);

        return 0;
}
 
But shouldn't it be, according to standard at least, that if function argument defines to pass a pointer (be it void) pointer should be passed ?

I don't think an average C programmer cares much about safety, standards, undefined behavior and so on. An almost free optimization on other hand…

(Note that C itself doesn't care about safety either, so it's mostly a self-selection issue.)
 
Modify your code slightly: For the variable that is an int, and the variable that is a void *, print their sizeof. That requires ignoring the warnings and running the program. Obviously, the int will have a sizeof == 4, and the void * will be == 8. You already know that, and you even know what the real source of the problem is (the i386 elf format). But this will give you a good debugging tool as you try to fix the source of the problem.

By the way, the casting style and the multiple assignments are nasty coding style, and will eventually get it in trouble. If this is supposed to be maintainable and production-worthy code, then you should invest some time in cleanup and making it pretty, because it will improve the long-term quality. On the other hand, if it is a one-off hack or an educational toy, the faster you get it done the better.
 
Back
Top