[Lldb-commits] [lldb] 584156d - [lldb][Expression] Add --c++-ignore-context-qualifiers expression evaluation option (#177926)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Feb 4 23:46:26 PST 2026
Author: Michael Buch
Date: 2026-02-05T07:46:20Z
New Revision: 584156d15d24c9b9f67aa7850e86ee2474a250c0
URL: https://github.com/llvm/llvm-project/commit/584156d15d24c9b9f67aa7850e86ee2474a250c0
DIFF: https://github.com/llvm/llvm-project/commit/584156d15d24c9b9f67aa7850e86ee2474a250c0.diff
LOG: [lldb][Expression] Add --c++-ignore-context-qualifiers expression evaluation option (#177926)
Depends on:
* https://github.com/llvm/llvm-project/pull/177920
* https://github.com/llvm/llvm-project/pull/177922
* https://github.com/llvm/llvm-project/pull/179208
(only commit d8676d0ed9286777e1a1e9f625389540cc42c231 and later are
relevant for this review)
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` minimally qualified, allowing it to call any
function/mutate any members.
Added:
Modified:
lldb/include/lldb/Target/Target.h
lldb/source/Commands/CommandObjectExpression.cpp
lldb/source/Commands/CommandObjectExpression.h
lldb/source/Commands/Options.td
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
lldb/source/Target/Target.cpp
lldb/test/API/lang/cpp/expression-context-qualifiers/const_method/TestExprInConstMethod.py
lldb/test/API/lang/cpp/expression-context-qualifiers/const_volatile_method/TestExprInConstVolatileMethod.py
lldb/test/API/lang/cpp/expression-context-qualifiers/non_const_method/TestExprInNonConstMethod.py
lldb/test/API/lang/cpp/expression-context-qualifiers/template_const_method/TestExprInTemplateConstMethod.py
lldb/test/API/lang/cpp/expression-context-qualifiers/template_non_const_method/TestExprInTemplateNonConstMethod.py
lldb/test/API/lang/cpp/this/TestCPPThis.py
lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index a79d0f1b6113e..f781c4dabdd9f 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/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 4919bd3639d3e..efc0df6cd738e 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':
+ cpp_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;
+ cpp_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.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 6fccf10e5dbc1..0439ddffce925 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 cpp_ignore_context_qualifiers;
};
CommandObjectExpression(CommandInterpreter &interpreter);
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index d96354a39b8b8..8e1b921f47c3d 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -778,6 +778,13 @@ 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<"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 "
+ "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/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..634cdec918057 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.GetCppIgnoreContextQualifiers())) {
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..7f1c1ddcad942 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.
@@ -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_type_system_helper.ResetDeclMap(
+ exe_ctx, result_delegate, keep_result_in_memory, m_ctx_obj,
+ m_options.GetCppIgnoreContextQualifiers());
}
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/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 301dbdc6da9be..d9e72cd5453e4 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 =
+ "c++-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 0d8f477dce1fd..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
@@ -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 --c++-ignore-context-qualifiers option.
+ self.expect(
+ "expression --c++-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 --c++-ignore-context-qualifiers via SBExpressionOptions.
+ options = lldb.SBExpressionOptions()
+ 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")
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..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
@@ -20,6 +20,16 @@ def test(self):
substrs=["has type 'const Foo'", "but function is not marked const"],
)
+ options = lldb.SBExpressionOptions()
+ options.SetBooleanLanguageOption("c++-ignore-context-qualifiers", True)
+ options.SetIgnoreBreakpoints(True)
+ self.expect_expr("volatile_method()", options=options)
+ self.expect(
+ "expression --c++-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 --c++-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 --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 835487f3bb7e0..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
@@ -36,6 +36,10 @@ def test(self):
],
)
+ options = lldb.SBExpressionOptions()
+ options.SetBooleanLanguageOption("c++-ignore-context-qualifiers", True)
+ 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..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
@@ -29,6 +29,10 @@ def test(self):
)
self.expect_expr("((Foo*)this)->bar()", result_type="double", result_value="5")
+ options = lldb.SBExpressionOptions()
+ 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(
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..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
@@ -36,6 +36,10 @@ def test(self):
],
)
+ options = lldb.SBExpressionOptions()
+ options.SetBooleanLanguageOption("c++-ignore-context-qualifiers", True)
+ 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..4c4db30589fbf 100644
--- a/lldb/test/API/lang/cpp/this/TestCPPThis.py
+++ b/lldb/test/API/lang/cpp/this/TestCPPThis.py
@@ -47,14 +47,18 @@ def test_with_run_command(self):
)
self.expect("expression -- (int)getpid(); m_a", startstr="(const int) $1 = 3")
+ self.expect(
+ "expression --c++-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();
}
More information about the lldb-commits
mailing list