20
20
#include " StringView.h"
21
21
#include " Utility.h"
22
22
23
+ #include < array>
23
24
#include < cctype>
24
25
#include < cstdio>
25
26
#include < tuple>
@@ -415,8 +416,13 @@ struct TemplateParams {
415
416
bool IntegerLiteralIsNegative = false ;
416
417
bool IsEmptyParameterPack = false ;
417
418
bool PointerToSymbol = false ;
419
+ bool NullptrLiteral = false ;
420
+ bool DataMemberPointer = false ;
418
421
bool ReferenceToSymbol = false ;
419
422
423
+ int ThunkOffsetCount = 0 ;
424
+ std::array<int64_t , 3 > ThunkOffsets;
425
+
420
426
// If IsIntegerLiteral is true, this is a non-type template parameter
421
427
// whose value is contained in this field.
422
428
uint64_t IntegralValue = 0 ;
@@ -794,11 +800,30 @@ static void outputParameterList(OutputStream &OS,
794
800
OS << ' -' ;
795
801
OS << Head->IntegralValue ;
796
802
} else if (Head->PointerToSymbol || Head->ReferenceToSymbol ) {
797
- if (Head->PointerToSymbol )
798
- OS << " &" ;
799
- Type::outputPre (OS, *Head->ParamType );
800
- outputName (OS, Head->ParamName , Head->ParamType );
801
- Type::outputPost (OS, *Head->ParamType );
803
+ if (Head->NullptrLiteral )
804
+ OS << " nullptr" ;
805
+ else {
806
+ if (Head->ThunkOffsetCount > 0 )
807
+ OS << " {" ;
808
+ else if (Head->PointerToSymbol )
809
+ OS << " &" ;
810
+ if (Head->ParamType )
811
+ Type::outputPre (OS, *Head->ParamType );
812
+ outputName (OS, Head->ParamName , Head->ParamType );
813
+ if (Head->ParamType )
814
+ Type::outputPost (OS, *Head->ParamType );
815
+ if (Head->ThunkOffsetCount > 0 ) {
816
+ for (int I = 0 ; I < Head->ThunkOffsetCount ; ++I) {
817
+ OS << " , " << Head->ThunkOffsets [I];
818
+ }
819
+ OS << " }" ;
820
+ }
821
+ }
822
+ } else if (Head->DataMemberPointer ) {
823
+ OS << " {" << Head->ThunkOffsets [0 ];
824
+ for (int I = 1 ; I < Head->ThunkOffsetCount ; ++I)
825
+ OS << " , " << Head->ThunkOffsets [I];
826
+ OS << " }" ;
802
827
} else if (Head->ParamType ) {
803
828
// simple type.
804
829
Type::outputPre (OS, *Head->ParamType );
@@ -840,12 +865,33 @@ static void outputNameComponent(OutputStream &OS, const Name &N) {
840
865
outputParameterList (OS, *N.TParams );
841
866
}
842
867
868
+ static const OperatorInfo *lastComponentAsOperator (const Name *TheName) {
869
+ if (!TheName)
870
+ return nullptr ;
871
+ while (TheName->Next )
872
+ TheName = TheName->Next ;
873
+ if (TheName->IsOperator )
874
+ return static_cast <const OperatorInfo *>(TheName);
875
+ return nullptr ;
876
+ }
877
+
843
878
static void outputName (OutputStream &OS, const Name *TheName, const Type *Ty) {
844
879
if (!TheName)
845
880
return ;
846
881
847
882
outputSpaceIfNecessary (OS);
848
883
884
+ const OperatorInfo *Operator = lastComponentAsOperator (TheName);
885
+ const VirtualMemberPtrThunk *Thunk = nullptr ;
886
+ if (Operator) {
887
+ if (Operator->Info ->Operator == OperatorTy::Vcall) {
888
+ Thunk = static_cast <const VirtualMemberPtrThunk *>(Operator);
889
+ OS << " [thunk]: " ;
890
+ outputCallingConvention (OS, Thunk->CC );
891
+ OS << " " ;
892
+ }
893
+ }
894
+
849
895
const Name *Previous = nullptr ;
850
896
// Print out namespaces or outer class BackReferences.
851
897
for (; TheName->Next ; TheName = TheName->Next ) {
@@ -860,10 +906,9 @@ static void outputName(OutputStream &OS, const Name *TheName, const Type *Ty) {
860
906
return ;
861
907
}
862
908
863
- const OperatorInfo &Operator = static_cast <const OperatorInfo &>(*TheName);
864
909
865
910
// Print out ctor or dtor.
866
- switch (Operator. Info ->Operator ) {
911
+ switch (Operator-> Info ->Operator ) {
867
912
case OperatorTy::Dtor:
868
913
OS << " ~" ;
869
914
LLVM_FALLTHROUGH;
@@ -884,43 +929,47 @@ static void outputName(OutputStream &OS, const Name *TheName, const Type *Ty) {
884
929
}
885
930
break ;
886
931
case OperatorTy::LiteralOperator:
887
- OS << Operator. Info ->Name ;
932
+ OS << Operator-> Info ->Name ;
888
933
outputNameComponent (OS, *TheName);
889
934
break ;
890
935
case OperatorTy::RttiBaseClassDescriptor: {
891
936
const RttiBaseClassDescriptor &BCD =
892
- static_cast <const RttiBaseClassDescriptor &>(Operator);
893
- OS << " `" << Operator. Info ->Name << " at (" ;
937
+ static_cast <const RttiBaseClassDescriptor &>(* Operator);
938
+ OS << " `" << Operator-> Info ->Name << " at (" ;
894
939
OS << BCD.NVOffset << " , " << BCD.VBPtrOffset << " , " << BCD.VBTableOffset
895
940
<< " , " << BCD.Flags ;
896
941
OS << " )'" ;
897
942
break ;
898
943
}
944
+ case OperatorTy::Vcall: {
945
+ OS << " `vcall'{" ;
946
+ OS << Thunk->OffsetInVTable << " , {flat}}" ;
947
+ break ;
948
+ }
949
+
899
950
case OperatorTy::LocalStaticGuard: {
900
951
const LocalStaticGuardVariable &LSG =
901
- static_cast <const LocalStaticGuardVariable &>(Operator);
902
- OS << Operator. Info ->Name ;
952
+ static_cast <const LocalStaticGuardVariable &>(* Operator);
953
+ OS << Operator-> Info ->Name ;
903
954
if (LSG.ScopeIndex > 0 )
904
955
OS << " {" << LSG.ScopeIndex << " }" ;
905
956
break ;
906
957
}
907
958
default :
908
- OS << Operator. Info ->Name ;
909
- if (Operator. IsTemplateInstantiation )
910
- outputParameterList (OS, *Operator. TParams );
959
+ OS << Operator-> Info ->Name ;
960
+ if (Operator-> IsTemplateInstantiation )
961
+ outputParameterList (OS, *Operator-> TParams );
911
962
break ;
912
963
}
913
964
}
914
965
915
966
static void outputSpecialOperator (OutputStream &OS, const Name *OuterName) {
916
967
assert (OuterName);
917
968
// The last component should be an operator.
918
- const Name *LastComponent = OuterName;
919
- while (LastComponent->Next )
920
- LastComponent = LastComponent->Next ;
969
+ const OperatorInfo *Operator = lastComponentAsOperator (OuterName);
921
970
922
- assert (LastComponent ->IsOperator );
923
- const OperatorInfo &Oper = static_cast <const OperatorInfo &>(*LastComponent );
971
+ assert (Operator ->IsOperator );
972
+ const OperatorInfo &Oper = static_cast <const OperatorInfo &>(*Operator );
924
973
switch (Oper.Info ->Operator ) {
925
974
case OperatorTy::StringLiteral: {
926
975
const StringLiteral &SL = static_cast <const StringLiteral &>(Oper);
@@ -1398,9 +1447,14 @@ Symbol *Demangler::parseOperator(StringView &MangledName) {
1398
1447
std::tie (OTy, S->SymbolName ) = demangleOperatorName (MangledName, true );
1399
1448
switch (OTy) {
1400
1449
case OperatorTy::StringLiteral:
1401
- case OperatorTy::Vcall:
1402
1450
S->Category = SymbolCategory::SpecialOperator;
1403
1451
break ;
1452
+ case OperatorTy::Vcall:
1453
+ S->Category = SymbolCategory::UnnamedFunction;
1454
+ break ;
1455
+ case OperatorTy::LocalStaticGuard:
1456
+ S->Category = SymbolCategory::UnnamedVariable;
1457
+ break ;
1404
1458
case OperatorTy::Vftable: // Foo@@6B@
1405
1459
case OperatorTy::LocalVftable: // Foo@@6B@
1406
1460
case OperatorTy::RttiCompleteObjLocator: // Foo@@6B@
@@ -1428,10 +1482,6 @@ Symbol *Demangler::parseOperator(StringView &MangledName) {
1428
1482
if (!MangledName.empty ())
1429
1483
Error = true ;
1430
1484
break ;
1431
- case OperatorTy::LocalStaticGuard: {
1432
- S->Category = SymbolCategory::UnnamedVariable;
1433
- break ;
1434
- }
1435
1485
default :
1436
1486
if (!Error)
1437
1487
std::tie (S->Category , S->SymbolType ) =
@@ -2878,57 +2928,102 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) {
2878
2928
// Template parameter lists don't participate in back-referencing.
2879
2929
*Current = Arena.alloc <TemplateParams>();
2880
2930
2931
+ TemplateParams &TP = **Current;
2932
+
2881
2933
// Empty parameter pack.
2882
2934
if (MangledName.consumeFront (" $S" ) || MangledName.consumeFront (" $$V" ) ||
2883
2935
MangledName.consumeFront (" $$$V" )) {
2884
- (*Current)-> IsEmptyParameterPack = true ;
2936
+ TP. IsEmptyParameterPack = true ;
2885
2937
break ;
2886
2938
}
2887
2939
2888
2940
if (MangledName.consumeFront (" $$Y" )) {
2889
2941
// Template alias
2890
- (*Current)-> IsTemplateTemplate = true ;
2891
- (*Current)-> IsAliasTemplate = true ;
2892
- (*Current)-> ParamName = demangleFullyQualifiedTypeName (MangledName);
2942
+ TP. IsTemplateTemplate = true ;
2943
+ TP. IsAliasTemplate = true ;
2944
+ TP. ParamName = demangleFullyQualifiedTypeName (MangledName);
2893
2945
} else if (MangledName.consumeFront (" $$B" )) {
2894
2946
// Array
2895
- (*Current)->ParamType =
2896
- demangleType (MangledName, QualifierMangleMode::Drop);
2947
+ TP.ParamType = demangleType (MangledName, QualifierMangleMode::Drop);
2897
2948
} else if (MangledName.consumeFront (" $$C" )) {
2898
2949
// Type has qualifiers.
2899
- (*Current)->ParamType =
2900
- demangleType (MangledName, QualifierMangleMode::Mangle);
2901
- } else if (MangledName.startsWith (" $1?" )) {
2902
- MangledName.consumeFront (" $1" );
2903
- // Pointer to symbol
2904
- Symbol *S = parse (MangledName);
2905
- (*Current)->ParamName = S->SymbolName ;
2906
- (*Current)->ParamType = S->SymbolType ;
2907
- (*Current)->PointerToSymbol = true ;
2950
+ TP.ParamType = demangleType (MangledName, QualifierMangleMode::Mangle);
2951
+ } else if (MangledName.startsWith (" $1" ) || MangledName.startsWith (" $H" ) ||
2952
+ MangledName.startsWith (" $I" ) || MangledName.startsWith (" $J" )) {
2953
+ MangledName = MangledName.dropFront ();
2954
+ // 1 - single inheritance <name>
2955
+ // H - multiple inheritance <name> <number>
2956
+ // I - virtual inheritance <name> <number> <number> <number>
2957
+ // J - unspecified inheritance <name> <number> <number> <number>
2958
+ char InheritanceSpecifier = MangledName.popFront ();
2959
+ // Pointer to member
2960
+ Symbol *S = MangledName.startsWith (' ?' ) ? parse (MangledName) : nullptr ;
2961
+ switch (InheritanceSpecifier) {
2962
+ case ' J' :
2963
+ TP.ThunkOffsets [TP.ThunkOffsetCount ++] = demangleSigned (MangledName);
2964
+ LLVM_FALLTHROUGH;
2965
+ case ' I' :
2966
+ TP.ThunkOffsets [TP.ThunkOffsetCount ++] = demangleSigned (MangledName);
2967
+ LLVM_FALLTHROUGH;
2968
+ case ' H' :
2969
+ TP.ThunkOffsets [TP.ThunkOffsetCount ++] = demangleSigned (MangledName);
2970
+ LLVM_FALLTHROUGH;
2971
+ case ' 1' :
2972
+ break ;
2973
+ default :
2974
+ Error = true ;
2975
+ break ;
2976
+ }
2977
+ TP.PointerToSymbol = true ;
2978
+ if (S) {
2979
+ TP.ParamName = S->SymbolName ;
2980
+ TP.ParamType = S->SymbolType ;
2981
+ } else
2982
+ TP.NullptrLiteral = true ;
2908
2983
} else if (MangledName.startsWith (" $E?" )) {
2909
2984
MangledName.consumeFront (" $E" );
2910
2985
// Reference to symbol
2911
2986
Symbol *S = parse (MangledName);
2912
- (*Current)->ParamName = S->SymbolName ;
2913
- (*Current)->ParamType = S->SymbolType ;
2914
- (*Current)->ReferenceToSymbol = true ;
2987
+ TP.ParamName = S->SymbolName ;
2988
+ TP.ParamType = S->SymbolType ;
2989
+ TP.ReferenceToSymbol = true ;
2990
+ } else if (MangledName.startsWith (" $F" ) || MangledName.startsWith (" $G" )) {
2991
+ // Data member pointer.
2992
+ MangledName = MangledName.dropFront ();
2993
+ char InheritanceSpecifier = MangledName.popFront ();
2994
+
2995
+ switch (InheritanceSpecifier) {
2996
+ case ' G' :
2997
+ TP.ThunkOffsets [TP.ThunkOffsetCount ++] = demangleSigned (MangledName);
2998
+ LLVM_FALLTHROUGH;
2999
+ case ' F' :
3000
+ TP.ThunkOffsets [TP.ThunkOffsetCount ++] = demangleSigned (MangledName);
3001
+ TP.ThunkOffsets [TP.ThunkOffsetCount ++] = demangleSigned (MangledName);
3002
+ LLVM_FALLTHROUGH;
3003
+ case ' 0' :
3004
+ break ;
3005
+ default :
3006
+ Error = true ;
3007
+ break ;
3008
+ }
3009
+ TP.DataMemberPointer = true ;
3010
+
2915
3011
} else if (MangledName.consumeFront (" $0" )) {
2916
3012
// Integral non-type template parameter
2917
3013
bool IsNegative = false ;
2918
3014
uint64_t Value = 0 ;
2919
3015
std::tie (Value, IsNegative) = demangleNumber (MangledName);
2920
3016
2921
- (*Current)-> IsIntegerLiteral = true ;
2922
- (*Current)-> IntegerLiteralIsNegative = IsNegative;
2923
- (*Current)-> IntegralValue = Value;
3017
+ TP. IsIntegerLiteral = true ;
3018
+ TP. IntegerLiteralIsNegative = IsNegative;
3019
+ TP. IntegralValue = Value;
2924
3020
} else {
2925
- (*Current)->ParamType =
2926
- demangleType (MangledName, QualifierMangleMode::Drop);
3021
+ TP.ParamType = demangleType (MangledName, QualifierMangleMode::Drop);
2927
3022
}
2928
3023
if (Error)
2929
3024
return nullptr ;
2930
3025
2931
- Current = &(*Current)-> Next ;
3026
+ Current = &TP. Next ;
2932
3027
}
2933
3028
2934
3029
if (Error)
0 commit comments