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