1 //===-- SBType.cpp ----------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/API/SBDefines.h" 11 #include "lldb/API/SBType.h" 12 #include "lldb/API/SBTypeEnumMember.h" 13 #include "lldb/API/SBStream.h" 14 #include "lldb/Core/ConstString.h" 15 #include "lldb/Core/Log.h" 16 #include "lldb/Core/Stream.h" 17 #include "lldb/Symbol/CompilerType.h" 18 #include "lldb/Symbol/Type.h" 19 #include "lldb/Symbol/TypeSystem.h" 20 21 #include "llvm/ADT/APSInt.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 SBType::SBType() : 27 m_opaque_sp() 28 { 29 } 30 31 SBType::SBType (const CompilerType &type) : 32 m_opaque_sp(new TypeImpl(CompilerType(type.GetTypeSystem(), 33 type.GetOpaqueQualType()))) 34 { 35 } 36 37 SBType::SBType (const lldb::TypeSP &type_sp) : 38 m_opaque_sp(new TypeImpl(type_sp)) 39 { 40 } 41 42 SBType::SBType (const lldb::TypeImplSP &type_impl_sp) : 43 m_opaque_sp(type_impl_sp) 44 { 45 } 46 47 48 SBType::SBType (const SBType &rhs) : 49 m_opaque_sp() 50 { 51 if (this != &rhs) 52 { 53 m_opaque_sp = rhs.m_opaque_sp; 54 } 55 } 56 57 58 //SBType::SBType (TypeImpl* impl) : 59 // m_opaque_ap(impl) 60 //{} 61 // 62 bool 63 SBType::operator == (SBType &rhs) 64 { 65 if (IsValid() == false) 66 return !rhs.IsValid(); 67 68 if (rhs.IsValid() == false) 69 return false; 70 71 return *m_opaque_sp.get() == *rhs.m_opaque_sp.get(); 72 } 73 74 bool 75 SBType::operator != (SBType &rhs) 76 { 77 if (IsValid() == false) 78 return rhs.IsValid(); 79 80 if (rhs.IsValid() == false) 81 return true; 82 83 return *m_opaque_sp.get() != *rhs.m_opaque_sp.get(); 84 } 85 86 lldb::TypeImplSP 87 SBType::GetSP () 88 { 89 return m_opaque_sp; 90 } 91 92 93 void 94 SBType::SetSP (const lldb::TypeImplSP &type_impl_sp) 95 { 96 m_opaque_sp = type_impl_sp; 97 } 98 99 SBType & 100 SBType::operator = (const SBType &rhs) 101 { 102 if (this != &rhs) 103 { 104 m_opaque_sp = rhs.m_opaque_sp; 105 } 106 return *this; 107 } 108 109 SBType::~SBType () 110 {} 111 112 TypeImpl & 113 SBType::ref () 114 { 115 if (m_opaque_sp.get() == NULL) 116 m_opaque_sp.reset (new TypeImpl()); 117 return *m_opaque_sp; 118 } 119 120 const TypeImpl & 121 SBType::ref () const 122 { 123 // "const SBAddress &addr" should already have checked "addr.IsValid()" 124 // prior to calling this function. In case you didn't we will assert 125 // and die to let you know. 126 assert (m_opaque_sp.get()); 127 return *m_opaque_sp; 128 } 129 130 bool 131 SBType::IsValid() const 132 { 133 if (m_opaque_sp.get() == NULL) 134 return false; 135 136 return m_opaque_sp->IsValid(); 137 } 138 139 uint64_t 140 SBType::GetByteSize() 141 { 142 if (!IsValid()) 143 return 0; 144 145 return m_opaque_sp->GetCompilerType(false).GetByteSize(nullptr); 146 147 } 148 149 bool 150 SBType::IsPointerType() 151 { 152 if (!IsValid()) 153 return false; 154 return m_opaque_sp->GetCompilerType(true).IsPointerType(); 155 } 156 157 bool 158 SBType::IsArrayType() 159 { 160 if (!IsValid()) 161 return false; 162 return m_opaque_sp->GetCompilerType(true).IsArrayType(nullptr, nullptr, nullptr); 163 } 164 165 bool 166 SBType::IsVectorType() 167 { 168 if (!IsValid()) 169 return false; 170 return m_opaque_sp->GetCompilerType(true).IsVectorType(nullptr, nullptr); 171 } 172 173 bool 174 SBType::IsReferenceType() 175 { 176 if (!IsValid()) 177 return false; 178 return m_opaque_sp->GetCompilerType(true).IsReferenceType(); 179 } 180 181 SBType 182 SBType::GetPointerType() 183 { 184 if (!IsValid()) 185 return SBType(); 186 187 return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointerType()))); 188 } 189 190 SBType 191 SBType::GetPointeeType() 192 { 193 if (!IsValid()) 194 return SBType(); 195 return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointeeType()))); 196 } 197 198 SBType 199 SBType::GetReferenceType() 200 { 201 if (!IsValid()) 202 return SBType(); 203 return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetReferenceType()))); 204 } 205 206 SBType 207 SBType::GetTypedefedType() 208 { 209 if (!IsValid()) 210 return SBType(); 211 return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetTypedefedType()))); 212 } 213 214 SBType 215 SBType::GetDereferencedType() 216 { 217 if (!IsValid()) 218 return SBType(); 219 return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetDereferencedType()))); 220 } 221 222 SBType 223 SBType::GetArrayElementType() 224 { 225 if (!IsValid()) 226 return SBType(); 227 return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetCompilerType(true).GetArrayElementType()))); 228 } 229 230 SBType 231 SBType::GetVectorElementType () 232 { 233 SBType type_sb; 234 if (IsValid()) 235 { 236 CompilerType vector_element_type; 237 if (m_opaque_sp->GetCompilerType(true).IsVectorType(&vector_element_type, nullptr)) 238 type_sb.SetSP(TypeImplSP(new TypeImpl(vector_element_type))); 239 } 240 return type_sb; 241 } 242 243 bool 244 SBType::IsFunctionType () 245 { 246 if (!IsValid()) 247 return false; 248 return m_opaque_sp->GetCompilerType(true).IsFunctionType(); 249 } 250 251 bool 252 SBType::IsPolymorphicClass () 253 { 254 if (!IsValid()) 255 return false; 256 return m_opaque_sp->GetCompilerType(true).IsPolymorphicClass(); 257 } 258 259 bool 260 SBType::IsTypedefType () 261 { 262 if (!IsValid()) 263 return false; 264 return m_opaque_sp->GetCompilerType(true).IsTypedefType(); 265 } 266 267 bool 268 SBType::IsAnonymousType () 269 { 270 if (!IsValid()) 271 return false; 272 return m_opaque_sp->GetCompilerType(true).IsAnonymousType(); 273 } 274 275 lldb::SBType 276 SBType::GetFunctionReturnType () 277 { 278 if (IsValid()) 279 { 280 CompilerType return_type (m_opaque_sp->GetCompilerType(true).GetFunctionReturnType()); 281 if (return_type.IsValid()) 282 return SBType(return_type); 283 } 284 return lldb::SBType(); 285 } 286 287 lldb::SBTypeList 288 SBType::GetFunctionArgumentTypes () 289 { 290 SBTypeList sb_type_list; 291 if (IsValid()) 292 { 293 CompilerType func_type(m_opaque_sp->GetCompilerType(true)); 294 size_t count = func_type.GetNumberOfFunctionArguments(); 295 for (size_t i = 0; 296 i < count; 297 i++) 298 { 299 sb_type_list.Append(SBType(func_type.GetFunctionArgumentAtIndex(i))); 300 } 301 } 302 return sb_type_list; 303 } 304 305 uint32_t 306 SBType::GetNumberOfMemberFunctions () 307 { 308 if (IsValid()) 309 { 310 return m_opaque_sp->GetCompilerType(true).GetNumMemberFunctions(); 311 } 312 return 0; 313 } 314 315 lldb::SBTypeMemberFunction 316 SBType::GetMemberFunctionAtIndex (uint32_t idx) 317 { 318 SBTypeMemberFunction sb_func_type; 319 if (IsValid()) 320 sb_func_type.reset(new TypeMemberFunctionImpl(m_opaque_sp->GetCompilerType(true).GetMemberFunctionAtIndex(idx))); 321 return sb_func_type; 322 } 323 324 lldb::SBType 325 SBType::GetUnqualifiedType() 326 { 327 if (!IsValid()) 328 return SBType(); 329 return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetUnqualifiedType()))); 330 } 331 332 lldb::SBType 333 SBType::GetCanonicalType() 334 { 335 if (IsValid()) 336 return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetCanonicalType()))); 337 return SBType(); 338 } 339 340 341 lldb::BasicType 342 SBType::GetBasicType() 343 { 344 if (IsValid()) 345 return m_opaque_sp->GetCompilerType(false).GetBasicTypeEnumeration (); 346 return eBasicTypeInvalid; 347 } 348 349 SBType 350 SBType::GetBasicType(lldb::BasicType basic_type) 351 { 352 if (IsValid() && m_opaque_sp->IsValid()) 353 return SBType(m_opaque_sp->GetTypeSystem(false)->GetBasicTypeFromAST(basic_type)); 354 return SBType(); 355 } 356 357 uint32_t 358 SBType::GetNumberOfDirectBaseClasses () 359 { 360 if (IsValid()) 361 return m_opaque_sp->GetCompilerType(true).GetNumDirectBaseClasses(); 362 return 0; 363 } 364 365 uint32_t 366 SBType::GetNumberOfVirtualBaseClasses () 367 { 368 if (IsValid()) 369 return m_opaque_sp->GetCompilerType(true).GetNumVirtualBaseClasses(); 370 return 0; 371 } 372 373 uint32_t 374 SBType::GetNumberOfFields () 375 { 376 if (IsValid()) 377 return m_opaque_sp->GetCompilerType(true).GetNumFields(); 378 return 0; 379 } 380 381 bool 382 SBType::GetDescription (SBStream &description, lldb::DescriptionLevel description_level) 383 { 384 Stream &strm = description.ref(); 385 386 if (m_opaque_sp) 387 { 388 m_opaque_sp->GetDescription (strm, description_level); 389 } 390 else 391 strm.PutCString ("No value"); 392 393 return true; 394 } 395 396 397 398 SBTypeMember 399 SBType::GetDirectBaseClassAtIndex (uint32_t idx) 400 { 401 SBTypeMember sb_type_member; 402 if (IsValid()) 403 { 404 uint32_t bit_offset = 0; 405 CompilerType base_class_type = m_opaque_sp->GetCompilerType (true).GetDirectBaseClassAtIndex(idx, &bit_offset); 406 if (base_class_type.IsValid()) 407 sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); 408 } 409 return sb_type_member; 410 411 } 412 413 SBTypeMember 414 SBType::GetVirtualBaseClassAtIndex (uint32_t idx) 415 { 416 SBTypeMember sb_type_member; 417 if (IsValid()) 418 { 419 uint32_t bit_offset = 0; 420 CompilerType base_class_type = m_opaque_sp->GetCompilerType (true).GetVirtualBaseClassAtIndex(idx, &bit_offset); 421 if (base_class_type.IsValid()) 422 sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); 423 } 424 return sb_type_member; 425 } 426 427 SBTypeEnumMemberList 428 SBType::GetEnumMembers () 429 { 430 SBTypeEnumMemberList sb_enum_member_list; 431 if (IsValid()) 432 { 433 CompilerType this_type (m_opaque_sp->GetCompilerType (true)); 434 if (this_type.IsValid()) 435 { 436 this_type.ForEachEnumerator([&sb_enum_member_list] (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value) -> bool { 437 SBTypeEnumMember enum_member (lldb::TypeEnumMemberImplSP (new TypeEnumMemberImpl(lldb::TypeImplSP(new TypeImpl(integer_type)), name, value))); 438 sb_enum_member_list.Append(enum_member); 439 return true; // Keep iterating 440 }); 441 } 442 } 443 return sb_enum_member_list; 444 } 445 446 SBTypeMember 447 SBType::GetFieldAtIndex (uint32_t idx) 448 { 449 SBTypeMember sb_type_member; 450 if (IsValid()) 451 { 452 CompilerType this_type (m_opaque_sp->GetCompilerType (false)); 453 if (this_type.IsValid()) 454 { 455 uint64_t bit_offset = 0; 456 uint32_t bitfield_bit_size = 0; 457 bool is_bitfield = false; 458 std::string name_sstr; 459 CompilerType field_type (this_type.GetFieldAtIndex (idx, 460 name_sstr, 461 &bit_offset, 462 &bitfield_bit_size, 463 &is_bitfield)); 464 if (field_type.IsValid()) 465 { 466 ConstString name; 467 if (!name_sstr.empty()) 468 name.SetCString(name_sstr.c_str()); 469 sb_type_member.reset (new TypeMemberImpl (TypeImplSP (new TypeImpl(field_type)), 470 bit_offset, 471 name, 472 bitfield_bit_size, 473 is_bitfield)); 474 } 475 } 476 } 477 return sb_type_member; 478 } 479 480 bool 481 SBType::IsTypeComplete() 482 { 483 if (!IsValid()) 484 return false; 485 return m_opaque_sp->GetCompilerType(false).IsCompleteType(); 486 } 487 488 uint32_t 489 SBType::GetTypeFlags () 490 { 491 if (!IsValid()) 492 return 0; 493 return m_opaque_sp->GetCompilerType(true).GetTypeInfo(); 494 } 495 496 const char* 497 SBType::GetName() 498 { 499 if (!IsValid()) 500 return ""; 501 return m_opaque_sp->GetName().GetCString(); 502 } 503 504 const char * 505 SBType::GetDisplayTypeName () 506 { 507 if (!IsValid()) 508 return ""; 509 return m_opaque_sp->GetDisplayTypeName().GetCString(); 510 } 511 512 lldb::TypeClass 513 SBType::GetTypeClass () 514 { 515 if (IsValid()) 516 return m_opaque_sp->GetCompilerType(true).GetTypeClass(); 517 return lldb::eTypeClassInvalid; 518 } 519 520 uint32_t 521 SBType::GetNumberOfTemplateArguments () 522 { 523 if (IsValid()) 524 return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments(); 525 return 0; 526 } 527 528 lldb::SBType 529 SBType::GetTemplateArgumentType (uint32_t idx) 530 { 531 if (IsValid()) 532 { 533 TemplateArgumentKind kind = eTemplateArgumentKindNull; 534 CompilerType template_arg_type = m_opaque_sp->GetCompilerType(false).GetTemplateArgument(idx, kind); 535 if (template_arg_type.IsValid()) 536 return SBType(template_arg_type); 537 } 538 return SBType(); 539 } 540 541 542 lldb::TemplateArgumentKind 543 SBType::GetTemplateArgumentKind (uint32_t idx) 544 { 545 TemplateArgumentKind kind = eTemplateArgumentKindNull; 546 if (IsValid()) 547 m_opaque_sp->GetCompilerType(false).GetTemplateArgument(idx, kind); 548 return kind; 549 } 550 551 552 SBTypeList::SBTypeList() : 553 m_opaque_ap(new TypeListImpl()) 554 { 555 } 556 557 SBTypeList::SBTypeList(const SBTypeList& rhs) : 558 m_opaque_ap(new TypeListImpl()) 559 { 560 for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++) 561 Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i)); 562 } 563 564 bool 565 SBTypeList::IsValid () 566 { 567 return (m_opaque_ap.get() != NULL); 568 } 569 570 SBTypeList& 571 SBTypeList::operator = (const SBTypeList& rhs) 572 { 573 if (this != &rhs) 574 { 575 m_opaque_ap.reset (new TypeListImpl()); 576 for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++) 577 Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i)); 578 } 579 return *this; 580 } 581 582 void 583 SBTypeList::Append (SBType type) 584 { 585 if (type.IsValid()) 586 m_opaque_ap->Append (type.m_opaque_sp); 587 } 588 589 SBType 590 SBTypeList::GetTypeAtIndex(uint32_t index) 591 { 592 if (m_opaque_ap.get()) 593 return SBType(m_opaque_ap->GetTypeAtIndex(index)); 594 return SBType(); 595 } 596 597 uint32_t 598 SBTypeList::GetSize() 599 { 600 return m_opaque_ap->GetSize(); 601 } 602 603 SBTypeList::~SBTypeList() 604 { 605 } 606 607 SBTypeMember::SBTypeMember() : 608 m_opaque_ap() 609 { 610 } 611 612 SBTypeMember::~SBTypeMember() 613 { 614 } 615 616 SBTypeMember::SBTypeMember (const SBTypeMember& rhs) : 617 m_opaque_ap() 618 { 619 if (this != &rhs) 620 { 621 if (rhs.IsValid()) 622 m_opaque_ap.reset(new TypeMemberImpl(rhs.ref())); 623 } 624 } 625 626 lldb::SBTypeMember& 627 SBTypeMember::operator = (const lldb::SBTypeMember& rhs) 628 { 629 if (this != &rhs) 630 { 631 if (rhs.IsValid()) 632 m_opaque_ap.reset(new TypeMemberImpl(rhs.ref())); 633 } 634 return *this; 635 } 636 637 bool 638 SBTypeMember::IsValid() const 639 { 640 return m_opaque_ap.get(); 641 } 642 643 const char * 644 SBTypeMember::GetName () 645 { 646 if (m_opaque_ap.get()) 647 return m_opaque_ap->GetName().GetCString(); 648 return NULL; 649 } 650 651 SBType 652 SBTypeMember::GetType () 653 { 654 SBType sb_type; 655 if (m_opaque_ap.get()) 656 { 657 sb_type.SetSP (m_opaque_ap->GetTypeImpl()); 658 } 659 return sb_type; 660 661 } 662 663 uint64_t 664 SBTypeMember::GetOffsetInBytes() 665 { 666 if (m_opaque_ap.get()) 667 return m_opaque_ap->GetBitOffset() / 8u; 668 return 0; 669 } 670 671 uint64_t 672 SBTypeMember::GetOffsetInBits() 673 { 674 if (m_opaque_ap.get()) 675 return m_opaque_ap->GetBitOffset(); 676 return 0; 677 } 678 679 bool 680 SBTypeMember::IsBitfield() 681 { 682 if (m_opaque_ap.get()) 683 return m_opaque_ap->GetIsBitfield(); 684 return false; 685 } 686 687 uint32_t 688 SBTypeMember::GetBitfieldSizeInBits() 689 { 690 if (m_opaque_ap.get()) 691 return m_opaque_ap->GetBitfieldBitSize(); 692 return 0; 693 } 694 695 696 bool 697 SBTypeMember::GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level) 698 { 699 Stream &strm = description.ref(); 700 701 if (m_opaque_ap.get()) 702 { 703 const uint32_t bit_offset = m_opaque_ap->GetBitOffset(); 704 const uint32_t byte_offset = bit_offset / 8u; 705 const uint32_t byte_bit_offset = bit_offset % 8u; 706 const char *name = m_opaque_ap->GetName().GetCString(); 707 if (byte_bit_offset) 708 strm.Printf ("+%u + %u bits: (", byte_offset, byte_bit_offset); 709 else 710 strm.Printf ("+%u: (", byte_offset); 711 712 TypeImplSP type_impl_sp (m_opaque_ap->GetTypeImpl()); 713 if (type_impl_sp) 714 type_impl_sp->GetDescription(strm, description_level); 715 716 strm.Printf (") %s", name); 717 if (m_opaque_ap->GetIsBitfield()) 718 { 719 const uint32_t bitfield_bit_size = m_opaque_ap->GetBitfieldBitSize(); 720 strm.Printf (" : %u", bitfield_bit_size); 721 } 722 } 723 else 724 { 725 strm.PutCString ("No value"); 726 } 727 return true; 728 } 729 730 731 void 732 SBTypeMember::reset(TypeMemberImpl *type_member_impl) 733 { 734 m_opaque_ap.reset(type_member_impl); 735 } 736 737 TypeMemberImpl & 738 SBTypeMember::ref () 739 { 740 if (m_opaque_ap.get() == NULL) 741 m_opaque_ap.reset (new TypeMemberImpl()); 742 return *m_opaque_ap.get(); 743 } 744 745 const TypeMemberImpl & 746 SBTypeMember::ref () const 747 { 748 return *m_opaque_ap.get(); 749 } 750 751 SBTypeMemberFunction::SBTypeMemberFunction() : 752 m_opaque_sp() 753 { 754 } 755 756 SBTypeMemberFunction::~SBTypeMemberFunction() 757 { 758 } 759 760 SBTypeMemberFunction::SBTypeMemberFunction (const SBTypeMemberFunction& rhs) : 761 m_opaque_sp(rhs.m_opaque_sp) 762 { 763 } 764 765 lldb::SBTypeMemberFunction& 766 SBTypeMemberFunction::operator = (const lldb::SBTypeMemberFunction& rhs) 767 { 768 if (this != &rhs) 769 m_opaque_sp = rhs.m_opaque_sp; 770 return *this; 771 } 772 773 bool 774 SBTypeMemberFunction::IsValid() const 775 { 776 return m_opaque_sp.get(); 777 } 778 779 const char * 780 SBTypeMemberFunction::GetName () 781 { 782 if (m_opaque_sp) 783 return m_opaque_sp->GetName().GetCString(); 784 return NULL; 785 } 786 787 SBType 788 SBTypeMemberFunction::GetType () 789 { 790 SBType sb_type; 791 if (m_opaque_sp) 792 { 793 sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetType()))); 794 } 795 return sb_type; 796 } 797 798 lldb::SBType 799 SBTypeMemberFunction::GetReturnType () 800 { 801 SBType sb_type; 802 if (m_opaque_sp) 803 { 804 sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetReturnType()))); 805 } 806 return sb_type; 807 } 808 809 uint32_t 810 SBTypeMemberFunction::GetNumberOfArguments () 811 { 812 if (m_opaque_sp) 813 return m_opaque_sp->GetNumArguments(); 814 return 0; 815 } 816 817 lldb::SBType 818 SBTypeMemberFunction::GetArgumentTypeAtIndex (uint32_t i) 819 { 820 SBType sb_type; 821 if (m_opaque_sp) 822 { 823 sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetArgumentAtIndex(i)))); 824 } 825 return sb_type; 826 } 827 828 lldb::MemberFunctionKind 829 SBTypeMemberFunction::GetKind () 830 { 831 if (m_opaque_sp) 832 return m_opaque_sp->GetKind(); 833 return lldb::eMemberFunctionKindUnknown; 834 835 } 836 837 bool 838 SBTypeMemberFunction::GetDescription (lldb::SBStream &description, 839 lldb::DescriptionLevel description_level) 840 { 841 Stream &strm = description.ref(); 842 843 if (m_opaque_sp) 844 return m_opaque_sp->GetDescription(strm); 845 846 return false; 847 } 848 849 void 850 SBTypeMemberFunction::reset(TypeMemberFunctionImpl *type_member_impl) 851 { 852 m_opaque_sp.reset(type_member_impl); 853 } 854 855 TypeMemberFunctionImpl & 856 SBTypeMemberFunction::ref () 857 { 858 if (!m_opaque_sp) 859 m_opaque_sp.reset (new TypeMemberFunctionImpl()); 860 return *m_opaque_sp.get(); 861 } 862 863 const TypeMemberFunctionImpl & 864 SBTypeMemberFunction::ref () const 865 { 866 return *m_opaque_sp.get(); 867 } 868