Bug 24505 – [REG2.108] ImportC: Function-like macros (newly translated to templates) may collide with regular symbols
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2024-04-15T17:37:03Z
Last change time
2024-04-23T14:24:16Z
Keywords
ImportC, industry, pull
Assigned to
No Owner
Creator
kinke
Comments
Comment #0 by kinke — 2024-04-15T17:37:03Z
This is a snippet derived from a Windows-specific Postgres header, which cannot be imported with DMD v2.108 anymore:
```
struct stat { int x; };
void __stat(int x, int y);
#define stat(x, y) __stat(x, y)
```
```
Error: template `c.stat(__MP21, __MP22)(__MP21 x, __MP22 y)` conflicts with struct `c.stat` at c.c(1)
```
I think it'd be better to skip the new macro-translation in such a case, maybe with a printed warning. Alternatively, some ugly escape hatch via e.g. `--ignore-macro=stat` - patching C headers isn't really a feasible option.
Comment #1 by tim.dlang — 2024-04-15T20:12:28Z
Maybe macros and normal symbols could be in different modules or mixin templates, so one is used by default, but it is still possible to get the other symbol explicitly. An example lowering could be:
```
struct stat { int x; };
void __stat(int x, int y);
mixin template __CMacros()
{
// #define stat(x, y) __stat(x, y)
void stat(T1, T2)(T1 x, T2 y)
{
__stat(x, y);
}
}
mixin __CMacros!() __cmacros;
```
Now the compiler would prefer the struct, when using `stat`, but it would be possible to get the macro using `__cmacros.stat`.
Comment #2 by kinke — 2024-04-16T10:37:52Z
The mixin template could work (the module is the .c file), but I doubt it'd be a big improvement over simply ignoring a conflicting macro - as the importer needs to know about such (potentially platform-dependant) header details, i.e., what symbol might be a macro.
Another manual solution could be to skip the translation if the macro is undefined later via `#undef stat` - that would be doable in the .c file including the headers, without having to patch the original headers.
Note that the Postgres header (https://github.com/postgres/postgres/blob/master/src/include/port/win32_port.h) is actually even a bit worse, defining 3 `stat` 'symbols':
```
#define stat microsoft_native_stat
#include <sys/stat.h>
#undef stat
[…]
struct stat { … };
[…]
#define stat(path, sb) _pgstat64(path, sb)
```
Comment #3 by dfj1esp02 — 2024-04-16T12:58:27Z
Looks like a generic problem. How posix stat should work? It's defined as
struct stat { };
int stat(const char *pathname, struct stat *statbuf);
Comment #4 by kinke — 2024-04-17T11:28:38Z
(In reply to anonymous4 from comment #3)
> Looks like a generic problem. How posix stat should work?
It is a generic problem, one that we cannot solve elegantly in D/importC - we don't have an ugly 2-stage compilation like C(++), with preprocessor 'symbols'. But we need to be able to deal with this. In this concrete case, our interop code doesn't use `stat` in D at all, it's a totally uninteresting symbol, like ~99% of the C symbols dragged in by ~400k preprocessed lines.
If one indeed depended on the `stat` macro, a solution could be to add a little wrapper in the .c file, letting the preprocessor do its magic, and then aliasing `stat` to that custom wrapper in the .d file importing the .c file.
Comment #5 by dlang-bot — 2024-04-17T16:50:44Z
@kinke created dlang/dmd pull request #16396 "[stable] Fix bugzilla 24505 - ImportC: Function-like macros may collide with regular symbols" fixing this issue:
- Fix bugzilla 24505 - ImportC: Function-like macros may collide with regular symbols
https://github.com/dlang/dmd/pull/16396
Comment #6 by dlang-bot — 2024-04-18T11:26:36Z
@kinke created dlang/dmd pull request #16398 "[stable] Fix bugzilla 24505 - ImportC: Don't generate symbols for #undef'd macros" fixing this issue:
- Fix bugzilla 24505 - ImportC: Don't generate symbols for #undef'd macros
https://github.com/dlang/dmd/pull/16398