The aim of this patch is to resolve the missing table_size symbol (see reduced test case). That const variable is declared and defined in libcxx/include/locale; however, the test case suggests that the symbol is missing. This is due to a C++ pitfall (highlighted here). In summary, assigning the reference of table_size doesn't enforce the const-ness and expects to find table_size in the DLL. The fix is to use constexpr or have an out-of-line definition in the src (for consistency).
Details
- Reviewers
• Quuxplusone ldionne - Group Reviewers
Restricted Project - Commits
- rG049f6c29a6f0: [libc++] Resolve missing table_size symbol
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
To reproduce:
Compile (with -std=c++17) and link the following program:
#include <locale> int main() { const size_t *okay = &std::ctype<char>::table_size; return 0; }
libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.statics/table_size.pass.cpp | ||
---|---|---|
24 | Do we need the pointer? Or can we just say assert(F::table_size >= 256); |
libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.statics/table_size.pass.cpp | ||
---|---|---|
24 | It could be a static_assert even, right? |
libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.statics/table_size.pass.cpp | ||
---|---|---|
24 | Yes, we need the pointer since the error under test occurs when we have a reference to F::table_size. The assert is there to avoid getting an unused variable warning (G). |
Adding my own distracting comment. ;) I figure @ldionne is the only one who can really give this the green light.
libcxx/include/__locale | ||
---|---|---|
712–718 ↗ | (On Diff #376343) | Peanut gallery says: This does fix the linker problem IIUC, but wouldn't it be more consistent to put an out-of-line definition in libcxx/src/locale.cpp? We do that for locale::id ctype<char>::id; (cf. line 712 above), and also for const ctype_base::mask ctype_base::space; const ctype_base::mask ctype_base::print; const ctype_base::mask ctype_base::cntrl; ~~~ Vice versa, if we're finally able to use constexpr for this stuff so that it doesn't need to be in locale.cpp, then maybe can we use constexpr consistently for all of the above stuff too? or we can't do that because ABI? |
Using out-of-line definition instead of constexpr. This way is more consistent and allows the test case to pass for standards prior to c++17.
Any insight as to why the CI is red? It seems to complain about a new symbol being added _ZNSt3__15ctypeIcE10table_sizeE, which is defined. However, that is the intention since we want to resolve the missing symbol.
The CI is testing that there are no ABI changes. This patch contains an ABI change, since it adds a symbol. The change is not an ABI *break* so it is acceptable, but it is nonetheless a change. You need to update the ABI lists to contain that symbol.
You can see how to do that here: https://libcxx.llvm.org/Contributing.html#exporting-new-symbols-from-the-library. Basically, go to https://buildkite.com/llvm-project/libcxx-ci/builds/6180#75b25b94-130a-472d-a409-72a7f5507f17 and click on Artifacts. The libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist file will contain the new symbol for table_size -- add it to the corresponding file in libcxx/. You'll then need to do the same on macOS (look at the macOS ABI lists in the macOS jobs once the CI gets that far).
Finally, please also add an entry in libcxx/lib/abi/CHANGELOG.TXT.
libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.statics/table_size.pass.cpp | ||
---|---|---|
12 | Please add a comment explaining what the test is checking. Something like this would suffice: // Make sure we can reference std::ctype<char>::table_size. | |
13 | You will need to add something like this: // Before https://llvm.org/D110647, the shared library did not contain // std::ctype<char>::table_size, so this test fails with a link error. // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{11|12|13}} Technically you would also need similar annotations for other vendors who ship libc++ as the system library, but I don't think they test back-deployment, so we don't have annotations for them. | |
24 | I think it is good to have the assert since std::ctype<char>::table_size is specified as being at least 256. |
Thanks for the explanation. I will add the commit hash to the libcxx/lib/abi/CHANGELOG.TXT once this lands. Comments have been addressed.
LGTM once CI passes and comments have been addressed.
libcxx/lib/abi/CHANGELOG.TXT | ||
---|---|---|
21 | Let's be verbose on the explanations. | |
libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist | ||
1649 | I think this should be {'name': '__ZNSt3__15ctypeIcE10table_sizeE', 'type': 'OBJECT', 'is_defined': True, 'size': 0} instead. For some reason, mangled names on Darwin start with two underscores, and one underscore on Linux. I should investigate why that is. | |
libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist | ||
1649 | Same. |
Let's be verbose on the explanations.