3
YADU
6y

Does anyone know of a tool that will statically analize a C program and check if it's behaviour would be the same as a C++ program? Flagging things like implicit void* coercions, for example.

The use case would be if you find a C library and want to use it with C++, for example. Or are writing a library and want it to be usable in both C and C++.

If this doesn't exist,
does anyone want to help me make it? I was thinking we could modify an existing C linter to do this.

Comments
  • 2
    C is already compliant with C++

    So you can use any C library as is in C++
  • 2
    @BigBoo that's not true.

    For example,

    char *var = malloc(10);

    Is valid C code, but not valid C++ code, because C++ disallows implicit coercions from void*, unlike C.

    For less fun example (in that both compile but they have different behaviour):

    In C,

    sizeof('a') == sizeof(int).

    In C++,

    sizeof('a') == sizeof(char).

    There's more, which is why a tool to check your C code would be nice, but these are just a few examples.
  • 3
    @YADU but libs are already compiled
  • 3
    @BigBoo

    When I say "library" i don't mean the standard c library, i mean like code people have written and you want to use in your project by including the header file.
  • 2
    @YADU And I mean compiled libs. Either static or shared. As per the definition. I don't care if you call chars ints. Just means that you are wrong
  • 2
    @BigBoo what do you mean if i call chars ints? Where did i do that?
  • 2
    @BigBoo that's fine if you mean compiled libs, but thats not the use case i was talking about
  • 2
    @YADU You didn't. But my point was. If you use standardized names to mean something else. You are just wrong.

    Also. You can compile non compiled libs with gcc and then use them in c++
  • 2
    @BigBoo alright, I'm sorry I used the wrong term. Not really my point at all but thanks.

    Doesn't change the fact that I'm right about C code not being completely compatible with C++.

    Or the fact that you can't compile your code as C and use it in your C++ code necessarily, unless the header was carefully written to allow this.

    An example where you wouldn't be able to do this would be if your header used bool. In C, this isn't a builtin keyword. It's a macro or typedef for something, depending on what else has been written. In C++, it's a builtin type, so trying to do those kinds of things would be an error / not what you want.

    Hence, it would be nice to have a to while writing my C code to catch things like this that would make my C incompatible with C++.
  • 2
    @YADU It's a one way street.

    You can use C code in C++ but not the other way around.

    So if you want to rewrite C++ into C. I don't really get why. But that sounds like compiler and not a linter. Then just check out how to write a compiler. Parsing and making a intermediate form (preferably a parse tree)

    Then you re-interpret that tree into C code.
    But C++ has a lot of funky keywords. So it's going to be messy.
  • 2
    @BigBoo have you looked at any of my examples at all? C code is not completely compatible with C++. I know it frequently is, but I've run into real world cases where it isn't.
    I'd like a linter that goes through C code and flags constructs that would be invalid C++ code, but are valid C code. I think it would be possible to write this by taking an existing C linter and modifying it a bit.

    I don't need a compiler since i don't want to generate code. I just want to be able to take C code and check that it will also behave the same if it were run through a C++ compiler.

    The use cases I see are checking if an existing body of C code would be useable in my C++ project (I'm writing the C++ in this case), or that my C code will be useable in C++ projects (I'm writing C code in this case).
  • 3
    Yes, but you keep switching back and forth between what target language you use. So it's confusing to know what you mean.

    You say bool is not a type in C, correct. So I assume you want to use C as a target. Since bool is a C++ type. So there is no problem using it in C++.

    Now, if you try to use someones typedef for bool in C++ sure. That will be a problem. But you should first compile the library with GCC. It doesn't need to be carefully crafted. It just doesn't need to be garbage. Also, they can't possibly typedef a whole lot of things that would overlap with C++. So you should be able to sed those typedefs before compiling if that turns out to be an issue.

    If you don't know how to compile code as a library. Then I would suggest you looking at that. Since it requires special flags.

    But this is really a non issue. So you wouldn't really solve any problems if you found a solution.
  • 2
    @BigBoo I'm always talking about running C code through this hypothetical tool, to make sure it's not "complete garbage", as you say.

    I know how to compile code as a library, but that doesn't help with the headers.
  • 2
    @YADU Btw

    int * a = malloc(10); //doesn't work

    int * a = (int*) malloc(10); //this does

    So you just need to cast void pointers to use them..
  • 2
    @BigBoo in C both work, in C++ you require the cast.

    I was thinking if you ran the C code through the tool, it would tell you to put the cast in so it was also valid C++ code.
  • 3
    @YADU Also that size of thing you said was false. 'a' is not equal to sizeof int in C.

    It's the same size in both C and C++.

    You get an error from the compiler when you need to do it. So.. isn't that enough? And it only seems to be this case. Atleast that you have been able to show so far.

    So my advice still stands. Compile C code as a lib with GCC and cast void pointers when needed.

    It's not that complicated.
  • 2
    Also.

    You can use a C++ compiler to check if it works or not.

    If it compiles... It works.

    If it doesn't compile... It doesn't work.

    It's literally what you are asking for.
  • 2
    @BigBoo run

    #include <stdio.h>

    int main(void) {
    printf("%lu\n", sizeof('a'));
    }

    Through a C compiler and tell me what you get, then run it through a C++ compiler and tell me what you get. I get 4 with the C compiler, 1 with the C++ compiler.
  • 2
    @njpugh90 yea you do, but i thought it would cool if there was a tool that actually checked this for you, to see whether you could also use a C++ compiler.

    I guess although the tool would technically do something, in practice it's probably not that useful, which is why i guess no one has written it.

    To clarify, i don't actually have this issue right now.
  • 1
    @YADU I can get the C compiler (both GCC and clang) to give out both results. Depending on file ending. So I guess you are right. But if I compile the same file with cpp as file ending it behaves differently. Lol.

    Note that I don't change to a c++ compiler even.

    So yeah, you're kind of right. But you could also fix that by changing the file ending in that case.
  • 1
    @BigBoo i think GCC and clang decide whether to compile as C or C++ based on ending. So you're not really compiling it as C++ code if you change the ending to .c to fix it.

    The different results are because C and C++ have different behaviour in this case. In C character literals are actually ints, whereas in C++ they're chars. (C++ breaks backward compability with C in this case to allow function overloading.)
  • 1
    @YADU I see. Well. The problem will be solved if you compile it with GCC instead of G++ though. So there isn't really an issue tbh.

    You can insist in doing it your way. But it feels like a huge waste of time when there's already a completely functional solution to the problem.

    It just doesn't work in the way you would prefer it seems.
  • 2
    @BigBoo i think you're right that it's not really an issue.

    When I came up with my idea I thought it would be more widely useful, but i think almost all of the issues are solved either by looking at the errors from compiling as C++ or by just compiling as C.

    Although I'm sure I could come up with a contrived example that will break both of those strategies :P
  • 0
    There are also nasty corner cases like type punning through unions, which is allowed in C, but not in C++ (IIRC).
  • 0
    @Fast-Nop yes, these are the sorts of things i was hoping the tool would catch. The weird corner cases that compile under both but behave different.

    IIRC there's also something weird with function pointers fron functions declared extern C in C++ code.
  • 1
    random me passing around...
Add Comment