Consistent Error Handling
Currently, error handling is done via return codes. Compared to Exceptions the advantage is performance and C compatibility. However, all of the following behaviours are present in the scenario where g calls f and f fails.
A. result of f() is checked, in case of error g() return error code
B. result of f() is checked, in case of error g() handles it (f.ex. warnings etc)
C. result of f() is checked, in case of error nothing is done because g() is void
D. result of f() is checked, in case of error g() calls fatal()
E. result of f() is never checked
A leads to a save fail. There is the possibility for cleanup and even later error handling, however, it is almost never used. It produces a lot of code since every function call is followed by the error check.
B is nice, however, g() might still check for error codes, even though f() never returns errors.
C is a problem and should be fixed in favour f either A or D.
D leads to an unsafe fail. Cleanup does not happen f.ex. resources are not freed. Most likely the issues can be resolved by the OS after the program is finished so it rarely causes problems. In terms of code, it is the most efficient and clean-looking solution.
E is a problem and should be fixed. To find such issues one can use [[nodiscard]] for all functions that might return error codes.