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