Index: include/llvm/Demangle/Canonicalize.h =================================================================== --- /dev/null +++ include/llvm/Demangle/Canonicalize.h @@ -0,0 +1,88 @@ +//===--- Canonicalize.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEMANGLE_CANONICALIZE_H +#define LLVM_DEMANGLE_CANONICALIZE_H + +#include "llvm/ADT/StringRef.h" + +#include + +namespace llvm { +/// Canonicalizer for mangled names. +/// +/// This class allows specifying a list of "equivalent" manglings. For example, +/// you can specify that Ss is equivalent to +/// NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE +/// and then manglings that refer to libstdc++'s 'std::string' will be +/// considered equivalent to manglings that are the same except that they refer +/// to libc++'s 'std::string'. +/// +/// This can be used when data (eg, profiling data) is available for a version +/// of a program built in a different configuration, with correspondingly +/// different manglings. +class ItaniumManglingCanonicalizer { +public: + ItaniumManglingCanonicalizer(); + ItaniumManglingCanonicalizer(const ItaniumManglingCanonicalizer &) = delete; + void operator=(const ItaniumManglingCanonicalizer &) = delete; + ~ItaniumManglingCanonicalizer(); + + enum class EquivalenceError { + Success, + + /// Both the equivalent manglings have already been used as components of + /// some other mangling we've looked at. It's too late to add this + /// equivalence. + ManglingAlreadyUsed, + + /// The first equivalent mangling is invalid. + InvalidFirstMangling, + + /// The second equivalent mangling is invalid. + InvalidSecondMangling, + }; + + enum class FragmentKind { + /// The mangling fragment is a (or a predefined ). + Name, + /// The mangling fragment is a . + Type, + /// The mangling fragment is an . + Encoding, + }; + + /// Add an equivalence between \p First and \p Second. Both manglings must + /// live at least as long as the canonicalizer. + EquivalenceError addEquivalence(FragmentKind Kind, StringRef First, + StringRef Second); + + using Key = uintptr_t; + + /// Form a canonical key for the specified mangling. They key will be the + /// same for all equivalent manglings, and different for any two + /// non-equivalent manglings, but is otherwise unspecified. + /// + /// Returns Key() if (and only if) the mangling is not a valid Itanium C++ + /// ABI mangling. + /// + /// The string denoted by Mangling must live as long as the canonicalizer. + Key canonicalize(StringRef Mangling); + + /// Find a canonical key for the specified mangling, if one has already been + /// formed. Otherwise returns Key(). + Key lookup(StringRef Mangling); + +private: + struct Impl; + Impl *P; +}; +} // namespace llvm + +#endif Index: include/llvm/LTO/Config.h =================================================================== --- include/llvm/LTO/Config.h +++ include/llvm/LTO/Config.h @@ -73,6 +73,9 @@ /// Sample PGO profile path. std::string SampleProfile; + /// Name remapping file for profile data. + std::string ProfileRemapping; + /// The directory to store .dwo files. std::string DwoDir; Index: include/llvm/Passes/PassBuilder.h =================================================================== --- include/llvm/Passes/PassBuilder.h +++ include/llvm/Passes/PassBuilder.h @@ -32,10 +32,13 @@ /// A struct capturing PGO tunables. struct PGOOptions { PGOOptions(std::string ProfileGenFile = "", std::string ProfileUseFile = "", - std::string SampleProfileFile = "", bool RunProfileGen = false, - bool SamplePGOSupport = false) + std::string SampleProfileFile = "", + std::string ProfileRemappingFile = "", + bool RunProfileGen = false, bool SamplePGOSupport = false) : ProfileGenFile(ProfileGenFile), ProfileUseFile(ProfileUseFile), - SampleProfileFile(SampleProfileFile), RunProfileGen(RunProfileGen), + SampleProfileFile(SampleProfileFile), + ProfileRemappingFile(ProfileRemappingFile), + RunProfileGen(RunProfileGen), SamplePGOSupport(SamplePGOSupport || !SampleProfileFile.empty()) { assert((RunProfileGen || !SampleProfileFile.empty() || @@ -45,6 +48,7 @@ std::string ProfileGenFile; std::string ProfileUseFile; std::string SampleProfileFile; + std::string ProfileRemappingFile; bool RunProfileGen; bool SamplePGOSupport; }; @@ -585,7 +589,8 @@ void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, OptimizationLevel Level, bool RunProfileGen, std::string ProfileGenFile, - std::string ProfileUseFile); + std::string ProfileUseFile, + std::string ProfileRemappingFile); void invokePeepholeEPCallbacks(FunctionPassManager &, OptimizationLevel); Index: include/llvm/ProfileData/InstrProfReader.h =================================================================== --- include/llvm/ProfileData/InstrProfReader.h +++ include/llvm/ProfileData/InstrProfReader.h @@ -348,6 +348,9 @@ using OnDiskHashTableImplV3 = OnDiskIterableChainedHashTable; +template +class InstrProfReaderItaniumRemapper; + template class InstrProfReaderIndex : public InstrProfReaderIndexBase { private: @@ -355,6 +358,8 @@ typename HashTableImpl::data_iterator RecordIterator; uint64_t FormatVersion; + friend class InstrProfReaderItaniumRemapper; + public: InstrProfReaderIndex(const unsigned char *Buckets, const unsigned char *const Payload, @@ -391,6 +396,8 @@ private: /// The profile data file contents. std::unique_ptr DataBuffer; + /// The profile remapping file contents. + std::unique_ptr RemappingBuffer; /// The index into the profile data. std::unique_ptr Index; /// Profile summary data. @@ -404,8 +411,11 @@ const unsigned char *Cur); public: - IndexedInstrProfReader(std::unique_ptr DataBuffer) - : DataBuffer(std::move(DataBuffer)), RecordIndex(0) {} + IndexedInstrProfReader( + std::unique_ptr DataBuffer, + std::unique_ptr RemappingBuffer = nullptr) + : DataBuffer(std::move(DataBuffer)), + RemappingBuffer(std::move(RemappingBuffer)), RecordIndex(0) {} IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; @@ -434,10 +444,11 @@ /// Factory method to create an indexed reader. static Expected> - create(const Twine &Path); + create(const Twine &Path, const Twine &RemappingPath = ""); static Expected> - create(std::unique_ptr Buffer); + create(std::unique_ptr Buffer, + std::unique_ptr RemappingBuffer = nullptr); // Used for testing purpose only. void setValueProfDataEndianness(support::endianness Endianness) { Index: include/llvm/ProfileData/ProfRemappingReader.h =================================================================== --- /dev/null +++ include/llvm/ProfileData/ProfRemappingReader.h @@ -0,0 +1,125 @@ +//===- ProfRemappingReader.h - Read profile remapping file ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions needed for reading and applying profile +// remapping files. +// +// NOTE: If you are making changes to this file format, please remember +// to document them in the Clang documentation at +// tools/clang/docs/UsersManual.rst. +// +// File format +// ----------- +// +// The profile remappings are written as an ASCII text file. Blank lines and +// lines starting with a # are ignored. All other lines specify a kind of +// mangled name fragment, along with two fragments of that kind that should +// be treated as equivalent, separated by spaces. +// +// See http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling for a +// description of the Itanium name mangling scheme. +// +// The accepted fragment kinds are: +// +// * name A , such as 6foobar or St3__1 +// * type A , such as Ss or N4llvm9StringRefE +// * encoding An (a complete mangling without the leading _Z) +// +// For example: +// +// # Ignore int / long differences to allow profile reuse between +// # 32-bit and 64-bit builds with differing size_t / ptrdiff_t / intptr_t. +// type i l +// type j m +// +// # Ignore differences between libc++ and libstdc++, and between libstdc++'s +// # C++98 and C++11 ABIs. +// name 3std St3__1 +// name 3std St7__cxx11 +// +// # Substitutions must be remapped separately from namespace 'std' for now. +// name Sa NSt3__19allocatorE +// name Sb NSt3__112basic_stringE +// type Ss NSt3__112basic_stringIcSt11char_traitsIcESaE +// # ... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_PROFREMAPPINGREADER_H +#define LLVM_PROFILEDATA_PROFREMAPPINGREADER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Demangle/Canonicalize.h" + +namespace llvm { + +class ProfileRemappingParseError + : public ErrorInfo { +public: + ProfileRemappingParseError(StringRef File, int64_t Line, Twine Message) + : File(File), Line(Line), Message(Message.str()) {} + + void log(llvm::raw_ostream &OS) const override { + OS << File << ':' << Line << ": " << Message; + } + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } + + StringRef getFileName() const { return File; } + int64_t getLineNum() const { return Line; } + StringRef getMessage() const { return Message; } + + static char ID; + +private: + std::string File; + int64_t Line; + std::string Message; +}; + +/// Profile name remapper. +/// +/// Remaps the symbol names in profile data to match those in the program +/// according to a set of rules specified in a given file. +class ItaniumProfileRemappingReader { +public: + /// Read remappings from the given buffer, which must live as long as + /// the remapper. + Error read(MemoryBuffer &B); + + using Key = ItaniumManglingCanonicalizer::Key; + + /// Map the given function name from the profiling data into a profile + /// data key. The result will be Key() if the name cannot be remapped. + Key remap(StringRef FunctionName) { + return Canonicalizer.canonicalize(FunctionName); + } + + /// Map the given function name from the program into a profile data key. + /// + /// The result will be Key() if the name has no corresponding entry in the + /// profile data, in which case the original name should be looked up in the + /// profile data. + /// + /// There is no guarantee that return values other than Key() have ever been + /// returned by remap(...), but this should be rare. + Key lookup(StringRef FunctionName) { + return Canonicalizer.lookup(FunctionName); + } + +private: + ItaniumManglingCanonicalizer Canonicalizer; +}; + +} // end namespace llvm + +#endif // LLVM_PROFILEDATA_PROFREMAPPINGREADER_H Index: include/llvm/ProfileData/SampleProfReader.h =================================================================== --- include/llvm/ProfileData/SampleProfReader.h +++ include/llvm/ProfileData/SampleProfReader.h @@ -219,6 +219,7 @@ #include "llvm/IR/ProfileSummary.h" #include "llvm/ProfileData/GCOV.h" #include "llvm/ProfileData/SampleProf.h" +#include "llvm/ProfileData/ProfRemappingReader.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" @@ -287,11 +288,16 @@ // The function name may have been updated by adding suffix. In sample // profile, the function names are all stripped, so we need to strip // the function name suffix before matching with profile. - StringRef Fname = F.getName().split('.').first; + return getSamplesFor(F.getName().split('.').first); + } + + /// Return the samples collected for function \p F. + virtual FunctionSamples *getSamplesFor(StringRef Fname) { std::string FGUID; Fname = getRepInFormat(Fname, getFormat(), FGUID); - if (Profiles.count(Fname)) - return &Profiles[Fname]; + auto It = Profiles.find(Fname); + if (It != Profiles.end()) + return &It->second; return nullptr; } @@ -335,6 +341,12 @@ /// Profile summary information. std::unique_ptr Summary; + /// Take ownership of the summary of this reader. + static std::unique_ptr + takeSummary(SampleProfileReader &Reader) { + return std::move(Reader.Summary); + } + /// Compute summary for this profile. void computeSummary(); @@ -503,6 +515,37 @@ static const uint32_t GCOVTagAFDOFunction = 0xac000000; }; +class SampleProfileReaderItaniumRemapper : public SampleProfileReader { +public: + SampleProfileReaderItaniumRemapper( + std::unique_ptr B, LLVMContext &C, + std::unique_ptr Underlying) + : SampleProfileReader(std::move(B), C, Underlying->getFormat()) { + Profiles = std::move(Underlying->getProfiles()); + Summary = takeSummary(*Underlying); + } + + /// Create a remapped sample profile from the given remapping file and + /// underlying samples. + static ErrorOr> + create(const Twine &Filename, LLVMContext &C, + std::unique_ptr Underlying); + + /// Read and validate the file header. + std::error_code readHeader() override { return sampleprof_error::success; } + + /// Read sample profiles from the associated file. + std::error_code read() override; + + /// Return the samples collected for function \p F. + FunctionSamples *getSamplesFor(StringRef FunctionName) override; + using SampleProfileReader::getSamplesFor; + +private: + ItaniumProfileRemappingReader Remappings; + DenseMap SampleMap; +}; + } // end namespace sampleprof } // end namespace llvm Index: include/llvm/Transforms/IPO/SampleProfile.h =================================================================== --- include/llvm/Transforms/IPO/SampleProfile.h +++ include/llvm/Transforms/IPO/SampleProfile.h @@ -25,13 +25,16 @@ /// The sample profiler data loader pass. class SampleProfileLoaderPass : public PassInfoMixin { public: - SampleProfileLoaderPass(std::string File = "", bool IsThinLTOPreLink = false) - : ProfileFileName(File), IsThinLTOPreLink(IsThinLTOPreLink) {} + SampleProfileLoaderPass(std::string File = "", std::string RemappingFile = "", + bool IsThinLTOPreLink = false) + : ProfileFileName(File), ProfileRemappingFileName(RemappingFile), + IsThinLTOPreLink(IsThinLTOPreLink) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); private: std::string ProfileFileName; + std::string ProfileRemappingFileName; bool IsThinLTOPreLink; }; Index: include/llvm/Transforms/Instrumentation/PGOInstrumentation.h =================================================================== --- include/llvm/Transforms/Instrumentation/PGOInstrumentation.h +++ include/llvm/Transforms/Instrumentation/PGOInstrumentation.h @@ -36,12 +36,14 @@ /// The profile annotation (profile-instr-use) pass for IR based PGO. class PGOInstrumentationUse : public PassInfoMixin { public: - PGOInstrumentationUse(std::string Filename = ""); + PGOInstrumentationUse(std::string Filename = "", + std::string RemappingFilename = ""); PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); private: std::string ProfileFileName; + std::string ProfileRemappingFileName; }; /// The indirect function call promotion pass. Index: lib/Demangle/ItaniumDemangle.cpp =================================================================== --- lib/Demangle/ItaniumDemangle.cpp +++ lib/Demangle/ItaniumDemangle.cpp @@ -11,10 +11,19 @@ // file does not yet support: // - C++ modules TS +#include "llvm/Demangle/Demangle.h" + #include "Compiler.h" #include "StringView.h" #include "Utility.h" -#include "llvm/Demangle/Demangle.h" + +#ifndef STANDALONE_DEMANGLER +#include "llvm/Demangle/Canonicalize.h" + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/StringRef.h" +#endif #include #include @@ -26,6 +35,12 @@ #include namespace { +#ifndef STANDALONE_DEMANGLER + void addString(llvm::FoldingSetNodeID &ID, StringView Str) { + ID.AddString(llvm::StringRef(Str.begin(), Str.size())); + } +#endif + // Base class of all AST nodes. The AST is built by the parser, then is // traversed by the printLeft/Right functions to produce a demangled string. class Node { @@ -64,7 +79,6 @@ KForwardTemplateReference, KNameWithTemplateArgs, KGlobalQualifiedName, - KStdQualifiedName, KExpandedSpecialSubstitution, KSpecialSubstitution, KCtorDtorName, @@ -100,6 +114,20 @@ : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {} +#ifndef STANDALONE_DEMANGLER + /// Compute a FoldingSetNodeID for the node created by invoking the + /// constructor with the given arguments. + static void profileCtor(llvm::FoldingSetNodeID &ID, Kind K, Cache = Cache::No, + Cache = Cache::No, Cache = Cache::No) { + ID.AddInteger(K); + // Don't profile the cached values. They're not part of the value of the + // node for profiling purposes. + } + + /// Compute a FoldingSetNodeID for this node. + virtual void profile(llvm::FoldingSetNodeID &ID) const { profileCtor(ID, K); } +#endif + bool hasRHSComponent(OutputStream &S) const { if (RHSComponentCache != Cache::Unknown) return RHSComponentCache == Cache::Yes; @@ -171,6 +199,14 @@ NodeArray(Node **Elements_, size_t NumElements_) : Elements(Elements_), NumElements(NumElements_) {} +#ifndef STANDALONE_DEMANGLER + void profile(llvm::FoldingSetNodeID &ID) { + ID.AddInteger(size()); + for (Node *N : *this) + ID.AddPointer(N); + } +#endif + bool empty() const { return NumElements == 0; } size_t size() const { return NumElements; } @@ -203,6 +239,17 @@ struct NodeArrayNode : Node { NodeArray Array; NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeArray A) { + Node::profileCtor(ID, KNodeArrayNode); + A.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Array); + } +#endif + void printLeft(OutputStream &S) const override { Array.printWithComma(S); } @@ -213,9 +260,21 @@ const StringView Suffix; public: - DotSuffix(Node *Prefix_, StringView Suffix_) + DotSuffix(const Node *Prefix_, StringView Suffix_) : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Prefix, + StringView Suffix) { + Node::profileCtor(ID, KDotSuffix); + ID.AddPointer(Prefix); + addString(ID, Suffix); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Prefix, Suffix); + } +#endif + void printLeft(OutputStream &s) const override { Prefix->print(s); s += " ("; @@ -229,9 +288,21 @@ StringView Ext; public: - VendorExtQualType(Node *Ty_, StringView Ext_) + VendorExtQualType(const Node *Ty_, StringView Ext_) : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Ty, + StringView Ext) { + Node::profileCtor(ID, KVendorExtQualType); + ID.AddPointer(Ty); + addString(ID, Ext); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Ty, Ext); + } +#endif + void printLeft(OutputStream &S) const override { Ty->print(S); S += " "; @@ -271,11 +342,23 @@ } public: - QualType(Node *Child_, Qualifiers Quals_) + QualType(const Node *Child_, Qualifiers Quals_) : Node(KQualType, Child_->RHSComponentCache, Child_->ArrayCache, Child_->FunctionCache), Quals(Quals_), Child(Child_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Child, + Qualifiers Quals) { + Node::profileCtor(ID, KQualType); + ID.AddPointer(Child); + ID.AddInteger(Quals); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Child, Quals); + } +#endif + bool hasRHSComponentSlow(OutputStream &S) const override { return Child->hasRHSComponent(S); } @@ -298,9 +381,19 @@ const Node *Ty; public: - ConversionOperatorType(Node *Ty_) + ConversionOperatorType(const Node *Ty_) : Node(KConversionOperatorType), Ty(Ty_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Ty) { + Node::profileCtor(ID, KConversionOperatorType); + ID.AddPointer(Ty); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Ty); + } +#endif + void printLeft(OutputStream &S) const override { S += "operator "; Ty->print(S); @@ -315,6 +408,18 @@ PostfixQualifiedType(Node *Ty_, StringView Postfix_) : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Ty, + StringView Postfix) { + Node::profileCtor(ID, KPostfixQualifiedType); + ID.AddPointer(Ty); + addString(ID, Postfix); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Ty, Postfix); + } +#endif + void printLeft(OutputStream &s) const override { Ty->printLeft(s); s += Postfix; @@ -327,6 +432,16 @@ public: NameType(StringView Name_) : Node(KNameType), Name(Name_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView Name) { + Node::profileCtor(ID, KNameType); + addString(ID, Name); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Name); + } +#endif + StringView getName() const { return Name; } StringView getBaseName() const override { return Name; } @@ -340,6 +455,18 @@ ElaboratedTypeSpefType(StringView Kind_, Node *Child_) : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView Kind, + Node *Child) { + Node::profileCtor(ID, KElaboratedTypeSpefType); + addString(ID, Kind); + ID.AddPointer(Child); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Kind, Child); + } +#endif + void printLeft(OutputStream &S) const override { S += Kind; S += ' '; @@ -356,6 +483,18 @@ Base_->ArrayCache, Base_->FunctionCache), Base(Base_), Tag(Tag_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, Node *Base, + StringView Tag) { + Node::profileCtor(ID, KAbiTagAttr); + ID.AddPointer(Base); + addString(ID, Tag); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Base, Tag); + } +#endif + void printLeft(OutputStream &S) const override { Base->printLeft(S); S += "[abi:"; @@ -370,6 +509,16 @@ EnableIfAttr(NodeArray Conditions_) : Node(KEnableIfAttr), Conditions(Conditions_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeArray Conditions) { + Node::profileCtor(ID, KEnableIfAttr); + Conditions.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Conditions); + } +#endif + void printLeft(OutputStream &S) const override { S += " [enable_if:"; Conditions.printWithComma(S); @@ -378,18 +527,30 @@ }; class ObjCProtoName : public Node { - Node *Ty; + const Node *Ty; StringView Protocol; friend class PointerType; public: - ObjCProtoName(Node *Ty_, StringView Protocol_) + ObjCProtoName(const Node *Ty_, StringView Protocol_) : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Ty, + StringView Protocol) { + Node::profileCtor(ID, KObjCProtoName); + ID.AddPointer(Ty); + addString(ID, Protocol); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Ty, Protocol); + } +#endif + bool isObjCObject() const { return Ty->getKind() == KNameType && - static_cast(Ty)->getName() == "objc_object"; + static_cast(Ty)->getName() == "objc_object"; } void printLeft(OutputStream &S) const override { @@ -404,10 +565,20 @@ const Node *Pointee; public: - PointerType(Node *Pointee_) + PointerType(const Node *Pointee_) : Node(KPointerType, Pointee_->RHSComponentCache), Pointee(Pointee_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Pointee) { + Node::profileCtor(ID, KPointerType); + ID.AddPointer(Pointee); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Pointee); + } +#endif + bool hasRHSComponentSlow(OutputStream &S) const override { return Pointee->hasRHSComponent(S); } @@ -469,10 +640,22 @@ } public: - ReferenceType(Node *Pointee_, ReferenceKind RK_) + ReferenceType(const Node *Pointee_, ReferenceKind RK_) : Node(KReferenceType, Pointee_->RHSComponentCache), Pointee(Pointee_), RK(RK_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Pointee, + ReferenceKind RK) { + Node::profileCtor(ID, KReferenceType); + ID.AddPointer(Pointee); + ID.AddInteger((unsigned)RK); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Pointee, RK); + } +#endif + bool hasRHSComponentSlow(OutputStream &S) const override { return Pointee->hasRHSComponent(S); } @@ -506,10 +689,22 @@ const Node *MemberType; public: - PointerToMemberType(Node *ClassType_, Node *MemberType_) + PointerToMemberType(const Node *ClassType_, const Node *MemberType_) : Node(KPointerToMemberType, MemberType_->RHSComponentCache), ClassType(ClassType_), MemberType(MemberType_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *ClassType, + const Node *MemberType) { + Node::profileCtor(ID, KPointerToMemberType); + ID.AddPointer(ClassType); + ID.AddPointer(MemberType); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, ClassType, MemberType); + } +#endif + bool hasRHSComponentSlow(OutputStream &S) const override { return MemberType->hasRHSComponent(S); } @@ -551,6 +746,18 @@ : First(static_cast(N)), Second(nullptr) {} NodeOrString() : First(nullptr), Second(nullptr) {} + void profile(llvm::FoldingSetNodeID &ID) { + if (isEmpty()) { + ID.AddInteger(0); + } else if (isNode()) { + ID.AddInteger(1); + ID.AddPointer(asNode()); + } else { + ID.AddInteger(2); + addString(ID, asString()); + } + } + bool isString() const { return Second && First; } bool isNode() const { return First && !Second; } bool isEmpty() const { return !First && !Second; } @@ -568,22 +775,27 @@ }; class ArrayType final : public Node { - Node *Base; + const Node *Base; NodeOrString Dimension; public: - ArrayType(Node *Base_, NodeOrString Dimension_) + ArrayType(const Node *Base_, NodeOrString Dimension_ = NodeOrString()) : Node(KArrayType, /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::Yes), Base(Base_), Dimension(Dimension_) {} - // Incomplete array type. - ArrayType(Node *Base_) - : Node(KArrayType, - /*RHSComponentCache=*/Cache::Yes, - /*ArrayCache=*/Cache::Yes), - Base(Base_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Base, + NodeOrString Dimension = NodeOrString()) { + Node::profileCtor(ID, KArrayType); + ID.AddPointer(Base); + Dimension.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Base, Dimension); + } +#endif bool hasRHSComponentSlow(OutputStream &) const override { return true; } bool hasArraySlow(OutputStream &) const override { return true; } @@ -604,21 +816,37 @@ }; class FunctionType final : public Node { - Node *Ret; + const Node *Ret; NodeArray Params; Qualifiers CVQuals; FunctionRefQual RefQual; - Node *ExceptionSpec; + const Node *ExceptionSpec; public: - FunctionType(Node *Ret_, NodeArray Params_, Qualifiers CVQuals_, - FunctionRefQual RefQual_, Node *ExceptionSpec_) + FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_, + FunctionRefQual RefQual_, const Node *ExceptionSpec_) : Node(KFunctionType, /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No, /*FunctionCache=*/Cache::Yes), Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_), ExceptionSpec(ExceptionSpec_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Ret, + NodeArray Params, Qualifiers CVQuals, + FunctionRefQual RefQual, const Node *ExceptionSpec) { + Node::profileCtor(ID, KFunctionType); + ID.AddPointer(Ret); + Params.profile(ID); + ID.AddInteger((unsigned)CVQuals); + ID.AddInteger((unsigned)RefQual); + ID.AddPointer(ExceptionSpec); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Ret, Params, CVQuals, RefQual, ExceptionSpec); + } +#endif + bool hasRHSComponentSlow(OutputStream &) const override { return true; } bool hasFunctionSlow(OutputStream &) const override { return true; } @@ -660,9 +888,19 @@ }; class NoexceptSpec : public Node { - Node *E; + const Node *E; public: - NoexceptSpec(Node *E_) : Node(KNoexceptSpec), E(E_) {} + NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *E) { + Node::profileCtor(ID, KNoexceptSpec); + ID.AddPointer(E); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, E); + } +#endif void printLeft(OutputStream &S) const override { S += "noexcept("; @@ -677,6 +915,16 @@ DynamicExceptionSpec(NodeArray Types_) : Node(KDynamicExceptionSpec), Types(Types_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeArray Types) { + Node::profileCtor(ID, KDynamicExceptionSpec); + Types.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Types); + } +#endif + void printLeft(OutputStream &S) const override { S += "throw("; Types.printWithComma(S); @@ -685,31 +933,49 @@ }; class FunctionEncoding final : public Node { - Node *Ret; - Node *Name; + const Node *Ret; + const Node *Name; NodeArray Params; - Node *Attrs; + const Node *Attrs; Qualifiers CVQuals; FunctionRefQual RefQual; public: - FunctionEncoding(Node *Ret_, Node *Name_, NodeArray Params_, - Node *Attrs_, Qualifiers CVQuals_, FunctionRefQual RefQual_) + FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_, + const Node *Attrs_, Qualifiers CVQuals_, + FunctionRefQual RefQual_) : Node(KFunctionEncoding, /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No, /*FunctionCache=*/Cache::Yes), Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_), CVQuals(CVQuals_), RefQual(RefQual_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Ret, + const Node *Name, NodeArray Params, const Node *Attrs, + Qualifiers CVQuals, FunctionRefQual RefQual) { + Node::profileCtor(ID, KFunctionEncoding); + ID.AddPointer(Ret); + ID.AddPointer(Name); + Params.profile(ID); + ID.AddPointer(Attrs); + ID.AddInteger((unsigned)CVQuals); + ID.AddInteger((unsigned)RefQual); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Ret, Name, Params, Attrs, CVQuals, RefQual); + } +#endif + Qualifiers getCVQuals() const { return CVQuals; } FunctionRefQual getRefQual() const { return RefQual; } NodeArray getParams() const { return Params; } - Node *getReturnType() const { return Ret; } + const Node *getReturnType() const { return Ret; } bool hasRHSComponentSlow(OutputStream &) const override { return true; } bool hasFunctionSlow(OutputStream &) const override { return true; } - Node *getName() { return const_cast(Name); } + const Node *getName() const { return Name; } void printLeft(OutputStream &S) const override { if (Ret) { @@ -748,7 +1014,18 @@ const Node *OpName; public: - LiteralOperator(Node *OpName_) : Node(KLiteralOperator), OpName(OpName_) {} + LiteralOperator(const Node *OpName_) + : Node(KLiteralOperator), OpName(OpName_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *OpName) { + Node::profileCtor(ID, KLiteralOperator); + ID.AddPointer(OpName); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, OpName); + } +#endif void printLeft(OutputStream &S) const override { S += "operator\"\" "; @@ -761,9 +1038,21 @@ const Node *Child; public: - SpecialName(StringView Special_, Node* Child_) + SpecialName(StringView Special_, const Node *Child_) : Node(KSpecialName), Special(Special_), Child(Child_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView Special, + const Node *Child) { + Node::profileCtor(ID, KSpecialName); + addString(ID, Special); + ID.AddPointer(Child); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Special, Child); + } +#endif + void printLeft(OutputStream &S) const override { S += Special; Child->print(S); @@ -775,10 +1064,22 @@ const Node *SecondType; public: - CtorVtableSpecialName(Node *FirstType_, Node *SecondType_) + CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_) : Node(KCtorVtableSpecialName), FirstType(FirstType_), SecondType(SecondType_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *FirstType, + const Node *SecondType) { + Node::profileCtor(ID, KCtorVtableSpecialName); + ID.AddPointer(FirstType); + ID.AddPointer(SecondType); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, FirstType, SecondType); + } +#endif + void printLeft(OutputStream &S) const override { S += "construction vtable for "; FirstType->print(S); @@ -794,6 +1095,18 @@ NestedName(Node *Qual_, Node *Name_) : Node(KNestedName), Qual(Qual_), Name(Name_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, Node *Qual, + Node *Name) { + Node::profileCtor(ID, KNestedName); + ID.AddPointer(Qual); + ID.AddPointer(Name); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Qual, Name); + } +#endif + StringView getBaseName() const override { return Name->getBaseName(); } void printLeft(OutputStream &S) const override { @@ -810,6 +1123,18 @@ LocalName(Node *Encoding_, Node *Entity_) : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, Node *Encoding, + Node *Entity) { + Node::profileCtor(ID, KLocalName); + ID.AddPointer(Encoding); + ID.AddPointer(Entity); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Encoding, Entity); + } +#endif + void printLeft(OutputStream &S) const override { Encoding->print(S); S += "::"; @@ -823,9 +1148,21 @@ const Node *Name; public: - QualifiedName(Node* Qualifier_, Node* Name_) + QualifiedName(const Node *Qualifier_, const Node *Name_) : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Qualifier, + const Node *Name) { + Node::profileCtor(ID, KQualifiedName); + ID.AddPointer(Qualifier); + ID.AddPointer(Name); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Qualifier, Name); + } +#endif + StringView getBaseName() const override { return Name->getBaseName(); } void printLeft(OutputStream &S) const override { @@ -838,16 +1175,38 @@ class VectorType final : public Node { const Node *BaseType; const NodeOrString Dimension; + // FIXME: Is this just the same as '!BaseType'? const bool IsPixel; public: VectorType(NodeOrString Dimension_) : Node(KVectorType), BaseType(nullptr), Dimension(Dimension_), IsPixel(true) {} - VectorType(Node *BaseType_, NodeOrString Dimension_) + VectorType(const Node *BaseType_, NodeOrString Dimension_) : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_), IsPixel(false) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeOrString Dimension) { + Node::profileCtor(ID, KVectorType); + ID.AddBoolean(true); // IsPixel + Dimension.profile(ID); + } + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *BaseType, + NodeOrString Dimension) { + Node::profileCtor(ID, KVectorType); + ID.AddBoolean(false); // IsPixel + ID.AddPointer(BaseType); + Dimension.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + if (IsPixel) + profileCtor(ID, Dimension); + else + profileCtor(ID, BaseType, Dimension); + } +#endif + void printLeft(OutputStream &S) const override { if (IsPixel) { S += "pixel vector["; @@ -901,6 +1260,16 @@ RHSComponentCache = Cache::No; } +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeArray Data) { + Node::profileCtor(ID, KParameterPack); + Data.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Data); + } +#endif + bool hasRHSComponentSlow(OutputStream &S) const override { initializePackExpansion(S); size_t Idx = S.CurrentPackIndex; @@ -947,6 +1316,16 @@ TemplateArgumentPack(NodeArray Elements_) : Node(KTemplateArgumentPack), Elements(Elements_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeArray Elements) { + Node::profileCtor(ID, KTemplateArgumentPack); + Elements.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Elements); + } +#endif + NodeArray getElements() const { return Elements; } void printLeft(OutputStream &S) const override { @@ -960,9 +1339,19 @@ const Node *Child; public: - ParameterPackExpansion(Node* Child_) + ParameterPackExpansion(const Node *Child_) : Node(KParameterPackExpansion), Child(Child_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Child) { + Node::profileCtor(ID, KParameterPackExpansion); + ID.AddPointer(Child); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Child); + } +#endif + const Node *getChild() const { return Child; } void printLeft(OutputStream &S) const override { @@ -1004,6 +1393,16 @@ public: TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeArray Params) { + Node::profileCtor(ID, KTemplateArgs); + Params.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Params); + } +#endif + NodeArray getParams() { return Params; } void printLeft(OutputStream &S) const override { @@ -1030,6 +1429,16 @@ Cache::Unknown), Index(Index_) {} + // We don't canonicalize these, because the index would mean different things + // in different mangled names, and we can't rely on the Ref being known in + // time. +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, size_t Index) = delete; + void profile(llvm::FoldingSetNodeID &ID) const override { + llvm_unreachable("forward template reference should not be canonicalized"); + } +#endif + bool hasRHSComponentSlow(OutputStream &S) const override { if (Printing) return false; @@ -1077,6 +1486,18 @@ NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_) : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, Node *Name, + Node *TemplateArgs) { + Node::profileCtor(ID, KNameWithTemplateArgs); + ID.AddPointer(Name); + ID.AddPointer(TemplateArgs); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Name, TemplateArgs); + } +#endif + StringView getBaseName() const override { return Name->getBaseName(); } void printLeft(OutputStream &S) const override { @@ -1092,6 +1513,16 @@ GlobalQualifiedName(Node* Child_) : Node(KGlobalQualifiedName), Child(Child_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, Node *Child) { + Node::profileCtor(ID, KGlobalQualifiedName); + ID.AddPointer(Child); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Child); + } +#endif + StringView getBaseName() const override { return Child->getBaseName(); } void printLeft(OutputStream &S) const override { @@ -1100,19 +1531,6 @@ } }; -struct StdQualifiedName : Node { - Node *Child; - - StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {} - - StringView getBaseName() const override { return Child->getBaseName(); } - - void printLeft(OutputStream &S) const override { - S += "std::"; - Child->print(S); - } -}; - enum class SpecialSubKind { allocator, basic_string, @@ -1129,6 +1547,16 @@ ExpandedSpecialSubstitution(SpecialSubKind SSK_) : Node(KExpandedSpecialSubstitution), SSK(SSK_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, SpecialSubKind SSK) { + Node::profileCtor(ID, KExpandedSpecialSubstitution); + ID.AddInteger((unsigned)SSK); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, SSK); + } +#endif + StringView getBaseName() const override { switch (SSK) { case SpecialSubKind::allocator: @@ -1178,6 +1606,16 @@ SpecialSubstitution(SpecialSubKind SSK_) : Node(KSpecialSubstitution), SSK(SSK_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, SpecialSubKind SSK) { + Node::profileCtor(ID, KSpecialSubstitution); + ID.AddInteger((unsigned)SSK); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, SSK); + } +#endif + StringView getBaseName() const override { switch (SSK) { case SpecialSubKind::allocator: @@ -1225,9 +1663,21 @@ const bool IsDtor; public: - CtorDtorName(Node *Basename_, bool IsDtor_) + CtorDtorName(const Node *Basename_, bool IsDtor_) : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Basename, + bool IsDtor) { + Node::profileCtor(ID, KCtorDtorName); + ID.AddPointer(Basename); + ID.AddBoolean(IsDtor); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Basename, IsDtor); + } +#endif + void printLeft(OutputStream &S) const override { if (IsDtor) S += "~"; @@ -1239,7 +1689,17 @@ const Node *Base; public: - DtorName(Node *Base_) : Node(KDtorName), Base(Base_) {} + DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Base) { + Node::profileCtor(ID, KDtorName); + ID.AddPointer(Base); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Base); + } +#endif void printLeft(OutputStream &S) const override { S += "~"; @@ -1253,6 +1713,16 @@ public: UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView Count) { + Node::profileCtor(ID, KUnnamedTypeName); + addString(ID, Count); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Count); + } +#endif + void printLeft(OutputStream &S) const override { S += "'unnamed"; S += Count; @@ -1268,6 +1738,18 @@ ClosureTypeName(NodeArray Params_, StringView Count_) : Node(KClosureTypeName), Params(Params_), Count(Count_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeArray Params, + StringView Count) { + Node::profileCtor(ID, KClosureTypeName); + Params.profile(ID); + addString(ID, Count); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Params, Count); + } +#endif + void printLeft(OutputStream &S) const override { S += "\'lambda"; S += Count; @@ -1283,6 +1765,16 @@ StructuredBindingName(NodeArray Bindings_) : Node(KStructuredBindingName), Bindings(Bindings_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeArray Bindings) { + Node::profileCtor(ID, KStructuredBindingName); + Bindings.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Bindings); + } +#endif + void printLeft(OutputStream &S) const override { S += '['; Bindings.printWithComma(S); @@ -1293,8 +1785,42 @@ // -- Expression Nodes -- struct Expr : public Node { + /// Expr kinds, used for profiling. + enum ExprKind : unsigned char { + KBinaryExpr, + KArraySubscriptExpr, + KPostfixExpr, + KConditionalExpr, + KMemberExpr, + KEnclosingExpr, + KCastExpr, + KSizeofParamPackExpr, + KCallExpr, + KNewExpr, + KDeleteExpr, + KPrefixExpr, + KFunctionParam, + KConversionExpr, + KInitListExpr, + KFoldExpr, + KThrowExpr, + KBoolExpr, + KIntegerCastExpr, + KIntegerExpr, + KFloatExpr, + }; + Expr(Kind K = KExpr) : Node(K) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, Kind K = KExpr) { + Node::profileCtor(ID, K); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, K); + } }; +#endif class BinaryExpr : public Expr { const Node *LHS; @@ -1302,9 +1828,23 @@ const Node *RHS; public: - BinaryExpr(Node *LHS_, StringView InfixOperator_, Node *RHS_) + BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_) : LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *LHS, + StringView InfixOperator, const Node *RHS) { + Expr::profileCtor(ID); + ID.AddInteger(KBinaryExpr); + ID.AddPointer(LHS); + addString(ID, InfixOperator); + ID.AddPointer(RHS); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, LHS, InfixOperator, RHS); + } +#endif + void printLeft(OutputStream &S) const override { // might be a template argument expression, then we need to disambiguate // with parens. @@ -1329,7 +1869,21 @@ const Node *Op2; public: - ArraySubscriptExpr(Node *Op1_, Node *Op2_) : Op1(Op1_), Op2(Op2_) {} + ArraySubscriptExpr(const Node *Op1_, const Node *Op2_) + : Op1(Op1_), Op2(Op2_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Op1, + const Node *Op2) { + Expr::profileCtor(ID); + ID.AddInteger(KArraySubscriptExpr); + ID.AddPointer(Op1); + ID.AddPointer(Op2); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Op1, Op2); + } +#endif void printLeft(OutputStream &S) const override { S += "("; @@ -1342,17 +1896,30 @@ class PostfixExpr : public Expr { const Node *Child; - const StringView Operand; + const StringView Operator; public: - PostfixExpr(Node *Child_, StringView Operand_) - : Child(Child_), Operand(Operand_) {} + PostfixExpr(const Node *Child_, StringView Operator_) + : Child(Child_), Operator(Operator_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Child, + StringView Operator) { + Expr::profileCtor(ID); + ID.AddInteger(KPostfixExpr); + ID.AddPointer(Child); + addString(ID, Operator); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Child, Operator); + } +#endif void printLeft(OutputStream &S) const override { S += "("; Child->print(S); S += ")"; - S += Operand; + S += Operator; } }; @@ -1362,9 +1929,23 @@ const Node *Else; public: - ConditionalExpr(Node *Cond_, Node *Then_, Node *Else_) + ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_) : Cond(Cond_), Then(Then_), Else(Else_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Cond, + const Node *Then, const Node *Else) { + Expr::profileCtor(ID); + ID.AddInteger(KConditionalExpr); + ID.AddPointer(Cond); + ID.AddPointer(Then); + ID.AddPointer(Else); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Cond, Then, Else); + } +#endif + void printLeft(OutputStream &S) const override { S += "("; Cond->print(S); @@ -1382,9 +1963,23 @@ const Node *RHS; public: - MemberExpr(Node *LHS_, StringView Kind_, Node *RHS_) + MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_) : LHS(LHS_), Kind(Kind_), RHS(RHS_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *LHS, + StringView Kind, const Node *RHS) { + Expr::profileCtor(ID); + ID.AddInteger(KMemberExpr); + ID.AddPointer(LHS); + addString(ID, Kind); + ID.AddPointer(RHS); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, LHS, Kind, RHS); + } +#endif + void printLeft(OutputStream &S) const override { LHS->print(S); S += Kind; @@ -1401,6 +1996,20 @@ EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_) : Prefix(Prefix_), Infix(Infix_), Postfix(Postfix_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView Prefix, + const Node *Infix, StringView Postfix) { + Expr::profileCtor(ID); + ID.AddInteger(KEnclosingExpr); + addString(ID, Prefix); + ID.AddPointer(Infix); + addString(ID, Postfix); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Prefix, Infix, Postfix); + } +#endif + void printLeft(OutputStream &S) const override { S += Prefix; Infix->print(S); @@ -1415,9 +2024,23 @@ const Node *From; public: - CastExpr(StringView CastKind_, Node *To_, Node *From_) + CastExpr(StringView CastKind_, const Node *To_, const Node *From_) : CastKind(CastKind_), To(To_), From(From_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView CastKind, + const Node *To, const Node *From) { + Expr::profileCtor(ID); + ID.AddInteger(KCastExpr); + addString(ID, CastKind); + ID.AddPointer(To); + ID.AddPointer(From); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, CastKind, To, From); + } +#endif + void printLeft(OutputStream &S) const override { S += CastKind; S += "<"; @@ -1429,10 +2052,21 @@ }; class SizeofParamPackExpr : public Expr { - Node *Pack; + const Node *Pack; public: - SizeofParamPackExpr(Node *Pack_) : Pack(Pack_) {} + SizeofParamPackExpr(const Node *Pack_) : Pack(Pack_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Pack) { + Expr::profileCtor(ID); + ID.AddInteger(KSizeofParamPackExpr); + ID.AddPointer(Pack); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Pack); + } +#endif void printLeft(OutputStream &S) const override { S += "sizeof...("; @@ -1447,7 +2081,21 @@ NodeArray Args; public: - CallExpr(Node *Callee_, NodeArray Args_) : Callee(Callee_), Args(Args_) {} + CallExpr(const Node *Callee_, NodeArray Args_) + : Callee(Callee_), Args(Args_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Callee, + NodeArray Args) { + Expr::profileCtor(ID); + ID.AddInteger(KCallExpr); + ID.AddPointer(Callee); + Args.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Callee, Args); + } +#endif void printLeft(OutputStream &S) const override { Callee->print(S); @@ -1470,6 +2118,23 @@ : ExprList(ExprList_), Type(Type_), InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, NodeArray ExprList, + Node *Type, NodeArray InitList, bool IsGlobal, + bool IsArray) { + Expr::profileCtor(ID); + ID.AddInteger(KNewExpr); + ExprList.profile(ID); + ID.AddPointer(Type); + InitList.profile(ID); + ID.AddBoolean(IsGlobal); + ID.AddBoolean(IsArray); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, ExprList, Type, InitList, IsGlobal, IsArray); + } +#endif + void printLeft(OutputStream &S) const override { if (IsGlobal) S += "::operator "; @@ -1501,6 +2166,20 @@ DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_) : Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, Node *Op, bool IsGlobal, + bool IsArray) { + Expr::profileCtor(ID); + ID.AddInteger(KDeleteExpr); + ID.AddPointer(Op); + ID.AddBoolean(IsGlobal); + ID.AddBoolean(IsArray); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Op, IsGlobal, IsArray); + } +#endif + void printLeft(OutputStream &S) const override { if (IsGlobal) S += "::"; @@ -1516,7 +2195,21 @@ Node *Child; public: - PrefixExpr(StringView Prefix_, Node *Child_) : Prefix(Prefix_), Child(Child_) {} + PrefixExpr(StringView Prefix_, Node *Child_) + : Prefix(Prefix_), Child(Child_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView Prefix, + Node *Child) { + Expr::profileCtor(ID); + ID.AddInteger(KPrefixExpr); + addString(ID, Prefix); + ID.AddPointer(Child); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Prefix, Child); + } +#endif void printLeft(OutputStream &S) const override { S += Prefix; @@ -1532,6 +2225,17 @@ public: FunctionParam(StringView Number_) : Number(Number_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView Number) { + Expr::profileCtor(ID); + ID.AddInteger(KFunctionParam); + addString(ID, Number); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Number); + } +#endif + void printLeft(OutputStream &S) const override { S += "fp"; S += Number; @@ -1546,6 +2250,19 @@ ConversionExpr(const Node *Type_, NodeArray Expressions_) : Type(Type_), Expressions(Expressions_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Type, + NodeArray Expressions) { + Expr::profileCtor(ID); + ID.AddInteger(KConversionExpr); + ID.AddPointer(Type); + Expressions.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Type, Expressions); + } +#endif + void printLeft(OutputStream &S) const override { S += "("; Type->print(S); @@ -1556,10 +2273,23 @@ }; class InitListExpr : public Expr { - Node *Ty; + const Node *Ty; NodeArray Inits; public: - InitListExpr(Node *Ty_, NodeArray Inits_) : Ty(Ty_), Inits(Inits_) {} + InitListExpr(const Node *Ty_, NodeArray Inits_) : Ty(Ty_), Inits(Inits_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Type, + NodeArray Inits) { + Expr::profileCtor(ID); + ID.AddInteger(KInitListExpr); + ID.AddPointer(Type); + Inits.profile(ID); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Ty, Inits); + } +#endif void printLeft(OutputStream &S) const override { if (Ty) @@ -1571,13 +2301,26 @@ }; class BracedExpr : public Expr { - Node *Elem; - Node *Init; + const Node *Elem; + const Node *Init; bool IsArray; public: - BracedExpr(Node *Elem_, Node *Init_, bool IsArray_) + BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_) : Expr(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Elem, + const Node *Init, bool IsArray) { + Expr::profileCtor(ID, KBracedExpr); + ID.AddPointer(Elem); + ID.AddPointer(Init); + ID.AddBoolean(IsArray); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Elem, Init, IsArray); + } +#endif + void printLeft(OutputStream &S) const override { if (IsArray) { S += '['; @@ -1594,13 +2337,26 @@ }; class BracedRangeExpr : public Expr { - Node *First; - Node *Last; - Node *Init; + const Node *First; + const Node *Last; + const Node *Init; public: - BracedRangeExpr(Node *First_, Node *Last_, Node *Init_) + BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_) : Expr(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *First, + const Node *Last, const Node *Init) { + Expr::profileCtor(ID, KBracedRangeExpr); + ID.AddPointer(First); + ID.AddPointer(Last); + ID.AddPointer(Init); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, First, Last, Init); + } +#endif + void printLeft(OutputStream &S) const override { S += '['; First->print(S); @@ -1614,14 +2370,31 @@ }; struct FoldExpr : Expr { - Node *Pack, *Init; + const Node *Pack, *Init; StringView OperatorName; bool IsLeftFold; - FoldExpr(bool IsLeftFold_, StringView OperatorName_, Node *Pack_, Node *Init_) + FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_, + const Node *Init_) : Pack(Pack_), Init(Init_), OperatorName(OperatorName_), IsLeftFold(IsLeftFold_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, bool IsLeftFold, + StringView OperatorName, const Node *Pack, + const Node *Init) { + Expr::profileCtor(ID); + ID.AddInteger(KFoldExpr); + ID.AddBoolean(IsLeftFold); + addString(ID, OperatorName); + ID.AddPointer(Pack); + ID.AddPointer(Init); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, IsLeftFold, OperatorName, Pack, Init); + } +#endif + void printLeft(OutputStream &S) const override { auto PrintPack = [&] { S += '('; @@ -1666,7 +2439,18 @@ const Node *Op; public: - ThrowExpr(Node *Op_) : Op(Op_) {} + ThrowExpr(const Node *Op_) : Op(Op_) {} + +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Op) { + Expr::profileCtor(ID); + ID.AddInteger(KThrowExpr); + ID.AddPointer(Op); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Op); + } +#endif void printLeft(OutputStream &S) const override { S += "throw "; @@ -1680,6 +2464,17 @@ public: BoolExpr(bool Value_) : Value(Value_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, bool Value) { + Expr::profileCtor(ID); + ID.AddInteger(KBoolExpr); + ID.AddBoolean(Value); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Value); + } +#endif + void printLeft(OutputStream &S) const override { S += Value ? StringView("true") : StringView("false"); } @@ -1687,13 +2482,26 @@ class IntegerCastExpr : public Expr { // ty(integer) - Node *Ty; + const Node *Ty; StringView Integer; public: - IntegerCastExpr(Node *Ty_, StringView Integer_) + IntegerCastExpr(const Node *Ty_, StringView Integer_) : Ty(Ty_), Integer(Integer_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, const Node *Ty, + StringView Integer) { + Expr::profileCtor(ID); + ID.AddInteger(KIntegerCastExpr); + ID.AddPointer(Ty); + addString(ID, Integer); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Ty, Integer); + } +#endif + void printLeft(OutputStream &S) const override { S += "("; Ty->print(S); @@ -1709,6 +2517,19 @@ public: IntegerExpr(StringView Type_, StringView Value_) : Type(Type_), Value(Value_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView Type, + StringView Value) { + Expr::profileCtor(ID); + ID.AddInteger(KIntegerExpr); + addString(ID, Type); + addString(ID, Value); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Type, Value); + } +#endif + void printLeft(OutputStream &S) const override { if (Type.size() > 3) { S += "("; @@ -1735,6 +2556,17 @@ public: FloatExpr(StringView Contents_) : Contents(Contents_) {} +#ifndef STANDALONE_DEMANGLER + static void profileCtor(llvm::FoldingSetNodeID &ID, StringView Contents) { + Expr::profileCtor(ID); + ID.AddInteger(KFloatExpr); + addString(ID, Contents); + } + void profile(llvm::FoldingSetNodeID &ID) const override { + profileCtor(ID, Contents); + } +#endif + void printLeft(OutputStream &s) const override { const char *first = Contents.begin(); const char *last = Contents.end() + 1; @@ -1942,6 +2774,80 @@ } }; +class DefaultAllocator { + BumpPointerAllocator Alloc; + +public: + void reset() { Alloc.reset(); } + + template T *makeNode(Args &&...args) { + return new (Alloc.allocate(sizeof(T))) + T(std::forward(args)...); + } + + void *allocateNodeArray(size_t sz) { + return Alloc.allocate(sizeof(Node *) * sz); + } +}; + +#ifndef STANDALONE_DEMANGLER +class FoldingNodeAllocator { + class alignas(alignof(Node *)) NodeHeader : public llvm::FoldingSetNode { + public: + ::Node *getNode() { return reinterpret_cast<::Node*>(this + 1); } + void Profile(llvm::FoldingSetNodeID &ID) { + getNode()->profile(ID); + } + }; + + BumpPointerAllocator RawAlloc; + llvm::FoldingSet Nodes; + +public: + void reset() {} + + template + std::pair makeNodeImpl(bool CreateNewNodes, Args &&...args) { + llvm::FoldingSetNodeID ID; + T::profileCtor(ID, args...); + + void *InsertPos; + if (NodeHeader *Existing = Nodes.FindNodeOrInsertPos(ID, InsertPos)) + return {static_cast(Existing->getNode()), false}; + + if (!CreateNewNodes) + return {nullptr, true}; + + void *Storage = RawAlloc.allocate(sizeof(NodeHeader) + sizeof(T)); + NodeHeader *New = new (Storage) NodeHeader; + T *Result = new (New->getNode()) T(std::forward(args)...); + Nodes.InsertNode(New, InsertPos); + return {Result, true}; + } + + template T *makeNode(Args &&...args) { + return makeNodeImpl(true, std::forward(args)...).first; + } + + void *allocateNodeArray(size_t sz) { + return RawAlloc.allocate(sizeof(Node *) * sz); + } +}; + +// FIXME: Don't canonicalize forward template references for now, because they +// contain state (the resolved template node) that's not known at their point +// of creation. +template <> +std::pair +FoldingNodeAllocator::makeNodeImpl( + bool, size_t &Index) { + return {new (RawAlloc.allocate(sizeof(ForwardTemplateReference))) + ForwardTemplateReference(Index), + true}; +} +#endif + +template struct Db { const char *First; const char *Last; @@ -1972,7 +2878,7 @@ bool PermitForwardTemplateReferences = false; bool ParsingLambdaParams = false; - BumpPointerAllocator ASTAllocator; + Alloc ASTAllocator; Db(const char *First_, const char *Last_) : First(First_), Last(Last_) {} @@ -1988,14 +2894,13 @@ ASTAllocator.reset(); } - template T *make(Args &&... args) { - return new (ASTAllocator.allocate(sizeof(T))) - T(std::forward(args)...); + template Node *make(Args &&... args) { + return ASTAllocator.template makeNode(std::forward(args)...); } template NodeArray makeNodeArray(It begin, It end) { size_t sz = static_cast(end - begin); - void *mem = ASTAllocator.allocate(sizeof(Node *) * sz); + void *mem = ASTAllocator.allocateNodeArray(sz); Node **data = new (mem) Node *[sz]; std::copy(begin, end, data); return NodeArray(data, sz); @@ -2132,7 +3037,7 @@ // // ::= // ::= -Node *Db::parseName(NameState *State) { +template Node *Db::parseName(NameState *State) { consumeIf('L'); // extension if (look() == 'N') @@ -2173,7 +3078,7 @@ // := Z E [] // := Z E s [] // := Z Ed [ ] _ -Node *Db::parseLocalName(NameState *State) { +template Node *Db::parseLocalName(NameState *State) { if (!consumeIf('Z')) return nullptr; Node *Encoding = parseEncoding(); @@ -2182,7 +3087,8 @@ if (consumeIf('s')) { First = parse_discriminator(First, Last); - return make(Encoding, make("string literal")); + auto *StringLitName = make("string literal"); + return make(Encoding, StringLitName); } if (consumeIf('d')) { @@ -2205,12 +3111,12 @@ // ::= // ::= St # ::std:: // extension ::= StL -Node *Db::parseUnscopedName(NameState *State) { +template Node *Db::parseUnscopedName(NameState *State) { if (consumeIf("StL") || consumeIf("St")) { Node *R = parseUnqualifiedName(State); if (R == nullptr) return nullptr; - return make(R); + return make(make("std"), R); } return parseUnqualifiedName(State); } @@ -2220,27 +3126,28 @@ // ::= // ::= // ::= DC + E # structured binding declaration -Node *Db::parseUnqualifiedName(NameState *State) { - // s are special-cased in parseNestedName(). - Node *Result; - if (look() == 'U') - Result = parseUnnamedTypeName(State); - else if (look() >= '1' && look() <= '9') - Result = parseSourceName(State); - else if (consumeIf("DC")) { - size_t BindingsBegin = Names.size(); - do { - Node *Binding = parseSourceName(State); - if (Binding == nullptr) - return nullptr; - Names.push_back(Binding); - } while (!consumeIf('E')); - Result = make(popTrailingNodeArray(BindingsBegin)); - } else - Result = parseOperatorName(State); - if (Result != nullptr) - Result = parseAbiTags(Result); - return Result; +template +Node *Db::parseUnqualifiedName(NameState *State) { + // s are special-cased in parseNestedName(). + Node *Result; + if (look() == 'U') + Result = parseUnnamedTypeName(State); + else if (look() >= '1' && look() <= '9') + Result = parseSourceName(State); + else if (consumeIf("DC")) { + size_t BindingsBegin = Names.size(); + do { + Node *Binding = parseSourceName(State); + if (Binding == nullptr) + return nullptr; + Names.push_back(Binding); + } while (!consumeIf('E')); + Result = make(popTrailingNodeArray(BindingsBegin)); + } else + Result = parseOperatorName(State); + if (Result != nullptr) + Result = parseAbiTags(Result); + return Result; } // ::= Ut [] _ @@ -2249,7 +3156,7 @@ // ::= Ul E [ ] _ // // ::= + # Parameter types or "v" if the lambda has no parameters -Node *Db::parseUnnamedTypeName(NameState *) { +template Node *Db::parseUnnamedTypeName(NameState *) { if (consumeIf("Ut")) { StringView Count = parseNumber(); if (!consumeIf('_')) @@ -2278,7 +3185,7 @@ } // ::= -Node *Db::parseSourceName(NameState *) { +template Node *Db::parseSourceName(NameState *) { size_t Length = 0; if (parsePositiveInteger(&Length)) return nullptr; @@ -2342,7 +3249,7 @@ // ::= rS # >>= // ::= ss # <=> C++2a // ::= v # vendor extended operator -Node *Db::parseOperatorName(NameState *State) { +template Node *Db::parseOperatorName(NameState *State) { switch (look()) { case 'a': switch (look(1)) { @@ -2585,7 +3492,8 @@ // ::= D1 # complete object destructor // ::= D2 # base object destructor // extension ::= D5 # ? -Node *Db::parseCtorDtorName(Node *&SoFar, NameState *State) { +template +Node *Db::parseCtorDtorName(Node *&SoFar, NameState *State) { if (SoFar->K == Node::KSpecialSubstitution) { auto SSK = static_cast(SoFar)->SSK; switch (SSK) { @@ -2639,7 +3547,7 @@ // ::=