Skip to content

Commit 3ce9539

Browse files
committed
[lldb][Expression] Emit a 'Note' diagnistc that indicates the language used for expression evaluation
Since it's a 'Note' diagnostic it would only show up when expression evaluation actually failed. This helps with expression evaluation failure reports in mixed language environments where it's not quite clear what language the expression ran as. It may also reduce confusion around why the expression evaluator ran an expression in a language it wasn't asked to run (a softer alternative to what I attempted in llvm#156648). Here are some example outputs: ``` (lldb) expr -l c -- blah ˄ ╰─ error: use of undeclared identifier 'blah' note: Requested expression evaluation as 'c' but fell back to 'c++'. (lldb) expr -l c++ -- blah ˄ ╰─ error: use of undeclared identifier 'blah' note: Requested expression evaluation as c++ (lldb) expr -l objc -- blah ˄ ╰─ error: use of undeclared identifier 'blah' note: Requested expression evaluation as 'objective-c' but fell back to 'objective-c++'. (lldb) expr -l rust -- blah ˄ ╰─ error: use of undeclared identifier 'blah' note: Requested expression evaluation as rust ``` I didn't put the diagnostic on the same line as the inline diagnostic for now because of implementation convenience, but if reviewers deem that a blocker I can take a stab at that again. Also, other language plugins (namely Swift), won't immediately benefit from this and will have to emit their own diagnistc. I played around with having a virtual API on `UserExpression` or `ExpressionParser` that will be called consistently, but by the time we're about to parse the expression we are already several frames deep into the plugin. Before (and at the beginning of) the generic `UserExpression::Parse` call we don't have enough information to notify which language we're going to parse in (at least for the C++ plugin). rdar://160297649
1 parent 582f575 commit 3ce9539

File tree

5 files changed

+31
-9
lines changed

5 files changed

+31
-9
lines changed

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#include "lldb/Core/Debugger.h"
7575
#include "lldb/Core/Disassembler.h"
7676
#include "lldb/Core/Module.h"
77+
#include "lldb/Expression/DiagnosticManager.h"
7778
#include "lldb/Expression/IRExecutionUnit.h"
7879
#include "lldb/Expression/IRInterpreter.h"
7980
#include "lldb/Host/File.h"
@@ -527,7 +528,8 @@ static void SetupTargetOpts(CompilerInstance &compiler,
527528

528529
static void SetupLangOpts(CompilerInstance &compiler,
529530
ExecutionContextScope &exe_scope,
530-
const Expression &expr) {
531+
const Expression &expr,
532+
DiagnosticManager &diagnostic_manager) {
531533
Log *log = GetLog(LLDBLog::Expressions);
532534

533535
// If the expression is being evaluated in the context of an existing stack
@@ -547,6 +549,8 @@ static void SetupLangOpts(CompilerInstance &compiler,
547549
: lldb::eLanguageTypeUnknown),
548550
lldb_private::Language::GetNameForLanguageType(language));
549551

552+
lldb::LanguageType language_for_note = language;
553+
550554
LangOptions &lang_opts = compiler.getLangOpts();
551555

552556
switch (language) {
@@ -560,12 +564,14 @@ static void SetupLangOpts(CompilerInstance &compiler,
560564
// family language, because the expression parser uses features of C++ to
561565
// capture values.
562566
lang_opts.CPlusPlus = true;
567+
language_for_note = lldb::eLanguageTypeC_plus_plus;
563568
break;
564569
case lldb::eLanguageTypeObjC:
565570
lang_opts.ObjC = true;
566571
// FIXME: the following language option is a temporary workaround,
567572
// to "ask for ObjC, get ObjC++" (see comment above).
568573
lang_opts.CPlusPlus = true;
574+
language_for_note = lldb::eLanguageTypeObjC_plus_plus;
569575

570576
// Clang now sets as default C++14 as the default standard (with
571577
// GNU extensions), so we do the same here to avoid mismatches that
@@ -610,6 +616,21 @@ static void SetupLangOpts(CompilerInstance &compiler,
610616
break;
611617
}
612618

619+
if (language_for_note != language)
620+
diagnostic_manager.AddDiagnostic(
621+
llvm::formatv(
622+
"Requested expression evaluation as '{0}' but fell back to '{1}'.",
623+
lldb_private::Language::GetNameForLanguageType(language),
624+
lldb_private::Language::GetNameForLanguageType(language_for_note))
625+
.str(),
626+
lldb::Severity::eSeverityInfo, DiagnosticOrigin::eDiagnosticOriginLLDB);
627+
else
628+
diagnostic_manager.AddDiagnostic(
629+
llvm::formatv("Requested expression evaluation as '{0}'",
630+
lldb_private::Language::GetNameForLanguageType(language))
631+
.str(),
632+
lldb::Severity::eSeverityInfo, DiagnosticOrigin::eDiagnosticOriginLLDB);
633+
613634
lang_opts.Bool = true;
614635
lang_opts.WChar = true;
615636
lang_opts.Blocks = true;
@@ -687,8 +708,8 @@ static void SetupImportStdModuleLangOpts(CompilerInstance &compiler,
687708

688709
ClangExpressionParser::ClangExpressionParser(
689710
ExecutionContextScope *exe_scope, Expression &expr,
690-
bool generate_debug_info, std::vector<std::string> include_directories,
691-
std::string filename)
711+
bool generate_debug_info, DiagnosticManager &diagnostic_manager,
712+
std::vector<std::string> include_directories, std::string filename)
692713
: ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(),
693714
m_pp_callbacks(nullptr),
694715
m_include_directories(std::move(include_directories)),
@@ -754,7 +775,7 @@ ClangExpressionParser::ClangExpressionParser(
754775
}
755776

756777
// 4. Set language options.
757-
SetupLangOpts(*m_compiler, *exe_scope, expr);
778+
SetupLangOpts(*m_compiler, *exe_scope, expr, diagnostic_manager);
758779
auto *clang_expr = dyn_cast<ClangUserExpression>(&m_expr);
759780
if (clang_expr && clang_expr->DidImportCxxModules()) {
760781
LLDB_LOG(log, "Adding lang options for importing C++ modules");

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class ClangExpressionParser : public ExpressionParser {
6565
/// diagnostics (i.e. errors, warnings or notes from Clang).
6666
ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr,
6767
bool generate_debug_info,
68+
DiagnosticManager &diagnostic_manager,
6869
std::vector<std::string> include_directories = {},
6970
std::string filename = "<clang expression>");
7071

lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,8 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp,
189189
lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
190190
if (jit_process_sp) {
191191
const bool generate_debug_info = true;
192-
auto *clang_parser = new ClangExpressionParser(jit_process_sp.get(), *this,
193-
generate_debug_info);
192+
auto *clang_parser = new ClangExpressionParser(
193+
jit_process_sp.get(), *this, generate_debug_info, diagnostic_manager);
194194
num_errors = clang_parser->Parse(diagnostic_manager);
195195
m_parser.reset(clang_parser);
196196
} else {

lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ bool ClangUserExpression::TryParse(
574574

575575
m_parser = std::make_unique<ClangExpressionParser>(
576576
exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info,
577-
m_include_directories, m_filename);
577+
diagnostic_manager, m_include_directories, m_filename);
578578

579579
unsigned num_errors = m_parser->Parse(diagnostic_manager);
580580

@@ -818,7 +818,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
818818
}
819819

820820
ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
821-
false);
821+
false, diagnostic_manager);
822822

823823
// We have to find the source code location where the user text is inside
824824
// the transformed expression code. When creating the transformed text, we

lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
120120

121121
const bool generate_debug_info = true;
122122
ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
123-
generate_debug_info);
123+
generate_debug_info, diagnostic_manager);
124124

125125
unsigned num_errors = parser.Parse(diagnostic_manager);
126126

0 commit comments

Comments
 (0)