Author: Ilia Kuklin
Date: 2026-02-13T18:34:58+05:00
New Revision: 80fffd527c20ac8970fbffc37c674caa17faa815

URL: 
https://github.com/llvm/llvm-project/commit/80fffd527c20ac8970fbffc37c674caa17faa815
DIFF: 
https://github.com/llvm/llvm-project/commit/80fffd527c20ac8970fbffc37c674caa17faa815.diff

LOG: [lldb] Add evaluation modes to DIL (#178747)

Adding more supported operators to DIL breaks tests in `DWIMPrint` and
`lldb-dap`, which shouldn't be simply adjusted for new DIL capabilities.
They act as a check for the boundaries of what subset of expressions
`DWIMPrint` and `lldb-dap` expect to be evaluated when using
`GetValueForVariableExpressionPath` function. With this patch, the
caller can now pick a mode that limits the expressions DIL can evaluate,
which ensures the expected preexisting behavior. More operators can now
be safely added to DIL, which can still be evaluated by DIL when using
`frame var` command or the API call with Full mode selected (or not
specified at all).

DIL will only attempt evaluating expressions that contain operations
allowed by a selected mode:
 - Simple: identifiers, operators: '.'
 - Legacy: identifiers, integers, operators: '.', '->', '*', '&', '[]'
 - Full: everything supported by DIL

Added: 
    

Modified: 
    lldb/include/lldb/API/SBFrame.h
    lldb/include/lldb/Target/BorrowedStackFrame.h
    lldb/include/lldb/Target/StackFrame.h
    lldb/include/lldb/ValueObject/DILLexer.h
    lldb/include/lldb/lldb-enumerations.h
    lldb/source/API/SBFrame.cpp
    lldb/source/Commands/CommandObjectDWIMPrint.cpp
    lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
    lldb/source/Plugins/Process/scripted/ScriptedFrame.h
    lldb/source/Target/BorrowedStackFrame.cpp
    lldb/source/Target/StackFrame.cpp
    lldb/source/ValueObject/DILLexer.cpp
    
lldb/test/API/commands/frame/var-dil/basics/AddressOf/TestFrameVarDILAddressOf.py
    
lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
    
lldb/test/API/commands/frame/var-dil/basics/LocalVars/TestFrameVarDILLocalVars.py
    
lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py
    
lldb/test/API/commands/frame/var-dil/basics/PointerDereference/TestFrameVarDILPointerDereference.py
    lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py
    lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
    lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
    lldb/tools/lldb-dap/SourceBreakpoint.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h
index 5283cdfe53faa..eaf9a4bfece96 100644
--- a/lldb/include/lldb/API/SBFrame.h
+++ b/lldb/include/lldb/API/SBFrame.h
@@ -182,12 +182,16 @@ class LLDB_API SBFrame {
   // expression result and is not a constant object like
   // SBFrame::EvaluateExpression(...) returns, but a child object of the
   // variable value.
-  lldb::SBValue GetValueForVariablePath(const char *var_expr_cstr,
-                                        DynamicValueType use_dynamic);
+  lldb::SBValue
+  GetValueForVariablePath(const char *var_expr_cstr,
+                          DynamicValueType use_dynamic,
+                          lldb::DILMode mode = lldb::eDILModeFull);
 
   /// The version that doesn't supply a 'use_dynamic' value will use the
   /// target's default.
-  lldb::SBValue GetValueForVariablePath(const char *var_path);
+  lldb::SBValue
+  GetValueForVariablePath(const char *var_path,
+                          lldb::DILMode mode = lldb::eDILModeFull);
 
   /// Find variables, register sets, registers, or persistent variables using
   /// the frame as the scope.

diff  --git a/lldb/include/lldb/Target/BorrowedStackFrame.h 
b/lldb/include/lldb/Target/BorrowedStackFrame.h
index 72e7777961da7..2a34f2816aed2 100644
--- a/lldb/include/lldb/Target/BorrowedStackFrame.h
+++ b/lldb/include/lldb/Target/BorrowedStackFrame.h
@@ -86,7 +86,8 @@ class BorrowedStackFrame : public StackFrame {
 
   lldb::ValueObjectSP GetValueForVariableExpressionPath(
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
-      uint32_t options, lldb::VariableSP &var_sp, Status &error) override;
+      uint32_t options, lldb::VariableSP &var_sp, Status &error,
+      lldb::DILMode mode = lldb::eDILModeFull) override;
 
   bool HasDebugInformation() override;
 

diff  --git a/lldb/include/lldb/Target/StackFrame.h 
b/lldb/include/lldb/Target/StackFrame.h
index 5cba9afe2a7e8..c114cd2a13fdf 100644
--- a/lldb/include/lldb/Target/StackFrame.h
+++ b/lldb/include/lldb/Target/StackFrame.h
@@ -316,11 +316,16 @@ class StackFrame : public ExecutionContextScope,
   /// \param[in] error
   ///     Record any errors encountered while evaluating var_expr.
   ///
+  /// \param[in] mode
+  ///     Data Inspection Language (DIL) evaluation mode.
+  ///     \see lldb::DILMode
+  ///
   /// \return
   ///     A shared pointer to the ValueObject described by var_expr.
   virtual lldb::ValueObjectSP GetValueForVariableExpressionPath(
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
-      uint32_t options, lldb::VariableSP &var_sp, Status &error);
+      uint32_t options, lldb::VariableSP &var_sp, Status &error,
+      lldb::DILMode mode = lldb::eDILModeFull);
 
   /// Determine whether this StackFrame has debug information available or not.
   ///
@@ -615,7 +620,8 @@ class StackFrame : public ExecutionContextScope,
 
   lldb::ValueObjectSP DILGetValueForVariableExpressionPath(
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
-      uint32_t options, lldb::VariableSP &var_sp, Status &error);
+      uint32_t options, lldb::VariableSP &var_sp, Status &error,
+      lldb::DILMode mode = lldb::eDILModeFull);
 
   StackFrame(const StackFrame &) = delete;
   const StackFrame &operator=(const StackFrame &) = delete;

diff  --git a/lldb/include/lldb/ValueObject/DILLexer.h 
b/lldb/include/lldb/ValueObject/DILLexer.h
index 47b117de7b80d..a927aa236377e 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -9,6 +9,7 @@
 #ifndef LLDB_VALUEOBJECT_DILLEXER_H
 #define LLDB_VALUEOBJECT_DILLEXER_H
 
+#include "lldb/lldb-enumerations.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -74,7 +75,8 @@ class DILLexer {
 public:
   /// Lexes all the tokens in expr and calls the private constructor
   /// with the lexed tokens.
-  static llvm::Expected<DILLexer> Create(llvm::StringRef expr);
+  static llvm::Expected<DILLexer>
+  Create(llvm::StringRef expr, lldb::DILMode mode = lldb::eDILModeFull);
 
   /// Return the current token to be handled by the DIL parser.
   const Token &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; }

diff  --git a/lldb/include/lldb/lldb-enumerations.h 
b/lldb/include/lldb/lldb-enumerations.h
index 4cbbabbf879ad..67600c8bb4248 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -1420,6 +1420,19 @@ enum NameMatchStyle {
   eNameMatchStyleRegex = eFunctionNameTypeSelector << 1
 };
 
+/// Data Inspection Language (DIL) evaluation modes.
+/// DIL will only attempt evaluating expressions that contain tokens
+/// allowed by a selected mode.
+enum DILMode {
+  /// Allowed: identifiers, operators: '.'.
+  eDILModeSimple,
+  /// Allowed: identifiers, integers, operators: '.', '->', '*', '&', '[]'.
+  eDILModeLegacy,
+  /// Allowed: everything supported by DIL.
+  /// \see lldb/docs/dil-expr-lang.ebnf
+  eDILModeFull
+};
+
 } // namespace lldb
 
 #endif // LLDB_LLDB_ENUMERATIONS_H

diff  --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp
index 31947a054aaaf..c0f932cc2c43b 100644
--- a/lldb/source/API/SBFrame.cpp
+++ b/lldb/source/API/SBFrame.cpp
@@ -363,7 +363,8 @@ void SBFrame::Clear() {
   m_opaque_sp->Clear();
 }
 
-lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path) {
+lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path,
+                                               lldb::DILMode mode) {
   LLDB_INSTRUMENT_VA(this, var_path);
 
   SBValue sb_value;
@@ -377,13 +378,14 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char 
*var_path) {
   if (StackFrame *frame = exe_ctx->GetFramePtr()) {
     lldb::DynamicValueType use_dynamic =
         frame->CalculateTarget()->GetPreferDynamicValue();
-    sb_value = GetValueForVariablePath(var_path, use_dynamic);
+    sb_value = GetValueForVariablePath(var_path, use_dynamic, mode);
   }
   return sb_value;
 }
 
 lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path,
-                                               DynamicValueType use_dynamic) {
+                                               DynamicValueType use_dynamic,
+                                               lldb::DILMode mode) {
   LLDB_INSTRUMENT_VA(this, var_path, use_dynamic);
 
   SBValue sb_value;
@@ -405,7 +407,7 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char 
*var_path,
         var_path, eNoDynamicValues,
         StackFrame::eExpressionPathOptionCheckPtrVsMember |
             StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
-        var_sp, error));
+        var_sp, error, mode));
     sb_value.SetSP(value_sp, use_dynamic);
   }
   return sb_value;

diff  --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp 
b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
index 40f00c90bbbfb..27bd71c21ad3f 100644
--- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp
+++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
@@ -170,8 +170,8 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
     Status status;
     auto valobj_sp = frame->GetValueForVariableExpressionPath(
         expr, eval_options.GetUseDynamic(),
-        StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, var_sp,
-        status);
+        StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, var_sp, 
status,
+        lldb::eDILModeSimple);
     if (valobj_sp && status.Success() && valobj_sp->GetError().Success()) {
       if (!suppress_result) {
         if (auto persisted_valobj = valobj_sp->Persist())

diff  --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp 
b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
index ab7f70efb4bd4..54b65dcaed873 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
@@ -316,7 +316,8 @@ lldb::ValueObjectSP 
ScriptedFrame::GetValueObjectForFrameVariable(
 
 lldb::ValueObjectSP ScriptedFrame::GetValueForVariableExpressionPath(
     llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
-    uint32_t options, lldb::VariableSP &var_sp, Status &error) {
+    uint32_t options, lldb::VariableSP &var_sp, Status &error,
+    lldb::DILMode mode) {
   // Unless the frame implementation knows how to create variables (which it
   // doesn't), we can't construct anything for the variable. This may seem
   // somewhat out of place, but it's basically because of how this API is used 
-

diff  --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.h 
b/lldb/source/Plugins/Process/scripted/ScriptedFrame.h
index 2bf62c06cdd19..c2fc1df7724df 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedFrame.h
+++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.h
@@ -76,7 +76,8 @@ class ScriptedFrame : public lldb_private::StackFrame {
 
   lldb::ValueObjectSP GetValueForVariableExpressionPath(
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
-      uint32_t options, lldb::VariableSP &var_sp, Status &error) override;
+      uint32_t options, lldb::VariableSP &var_sp, Status &error,
+      lldb::DILMode mode = lldb::eDILModeFull) override;
 
   bool isA(const void *ClassID) const override {
     return ClassID == &ID || StackFrame::isA(ClassID);

diff  --git a/lldb/source/Target/BorrowedStackFrame.cpp 
b/lldb/source/Target/BorrowedStackFrame.cpp
index 5afadf21fde03..5b81a1f05bbfb 100644
--- a/lldb/source/Target/BorrowedStackFrame.cpp
+++ b/lldb/source/Target/BorrowedStackFrame.cpp
@@ -99,9 +99,9 @@ BorrowedStackFrame::GetInScopeVariableList(bool 
get_file_globals,
 
 ValueObjectSP BorrowedStackFrame::GetValueForVariableExpressionPath(
     llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,
-    VariableSP &var_sp, Status &error) {
+    VariableSP &var_sp, Status &error, lldb::DILMode mode) {
   return m_borrowed_frame_sp->GetValueForVariableExpressionPath(
-      var_expr, use_dynamic, options, var_sp, error);
+      var_expr, use_dynamic, options, var_sp, error, mode);
 }
 
 bool BorrowedStackFrame::HasDebugInformation() {

diff  --git a/lldb/source/Target/StackFrame.cpp 
b/lldb/source/Target/StackFrame.cpp
index 340607e14abed..9c80e8c0b8ccf 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -524,13 +524,13 @@ StackFrame::GetInScopeVariableList(bool get_file_globals,
 
 ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
     llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,
-    VariableSP &var_sp, Status &error) {
+    VariableSP &var_sp, Status &error, lldb::DILMode mode) {
   ExecutionContext exe_ctx;
   CalculateExecutionContext(exe_ctx);
   bool use_DIL = exe_ctx.GetTargetRef().GetUseDIL(&exe_ctx);
   if (use_DIL)
     return DILGetValueForVariableExpressionPath(var_expr, use_dynamic, options,
-                                                var_sp, error);
+                                                var_sp, error, mode);
 
   return LegacyGetValueForVariableExpressionPath(var_expr, use_dynamic, 
options,
                                                  var_sp, error);
@@ -538,7 +538,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
 
 ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath(
     llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
-    uint32_t options, lldb::VariableSP &var_sp, Status &error) {
+    uint32_t options, lldb::VariableSP &var_sp, Status &error,
+    lldb::DILMode mode) {
 
   const bool check_ptr_vs_member =
       (options & eExpressionPathOptionCheckPtrVsMember) != 0;
@@ -548,7 +549,7 @@ ValueObjectSP 
StackFrame::DILGetValueForVariableExpressionPath(
       (options & eExpressionPathOptionsNoSyntheticChildren) != 0;
 
   // Lex the expression.
-  auto lex_or_err = dil::DILLexer::Create(var_expr);
+  auto lex_or_err = dil::DILLexer::Create(var_expr, mode);
   if (!lex_or_err) {
     error = Status::FromError(lex_or_err.takeError());
     return ValueObjectConstResult::Create(nullptr, std::move(error));

diff  --git a/lldb/source/ValueObject/DILLexer.cpp 
b/lldb/source/ValueObject/DILLexer.cpp
index 72c97f7bf272b..c1ad354502438 100644
--- a/lldb/source/ValueObject/DILLexer.cpp
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -111,12 +111,41 @@ static std::optional<llvm::StringRef> 
IsNumber(llvm::StringRef &remainder,
   return std::nullopt;
 }
 
-llvm::Expected<DILLexer> DILLexer::Create(llvm::StringRef expr) {
+static llvm::Error IsNotAllowedByMode(llvm::StringRef expr, Token token,
+                                      lldb::DILMode mode) {
+  switch (mode) {
+  case lldb::eDILModeSimple:
+    if (!token.IsOneOf({Token::identifier, Token::period, Token::eof})) {
+      return llvm::make_error<DILDiagnosticError>(
+          expr, llvm::formatv("{0} is not allowed in DIL simple mode", token),
+          token.GetLocation());
+    }
+    break;
+  case lldb::eDILModeLegacy:
+    if (!token.IsOneOf({Token::identifier, Token::integer_constant,
+                        Token::period, Token::arrow, Token::star, Token::amp,
+                        Token::l_square, Token::r_square, Token::eof})) {
+      return llvm::make_error<DILDiagnosticError>(
+          expr, llvm::formatv("{0} is not allowed in DIL legacy mode", token),
+          token.GetLocation());
+    }
+    break;
+  case lldb::eDILModeFull:
+    break;
+  }
+  return llvm::Error::success();
+}
+
+llvm::Expected<DILLexer> DILLexer::Create(llvm::StringRef expr,
+                                          lldb::DILMode mode) {
   std::vector<Token> tokens;
   llvm::StringRef remainder = expr;
   do {
     if (llvm::Expected<Token> t = Lex(expr, remainder)) {
-      tokens.push_back(std::move(*t));
+      Token token = *t;
+      if (llvm::Error error = IsNotAllowedByMode(expr, token, mode))
+        return error;
+      tokens.push_back(std::move(token));
     } else {
       return t.takeError();
     }

diff  --git 
a/lldb/test/API/commands/frame/var-dil/basics/AddressOf/TestFrameVarDILAddressOf.py
 
b/lldb/test/API/commands/frame/var-dil/basics/AddressOf/TestFrameVarDILAddressOf.py
index 8eab75949047d..bfe29370b4704 100644
--- 
a/lldb/test/API/commands/frame/var-dil/basics/AddressOf/TestFrameVarDILAddressOf.py
+++ 
b/lldb/test/API/commands/frame/var-dil/basics/AddressOf/TestFrameVarDILAddressOf.py
@@ -21,7 +21,7 @@ def expect_var_path(self, expr, compare_to_framevar=False, 
value=None, type=None
 
     def test_frame_var(self):
         self.build()
-        lldbutil.run_to_source_breakpoint(
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
             self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
         )
 
@@ -36,3 +36,10 @@ def test_frame_var(self):
         self.expect_var_path("&globalVar", True, type="int *")
         self.expect_var_path("&s_str", True, type="const char **")
         self.expect_var_path("&argc", True, type="int *")
+
+        # Check that '&' is not allowed in simple mode, but allowed in legacy 
mode
+        frame = thread.GetFrameAtIndex(0)
+        simple = frame.GetValueForVariablePath("&x", lldb.eDILModeSimple)
+        legacy = frame.GetValueForVariablePath("&x", lldb.eDILModeLegacy)
+        self.assertFailure(simple.GetError())
+        self.assertSuccess(legacy.GetError())

diff  --git 
a/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
 
b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
index b22a445e603cd..6f3bbfb970aa4 100644
--- 
a/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
+++ 
b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
@@ -13,7 +13,7 @@ class TestFrameVarDILArraySubscript(TestBase):
 
     def test_subscript(self):
         self.build()
-        lldbutil.run_to_source_breakpoint(
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
             self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
         )
 
@@ -87,6 +87,13 @@ def test_subscript(self):
             substrs=["subscript of pointer to incomplete type 'void'"],
         )
 
+        # Check that subscription is not allowed in simple mode, but allowed 
in legacy mode
+        frame = thread.GetFrameAtIndex(0)
+        simple = frame.GetValueForVariablePath("int_arr[0]", 
lldb.eDILModeSimple)
+        legacy = frame.GetValueForVariablePath("int_arr[0]", 
lldb.eDILModeLegacy)
+        self.assertFailure(simple.GetError())
+        self.assertSuccess(legacy.GetError())
+
     def test_subscript_synthetic(self):
         self.build()
         lldbutil.run_to_source_breakpoint(

diff  --git 
a/lldb/test/API/commands/frame/var-dil/basics/LocalVars/TestFrameVarDILLocalVars.py
 
b/lldb/test/API/commands/frame/var-dil/basics/LocalVars/TestFrameVarDILLocalVars.py
index b082d977a3a99..79d8d7abd4671 100644
--- 
a/lldb/test/API/commands/frame/var-dil/basics/LocalVars/TestFrameVarDILLocalVars.py
+++ 
b/lldb/test/API/commands/frame/var-dil/basics/LocalVars/TestFrameVarDILLocalVars.py
@@ -16,7 +16,7 @@ class TestFrameVarDILLocalVars(TestBase):
 
     def test_frame_var(self):
         self.build()
-        lldbutil.run_to_source_breakpoint(
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
             self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
         )
 
@@ -25,3 +25,10 @@ def test_frame_var(self):
         self.expect_var_path("b", value="2")
         self.expect_var_path("c", value="'\\xfd'")
         self.expect_var_path("s", value="4")
+
+        # Check that identifiers are allowed in both simple and legacy modes
+        frame = thread.GetFrameAtIndex(0)
+        simple = frame.GetValueForVariablePath("a", lldb.eDILModeSimple)
+        legacy = frame.GetValueForVariablePath("a", lldb.eDILModeLegacy)
+        self.assertSuccess(simple.GetError())
+        self.assertSuccess(legacy.GetError())

diff  --git 
a/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py
 
b/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py
index ca6754a556d89..d37ce0bbc4201 100644
--- 
a/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py
+++ 
b/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py
@@ -11,6 +11,7 @@
 import shutil
 import time
 
+
 class TestFrameVarDILMemberOf(TestBase):
     # If your test case doesn't stress debug info, then
     # set this to true.  That way it won't be run once for
@@ -19,11 +20,11 @@ class TestFrameVarDILMemberOf(TestBase):
 
     def test_frame_var(self):
         self.build()
-        lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here",
-                                          lldb.SBFileSpec("main.cpp"))
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
+        )
 
-        self.expect("settings set target.experimental.use-DIL true",
-                    substrs=[""])
+        self.expect("settings set target.experimental.use-DIL true", 
substrs=[""])
         self.expect_var_path("s.x", value="1")
         self.expect_var_path("s.r", type="int &")
         self.expect_var_path("sr.x", value="1")
@@ -48,3 +49,16 @@ def test_frame_var(self):
         # Test for record typedefs.
         self.expect_var_path("sa.x", value="3")
         self.expect_var_path("sa.y", value="'\\x04'")
+
+        # Check that '.' is allowed in both simple and legacy modes
+        frame = thread.GetFrameAtIndex(0)
+        simple = frame.GetValueForVariablePath("s.x", lldb.eDILModeSimple)
+        legacy = frame.GetValueForVariablePath("s.x", lldb.eDILModeLegacy)
+        self.assertSuccess(simple.GetError())
+        self.assertSuccess(legacy.GetError())
+
+        # Check that '->' is not allowed in simple mode, but allowed in legacy 
mode
+        simple = frame.GetValueForVariablePath("sp->x", lldb.eDILModeSimple)
+        legacy = frame.GetValueForVariablePath("sp->x", lldb.eDILModeLegacy)
+        self.assertFailure(simple.GetError())
+        self.assertSuccess(legacy.GetError())

diff  --git 
a/lldb/test/API/commands/frame/var-dil/basics/PointerDereference/TestFrameVarDILPointerDereference.py
 
b/lldb/test/API/commands/frame/var-dil/basics/PointerDereference/TestFrameVarDILPointerDereference.py
index ffb447441e982..e18e18e146a46 100644
--- 
a/lldb/test/API/commands/frame/var-dil/basics/PointerDereference/TestFrameVarDILPointerDereference.py
+++ 
b/lldb/test/API/commands/frame/var-dil/basics/PointerDereference/TestFrameVarDILPointerDereference.py
@@ -17,7 +17,7 @@ class TestFrameVarDILPointerDereference(TestBase):
 
     def test_frame_var(self):
         self.build()
-        lldbutil.run_to_source_breakpoint(
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
             self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
         )
 
@@ -46,3 +46,10 @@ def test_frame_var(self):
             pp_int0_2stars_got.GetValueAsAddress(),
             pp_int0_2stars_exp.GetValueAsAddress(),
         )
+
+        # Check that * is not allowed in simple mode, but allowed in legacy 
mode
+        frame = thread.GetFrameAtIndex(0)
+        simple = frame.GetValueForVariablePath("*p_int0", lldb.eDILModeSimple)
+        legacy = frame.GetValueForVariablePath("*p_int0", lldb.eDILModeLegacy)
+        self.assertFailure(simple.GetError())
+        self.assertSuccess(legacy.GetError())

diff  --git 
a/lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py 
b/lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py
index 6e83622ef9fb9..50affd4ccb03e 100644
--- a/lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py
+++ b/lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py
@@ -285,3 +285,10 @@ def test_type_cast(self):
             error=True,
             substrs=["expected 'eof', got: <'InnerFoo' (identifier)>"],
         )
+
+        # Check that casts are not allowed in both simple and legacy modes
+        frame = thread.GetFrameAtIndex(0)
+        simple = frame.GetValueForVariablePath("(char)a", lldb.eDILModeSimple)
+        legacy = frame.GetValueForVariablePath("(char)a", lldb.eDILModeLegacy)
+        self.assertFailure(simple.GetError())
+        self.assertFailure(legacy.GetError())

diff  --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py 
b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
index 98ed0b9df228a..556168e5adfa8 100644
--- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
+++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
@@ -253,6 +253,7 @@ def run_test_evaluate_expressions(
             self.assertEvaluateFailure("a_function(1)")
             self.assertEvaluateFailure("var2 + struct1.foo")
             self.assertEvaluateFailure("foo_func")
+            self.assertEvaluateFailure("(float) var2")
             self.assertEvaluate("foo_var", "44")
 
         # Expressions at breakpoint 2, which is an anonymous block

diff  --git a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
index 82a011b8088df..44a5be5c17b20 100644
--- a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
@@ -54,8 +54,8 @@ static lldb::SBValue 
EvaluateVariableExpression(lldb::SBTarget &target,
     // Check if it is a variable or an expression path for a variable. i.e.
     // 'foo->bar' finds the 'bar' variable. It is more reliable than the
     // expression parser in many cases and it is faster.
-    value = frame.GetValueForVariablePath(expression_cstr,
-                                          lldb::eDynamicDontRunTarget);
+    value = frame.GetValueForVariablePath(
+        expression_cstr, lldb::eDynamicDontRunTarget, lldb::eDILModeLegacy);
     if (value || !run_as_expression)
       return value;
 

diff  --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp 
b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
index 6f776f4d5f429..233dbff81f337 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
@@ -397,8 +397,8 @@ bool SourceBreakpoint::BreakpointHitCallback(
       // evaluation
       const std::string &expr_str = messagePart.text;
       const char *expr = expr_str.c_str();
-      lldb::SBValue value =
-          frame.GetValueForVariablePath(expr, lldb::eDynamicDontRunTarget);
+      lldb::SBValue value = frame.GetValueForVariablePath(
+          expr, lldb::eDynamicDontRunTarget, lldb::eDILModeLegacy);
       if (value.GetError().Fail())
         value = frame.EvaluateExpression(expr);
       output += VariableDescription(


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

Reply via email to