I'm using libgmp with Swift, but for some reason the Clang C module importer does not do what I'm expecting. Here's an excerpt of gmp.h, which is the main header file. Consider the following definition:
To use this from C, I just do mpz_clear(e). To use this from Swift, I have to do __gmpz_clear(&e).
Why is the Clang importer not honoring the #define here?
I created an example Xcode project for you to reproduce.
I think there's a new-ish way to diagnose Clang importer questions such as yours, thanks to @NuriAmari’s work in PR #39923: Improve ClangImporter Diagnostics. From reading the PR, I assumed you should be able to pass -Xfrontend -enable-experimental-clang-importer-diagnostics to the compiler, but this doesn’t work for me with your sample project with Swift 5.7 (Xcode 14.0.1 or Xcode 14.1b3) because the compiler doesn’t recognize the flag:
I think there's a new-ish way to diagnose Clang importer questions such as yours, thanks to @NuriAmari’s work in PR #39923: Improve ClangImporter Diagnostics . From reading the PR, I assumed you should be able to pass -Xfrontend -enable-experimental-clang-importer-diagnostics to the compiler, but this doesn’t work for me with your sample project with Swift 5.7 (Xcode 14.0.1 or Xcode 14.1b3) because the compiler doesn’t recognize the flag:
Maybe this flag is not part of the Xcode toolchains (yet?)? I haven't tested with a current nightly toolchain. I think there's a new-ish way to diagnose Clang importer questions such as yours, thanks to @NuriAmari’s work in PR #39923: Improve ClangImporter Diagnostics . From reading the PR, I assumed you should be able to pass -Xfrontend -enable-experimental-clang-importer-diagnostics to the compiler, but this doesn’t work for me with your sample project with Swift 5.7 (Xcode 14.0.1 or Xcode 14.1b3) because the compiler doesn’t recognize the flag:
Ok, thanks for acknowledging that this is a bug. Unfortunately, it's not only about one single symbol, gmp.h is full of those #defines. Would be cool, if this could be fixed sooner or later.
ClangImporter's ability to import macros is extremely limited; it really only covers simple constant-like macros like #define RED ((uint32_t)0xff0000). It can import macros with identifiers that refer to other macros, but not the general case.
We're not likely to expand macro import support to handle your use case, but an alternative would be to use swift_name attributes to rename functions when they're imported into Swift. For example, if you marked this function with __attribute__((swift_name("mpz_clear"))), Swift would import it with the desired name. If you don't want to edit the header file, you can instead use API notes, a YAML format which can add attributes to clang declarations. (In an API note, the attribute will be spelled SwiftName.) If the library uses this pattern in a sufficiently regular way, you could probably write a small script to read in the header and generate API notes for you.
If you want to get fancy with this, the swift_name attribute can also map global C functions to members of types. For instance, if you used the Swift name mpz_t.clear(self:), then depending on the definition of mpz_t this method would come in as a method called clear().