This is an archive of the discontinued LLVM Phabricator instance.

[AST] Better recovery on an expression refers to an invalid decl.
ClosedPublic

Authored by hokein on Mar 14 2022, 6:17 AM.

Details

Summary

Prior to the patch, we didn't build a DeclRefExpr if the Decl being
referred to is invalid, because many clang downstream AST consumers
assume it, violating it will cause many diagnostic regressions.

With this patch, we build a DeclRefExpr enven for an invalid decl (when the
AcceptInvalidDecl is true), and wrap it with a dependent-type
RecoveryExpr (to prevent follow-up semantic analysis, and diagnostic
regressions).

This is a revised version of https://reviews.llvm.org/D76831

Event Timeline

hokein created this revision.Mar 14 2022, 6:17 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 14 2022, 6:17 AM
hokein requested review of this revision.Mar 14 2022, 6:17 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 14 2022, 6:17 AM
sammccall accepted this revision.Apr 4 2022, 8:03 AM

Diagnostic changes look great!

clang/lib/Sema/SemaDecl.cpp
1250

wonder if if the results of setting AcceptInvalidDecl here would be good/bad?
(happy with in this patch/separate one/not at all, just curious)

Also possible candidates are the calls in:

  • Sema::ActOnIdExpression
  • Sema::BuildQualifiedDeclarationNameExpr
  • Sema::BuildPossibleImplicitMemberExpr
  • BuildRecoveryCallExpr in SemaOverload
clang/lib/Sema/SemaExpr.cpp
3189

if AcceptInvalid is true here, why do we skip all the rest of the checks?

Seems like in that case there's not much point calling the function at all...

My suspicion is that if we resolve to e.g. an invalid typedef then the diagnostic is good.

3502

Maybe drop the "many", which kind of implies they're incorrect to do so?

3507

This means we're changing the AST returned for existing AcceptInvalidDecl=true callers, right?

I think this is just attemptRecovery() in SemaCXX.cpp, which is part of typo correction. Previously we might transforming typos into DeclRefExpr to invalid, but now we're transforming them to RecoveryExpr wrapping DeclExpr to invalid.

This seems sensible, but I'm a little concerned there are no test changes for it. Is it possible to construct one?

I kind of expected this to work:

m *foo;
void z() {
  goo;
}

but in fact we produce an opaque RecoveryExpr (with no DeclRefExpr) inside today.

This revision is now accepted and ready to land.Apr 4 2022, 8:03 AM
hokein updated this revision to Diff 462131.Sep 22 2022, 4:26 AM
hokein marked 3 inline comments as done.

rebase and address comments.

hokein added inline comments.Sep 22 2022, 4:28 AM
clang/lib/Sema/SemaDecl.cpp
1250

yeah, this is interesting. we need to try it and see how well it goes. I will follow-up after this patch.

clang/lib/Sema/SemaExpr.cpp
3507

you're right. Added one testcase for the typo correction case.