Page MenuHomePhabricator

[AST] Add RecoveryExpr; produce it on overload resolution failure and missing member.
Needs ReviewPublic

Authored by sammccall on May 21 2019, 3:25 AM.
This revision needs review, but there are no reviewers specified.



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 a new type ErrorTy.

In this patch, ErrorTy is not dependent. See D61722 for that approach.
Here ErrorTy must be explicitly handled on many paths, similar to dependent
types (though also for C). I've certainly missed some that tests didn't flag.

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: Testcase subsequently modified to test for a crash:
  • CodeGen/builtins-systemz-zvector[2]-error.c: these tests now generate extra noisy (but correct) diagnostics: vecintrin.h uses a cast to an invalid type to suppress them, and the cast now succeeds. The right fix is probably to rewrite the builtin header somehow, I haven't investigated fully yet.

Diff Detail