Compiler error messages: show just the first, or all of them?

As a Fortran user/developer, when you use Fortran compilers:

  • Do you prefer to just get the first error message (e.g., -fmax-errors=1 in GFortran)?
  • Or do you prefer to get all of the error messages (the default)?
  • Just one error message
  • All of the error messages
  • Other (please explain in comments)

0 voters

I prefer to get all of them, because on occasion the first error is not the cause of the problem. Of course if you’re compiling and testing frequently enough that shouldn’t be a problem :wink:

3 Likes

What is an example where the first error is not the cause of the problem?

Some compilers cannot proceed to the next analysis phase (which might uncover more errors) until the earlier phase is error-free. So, the user fixes the indicated errors only to find yet more! Not ideal, but pretty inevitable.

1 Like

I don’t remember a specific example when this happened. It’s pretty rare. I think I may have seen something like misspelling the name on an end function name but then the first error reported was unexpected end of module.

If you use compiler options that treat certain warnings as errors, the first “error” may not cause the other errors. I have Windows cmd scripts that print “errors” of a certain type, for example

@ echo off
:: list unused variables in Fortran source file, compiled with gfortran
:: usage: gfun.bat foo.f90
set gfout=temp_gf.txt
gfortran -c -Wall %1 2> %gfout%
:: echo unused variables:
grep Unused %gfout% | tr -d "'" | cut -d ' ' -f 4

and

@ echo off
:: list undeclared variables in Fortran source file, compiled with gfortran
:: usage: gfundec.bat foo.f90
setlocal
set gfout=temp_gf.txt
gfortran -c -Wall %1 2> %gfout%
echo undeclared in %1:
grep IMPLICIT %gfout% | tr -d "'" | cut -d ' ' -f 3

I use them when refactoring code.

That’s right — I actually stopped using -fmax-errors=1 for GFortran, because sometimes it didn’t give sufficient information. I remember some issue when warnings are turned into errors. But it also sometimes happened that GFortran returned two error messages that describe that one error (perhaps two places in the file related to it), and -fmax-errors=1 only reported one, so it was no sufficient to know where the error was.

However, all these things I consider to be a bug in a compiler. I want a compiler to give me just one error message, but it needs to be a good one. So I voted “just one” above.

Compilers can and do report on multiple unrelated errors besides errors that are consequences of preceding errors. A trained eye can pretty readily pick these out in the output. That allows one to go and fix multiple errors at once before recompiling. That’s a lot more efficient than fixing and recompiling one at a time. I voted “all”.

4 Likes

I am not sure what do you mean by ‘the problem’. Nevertheless, not all errors come from cascading. I very often see errors originating from independent mistakes, even when warnings are treated separately. May be this partly due to the fact that I do not use any modern IDE or concurrent syntax analyzer, and instead depend on compiler for catching even the most mundane errors.

I was looking for an example of this behavior:

I prefer to get on the order of twenty of them. Not all error are from an error cascade, and its useful to get a representative sample In particular, I have an essential tremor and am particularly prone to typos. With about twenty all of them fit on on a page and I can fix a significant number of them without having to scroll back forever.

4 Likes

I tend to ask for just one error to avoid having to scroll back through pages of output, and then turn on multiple errors if the one error isn’t very helpful.

I wonder if it would be possible to have the best of both worlds: store all the errors until whatever the abort condition is (e.g. the end of the file with the first error), and then print them in reverse order, so the first error is right there without needing to scroll, and the later errors are on hand if they’re useful.

I guess it would also be nice if the errors could be grouped by type, so e.g. instead of having to pick out the undefined variables (usually typos) from a list of other errors, they could all be in a single list.

1 Like

I voted all for the same reason as @nncarlson. It is more efficient to fix multiple errors before recompiling.

For a small Fortran project (500 lines) I will typically get a few dozen errors, forgetting to declare variables, or getting the call sequences wrong. I like to see the error messages shrink as I recompile after fixing batches of 1 to 10 errors. I will often use Ctrl + g + <line number> in my text editor to jump directly to the affected line.

2 Likes

If I get in a situation where the compiler is printing a huge amount of errors, I’ll use “clear” on the terminal, then compile and be able to scroll and stop automatically at the top.

1 Like

One example is for a program unit for which IMPLICIT NONE is in effect (a good idea in general), and there are separate messages for each undeclared variable. Easier for me to deal with all the cases (often a typo in the spelling of the variable name in either the usage location or (worse) in the declaration). Faster to deal with all of them at once rather than recompiling for each one sequentially. [It is sometimes better for “all” messages output to really mean all up to some limit, like 100, just to keep things manageable.]

1 Like

My own scripts always compile to a log file and tee the output into a pager (ie. less(1) or more(1)) when a tty is detected. I set pager options so if screen is not filled no paging occurs; I have also used a line count limit
using head(1) instead. So if interactive get first page of errors and can quit if desired, or if a lot (like a lot of variables without a type) then everything is in a file I can edit. When I wrote the scripts some pagers had issues with saving or editing piped input and such so the file is often then already available to use in a separate window or can be used for other scripts to create a bunch of declarations using default implicit type assumptions, or grepped for line numbers, etc. So it is not that I want one error, I want one page. When making changes to existing codes I usually want one error at a time; when porting codes to new programming environments or adding new requirements like removing deprecated features, enforcing typing, identifying non-portable or non-standard usage, and so on I want all the messages. So “none of the above”, but when using the compiler commands directly I usually prefer 1 to 4 if working on something I know should not have any errors other than those recently introduced by rework or new feature development, I want “all” in particular the first time I compile something with a new compiler or after making a change like adding “implicit none”.

As an aside, with something like fpm I would like behavior something like that. If a new compile with no subdirectory in build/ (assuming a fresh compile means a new code or new options on the compile) I would like to see all the messages; if I just compiled a few minutes ago I typically one just one error; or at least < 4. Just revisited that with @lkedward a bit in a recent discussion. Still pondering it, but I think every latest build should write a logfile, and someone should make a plugin that lets you interact with the logfile to review it, or use it to invoke the editor at specified lines, open a www search for the error message, call a vendor “explain” utility, bring up a man-page on a routine, open up a vendor bug report or a discourse(1) discussion :> … So fpm(1) would stay core-focused by IDE-like functions could be added; and all messages would be available without recompiling (which is usually not a very long operation, but for some circumstances can be very slow ).

3 Likes

If you have written error messages to a file and then print them, you may decide to stop displaying messages after certain types of errors are encountered, because later errors will result from them. Such “showstopper” errors include

  • use m, only: foo if foo is not found in m
  • mismatches, such as function foo followed by end function bar, do followed by endif instead of enddo, labeled do loop closed by mislabeled enddo

What are some other showstoppers?

I usually compile with options that turn some warnings into errors. If a source file does not compile, I may recompile without such options and fix the true errors first. This procedure could be automated.

Btw, to ensure that error messages are independent (i.e., that the first is not the cause of the other ones), one approach to do that is to “poison” the AST tree from the error node all the way up, and only show other errors if they come from a not yet poisoned AST node. As an example if there is a type mismatch error in an expression, then one can poison the whole subroutine and anything that calls it. But if there is another subroutine (definitely in a separate module, but probably also in the same module) that also has a type mismatch error, then that can be reported.

If one is aggressive with “poisoning”, I think one can achieve quite good independent error messages.

For example, if a function call is not declared inside a subroutine, one could assume that the module is missing a use statement, so one can poison everything in the module. So any other missing functions would not be reported, because they could presumably come from the same missing used module.

However, as several people commented above, they actually like if the compiler reports all undeclared variables (and functions I assume) even in the same module I guess. So even if theoretically all such errors might be caused by the “first error” (which is caused by one missing use statement), in practice they might not.

This is a tough problem.