www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 22674] New: ImportC: compatible types declared in different

https://issues.dlang.org/show_bug.cgi?id=22674

          Issue ID: 22674
           Summary: ImportC: compatible types declared in different
                    translation units are not treated equivalent in D.
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: dave287091 gmail.com

This situation comes up if you are consuming two C headers that included a type
from a header common to both of them.

Consider the following files:

// foo_def.h
typedef struct Foo *FooRef;

// maker.h
#include "foo_def.h"
FooRef make_foo(void);

// freer.h
#include "foo_def.h"
void free_foo(FooRef foo);

Which then preprocesses to:

// maker.i
typedef struct Foo *FooRef;
FooRef make_foo(void);

// freer.i
typedef struct Foo *FooRef;
void free_foo(FooRef foo);

You then try to use it in your D program:

// use_foo.d
import maker;
import freer;

void do_foo(){
    FooRef f = make_foo(); // use_foo.d(5)
    free_foo(f);           // use_foo.d(6)
}

use_foo.d(5): Error: alias `maker.FooRef` at maker.c(1) conflicts with alias
`freer.FooRef` at freer.i(1)
use_foo.d(6): Error: function `freer.free_foo(Foo* foo)` is not callable using
argument types `(Foo*)`
use_foo.d(6):        cannot pass argument `f` of type `maker.Foo*` to parameter
`freer.Foo* foo`

C11’s rules for when types are considered compatible are in "6.2.7 Compatible
type and composite type".

You can currently work around this by including both C headers in a single mega
translation unit that you then import, but it would be nicer if the compiler
could understand that as they are C declarations, they are actually the same
type.

--
Jan 13 2022