Index: llvm/lib/Demangle/MicrosoftDemangle.cpp =================================================================== --- llvm/lib/Demangle/MicrosoftDemangle.cpp +++ llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -21,6 +21,7 @@ #include "Utility.h" #include +#include // This memory allocator is extremely fast, but it doesn't call dtors // for allocated objects. That means you can't use STL containers @@ -113,7 +114,7 @@ }; enum class QualifierMangleMode { Drop, Mangle, Result }; -enum class QualifierMangleLocation { Member, NonMember, Detect }; +enum class MemberPointerMode { Member, NonMember, DontKnow }; // Calling conventions enum class CallingConv : uint8_t { @@ -236,7 +237,8 @@ void outputPre(OutputStream &OS) override; void outputPost(OutputStream &OS) override; - bool isMemberPointer() const { return false; } + // True if this is a member pointer. + Name *MemberName = nullptr; // Represents a type X in "a pointer to X", "a reference to X", // "an array of X", or "a function returning X". @@ -494,6 +496,11 @@ if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) OS << "("; + if (MemberName) { + outputName(OS, MemberName); + OS << "::"; + } + if (Prim == PrimTy::Ptr) OS << "*"; else @@ -611,7 +618,7 @@ Type *demangleType(QualifierMangleMode QMM); Type *demangleBasicType(); UdtType *demangleClassType(); - PointerType *demanglePointerType(); + PointerType *demanglePointerType(MemberPointerMode MPM); ArrayType *demangleArrayType(); @@ -630,12 +637,7 @@ StorageClass demangleVariableStorageClass(); ReferenceKind demangleReferenceKind(); - Qualifiers demangleFunctionQualifiers(); - Qualifiers demangleVariablQualifiers(); - Qualifiers demangleReturnTypQualifiers(); - - Qualifiers demangleQualifiers( - QualifierMangleLocation Location = QualifierMangleLocation::Detect); + std::pair demangleQualifiers(); // The result is written to this stream. OutputStream OS; @@ -707,13 +709,11 @@ Ty->Quals = Qualifiers(Ty->Quals | demanglePointerExtQualifiers()); PointerType *PTy = static_cast(Ty); - QualifierMangleLocation Location = PTy->isMemberPointer() - ? QualifierMangleLocation::Member - : QualifierMangleLocation::NonMember; - ExtraChildQuals = demangleQualifiers(Location); + bool IsMember; + std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(); - if (PTy->isMemberPointer()) { + if (PTy->MemberName) { Name *BackRefName = demangleName(); (void)BackRefName; } @@ -722,7 +722,7 @@ break; } default: - Ty->Quals = demangleQualifiers(); + Ty->Quals = demangleQualifiers().first; break; } @@ -846,6 +846,10 @@ Elem->Next = Head; Head = Elem; + if (MangledName.empty()) { + Error = true; + return nullptr; + } } return Head; @@ -1019,26 +1023,6 @@ return 0; } -Qualifiers Demangler::demangleFunctionQualifiers() { - SwapAndRestore RestoreOnError(MangledName, MangledName); - RestoreOnError.shouldRestore(false); - - switch (MangledName.popFront()) { - case 'A': - return Q_None; - case 'B': - return Q_Const; - case 'C': - return Q_Volatile; - case 'D': - return Qualifiers(Q_Const | Q_Volatile); - } - - Error = true; - RestoreOnError.shouldRestore(true); - return Q_None; -} - CallingConv Demangler::demangleCallingConvention() { switch (MangledName.popFront()) { case 'A': @@ -1088,116 +1072,47 @@ return StorageClass::None; } -Qualifiers Demangler::demangleVariablQualifiers() { - SwapAndRestore RestoreOnError(MangledName, MangledName); - RestoreOnError.shouldRestore(false); - - switch (MangledName.popFront()) { - case 'A': - return Q_None; - case 'B': - return Q_Const; - case 'C': - return Q_Volatile; - case 'D': - return Qualifiers(Q_Const | Q_Volatile); - case 'E': - return Q_Far; - case 'F': - return Qualifiers(Q_Const | Q_Far); - case 'G': - return Qualifiers(Q_Volatile | Q_Far); - case 'H': - return Qualifiers(Q_Const | Q_Volatile | Q_Far); - } - - Error = true; - RestoreOnError.shouldRestore(true); - return Q_None; -} - -Qualifiers Demangler::demangleReturnTypQualifiers() { - if (!MangledName.consumeFront("?")) - return Q_None; - - SwapAndRestore RestoreOnError(MangledName, MangledName); - RestoreOnError.shouldRestore(false); +std::pair Demangler::demangleQualifiers() { switch (MangledName.popFront()) { + // Member qualifiers + case 'Q': + return std::make_pair(Q_None, true); + case 'R': + return std::make_pair(Q_Const, true); + case 'S': + return std::make_pair(Q_Volatile, true); + case 'T': + return std::make_pair(Qualifiers(Q_Const | Q_Volatile), true); + // Non-Member qualifiers case 'A': - return Q_None; + return std::make_pair(Q_None, false); case 'B': - return Q_Const; + return std::make_pair(Q_Const, false); case 'C': - return Q_Volatile; + return std::make_pair(Q_Volatile, false); case 'D': - return Qualifiers(Q_Const | Q_Volatile); - } - - Error = true; - RestoreOnError.shouldRestore(true); - return Q_None; -} - -Qualifiers Demangler::demangleQualifiers(QualifierMangleLocation Location) { - if (Location == QualifierMangleLocation::Detect) { - switch (MangledName.front()) { - case 'Q': - case 'R': - case 'S': - case 'T': - Location = QualifierMangleLocation::Member; - break; - case 'A': - case 'B': - case 'C': - case 'D': - Location = QualifierMangleLocation::NonMember; - break; - default: - Error = true; - return Q_None; - } - } - - if (Location == QualifierMangleLocation::Member) { - switch (MangledName.popFront()) { - // Member qualifiers - case 'Q': - return Q_None; - case 'R': - return Q_Const; - case 'S': - return Q_Volatile; - case 'T': - return Qualifiers(Q_Const | Q_Volatile); - } - } else { - switch (MangledName.popFront()) { - // Non-Member qualifiers - case 'A': - return Q_None; - case 'B': - return Q_Const; - case 'C': - return Q_Volatile; - case 'D': - return Qualifiers(Q_Const | Q_Volatile); - } + return std::make_pair(Qualifiers(Q_Const | Q_Volatile), false); } Error = true; - return Q_None; + return std::make_pair(Q_None, false); } // ::= // ::= # pointers, references Type *Demangler::demangleType(QualifierMangleMode QMM) { Qualifiers Quals = Q_None; - if (QMM == QualifierMangleMode::Mangle) - Quals = Qualifiers(Quals | demangleQualifiers()); - else if (QMM == QualifierMangleMode::Result) { - if (MangledName.consumeFront('?')) - Quals = Qualifiers(Quals | demangleQualifiers()); + MemberPointerMode MPM = MemberPointerMode::DontKnow; + if (QMM == QualifierMangleMode::Mangle) { + bool IsMember = false; + std::tie(Quals, IsMember) = demangleQualifiers(); + MPM = IsMember ? MemberPointerMode::Member : MemberPointerMode::NonMember; + } else if (QMM == QualifierMangleMode::Result) { + if (MangledName.consumeFront('?')) { + bool IsMember = false; + std::tie(Quals, IsMember) = demangleQualifiers(); + MPM = IsMember ? MemberPointerMode::Member : MemberPointerMode::NonMember; + } } Type *Ty = nullptr; @@ -1213,7 +1128,7 @@ case 'Q': // foo *const case 'R': // foo *volatile case 'S': // foo *const volatile - Ty = demanglePointerType(); + Ty = demanglePointerType(MPM); break; case 'Y': Ty = demangleArrayType(); @@ -1251,7 +1166,7 @@ if (functionHasThisPtr(*FTy)) { FTy->Quals = demanglePointerExtQualifiers(); FTy->RefKind = demangleReferenceKind(); - FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers()); + FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers().first); } // Fields that appear on both member and non-member functions. @@ -1367,9 +1282,43 @@ return UTy; } +static bool isMemberPointer(StringView MangledName) { + // If it starts with a number, then 6 indicates a non-member function + // pointer, and 8 indicates a member function pointer. + if (startsWithDigit(MangledName)) { + assert(MangledName.front() == '6' || MangledName.front() == '8'); + return (MangledName.front() == '8') ? true : false; + } + + // Remove ext qualifiers since those can appear on either type and are + // therefore not indicative. + MangledName.consumeFront('E'); // 64-bit + MangledName.consumeFront('I'); // restrict + MangledName.consumeFront('F'); // unaligned + + assert(!MangledName.empty()); + + // The next value should be either ABCD (non-member) or QRST (member). + switch (MangledName.front()) { + case 'A': + case 'B': + case 'C': + case 'D': + return false; + case 'Q': + case 'R': + case 'S': + case 'T': + return true; + default: + assert(false); + } + return false; +} + // ::= E? // # the E is required for 64-bit non-static pointers -PointerType *Demangler::demanglePointerType() { +PointerType *Demangler::demanglePointerType(MemberPointerMode MPM) { PointerType *Pointer = Arena.alloc(); Pointer->Quals = Q_None; @@ -1396,25 +1345,44 @@ assert(false && "Ty is not a pointer type!"); } - if (MangledName.consumeFront("6")) { - FunctionType *FTy = Arena.alloc(); - FTy->Prim = PrimTy::Function; - FTy->CallConvention = demangleCallingConvention(); + if (MPM == MemberPointerMode::DontKnow) { + bool IsMember = isMemberPointer(MangledName); + MPM = IsMember ? MemberPointerMode::Member : MemberPointerMode::NonMember; + } - FTy->ReturnType = demangleType(QualifierMangleMode::Drop); - FTy->Params = demangleParameterList(); + if (MPM == MemberPointerMode::Member) { + Qualifiers ExtQuals = demanglePointerExtQualifiers(); + Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); - if (!MangledName.consumeFront("@Z")) - MangledName.consumeFront("Z"); + Qualifiers PointeeQuals = Q_None; + bool IsMember = false; + std::tie(PointeeQuals, IsMember) = demangleQualifiers(); + assert(IsMember); + Pointer->MemberName = demangleName(); - Pointer->Pointee = FTy; - return Pointer; - } + Pointer->Pointee = demangleType(QualifierMangleMode::Drop); + Pointer->Pointee->Quals = PointeeQuals; + } else { + if (MangledName.consumeFront("6")) { + FunctionType *FTy = Arena.alloc(); + FTy->Prim = PrimTy::Function; + FTy->CallConvention = demangleCallingConvention(); - Qualifiers ExtQuals = demanglePointerExtQualifiers(); - Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); + FTy->ReturnType = demangleType(QualifierMangleMode::Drop); + FTy->Params = demangleParameterList(); - Pointer->Pointee = demangleType(QualifierMangleMode::Mangle); + if (!MangledName.consumeFront("@Z")) + MangledName.consumeFront("Z"); + + Pointer->Pointee = FTy; + return Pointer; + } + + Qualifiers ExtQuals = demanglePointerExtQualifiers(); + Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); + + Pointer->Pointee = demangleType(QualifierMangleMode::Mangle); + } return Pointer; } Index: llvm/test/Demangle/ms-mangle.test =================================================================== --- llvm/test/Demangle/ms-mangle.test +++ llvm/test/Demangle/ms-mangle.test @@ -92,15 +92,14 @@ ?j@@3P6GHCE@ZA ; CHECK: int __stdcall (*j)(signed char, unsigned char) +?k@@3PTfoo@@DT1@ +; CHECK: char const volatile foo::*k -; FIXME: We don't handle member pointers yet. -; ?k@@3PTfoo@@DT1 -; FIXME: char const volatile foo::*k +?k@@3PETfoo@@DET1@ +; CHECK: char const volatile foo::*k -; ?k@@3PETfoo@@DET1 -; FIXME: char const volatile foo::*k - -; ?l@@3P8foo@@AEHH@ZQ1 +; FIXME: We don't support member function pointers yet. +; ?l@@3P8foo@@AEHH@ZQ1@ ; FIXME: int __thiscall (foo::*l)(int) ?g_cInt@@3HB