Examples of exception-free code


as I understand, the LLVM project prohibits the use of exceptions. I
don't want to start a discussion about this decision, but I'd love to
see what alternative error handling is used.

Could you please point me to some good code examples in the LLVM tree
where one can see how exceptions are avoided? Skimming through the code
I found different approaches (private ctor and create() method with
error return code; using only the ctor and ignoring possible allocation
errors; ...)
Surely, the use of the right error handling strategy is highly
situational, but LLVM also improved over time and without deeper
knowledge of the code base it is impossible for me to see which parts
are "good" and which parts are older and might need refactoring.

Kind regards

Hi there,

You’re right that some of the differences are based on different conditions/needs, and some are based on different styles (some which are historic - some which might vary by individual developer preferences, or common idioms within one part of the codebase that might be different in other parts)

Probably one of the more generically/full-functioned examples of non-exception error handling would be llvm::Error (& llvm::Expected), like google’s util::Status (& util::StatusOr).

But if there’s nothing interesting to say about the failure, a boolean return (or Optional - where T is the success value, and non-present for failure).

A long time ago some parts of Clang got in the habit of returning ‘true’ on failure, instead of false - this was in part motivated by the C idiom of non-zero-on-failure/errorcode style failures - but it’s gotten all a bit muddled up and I think the general sense is that false on failure is the direction to go moving forward for those sort of situations (where boolean failure is sufficient - no descriptive error message).

  • Dave

Broadly speaking, I would say that LLVM is not a good example for projects that want to handle errors with reliability. We tend to have two kinds of errors in compilers:

  1. Broken invariants
  2. Invalid input

When LLVM detects broken invariants, it tends to assert or exit with a fatal error. See this long standing guideline: https://llvm.org/docs/CodingStandards.html#assert-liberally If you are looking for examples of software that is reliable in the face of unforeseen faults, LLVM is not a good example of that. As you mention, OOMs are similarly treated as a fatal error.

You might still be interested in the elaborate infrastructure for handling relatively common, expected errors of invalid input, missing files, etc. As David mentioned, there’s the llvm::Error and Expected classes.

I’d also point out clang’s diagnostic machinery as a common design pattern, where you record errors on some side context, and then propagate failure locally with simple boolean return values. This is, IMO, much more pervasive than Error or error_code, and I personally prefer working with it. This pattern works well when all errors are generally treated the same way, using the same recovery strategies, which is usually the case when attempting to validate input.