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 uint64_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::SBType
278 SBType::GetCanonicalType()
279 {
280     if (IsValid())
281     {
282         QualType qt (QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType()));
283         return SBType(ClangASTType(m_opaque_sp->GetASTContext(),qt.getCanonicalType().getAsOpaquePtr()));
284     }
285     return SBType();
286 }
287 
288 
289 lldb::BasicType
290 SBType::GetBasicType()
291 {
292     if (IsValid())
293         return ClangASTContext::GetLLDBBasicTypeEnumeration (m_opaque_sp->GetOpaqueQualType());
294     return eBasicTypeInvalid;
295 }
296 
297 SBType
298 SBType::GetBasicType(lldb::BasicType type)
299 {
300     if (IsValid())
301         return SBType (ClangASTType::GetBasicType (m_opaque_sp->GetASTContext(), type));
302     return SBType();
303 }
304 
305 uint32_t
306 SBType::GetNumberOfDirectBaseClasses ()
307 {
308     if (IsValid())
309         return ClangASTContext::GetNumDirectBaseClasses(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType());
310     return 0;
311 }
312 
313 uint32_t
314 SBType::GetNumberOfVirtualBaseClasses ()
315 {
316     if (IsValid())
317         return ClangASTContext::GetNumVirtualBaseClasses(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType());
318     return 0;
319 }
320 
321 uint32_t
322 SBType::GetNumberOfFields ()
323 {
324     if (IsValid())
325         return ClangASTContext::GetNumFields(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType());
326     return 0;
327 }
328 
329 bool
330 SBType::GetDescription (SBStream &description, lldb::DescriptionLevel description_level)
331 {
332     Stream &strm = description.ref();
333 
334     if (m_opaque_sp)
335     {
336         m_opaque_sp->GetDescription (strm, description_level);
337     }
338     else
339         strm.PutCString ("No value");
340 
341     return true;
342 }
343 
344 
345 
346 SBTypeMember
347 SBType::GetDirectBaseClassAtIndex (uint32_t idx)
348 {
349     SBTypeMember sb_type_member;
350     if (IsValid())
351     {
352         clang::ASTContext* ast = m_opaque_sp->GetASTContext();
353         uint32_t bit_offset = 0;
354         clang_type_t clang_type = ClangASTContext::GetDirectBaseClassAtIndex (ast, m_opaque_sp->GetOpaqueQualType(), idx, &bit_offset);
355         if (clang_type)
356         {
357             TypeImplSP type_impl_sp (new TypeImpl(ClangASTType (ast, clang_type)));
358             sb_type_member.reset (new TypeMemberImpl (type_impl_sp, bit_offset));
359         }
360     }
361     return sb_type_member;
362 
363 }
364 
365 SBTypeMember
366 SBType::GetVirtualBaseClassAtIndex (uint32_t idx)
367 {
368     SBTypeMember sb_type_member;
369     if (IsValid())
370     {
371         uint32_t bit_offset = 0;
372         clang::ASTContext* ast = m_opaque_sp->GetASTContext();
373         clang_type_t clang_type = ClangASTContext::GetVirtualBaseClassAtIndex (ast, m_opaque_sp->GetOpaqueQualType(), idx, &bit_offset);
374         if (clang_type)
375         {
376             TypeImplSP type_impl_sp (new TypeImpl(ClangASTType (ast, clang_type)));
377             sb_type_member.reset (new TypeMemberImpl (type_impl_sp, bit_offset));
378         }
379     }
380     return sb_type_member;
381 }
382 
383 SBTypeMember
384 SBType::GetFieldAtIndex (uint32_t idx)
385 {
386     SBTypeMember sb_type_member;
387     if (IsValid())
388     {
389         uint64_t bit_offset = 0;
390         uint32_t bitfield_bit_size = 0;
391         bool is_bitfield = false;
392         clang::ASTContext* ast = m_opaque_sp->GetASTContext();
393         std::string name_sstr;
394         clang_type_t clang_type = ClangASTContext::GetFieldAtIndex (ast, m_opaque_sp->GetOpaqueQualType(), idx, name_sstr, &bit_offset, &bitfield_bit_size, &is_bitfield);
395         if (clang_type)
396         {
397             ConstString name;
398             if (!name_sstr.empty())
399                 name.SetCString(name_sstr.c_str());
400             TypeImplSP type_impl_sp (new TypeImpl(ClangASTType (ast, clang_type)));
401             sb_type_member.reset (new TypeMemberImpl (type_impl_sp, bit_offset, name, bitfield_bit_size, is_bitfield));
402         }
403     }
404     return sb_type_member;
405 }
406 
407 bool
408 SBType::IsTypeComplete()
409 {
410     if (!IsValid())
411         return false;
412 
413     return ClangASTContext::IsCompleteType(m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType());
414 }
415 
416 const char*
417 SBType::GetName()
418 {
419     if (!IsValid())
420         return "";
421 
422     return ClangASTType::GetConstTypeName(m_opaque_sp->GetASTContext(),
423                                           m_opaque_sp->GetOpaqueQualType()).GetCString();
424 }
425 
426 lldb::TypeClass
427 SBType::GetTypeClass ()
428 {
429     if (IsValid())
430         return ClangASTType::GetTypeClass (m_opaque_sp->GetASTContext(),
431                                            m_opaque_sp->GetOpaqueQualType());
432     return lldb::eTypeClassInvalid;
433 }
434 
435 uint32_t
436 SBType::GetNumberOfTemplateArguments ()
437 {
438     if (IsValid())
439     {
440         return ClangASTContext::GetNumTemplateArguments (m_opaque_sp->GetASTContext(),
441                                                          m_opaque_sp->GetOpaqueQualType());
442     }
443     return 0;
444 }
445 
446 lldb::SBType
447 SBType::GetTemplateArgumentType (uint32_t idx)
448 {
449     if (IsValid())
450     {
451         TemplateArgumentKind kind = eTemplateArgumentKindNull;
452         return SBType(ClangASTType(m_opaque_sp->GetASTContext(),
453                                    ClangASTContext::GetTemplateArgument(m_opaque_sp->GetASTContext(),
454                                                                         m_opaque_sp->GetOpaqueQualType(),
455                                                                         idx,
456                                                                         kind)));
457     }
458     return SBType();
459 }
460 
461 
462 lldb::TemplateArgumentKind
463 SBType::GetTemplateArgumentKind (uint32_t idx)
464 {
465     TemplateArgumentKind kind = eTemplateArgumentKindNull;
466     if (IsValid())
467     {
468         ClangASTContext::GetTemplateArgument(m_opaque_sp->GetASTContext(),
469                                              m_opaque_sp->GetOpaqueQualType(),
470                                              idx,
471                                              kind);
472     }
473     return kind;
474 }
475 
476 
477 
478 
479 SBTypeList::SBTypeList() :
480     m_opaque_ap(new TypeListImpl())
481 {
482 }
483 
484 SBTypeList::SBTypeList(const SBTypeList& rhs) :
485     m_opaque_ap(new TypeListImpl())
486 {
487     for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++)
488         Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i));
489 }
490 
491 bool
492 SBTypeList::IsValid ()
493 {
494     return (m_opaque_ap.get() != NULL);
495 }
496 
497 SBTypeList&
498 SBTypeList::operator = (const SBTypeList& rhs)
499 {
500     if (this != &rhs)
501     {
502         m_opaque_ap.reset (new TypeListImpl());
503         for (uint32_t i = 0, rhs_size = const_cast<SBTypeList&>(rhs).GetSize(); i < rhs_size; i++)
504             Append(const_cast<SBTypeList&>(rhs).GetTypeAtIndex(i));
505     }
506     return *this;
507 }
508 
509 void
510 SBTypeList::Append (SBType type)
511 {
512     if (type.IsValid())
513         m_opaque_ap->Append (type.m_opaque_sp);
514 }
515 
516 SBType
517 SBTypeList::GetTypeAtIndex(uint32_t index)
518 {
519     if (m_opaque_ap.get())
520         return SBType(m_opaque_ap->GetTypeAtIndex(index));
521     return SBType();
522 }
523 
524 uint32_t
525 SBTypeList::GetSize()
526 {
527     return m_opaque_ap->GetSize();
528 }
529 
530 SBTypeList::~SBTypeList()
531 {
532 }
533 
534 bool
535 SBType::IsPointerType (void *opaque_type)
536 {
537     Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
538 
539     bool ret_value = ClangASTContext::IsPointerType (opaque_type);
540 
541     if (log)
542         log->Printf ("SBType::IsPointerType (opaque_type=%p) ==> '%s'", opaque_type, (ret_value ? "true" : "false"));
543 
544     return ret_value;
545 }
546 
547 
548 SBTypeMember::SBTypeMember() :
549     m_opaque_ap()
550 {
551 }
552 
553 SBTypeMember::~SBTypeMember()
554 {
555 }
556 
557 SBTypeMember::SBTypeMember (const SBTypeMember& rhs) :
558     m_opaque_ap()
559 {
560     if (this != &rhs)
561     {
562         if (rhs.IsValid())
563             m_opaque_ap.reset(new TypeMemberImpl(rhs.ref()));
564     }
565 }
566 
567 lldb::SBTypeMember&
568 SBTypeMember::operator = (const lldb::SBTypeMember& rhs)
569 {
570     if (this != &rhs)
571     {
572         if (rhs.IsValid())
573             m_opaque_ap.reset(new TypeMemberImpl(rhs.ref()));
574     }
575     return *this;
576 }
577 
578 bool
579 SBTypeMember::IsValid() const
580 {
581     return m_opaque_ap.get();
582 }
583 
584 const char *
585 SBTypeMember::GetName ()
586 {
587     if (m_opaque_ap.get())
588         return m_opaque_ap->GetName().GetCString();
589     return NULL;
590 }
591 
592 SBType
593 SBTypeMember::GetType ()
594 {
595     SBType sb_type;
596     if (m_opaque_ap.get())
597     {
598         sb_type.SetSP (m_opaque_ap->GetTypeImpl());
599     }
600     return sb_type;
601 
602 }
603 
604 uint64_t
605 SBTypeMember::GetOffsetInBytes()
606 {
607     if (m_opaque_ap.get())
608         return m_opaque_ap->GetBitOffset() / 8u;
609     return 0;
610 }
611 
612 uint64_t
613 SBTypeMember::GetOffsetInBits()
614 {
615     if (m_opaque_ap.get())
616         return m_opaque_ap->GetBitOffset();
617     return 0;
618 }
619 
620 bool
621 SBTypeMember::IsBitfield()
622 {
623     if (m_opaque_ap.get())
624         return m_opaque_ap->GetIsBitfield();
625     return false;
626 }
627 
628 uint32_t
629 SBTypeMember::GetBitfieldSizeInBits()
630 {
631     if (m_opaque_ap.get())
632         return m_opaque_ap->GetBitfieldBitSize();
633     return 0;
634 }
635 
636 
637 bool
638 SBTypeMember::GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level)
639 {
640     Stream &strm = description.ref();
641 
642     if (m_opaque_ap.get())
643     {
644         const uint32_t bit_offset = m_opaque_ap->GetBitOffset();
645         const uint32_t byte_offset = bit_offset / 8u;
646         const uint32_t byte_bit_offset = bit_offset % 8u;
647         const char *name = m_opaque_ap->GetName().GetCString();
648         if (byte_bit_offset)
649             strm.Printf ("+%u + %u bits: (", byte_offset, byte_bit_offset);
650         else
651             strm.Printf ("+%u: (", byte_offset);
652 
653         TypeImplSP type_impl_sp (m_opaque_ap->GetTypeImpl());
654         if (type_impl_sp)
655             type_impl_sp->GetDescription(strm, description_level);
656 
657         strm.Printf (") %s", name);
658         if (m_opaque_ap->GetIsBitfield())
659         {
660             const uint32_t bitfield_bit_size = m_opaque_ap->GetBitfieldBitSize();
661             strm.Printf (" : %u", bitfield_bit_size);
662         }
663     }
664     else
665     {
666         strm.PutCString ("No value");
667     }
668     return true;
669 }
670 
671 
672 void
673 SBTypeMember::reset(TypeMemberImpl *type_member_impl)
674 {
675     m_opaque_ap.reset(type_member_impl);
676 }
677 
678 TypeMemberImpl &
679 SBTypeMember::ref ()
680 {
681     if (m_opaque_ap.get() == NULL)
682         m_opaque_ap.reset (new TypeMemberImpl());
683     return *m_opaque_ap.get();
684 }
685 
686 const TypeMemberImpl &
687 SBTypeMember::ref () const
688 {
689     return *m_opaque_ap.get();
690 }
691