In many places, Sema refuses to create an Expr if it encounters an error.
This means that broken code has no representation in the AST. As well as the broken node itself, child Exprs and parent Exprs are usually dropped.
This is terrible for tools that rely on the AST and see a lot of broken code (e.g. libclang-based IDEs and clangd).
In the expression foo(a, takes2args(b)), "go to definition" doesn't work on any of the subexpressions. And after takes2args(x)., member completion doesn't work, although in practice we almost always know the type.
This patch introduces RecoveryExpr. This AST node represents broken code, and has very weak semantics. It's part of the final AST (unlike TypoExpr) but can't produce code, as it's always accompanied by an error.
It captures valid subexpressions without checking or assigning them meaning.
Some RecoveryExprs have a known type (e.g. a broken non-overloaded call).
Where the type is unknown, it is modeled as the dependent RecoveryTy.
This allows us to reuse most existing behavior for suppressing further checks.
RecoveryTy is only used in C++, in C we don't recover unless the type is known.
Initiallly, RecoveryExpr is emitted in two common cases:
- a function call where overload resolution failed (most typically: wrong args) Callee is captured as an UnresolvedLookupExpr, and args are captured. Type is available if the "best" candidates have the same return type.
- access of a nonexistent member Base expression is captured, type is never available.
Test changes:
- SemaCXX/enable_if.cpp: we now emit more detailed diagnostics (the non-constexpr subexpression is inside a function call), which breaks the heuristic that tries to move the whole diagnostic to the subexpression location. This case (IMO) doesn't matter much: the subexpression is invalid, flagging it as non-constexpr isn't very useful to start with.
- SemaTemplate/instantiate-function-params.cpp: it looks like the testcase was minimized in an unrealistic way: the only version of if_ doesn't have type and the only version of requirement_ doesn't have failed, and it seems reasonable to diagnose this. If the precise invalid form is required, I can add another 17 expect-*s to the test, or remove -verify so we only fail on crashing. Original patch adding this test is very terse: https://github.com/llvm/llvm-project/commit/5112157958438005095aff805853f9b14ba974eb Testcase subsequently modified to test for a crash: https://github.com/llvm/llvm-project/commit/a02bb341552b2b91c93e708645c32d11cc4133d2
Why are you creating a new type as opposed to just using DependentTy (sorta like TypoExpr does)? It seems like if you want to recycle all the dependence-propagating code in Sema, then you need to fall back to DependentTy anyways, i.e. 1 + <recovery-expr> will have dependent type with this patch, right?