From b4a0b9fab4dcb7b808612b49604709c2aeadf9f8 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 18 Jan 2023 16:42:20 +0000 Subject: [PATCH] [lldb][Language] List supported languages in expr error text Before: ``` (lldb) expr --language abc -- 1 + 1 error: unknown language type: 'abc' for expression ``` After: ``` (lldb) expr --language abc -- 1 + 1 error: unknown language type: 'abc' for expression. List of supported languages: c++ objective-c++ c++03 c++11 c++14 objc++ ``` We choose to only list the languages which `expr` will actually accept instead of all the language constants defined in `Language.cpp` since that's what the user will most likely need. Differential Revision: https://reviews.llvm.org/D142034 --- lldb/include/lldb/Target/Language.h | 10 ++++++++++ lldb/source/Commands/CommandObjectExpression.cpp | 13 +++++++++---- lldb/source/Target/Language.cpp | 11 +++++++++++ .../expression/invalid-args/TestInvalidArgsExpression.py | 4 +++- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h index 89136cc..8cc1e72 100644 --- a/lldb/include/lldb/Target/Language.h +++ b/lldb/include/lldb/Target/Language.h @@ -279,6 +279,16 @@ public: static void PrintAllLanguages(Stream &s, const char *prefix, const char *suffix); + /// Prints to the specified stream 's' each language type that the + /// current target supports for expression evaluation. + /// + /// \param[out] s Stream to which the language types are written. + /// \param[in] prefix String that is prepended to the language type. + /// \param[in] suffix String that is appended to the language type. + static void PrintSupportedLanguagesForExpressions(Stream &s, + llvm::StringRef prefix, + llvm::StringRef suffix); + // return false from callback to stop iterating static void ForAllLanguages(std::function callback); diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 49d4976..9cce009f 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -42,10 +42,15 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue( switch (short_option) { case 'l': language = Language::GetLanguageTypeFromString(option_arg); - if (language == eLanguageTypeUnknown) - error.SetErrorStringWithFormat( - "unknown language type: '%s' for expression", - option_arg.str().c_str()); + if (language == eLanguageTypeUnknown) { + StreamString sstr; + sstr.Printf("unknown language type: '%s' for expression. " + "List of supported languages:\n", + option_arg.str().c_str()); + + Language::PrintSupportedLanguagesForExpressions(sstr, " ", "\n"); + error.SetErrorString(sstr.GetString()); + } break; case 'a': { diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp index 9243100..892d2a8 100644 --- a/lldb/source/Target/Language.cpp +++ b/lldb/source/Target/Language.cpp @@ -221,6 +221,17 @@ const char *Language::GetNameForLanguageType(LanguageType language) { return language_names[eLanguageTypeUnknown].name; } +void Language::PrintSupportedLanguagesForExpressions(Stream &s, + llvm::StringRef prefix, + llvm::StringRef suffix) { + auto supported = Language::GetLanguagesSupportingTypeSystemsForExpressions(); + for (size_t idx = 0; idx < num_languages; ++idx) { + auto const &lang = language_names[idx]; + if (supported[lang.type]) + s << prefix << lang.name << suffix; + } +} + void Language::PrintAllLanguages(Stream &s, const char *prefix, const char *suffix) { for (uint32_t i = 1; i < num_languages; i++) { diff --git a/lldb/test/API/commands/expression/invalid-args/TestInvalidArgsExpression.py b/lldb/test/API/commands/expression/invalid-args/TestInvalidArgsExpression.py index 859b823..1c53583 100644 --- a/lldb/test/API/commands/expression/invalid-args/TestInvalidArgsExpression.py +++ b/lldb/test/API/commands/expression/invalid-args/TestInvalidArgsExpression.py @@ -7,7 +7,9 @@ class InvalidArgsExpressionTestCase(TestBase): @no_debug_info_test def test_invalid_lang(self): self.expect("expression -l foo --", error=True, - substrs=["error: unknown language type: 'foo' for expression"]) + substrs=["error: unknown language type: 'foo' for expression", + "List of supported languages:", + "c++", "c++11", "c++14"]) @no_debug_info_test def test_invalid_all_thread(self): -- 2.7.4