Re: [gcc15] nested functions in C
On 2023-12-07 10:42, Eric Botcazou wrote: I think from a language standpoint, the general idea that nested functions are just any functions inside functions (which is how the C nested functions essentially behave) is too broad and they should be restricted to minimal implementations that, e.g. don't have side-effects or if they do, there's explicit syntactic sugar to make it clearer. That sounds totally arbitrary though. Algol-derived languages have had nested subprograms for ages, e.g. Pascal or Ada, and they can be very useful. I'll admit that it is a subjective preference and is probably not in the spirit of traditional C. Sid
Re: [gcc15] nested functions in C
> I think from a language standpoint, the general idea that nested > functions are just any functions inside functions (which is how the C > nested functions essentially behave) is too broad and they should be > restricted to minimal implementations that, e.g. don't have side-effects > or if they do, there's explicit syntactic sugar to make it clearer. That sounds totally arbitrary though. Algol-derived languages have had nested subprograms for ages, e.g. Pascal or Ada, and they can be very useful. -- Eric Botcazou
Re: [gcc15] nested functions in C
On Tue, Dec 5, 2023 at 10:16 PM Martin Uecker wrote: > > Am Dienstag, dem 05.12.2023 um 21:08 + schrieb Joseph Myers: > > On Mon, 4 Dec 2023, Martin Uecker wrote: > > > > > > The key feature of lambdas (which failed to make it into C23) for this > > > > purpose is that you can't convert them to function pointers, which > > > > eliminates any need for trampolines. > > > > > > And also makes them useful only for template-like macro programming, > > > but not much else. So my understanding was that this needs to be > > > addressed at some point. > > > > Where "addressed" probably means some kind of callable object that stores > > more than just a function pointer in order to be able to encapsulate both > > the code address of a lambda and the context it needs to receive > > implicitly. So still not needing trampolines. > > Yes, a wide function pointer type similar to C++'s std::function. > > This would also be a way to eliminate the need for trampolines > for GCC's nested function. And conversion to ordinary function pointer types would be still possible by using (on heap) trampolines then and would offer backward compatibility. I wonder how much implementation work would it be to add the wide function pointer types (please hide details in the C frontend). Richard. > Martin > > >
Re: [gcc15] nested functions in C
Am Dienstag, dem 05.12.2023 um 21:08 + schrieb Joseph Myers: > On Mon, 4 Dec 2023, Martin Uecker wrote: > > > > The key feature of lambdas (which failed to make it into C23) for this > > > purpose is that you can't convert them to function pointers, which > > > eliminates any need for trampolines. > > > > And also makes them useful only for template-like macro programming, > > but not much else. So my understanding was that this needs to be > > addressed at some point. > > Where "addressed" probably means some kind of callable object that stores > more than just a function pointer in order to be able to encapsulate both > the code address of a lambda and the context it needs to receive > implicitly. So still not needing trampolines. Yes, a wide function pointer type similar to C++'s std::function. This would also be a way to eliminate the need for trampolines for GCC's nested function. Martin >
Re: [gcc15] nested functions in C
On Mon, 4 Dec 2023, Martin Uecker wrote: > > The key feature of lambdas (which failed to make it into C23) for this > > purpose is that you can't convert them to function pointers, which > > eliminates any need for trampolines. > > And also makes them useful only for template-like macro programming, > but not much else. So my understanding was that this needs to be > addressed at some point. Where "addressed" probably means some kind of callable object that stores more than just a function pointer in order to be able to encapsulate both the code address of a lambda and the context it needs to receive implicitly. So still not needing trampolines. -- Joseph S. Myers jos...@codesourcery.com
Re: [gcc15] nested functions in C
On 2023-12-04 16:31, Martin Uecker wrote: If (assuming from them being called lambdas) they are primarily for small functions without side-effects then it's already a significantly stronger specification than what we have right now with C nested functions. That would end up enforcing what you demonstrate as the good way to use nested functions. The proposal we have seen for C23 (which was not accepted into C23 mostly due to timing and lack of implementation experience) were similar to C++'s lambdas and did not have any such restriction. Oh well :/ If nested functions are eventually going to make it into the C standard then effort is probably better spent in porting the C nested functions to use descriptors instead of executable stacks or heaps. I submitted a patch for this a long time ago which was based on the code for Ada that uses a bit in the pointer to differentiate between conventional pointers and descriptors. I would now prefer an approach that uses a qualifier on the function type to indicate that the static chain has to be set. A pointer to such a qualified function would a descriptor that consists of the address and the value for the static chain. This would be useful for many things. Ack, this probably becomes a gcc15 thing then, given that stage 1 has closed. Are you planning to revive your work and repost? Thanks, Sid
Re: [gcc15] nested functions in C
Am Montag, dem 04.12.2023 um 19:51 +0100 schrieb Jakub Jelinek: > On Mon, Dec 04, 2023 at 01:27:32PM -0500, Siddhesh Poyarekar wrote: > > [Branching this into a separate conversation to avoid derailing the patch, > > which isn't directly related] > > > > On 2023-12-04 12:21, Martin Uecker wrote: > > > I do not really agree with that. Nested functions can substantially > > > improve code quality and in C can avoid type unsafe use of > > > void* pointers in callbacks. The code is often much better with > > > nested functions than without. Nested functions and lambdas > > > (i.e. anonymous nested functions) are used in many languages > > > because they make code better and GNU's nested function are no > > > exception. > > > > > > So I disagree with the idea that discouraging nested functions leads > > > to better code - I think the exact opposite is true. > > > > I would argue that GNU's nested functions *are* an exception because they're > > like feathers stuck on a pig to try and make it fly; I think a significant > > specification effort is required to actually make it a cleanly usable > > feature. > > Why? The syntax doesn't seem to be something unexpected, and as C doesn't > have lambdas, one can use the nested functions instead. > The only problem is if you need to pass function pointers somewhere else > (and target doesn't have function descriptors or something similar), if it > is only done to make code more readable compared to say use of macros, I > think the nested functions are better, one doesn't have to worry about > multiple evaluations of argument side-effects etc. And if everything is > inlined and SRA optimized, there is no extra cost. > The problem of passing it as a function pointer to other functions is > common with C++, only lambdas which don't capture anything actually can be > convertible to function pointer, for anything else you need a template and > instantiate it for a particular lambda (which is something you can't do in > C). In C++ you can erase the type with std::function. C is missing a function pointer type which can encapsulate the static chain on all archs (not only for nested functions, also for language interoperability). Martin >
Re: [gcc15] nested functions in C
Am Montag, dem 04.12.2023 um 15:35 -0500 schrieb Siddhesh Poyarekar: > On 2023-12-04 13:48, Martin Uecker wrote: > > > I empathize with Jakub's stated use case though of keeping the C > > > frontend support for testing purposes, but that could easily be done > > > behind a flag, or by putting nested C func deprecation behind a flag. > > > > I am relatively sure C will get some form of nested functions. > > Maybe as anonymous nested functions, i.e. lambdas, but I do > > not see a fundamental difference here (I personally like naming > > things for clarity, so i prefer named nested functions) > > If (assuming from them being called lambdas) they are primarily for > small functions without side-effects then it's already a significantly > stronger specification than what we have right now with C nested > functions. That would end up enforcing what you demonstrate as the good > way to use nested functions. The proposal we have seen for C23 (which was not accepted into C23 mostly due to timing and lack of implementation experience) were similar to C++'s lambdas and did not have any such restriction. > > I suppose minimal, contained side-effects (such as atomically updating a > structure) may also constitute sound design, but that should be made > explicit in the language. Updating some variable is useful for example for contractions, e.g. summing over a certain range of values in an array, etc. > > > > I don't disagree for cases like -Warray-bounds, > > > but for warnings/errors that are more deterministic in nature (like > > > -Werror=trampolines), they're going to point at actual problems and > > > larger projects and distributions will usually prefer to at least track > > > them, if not actually fix them. For Fedora we tend to provide macro > > > overrides for packages that need to explicitly disable a security > > > related flag. > > > > In projects such as mine, this will lead to a lot of code > > transformations as indicated above, i.e. much worse code. > > > > One could get away with it, since nested functions are rarely > > used, but I think this is bad, because a lot of code would > > improve if it used them. > > If nested functions are eventually going to make it into the C standard > then effort is probably better spent in porting the C nested functions > to use descriptors instead of executable stacks or heaps. I submitted a patch for this a long time ago which was based on the code for Ada that uses a bit in the pointer to differentiate between conventional pointers and descriptors. I would now prefer an approach that uses a qualifier on the function type to indicate that the static chain has to be set. A pointer to such a qualified function would a descriptor that consists of the address and the value for the static chain. This would be useful for many things. Martin
Re: [gcc15] nested functions in C
On Mon, 4 Dec 2023, Siddhesh Poyarekar wrote: > On 2023-12-04 13:48, Martin Uecker wrote: > > > I empathize with Jakub's stated use case though of keeping the C > > > frontend support for testing purposes, but that could easily be done > > > behind a flag, or by putting nested C func deprecation behind a flag. > > > > I am relatively sure C will get some form of nested functions. > > Maybe as anonymous nested functions, i.e. lambdas, but I do > > not see a fundamental difference here (I personally like naming > > things for clarity, so i prefer named nested functions) > > If (assuming from them being called lambdas) they are primarily for small > functions without side-effects then it's already a significantly stronger > specification than what we have right now with C nested functions. That would > end up enforcing what you demonstrate as the good way to use nested functions. The key feature of lambdas (which failed to make it into C23) for this purpose is that you can't convert them to function pointers, which eliminates any need for trampolines. -- Joseph S. Myers jos...@codesourcery.com
Re: [gcc15] nested functions in C
Am Montag, dem 04.12.2023 um 21:33 + schrieb Joseph Myers: > On Mon, 4 Dec 2023, Siddhesh Poyarekar wrote: > > > On 2023-12-04 13:48, Martin Uecker wrote: > > > > I empathize with Jakub's stated use case though of keeping the C > > > > frontend support for testing purposes, but that could easily be done > > > > behind a flag, or by putting nested C func deprecation behind a flag. > > > > > > I am relatively sure C will get some form of nested functions. > > > Maybe as anonymous nested functions, i.e. lambdas, but I do > > > not see a fundamental difference here (I personally like naming > > > things for clarity, so i prefer named nested functions) > > > > If (assuming from them being called lambdas) they are primarily for small > > functions without side-effects then it's already a significantly stronger > > specification than what we have right now with C nested functions. That > > would > > end up enforcing what you demonstrate as the good way to use nested > > functions. > > The key feature of lambdas (which failed to make it into C23) for this > purpose is that you can't convert them to function pointers, which > eliminates any need for trampolines. And also makes them useful only for template-like macro programming, but not much else. So my understanding was that this needs to be addressed at some point. Martin >
Re: [gcc15] nested functions in C
On 2023-12-04 13:51, Jakub Jelinek wrote: Why? The syntax doesn't seem to be something unexpected, and as C doesn't have lambdas, one can use the nested functions instead. The only problem is if you need to pass function pointers somewhere else (and target doesn't have function descriptors or something similar), if it is only done to make code more readable compared to say use of macros, I think the nested functions are better, one doesn't have to worry about multiple evaluations of argument side-effects etc. And if everything is inlined and SRA optimized, there is no extra cost. The problem of passing it as a function pointer to other functions is common with C++, only lambdas which don't capture anything actually can be convertible to function pointer, for anything else you need a template and instantiate it for a particular lambda (which is something you can't do in C). I think from a language standpoint, the general idea that nested functions are just any functions inside functions (which is how the C nested functions essentially behave) is too broad and they should be restricted to minimal implementations that, e.g. don't have side-effects or if they do, there's explicit syntactic sugar to make it clearer. If (like Martin stated earlier), nested functions are in fact going to enter the C standard in future then maybe this discussion is moot and we probably are better off implementing descriptor support for C to replace the on-stack trampolines instead of adding -Werror=trampolines in a hurry. Thanks, Sid
Re: [gcc15] nested functions in C
On 2023-12-04 13:48, Martin Uecker wrote: I empathize with Jakub's stated use case though of keeping the C frontend support for testing purposes, but that could easily be done behind a flag, or by putting nested C func deprecation behind a flag. I am relatively sure C will get some form of nested functions. Maybe as anonymous nested functions, i.e. lambdas, but I do not see a fundamental difference here (I personally like naming things for clarity, so i prefer named nested functions) If (assuming from them being called lambdas) they are primarily for small functions without side-effects then it's already a significantly stronger specification than what we have right now with C nested functions. That would end up enforcing what you demonstrate as the good way to use nested functions. I suppose minimal, contained side-effects (such as atomically updating a structure) may also constitute sound design, but that should be made explicit in the language. I don't disagree for cases like -Warray-bounds, but for warnings/errors that are more deterministic in nature (like -Werror=trampolines), they're going to point at actual problems and larger projects and distributions will usually prefer to at least track them, if not actually fix them. For Fedora we tend to provide macro overrides for packages that need to explicitly disable a security related flag. In projects such as mine, this will lead to a lot of code transformations as indicated above, i.e. much worse code. One could get away with it, since nested functions are rarely used, but I think this is bad, because a lot of code would improve if it used them. If nested functions are eventually going to make it into the C standard then effort is probably better spent in porting the C nested functions to use descriptors instead of executable stacks or heaps. Thanks, Sid
Re: [gcc15] nested functions in C
On Mon, Dec 04, 2023 at 01:27:32PM -0500, Siddhesh Poyarekar wrote: > [Branching this into a separate conversation to avoid derailing the patch, > which isn't directly related] > > On 2023-12-04 12:21, Martin Uecker wrote: > > I do not really agree with that. Nested functions can substantially > > improve code quality and in C can avoid type unsafe use of > > void* pointers in callbacks. The code is often much better with > > nested functions than without. Nested functions and lambdas > > (i.e. anonymous nested functions) are used in many languages > > because they make code better and GNU's nested function are no > > exception. > > > > So I disagree with the idea that discouraging nested functions leads > > to better code - I think the exact opposite is true. > > I would argue that GNU's nested functions *are* an exception because they're > like feathers stuck on a pig to try and make it fly; I think a significant > specification effort is required to actually make it a cleanly usable > feature. Why? The syntax doesn't seem to be something unexpected, and as C doesn't have lambdas, one can use the nested functions instead. The only problem is if you need to pass function pointers somewhere else (and target doesn't have function descriptors or something similar), if it is only done to make code more readable compared to say use of macros, I think the nested functions are better, one doesn't have to worry about multiple evaluations of argument side-effects etc. And if everything is inlined and SRA optimized, there is no extra cost. The problem of passing it as a function pointer to other functions is common with C++, only lambdas which don't capture anything actually can be convertible to function pointer, for anything else you need a template and instantiate it for a particular lambda (which is something you can't do in C). Jakub
Re: [gcc15] nested functions in C
Am Montag, dem 04.12.2023 um 13:27 -0500 schrieb Siddhesh Poyarekar: > [Branching this into a separate conversation to avoid derailing the > patch, which isn't directly related] > > On 2023-12-04 12:21, Martin Uecker wrote: > > I do not really agree with that. Nested functions can substantially > > improve code quality and in C can avoid type unsafe use of > > void* pointers in callbacks. The code is often much better with > > nested functions than without. Nested functions and lambdas > > (i.e. anonymous nested functions) are used in many languages > > because they make code better and GNU's nested function are no > > exception. > > > > So I disagree with the idea that discouraging nested functions leads > > to better code - I think the exact opposite is true. > > I would argue that GNU's nested functions *are* an exception because > they're like feathers stuck on a pig to try and make it fly; I think a > significant specification effort is required to actually make it a > cleanly usable feature. It *may* be possible to implement patterns that > use C nested functions well enough *and* result in readable code, but > IMO it is easier to write clunky and unmaintainable code with it. I use them in my code a lot and I think they improve code quality. For example: int foo_find(int N, struct foo in_array[N], const char* *key) { bool cond(struct foo* x) { return 0 == strcmp(x->name, key); } return find(N, in_array, cond); } is a lot cleaner and safer than what you need to write without nested functions: struct foo_find { const char* name; }; int foo_cond(void *vdata, struct foo* a) { struct foo *key = data; return 0 == strcmp(x->name, key->name); } void foo_sort(int N, struct foo in_array[N], const char* key) { struct foo_find data = { key }; sort(N, in_array, foo_cond, ); } and this is a toy example, the improvement gets more substantial with more complicated logic. > > I empathize with Jakub's stated use case though of keeping the C > frontend support for testing purposes, but that could easily be done > behind a flag, or by putting nested C func deprecation behind a flag. I am relatively sure C will get some form of nested functions. Maybe as anonymous nested functions, i.e. lambdas, but I do not see a fundamental difference here (I personally like naming things for clarity, so i prefer named nested functions) > > I am generally wary of mitigations that may make exploitation of > > buffer overflows a bit harder while increasing the likelihood > > of buffer overflows by reducing type safety and/or code quality. > > > > But I would agree that trampolines are generally problematic. A > > better strategy would be wide function pointer type (as in Apple' > > Blocks extension). Alternatively, an explicit way to obtain the > > static chain for a nested function which could be used with > > __builtin_call_with_static_chain could also work. > > > > But in any case, I think it diminishes the value of -fhardening > > it if requires source code changes, because then it is not as easy > > to simply turn it on in larger projects / distributitions. > > I suppose you mean source code changes even in correct code just to > comply with the flag? Yes > I don't disagree for cases like -Warray-bounds, > but for warnings/errors that are more deterministic in nature (like > -Werror=trampolines), they're going to point at actual problems and > larger projects and distributions will usually prefer to at least track > them, if not actually fix them. For Fedora we tend to provide macro > overrides for packages that need to explicitly disable a security > related flag. In projects such as mine, this will lead to a lot of code transformations as indicated above, i.e. much worse code. One could get away with it, since nested functions are rarely used, but I think this is bad, because a lot of code would improve if it used them. Martin > > Thanks, > Sid