1 //===-- ObjCLanguage.cpp ----------------------------------------*- C++ -*-===// 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 <mutex> 10 11 #include "ObjCLanguage.h" 12 13 #include "lldb/Core/PluginManager.h" 14 #include "lldb/Core/ValueObject.h" 15 #include "lldb/DataFormatters/DataVisualization.h" 16 #include "lldb/DataFormatters/FormattersHelpers.h" 17 #include "lldb/Symbol/ClangASTContext.h" 18 #include "lldb/Symbol/CompilerType.h" 19 #include "lldb/Target/ObjCLanguageRuntime.h" 20 #include "lldb/Target/Target.h" 21 #include "lldb/Utility/ConstString.h" 22 #include "lldb/Utility/StreamString.h" 23 24 #include "llvm/Support/Threading.h" 25 26 #include "CF.h" 27 #include "Cocoa.h" 28 #include "CoreMedia.h" 29 #include "NSDictionary.h" 30 #include "NSSet.h" 31 #include "NSString.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 using namespace lldb_private::formatters; 36 37 void ObjCLanguage::Initialize() { 38 PluginManager::RegisterPlugin(GetPluginNameStatic(), "Objective-C Language", 39 CreateInstance); 40 } 41 42 void ObjCLanguage::Terminate() { 43 PluginManager::UnregisterPlugin(CreateInstance); 44 } 45 46 lldb_private::ConstString ObjCLanguage::GetPluginNameStatic() { 47 static ConstString g_name("objc"); 48 return g_name; 49 } 50 51 //------------------------------------------------------------------ 52 // PluginInterface protocol 53 //------------------------------------------------------------------ 54 55 lldb_private::ConstString ObjCLanguage::GetPluginName() { 56 return GetPluginNameStatic(); 57 } 58 59 uint32_t ObjCLanguage::GetPluginVersion() { return 1; } 60 61 //------------------------------------------------------------------ 62 // Static Functions 63 //------------------------------------------------------------------ 64 65 Language *ObjCLanguage::CreateInstance(lldb::LanguageType language) { 66 switch (language) { 67 case lldb::eLanguageTypeObjC: 68 return new ObjCLanguage(); 69 default: 70 return nullptr; 71 } 72 } 73 74 void ObjCLanguage::MethodName::Clear() { 75 m_full.Clear(); 76 m_class.Clear(); 77 m_category.Clear(); 78 m_selector.Clear(); 79 m_type = eTypeUnspecified; 80 m_category_is_valid = false; 81 } 82 83 bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) { 84 Clear(); 85 if (name.empty()) 86 return IsValid(strict); 87 88 // If "strict" is true. then the method must be specified with a '+' or '-' 89 // at the beginning. If "strict" is false, then the '+' or '-' can be omitted 90 bool valid_prefix = false; 91 92 if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) { 93 valid_prefix = name[1] == '['; 94 if (name[0] == '+') 95 m_type = eTypeClassMethod; 96 else 97 m_type = eTypeInstanceMethod; 98 } else if (!strict) { 99 // "strict" is false, the name just needs to start with '[' 100 valid_prefix = name[0] == '['; 101 } 102 103 if (valid_prefix) { 104 int name_len = name.size(); 105 // Objective-C methods must have at least: 106 // "-[" or "+[" prefix 107 // One character for a class name 108 // One character for the space between the class name 109 // One character for the method name 110 // "]" suffix 111 if (name_len >= (5 + (strict ? 1 : 0)) && name.back() == ']') { 112 m_full.SetString(name); 113 } 114 } 115 return IsValid(strict); 116 } 117 118 bool ObjCLanguage::MethodName::SetName(const char *name, bool strict) { 119 return SetName(llvm::StringRef(name), strict); 120 } 121 122 ConstString ObjCLanguage::MethodName::GetClassName() { 123 if (!m_class) { 124 if (IsValid(false)) { 125 const char *full = m_full.GetCString(); 126 const char *class_start = (full[0] == '[' ? full + 1 : full + 2); 127 const char *paren_pos = strchr(class_start, '('); 128 if (paren_pos) { 129 m_class.SetCStringWithLength(class_start, paren_pos - class_start); 130 } else { 131 // No '(' was found in the full name, we can definitively say that our 132 // category was valid (and empty). 133 m_category_is_valid = true; 134 const char *space_pos = strchr(full, ' '); 135 if (space_pos) { 136 m_class.SetCStringWithLength(class_start, space_pos - class_start); 137 if (!m_class_category) { 138 // No category in name, so we can also fill in the m_class_category 139 m_class_category = m_class; 140 } 141 } 142 } 143 } 144 } 145 return m_class; 146 } 147 148 ConstString ObjCLanguage::MethodName::GetClassNameWithCategory() { 149 if (!m_class_category) { 150 if (IsValid(false)) { 151 const char *full = m_full.GetCString(); 152 const char *class_start = (full[0] == '[' ? full + 1 : full + 2); 153 const char *space_pos = strchr(full, ' '); 154 if (space_pos) { 155 m_class_category.SetCStringWithLength(class_start, 156 space_pos - class_start); 157 // If m_class hasn't been filled in and the class with category doesn't 158 // contain a '(', then we can also fill in the m_class 159 if (!m_class && strchr(m_class_category.GetCString(), '(') == nullptr) { 160 m_class = m_class_category; 161 // No '(' was found in the full name, we can definitively say that 162 // our category was valid (and empty). 163 m_category_is_valid = true; 164 } 165 } 166 } 167 } 168 return m_class_category; 169 } 170 171 ConstString ObjCLanguage::MethodName::GetSelector() { 172 if (!m_selector) { 173 if (IsValid(false)) { 174 const char *full = m_full.GetCString(); 175 const char *space_pos = strchr(full, ' '); 176 if (space_pos) { 177 ++space_pos; // skip the space 178 m_selector.SetCStringWithLength(space_pos, m_full.GetLength() - 179 (space_pos - full) - 1); 180 } 181 } 182 } 183 return m_selector; 184 } 185 186 ConstString ObjCLanguage::MethodName::GetCategory() { 187 if (!m_category_is_valid && !m_category) { 188 if (IsValid(false)) { 189 m_category_is_valid = true; 190 const char *full = m_full.GetCString(); 191 const char *class_start = (full[0] == '[' ? full + 1 : full + 2); 192 const char *open_paren_pos = strchr(class_start, '('); 193 if (open_paren_pos) { 194 ++open_paren_pos; // Skip the open paren 195 const char *close_paren_pos = strchr(open_paren_pos, ')'); 196 if (close_paren_pos) 197 m_category.SetCStringWithLength(open_paren_pos, 198 close_paren_pos - open_paren_pos); 199 } 200 } 201 } 202 return m_category; 203 } 204 205 ConstString ObjCLanguage::MethodName::GetFullNameWithoutCategory( 206 bool empty_if_no_category) { 207 if (IsValid(false)) { 208 if (HasCategory()) { 209 StreamString strm; 210 if (m_type == eTypeClassMethod) 211 strm.PutChar('+'); 212 else if (m_type == eTypeInstanceMethod) 213 strm.PutChar('-'); 214 strm.Printf("[%s %s]", GetClassName().GetCString(), 215 GetSelector().GetCString()); 216 return ConstString(strm.GetString()); 217 } 218 219 if (!empty_if_no_category) { 220 // Just return the full name since it doesn't have a category 221 return GetFullName(); 222 } 223 } 224 return ConstString(); 225 } 226 227 size_t ObjCLanguage::MethodName::GetFullNames(std::vector<ConstString> &names, 228 bool append) { 229 if (!append) 230 names.clear(); 231 if (IsValid(false)) { 232 StreamString strm; 233 const bool is_class_method = m_type == eTypeClassMethod; 234 const bool is_instance_method = m_type == eTypeInstanceMethod; 235 ConstString category = GetCategory(); 236 if (is_class_method || is_instance_method) { 237 names.push_back(m_full); 238 if (category) { 239 strm.Printf("%c[%s %s]", is_class_method ? '+' : '-', 240 GetClassName().GetCString(), GetSelector().GetCString()); 241 names.emplace_back(strm.GetString()); 242 } 243 } else { 244 ConstString class_name = GetClassName(); 245 ConstString selector = GetSelector(); 246 strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString()); 247 names.emplace_back(strm.GetString()); 248 strm.Clear(); 249 strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString()); 250 names.emplace_back(strm.GetString()); 251 strm.Clear(); 252 if (category) { 253 strm.Printf("+[%s(%s) %s]", class_name.GetCString(), 254 category.GetCString(), selector.GetCString()); 255 names.emplace_back(strm.GetString()); 256 strm.Clear(); 257 strm.Printf("-[%s(%s) %s]", class_name.GetCString(), 258 category.GetCString(), selector.GetCString()); 259 names.emplace_back(strm.GetString()); 260 } 261 } 262 } 263 return names.size(); 264 } 265 266 static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { 267 if (!objc_category_sp) 268 return; 269 270 TypeSummaryImpl::Flags objc_flags; 271 objc_flags.SetCascades(false) 272 .SetSkipPointers(true) 273 .SetSkipReferences(true) 274 .SetDontShowChildren(true) 275 .SetDontShowValue(true) 276 .SetShowMembersOneLiner(false) 277 .SetHideItemNames(false); 278 279 lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat( 280 objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider, "")); 281 objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"), 282 ObjC_BOOL_summary); 283 objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"), 284 ObjC_BOOL_summary); 285 objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"), 286 ObjC_BOOL_summary); 287 288 #ifndef LLDB_DISABLE_PYTHON 289 // we need to skip pointers here since we are special casing a SEL* when 290 // retrieving its value 291 objc_flags.SetSkipPointers(true); 292 AddCXXSummary(objc_category_sp, 293 lldb_private::formatters::ObjCSELSummaryProvider<false>, 294 "SEL summary provider", ConstString("SEL"), objc_flags); 295 AddCXXSummary( 296 objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, 297 "SEL summary provider", ConstString("struct objc_selector"), objc_flags); 298 AddCXXSummary( 299 objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, 300 "SEL summary provider", ConstString("objc_selector"), objc_flags); 301 AddCXXSummary( 302 objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, 303 "SEL summary provider", ConstString("objc_selector *"), objc_flags); 304 AddCXXSummary(objc_category_sp, 305 lldb_private::formatters::ObjCSELSummaryProvider<true>, 306 "SEL summary provider", ConstString("SEL *"), objc_flags); 307 308 AddCXXSummary(objc_category_sp, 309 lldb_private::formatters::ObjCClassSummaryProvider, 310 "Class summary provider", ConstString("Class"), objc_flags); 311 312 SyntheticChildren::Flags class_synth_flags; 313 class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( 314 false); 315 316 AddCXXSynthetic(objc_category_sp, 317 lldb_private::formatters::ObjCClassSyntheticFrontEndCreator, 318 "Class synthetic children", ConstString("Class"), 319 class_synth_flags); 320 #endif // LLDB_DISABLE_PYTHON 321 322 objc_flags.SetSkipPointers(false); 323 objc_flags.SetCascades(true); 324 objc_flags.SetSkipReferences(false); 325 326 AddStringSummary(objc_category_sp, "${var.__FuncPtr%A}", 327 ConstString("__block_literal_generic"), objc_flags); 328 329 AddStringSummary(objc_category_sp, "${var.years} years, ${var.months} " 330 "months, ${var.days} days, ${var.hours} " 331 "hours, ${var.minutes} minutes " 332 "${var.seconds} seconds", 333 ConstString("CFGregorianUnits"), objc_flags); 334 AddStringSummary(objc_category_sp, 335 "location=${var.location} length=${var.length}", 336 ConstString("CFRange"), objc_flags); 337 338 AddStringSummary(objc_category_sp, 339 "location=${var.location}, length=${var.length}", 340 ConstString("NSRange"), objc_flags); 341 AddStringSummary(objc_category_sp, "(${var.origin}, ${var.size}), ...", 342 ConstString("NSRectArray"), objc_flags); 343 344 AddOneLineSummary(objc_category_sp, ConstString("NSPoint"), objc_flags); 345 AddOneLineSummary(objc_category_sp, ConstString("NSSize"), objc_flags); 346 AddOneLineSummary(objc_category_sp, ConstString("NSRect"), objc_flags); 347 348 AddOneLineSummary(objc_category_sp, ConstString("CGSize"), objc_flags); 349 AddOneLineSummary(objc_category_sp, ConstString("CGPoint"), objc_flags); 350 AddOneLineSummary(objc_category_sp, ConstString("CGRect"), objc_flags); 351 352 AddStringSummary(objc_category_sp, 353 "red=${var.red} green=${var.green} blue=${var.blue}", 354 ConstString("RGBColor"), objc_flags); 355 AddStringSummary( 356 objc_category_sp, 357 "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})", 358 ConstString("Rect"), objc_flags); 359 AddStringSummary(objc_category_sp, "{(v=${var.v}, h=${var.h})}", 360 ConstString("Point"), objc_flags); 361 AddStringSummary(objc_category_sp, 362 "${var.month}/${var.day}/${var.year} ${var.hour} " 363 ":${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}", 364 ConstString("DateTimeRect *"), objc_flags); 365 AddStringSummary(objc_category_sp, "${var.ld.month}/${var.ld.day}/" 366 "${var.ld.year} ${var.ld.hour} " 367 ":${var.ld.minute} :${var.ld.second} " 368 "dayOfWeek:${var.ld.dayOfWeek}", 369 ConstString("LongDateRect"), objc_flags); 370 AddStringSummary(objc_category_sp, "(x=${var.x}, y=${var.y})", 371 ConstString("HIPoint"), objc_flags); 372 AddStringSummary(objc_category_sp, "origin=${var.origin} size=${var.size}", 373 ConstString("HIRect"), objc_flags); 374 375 TypeSummaryImpl::Flags appkit_flags; 376 appkit_flags.SetCascades(true) 377 .SetSkipPointers(false) 378 .SetSkipReferences(false) 379 .SetDontShowChildren(true) 380 .SetDontShowValue(false) 381 .SetShowMembersOneLiner(false) 382 .SetHideItemNames(false); 383 384 appkit_flags.SetDontShowChildren(false); 385 386 #ifndef LLDB_DISABLE_PYTHON 387 AddCXXSummary( 388 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 389 "NSArray summary provider", ConstString("NSArray"), appkit_flags); 390 AddCXXSummary( 391 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 392 "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags); 393 AddCXXSummary( 394 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 395 "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags); 396 AddCXXSummary( 397 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 398 "NSArray summary provider", ConstString("__NSArray0"), appkit_flags); 399 AddCXXSummary(objc_category_sp, 400 lldb_private::formatters::NSArraySummaryProvider, 401 "NSArray summary provider", 402 ConstString("__NSSingleObjectArrayI"), appkit_flags); 403 AddCXXSummary( 404 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 405 "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags); 406 AddCXXSummary( 407 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 408 "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags); 409 AddCXXSummary( 410 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 411 "NSArray summary provider", ConstString("_NSCallStackArray"), appkit_flags); 412 AddCXXSummary( 413 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 414 "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags); 415 AddCXXSummary(objc_category_sp, 416 lldb_private::formatters::NSArraySummaryProvider, 417 "NSArray summary provider", ConstString("CFMutableArrayRef"), 418 appkit_flags); 419 420 AddCXXSummary(objc_category_sp, 421 lldb_private::formatters::NSDictionarySummaryProvider<false>, 422 "NSDictionary summary provider", ConstString("NSDictionary"), 423 appkit_flags); 424 AddCXXSummary(objc_category_sp, 425 lldb_private::formatters::NSDictionarySummaryProvider<false>, 426 "NSDictionary summary provider", 427 ConstString("NSMutableDictionary"), appkit_flags); 428 AddCXXSummary(objc_category_sp, 429 lldb_private::formatters::NSDictionarySummaryProvider<false>, 430 "NSDictionary summary provider", 431 ConstString("__NSCFDictionary"), appkit_flags); 432 AddCXXSummary(objc_category_sp, 433 lldb_private::formatters::NSDictionarySummaryProvider<false>, 434 "NSDictionary summary provider", ConstString("__NSDictionaryI"), 435 appkit_flags); 436 AddCXXSummary(objc_category_sp, 437 lldb_private::formatters::NSDictionarySummaryProvider<false>, 438 "NSDictionary summary provider", 439 ConstString("__NSSingleEntryDictionaryI"), appkit_flags); 440 AddCXXSummary(objc_category_sp, 441 lldb_private::formatters::NSDictionarySummaryProvider<false>, 442 "NSDictionary summary provider", ConstString("__NSDictionaryM"), 443 appkit_flags); 444 AddCXXSummary(objc_category_sp, 445 lldb_private::formatters::NSDictionarySummaryProvider<true>, 446 "NSDictionary summary provider", ConstString("CFDictionaryRef"), 447 appkit_flags); 448 AddCXXSummary(objc_category_sp, 449 lldb_private::formatters::NSDictionarySummaryProvider<true>, 450 "NSDictionary summary provider", 451 ConstString("CFMutableDictionaryRef"), appkit_flags); 452 453 AddCXXSummary(objc_category_sp, 454 lldb_private::formatters::NSSetSummaryProvider<false>, 455 "NSSet summary", ConstString("NSSet"), appkit_flags); 456 AddCXXSummary( 457 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 458 "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags); 459 AddCXXSummary(objc_category_sp, 460 lldb_private::formatters::NSSetSummaryProvider<true>, 461 "CFSetRef summary", ConstString("CFSetRef"), appkit_flags); 462 AddCXXSummary( 463 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, 464 "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags); 465 AddCXXSummary(objc_category_sp, 466 lldb_private::formatters::NSSetSummaryProvider<false>, 467 "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags); 468 AddCXXSummary(objc_category_sp, 469 lldb_private::formatters::NSSetSummaryProvider<false>, 470 "__NSSetI summary", ConstString("__NSSetI"), appkit_flags); 471 AddCXXSummary(objc_category_sp, 472 lldb_private::formatters::NSSetSummaryProvider<false>, 473 "__NSSetM summary", ConstString("__NSSetM"), appkit_flags); 474 AddCXXSummary( 475 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 476 "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags); 477 AddCXXSummary( 478 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 479 "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags); 480 AddCXXSummary( 481 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 482 "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags); 483 AddCXXSummary( 484 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 485 "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags); 486 AddCXXSummary( 487 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 488 "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags); 489 490 AddCXXSummary( 491 objc_category_sp, lldb_private::formatters::NSError_SummaryProvider, 492 "NSError summary provider", ConstString("NSError"), appkit_flags); 493 AddCXXSummary( 494 objc_category_sp, lldb_private::formatters::NSException_SummaryProvider, 495 "NSException summary provider", ConstString("NSException"), appkit_flags); 496 497 // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", 498 // ConstString("$_lldb_typegen_nspair"), appkit_flags); 499 500 appkit_flags.SetDontShowChildren(true); 501 502 AddCXXSynthetic(objc_category_sp, 503 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 504 "NSArray synthetic children", ConstString("__NSArrayM"), 505 ScriptedSyntheticChildren::Flags()); 506 AddCXXSynthetic(objc_category_sp, 507 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 508 "NSArray synthetic children", ConstString("__NSArrayI"), 509 ScriptedSyntheticChildren::Flags()); 510 AddCXXSynthetic(objc_category_sp, 511 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 512 "NSArray synthetic children", ConstString("__NSArray0"), 513 ScriptedSyntheticChildren::Flags()); 514 AddCXXSynthetic(objc_category_sp, 515 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 516 "NSArray synthetic children", 517 ConstString("__NSSingleObjectArrayI"), 518 ScriptedSyntheticChildren::Flags()); 519 AddCXXSynthetic(objc_category_sp, 520 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 521 "NSArray synthetic children", ConstString("NSArray"), 522 ScriptedSyntheticChildren::Flags()); 523 AddCXXSynthetic(objc_category_sp, 524 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 525 "NSArray synthetic children", ConstString("NSMutableArray"), 526 ScriptedSyntheticChildren::Flags()); 527 AddCXXSynthetic(objc_category_sp, 528 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 529 "NSArray synthetic children", ConstString("__NSCFArray"), 530 ScriptedSyntheticChildren::Flags()); 531 AddCXXSynthetic(objc_category_sp, 532 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 533 "NSArray synthetic children", ConstString("_NSCallStackArray"), 534 ScriptedSyntheticChildren::Flags()); 535 AddCXXSynthetic(objc_category_sp, 536 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 537 "NSArray synthetic children", 538 ConstString("CFMutableArrayRef"), 539 ScriptedSyntheticChildren::Flags()); 540 AddCXXSynthetic(objc_category_sp, 541 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 542 "NSArray synthetic children", ConstString("CFArrayRef"), 543 ScriptedSyntheticChildren::Flags()); 544 545 AddCXXSynthetic( 546 objc_category_sp, 547 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 548 "NSDictionary synthetic children", ConstString("__NSDictionaryM"), 549 ScriptedSyntheticChildren::Flags()); 550 AddCXXSynthetic( 551 objc_category_sp, 552 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 553 "NSDictionary synthetic children", ConstString("__NSDictionaryI"), 554 ScriptedSyntheticChildren::Flags()); 555 AddCXXSynthetic( 556 objc_category_sp, 557 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 558 "NSDictionary synthetic children", 559 ConstString("__NSSingleEntryDictionaryI"), 560 ScriptedSyntheticChildren::Flags()); 561 AddCXXSynthetic( 562 objc_category_sp, 563 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 564 "NSDictionary synthetic children", ConstString("__NSCFDictionary"), 565 ScriptedSyntheticChildren::Flags()); 566 AddCXXSynthetic( 567 objc_category_sp, 568 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 569 "NSDictionary synthetic children", ConstString("NSDictionary"), 570 ScriptedSyntheticChildren::Flags()); 571 AddCXXSynthetic( 572 objc_category_sp, 573 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 574 "NSDictionary synthetic children", ConstString("NSMutableDictionary"), 575 ScriptedSyntheticChildren::Flags()); 576 AddCXXSynthetic( 577 objc_category_sp, 578 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 579 "NSDictionary synthetic children", ConstString("CFDictionaryRef"), 580 ScriptedSyntheticChildren::Flags()); 581 AddCXXSynthetic( 582 objc_category_sp, 583 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 584 "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), 585 ScriptedSyntheticChildren::Flags()); 586 587 AddCXXSynthetic(objc_category_sp, 588 lldb_private::formatters::NSErrorSyntheticFrontEndCreator, 589 "NSError synthetic children", ConstString("NSError"), 590 ScriptedSyntheticChildren::Flags()); 591 AddCXXSynthetic(objc_category_sp, 592 lldb_private::formatters::NSExceptionSyntheticFrontEndCreator, 593 "NSException synthetic children", ConstString("NSException"), 594 ScriptedSyntheticChildren::Flags()); 595 596 AddCXXSynthetic(objc_category_sp, 597 lldb_private::formatters::NSSetSyntheticFrontEndCreator, 598 "NSSet synthetic children", ConstString("NSSet"), 599 ScriptedSyntheticChildren::Flags()); 600 AddCXXSynthetic(objc_category_sp, 601 lldb_private::formatters::NSSetSyntheticFrontEndCreator, 602 "__NSSetI synthetic children", ConstString("__NSSetI"), 603 ScriptedSyntheticChildren::Flags()); 604 AddCXXSynthetic(objc_category_sp, 605 lldb_private::formatters::NSSetSyntheticFrontEndCreator, 606 "__NSSetM synthetic children", ConstString("__NSSetM"), 607 ScriptedSyntheticChildren::Flags()); 608 AddCXXSynthetic( 609 objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, 610 "NSMutableSet synthetic children", ConstString("NSMutableSet"), 611 ScriptedSyntheticChildren::Flags()); 612 AddCXXSynthetic( 613 objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, 614 "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), 615 ScriptedSyntheticChildren::Flags()); 616 AddCXXSynthetic( 617 objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, 618 "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), 619 ScriptedSyntheticChildren::Flags()); 620 AddCXXSynthetic( 621 objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, 622 "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), 623 ScriptedSyntheticChildren::Flags()); 624 625 AddCXXSynthetic(objc_category_sp, 626 lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, 627 "NSIndexPath synthetic children", ConstString("NSIndexPath"), 628 ScriptedSyntheticChildren::Flags()); 629 630 AddCXXSummary( 631 objc_category_sp, lldb_private::formatters::CFBagSummaryProvider, 632 "CFBag summary provider", ConstString("CFBagRef"), appkit_flags); 633 AddCXXSummary(objc_category_sp, 634 lldb_private::formatters::CFBagSummaryProvider, 635 "CFBag summary provider", ConstString("__CFBag"), appkit_flags); 636 AddCXXSummary(objc_category_sp, 637 lldb_private::formatters::CFBagSummaryProvider, 638 "CFBag summary provider", ConstString("const struct __CFBag"), 639 appkit_flags); 640 AddCXXSummary( 641 objc_category_sp, lldb_private::formatters::CFBagSummaryProvider, 642 "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags); 643 644 AddCXXSummary(objc_category_sp, 645 lldb_private::formatters::CFBinaryHeapSummaryProvider, 646 "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), 647 appkit_flags); 648 AddCXXSummary(objc_category_sp, 649 lldb_private::formatters::CFBinaryHeapSummaryProvider, 650 "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), 651 appkit_flags); 652 653 AddCXXSummary( 654 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 655 "NSString summary provider", ConstString("NSString"), appkit_flags); 656 AddCXXSummary( 657 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 658 "NSString summary provider", ConstString("CFStringRef"), appkit_flags); 659 AddCXXSummary( 660 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 661 "NSString summary provider", ConstString("__CFString"), appkit_flags); 662 AddCXXSummary(objc_category_sp, 663 lldb_private::formatters::NSStringSummaryProvider, 664 "NSString summary provider", ConstString("CFMutableStringRef"), 665 appkit_flags); 666 AddCXXSummary(objc_category_sp, 667 lldb_private::formatters::NSStringSummaryProvider, 668 "NSString summary provider", ConstString("NSMutableString"), 669 appkit_flags); 670 AddCXXSummary(objc_category_sp, 671 lldb_private::formatters::NSStringSummaryProvider, 672 "NSString summary provider", 673 ConstString("__NSCFConstantString"), appkit_flags); 674 AddCXXSummary( 675 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 676 "NSString summary provider", ConstString("__NSCFString"), appkit_flags); 677 AddCXXSummary(objc_category_sp, 678 lldb_private::formatters::NSStringSummaryProvider, 679 "NSString summary provider", ConstString("NSCFConstantString"), 680 appkit_flags); 681 AddCXXSummary( 682 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 683 "NSString summary provider", ConstString("NSCFString"), appkit_flags); 684 AddCXXSummary( 685 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 686 "NSString summary provider", ConstString("NSPathStore2"), appkit_flags); 687 AddCXXSummary(objc_category_sp, 688 lldb_private::formatters::NSStringSummaryProvider, 689 "NSString summary provider", 690 ConstString("NSTaggedPointerString"), appkit_flags); 691 692 AddCXXSummary(objc_category_sp, 693 lldb_private::formatters::NSAttributedStringSummaryProvider, 694 "NSAttributedString summary provider", 695 ConstString("NSAttributedString"), appkit_flags); 696 AddCXXSummary( 697 objc_category_sp, 698 lldb_private::formatters::NSMutableAttributedStringSummaryProvider, 699 "NSMutableAttributedString summary provider", 700 ConstString("NSMutableAttributedString"), appkit_flags); 701 AddCXXSummary( 702 objc_category_sp, 703 lldb_private::formatters::NSMutableAttributedStringSummaryProvider, 704 "NSMutableAttributedString summary provider", 705 ConstString("NSConcreteMutableAttributedString"), appkit_flags); 706 707 AddCXXSummary( 708 objc_category_sp, lldb_private::formatters::NSBundleSummaryProvider, 709 "NSBundle summary provider", ConstString("NSBundle"), appkit_flags); 710 711 AddCXXSummary(objc_category_sp, 712 lldb_private::formatters::NSDataSummaryProvider<false>, 713 "NSData summary provider", ConstString("NSData"), appkit_flags); 714 AddCXXSummary( 715 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, 716 "NSData summary provider", ConstString("_NSInlineData"), appkit_flags); 717 AddCXXSummary( 718 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, 719 "NSData summary provider", ConstString("NSConcreteData"), appkit_flags); 720 AddCXXSummary(objc_category_sp, 721 lldb_private::formatters::NSDataSummaryProvider<false>, 722 "NSData summary provider", ConstString("NSConcreteMutableData"), 723 appkit_flags); 724 AddCXXSummary( 725 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, 726 "NSData summary provider", ConstString("NSMutableData"), appkit_flags); 727 AddCXXSummary( 728 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, 729 "NSData summary provider", ConstString("__NSCFData"), appkit_flags); 730 AddCXXSummary( 731 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, 732 "NSData summary provider", ConstString("CFDataRef"), appkit_flags); 733 AddCXXSummary( 734 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, 735 "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags); 736 737 AddCXXSummary( 738 objc_category_sp, lldb_private::formatters::NSMachPortSummaryProvider, 739 "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags); 740 741 AddCXXSummary(objc_category_sp, 742 lldb_private::formatters::NSNotificationSummaryProvider, 743 "NSNotification summary provider", 744 ConstString("NSNotification"), appkit_flags); 745 AddCXXSummary(objc_category_sp, 746 lldb_private::formatters::NSNotificationSummaryProvider, 747 "NSNotification summary provider", 748 ConstString("NSConcreteNotification"), appkit_flags); 749 750 AddCXXSummary( 751 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 752 "NSNumber summary provider", ConstString("NSNumber"), appkit_flags); 753 AddCXXSummary( 754 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 755 "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags); 756 AddCXXSummary( 757 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 758 "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags); 759 AddCXXSummary( 760 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 761 "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags); 762 AddCXXSummary( 763 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 764 "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags); 765 AddCXXSummary( 766 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 767 "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags); 768 AddCXXSummary(objc_category_sp, 769 lldb_private::formatters::NSNumberSummaryProvider, 770 "NSDecimalNumber summary provider", 771 ConstString("NSDecimalNumber"), appkit_flags); 772 773 AddCXXSummary(objc_category_sp, 774 lldb_private::formatters::NSURLSummaryProvider, 775 "NSURL summary provider", ConstString("NSURL"), appkit_flags); 776 AddCXXSummary( 777 objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, 778 "NSURL summary provider", ConstString("CFURLRef"), appkit_flags); 779 780 AddCXXSummary(objc_category_sp, 781 lldb_private::formatters::NSDateSummaryProvider, 782 "NSDate summary provider", ConstString("NSDate"), appkit_flags); 783 AddCXXSummary( 784 objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, 785 "NSDate summary provider", ConstString("__NSDate"), appkit_flags); 786 AddCXXSummary( 787 objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, 788 "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags); 789 AddCXXSummary( 790 objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, 791 "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags); 792 793 AddCXXSummary( 794 objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, 795 "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags); 796 AddCXXSummary(objc_category_sp, 797 lldb_private::formatters::NSTimeZoneSummaryProvider, 798 "NSTimeZone summary provider", ConstString("CFTimeZoneRef"), 799 appkit_flags); 800 AddCXXSummary( 801 objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, 802 "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags); 803 804 // CFAbsoluteTime is actually a double rather than a pointer to an object we 805 // do not care about the numeric value, since it is probably meaningless to 806 // users 807 appkit_flags.SetDontShowValue(true); 808 AddCXXSummary(objc_category_sp, 809 lldb_private::formatters::CFAbsoluteTimeSummaryProvider, 810 "CFAbsoluteTime summary provider", 811 ConstString("CFAbsoluteTime"), appkit_flags); 812 appkit_flags.SetDontShowValue(false); 813 814 AddCXXSummary( 815 objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, 816 "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags); 817 AddCXXSummary(objc_category_sp, 818 lldb_private::formatters::NSIndexSetSummaryProvider, 819 "NSIndexSet summary provider", ConstString("NSMutableIndexSet"), 820 appkit_flags); 821 822 AddStringSummary(objc_category_sp, 823 "@\"${var.month%d}/${var.day%d}/${var.year%d} " 824 "${var.hour%d}:${var.minute%d}:${var.second}\"", 825 ConstString("CFGregorianDate"), appkit_flags); 826 827 AddCXXSummary(objc_category_sp, 828 lldb_private::formatters::CFBitVectorSummaryProvider, 829 "CFBitVector summary provider", ConstString("CFBitVectorRef"), 830 appkit_flags); 831 AddCXXSummary(objc_category_sp, 832 lldb_private::formatters::CFBitVectorSummaryProvider, 833 "CFBitVector summary provider", 834 ConstString("CFMutableBitVectorRef"), appkit_flags); 835 AddCXXSummary(objc_category_sp, 836 lldb_private::formatters::CFBitVectorSummaryProvider, 837 "CFBitVector summary provider", ConstString("__CFBitVector"), 838 appkit_flags); 839 AddCXXSummary(objc_category_sp, 840 lldb_private::formatters::CFBitVectorSummaryProvider, 841 "CFBitVector summary provider", 842 ConstString("__CFMutableBitVector"), appkit_flags); 843 #endif // LLDB_DISABLE_PYTHON 844 } 845 846 static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) { 847 if (!objc_category_sp) 848 return; 849 850 TypeSummaryImpl::Flags cm_flags; 851 cm_flags.SetCascades(true) 852 .SetDontShowChildren(false) 853 .SetDontShowValue(false) 854 .SetHideItemNames(false) 855 .SetShowMembersOneLiner(false) 856 .SetSkipPointers(false) 857 .SetSkipReferences(false); 858 859 #ifndef LLDB_DISABLE_PYTHON 860 AddCXXSummary(objc_category_sp, 861 lldb_private::formatters::CMTimeSummaryProvider, 862 "CMTime summary provider", ConstString("CMTime"), cm_flags); 863 #endif // LLDB_DISABLE_PYTHON 864 } 865 866 lldb::TypeCategoryImplSP ObjCLanguage::GetFormatters() { 867 static llvm::once_flag g_initialize; 868 static TypeCategoryImplSP g_category; 869 870 llvm::call_once(g_initialize, [this]() -> void { 871 DataVisualization::Categories::GetCategory(GetPluginName(), g_category); 872 if (g_category) { 873 LoadCoreMediaFormatters(g_category); 874 LoadObjCFormatters(g_category); 875 } 876 }); 877 return g_category; 878 } 879 880 std::vector<ConstString> 881 ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj, 882 lldb::DynamicValueType use_dynamic) { 883 std::vector<ConstString> result; 884 885 if (use_dynamic == lldb::eNoDynamicValues) 886 return result; 887 888 CompilerType compiler_type(valobj.GetCompilerType()); 889 890 const bool check_cpp = false; 891 const bool check_objc = true; 892 bool canBeObjCDynamic = 893 compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc); 894 895 if (canBeObjCDynamic) { 896 do { 897 lldb::ProcessSP process_sp = valobj.GetProcessSP(); 898 if (!process_sp) 899 break; 900 ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); 901 if (runtime == nullptr) 902 break; 903 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp( 904 runtime->GetClassDescriptor(valobj)); 905 if (!objc_class_sp) 906 break; 907 if (ConstString name = objc_class_sp->GetClassName()) 908 result.push_back(name); 909 } while (false); 910 } 911 912 return result; 913 } 914 915 std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() { 916 class ObjCScavengerResult : public Language::TypeScavenger::Result { 917 public: 918 ObjCScavengerResult(CompilerType type) 919 : Language::TypeScavenger::Result(), m_compiler_type(type) {} 920 921 bool IsValid() override { return m_compiler_type.IsValid(); } 922 923 bool DumpToStream(Stream &stream, bool print_help_if_available) override { 924 if (IsValid()) { 925 m_compiler_type.DumpTypeDescription(&stream); 926 stream.EOL(); 927 return true; 928 } 929 return false; 930 } 931 932 private: 933 CompilerType m_compiler_type; 934 }; 935 936 class ObjCRuntimeScavenger : public Language::TypeScavenger { 937 protected: 938 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 939 ResultSet &results) override { 940 bool result = false; 941 942 Process *process = exe_scope->CalculateProcess().get(); 943 if (process) { 944 const bool create_on_demand = false; 945 auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand); 946 if (objc_runtime) { 947 auto decl_vendor = objc_runtime->GetDeclVendor(); 948 if (decl_vendor) { 949 std::vector<clang::NamedDecl *> decls; 950 ConstString name(key); 951 decl_vendor->FindDecls(name, true, UINT32_MAX, decls); 952 for (auto decl : decls) { 953 if (decl) { 954 if (CompilerType candidate = 955 ClangASTContext::GetTypeForDecl(decl)) { 956 result = true; 957 std::unique_ptr<Language::TypeScavenger::Result> result( 958 new ObjCScavengerResult(candidate)); 959 results.insert(std::move(result)); 960 } 961 } 962 } 963 } 964 } 965 } 966 967 return result; 968 } 969 970 friend class lldb_private::ObjCLanguage; 971 }; 972 973 class ObjCModulesScavenger : public Language::TypeScavenger { 974 protected: 975 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 976 ResultSet &results) override { 977 bool result = false; 978 979 Target *target = exe_scope->CalculateTarget().get(); 980 if (target) { 981 if (auto clang_modules_decl_vendor = 982 target->GetClangModulesDeclVendor()) { 983 std::vector<clang::NamedDecl *> decls; 984 ConstString key_cs(key); 985 986 if (clang_modules_decl_vendor->FindDecls(key_cs, false, UINT32_MAX, 987 decls) > 0 && 988 !decls.empty()) { 989 CompilerType module_type = 990 ClangASTContext::GetTypeForDecl(decls.front()); 991 result = true; 992 std::unique_ptr<Language::TypeScavenger::Result> result( 993 new ObjCScavengerResult(module_type)); 994 results.insert(std::move(result)); 995 } 996 } 997 } 998 999 return result; 1000 } 1001 1002 friend class lldb_private::ObjCLanguage; 1003 }; 1004 1005 class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger { 1006 public: 1007 virtual CompilerType AdjustForInclusion(CompilerType &candidate) override { 1008 LanguageType lang_type(candidate.GetMinimumLanguage()); 1009 if (!Language::LanguageIsObjC(lang_type)) 1010 return CompilerType(); 1011 if (candidate.IsTypedefType()) 1012 return candidate.GetTypedefedType(); 1013 return candidate; 1014 } 1015 }; 1016 1017 return std::unique_ptr<TypeScavenger>( 1018 new Language::EitherTypeScavenger<ObjCModulesScavenger, 1019 ObjCRuntimeScavenger, 1020 ObjCDebugInfoScavenger>()); 1021 } 1022 1023 bool ObjCLanguage::GetFormatterPrefixSuffix(ValueObject &valobj, 1024 ConstString type_hint, 1025 std::string &prefix, 1026 std::string &suffix) { 1027 static ConstString g_CFBag("CFBag"); 1028 static ConstString g_CFBinaryHeap("CFBinaryHeap"); 1029 1030 static ConstString g_NSNumberChar("NSNumber:char"); 1031 static ConstString g_NSNumberShort("NSNumber:short"); 1032 static ConstString g_NSNumberInt("NSNumber:int"); 1033 static ConstString g_NSNumberLong("NSNumber:long"); 1034 static ConstString g_NSNumberInt128("NSNumber:int128_t"); 1035 static ConstString g_NSNumberFloat("NSNumber:float"); 1036 static ConstString g_NSNumberDouble("NSNumber:double"); 1037 1038 static ConstString g_NSData("NSData"); 1039 static ConstString g_NSArray("NSArray"); 1040 static ConstString g_NSString("NSString"); 1041 static ConstString g_NSStringStar("NSString*"); 1042 1043 if (type_hint.IsEmpty()) 1044 return false; 1045 1046 prefix.clear(); 1047 suffix.clear(); 1048 1049 if (type_hint == g_CFBag || type_hint == g_CFBinaryHeap) { 1050 prefix = "@"; 1051 return true; 1052 } 1053 1054 if (type_hint == g_NSNumberChar) { 1055 prefix = "(char)"; 1056 return true; 1057 } 1058 if (type_hint == g_NSNumberShort) { 1059 prefix = "(short)"; 1060 return true; 1061 } 1062 if (type_hint == g_NSNumberInt) { 1063 prefix = "(int)"; 1064 return true; 1065 } 1066 if (type_hint == g_NSNumberLong) { 1067 prefix = "(long)"; 1068 return true; 1069 } 1070 if (type_hint == g_NSNumberInt128) { 1071 prefix = "(int128_t)"; 1072 return true; 1073 } 1074 if (type_hint == g_NSNumberFloat) { 1075 prefix = "(float)"; 1076 return true; 1077 } 1078 if (type_hint == g_NSNumberDouble) { 1079 prefix = "(double)"; 1080 return true; 1081 } 1082 1083 if (type_hint == g_NSData || type_hint == g_NSArray) { 1084 prefix = "@\""; 1085 suffix = "\""; 1086 return true; 1087 } 1088 1089 if (type_hint == g_NSString || type_hint == g_NSStringStar) { 1090 prefix = "@"; 1091 return true; 1092 } 1093 1094 return false; 1095 } 1096 1097 bool ObjCLanguage::IsNilReference(ValueObject &valobj) { 1098 const uint32_t mask = eTypeIsObjC | eTypeIsPointer; 1099 bool isObjCpointer = 1100 (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask); 1101 if (!isObjCpointer) 1102 return false; 1103 bool canReadValue = true; 1104 bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0; 1105 return canReadValue && isZero; 1106 } 1107 1108 bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const { 1109 const auto suffixes = {".h", ".m", ".M"}; 1110 for (auto suffix : suffixes) { 1111 if (file_path.endswith_lower(suffix)) 1112 return true; 1113 } 1114 return false; 1115 } 1116