https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/177926
>From 5ab6fcca44f249df200f9bcc1deca16cc188f189 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Fri, 23 Jan 2026 14:49:56 +0000 Subject: [PATCH 1/9] [lldb][Expression] Add --ignore-const-context expression evaluation option Depends on: * https://github.com/llvm/llvm-project/pull/177920 * https://github.com/llvm/llvm-project/pull/177922 In https://github.com/llvm/llvm-project/pull/177922 we make expressions run in C++ member functions honor the function qualifiers of the current stop context. E.g., this means we can no longer run non-const member functions when stopped in a const-member function. To ensure users can still do this if they really need/want to, we provide an option to not honor the qualifiers at all, leaving the `__lldb_expr` as the least qualified, allowing it to call any function/mutate any members. --- lldb/include/lldb/Target/Target.h | 6 ++++ .../Commands/CommandObjectExpression.cpp | 5 +++ .../source/Commands/CommandObjectExpression.h | 1 + lldb/source/Commands/Options.td | 8 +++++ .../Clang/ClangExpressionDeclMap.cpp | 9 +++-- .../Clang/ClangExpressionDeclMap.h | 15 +++++++- .../Clang/ClangExpressionSourceCode.cpp | 34 +++++++++++-------- .../Clang/ClangExpressionSourceCode.h | 4 +-- .../Clang/ClangUserExpression.cpp | 9 ++--- .../Clang/ClangUserExpression.h | 8 ++--- .../Clang/ClangUtilityFunction.cpp | 2 +- .../const_method/TestExprInConstMethod.py | 30 +++++++++++++++- .../TestExprInConstVolatileMethod.py | 25 ++++++++++++++ .../TestExprInNonConstMethod.py | 4 +++ .../TestExprInTemplateConstMethod.py | 8 ++++- .../TestExprInTemplateNonConstMethod.py | 4 +++ lldb/test/API/lang/cpp/this/TestCPPThis.py | 7 ++-- .../Expression/ClangExpressionDeclMapTest.cpp | 2 +- 18 files changed, 147 insertions(+), 34 deletions(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index a79d0f1b6113e..5dea769bfc82b 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -539,6 +539,12 @@ 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; + + /// If true, evaluates the expression without taking into account the + /// CV-qualifiers of the scope. E.g., this would permit calling a + /// non-const C++ method when stopped in a const-method (which would be + /// disallowed by C++ language rules). + bool m_ignore_context_qualifierss = false; }; // Target diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 4919bd3639d3e..ab1dcd7d82cbf 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -44,6 +44,9 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue( const int short_option = GetDefinitions()[option_idx].short_option; switch (short_option) { + case 'Q': + ignore_context_qualifiers = true; + break; case 'l': language = Language::GetLanguageTypeFromString(option_arg); if (language == eLanguageTypeUnknown) { @@ -191,6 +194,7 @@ void CommandObjectExpression::CommandOptions::OptionParsingStarting( top_level = false; allow_jit = true; suppress_persistent_result = eLazyBoolCalculate; + ignore_context_qualifiers = false; } llvm::ArrayRef<OptionDefinition> @@ -213,6 +217,7 @@ CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions( options.SetExecutionPolicy( allow_jit ? EvaluateExpressionOptions::default_execution_policy : lldb_private::eExecutionPolicyNever); + options.SetIgnoreContextQualifiers(ignore_context_qualifiers); 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..6d60a674e5708 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_context_qualifiers; }; CommandObjectExpression(CommandInterpreter &interpreter); diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index d96354a39b8b8..c3dddd0f64c2c 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -778,6 +778,14 @@ 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_context_qualifiers + : Option<"ignore-context-qualifiers", "Q">, + Groups<[1, 2]>, + Desc<"When specified, evaluates the expression without taking into " + "account the type ${Q}ualifiers of the scope. E.g., this would " + "permit " + "calling a non-const C++ method when stopped in a const-method " + "(which would be disallowed by C++ language rules).">; } let Command = "frame diag" in { diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index b1f246f6690e7..9f4ccc60c0b34 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_context_qualifiers) : 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_context_qualifiers(ignore_context_qualifiers), m_parser_vars(), m_struct_vars() { EnableStructVars(); } @@ -1997,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, ut.GetTypeQualifiers()); + void_clang_type, args, false, + m_ignore_context_qualifiers ? 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 df74ebc37a5de..d44c95068f45d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -78,11 +78,18 @@ class ClangExpressionDeclMap : public ClangASTSource { /// \param[in] ctx_obj /// If not empty, then expression is evaluated in context of this object. /// See the comment to `UserExpression::Evaluate` for details. + /// + /// \param[in] ignore_context_qualifiers + /// If \c true, evaluates the expression without taking into account the + /// CV-qualifiers of the scope. E.g., this would permit calling a + /// non-const C++ method when stopped in a const-method (which would be + /// disallowed by C++ language rules). 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_context_qualifiers); /// Destructor ~ClangExpressionDeclMap() override; @@ -306,6 +313,12 @@ class ClangExpressionDeclMap : public ClangASTSource { ///For details see the comment to ///`UserExpression::Evaluate`. + /// If \c true, evaluates the expression without taking into account the + /// CV-qualifiers of the scope. E.g., this would permit calling a + /// non-const C++ method when stopped in a const-method (which would be + /// disallowed by C++ language rules). + bool m_ignore_context_qualifiers = 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 ca4199faa3841..c711367cb6177 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -363,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_context_qualifiers) const { const char *target_specific_defines = "typedef signed char BOOL;\n"; std::string module_macros; llvm::raw_string_ostream module_macros_stream(module_macros); @@ -486,17 +489,20 @@ bool ClangExpressionSourceCode::GetText( lldb_local_var_decls.GetData(), tagged_body.c_str()); break; case WrapKind::CppMemberFunction: - wrap_stream.Printf( - "%s" - "void \n" - "$__lldb_class::%s(void *$__lldb_arg) %s \n" - "{ \n" - " %s; \n" - "%s" - "} \n", - module_imports.c_str(), m_name.c_str(), - GetFrameCVQualifiers(exe_ctx.GetFramePtr()).getAsString().c_str(), - lldb_local_var_decls.GetData(), tagged_body.c_str()); + wrap_stream.Printf("%s" + "void \n" + "$__lldb_class::%s(void *$__lldb_arg) %s \n" + "{ \n" + " %s; \n" + "%s" + "} \n", + module_imports.c_str(), m_name.c_str(), + ignore_context_qualifiers + ? "" + : GetFrameCVQualifiers(exe_ctx.GetFramePtr()) + .getAsString() + .c_str(), + lldb_local_var_decls.GetData(), tagged_body.c_str()); break; case WrapKind::ObjCInstanceMethod: wrap_stream.Printf( diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h index f721bb2f319e1..914d405139193 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_context_qualifiers) 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..2436468569958 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -416,7 +416,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.GetIgnoreContextQualifiers())) { diagnostic_manager.PutString(lldb::eSeverityError, "couldn't construct expression body"); return; @@ -950,8 +951,8 @@ char ClangUserExpression::ClangUserExpressionHelper::ID; void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap( ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, - bool keep_result_in_memory, - ValueObject *ctx_obj) { + bool keep_result_in_memory, ValueObject *ctx_obj, + bool ignore_context_qualifiers) { std::shared_ptr<ClangASTImporter> ast_importer; auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeC); @@ -961,7 +962,7 @@ void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap( } m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>( keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(), ast_importer, - ctx_obj); + ctx_obj, ignore_context_qualifiers); } clang::ASTConsumer * diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index 7c0c6a0147e2a..b3c31529446ad 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -71,8 +71,8 @@ class ClangUserExpression : public LLVMUserExpression { void ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, - bool keep_result_in_memory, - ValueObject *ctx_obj); + bool keep_result_in_memory, ValueObject *ctx_obj, + bool ignore_context_qualifiers); /// Return the object that the parser should allow to access ASTs. May be /// NULL if the ASTs do not need to be transformed. @@ -167,8 +167,8 @@ class ClangUserExpression : public LLVMUserExpression { Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory) { m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, - keep_result_in_memory, - m_ctx_obj); + keep_result_in_memory, m_ctx_obj, + m_options.GetIgnoreContextQualifiers()); } lldb::ExpressionVariableSP diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index e6983066a12fa..112ce9be7bd1a 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -187,5 +187,5 @@ void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap( } m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>( keep_result_in_memory, nullptr, exe_ctx.GetTargetSP(), ast_importer, - nullptr); + nullptr, /*ignore_context_qualifiers=*/false); } diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py index 0d8f477dce1fd..d73b6563b29a6 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py @@ -27,6 +27,26 @@ def test(self): "cannot assign to non-static data member within const member function" ], ) + self.expect_expr("m_mem", result_value="-2") + + # Test short and long --ignore-context-qualifiers option. + self.expect( + "expression --ignore-context-qualifiers -- m_mem = 3.0", + error=False, + ) + self.expect_expr("m_mem", result_value="3") + + self.expect( + "expression -Q -- m_mem = 4.0", + error=False, + ) + self.expect_expr("m_mem", result_value="4") + + # Test --ignore-context-qualifiers via SBExpressionOptions. + options = lldb.SBExpressionOptions() + options.SetIgnoreContextQualifiers() + self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") + self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") lldbutil.continue_to_source_breakpoint( @@ -43,6 +63,9 @@ def test(self): "cannot assign to non-static data member within const member function" ], ) + self.expect_expr("x", result_value="2") + + self.expect_expr("x = -5; x", options=options, result_value="-5") lldbutil.continue_to_source_breakpoint( self, @@ -76,6 +99,9 @@ def test(self): ], ) self.expect_expr("m_mem", result_value="-2") + + self.expect_expr("m_mem = -1; m_mem", options=options, result_value="-1") + self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") lldbutil.continue_to_source_breakpoint( @@ -102,4 +128,6 @@ def test(self): "cannot assign to non-static data member within const member function" ], ) - self.expect_expr("m_mem", result_value="-2") + self.expect_expr("m_mem", result_value="-1") + + self.expect_expr("m_mem = -2; m_mem", options=options, result_value="-2") diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py index f20b9d8164841..0069b42f5da10 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py @@ -20,6 +20,16 @@ def test(self): substrs=["has type 'const Foo'", "but function is not marked const"], ) + options = lldb.SBExpressionOptions() + options.SetIgnoreContextQualifiers() + options.SetIgnoreBreakpoints(True) + self.expect_expr("volatile_method()", options=options) + self.expect( + "expression --ignore-context-qualifiers -- bar()", + error=True, + substrs=["call to member function 'bar' is ambiguous"], + ) + lldbutil.continue_to_source_breakpoint( self, process, "Break here: volatile", lldb.SBFileSpec("main.cpp") ) @@ -35,6 +45,13 @@ def test(self): ) self.expect_expr("volatile_method()") + self.expect_expr("const_method()", options=options) + self.expect( + "expression --ignore-context-qualifiers -- bar()", + error=True, + substrs=["call to member function 'bar' is ambiguous"], + ) + lldbutil.continue_to_source_breakpoint( self, process, "Break here: const volatile", lldb.SBFileSpec("main.cpp") ) @@ -58,3 +75,11 @@ def test(self): "but function is not marked const or volatile", ], ) + + self.expect_expr("const_method()", options=options) + self.expect_expr("volatile_method()", options=options) + self.expect( + "expression --ignore-context-qualifiers -- bar()", + error=True, + substrs=["call to member function 'bar' is ambiguous"], + ) diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py index 835487f3bb7e0..78fe27508d10f 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py @@ -36,6 +36,10 @@ def test(self): ], ) + options = lldb.SBExpressionOptions() + options.SetIgnoreContextQualifiers() + self.expect_expr("x = 6.0; x", options=options, result_value="6") + lldbutil.continue_to_source_breakpoint( self, process, diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py index 0d8f477dce1fd..8489f09b69bba 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py @@ -29,6 +29,10 @@ def test(self): ) self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") + options = lldb.SBExpressionOptions() + options.SetIgnoreContextQualifiers() + self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") + lldbutil.continue_to_source_breakpoint( self, process, @@ -43,6 +47,7 @@ def test(self): "cannot assign to non-static data member within const member function" ], ) + self.expect_expr("x = -7.0; x", options=options, result_value="-7") lldbutil.continue_to_source_breakpoint( self, @@ -77,6 +82,7 @@ def test(self): ) self.expect_expr("m_mem", result_value="-2") self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") + self.expect_expr("m_mem = -8.0; m_mem", options=options, result_value="-8") lldbutil.continue_to_source_breakpoint( self, @@ -102,4 +108,4 @@ def test(self): "cannot assign to non-static data member within const member function" ], ) - self.expect_expr("m_mem", result_value="-2") + self.expect_expr("m_mem = -11.0; m_mem", options=options, result_value="-11") diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py index 835487f3bb7e0..78fe27508d10f 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py @@ -36,6 +36,10 @@ def test(self): ], ) + options = lldb.SBExpressionOptions() + options.SetIgnoreContextQualifiers() + self.expect_expr("x = 6.0; x", options=options, result_value="6") + lldbutil.continue_to_source_breakpoint( self, process, diff --git a/lldb/test/API/lang/cpp/this/TestCPPThis.py b/lldb/test/API/lang/cpp/this/TestCPPThis.py index f127f80663578..5a59bf3631e82 100644 --- a/lldb/test/API/lang/cpp/this/TestCPPThis.py +++ b/lldb/test/API/lang/cpp/this/TestCPPThis.py @@ -47,14 +47,17 @@ def test_with_run_command(self): ) self.expect("expression -- (int)getpid(); m_a", startstr="(const int) $1 = 3") + self.expect( + "expression --ignore-context-qualifiers -- m_a = 2", startstr="(int) $2 = 2" + ) self.runCmd("process continue") - self.expect("expression -- s_a", startstr="(int) $2 = 5") + self.expect("expression -- s_a", startstr="(int) $3 = 5") self.runCmd("process continue") - self.expect("expression -- m_a", startstr="(int) $3 = 3") + self.expect("expression -- m_a", startstr="(int) $4 = 2") def set_breakpoint(self, line): lldbutil.run_break_set_by_file_and_line( diff --git a/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp b/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp index 1c07119d4497f..61905ee8df862 100644 --- a/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp +++ b/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp @@ -23,7 +23,7 @@ namespace { struct FakeClangExpressionDeclMap : public ClangExpressionDeclMap { FakeClangExpressionDeclMap(const std::shared_ptr<ClangASTImporter> &importer) : ClangExpressionDeclMap(false, nullptr, lldb::TargetSP(), importer, - nullptr) { + nullptr, /*ignore_context_qualifiers=*/false) { m_holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); m_scratch_context = m_holder->GetAST(); } >From 78effdfaeb729da8332a760a0a99c99405619874 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Fri, 30 Jan 2026 11:12:13 +0000 Subject: [PATCH 2/9] fixup! rename option to more c++ specific name --- lldb/include/lldb/Target/Target.h | 4 +++- lldb/source/Commands/CommandObjectExpression.cpp | 6 +++--- lldb/source/Commands/CommandObjectExpression.h | 2 +- lldb/source/Commands/Options.td | 9 ++++----- .../ExpressionParser/Clang/ClangUserExpression.cpp | 2 +- .../Plugins/ExpressionParser/Clang/ClangUserExpression.h | 6 +++--- .../const_method/TestExprInConstMethod.py | 6 +++--- .../TestExprInConstVolatileMethod.py | 8 ++++---- .../non_const_method/TestExprInNonConstMethod.py | 2 +- .../TestExprInTemplateConstMethod.py | 2 +- .../TestExprInTemplateNonConstMethod.py | 2 +- lldb/test/API/lang/cpp/this/TestCPPThis.py | 2 +- 12 files changed, 26 insertions(+), 25 deletions(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 5dea769bfc82b..6181da9041566 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -544,7 +544,9 @@ class EvaluateExpressionOptions { /// CV-qualifiers of the scope. E.g., this would permit calling a /// non-const C++ method when stopped in a const-method (which would be /// disallowed by C++ language rules). - bool m_ignore_context_qualifierss = false; + /// + /// FIXME: move this to a language-specific dictionary of options. + bool m_cpp_ignore_context_qualifierss = false; }; // Target diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index ab1dcd7d82cbf..efc0df6cd738e 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -45,7 +45,7 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue( switch (short_option) { case 'Q': - ignore_context_qualifiers = true; + cpp_ignore_context_qualifiers = true; break; case 'l': language = Language::GetLanguageTypeFromString(option_arg); @@ -194,7 +194,7 @@ void CommandObjectExpression::CommandOptions::OptionParsingStarting( top_level = false; allow_jit = true; suppress_persistent_result = eLazyBoolCalculate; - ignore_context_qualifiers = false; + cpp_ignore_context_qualifiers = false; } llvm::ArrayRef<OptionDefinition> @@ -217,7 +217,7 @@ CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions( options.SetExecutionPolicy( allow_jit ? EvaluateExpressionOptions::default_execution_policy : lldb_private::eExecutionPolicyNever); - options.SetIgnoreContextQualifiers(ignore_context_qualifiers); + options.SetCppIgnoreContextQualifiers(cpp_ignore_context_qualifiers); 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 6d60a674e5708..0439ddffce925 100644 --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -57,7 +57,7 @@ class CommandObjectExpression : public CommandObjectRaw, LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; LazyBool auto_apply_fixits; LazyBool suppress_persistent_result; - bool ignore_context_qualifiers; + bool cpp_ignore_context_qualifiers; }; CommandObjectExpression(CommandInterpreter &interpreter); diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index c3dddd0f64c2c..72bb5df4dddac 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -779,13 +779,12 @@ let Command = "expression" in { "Expression results will be labeled with $-prefixed variables, " "e.g. $0, $1, etc.">; def ignore_context_qualifiers - : Option<"ignore-context-qualifiers", "Q">, + : Option<"cpp-ignore-context-qualifiers", "Q">, Groups<[1, 2]>, Desc<"When specified, evaluates the expression without taking into " - "account the type ${Q}ualifiers of the scope. E.g., this would " - "permit " - "calling a non-const C++ method when stopped in a const-method " - "(which would be disallowed by C++ language rules).">; + "account the type ${Q}ualifiers of the scope. In C++, this would " + "permit calling a non-const method when stopped in a const-method " + "(which would be disallowed by language rules).">; } let Command = "frame diag" in { diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 2436468569958..634cdec918057 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -417,7 +417,7 @@ void ClangUserExpression::CreateSourceCode( if (!m_source_code->GetText(m_transformed_text, exe_ctx, !m_ctx_obj, for_completion, modules_to_import, - m_options.GetIgnoreContextQualifiers())) { + m_options.GetCppIgnoreContextQualifiers())) { diagnostic_manager.PutString(lldb::eSeverityError, "couldn't construct expression body"); return; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index b3c31529446ad..7f1c1ddcad942 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -166,9 +166,9 @@ class ClangUserExpression : public LLVMUserExpression { void ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory) { - m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, - keep_result_in_memory, m_ctx_obj, - m_options.GetIgnoreContextQualifiers()); + m_type_system_helper.ResetDeclMap( + exe_ctx, result_delegate, keep_result_in_memory, m_ctx_obj, + m_options.GetCppIgnoreContextQualifiers()); } lldb::ExpressionVariableSP diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py index d73b6563b29a6..b501836a46483 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py @@ -29,9 +29,9 @@ def test(self): ) self.expect_expr("m_mem", result_value="-2") - # Test short and long --ignore-context-qualifiers option. + # Test short and long --cpp-ignore-context-qualifiers option. self.expect( - "expression --ignore-context-qualifiers -- m_mem = 3.0", + "expression --cpp-ignore-context-qualifiers -- m_mem = 3.0", error=False, ) self.expect_expr("m_mem", result_value="3") @@ -42,7 +42,7 @@ def test(self): ) self.expect_expr("m_mem", result_value="4") - # Test --ignore-context-qualifiers via SBExpressionOptions. + # Test --cpp-ignore-context-qualifiers via SBExpressionOptions. options = lldb.SBExpressionOptions() options.SetIgnoreContextQualifiers() self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py index 0069b42f5da10..40e5bff0aa60c 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py @@ -21,11 +21,11 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetIgnoreContextQualifiers() + options.SetCppIgnoreContextQualifiers() options.SetIgnoreBreakpoints(True) self.expect_expr("volatile_method()", options=options) self.expect( - "expression --ignore-context-qualifiers -- bar()", + "expression --cpp-ignore-context-qualifiers -- bar()", error=True, substrs=["call to member function 'bar' is ambiguous"], ) @@ -47,7 +47,7 @@ def test(self): self.expect_expr("const_method()", options=options) self.expect( - "expression --ignore-context-qualifiers -- bar()", + "expression --cpp-ignore-context-qualifiers -- bar()", error=True, substrs=["call to member function 'bar' is ambiguous"], ) @@ -79,7 +79,7 @@ def test(self): self.expect_expr("const_method()", options=options) self.expect_expr("volatile_method()", options=options) self.expect( - "expression --ignore-context-qualifiers -- bar()", + "expression --cpp-ignore-context-qualifiers -- bar()", error=True, substrs=["call to member function 'bar' is ambiguous"], ) diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py index 78fe27508d10f..c26239adb34ca 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py @@ -37,7 +37,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetIgnoreContextQualifiers() + options.SetCppIgnoreContextQualifiers() self.expect_expr("x = 6.0; x", options=options, result_value="6") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py index 8489f09b69bba..e4cd5ea759f60 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py @@ -30,7 +30,7 @@ def test(self): self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") options = lldb.SBExpressionOptions() - options.SetIgnoreContextQualifiers() + options.SetCppIgnoreContextQualifiers() self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py index 78fe27508d10f..c26239adb34ca 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py @@ -37,7 +37,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetIgnoreContextQualifiers() + options.SetCppIgnoreContextQualifiers() self.expect_expr("x = 6.0; x", options=options, result_value="6") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/this/TestCPPThis.py b/lldb/test/API/lang/cpp/this/TestCPPThis.py index 5a59bf3631e82..cb462b0ae68de 100644 --- a/lldb/test/API/lang/cpp/this/TestCPPThis.py +++ b/lldb/test/API/lang/cpp/this/TestCPPThis.py @@ -48,7 +48,7 @@ def test_with_run_command(self): self.expect("expression -- (int)getpid(); m_a", startstr="(const int) $1 = 3") self.expect( - "expression --ignore-context-qualifiers -- m_a = 2", startstr="(int) $2 = 2" + "expression --cpp-ignore-context-qualifiers -- m_a = 2", startstr="(int) $2 = 2" ) self.runCmd("process continue") >From db397cbcc61c9966ae480e68ad01c422cca91445 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Fri, 30 Jan 2026 11:21:53 +0000 Subject: [PATCH 3/9] fixup! python format --- lldb/test/API/lang/cpp/this/TestCPPThis.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/test/API/lang/cpp/this/TestCPPThis.py b/lldb/test/API/lang/cpp/this/TestCPPThis.py index cb462b0ae68de..3d87eba8fe05a 100644 --- a/lldb/test/API/lang/cpp/this/TestCPPThis.py +++ b/lldb/test/API/lang/cpp/this/TestCPPThis.py @@ -48,7 +48,8 @@ def test_with_run_command(self): self.expect("expression -- (int)getpid(); m_a", startstr="(const int) $1 = 3") self.expect( - "expression --cpp-ignore-context-qualifiers -- m_a = 2", startstr="(int) $2 = 2" + "expression --cpp-ignore-context-qualifiers -- m_a = 2", + startstr="(int) $2 = 2", ) self.runCmd("process continue") >From 2254e5f94333cfb7312bc360b35b80665121f81e Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Fri, 30 Jan 2026 11:24:16 +0000 Subject: [PATCH 4/9] fixup! fix typo --- lldb/include/lldb/Target/Target.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 6181da9041566..daaef03c0d1ef 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -546,7 +546,7 @@ class EvaluateExpressionOptions { /// disallowed by C++ language rules). /// /// FIXME: move this to a language-specific dictionary of options. - bool m_cpp_ignore_context_qualifierss = false; + bool m_cpp_ignore_context_qualifiers = false; }; // Target >From 5c7f16fcdff8999deeebe17e2ea90c29a66788bb Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Fri, 30 Jan 2026 12:40:41 +0000 Subject: [PATCH 5/9] fixup! rename option --- .../const_method/TestExprInConstMethod.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py index b501836a46483..74a68aae4817a 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py @@ -44,7 +44,7 @@ def test(self): # Test --cpp-ignore-context-qualifiers via SBExpressionOptions. options = lldb.SBExpressionOptions() - options.SetIgnoreContextQualifiers() + options.SetCppIgnoreContextQualifiers() self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") >From dbe0688a0f45c30814d0e253244fb293724de16c Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Wed, 4 Feb 2026 15:32:43 +0000 Subject: [PATCH 6/9] fixup! rebase on new (S|G)etBooleanLanguageOption APIs --- lldb/include/lldb/Target/Target.h | 7 +++++-- lldb/source/Target/Target.cpp | 20 +++++++++++++++++++ .../const_method/TestExprInConstMethod.py | 2 +- .../TestExprInConstVolatileMethod.py | 2 +- .../TestExprInNonConstMethod.py | 2 +- .../TestExprInTemplateConstMethod.py | 2 +- .../TestExprInTemplateNonConstMethod.py | 2 +- 7 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index daaef03c0d1ef..264074728faad 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -308,8 +308,7 @@ class TargetProperties : public Properties { class EvaluateExpressionOptions { public: - EvaluateExpressionOptions() - : m_language_options_sp(std::make_shared<StructuredData::Dictionary>()) {} + EvaluateExpressionOptions(); // MSVC has a bug here that reports C4268: 'const' static/global data // initialized with compiler generated default constructor fills the object @@ -494,6 +493,10 @@ class EvaluateExpressionOptions { llvm::Expected<bool> GetBooleanLanguageOption(llvm::StringRef option_name) const; + void SetCppIgnoreContextQualifiers(bool value); + + bool GetCppIgnoreContextQualifiers() const; + private: const StructuredData::Dictionary &GetLanguageOptions() const; diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 301dbdc6da9be..42fd9eb92157c 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -5409,3 +5409,23 @@ StructuredData::Dictionary &EvaluateExpressionOptions::GetLanguageOptions() { return *m_language_options_sp; } + +// FIXME: this option is C++ plugin specific and should be registered by it, +// instead of hard-coding it here. +constexpr llvm::StringLiteral s_cpp_ignore_context_qualifiers_option = + "cpp-ignore-context-qualifiers"; + +EvaluateExpressionOptions::EvaluateExpressionOptions() + : m_language_options_sp(std::make_shared<StructuredData::Dictionary>()) { + SetCppIgnoreContextQualifiers(false); +} + +void EvaluateExpressionOptions::SetCppIgnoreContextQualifiers(bool value) { + llvm::cantFail( + SetBooleanLanguageOption(s_cpp_ignore_context_qualifiers_option, value)); +} + +bool EvaluateExpressionOptions::GetCppIgnoreContextQualifiers() const { + return llvm::cantFail( + GetBooleanLanguageOption(s_cpp_ignore_context_qualifiers_option)); +} diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py index 74a68aae4817a..c0f945d05340e 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py @@ -44,7 +44,7 @@ def test(self): # Test --cpp-ignore-context-qualifiers via SBExpressionOptions. options = lldb.SBExpressionOptions() - options.SetCppIgnoreContextQualifiers() + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py index 40e5bff0aa60c..ab4a141cc3581 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py @@ -21,7 +21,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetCppIgnoreContextQualifiers() + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") options.SetIgnoreBreakpoints(True) self.expect_expr("volatile_method()", options=options) self.expect( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py index c26239adb34ca..179415c927397 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py @@ -37,7 +37,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetCppIgnoreContextQualifiers() + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") self.expect_expr("x = 6.0; x", options=options, result_value="6") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py index e4cd5ea759f60..c3f5f732ddf4f 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py @@ -30,7 +30,7 @@ def test(self): self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") options = lldb.SBExpressionOptions() - options.SetCppIgnoreContextQualifiers() + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py index c26239adb34ca..179415c927397 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py @@ -37,7 +37,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetCppIgnoreContextQualifiers() + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") self.expect_expr("x = 6.0; x", options=options, result_value="6") lldbutil.continue_to_source_breakpoint( >From 14020df8aeadc7ffb4591297c4f1c2d4e1163eb7 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Wed, 4 Feb 2026 16:40:44 +0000 Subject: [PATCH 7/9] fixup! remove unused member variable --- lldb/include/lldb/Target/Target.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 264074728faad..f781c4dabdd9f 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -542,14 +542,6 @@ 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; - - /// If true, evaluates the expression without taking into account the - /// CV-qualifiers of the scope. E.g., this would permit calling a - /// non-const C++ method when stopped in a const-method (which would be - /// disallowed by C++ language rules). - /// - /// FIXME: move this to a language-specific dictionary of options. - bool m_cpp_ignore_context_qualifiers = false; }; // Target >From b17008dfc9fb28dff86de1b307e8b6d155c34150 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Wed, 4 Feb 2026 17:01:43 +0000 Subject: [PATCH 8/9] fixup! fix tests --- .../const_method/TestExprInConstMethod.py | 2 +- .../const_volatile_method/TestExprInConstVolatileMethod.py | 2 +- .../non_const_method/TestExprInNonConstMethod.py | 2 +- .../template_const_method/TestExprInTemplateConstMethod.py | 2 +- .../TestExprInTemplateNonConstMethod.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py index c0f945d05340e..233ad5947848d 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py @@ -44,7 +44,7 @@ def test(self): # Test --cpp-ignore-context-qualifiers via SBExpressionOptions. options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py index ab4a141cc3581..3b938d2f13119 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py @@ -21,7 +21,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) options.SetIgnoreBreakpoints(True) self.expect_expr("volatile_method()", options=options) self.expect( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py index 179415c927397..39150d6031500 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py @@ -37,7 +37,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) self.expect_expr("x = 6.0; x", options=options, result_value="6") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py index c3f5f732ddf4f..7fac61f65ba3b 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py @@ -30,7 +30,7 @@ def test(self): self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py index 179415c927397..39150d6031500 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py @@ -37,7 +37,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers") + options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) self.expect_expr("x = 6.0; x", options=options, result_value="6") lldbutil.continue_to_source_breakpoint( >From d5ac01d53e6be171c2ce9084a394a2459cd6a39d Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Wed, 4 Feb 2026 23:35:28 +0000 Subject: [PATCH 9/9] fixup! cpp -> c++ --- lldb/source/Commands/Options.td | 2 +- lldb/source/Target/Target.cpp | 2 +- .../const_method/TestExprInConstMethod.py | 8 ++++---- .../TestExprInConstVolatileMethod.py | 8 ++++---- .../non_const_method/TestExprInNonConstMethod.py | 2 +- .../TestExprInTemplateConstMethod.py | 2 +- .../TestExprInTemplateNonConstMethod.py | 2 +- lldb/test/API/lang/cpp/this/TestCPPThis.py | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 72bb5df4dddac..8e1b921f47c3d 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -779,7 +779,7 @@ let Command = "expression" in { "Expression results will be labeled with $-prefixed variables, " "e.g. $0, $1, etc.">; def ignore_context_qualifiers - : Option<"cpp-ignore-context-qualifiers", "Q">, + : Option<"c++-ignore-context-qualifiers", "Q">, Groups<[1, 2]>, Desc<"When specified, evaluates the expression without taking into " "account the type ${Q}ualifiers of the scope. In C++, this would " diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 42fd9eb92157c..d9e72cd5453e4 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -5413,7 +5413,7 @@ StructuredData::Dictionary &EvaluateExpressionOptions::GetLanguageOptions() { // FIXME: this option is C++ plugin specific and should be registered by it, // instead of hard-coding it here. constexpr llvm::StringLiteral s_cpp_ignore_context_qualifiers_option = - "cpp-ignore-context-qualifiers"; + "c++-ignore-context-qualifiers"; EvaluateExpressionOptions::EvaluateExpressionOptions() : m_language_options_sp(std::make_shared<StructuredData::Dictionary>()) { diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py index 233ad5947848d..25c76b69aa3ab 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py @@ -29,9 +29,9 @@ def test(self): ) self.expect_expr("m_mem", result_value="-2") - # Test short and long --cpp-ignore-context-qualifiers option. + # Test short and long --c++-ignore-context-qualifiers option. self.expect( - "expression --cpp-ignore-context-qualifiers -- m_mem = 3.0", + "expression --c++-ignore-context-qualifiers -- m_mem = 3.0", error=False, ) self.expect_expr("m_mem", result_value="3") @@ -42,9 +42,9 @@ def test(self): ) self.expect_expr("m_mem", result_value="4") - # Test --cpp-ignore-context-qualifiers via SBExpressionOptions. + # Test --c++-ignore-context-qualifiers via SBExpressionOptions. options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) + options.SetBooleanLanguageOption("c++-ignore-context-qualifiers", True) self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py index 3b938d2f13119..f1bcfb3c0827d 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py @@ -21,11 +21,11 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) + options.SetBooleanLanguageOption("c++-ignore-context-qualifiers", True) options.SetIgnoreBreakpoints(True) self.expect_expr("volatile_method()", options=options) self.expect( - "expression --cpp-ignore-context-qualifiers -- bar()", + "expression --c++-ignore-context-qualifiers -- bar()", error=True, substrs=["call to member function 'bar' is ambiguous"], ) @@ -47,7 +47,7 @@ def test(self): self.expect_expr("const_method()", options=options) self.expect( - "expression --cpp-ignore-context-qualifiers -- bar()", + "expression --c++-ignore-context-qualifiers -- bar()", error=True, substrs=["call to member function 'bar' is ambiguous"], ) @@ -79,7 +79,7 @@ def test(self): self.expect_expr("const_method()", options=options) self.expect_expr("volatile_method()", options=options) self.expect( - "expression --cpp-ignore-context-qualifiers -- bar()", + "expression --c++-ignore-context-qualifiers -- bar()", error=True, substrs=["call to member function 'bar' is ambiguous"], ) diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py index 39150d6031500..f6358d2037095 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py @@ -37,7 +37,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) + options.SetBooleanLanguageOption("c++-ignore-context-qualifiers", True) self.expect_expr("x = 6.0; x", options=options, result_value="6") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py index 7fac61f65ba3b..cdaa06b8808b5 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py @@ -30,7 +30,7 @@ def test(self): self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5") options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) + options.SetBooleanLanguageOption("c++-ignore-context-qualifiers", True) self.expect_expr("m_mem = -2.0; m_mem", options=options, result_value="-2") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py index 39150d6031500..f6358d2037095 100644 --- a/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py +++ b/lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py @@ -37,7 +37,7 @@ def test(self): ) options = lldb.SBExpressionOptions() - options.SetBooleanLanguageOption("cpp-ignore-context-qualifiers", True) + options.SetBooleanLanguageOption("c++-ignore-context-qualifiers", True) self.expect_expr("x = 6.0; x", options=options, result_value="6") lldbutil.continue_to_source_breakpoint( diff --git a/lldb/test/API/lang/cpp/this/TestCPPThis.py b/lldb/test/API/lang/cpp/this/TestCPPThis.py index 3d87eba8fe05a..4c4db30589fbf 100644 --- a/lldb/test/API/lang/cpp/this/TestCPPThis.py +++ b/lldb/test/API/lang/cpp/this/TestCPPThis.py @@ -48,7 +48,7 @@ def test_with_run_command(self): self.expect("expression -- (int)getpid(); m_a", startstr="(const int) $1 = 3") self.expect( - "expression --cpp-ignore-context-qualifiers -- m_a = 2", + "expression --c++-ignore-context-qualifiers -- m_a = 2", startstr="(int) $2 = 2", ) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
