-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Avoid C99 typedef redeclaration error #15079
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I wonder if there might be some more issues related to this typedef redefinition warnings (or errors on some compiler configurations). #13347 Another one, I've also seen in the ext/dom and I think one in ext/opcache somewhere but if the build on that macOS with GCC 4.2 works out then that's fine I guess. I'll also retest it with my build system a bit. |
I do think we should seriously consider bumping the compiler requirement to C11 soon. We should do so before investing too much time here. |
@barracuda156, could you please check if this compiles with the old GCC? |
That would be great. I wasn't actually able to test this, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me; a different solution might be to include zend_types.h
instead of zend_portability.h
.
Well, I just looked and couldn't even find any user targeted information on the C99 requirement (neither in the docs which say you need an "An ANSI C compiler", nor in README.md). Maybe this should be fixed first, before bumping the compiler requirements to C11 (although I don't have strong feelings about this). |
@cmb69 It's here, quite hidden. Line 12 in e63f822
Edit: Oh, you edited that, so you're probably aware. Yes, that's not particularly user-targeted, and yes https://www.php.net/manual/en/install.unix.php is very much outdated. |
I think this small PR is okay. But honestly, the user's OS is far-outdated, from 2009. We should not spend significant effort maintaining something so old. |
typedef struct _zend_object_iterator zend_object_iterator; | ||
typedef struct _zval_struct zval; | ||
/* Intentionally avoid typedef because of C99 redeclaration errors. */ | ||
struct _zend_array; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing this, I already wondered before: Why is the struct tag even prefixed with an underscore instead of matching the typedef'd name exactly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is just an convention to avoid having identical names. And maybe also as a hint that clients should use the typedef'd name.
@morrisonlevi, for me, this is not about supporting old compilers and build tools, but to stick to the given standard (C99). There may be even new compilers who complain about this, at least when advised (e.g. https://clang.llvm.org/docs/DiagnosticsReference.html#wtypedef-redefinition). |
@cmb69 Even though this is enabled by default, Clang only warns about this with Maybe I misunderstood your statement, but if we correctly supplied the |
@cmb69 Sure, will do it soon and update you. |
@barracuda156 Please wait for a few more hours. I noticed that there are many more new errors like this. I'll update this PR. |
C99 uses __asm__
@morrisonlevi This is not the issue. We have gcc15 (current master) working on this 2009 macOS, so there is no problem to support any C standard. But if C11 is not required, then the code is supposed to compile with C99. |
Clang emits the best errors when violating the provided standard.
From a quick google it seems that C11 support was introduced in gcc 4.7, and "GCC 4.9 Changes: “ISO C11 support is now at a similar level of completeness to ISO C99 support". GCC 4.9 is from 2014 and GCC 4.7 is from 2012. So the compilers are 10-12 years old. Does it make sense to make these changes? You'd also have to make the changes on lower branches I guess... |
I was assuming that lower branches compiled with no warnings
I guess not. I did not expect there to be this many issues. I will consult the mailing list about switching to C11. |
Anything which can build with gcc10 is fine, IMO, since gcc10 can be bootstrapped without support for C11/C11+ is the system compiler. So while one has to build a suitable compiler first, it is a one-step pathway (and honestly at least C11/C11+ is needed nowadays so often that hardly anyone actually using legacy systems is limited to gcc 4.x). Requiring something newer than gcc10 can build is a bit problematic, though even that is not really a stopper. |
@cmb69 It seems like MSVC only supports C11 from Visual Studio 2019 [1] but VS 2015 and 2017 remain supported [2]. Do you think that is a problem? [1] https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ |
@iluuu1994, no problem there since VisualStudio 2017 is no longer used for PHP 8 officially. Some users might still use it, but I don't think that should be of concern. And particularly about the typedef redefinition, I don't think that's an issue even for older Visual Studio, since that is allowed in C++ anyway (and VS doesn't make a big difference between C and C++). Anyway, I think requiring C11 should be discussed on the mailing list; hopefully a quick and uncontroversal discussion not requiring an RFC. |
@cmb69 I agree. I was just gathering information about common environments to send an informed e-mail. Thank you! |
@iluuu1994 can we also set a minimum GCC and Clang compilers versions while bumping the C11? Because there is this constant issue of what is the minimum GCC version supported in PHP. I know that this might not be such a common practice out there but it will be quite helpful. Getting version in Autoconf can be done something like this: https://github.com/autoconf-archive/autoconf-archive/blob/master/m4/ax_compiler_version.m4 but this will be adjusted to a bit simpler PHP_COMPILER or something M4 macro. |
@@ -22,12 +22,12 @@ | |||
|
|||
#include "zend_types.h" | |||
|
|||
typedef struct _zval_struct zval; | |||
struct _zval_struct; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stupid question maybe, but why do we need this at all? The typedef is defined in zend_types.h which is included right above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, this one is indeed probably unneeded.
@iluuu1994 I think there are quite a few places in Zend/ (e.g. zend_frameless_functions.h) which reference definitions from zend_string.h or zend_types.h. I think there's no need to avoid including zend_types.h/zend_string.h multiple times. These files are anyway relatively small. and will sort of anyway be somehow included by any file using Zend things. |
I'm always baffled when I encounter these
Why? Requiring a C99 compiler, or a C11 compiler if you absolutely must, should be sufficient. If it isn't, and you want to define lower limits for clang, do not forget that there are two different compilers called clang—one released by llvm.org and one released by Apple—and they use different version numbering schemes, so you must state what the lower limit is for each of them. |
For DOM, because I don't want to include another header inside the header file to get a certain typedef. But I'm always baffled when people pull out ancient compiler versions 🤷. |
I agree. Some of the PHP headers are gigantic and it's easy to run into recursive dependencies when not careful. I added some new headers that are included in common headers, and to avoid adding more dependencies I used some forward declarations. |
Why bumping compiler minimum version? Because of the compiler features that we constantly check here and there. For example of issues like this #14497 and for example checking the attribute is also inconsistent in php-src at the moment. There are still some checks for GCC version 2 in the code. Obviously PHP doesn't build on GCC 2 anymore. Treating compiler versions like part of the requirements. Minimum re2c, bison, Autoconf, and also build tools like compiler sounds quite logical to me in the very inconsistent C landscape. |
And yes, I agree. The "AppleClang" should be treated as a standalone compiler here indeed. So, checking for version of AppleClang separately from Clang. This Clang isn't so much of an issue actually. This would be an ideal case or in the bare minimum to check for GCC version. |
I had recently a bug report (by email as that person did not have GitHub) running GCC 4.9. I doubt that there will be too many older versions in use so if we can set minimal version to 4.9, it should be hopefully fine even for 8.4. We could consider further bump in the future but 4.9 would be probably good start IMHO. |
Just adding here another example of the compiler version issue: https://bugs.php.net/bug.php?id=77883 Probably, I've also missed something, because I haven't finished reviewing entire php-src attributes and similar compiler features implementation but I also still think that setting only the C standard wouldn't be enough in PHP's case. For example, should the attributes be handled in the C code conditionally etc. without limiting the minimum compiler version(s) or should some minimum compiler version be a requirement... |
@iluuu1994, are you still planning to write to internals? I don't want to rush, but I think this issue should be resolved prior to 8.4.0beta1. If you don't have time, I can send the mail instead (although I would be happy if you could provide me with info about compiler compatibility you have gathered so far).
I'd rather focus on a C (C++) standard, and would only document exact versions of the most important compilers (and even that probably only if there's actual need, i.e. if we come across an issue with an old compiler version). I can imagine there are still a couple of compilers (or variants) in use, we don't really know about. |
@cmb69 Yes, sorry for the delay. I'll try to send it tonight or tomorrow. |
Hi everyone We've gotten a bug report about compile errors in the PHP 8.4 alpha on old C99 compilers (and on some modern compilers when passing the -std=c99 flag). Specifically, C99 does not support typedef redeclarations, which is a C11 feature. // some_header.h
typedef struct _zval_struct zval;
void some_func(zval *zv);
// zend_types.h
struct _zval_struct { ... };
typedef struct _zval_struct zval; Some headers might want to forward declare zval so that zend_types.h doesn't have to be included. The two primary reasons you might want to avoid that is 1. to reduce compile times if the header is very large and 2. to prevent recursive header dependencies. However, in C99 this code is actually illegal if both of these headers end up being included, because redeclarations of typedefs are not allowed. To fix it, the typedef must be removed and the signatures must refer to the struct directly. // some_header.h
struct _zval_struct;
void some_func(struct _zval_struct *zv); I started fixing these in a PR [1] which required more changes than expected. After a short discourse, we were wondering whether it might be better to switch to a newer C standard instead. Our coding standards [2] currently specify that compiling php-src requires C99. The Unix installation page on php.net [3] claim it is ANSI C, which is certainly outdated. There have been suggestions to require C11 for a while, which should be well supported by all compilers shipped with maintained distributions. GCC gained support for C11 in 4.7 [4], Clang in 3.1, both released in 2012. For context, Debian Bullseye comes with GCC 10.2 [5], Ubuntu Focal Fossa comes with GCC 9.3 [6], RHEL 8 comes with GCC 8.x [7]. The biggest blocker in the past was MSVC, which has finally added C11 support in Visual Studio 2019 [8]. Technically, Visual Studio 2015 and 2017 are still supported by Microsoft [9], but according to Christoph they are no longer used for PHP builds since version 8. Hence, it seems like it would be ok to bump our C compiler requirement to C11. We'd like to make this change before beta 1 if there are no objections. If you have any, please let me know. Ilija [1] #15079 Line 12 in 8b6f14a
[3] https://www.php.net/manual/en/install.unix.php [4] https://stackoverflow.com/a/16256596 [5] https://packages.debian.org/bullseye/gcc [6] https://packages.ubuntu.com/focal/gcc [7] https://access.redhat.com/solutions/19458 [8] https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ [9] https://learn.microsoft.com/en-us/visualstudio/productinfo/vs-servicing Sounds ok? |
@iluuu1994, looks very good. Maybe add
|
As I mentioned previously, there are two different things called clang so it is importantly to specify which one one is talking about: llvm.org clang or Apple clang. According to this table, Apple clang 3.1, 4.0, and 4.1 were all based on prerelease versions of llvm.org clang 3.1 and Apple clang 4.2 was based on a prerelease version of llvm.org clang 3.2. If the feature you need was introduced in llvm.org clang 3.1, I do not know in which version of Apple clang it was introduced. |
typedef struct _php_random_fallback_seed_state php_random_fallback_seed_state; | ||
struct _php_random_fallback_seed_state; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can keep this as is, just remove the typedef struct.. later in the same file.
Closing in favor of #15397. For context: https://externals.io/message/124706#124922 |
Fixes GH-15070