xref: /petsc/lib/petsc/bin/maint/abi-compliance-checker/modules/Internals/GccAst.pm (revision c7fbd2bd3f8c01fa99614987dbf75cef1ca8e75e)
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