[HN Gopher] Checked C ___________________________________________________________________ Checked C Author : soheilpro Score : 134 points Date : 2022-12-21 18:29 UTC (4 hours ago) (HTM) web link (github.com) (TXT) w3m dump (github.com) | kelnos wrote: | Thinking about this at a higher level, the real problem is that | we use C arrays at all. But we can't stop using C arrays, because | libc and a huge body of other C libraries out there represent | lists of data using C arrays. | | As a useful counterexample, glib has GArray, GPtrArray, and | GList, along with functions that you use to manipulate the lists. | Those functions are presumably implemented correctly, and will | prevent you from making out-of-bounds accesses. | | But of course those things are not widely adopted, because | they're not standardized, they're not in libc, and libc has not | been reimagined such that all of its APIs take and return these | safer list primitives instead of bare C arrays. | | (And sure, GArray etc. are not necessarily suitable everywhere, | as they require heap allocations. But I could imagine a safe | abstraction that could allow for using stack or static | allocations to back it.) | | So I see something like Checked C as a band-aid, when the | language and stdlib just needs a complete overhaul. Obviously | that's incredibly unlikely to ever happen, so something like | Checked C is a decent compromise, I guess. | sramsay wrote: | > As a useful counterexample, glib has GArray, GPtrArray, and | GList, along with functions that you use to manipulate the | lists. Those functions are presumably implemented correctly, | and will prevent you from making out-of-bounds accesses. | | > But of course those things are not widely adopted, because | they're not standardized, they're not in libc, and libc has not | been reimagined such that all of its APIs take and return these | safer list primitives instead of bare C arrays. | | I'm really not sure why the second thing is regarded by C | programmers as such an insuperable barrier to the first thing. | | I absolutely understand that there are circumstances where | extreme portability is a major requirement. That, and C's | ability to operate in highly constrained environments are among | its most laudable features. | | But many of us (including me) write user-facing C applications | that have neither requirement and where Glib is either already | installed or easy to install. Why not just go ahead and use it? | If you're trying to get it to run on a tiny embedded system or | in some land without Glib . . . well, this isn't the program | for you! | | I feel like this is more of a weird cultural prejudice than a | technical matter. People run programs in JavaScript (or | Haskell, or Python) with _hundreds_ of dependencies, and while | some find that annoying, I don 't hear people in these | communities objecting to _idea_ of dependencies the way people | do with C. | | Could the standard library be better? Of course. But there's | something to be said for not including a lot of batteries in | the _standard_ and just using the third-party tools that are | available. | emmanueloga_ wrote: | Does anybody know how does this compare to https://compcert.org/ | ? | ryao wrote: | It does not. One is a language extension that claims to prevent | certain classes of issues. The other is a C compiler that | claims to do nothing to prevent those classes of issues. The | two are not comparable at all. | | You would be better off comparing it to Astree, which is a | static analyzer written by the group that wrote the Compcert C | compiler. | | https://www.absint.com/astree/index.htm | | Astree claims to be able to prove the absence of use-after- | free, which the checked C documentation says that checked C | does not prevent. | | You would need to check to see if Astree can prove the absence | of all of the issues that checked C is intended to prevent, but | at a glance that seems possible. In theory, Astree can be used | to fix all of them by doing fixes until it stops complaining. | belter wrote: | "A Formal Model of Checked C" - | https://news.ycombinator.com/item?id=30321535 - 37 comments - 10 | months ago | | "Checked C" - https://news.ycombinator.com/item?id=26190403 - 133 | comments - 2021 | | "Refactoring the FreeBSD Kernel with Checked C" - | https://news.ycombinator.com/item?id=25989115 - 41 comments - | 2021 | | "Achieving Safety Incrementally with Checked C" - | https://news.ycombinator.com/item?id=19424106 - 21 comments - | 2019 | | "Checked C: Making C Safer by Extension" - | https://news.ycombinator.com/item?id=17939537 - 55 comments - | 2018 | | "Checked C: extension to C that adds static and dynamic checking" | - https://news.ycombinator.com/item?id=16588483 - 92 comments - | 2018 | | "Checked C" - https://news.ycombinator.com/item?id=11899925 - 156 | comments - 2016 | dang wrote: | Thanks! Added a few: | | _C to Checked C by 3C_ - | https://news.ycombinator.com/item?id=30857289 - March 2022 (1 | comment) | | _A Formal Model of Checked C_ - | https://news.ycombinator.com/item?id=30321535 - Feb 2022 (37 | comments) | | _Why Checked C when there was Verona?_ - | https://news.ycombinator.com/item?id=26499846 - March 2021 (2 | comments) | | _Checked C_ - https://news.ycombinator.com/item?id=26190403 - | Feb 2021 (133 comments) | | _Refactoring the FreeBSD Kernel with Checked C [pdf]_ - | https://news.ycombinator.com/item?id=25989115 - Feb 2021 (41 | comments) | | _Refactoring the FreeBSD Kernel with Checked C [pdf]_ - | https://news.ycombinator.com/item?id=24019185 - Aug 2020 (13 | comments) | | _Achieving Safety Incrementally with Checked C_ - | https://news.ycombinator.com/item?id=19424106 - March 2019 (21 | comments) | | _Checked C: Making C Safer by Extension_ - | https://news.ycombinator.com/item?id=17939537 - Sept 2018 (55 | comments) | | _Checked C: extension to C that adds static and dynamic | checking_ - https://news.ycombinator.com/item?id=16588483 - | March 2018 (92 comments) | | _Checked C_ - https://news.ycombinator.com/item?id=12049548 - | July 2016 (3 comments) | | _Checked C - A Safer C /C++ from Microsoft_ - | https://news.ycombinator.com/item?id=11936418 - June 2016 (3 | comments) | | _Checked C_ - https://news.ycombinator.com/item?id=11899925 - | June 2016 (156 comments) | WalterBright wrote: | Checked C: int a[5] = { 0, 1, 2, 3, 4}; | _Array_ptr<int> p : count(5) = a; // p points to 5 elements. | | My proposal for C: int a[5] = { 0, 1, 2, 3, 4}; | int p[..] = a; // p points to 5 elements. | | https://www.digitalmars.com/articles/C-biggest-mistake.html | | https://github.com/Microsoft/checkedc/wiki/New-pointer-and-a... | elcritch wrote: | I like your version, but how do you annotate the size from | existing things like "main(int *argv, argc)" to know that the | size is argc? | wahern wrote: | There was a proposal during the C23 process to make "main(int | argc, char *argv[argc])" work as one would expect, as well as | some similar changes elsewhere, such as with structure | members. They went through several revisions but never made | the cut, I think partially because they all required at least | some minimal backward incompatibility. | | IMO, if GCC or clang implemented and ran with those proposed | changes, they'd probably be accepted for the next C revision, | and become popular long before then. This is mostly a matter | of time and motivation; corporate funded developer time seems | to be mostly focused on half measures; e.g. type attributes, | rather than fundamentally improving pointer and array | semantics. But if someone put in enough time and effort, | including going through the rigmarole of integration into | mainline, this could happen. | kelnos wrote: | You just... annotate it? Like, I don't see what the issue is. | You just write int main(int argc, char | **argv : count(argc)) {} | | If you're already creating an extension for C, then it's fine | to "change" its signature in this way. Or am I | misunderstanding your objection? | | Sure, the compiler can't verify that argv does indeed have | argc elements, but hopefully we can rely on the kernel and C | runtime to populate things properly. If not, I would say it | doesn't matter that the compiler can't help you here; your | system is screwed beyond repair already. | | At the very least, the compiler _can_ emit bounds checking to | ensure that you don 't try to access past argc elements in | that array, which is still valuable. | | Edit: it occurs to me that you were talking about | WalterBright's version, not the version in Checked C. But I | think my comment still applies: if you're changing how things | work, then you just keep changing how things work to cover | cases like this. | WalterBright wrote: | Create an adapter: int main(int argc, char | **argv) { return myMain(argv[0 .. argc]); } | | Strings can be done like this: char [..] s | = p[0 .. strlen(p)]; | elcritch wrote: | Hmmm, the "[..]" is a fat pointer right? Couldn't you just | say: int main(char [..] args) | | Maybe with some way to tell the compiler the correct | parameter order if needed? Perhaps: int | main(char [..argc] argv) | | I'm curious if ELF and other formats have enough info to | figure that mapping out? | WalterBright wrote: | > the "[..]" is a fat pointer right? | | yes | | > if ELF and other formats have enough info to figure | that mapping out? | | No, as there is no semantic connection between `argc` and | `argv`. | tomcam wrote: | Elegant, but of course it would be. It's like you're a trained | professional or something ;) | WalterBright wrote: | not my first rodeo! ABEL was the first language I designed | (for Data I/O) back in the 80s. | | ABEL = "Advanced Boolean Expression Language", a language for | programming PLDs (Programmable Logic Devices) which was a | core business for Data I/O. | bachmeier wrote: | There's no substitute for decades of having programmers | giving you (and shouting at you) blunt feedback on your | programming language proposals. | WalterBright wrote: | Here's the timeline: | | 1. who would do such a dumb feature | | 2. what, are you insane? | | 3. it becomes obvious | | 4. other languages adopt it | gavinray wrote: | You might show an example of how to use D's templates (if it's | possible) to emulate the more complex example of computing the | bounds from an input argument char | *strncpy(char * restrict dest : count(n), | const char * restrict src : count(n), size_t | n) : bounds(dest, (_Array_ptr<char>)dest + n); | WalterBright wrote: | https://news.ycombinator.com/item?id=34085835 | gavinray wrote: | I meant something more like this (although this doesn't | QUITE compile, but it's close I think): | static ubyte* [n*2] requires_ptr_twice_as_large_as_input(n | : uint) ( ubyte*[n] input, | ubyte*[n*2] output, ) { output[0..n] = | input[0..n]; output[n..2*n] = input[0..n]; | return output; } void main() { | ubyte[10] input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; | ubyte[20] output = new ubyte[20]; | requires_ptr_twice_as_large_as_input!(10)(&input, &output); | } | KingLancelot wrote: | Fat pointers are a good idea, but I think it'd be a better idea | to store the start and evd pointers instead of a pointer to the | first element and a size_t. | 1980phipsi wrote: | Why? | masklinn wrote: | I'd guess it's because that's what C++ does. Though it's | unclear to me that C++-style iteration (where you increment | a running pointer until you reach an EOI pointer) is much | used in C. | WalterBright wrote: | Storing two pointers into the same array is a memory | safety problem. It's hard to implement a borrow checker | when there are two live mutable pointers into the same | memory object. | sirwhinesalot wrote: | It's a shame this will never get through the insane bureaucracy | that is the C standards committee. Had they listened to you all | the way back in 2009, C11 might have been a game changer the | same way C++11 was. Alas. | | At least there's BetterC ;) | WalterBright wrote: | This proposal could very well save C, as array bounds | overflows are consistently the #1 cause of corruption bugs in | shipped C software. | ryao wrote: | In theory, sound static analyzers could be another method | by which this is achieved in existing projects. They claim | to be able to catch all instances of this. Some examples of | sound static analyzers include: | | https://www.absint.com/astree/index.htm | | https://github.com/NASA-SW-VnV/ikos | | https://github.com/static-analysis-engineering/CodeHawk-C | | I have planned to try using them on OpenZFS for a while, | but I am still busy reviewing and fixing reports made by | conventional static analyzers. I plan to look into these | next. | | That said, at least one of them claims to be able to prove | the absence of issues in C that checked C's documentation | explicitly says it cannot prevent. The obvious one is use- | after-free. | WalterBright wrote: | I don't know how a static analyzer could do this: | size_t i = some_function(); // gets return value from | environment array[i] = 3; | roywiggins wrote: | If it's sound it will point out that there's a potential | for an error if it can't prove otherwise. To silence the | error you'd have to manually put a check in. | ryao wrote: | A sound static analyzer in theory can check the safety of | that by examining all code paths and complain whenever | any exist where it is possible to go out of bounds. It is | called sound because the absence of a complaint means it | has proven the absence of the issues it is meant to | catch. | jeffybefffy519 wrote: | It doesnt need to get through any committees to have impact. | Microsoft just has to use it (which i assume they are given | they are the authors) and then its had impact. | adastra22 wrote: | I don't think the comment you are replying to is talking | about MSFT's Checked C? | ryao wrote: | Do they still refuse to update their compiler to support | any version of C beyond C89? | | Unless they have changed course, it seems more likely that | Microsoft will drop NT for a UNIX kernel than Microsoft | would put this into their compiler. I assume that this is | by Microsoft Research and work by Microsoft Research is | almost never used by Microsoft. The only exception I know | is Drawbridge, which they reportedly used in Azure. | my123 wrote: | SQL Server on Linux runs on Drawbridge, with NTUM and | all. | ryao wrote: | > It's a shame this will never get through the insane | bureaucracy that is the C standards committee. Had they | listened to you all the way back in 2009, C11 might have been | a game changer the same way C++11 was. Alas. | | This comment did not age well: | | https://news.ycombinator.com/item?id=34086304 | | A quick test with `clang -std=c89 -pedantic` says it was in | C99. Amazingly, it seems that almost nobody knew about it. | sirwhinesalot wrote: | Not the same thing at all, that only works with compile- | time known sizes. | WalterBright wrote: | Pascal arrays were fixed at compile time, which I quickly | discovered made Pascal rather useless without extensions. | ryao wrote: | The example was for compile-time known sizes. | Xeoncross wrote: | Yes, needing a fixed-sized array seems like a fairly common | need to me. a := [5]int32{0, 1, 2, 3, 4} // | Go let mut array: [i32; 5] = [0, 1, 2, 3, 4]; // | Rust | masklinn wrote: | C has fixed-size arrays. | | The problem is that it doesn't use them much, and gets rid of | them as soon as possible: int a[5] = {1, 2, | 3, 4, 5, 6}; printf("%d\n", a[8]); | | in clang, this warns, by default, on both misuse sites | "excess elements in array initializer" and "array index is | past the end of the array". Which is good. | | However things go downhill as soon as you pass the arrays | downstack: #include <stdio.h> | static void foo(int *a) { printf("%d\n", a[8]); | } static void bar(int a[]){ | printf("%d\n", a[8]); } static void qux(int | a[6]){ printf("%d\n", a[8]); } | int main() { int a[5] = {1, 2, 3, 4, 5}; | foo(a); bar(a); qux(a); } | | no warning anywhere, even under "-Wall -Weverything". | [deleted] | klodolph wrote: | Yeah, so the syntax is a bit funny but you can actually get | the bounds checking you want here: #include | <stdio.h> static void qux(int a[static 6]){ | printf("%d\n", a[8]); } int main() { | int a[5] = {1, 2, 3, 4, 5}; qux(a); } | | I get, test.c:9:5: warning: array argument | is too small; contains 5 elements, callee requires at least | 6 [-Warray-bounds] | | I did not enable any warning flags at all, this is just | default Clang on a Mac. | | If you want to catch the a[8] inside the function you need | something else. | ryao wrote: | It appears that Clang will warn even without this syntax | while GCC does not warn unless it has this syntax. At | least, it did when I dropped the `static 6` from the | example. | Jasper_ wrote: | Unfortunately, `int a[static 3][static 4]` does not work. | klodolph wrote: | That's because you'd write it as: int | a[static 3][4] | | You only need to put static on the outermost type, the | one that decays into a pointer. Same thing applies if you | need restrict: int a[static restrict | 3][4] | | which is ugly but gets the job done. Think of int | a[3][4], when used as a function parameter, as "pointer | to int[4]" (the 3 disappears completely), and think of | int a[static 3][4] as "pointer to first of at least 3 | int[4]". | | (Not trying to defend C here, just explaining how C | works.) | WalterBright wrote: | The explicit "6" is a problem if you aren't using fixed | size arrays. | klodolph wrote: | Yes, this was in direct response to someone talking about | fixed-size arrays. Think of this as just "one small way | in which C does not happen to be broken" rather than some | kind of endorsement of C! | | Note that you could static void qux(int | n, int a[n]) | | but this changes the interface somewhat and there are | lots of reasons why you might want to avoid VLAs in C. | WalterBright wrote: | The problem with that syntax is you have to repeat it | every time `a` is forwarded to another function. The | array data and length need to be combined into a single | semantic entity. | klodolph wrote: | Yes, but I don't think a deeper discussion about the | flaws of array handling C is really going to illuminate | anything here. The conclusions generally go in one of | three ways--either you choose to use a different | language, choose to deal with C (with tools like static | analyzers or instrumentation), or choose to make | proposals to the C committee. | | Proper array types are not present in C and they're | unlikely to be added at any point in the future, so if | the conversation is "the array data and length need to be | combined into a single semantic entity", then the | conversation is no longer about C, but the starting point | for choosing another language. | | The int a[static 6] syntax made it into the language | because it's a small enough change that it's not | disruptive to existing uses of C, but it still has some | benefit (I've used it, I've seen its benefits). | WalterBright wrote: | My proposal is backwards compatible and will not disrupt | existing use. | klodolph wrote: | Do you have a write-up somewhere? | gavinray wrote: | Note that active development seems to be continuing here: | | https://github.com/secure-sw-dev/checkedc-llvm-project | jimbob45 wrote: | Why not just use C++? | | Also why can we not get better syntax for C? Function pointer | syntax is so bad that people actively avoid using them. #pragma | once is a hack. Every string library function is actively | dangerous in addition to puts/gets. | | I know that nobody wants to be the one to mess with the core | language and ruin it but this is awfully low-hanging fruit that | hasn't been fixed in 50 years. | flohofwoe wrote: | The stdlib needs a modernization much more than the language, | unlike 'C the language', 'C the stdlib' is still stuck deep in | the K&R era (together with POSIX). | | For a different language syntax it makes a lot more sense to | consider using a different language in the first place though, | because everybody has a different opinion what such a 'better | C' syntax should look like (e.g. it sounds like you'd actually | want Zig). | omeysalvi wrote: | >Why not just use C++? | | Nothing good has come to anyone who started an argument with | those words. | gavinray wrote: | Am sort of curious what the difference is between this and | templated constexpr functions with span<T, N> in C++ | mirekrusin wrote: | It has been fixed. The fix has the codename "zig". | pjmlp wrote: | It isn't a fix when it still allows for use after free. | shrimp_emoji wrote: | I heard it was "Rust". | anfilt wrote: | Rust is not exactly a C replacement. Definitely the better | choice these days over C++ in my opinion if you can use | rust. | | It can be made to function more like C with #![no_std]. | However that is an even less than batteries included | experience than C. | masklinn wrote: | > Rust is not exactly a C replacement. | | Rust is absolutely a C replacement. | | Whether C heads want to use it is a more complicated | question. But some are very much into it (e.g. Brian | Cantrill). | | > It can be made to function more like C with #![no_std]. | However that is an even less than batteries included | experience than C. | | std assumes you have a heap and IO, which most C | environments do. | | no_std removes all that (leaving only libcore as | baseline), however you can re-add a dependency on "alloc" | to get allocations and most of the standard collections | back (all but hashset and hashmap, because no secure | RNG). | | You can also / instead fill your needs with third-party | crates more dedicated to restricted or freestanding | environments, like heapless | (https://crates.io/crates/heapless). | tialaramex wrote: | You get a lot more in core (and thus no-std) than the | free standing C language. | | For example C's qsort lives in the standard library, | whereas in Rust although [].sort() needs alloc, the | [].sort_unstable() is a core feature! | | str::split_once(['5', '7']) will split a string at the | first digit 5 or 7... You need considerable work to do | that in C, and doing it modifies the string. In Rust it's | a core feature. | | Of course Rust is relying on the fact that none of the | machine code is emitted unless you use these features, | indeed split_once is fully generic, the types used only | come into existence because you called the function. So | presumably this was not practical as the fundamental | language for writing Unix fifty years ago. | maxbond wrote: | I think you & GP are using different senses of | replacement ("drop in replacement" vs. "replacement for | greenfield projects"). You might consider Rust to be the | latter (with qualifications, eg, excluding certain | architectures & proprietary programming environments) but | it's explicitly not the former (it's interoperable with | C, but not compatible with C). | | I think we should avoid saying "replacement" in general | because eliminating all lines of C isn't a goal worth | pursuing, C doesn't need to die for Rust to succeed, and | there's room enough in this world for a hundred safe | systems languages fulfilling different niches. I think a | lot of people feel attacked & invalidated by the idea of | a "C replacement" that isn't C compatible, like we're | telling them their skills are no longer necessary or | valuable, which is untrue & leads to flamewars and | misunderstandings. | zozbot234 wrote: | Rust is absolutely a "drop-in" replacement to C in most | cases even for existing projects, it was absolutely built | with that goal in mind. You can go as fine-grained as | replacing a single function with a Rust-coded version | (even using bindgen to ingest existing C headers) - | though that generally involves unsafety because you're | dealing with general pointers, extern calls and such. | Even Checked C cannot prove these things 100% safe, it | just catches common misuse. | | (Of course some C projects could abuse the preprocessor | in ways that make it infeasible to even replace a C | function with a Rust equivalent, but that's incredibly | rare. And Rust has macro facilities of its own.) | chaosite wrote: | Rust is more comparable to C++ than C. | seanw444 wrote: | Looking forward to it becoming more mature. Really cool | language. | constantcrying wrote: | >Also why can we not get better syntax for C? | | Backwards compatability. | | >Function pointer syntax is so bad that people actively avoid | using them. | | That is because C syntax mistakenly put the return value before | the parameters. You use function pointers if you have to. | | >#pragma once is a hack. | | It is a hack to prevent the previous hack of #ifdef'ing the | thing. | | >but this is awfully low-hanging fruit that hasn't been fixed | in 50 years. | | It is literally impossible to fix. | jimbob45 wrote: | There are ways to fix backwards compatibility, no? You | introduce the new syntax, let it sit for several years, and | then deprecate the old syntax. Would it truly be that | difficult to introduce a "fn" keyword? Also #includeHeader | "myHeader.h" would solve the #pragma once problem. | | I simply can't tell if we're not fixing this stuff out of | laziness, out of fear, or because no one wants to admit that | no one knows who's holding us back. | constantcrying wrote: | C++ addresses most of your concerns already. The headers | are C++23 iirc, somewhat similar to your proposal. | | I don't think you really understand what C actually is. C | basically does not compete as a programming language. On a | UNIX like it is the language of the kernel and as such its | quirks inevitably represent the quirks of the kernel, you | use C if you want to talk to the kernel. | | >Would it truly be that difficult to introduce a "fn" | keyword? | | Yes, literally impossible. Just look at the controversy of | C23 removing the almost entirely unused K&R function | declaration syntax. | elcritch wrote: | Ugh, the C syntax makes it so hard to parse, humans or | machine. | | I recently submitted a PR for the `c2nim` import tool to | handle double function pointers. I didn't actually understand | the C code until I got the transpiler working despite | cdecl.org: // posix signal | void(*signal(int, void (*)(int)))(int); | | in Nim becomes: var signal*: proc (a1: | cint; a2: proc (a1: cint)): proc (a1: cint) | | Well I'm 99.5% certain at least. Even now I'm uncertain of | the C syntax. And I've not been bold enough to test 3rd order | C function pointers. I figure that's probably C code you | don't wanna touch if possible. | | https://github.com/nim- | lang/c2nim/blob/11f2c5363dfe7e8c7c8ce... | | The other annoying one is that "signed" and "unsigned" are | basically adjectives, but "long" can be both a type and a | modifier. So it's difficult to parse unless you're the target | C compiler. Technically you can, but you have to use | backtracking. | secondcoming wrote: | That nim version isn't much better IMO, but I am unfamiliar | with the language. | kelnos wrote: | I'm completely unfamiliar with the language but was able | to read it from left-to-right very easily: | var signal*: proc (a1: cint; a2: proc (a1: cint)): proc | (a1: cint) | | That reads to me as: | | Variable signal is a pointer to a function that that | takes two arguments (an int, and a function that takes an | int), and returns a function that takes one argument (an | int). | | Of course, I'm assuming my interpretation is correct... | perhaps it's not ;) | elcritch wrote: | That's right. It's actually just an ugly bit of code | though it's pragmatic. | | Note that Nim uses "*" as a public symbol sigil not a | pointer. Its a bit odd at first coming from C but is nice | and consistent. | shirleyquirk wrote: | I agree, I prefer Nim's alternate syntax for this sort of | stuff: var signal*: (cint,(cint)->void) | -> (cint)->void | slavik81 wrote: | The signed and unsigned keywords work the same way as long, | e.g., `unsigned` alone is equivalent to `unsigned int`. | elcritch wrote: | Yah but you can't have "unsigned unsigned". You can and | do have "long long", or possibly a "long long long" in | addition to the saner "long int". | constantcrying wrote: | >Yah but you can't have "unsigned unsigned". | | Seems like a good thing to be honest. | elcritch wrote: | Lets not give the C committee ideas ;) | | But actually I'd suggest the opposite of disallowing | "long long" and making it like signed/unsiged as purely a | modifier. | xormapmap wrote: | > void( _signal(int, void (_ )(int)))(int); | | This is trivial to parse if you use spiral rule, humans or | machine. | constantcrying wrote: | >Ugh, the C syntax makes it so hard to parse, humans or | machine. | | As a _generalization_ I completely disagree. But for | function pointers specifically, yes, they are easily the | worst part of the C syntax. | | >void( _signal(int, void (_ )(int)))(int); | | That's just declaring signal as function (int, pointer to | function (int) returning void) returning pointer to | function (int) returning void, DUH. Thank you cdecl.org | | But notice how absolutely ugly it is that the final return | type comes _first_ , that is due to the C function | signatures. | WalterBright wrote: | > difficult to parse | | Not really. Just create a bit mask. | | https://github.com/dlang/dmd/blob/master/compiler/src/dmd/c | p... | elcritch wrote: | Thanks! I'd read you had a full c compiler, this is | awesome. | | Looks like there's only about ~388 lines of logic to the | bitmask? haha your definition of difficult might not | match mine. ;) | [deleted] | WalterBright wrote: | D has had a BetterC subset of D for a while: | | https://dlang.org/spec/betterc.html | nottorp wrote: | Hmm. Didn't Turbo Pascal have array bounds checking 3 billion | years ago when we all had pet dinosaurs? It could have simply | been added to the compiler in C as well... | baq wrote: | Turbo Pascal had a lot of good ideas back in the late 80s and | early 90s which were ridiculed back then and are now considered | best practices... modules, safe strings, safe arrays, Delphi | added quite nice objects. Alas, it was never popular in the | Internet age. Just imagine if we had pascalscript instead of | JavaScript - a decade of wasted developer time saved... | timmg wrote: | Quite honestly, I love what MS has done with JavsScript with | Typescript. It would be great if they could do the same for C. | | I guess the hard part will be the fact that all your dependent | libraries will (likely) still be unsafe. | pjmlp wrote: | See also https://devblogs.microsoft.com/cppblog/high- | confidence-lifet... | flohofwoe wrote: | I'm a bit confused, at the start they talk about C++, but | some of the code examples look like C. Do those checks also | work in the C compiler? (the difference is kinda important, | because unlike Clang, the MSVC C++ compiler doesn't have | enough non-standard language extensions to compile C code | that was written in the last 20 years). | pjmlp wrote: | They talk about C++, because that is what mostly matters to | Visual C++ customers, however /analyse mode also works in C | code. | | https://learn.microsoft.com/en-us/cpp/code-quality/code- | anal... | sendfoods wrote: | I'm a bit confused. Didn't Herb Sutter essentially fork | clang and extended the codebase in the beginning? Is | microsoft working with that fork and (most importantly) | re-contributing? | phailhaus wrote: | I'm begging them to do the same for Python. | corndoge wrote: | They made pyright which is pretty rad | phailhaus wrote: | Yeah it's pretty great, but still hamstrung by the inherent | limitations of the language itself. Would love to see a new | language on top of Python that treats types as first-class | constructs. | pjmlp wrote: | Older discussions on Checked C, | | https://news.ycombinator.com/item?id=30321535 | | https://news.ycombinator.com/item?id=19424106 | guerrilla wrote: | Why not frama-c instead? ___________________________________________________________________ (page generated 2022-12-21 23:00 UTC)