Changeset View
Changeset View
Standalone View
Standalone View
llvm/include/llvm/Demangle/ItaniumDemangle.h
Show All 10 Lines | |||||
// libcxxabi is the original and the one under llvm is the copy. Use | // libcxxabi is the original and the one under llvm is the copy. Use | ||||
// cp-to-llvm.sh to update the copy. See README.txt for more details. | // cp-to-llvm.sh to update the copy. See README.txt for more details. | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
#ifndef DEMANGLE_ITANIUMDEMANGLE_H | #ifndef DEMANGLE_ITANIUMDEMANGLE_H | ||||
#define DEMANGLE_ITANIUMDEMANGLE_H | #define DEMANGLE_ITANIUMDEMANGLE_H | ||||
// FIXME: (possibly) incomplete list of features that clang mangles that this | |||||
// file does not yet support: | |||||
// - C++ modules TS | |||||
#include "DemangleConfig.h" | #include "DemangleConfig.h" | ||||
#include "StringView.h" | #include "StringView.h" | ||||
#include "Utility.h" | #include "Utility.h" | ||||
#include <algorithm> | #include <algorithm> | ||||
#include <cassert> | #include <cassert> | ||||
#include <cctype> | #include <cctype> | ||||
#include <cstdio> | #include <cstdio> | ||||
#include <cstdlib> | #include <cstdlib> | ||||
Show All 22 Lines | #define FOR_EACH_NODE_KIND(X) \ | ||||
X(DynamicExceptionSpec) \ | X(DynamicExceptionSpec) \ | ||||
X(FunctionEncoding) \ | X(FunctionEncoding) \ | ||||
X(LiteralOperator) \ | X(LiteralOperator) \ | ||||
X(SpecialName) \ | X(SpecialName) \ | ||||
X(CtorVtableSpecialName) \ | X(CtorVtableSpecialName) \ | ||||
X(QualifiedName) \ | X(QualifiedName) \ | ||||
X(NestedName) \ | X(NestedName) \ | ||||
X(LocalName) \ | X(LocalName) \ | ||||
X(ModuleName) \ | |||||
X(ModuleEntity) \ | |||||
X(VectorType) \ | X(VectorType) \ | ||||
X(PixelVectorType) \ | X(PixelVectorType) \ | ||||
X(BinaryFPType) \ | X(BinaryFPType) \ | ||||
X(SyntheticTemplateParamName) \ | X(SyntheticTemplateParamName) \ | ||||
X(TypeTemplateParamDecl) \ | X(TypeTemplateParamDecl) \ | ||||
X(NonTypeTemplateParamDecl) \ | X(NonTypeTemplateParamDecl) \ | ||||
X(TemplateTemplateParamDecl) \ | X(TemplateTemplateParamDecl) \ | ||||
X(TemplateParamPackDecl) \ | X(TemplateParamPackDecl) \ | ||||
▲ Show 20 Lines • Show All 926 Lines • ▼ Show 20 Lines | struct NestedName : Node { | ||||
void printLeft(OutputBuffer &OB) const override { | void printLeft(OutputBuffer &OB) const override { | ||||
Qual->print(OB); | Qual->print(OB); | ||||
OB += "::"; | OB += "::"; | ||||
Name->print(OB); | Name->print(OB); | ||||
} | } | ||||
}; | }; | ||||
struct ModuleName : Node { | |||||
ModuleName *Parent; | |||||
Node *Name; | |||||
bool IsPartition; | |||||
ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false) | |||||
: Node(KModuleName), Parent(Parent_), Name(Name_), | |||||
IsPartition(IsPartition_) {} | |||||
template <typename Fn> void match(Fn F) const { F(Parent, Name); } | |||||
void printLeft(OutputBuffer &OB) const override { | |||||
if (Parent) | |||||
Parent->print(OB); | |||||
if (Parent || IsPartition) | |||||
OB += IsPartition ? ':' : '.'; | |||||
Name->print(OB); | |||||
} | |||||
}; | |||||
struct ModuleEntity : Node { | |||||
ModuleName *Module; | |||||
Node *Name; | |||||
ModuleEntity(ModuleName *Module_, Node *Name_) | |||||
: Node(KModuleEntity), Module(Module_), Name(Name_) {} | |||||
template <typename Fn> void match(Fn F) const { F(Module, Name); } | |||||
StringView getBaseName() const override { return Name->getBaseName(); } | |||||
void printLeft(OutputBuffer &OB) const override { | |||||
Name->print(OB); | |||||
OB += '@'; | |||||
Module->print(OB); | |||||
} | |||||
}; | |||||
struct LocalName : Node { | struct LocalName : Node { | ||||
Node *Encoding; | Node *Encoding; | ||||
Node *Entity; | Node *Entity; | ||||
LocalName(Node *Encoding_, Node *Entity_) | LocalName(Node *Encoding_, Node *Entity_) | ||||
: Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {} | : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {} | ||||
template<typename Fn> void match(Fn F) const { F(Encoding, Entity); } | template<typename Fn> void match(Fn F) const { F(Encoding, Entity); } | ||||
▲ Show 20 Lines • Show All 1,531 Lines • ▼ Show 20 Lines | bool resolveForwardTemplateRefs(NameState &State) { | ||||
ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin); | ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin); | ||||
return false; | return false; | ||||
} | } | ||||
/// Parse the <name> production> | /// Parse the <name> production> | ||||
Node *parseName(NameState *State = nullptr); | Node *parseName(NameState *State = nullptr); | ||||
Node *parseLocalName(NameState *State); | Node *parseLocalName(NameState *State); | ||||
Node *parseOperatorName(NameState *State); | Node *parseOperatorName(NameState *State); | ||||
Node *parseUnqualifiedName(NameState *State, Node *Scope); | bool parseModuleNameOpt(ModuleName *&Module); | ||||
Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module); | |||||
Node *parseUnnamedTypeName(NameState *State); | Node *parseUnnamedTypeName(NameState *State); | ||||
Node *parseSourceName(NameState *State); | Node *parseSourceName(NameState *State); | ||||
Node *parseUnscopedName(NameState *State); | Node *parseUnscopedName(NameState *State, bool *isSubstName); | ||||
Node *parseNestedName(NameState *State); | Node *parseNestedName(NameState *State); | ||||
Node *parseCtorDtorName(Node *&SoFar, NameState *State); | Node *parseCtorDtorName(Node *&SoFar, NameState *State); | ||||
Node *parseAbiTags(Node *N); | Node *parseAbiTags(Node *N); | ||||
struct OperatorInfo { | struct OperatorInfo { | ||||
enum OIKind : unsigned char { | enum OIKind : unsigned char { | ||||
Prefix, // Prefix unary: @ expr | Prefix, // Prefix unary: @ expr | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
template <typename Derived, typename Alloc> | template <typename Derived, typename Alloc> | ||||
Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) { | Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) { | ||||
if (look() == 'N') | if (look() == 'N') | ||||
return getDerived().parseNestedName(State); | return getDerived().parseNestedName(State); | ||||
if (look() == 'Z') | if (look() == 'Z') | ||||
return getDerived().parseLocalName(State); | return getDerived().parseLocalName(State); | ||||
Node *Result = nullptr; | Node *Result = nullptr; | ||||
bool IsSubst = look() == 'S' && look(1) != 't'; | bool IsSubst = false; | ||||
if (IsSubst) { | |||||
// A substitution must lead to: | Result = getDerived().parseUnscopedName(State, &IsSubst); | ||||
// ::= <unscoped-template-name> <template-args> | if (!Result) | ||||
Result = getDerived().parseSubstitution(); | |||||
} else { | |||||
// An unscoped name can be one of: | |||||
// ::= <unscoped-name> | |||||
// ::= <unscoped-template-name> <template-args> | |||||
Result = getDerived().parseUnscopedName(State); | |||||
} | |||||
if (Result == nullptr) | |||||
return nullptr; | return nullptr; | ||||
if (look() == 'I') { | if (look() == 'I') { | ||||
// ::= <unscoped-template-name> <template-args> | // ::= <unscoped-template-name> <template-args> | ||||
if (!IsSubst) | if (!IsSubst) | ||||
// An unscoped-template-name is substitutable. | // An unscoped-template-name is substitutable. | ||||
Subs.push_back(Result); | Subs.push_back(Result); | ||||
Node *TA = getDerived().parseTemplateArgs(State != nullptr); | Node *TA = getDerived().parseTemplateArgs(State != nullptr); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) { | ||||
return make<LocalName>(Encoding, Entity); | return make<LocalName>(Encoding, Entity); | ||||
} | } | ||||
// <unscoped-name> ::= [L]* <unqualified-name> | // <unscoped-name> ::= [L]* <unqualified-name> | ||||
// ::= St [L]* <unqualified-name> # ::std:: | // ::= St [L]* <unqualified-name> # ::std:: | ||||
// [*] extension | // [*] extension | ||||
template <typename Derived, typename Alloc> | template <typename Derived, typename Alloc> | ||||
Node * | Node * | ||||
AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) { | AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State, | ||||
bool *IsSubst) { | |||||
Node *Std = nullptr; | Node *Std = nullptr; | ||||
if (consumeIf("St")) { | if (consumeIf("St")) { | ||||
Std = make<NameType>("std"); | Std = make<NameType>("std"); | ||||
if (Std == nullptr) | if (Std == nullptr) | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
consumeIf('L'); | consumeIf('L'); | ||||
return getDerived().parseUnqualifiedName(State, Std); | Node *Res = nullptr; | ||||
ModuleName *Module = nullptr; | |||||
if (look() == 'S') { | |||||
Node *S = getDerived().parseSubstitution(); | |||||
if (!S) | |||||
return nullptr; | |||||
if (S->getKind() == Node::KModuleName) | |||||
Module = static_cast<ModuleName *>(S); | |||||
else if (IsSubst && Std == nullptr) { | |||||
Res = S; | |||||
*IsSubst = true; | |||||
} else { | |||||
return nullptr; | |||||
} | |||||
} | } | ||||
// <unqualified-name> ::= <operator-name> [abi-tags] | if (Res == nullptr) | ||||
// ::= <ctor-dtor-name> [<abi-tags>] | Res = getDerived().parseUnqualifiedName(State, Std, Module); | ||||
// ::= <source-name> [<abi-tags>] | |||||
// ::= <unnamed-type-name> [<abi-tags>] | return Res; | ||||
// ::= DC <source-name>+ E # structured binding declaration | } | ||||
template <typename Derived, typename Alloc> | |||||
Node * | // <unqualified-name> ::= [<module-name>] <operator-name> [<abi-tags>] | ||||
AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State, | // ::= [<module-name>] <ctor-dtor-name> [<abi-tags>] | ||||
Node *Scope) { | // ::= [<module-name>] <source-name> [<abi-tags>] | ||||
// ::= [<module-name>] <unnamed-type-name> [<abi-tags>] | |||||
// # structured binding declaration | |||||
// ::= [<module-name>] DC <source-name>+ E | |||||
template <typename Derived, typename Alloc> | |||||
Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName( | |||||
NameState *State, Node *Scope, ModuleName *Module) { | |||||
if (getDerived().parseModuleNameOpt(Module)) | |||||
return nullptr; | |||||
Node *Result; | Node *Result; | ||||
if (look() == 'U') | if (look() == 'U') { | ||||
Result = getDerived().parseUnnamedTypeName(State); | Result = getDerived().parseUnnamedTypeName(State); | ||||
else if (look() >= '1' && look() <= '9') | } else if (look() >= '1' && look() <= '9') { | ||||
Result = getDerived().parseSourceName(State); | Result = getDerived().parseSourceName(State); | ||||
else if (consumeIf("DC")) { | } else if (consumeIf("DC")) { | ||||
// Structured binding | // Structured binding | ||||
size_t BindingsBegin = Names.size(); | size_t BindingsBegin = Names.size(); | ||||
do { | do { | ||||
Node *Binding = getDerived().parseSourceName(State); | Node *Binding = getDerived().parseSourceName(State); | ||||
if (Binding == nullptr) | if (Binding == nullptr) | ||||
return nullptr; | return nullptr; | ||||
Names.push_back(Binding); | Names.push_back(Binding); | ||||
} while (!consumeIf('E')); | } while (!consumeIf('E')); | ||||
Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin)); | Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin)); | ||||
} else if (look() == 'C' || look() == 'D') { | } else if (look() == 'C' || look() == 'D') { | ||||
// A <ctor-dtor-name>. | // A <ctor-dtor-name>. | ||||
if (Scope == nullptr) | if (Scope == nullptr || Module != nullptr) | ||||
return nullptr; | return nullptr; | ||||
Result = getDerived().parseCtorDtorName(Scope, State); | Result = getDerived().parseCtorDtorName(Scope, State); | ||||
} else { | } else { | ||||
Result = getDerived().parseOperatorName(State); | Result = getDerived().parseOperatorName(State); | ||||
} | } | ||||
if (Module) | |||||
Result = make<ModuleEntity>(Module, Result); | |||||
if (Result != nullptr) | if (Result != nullptr) | ||||
Result = getDerived().parseAbiTags(Result); | Result = getDerived().parseAbiTags(Result); | ||||
if (Result != nullptr && Scope != nullptr) | if (Result != nullptr && Scope != nullptr) | ||||
Result = make<NestedName>(Scope, Result); | Result = make<NestedName>(Scope, Result); | ||||
return Result; | return Result; | ||||
} | } | ||||
// <module-name> ::= <module-subname> | |||||
// ::= <module-name> <module-subname> | |||||
// ::= <substitution> # passed in by caller | |||||
// <module-subname> ::= W <source-name> | |||||
// ::= W P <source-name> | |||||
template <typename Derived, typename Alloc> | |||||
bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt( | |||||
ModuleName *&Module) { | |||||
while (consumeIf('W')) { | |||||
bool IsPartition = consumeIf('P'); | |||||
dblaikie: Is the comment about `S` out of date, and should say `W` instead? | |||||
oops, I'd think'od that, it is indeed 'W' urnathan: oops, I'd think'od that, it is indeed 'W' | |||||
Node *Sub = getDerived().parseSourceName(nullptr); | |||||
if (!Sub) | |||||
return true; | |||||
Module = | |||||
static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition)); | |||||
Subs.push_back(Module); | |||||
} | |||||
return false; | |||||
} | |||||
// <unnamed-type-name> ::= Ut [<nonnegative number>] _ | // <unnamed-type-name> ::= Ut [<nonnegative number>] _ | ||||
// ::= <closure-type-name> | // ::= <closure-type-name> | ||||
// | // | ||||
// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ | // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ | ||||
// | // | ||||
// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters | // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters | ||||
template <typename Derived, typename Alloc> | template <typename Derived, typename Alloc> | ||||
Node * | Node * | ||||
▲ Show 20 Lines • Show All 357 Lines • ▼ Show 20 Lines | if (look() == 'T') { | ||||
if (State) | if (State) | ||||
State->EndsWithTemplateArgs = true; | State->EndsWithTemplateArgs = true; | ||||
SoFar = make<NameWithTemplateArgs>(SoFar, TA); | SoFar = make<NameWithTemplateArgs>(SoFar, TA); | ||||
} else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) { | } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) { | ||||
// ::= <decltype> | // ::= <decltype> | ||||
if (SoFar != nullptr) | if (SoFar != nullptr) | ||||
return nullptr; // Cannot have a prefix. | return nullptr; // Cannot have a prefix. | ||||
SoFar = getDerived().parseDecltype(); | SoFar = getDerived().parseDecltype(); | ||||
} else if (look() == 'S') { | } else { | ||||
ModuleName *Module = nullptr; | |||||
bool IsLocal = consumeIf('L'); // extension | |||||
if (look() == 'S') { | |||||
// ::= <substitution> | // ::= <substitution> | ||||
if (SoFar != nullptr) | Node *S = nullptr; | ||||
return nullptr; // Cannot have a prefix. | |||||
if (look(1) == 't') { | if (look(1) == 't') { | ||||
// parseSubstition does not handle 'St'. | |||||
First += 2; | First += 2; | ||||
SoFar = make<NameType>("std"); | S = make<NameType>("std"); | ||||
} else { | } else { | ||||
SoFar = getDerived().parseSubstitution(); | S = getDerived().parseSubstitution(); | ||||
} | } | ||||
if (SoFar == nullptr) | if (!S) | ||||
return nullptr; | return nullptr; | ||||
continue; // Do not push a new substitution. | if (S->getKind() == Node::KModuleName) { | ||||
Module = static_cast<ModuleName *>(S); | |||||
} else if (SoFar != nullptr || IsLocal) { | |||||
return nullptr; // Cannot have a prefix. | |||||
} else { | } else { | ||||
consumeIf('L'); // extension | SoFar = S; | ||||
continue; // Do not push a new substitution. | |||||
} | |||||
} | |||||
// ::= [<prefix>] <unqualified-name> | // ::= [<prefix>] <unqualified-name> | ||||
SoFar = getDerived().parseUnqualifiedName(State, SoFar); | SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module); | ||||
} | } | ||||
if (SoFar == nullptr) | if (SoFar == nullptr) | ||||
return nullptr; | return nullptr; | ||||
Subs.push_back(SoFar); | Subs.push_back(SoFar); | ||||
// No longer used. | // No longer used. | ||||
// <data-member-prefix> := <member source-name> [<template-args>] M | // <data-member-prefix> := <member source-name> [<template-args>] M | ||||
consumeIf('M'); | consumeIf('M'); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 796 Lines • ▼ Show 20 Lines | case 'G': { | ||||
if (P == nullptr) | if (P == nullptr) | ||||
return P; | return P; | ||||
Result = make<PostfixQualifiedType>(P, " imaginary"); | Result = make<PostfixQualifiedType>(P, " imaginary"); | ||||
break; | break; | ||||
} | } | ||||
// ::= <substitution> # See Compression below | // ::= <substitution> # See Compression below | ||||
case 'S': { | case 'S': { | ||||
if (look(1) != 't') { | if (look(1) != 't') { | ||||
Result = getDerived().parseSubstitution(); | bool IsSubst = false; | ||||
if (Result == nullptr) | Result = getDerived().parseUnscopedName(nullptr, &IsSubst); | ||||
if (!Result) | |||||
return nullptr; | return nullptr; | ||||
// Sub could be either of: | // Sub could be either of: | ||||
// <type> ::= <substitution> | // <type> ::= <substitution> | ||||
// <type> ::= <template-template-param> <template-args> | // <type> ::= <template-template-param> <template-args> | ||||
// | // | ||||
// <template-template-param> ::= <template-param> | // <template-template-param> ::= <template-param> | ||||
// ::= <substitution> | // ::= <substitution> | ||||
// | // | ||||
// If this is followed by some <template-args>, and we're permitted to | // If this is followed by some <template-args>, and we're permitted to | ||||
// parse them, take the second production. | // parse them, take the second production. | ||||
if (TryToParseTemplateArgs && look() == 'I') { | if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) { | ||||
if (!IsSubst) | |||||
Subs.push_back(Result); | |||||
Node *TA = getDerived().parseTemplateArgs(); | Node *TA = getDerived().parseTemplateArgs(); | ||||
if (TA == nullptr) | if (TA == nullptr) | ||||
return nullptr; | return nullptr; | ||||
Result = make<NameWithTemplateArgs>(Result, TA); | Result = make<NameWithTemplateArgs>(Result, TA); | ||||
} else { | } else if (IsSubst) { | ||||
// If all we parsed was a substitution, don't re-insert into the | // If all we parsed was a substitution, don't re-insert into the | ||||
// substitution table. | // substitution table. | ||||
return Result; | return Result; | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
DEMANGLE_FALLTHROUGH; | DEMANGLE_FALLTHROUGH; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 732 Lines • ▼ Show 20 Lines | |||||
// ::= TI <type> # typeinfo structure | // ::= TI <type> # typeinfo structure | ||||
// ::= TS <type> # typeinfo name (null-terminated byte string) | // ::= TS <type> # typeinfo name (null-terminated byte string) | ||||
// ::= Tc <call-offset> <call-offset> <base encoding> | // ::= Tc <call-offset> <call-offset> <base encoding> | ||||
// # base is the nominal target function of thunk | // # base is the nominal target function of thunk | ||||
// # first call-offset is 'this' adjustment | // # first call-offset is 'this' adjustment | ||||
// # second call-offset is result adjustment | // # second call-offset is result adjustment | ||||
// ::= T <call-offset> <base encoding> | // ::= T <call-offset> <base encoding> | ||||
// # base is the nominal target function of thunk | // # base is the nominal target function of thunk | ||||
// ::= GV <object name> # Guard variable for one-time initialization | // # Guard variable for one-time initialization | ||||
// ::= GV <object name> | |||||
// # No <type> | // # No <type> | ||||
// ::= TW <object name> # Thread-local wrapper | // ::= TW <object name> # Thread-local wrapper | ||||
// ::= TH <object name> # Thread-local initialization | // ::= TH <object name> # Thread-local initialization | ||||
// ::= GR <object name> _ # First temporary | // ::= GR <object name> _ # First temporary | ||||
// ::= GR <object name> <seq-id> _ # Subsequent temporaries | // ::= GR <object name> <seq-id> _ # Subsequent temporaries | ||||
// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first | // # construction vtable for second-in-first | ||||
// extension ::= TC <first type> <number> _ <second type> | |||||
// extension ::= GR <object name> # reference temporary for object | // extension ::= GR <object name> # reference temporary for object | ||||
// extension ::= GI <module name> # module global initializer | |||||
template <typename Derived, typename Alloc> | template <typename Derived, typename Alloc> | ||||
Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() { | Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() { | ||||
switch (look()) { | switch (look()) { | ||||
case 'T': | case 'T': | ||||
switch (look(1)) { | switch (look(1)) { | ||||
// TA <template-arg> # template parameter object | // TA <template-arg> # template parameter object | ||||
// | // | ||||
// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63 | // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63 | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | case 'R': { | ||||
if (Name == nullptr) | if (Name == nullptr) | ||||
return nullptr; | return nullptr; | ||||
size_t Count; | size_t Count; | ||||
bool ParsedSeqId = !parseSeqId(&Count); | bool ParsedSeqId = !parseSeqId(&Count); | ||||
if (!consumeIf('_') && ParsedSeqId) | if (!consumeIf('_') && ParsedSeqId) | ||||
return nullptr; | return nullptr; | ||||
return make<SpecialName>("reference temporary for ", Name); | return make<SpecialName>("reference temporary for ", Name); | ||||
} | } | ||||
// GI <module-name> v | |||||
case 'I': { | |||||
First += 2; | |||||
ModuleName *Module = nullptr; | |||||
if (getDerived().parseModuleNameOpt(Module)) | |||||
return nullptr; | |||||
if (Module == nullptr) | |||||
return nullptr; | |||||
return make<SpecialName>("initializer for module ", Module); | |||||
} | |||||
} | } | ||||
} | } | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
// <encoding> ::= <function name> <bare-function-type> | // <encoding> ::= <function name> <bare-function-type> | ||||
// ::= <data name> | // ::= <data name> | ||||
// ::= <special-name> | // ::= <special-name> | ||||
▲ Show 20 Lines • Show All 485 Lines • Show Last 20 Lines |
Is the comment about S out of date, and should say W instead?