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 <string.h>
11 
12 #include "clang/AST/ASTContext.h"
13 #include "clang/AST/TemplateBase.h"
14 #include "clang/AST/Type.h"
15 
16 #include "lldb/API/SBDefines.h"
17 #include "lldb/API/SBType.h"
18 #include "lldb/API/SBStream.h"
19 #include "lldb/Core/ConstString.h"
20 #include "lldb/Core/Log.h"
21 #include "lldb/Core/Stream.h"
22 #include "lldb/Symbol/ClangASTContext.h"
23 #include "lldb/Symbol/ClangASTType.h"
24 #include "lldb/Symbol/Type.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 using namespace clang;
29 
30 SBType::SBType() :
31     m_opaque_sp()
32 {
33 }
34 
35 SBType::SBType (const ClangASTType &type) :
36     m_opaque_sp(new TypeImpl(ClangASTType(type.GetASTContext(),
37                                           type.GetOpaqueQualType())))
38 {
39 }
40 
41 SBType::SBType (const lldb::TypeSP &type_sp) :
42     m_opaque_sp(new TypeImpl(type_sp))
43 {
44 }
45 
46 SBType::SBType (const lldb::TypeImplSP &type_impl_sp) :
47     m_opaque_sp(type_impl_sp)
48 {
49 }
50 
51 
52 SBType::SBType (const SBType &rhs) :
53     m_opaque_sp()
54 {
55     if (this != &rhs)
56     {
57         m_opaque_sp = rhs.m_opaque_sp;
58     }
59 }
60 
61 
62 //SBType::SBType (TypeImpl* impl) :
63 //    m_opaque_ap(impl)
64 //{}
65 //
66 bool
67 SBType::operator == (SBType &rhs)
68 {
69     if (IsValid() == false)
70         return !rhs.IsValid();
71 
72     return  (rhs.m_opaque_sp->GetASTContext() == m_opaque_sp->GetASTContext()) &&
73             (rhs.m_opaque_sp->GetOpaqueQualType() == m_opaque_sp->GetOpaqueQualType());
74 }
75 
76 bool
77 SBType::operator != (SBType &rhs)
78 {
79     if (IsValid() == false)
80         return rhs.IsValid();
81 
82     return  (rhs.m_opaque_sp->GetASTContext() != m_opaque_sp->GetASTContext()) ||
83             (rhs.m_opaque_sp->GetOpaqueQualType() != m_opaque_sp->GetOpaqueQualType());
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 size_t
140 SBType::GetByteSize()
141 {
142     if (!IsValid())
143         return 0;
144 
145     return ClangASTType::GetTypeByteSize(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType());
146 
147 }
148 
149 bool
150 SBType::IsPointerType()
151 {
152     if (!IsValid())
153         return false;
154 
155     QualType qt = QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType());
156     const clang::Type* typePtr = qt.getTypePtrOrNull();
157 
158     if (typePtr)
159         return typePtr->isAnyPointerType();
160     return false;
161 }
162 
163 bool
164 SBType::IsReferenceType()
165 {
166     if (!IsValid())
167         return false;
168 
169     QualType qt = QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType());
170     const clang::Type* typePtr = qt.getTypePtrOrNull();
171 
172     if (typePtr)
173         return typePtr->isReferenceType();
174     return false;
175 }
176 
177 SBType
178 SBType::GetPointerType()
179 {
180     if (!IsValid())
181         return SBType();
182 
183     return SBType(ClangASTType(m_opaque_sp->GetASTContext(),
184                                ClangASTContext::CreatePointerType(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType())));
185 }
186 
187 SBType
188 SBType::GetPointeeType()
189 {
190     if (!IsValid())
191         return SBType();
192 
193     QualType qt = QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType());
194     const clang::Type* typePtr = qt.getTypePtrOrNull();
195 
196     if (typePtr)
197         return SBType(ClangASTType(m_opaque_sp->GetASTContext(),typePtr->getPointeeType().getAsOpaquePtr()));
198     return SBType();
199 }
200 
201 SBType
202 SBType::GetReferenceType()
203 {
204     if (!IsValid())
205         return SBType();
206 
207     return SBType(ClangASTType(m_opaque_sp->GetASTContext(),
208                                ClangASTContext::CreateLValueReferenceType(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType())));
209 }
210 
211 SBType
212 SBType::GetDereferencedType()
213 {
214     if (!IsValid())
215         return SBType();
216 
217     QualType qt = QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType());
218 
219     return SBType(ClangASTType(m_opaque_sp->GetASTContext(),qt.getNonReferenceType().getAsOpaquePtr()));
220 }
221 
222 bool
223 SBType::IsFunctionType ()
224 {
225     if (IsValid())
226     {
227         QualType qual_type(QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType()));
228         const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
229         return func != NULL;
230     }
231     return false;
232 }
233 
234 lldb::SBType
235 SBType::GetFunctionReturnType ()
236 {
237     if (IsValid())
238     {
239         QualType qual_type(QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType()));
240         const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
241 
242         if (func)
243             return SBType(ClangASTType(m_opaque_sp->GetASTContext(),
244                                        func->getResultType().getAsOpaquePtr()));
245     }
246     return lldb::SBType();
247 }
248 
249 lldb::SBTypeList
250 SBType::GetFunctionArgumentTypes ()
251 {
252     SBTypeList sb_type_list;
253     if (IsValid())
254     {
255         QualType qual_type(QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType()));
256         const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
257         if (func)
258         {
259             const uint32_t num_args = func->getNumArgs();
260             for (uint32_t i=0; i<num_args; ++i)
261                 sb_type_list.Append (SBType(ClangASTType(m_opaque_sp->GetASTContext(), func->getArgType(i).getAsOpaquePtr())));
262         }
263     }
264     return sb_type_list;
265 }
266 
267 lldb::SBType
268 SBType::GetUnqualifiedType()
269 {
270     if (!IsValid())
271         return SBType();
272 
273     QualType qt (QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType()));
274     return SBType(ClangASTType(m_opaque_sp->GetASTContext(),qt.getUnqualifiedType().getAsOpaquePtr()));
275 }
276 
277 lldb::BasicType
278 SBType::GetBasicType()
279 {
280     if (IsValid())
281         return ClangASTContext::GetLLDBBasicTypeEnumeration (m_opaque_sp->GetOpaqueQualType());
282     return eBasicTypeInvalid;
283 }
284 
285 SBType
286 SBType::GetBasicType(lldb::BasicType type)
287 {
288     if (!IsValid())
289         return SBType();
290 
291     clang::QualType base_type_qual;
292 
293     switch (type)
294     {
295         case eBasicTypeVoid:
296             base_type_qual = m_opaque_sp->GetASTContext()->VoidTy;
297             break;
298         case eBasicTypeChar:
299             base_type_qual = m_opaque_sp->GetASTContext()->CharTy;
300             break;
301         case eBasicTypeSignedChar:
302             base_type_qual = m_opaque_sp->GetASTContext()->SignedCharTy;
303             break;
304         case eBasicTypeUnsignedChar:
305             base_type_qual = m_opaque_sp->GetASTContext()->UnsignedCharTy;
306             break;
307         case eBasicTypeWChar:
308             base_type_qual = m_opaque_sp->GetASTContext()->getWCharType();
309             break;
310         case eBasicTypeSignedWChar:
311             base_type_qual = m_opaque_sp->GetASTContext()->getSignedWCharType();
312             break;
313         case eBasicTypeUnsignedWChar:
314             base_type_qual = m_opaque_sp->GetASTContext()->getUnsignedWCharType();
315             break;
316         case eBasicTypeChar16:
317             base_type_qual = m_opaque_sp->GetASTContext()->Char16Ty;
318             break;
319         case eBasicTypeChar32:
320             base_type_qual = m_opaque_sp->GetASTContext()->Char32Ty;
321             break;
322         case eBasicTypeShort:
323             base_type_qual = m_opaque_sp->GetASTContext()->ShortTy;
324             break;
325         case eBasicTypeUnsignedShort:
326             base_type_qual = m_opaque_sp->GetASTContext()->UnsignedShortTy;
327             break;
328         case eBasicTypeInt:
329             base_type_qual = m_opaque_sp->GetASTContext()->IntTy;
330             break;
331         case eBasicTypeUnsignedInt:
332             base_type_qual = m_opaque_sp->GetASTContext()->UnsignedIntTy;
333             break;
334         case eBasicTypeLong:
335             base_type_qual = m_opaque_sp->GetASTContext()->LongTy;
336             break;
337         case eBasicTypeUnsignedLong:
338             base_type_qual = m_opaque_sp->GetASTContext()->UnsignedLongTy;
339             break;
340         case eBasicTypeLongLong:
341             base_type_qual = m_opaque_sp->GetASTContext()->LongLongTy;
342             break;
343         case eBasicTypeUnsignedLongLong:
344             base_type_qual = m_opaque_sp->GetASTContext()->UnsignedLongLongTy;
345             break;
346         case eBasicTypeInt128:
347             base_type_qual = m_opaque_sp->GetASTContext()->Int128Ty;
348             break;
349         case eBasicTypeUnsignedInt128:
350             base_type_qual = m_opaque_sp->GetASTContext()->UnsignedInt128Ty;
351             break;
352         case eBasicTypeBool:
353             base_type_qual = m_opaque_sp->GetASTContext()->BoolTy;
354             break;
355         case eBasicTypeHalf:
356             base_type_qual = m_opaque_sp->GetASTContext()->HalfTy;
357             break;
358         case eBasicTypeFloat:
359             base_type_qual = m_opaque_sp->GetASTContext()->FloatTy;
360             break;
361         case eBasicTypeDouble:
362             base_type_qual = m_opaque_sp->GetASTContext()->DoubleTy;
363             break;
364         case eBasicTypeLongDouble:
365             base_type_qual = m_opaque_sp->GetASTContext()->LongDoubleTy;
366             break;
367         case eBasicTypeFloatComplex:
368             base_type_qual = m_opaque_sp->GetASTContext()->FloatComplexTy;
369             break;
370         case eBasicTypeDoubleComplex:
371             base_type_qual = m_opaque_sp->GetASTContext()->DoubleComplexTy;
372             break;
373         case eBasicTypeLongDoubleComplex:
374             base_type_qual = m_opaque_sp->GetASTContext()->LongDoubleComplexTy;
375             break;
376         case eBasicTypeObjCID:
377             base_type_qual = m_opaque_sp->GetASTContext()->ObjCBuiltinIdTy;
378             break;
379         case eBasicTypeObjCClass:
380             base_type_qual = m_opaque_sp->GetASTContext()->ObjCBuiltinClassTy;
381             break;
382         case eBasicTypeObjCSel:
383             base_type_qual = m_opaque_sp->GetASTContext()->ObjCBuiltinSelTy;
384             break;
385         case eBasicTypeNullPtr:
386             base_type_qual = m_opaque_sp->GetASTContext()->NullPtrTy;
387             break;
388         default:
389             return SBType();
390     }
391 
392     return SBType(ClangASTType(m_opaque_sp->GetASTContext(), base_type_qual.getAsOpaquePtr()));
393 }
394 
395 uint32_t
396 SBType::GetNumberOfDirectBaseClasses ()
397 {
398     if (IsValid())
399         return ClangASTContext::GetNumDirectBaseClasses(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType());
400     return 0;
401 }
402 
403 uint32_t
404 SBType::GetNumberOfVirtualBaseClasses ()
405 {
406     if (IsValid())
407         return ClangASTContext::GetNumVirtualBaseClasses(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType());
408     return 0;
409 }
410 
411 uint32_t
412 SBType::GetNumberOfFields ()
413 {
414     if (IsValid())
415         return ClangASTContext::GetNumFields(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType());
416     return 0;
417 }
418 
419 bool
420 SBType::GetDescription (SBStream &description, lldb::DescriptionLevel description_level)
421 {
422     Stream &strm = description.ref();
423 
424     if (m_opaque_sp)
425     {
426         m_opaque_sp->GetDescription (strm, description_level);
427     }
428     else
429         strm.PutCString ("No value");
430 
431     return true;
432 }
433 
434 
435 
436 SBTypeMember
437 SBType::GetDirectBaseClassAtIndex (uint32_t idx)
438 {
439     SBTypeMember sb_type_member;
440     if (IsValid())
441     {
442         clang::ASTContext* ast = m_opaque_sp->GetASTContext();
443         uint32_t bit_offset = 0;
444         clang_type_t clang_type = ClangASTContext::GetDirectBaseClassAtIndex (ast, m_opaque_sp->GetOpaqueQualType(), idx, &bit_offset);
445         if (clang_type)
446         {
447             TypeImplSP type_impl_sp (new TypeImpl(ClangASTType (ast, clang_type)));
448             sb_type_member.reset (new TypeMemberImpl (type_impl_sp, bit_offset));
449         }
450     }
451     return sb_type_member;
452 
453 }
454 
455 SBTypeMember
456 SBType::GetVirtualBaseClassAtIndex (uint32_t idx)
457 {
458     SBTypeMember sb_type_member;
459     if (IsValid())
460     {
461         uint32_t bit_offset = 0;
462         clang::ASTContext* ast = m_opaque_sp->GetASTContext();
463         clang_type_t clang_type = ClangASTContext::GetVirtualBaseClassAtIndex (ast, m_opaque_sp->GetOpaqueQualType(), idx, &bit_offset);
464         if (clang_type)
465         {
466             TypeImplSP type_impl_sp (new TypeImpl(ClangASTType (ast, clang_type)));
467             sb_type_member.reset (new TypeMemberImpl (type_impl_sp, bit_offset));
468         }
469     }
470     return sb_type_member;
471 }
472 
473 SBTypeMember
474 SBType::GetFieldAtIndex (uint32_t idx)
475 {
476     SBTypeMember sb_type_member;
477     if (IsValid())
478     {
479         uint64_t bit_offset = 0;
480         uint32_t bitfield_bit_size = 0;
481         bool is_bitfield = false;
482         clang::ASTContext* ast = m_opaque_sp->GetASTContext();
483         std::string name_sstr;
484         clang_type_t clang_type = ClangASTContext::GetFieldAtIndex (ast, m_opaque_sp->GetOpaqueQualType(), idx, name_sstr, &bit_offset, &bitfield_bit_size, &is_bitfield);
485         if (clang_type)
486         {
487             ConstString name;
488             if (!name_sstr.empty())
489                 name.SetCString(name_sstr.c_str());
490             TypeImplSP type_impl_sp (new TypeImpl(ClangASTType (ast, clang_type)));
491             sb_type_member.reset (new TypeMemberImpl (type_impl_sp, bit_offset, name, bitfield_bit_size, is_bitfield));
492         }
493     }
494     return sb_type_member;
495 }
496 
497 bool
498 SBType::IsTypeComplete()
499 {
500     if (!IsValid())
501         return false;
502 
503     return ClangASTContext::IsCompleteType(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType());
504 }
505 
506 const char*
507 SBType::GetName()
508 {
509     if (!IsValid())
510         return "";
511 
512     return ClangASTType::GetConstTypeName(m_opaque_sp->GetASTContext(),
513                                           m_opaque_sp->GetOpaqueQualType()).GetCString();
514 }
515 
516 lldb::TypeClass
517 SBType::GetTypeClass ()
518 {
519     if (IsValid())
520         return ClangASTType::GetTypeClass (m_opaque_sp->GetASTContext(),
521                                            m_opaque_sp->GetOpaqueQualType());
522     return lldb::eTypeClassInvalid;
523 }
524 
525 uint32_t
526 SBType::GetNumberOfTemplateArguments ()
527 {
528     if (IsValid())
529     {
530         return ClangASTContext::GetNumTemplateArguments (m_opaque_sp->GetASTContext(),
531                                                          m_opaque_sp->GetOpaqueQualType());
532     }
533     return 0;
534 }
535 
536 lldb::SBType
537 SBType::GetTemplateArgumentType (uint32_t idx)
538 {
539     if (IsValid())
540     {
541         TemplateArgumentKind kind = eTemplateArgumentKindNull;
542         return SBType(ClangASTType(m_opaque_sp->GetASTContext(),
543                                    ClangASTContext::GetTemplateArgument(m_opaque_sp->GetASTContext(),
544                                                                         m_opaque_sp->GetOpaqueQualType(),
545                                                                         idx,
546                                                                         kind)));
547     }
548     return SBType();
549 }
550 
551 
552 lldb::TemplateArgumentKind
553 SBType::GetTemplateArgumentKind (uint32_t idx)
554 {
555     TemplateArgumentKind kind = eTemplateArgumentKindNull;
556     if (IsValid())
557     {
558         ClangASTContext::GetTemplateArgument(m_opaque_sp->GetASTContext(),
559                                              m_opaque_sp->GetOpaqueQualType(),
560                                              idx,
561                                              kind);
562     }
563     return kind;
564 }
565 
566 
567 
568 
569 SBTypeList::SBTypeList() :
570     m_opaque_ap(new TypeListImpl())
571 {
572 }
573 
574 SBTypeList::SBTypeList(const SBTypeList& rhs) :
575     m_opaque_ap(new TypeListImpl())
576 {
577     for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++)
578         Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i));
579 }
580 
581 bool
582 SBTypeList::IsValid ()
583 {
584     return (m_opaque_ap.get() != NULL);
585 }
586 
587 SBTypeList&
588 SBTypeList::operator = (const SBTypeList& rhs)
589 {
590     if (this != &rhs)
591     {
592         m_opaque_ap.reset (new TypeListImpl());
593         for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++)
594             Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i));
595     }
596     return *this;
597 }
598 
599 void
600 SBTypeList::Append (SBType type)
601 {
602     if (type.IsValid())
603         m_opaque_ap->Append (type.m_opaque_sp);
604 }
605 
606 SBType
607 SBTypeList::GetTypeAtIndex(uint32_t index)
608 {
609     if (m_opaque_ap.get())
610         return SBType(m_opaque_ap->GetTypeAtIndex(index));
611     return SBType();
612 }
613 
614 uint32_t
615 SBTypeList::GetSize()
616 {
617     return m_opaque_ap->GetSize();
618 }
619 
620 SBTypeList::~SBTypeList()
621 {
622 }
623 
624 bool
625 SBType::IsPointerType (void *opaque_type)
626 {
627     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
628 
629     bool ret_value = ClangASTContext::IsPointerType (opaque_type);
630 
631     if (log)
632         log->Printf ("SBType::IsPointerType (opaque_type=%p) ==> '%s'", opaque_type, (ret_value ? "true" : "false"));
633 
634     return ret_value;
635 }
636 
637 
638 SBTypeMember::SBTypeMember() :
639     m_opaque_ap()
640 {
641 }
642 
643 SBTypeMember::~SBTypeMember()
644 {
645 }
646 
647 SBTypeMember::SBTypeMember (const SBTypeMember& rhs) :
648     m_opaque_ap()
649 {
650     if (this != &rhs)
651     {
652         if (rhs.IsValid())
653             m_opaque_ap.reset(new TypeMemberImpl(rhs.ref()));
654     }
655 }
656 
657 lldb::SBTypeMember&
658 SBTypeMember::operator = (const lldb::SBTypeMember& rhs)
659 {
660     if (this != &rhs)
661     {
662         if (rhs.IsValid())
663             m_opaque_ap.reset(new TypeMemberImpl(rhs.ref()));
664     }
665     return *this;
666 }
667 
668 bool
669 SBTypeMember::IsValid() const
670 {
671     return m_opaque_ap.get();
672 }
673 
674 const char *
675 SBTypeMember::GetName ()
676 {
677     if (m_opaque_ap.get())
678         return m_opaque_ap->GetName().GetCString();
679     return NULL;
680 }
681 
682 SBType
683 SBTypeMember::GetType ()
684 {
685     SBType sb_type;
686     if (m_opaque_ap.get())
687     {
688         sb_type.SetSP (m_opaque_ap->GetTypeImpl());
689     }
690     return sb_type;
691 
692 }
693 
694 uint64_t
695 SBTypeMember::GetOffsetInBytes()
696 {
697     if (m_opaque_ap.get())
698         return m_opaque_ap->GetBitOffset() / 8u;
699     return 0;
700 }
701 
702 uint64_t
703 SBTypeMember::GetOffsetInBits()
704 {
705     if (m_opaque_ap.get())
706         return m_opaque_ap->GetBitOffset();
707     return 0;
708 }
709 
710 bool
711 SBTypeMember::IsBitfield()
712 {
713     if (m_opaque_ap.get())
714         return m_opaque_ap->GetIsBitfield();
715     return false;
716 }
717 
718 uint32_t
719 SBTypeMember::GetBitfieldSizeInBits()
720 {
721     if (m_opaque_ap.get())
722         return m_opaque_ap->GetBitfieldBitSize();
723     return 0;
724 }
725 
726 
727 bool
728 SBTypeMember::GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level)
729 {
730     Stream &strm = description.ref();
731 
732     if (m_opaque_ap.get())
733     {
734         const uint32_t bit_offset = m_opaque_ap->GetBitOffset();
735         const uint32_t byte_offset = bit_offset / 8u;
736         const uint32_t byte_bit_offset = bit_offset % 8u;
737         const char *name = m_opaque_ap->GetName().GetCString();
738         if (byte_bit_offset)
739             strm.Printf ("+%u + %u bits: (", byte_offset, byte_bit_offset);
740         else
741             strm.Printf ("+%u: (", byte_offset);
742 
743         TypeImplSP type_impl_sp (m_opaque_ap->GetTypeImpl());
744         if (type_impl_sp)
745             type_impl_sp->GetDescription(strm, description_level);
746 
747         strm.Printf (") %s", name);
748         if (m_opaque_ap->GetIsBitfield())
749         {
750             const uint32_t bitfield_bit_size = m_opaque_ap->GetBitfieldBitSize();
751             strm.Printf (" : %u", bitfield_bit_size);
752         }
753     }
754     else
755     {
756         strm.PutCString ("No value");
757     }
758     return true;
759 }
760 
761 
762 void
763 SBTypeMember::reset(TypeMemberImpl *type_member_impl)
764 {
765     m_opaque_ap.reset(type_member_impl);
766 }
767 
768 TypeMemberImpl &
769 SBTypeMember::ref ()
770 {
771     if (m_opaque_ap.get() == NULL)
772         m_opaque_ap.reset (new TypeMemberImpl());
773     return *m_opaque_ap.get();
774 }
775 
776 const TypeMemberImpl &
777 SBTypeMember::ref () const
778 {
779     return *m_opaque_ap.get();
780 }
781