Something equivalent to NS_SWIFT_UNAVAILABLE, but for C++ interop?

When importing C++ headers via module map I get a lot of messages in the compiler output of the form: function 'xyz' unavailable (cannot import). I find these messages fine and useful in general, but I would like to suppress them in cases where I’ve decided that a given API entry point does not need to be fixed because I don’t need to call it from swift.
Things I tried:

  • __attribute__((swift_unavailable( "Not exported to swift." ))): Google search AI mode suggested this, but I think it’s an hallucination because the compiler does not accept that attribute.
  • __attribute__((unavailable( “Not exported to swift“))): This is what the NS_SWIFT_UNAVAILABLE Objective-C interop macro evaluates to. The compiler accepts this attribute in C++ headers (no error messages about unrecognized attributes), but it has no effect.

The only thing I found that works is #if !defined(__swift__), but that solution is not good enough because it can lead to object layout and v-table discrepancies when applied to class/struct data members or virtual methods. These discrepancies are not detected as compile-time ODR violations because they only come into play at link time and the linker does not detect ODR violations (by default), which can lead to very bad things like memory corruption, crashes and security vulnerabilities.

Is there another solution?

Thanks.

Could you please try __attribute__((swift_private))? What kind of declaration would you like to hide from Swift: is it a method, or a field of a struct?

For now, it’s class methods, but I anticipate that I’ll need to do this for class/struct fields in the near future.

I tried __attribute__((swift_private)) just now. Unfortunately it does not suppress the “cannot import” compiler messages to stderr.

It seems that the swift_private attribute would indeed be a reasonable solution here but I found that ClangImporter is just not checking that attribute when processing most types of C++ declarations. I believe this is probably just an oversight in the implementation. I am going to propose a PR that fixes this…

1 Like