Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

translate-c silently ignores non-equivalent macro redefinitions and macros shadowing non-macros #20301

Open
cbilz opened this issue Jun 15, 2024 · 0 comments
Labels
bug Observed behavior contradicts documented or intended behavior translate-c C to Zig source translation feature (@cImport)
Milestone

Comments

@cbilz
Copy link
Contributor

cbilz commented Jun 15, 2024

Zig Version

0.13.0

Steps to Reproduce and Observed Behavior

EDIT: Added examples showing related shadowing issues

Macro redefinitions

Create a file named header.h with these contents:

// snippet 1
#define MACRO 0
#define MACRO 1

Then run zig translate-c header.h and observe that the macro is translated into:

pub const MACRO = @as(c_int, 0);

The redefinition was silently ignored. Meanwhile, Clang and GCC accept the redefinition and issue a warning. To be clear, this means that Clang and GCC would replace MACRO with 1, not 0, see Godbolt. My understanding is that the C standard forbids macro redefinitions unless the replacements are equivalent in some sense.

Macros shadowing non-macros

There are similar issues when a macro has the same name as a non-macro: translate-c again treats

// snippet 2
const int MACRO = 0;
#define MACRO 1

as if the second line didn't exist, but C code including this snippet would subsequently replace MACRO with 1.

As for function-like macros, translate-c turns both

// snippet 3
int f(int x) {
    return x;
}
#define f(x) f(x+1)

and

// snippet 4
#define f(x) f(x+1)
int (f)(int x) {
    return x;
}

into the following Zig code as if the macro definition wasn't there:

pub export fn f(arg_x: c_int) c_int {
    var x = arg_x;
    _ = &x;
    return x;
}

Meanwhile, in C code including either of the above snippets, f(x) has the same value as x+1, see Godbolt.

Expected Behavior

Macro redefinitions (snippet 1)

Since Zig doesn't issue warnings, I think translate-c should do one of the following:

  • Fail with an error whenever there is an illegal redefinition, but accept legal redefinitions. For example, GCC's docs explain what they do and don't allow for both object-like and function-like macros. I don't understand the implementation of translate-c well enough to see whether this is easy to implement.
  • Only fail if two definitions of the same macro translate differently into Zig. I imagine this is easier to implement, but still offers some protection against accidental redefinitions. (But how do you treat redefinitions of function-like macros?)
  • Accept all redefinitions. This is what GCC and Clang do when warnings are turned off.

Macros shadowing non-macros (snippets 2-4)

I think the macro definitions should take precedence in these snippets, because this is how they would behave if included in C code. These semantics shouldn't change if the same code is @cIncluded instead. But note that while C code can invoke (f)(x) to circumvent the macro, the translated Zig would not even export the function.

@cbilz cbilz added the bug Observed behavior contradicts documented or intended behavior label Jun 15, 2024
@cbilz cbilz changed the title translate-c silently ignores non-equivalent macro redefinitions translate-c silently ignores non-equivalent macro redefinitions and macros shadowing non-macros Jun 15, 2024
@Vexu Vexu added the translate-c C to Zig source translation feature (@cImport) label Jun 15, 2024
@Vexu Vexu added this to the 0.15.0 milestone Jun 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior translate-c C to Zig source translation feature (@cImport)
Projects
None yet
Development

No branches or pull requests

2 participants