[lldb][ClangExpressionParser] Reset DiagnosticManager before we create persistent variables (#160074)

Here's an example crash that we've seen sporadically over the years:
```
0   libsystem_kernel.dylib        	       0x19d392388 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x19d3cb88c pthread_kill + 296
2   libsystem_c.dylib             	       0x19d29cd04 raise + 32
3   LLDB                          	       0x112cbbc94 SignalHandler(int, __siginfo*, void*) + 324
4   libsystem_platform.dylib      	       0x19d4056a4 _sigtramp + 56
5   LLDB                          	       0x110dcbd38 clang::TextDiagnosticPrinter::HandleDiagnostic(clang::DiagnosticsEngine::Level, clang::Diagnostic const&) + 1216
6   LLDB                          	       0x110dcbd38 clang::TextDiagnosticPrinter::HandleDiagnostic(clang::DiagnosticsEngine::Level, clang::Diagnostic const&) + 1216
7   LLDB                          	       0x10de12128 ClangDiagnosticManagerAdapter::HandleDiagnostic(clang::DiagnosticsEngine::Level, clang::Diagnostic const&) + 332
8   LLDB                          	       0x1121eb3dc clang::DiagnosticIDs::ProcessDiag(clang::DiagnosticsEngine&) const + 200
9   LLDB                          	       0x1121e67a0 clang::DiagnosticsEngine::EmitCurrentDiagnostic(bool) + 100
10  LLDB                          	       0x111d766cc IsStructurallyEquivalent(clang::StructuralEquivalenceContext&, clang::FieldDecl*, clang::FieldDecl*, clang::QualType) + 1568
11  LLDB                          	       0x111d71b54 IsStructurallyEquivalent(clang::StructuralEquivalenceContext&, clang::RecordDecl*, clang::RecordDecl*) + 2076
12  LLDB                          	       0x111d6e448 clang::StructuralEquivalenceContext::Finish() + 204
13  LLDB                          	       0x111d6e1e0 clang::StructuralEquivalenceContext::IsEquivalent(clang::Decl*, clang::Decl*) + 32
14  LLDB                          	       0x111d3b788 clang::ASTNodeImporter::IsStructuralMatch(clang::Decl*, clang::Decl*, bool, bool) + 168
15  LLDB                          	       0x111d404e0 clang::ASTNodeImporter::VisitFunctionDecl(clang::FunctionDecl*) + 1300
16  LLDB                          	       0x111d5cae0 clang::ASTImporter::ImportImpl(clang::Decl*) + 24
17  LLDB                          	       0x10ddf30bc lldb_private::ClangASTImporter::ASTImporterDelegate::ImportImpl(clang::Decl*) + 308
18  LLDB                          	       0x111d48140 clang::ASTImporter::Import(clang::Decl*) + 984
19  LLDB                          	       0x10ddee9dc lldb_private::ClangASTImporter::CopyDecl(clang::ASTContext*, clang::Decl*) + 100
20  LLDB                          	       0x10ddfab40 lldb_private::ClangASTSource::FindExternalLexicalDecls(clang::DeclContext const*, llvm::function_ref<bool (clang::Decl::Kind)>, llvm::SmallVectorImpl<clang::Decl*>&) + 1692
21  LLDB                          	       0x111e1cb84 clang::DeclContext::LoadLexicalDeclsFromExternalStorage() const + 180
22  LLDB                          	       0x111e1df50 clang::DeclContext::buildLookup() + 204
23  LLDB                          	       0x111e1dcf4 clang::DeclContext::makeDeclVisibleInContextWithFlags(clang::NamedDecl*, bool, bool) + 504
24  LLDB                          	       0x111d3b01c clang::ASTNodeImporter::ImportDeclContext(clang::DeclContext*, bool) + 724
25  LLDB                          	       0x111d62d10 clang::ASTImporter::ImportDefinition(clang::Decl*) + 428
26  LLDB                          	       0x10ddf1cb0 lldb_private::ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(clang::Decl*, clang::Decl*) + 524
27  LLDB                          	       0x10ddef3c8 (anonymous namespace)::CompleteTagDeclsScope::~CompleteTagDeclsScope() + 616
28  LLDB                          	       0x10ddef6dc lldb_private::ClangASTImporter::DeportDecl(clang::ASTContext*, clang::Decl*) + 436
29  LLDB                          	       0x10ddec3dc lldb_private::ASTResultSynthesizer::CommitPersistentDecls() + 236
30  LLDB                          	       0x10de1091c lldb_private::ClangExpressionParser::ParseInternal(lldb_private::DiagnosticManager&, clang::CodeCompleteConsumer*, unsigned int, unsigned int) + 2292
31  LLDB                          	       0x10de21238 lldb_private::ClangUserExpression::TryParse(lldb_private::DiagnosticManager&, lldb_private::ExecutionContext&, lldb_private::ExecutionPolicy, bool, bool) + 328
...
```

Here `ASTImporter::IsStructurallyEquivalent` is trying to emit a
diagnostic using `ClangExpressionParser`'s
`ClangDiagnosticManagerAdapter`. But `TextDiagnosticPrinter::TextDiag`
seems to be `nullptr`. This can only happen when we call
`HandleDiagnostic` on `ClangDiagnosticManagerAdapter` after we called
`EndSourceFile`. Specifically, it looks like when moving a type from
`Expression` AST to `Scratch` AST (in `CommitPersistentDecls`),
something went wrong, so the ASTImporter tried to emit a diagnostic, but
we already called `EndSourceFile` at that point.

This patch moves the call to `ResetManager` to before
`CommitPersistentDecls`, so if we called `HandleDiagnostic`, we would
correctly short-circuit out of it. This seems to have been intended
anyway based on this comment:
https://github.com/llvm/llvm-project/blob/cecdff92838f3c049548e3445a15d8c9c7a49205/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp#L200-L204

But something must have broken that during a refactor.

I'm not 100% sure how best to test this because we need a scenario where
moving a type into the scratch AST fails, but the expression itself
succeeded.

rdar://159647906
1 file changed
tree: 13416b00d077769f7b7bb217df47c33cfc575ef5
  1. .ci/
  2. .github/
  3. bolt/
  4. clang/
  5. clang-tools-extra/
  6. cmake/
  7. compiler-rt/
  8. cross-project-tests/
  9. flang/
  10. flang-rt/
  11. libc/
  12. libclc/
  13. libcxx/
  14. libcxxabi/
  15. libsycl/
  16. libunwind/
  17. lld/
  18. lldb/
  19. llvm/
  20. llvm-libgcc/
  21. mlir/
  22. offload/
  23. openmp/
  24. orc-rt/
  25. polly/
  26. runtimes/
  27. third-party/
  28. utils/
  29. .clang-format
  30. .clang-format-ignore
  31. .clang-tidy
  32. .git-blame-ignore-revs
  33. .gitattributes
  34. .gitignore
  35. .mailmap
  36. CODE_OF_CONDUCT.md
  37. CONTRIBUTING.md
  38. LICENSE.TXT
  39. pyproject.toml
  40. README.md
  41. SECURITY.md
README.md

The LLVM Compiler Infrastructure

OpenSSF Scorecard OpenSSF Best Practices libc++

Welcome to the LLVM project!

This repository contains the source code for LLVM, a toolkit for the construction of highly optimized compilers, optimizers, and run-time environments.

The LLVM project has multiple components. The core of the project is itself called “LLVM”. This contains all of the tools, libraries, and header files needed to process intermediate representations and convert them into object files. Tools include an assembler, disassembler, bitcode analyzer, and bitcode optimizer.

C-like languages use the Clang frontend. This component compiles C, C++, Objective-C, and Objective-C++ code into LLVM bitcode -- and from there into object files, using LLVM.

Other components include: the libc++ C++ standard library, the LLD linker, and more.

Getting the Source Code and Building LLVM

Consult the Getting Started with LLVM page for information on building and running LLVM.

For information on how to contribute to the LLVM project, please take a look at the Contributing to LLVM guide.

Getting in touch

Join the LLVM Discourse forums, Discord chat, LLVM Office Hours or Regular sync-ups.

The LLVM project has adopted a code of conduct for participants to all modes of communication within the project.