Issue 24641 - ImportC: enum typedef before definition is not supported
Summary: ImportC: enum typedef before definition is not supported
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Windows
: P1 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-06-30 08:29 UTC by Andrej Mitrovic
Modified: 2024-06-30 08:35 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Andrej Mitrovic 2024-06-30 08:29:14 UTC
This is a small snippet from a C++ library blend2d that can be used in C.

Here's the header file lib.h:

---
#ifdef __cplusplus
  #define BL_DEFINE_CONST static constexpr
  #define BL_DEFINE_ENUM(NAME) enum NAME : uint32_t
  #define BL_FORCE_ENUM_UINT32(ENUM_VALUE_PREFIX)
#else
  #define BL_DEFINE_CONST static const
  #define BL_DEFINE_ENUM(NAME) typedef enum NAME NAME; enum NAME
  #define BL_FORCE_ENUM_UINT32(ENUM_VALUE_PREFIX) ,ENUM_VALUE_PREFIX##_FORCE_UINT = 0xFFFFFFFFu
#endif

BL_DEFINE_ENUM(BLObjectType) {
  BL_OBJECT_TYPE_RGBA = 0,
  BL_OBJECT_TYPE_RGBA32 = 1,
};

int blArrayInit(BLObjectType arrayType);
---

Running the VC preprocessor:

---
cl /P /TC /EP /Filib.c lib.h
---

Generates this code:

---
typedef enum BLObjectType BLObjectType; enum BLObjectType {
  BL_OBJECT_TYPE_RGBA = 0,
  BL_OBJECT_TYPE_RGBA32 = 1,
};

int blArrayInit(BLObjectType arrayType);
---

This cannot be imported with DMD:

---
$ dmd -o- lib.c

lib.c(5): Error: cannot have parameter of opaque type `BLObjectType` by value
---

Moving the type def /after/ the enum definition fixes this as expected.

But it looks like existing C compilers (other than DMD's) seem to support this syntax.

Both VC and GCC work with these typedefs. I'm not sure what they do underneath the hood to make this work.
Comment 1 Andrej Mitrovic 2024-06-30 08:35:39 UTC
For reference I managed to find a very simple fix. I replaced the macro from:

---
#define BL_DEFINE_ENUM(NAME) typedef enum NAME NAME; enum NAME
---

to:

---
#define BL_DEFINE_ENUM(NAME) enum NAME
---

And then the preprocessed file can be imported into DMD nicely.