@@ -1561,6 +1561,19 @@ void request_completions(const llvm::json::Object &request) {
15611561// client can use this optional information to
15621562// present the variables in a paged UI and fetch
15631563// them in chunks."
1564+ // },
1565+ // "valueLocationReference": {
1566+ // "type": "integer",
1567+ // "description": "A reference that allows the client to request
1568+ // the location where the returned value is
1569+ // declared. For example, if a function pointer is
1570+ // returned, the adapter may be able to look up the
1571+ // function's location. This should be present only
1572+ // if the adapter is likely to be able to resolve
1573+ // the location.\n\nThis reference shares the same
1574+ // lifetime as the `variablesReference`. See
1575+ // 'Lifetime of Object References' in the
1576+ // Overview section for details."
15641577// }
15651578// "memoryReference": {
15661579// "type": "string",
@@ -1647,16 +1660,19 @@ void request_evaluate(const llvm::json::Object &request) {
16471660 VariableDescription desc (value);
16481661 EmplaceSafeString (body, " result" , desc.GetResult (context));
16491662 EmplaceSafeString (body, " type" , desc.display_type_name );
1650- if (value.MightHaveChildren ()) {
1651- auto variableReference = g_dap.variables .InsertVariable (
1663+ int64_t var_ref = 0 ;
1664+ if (value.MightHaveChildren () || ValuePointsToCode (value))
1665+ var_ref = g_dap.variables .InsertVariable (
16521666 value, /* is_permanent=*/ context == " repl" );
1653- body.try_emplace (" variablesReference" , variableReference);
1654- } else {
1667+ if (value.MightHaveChildren ())
1668+ body.try_emplace (" variablesReference" , var_ref);
1669+ else
16551670 body.try_emplace (" variablesReference" , (int64_t )0 );
1656- }
16571671 if (lldb::addr_t addr = value.GetLoadAddress ();
16581672 addr != LLDB_INVALID_ADDRESS)
16591673 body.try_emplace (" memoryReference" , EncodeMemoryReference (addr));
1674+ if (ValuePointsToCode (value))
1675+ body.try_emplace (" valueLocationReference" , var_ref);
16601676 }
16611677 }
16621678 response.try_emplace (" body" , std::move (body));
@@ -3770,6 +3786,17 @@ void request_threads(const llvm::json::Object &request) {
37703786// "description": "The number of indexed child variables. The client
37713787// can use this optional information to present the variables in a
37723788// paged UI and fetch them in chunks."
3789+ // },
3790+ // "valueLocationReference": {
3791+ // "type": "integer",
3792+ // "description": "A reference that allows the client to request the
3793+ // location where the new value is declared. For example, if the new
3794+ // value is function pointer, the adapter may be able to look up the
3795+ // function's location. This should be present only if the adapter
3796+ // is likely to be able to resolve the location.\n\nThis reference
3797+ // shares the same lifetime as the `variablesReference`. See
3798+ // 'Lifetime of Object References' in the Overview section for
3799+ // details."
37733800// }
37743801// },
37753802// "required": [ "value" ]
@@ -3794,7 +3821,6 @@ void request_setVariable(const llvm::json::Object &request) {
37943821 response.try_emplace (" success" , false );
37953822
37963823 lldb::SBValue variable;
3797- int64_t newVariablesReference = 0 ;
37983824
37993825 // The "id" is the unique integer ID that is unique within the enclosing
38003826 // variablesReference. It is optionally added to any "interface Variable"
@@ -3824,14 +3850,17 @@ void request_setVariable(const llvm::json::Object &request) {
38243850 // so always insert a new one to get its variablesReference.
38253851 // is_permanent is false because debug console does not support
38263852 // setVariable request.
3853+ int64_t new_var_ref =
3854+ g_dap.variables .InsertVariable (variable, /* is_permanent=*/ false );
38273855 if (variable.MightHaveChildren ())
3828- newVariablesReference =
3829- g_dap.variables .InsertVariable (variable, /* is_permanent=*/ false );
3830- body.try_emplace (" variablesReference" , newVariablesReference);
3831-
3856+ body.try_emplace (" variablesReference" , new_var_ref);
3857+ else
3858+ body.try_emplace (" variablesReference" , 0 );
38323859 if (lldb::addr_t addr = variable.GetLoadAddress ();
38333860 addr != LLDB_INVALID_ADDRESS)
38343861 body.try_emplace (" memoryReference" , EncodeMemoryReference (addr));
3862+ if (ValuePointsToCode (variable))
3863+ body.try_emplace (" valueLocationReference" , new_var_ref);
38353864 } else {
38363865 EmplaceSafeString (body, " message" , std::string (error.GetCString ()));
38373866 }
@@ -4122,32 +4151,64 @@ void request_variables(const llvm::json::Object &request) {
41224151void request_locations (const llvm::json::Object &request) {
41234152 llvm::json::Object response;
41244153 FillResponse (request, response);
4125- auto arguments = request.getObject (" arguments" );
4154+ auto * arguments = request.getObject (" arguments" );
41264155
4127- uint64_t reference_id = GetUnsigned (arguments, " locationReference" , 0 );
4128- lldb::SBValue variable = g_dap.variables .GetVariable (reference_id);
4156+ uint64_t location_id = GetUnsigned (arguments, " locationReference" , 0 );
4157+ // We use the lowest bit to distinguish between value location and declaration
4158+ // location
4159+ auto [var_ref, is_value_location] = UnpackLocation (location_id);
4160+ lldb::SBValue variable = g_dap.variables .GetVariable (var_ref);
41294161 if (!variable.IsValid ()) {
41304162 response[" success" ] = false ;
41314163 response[" message" ] = " Invalid variable reference" ;
41324164 g_dap.SendJSON (llvm::json::Value (std::move (response)));
41334165 return ;
41344166 }
41354167
4136- // Get the declaration location
4137- lldb::SBDeclaration decl = variable.GetDeclaration ();
4138- if (!decl.IsValid ()) {
4139- response[" success" ] = false ;
4140- response[" message" ] = " No declaration location available" ;
4141- g_dap.SendJSON (llvm::json::Value (std::move (response)));
4142- return ;
4143- }
4144-
41454168 llvm::json::Object body;
4146- body.try_emplace (" source" , CreateSource (decl.GetFileSpec ()));
4147- if (int line = decl.GetLine ())
4148- body.try_emplace (" line" , line);
4149- if (int column = decl.GetColumn ())
4150- body.try_emplace (" column" , column);
4169+ if (is_value_location) {
4170+ // Get the value location
4171+ if (!variable.GetType ().IsPointerType () &&
4172+ !variable.GetType ().IsReferenceType ()) {
4173+ response[" success" ] = false ;
4174+ response[" message" ] =
4175+ " Value locations are only available for pointers and references" ;
4176+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4177+ return ;
4178+ }
4179+
4180+ lldb::addr_t addr = variable.GetValueAsAddress ();
4181+ lldb::SBLineEntry line_entry =
4182+ g_dap.target .ResolveLoadAddress (addr).GetLineEntry ();
4183+
4184+ if (!line_entry.IsValid ()) {
4185+ response[" success" ] = false ;
4186+ response[" message" ] = " Failed to resolve line entry for location" ;
4187+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4188+ return ;
4189+ }
4190+
4191+ body.try_emplace (" source" , CreateSource (line_entry.GetFileSpec ()));
4192+ if (int line = line_entry.GetLine ())
4193+ body.try_emplace (" line" , line);
4194+ if (int column = line_entry.GetColumn ())
4195+ body.try_emplace (" column" , column);
4196+ } else {
4197+ // Get the declaration location
4198+ lldb::SBDeclaration decl = variable.GetDeclaration ();
4199+ if (!decl.IsValid ()) {
4200+ response[" success" ] = false ;
4201+ response[" message" ] = " No declaration location available" ;
4202+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4203+ return ;
4204+ }
4205+
4206+ body.try_emplace (" source" , CreateSource (decl.GetFileSpec ()));
4207+ if (int line = decl.GetLine ())
4208+ body.try_emplace (" line" , line);
4209+ if (int column = decl.GetColumn ())
4210+ body.try_emplace (" column" , column);
4211+ }
41514212
41524213 response.try_emplace (" body" , std::move (body));
41534214 g_dap.SendJSON (llvm::json::Value (std::move (response)));
0 commit comments