Index: libcxxabi/src/demangle/ItaniumDemangle.h =================================================================== --- libcxxabi/src/demangle/ItaniumDemangle.h +++ libcxxabi/src/demangle/ItaniumDemangle.h @@ -2592,34 +2592,38 @@ if (look() == 'Z') return getDerived().parseLocalName(State); - // ::= - if (look() == 'S' && look(1) != 't') { - Node *S = getDerived().parseSubstitution(); - if (S == nullptr) - return nullptr; - if (look() != 'I') - return nullptr; - Node *TA = getDerived().parseTemplateArgs(State != nullptr); - if (TA == nullptr) - return nullptr; - if (State) State->EndsWithTemplateArgs = true; - return make(S, TA); + Node *Result = nullptr; + bool IsSubst = look() == 'S' && look(1) != 't'; + if (IsSubst) { + // A substitution must lead to: + // ::= + Result = getDerived().parseSubstitution(); + } else { + // An unscoped name can be one of: + // ::= + // ::= + Result = getDerived().parseUnscopedName(State); } - - Node *N = getDerived().parseUnscopedName(State); - if (N == nullptr) + if (Result == nullptr) return nullptr; - // ::= + if (look() == 'I') { - Subs.push_back(N); + // ::= + if (!IsSubst) + // An unscoped-template-name is substitutable. + Subs.push_back(Result); Node *TA = getDerived().parseTemplateArgs(State != nullptr); if (TA == nullptr) return nullptr; - if (State) State->EndsWithTemplateArgs = true; - return make(N, TA); + if (State) + State->EndsWithTemplateArgs = true; + Result = make(Result, TA); + } else if (IsSubst) { + // The substitution case must be followed by . + return nullptr; } - // ::= - return N; + + return Result; } // := Z E [] @@ -2664,13 +2668,17 @@ template Node * AbstractManglingParser::parseUnscopedName(NameState *State) { - if (consumeIf("StL") || consumeIf("St")) { - Node *R = getDerived().parseUnqualifiedName(State); - if (R == nullptr) - return nullptr; - return make(R); - } - return getDerived().parseUnqualifiedName(State); + bool IsStd = consumeIf("St"); + if (IsStd) + consumeIf('L'); + + Node *Result = getDerived().parseUnqualifiedName(State); + if (Result == nullptr) + return nullptr; + if (IsStd) + Result = make(Result); + + return Result; } // ::= [abi-tags] @@ -4065,9 +4073,9 @@ } // ::= # See Compression below case 'S': { - if (look(1) && look(1) != 't') { - Node *Sub = getDerived().parseSubstitution(); - if (Sub == nullptr) + if (look(1) != 't') { + Result = getDerived().parseSubstitution(); + if (Result == nullptr) return nullptr; // Sub could be either of: @@ -4084,13 +4092,13 @@ Node *TA = getDerived().parseTemplateArgs(); if (TA == nullptr) return nullptr; - Result = make(Sub, TA); - break; + Result = make(Result, TA); + } else { + // If all we parsed was a substitution, don't re-insert into the + // substitution table. + return Result; } - - // If all we parsed was a substitution, don't re-insert into the - // substitution table. - return Sub; + break; } DEMANGLE_FALLTHROUGH; } Index: libcxxabi/test/test_demangle.pass.cpp =================================================================== --- libcxxabi/test/test_demangle.pass.cpp +++ libcxxabi/test/test_demangle.pass.cpp @@ -29855,6 +29855,8 @@ // This should be invalid, but it is currently not recognized as such // See https://llvm.org/PR51407 {"_Zcv1BIRT_EIS1_E", "operator B<><>"}, + + {"_Z3TPLIiET_S0_", "int TPL(int)"}, }; const unsigned N = sizeof(cases) / sizeof(cases[0]); Index: llvm/include/llvm/Demangle/ItaniumDemangle.h =================================================================== --- llvm/include/llvm/Demangle/ItaniumDemangle.h +++ llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -21,13 +21,12 @@ #include "DemangleConfig.h" #include "StringView.h" #include "Utility.h" -#include #include #include #include #include #include -#include +#include #include #define FOR_EACH_NODE_KIND(X) \ @@ -2593,34 +2592,38 @@ if (look() == 'Z') return getDerived().parseLocalName(State); - // ::= - if (look() == 'S' && look(1) != 't') { - Node *S = getDerived().parseSubstitution(); - if (S == nullptr) - return nullptr; - if (look() != 'I') - return nullptr; - Node *TA = getDerived().parseTemplateArgs(State != nullptr); - if (TA == nullptr) - return nullptr; - if (State) State->EndsWithTemplateArgs = true; - return make(S, TA); + Node *Result = nullptr; + bool IsSubst = look() == 'S' && look(1) != 't'; + if (IsSubst) { + // A substitution must lead to: + // ::= + Result = getDerived().parseSubstitution(); + } else { + // An unscoped name can be one of: + // ::= + // ::= + Result = getDerived().parseUnscopedName(State); } - - Node *N = getDerived().parseUnscopedName(State); - if (N == nullptr) + if (Result == nullptr) return nullptr; - // ::= + if (look() == 'I') { - Subs.push_back(N); + // ::= + if (!IsSubst) + // An unscoped-template-name is substitutable. + Subs.push_back(Result); Node *TA = getDerived().parseTemplateArgs(State != nullptr); if (TA == nullptr) return nullptr; - if (State) State->EndsWithTemplateArgs = true; - return make(N, TA); + if (State) + State->EndsWithTemplateArgs = true; + Result = make(Result, TA); + } else if (IsSubst) { + // The substitution case must be followed by . + return nullptr; } - // ::= - return N; + + return Result; } // := Z E [] @@ -2665,13 +2668,17 @@ template Node * AbstractManglingParser::parseUnscopedName(NameState *State) { - if (consumeIf("StL") || consumeIf("St")) { - Node *R = getDerived().parseUnqualifiedName(State); - if (R == nullptr) - return nullptr; - return make(R); - } - return getDerived().parseUnqualifiedName(State); + bool IsStd = consumeIf("St"); + if (IsStd) + consumeIf('L'); + + Node *Result = getDerived().parseUnqualifiedName(State); + if (Result == nullptr) + return nullptr; + if (IsStd) + Result = make(Result); + + return Result; } // ::= [abi-tags] @@ -4066,9 +4073,9 @@ } // ::= # See Compression below case 'S': { - if (look(1) && look(1) != 't') { - Node *Sub = getDerived().parseSubstitution(); - if (Sub == nullptr) + if (look(1) != 't') { + Result = getDerived().parseSubstitution(); + if (Result == nullptr) return nullptr; // Sub could be either of: @@ -4085,13 +4092,13 @@ Node *TA = getDerived().parseTemplateArgs(); if (TA == nullptr) return nullptr; - Result = make(Sub, TA); - break; + Result = make(Result, TA); + } else { + // If all we parsed was a substitution, don't re-insert into the + // substitution table. + return Result; } - - // If all we parsed was a substitution, don't re-insert into the - // substitution table. - return Sub; + break; } DEMANGLE_FALLTHROUGH; } Index: llvm/include/llvm/Demangle/StringView.h =================================================================== --- llvm/include/llvm/Demangle/StringView.h +++ llvm/include/llvm/Demangle/StringView.h @@ -14,6 +14,7 @@ #define DEMANGLE_STRINGVIEW_H #include "DemangleConfig.h" +#include #include #include @@ -37,16 +38,15 @@ StringView substr(size_t Pos, size_t Len = npos) const { assert(Pos <= size()); - if (Len > size() - Pos) - Len = size() - Pos; - return StringView(begin() + Pos, Len); + return StringView(begin() + Pos, std::min(Len, size() - Pos)); } size_t find(char C, size_t From = 0) const { + size_t FindBegin = std::min(From, size()); // Avoid calling memchr with nullptr. - if (From < size()) { + if (FindBegin < size()) { // Just forward to memchr, which is faster than a hand-rolled loop. - if (const void *P = ::memchr(First + From, C, size() - From)) + if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin)) return size_t(static_cast(P) - First); } return npos; @@ -98,7 +98,7 @@ bool startsWith(StringView Str) const { if (Str.size() > size()) return false; - return std::strncmp(Str.begin(), begin(), Str.size()) == 0; + return std::equal(Str.begin(), Str.end(), begin()); } const char &operator[](size_t Idx) const { return *(begin() + Idx); } @@ -111,7 +111,7 @@ inline bool operator==(const StringView &LHS, const StringView &RHS) { return LHS.size() == RHS.size() && - std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0; + std::equal(LHS.begin(), LHS.end(), RHS.begin()); } DEMANGLE_NAMESPACE_END Index: llvm/include/llvm/Demangle/Utility.h =================================================================== --- llvm/include/llvm/Demangle/Utility.h +++ llvm/include/llvm/Demangle/Utility.h @@ -14,11 +14,10 @@ #define DEMANGLE_UTILITY_H #include "StringView.h" -#include #include #include #include -#include +#include #include DEMANGLE_NAMESPACE_BEGIN @@ -49,8 +48,8 @@ return; } - std::array Temp; - char *TempPtr = Temp.data() + Temp.size(); + char Temp[21]; + char *TempPtr = std::end(Temp); while (N) { *--TempPtr = char('0' + N % 10); @@ -60,7 +59,7 @@ // Add negative sign... if (isNeg) *--TempPtr = '-'; - this->operator<<(StringView(TempPtr, Temp.data() + Temp.size())); + this->operator<<(StringView(TempPtr, std::end(Temp))); } public: