xref: /openbsd-src/gnu/llvm/lldb/source/Interpreter/OptionValueProperties.cpp (revision a0747c9f67a4ae71ccb71e62a28d1ea19e06a63c)
1 //===-- OptionValueProperties.cpp -----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Interpreter/OptionValueProperties.h"
10 
11 #include "lldb/Utility/Flags.h"
12 
13 #include "lldb/Core/UserSettingsController.h"
14 #include "lldb/Interpreter/OptionValues.h"
15 #include "lldb/Interpreter/Property.h"
16 #include "lldb/Utility/Args.h"
17 #include "lldb/Utility/Stream.h"
18 #include "lldb/Utility/StringList.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 
23 OptionValueProperties::OptionValueProperties(ConstString name) : m_name(name) {}
24 
25 size_t OptionValueProperties::GetNumProperties() const {
26   return m_properties.size();
27 }
28 
29 void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {
30   for (const auto &definition : defs) {
31     Property property(definition);
32     assert(property.IsValid());
33     m_name_to_index.Append(ConstString(property.GetName()), m_properties.size());
34     property.GetValue()->SetParent(shared_from_this());
35     m_properties.push_back(property);
36   }
37   m_name_to_index.Sort();
38 }
39 
40 void OptionValueProperties::SetValueChangedCallback(
41     uint32_t property_idx, std::function<void()> callback) {
42   Property *property = ProtectedGetPropertyAtIndex(property_idx);
43   if (property)
44     property->SetValueChangedCallback(std::move(callback));
45 }
46 
47 void OptionValueProperties::AppendProperty(ConstString name,
48                                            ConstString desc,
49                                            bool is_global,
50                                            const OptionValueSP &value_sp) {
51   Property property(name, desc, is_global, value_sp);
52   m_name_to_index.Append(name, m_properties.size());
53   m_properties.push_back(property);
54   value_sp->SetParent(shared_from_this());
55   m_name_to_index.Sort();
56 }
57 
58 // bool
59 // OptionValueProperties::GetQualifiedName (Stream &strm)
60 //{
61 //    bool dumped_something = false;
62 ////    lldb::OptionValuePropertiesSP parent_sp(GetParent ());
63 ////    if (parent_sp)
64 ////    {
65 ////        parent_sp->GetQualifiedName (strm);
66 ////        strm.PutChar('.');
67 ////        dumped_something = true;
68 ////    }
69 //    if (m_name)
70 //    {
71 //        strm << m_name;
72 //        dumped_something = true;
73 //    }
74 //    return dumped_something;
75 //}
76 //
77 lldb::OptionValueSP
78 OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
79                                       ConstString key,
80                                       bool will_modify) const {
81   lldb::OptionValueSP value_sp;
82   size_t idx = m_name_to_index.Find(key, SIZE_MAX);
83   if (idx < m_properties.size())
84     value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
85   return value_sp;
86 }
87 
88 lldb::OptionValueSP
89 OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
90                                    llvm::StringRef name, bool will_modify,
91                                    Status &error) const {
92   lldb::OptionValueSP value_sp;
93   if (name.empty())
94     return OptionValueSP();
95 
96   llvm::StringRef sub_name;
97   ConstString key;
98   size_t key_len = name.find_first_of(".[{");
99   if (key_len != llvm::StringRef::npos) {
100     key.SetString(name.take_front(key_len));
101     sub_name = name.drop_front(key_len);
102   } else
103     key.SetString(name);
104 
105   value_sp = GetValueForKey(exe_ctx, key, will_modify);
106   if (sub_name.empty() || !value_sp)
107     return value_sp;
108 
109   switch (sub_name[0]) {
110   case '.': {
111     lldb::OptionValueSP return_val_sp;
112     return_val_sp =
113         value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), will_modify, error);
114     if (!return_val_sp) {
115       if (Properties::IsSettingExperimental(sub_name.drop_front())) {
116         size_t experimental_len =
117             strlen(Properties::GetExperimentalSettingsName());
118         if (sub_name[experimental_len + 1] == '.')
119           return_val_sp = value_sp->GetSubValue(
120               exe_ctx, sub_name.drop_front(experimental_len + 2), will_modify, error);
121         // It isn't an error if an experimental setting is not present.
122         if (!return_val_sp)
123           error.Clear();
124       }
125     }
126     return return_val_sp;
127   }
128   case '[':
129     // Array or dictionary access for subvalues like: "[12]"       -- access
130     // 12th array element "['hello']"  -- dictionary access of key named hello
131     return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
132 
133   default:
134     value_sp.reset();
135     break;
136   }
137   return value_sp;
138 }
139 
140 Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
141                                           VarSetOperationType op,
142                                           llvm::StringRef name,
143                                           llvm::StringRef value) {
144   Status error;
145   const bool will_modify = true;
146   llvm::SmallVector<llvm::StringRef, 8> components;
147   name.split(components, '.');
148   bool name_contains_experimental = false;
149   for (const auto &part : components)
150     if (Properties::IsSettingExperimental(part))
151       name_contains_experimental = true;
152 
153   lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
154   if (value_sp)
155     error = value_sp->SetValueFromString(value, op);
156   else {
157     // Don't set an error if the path contained .experimental. - those are
158     // allowed to be missing and should silently fail.
159     if (!name_contains_experimental && error.AsCString() == nullptr) {
160       error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
161     }
162   }
163   return error;
164 }
165 
166 uint32_t
167 OptionValueProperties::GetPropertyIndex(ConstString name) const {
168   return m_name_to_index.Find(name, SIZE_MAX);
169 }
170 
171 const Property *
172 OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx,
173                                    bool will_modify,
174                                    ConstString name) const {
175   return GetPropertyAtIndex(
176       exe_ctx, will_modify,
177       m_name_to_index.Find(name, SIZE_MAX));
178 }
179 
180 const Property *OptionValueProperties::GetPropertyAtIndex(
181     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
182   return ProtectedGetPropertyAtIndex(idx);
183 }
184 
185 lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
186     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
187   const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx);
188   if (setting)
189     return setting->GetValue();
190   return OptionValueSP();
191 }
192 
193 OptionValuePathMappings *
194 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
195     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
196   OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
197   if (value_sp)
198     return value_sp->GetAsPathMappings();
199   return nullptr;
200 }
201 
202 OptionValueFileSpecList *
203 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
204     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
205   OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
206   if (value_sp)
207     return value_sp->GetAsFileSpecList();
208   return nullptr;
209 }
210 
211 OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch(
212     const ExecutionContext *exe_ctx, uint32_t idx) const {
213   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
214   if (property)
215     return property->GetValue()->GetAsArch();
216   return nullptr;
217 }
218 
219 OptionValueLanguage *
220 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage(
221     const ExecutionContext *exe_ctx, uint32_t idx) const {
222   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
223   if (property)
224     return property->GetValue()->GetAsLanguage();
225   return nullptr;
226 }
227 
228 bool OptionValueProperties::GetPropertyAtIndexAsArgs(
229     const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const {
230   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
231   if (!property)
232     return false;
233 
234   OptionValue *value = property->GetValue().get();
235   if (!value)
236     return false;
237 
238   const OptionValueArgs *arguments = value->GetAsArgs();
239   if (arguments)
240     return arguments->GetArgs(args);
241 
242   const OptionValueArray *array = value->GetAsArray();
243   if (array)
244     return array->GetArgs(args);
245 
246   const OptionValueDictionary *dict = value->GetAsDictionary();
247   if (dict)
248     return dict->GetArgs(args);
249 
250   return false;
251 }
252 
253 bool OptionValueProperties::SetPropertyAtIndexFromArgs(
254     const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) {
255   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
256   if (!property)
257     return false;
258 
259   OptionValue *value = property->GetValue().get();
260   if (!value)
261     return false;
262 
263   OptionValueArgs *arguments = value->GetAsArgs();
264   if (arguments)
265     return arguments->SetArgs(args, eVarSetOperationAssign).Success();
266 
267   OptionValueArray *array = value->GetAsArray();
268   if (array)
269     return array->SetArgs(args, eVarSetOperationAssign).Success();
270 
271   OptionValueDictionary *dict = value->GetAsDictionary();
272   if (dict)
273     return dict->SetArgs(args, eVarSetOperationAssign).Success();
274 
275   return false;
276 }
277 
278 bool OptionValueProperties::GetPropertyAtIndexAsBoolean(
279     const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const {
280   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
281   if (property) {
282     OptionValue *value = property->GetValue().get();
283     if (value)
284       return value->GetBooleanValue(fail_value);
285   }
286   return fail_value;
287 }
288 
289 bool OptionValueProperties::SetPropertyAtIndexAsBoolean(
290     const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) {
291   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
292   if (property) {
293     OptionValue *value = property->GetValue().get();
294     if (value) {
295       value->SetBooleanValue(new_value);
296       return true;
297     }
298   }
299   return false;
300 }
301 
302 OptionValueDictionary *
303 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
304     const ExecutionContext *exe_ctx, uint32_t idx) const {
305   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
306   if (property)
307     return property->GetValue()->GetAsDictionary();
308   return nullptr;
309 }
310 
311 int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration(
312     const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
313   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
314   if (property) {
315     OptionValue *value = property->GetValue().get();
316     if (value)
317       return value->GetEnumerationValue(fail_value);
318   }
319   return fail_value;
320 }
321 
322 bool OptionValueProperties::SetPropertyAtIndexAsEnumeration(
323     const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
324   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
325   if (property) {
326     OptionValue *value = property->GetValue().get();
327     if (value)
328       return value->SetEnumerationValue(new_value);
329   }
330   return false;
331 }
332 
333 const FormatEntity::Entry *
334 OptionValueProperties::GetPropertyAtIndexAsFormatEntity(
335     const ExecutionContext *exe_ctx, uint32_t idx) {
336   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
337   if (property) {
338     OptionValue *value = property->GetValue().get();
339     if (value)
340       return value->GetFormatEntity();
341   }
342   return nullptr;
343 }
344 
345 OptionValueFileSpec *
346 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
347     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
348   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
349   if (property) {
350     OptionValue *value = property->GetValue().get();
351     if (value)
352       return value->GetAsFileSpec();
353   }
354   return nullptr;
355 }
356 
357 FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec(
358     const ExecutionContext *exe_ctx, uint32_t idx) const {
359   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
360   if (property) {
361     OptionValue *value = property->GetValue().get();
362     if (value)
363       return value->GetFileSpecValue();
364   }
365   return FileSpec();
366 }
367 
368 bool OptionValueProperties::SetPropertyAtIndexAsFileSpec(
369     const ExecutionContext *exe_ctx, uint32_t idx,
370     const FileSpec &new_file_spec) {
371   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
372   if (property) {
373     OptionValue *value = property->GetValue().get();
374     if (value)
375       return value->SetFileSpecValue(new_file_spec);
376   }
377   return false;
378 }
379 
380 const RegularExpression *
381 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex(
382     const ExecutionContext *exe_ctx, uint32_t idx) const {
383   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
384   if (property) {
385     OptionValue *value = property->GetValue().get();
386     if (value)
387       return value->GetRegexValue();
388   }
389   return nullptr;
390 }
391 
392 OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
393     const ExecutionContext *exe_ctx, uint32_t idx) const {
394   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
395   if (property) {
396     OptionValue *value = property->GetValue().get();
397     if (value)
398       return value->GetAsSInt64();
399   }
400   return nullptr;
401 }
402 
403 int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
404     const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
405   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
406   if (property) {
407     OptionValue *value = property->GetValue().get();
408     if (value)
409       return value->GetSInt64Value(fail_value);
410   }
411   return fail_value;
412 }
413 
414 bool OptionValueProperties::SetPropertyAtIndexAsSInt64(
415     const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
416   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
417   if (property) {
418     OptionValue *value = property->GetValue().get();
419     if (value)
420       return value->SetSInt64Value(new_value);
421   }
422   return false;
423 }
424 
425 llvm::StringRef OptionValueProperties::GetPropertyAtIndexAsString(
426     const ExecutionContext *exe_ctx, uint32_t idx,
427     llvm::StringRef fail_value) const {
428   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
429   if (property) {
430     OptionValue *value = property->GetValue().get();
431     if (value)
432       return value->GetStringValue(fail_value);
433   }
434   return fail_value;
435 }
436 
437 bool OptionValueProperties::SetPropertyAtIndexAsString(
438     const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) {
439   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
440   if (property) {
441     OptionValue *value = property->GetValue().get();
442     if (value)
443       return value->SetStringValue(new_value);
444   }
445   return false;
446 }
447 
448 OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
449     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
450   OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
451   if (value_sp)
452     return value_sp->GetAsString();
453   return nullptr;
454 }
455 
456 uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64(
457     const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const {
458   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
459   if (property) {
460     OptionValue *value = property->GetValue().get();
461     if (value)
462       return value->GetUInt64Value(fail_value);
463   }
464   return fail_value;
465 }
466 
467 bool OptionValueProperties::SetPropertyAtIndexAsUInt64(
468     const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) {
469   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
470   if (property) {
471     OptionValue *value = property->GetValue().get();
472     if (value)
473       return value->SetUInt64Value(new_value);
474   }
475   return false;
476 }
477 
478 void OptionValueProperties::Clear() {
479   const size_t num_properties = m_properties.size();
480   for (size_t i = 0; i < num_properties; ++i)
481     m_properties[i].GetValue()->Clear();
482 }
483 
484 Status OptionValueProperties::SetValueFromString(llvm::StringRef value,
485                                                  VarSetOperationType op) {
486   Status error;
487 
488   //    Args args(value_cstr);
489   //    const size_t argc = args.GetArgumentCount();
490   switch (op) {
491   case eVarSetOperationClear:
492     Clear();
493     break;
494 
495   case eVarSetOperationReplace:
496   case eVarSetOperationAssign:
497   case eVarSetOperationRemove:
498   case eVarSetOperationInsertBefore:
499   case eVarSetOperationInsertAfter:
500   case eVarSetOperationAppend:
501   case eVarSetOperationInvalid:
502     error = OptionValue::SetValueFromString(value, op);
503     break;
504   }
505 
506   return error;
507 }
508 
509 void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
510                                       Stream &strm, uint32_t dump_mask) {
511   const size_t num_properties = m_properties.size();
512   for (size_t i = 0; i < num_properties; ++i) {
513     const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
514     if (property) {
515       OptionValue *option_value = property->GetValue().get();
516       assert(option_value);
517       const bool transparent_value = option_value->ValueIsTransparent();
518       property->Dump(exe_ctx, strm, dump_mask);
519       if (!transparent_value)
520         strm.EOL();
521     }
522   }
523 }
524 
525 Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
526                                                 Stream &strm,
527                                                 llvm::StringRef property_path,
528                                                 uint32_t dump_mask) {
529   Status error;
530   const bool will_modify = false;
531   lldb::OptionValueSP value_sp(
532       GetSubValue(exe_ctx, property_path, will_modify, error));
533   if (value_sp) {
534     if (!value_sp->ValueIsTransparent()) {
535       if (dump_mask & eDumpOptionName)
536         strm.PutCString(property_path);
537       if (dump_mask & ~eDumpOptionName)
538         strm.PutChar(' ');
539     }
540     value_sp->DumpValue(exe_ctx, strm, dump_mask);
541   }
542   return error;
543 }
544 
545 OptionValuePropertiesSP
546 OptionValueProperties::CreateLocalCopy(const Properties &global_properties) {
547   auto global_props_sp = global_properties.GetValueProperties();
548   lldbassert(global_props_sp);
549 
550   auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent());
551   return std::static_pointer_cast<OptionValueProperties>(copy_sp);
552 }
553 
554 OptionValueSP
555 OptionValueProperties::DeepCopy(const OptionValueSP &new_parent) const {
556   auto copy_sp = OptionValue::DeepCopy(new_parent);
557   // copy_sp->GetAsProperties cannot be used here as it doesn't work for derived
558   // types that override GetType returning a different value.
559   auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get());
560   lldbassert(props_value_ptr);
561 
562   for (auto &property : props_value_ptr->m_properties) {
563     // Duplicate any values that are not global when constructing properties
564     // from a global copy.
565     if (!property.IsGlobal()) {
566       auto value_sp = property.GetValue()->DeepCopy(copy_sp);
567       property.SetOptionValue(value_sp);
568     }
569   }
570   return copy_sp;
571 }
572 
573 const Property *OptionValueProperties::GetPropertyAtPath(
574     const ExecutionContext *exe_ctx, bool will_modify, llvm::StringRef name) const {
575   const Property *property = nullptr;
576   if (name.empty())
577     return nullptr;
578   llvm::StringRef sub_name;
579   ConstString key;
580   size_t key_len = name.find_first_of(".[{");
581 
582   if (key_len != llvm::StringRef::npos) {
583     key.SetString(name.take_front(key_len));
584     sub_name = name.drop_front(key_len);
585   } else
586     key.SetString(name);
587 
588   property = GetProperty(exe_ctx, will_modify, key);
589   if (sub_name.empty() || !property)
590     return property;
591 
592   if (sub_name[0] == '.') {
593     OptionValueProperties *sub_properties =
594         property->GetValue()->GetAsProperties();
595     if (sub_properties)
596       return sub_properties->GetPropertyAtPath(exe_ctx, will_modify,
597                                                 sub_name.drop_front());
598   }
599   return nullptr;
600 }
601 
602 void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
603                                                 Stream &strm) const {
604   size_t max_name_len = 0;
605   const size_t num_properties = m_properties.size();
606   for (size_t i = 0; i < num_properties; ++i) {
607     const Property *property = ProtectedGetPropertyAtIndex(i);
608     if (property)
609       max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
610   }
611   for (size_t i = 0; i < num_properties; ++i) {
612     const Property *property = ProtectedGetPropertyAtIndex(i);
613     if (property)
614       property->DumpDescription(interpreter, strm, max_name_len, false);
615   }
616 }
617 
618 void OptionValueProperties::Apropos(
619     llvm::StringRef keyword,
620     std::vector<const Property *> &matching_properties) const {
621   const size_t num_properties = m_properties.size();
622   StreamString strm;
623   for (size_t i = 0; i < num_properties; ++i) {
624     const Property *property = ProtectedGetPropertyAtIndex(i);
625     if (property) {
626       const OptionValueProperties *properties =
627           property->GetValue()->GetAsProperties();
628       if (properties) {
629         properties->Apropos(keyword, matching_properties);
630       } else {
631         bool match = false;
632         llvm::StringRef name = property->GetName();
633         if (name.contains_insensitive(keyword))
634           match = true;
635         else {
636           llvm::StringRef desc = property->GetDescription();
637           if (desc.contains_insensitive(keyword))
638             match = true;
639         }
640         if (match) {
641           matching_properties.push_back(property);
642         }
643       }
644     }
645   }
646 }
647 
648 lldb::OptionValuePropertiesSP
649 OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
650                                       ConstString name) {
651   lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
652   if (option_value_sp) {
653     OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
654     if (ov_properties)
655       return ov_properties->shared_from_this();
656   }
657   return lldb::OptionValuePropertiesSP();
658 }
659