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
26using namespace lldb;
27using namespace lldb_private;
28using namespace clang;
29
30SBType::SBType() :
31    m_opaque_sp()
32{
33}
34
35SBType::SBType (const ClangASTType &type) :
36    m_opaque_sp(new TypeImpl(ClangASTType(type.GetASTContext(),
37                                          type.GetOpaqueQualType())))
38{
39}
40
41SBType::SBType (const lldb::TypeSP &type_sp) :
42    m_opaque_sp(new TypeImpl(type_sp))
43{
44}
45
46SBType::SBType (const lldb::TypeImplSP &type_impl_sp) :
47    m_opaque_sp(type_impl_sp)
48{
49}
50
51
52SBType::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//
66bool
67SBType::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
76bool
77SBType::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
86lldb::TypeImplSP
87SBType::GetSP ()
88{
89    return m_opaque_sp;
90}
91
92
93void
94SBType::SetSP (const lldb::TypeImplSP &type_impl_sp)
95{
96    m_opaque_sp = type_impl_sp;
97}
98
99SBType &
100SBType::operator = (const SBType &rhs)
101{
102    if (this != &rhs)
103    {
104        m_opaque_sp = rhs.m_opaque_sp;
105    }
106    return *this;
107}
108
109SBType::~SBType ()
110{}
111
112TypeImpl &
113SBType::ref ()
114{
115    if (m_opaque_sp.get() == NULL)
116        m_opaque_sp.reset (new TypeImpl());
117        return *m_opaque_sp;
118}
119
120const TypeImpl &
121SBType::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
130bool
131SBType::IsValid() const
132{
133    if (m_opaque_sp.get() == NULL)
134        return false;
135
136    return m_opaque_sp->IsValid();
137}
138
139uint64_t
140SBType::GetByteSize()
141{
142    if (!IsValid())
143        return 0;
144
145    return m_opaque_sp->GetClangASTType().GetByteSize();
146
147}
148
149bool
150SBType::IsPointerType()
151{
152    if (!IsValid())
153        return false;
154    return m_opaque_sp->GetClangASTType().IsPointerType();
155}
156
157bool
158SBType::IsReferenceType()
159{
160    if (!IsValid())
161        return false;
162    return m_opaque_sp->GetClangASTType().IsReferenceType();
163}
164
165SBType
166SBType::GetPointerType()
167{
168    if (!IsValid())
169        return SBType();
170
171    return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointerType()));
172}
173
174SBType
175SBType::GetPointeeType()
176{
177    if (!IsValid())
178        return SBType();
179    return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointeeType()));
180}
181
182SBType
183SBType::GetReferenceType()
184{
185    if (!IsValid())
186        return SBType();
187    return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetLValueReferenceType()));
188}
189
190SBType
191SBType::GetDereferencedType()
192{
193    if (!IsValid())
194        return SBType();
195    return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetNonReferenceType()));
196}
197
198bool
199SBType::IsFunctionType ()
200{
201    if (!IsValid())
202        return false;
203    return m_opaque_sp->GetClangASTType().IsFunctionType();
204}
205
206bool
207SBType::IsPolymorphicClass ()
208{
209    if (!IsValid())
210        return false;
211    return m_opaque_sp->GetClangASTType().IsPolymorphicClass();
212}
213
214
215
216lldb::SBType
217SBType::GetFunctionReturnType ()
218{
219    if (IsValid())
220    {
221        ClangASTType return_clang_type (m_opaque_sp->GetClangASTType().GetFunctionReturnType());
222        if (return_clang_type.IsValid())
223            return SBType(return_clang_type);
224    }
225    return lldb::SBType();
226}
227
228lldb::SBTypeList
229SBType::GetFunctionArgumentTypes ()
230{
231    SBTypeList sb_type_list;
232    if (IsValid())
233    {
234        QualType qual_type(QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType()));
235        const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
236        if (func)
237        {
238            const uint32_t num_args = func->getNumArgs();
239            for (uint32_t i=0; i<num_args; ++i)
240                sb_type_list.Append (SBType(ClangASTType(m_opaque_sp->GetASTContext(), func->getArgType(i).getAsOpaquePtr())));
241        }
242    }
243    return sb_type_list;
244}
245
246lldb::SBType
247SBType::GetUnqualifiedType()
248{
249    if (!IsValid())
250        return SBType();
251    return SBType(m_opaque_sp->GetClangASTType().GetFullyUnqualifiedType());
252}
253
254lldb::SBType
255SBType::GetCanonicalType()
256{
257    if (IsValid())
258        return SBType(m_opaque_sp->GetClangASTType().GetCanonicalType());
259    return SBType();
260}
261
262
263lldb::BasicType
264SBType::GetBasicType()
265{
266    if (IsValid())
267        return m_opaque_sp->GetClangASTType().GetBasicTypeEnumeration ();
268    return eBasicTypeInvalid;
269}
270
271SBType
272SBType::GetBasicType(lldb::BasicType basic_type)
273{
274    if (IsValid())
275        return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetASTContext(), basic_type));
276    return SBType();
277}
278
279uint32_t
280SBType::GetNumberOfDirectBaseClasses ()
281{
282    if (IsValid())
283        return m_opaque_sp->GetClangASTType().GetNumDirectBaseClasses();
284    return 0;
285}
286
287uint32_t
288SBType::GetNumberOfVirtualBaseClasses ()
289{
290    if (IsValid())
291        return m_opaque_sp->GetClangASTType().GetNumVirtualBaseClasses();
292    return 0;
293}
294
295uint32_t
296SBType::GetNumberOfFields ()
297{
298    if (IsValid())
299        return m_opaque_sp->GetClangASTType().GetNumFields();
300    return 0;
301}
302
303bool
304SBType::GetDescription (SBStream &description, lldb::DescriptionLevel description_level)
305{
306    Stream &strm = description.ref();
307
308    if (m_opaque_sp)
309    {
310        m_opaque_sp->GetDescription (strm, description_level);
311    }
312    else
313        strm.PutCString ("No value");
314
315    return true;
316}
317
318
319
320SBTypeMember
321SBType::GetDirectBaseClassAtIndex (uint32_t idx)
322{
323    SBTypeMember sb_type_member;
324    if (IsValid())
325    {
326        ClangASTType this_type (m_opaque_sp->GetClangASTType ());
327        if (this_type.IsValid())
328        {
329            uint32_t bit_offset = 0;
330            ClangASTType base_class_type (this_type.GetDirectBaseClassAtIndex(idx, &bit_offset));
331            if (base_class_type.IsValid())
332            {
333                sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset));
334            }
335        }
336    }
337    return sb_type_member;
338
339}
340
341SBTypeMember
342SBType::GetVirtualBaseClassAtIndex (uint32_t idx)
343{
344    SBTypeMember sb_type_member;
345    if (IsValid())
346    {
347        ClangASTType this_type (m_opaque_sp->GetClangASTType ());
348        if (this_type.IsValid())
349        {
350            uint32_t bit_offset = 0;
351            ClangASTType base_class_type (this_type.GetVirtualBaseClassAtIndex(idx, &bit_offset));
352            if (base_class_type.IsValid())
353            {
354                sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset));
355            }
356        }
357    }
358    return sb_type_member;
359}
360
361SBTypeMember
362SBType::GetFieldAtIndex (uint32_t idx)
363{
364    SBTypeMember sb_type_member;
365    if (IsValid())
366    {
367        ClangASTType this_type (m_opaque_sp->GetClangASTType ());
368        if (this_type.IsValid())
369        {
370            uint64_t bit_offset = 0;
371            uint32_t bitfield_bit_size = 0;
372            bool is_bitfield = false;
373            std::string name_sstr;
374            ClangASTType field_type (this_type.GetFieldAtIndex (idx,
375                                                                name_sstr,
376                                                                &bit_offset,
377                                                                &bitfield_bit_size,
378                                                                &is_bitfield));
379            if (field_type.IsValid())
380            {
381                ConstString name;
382                if (!name_sstr.empty())
383                    name.SetCString(name_sstr.c_str());
384                sb_type_member.reset (new TypeMemberImpl (TypeImplSP (new TypeImpl(field_type)),
385                                                          bit_offset,
386                                                          name,
387                                                          bitfield_bit_size,
388                                                          is_bitfield));
389            }
390        }
391    }
392    return sb_type_member;
393}
394
395bool
396SBType::IsTypeComplete()
397{
398    if (!IsValid())
399        return false;
400    return m_opaque_sp->GetClangASTType().IsCompleteType();
401}
402
403const char*
404SBType::GetName()
405{
406    if (!IsValid())
407        return "";
408    return m_opaque_sp->GetClangASTType().GetConstTypeName().GetCString();
409}
410
411lldb::TypeClass
412SBType::GetTypeClass ()
413{
414    if (IsValid())
415        return m_opaque_sp->GetClangASTType().GetTypeClass();
416    return lldb::eTypeClassInvalid;
417}
418
419uint32_t
420SBType::GetNumberOfTemplateArguments ()
421{
422    if (IsValid())
423        return m_opaque_sp->GetClangASTType().GetNumTemplateArguments();
424    return 0;
425}
426
427lldb::SBType
428SBType::GetTemplateArgumentType (uint32_t idx)
429{
430    if (IsValid())
431    {
432        TemplateArgumentKind kind = eTemplateArgumentKindNull;
433        ClangASTType template_arg_type = m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind);
434        if (template_arg_type.IsValid())
435            return SBType(template_arg_type);
436    }
437    return SBType();
438}
439
440
441lldb::TemplateArgumentKind
442SBType::GetTemplateArgumentKind (uint32_t idx)
443{
444    TemplateArgumentKind kind = eTemplateArgumentKindNull;
445    if (IsValid())
446        m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind);
447    return kind;
448}
449
450
451SBTypeList::SBTypeList() :
452    m_opaque_ap(new TypeListImpl())
453{
454}
455
456SBTypeList::SBTypeList(const SBTypeList& rhs) :
457    m_opaque_ap(new TypeListImpl())
458{
459    for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++)
460        Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i));
461}
462
463bool
464SBTypeList::IsValid ()
465{
466    return (m_opaque_ap.get() != NULL);
467}
468
469SBTypeList&
470SBTypeList::operator = (const SBTypeList& rhs)
471{
472    if (this != &rhs)
473    {
474        m_opaque_ap.reset (new TypeListImpl());
475        for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++)
476            Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i));
477    }
478    return *this;
479}
480
481void
482SBTypeList::Append (SBType type)
483{
484    if (type.IsValid())
485        m_opaque_ap->Append (type.m_opaque_sp);
486}
487
488SBType
489SBTypeList::GetTypeAtIndex(uint32_t index)
490{
491    if (m_opaque_ap.get())
492        return SBType(m_opaque_ap->GetTypeAtIndex(index));
493    return SBType();
494}
495
496uint32_t
497SBTypeList::GetSize()
498{
499    return m_opaque_ap->GetSize();
500}
501
502SBTypeList::~SBTypeList()
503{
504}
505
506SBTypeMember::SBTypeMember() :
507    m_opaque_ap()
508{
509}
510
511SBTypeMember::~SBTypeMember()
512{
513}
514
515SBTypeMember::SBTypeMember (const SBTypeMember& rhs) :
516    m_opaque_ap()
517{
518    if (this != &rhs)
519    {
520        if (rhs.IsValid())
521            m_opaque_ap.reset(new TypeMemberImpl(rhs.ref()));
522    }
523}
524
525lldb::SBTypeMember&
526SBTypeMember::operator = (const lldb::SBTypeMember& rhs)
527{
528    if (this != &rhs)
529    {
530        if (rhs.IsValid())
531            m_opaque_ap.reset(new TypeMemberImpl(rhs.ref()));
532    }
533    return *this;
534}
535
536bool
537SBTypeMember::IsValid() const
538{
539    return m_opaque_ap.get();
540}
541
542const char *
543SBTypeMember::GetName ()
544{
545    if (m_opaque_ap.get())
546        return m_opaque_ap->GetName().GetCString();
547    return NULL;
548}
549
550SBType
551SBTypeMember::GetType ()
552{
553    SBType sb_type;
554    if (m_opaque_ap.get())
555    {
556        sb_type.SetSP (m_opaque_ap->GetTypeImpl());
557    }
558    return sb_type;
559
560}
561
562uint64_t
563SBTypeMember::GetOffsetInBytes()
564{
565    if (m_opaque_ap.get())
566        return m_opaque_ap->GetBitOffset() / 8u;
567    return 0;
568}
569
570uint64_t
571SBTypeMember::GetOffsetInBits()
572{
573    if (m_opaque_ap.get())
574        return m_opaque_ap->GetBitOffset();
575    return 0;
576}
577
578bool
579SBTypeMember::IsBitfield()
580{
581    if (m_opaque_ap.get())
582        return m_opaque_ap->GetIsBitfield();
583    return false;
584}
585
586uint32_t
587SBTypeMember::GetBitfieldSizeInBits()
588{
589    if (m_opaque_ap.get())
590        return m_opaque_ap->GetBitfieldBitSize();
591    return 0;
592}
593
594
595bool
596SBTypeMember::GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level)
597{
598    Stream &strm = description.ref();
599
600    if (m_opaque_ap.get())
601    {
602        const uint32_t bit_offset = m_opaque_ap->GetBitOffset();
603        const uint32_t byte_offset = bit_offset / 8u;
604        const uint32_t byte_bit_offset = bit_offset % 8u;
605        const char *name = m_opaque_ap->GetName().GetCString();
606        if (byte_bit_offset)
607            strm.Printf ("+%u + %u bits: (", byte_offset, byte_bit_offset);
608        else
609            strm.Printf ("+%u: (", byte_offset);
610
611        TypeImplSP type_impl_sp (m_opaque_ap->GetTypeImpl());
612        if (type_impl_sp)
613            type_impl_sp->GetDescription(strm, description_level);
614
615        strm.Printf (") %s", name);
616        if (m_opaque_ap->GetIsBitfield())
617        {
618            const uint32_t bitfield_bit_size = m_opaque_ap->GetBitfieldBitSize();
619            strm.Printf (" : %u", bitfield_bit_size);
620        }
621    }
622    else
623    {
624        strm.PutCString ("No value");
625    }
626    return true;
627}
628
629
630void
631SBTypeMember::reset(TypeMemberImpl *type_member_impl)
632{
633    m_opaque_ap.reset(type_member_impl);
634}
635
636TypeMemberImpl &
637SBTypeMember::ref ()
638{
639    if (m_opaque_ap.get() == NULL)
640        m_opaque_ap.reset (new TypeMemberImpl());
641    return *m_opaque_ap.get();
642}
643
644const TypeMemberImpl &
645SBTypeMember::ref () const
646{
647    return *m_opaque_ap.get();
648}
649