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(nullptr);
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::IsVectorType()
168 {
169     if (!IsValid())
170         return false;
171     return m_opaque_sp->GetClangASTType(true).IsVectorType(nullptr, nullptr);
172 }
173 
174 bool
175 SBType::IsReferenceType()
176 {
177     if (!IsValid())
178         return false;
179     return m_opaque_sp->GetClangASTType(true).IsReferenceType();
180 }
181 
182 SBType
183 SBType::GetPointerType()
184 {
185     if (!IsValid())
186         return SBType();
187 
188     return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointerType())));
189 }
190 
191 SBType
192 SBType::GetPointeeType()
193 {
194     if (!IsValid())
195         return SBType();
196     return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointeeType())));
197 }
198 
199 SBType
200 SBType::GetReferenceType()
201 {
202     if (!IsValid())
203         return SBType();
204     return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetReferenceType())));
205 }
206 
207 SBType
208 SBType::GetTypedefedType()
209 {
210     if (!IsValid())
211         return SBType();
212     return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetTypedefedType())));
213 }
214 
215 SBType
216 SBType::GetDereferencedType()
217 {
218     if (!IsValid())
219         return SBType();
220     return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetDereferencedType())));
221 }
222 
223 SBType
224 SBType::GetArrayElementType()
225 {
226     if (!IsValid())
227         return SBType();
228     return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetClangASTType(true).GetArrayElementType())));
229 }
230 
231 SBType
232 SBType::GetVectorElementType ()
233 {
234     SBType type_sb;
235     if (IsValid())
236     {
237         ClangASTType vector_element_type;
238         if (m_opaque_sp->GetClangASTType(true).IsVectorType(&vector_element_type, nullptr))
239             type_sb.SetSP(TypeImplSP(new TypeImpl(vector_element_type)));
240     }
241     return type_sb;
242 }
243 
244 bool
245 SBType::IsFunctionType ()
246 {
247     if (!IsValid())
248         return false;
249     return m_opaque_sp->GetClangASTType(true).IsFunctionType();
250 }
251 
252 bool
253 SBType::IsPolymorphicClass ()
254 {
255     if (!IsValid())
256         return false;
257     return m_opaque_sp->GetClangASTType(true).IsPolymorphicClass();
258 }
259 
260 bool
261 SBType::IsTypedefType ()
262 {
263     if (!IsValid())
264         return false;
265     return m_opaque_sp->GetClangASTType(true).IsTypedefType();
266 }
267 
268 lldb::SBType
269 SBType::GetFunctionReturnType ()
270 {
271     if (IsValid())
272     {
273         ClangASTType return_clang_type (m_opaque_sp->GetClangASTType(true).GetFunctionReturnType());
274         if (return_clang_type.IsValid())
275             return SBType(return_clang_type);
276     }
277     return lldb::SBType();
278 }
279 
280 lldb::SBTypeList
281 SBType::GetFunctionArgumentTypes ()
282 {
283     SBTypeList sb_type_list;
284     if (IsValid())
285     {
286         ClangASTType func_type(m_opaque_sp->GetClangASTType(true));
287         size_t count = func_type.GetNumberOfFunctionArguments();
288         for (size_t i = 0;
289              i < count;
290              i++)
291         {
292             sb_type_list.Append(SBType(func_type.GetFunctionArgumentAtIndex(i)));
293         }
294     }
295     return sb_type_list;
296 }
297 
298 uint32_t
299 SBType::GetNumberOfMemberFunctions ()
300 {
301     if (IsValid())
302     {
303         return m_opaque_sp->GetClangASTType(true).GetNumMemberFunctions();
304     }
305     return 0;
306 }
307 
308 lldb::SBTypeMemberFunction
309 SBType::GetMemberFunctionAtIndex (uint32_t idx)
310 {
311     SBTypeMemberFunction sb_func_type;
312     if (IsValid())
313         sb_func_type.reset(new TypeMemberFunctionImpl(m_opaque_sp->GetClangASTType(true).GetMemberFunctionAtIndex(idx)));
314     return sb_func_type;
315 }
316 
317 lldb::SBType
318 SBType::GetUnqualifiedType()
319 {
320     if (!IsValid())
321         return SBType();
322     return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetUnqualifiedType())));
323 }
324 
325 lldb::SBType
326 SBType::GetCanonicalType()
327 {
328     if (IsValid())
329         return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetCanonicalType())));
330     return SBType();
331 }
332 
333 
334 lldb::BasicType
335 SBType::GetBasicType()
336 {
337     if (IsValid())
338         return m_opaque_sp->GetClangASTType(false).GetBasicTypeEnumeration ();
339     return eBasicTypeInvalid;
340 }
341 
342 SBType
343 SBType::GetBasicType(lldb::BasicType basic_type)
344 {
345     if (IsValid())
346         return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetClangASTContext(false), basic_type));
347     return SBType();
348 }
349 
350 uint32_t
351 SBType::GetNumberOfDirectBaseClasses ()
352 {
353     if (IsValid())
354         return m_opaque_sp->GetClangASTType(true).GetNumDirectBaseClasses();
355     return 0;
356 }
357 
358 uint32_t
359 SBType::GetNumberOfVirtualBaseClasses ()
360 {
361     if (IsValid())
362         return m_opaque_sp->GetClangASTType(true).GetNumVirtualBaseClasses();
363     return 0;
364 }
365 
366 uint32_t
367 SBType::GetNumberOfFields ()
368 {
369     if (IsValid())
370         return m_opaque_sp->GetClangASTType(true).GetNumFields();
371     return 0;
372 }
373 
374 bool
375 SBType::GetDescription (SBStream &description, lldb::DescriptionLevel description_level)
376 {
377     Stream &strm = description.ref();
378 
379     if (m_opaque_sp)
380     {
381         m_opaque_sp->GetDescription (strm, description_level);
382     }
383     else
384         strm.PutCString ("No value");
385 
386     return true;
387 }
388 
389 
390 
391 SBTypeMember
392 SBType::GetDirectBaseClassAtIndex (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.GetDirectBaseClassAtIndex(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 
412 SBTypeMember
413 SBType::GetVirtualBaseClassAtIndex (uint32_t idx)
414 {
415     SBTypeMember sb_type_member;
416     if (IsValid())
417     {
418         ClangASTType this_type (m_opaque_sp->GetClangASTType (true));
419         if (this_type.IsValid())
420         {
421             uint32_t bit_offset = 0;
422             ClangASTType base_class_type (this_type.GetVirtualBaseClassAtIndex(idx, &bit_offset));
423             if (base_class_type.IsValid())
424             {
425                 sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset));
426             }
427         }
428     }
429     return sb_type_member;
430 }
431 
432 SBTypeEnumMemberList
433 SBType::GetEnumMembers ()
434 {
435     SBTypeEnumMemberList sb_enum_member_list;
436     if (IsValid())
437     {
438         const clang::EnumDecl *enum_decl = m_opaque_sp->GetClangASTType(true).GetFullyUnqualifiedType().GetAsEnumDecl();
439         if (enum_decl)
440         {
441             clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
442             for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
443             {
444                 SBTypeEnumMember enum_member;
445                 enum_member.reset(new TypeEnumMemberImpl(*enum_pos, ClangASTType(m_opaque_sp->GetClangASTContext(true), enum_decl->getIntegerType())));
446                 sb_enum_member_list.Append(enum_member);
447             }
448         }
449     }
450     return sb_enum_member_list;
451 }
452 
453 SBTypeMember
454 SBType::GetFieldAtIndex (uint32_t idx)
455 {
456     SBTypeMember sb_type_member;
457     if (IsValid())
458     {
459         ClangASTType this_type (m_opaque_sp->GetClangASTType (false));
460         if (this_type.IsValid())
461         {
462             uint64_t bit_offset = 0;
463             uint32_t bitfield_bit_size = 0;
464             bool is_bitfield = false;
465             std::string name_sstr;
466             ClangASTType field_type (this_type.GetFieldAtIndex (idx,
467                                                                 name_sstr,
468                                                                 &bit_offset,
469                                                                 &bitfield_bit_size,
470                                                                 &is_bitfield));
471             if (field_type.IsValid())
472             {
473                 ConstString name;
474                 if (!name_sstr.empty())
475                     name.SetCString(name_sstr.c_str());
476                 sb_type_member.reset (new TypeMemberImpl (TypeImplSP (new TypeImpl(field_type)),
477                                                           bit_offset,
478                                                           name,
479                                                           bitfield_bit_size,
480                                                           is_bitfield));
481             }
482         }
483     }
484     return sb_type_member;
485 }
486 
487 bool
488 SBType::IsTypeComplete()
489 {
490     if (!IsValid())
491         return false;
492     return m_opaque_sp->GetClangASTType(false).IsCompleteType();
493 }
494 
495 uint32_t
496 SBType::GetTypeFlags ()
497 {
498     if (!IsValid())
499         return 0;
500     return m_opaque_sp->GetClangASTType(true).GetTypeInfo();
501 }
502 
503 const char*
504 SBType::GetName()
505 {
506     if (!IsValid())
507         return "";
508     return m_opaque_sp->GetName().GetCString();
509 }
510 
511 const char *
512 SBType::GetDisplayTypeName ()
513 {
514     if (!IsValid())
515         return "";
516     return m_opaque_sp->GetDisplayTypeName().GetCString();
517 }
518 
519 lldb::TypeClass
520 SBType::GetTypeClass ()
521 {
522     if (IsValid())
523         return m_opaque_sp->GetClangASTType(true).GetTypeClass();
524     return lldb::eTypeClassInvalid;
525 }
526 
527 uint32_t
528 SBType::GetNumberOfTemplateArguments ()
529 {
530     if (IsValid())
531         return m_opaque_sp->GetClangASTType(false).GetNumTemplateArguments();
532     return 0;
533 }
534 
535 lldb::SBType
536 SBType::GetTemplateArgumentType (uint32_t idx)
537 {
538     if (IsValid())
539     {
540         TemplateArgumentKind kind = eTemplateArgumentKindNull;
541         ClangASTType template_arg_type = m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind);
542         if (template_arg_type.IsValid())
543             return SBType(template_arg_type);
544     }
545     return SBType();
546 }
547 
548 
549 lldb::TemplateArgumentKind
550 SBType::GetTemplateArgumentKind (uint32_t idx)
551 {
552     TemplateArgumentKind kind = eTemplateArgumentKindNull;
553     if (IsValid())
554         m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind);
555     return kind;
556 }
557 
558 
559 SBTypeList::SBTypeList() :
560     m_opaque_ap(new TypeListImpl())
561 {
562 }
563 
564 SBTypeList::SBTypeList(const SBTypeList& rhs) :
565     m_opaque_ap(new TypeListImpl())
566 {
567     for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++)
568         Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i));
569 }
570 
571 bool
572 SBTypeList::IsValid ()
573 {
574     return (m_opaque_ap.get() != NULL);
575 }
576 
577 SBTypeList&
578 SBTypeList::operator = (const SBTypeList& rhs)
579 {
580     if (this != &rhs)
581     {
582         m_opaque_ap.reset (new TypeListImpl());
583         for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++)
584             Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i));
585     }
586     return *this;
587 }
588 
589 void
590 SBTypeList::Append (SBType type)
591 {
592     if (type.IsValid())
593         m_opaque_ap->Append (type.m_opaque_sp);
594 }
595 
596 SBType
597 SBTypeList::GetTypeAtIndex(uint32_t index)
598 {
599     if (m_opaque_ap.get())
600         return SBType(m_opaque_ap->GetTypeAtIndex(index));
601     return SBType();
602 }
603 
604 uint32_t
605 SBTypeList::GetSize()
606 {
607     return m_opaque_ap->GetSize();
608 }
609 
610 SBTypeList::~SBTypeList()
611 {
612 }
613 
614 SBTypeMember::SBTypeMember() :
615     m_opaque_ap()
616 {
617 }
618 
619 SBTypeMember::~SBTypeMember()
620 {
621 }
622 
623 SBTypeMember::SBTypeMember (const SBTypeMember& rhs) :
624     m_opaque_ap()
625 {
626     if (this != &rhs)
627     {
628         if (rhs.IsValid())
629             m_opaque_ap.reset(new TypeMemberImpl(rhs.ref()));
630     }
631 }
632 
633 lldb::SBTypeMember&
634 SBTypeMember::operator = (const lldb::SBTypeMember& rhs)
635 {
636     if (this != &rhs)
637     {
638         if (rhs.IsValid())
639             m_opaque_ap.reset(new TypeMemberImpl(rhs.ref()));
640     }
641     return *this;
642 }
643 
644 bool
645 SBTypeMember::IsValid() const
646 {
647     return m_opaque_ap.get();
648 }
649 
650 const char *
651 SBTypeMember::GetName ()
652 {
653     if (m_opaque_ap.get())
654         return m_opaque_ap->GetName().GetCString();
655     return NULL;
656 }
657 
658 SBType
659 SBTypeMember::GetType ()
660 {
661     SBType sb_type;
662     if (m_opaque_ap.get())
663     {
664         sb_type.SetSP (m_opaque_ap->GetTypeImpl());
665     }
666     return sb_type;
667 
668 }
669 
670 uint64_t
671 SBTypeMember::GetOffsetInBytes()
672 {
673     if (m_opaque_ap.get())
674         return m_opaque_ap->GetBitOffset() / 8u;
675     return 0;
676 }
677 
678 uint64_t
679 SBTypeMember::GetOffsetInBits()
680 {
681     if (m_opaque_ap.get())
682         return m_opaque_ap->GetBitOffset();
683     return 0;
684 }
685 
686 bool
687 SBTypeMember::IsBitfield()
688 {
689     if (m_opaque_ap.get())
690         return m_opaque_ap->GetIsBitfield();
691     return false;
692 }
693 
694 uint32_t
695 SBTypeMember::GetBitfieldSizeInBits()
696 {
697     if (m_opaque_ap.get())
698         return m_opaque_ap->GetBitfieldBitSize();
699     return 0;
700 }
701 
702 
703 bool
704 SBTypeMember::GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level)
705 {
706     Stream &strm = description.ref();
707 
708     if (m_opaque_ap.get())
709     {
710         const uint32_t bit_offset = m_opaque_ap->GetBitOffset();
711         const uint32_t byte_offset = bit_offset / 8u;
712         const uint32_t byte_bit_offset = bit_offset % 8u;
713         const char *name = m_opaque_ap->GetName().GetCString();
714         if (byte_bit_offset)
715             strm.Printf ("+%u + %u bits: (", byte_offset, byte_bit_offset);
716         else
717             strm.Printf ("+%u: (", byte_offset);
718 
719         TypeImplSP type_impl_sp (m_opaque_ap->GetTypeImpl());
720         if (type_impl_sp)
721             type_impl_sp->GetDescription(strm, description_level);
722 
723         strm.Printf (") %s", name);
724         if (m_opaque_ap->GetIsBitfield())
725         {
726             const uint32_t bitfield_bit_size = m_opaque_ap->GetBitfieldBitSize();
727             strm.Printf (" : %u", bitfield_bit_size);
728         }
729     }
730     else
731     {
732         strm.PutCString ("No value");
733     }
734     return true;
735 }
736 
737 
738 void
739 SBTypeMember::reset(TypeMemberImpl *type_member_impl)
740 {
741     m_opaque_ap.reset(type_member_impl);
742 }
743 
744 TypeMemberImpl &
745 SBTypeMember::ref ()
746 {
747     if (m_opaque_ap.get() == NULL)
748         m_opaque_ap.reset (new TypeMemberImpl());
749     return *m_opaque_ap.get();
750 }
751 
752 const TypeMemberImpl &
753 SBTypeMember::ref () const
754 {
755     return *m_opaque_ap.get();
756 }
757 
758 SBTypeMemberFunction::SBTypeMemberFunction() :
759 m_opaque_sp()
760 {
761 }
762 
763 SBTypeMemberFunction::~SBTypeMemberFunction()
764 {
765 }
766 
767 SBTypeMemberFunction::SBTypeMemberFunction (const SBTypeMemberFunction& rhs) :
768     m_opaque_sp(rhs.m_opaque_sp)
769 {
770 }
771 
772 lldb::SBTypeMemberFunction&
773 SBTypeMemberFunction::operator = (const lldb::SBTypeMemberFunction& rhs)
774 {
775     if (this != &rhs)
776         m_opaque_sp = rhs.m_opaque_sp;
777     return *this;
778 }
779 
780 bool
781 SBTypeMemberFunction::IsValid() const
782 {
783     return m_opaque_sp.get();
784 }
785 
786 const char *
787 SBTypeMemberFunction::GetName ()
788 {
789     if (m_opaque_sp)
790         return m_opaque_sp->GetName().GetCString();
791     return NULL;
792 }
793 
794 SBType
795 SBTypeMemberFunction::GetType ()
796 {
797     SBType sb_type;
798     if (m_opaque_sp)
799     {
800         sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetType())));
801     }
802     return sb_type;
803 }
804 
805 lldb::SBType
806 SBTypeMemberFunction::GetReturnType ()
807 {
808     SBType sb_type;
809     if (m_opaque_sp)
810     {
811         sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetReturnType())));
812     }
813     return sb_type;
814 }
815 
816 uint32_t
817 SBTypeMemberFunction::GetNumberOfArguments ()
818 {
819     if (m_opaque_sp)
820         return m_opaque_sp->GetNumArguments();
821     return 0;
822 }
823 
824 lldb::SBType
825 SBTypeMemberFunction::GetArgumentTypeAtIndex (uint32_t i)
826 {
827     SBType sb_type;
828     if (m_opaque_sp)
829     {
830         sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetArgumentAtIndex(i))));
831     }
832     return sb_type;
833 }
834 
835 lldb::MemberFunctionKind
836 SBTypeMemberFunction::GetKind ()
837 {
838     if (m_opaque_sp)
839         return m_opaque_sp->GetKind();
840     return lldb::eMemberFunctionKindUnknown;
841 
842 }
843 
844 bool
845 SBTypeMemberFunction::GetDescription (lldb::SBStream &description,
846                                       lldb::DescriptionLevel description_level)
847 {
848     Stream &strm = description.ref();
849 
850     if (m_opaque_sp)
851         return m_opaque_sp->GetDescription(strm);
852 
853     return false;
854 }
855 
856 void
857 SBTypeMemberFunction::reset(TypeMemberFunctionImpl *type_member_impl)
858 {
859     m_opaque_sp.reset(type_member_impl);
860 }
861 
862 TypeMemberFunctionImpl &
863 SBTypeMemberFunction::ref ()
864 {
865     if (!m_opaque_sp)
866         m_opaque_sp.reset (new TypeMemberFunctionImpl());
867     return *m_opaque_sp.get();
868 }
869 
870 const TypeMemberFunctionImpl &
871 SBTypeMemberFunction::ref () const
872 {
873     return *m_opaque_sp.get();
874 }
875