diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-08-24 23:30:26 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-08-24 23:30:26 +0000 |
commit | 30d0f345a475735af3ac1f831332b87a316c1207 (patch) | |
tree | b2fed039d6d2944376420b0598b885e3c4ac26de /libcxxabi/src | |
parent | 9121dfbe3a2a19c2f6d06dbcb8608e74850b4cf9 (diff) |
Port my recent changes from LLVM copy of the demangler:
r340663 - Allow Allocator::make to make a node of a different type than that
requested.
r340664 - Add documentation comment to ForwardTemplateReference.
r340665 - Fix ExpandedSpecialSubstitution demangling for Sa and Sb.
r340670 - Allow demangler's node allocator to fail, and bail out of the entire
demangling process when it does.
Diffstat (limited to 'libcxxabi/src')
-rw-r--r-- | libcxxabi/src/demangle/ItaniumDemangle.h | 98 |
1 files changed, 74 insertions, 24 deletions
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h index e12dbf3b02f..e475197abf7 100644 --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -1123,6 +1123,24 @@ public: } }; +/// A forward-reference to a template argument that was not known at the point +/// where the template parameter name was parsed in a mangling. +/// +/// This is created when demangling the name of a specialization of a +/// conversion function template: +/// +/// \code +/// struct A { +/// template<typename T> operator T*(); +/// }; +/// \endcode +/// +/// When demangling a specialization of the conversion function template, we +/// encounter the name of the template (including the \c T) before we reach +/// the template argument list, so we cannot substitute the parameter name +/// for the corresponding argument while parsing. Instead, we create a +/// \c ForwardTemplateReference node that is resolved after we parse the +/// template arguments. struct ForwardTemplateReference : Node { size_t Index; Node *Ref = nullptr; @@ -1271,10 +1289,11 @@ public: void printLeft(OutputStream &S) const override { switch (SSK) { case SpecialSubKind::allocator: - S += "std::basic_string<char, std::char_traits<char>, " - "std::allocator<char> >"; + S += "std::allocator"; break; case SpecialSubKind::basic_string: + S += "std::basic_string"; + break; case SpecialSubKind::string: S += "std::basic_string<char, std::char_traits<char>, " "std::allocator<char> >"; @@ -2165,7 +2184,7 @@ struct Db { ASTAllocator.reset(); } - template <class T, class... Args> T *make(Args &&... args) { + template <class T, class... Args> Node *make(Args &&... args) { return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...); } @@ -2358,7 +2377,10 @@ template<typename Alloc> Node *Db<Alloc>::parseLocalName(NameState *State) { if (consumeIf('s')) { First = parse_discriminator(First, Last); - return make<LocalName>(Encoding, make<NameType>("string literal")); + auto *StringLitName = make<NameType>("string literal"); + if (!StringLitName) + return nullptr; + return make<LocalName>(Encoding, StringLitName); } if (consumeIf('d')) { @@ -2772,6 +2794,8 @@ Node *Db<Alloc>::parseCtorDtorName(Node *&SoFar, NameState *State) { case SpecialSubKind::ostream: case SpecialSubKind::iostream: SoFar = make<ExpandedSpecialSubstitution>(SSK); + if (!SoFar) + return nullptr; default: break; } @@ -2833,13 +2857,18 @@ template<typename Alloc> Node *Db<Alloc>::parseNestedName(NameState *State) { Node *SoFar = nullptr; auto PushComponent = [&](Node *Comp) { + if (!Comp) return false; if (SoFar) SoFar = make<NestedName>(SoFar, Comp); else SoFar = Comp; if (State) State->EndsWithTemplateArgs = false; + return SoFar != nullptr; }; - if (consumeIf("St")) + if (consumeIf("St")) { SoFar = make<NameType>("std"); + if (!SoFar) + return nullptr; + } while (!consumeIf('E')) { consumeIf('L'); // extension @@ -2853,10 +2882,8 @@ template<typename Alloc> Node *Db<Alloc>::parseNestedName(NameState *State) { // ::= <template-param> if (look() == 'T') { - Node *TP = parseTemplateParam(); - if (TP == nullptr) + if (!PushComponent(parseTemplateParam())) return nullptr; - PushComponent(TP); Subs.push_back(SoFar); continue; } @@ -2867,6 +2894,8 @@ template<typename Alloc> Node *Db<Alloc>::parseNestedName(NameState *State) { if (TA == nullptr || SoFar == nullptr) return nullptr; SoFar = make<NameWithTemplateArgs>(SoFar, TA); + if (!SoFar) + return nullptr; if (State) State->EndsWithTemplateArgs = true; Subs.push_back(SoFar); continue; @@ -2874,10 +2903,8 @@ template<typename Alloc> Node *Db<Alloc>::parseNestedName(NameState *State) { // ::= <decltype> if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) { - Node *DT = parseDecltype(); - if (DT == nullptr) + if (!PushComponent(parseDecltype())) return nullptr; - PushComponent(DT); Subs.push_back(SoFar); continue; } @@ -2885,9 +2912,8 @@ template<typename Alloc> Node *Db<Alloc>::parseNestedName(NameState *State) { // ::= <substitution> if (look() == 'S' && look(1) != 't') { Node *S = parseSubstitution(); - if (S == nullptr) + if (!PushComponent(S)) return nullptr; - PushComponent(S); if (SoFar != S) Subs.push_back(S); continue; @@ -2897,10 +2923,8 @@ template<typename Alloc> Node *Db<Alloc>::parseNestedName(NameState *State) { if (look() == 'C' || (look() == 'D' && look(1) != 'C')) { if (SoFar == nullptr) return nullptr; - Node *CtorDtor = parseCtorDtorName(SoFar, State); - if (CtorDtor == nullptr) + if (!PushComponent(parseCtorDtorName(SoFar, State))) return nullptr; - PushComponent(CtorDtor); SoFar = parseAbiTags(SoFar); if (SoFar == nullptr) return nullptr; @@ -2909,10 +2933,8 @@ template<typename Alloc> Node *Db<Alloc>::parseNestedName(NameState *State) { } // ::= <prefix> <unqualified-name> - Node *N = parseUnqualifiedName(State); - if (N == nullptr) + if (!PushComponent(parseUnqualifiedName(State))) return nullptr; - PushComponent(N); Subs.push_back(SoFar); } @@ -3025,6 +3047,8 @@ template<typename Alloc> Node *Db<Alloc>::parseUnresolvedName() { if (TA == nullptr) return nullptr; SoFar = make<NameWithTemplateArgs>(SoFar, TA); + if (!SoFar) + return nullptr; } while (!consumeIf('E')) { @@ -3032,6 +3056,8 @@ template<typename Alloc> Node *Db<Alloc>::parseUnresolvedName() { if (Qual == nullptr) return nullptr; SoFar = make<QualifiedName>(SoFar, Qual); + if (!SoFar) + return nullptr; } Node *Base = parseBaseUnresolvedName(); @@ -3064,6 +3090,8 @@ template<typename Alloc> Node *Db<Alloc>::parseUnresolvedName() { SoFar = make<GlobalQualifiedName>(Qual); else SoFar = Qual; + if (!SoFar) + return nullptr; } while (!consumeIf('E')); } // sr <unresolved-type> <base-unresolved-name> @@ -3078,6 +3106,8 @@ template<typename Alloc> Node *Db<Alloc>::parseUnresolvedName() { if (TA == nullptr) return nullptr; SoFar = make<NameWithTemplateArgs>(SoFar, TA); + if (!SoFar) + return nullptr; } } @@ -3097,6 +3127,8 @@ template<typename Alloc> Node *Db<Alloc>::parseAbiTags(Node *N) { if (SN.empty()) return nullptr; N = make<AbiTagAttr>(N, SN); + if (!N) + return nullptr; } return N; } @@ -3149,11 +3181,15 @@ template<typename Alloc> Node *Db<Alloc>::parseFunctionType() { Node *ExceptionSpec = nullptr; if (consumeIf("Do")) { ExceptionSpec = make<NameType>("noexcept"); + if (!ExceptionSpec) + return nullptr; } else if (consumeIf("DO")) { Node *E = parseExpr(); if (E == nullptr || !consumeIf('E')) return nullptr; ExceptionSpec = make<NoexceptSpec>(E); + if (!ExceptionSpec) + return nullptr; } else if (consumeIf("Dw")) { size_t SpecsBegin = Names.size(); while (!consumeIf('E')) { @@ -3164,6 +3200,8 @@ template<typename Alloc> Node *Db<Alloc>::parseFunctionType() { } ExceptionSpec = make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin)); + if (!ExceptionSpec) + return nullptr; } consumeIf("Dx"); // transaction safe @@ -4503,9 +4541,10 @@ template<typename Alloc> Node *Db<Alloc>::parseExpr() { return nullptr; Names.push_back(Arg); } - return make<EnclosingExpr>( - "sizeof... (", make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin)), - ")"); + auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin)); + if (!Pack) + return nullptr; + return make<EnclosingExpr>("sizeof... (", Pack, ")"); } } return nullptr; @@ -4757,6 +4796,8 @@ template<typename Alloc> Node *Db<Alloc>::parseEncoding() { Names.push_back(Arg); } Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs)); + if (!Attrs) + return nullptr; } Node *ReturnType = nullptr; @@ -4901,6 +4942,8 @@ template<typename Alloc> Node *Db<Alloc>::parseSubstitution() { default: return nullptr; } + if (!SpecialSub) + return nullptr; // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution> // has ABI tags, the tags are appended to the substitution; the result is a // substitutable component. @@ -4953,8 +4996,13 @@ template<typename Alloc> Node *Db<Alloc>::parseTemplateParam() { // <template-arg> further ahead in the mangled name (currently just conversion // operator types), then we should only look it up in the right context. if (PermitForwardTemplateReferences) { - ForwardTemplateRefs.push_back(make<ForwardTemplateReference>(Index)); - return ForwardTemplateRefs.back(); + Node *ForwardRef = make<ForwardTemplateReference>(Index); + if (!ForwardRef) + return nullptr; + assert(ForwardRef->getKind() == Node::KForwardTemplateReference); + ForwardTemplateRefs.push_back( + static_cast<ForwardTemplateReference *>(ForwardRef)); + return ForwardRef; } if (Index >= TemplateParams.size()) @@ -5030,6 +5078,8 @@ Node *Db<Alloc>::parseTemplateArgs(bool TagTemplates) { if (Arg->getKind() == Node::KTemplateArgumentPack) { TableEntry = make<ParameterPack>( static_cast<TemplateArgumentPack*>(TableEntry)->getElements()); + if (!TableEntry) + return nullptr; } TemplateParams.push_back(TableEntry); } else { |