Summary: | ctype.h performance (and potentially behavior) depends on include order | ||
---|---|---|---|
Product: | glibc | Reporter: | Travis Downs <travis.downs> |
Component: | libc | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | UNCONFIRMED --- | ||
Severity: | normal | CC: | andysem, drepper.fsp, fweimer |
Priority: | P2 | Flags: | fweimer:
security-
|
Version: | 2.27 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Last reconfirmed: |
Description
Travis Downs
2019-11-22 01:21:45 UTC
Are you compiling as C++? Some libstdc++ headers define __NO_CTYPE (because C++ prohibits headers from defining standard functions as macros), but I don't see anything in the glibc headers defining that macro. Yes, I'm compiling as C++, and I should have made that clear from the start. In C, the flow is totally different and toupper/tolower are macros, not functions (as you pointed out). Although I'm compiling as C++, the only headers I'm including are <stdlib.h> and <ctype.h>. I'm not sure exactly where __NO_CTYPE is getting defined in this case, but in another case I looked at (this time including C++ headers like <algorithm>, the __NO_CTYPE definition came from <bits/os_defines.h>). Here's an example that shows that <stdlib.h> defines __NO_CTYPE when compiled in C++: https://godbolt.org/z/y6Quxs In C it is not defined. (In reply to Travis Downs from comment #3) > Here's an example that shows that <stdlib.h> defines __NO_CTYPE when > compiled in C++: > > https://godbolt.org/z/y6Quxs > > In C it is not defined. gcc ships C library header overrides, including stdlib.h, so when you're including stdlib.h from a C++ program you're getting its C++ version. Eventually it includes the C stdlib.h, but before that it may define necessary config macros and do other stuff necessary for compliance with C++. You can see all includes, with paths, in preprocessed output by adding -P to gcc command line. On my system with gcc 10 your test program shows these includes, in that order, among the first lines of the preprocessed output: /usr/include/c++/10/stdlib.h /usr/include/c++/10/cstdlib /usr/include/x86_64-linux-gnu/c++/10/bits/c++config.h /usr/include/x86_64-linux-gnu/c++/10/bits/os_defines.h and os_defines.h defines __NO_CTYPE. I would think that the macro should be either defined or not in C++ regardless of the header you include first. Otherwise there is potential for ODR violations, which result in nasty bugs. If this isn't the case, you should probably report a libstdc++ bug, describing the sequence of includes and the effects. Separately, I think it is worth requesting libstdc++ to implement a similar optimization that glibc does so that the locale functions are inlined, when possible. This could even reuse glibc implementation by juggling pragma push_macro/pop_macro (https://gcc.gnu.org/onlinedocs/gcc/Push_002fPop-Macro-Pragmas.html). Sorry, the command line argument is -E. Thanks Andrey, I've filed this bug against libstdc++: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100128 |