llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) <details> <summary>Changes</summary> Depends on: * https://github.com/llvm/llvm-project/pull/177921 * https://github.com/llvm/llvm-project/pull/177926 (only last commit is relevant for this review) This patch emits a `note:` diagnostic when an expression fails due to trying to mutate state/call functions CV-qualifiers that are disallowed by C++ language rules based on the context the expression is evaluated in. The note looks as follows: ``` (lldb) expr next.method() ˄ ╰─ error: 'this' argument to member function 'method' has type 'const Bar', but function is not marked const note: Ran expression as 'C++14'. note: note: 'method' declared here note: Possibly trying to mutate object in a const context. Try running the expression with: expression --ignore-const-context -- <your expression> ``` --- Patch is 63.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/177927.diff 41 Files Affected: - (modified) lldb/include/lldb/API/SBExpressionOptions.h (+4) - (modified) lldb/include/lldb/Expression/UserExpression.h (+10) - (modified) lldb/include/lldb/Target/Target.h (+6) - (modified) lldb/packages/Python/lldbsuite/test/lldbtest.py (+9-5) - (modified) lldb/source/API/SBExpressionOptions.cpp (+12) - (modified) lldb/source/Commands/CommandObjectExpression.cpp (+6) - (modified) lldb/source/Commands/CommandObjectExpression.h (+1) - (modified) lldb/source/Commands/Options.td (+3) - (modified) lldb/source/Expression/UserExpression.cpp (+11-13) - (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp (+12-3) - (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h (+4-1) - (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp (+39-8) - (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h (+2-2) - (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp (+43-4) - (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h (+8-4) - (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp (+1-1) - (modified) lldb/test/API/commands/expression/expr_inside_lambda/TestExprInsideLambdas.py (+2-2) - (modified) lldb/test/API/lang/cpp/const_this/TestConstThis.py (+4-6) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/Makefile (+3) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py (+152) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/main.cpp (+49) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/Makefile (+3) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py (+95) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/main.cpp (+43) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/cv_qualified_objects/Makefile (+3) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/cv_qualified_objects/TestExprOnCVQualifiedObjects.py (+21) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/cv_qualified_objects/main.cpp (+25) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/fixit/Makefile (+3) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/fixit/TestExprInConstMethodWithFixit.py (+67) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/fixit/main.cpp (+22) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/Makefile (+3) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py (+90) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/main.cpp (+49) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/Makefile (+3) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py (+116) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/main.cpp (+51) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/Makefile (+3) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py (+90) - (added) lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/main.cpp (+49) - (modified) lldb/test/API/lang/cpp/this/TestCPPThis.py (+13-3) - (modified) lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp (+1-1) ``````````diff diff --git a/lldb/include/lldb/API/SBExpressionOptions.h b/lldb/include/lldb/API/SBExpressionOptions.h index a9e929a4c0bd9..2b922b97f75b9 100644 --- a/lldb/include/lldb/API/SBExpressionOptions.h +++ b/lldb/include/lldb/API/SBExpressionOptions.h @@ -107,6 +107,10 @@ class LLDB_API SBExpressionOptions { // Sets whether we will JIT an expression if it cannot be interpreted void SetAllowJIT(bool allow); + bool GetIgnoreConstContext(); + + void SetIgnoreConstContext(bool b = true); + protected: lldb_private::EvaluateExpressionOptions *get() const; diff --git a/lldb/include/lldb/Expression/UserExpression.h b/lldb/include/lldb/Expression/UserExpression.h index 2fde73dafa035..977a0adef1cbe 100644 --- a/lldb/include/lldb/Expression/UserExpression.h +++ b/lldb/include/lldb/Expression/UserExpression.h @@ -313,6 +313,16 @@ class UserExpression : public Expression { lldb::ProcessSP &process_sp, lldb::StackFrameSP &frame_sp); + /// Called by expression evaluator when a parse error occurs. Gives this + /// UserExpression object a chance to inspect and adjust the error diagnostics + /// contained in the specified \c diagnostic_manager. + /// + /// \param[in,out] diagnostic_manager DiagnosticManager manager holding the + /// parse error diagnostics. This function may mutate the diagnostics. + /// + virtual void + FixupParseErrorDiagnostics(DiagnosticManager &diagnostic_manager) const {} + /// The address the process is stopped in. Address m_address; /// The text of the expression, as typed by the user. diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 812a638910b3b..77caccdbcc74d 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -481,6 +481,10 @@ class EvaluateExpressionOptions { void SetIsForUtilityExpr(bool b) { m_running_utility_expression = b; } + bool GetIgnoreConstContext() const { return m_ignore_const_contexts; } + + void SetIgnoreConstContext(bool val) { m_ignore_const_contexts = val; } + private: ExecutionPolicy m_execution_policy = default_execution_policy; SourceLanguage m_language; @@ -518,6 +522,8 @@ class EvaluateExpressionOptions { /// used for symbol/function lookup before any other context (except for /// the module corresponding to the current frame). SymbolContextList m_preferred_lookup_contexts; + + bool m_ignore_const_contexts = false; }; // Target diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 6bb4516948da5..6034eca3b93f2 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -2575,6 +2575,7 @@ def expect_expr( result_value=None, result_type=None, result_children=None, + options=None, ): """ Evaluates the given expression and verifies the result. @@ -2584,6 +2585,7 @@ def expect_expr( :param result_type: The type that the expression result should have. None if the type should not be checked. :param result_children: The expected children of the expression result as a list of ValueChecks. None if the children shouldn't be checked. + :param options: Expression evaluation options. None if a default set of options should be used. """ self.assertTrue( expr.strip() == expr, @@ -2591,13 +2593,15 @@ def expect_expr( ) frame = self.frame() - options = lldb.SBExpressionOptions() - # Disable fix-its that tests don't pass by accident. - options.SetAutoApplyFixIts(False) + if not options: + options = lldb.SBExpressionOptions() - # Set the usual default options for normal expressions. - options.SetIgnoreBreakpoints(True) + # Disable fix-its that tests don't pass by accident. + options.SetAutoApplyFixIts(False) + + # Set the usual default options for normal expressions. + options.SetIgnoreBreakpoints(True) if self.frame().IsValid(): options.SetLanguage(frame.GuessLanguage()) diff --git a/lldb/source/API/SBExpressionOptions.cpp b/lldb/source/API/SBExpressionOptions.cpp index 15ed403eaaea1..84f23df47b0cb 100644 --- a/lldb/source/API/SBExpressionOptions.cpp +++ b/lldb/source/API/SBExpressionOptions.cpp @@ -256,6 +256,18 @@ void SBExpressionOptions::SetAllowJIT(bool allow) { : eExecutionPolicyNever); } +bool SBExpressionOptions::GetIgnoreConstContext() { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_up->GetIgnoreConstContext(); +} + +void SBExpressionOptions::SetIgnoreConstContext(bool b) { + LLDB_INSTRUMENT_VA(this, b); + + m_opaque_up->SetIgnoreConstContext(b); +} + EvaluateExpressionOptions *SBExpressionOptions::get() const { return m_opaque_up.get(); } diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 4919bd3639d3e..14dea55164c6e 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -25,6 +25,7 @@ #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-private-enumerations.h" +#include <tuple> using namespace lldb; using namespace lldb_private; @@ -44,6 +45,9 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue( const int short_option = GetDefinitions()[option_idx].short_option; switch (short_option) { + case 'K': + ignore_const_context = true; + break; case 'l': language = Language::GetLanguageTypeFromString(option_arg); if (language == eLanguageTypeUnknown) { @@ -191,6 +195,7 @@ void CommandObjectExpression::CommandOptions::OptionParsingStarting( top_level = false; allow_jit = true; suppress_persistent_result = eLazyBoolCalculate; + ignore_const_context = false; } llvm::ArrayRef<OptionDefinition> @@ -213,6 +218,7 @@ CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions( options.SetExecutionPolicy( allow_jit ? EvaluateExpressionOptions::default_execution_policy : lldb_private::eExecutionPolicyNever); + options.SetIgnoreConstContext(ignore_const_context); bool auto_apply_fixits; if (this->auto_apply_fixits == eLazyBoolCalculate) diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h index 6fccf10e5dbc1..6bbe02f584b21 100644 --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -57,6 +57,7 @@ class CommandObjectExpression : public CommandObjectRaw, LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; LazyBool auto_apply_fixits; LazyBool suppress_persistent_result; + bool ignore_const_context; }; CommandObjectExpression(CommandInterpreter &interpreter); diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index d96354a39b8b8..c82a029ae95ce 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -778,6 +778,9 @@ let Command = "expression" in { Desc<"Persist expression result in a variable for subsequent use. " "Expression results will be labeled with $-prefixed variables, " "e.g. $0, $1, etc.">; + def ignore_const_context : Option<"ignore-const-context", "K">, + Groups<[1, 2]>, + Desc<"TODO">; } let Command = "frame diag" in { diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index ff7a356dbbb1e..d39bcced48390 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -290,34 +290,29 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, // If there is a fixed expression, try to parse it: if (!parse_success) { - // Delete the expression that failed to parse before attempting to parse - // the next expression. - user_expression_sp.reset(); - execution_results = lldb::eExpressionParseError; if (!fixed_expression->empty() && options.GetAutoApplyFixIts()) { const uint64_t max_fix_retries = options.GetRetriesWithFixIts(); for (uint64_t i = 0; i < max_fix_retries; ++i) { // Try parsing the fixed expression. - lldb::UserExpressionSP fixed_expression_sp( - target->GetUserExpressionForLanguage( - fixed_expression->c_str(), full_prefix, language, desired_type, - options, ctx_obj, error)); - if (!fixed_expression_sp) + user_expression_sp.reset(target->GetUserExpressionForLanguage( + fixed_expression->c_str(), full_prefix, language, desired_type, + options, ctx_obj, error)); + if (!user_expression_sp) break; + DiagnosticManager fixed_diagnostic_manager; - parse_success = fixed_expression_sp->Parse( + parse_success = user_expression_sp->Parse( fixed_diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info); if (parse_success) { diagnostic_manager.Clear(); - user_expression_sp = fixed_expression_sp; break; } // The fixed expression also didn't parse. Let's check for any new // fixits we could try. - if (!fixed_expression_sp->GetFixedText().empty()) { - *fixed_expression = fixed_expression_sp->GetFixedText().str(); + if (!user_expression_sp->GetFixedText().empty()) { + *fixed_expression = user_expression_sp->GetFixedText().str(); } else { // Fixed expression didn't compile without a fixit, don't retry and // don't tell the user about it. @@ -328,6 +323,9 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, } if (!parse_success) { + if (user_expression_sp) + user_expression_sp->FixupParseErrorDiagnostics(diagnostic_manager); + if (target->GetEnableNotifyAboutFixIts() && fixed_expression && !fixed_expression->empty()) { std::string fixit = diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 24a5dc5362964..52a77fbbac66a 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -88,10 +88,12 @@ ClangExpressionDeclMap::ClangExpressionDeclMap( bool keep_result_in_memory, Materializer::PersistentVariableDelegate *result_delegate, const lldb::TargetSP &target, - const std::shared_ptr<ClangASTImporter> &importer, ValueObject *ctx_obj) + const std::shared_ptr<ClangASTImporter> &importer, ValueObject *ctx_obj, + bool ignore_const_context) : ClangASTSource(target, importer), m_found_entities(), m_struct_members(), m_keep_result_in_memory(keep_result_in_memory), - m_result_delegate(result_delegate), m_ctx_obj(ctx_obj), m_parser_vars(), + m_result_delegate(result_delegate), m_ctx_obj(ctx_obj), + m_ignore_const_context(ignore_const_context), m_parser_vars(), m_struct_vars() { EnableStructVars(); } @@ -844,6 +846,12 @@ void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context) { QualType class_qual_type = m_ast_context->getCanonicalTagType(class_decl); + // The synthesized __lldb_expr will adopt the qualifiers from this class + // type. Make sure we use the qualifiers of the method that we're currently + // stopped in. + class_qual_type.addFastQualifiers( + method_decl->getMethodQualifiers().getFastQualifiers()); + TypeFromUser class_user_type( class_qual_type.getAsOpaquePtr(), function_decl_ctx.GetTypeSystem()->weak_from_this()); @@ -1991,7 +1999,8 @@ void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context, std::array<CompilerType, 1> args{void_clang_type.GetPointerType()}; CompilerType method_type = m_clang_ast_context->CreateFunctionType( - void_clang_type, args, false, 0); + void_clang_type, args, false, + m_ignore_const_context ? 0 : ut.GetTypeQualifiers()); const bool is_virtual = false; const bool is_static = false; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index dddc5a06c9051..3a5f702f6c674 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -82,7 +82,8 @@ class ClangExpressionDeclMap : public ClangASTSource { bool keep_result_in_memory, Materializer::PersistentVariableDelegate *result_delegate, const lldb::TargetSP &target, - const std::shared_ptr<ClangASTImporter> &importer, ValueObject *ctx_obj); + const std::shared_ptr<ClangASTImporter> &importer, ValueObject *ctx_obj, + bool ignore_const_context); /// Destructor ~ClangExpressionDeclMap() override; @@ -306,6 +307,8 @@ class ClangExpressionDeclMap : public ClangASTSource { ///For details see the comment to ///`UserExpression::Evaluate`. + bool m_ignore_const_context = false; + /// The following values should not live beyond parsing class ParserVars { public: diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index cfe187ffc4114..2c764d250d465 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -10,6 +10,7 @@ #include "ClangExpressionUtil.h" +#include "clang/AST/TypeBase.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" @@ -189,6 +190,28 @@ static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, } } +/// Return qualifers of the current C++ method. +static clang::Qualifiers GetFrameCVQualifiers(StackFrame *frame) { + if (!frame) + return {}; + + auto this_sp = frame->FindVariable(ConstString("this")); + if (!this_sp) + return {}; + + // Lambdas that capture 'this' have a member variable called 'this'. The class + // context of __lldb_expr for a lambda is the class type of the 'this' capture + // (not the anonymous lambda structure). So use the qualifiers of the captured + // 'this'. + if (auto this_this_sp = this_sp->GetChildMemberWithName("this")) + return clang::Qualifiers::fromCVRMask( + this_this_sp->GetCompilerType().GetPointeeType().GetTypeQualifiers()); + + // Not in a lambda. Return 'this' qualifiers. + return clang::Qualifiers::fromCVRMask( + this_sp->GetCompilerType().GetPointeeType().GetTypeQualifiers()); +} + lldb_private::ClangExpressionSourceCode::ClangExpressionSourceCode( llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix, llvm::StringRef body, Wrapping wrap, WrapKind wrap_kind) @@ -340,9 +363,12 @@ void ClangExpressionSourceCode::AddLocalVariableDecls(StreamString &stream, } } -bool ClangExpressionSourceCode::GetText( - std::string &text, ExecutionContext &exe_ctx, bool add_locals, - bool force_add_all_locals, llvm::ArrayRef<std::string> modules) const { +bool ClangExpressionSourceCode::GetText(std::string &text, + ExecutionContext &exe_ctx, + bool add_locals, + bool force_add_all_locals, + llvm::ArrayRef<std::string> modules, + bool ignore_const_context) const { const char *target_specific_defines = "typedef signed char BOOL;\n"; std::string module_macros; llvm::raw_string_ostream module_macros_stream(module_macros); @@ -464,13 +490,18 @@ bool ClangExpressionSourceCode::GetText( break; case WrapKind::CppMemberFunction: wrap_stream.Printf("%s" - "void \n" - "$__lldb_class::%s(void *$__lldb_arg) \n" - "{ \n" - " %s; \n" + "void \n" + "$__lldb_class::%s(void *$__lldb_arg) %s \n" + "{ \n" + " %s; \n" "%s" - "} \n", + "} \n", module_imports.c_str(), m_name.c_str(), + ignore_const_context + ? "" + : GetFrameCVQualifiers(exe_ctx.GetFramePtr()) + .getAsString() + .c_str(), lldb_local_var_decls.GetData(), tagged_body.c_str()); break; case WrapKind::ObjCInstanceMethod: diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h index f721bb2f319e1..02090b1aa9b12 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h @@ -63,8 +63,8 @@ class ClangExpressionSourceCode : public ExpressionSourceCode { /// /// \return true iff the source code was successfully generated. bool GetText(std::string &text, ExecutionContext &exe_ctx, bool add_locals, - bool force_add_all_locals, - llvm::ArrayRef<std::string> modules) const; + bool force_add_all_locals, llvm::ArrayRef<std::string> modules, + bool ignore_const_context) const; // Given a string returned by GetText, find the beginning and end of the body // passed to CreateWrapped. Return true if the bounds could be found. This diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 2cbbae11bd18a..5695e59ad08dc 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -27,6 +27,7 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" @@ -55,6 +56,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/BinaryFormat/Dwarf.h" @@ -416,7 +418,8 @@ void ClangUserExpression::CreateSourceCode( m_filename, prefix, m_expr_text, GetWrapKind())); if (!m_source_code->GetText(m_transformed_text, exe_ctx, !m_ctx_obj, - for_completion, modules_to_import)) { + for_completion, modules_to_import, + m_options.GetIgnoreConstContext())) { diagnostic_manager.PutString(lldb::eSeverityError, "couldn't construct expression body"); return; @@ -945,13 +948,49 @@ lldb::ExpressionVariableSP ClangUserExpression::GetResultAfterDematerialization( return m_result_delegate.GetVariable(); } +void ClangUserExpression::FixupParseErrorDiagnostics( + DiagnosticManager &diagnostic_manager) const { + const bool is_fixable_cvr_error = llvm::any_of( + diagnostic_manager.Diagnostics(), + [](std::unique_ptr<Diagnostic> const &diag) { + switch (diag->GetCompilerID()) { + ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/177927 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
