1########################################################################### 2# A module to parse GCC AST 3# 4# Copyright (C) 2015-2019 Andrey Ponomarenko's ABI Laboratory 5# 6# Written by Andrey Ponomarenko 7# 8# This library is free software; you can redistribute it and/or 9# modify it under the terms of the GNU Lesser General Public 10# License as published by the Free Software Foundation; either 11# version 2.1 of the License, or (at your option) any later version. 12# 13# This library is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16# Lesser General Public License for more details. 17# 18# You should have received a copy of the GNU Lesser General Public 19# License along with this library; if not, write to the Free Software 20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21# MA 02110-1301 USA 22########################################################################### 23use strict; 24use Storable qw(dclone); 25 26my %Cache; 27 28my $BYTE = 8; 29 30my %OperatorIndication = ( 31 "not" => "~", 32 "assign" => "=", 33 "andassign" => "&=", 34 "orassign" => "|=", 35 "xorassign" => "^=", 36 "or" => "|", 37 "xor" => "^", 38 "addr" => "&", 39 "and" => "&", 40 "lnot" => "!", 41 "eq" => "==", 42 "ne" => "!=", 43 "lt" => "<", 44 "lshift" => "<<", 45 "lshiftassign" => "<<=", 46 "rshiftassign" => ">>=", 47 "call" => "()", 48 "mod" => "%", 49 "modassign" => "%=", 50 "subs" => "[]", 51 "land" => "&&", 52 "lor" => "||", 53 "rshift" => ">>", 54 "ref" => "->", 55 "le" => "<=", 56 "deref" => "*", 57 "mult" => "*", 58 "preinc" => "++", 59 "delete" => " delete", 60 "vecnew" => " new[]", 61 "vecdelete" => " delete[]", 62 "predec" => "--", 63 "postinc" => "++", 64 "postdec" => "--", 65 "plusassign" => "+=", 66 "plus" => "+", 67 "minus" => "-", 68 "minusassign" => "-=", 69 "gt" => ">", 70 "ge" => ">=", 71 "new" => " new", 72 "multassign" => "*=", 73 "divassign" => "/=", 74 "div" => "/", 75 "neg" => "-", 76 "pos" => "+", 77 "memref" => "->*", 78 "compound" => "," 79); 80 81my %NodeType= ( 82 "array_type" => "Array", 83 "binfo" => "Other", 84 "boolean_type" => "Intrinsic", 85 "complex_type" => "Intrinsic", 86 "const_decl" => "Other", 87 "enumeral_type" => "Enum", 88 "field_decl" => "Other", 89 "function_decl" => "Other", 90 "function_type" => "FunctionType", 91 "identifier_node" => "Other", 92 "integer_cst" => "Other", 93 "integer_type" => "Intrinsic", 94 "vector_type" => "Vector", 95 "method_type" => "MethodType", 96 "namespace_decl" => "Other", 97 "parm_decl" => "Other", 98 "pointer_type" => "Pointer", 99 "real_cst" => "Other", 100 "real_type" => "Intrinsic", 101 "record_type" => "Struct", 102 "reference_type" => "Ref", 103 "string_cst" => "Other", 104 "template_decl" => "Other", 105 "template_type_parm" => "TemplateParam", 106 "typename_type" => "TypeName", 107 "sizeof_expr" => "SizeOf", 108 "tree_list" => "Other", 109 "tree_vec" => "Other", 110 "type_decl" => "Other", 111 "union_type" => "Union", 112 "var_decl" => "Other", 113 "void_type" => "Intrinsic", 114 "nop_expr" => "Other", 115 "addr_expr" => "Other", 116 "offset_type" => "Other" 117); 118 119my %UnQual = ( 120 "r"=>"restrict", 121 "v"=>"volatile", 122 "c"=>"const", 123 "cv"=>"const volatile" 124); 125 126my %IntrinsicNames = map {$_=>1} ( 127 "void", 128 "bool", 129 "wchar_t", 130 "char", 131 "signed char", 132 "unsigned char", 133 "short", 134 "unsigned short", 135 "int", 136 "unsigned int", 137 "long", 138 "unsigned long", 139 "long long", 140 "__int64", 141 "unsigned long long", 142 "__int128", 143 "unsigned __int128", 144 "float", 145 "double", 146 "long double" , 147 "__float80", 148 "__float128", 149 "..." 150); 151 152my %ConstantSuffix = ( 153 "unsigned int"=>"u", 154 "long"=>"l", 155 "unsigned long"=>"ul", 156 "long long"=>"ll", 157 "unsigned long long"=>"ull" 158); 159 160my %DefaultStdArgs = map {$_=>1} ( 161 "_Alloc", 162 "_Compare", 163 "_Traits", 164 "_Rx_traits", 165 "_InIter", 166 "_OutIter" 167); 168 169my %LibInfo; 170my %UnknownOperator; 171my %Typedef_Tr; 172my %Typedef_Eq; 173my %StdCxxTypedef; 174my %MissedTypedef; 175my %MissedBase; 176my %MissedBase_R; 177my %CheckedTypeInfo; 178my %TemplateInstance; 179my %BasicTemplate; 180my %TemplateArg; 181my %TemplateDecl; 182my %TemplateMap; 183my %EnumMembName_Id; 184my %TypedefToAnon; 185my %MangledNames; 186my $MAX_ID = 0; 187 188my $V = undef; 189 190# Aliases 191my (%SymbolInfo, %TypeInfo, %TName_Tid) = (); 192 193foreach (1, 2) 194{ 195 $SymbolInfo{$_} = $In::ABI{$_}{"SymbolInfo"}; 196 $TypeInfo{$_} = $In::ABI{$_}{"TypeInfo"}; 197 $TName_Tid{$_} = $In::ABI{$_}{"TName_Tid"}; 198} 199 200sub readGccAst($$) 201{ 202 my ($LVer, $DumpPath) = @_; 203 204 $V = $LVer; 205 206 open(TU_DUMP, $DumpPath); 207 local $/ = undef; 208 my $Content = <TU_DUMP>; 209 close(TU_DUMP); 210 211 unlink($DumpPath); 212 213 $Content=~s/\n[ ]+/ /g; 214 my @Lines = split(/\n/, $Content); 215 216 # clean memory 217 undef $Content; 218 219 $MAX_ID = $#Lines+1; # number of lines == number of nodes 220 221 foreach (0 .. $#Lines) 222 { 223 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i) 224 { # get a number and attributes of a node 225 next if(not $NodeType{$2}); 226 $LibInfo{$V}{"info_type"}{$1} = $2; 227 $LibInfo{$V}{"info"}{$1} = $3." "; 228 } 229 230 # clean memory 231 delete($Lines[$_]); 232 } 233 234 # clean memory 235 undef @Lines; 236 237 # processing info 238 setTemplateParams_All(); 239 240 if($In::Opt{"ExtraDump"}) { 241 setAnonTypedef_All(); 242 } 243 244 getTypeInfo_All(); 245 simplifyNames(); 246 simplifyConstants(); 247 getVarInfo_All(); 248 getSymbolInfo_All(); 249 250 # clean memory 251 %LibInfo = (); 252 %TemplateInstance = (); 253 %BasicTemplate = (); 254 %MangledNames = (); 255 %TemplateDecl = (); 256 %StdCxxTypedef = (); 257 %MissedTypedef = (); 258 %Typedef_Tr = (); 259 %Typedef_Eq = (); 260 %TypedefToAnon = (); 261 262 # clean cache 263 delete($Cache{"getTypeAttr"}); 264 delete($Cache{"getTypeDeclId"}); 265 266 if($In::Opt{"ExtraDump"}) 267 { 268 remove_Unused($V, "Extra"); 269 } 270 else 271 { # remove unused types 272 if($In::Opt{"BinOnly"} and not $In::Opt{"ExtendedCheck"}) 273 { # --binary 274 remove_Unused($V, "All"); 275 } 276 else { 277 remove_Unused($V, "Extended"); 278 } 279 } 280 281 if($In::Opt{"CheckInfo"}) 282 { 283 foreach my $Tid (keys(%{$TypeInfo{$V}})) { 284 checkCompleteness($TypeInfo{$V}{$Tid}); 285 } 286 287 foreach my $Sid (keys(%{$SymbolInfo{$V}})) { 288 checkCompleteness($SymbolInfo{$V}{$Sid}); 289 } 290 } 291} 292 293sub checkCompleteness($) 294{ 295 my $Info = $_[0]; 296 297 # data types 298 if(defined $Info->{"Memb"}) 299 { 300 foreach my $Pos (keys(%{$Info->{"Memb"}})) 301 { 302 if(defined $Info->{"Memb"}{$Pos}{"type"}) { 303 checkTypeInfo($Info->{"Memb"}{$Pos}{"type"}); 304 } 305 } 306 } 307 if(defined $Info->{"Base"}) 308 { 309 foreach my $Bid (keys(%{$Info->{"Base"}})) { 310 checkTypeInfo($Bid); 311 } 312 } 313 if(defined $Info->{"BaseType"}) { 314 checkTypeInfo($Info->{"BaseType"}); 315 } 316 if(defined $Info->{"TParam"}) 317 { 318 foreach my $Pos (keys(%{$Info->{"TParam"}})) 319 { 320 my $TName = $Info->{"TParam"}{$Pos}{"name"}; 321 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) { 322 next; 323 } 324 if($TName eq "_BoolType") { 325 next; 326 } 327 if($TName=~/\Asizeof\(/) { 328 next; 329 } 330 if(my $Tid = $TName_Tid{$V}{$TName}) { 331 checkTypeInfo($Tid); 332 } 333 else 334 { 335 if(defined $In::Opt{"Debug"}) { 336 printMsg("WARNING", "missed type $TName"); 337 } 338 } 339 } 340 } 341 342 # symbols 343 if(defined $Info->{"Param"}) 344 { 345 foreach my $Pos (keys(%{$Info->{"Param"}})) 346 { 347 if(defined $Info->{"Param"}{$Pos}{"type"}) { 348 checkTypeInfo($Info->{"Param"}{$Pos}{"type"}); 349 } 350 } 351 } 352 if(defined $Info->{"Return"}) { 353 checkTypeInfo($Info->{"Return"}); 354 } 355 if(defined $Info->{"Class"}) { 356 checkTypeInfo($Info->{"Class"}); 357 } 358} 359 360sub checkTypeInfo($) 361{ 362 my $Tid = $_[0]; 363 364 if(defined $CheckedTypeInfo{$V}{$Tid}) { 365 return; 366 } 367 $CheckedTypeInfo{$V}{$Tid} = 1; 368 369 if(defined $TypeInfo{$V}{$Tid}) 370 { 371 if(not $TypeInfo{$V}{$Tid}{"Name"}) { 372 printMsg("ERROR", "missed type name ($Tid)"); 373 } 374 checkCompleteness($TypeInfo{$V}{$Tid}); 375 } 376 else { 377 printMsg("ERROR", "missed type id $Tid"); 378 } 379} 380 381sub getSymbolInfo_All() 382{ 383 foreach (sort {$b<=>$a} keys(%{$LibInfo{$V}{"info"}})) 384 { # reverse order 385 if($LibInfo{$V}{"info_type"}{$_} eq "function_decl") { 386 getSymbolInfo($_); 387 } 388 } 389 390 if($In::Opt{"AddTemplateInstances"}) 391 { 392 # templates 393 foreach my $Sid (sort {$a<=>$b} keys(%{$SymbolInfo{$V}})) 394 { 395 my %Map = (); 396 397 if(my $ClassId = $SymbolInfo{$V}{$Sid}{"Class"}) 398 { 399 if(defined $TemplateMap{$V}{$ClassId}) 400 { 401 foreach (keys(%{$TemplateMap{$V}{$ClassId}})) { 402 $Map{$_} = $TemplateMap{$V}{$ClassId}{$_}; 403 } 404 } 405 } 406 407 if(defined $TemplateMap{$V}{$Sid}) 408 { 409 foreach (keys(%{$TemplateMap{$V}{$Sid}})) { 410 $Map{$_} = $TemplateMap{$V}{$Sid}{$_}; 411 } 412 } 413 414 if(defined $SymbolInfo{$V}{$Sid}{"Param"}) 415 { 416 foreach (sort {$a<=>$b} keys(%{$SymbolInfo{$V}{$Sid}{"Param"}})) 417 { 418 my $PTid = $SymbolInfo{$V}{$Sid}{"Param"}{$_}{"type"}; 419 $SymbolInfo{$V}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid); 420 } 421 } 422 if(my $Return = $SymbolInfo{$V}{$Sid}{"Return"}) { 423 $SymbolInfo{$V}{$Sid}{"Return"} = instType(\%Map, $Return); 424 } 425 } 426 } 427} 428 429sub getVarInfo_All() 430{ 431 foreach (sort {$b<=>$a} keys(%{$LibInfo{$V}{"info"}})) 432 { # reverse order 433 if($LibInfo{$V}{"info_type"}{$_} eq "var_decl") { 434 getVarInfo($_); 435 } 436 } 437} 438 439sub getTypeInfo_All() 440{ 441 if(not checkGcc("4.5")) 442 { # support for GCC < 4.5 443 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag> 444 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump 445 # FIXME: check GCC versions 446 addMissedTypes_Pre(); 447 } 448 449 foreach (sort {$a<=>$b} keys(%{$LibInfo{$V}{"info"}})) 450 { # forward order only 451 my $IType = $LibInfo{$V}{"info_type"}{$_}; 452 if($IType=~/_type\Z/ and $IType ne "function_type" 453 and $IType ne "method_type") { 454 getTypeInfo("$_"); 455 } 456 } 457 458 # add "..." type 459 $TypeInfo{$V}{"-1"} = { 460 "Name" => "...", 461 "Type" => "Intrinsic", 462 "Tid" => "-1" 463 }; 464 $TName_Tid{$V}{"..."} = "-1"; 465 466 if(not checkGcc("4.5")) 467 { # support for GCC < 4.5 468 addMissedTypes_Post(); 469 } 470 471 if($In::Opt{"AddTemplateInstances"}) 472 { 473 # templates 474 foreach my $Tid (sort {$a<=>$b} keys(%{$TypeInfo{$V}})) 475 { 476 if(defined $TemplateMap{$V}{$Tid} 477 and not defined $TypeInfo{$V}{$Tid}{"Template"}) 478 { 479 if(defined $TypeInfo{$V}{$Tid}{"Memb"}) 480 { 481 foreach my $Pos (sort {$a<=>$b} keys(%{$TypeInfo{$V}{$Tid}{"Memb"}})) 482 { 483 if(my $MembTypeId = $TypeInfo{$V}{$Tid}{"Memb"}{$Pos}{"type"}) 484 { 485 if(my $MAttr = getTypeAttr($MembTypeId)) 486 { 487 $TypeInfo{$V}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr->{"Algn"}; 488 $MembTypeId = $TypeInfo{$V}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$V}{$Tid}, $MembTypeId); 489 } 490 } 491 } 492 } 493 if(defined $TypeInfo{$V}{$Tid}{"Base"}) 494 { 495 foreach my $Bid (sort {$a<=>$b} keys(%{$TypeInfo{$V}{$Tid}{"Base"}})) 496 { 497 my $NBid = instType($TemplateMap{$V}{$Tid}, $Bid); 498 499 if($NBid ne $Bid 500 and $NBid ne $Tid) 501 { 502 %{$TypeInfo{$V}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$V}{$Tid}{"Base"}{$Bid}}; 503 delete($TypeInfo{$V}{$Tid}{"Base"}{$Bid}); 504 } 505 } 506 } 507 } 508 } 509 } 510} 511 512sub getVarInfo($) 513{ 514 my $InfoId = $_[0]; 515 if(my $NSid = getTreeAttr_Scpe($InfoId)) 516 { 517 my $NSInfoType = $LibInfo{$V}{"info_type"}{$NSid}; 518 if($NSInfoType and $NSInfoType eq "function_decl") { 519 return; 520 } 521 } 522 523 if(not $SymbolInfo{$V}{$InfoId}) { 524 $SymbolInfo{$V}{$InfoId} = {}; 525 } 526 527 my $SInfo = $SymbolInfo{$V}{$InfoId}; 528 529 ($SInfo->{"Header"}, $SInfo->{"Line"}) = getLocation($InfoId); 530 if(not $SInfo->{"Header"} 531 or isBuiltIn($SInfo->{"Header"})) { 532 delete($SymbolInfo{$V}{$InfoId}); 533 return; 534 } 535 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId)); 536 if(not $ShortName) { 537 delete($SymbolInfo{$V}{$InfoId}); 538 return; 539 } 540 if($ShortName=~/\Atmp_add_class_\d+\Z/) { 541 delete($SymbolInfo{$V}{$InfoId}); 542 return; 543 } 544 $SInfo->{"ShortName"} = $ShortName; 545 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId))) 546 { 547 if($In::Opt{"OS"} eq "windows") 548 { # cut the offset 549 $MnglName=~s/\@\d+\Z//g; 550 } 551 $SInfo->{"MnglName"} = $MnglName; 552 } 553 if($SInfo->{"MnglName"} 554 and index($SInfo->{"MnglName"}, "_Z")!=0) 555 { # validate mangled name 556 delete($SymbolInfo{$V}{$InfoId}); 557 return; 558 } 559 if(not $SInfo->{"MnglName"} 560 and index($ShortName, "_Z")==0) 561 { # _ZTS, etc. 562 $SInfo->{"MnglName"} = $ShortName; 563 } 564 if(isPrivateData($SInfo->{"MnglName"})) 565 { # non-public global data 566 delete($SymbolInfo{$V}{$InfoId}); 567 return; 568 } 569 $SInfo->{"Data"} = 1; 570 if(my $Rid = getTypeId($InfoId)) 571 { 572 if(not defined $TypeInfo{$V}{$Rid} 573 or not $TypeInfo{$V}{$Rid}{"Name"}) 574 { 575 delete($SymbolInfo{$V}{$InfoId}); 576 return; 577 } 578 $SInfo->{"Return"} = $Rid; 579 my $Val = getDataVal($InfoId, $Rid); 580 if(defined $Val) { 581 $SInfo->{"Value"} = $Val; 582 } 583 } 584 setClassAndNs($InfoId); 585 if(my $ClassId = $SInfo->{"Class"}) 586 { 587 if(not defined $TypeInfo{$V}{$ClassId} 588 or not $TypeInfo{$V}{$ClassId}{"Name"}) 589 { 590 delete($SymbolInfo{$V}{$InfoId}); 591 return; 592 } 593 } 594 595 if(my $ClassId = $SInfo->{"Class"}) 596 { 597 if(not $In::Opt{"StdcxxTesting"}) 598 { # stdc++ data 599 if(index($TypeInfo{$V}{$ClassId}{"Name"}, "std::")==0) 600 { 601 delete($SymbolInfo{$V}{$InfoId}); 602 return; 603 } 604 } 605 606 if($TypeInfo{$V}{$ClassId}{"NameSpace"}) 607 { 608 if(index($TypeInfo{$V}{$ClassId}{"NameSpace"}, "__gnu_cxx")==0) 609 { 610 delete($SymbolInfo{$V}{$InfoId}); 611 return; 612 } 613 } 614 } 615 616 if($SInfo->{"NameSpace"}) 617 { 618 if(index($SInfo->{"NameSpace"}, "__gnu_cxx")==0) 619 { 620 delete($SymbolInfo{$V}{$InfoId}); 621 return; 622 } 623 } 624 625 if($LibInfo{$V}{"info"}{$InfoId}=~/ lang:[ ]*C /i) 626 { # extern "C" 627 $SInfo->{"Lang"} = "C"; 628 $SInfo->{"MnglName"} = $ShortName; 629 } 630 if($In::Opt{"UserLang"} eq "C") 631 { # --lang=C option 632 $SInfo->{"MnglName"} = $ShortName; 633 } 634 if(not $In::Opt{"CheckHeadersOnly"}) 635 { 636 if(not $SInfo->{"Class"}) 637 { 638 if(not $SInfo->{"MnglName"} 639 or not linkSymbol($SInfo->{"MnglName"}, $V, "-Deps")) 640 { 641 if(linkSymbol($ShortName, $V, "-Deps")) 642 { # "const" global data is mangled as _ZL... in the TU dump 643 # but not mangled when compiling a C shared library 644 $SInfo->{"MnglName"} = $ShortName; 645 } 646 } 647 } 648 } 649 if($In::ABI{$V}{"Language"} eq "C++") 650 { 651 if(not $SInfo->{"MnglName"}) 652 { # for some symbols (_ZTI) the short name is the mangled name 653 if(index($ShortName, "_Z")==0) { 654 $SInfo->{"MnglName"} = $ShortName; 655 } 656 } 657 658 if(not $SInfo->{"MnglName"} 659 or $In::Opt{"Target"} eq "windows") 660 { # try to mangle symbol (link with libraries) 661 if(my $Mangled = linkWithSymbol($InfoId)) { 662 $SInfo->{"MnglName"} = $Mangled; 663 } 664 } 665 } 666 if(not $SInfo->{"MnglName"}) 667 { 668 if($SInfo->{"Class"}) { 669 return; 670 } 671 $SInfo->{"MnglName"} = $ShortName; 672 } 673 if(my $Symbol = $SInfo->{"MnglName"}) 674 { 675 if(not selectSymbol($Symbol, $SInfo, "Dump", $V)) 676 { # non-target symbols 677 delete($SymbolInfo{$V}{$InfoId}); 678 return; 679 } 680 } 681 if(my $Rid = $SInfo->{"Return"}) 682 { 683 if(defined $MissedTypedef{$V}{$Rid}) 684 { 685 if(my $AddedTid = $MissedTypedef{$V}{$Rid}{"Tid"}) { 686 $SInfo->{"Return"} = $AddedTid; 687 } 688 } 689 } 690 setFuncAccess($InfoId); 691 if(index($SInfo->{"MnglName"}, "_ZTV")==0) { 692 delete($SInfo->{"Return"}); 693 } 694 if($ShortName=~/\A(_Z|\?)/) { 695 delete($SInfo->{"ShortName"}); 696 } 697 698 if($In::Opt{"ExtraDump"}) { 699 $SInfo->{"Header"} = guessHeader($InfoId); 700 } 701} 702 703sub getSymbolInfo($) 704{ 705 my $InfoId = $_[0]; 706 if(isInternal($InfoId)) { 707 return; 708 } 709 710 if(not $SymbolInfo{$V}{$InfoId}) { 711 $SymbolInfo{$V}{$InfoId} = {}; 712 } 713 714 my $SInfo = $SymbolInfo{$V}{$InfoId}; 715 716 ($SInfo->{"Header"}, $SInfo->{"Line"}) = getLocation($InfoId); 717 if(not $SInfo->{"Header"} 718 or isBuiltIn($SInfo->{"Header"})) 719 { 720 delete($SymbolInfo{$V}{$InfoId}); 721 return; 722 } 723 setFuncAccess($InfoId); 724 setFuncKind($InfoId); 725 if($SInfo->{"PseudoTemplate"}) 726 { 727 delete($SymbolInfo{$V}{$InfoId}); 728 return; 729 } 730 731 $SInfo->{"Type"} = getFuncType($InfoId); 732 if(my $Return = getFuncReturn($InfoId)) 733 { 734 if(not defined $TypeInfo{$V}{$Return} 735 or not $TypeInfo{$V}{$Return}{"Name"}) 736 { 737 delete($SymbolInfo{$V}{$InfoId}); 738 return; 739 } 740 $SInfo->{"Return"} = $Return; 741 } 742 if(my $Rid = $SInfo->{"Return"}) 743 { 744 if(defined $MissedTypedef{$V}{$Rid}) 745 { 746 if(my $AddedTid = $MissedTypedef{$V}{$Rid}{"Tid"}) { 747 $SInfo->{"Return"} = $AddedTid; 748 } 749 } 750 } 751 if(not $SInfo->{"Return"}) { 752 delete($SInfo->{"Return"}); 753 } 754 my $Orig = getFuncOrig($InfoId); 755 $SInfo->{"ShortName"} = getFuncShortName($Orig); 756 if(index($SInfo->{"ShortName"}, "\._")!=-1) 757 { 758 delete($SymbolInfo{$V}{$InfoId}); 759 return; 760 } 761 762 if(index($SInfo->{"ShortName"}, "tmp_add_func")==0) 763 { 764 delete($SymbolInfo{$V}{$InfoId}); 765 return; 766 } 767 768 if(defined $TemplateInstance{$V}{"Func"}{$Orig}) 769 { 770 my $Tmpl = $BasicTemplate{$V}{$InfoId}; 771 772 my @TParams = getTParams($Orig, "Func"); 773 if(not @TParams) 774 { 775 delete($SymbolInfo{$V}{$InfoId}); 776 return; 777 } 778 foreach my $Pos (0 .. $#TParams) 779 { 780 my $Val = $TParams[$Pos]; 781 $SInfo->{"TParam"}{$Pos}{"name"} = $Val; 782 783 if($Tmpl) 784 { 785 if(my $Arg = $TemplateArg{$V}{$Tmpl}{$Pos}) 786 { 787 $TemplateMap{$V}{$InfoId}{$Arg} = $Val; 788 } 789 } 790 } 791 792 if($Tmpl) 793 { 794 foreach my $Pos (sort {$a<=>$b} keys(%{$TemplateArg{$V}{$Tmpl}})) 795 { 796 if($Pos>$#TParams) 797 { 798 my $Arg = $TemplateArg{$V}{$Tmpl}{$Pos}; 799 $TemplateMap{$V}{$InfoId}{$Arg} = ""; 800 } 801 } 802 } 803 804 if($SInfo->{"ShortName"}=~/\Aoperator\W+\Z/) 805 { # operator<< <T>, operator>> <T> 806 $SInfo->{"ShortName"} .= " "; 807 } 808 809 if(@TParams) { 810 $SInfo->{"ShortName"} .= "<".join(", ", @TParams).">"; 811 } 812 else { 813 $SInfo->{"ShortName"} .= "<...>"; 814 } 815 816 $SInfo->{"ShortName"} = formatName($SInfo->{"ShortName"}, "S"); 817 } 818 else 819 { # support for GCC 3.4 820 $SInfo->{"ShortName"}=~s/<.+>\Z//; 821 } 822 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId))) 823 { 824 if($In::Opt{"OS"} eq "windows") 825 { # cut the offset 826 $MnglName=~s/\@\d+\Z//g; 827 } 828 $SInfo->{"MnglName"} = $MnglName; 829 830 # NOTE: mangling of some symbols may change depending on GCC version 831 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E 832 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_ 833 } 834 835 if($SInfo->{"MnglName"} 836 and index($SInfo->{"MnglName"}, "_Z")!=0) 837 { 838 delete($SymbolInfo{$V}{$InfoId}); 839 return; 840 } 841 if(not $SInfo->{"Destructor"}) 842 { # destructors have an empty parameter list 843 my $Skip = setFuncParams($InfoId); 844 if($Skip) 845 { 846 delete($SymbolInfo{$V}{$InfoId}); 847 return; 848 } 849 } 850 if($LibInfo{$V}{"info"}{$InfoId}=~/ artificial /i) { 851 $SInfo->{"Artificial"} = 1; 852 } 853 854 if(setClassAndNs($InfoId)) 855 { 856 delete($SymbolInfo{$V}{$InfoId}); 857 return; 858 } 859 860 if(my $ClassId = $SInfo->{"Class"}) 861 { 862 if(not defined $TypeInfo{$V}{$ClassId} 863 or not $TypeInfo{$V}{$ClassId}{"Name"}) 864 { 865 delete($SymbolInfo{$V}{$InfoId}); 866 return; 867 } 868 } 869 870 if($SInfo->{"Constructor"}) 871 { 872 my $CShort = getFuncShortName($InfoId); 873 874 if($CShort eq "__comp_ctor") { 875 $SInfo->{"Constructor"} = "C1"; 876 } 877 elsif($CShort eq "__base_ctor") { 878 $SInfo->{"Constructor"} = "C2"; 879 } 880 } 881 elsif($SInfo->{"Destructor"}) 882 { 883 my $DShort = getFuncShortName($InfoId); 884 885 if($DShort eq "__deleting_dtor") { 886 $SInfo->{"Destructor"} = "D0"; 887 } 888 elsif($DShort eq "__comp_dtor") { 889 $SInfo->{"Destructor"} = "D1"; 890 } 891 elsif($DShort eq "__base_dtor") { 892 $SInfo->{"Destructor"} = "D2"; 893 } 894 } 895 896 if(not $SInfo->{"Constructor"} 897 and my $Spec = getVirtSpec($Orig)) 898 { # identify virtual and pure virtual functions 899 # NOTE: constructors cannot be virtual 900 # NOTE: in GCC 4.7 D1 destructors have no virtual spec 901 # in the TU dump, so taking it from the original symbol 902 if(not ($SInfo->{"Destructor"} 903 and $SInfo->{"Destructor"} eq "D2")) 904 { # NOTE: D2 destructors are not present in a v-table 905 $SInfo->{$Spec} = 1; 906 } 907 } 908 909 if(isInline($InfoId)) { 910 $SInfo->{"InLine"} = 1; 911 } 912 913 if(hasThrow($InfoId)) { 914 $SInfo->{"Throw"} = 1; 915 } 916 917 if($SInfo->{"Constructor"} 918 and my $ClassId = $SInfo->{"Class"}) 919 { 920 if(not $SInfo->{"InLine"} 921 and not $SInfo->{"Artificial"}) 922 { # inline or auto-generated constructor 923 delete($TypeInfo{$V}{$ClassId}{"Copied"}); 924 } 925 } 926 927 if(my $ClassId = $SInfo->{"Class"}) 928 { 929 if(not $In::Opt{"StdcxxTesting"}) 930 { # stdc++ interfaces 931 if(not $SInfo->{"Virt"} and not $SInfo->{"PureVirt"}) 932 { 933 if(index($TypeInfo{$V}{$ClassId}{"Name"}, "std::")==0) 934 { 935 delete($SymbolInfo{$V}{$InfoId}); 936 return; 937 } 938 } 939 } 940 941 if($TypeInfo{$V}{$ClassId}{"NameSpace"}) 942 { 943 if(index($TypeInfo{$V}{$ClassId}{"NameSpace"}, "__gnu_cxx")==0) 944 { 945 delete($SymbolInfo{$V}{$InfoId}); 946 return; 947 } 948 } 949 } 950 951 if($SInfo->{"NameSpace"}) 952 { 953 if(index($SInfo->{"NameSpace"}, "__gnu_cxx")==0) 954 { 955 delete($SymbolInfo{$V}{$InfoId}); 956 return; 957 } 958 } 959 960 if($LibInfo{$V}{"info"}{$InfoId}=~/ lang:[ ]*C /i) 961 { # extern "C" 962 $SInfo->{"Lang"} = "C"; 963 $SInfo->{"MnglName"} = $SInfo->{"ShortName"}; 964 } 965 if($In::Opt{"UserLang"} eq "C") 966 { # --lang=C option 967 $SInfo->{"MnglName"} = $SInfo->{"ShortName"}; 968 } 969 970 if($In::ABI{$V}{"Language"} eq "C++") 971 { # correct mangled & short names 972 # C++ or --headers-only mode 973 if($SInfo->{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/) 974 { # support for old GCC versions: reconstruct real names for constructors and destructors 975 $SInfo->{"ShortName"} = getNameByInfo(getTypeDeclId($SInfo->{"Class"})); 976 $SInfo->{"ShortName"}=~s/<.+>\Z//; 977 } 978 979 if(not $SInfo->{"MnglName"} 980 or $In::Opt{"Target"} eq "windows") 981 { # try to mangle symbol (link with libraries) 982 if(my $Mangled = linkWithSymbol($InfoId)) { 983 $SInfo->{"MnglName"} = $Mangled; 984 } 985 } 986 } 987 else 988 { # not mangled in C 989 $SInfo->{"MnglName"} = $SInfo->{"ShortName"}; 990 } 991 if(not $In::Opt{"CheckHeadersOnly"} 992 and $SInfo->{"Type"} eq "Function" 993 and not $SInfo->{"Class"}) 994 { 995 my $Incorrect = 0; 996 997 if($SInfo->{"MnglName"}) 998 { 999 if(index($SInfo->{"MnglName"}, "_Z")==0 1000 and not linkSymbol($SInfo->{"MnglName"}, $V, "-Deps")) 1001 { # mangled in the TU dump, but not mangled in the library 1002 $Incorrect = 1; 1003 } 1004 } 1005 else 1006 { 1007 if($SInfo->{"Lang"} ne "C") 1008 { # all C++ functions are not mangled in the TU dump 1009 $Incorrect = 1; 1010 } 1011 } 1012 if($Incorrect) 1013 { 1014 if(linkSymbol($SInfo->{"ShortName"}, $V, "-Deps")) { 1015 $SInfo->{"MnglName"} = $SInfo->{"ShortName"}; 1016 } 1017 } 1018 } 1019 1020 if(not $SInfo->{"MnglName"}) 1021 { # can't detect symbol name 1022 delete($SymbolInfo{$V}{$InfoId}); 1023 return; 1024 } 1025 1026 if(my $Symbol = $SInfo->{"MnglName"}) 1027 { 1028 if(not $In::Opt{"ExtraDump"}) 1029 { 1030 if(not selectSymbol($Symbol, $SInfo, "Dump", $V)) 1031 { # non-target symbols 1032 delete($SymbolInfo{$V}{$InfoId}); 1033 return; 1034 } 1035 } 1036 } 1037 if($SInfo->{"Type"} eq "Method" 1038 or $SInfo->{"Constructor"} 1039 or $SInfo->{"Destructor"} 1040 or $SInfo->{"Class"}) 1041 { 1042 if($SInfo->{"MnglName"}!~/\A(_Z|\?)/) 1043 { 1044 delete($SymbolInfo{$V}{$InfoId}); 1045 return; 1046 } 1047 } 1048 if($SInfo->{"MnglName"}) 1049 { 1050 if($MangledNames{$V}{$SInfo->{"MnglName"}}) 1051 { # one instance for one mangled name only 1052 delete($SymbolInfo{$V}{$InfoId}); 1053 return; 1054 } 1055 else { 1056 $MangledNames{$V}{$SInfo->{"MnglName"}} = 1; 1057 } 1058 } 1059 if($SInfo->{"Constructor"} 1060 or $SInfo->{"Destructor"}) { 1061 delete($SInfo->{"Return"}); 1062 } 1063 if($SInfo->{"MnglName"}=~/\A(_Z|\?)/ 1064 and $SInfo->{"Class"}) 1065 { 1066 if($SInfo->{"Type"} eq "Function") 1067 { # static methods 1068 $SInfo->{"Static"} = 1; 1069 } 1070 } 1071 if(getFuncLink($InfoId) eq "Static") { 1072 $SInfo->{"Static"} = 1; 1073 } 1074 if($SInfo->{"MnglName"}=~/\A(_Z|\?)/) 1075 { 1076 if(my $Unmangled = getUnmangled($SInfo->{"MnglName"}, $V)) 1077 { 1078 if($Unmangled=~/\.\_\d/) 1079 { 1080 delete($SymbolInfo{$V}{$InfoId}); 1081 return; 1082 } 1083 } 1084 } 1085 1086 if($SInfo->{"MnglName"}=~/\A_ZN(V|)K/) { 1087 $SInfo->{"Const"} = 1; 1088 } 1089 if($SInfo->{"MnglName"}=~/\A_ZN(K|)V/) { 1090 $SInfo->{"Volatile"} = 1; 1091 } 1092 1093 if($In::ABI{$V}{"WeakSymbols"}{$SInfo->{"MnglName"}}) { 1094 $SInfo->{"Weak"} = 1; 1095 } 1096 1097 if($In::Opt{"ExtraDump"}) { 1098 $SInfo->{"Header"} = guessHeader($InfoId); 1099 } 1100} 1101 1102sub getTypeInfo($) 1103{ 1104 my $TypeId = $_[0]; 1105 $TypeInfo{$V}{$TypeId} = getTypeAttr($TypeId); 1106 my $TName = $TypeInfo{$V}{$TypeId}{"Name"}; 1107 if(not $TName) { 1108 delete($TypeInfo{$V}{$TypeId}); 1109 } 1110} 1111 1112sub getTypeAttr($) 1113{ 1114 my $TypeId = $_[0]; 1115 1116 if(defined $TypeInfo{$V}{$TypeId} 1117 and $TypeInfo{$V}{$TypeId}{"Name"}) 1118 { # already created 1119 return $TypeInfo{$V}{$TypeId}; 1120 } 1121 elsif($Cache{"getTypeAttr"}{$V}{$TypeId}) 1122 { # incomplete type 1123 return {}; 1124 } 1125 $Cache{"getTypeAttr"}{$V}{$TypeId} = 1; 1126 1127 my %TypeAttr = (); 1128 1129 my $TypeDeclId = getTypeDeclId($TypeId); 1130 $TypeAttr{"Tid"} = $TypeId; 1131 1132 if(not $MissedBase{$V}{$TypeId} and isTypedef($TypeId)) 1133 { 1134 if(my $Info = $LibInfo{$V}{"info"}{$TypeId}) 1135 { 1136 if($Info=~/qual[ ]*:/) 1137 { 1138 my $NewId = ++$MAX_ID; 1139 1140 $MissedBase{$V}{$TypeId} = "$NewId"; 1141 $MissedBase_R{$V}{$NewId} = $TypeId; 1142 $LibInfo{$V}{"info"}{$NewId} = $LibInfo{$V}{"info"}{$TypeId}; 1143 $LibInfo{$V}{"info_type"}{$NewId} = $LibInfo{$V}{"info_type"}{$TypeId}; 1144 } 1145 } 1146 $TypeAttr{"Type"} = "Typedef"; 1147 } 1148 else { 1149 $TypeAttr{"Type"} = getTypeType($TypeId); 1150 } 1151 1152 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId)) 1153 { 1154 if($LibInfo{$V}{"info_type"}{$ScopeId} eq "function_decl") 1155 { # local code 1156 return {}; 1157 } 1158 } 1159 1160 if($TypeAttr{"Type"} eq "Unknown") { 1161 return {}; 1162 } 1163 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/) 1164 { 1165 my $MemPtrAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"}); 1166 if(my $TName = $MemPtrAttr->{"Name"}) 1167 { 1168 $TypeInfo{$V}{$TypeId} = $MemPtrAttr; 1169 $TName_Tid{$V}{$TName} = $TypeId; 1170 return $MemPtrAttr; 1171 } 1172 1173 return {}; 1174 } 1175 elsif($TypeAttr{"Type"} eq "Array") 1176 { 1177 my ($BTid, $BTSpec) = selectBaseType($TypeId); 1178 if(not $BTid) { 1179 return {}; 1180 } 1181 if(my $Algn = getAlgn($TypeId)) { 1182 $TypeAttr{"Algn"} = $Algn/$BYTE; 1183 } 1184 $TypeAttr{"BaseType"} = $BTid; 1185 if(my $BTAttr = getTypeAttr($BTid)) 1186 { 1187 if(not $BTAttr->{"Name"}) { 1188 return {}; 1189 } 1190 if(my $NElems = getArraySize($TypeId, $BTAttr->{"Name"})) 1191 { 1192 if(my $Size = getSize($TypeId)) { 1193 $TypeAttr{"Size"} = $Size/$BYTE; 1194 } 1195 if($BTAttr->{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) { 1196 $TypeAttr{"Name"} = $1."[$NElems]".$2; 1197 } 1198 else { 1199 $TypeAttr{"Name"} = $BTAttr->{"Name"}."[$NElems]"; 1200 } 1201 } 1202 else 1203 { 1204 $TypeAttr{"Size"} = $In::ABI{$V}{"WordSize"}; # pointer 1205 if($BTAttr->{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) { 1206 $TypeAttr{"Name"} = $1."[]".$2; 1207 } 1208 else { 1209 $TypeAttr{"Name"} = $BTAttr->{"Name"}."[]"; 1210 } 1211 } 1212 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T"); 1213 if($BTAttr->{"Header"}) { 1214 $TypeAttr{"Header"} = $BTAttr->{"Header"}; 1215 } 1216 1217 $TName_Tid{$V}{$TypeAttr{"Name"}} = $TypeId; 1218 $TypeInfo{$V}{$TypeId} = \%TypeAttr; 1219 return \%TypeAttr; 1220 } 1221 return {}; 1222 } 1223 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/) 1224 { 1225 my $TrivialAttr = getTrivialTypeAttr($TypeId); 1226 if($TrivialAttr->{"Name"}) 1227 { 1228 $TypeInfo{$V}{$TypeId} = $TrivialAttr; 1229 1230 if(not defined $IntrinsicNames{$TrivialAttr->{"Name"}} 1231 or getTypeDeclId($TrivialAttr->{"Tid"})) 1232 { # NOTE: register only one int: with built-in decl 1233 if(not $TName_Tid{$V}{$TrivialAttr->{"Name"}}) { 1234 $TName_Tid{$V}{$TrivialAttr->{"Name"}} = $TypeId; 1235 } 1236 } 1237 1238 return $TrivialAttr; 1239 } 1240 1241 return {}; 1242 } 1243 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/) 1244 { 1245 my $TrivialAttr = getTrivialTypeAttr($TypeId); 1246 if($TrivialAttr->{"Name"}) 1247 { 1248 $TypeInfo{$V}{$TypeId} = $TrivialAttr; 1249 if(not $TName_Tid{$V}{$TrivialAttr->{"Name"}}) { 1250 $TName_Tid{$V}{$TrivialAttr->{"Name"}} = $TypeId; 1251 } 1252 return $TrivialAttr; 1253 } 1254 1255 return {}; 1256 } 1257 elsif($TypeAttr{"Type"} eq "SizeOf") 1258 { 1259 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId); 1260 my $BTAttr = getTypeAttr($TypeAttr{"BaseType"}); 1261 $TypeAttr{"Name"} = "sizeof(".$BTAttr->{"Name"}.")"; 1262 if($TypeAttr{"Name"}) 1263 { 1264 $TypeInfo{$V}{$TypeId} = \%TypeAttr; 1265 return \%TypeAttr; 1266 } 1267 1268 return {}; 1269 } 1270 else 1271 { # derived types 1272 my ($BTid, $BTSpec) = selectBaseType($TypeId); 1273 if(not $BTid) { 1274 return {}; 1275 } 1276 $TypeAttr{"BaseType"} = $BTid; 1277 if(defined $MissedTypedef{$V}{$BTid}) 1278 { 1279 if(my $MissedTDid = $MissedTypedef{$V}{$BTid}{"TDid"}) 1280 { 1281 if($MissedTDid ne $TypeDeclId) { 1282 $TypeAttr{"BaseType"} = $MissedTypedef{$V}{$BTid}{"Tid"}; 1283 } 1284 } 1285 } 1286 my $BTAttr = getTypeAttr($TypeAttr{"BaseType"}); 1287 if(not $BTAttr->{"Name"}) 1288 { # templates 1289 return {}; 1290 } 1291 if($BTAttr->{"Type"} eq "Typedef") 1292 { # relinking typedefs 1293 my %BaseBase = getType($BTAttr->{"BaseType"}, $V); 1294 if($BTAttr->{"Name"} eq $BaseBase{"Name"}) { 1295 $TypeAttr{"BaseType"} = $BaseBase{"Tid"}; 1296 } 1297 } 1298 if($BTSpec) 1299 { 1300 if($TypeAttr{"Type"} eq "Pointer" 1301 and $BTAttr->{"Name"}=~/\([\*]+\)/) 1302 { 1303 $TypeAttr{"Name"} = $BTAttr->{"Name"}; 1304 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g; 1305 } 1306 else { 1307 $TypeAttr{"Name"} = $BTAttr->{"Name"}." ".$BTSpec; 1308 } 1309 } 1310 else { 1311 $TypeAttr{"Name"} = $BTAttr->{"Name"}; 1312 } 1313 if($TypeAttr{"Type"} eq "Typedef") 1314 { 1315 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId); 1316 1317 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) { 1318 return {}; 1319 } 1320 1321 if(isAnon($TypeAttr{"Name"})) 1322 { # anon typedef to anon type: ._N 1323 return {}; 1324 } 1325 1326 if($LibInfo{$V}{"info"}{$TypeDeclId}=~/ artificial /i) 1327 { # artificial typedef of "struct X" to "X" 1328 $TypeAttr{"Artificial"} = 1; 1329 } 1330 1331 if(my $NS = getNameSpace($TypeDeclId)) 1332 { 1333 my $TypeName = $TypeAttr{"Name"}; 1334 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/) 1335 { # "some_type" is the typedef to "struct some_type" in C++ 1336 if($3) { 1337 $TypeAttr{"Name"} = $3."::".$TypeName; 1338 } 1339 } 1340 else 1341 { 1342 $TypeAttr{"NameSpace"} = $NS; 1343 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"}; 1344 1345 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/ 1346 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/) 1347 { 1348 if($BTAttr->{"NameSpace"} 1349 and $BTAttr->{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr->{"Name"}=~/</) 1350 { # types like "std::fpos<__mbstate_t>" are 1351 # not covered by typedefs in the TU dump 1352 # so trying to add such typedefs manually 1353 $StdCxxTypedef{$V}{$BTAttr->{"Name"}}{$TypeAttr{"Name"}} = 1; 1354 if(length($TypeAttr{"Name"})<=length($BTAttr->{"Name"})) 1355 { 1356 if(($BTAttr->{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) 1357 { # skip "other" in "std" and "type" in "boost" 1358 $Typedef_Eq{$V}{$BTAttr->{"Name"}} = $TypeAttr{"Name"}; 1359 } 1360 } 1361 } 1362 } 1363 } 1364 } 1365 if($TypeAttr{"Name"} ne $BTAttr->{"Name"} and not $TypeAttr{"Artificial"} 1366 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr->{"Name"}!~/>(::\w+)+\Z/) 1367 { 1368 $In::ABI{$V}{"TypedefBase"}{$TypeAttr{"Name"}} = $BTAttr->{"Name"}; 1369 if($BTAttr->{"Name"}=~/</) 1370 { 1371 if(($BTAttr->{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) { 1372 $Typedef_Tr{$V}{$BTAttr->{"Name"}}{$TypeAttr{"Name"}} = 1; 1373 } 1374 } 1375 } 1376 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId); 1377 } 1378 if(not $TypeAttr{"Size"}) 1379 { 1380 if($TypeAttr{"Type"} eq "Pointer") { 1381 $TypeAttr{"Size"} = $In::ABI{$V}{"WordSize"}; 1382 } 1383 elsif($BTAttr->{"Size"}) { 1384 $TypeAttr{"Size"} = $BTAttr->{"Size"}; 1385 } 1386 } 1387 if(my $Algn = getAlgn($TypeId)) { 1388 $TypeAttr{"Algn"} = $Algn/$BYTE; 1389 } 1390 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T"); 1391 if(not $TypeAttr{"Header"} and $BTAttr->{"Header"}) { 1392 $TypeAttr{"Header"} = $BTAttr->{"Header"}; 1393 } 1394 %{$TypeInfo{$V}{$TypeId}} = %TypeAttr; 1395 if($TypeAttr{"Name"} ne $BTAttr->{"Name"}) 1396 { # typedef to "class Class" 1397 # should not be registered in TName_Tid 1398 if(not $TName_Tid{$V}{$TypeAttr{"Name"}}) { 1399 $TName_Tid{$V}{$TypeAttr{"Name"}} = $TypeId; 1400 } 1401 } 1402 return \%TypeAttr; 1403 } 1404} 1405 1406sub getTrivialName($$) 1407{ 1408 my ($TypeInfoId, $TypeId) = @_; 1409 my %TypeAttr = (); 1410 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId); 1411 if(not $TypeAttr{"Name"}) { 1412 $TypeAttr{"Name"} = getTreeTypeName($TypeId); 1413 } 1414 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId); 1415 $TypeAttr{"Type"} = getTypeType($TypeId); 1416 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name 1417 if(isAnon($TypeAttr{"Name"})) 1418 { 1419 my $NameSpaceId = $TypeId; 1420 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId))) 1421 { # searching for a first not anon scope 1422 if($NSId eq $NameSpaceId) { 1423 last; 1424 } 1425 else 1426 { 1427 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId)); 1428 if(not $TypeAttr{"NameSpace"} 1429 or not isAnon($TypeAttr{"NameSpace"})) { 1430 last; 1431 } 1432 } 1433 $NameSpaceId = $NSId; 1434 } 1435 } 1436 else 1437 { 1438 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId)) 1439 { 1440 if($NameSpaceId ne $TypeId) { 1441 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId); 1442 } 1443 } 1444 } 1445 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) { 1446 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"}; 1447 } 1448 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T"); 1449 if(isAnon($TypeAttr{"Name"})) 1450 { # anon-struct-header.h-line 1451 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-"; 1452 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"}; 1453 if($TypeAttr{"NameSpace"}) { 1454 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"}; 1455 } 1456 } 1457 if(defined $TemplateInstance{$V}{"Type"}{$TypeId} 1458 and getTypeDeclId($TypeId) eq $TypeInfoId) 1459 { 1460 if(my @TParams = getTParams($TypeId, "Type")) { 1461 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T"); 1462 } 1463 else { 1464 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T"); 1465 } 1466 } 1467 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}); 1468} 1469 1470sub getTrivialTypeAttr($) 1471{ 1472 my $TypeId = $_[0]; 1473 my $TypeInfoId = getTypeDeclId($_[0]); 1474 1475 my %TypeAttr = (); 1476 1477 if($TemplateDecl{$V}{$TypeId}) 1478 { # template_decl 1479 $TypeAttr{"Template"} = 1; 1480 } 1481 1482 setTypeAccess($TypeId, \%TypeAttr); 1483 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId); 1484 if(isBuiltIn($TypeAttr{"Header"})) 1485 { 1486 delete($TypeAttr{"Header"}); 1487 delete($TypeAttr{"Line"}); 1488 } 1489 1490 $TypeAttr{"Type"} = getTypeType($TypeId); 1491 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId); 1492 if(not $TypeAttr{"Name"}) { 1493 return {}; 1494 } 1495 if(not $TypeAttr{"NameSpace"}) { 1496 delete($TypeAttr{"NameSpace"}); 1497 } 1498 1499 if($TypeAttr{"Type"} eq "Intrinsic") 1500 { 1501 if(defined $TypeAttr{"Header"}) 1502 { 1503 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/) 1504 { # support for SUSE 11.2 1505 # integer_type has srcp dump{1-2}.i 1506 delete($TypeAttr{"Header"}); 1507 } 1508 } 1509 } 1510 1511 my $Tmpl = undef; 1512 1513 if(defined $TemplateInstance{$V}{"Type"}{$TypeId}) 1514 { 1515 $Tmpl = $BasicTemplate{$V}{$TypeId}; 1516 1517 if(my @TParams = getTParams($TypeId, "Type")) 1518 { 1519 foreach my $Pos (0 .. $#TParams) 1520 { 1521 my $Val = $TParams[$Pos]; 1522 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val; 1523 1524 if(not defined $TypeAttr{"Template"}) 1525 { 1526 my %Base = getBaseType($TemplateInstance{$V}{"Type"}{$TypeId}{$Pos}, $V); 1527 1528 if($Base{"Type"} eq "TemplateParam" 1529 or defined $Base{"Template"}) { 1530 $TypeAttr{"Template"} = 1; 1531 } 1532 } 1533 1534 if($Tmpl) 1535 { 1536 if(my $Arg = $TemplateArg{$V}{$Tmpl}{$Pos}) 1537 { 1538 $TemplateMap{$V}{$TypeId}{$Arg} = $Val; 1539 1540 if($Val eq $Arg) { 1541 $TypeAttr{"Template"} = 1; 1542 } 1543 } 1544 } 1545 } 1546 1547 if($Tmpl) 1548 { 1549 foreach my $Pos (sort {$a<=>$b} keys(%{$TemplateArg{$V}{$Tmpl}})) 1550 { 1551 if($Pos>$#TParams) 1552 { 1553 my $Arg = $TemplateArg{$V}{$Tmpl}{$Pos}; 1554 $TemplateMap{$V}{$TypeId}{$Arg} = ""; 1555 } 1556 } 1557 } 1558 } 1559 1560 if($In::Opt{"AddTemplateInstances"}) 1561 { 1562 if($Tmpl) 1563 { 1564 if(my $MainInst = getTreeAttr_Type($Tmpl)) 1565 { 1566 if(not getTreeAttr_Flds($TypeId)) 1567 { 1568 if(my $Flds = getTreeAttr_Flds($MainInst)) { 1569 $LibInfo{$V}{"info"}{$TypeId} .= " flds: \@$Flds "; 1570 } 1571 } 1572 if(not getTreeAttr_Binf($TypeId)) 1573 { 1574 if(my $Binf = getTreeAttr_Binf($MainInst)) { 1575 $LibInfo{$V}{"info"}{$TypeId} .= " binf: \@$Binf "; 1576 } 1577 } 1578 } 1579 } 1580 } 1581 } 1582 1583 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr); 1584 1585 if(my $Size = getSize($TypeId)) 1586 { 1587 $Size = $Size/$BYTE; 1588 $TypeAttr{"Size"} = "$Size"; 1589 } 1590 else 1591 { 1592 if($In::Opt{"ExtraDump"}) 1593 { 1594 if(not defined $TypeAttr{"Memb"} 1595 and not $Tmpl) 1596 { # declaration only 1597 $TypeAttr{"Forward"} = 1; 1598 } 1599 } 1600 } 1601 1602 if($TypeAttr{"Type"} eq "Struct" 1603 and ($StaticFields or detectLang($TypeId))) 1604 { 1605 $TypeAttr{"Type"} = "Class"; 1606 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo() 1607 } 1608 if($TypeAttr{"Type"} eq "Struct" 1609 or $TypeAttr{"Type"} eq "Class") 1610 { 1611 my $Skip = setBaseClasses($TypeId, \%TypeAttr); 1612 if($Skip) { 1613 return {}; 1614 } 1615 } 1616 if(my $Algn = getAlgn($TypeId)) { 1617 $TypeAttr{"Algn"} = $Algn/$BYTE; 1618 } 1619 setSpec($TypeId, \%TypeAttr); 1620 1621 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/) 1622 { 1623 if(not $TypedefToAnon{$TypeId} 1624 and not defined $TemplateInstance{$V}{"Type"}{$TypeId}) 1625 { 1626 if(not isAnon($TypeAttr{"Name"})) { 1627 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"}; 1628 } 1629 } 1630 } 1631 1632 $TypeAttr{"Tid"} = $TypeId; 1633 1634 if(my $VTable = $In::ABI{$V}{"ClassVTable_Content"}{$TypeAttr{"Name"}}) 1635 { 1636 my @Entries = split(/\n/, $VTable); 1637 foreach (1 .. $#Entries) 1638 { 1639 my $Entry = $Entries[$_]; 1640 if($Entry=~/\A(\d+)\s+(.+)\Z/) { 1641 $TypeAttr{"VTable"}{$1} = simplifyVTable($2); 1642 } 1643 } 1644 } 1645 1646 if($TypeAttr{"Type"} eq "Enum") 1647 { 1648 if(not $TypeAttr{"NameSpace"}) 1649 { 1650 foreach my $Pos (keys(%{$TypeAttr{"Memb"}})) 1651 { 1652 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"}; 1653 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"}; 1654 $In::ABI{$V}{"EnumConstants"}{$MName} = { 1655 "Value"=>$MVal, 1656 "Header"=>$TypeAttr{"Header"} 1657 }; 1658 if(isAnon($TypeAttr{"Name"})) 1659 { 1660 if($In::Opt{"ExtraDump"} or isTargetHeader($TypeAttr{"Header"}, $V) 1661 or isTargetSource($TypeAttr{"Source"}, $V)) 1662 { 1663 $In::ABI{$V}{"Constants"}{$MName} = { 1664 "Value" => $MVal, 1665 "Header" => $TypeAttr{"Header"} 1666 }; 1667 } 1668 } 1669 } 1670 } 1671 } 1672 if($In::Opt{"ExtraDump"}) 1673 { 1674 if(defined $TypedefToAnon{$TypeId}) { 1675 $TypeAttr{"AnonTypedef"} = 1; 1676 } 1677 } 1678 1679 return \%TypeAttr; 1680} 1681 1682sub setAnonTypedef_All() 1683{ 1684 foreach my $InfoId (keys(%{$LibInfo{$V}{"info"}})) 1685 { 1686 if($LibInfo{$V}{"info_type"}{$InfoId} eq "type_decl") 1687 { 1688 if(isAnon(getNameByInfo($InfoId))) { 1689 $TypedefToAnon{getTypeId($InfoId)} = 1; 1690 } 1691 } 1692 } 1693} 1694 1695sub setTemplateParams_All() 1696{ 1697 foreach (sort {$a<=>$b} keys(%{$LibInfo{$V}{"info"}})) 1698 { 1699 if($LibInfo{$V}{"info_type"}{$_} eq "template_decl") { 1700 setTemplateParams($_); 1701 } 1702 } 1703} 1704 1705sub setTemplateParams($) 1706{ 1707 my $Tid = getTypeId($_[0]); 1708 if(my $Info = $LibInfo{$V}{"info"}{$_[0]}) 1709 { 1710 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /) 1711 { 1712 my $TmplInst_Id = $2; 1713 setTemplateInstParams($_[0], $TmplInst_Id); 1714 while($TmplInst_Id = getNextElem($TmplInst_Id)) { 1715 setTemplateInstParams($_[0], $TmplInst_Id); 1716 } 1717 } 1718 1719 $BasicTemplate{$V}{$Tid} = $_[0]; 1720 1721 if(my $Prms = getTreeAttr_Prms($_[0])) 1722 { 1723 if(my $Valu = getTreeAttr_Valu($Prms)) 1724 { 1725 my $Vector = getTreeVec($Valu); 1726 foreach my $Pos (sort {$a<=>$b} keys(%{$Vector})) 1727 { 1728 if(my $Val = getTreeAttr_Valu($Vector->{$Pos})) 1729 { 1730 if(my $Name = getNameByInfo($Val)) 1731 { 1732 $TemplateArg{$V}{$_[0]}{$Pos} = $Name; 1733 if($LibInfo{$V}{"info_type"}{$Val} eq "parm_decl") { 1734 $TemplateInstance{$V}{"Type"}{$Tid}{$Pos} = $Val; 1735 } 1736 else { 1737 $TemplateInstance{$V}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val); 1738 } 1739 } 1740 } 1741 } 1742 } 1743 } 1744 } 1745 if(my $TypeId = getTreeAttr_Type($_[0])) 1746 { 1747 if(my $IType = $LibInfo{$V}{"info_type"}{$TypeId}) 1748 { 1749 if($IType eq "record_type") { 1750 $TemplateDecl{$V}{$TypeId} = 1; 1751 } 1752 } 1753 } 1754} 1755 1756sub setTemplateInstParams($$) 1757{ 1758 my ($Tmpl, $Inst) = @_; 1759 1760 if(my $Info = $LibInfo{$V}{"info"}{$Inst}) 1761 { 1762 my ($Params_InfoId, $ElemId) = (); 1763 if($Info=~/purp[ ]*:[ ]*@(\d+) /) { 1764 $Params_InfoId = $1; 1765 } 1766 if($Info=~/valu[ ]*:[ ]*@(\d+) /) { 1767 $ElemId = $1; 1768 } 1769 if($Params_InfoId and $ElemId) 1770 { 1771 my $Params_Info = $LibInfo{$V}{"info"}{$Params_InfoId}; 1772 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /) 1773 { 1774 my ($PPos, $PTypeId) = ($1, $2); 1775 if(my $PType = $LibInfo{$V}{"info_type"}{$PTypeId}) 1776 { 1777 if($PType eq "template_type_parm") { 1778 $TemplateDecl{$V}{$ElemId} = 1; 1779 } 1780 } 1781 if($LibInfo{$V}{"info_type"}{$ElemId} eq "function_decl") 1782 { # functions 1783 $TemplateInstance{$V}{"Func"}{$ElemId}{$PPos} = $PTypeId; 1784 $BasicTemplate{$V}{$ElemId} = $Tmpl; 1785 } 1786 else 1787 { # types 1788 $TemplateInstance{$V}{"Type"}{$ElemId}{$PPos} = $PTypeId; 1789 $BasicTemplate{$V}{$ElemId} = $Tmpl; 1790 } 1791 } 1792 } 1793 } 1794} 1795 1796sub getTypeDeclId($) 1797{ 1798 my $Id = $_[0]; 1799 if($Id) 1800 { 1801 if(defined $Cache{"getTypeDeclId"}{$V}{$Id}) { 1802 return $Cache{"getTypeDeclId"}{$V}{$Id}; 1803 } 1804 if(my $Info = $LibInfo{$V}{"info"}{$Id}) 1805 { 1806 if($Info=~/name[ ]*:[ ]*@(\d+)/) { 1807 return ($Cache{"getTypeDeclId"}{$V}{$Id} = $1); 1808 } 1809 } 1810 } 1811 return ($Cache{"getTypeDeclId"}{$V}{$Id} = 0); 1812} 1813 1814sub addMissedTypes_Pre() 1815{ 1816 my %MissedTypes = (); 1817 foreach my $MissedTDid (sort {$a<=>$b} keys(%{$LibInfo{$V}{"info"}})) 1818 { # detecting missed typedefs 1819 if($LibInfo{$V}{"info_type"}{$MissedTDid} eq "type_decl") 1820 { 1821 my $TypeId = getTreeAttr_Type($MissedTDid); 1822 next if(not $TypeId); 1823 my $TypeType = getTypeType($TypeId); 1824 if($TypeType eq "Unknown") 1825 { # template_type_parm 1826 next; 1827 } 1828 my $TypeDeclId = getTypeDeclId($TypeId); 1829 if($TypeDeclId eq $MissedTDid) { 1830 next; 1831 } 1832 if(my $TypedefName = getNameByInfo($MissedTDid)) 1833 { 1834 if($TypedefName eq "__float80" or isAnon($TypedefName)) { 1835 next; 1836 } 1837 1838 if(not $TypeDeclId 1839 or getNameByInfo($TypeDeclId) ne $TypedefName) { 1840 $MissedTypes{$V}{$TypeId}{$MissedTDid} = 1; 1841 } 1842 } 1843 } 1844 } 1845 my %AddTypes = (); 1846 foreach my $Tid (sort {$a<=>$b} keys(%{$MissedTypes{$V}})) 1847 { # add missed typedefs 1848 my @Missed = sort {$a<=>$b} keys(%{$MissedTypes{$V}{$Tid}}); 1849 if(not @Missed or $#Missed>=1) { 1850 next; 1851 } 1852 my $MissedTDid = $Missed[0]; 1853 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid); 1854 if(not $TypedefName) { 1855 next; 1856 } 1857 my $NewId = ++$MAX_ID; 1858 my %MissedInfo = ( # typedef info 1859 "Name" => $TypedefName, 1860 "NameSpace" => $TypedefNS, 1861 "BaseType" => $Tid, 1862 "Type" => "Typedef", 1863 "Tid" => "$NewId" ); 1864 my ($H, $L) = getLocation($MissedTDid); 1865 $MissedInfo{"Header"} = $H; 1866 $MissedInfo{"Line"} = $L; 1867 if($TypedefName=~/\*|\&|\s/) 1868 { # other types 1869 next; 1870 } 1871 if($TypedefName=~/>(::\w+)+\Z/) 1872 { # QFlags<Qt::DropAction>::enum_type 1873 next; 1874 } 1875 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/) 1876 { # double-check for the name of typedef 1877 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info 1878 next if(not $TName); 1879 if(length($TypedefName)>=length($TName)) 1880 { # too long typedef 1881 next; 1882 } 1883 if($TName=~/\A\Q$TypedefName\E</) { 1884 next; 1885 } 1886 if($TypedefName=~/\A\Q$TName\E/) 1887 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type 1888 next; 1889 } 1890 if(getDepth($TypedefName)==0 and getDepth($TName)!=0) 1891 { # std::_Vector_base and std::vector::_Base 1892 next; 1893 } 1894 } 1895 1896 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo; 1897 1898 # register typedef 1899 $MissedTypedef{$V}{$Tid}{"Tid"} = $MissedInfo{"Tid"}; 1900 $MissedTypedef{$V}{$Tid}{"TDid"} = $MissedTDid; 1901 $TName_Tid{$V}{$TypedefName} = $MissedInfo{"Tid"}; 1902 } 1903 1904 # add missed & remove other 1905 $TypeInfo{$V} = \%AddTypes; 1906 delete($Cache{"getTypeAttr"}{$V}); 1907} 1908 1909sub addMissedTypes_Post() 1910{ 1911 foreach my $BaseId (keys(%{$MissedTypedef{$V}})) 1912 { 1913 if(my $Tid = $MissedTypedef{$V}{$BaseId}{"Tid"}) 1914 { 1915 $TypeInfo{$V}{$Tid}{"Size"} = $TypeInfo{$V}{$BaseId}{"Size"}; 1916 if(my $TName = $TypeInfo{$V}{$Tid}{"Name"}) { 1917 $In::ABI{$V}{"TypedefBase"}{$TName} = $TypeInfo{$V}{$BaseId}{"Name"}; 1918 } 1919 } 1920 } 1921} 1922 1923sub getArraySize($$) 1924{ 1925 my ($TypeId, $BaseName) = @_; 1926 if(my $Size = getSize($TypeId)) 1927 { 1928 my $Elems = $Size/$BYTE; 1929 while($BaseName=~s/\s*\[(\d+)\]//) { 1930 $Elems/=$1; 1931 } 1932 if(my $BasicId = $TName_Tid{$V}{$BaseName}) 1933 { 1934 if(my $BasicSize = $TypeInfo{$V}{$BasicId}{"Size"}) { 1935 $Elems/=$BasicSize; 1936 } 1937 } 1938 return $Elems; 1939 } 1940 return 0; 1941} 1942 1943sub getTParams($$) 1944{ 1945 my ($TypeId, $Kind) = @_; 1946 my @TmplParams = (); 1947 my @Positions = sort {$a<=>$b} keys(%{$TemplateInstance{$V}{$Kind}{$TypeId}}); 1948 foreach my $Pos (@Positions) 1949 { 1950 my $Param_TypeId = $TemplateInstance{$V}{$Kind}{$TypeId}{$Pos}; 1951 my $NodeType = $LibInfo{$V}{"info_type"}{$Param_TypeId}; 1952 if(not $NodeType) 1953 { # typename_type 1954 return (); 1955 } 1956 if($NodeType eq "tree_vec") 1957 { 1958 if($Pos!=$#Positions) 1959 { # select last vector of parameters ( ns<P1>::type<P2> ) 1960 next; 1961 } 1962 } 1963 my @Params = getTemplateParam($Pos, $Param_TypeId); 1964 foreach my $P (@Params) 1965 { 1966 if($P eq "") { 1967 return (); 1968 } 1969 elsif($P ne "\@skip\@") { 1970 @TmplParams = (@TmplParams, $P); 1971 } 1972 } 1973 } 1974 return @TmplParams; 1975} 1976 1977sub getTreeVec($) 1978{ 1979 my %Vector = (); 1980 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 1981 { 1982 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /) 1983 { # string length is N-1 because of the null terminator 1984 $Vector{$1} = $2; 1985 } 1986 } 1987 return \%Vector; 1988} 1989 1990sub getTemplateParam($$) 1991{ 1992 my ($Pos, $Type_Id) = @_; 1993 return () if(not $Type_Id); 1994 my $NodeType = $LibInfo{$V}{"info_type"}{$Type_Id}; 1995 return () if(not $NodeType); 1996 if($NodeType eq "integer_cst") 1997 { # int (1), unsigned (2u), char ('c' as 99), ... 1998 my $CstTid = getTreeAttr_Type($Type_Id); 1999 my $CstType = getTypeAttr($CstTid); # without recursion 2000 my $Num = getNodeIntCst($Type_Id); 2001 if(my $CstSuffix = $ConstantSuffix{$CstType->{"Name"}}) { 2002 return ($Num.$CstSuffix); 2003 } 2004 else { 2005 return ("(".$CstType->{"Name"}.")".$Num); 2006 } 2007 } 2008 elsif($NodeType eq "string_cst") { 2009 return (getNodeStrCst($Type_Id)); 2010 } 2011 elsif($NodeType eq "tree_vec") 2012 { 2013 my $Vector = getTreeVec($Type_Id); 2014 my @Params = (); 2015 foreach my $P1 (sort {$a<=>$b} keys(%{$Vector})) 2016 { 2017 foreach my $P2 (getTemplateParam($Pos, $Vector->{$P1})) { 2018 push(@Params, $P2); 2019 } 2020 } 2021 return @Params; 2022 } 2023 elsif($NodeType eq "parm_decl") 2024 { 2025 return (getNameByInfo($Type_Id)); 2026 } 2027 else 2028 { 2029 my $ParamAttr = getTypeAttr($Type_Id); 2030 my $PName = $ParamAttr->{"Name"}; 2031 if(not $PName) { 2032 return (); 2033 } 2034 if($PName=~/\>/) 2035 { 2036 if(my $Cover = coverStdcxxTypedef($PName)) { 2037 $PName = $Cover; 2038 } 2039 } 2040 if($Pos>=1 and 2041 isDefaultStd($PName)) 2042 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> > 2043 # template<typename _Key, typename _Compare = std::less<_Key> 2044 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> > 2045 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> > 2046 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> > 2047 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> > 2048 return ("\@skip\@"); 2049 } 2050 return ($PName); 2051 } 2052} 2053 2054sub coverStdcxxTypedef($) 2055{ 2056 my $TypeName = $_[0]; 2057 if(my @Covers = sort {length($a)<=>length($b)} 2058 sort keys(%{$StdCxxTypedef{$V}{$TypeName}})) 2059 { # take the shortest typedef 2060 # FIXME: there may be more than 2061 # one typedefs to the same type 2062 return $Covers[0]; 2063 } 2064 my $Covered = $TypeName; 2065 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){}; 2066 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$V}{$TypeName}})) 2067 { 2068 if(my $Cover = $Covers[0]) 2069 { 2070 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g; 2071 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g; 2072 } 2073 } 2074 return formatName($Covered, "T"); 2075} 2076 2077sub getNodeIntCst($) 2078{ 2079 my $CstId = $_[0]; 2080 my $CstTypeId = getTreeAttr_Type($CstId); 2081 if($EnumMembName_Id{$V}{$CstId}) { 2082 return $EnumMembName_Id{$V}{$CstId}; 2083 } 2084 elsif((my $Value = getTreeValue($CstId)) ne "") 2085 { 2086 if($Value eq "0") 2087 { 2088 if($LibInfo{$V}{"info_type"}{$CstTypeId} eq "boolean_type") { 2089 return "false"; 2090 } 2091 else { 2092 return "0"; 2093 } 2094 } 2095 elsif($Value eq "1") 2096 { 2097 if($LibInfo{$V}{"info_type"}{$CstTypeId} eq "boolean_type") { 2098 return "true"; 2099 } 2100 else { 2101 return "1"; 2102 } 2103 } 2104 else { 2105 return $Value; 2106 } 2107 } 2108 return ""; 2109} 2110 2111sub getNodeStrCst($) 2112{ 2113 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 2114 { 2115 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/) 2116 { 2117 if($LibInfo{$V}{"info_type"}{$_[0]} eq "string_cst") 2118 { # string length is N-1 because of the null terminator 2119 return substr($1, 0, $2-1); 2120 } 2121 else 2122 { # identifier_node 2123 return substr($1, 0, $2); 2124 } 2125 } 2126 } 2127 return ""; 2128} 2129 2130sub getMemPtrAttr($$$) 2131{ # function, method and field pointers 2132 my ($PtrId, $TypeId, $Type) = @_; 2133 my $MemInfo = $LibInfo{$V}{"info"}{$PtrId}; 2134 if($Type eq "FieldPtr") { 2135 $MemInfo = $LibInfo{$V}{"info"}{$TypeId}; 2136 } 2137 my $MemInfo_Type = $LibInfo{$V}{"info_type"}{$PtrId}; 2138 my $MemPtrName = ""; 2139 my %TypeAttr = ("Size"=>$In::ABI{$V}{"WordSize"}, "Type"=>$Type, "Tid"=>$TypeId); 2140 if($Type eq "MethodPtr") 2141 { # size of "method pointer" may be greater than WORD size 2142 if(my $Size = getSize($TypeId)) 2143 { 2144 $Size/=$BYTE; 2145 $TypeAttr{"Size"} = "$Size"; 2146 } 2147 } 2148 if(my $Algn = getAlgn($TypeId)) { 2149 $TypeAttr{"Algn"} = $Algn/$BYTE; 2150 } 2151 # Return 2152 if($Type eq "FieldPtr") 2153 { 2154 my $ReturnAttr = getTypeAttr($PtrId); 2155 if($ReturnAttr->{"Name"}) { 2156 $MemPtrName .= $ReturnAttr->{"Name"}; 2157 } 2158 $TypeAttr{"Return"} = $PtrId; 2159 } 2160 else 2161 { 2162 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /) 2163 { 2164 my $ReturnTypeId = $1; 2165 my $ReturnAttr = getTypeAttr($ReturnTypeId); 2166 if(not $ReturnAttr->{"Name"}) 2167 { # templates 2168 return {}; 2169 } 2170 $MemPtrName .= $ReturnAttr->{"Name"}; 2171 $TypeAttr{"Return"} = $ReturnTypeId; 2172 } 2173 } 2174 # Class 2175 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /) 2176 { 2177 $TypeAttr{"Class"} = $2; 2178 my $ClassAttr = getTypeAttr($TypeAttr{"Class"}); 2179 if($ClassAttr->{"Name"}) { 2180 $MemPtrName .= " (".$ClassAttr->{"Name"}."\:\:*)"; 2181 } 2182 else { 2183 $MemPtrName .= " (*)"; 2184 } 2185 } 2186 else { 2187 $MemPtrName .= " (*)"; 2188 } 2189 # Parameters 2190 if($Type eq "FuncPtr" 2191 or $Type eq "MethodPtr") 2192 { 2193 my @ParamTypeName = (); 2194 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /) 2195 { 2196 my $PTypeInfoId = $1; 2197 my ($Pos, $PPos) = (0, 0); 2198 while($PTypeInfoId) 2199 { 2200 my $PTypeInfo = $LibInfo{$V}{"info"}{$PTypeInfoId}; 2201 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /) 2202 { 2203 my $PTypeId = $1; 2204 my $ParamAttr = getTypeAttr($PTypeId); 2205 if(not $ParamAttr->{"Name"}) 2206 { # templates (template_type_parm), etc. 2207 return {}; 2208 } 2209 if($ParamAttr->{"Name"} eq "void") { 2210 last; 2211 } 2212 if($Pos!=0 or $Type ne "MethodPtr") 2213 { 2214 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId; 2215 push(@ParamTypeName, $ParamAttr->{"Name"}); 2216 } 2217 if($PTypeInfoId = getNextElem($PTypeInfoId)) { 2218 $Pos+=1; 2219 } 2220 else { 2221 last; 2222 } 2223 } 2224 else { 2225 last; 2226 } 2227 } 2228 } 2229 $MemPtrName .= " (".join(", ", @ParamTypeName).")"; 2230 } 2231 $TypeAttr{"Name"} = formatName($MemPtrName, "T"); 2232 return \%TypeAttr; 2233} 2234 2235sub getTreeTypeName($) 2236{ 2237 my $TypeId = $_[0]; 2238 if(my $Info = $LibInfo{$V}{"info"}{$TypeId}) 2239 { 2240 if($LibInfo{$V}{"info_type"}{$_[0]} eq "integer_type") 2241 { 2242 if(my $Name = getNameByInfo($TypeId)) 2243 { # bit_size_type 2244 return $Name; 2245 } 2246 elsif($Info=~/unsigned/) { 2247 return "unsigned int"; 2248 } 2249 else { 2250 return "int"; 2251 } 2252 } 2253 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) { 2254 return getNameByInfo($1); 2255 } 2256 } 2257 return ""; 2258} 2259 2260sub isFuncPtr($) 2261{ 2262 my $Ptd = pointTo($_[0]); 2263 return 0 if(not $Ptd); 2264 if(my $Info = $LibInfo{$V}{"info"}{$_[0]}) 2265 { 2266 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) { 2267 return 0; 2268 } 2269 } 2270 if(my $InfoT1 = $LibInfo{$V}{"info_type"}{$_[0]} 2271 and my $InfoT2 = $LibInfo{$V}{"info_type"}{$Ptd}) 2272 { 2273 if($InfoT1 eq "pointer_type" 2274 and $InfoT2 eq "function_type") { 2275 return 1; 2276 } 2277 } 2278 return 0; 2279} 2280 2281sub isMethodPtr($) 2282{ 2283 my $Ptd = pointTo($_[0]); 2284 return 0 if(not $Ptd); 2285 if(my $Info = $LibInfo{$V}{"info"}{$_[0]}) 2286 { 2287 if($LibInfo{$V}{"info_type"}{$_[0]} eq "record_type" 2288 and $LibInfo{$V}{"info_type"}{$Ptd} eq "method_type" 2289 and $Info=~/ ptrmem /) { 2290 return 1; 2291 } 2292 } 2293 return 0; 2294} 2295 2296sub isFieldPtr($) 2297{ 2298 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 2299 { 2300 if($LibInfo{$V}{"info_type"}{$_[0]} eq "offset_type" 2301 and $Info=~/ ptrmem /) { 2302 return 1; 2303 } 2304 } 2305 return 0; 2306} 2307 2308sub pointTo($) 2309{ 2310 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 2311 { 2312 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) { 2313 return $1; 2314 } 2315 } 2316 return ""; 2317} 2318 2319sub getTypeTypeByTypeId($) 2320{ 2321 my $TypeId = $_[0]; 2322 if(my $TType = $LibInfo{$V}{"info_type"}{$TypeId}) 2323 { 2324 my $NType = $NodeType{$TType}; 2325 if($NType eq "Intrinsic") { 2326 return $NType; 2327 } 2328 elsif(isFuncPtr($TypeId)) { 2329 return "FuncPtr"; 2330 } 2331 elsif(isMethodPtr($TypeId)) { 2332 return "MethodPtr"; 2333 } 2334 elsif(isFieldPtr($TypeId)) { 2335 return "FieldPtr"; 2336 } 2337 elsif($NType ne "Other") { 2338 return $NType; 2339 } 2340 } 2341 return "Unknown"; 2342} 2343 2344sub getQual($) 2345{ 2346 my $TypeId = $_[0]; 2347 if(my $Info = $LibInfo{$V}{"info"}{$TypeId}) 2348 { 2349 my ($Qual, $To) = (); 2350 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) { 2351 $Qual = $UnQual{$1}; 2352 } 2353 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) { 2354 $To = $1; 2355 } 2356 if($Qual and $To) { 2357 return ($Qual, $To); 2358 } 2359 } 2360 return (); 2361} 2362 2363sub getQualType($) 2364{ 2365 if($_[0] eq "const volatile") { 2366 return "ConstVolatile"; 2367 } 2368 return ucfirst($_[0]); 2369} 2370 2371sub getTypeType($) 2372{ 2373 my $TypeId = $_[0]; 2374 my $TypeDeclId = getTypeDeclId($TypeId); 2375 if(defined $MissedTypedef{$V}{$TypeId}) 2376 { # support for old GCC versions 2377 if($MissedTypedef{$V}{$TypeId}{"TDid"} eq $TypeDeclId) { 2378 return "Typedef"; 2379 } 2380 } 2381 my $Info = $LibInfo{$V}{"info"}{$TypeId}; 2382 my ($Qual, $To) = getQual($TypeId); 2383 if(($Qual or $To) and $TypeDeclId 2384 and (getTypeId($TypeDeclId) ne $TypeId)) 2385 { # qualified types (special) 2386 return getQualType($Qual); 2387 } 2388 elsif(not $MissedBase_R{$V}{$TypeId} 2389 and isTypedef($TypeId)) { 2390 return "Typedef"; 2391 } 2392 elsif($Qual) 2393 { # qualified types 2394 return getQualType($Qual); 2395 } 2396 2397 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) 2398 { # typedef struct { ... } name 2399 $In::ABI{$V}{"TypeTypedef"}{$TypeId} = $1; 2400 } 2401 2402 my $TypeType = getTypeTypeByTypeId($TypeId); 2403 if($TypeType eq "Struct") 2404 { 2405 if($TypeDeclId 2406 and $LibInfo{$V}{"info_type"}{$TypeDeclId} eq "template_decl") { 2407 return "Template"; 2408 } 2409 } 2410 return $TypeType; 2411} 2412 2413sub isTypedef($) 2414{ 2415 if($_[0]) 2416 { 2417 if($LibInfo{$V}{"info_type"}{$_[0]} eq "vector_type") 2418 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16))); 2419 return 0; 2420 } 2421 if(my $Info = $LibInfo{$V}{"info"}{$_[0]}) 2422 { 2423 if(my $TDid = getTypeDeclId($_[0])) 2424 { 2425 if(getTypeId($TDid) eq $_[0] 2426 and getNameByInfo($TDid)) 2427 { 2428 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) { 2429 return $1; 2430 } 2431 } 2432 } 2433 } 2434 } 2435 return 0; 2436} 2437 2438sub selectBaseType($) 2439{ 2440 my $TypeId = $_[0]; 2441 if(defined $MissedTypedef{$V}{$TypeId}) 2442 { # add missed typedefs 2443 if($MissedTypedef{$V}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) { 2444 return ($TypeId, ""); 2445 } 2446 } 2447 my $Info = $LibInfo{$V}{"info"}{$TypeId}; 2448 my $InfoType = $LibInfo{$V}{"info_type"}{$TypeId}; 2449 2450 my $MB_R = $MissedBase_R{$V}{$TypeId}; 2451 my $MB = $MissedBase{$V}{$TypeId}; 2452 2453 my ($Qual, $To) = getQual($TypeId); 2454 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) / 2455 and (getTypeId($1) ne $TypeId) 2456 and (not $MB_R or getTypeId($1) ne $MB_R)) 2457 { # qualified types (special) 2458 return (getTypeId($1), $Qual); 2459 } 2460 elsif($MB) 2461 { # add base 2462 return ($MB, ""); 2463 } 2464 elsif(not $MB_R and my $Bid = isTypedef($TypeId)) 2465 { # typedefs 2466 return ($Bid, ""); 2467 } 2468 elsif($Qual or $To) 2469 { # qualified types 2470 return ($To, $Qual); 2471 } 2472 elsif($InfoType eq "reference_type") 2473 { 2474 if($Info=~/refd[ ]*:[ ]*@(\d+) /) { 2475 return ($1, "&"); 2476 } 2477 } 2478 elsif($InfoType eq "array_type") 2479 { 2480 if($Info=~/elts[ ]*:[ ]*@(\d+) /) { 2481 return ($1, ""); 2482 } 2483 } 2484 elsif($InfoType eq "pointer_type") 2485 { 2486 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) { 2487 return ($1, "*"); 2488 } 2489 } 2490 2491 return (0, ""); 2492} 2493 2494sub detectLang($) 2495{ 2496 my $TypeId = $_[0]; 2497 my $Info = $LibInfo{$V}{"info"}{$TypeId}; 2498 2499 if(checkGcc("8")) 2500 { 2501 if(getTreeAttr_VFld($TypeId)) { 2502 return 1; 2503 } 2504 2505 if(my $Chain = getTreeAttr_Flds($TypeId)) 2506 { 2507 while(1) 2508 { 2509 if($LibInfo{$V}{"info_type"}{$Chain} eq "function_decl") { 2510 return 1; 2511 } 2512 2513 $Chain = getTreeAttr_Chain($Chain); 2514 2515 if(not $Chain) { 2516 last; 2517 } 2518 } 2519 } 2520 } 2521 2522 if(checkGcc("4")) 2523 { # GCC 4 fncs-node points to only non-artificial methods 2524 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /); 2525 } 2526 else 2527 { # GCC 3 2528 my $Fncs = getTreeAttrFncs($TypeId); 2529 while($Fncs) 2530 { 2531 if($LibInfo{$V}{"info"}{$Fncs}!~/artificial/) { 2532 return 1; 2533 } 2534 $Fncs = getTreeAttr_Chan($Fncs); 2535 } 2536 } 2537 2538 return 0; 2539} 2540 2541sub setSpec($$) 2542{ 2543 my ($TypeId, $TypeAttr) = @_; 2544 my $Info = $LibInfo{$V}{"info"}{$TypeId}; 2545 if($Info=~/\s+spec\s+/) { 2546 $TypeAttr->{"Spec"} = 1; 2547 } 2548} 2549 2550sub setBaseClasses($$) 2551{ 2552 my ($TypeId, $TypeAttr) = @_; 2553 my $Info = $LibInfo{$V}{"info"}{$TypeId}; 2554 if(my $Binf = getTreeAttr_Binf($TypeId)) 2555 { 2556 my $Info = $LibInfo{$V}{"info"}{$Binf}; 2557 my $Pos = 0; 2558 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //) 2559 { 2560 my ($Access, $BInfoId) = ($1, $2); 2561 my $ClassId = getBinfClassId($BInfoId); 2562 2563 if($ClassId eq $TypeId) 2564 { # class A<N>:public A<N-1> 2565 next; 2566 } 2567 2568 my $CType = $LibInfo{$V}{"info_type"}{$ClassId}; 2569 if(not $CType or $CType eq "template_type_parm" 2570 or $CType eq "typename_type") 2571 { # skip 2572 # return 1; 2573 } 2574 my $BaseInfo = $LibInfo{$V}{"info"}{$BInfoId}; 2575 if($Access=~/prot/) { 2576 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected"; 2577 } 2578 elsif($Access=~/priv/) { 2579 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private"; 2580 } 2581 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos"; 2582 if($BaseInfo=~/virt/) 2583 { # virtual base 2584 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1; 2585 } 2586 2587 $Pos += 1; 2588 } 2589 } 2590 return 0; 2591} 2592 2593sub getBinfClassId($) 2594{ 2595 my $Info = $LibInfo{$V}{"info"}{$_[0]}; 2596 if($Info=~/type[ ]*:[ ]*@(\d+) /) { 2597 return $1; 2598 } 2599 2600 return ""; 2601} 2602 2603sub isInternal($) 2604{ 2605 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 2606 { 2607 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) 2608 { 2609 if($LibInfo{$V}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/) 2610 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL* 2611 return 1; 2612 } 2613 } 2614 } 2615 return 0; 2616} 2617 2618sub getDataVal($$) 2619{ 2620 my ($InfoId, $TypeId) = @_; 2621 if(my $Info = $LibInfo{$V}{"info"}{$InfoId}) 2622 { 2623 if($Info=~/init[ ]*:[ ]*@(\d+) /) 2624 { 2625 if(defined $LibInfo{$V}{"info_type"}{$1} 2626 and $LibInfo{$V}{"info_type"}{$1} eq "nop_expr") 2627 { 2628 if(my $Nop = getTreeAttr_Op($1)) 2629 { 2630 if(defined $LibInfo{$V}{"info_type"}{$Nop} 2631 and $LibInfo{$V}{"info_type"}{$Nop} eq "addr_expr") 2632 { 2633 if(my $Addr = getTreeAttr_Op($1)) { 2634 return getInitVal($Addr, $TypeId); 2635 } 2636 } 2637 } 2638 } 2639 else { 2640 return getInitVal($1, $TypeId); 2641 } 2642 } 2643 } 2644 return undef; 2645} 2646 2647sub getInitVal($$) 2648{ 2649 my ($InfoId, $TypeId) = @_; 2650 if(my $Info = $LibInfo{$V}{"info"}{$InfoId}) 2651 { 2652 if(my $InfoType = $LibInfo{$V}{"info_type"}{$InfoId}) 2653 { 2654 if($InfoType eq "integer_cst") 2655 { 2656 my $Val = getNodeIntCst($InfoId); 2657 if($TypeId and $TypeInfo{$V}{$TypeId}{"Name"}=~/\Achar(| const)\Z/) 2658 { # characters 2659 $Val = chr($Val); 2660 } 2661 return $Val; 2662 } 2663 elsif($InfoType eq "string_cst") { 2664 return getNodeStrCst($InfoId); 2665 } 2666 elsif($InfoType eq "var_decl") 2667 { 2668 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) { 2669 return $Name; 2670 } 2671 } 2672 } 2673 } 2674 return undef; 2675} 2676 2677sub setClassAndNs($) 2678{ 2679 my $InfoId = $_[0]; 2680 my $SInfo = $SymbolInfo{$V}{$InfoId}; 2681 2682 if(my $Info = $LibInfo{$V}{"info"}{$InfoId}) 2683 { 2684 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) 2685 { 2686 my $NSInfoId = $1; 2687 if(my $InfoType = $LibInfo{$V}{"info_type"}{$NSInfoId}) 2688 { 2689 if($InfoType eq "namespace_decl") { 2690 $SInfo->{"NameSpace"} = getNameSpace($InfoId); 2691 } 2692 elsif($InfoType eq "record_type") { 2693 $SInfo->{"Class"} = $NSInfoId; 2694 } 2695 } 2696 } 2697 } 2698 if($SInfo->{"Class"} 2699 or $SInfo->{"NameSpace"}) 2700 { 2701 if($In::ABI{$V}{"Language"} ne "C++") 2702 { # skip 2703 return 1; 2704 } 2705 } 2706 2707 return 0; 2708} 2709 2710sub isInline($) 2711{ # "body: undefined" in the tree 2712 # -fkeep-inline-functions GCC option should be specified 2713 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 2714 { 2715 if($Info=~/ undefined /i) { 2716 return 0; 2717 } 2718 } 2719 return 1; 2720} 2721 2722sub hasThrow($) 2723{ 2724 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 2725 { 2726 if($Info=~/type[ ]*:[ ]*@(\d+) /) { 2727 return getTreeAttr_Unql($1, "unql"); 2728 } 2729 } 2730 return 1; 2731} 2732 2733sub getTypeId($) 2734{ 2735 my $Id = $_[0]; 2736 if($Id and my $Info = $LibInfo{$V}{"info"}{$Id}) 2737 { 2738 if($Info=~/type[ ]*:[ ]*@(\d+) /) { 2739 return $1; 2740 } 2741 } 2742 return ""; 2743} 2744 2745sub setTypeMemb($$) 2746{ 2747 my ($TypeId, $TypeAttr) = @_; 2748 my $TypeType = $TypeAttr->{"Type"}; 2749 my ($Pos, $UnnamedPos) = (0, 0); 2750 my $StaticFields = 0; 2751 if($TypeType eq "Enum") 2752 { 2753 my $MInfoId = getTreeAttr_Csts($TypeId); 2754 while($MInfoId) 2755 { 2756 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId); 2757 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId)); 2758 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName; 2759 if(my $EMId = getTreeAttr_Valu($MInfoId)) 2760 { 2761 if($TypeAttr->{"NameSpace"}) { 2762 $EnumMembName_Id{$V}{$EMId} = $TypeAttr->{"NameSpace"}."::".$MembName; 2763 } 2764 else { 2765 $EnumMembName_Id{$V}{$EMId} = $MembName; 2766 } 2767 } 2768 $MInfoId = getNextElem($MInfoId); 2769 $Pos += 1; 2770 } 2771 } 2772 elsif($TypeType=~/\A(Struct|Class|Union)\Z/) 2773 { 2774 my $MInfoId = getTreeAttr_Flds($TypeId); 2775 while($MInfoId) 2776 { 2777 my $IType = $LibInfo{$V}{"info_type"}{$MInfoId}; 2778 my $MInfo = $LibInfo{$V}{"info"}{$MInfoId}; 2779 if(not $IType or $IType ne "field_decl") 2780 { # search for fields, skip other stuff in the declaration 2781 2782 if($IType eq "var_decl") 2783 { # static field 2784 $StaticFields = 1; 2785 } 2786 2787 $MInfoId = getNextElem($MInfoId); 2788 next; 2789 } 2790 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId)); 2791 if(index($StructMembName, "_vptr.")==0) 2792 { # virtual tables 2793 $StructMembName = "_vptr"; 2794 } 2795 if(not $StructMembName) 2796 { # unnamed fields 2797 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1) 2798 { 2799 my $UnnamedTid = getTreeAttr_Type($MInfoId); 2800 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid)); 2801 if(isAnon($UnnamedTName)) 2802 { # rename unnamed fields to unnamed0, unnamed1, ... 2803 $StructMembName = "unnamed".($UnnamedPos++); 2804 } 2805 } 2806 } 2807 if(not $StructMembName) 2808 { # unnamed fields and base classes 2809 $MInfoId = getNextElem($MInfoId); 2810 next; 2811 } 2812 my $MembTypeId = getTreeAttr_Type($MInfoId); 2813 if(defined $MissedTypedef{$V}{$MembTypeId}) 2814 { 2815 if(my $AddedTid = $MissedTypedef{$V}{$MembTypeId}{"Tid"}) { 2816 $MembTypeId = $AddedTid; 2817 } 2818 } 2819 2820 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId; 2821 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName; 2822 if((my $Access = getTreeAccess($MInfoId)) ne "public") 2823 { # marked only protected and private, public by default 2824 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access; 2825 } 2826 if($MInfo=~/spec:\s*mutable /) 2827 { # mutable fields 2828 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1; 2829 } 2830 if(my $Algn = getAlgn($MInfoId)) { 2831 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn; 2832 } 2833 if(my $BFSize = getBitField($MInfoId)) 2834 { # in bits 2835 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize; 2836 } 2837 else 2838 { # in bytes 2839 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1) 2840 { # template 2841 delete($TypeAttr->{"Memb"}{$Pos}{"algn"}); 2842 } 2843 else { 2844 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE; 2845 } 2846 } 2847 2848 $MInfoId = getNextElem($MInfoId); 2849 $Pos += 1; 2850 } 2851 } 2852 2853 return $StaticFields; 2854} 2855 2856sub setFuncParams($) 2857{ 2858 my $InfoId = $_[0]; 2859 my $ParamInfoId = getTreeAttr_Args($InfoId); 2860 2861 my $FType = getFuncType($InfoId); 2862 my $SInfo = $SymbolInfo{$V}{$InfoId}; 2863 2864 if($FType eq "Method") 2865 { # check type of "this" pointer 2866 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId); 2867 if(my $ObjectName = $TypeInfo{$V}{$ObjectTypeId}{"Name"}) 2868 { 2869 if($ObjectName=~/\bconst(| volatile)\*const\b/) { 2870 $SInfo->{"Const"} = 1; 2871 } 2872 if($ObjectName=~/\bvolatile\b/) { 2873 $SInfo->{"Volatile"} = 1; 2874 } 2875 } 2876 else 2877 { # skip 2878 return 1; 2879 } 2880 # skip "this"-parameter 2881 # $ParamInfoId = getNextElem($ParamInfoId); 2882 } 2883 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1); 2884 while($ParamInfoId) 2885 { # formal args 2886 my $ParamTypeId = getTreeAttr_Type($ParamInfoId); 2887 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId)); 2888 if(not $ParamName) 2889 { # unnamed 2890 $ParamName = "p".($PPos+1); 2891 } 2892 if(defined $MissedTypedef{$V}{$ParamTypeId}) 2893 { 2894 if(my $AddedTid = $MissedTypedef{$V}{$ParamTypeId}{"Tid"}) { 2895 $ParamTypeId = $AddedTid; 2896 } 2897 } 2898 my $PType = $TypeInfo{$V}{$ParamTypeId}{"Type"}; 2899 if(not $PType or $PType eq "Unknown") { 2900 return 1; 2901 } 2902 my $PTName = $TypeInfo{$V}{$ParamTypeId}{"Name"}; 2903 if(not $PTName) { 2904 return 1; 2905 } 2906 if($PTName eq "void") { 2907 last; 2908 } 2909 if($ParamName eq "__vtt_parm" 2910 and $TypeInfo{$V}{$ParamTypeId}{"Name"} eq "void const**") 2911 { 2912 $Vtt_Pos = $Pos; 2913 $ParamInfoId = getNextElem($ParamInfoId); 2914 next; 2915 } 2916 $SInfo->{"Param"}{$Pos}{"type"} = $ParamTypeId; 2917 2918 if(my %Base = getBaseType($ParamTypeId, $V)) 2919 { 2920 if(defined $Base{"Template"}) { 2921 return 1; 2922 } 2923 } 2924 2925 $SInfo->{"Param"}{$Pos}{"name"} = $ParamName; 2926 if(my $Algn = getAlgn($ParamInfoId)) { 2927 $SInfo->{"Param"}{$Pos}{"algn"} = $Algn/$BYTE; 2928 } 2929 if($LibInfo{$V}{"info"}{$ParamInfoId}=~/spec:\s*register /) 2930 { # foo(register type arg) 2931 $SInfo->{"Param"}{$Pos}{"reg"} = 1; 2932 } 2933 $ParamInfoId = getNextElem($ParamInfoId); 2934 $Pos += 1; 2935 if($ParamName ne "this" or $FType ne "Method") { 2936 $PPos += 1; 2937 } 2938 } 2939 if(setFuncArgs($InfoId, $Vtt_Pos)) { 2940 $SInfo->{"Param"}{$Pos}{"type"} = "-1"; 2941 } 2942 return 0; 2943} 2944 2945sub setFuncArgs($$) 2946{ 2947 my ($InfoId, $Vtt_Pos) = @_; 2948 my $FuncTypeId = getFuncTypeId($InfoId); 2949 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId); 2950 my $FType = getFuncType($InfoId); 2951 my $SInfo = $SymbolInfo{$V}{$InfoId}; 2952 2953 if($FType eq "Method") 2954 { 2955 # skip "this"-parameter 2956 # $ParamListElemId = getNextElem($ParamListElemId); 2957 } 2958 if(not $ParamListElemId) 2959 { # foo(...) 2960 return 1; 2961 } 2962 my $HaveVoid = 0; 2963 my ($Pos, $PPos) = (0, 0); 2964 while($ParamListElemId) 2965 { # actual params: may differ from formal args 2966 # formal int*const 2967 # actual: int* 2968 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos) 2969 { 2970 $Vtt_Pos=-1; 2971 $ParamListElemId = getNextElem($ParamListElemId); 2972 next; 2973 } 2974 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId); 2975 if($TypeInfo{$V}{$ParamTypeId}{"Name"} eq "void") 2976 { 2977 $HaveVoid = 1; 2978 last; 2979 } 2980 else 2981 { 2982 if(not defined $SInfo->{"Param"}{$Pos}{"type"}) 2983 { 2984 $SInfo->{"Param"}{$Pos}{"type"} = $ParamTypeId; 2985 if(not $SInfo->{"Param"}{$Pos}{"name"}) 2986 { # unnamed 2987 $SInfo->{"Param"}{$Pos}{"name"} = "p".($PPos+1); 2988 } 2989 } 2990 elsif(my $OldId = $SInfo->{"Param"}{$Pos}{"type"}) 2991 { 2992 if($Pos>0 or getFuncType($InfoId) ne "Method") 2993 { # params 2994 if($OldId ne $ParamTypeId) 2995 { 2996 my %Old_Pure = getPureType($OldId, $V); 2997 my %New_Pure = getPureType($ParamTypeId, $V); 2998 2999 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) { 3000 $SInfo->{"Param"}{$Pos}{"type"} = $ParamTypeId; 3001 } 3002 } 3003 } 3004 } 3005 } 3006 if(my $PurpId = getTreeAttr_Purp($ParamListElemId)) 3007 { # default arguments 3008 if(my $PurpType = $LibInfo{$V}{"info_type"}{$PurpId}) 3009 { 3010 if($PurpType eq "nop_expr") 3011 { # func ( const char* arg = (const char*)(void*)0 ) 3012 $PurpId = getTreeAttr_Op($PurpId); 3013 } 3014 my $Val = getInitVal($PurpId, $ParamTypeId); 3015 if(defined $Val) { 3016 $SInfo->{"Param"}{$Pos}{"default"} = $Val; 3017 } 3018 } 3019 } 3020 $ParamListElemId = getNextElem($ParamListElemId); 3021 if($Pos!=0 or $FType ne "Method") { 3022 $PPos += 1; 3023 } 3024 $Pos += 1; 3025 } 3026 return ($Pos>=1 and not $HaveVoid); 3027} 3028 3029sub getTreeAttr_Chan($) 3030{ 3031 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3032 { 3033 if($Info=~/chan[ ]*:[ ]*@(\d+) /) { 3034 return $1; 3035 } 3036 } 3037 return ""; 3038} 3039 3040sub getTreeAttr_Chain($) 3041{ 3042 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3043 { 3044 if($Info=~/chain[ ]*:[ ]*@(\d+) /) { 3045 return $1; 3046 } 3047 } 3048 return ""; 3049} 3050 3051sub getTreeAttr_Unql($) 3052{ 3053 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3054 { 3055 if($Info=~/unql[ ]*:[ ]*@(\d+) /) { 3056 return $1; 3057 } 3058 } 3059 return ""; 3060} 3061 3062sub getTreeAttr_Scpe($) 3063{ 3064 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3065 { 3066 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) { 3067 return $1; 3068 } 3069 } 3070 return ""; 3071} 3072 3073sub getTreeAttr_Type($) 3074{ 3075 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3076 { 3077 if($Info=~/type[ ]*:[ ]*@(\d+) /) { 3078 return $1; 3079 } 3080 } 3081 return ""; 3082} 3083 3084sub getTreeAttr_Name($) 3085{ 3086 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3087 { 3088 if($Info=~/name[ ]*:[ ]*@(\d+) /) { 3089 return $1; 3090 } 3091 } 3092 return ""; 3093} 3094 3095sub getTreeAttr_Mngl($) 3096{ 3097 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3098 { 3099 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) { 3100 return $1; 3101 } 3102 } 3103 return ""; 3104} 3105 3106sub getTreeAttr_Prms($) 3107{ 3108 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3109 { 3110 if($Info=~/prms[ ]*:[ ]*@(\d+) /) { 3111 return $1; 3112 } 3113 } 3114 return ""; 3115} 3116 3117sub getTreeAttrFncs($) 3118{ 3119 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3120 { 3121 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) { 3122 return $1; 3123 } 3124 } 3125 return ""; 3126} 3127 3128sub getTreeAttr_Csts($) 3129{ 3130 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3131 { 3132 if($Info=~/csts[ ]*:[ ]*@(\d+) /) { 3133 return $1; 3134 } 3135 } 3136 return ""; 3137} 3138 3139sub getTreeAttr_Purp($) 3140{ 3141 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3142 { 3143 if($Info=~/purp[ ]*:[ ]*@(\d+) /) { 3144 return $1; 3145 } 3146 } 3147 return ""; 3148} 3149 3150sub getTreeAttr_Op($) 3151{ 3152 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3153 { 3154 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) { 3155 return $1; 3156 } 3157 } 3158 return ""; 3159} 3160 3161sub getTreeAttr_Valu($) 3162{ 3163 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3164 { 3165 if($Info=~/valu[ ]*:[ ]*@(\d+) /) { 3166 return $1; 3167 } 3168 } 3169 return ""; 3170} 3171 3172sub getTreeAttr_Flds($) 3173{ 3174 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3175 { 3176 if($Info=~/flds[ ]*:[ ]*@(\d+) /) { 3177 return $1; 3178 } 3179 } 3180 return ""; 3181} 3182 3183sub getTreeAttr_VFld($) 3184{ 3185 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3186 { 3187 if($Info=~/vfld[ ]*:[ ]*@(\d+) /) { 3188 return $1; 3189 } 3190 } 3191 return ""; 3192} 3193 3194sub getTreeAttr_Binf($) 3195{ 3196 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3197 { 3198 if($Info=~/binf[ ]*:[ ]*@(\d+) /) { 3199 return $1; 3200 } 3201 } 3202 return ""; 3203} 3204 3205sub getTreeAttr_Args($) 3206{ 3207 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3208 { 3209 if($Info=~/args[ ]*:[ ]*@(\d+) /) { 3210 return $1; 3211 } 3212 } 3213 return ""; 3214} 3215 3216sub getTreeValue($) 3217{ 3218 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3219 { 3220 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) { 3221 return $2; 3222 } 3223 } 3224 return ""; 3225} 3226 3227sub getTreeAccess($) 3228{ 3229 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3230 { 3231 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /) 3232 { 3233 my $Access = $1; 3234 if($Access eq "prot") { 3235 return "protected"; 3236 } 3237 elsif($Access eq "priv") { 3238 return "private"; 3239 } 3240 } 3241 elsif($Info=~/ protected /) 3242 { # support for old GCC versions 3243 return "protected"; 3244 } 3245 elsif($Info=~/ private /) 3246 { # support for old GCC versions 3247 return "private"; 3248 } 3249 } 3250 return "public"; 3251} 3252 3253sub setFuncAccess($) 3254{ 3255 my $Access = getTreeAccess($_[0]); 3256 if($Access eq "protected") { 3257 $SymbolInfo{$V}{$_[0]}{"Protected"} = 1; 3258 } 3259 elsif($Access eq "private") { 3260 $SymbolInfo{$V}{$_[0]}{"Private"} = 1; 3261 } 3262} 3263 3264sub setTypeAccess($$) 3265{ 3266 my ($TypeId, $TypeAttr) = @_; 3267 my $Access = getTreeAccess($TypeId); 3268 if($Access eq "protected") { 3269 $TypeAttr->{"Protected"} = 1; 3270 } 3271 elsif($Access eq "private") { 3272 $TypeAttr->{"Private"} = 1; 3273 } 3274} 3275 3276sub setFuncKind($) 3277{ 3278 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3279 { 3280 if($Info=~/pseudo tmpl/) { 3281 $SymbolInfo{$V}{$_[0]}{"PseudoTemplate"} = 1; 3282 } 3283 elsif($Info=~/ constructor /) { 3284 $SymbolInfo{$V}{$_[0]}{"Constructor"} = 1; 3285 } 3286 elsif($Info=~/ destructor /) { 3287 $SymbolInfo{$V}{$_[0]}{"Destructor"} = 1; 3288 } 3289 } 3290} 3291 3292sub getVirtSpec($) 3293{ 3294 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3295 { 3296 if($Info=~/spec[ ]*:[ ]*pure /) { 3297 return "PureVirt"; 3298 } 3299 elsif($Info=~/spec[ ]*:[ ]*virt /) { 3300 return "Virt"; 3301 } 3302 elsif($Info=~/ pure\s+virtual /) 3303 { # support for old GCC versions 3304 return "PureVirt"; 3305 } 3306 elsif($Info=~/ virtual /) 3307 { # support for old GCC versions 3308 return "Virt"; 3309 } 3310 } 3311 return ""; 3312} 3313 3314sub getFuncLink($) 3315{ 3316 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3317 { 3318 if($Info=~/link[ ]*:[ ]*static /) { 3319 return "Static"; 3320 } 3321 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) { 3322 return $1; 3323 } 3324 } 3325 return ""; 3326} 3327 3328sub getNameSpace($) 3329{ 3330 my $InfoId = $_[0]; 3331 if(my $NSInfoId = getTreeAttr_Scpe($InfoId)) 3332 { 3333 if(my $InfoType = $LibInfo{$V}{"info_type"}{$NSInfoId}) 3334 { 3335 if($InfoType eq "namespace_decl") 3336 { 3337 if($LibInfo{$V}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /) 3338 { 3339 my $NameSpace = getTreeStr($1); 3340 if($NameSpace eq "::") 3341 { # global namespace 3342 return ""; 3343 } 3344 if(my $BaseNameSpace = getNameSpace($NSInfoId)) { 3345 $NameSpace = $BaseNameSpace."::".$NameSpace; 3346 } 3347 $In::ABI{$V}{"NameSpaces"}{$NameSpace} = 1; 3348 return $NameSpace; 3349 } 3350 else { 3351 return ""; 3352 } 3353 } 3354 elsif($InfoType ne "function_decl") 3355 { # inside data type 3356 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId); 3357 return $Name; 3358 } 3359 } 3360 } 3361 return ""; 3362} 3363 3364sub getEnumMembVal($) 3365{ 3366 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3367 { 3368 if($Info=~/valu[ ]*:[ ]*\@(\d+)/) 3369 { 3370 if(my $VInfo = $LibInfo{$V}{"info"}{$1}) 3371 { 3372 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/) 3373 { # in newer versions of GCC the value is in the "const_decl->cnst" node 3374 return getTreeValue($1); 3375 } 3376 else 3377 { # some old versions of GCC (3.3) have the value in the "integer_cst" node 3378 return getTreeValue($1); 3379 } 3380 } 3381 } 3382 } 3383 return ""; 3384} 3385 3386sub getSize($) 3387{ 3388 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3389 { 3390 if($Info=~/size[ ]*:[ ]*\@(\d+)/) { 3391 return getTreeValue($1); 3392 } 3393 } 3394 return 0; 3395} 3396 3397sub getAlgn($) 3398{ 3399 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3400 { 3401 if($Info=~/algn[ ]*:[ ]*(\d+) /) { 3402 return $1; 3403 } 3404 } 3405 return ""; 3406} 3407 3408sub getBitField($) 3409{ 3410 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3411 { 3412 if($Info=~/ bitfield /) { 3413 return getSize($_[0]); 3414 } 3415 } 3416 return 0; 3417} 3418 3419sub getNextElem($) 3420{ 3421 if(my $Chan = getTreeAttr_Chan($_[0])) { 3422 return $Chan; 3423 } 3424 elsif(my $Chain = getTreeAttr_Chain($_[0])) { 3425 return $Chain; 3426 } 3427 return ""; 3428} 3429 3430sub getLocation($) 3431{ 3432 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3433 { 3434 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) { 3435 return (pathFmt($1), $2); 3436 } 3437 } 3438 return (); 3439} 3440 3441sub getNameByInfo($) 3442{ 3443 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3444 { 3445 if($Info=~/name[ ]*:[ ]*@(\d+) /) 3446 { 3447 if(my $NInfo = $LibInfo{$V}{"info"}{$1}) 3448 { 3449 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/) 3450 { # short unsigned int (may include spaces) 3451 my $Str = $1; 3452 if($In::Desc{$V}{"CppMode"} 3453 and index($Str, "c99_")==0 3454 and $Str=~/\Ac99_(.+)\Z/) { 3455 $Str = $1; 3456 } 3457 return $Str; 3458 } 3459 } 3460 } 3461 } 3462 return ""; 3463} 3464 3465sub getTreeStr($) 3466{ 3467 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3468 { 3469 if($Info=~/strg[ ]*:[ ]*([^ ]*)/) 3470 { 3471 my $Str = $1; 3472 if($In::Desc{$V}{"CppMode"} 3473 and index($Str, "c99_")==0 3474 and $Str=~/\Ac99_(.+)\Z/) 3475 { 3476 $Str = $1; 3477 } 3478 return $Str; 3479 } 3480 } 3481 return ""; 3482} 3483 3484sub getFuncShortName($) 3485{ 3486 if(my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3487 { 3488 if(index($Info, " operator ")!=-1) 3489 { 3490 if(index($Info, " conversion ")!=-1) 3491 { 3492 if(my $Rid = $SymbolInfo{$V}{$_[0]}{"Return"}) 3493 { 3494 if(my $RName = $TypeInfo{$V}{$Rid}{"Name"}) { 3495 return "operator ".$RName; 3496 } 3497 } 3498 } 3499 else 3500 { 3501 if($Info=~/ operator[ ]+([a-zA-Z]+) /) 3502 { 3503 if(my $Ind = $OperatorIndication{$1}) { 3504 return "operator".$Ind; 3505 } 3506 elsif(not $UnknownOperator{$1}) 3507 { 3508 printMsg("WARNING", "unknown operator $1"); 3509 $UnknownOperator{$1} = 1; 3510 } 3511 } 3512 } 3513 } 3514 else 3515 { 3516 if($Info=~/name[ ]*:[ ]*@(\d+) /) { 3517 return getTreeStr($1); 3518 } 3519 } 3520 } 3521 return ""; 3522} 3523 3524sub getFuncReturn($) 3525{ 3526 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3527 { 3528 if($Info=~/type[ ]*:[ ]*@(\d+) /) 3529 { 3530 if($LibInfo{$V}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) { 3531 return $1; 3532 } 3533 } 3534 } 3535 return ""; 3536} 3537 3538sub getFuncOrig($) 3539{ 3540 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3541 { 3542 if($Info=~/orig[ ]*:[ ]*@(\d+) /) { 3543 return $1; 3544 } 3545 } 3546 return $_[0]; 3547} 3548 3549sub getFuncType($) 3550{ 3551 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3552 { 3553 if($Info=~/type[ ]*:[ ]*@(\d+) /) 3554 { 3555 if(my $Type = $LibInfo{$V}{"info_type"}{$1}) 3556 { 3557 if($Type eq "method_type") { 3558 return "Method"; 3559 } 3560 elsif($Type eq "function_type") { 3561 return "Function"; 3562 } 3563 else { 3564 return "Other"; 3565 } 3566 } 3567 } 3568 } 3569 return ""; 3570} 3571 3572sub getFuncTypeId($) 3573{ 3574 if($_[0] and my $Info = $LibInfo{$V}{"info"}{$_[0]}) 3575 { 3576 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) { 3577 return $1; 3578 } 3579 } 3580 return 0; 3581} 3582 3583 3584 3585sub guessHeader($) 3586{ 3587 my $InfoId = $_[0]; 3588 my $SInfo = $SymbolInfo{$V}{$InfoId}; 3589 3590 my $ShortName = $SInfo->{"ShortName"}; 3591 my $ClassName = ""; 3592 if(my $ClassId = $SInfo->{"Class"}) { 3593 $ClassName = getShortClass($ClassId, $V); 3594 } 3595 my $Header = $SInfo->{"Header"}; 3596 3597 if(my $HPath = $In::ABI{$V}{"SymbolHeader"}{$ClassName}{$ShortName}) 3598 { 3599 if(getFilename($HPath) eq $Header) 3600 { 3601 my $HDir = getFilename(getDirname($HPath)); 3602 if($HDir ne "include" 3603 and $HDir=~/\A[a-z]+\Z/i) { 3604 return join_P($HDir, $Header); 3605 } 3606 } 3607 } 3608 return $Header; 3609} 3610 3611sub linkWithSymbol($) 3612{ # link symbols from shared libraries 3613 # with the symbols from header files 3614 my $InfoId = $_[0]; 3615 3616 if($In::Opt{"Target"} eq "windows") 3617 { # link MS C++ symbols from library with GCC symbols from headers 3618 if(my $Mangled1 = getMangled_MSVC(modelUnmangled($InfoId, "MSVC", $V), $V)) 3619 { # exported symbols 3620 return $Mangled1; 3621 } 3622 elsif(my $Mangled2 = mangleSymbol($InfoId, "MSVC", $V)) 3623 { # pure virtual symbols 3624 return $Mangled2; 3625 } 3626 } 3627 3628 # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data) 3629 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions 3630 # GCC 4.8.[012] and 6.[12].0 don't mangle anything 3631 3632 # try to mangle symbol 3633 if((not checkGcc("4") and $SymbolInfo{$V}{$InfoId}{"Class"}) 3634 or (checkGcc("4") and not $SymbolInfo{$V}{$InfoId}{"Class"}) 3635 or $In::Opt{"GccMissedMangling"}) 3636 { 3637 if(not $In::Opt{"CheckHeadersOnly"}) 3638 { 3639 if(my $Mangled = getMangled_GCC(modelUnmangled($InfoId, "GCC", $V), $V)) { 3640 return correctIncharge($InfoId, $V, $Mangled); 3641 } 3642 } 3643 3644 if(my $Mangled = mangleSymbol($InfoId, "GCC", $V)) { 3645 return correctIncharge($InfoId, $V, $Mangled); 3646 } 3647 } 3648 3649 return undef; 3650} 3651 3652sub simplifyNames() 3653{ 3654 foreach my $Base (keys(%{$Typedef_Tr{$V}})) 3655 { 3656 if($Typedef_Eq{$V}{$Base}) { 3657 next; 3658 } 3659 my @Translations = sort keys(%{$Typedef_Tr{$V}{$Base}}); 3660 if($#Translations==0) 3661 { 3662 if(length($Translations[0])<=length($Base)) { 3663 $Typedef_Eq{$V}{$Base} = $Translations[0]; 3664 } 3665 } 3666 else 3667 { # select most appropriate 3668 foreach my $Tr (@Translations) 3669 { 3670 if($Base=~/\A\Q$Tr\E/) 3671 { 3672 $Typedef_Eq{$V}{$Base} = $Tr; 3673 last; 3674 } 3675 } 3676 } 3677 } 3678 3679 foreach my $TypeId (sort {$a<=>$b} keys(%{$TypeInfo{$V}})) 3680 { # template instances only 3681 my $TypeName = $TypeInfo{$V}{$TypeId}{"Name"}; 3682 if(not $TypeName) { 3683 next; 3684 } 3685 if(index($TypeName, "<")==-1) { 3686 next; 3687 } 3688 if($TypeName=~/>(::\w+)+\Z/) 3689 { # skip unused types 3690 next; 3691 } 3692 3693 my $TypeName_N = $TypeName; 3694 3695 foreach my $Base (sort {length($b)<=>length($a)} 3696 sort {$b cmp $a} keys(%{$Typedef_Eq{$V}})) 3697 { 3698 next if(not $Base); 3699 if(index($TypeName_N, $Base)==-1) { 3700 next; 3701 } 3702 if(length($TypeName_N) - length($Base) <= 3) { 3703 next; 3704 } 3705 3706 if(my $Typedef = $Typedef_Eq{$V}{$Base}) 3707 { 3708 if($TypeName_N=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g 3709 or $TypeName_N=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g) 3710 { 3711 if(defined $TypeInfo{$V}{$TypeId}{"TParam"}) 3712 { 3713 foreach my $TPos (keys(%{$TypeInfo{$V}{$TypeId}{"TParam"}})) 3714 { 3715 if(my $TPName = $TypeInfo{$V}{$TypeId}{"TParam"}{$TPos}{"name"}) 3716 { 3717 if(index($TPName, $Base)==-1) { 3718 next; 3719 } 3720 if($TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g 3721 or $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g) { 3722 $TypeInfo{$V}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T"); 3723 } 3724 } 3725 } 3726 } 3727 } 3728 } 3729 } 3730 3731 if($TypeName_N ne $TypeName) 3732 { 3733 $TypeName_N = formatName($TypeName_N, "T"); 3734 $TypeInfo{$V}{$TypeId}{"Name"} = $TypeName_N; 3735 3736 if(not defined $TName_Tid{$V}{$TypeName_N}) { 3737 $TName_Tid{$V}{$TypeName_N} = $TypeId; 3738 } 3739 } 3740 } 3741} 3742 3743sub createType($) 3744{ 3745 my $Attr = $_[0]; 3746 my $NewId = ++$MAX_ID; 3747 3748 $Attr->{"Tid"} = $NewId; 3749 $TypeInfo{$V}{$NewId} = $Attr; 3750 $TName_Tid{$V}{formatName($Attr->{"Name"}, "T")} = $NewId; 3751 3752 return "$NewId"; 3753} 3754 3755sub instType($$) 3756{ # create template instances 3757 my ($Map, $Tid) = @_; 3758 3759 my $TInfoRef = $TypeInfo{$V}; 3760 3761 if(not $TInfoRef->{$Tid}) { 3762 return undef; 3763 } 3764 my $Attr = dclone($TInfoRef->{$Tid}); 3765 3766 foreach my $Key (sort keys(%{$Map})) 3767 { 3768 if(my $Val = $Map->{$Key}) 3769 { 3770 $Attr->{"Name"}=~s/\b$Key\b/$Val/g; 3771 3772 if(defined $Attr->{"NameSpace"}) { 3773 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g; 3774 } 3775 foreach (keys(%{$Attr->{"TParam"}})) { 3776 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g; 3777 } 3778 } 3779 else 3780 { # remove absent 3781 # _Traits, etc. 3782 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g; 3783 if(defined $Attr->{"NameSpace"}) { 3784 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g; 3785 } 3786 foreach (keys(%{$Attr->{"TParam"}})) 3787 { 3788 if($Attr->{"TParam"}{$_}{"name"} eq $Key) { 3789 delete($Attr->{"TParam"}{$_}); 3790 } 3791 else { 3792 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g; 3793 } 3794 } 3795 } 3796 } 3797 3798 my $Tmpl = 0; 3799 3800 if(defined $Attr->{"TParam"}) 3801 { 3802 foreach (sort {$a<=>$b} keys(%{$Attr->{"TParam"}})) 3803 { 3804 my $PName = $Attr->{"TParam"}{$_}{"name"}; 3805 3806 if(my $PTid = $TName_Tid{$V}{$PName}) 3807 { 3808 my %Base = getBaseType($PTid, $V); 3809 3810 if($Base{"Type"} eq "TemplateParam" 3811 or defined $Base{"Template"}) 3812 { 3813 $Tmpl = 1; 3814 last 3815 } 3816 } 3817 } 3818 } 3819 3820 if(my $Id = getTypeIdByName($Attr->{"Name"}, $V)) { 3821 return "$Id"; 3822 } 3823 else 3824 { 3825 if(not $Tmpl) { 3826 delete($Attr->{"Template"}); 3827 } 3828 3829 my $New = createType($Attr); 3830 3831 my %EMap = (); 3832 if(defined $TemplateMap{$V}{$Tid}) { 3833 %EMap = %{$TemplateMap{$V}{$Tid}}; 3834 } 3835 foreach (keys(%{$Map})) { 3836 $EMap{$_} = $Map->{$_}; 3837 } 3838 3839 if(defined $TInfoRef->{$New}{"BaseType"}) { 3840 $TInfoRef->{$New}{"BaseType"} = instType(\%EMap, $TInfoRef->{$New}{"BaseType"}); 3841 } 3842 if(defined $TInfoRef->{$New}{"Base"}) 3843 { 3844 foreach my $Bid (sort {$a<=>$b} keys(%{$TInfoRef->{$New}{"Base"}})) 3845 { 3846 my $NBid = instType(\%EMap, $Bid); 3847 3848 if($NBid ne $Bid 3849 and $NBid ne $New) 3850 { 3851 %{$TInfoRef->{$New}{"Base"}{$NBid}} = %{$TInfoRef->{$New}{"Base"}{$Bid}}; 3852 delete($TInfoRef->{$New}{"Base"}{$Bid}); 3853 } 3854 } 3855 } 3856 3857 if(defined $TInfoRef->{$New}{"Memb"}) 3858 { 3859 foreach (sort {$a<=>$b} keys(%{$TInfoRef->{$New}{"Memb"}})) 3860 { 3861 if(defined $TInfoRef->{$New}{"Memb"}{$_}{"type"}) { 3862 $TInfoRef->{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TInfoRef->{$New}{"Memb"}{$_}{"type"}); 3863 } 3864 } 3865 } 3866 3867 if(defined $TInfoRef->{$New}{"Param"}) 3868 { 3869 foreach (sort {$a<=>$b} keys(%{$TInfoRef->{$New}{"Param"}})) { 3870 $TInfoRef->{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TInfoRef->{$New}{"Param"}{$_}{"type"}); 3871 } 3872 } 3873 3874 if(defined $TInfoRef->{$New}{"Return"}) { 3875 $TInfoRef->{$New}{"Return"} = instType(\%EMap, $TInfoRef->{$New}{"Return"}); 3876 } 3877 3878 return $New; 3879 } 3880} 3881 3882sub correctIncharge($$$) 3883{ 3884 my ($InfoId, $V, $Mangled) = @_; 3885 if($In::ABI{$V}{"SymbolInfo"}{$InfoId}{"Constructor"}) 3886 { 3887 if($MangledNames{$V}{$Mangled}) { 3888 $Mangled=~s/C1([EI])/C2$1/; 3889 } 3890 } 3891 elsif($In::ABI{$V}{"SymbolInfo"}{$InfoId}{"Destructor"}) 3892 { 3893 if($MangledNames{$V}{$Mangled}) { 3894 $Mangled=~s/D0([EI])/D1$1/; 3895 } 3896 if($MangledNames{$V}{$Mangled}) { 3897 $Mangled=~s/D1([EI])/D2$1/; 3898 } 3899 } 3900 return $Mangled; 3901} 3902 3903sub simplifyConstants() 3904{ 3905 my $CRef = $In::ABI{$V}{"Constants"}; 3906 foreach my $Constant (keys(%{$CRef})) 3907 { 3908 if(defined $CRef->{$Constant}{"Header"}) 3909 { 3910 my $Value = $CRef->{$Constant}{"Value"}; 3911 if(defined $In::ABI{$V}{"EnumConstants"}{$Value}) { 3912 $CRef->{$Constant}{"Value"} = $In::ABI{$V}{"EnumConstants"}{$Value}{"Value"}; 3913 } 3914 } 3915 } 3916} 3917 3918sub simplifyVTable($) 3919{ 3920 my $Content = $_[0]; 3921 if($Content=~s/ \[with (.+)]//) 3922 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>] 3923 if(my @Elems = sepParams($1, 0, 0)) 3924 { 3925 foreach my $Elem (@Elems) 3926 { 3927 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/) 3928 { 3929 my ($Arg, $Val) = ($1, $2); 3930 3931 if(defined $DefaultStdArgs{$Arg}) { 3932 $Content=~s/,\s*$Arg\b//g; 3933 } 3934 else { 3935 $Content=~s/\b$Arg\b/$Val/g; 3936 } 3937 } 3938 } 3939 } 3940 } 3941 3942 return $Content; 3943} 3944 3945return 1; 3946