@encode() discrepancy between C++11 and earlier


http://reviews.llvm.org/D76801 changed clang/lib/AST/TypePrinter.cpp to not print a space between consecutive '>'s in templates if targeting C++11 or later.

I noticed recently that this affects Objective-C’s @encode too, which means it has different results based on language standard, making it impossible to build part of a program with C++98 and another part with C++11 (…if both parts need @encode if some common type to agree). It also means @encode for types changed with that patch, which is an ABI break of sorts.

However, the change landed in March, so maybe it’s already deployed in new Xcodes.

Should we make @encode opt out of this pretty printing change to restore the old behavior? (Several other places also broke due to that change and were changed to opt out – debug info, for example).

I found this while writing tests for an unrelated change [1] and I don’t know of any projects adversely affected by this.


1: See “FIXME” in https://reviews.llvm.org/D90622#change-Aht3gYP3AIRe

Hi Nico,

Thanks for reaching out. Michael Spencer is probably the best contact for this kind of question these days; I’ve cc’ed him.


I think some of the other recent TypePrinter changes might also risk changing the @encode output. Generally it seems unwise for @encode to be using the type pretty-printer if it wants to be ABI-stable; I don’t think it’s reasonable to expect any guarantees as to the stability of pretty-printed type names. I think USR generation suffers from similar problems; it too uses the type pretty-printer to generate supposedly-ABI-stable keys in at least some cases.

As I recall, Objective-C++ doesn't specify what goes in the string for C++ classes (for C structs it's fairly unambiguous, and Objective-C++ just does something similar by analogy, there's no official documentation on precisely what it generates). Is there code that you're aware of that parses the C++ type names? If not, I'd suggest that the best thing for us to do is simply document that this encoding is not stable. Any Objective-C++ code trying to parse C++ type declarations is going to need to be careful about unknown tokens anyway: something that can parse all C++98 will find a lot of unknown things in a C++20 program.

It would be useful if we implemented type encodings for C++ arguments in such a way that `NSInvocation` could correctly move-construct copies of the arguments to pass to another thread, but that would be an invasive ABI change. I don't think it's something that you can adequately get out of the encoding.