-
-
Notifications
You must be signed in to change notification settings - Fork 8
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
n3329 - Transparent _Aliases #36
Comments
This is now the https://thephd.dev/_vendor/future_cxx/papers/C%20-%20Transparent%20Function%20Aliases.html |
Still not on twitter, but saw your wail about how undef's might break this proposal. It's likely I don't get all the nuances, but I was wondering: since |
The problem isn't the |
Yeah, that's what I meant by "rolling your own". I still think my point stands though - why not forbid redeclaration of an I'm sure that would receive some pushback from those who redeclared stdlib-stuff and never want to touch their pustulant codebases yet still get to upgrade their dependencies indefinitely. But there comes a point where someone needs to pay for the crimes of the past (it's also not like renaming the redeclared function would be that hard); and the good thing is that it'd be a smaller group than those that "just" don't want to touch their code (but haven't redeclared critical functions). |
Tabled for post-C23. |
N2901. |
Doesn't a static function pointer already let us do this? Sorry if this is answered somewhere, I just came here from your blog post and haven't had the time to read the proposal itself. Maybe this can serve as a nice FAQ entry for others with the same question though. Seems to me that even as far back as C89, we could portably indirect between ABI function name and C function name like this: int f(int x)
{
return x - 1;
}
static int (* g)(int x) = f;
int h(int x)
{
return g(x);
} When I compile this with a recent This seems to achieve the same goal as the proposed Of course, static function pointer becoming zero cost requires the compiler to implement a modest optimization - but I do realize that think "freedom for a bad implementation to needlessly store one pointer and indirect through it" is QoI wiggle room, which your blog post was strongly against, but it's just a tiny bit of performance wiggle room, not code behavior and ABI wiggle room, right? On the other hand, I can see how having an explicit new syntax would help educate developers on this pattern, and might be useful for tooling? Any other advantages I missed? (An "already answered in N2901" reply is fine, I'm happy to take the time to find it once I know it's in there.) |
There's one true problem with (static) function pointers, and it's that indirection does not work as intended. int f(int x)
{
return x - 1;
}
static int (* g)(int x) = f;
int h(int x)
{
return
f(x) // ok
+ (&f)(x)// ok
+ g(x) // ok
+ (&g)(x)// breaks
;
} This matters mostly for macro expansion and the like. That slight syntactic difference makes it painful enough to warrant a better front-end feature. The next iterations of the paper are also going to apply the concept to more than just functions: we are going to allow variables to be |
Ah. As an abuser of macros I do appreciate that edge case. Thank you! |
Wait, static no-op wrapper functions solve the indirection problem: int f(int x)
{
return x - 1;
}
static int g(int x)
{
return f(x);
}
int h(int x)
{
return
g(x) // ok
+ (&g)(x) // ok!
;
} Also would get optimized out to nothing on modern compilers in my experience. |
Yes, but that defeats the property that |
Oh, right, my bad, I should've noticed/remembered that as a goal. One more please: what's the downside with using a (not function-like) int f(int x)
{
return x - 1;
}
#define g f
int h(int x)
{
return g(x) + (&g)(x) + (g)(x);
} Off the top of my head I only see things that could be surmountable (tooling having difficulty with symbols that don't exist after the preprocessor is done with the code; developer aversion to using macros like that) or could be reasonably answered with "well don't do that!" (vulnerability to |
Ohhh I found it in the proposal:
Okay yeah I see it now. If we were writing a third party library this wouldn't matter because we could say "don't |
Why To me as a developer that seems like an extra arbitrary difference which I'd have to just memorize, but I suspect you've got great rationale for that equal sign being in the syntax as well? |
It's talked about in the proposal. I wrote it that way because it makes sense to me, but honestly it can be spelled any-which-way; I have 0 preference. |
Yeah I saw section 3.5 about syntax it just didn't seem to have anything about the equal sign vs no equal sign. Thank you for replies by the way! I really appreciate it! (Also, looking at the rest your blog and proposals, I really appreciate the careful and caring thought you put into improving C for all of us!) |
Actually, I want to challenge
If a macro wants an address of something which already decays to a pointer, then it is usually worse for clarity, readability, reasoning about what the code will do, and composability, if the macro internally slaps a
So I think it's worth adding into the consideration that maybe the language-level advantage of aliases over static function pointers of But maybe I'm missing good reasons to sometimes write macros that do P.S. Of course that's still not necessarily sufficient reason against this proposal, in fact you could use all this as a strong argument for alias - even if I'm right, developers would benefit from |
I gave more thought to I think it should be determined by how much, if at all, developers need to keep in mind the difference between aliases and regular variables. If developers can think of If there are situations where a developer might write the wrong code due to having the misconception that To illustrate the difference: You alias a function name from another library which is dynamically linked at runtime. You call that function once through an alias. Then other code in the same program unlinks/unloads one copy of that library, and links/loads another copy. You call through the function alias again. What happens? Probably undefined behavior, but:
As I understand it these aliases have to compile like the latter, right? If you generalize aliases to global variables, which was mentioned elsewhere as a possible future direction, this is even more apparent: normally, after And in fact, if I didn't know about this proposal and I saw it in code, if there's an equal sign, my first idea would be that So I think dropping the equal sign would also help clue in developers that it is not a normal assignment, not a normal variable, and doesn't behave quite like one. |
I've got not problem dropping the equals sign and using the typedef-like syntax! The typedef-like syntax was mostly because typedefs are part of declarators, so evolved out of that since |
An outsider's first impressions, for what it's worth:
Anyway all of that may be less important than the basic question: Is it OK to break the ABI if migration is possible? There'd be no trouble with libc, but I can still imagine situations where an old third-party DLL wreaks havoc with a new EXE with a different idea of what |
I don't think that's exactly right. Other libraries don't strictly need to avoid
I think this is less of an internal libc detail and more of an interface with the compiler which - only incidentally - a libc might need if it wants to decouple ABI compatibility and source-level compatibility. I also would like to see C have a bias towards minimizing how much functionality is only available to libc implementations which have the manpower and willingness to be coupled to non-standard compiler extensions. (We kinda had this problem in C99 with tgmath.h, before C11 standardized I also think basically all platforms and compilers currently have a way to alias identifiers like this, and (for example) glibc already uses that. So this is in many ways just taking a feature that implementations have already converged on anyway, and giving it a standard name/interface.
Hmm.. maybe we can talk through an example? I imagine it goes like this:
(Aside: a point in favor of making it
Notably, this is still a bad/messy/complected problem, but it doesn't get worse with dependencies-of-dependencies, so that's nice. By enabling old ABI-compatible identifiers to remain at their old names at all but source level, we turn the problem from an ABI break problem (which does ripple down through the dependencies as each dependency is rebuilt) into just a header-updating problem, and you no longer need to worry about anything that your code doesn't call directly. That's still not always realistically tractable, and I don't know if it will solve the |
Anything a libc can do, a normal user should be able to do. The less special magic soup implementations have to do things in C code and the more that is normally accessible to the plain user, the better. Furthermore, this is not just a libc problem. Literally every single implementation -- including proprietary ones like IBM -- that is represented in the Committee has one of these mechanisms. We are standardizing an existing practice to a long standing issue. We also know that this is a persistent issue because every implementation votes out improvements to libc on ABI grounds, despite every implementation currently attending the C and C++ Committee having a mechanism for this. Going by the letter of the standard, despite knowing every single implementation has had techniques to keep this from being a problem from anywhere from the last 20 to 40 years, is helpful. Finally, normal users deserve the ability to write better, backwards compatible libraries too. They also deserve the ability to implement new interfaces without stepping all over their existing users, if that's something they would like to support. |
Current version of the paper here: |
I added the latest version of the paper here, with revamped motivation and everything else: https://thephd.dev/_vendor/future_cxx/papers/C%20-%20Transparent%20Aliases.html (Will be on the WG14 Document log as N3329 sometime soonish.) |
The first paragraph of 4.7 (Variables) at https://thephd.dev/_vendor/future_cxx/papers/C%20-%20Transparent%20Aliases.html#design-variables currently ends abruptly:
A few paragraphs later has a double word:
The code sample has a typo "deprecatad". |
EDIT - Latest Draft: https://thephd.dev/_vendor/future_cxx/papers/C%20-%20Transparent%20Aliases.html
For C. The goal is to defend against ABI by allowing function renaming. Attributes on the renaming declarations can also provide an easy-out for weak symbols.
The text was updated successfully, but these errors were encountered: