@@ -1346,6 +1346,19 @@ void request_completions(const llvm::json::Object &request) {
1346
1346
// client can use this optional information to
1347
1347
// present the variables in a paged UI and fetch
1348
1348
// them in chunks."
1349
+ // },
1350
+ // "valueLocationReference": {
1351
+ // "type": "integer",
1352
+ // "description": "A reference that allows the client to request
1353
+ // the location where the returned value is
1354
+ // declared. For example, if a function pointer is
1355
+ // returned, the adapter may be able to look up the
1356
+ // function's location. This should be present only
1357
+ // if the adapter is likely to be able to resolve
1358
+ // the location.\n\nThis reference shares the same
1359
+ // lifetime as the `variablesReference`. See
1360
+ // 'Lifetime of Object References' in the
1361
+ // Overview section for details."
1349
1362
// }
1350
1363
// },
1351
1364
// "required": [ "result", "variablesReference" ]
@@ -1405,13 +1418,14 @@ void request_evaluate(const llvm::json::Object &request) {
1405
1418
VariableDescription desc (value);
1406
1419
EmplaceSafeString (body, " result" , desc.GetResult (context));
1407
1420
EmplaceSafeString (body, " type" , desc.display_type_name );
1408
- if (value. MightHaveChildren ()) {
1409
- auto variableReference = g_dap. variables . InsertVariable (
1410
- value, /* is_permanent= */ context == " repl " );
1411
- body.try_emplace (" variablesReference" , variableReference );
1412
- } else {
1421
+ auto var_ref = g_dap. variables . InsertVariable (
1422
+ value, /* is_permanent= */ context == " repl " );
1423
+ if ( value. MightHaveChildren ())
1424
+ body.try_emplace (" variablesReference" , var_ref );
1425
+ else
1413
1426
body.try_emplace (" variablesReference" , (int64_t )0 );
1414
- }
1427
+ if (HasValueLocation (value))
1428
+ body.try_emplace (" valueLocationReference" , var_ref);
1415
1429
}
1416
1430
}
1417
1431
response.try_emplace (" body" , std::move (body));
@@ -3573,6 +3587,17 @@ void request_threads(const llvm::json::Object &request) {
3573
3587
// "description": "The number of indexed child variables. The client
3574
3588
// can use this optional information to present the variables in a
3575
3589
// paged UI and fetch them in chunks."
3590
+ // },
3591
+ // "valueLocationReference": {
3592
+ // "type": "integer",
3593
+ // "description": "A reference that allows the client to request the
3594
+ // location where the new value is declared. For example, if the new
3595
+ // value is function pointer, the adapter may be able to look up the
3596
+ // function's location. This should be present only if the adapter
3597
+ // is likely to be able to resolve the location.\n\nThis reference
3598
+ // shares the same lifetime as the `variablesReference`. See
3599
+ // 'Lifetime of Object References' in the Overview section for
3600
+ // details."
3576
3601
// }
3577
3602
// },
3578
3603
// "required": [ "value" ]
@@ -3597,7 +3622,6 @@ void request_setVariable(const llvm::json::Object &request) {
3597
3622
response.try_emplace (" success" , false );
3598
3623
3599
3624
lldb::SBValue variable;
3600
- int64_t newVariablesReference = 0 ;
3601
3625
3602
3626
// The "id" is the unique integer ID that is unique within the enclosing
3603
3627
// variablesReference. It is optionally added to any "interface Variable"
@@ -3627,11 +3651,15 @@ void request_setVariable(const llvm::json::Object &request) {
3627
3651
// so always insert a new one to get its variablesReference.
3628
3652
// is_permanent is false because debug console does not support
3629
3653
// setVariable request.
3630
- if (variable.MightHaveChildren ())
3631
- newVariablesReference =
3632
- g_dap.variables .InsertVariable (variable, /* is_permanent=*/ false );
3654
+ int64_t new_var_ref =
3655
+ g_dap.variables .InsertVariable (variable, /* is_permanent=*/ false );
3633
3656
3634
- body.try_emplace (" variablesReference" , newVariablesReference);
3657
+ if (variable.MightHaveChildren ())
3658
+ body.try_emplace (" variablesReference" , new_var_ref);
3659
+ else
3660
+ body.try_emplace (" variablesReference" , 0 );
3661
+ if (HasValueLocation (variable))
3662
+ body.try_emplace (" valueLocationReference" , new_var_ref);
3635
3663
} else {
3636
3664
EmplaceSafeString (body, " message" , std::string (error.GetCString ()));
3637
3665
}
@@ -3925,29 +3953,61 @@ void request_locations(const llvm::json::Object &request) {
3925
3953
auto arguments = request.getObject (" arguments" );
3926
3954
3927
3955
uint64_t reference_id = GetUnsigned (arguments, " locationReference" , 0 );
3928
- lldb::SBValue variable = g_dap.variables .GetVariable (reference_id);
3956
+ // We use the lowest bit to distinguish between value location and declaration
3957
+ // location
3958
+ bool isValueLocation = reference_id & 1 ;
3959
+ lldb::SBValue variable = g_dap.variables .GetVariable (reference_id >> 1 );
3929
3960
if (!variable.IsValid ()) {
3930
3961
response[" success" ] = false ;
3931
3962
response[" message" ] = " Invalid variable reference" ;
3932
3963
g_dap.SendJSON (llvm::json::Value (std::move (response)));
3933
3964
return ;
3934
3965
}
3935
3966
3936
- // Get the declaration location
3937
- lldb::SBDeclaration decl = variable.GetDeclaration ();
3938
- if (!decl.IsValid ()) {
3939
- response[" success" ] = false ;
3940
- response[" message" ] = " No declaration location available" ;
3941
- g_dap.SendJSON (llvm::json::Value (std::move (response)));
3942
- return ;
3943
- }
3944
-
3945
3967
llvm::json::Object body;
3946
- body.try_emplace (" source" , CreateSource (decl.GetFileSpec ()));
3947
- if (int line = decl.GetLine ())
3948
- body.try_emplace (" line" , line);
3949
- if (int column = decl.GetColumn ())
3950
- body.try_emplace (" column" , column);
3968
+ if (isValueLocation) {
3969
+ // Get the value location
3970
+ if (!variable.GetType ().IsPointerType () &&
3971
+ !variable.GetType ().IsReferenceType ()) {
3972
+ response[" success" ] = false ;
3973
+ response[" message" ] =
3974
+ " Value locations are only available for pointers and references" ;
3975
+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
3976
+ return ;
3977
+ }
3978
+
3979
+ lldb::addr_t addr = variable.GetValueAsAddress ();
3980
+ lldb::SBLineEntry line_entry =
3981
+ g_dap.target .ResolveLoadAddress (addr).GetLineEntry ();
3982
+
3983
+ if (!line_entry.IsValid ()) {
3984
+ response[" success" ] = false ;
3985
+ response[" message" ] = " Failed to resolve line entry for location" ;
3986
+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
3987
+ return ;
3988
+ }
3989
+
3990
+ body.try_emplace (" source" , CreateSource (line_entry.GetFileSpec ()));
3991
+ if (int line = line_entry.GetLine ())
3992
+ body.try_emplace (" line" , line);
3993
+ if (int column = line_entry.GetColumn ())
3994
+ body.try_emplace (" column" , column);
3995
+ } else {
3996
+ // Get the declaration location
3997
+ lldb::SBDeclaration decl = variable.GetDeclaration ();
3998
+ if (!decl.IsValid ()) {
3999
+ response[" success" ] = false ;
4000
+ response[" message" ] = " No declaration location available" ;
4001
+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4002
+ return ;
4003
+ }
4004
+
4005
+ body.try_emplace (" source" , CreateSource (decl.GetFileSpec ()));
4006
+ if (int line = decl.GetLine ())
4007
+ body.try_emplace (" line" , line);
4008
+ if (int column = decl.GetColumn ())
4009
+ body.try_emplace (" column" , column);
4010
+ }
3951
4011
3952
4012
response.try_emplace (" body" , std::move (body));
3953
4013
g_dap.SendJSON (llvm::json::Value (std::move (response)));
0 commit comments