atilaneves / dpp

Directly include C headers in D source code
Boost Software License 1.0
229 stars 31 forks source link

typedef leads to multiple definitions of the same struct #294

Closed alexandrumc closed 2 years ago

alexandrumc commented 2 years ago
@("typedef multiple definitions")
@safe unittest {
    // See https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.16299.0/um/winscard.h#L504-L528
    with(immutable IncludeSandbox()) {
        writeFile("hdr.h",
                `
                    typedef struct {
                        int dwStructSize;
                        int lpstrGroupNames;
                    } a, *b, *c;

                    typedef struct {
                        int dwStructSize;
                        int lpstrGroupNames;
                    } x, *y, *z;

                    #ifdef SOMETHING
                    typedef x X;
                    typedef y Y;
                    typedef z Z;
                    #else
                    typedef a X;
                    typedef b Y;
                    typedef c Z;
                    #endif
                `);

        writeFile("main.dpp",
                `
                    #include "hdr.h"
                    void main() { }
                `);

        runPreprocessOnly("main.dpp");

        shouldCompile("main.d");
    }
}

main.d(117): Error: struct main._Anonymous_0 conflicts with struct main._Anonymous_0 at main.d(107) main.d(145): Error: struct main._Anonymous_1 conflicts with struct main._Anonymous_1 at main.d(135)

it.c.compile.typedef_.typedef multiple definitions:
    tests/it/c/compile/typedef_.d:203 -·

Could not execute `dmd -m64 -o- -c main.d`:
main.d(117): Error: struct `main._Anonymous_0` conflicts with struct `main._Anonymous_0` at main.d(107)
main.d(145): Error: struct `main._Anonymous_1` conflicts with struct `main._Anonymous_1` at main.d(135)

main.d:
----------
   53:
   54:           struct Int128 { long lower; long upper; }
   55:           struct UInt128 { ulong lower; ulong upper; }
   56:
   57:           struct __locale_data { int dummy; } // FIXME
   58:
   59:
   60:
   61:   alias _Bool = bool;
   62:   struct dpp {
   63:       static struct Opaque(int N) {
   64:           void[N] bytes;
   65:       }
   66:       // Replacement for the gcc/clang intrinsic
   67:       static bool isEmpty(T)() {
   68:           return T.tupleof.length == 0;
   69:       }
   70:       static struct Move(T) {
   71:           T* ptr;
   72:       }
   73:       // dmd bug causes a crash if T is passed by value.
   74:       // Works fine with ldc.
   75:       static auto move(T)(ref T value) {
   76:           return Move!T(&value);
   77:       }
   78:       mixin template EnumD(string name, T, string prefix) if(is(T == enum)) {
   79:           private static string _memberMixinStr(string member) {
   80:               import std.conv: text;
   81:               import std.array: replace;
   82:               return text(` `, member.replace(prefix, ""), ` = `, T.stringof, `.`, member, `,`);
   83:           }
   84:           private static string _enumMixinStr() {
   85:               import std.array: join;
   86:               string[] ret;
   87:               ret ~= "enum " ~ name ~ "{";
   88:               static foreach(member; __traits(allMembers, T)) {
   89:                   ret ~= _memberMixinStr(member);
   90:               }
   91:               ret ~= "}";
   92:               return ret.join("\n");
   93:           }
   94:           mixin(_enumMixinStr());
   95:       }
   96:   }
   97:
   98:   extern(C)
   99:   {
  100:
  101:       alias Z = a*;
  102:
  103:       alias Y = a*;
  104:
  105:       alias X = a;
  106:
  107:       struct _Anonymous_0
  108:       {
  109:
  110:           int dwStructSize;
  111:
  112:           int lpstrGroupNames;
  113:       }
  114:
  115:       alias z = x*;
  116:
  117:       struct _Anonymous_0
  118:       {
  119:
  120:           int dwStructSize;
  121:
  122:           int lpstrGroupNames;
  123:       }
  124:
  125:       alias y = x*;
  126:
  127:       struct x
  128:       {
  129:
  130:           int dwStructSize;
  131:
  132:           int lpstrGroupNames;
  133:       }
  134:
  135:       struct _Anonymous_1
  136:       {
  137:
  138:           int dwStructSize;
  139:
  140:           int lpstrGroupNames;
  141:       }
  142:
  143:       alias c = a*;
  144:
  145:       struct _Anonymous_1
  146:       {
  147:
  148:           int dwStructSize;
  149:
  150:           int lpstrGroupNames;
  151:       }
  152:
  153:       alias b = a*;
  154:
  155:       struct a
  156:       {
  157:
  158:           int dwStructSize;
  159:
  160:           int lpstrGroupNames;
  161:       }
  162:   }
  163:
  164:
  165:
  166:                       void main() { }