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();
   }


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to