Usability Improvements in GCC 9
developers.redhat.com
developers.redhat.com
$ gcc-9 -c cve-2014-1266.c -Wall
cve-2014-1266.c: In function ‘SSLVerifySignedServerKeyExchange’:
cve-2014-1266.c:629:2: warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]
629 | if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
| ^~
cve-2014-1266.c:631:3: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
631 | goto fail;
| ^~~~
this is a cute example ;)This will allow much of the code coverage calculation process to be done in parallel (i.e. much faster than is currently possible). This is because currently gcov writes everything out to files, which forces the wrapper to be single threaded lest one gcov process overwrite the output file of another.
For fun, I wrote a parallelized GCC9 gcov wrapper in python that generates an LCOV coverage report that genhtml can consume. Unofficial/anecdotal bench marking shows incredible gains over lcov on my own personal projects (700ms vs. 90 seconds). I'm sure it could be improved even more.
After that, I ended up shifting to tackling the generation of the initial data from .gcda and .gcno, which is where I discovered bugs in both lcov and gcov in the collection process. One bug is that gcov somehow manages to compute negative edge counts on certain cycles in the graph, and when that happens, it double-counts those cycles.
With that, `msoak make` will show the first lines first, and let you scroll down to see the rest. (Simply doing `make | less` isn't enough, because you need to fool the program into thinking it's sending output to a TTY for nice colors.)
For example, tables would be output with type info and proper unambiguous delimiting of some sort.
Unrelated to that I once wrote a program in the past several years ago as two distinct parts that communicated over a pair of Unix pipes; one part the GUI which embedded a web view and the other part which contained the program logic and which output HTML to stdout. The code was quite ugly, but anyway it did the job at the time.
But the idea of outputting JSON is somewhat in between this two things. But the main takeaway here IMO is the idea about outputting a specific format as controlled by a flag. Of course other tools have done this too in the past.
Consider a few Unix utilities reimplemented to work a bit tighter together in terms of how some data is represented, and using for example Cap’n Proto to serialize the data and piping that between them but also writing a library for destructively converting to plain text representation and then using some method or combination of methods for deciding when to use binary piping. For example,
- A user-provided flag. Tiresome to type.
- A user-provided environment variable. Problematic when mixing tools that implement serialization with pure plaintext tools.
- The shell could be aware of which programs implement this serialization and invoke them with the flags or env vars corresponding to whether or not each program on each side of each pipe in a pipeline supports the serialization. Possibly the way to go.
In this way one could incrementally rebuild the Unix tools to work this way without having to change everything at once and still being compatible with the universal interface of plaintext forever, since no-one wants nor can implement this in every Unix tool out there.
Once you have a couple of tools support this then the possibility for new ways to interact with pipelines becomes available.
I still love and will use the classic command-line. But in some situations the possibilities enabled by this would be very compelling indeed.
JSON (or another pure data serialization format) is much better in that regard, because then you only need to agree on some basic data structures at the boundary.
It wouldn't require special tools but it could work with them.
You could save the column headers, types and separator in extended attributes.
That would save a lot of repeated wasteful parsing and checking.
Both sides just default to plain text so it'll be backwards compatible.
How to Quickly and Correctly Generate a Git Log in HTML http://www.oilshell.org/blog/2017/09/19.html
Git Log in HTML: A Harder Problem and A Safe Solution http://www.oilshell.org/blog/2017/09/29.html
I'm interested in ideas for structured data over pipes, or even better a prototype and example programs :)
Honestly though, who would build a tool which depends on the (presumably undocumented) text output of another application, and then expect it not to break?
Text output, particularly warnings and notes, isn't usually intentioned to be machine parseable and consistent in the first place, but rather is meant for humans to read and may be changed to be better read by humans at will.
https://gcc.gnu.org/onlinedocs/gnat_ugn/Output-and-Error-Mes...
Not expecting it not to break, but building tools that depend on the undocumented text output of other tools that.
Hypothetical example: can I read only the man pages of GNU’s and all BSD’s `ls`es and from that write a cross-platform tool that parses the output of all of them?
That makes them even more stable than flavors of the decade like xml or json.
In fact, the : delimited compiler error format is so well established that it will probably outlive the json schema the article presents, and maybe even json-as-defacto-standard.
I’m not saying the json thing is bad (it provides rich information that will be useful to some tools), but it’s shelf life will probably be much less than 25 years.
your comment reminds of of a hilarious but very true ringing anecdote here¹ about json and 'The Sins of the Father' :-)
Nice! Now, can we get warned about UB?
Would you want a warning to be emitted at compile time every single time you write "for (int i = 0...)"? I'm sure that would actually end up doing more harm than good as it would just condition people to ignore these warnings altogether. As the poster mentioned, ubsan will catch the cases you actually care about, albeit at runtime. It's also worth noting that GCC does try to warn at compile time about a lot of the undefined behavior that you do care about, such as strict aliasing violations when -Wall is enabled.
Yes, I would. I have transitioned to always using ranged loops. I haven't had to write a "for (int i = 0...)" style loop for over a year. Even one where I thought it was still needed, I learned about zip iterator adapters from a C++ conference video; wrote my own, paired it with a proxy iterator, and the problem solved. Everywhere such a loop has existed, it has been replaced with generator class to provide the range needed.
Not only would I want a warning, but I'd personally turn the warning into an error. I'm one of those dudes who runs around with pretty much as many warnings as possible turned on, and most of them turned into errors. Most of the warnings that are disabled by default are extremely helpful in preventing simple errors. Understanding what those warnings mean and how to resolve them is something I consider to be core understanding for anyone who wants to become more than a junior C++ developer.
There's a _ton_ of libraries that don't work like that. Sucks to be them. Linking to boost works (most of the time) though, and that's the only real hard requirement I have.
I strongly agree, which is why I think it's important that these warnings are not spurious. -Werror is no longer viable if what it takes to resolve warnings is more ceremony than substance. Emitting a warning every single time the compiler encounters undefined behavior would be utterly overwhelming given that the vast majority of these instances are harmless like skipping a load because it would be undefined behavior for a couple of pointers to alias. Obviously GCC and Clang could do more (for example, Clang doesn't implement -Wstrict-aliasing if I recall correctly), but their current approach of warning about UB when harmful, rather than reporting all UB, is correct in my opinion.
> overwhelmingly common case you won't see undefined behavior.
You think so. But this actually can be a source of serious security vulnerabilities. I want at least the option to know.
Or for every a[i++] in a loop (including a[i] with i++ in the for loop of course), where the compiler assumes it can convert the induction variable to *p++?
Both of these are undefined behavior if "i" is signed and it overflows.
Be glad they fixed it, sometime back, so "-W -Wall" doesn't turn off the extra -W warnings.