-
Notifications
You must be signed in to change notification settings - Fork 28
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
eval_pv fails to compile on non-gcc compilers with Perl < 5.031 #216
Comments
Would following patch fix your issue? diff --git a/parts/inc/call b/parts/inc/call
index 351f8cc5547d..756378c7f453 100644
--- a/parts/inc/call
+++ b/parts/inc/call
@@ -51,7 +51,8 @@ __UNDEFINED__ PERL_LOADMOD_IMPORT_OPS 0x4
#if defined(PERL_USE_GCC_BRACE_GROUPS)
# define D_PPP_CROAK_IF_ERROR(cond) ({ SV *_errsv; ((cond) && (_errsv = ERRSV) && (SvROK(_errsv) || SvTRUE(_errsv)) && (croak_sv(_errsv), 1)); })
#else
-# define D_PPP_CROAK_IF_ERROR(cond) ((cond) && (SvROK(ERRSV) || SvTRUE(ERRSV)) && (croak_sv(ERRSV), 1))
+ static void D_PPP_CROAK_IF_ERROR(int cond) { dTHX; SV *errsv; if (!cond) return; errsv = ERRSV; if (SvROK(errsv) || SvTRUE(errsv)) croak_sv(errsv); }
+# define D_PPP_CROAK_IF_ERROR(cond) D_PPP_CROAK_IF_ERROR(cond)
#endif
#ifndef G_METHOD |
As given, that doesn't seem to work for me: I get a bunch of errors/warnings that look like the proposed inline function isn't quite right. cc: "ppport.h", line 15051: error 1000: Unexpected symbol: "void". You might be able to make something of the idea with some adjustments, but I don't know this code well enough to suggest exactly what. |
I updated patch, could you try it if it helps? |
After a bit more poking at it, the primary reason for the compile failures is that you missed doing the pTHX_/aTHX_ dance. For me, editing ppport.h like this: -# define D_PPP_CROAK_IF_ERROR(cond) ((cond) && (SvROK(ERRSV) || SvTRUE(ERRSV)) && (croak_sv(ERRSV), 1)) allows the compile to go through, but then (unsurprisingly) I get link-time errors about multiple modules defining D_PPP_CROAK_IF_ERROR. Not sure why the STATIC_INLINE bit doesn't work, but it doesn't compile with that. |
That is why I updated patch with
That makes sense. |
Oh! My fault, I did not notice that you'd made that edit in addition to removal of the STATIC_INLINE bit. Yes, "dTHX;" works equally well as pTHX_/aTHX_, at least in my test case. With the particular ancient compiler I'm testing, declaring the function as plain "static" works fine, with no unused-function warnings. I'm worried though that other compilers will whine about it in modules that use neither eval_pv nor eval_sv. |
Oh ... the reason PERL_STATIC_INLINE fails is that I'm testing against perl 5.8.9, which if I'm reading the chart right lacks that symbol (and I don't see it in grepping the perl headers, either). So plain "static" might be the only way. |
Could you check if macro #ifndef PERL_STATIC_INLINE
#define PERL_STATIC_INLINE static
#endif So I have feeling that Devel::PPPort does not define |
Indeed, there is no such definition in ppport.h. |
Ok! So seems that Devel::PPPort needs to backport |
I'm still a bit worried about the unused-function-warning aspect, but maybe the set of cases where you'd get one is small enough to not bother about. Most people should be developing against versions that have PERL_STATIC_INLINE, and having that properly defined should be enough to prevent a warning. |
Could you try following patch for backporting diff --git a/parts/inc/misc b/parts/inc/misc
index 6d3edbc5af6d..a74e8cf8a017 100644
--- a/parts/inc/misc
+++ b/parts/inc/misc
@@ -19,6 +19,7 @@ MUTABLE_PTR
NVTYPE
PERLIO_FUNCS_CAST
PERLIO_FUNCS_DECL
+PERL_STATIC_INLINE
PERL_UNUSED_ARG
PERL_UNUSED_CONTEXT
PERL_UNUSED_DECL
@@ -38,6 +39,12 @@ ASSUME
=implementation
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+__UNDEFINED__ PERL_STATIC_INLINE static inline
+#else
+__UNDEFINED__ PERL_STATIC_INLINE static
+#endif
+
__UNDEFINED__ cBOOL(cbool) ((cbool) ? (bool)1 : (bool)0)
__UNDEFINED__ OpHAS_SIBLING(o) (cBOOL((o)->op_sibling))
__UNDEFINED__ OpSIBLING(o) (0 + (o)->op_sibling) Ad unused-function-warning, we are dealing with old compilers, I would not spend too much time how to mute false-positive warnings for these compilers. Just to ensure that code is correct and accepted by older compilers. If you need to check that code is correct, just use some new compiler... |
Sorry, I'm not really set up to build Devel::PPPort from source. But I can confirm that editing ppport.h like this passes my tests: |
Pull request with fix is here: #217 |
Thanks! |
Testing with all the suite without brace groups, failed in 5.9.3
is the expansion that fails, with
I'm not good at this part of C, figuring out what could get it to work |
I was not able to install |
As I told atoomic privately, usually a problem will exist in all previous versions to the one it is first found in. I looked at just the official versions, and sure enough, this bug exists in the first such one prior to 5.9.3; which is 5.8.8 |
The bottom line is we've been testing only with gcc all this time, and it is not the only compiler that people use on older perls |
I am working on testing other possible problems. So far I have found one more failure which is easy to fix |
The other problem I found plus this one
are the only ones that surfaced when run without gcc brace groups. The other fix is easy; I haven't stared at this to see what to do about it. Feel free to figure it out. |
Use a ?: expression? (PL_Sv = (sv), SvGMAGICAL(x) ? mg_get(x) : (void)0, sv_len_utf8_nomg(PL_Sv)) But I don't understand this macro. Where is "x" coming from? |
On 2/14/22 22:18, Tom Lane wrote:
Use a ?: expression?
(PL_Sv = (sv), SvGMAGICAL(x) ? mg_get(x) : (void)0, sv_len_utf8_nomg(PL_Sv))
But I don't understand this macro. Where is "x" coming from?
It is missing the beginning
#define foo(x) (PL_Sv = (sv), SvGMAGICAL(x) ? mg_get(x) : (void)0,
sv_len_utf8_nomg(PL_Sv))
|
Hm ... well, the double evaluation of the macro argument is bad practice, but it was like that already. |
@tglsfdc: Look! @khwilliamson wrote it incompletely, #define SvGETMAGIC(x) do { if (SvGMAGICAL(x)) mg_get(x); } while (0)
#define sv_len_utf8_nomg(sv) (PL_Sv = (sv), (SvUTF8(PL_Sv) ? Perl_sv_len_utf8(aTHX_ (!SvGMAGICAL(PL_Sv) ? PL_Sv : sv_mortalcopy_flags(PL_Sv, SV_NOSTEAL))) : (SvPV_nomg(PL_Sv, PL_na), PL_na)))
#define sv_len_utf8(sv) (PL_Sv = (sv), SvGETMAGIC(PL_Sv), sv_len_utf8_nomg(PL_Sv)) where Most of the perl macros evaluates its argument more than once, and this practice is documented the official in |
Got it. So this should be enough: #define SvGETMAGIC(x) (SvGMAGICAL(x) ? mg_get(x) : (void) 0) I didn't find the definition of mg_get in a quick look, so I'm not sure if the cast to void is right. |
#define mg_get(a) Perl_mg_get(aTHX_ a)
PERL_CALLCONV int Perl_mg_get(pTHX_ SV* sv);
In Perl source code is #define SvGETMAGIC(x) ((void)(UNLIKELY(SvGMAGICAL(x)) && mg_get(x))) So what about defining it in Devel::PPPort in the same way? Probably with dropped |
I am working on testing other possible problems. So far I have found one more failure which is easy to fix |
I would not have thought to go looking for an updated definition, so I really appreciate pali's having done so. Changing to use this definition causes it to compile, but the sv_len_utf8 (with and without _nomg) tests fail. undef is being returned. I am starting to look at this. |
I have been busy on other things, but also beating my head against the other issues that were uncovered by this. It turns out that sv_len_utf8_nomg() has likely never been a public function. I know not why. That's what threw me off. @pali submitted a patch to make it visible 303ccc0. That patch doesn't work without brace groups. And, do we need it.? No module that doesn't include ppport.h can see it, because it is not publicly available. In other words, this is a function that is only furnished by Devel::PPPort, not by perl. |
I see that embed.h defines sv_len_utf8_nomg only #ifdef PERL_CORE, so I agree it's not meant to be public. But ppport.h is using it to implement sv_len_utf8, so maybe you have to have it for that? |
Look at these two macros: __UNDEFINED__ newSVsv_flags(sv, flags) ((PL_Sv = newSV(0)), sv_setsv_flags(PL_Sv, (sv), (flags)), PL_Sv)
__UNDEFINED__ sv_mortalcopy_flags(sv, flags) sv_2mortal(newSVsv_flags((sv), (flags))) It means that it is not possible to call
But How to solve it? I have an idea about suboptimal implementation which will call other functions even when not needed, but I think it could provide correct result: __UNDEFINED__ sv_len_utf8_nomg(sv) sv_len_utf8(sv_mortalcopy_flags((sv), SV_NOSTEAL)) Any idea? Tests and comments are welcome. |
#218 should fix this. Feel free to comment and test |
Approved. |
I've found that the eval_pv implementation added in PPPort 3.54 does not work on compilers that don't support gcc-like statements within expressions. Without BRACE_GROUPS, that macro looks like
#define eval_pv(p, croak_on_error) ((PL_Sv = Perl_eval_pv(aTHX_ p, 0)), (croak_on_error && (SvROK(ERRSV) || SvTRUE(ERRSV)) && (croak_sv(ERRSV), 1)), PL_Sv)
but croak_sv expands to something involving STMT_START { ... } STMT_END, so kaboom.
Observed with perl 5.12.5 and Solaris 11.3's acomp, and also with perl 5.8.9 and a really hoary HPUX compiler. Things were fine before we updated to a late-model ppport.h ...
The text was updated successfully, but these errors were encountered: