1 //===-- Type.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 // Other libraries and framework includes 11 12 #include "lldb/Core/DataExtractor.h" 13 #include "lldb/Core/DataBufferHeap.h" 14 #include "lldb/Core/Module.h" 15 #include "lldb/Core/Scalar.h" 16 #include "lldb/Core/StreamString.h" 17 18 #include "lldb/Symbol/ClangASTType.h" 19 #include "lldb/Symbol/ClangASTContext.h" 20 #include "lldb/Symbol/ObjectFile.h" 21 #include "lldb/Symbol/SymbolContextScope.h" 22 #include "lldb/Symbol/SymbolFile.h" 23 #include "lldb/Symbol/Type.h" 24 #include "lldb/Symbol/TypeList.h" 25 26 #include "lldb/Target/ExecutionContext.h" 27 #include "lldb/Target/Process.h" 28 #include "lldb/Target/Target.h" 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 Type * 34 SymbolFileType::GetType () 35 { 36 if (!m_type_sp) 37 m_type_sp = m_symbol_file.ResolveTypeUID (GetID())->shared_from_this(); 38 return m_type_sp.get(); 39 } 40 41 42 Type::Type 43 ( 44 lldb::user_id_t uid, 45 SymbolFile* symbol_file, 46 const ConstString &name, 47 uint32_t byte_size, 48 SymbolContextScope *context, 49 user_id_t encoding_uid, 50 EncodingDataType encoding_uid_type, 51 const Declaration& decl, 52 clang_type_t clang_type, 53 ResolveState clang_type_resolve_state 54 ) : 55 UserID (uid), 56 m_name (name), 57 m_symbol_file (symbol_file), 58 m_context (context), 59 m_encoding_type (NULL), 60 m_encoding_uid (encoding_uid), 61 m_encoding_uid_type (encoding_uid_type), 62 m_byte_size (byte_size), 63 m_decl (decl), 64 m_clang_type (clang_type), 65 m_clang_type_resolve_state (clang_type ? clang_type_resolve_state : eResolveStateUnresolved) 66 { 67 } 68 69 Type::Type () : 70 UserID (0), 71 m_name ("<INVALID TYPE>"), 72 m_symbol_file (NULL), 73 m_context (NULL), 74 m_encoding_type (NULL), 75 m_encoding_uid (0), 76 m_encoding_uid_type (eEncodingInvalid), 77 m_byte_size (0), 78 m_decl (), 79 m_clang_type (NULL), 80 m_clang_type_resolve_state (eResolveStateUnresolved) 81 { 82 } 83 84 85 Type::Type (const Type &rhs) : 86 UserID (rhs), 87 m_name (rhs.m_name), 88 m_symbol_file (rhs.m_symbol_file), 89 m_context (rhs.m_context), 90 m_encoding_type (rhs.m_encoding_type), 91 m_encoding_uid (rhs.m_encoding_uid), 92 m_encoding_uid_type (rhs.m_encoding_uid_type), 93 m_byte_size (rhs.m_byte_size), 94 m_decl (rhs.m_decl), 95 m_clang_type (rhs.m_clang_type), 96 m_clang_type_resolve_state (rhs.m_clang_type_resolve_state) 97 { 98 } 99 100 const Type& 101 Type::operator= (const Type& rhs) 102 { 103 if (this != &rhs) 104 { 105 } 106 return *this; 107 } 108 109 110 void 111 Type::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_name) 112 { 113 *s << "id = " << (const UserID&)*this; 114 115 // Call the name accessor to make sure we resolve the type name 116 if (show_name && GetName()) 117 *s << ", name = \"" << m_name << '"'; 118 119 // Call the get byte size accesor so we resolve our byte size 120 if (GetByteSize()) 121 s->Printf(", byte-size = %u", m_byte_size); 122 bool show_fullpaths = (level == lldb::eDescriptionLevelVerbose); 123 m_decl.Dump(s, show_fullpaths); 124 125 if (m_clang_type) 126 { 127 *s << ", clang_type = \""; 128 ClangASTType::DumpTypeDescription (GetClangAST(), m_clang_type, s); 129 *s << '"'; 130 } 131 else if (m_encoding_uid != LLDB_INVALID_UID) 132 { 133 s->Printf(", type_uid = 0x%8.8x", m_encoding_uid); 134 switch (m_encoding_uid_type) 135 { 136 case eEncodingInvalid: break; 137 case eEncodingIsUID: s->PutCString(" (unresolved type)"); break; 138 case eEncodingIsConstUID: s->PutCString(" (unresolved const type)"); break; 139 case eEncodingIsRestrictUID: s->PutCString(" (unresolved restrict type)"); break; 140 case eEncodingIsVolatileUID: s->PutCString(" (unresolved volatile type)"); break; 141 case eEncodingIsTypedefUID: s->PutCString(" (unresolved typedef)"); break; 142 case eEncodingIsPointerUID: s->PutCString(" (unresolved pointer)"); break; 143 case eEncodingIsLValueReferenceUID: s->PutCString(" (unresolved L value reference)"); break; 144 case eEncodingIsRValueReferenceUID: s->PutCString(" (unresolved R value reference)"); break; 145 case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break; 146 } 147 } 148 } 149 150 151 void 152 Type::Dump (Stream *s, bool show_context) 153 { 154 s->Printf("%p: ", this); 155 s->Indent(); 156 *s << "Type" << (const UserID&)*this << ' '; 157 if (m_name) 158 *s << ", name = \"" << m_name << "\""; 159 160 if (m_byte_size != 0) 161 s->Printf(", size = %u", m_byte_size); 162 163 if (show_context && m_context != NULL) 164 { 165 s->PutCString(", context = ( "); 166 m_context->DumpSymbolContext(s); 167 s->PutCString(" )"); 168 } 169 170 bool show_fullpaths = false; 171 m_decl.Dump (s,show_fullpaths); 172 173 if (m_clang_type) 174 { 175 *s << ", clang_type = " << m_clang_type << ' '; 176 177 ClangASTType::DumpTypeDescription (GetClangAST(), m_clang_type, s); 178 } 179 else if (m_encoding_uid != LLDB_INVALID_UID) 180 { 181 *s << ", type_data = " << (uint64_t)m_encoding_uid; 182 switch (m_encoding_uid_type) 183 { 184 case eEncodingInvalid: break; 185 case eEncodingIsUID: s->PutCString(" (unresolved type)"); break; 186 case eEncodingIsConstUID: s->PutCString(" (unresolved const type)"); break; 187 case eEncodingIsRestrictUID: s->PutCString(" (unresolved restrict type)"); break; 188 case eEncodingIsVolatileUID: s->PutCString(" (unresolved volatile type)"); break; 189 case eEncodingIsTypedefUID: s->PutCString(" (unresolved typedef)"); break; 190 case eEncodingIsPointerUID: s->PutCString(" (unresolved pointer)"); break; 191 case eEncodingIsLValueReferenceUID: s->PutCString(" (unresolved L value reference)"); break; 192 case eEncodingIsRValueReferenceUID: s->PutCString(" (unresolved R value reference)"); break; 193 case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break; 194 } 195 } 196 197 // 198 // if (m_access) 199 // s->Printf(", access = %u", m_access); 200 s->EOL(); 201 } 202 203 const ConstString & 204 Type::GetName() 205 { 206 if (!m_name) 207 { 208 if (ResolveClangType(eResolveStateForward)) 209 m_name = ClangASTType::GetConstTypeName (m_clang_type); 210 } 211 return m_name; 212 } 213 214 void 215 Type::DumpTypeName(Stream *s) 216 { 217 GetName().Dump(s, "<invalid-type-name>"); 218 } 219 220 221 void 222 Type::DumpValue 223 ( 224 ExecutionContext *exe_ctx, 225 Stream *s, 226 const DataExtractor &data, 227 uint32_t data_byte_offset, 228 bool show_types, 229 bool show_summary, 230 bool verbose, 231 lldb::Format format 232 ) 233 { 234 if (ResolveClangType(eResolveStateForward)) 235 { 236 if (show_types) 237 { 238 s->PutChar('('); 239 if (verbose) 240 s->Printf("Type{0x%8.8llx} ", GetID()); 241 DumpTypeName (s); 242 s->PutCString(") "); 243 } 244 245 ClangASTType::DumpValue (GetClangAST (), 246 m_clang_type, 247 exe_ctx, 248 s, 249 format == lldb::eFormatDefault ? GetFormat() : format, 250 data, 251 data_byte_offset, 252 GetByteSize(), 253 0, // Bitfield bit size 254 0, // Bitfield bit offset 255 show_types, 256 show_summary, 257 verbose, 258 0); 259 } 260 } 261 262 Type * 263 Type::GetEncodingType () 264 { 265 if (m_encoding_type == NULL && m_encoding_uid != LLDB_INVALID_UID) 266 m_encoding_type = m_symbol_file->ResolveTypeUID(m_encoding_uid); 267 return m_encoding_type; 268 } 269 270 271 272 uint32_t 273 Type::GetByteSize() 274 { 275 if (m_byte_size == 0) 276 { 277 switch (m_encoding_uid_type) 278 { 279 case eEncodingInvalid: 280 case eEncodingIsSyntheticUID: 281 break; 282 case eEncodingIsUID: 283 case eEncodingIsConstUID: 284 case eEncodingIsRestrictUID: 285 case eEncodingIsVolatileUID: 286 case eEncodingIsTypedefUID: 287 { 288 Type *encoding_type = GetEncodingType (); 289 if (encoding_type) 290 m_byte_size = encoding_type->GetByteSize(); 291 if (m_byte_size == 0) 292 { 293 uint32_t bit_width = ClangASTType::GetClangTypeBitWidth (GetClangAST(), GetClangLayoutType()); 294 m_byte_size = (bit_width + 7 ) / 8; 295 } 296 } 297 break; 298 299 // If we are a pointer or reference, then this is just a pointer size; 300 case eEncodingIsPointerUID: 301 case eEncodingIsLValueReferenceUID: 302 case eEncodingIsRValueReferenceUID: 303 m_byte_size = m_symbol_file->GetClangASTContext().GetPointerBitSize() / 8; 304 break; 305 } 306 } 307 return m_byte_size; 308 } 309 310 311 uint32_t 312 Type::GetNumChildren (bool omit_empty_base_classes) 313 { 314 if (ResolveClangType(eResolveStateForward)) 315 { 316 return ClangASTContext::GetNumChildren (m_symbol_file->GetClangASTContext().getASTContext(), 317 m_clang_type, 318 omit_empty_base_classes); 319 } 320 return 0; 321 } 322 323 bool 324 Type::IsAggregateType () 325 { 326 if (ResolveClangType(eResolveStateForward)) 327 return ClangASTContext::IsAggregateType (m_clang_type); 328 return false; 329 } 330 331 lldb::Format 332 Type::GetFormat () 333 { 334 // Make sure we resolve our type if it already hasn't been. 335 if (!ResolveClangType(eResolveStateForward)) 336 return lldb::eFormatInvalid; 337 return ClangASTType::GetFormat (m_clang_type); 338 } 339 340 341 342 lldb::Encoding 343 Type::GetEncoding (uint32_t &count) 344 { 345 // Make sure we resolve our type if it already hasn't been. 346 if (!ResolveClangType(eResolveStateForward)) 347 return lldb::eEncodingInvalid; 348 349 return ClangASTType::GetEncoding (m_clang_type, count); 350 } 351 352 353 354 bool 355 Type::DumpValueInMemory 356 ( 357 ExecutionContext *exe_ctx, 358 Stream *s, 359 lldb::addr_t address, 360 AddressType address_type, 361 bool show_types, 362 bool show_summary, 363 bool verbose 364 ) 365 { 366 if (address != LLDB_INVALID_ADDRESS) 367 { 368 DataExtractor data; 369 Target *target = NULL; 370 if (exe_ctx) 371 target = exe_ctx->GetTargetPtr(); 372 if (target) 373 data.SetByteOrder (target->GetArchitecture().GetByteOrder()); 374 if (ReadFromMemory (exe_ctx, address, address_type, data)) 375 { 376 DumpValue(exe_ctx, s, data, 0, show_types, show_summary, verbose); 377 return true; 378 } 379 } 380 return false; 381 } 382 383 384 bool 385 Type::ReadFromMemory (ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, DataExtractor &data) 386 { 387 if (address_type == eAddressTypeFile) 388 { 389 // Can't convert a file address to anything valid without more 390 // context (which Module it came from) 391 return false; 392 } 393 394 const uint32_t byte_size = GetByteSize(); 395 if (data.GetByteSize() < byte_size) 396 { 397 lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0')); 398 data.SetData(data_sp); 399 } 400 401 uint8_t* dst = (uint8_t*)data.PeekData(0, byte_size); 402 if (dst != NULL) 403 { 404 if (address_type == eAddressTypeHost) 405 { 406 // The address is an address in this process, so just copy it 407 memcpy (dst, (uint8_t*)NULL + addr, byte_size); 408 return true; 409 } 410 else 411 { 412 if (exe_ctx) 413 { 414 Process *process = exe_ctx->GetProcessPtr(); 415 if (process) 416 { 417 Error error; 418 return exe_ctx->GetProcessPtr()->ReadMemory(addr, dst, byte_size, error) == byte_size; 419 } 420 } 421 } 422 } 423 return false; 424 } 425 426 427 bool 428 Type::WriteToMemory (ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, DataExtractor &data) 429 { 430 return false; 431 } 432 433 434 TypeList* 435 Type::GetTypeList() 436 { 437 return GetSymbolFile()->GetTypeList(); 438 } 439 440 const Declaration & 441 Type::GetDeclaration () const 442 { 443 return m_decl; 444 } 445 446 bool 447 Type::ResolveClangType (ResolveState clang_type_resolve_state) 448 { 449 Type *encoding_type = NULL; 450 if (m_clang_type == NULL) 451 { 452 encoding_type = GetEncodingType(); 453 if (encoding_type) 454 { 455 switch (m_encoding_uid_type) 456 { 457 case eEncodingIsUID: 458 if (encoding_type->ResolveClangType(clang_type_resolve_state)) 459 { 460 m_clang_type = encoding_type->m_clang_type; 461 m_clang_type_resolve_state = encoding_type->m_clang_type_resolve_state; 462 } 463 break; 464 465 case eEncodingIsConstUID: 466 m_clang_type = ClangASTContext::AddConstModifier (encoding_type->GetClangForwardType()); 467 break; 468 469 case eEncodingIsRestrictUID: 470 m_clang_type = ClangASTContext::AddRestrictModifier (encoding_type->GetClangForwardType()); 471 break; 472 473 case eEncodingIsVolatileUID: 474 m_clang_type = ClangASTContext::AddVolatileModifier (encoding_type->GetClangForwardType()); 475 break; 476 477 case eEncodingIsTypedefUID: 478 m_clang_type = CreateClangTypedefType (this, encoding_type); 479 // Clear the name so it can get fully qualified in case the 480 // typedef is in a namespace. 481 m_name.Clear(); 482 break; 483 484 case eEncodingIsPointerUID: 485 m_clang_type = CreateClangPointerType (encoding_type); 486 break; 487 488 case eEncodingIsLValueReferenceUID: 489 m_clang_type = CreateClangLValueReferenceType (encoding_type); 490 break; 491 492 case eEncodingIsRValueReferenceUID: 493 m_clang_type = CreateClangRValueReferenceType (encoding_type); 494 break; 495 496 default: 497 assert(!"Unhandled encoding_data_type."); 498 break; 499 } 500 } 501 else 502 { 503 // We have no encoding type, return void? 504 clang_type_t void_clang_type = GetClangASTContext().GetBuiltInType_void(); 505 switch (m_encoding_uid_type) 506 { 507 case eEncodingIsUID: 508 m_clang_type = void_clang_type; 509 break; 510 511 case eEncodingIsConstUID: 512 m_clang_type = ClangASTContext::AddConstModifier (void_clang_type); 513 break; 514 515 case eEncodingIsRestrictUID: 516 m_clang_type = ClangASTContext::AddRestrictModifier (void_clang_type); 517 break; 518 519 case eEncodingIsVolatileUID: 520 m_clang_type = ClangASTContext::AddVolatileModifier (void_clang_type); 521 break; 522 523 case eEncodingIsTypedefUID: 524 m_clang_type = GetClangASTContext().CreateTypedefType (m_name.AsCString(), void_clang_type, NULL); 525 break; 526 527 case eEncodingIsPointerUID: 528 m_clang_type = GetClangASTContext().CreatePointerType (void_clang_type); 529 break; 530 531 case eEncodingIsLValueReferenceUID: 532 m_clang_type = GetClangASTContext().CreateLValueReferenceType (void_clang_type); 533 break; 534 535 case eEncodingIsRValueReferenceUID: 536 m_clang_type = GetClangASTContext().CreateRValueReferenceType (void_clang_type); 537 break; 538 539 default: 540 assert(!"Unhandled encoding_data_type."); 541 break; 542 } 543 } 544 } 545 546 // Check if we have a forward reference to a class/struct/union/enum? 547 if (m_clang_type && m_clang_type_resolve_state < clang_type_resolve_state) 548 { 549 m_clang_type_resolve_state = eResolveStateFull; 550 if (!ClangASTType::IsDefined (m_clang_type)) 551 { 552 // We have a forward declaration, we need to resolve it to a complete 553 // definition. 554 m_symbol_file->ResolveClangOpaqueTypeDefinition (m_clang_type); 555 } 556 } 557 558 // If we have an encoding type, then we need to make sure it is 559 // resolved appropriately. 560 if (m_encoding_uid != LLDB_INVALID_UID) 561 { 562 if (encoding_type == NULL) 563 encoding_type = GetEncodingType(); 564 if (encoding_type) 565 { 566 ResolveState encoding_clang_type_resolve_state = clang_type_resolve_state; 567 568 if (clang_type_resolve_state == eResolveStateLayout) 569 { 570 switch (m_encoding_uid_type) 571 { 572 case eEncodingIsPointerUID: 573 case eEncodingIsLValueReferenceUID: 574 case eEncodingIsRValueReferenceUID: 575 encoding_clang_type_resolve_state = eResolveStateForward; 576 break; 577 default: 578 break; 579 } 580 } 581 encoding_type->ResolveClangType (encoding_clang_type_resolve_state); 582 } 583 } 584 return m_clang_type != NULL; 585 } 586 uint32_t 587 Type::GetEncodingMask () 588 { 589 uint32_t encoding_mask = 1u << m_encoding_uid_type; 590 Type *encoding_type = GetEncodingType(); 591 assert (encoding_type != this); 592 if (encoding_type) 593 encoding_mask |= encoding_type->GetEncodingMask (); 594 return encoding_mask; 595 } 596 597 clang_type_t 598 Type::GetClangFullType () 599 { 600 ResolveClangType(eResolveStateFull); 601 return m_clang_type; 602 } 603 604 clang_type_t 605 Type::GetClangLayoutType () 606 { 607 ResolveClangType(eResolveStateLayout); 608 return m_clang_type; 609 } 610 611 clang_type_t 612 Type::GetClangForwardType () 613 { 614 ResolveClangType (eResolveStateForward); 615 return m_clang_type; 616 } 617 618 clang::ASTContext * 619 Type::GetClangAST () 620 { 621 return GetClangASTContext().getASTContext(); 622 } 623 624 ClangASTContext & 625 Type::GetClangASTContext () 626 { 627 return m_symbol_file->GetClangASTContext(); 628 } 629 630 int 631 Type::Compare(const Type &a, const Type &b) 632 { 633 // Just compare the UID values for now... 634 lldb::user_id_t a_uid = a.GetID(); 635 lldb::user_id_t b_uid = b.GetID(); 636 if (a_uid < b_uid) 637 return -1; 638 if (a_uid > b_uid) 639 return 1; 640 return 0; 641 // if (a.getQualType() == b.getQualType()) 642 // return 0; 643 } 644 645 646 void * 647 Type::CreateClangPointerType (Type *type) 648 { 649 assert(type); 650 return GetClangASTContext().CreatePointerType(type->GetClangForwardType()); 651 } 652 653 void * 654 Type::CreateClangTypedefType (Type *typedef_type, Type *base_type) 655 { 656 assert(typedef_type && base_type); 657 return GetClangASTContext().CreateTypedefType (typedef_type->GetName().AsCString(), 658 base_type->GetClangForwardType(), 659 typedef_type->GetSymbolFile()->GetClangDeclContextContainingTypeUID(typedef_type->GetID())); 660 } 661 662 void * 663 Type::CreateClangLValueReferenceType (Type *type) 664 { 665 assert(type); 666 return GetClangASTContext().CreateLValueReferenceType(type->GetClangForwardType()); 667 } 668 669 void * 670 Type::CreateClangRValueReferenceType (Type *type) 671 { 672 assert(type); 673 return GetClangASTContext().CreateRValueReferenceType (type->GetClangForwardType()); 674 } 675 676 bool 677 Type::IsRealObjCClass() 678 { 679 // For now we are just skipping ObjC classes that get made by hand from the runtime, because 680 // those don't have any information. We could extend this to only return true for "full 681 // definitions" if we can figure that out. 682 683 if (ClangASTContext::IsObjCClassType(m_clang_type) && GetByteSize() != 0) 684 return true; 685 else 686 return false; 687 } 688 689 TypeAndOrName::TypeAndOrName () : m_type_sp(), m_type_name() 690 { 691 692 } 693 694 TypeAndOrName::TypeAndOrName (TypeSP &in_type_sp) : m_type_sp(in_type_sp) 695 { 696 if (in_type_sp) 697 m_type_name = in_type_sp->GetName(); 698 } 699 700 TypeAndOrName::TypeAndOrName (const char *in_type_str) : m_type_name(in_type_str) 701 { 702 } 703 704 TypeAndOrName::TypeAndOrName (const TypeAndOrName &rhs) : m_type_sp (rhs.m_type_sp), m_type_name (rhs.m_type_name) 705 { 706 707 } 708 709 TypeAndOrName::TypeAndOrName (ConstString &in_type_const_string) : m_type_name (in_type_const_string) 710 { 711 } 712 713 TypeAndOrName & 714 TypeAndOrName::operator= (const TypeAndOrName &rhs) 715 { 716 if (this != &rhs) 717 { 718 m_type_name = rhs.m_type_name; 719 m_type_sp = rhs.m_type_sp; 720 } 721 return *this; 722 } 723 724 ConstString 725 TypeAndOrName::GetName () const 726 { 727 if (m_type_sp) 728 return m_type_sp->GetName(); 729 else 730 return m_type_name; 731 } 732 733 void 734 TypeAndOrName::SetName (ConstString &type_name_const_str) 735 { 736 m_type_name = type_name_const_str; 737 } 738 739 void 740 TypeAndOrName::SetName (const char *type_name_str) 741 { 742 m_type_name.SetCString (type_name_str); 743 } 744 745 void 746 TypeAndOrName::SetTypeSP (lldb::TypeSP type_sp) 747 { 748 m_type_sp = type_sp; 749 if (type_sp) 750 m_type_name = type_sp->GetName(); 751 } 752 753 bool 754 TypeAndOrName::IsEmpty() 755 { 756 if (m_type_name || m_type_sp) 757 return false; 758 else 759 return true; 760 } 761 762 TypeImpl::TypeImpl(const lldb_private::ClangASTType& clang_ast_type) : 763 m_clang_ast_type(clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType()), 764 m_type_sp() 765 {} 766 767 TypeImpl::TypeImpl(const lldb::TypeSP& type) : 768 m_clang_ast_type(type->GetClangAST(), type->GetClangFullType()), 769 m_type_sp(type) 770 { 771 } 772 773 TypeImpl& 774 TypeImpl::operator = (const TypeImpl& rhs) 775 { 776 if (*this != rhs) 777 { 778 m_clang_ast_type = rhs.m_clang_ast_type; 779 m_type_sp = rhs.m_type_sp; 780 } 781 return *this; 782 } 783 784 clang::ASTContext* 785 TypeImpl::GetASTContext() 786 { 787 if (!IsValid()) 788 return NULL; 789 790 return m_clang_ast_type.GetASTContext(); 791 } 792 793 lldb::clang_type_t 794 TypeImpl::GetOpaqueQualType() 795 { 796 if (!IsValid()) 797 return NULL; 798 799 return m_clang_ast_type.GetOpaqueQualType(); 800 } 801 802 bool 803 TypeImpl::GetDescription (lldb_private::Stream &strm, 804 lldb::DescriptionLevel description_level) 805 { 806 if (m_clang_ast_type.IsValid()) 807 { 808 ClangASTType::DumpTypeDescription (m_clang_ast_type.GetASTContext(), 809 m_clang_ast_type.GetOpaqueQualType(), 810 &strm); 811 } 812 else 813 { 814 strm.PutCString ("No value"); 815 } 816 return true; 817 } 818 819