-
Notifications
You must be signed in to change notification settings - Fork 36
Fixes for C23 #229
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
base: gcos4gnucobol-3.x
Are you sure you want to change the base?
Fixes for C23 #229
Conversation
|
In order to fix the last failing test, I was able to skip generating the "default" prototype when an actual prototype is provided in the COBOL source. However, the test fails later, when testing the >>IMP directive: since this may add function prototypes, they may clash with the ones inferred for static calls, and we have no way to detect that... |
GitMensch
left a comment
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'm unsure how the code in call.c should work, even more if we don't use the deprecated and in C2x forbidden variable arguments option.
It seems that the best option is to pass only the amount of arguments in a way we can query from the loaded program, with an exported symbol in the shared object... but even then we would need for example libffi (we could include the sources and statically link that per default as GCC does) to do a dynamic call [and if we don't get the number of arguments from the callee, we could use the argc).
... I feel a bit stuck here (still left some comments).
Thoughts?
| sclp->convention = convention; | ||
| sclp->return_type = return_type; | ||
| sclp->args = args; | ||
| sclp->next = static_call_cache; |
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.
Not checked, mostly wondering: Should the above code in the loop do anything with the args or other parameters? (an hour later) We should have all of that already done in the compiler when we build and compare the internal prototype - which should be what we use here.
Thinking of it... the internal prototype should have convention, return_type and arg list within a structure, maybe that exists and can be used here, maybe it should be added...
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.
@ddeclerck Can you check that, please?
If we can pass the prototype instead of its components "return type" + "args", we should do so.
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.
ping @ddeclerck - also for the other review comments and cobc/Changelog
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.
pong ;)
I wrote that a while ago and that seemed to make sense back then.
I'd need some time to dive back into this - but with the current failure on test 27, I don't even know how much this is going to change.
| } | ||
| if (static_call_cache) { | ||
| const char *convention_modifier; | ||
| FILE *savetarget = output_target; |
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.
Zhe code below uses output_local only and that goes to cb_local_file - What did I miss?
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.
Below we call output_function_arg_types, which may output either to the "local" file (when outputting function definitions) or to the "main" file (when outputing casts in actual code).
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.
Please add a comment on line 1898 that we switch that for the output_function_arg_types call.
| output_function_cast (struct cb_call *p, size_t ret_ptr, const char *convention, const char *name_str) | ||
| { | ||
| output_prefix (); | ||
| if (ret_ptr) { |
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.
ret_ptr should never have been a size_t, please fix that here and in the callers
| static void | ||
| output_function_cast (struct cb_call *p, size_t ret_ptr, const char *convention, const char *name_str) |
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 new (partially extracted) function should definitely get a good doxygen-style comment
libcob/call.c
Outdated
| #pragma warning(suppress: 4113) /* funcint is a generic function prototype */ | ||
| cancel_func = p->module->module_cancel.funcint; | ||
| #else |
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.
that pragma should go away and still work fine with the new code
libcob/call.c
Outdated
| (void)cancel_func (-1, NULL, NULL, NULL, | ||
| NULL); |
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 have no clue why the cancel_func is setup to have 4 NULL, especially if we have a program with no USING then the cancel_func has only a single parameter const int entry, no?
Telling C explicit how many arguments to handle and then ask it to handle too much seems to ask for trouble...
Well I'm missing the "big picture" about how GnuCOBOL handles calling in general, so I might not see the implications, but to me, I don't see much differences between:
So when we get to call a function whose prototype we don't know, let's just declare it with a dummy type, and cast it at call site according to the arguments that are passed (and in fact that's more or less what's done in this PR). But really, users should define proper prototypes... |
That would be the wrong approach. It should be called according to the prototype. Note that cobc deduces the prototype when it processes a program during compilation and if it cannot deduce anything by that, then it still can deduce an internal prototype by the actual CALL statement(s). Agreed that the The codegen part is something I need to inspect again (did so longer today) - maybe you can have a look how that aligns to the internal prototypes that are for example used in the compile-time checks? What does the |
Of course I was only suggesting this for those functions where we don't have any prototype nor we can not infer any.
Will do.
Codegen remains tricky, I'm really not confident about this code yet - and I still have one failing test. I need more time to dig into that.
It changes the single |
GitMensch
left a comment
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 may needs a rebase, but it definitely needs a Changelog update :-)
It would also be good to handle review comments.
| } | ||
| if (static_call_cache) { | ||
| const char *convention_modifier; | ||
| FILE *savetarget = output_target; |
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.
Please add a comment on line 1898 that we switch that for the output_function_arg_types call.
| sclp->convention = convention; | ||
| sclp->return_type = return_type; | ||
| sclp->args = args; | ||
| sclp->next = static_call_cache; |
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.
@ddeclerck Can you check that, please?
If we can pass the prototype instead of its components "return type" + "args", we should do so.
| static void | ||
| output_function_arg_types (cb_tree args) | ||
| { | ||
| cb_tree x; |
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.
new function, so please add a doxygen-style comment here as well
|
All parts but cobc were adjusted upstream and that seems to build fine with gcc-15 now - but fails a bunch of internal checks, which will likely be solved by the changes here; please rebase. Note: I'm not sure that casting the funcint in cob_call_field to all possible argument numbers is really a good idea... I guess it may "crash harder" in the case that the function does not take any arguments than specifying none explicit... on some architectures. |
|
@ddeclerck Thanks for finishing that! |
5fa94b8 to
3b7bba2
Compare
|
Of course, now that I rebased, test 27 fails. Seems there's a clash between the generated declaration and the one provided through the Note sure what to do here: is it the responsability of the user to provide prototypes compatible with the generated ones ? Should we give him an option to disable the generated prototypes (so he'd have to provide a prototype for each function) ? Something else ? |
If the user provides a prototype, then it should be "correct". |
I had completely forgotten about the Still have to tackle the other comments. |
This PR attempts to fix GnuCOBOL for C23, by adding appropriate function type casts, both in libcob and codegen.
There's still one test failing, due to multiple definition of the same function prototype (I guess this was working before C23 because the first prototype was incomplete ; now it includes all the arguments). Investigation led me to line 1908 in
codegen.c:output_call_cache:Apparently the intent was to use an
#ifndefto prevent multiple definition of the same symbol... yet preprocessor directives may not be used to test whether a function is defined...