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