From 2c30d8b5e64ce7531176ee7f48f8a9f82d85876e Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Fri, 24 May 2019 17:38:29 +0300 Subject: [PATCH 1/4] [SYCL] Remove re-flower pass from clang Signed-off-by: Mariya Podchishchaeva --- clang/lib/CodeGen/BackendUtil.cpp | 5 - clang/lib/CodeGen/CMakeLists.txt | 3 - .../CodeGen/OclCxxRewrite/BifNameReflower.cpp | 1135 ---- .../lib/CodeGen/OclCxxRewrite/CMakeLists.txt | 29 - .../CodeGen/OclCxxRewrite/OclCxxDemangler.cpp | 5655 ----------------- .../CodeGen/OclCxxRewrite/OclCxxDemangler.h | 139 - .../OclCxxRewrite/OclCxxDemanglerResult.cpp | 46 - .../OclCxxRewrite/OclCxxDemanglerResult.h | 3318 ---------- .../OclCxxRewrite/OclCxxMangleEncodings.inc | 331 - .../OclCxxRewrite/OclCxxParseVariant.h | 685 -- .../CodeGen/OclCxxRewrite/OclCxxPrinter.cpp | 1088 ---- .../lib/CodeGen/OclCxxRewrite/OclCxxPrinter.h | 2030 ------ 12 files changed, 14464 deletions(-) delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/BifNameReflower.cpp delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/CMakeLists.txt delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/OclCxxDemangler.cpp delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/OclCxxDemangler.h delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/OclCxxDemanglerResult.cpp delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/OclCxxDemanglerResult.h delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/OclCxxMangleEncodings.inc delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/OclCxxParseVariant.h delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/OclCxxPrinter.cpp delete mode 100644 clang/lib/CodeGen/OclCxxRewrite/OclCxxPrinter.h diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 7691e9d618804..ce3be99226466 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -11,7 +11,6 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetOptions.h" -#include "clang/CodeGen/OclCxxRewrite/BifNameReflower.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearchOptions.h" @@ -817,10 +816,6 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, PerFunctionPasses.add( createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - if (LangOpts.SYCLIsDevice) { - PerModulePasses.add(createOclCxxBifNameReflowerPass()); - } - CreatePasses(PerModulePasses, PerFunctionPasses); legacy::PassManager CodeGenPasses; diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 0d315954d0624..7c8162067e77a 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -1,5 +1,3 @@ -add_subdirectory(OclCxxRewrite) - set(LLVM_LINK_COMPONENTS Analysis BitReader @@ -107,5 +105,4 @@ add_clang_library(clangCodeGen clangFrontend clangLex clangSerialization - clangOclCxxRewrite ) diff --git a/clang/lib/CodeGen/OclCxxRewrite/BifNameReflower.cpp b/clang/lib/CodeGen/OclCxxRewrite/BifNameReflower.cpp deleted file mode 100644 index 571ef4962303b..0000000000000 --- a/clang/lib/CodeGen/OclCxxRewrite/BifNameReflower.cpp +++ /dev/null @@ -1,1135 +0,0 @@ -//===- BifNameReflower.cpp - Built-in name reflower pass(OCLC++)-*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// -// -// Copyright (c) 2015 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and/or associated documentation files (the -// "Materials"), to deal in the Materials without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Materials, and to -// permit persons to whom the Materials are furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Materials. -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -// -//===----------------------------------------------------------------------===// - - -#include "clang/CodeGen/OclCxxRewrite/BifNameReflower.h" - -#include "OclCxxDemangler.h" -#include "OclCxxPrinter.h" - -#include "llvm/Pass.h" -#include "llvm/PassSupport.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Debug.h" - -#include -#include - -#define DEBUG_TYPE "OclCxxBifNameReflower" - - -namespace { -using namespace oclcxx::adaptation; - - -/// \brief Node adaptation traits for Itanium-mangling printer which -/// adapt names and types from OpenCL C++ to interface layer of -/// SPIR-V generator. -struct OclCxxBiAdaptTraits { - /// \brief Indicates that parsed name is candidate for built-in name - /// reflow. - /// - /// \param ParsedName Result returned from demangler parsing. - /// Result can be failed. - /// \param AllowRttiTypeNameString Indicates that RTTI type strings with - /// type names are allowed to be reflown. - /// \return true if current name is valid candidate - /// for reflow; otherwise, false. - static bool isCandidateForReflow(const DmngRslt &ParsedName, - bool AllowRttiTypeNameString = false) { - // Only process ordinary function names which have mangled name in - // cl::__spirv namespace. - if (!ParsedName.isSuccessful()) - return false; - auto PName = ParsedName.getName(); - - // If RTTI type string is allowed, go to related type name and use it - // as base name for candidate analysis. - if (AllowRttiTypeNameString && PName->isSpecial()) { - auto PSpecName = PName->getAs(); - if (PSpecName->getSpecialKind() != DSNK_TypeInfoNameString) - return false; - auto PRelTypeName = PSpecName->getRelatedType()->getAs(); - if (PRelTypeName == nullptr) - return false; - PName = PRelTypeName->getTypeName(); - } - - if (!PName->isOrdinary()) - return false; - auto POrdName = PName->getAs(); - if (POrdName->isLocal()) - return false; - const auto &PNameParts = POrdName->getParts(); - if (PNameParts.size() <= 2) - return false; - auto PFirstNamePart = PNameParts[0]->getAs(); - auto PSecondNamePart = PNameParts[1]->getAs(); - if (PFirstNamePart == nullptr || PSecondNamePart == nullptr || - PFirstNamePart->isTemplate() || PSecondNamePart->isTemplate() || - PFirstNamePart->getSourceName() != "cl" || - PSecondNamePart->getSourceName() != "__spirv") - return false; - - return true; - } - -private: - /// \brief Built-in entity category. - enum class BiCategory { - Failure, ///< Category is unknown. Failed to detect category. - Function, ///< Built-in function (either in extended set or core "Op" - ///< function). - Type, ///< Built-in type (core "OpType"-function-generated). - Variable, ///< Built-in variable (core "Var"-prefixed global variable). - }; - - /// \brief Gets extended set and built-in names based on candidate name. - /// - /// \param NameNode Node in result that describes name of built-in entity. - /// \return Triple containing name of extended set (first argument), - /// name of built-in entity (second argument) and its - /// category (third argument). - /// - /// If method failed, the triple with empty strings - /// and BiCategory::Failure is returned. - static std::tuple getExtSetBiName( - const std::shared_ptr &NameNode) { - assert(NameNode != nullptr && "Node must exist."); - - // If function is directly in a subnamespace of cl::__spirv namespace and - // it does not name any special function then it will be treated as - // built-in from extended set named the same as subnamespace name. - // - // If function is directly in cl::__spirv namespace and it does not name - // any special function then it will be treated as built-in name. - // If the built-in name starts with "Op" prefix, it is core built-in; - // otherwise, it is built-in from "ocl" extended set. - const auto &PNameParts = NameNode->getParts(); - - std::string ExtSetName; - std::string BiName; - BiCategory Category = BiCategory::Failure; - switch (PNameParts.size()) { - case 4: { - auto PExtSetNamePart = PNameParts[2]->getAs(); - if (PExtSetNamePart == nullptr || PExtSetNamePart->isTemplate()) - return std::make_tuple(std::string(), std::string(), Category); - ExtSetName = PExtSetNamePart->getSourceName(); - } - break; - case 3: break; // ExtSetName = ""; - default: - return std::make_tuple(std::string(), std::string(), Category); - } - - auto PBiNamePart = PNameParts.back()->getAs(); - if (PBiNamePart == nullptr) - return std::make_tuple(std::string(), std::string(), Category); - if (ExtSetName.empty() && - PBiNamePart->getSourceName().compare(0, 2, "Op") == 0) - if (NameNode->isData() && - PBiNamePart->getSourceName().compare(2, 4, "Type") == 0) { - BiName = PBiNamePart->getSourceName().substr(6); - Category = BiCategory::Type; - } - else if (NameNode->isData() && - PBiNamePart->getSourceName().compare(2, 8, "Constant") == 0) { - BiName = PBiNamePart->getSourceName().substr(2); - Category = BiCategory::Type; - } - else { - BiName = PBiNamePart->getSourceName().substr(2); - Category = BiCategory::Function; - } - else if (ExtSetName.empty() && NameNode->isData() && - PBiNamePart->getSourceName().compare(0, 3, "Var") == 0) { - BiName = PBiNamePart->getSourceName().substr(3); - Category = BiCategory::Variable; - } - else { - if (ExtSetName.empty()) - ExtSetName = "ocl"; - BiName = PBiNamePart->getSourceName(); - Category = BiCategory::Function; - } - - return std::make_tuple(ExtSetName, BiName, Category); - } - - - /// \brief Gets effective number of elements in array or vector. - /// - /// \param TypeNode Node in demangler's result which points to array or - /// vector type. The method asserts, if node is invalid. - /// \return Computed effective number of elements, or 0 if function - /// cannot compute it (unspecified or variable). - static unsigned long long getEffectiveArrayVecElements( - const std::shared_ptr &TypeNode) { - assert(TypeNode != nullptr && "Node must exist."); - - // Simple size. - if (TypeNode->getSizeExpr() == nullptr) - return TypeNode->getSize(); - - // Size is an expression. If it is template parameter, resolve it - // to final expression if possible. - auto SizeExpr = TypeNode->getSizeExpr(); - while (SizeExpr != nullptr && SizeExpr->getKind() == DXK_TemplateParam) { - auto SizeTArg = SizeExpr->getAs()->getReferredTArg(); - if (SizeTArg == nullptr || !SizeTArg->isExpression()) - return 0; - SizeExpr = SizeTArg->getExpression(); - } - - // If final size expression is primary expression (literal), get its - // value. - auto PrimExpr = SizeExpr->getAs(); - if (PrimExpr != nullptr && PrimExpr->isLiteral()) { - switch (PrimExpr->getContentType()) { - case DmngRsltPrimaryExpr::UInt: - case DmngRsltPrimaryExpr::Bool: - return PrimExpr->getContentAsUInt(); - case DmngRsltPrimaryExpr::SInt: - return PrimExpr->getContentAsSInt() > 0 - ? static_cast(PrimExpr->getContentAsSInt()) - : 0; - default: - return 0; - } - } - - // Fall, if size cannot be computed. - return 0; - } - - /// \brief Gets effective type. - /// - /// \param TypeNode Node in demangler's result which points to type. - /// The method asserts, if node is invalid. - /// \return Effective type of TypeNode. The effective type is a type - /// after resolving template parameter or decltype() - /// expressions. - /// If type cannot be resolved, empty shared pointer is - /// returned. - static std::shared_ptr getEffectiveType( - const std::shared_ptr &TypeNode) { - assert(TypeNode != nullptr && "Node must exist."); - - // If type node is template parameter or decltype() node, - // resolve it to final type. - auto FinalNode = TypeNode; - while (FinalNode != nullptr && (FinalNode->getKind() == DTK_TemplateParam || - FinalNode->getKind() == DTK_Decltype)) { - std::shared_ptr TypeExpr; - if (FinalNode->getKind() == DTK_TemplateParam) - TypeExpr = FinalNode->getAs()->getTemplateParam(); - else - TypeExpr = FinalNode->getAs()->getDecltype(); - - // If expression node is template parameter expression, go to referred - // type or inner expression. If expression node is decltype() expression, - // go to inner expression. - FinalNode = nullptr; - while (TypeExpr != nullptr && (TypeExpr->getKind() == DXK_TemplateParam || - TypeExpr->getKind() == DXK_Decltype)) { - if (TypeExpr->getKind() == DXK_TemplateParam) { - auto TArg = TypeExpr->getAs()->getReferredTArg(); - if (TArg != nullptr) { - if (TArg->isExpression()) { - TypeExpr = TArg->getExpression(); - continue; - } - if (TArg->isType()) - FinalNode = TArg->getType(); - } - break; - } - TypeExpr = TypeExpr->getAs()->getExpression(); - } - } - - return FinalNode; - } - - /// \brief Gets effective type. - /// - /// \param TArg Template argument in demangler's result. - /// \return Effective type of TArg. The effective type is a type stored in - /// template arg after resolving template parameter or decltype() - /// expressions. - /// If type cannot be resolved, empty shared pointer is returned. - static std::shared_ptr getEffectiveType( - const DmngRsltTArg &TArg) { - const auto *EffectiveTArg = &TArg; - - while (EffectiveTArg != nullptr) { - if (EffectiveTArg->isType()) - return getEffectiveType(EffectiveTArg->getType()); - - if (!EffectiveTArg->isExpression()) - return nullptr; - - auto Expr = EffectiveTArg->getExpression(); - EffectiveTArg = nullptr; - while (Expr != nullptr) { - switch (Expr->getKind()) { - case DXK_TemplateParam: - EffectiveTArg = Expr->getAs() - ->getReferredTArg().get(); - Expr = nullptr; - break; - case DXK_Decltype: - Expr = Expr->getAs()->getExpression(); - break; - default: - return nullptr; - } - } - } - return nullptr; - } - - /// \brief Gets effective primary expression (literal or external name) - /// stored in template argument. - /// - /// \param TArg Template argument in demangler's result. - /// \return Effective primary expression stored in template argument. - /// The effective expression is a expression after resolving - /// template parameter or decltype() expressions. - /// If expression cannot be resolved, empty shared pointer - /// is returned. - static std::shared_ptr getEffectivePrimaryExpr( - const DmngRsltTArg &TArg) { - const auto *EffectiveTArg = &TArg; - - while (EffectiveTArg != nullptr) { - if (!EffectiveTArg->isExpression()) - return nullptr; - auto Expr = EffectiveTArg->getExpression(); - assert(Expr && "No expression info."); - switch (Expr->getKind()) { - case DXK_TemplateParam: - EffectiveTArg = Expr->getAs() - ->getReferredTArg().get(); - break; - case DXK_Primary: - return Expr->getAs(); - default: - return nullptr; - } - } - return nullptr; - } - - - /// \brief Gets encoding for special return types. - /// - /// \param TypeNode Node in demangler's result which points to - /// (return) type. - /// The method asserts, if node is invalid. - /// \param AllowVoidEncoding Encoding void type is only allowed in - /// the special cases. - /// \return Encoded name of special return type, or empty - /// string if type is not special or type is - /// invalid. - static std::string getSpecialReturnTypeEncoding( - const std::shared_ptr &TypeNode, - bool AllowVoidEncoding = false) { - auto EffectiveType = getEffectiveType(TypeNode); - if (EffectiveType == nullptr) - return std::string(); - - // Vector type suffix. - std::string VecSuffix; - auto EffectiveVecType = EffectiveType->getAs(); - if (EffectiveVecType != nullptr) { - auto VecSize = getEffectiveArrayVecElements(EffectiveVecType); - switch (VecSize) { - case 1: break; - case 2: VecSuffix = "2"; break; - case 3: VecSuffix = "3"; break; - case 4: VecSuffix = "4"; break; - case 8: VecSuffix = "8"; break; - case 16: VecSuffix = "16"; break; - default: - return std::string(); // Invalid vector size. - } - - EffectiveType = getEffectiveType(EffectiveVecType->getElemType()); - if (EffectiveType == nullptr) - return std::string(); // Invalid element type. - } - - // Scalar type or vector element type. - std::string ScalarType; - auto EffectBiType = EffectiveType->getAs(); - if (EffectBiType != nullptr) { - switch (EffectBiType->getBuiltinType()) { - case DBT_Void: - if (AllowVoidEncoding && VecSuffix.empty()) - ScalarType = "void"; - else - return std::string(); break; - case DBT_Char: - case DBT_SChar: ScalarType = "char"; break; - case DBT_UChar: ScalarType = "uchar"; break; - case DBT_Short: ScalarType = "short"; break; - case DBT_UShort: ScalarType = "ushort"; break; - case DBT_Int: ScalarType = "int"; break; - case DBT_UInt: ScalarType = "uint"; break; - case DBT_Long: - case DBT_Int64: ScalarType = "long"; break; - case DBT_ULong: - case DBT_UInt64: ScalarType = "ulong"; break; - case DBT_Half: ScalarType = "half"; break; - case DBT_Float: - case DBT_Float32R: ScalarType = "float"; break; - case DBT_Double: - case DBT_Float64R: ScalarType = "double"; break; - case DBT_Bool: ScalarType = "bool"; break; - default: - return std::string(); - } - } - - return ScalarType + VecSuffix; - } - - /// \brief Type of special enum to encode in name. - enum class SpecialEnumType { - Sat, ///< Saturation option. - RoundingMode ///< Rounding mode option. - }; - - /// \brief Get encoding for special enumeration values in template argument. - /// - /// Stops scanning on first encountered special enum value. - /// - /// \tparam EnumType Type of special enum to scan for. - /// - /// \param TArg Template argument in demangler's result to scan for - /// special enum values. - /// \param ScanPacks Indicates that nested template parameter packs should - /// also be scanned. - /// \return Encoded name of special enum value, or nullptr if - /// template argument does not contain special value. - template - static const char *getSpecialEnumValueEncoding(const DmngRsltTArg &TArg, - bool ScanPacks = false) { - if (ScanPacks && TArg.isPack()) - return getSpecialEnumValueEncoding(TArg.getPack(), ScanPacks); - - // Resolve enum type name. - auto EffectiveExpr = getEffectivePrimaryExpr(TArg); - if (EffectiveExpr == nullptr || !EffectiveExpr->isLiteral()) - return nullptr; - auto EffectiveType = getEffectiveType(EffectiveExpr->getLiteralType()); - if (EffectiveType == nullptr || EffectiveType->getKind() != DTK_TypeName) - return nullptr; - auto LiteralTypeNameType = EffectiveType->getAs(); - if (LiteralTypeNameType->getElaboration() != DTNK_None && - LiteralTypeNameType->getElaboration() != DTNK_ElaboratedEnum) - return nullptr; - auto LiteralTypeName = LiteralTypeNameType->getTypeName(); - if (!LiteralTypeName->isData()) - return nullptr; - - // Check type name for proper parts. - if (LiteralTypeName->getParts().size() != 2) - return nullptr; - auto NsPart = LiteralTypeName->getParts()[0]->getAs(); - auto EnumPart = LiteralTypeName->getParts()[1]->getAs(); - if (NsPart == nullptr || EnumPart == nullptr || - NsPart->getSourceName() != "cl") - return nullptr; - - - // enum class cl::saturate { off, on }; - if (EnumType == SpecialEnumType::Sat) { - if (EnumPart->getSourceName() != "saturate") - return nullptr; - - switch (EffectiveExpr->getContentAsUInt()) { - case 0: // off - return ""; - case 1: // on - return "_sat"; - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unsupported enum value for cl::saturate."); - return nullptr; - } - } - - // enum class cl::rounding_mode { rte, rtz, rtp, rtn }; - if (EnumType == SpecialEnumType::RoundingMode) { - if (EnumPart->getSourceName() != "rounding_mode") - return nullptr; - - switch (EffectiveExpr->getContentAsUInt()) { - case 0: // rte - return "_rte"; - case 1: // rtz - return "_rtz"; - case 2: // rtp - return "_rtp"; - case 3: // rtn - return "_rtn"; - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unsupported enum value for cl::rounding_mode."); - return nullptr; - } - } - - return nullptr; - } - - /// \brief Get encoding for special enumeration values in template arguments. - /// - /// Stops scanning on first encountered special enum value. - /// - /// \tparam EnumType Type of special enum to scan for. - /// - /// \param TArgs Template arguments collection in demangler's result - /// to scan for special enum values. - /// \param ScanPacks Indicates that nested template parameter packs should - /// also be scanned. - /// \return Encoded name of special enum value, or nullptr if - /// template arguments do not contain special value. - template - static const char *getSpecialEnumValueEncoding( - const DmngRsltTArg::TArgsPackColT &TArgs, bool ScanPacks = false) { - for (const auto &TArg : TArgs) { - auto EnumVal = getSpecialEnumValueEncoding(TArg, ScanPacks); - if (EnumVal != nullptr) - return EnumVal; - } - return nullptr; - } - - - /// \brief Encodes template argument of data type (or data variable). - /// - /// If parameter packs are also scanned, they are flattened and their template - /// arguments are encoded in order they appear. If any template argument is - /// not supported assert is created and the argument omitted. - /// - /// \param SuffixOut Output stream where encoded suffix will be written to. - /// \param TArg Template argument in demangler's result to encode in - /// new data name (as optional suffix). - /// \param ScanPacks Indicates that nested template parameter packs should - /// also be scanned. - /// \return Value indicating that encoding was successful. - static bool encodeDataTypeTArgs(printer::StringOStreamT &SuffixOut, - const DmngRsltTArg &TArg, - bool ScanPacks = false) { - if (ScanPacks && TArg.isPack()) { - SuffixOut << encodeDataTypeTArgs(TArg.getPack(), ScanPacks); - return true; - } - - // Encode supported types specified as template argument. - auto EffectiveType = getEffectiveType(TArg); - if (EffectiveType != nullptr) { - auto TypeEncoding = getSpecialReturnTypeEncoding(EffectiveType, true); - if (TypeEncoding.empty()) - return false; - - SuffixOut << "_" << TypeEncoding; - return true; - } - - // Resolve literal expression with non-void content. - auto EffectiveExpr = getEffectivePrimaryExpr(TArg); - if (EffectiveExpr == nullptr || !EffectiveExpr->isLiteral()) - return false; - - // Get content as integral. Negative integral is encoded as 64-bit unsigned - // value (no bit change, as its value was incremented by 2^64). Boolean - // value is encoded as 0 (false) or 1 (true). - // For negative integral value assert is generated. - switch (EffectiveExpr->getContentType()) { - case DmngRsltPrimaryExpr::UInt: - case DmngRsltPrimaryExpr::Bool: - SuffixOut << "_" << EffectiveExpr->getContentAsUInt(); - return true; - case DmngRsltPrimaryExpr::SInt: - assert(EffectiveExpr->getContentAsSInt() >= 0 && - "Encoding of negative value is not really supported."); - SuffixOut << "_" << EffectiveExpr->getContentAsUInt(); - return true; - default: - return false; - } - } - - /// \brief Encodes template arguments of data type (or data variable). - /// - /// Template arguments are encoded in order they appear on template argument - /// list. If parameter packs are also scanned, they are flattened. If any - /// template argument is not supported assert is created and the argument - /// omitted. - /// - /// \param SuffixOut Output stream where encoded suffix will be written to. - /// \param TArgs Template arguments collection in demangler's result - /// to encode in new data name (as optional suffix). - /// \param ScanPacks Indicates that nested template parameter packs should - /// also be scanned. - /// \return Encoded name of special enum value, or empty string if - /// template arguments cannot be encoded or there is no - /// template arguments to encode. - static std::string encodeDataTypeTArgs( - const DmngRsltTArg::TArgsPackColT &TArgs, bool ScanPacks = false) { - if (TArgs.empty()) // Fast return. - return std::string(); - - // NOTE: Helper string to support llvm::raw_string_ostream. - std::string Suffixes; - printer::StringOStreamT SuffixesStream(Suffixes); - - for (const auto &TArg : TArgs) { - bool Success = encodeDataTypeTArgs(SuffixesStream, TArg, ScanPacks); - assert(Success && "Template argument is not supported for encoding."); - } - - return SuffixesStream.str(); - } - - - /// \brief Determines whether result entity (node or template argument) is - /// type/value/instance-dependant. - /// - /// \param TArg Tested template argument. - /// \return true if argument is dependant (it references template - /// argument from outer scope); otherwise, false. - static bool isDependant(const DmngRsltTArg &TArg) { - if (TArg.isType()) - return isDependant(TArg.getType()); - if (TArg.isExpression()) - return isDependant(TArg.getExpression()); - if (TArg.isPack()) { - for (const auto &PackArg : TArg.getPack()) { - if (isDependant(PackArg)) - return true; - } - } - return false; - } - - /// \brief Determines whether result entity (node or template argument) is - /// type/value/instance-dependant. - /// - /// \param NameNode Tested name node from demangler result. - /// \param TArgScopeChanged Placeholder for boolean value indicating that - /// scope of template arguments has changed (only - /// set on change - pass variable initialized to - /// false). All template referencing after scope - /// change referes to new scope. - /// \return true if argument is dependant (it references - /// template argument from outer scope); otherwise, - /// false. - static bool isDependant(const std::shared_ptr &NameNode, - bool *TArgScopeChanged = nullptr) { - if (NameNode == nullptr) - return false; - - auto SpecName = NameNode->getAs(); - if (SpecName != nullptr) { - return isDependant(SpecName->getRelatedObject()) || - isDependant(SpecName->getOrigin()) || - isDependant(SpecName->getRelatedObject()); - } - - auto OrdName = NameNode->getAs(); - if (OrdName != nullptr) { - for (const auto &VQual : OrdName->getVendorQuals()) { - if (!VQual.isTemplate()) - continue; - for (const auto &TArg : VQual.getTemplateArgs()) { - if (isDependant(TArg)) - return true; - } - } - - bool ScopeChanged = false; - if (isDependant(OrdName->getLocalScope(), &ScopeChanged)) - return true; - if (ScopeChanged) { - if (TArgScopeChanged != nullptr) - *TArgScopeChanged = true; - return false; - } - - for (const auto &Part : OrdName->getParts()) { - if (Part->getPartKind() == DNPK_TemplateParam) - return true; - if (Part->getPartKind() == DNPK_Decltype && - isDependant(Part->getAs()->getDecltype())) { - return true; - } - - if (!Part->isTemplate()) - continue; - for (const auto &TArg : Part->getTemplateArgs()) { - if (isDependant(TArg)) - return true; - } - ScopeChanged = true; - } - if (ScopeChanged) { - if (TArgScopeChanged != nullptr) - *TArgScopeChanged = true; - return false; - } - - for (const auto &SigType : OrdName->getSignatureTypes()) { - if (isDependant(SigType)) - return true; - } - } - - return false; - } - - /// \brief Determines whether result entity (node or template argument) is - /// type/value/instance-dependant. - /// - /// \param ExprNode Tested expression node from demangler result. - /// \return true if argument is dependant (it references template - /// argument from outer scope); otherwise, false. - static bool isDependant(const std::shared_ptr &ExprNode) { - if (ExprNode == nullptr) - return false; - - switch (ExprNode->getKind()) { - case DXK_TemplateParam: - return true; - case DXK_Decltype: - return isDependant(ExprNode->getAs()->getExpression()); - case DXK_Primary: - return isDependant(ExprNode->getAs()->getExternalName()); - default: - return false; - } - } - - /// \brief Determines whether result entity (node or template argument) is - /// type/value/instance-dependant. - /// - /// \param TypeNode Tested type node from demangler result. - /// \return true if argument is dependant (it references template - /// argument from outer scope); otherwise, false. - static bool isDependant(const std::shared_ptr &TypeNode) { - if (TypeNode == nullptr) - return false; - - switch (TypeNode->getKind()) { - case DTK_Builtin: - return false; - case DTK_TemplateParam: - case DTK_PackExpansion: // Pack expansion always requires template param. - return true; - case DTK_Function: { - auto FuncType = TypeNode->getAs(); - for (const auto &SigType : FuncType->getSignatureTypes()) { - if (isDependant(SigType)) - return true; - } - return false; - } - case DTK_TypeName: - return isDependant(TypeNode->getAs()->getTypeName()); - case DTK_Array: { - auto ArrayType = TypeNode->getAs(); - return isDependant(ArrayType->getSizeExpr()) || - isDependant(ArrayType->getElemType()); - } - case DTK_Vector: { - auto VecType = TypeNode->getAs(); - return isDependant(VecType->getSizeExpr()) || - isDependant(VecType->getElemType()); - } - case DTK_PointerToMember: { - auto P2MType = TypeNode->getAs(); - return isDependant(P2MType->getClassType()) || - isDependant(P2MType->getMemberType()); - } - case DTK_Decltype: - return isDependant(TypeNode->getAs()->getDecltype()); - case DTK_Pointer: - return isDependant(TypeNode->getAs()->getInnerType()); - case DTK_LValueRef: - return isDependant(TypeNode->getAs()->getInnerType()); - case DTK_RValueRef: - return isDependant(TypeNode->getAs()->getInnerType()); - case DTK_C2000Complex: - return isDependant( - TypeNode->getAs()->getInnerType()); - case DTK_C2000Imaginary: - return isDependant( - TypeNode->getAs()->getInnerType()); - case DTK_QualGroup: { - auto QType = TypeNode->getAs(); - // Most likely case first (dependant type is inner type). - if (isDependant(QType->getInnerType())) - return true; - - for (const auto &VQual : QType->getVendorQuals()) { - if (!VQual.isTemplate()) - continue; - for (const auto &TArg : VQual.getTemplateArgs()) { - if (isDependant(TArg)) - return true; - } - } - - return false; - } - default: - return false; - } - } - - - /// \brief Adapts input name node which identifies data type/variable node. - /// - /// The method tries to adapt data/variable name node. If node is not data - /// node, the method fails adaptation. - /// - /// \param DataNode Input data node which will be adapted. Node must - /// exist, otherwise assert is generated. - /// \param ExtSetBiName Triple that identifies extended set, built-in name and - /// its category. This triple is result of getExtSetBiName - /// method. If the triple is invalid, the method asserts. - /// \return Adaptation result pair. First element indicates - /// status of adaptation. Second contains possibly adapted - /// node. For details please see "Adaptation traits" - /// paragraph ItaniumEncodeTraits. - static std::pair> - adaptDataTypeName( - const std::shared_ptr &DataNode, - const std::tuple &ExtSetBiName) { - assert(DataNode != nullptr && "Node must exist."); - assert(std::get<2>(ExtSetBiName) != BiCategory::Failure && - "Built-in name and category must be valid."); - - // If name does not name data (it is function name), fail adaptation. - if (!DataNode->isData()) - return std::make_pair(printer::AR_Failure, DataNode); - - // If there are no namespace (cl::__spriv). The node was already adapted. - if (DataNode->getParts().size() <= 2) - return std::make_pair(printer::AR_NoAdapt, DataNode); - - // Check whether built-in category is data type or variable. Reflow - // only matching categories. - if (std::get<2>(ExtSetBiName) != BiCategory::Type && - std::get<2>(ExtSetBiName) != BiCategory::Variable) - return std::make_pair(printer::AR_NoAdapt, DataNode); - - // Generate data type name's or variable's optional prefixes. - std::string OptionalPrefixes; - if (std::get<2>(ExtSetBiName) == BiCategory::Variable) - OptionalPrefixes = "BuiltIn"; - - // Generate data type name's or variable's optional suffixes for special - // values and types. - std::string OptionalSuffixes; - if (DataNode->getLastPart()->isTemplate()) { - OptionalSuffixes = encodeDataTypeTArgs( - DataNode->getLastPart()->getTemplateArgs()); - if (!OptionalSuffixes.empty()) - OptionalSuffixes.insert(0, "_"); - } - - // Create new built-in name (data). - std::string NewBiName = "__spirv_"; - if (!std::get<0>(ExtSetBiName).empty()) - NewBiName += std::get<0>(ExtSetBiName) + "_"; - NewBiName += OptionalPrefixes + std::get<1>(ExtSetBiName) + - OptionalSuffixes; - - // Create new node representing new data type/variable name. - auto NewNode = DataNode->clone(false); - NewNode->setPart(std::make_shared(NewBiName)); - NewNode->resetQuals(); - - return std::make_pair(printer::AR_Adapt, NewNode); - } - - -public: - /// \brief Adapts name node (special). - /// - /// For details please see "Adaptation traits" paragraph ItaniumEncodeTraits. - std::pair> - adapt(const std::shared_ptr &Node) const { - assert(Node != nullptr && "Node must exist."); - - if (Node->getSpecialKind() != DSNK_TypeInfoNameString) - return std::make_pair(printer::AR_Failure, nullptr); - auto RelType = Node->getRelatedType(); - assert(RelType && "No related type info."); - auto RelTypeNameNode = RelType->getAs(); - if (RelTypeNameNode == nullptr) - return std::make_pair(printer::AR_Failure, nullptr); - - return std::make_pair(printer::AR_Adapt, RelTypeNameNode->getTypeName()); - } - - /// \brief Adapts name node (ordinary). - /// - /// For details please see "Adaptation traits" paragraph ItaniumEncodeTraits. - std::pair> - adapt(const std::shared_ptr &Node) const { - assert(Node != nullptr && "Node must exist."); - - // If there are no namespace (cl::__spriv). The node was already adapted. - if (Node->getParts().size() <= 2) - return std::make_pair(printer::AR_NoAdapt, Node); - - // Detect extended set and built-in names. - auto ExtSetBiName = getExtSetBiName(Node); - if (std::get<2>(ExtSetBiName) == BiCategory::Failure) - return std::make_pair(printer::AR_Failure, Node); - - // Handle data type names. - if (Node->isData()) - return adaptDataTypeName(Node, ExtSetBiName); - - // Generate function's optional suffixes for special values and types. - std::string OptionalSuffixes; - if (Node->getLastPart()->isTemplate()) { - if (Node->hasReturnType() && isDependant(Node->getReturnType())) { - auto SpecRet = getSpecialReturnTypeEncoding(Node->getReturnType()); - assert(!SpecRet.empty() && - "Template has dependant return type, but it is not special " - "return type. There is currently no way to encode it."); - if (!SpecRet.empty()) - OptionalSuffixes += "_R" + SpecRet; - } - - auto SpecSatEnum = getSpecialEnumValueEncoding( - Node->getLastPart()->getTemplateArgs()); - if (SpecSatEnum != nullptr) - OptionalSuffixes += SpecSatEnum; - - auto SpecRmEnum = - getSpecialEnumValueEncoding( - Node->getLastPart()->getTemplateArgs()); - if (SpecRmEnum != nullptr) - OptionalSuffixes += SpecRmEnum; - } - - // Create new built-in name (function). - std::string NewBiName = "__spirv_"; - if (!std::get<0>(ExtSetBiName).empty()) { - NewBiName += std::get<0>(ExtSetBiName) + "_"; - if (!OptionalSuffixes.empty()) - OptionalSuffixes.insert(0, "_"); - } - NewBiName += std::get<1>(ExtSetBiName) + OptionalSuffixes; - - // Create new node representing new function name. - auto NewNode = Node->clone(false); - NewNode->setPart(std::make_shared(NewBiName)); - NewNode->resetQuals(); - // Node is not template anymore, so encoded return type need to be - // removed. - if (Node->hasReturnType()) { - NewNode->resetSignature(); - for (const auto &ParamType : Node->getParamTypes()) - NewNode->addSignatureType(ParamType); - } - - return std::make_pair(printer::AR_Adapt, NewNode); - } - - /// \brief Adapts array and vector nodes (type flattening). - /// - /// For details please see "Adaptation traits" paragraph ItaniumEncodeTraits. - std::pair> - adapt(const std::shared_ptr &Node) const { - assert(Node != nullptr && "Node must exist."); - - // Array or vector has already got effective size. - if (!Node->isSizeSpecified() || Node->getSizeExpr() == nullptr) - return std::make_pair(printer::AR_NoAdapt, Node); - - // If effective size cannot be computed, do not adapt array/vector. - auto EffectiveSize = getEffectiveArrayVecElements(Node); - if (EffectiveSize == 0) - return std::make_pair(printer::AR_NoAdapt, Node); - - auto NewArrayVec = std::make_shared( - Node->getElemType(), EffectiveSize, - Node->getKind() == DTK_Vector); - return std::make_pair(printer::AR_Adapt, NewArrayVec); - } -}; - -struct OclCxxBifNameReflower : llvm::ModulePass { - /// Identifier of the pass (its address). - static char ID; - - OclCxxBifNameReflower() : ModulePass(ID) {} - - //StringRef getPassName() const override { return "oclcxx-bif-name-reflower"; } - - bool runOnModule(llvm::Module &M) override { - LLVM_DEBUG(llvm::dbgs() << "\n\nSTART OCLCXX-BIF-NAME-REFLOWER PASS\n"); - using EncodeTraits = printer::ItaniumEncodeTraits; - - bool Modified = false; - ItaniumNameParser Parser(OclASExtract); - - // Process type names. - for (llvm::StructType *T : M.getIdentifiedStructTypes()) { - if (T == nullptr) - continue; - auto TypeName = T->getName(); - if (TypeName.empty()) - continue; - - // Extract mangled part of LLVM type name. - auto TypeNameMStart = TypeName.find('.'); - if (TypeNameMStart == llvm::StringRef::npos) - continue; - ++TypeNameMStart; - auto TypeNameMEnd = TypeName.find('.', TypeNameMStart); - if (TypeNameMEnd == llvm::StringRef::npos) - continue; - - auto MangledName = TypeName.substr(TypeNameMStart, - TypeNameMEnd - TypeNameMStart).str(); - // Original LLVM type name (before addition of mangled part). - auto OriginalName = TypeName.substr(0, TypeNameMStart).str() + - TypeName.substr(TypeNameMEnd + 1).str(); - - // Reflow name of LLVM type (if possible) or restore original. - if (MangledName.empty()) { - T->setName(OriginalName); // restore original. - continue; - } - - auto PResult = Parser.parse(MangledName); - if (!OclCxxBiAdaptTraits::isCandidateForReflow(PResult, true)) { - T->setName(OriginalName); // restore original. - continue; - } - - // NOTE: Helper string to support llvm::raw_string_ostream. - EncodeTraits::StringT NewTypeName; - EncodeTraits::StringOStreamT NewTypeNameStream(NewTypeName); - - if (!printer::print(NewTypeNameStream, PResult).first) { - T->setName(OriginalName); // restore original. - continue; - } - - // Check if has proper prefix in name. - NewTypeName = NewTypeNameStream.str(); - if (NewTypeName.compare(0, 8, "__spirv_") != 0) { - T->setName(OriginalName); // restore original. - continue; - } - - // Reformat name string to form correct for LLVM type elements. - auto ResultTypeName = "spirv." + NewTypeName.substr(8); - auto PostfixPos = ResultTypeName.find("__"); - if (PostfixPos != std::string::npos) - ResultTypeName[PostfixPos] = '.'; - - LLVM_DEBUG(llvm::dbgs() << "\nOCLCXX-BIF-NAME-REFLOWER: " - << "The TYPE name is fixed from:\n " << TypeName - << "\n to:\n " << ResultTypeName << "\n"); - - T->setName(ResultTypeName); - Modified = true; - } - - // Process global variables. - for (llvm::GlobalVariable &G : M.globals()) { - auto PResult = Parser.parse(G.getName()); - if (!OclCxxBiAdaptTraits::isCandidateForReflow(PResult)) - continue; - - // NOTE: Helper string to support llvm::raw_string_ostream. - EncodeTraits::StringT NewBiName; - EncodeTraits::StringOStreamT NewBiNameStream(NewBiName); - - if (printer::print(NewBiNameStream, PResult).first) { - G.setName(NewBiNameStream.str()); - Modified = true; - } - } - - // Process function names. - for (llvm::Function &F : M) { - auto PResult = Parser.parse(F.getName()); - if (!OclCxxBiAdaptTraits::isCandidateForReflow(PResult)) - continue; - - // NOTE: Helper string to support llvm::raw_string_ostream. - EncodeTraits::StringT NewBiName; - EncodeTraits::StringOStreamT NewBiNameStream(NewBiName); - - if (printer::print(NewBiNameStream, PResult).first) { - LLVM_DEBUG(llvm::dbgs() << "\nOCLCXX-BIF-NAME-REFLOWER: " - << "The FUNC name has been fixed from:\n " - << F.getName() << "\nto:\n " - << NewBiNameStream.str() << "\n"); - F.setName(NewBiNameStream.str()); - Modified = true; - } - } - return Modified; - } -}; -} - - -char OclCxxBifNameReflower::ID = 0; - -using namespace llvm; -INITIALIZE_PASS(OclCxxBifNameReflower, - "oclcxx-bif-name-reflower", - "Built-in name reflower for OpenCL C++", - false, false) - -ModulePass *llvm::createOclCxxBifNameReflowerPass() { - return new OclCxxBifNameReflower; -} diff --git a/clang/lib/CodeGen/OclCxxRewrite/CMakeLists.txt b/clang/lib/CodeGen/OclCxxRewrite/CMakeLists.txt deleted file mode 100644 index 510fefa0e3922..0000000000000 --- a/clang/lib/CodeGen/OclCxxRewrite/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -set(LLVM_LINK_COMPONENTS - Core - Support - ) - -# In a standard Clang+LLVM build, we need to generate intrinsics before -# building codegen. In a standalone build, LLVM is already built and we don't -# need this dependency. Furthermore, LLVM doesn't export it so we can't have -# this dependency. -set(codegen_deps intrinsics_gen) -if (CLANG_BUILT_STANDALONE) - set(codegen_deps) -endif() - -add_clang_library(clangOclCxxRewrite - BifNameReflower.cpp - OclCxxPrinter.cpp - OclCxxDemangler.cpp - OclCxxDemanglerResult.cpp - - DEPENDS - ${codegen_deps} - - LINK_LIBS - clangAST - clangBasic - clangFrontend - clangLex - ) diff --git a/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemangler.cpp b/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemangler.cpp deleted file mode 100644 index 6a61b1781d23d..0000000000000 --- a/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemangler.cpp +++ /dev/null @@ -1,5655 +0,0 @@ -//===- OclCxxDemangler.cpp - OCLC++ simple demangler -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// -// -// Copyright (c) 2015 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and/or associated documentation files (the -// "Materials"), to deal in the Materials without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Materials, and to -// permit persons to whom the Materials are furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Materials. -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -// -//===----------------------------------------------------------------------===// - - -#include "OclCxxDemangler.h" -#include "OclCxxParseVariant.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace oclcxx::adaptation; - - -// ----------------------------------------------------------------------------- -// TOKENIZER HELPERS -// ----------------------------------------------------------------------------- - -using ParsePosT = std::string::size_type; - - -/// \brief Matches fixed-size prefix. -template -inline static bool matchPrefix(const std::string& ParsedText, - std::string::size_type ParsePos, - const char (&Prefix)[N]) { - if (ParsePos >= ParsedText.length()) - return false; - return ParsedText.compare(ParsePos, N - 1, Prefix) == 0; -} - -/// \brief Matches fixed-size prefix and advances position if succeeded. -template -inline static bool matchPrefixAndAdvance(const std::string& ParsedText, - std::string::size_type& ParsePos, - const char (&Prefix)[N]) { - if (matchPrefix(ParsedText, ParsePos, Prefix)) { - ParsePos += N - 1; - return true; - } - return false; -} - -// ----------------------------------------------------------------------------- -// ::= [n] /[0-9]|[1-9][0-9]+/ - -/// \brief Kind of number maching used by match function. -enum NumberMatchKind { - NMK_Positive, ///< Only positive integral numbers. - NMK_NonNegative, ///< Only non-negative integral numbers. - NMK_NonPositive, ///< Only non-positive integral numbers. - NMK_Negative, ///< Only negative intergal numbers. - NMK_Any, ///< Any integral number. -}; - -/// \brief Matches mangled decimal number and advances position if succeeded. -/// -/// \tparam ResultT Result type for matching. -/// \tparam MatchKind Kind of decimal number match. -/// \tparam MatchLimit Limit of decimal digits in match (0 - no limit). -/// \tparam AllowLeadingZeros Allows leading zeros in match. -/// \param ParsedText Input text for match. -/// \param ParsePos Start position of matching. -/// \param MatchedNumber Placeholder for matched number. -/// \return Indicates that match succeeded. -template -inline static bool matchIntNumberAndAdvance(const std::string& ParsedText, - ParsePosT& ParsePos, - ResultT& MatchedNumber) { - using UResultT = typename std::make_unsigned::type; - const auto ResultTMin = std::numeric_limits::min(); - const auto ResultTMax = std::numeric_limits::max(); - const auto UResultTMax = std::numeric_limits::max(); - - auto TextLen = ParsedText.length(); - auto SignPos = ParsePos; - auto ResultSign = true; // Positive. - UResultT Result = 0; - - if (SignPos < TextLen && ParsedText[SignPos] == 'n') { - if (MatchKind == NMK_Positive || MatchKind == NMK_NonNegative) - return false; - assert(std::numeric_limits::is_signed && - "Matched number cannot be stored in result type (sign)."); - ResultSign = false; - ++SignPos; - } - else if (MatchKind == NMK_Negative) - return false; - - auto DigitPos = SignPos; - while (DigitPos < TextLen && - (MatchLimit <= 0 || DigitPos < SignPos + MatchLimit)) { - auto ParsedDigit = ParsedText[DigitPos] - '0'; - if (ParsedDigit < 0 || ParsedDigit > 9) - break; - // If we have valid next digit while first was 0 (deduced from accumulator), - // we have leading zeros. - if (!AllowLeadingZeros && Result == 0 && DigitPos > SignPos) - return false; - - assert(Result <= UResultTMax / 10 && - Result * 10 + ParsedDigit >= Result * 10 && - "Matched number cannot be stored in result type."); - Result = Result * 10 + ParsedDigit; - ++DigitPos; - } - if (DigitPos == SignPos) - return false; - - if ((MatchKind == NMK_Positive || MatchKind == NMK_Negative) && Result == 0) - return false; - if (MatchKind == NMK_NonPositive && ResultSign && Result > 0) - return false; - - ParsePos = DigitPos; - if (ResultSign) { - assert(Result <= static_cast(ResultTMax) && - "Matched number cannot be stored in result."); - MatchedNumber = static_cast(Result); - } - else { -#ifdef _MSC_VER - // NOTE: This is for removal of annoying non-C++ compliant error when - // using negate operation with unsigned type. The behavior in C++11 - // is well-defined, but on VS with SDL checks it will generate error - // here. This makes harder to use template code and we have already - // assert() which tests parsing signed with unsigned result, so we - // can disable this warning. - #pragma warning(push) - #pragma warning(disable: 4146) -#endif - assert(Result <= static_cast(ResultTMin) && - "Matched number cannot be stored in result."); - MatchedNumber = Result <= static_cast(ResultTMax) - ? -static_cast(Result) - : static_cast(Result); // 2's-complement assumed. -#ifdef _MSC_VER - #pragma warning(pop) -#endif - } - return true; -} - -// ----------------------------------------------------------------------------- -// ::= # number is positive -// -// ::= [a-zA-Z0-9_\x80-\xFF]+ # sequence of bytes of UTF-8 - -/// \brief Matches mangled source name. -/// -/// \param ParsedText Input text for match. -/// \param ParsePos Start position of matching. -/// \param MatchedIdentifier Placeholder for matched identifier. -/// \return Indicates that match succeeded. -inline static bool matchSourceNameAndAdvance(const std::string& ParsedText, - ParsePosT& ParsePos, - std::string& MatchedIdentifier) { - auto TextLen = ParsedText.size(); - auto Pos = ParsePos; - ParsePosT IdentifierSize = 0; - - if (!matchIntNumberAndAdvance(ParsedText, Pos, - IdentifierSize)) - return false; - if (Pos + IdentifierSize < Pos || Pos + IdentifierSize > TextLen) - return false; - - ParsePos = Pos + IdentifierSize; - MatchedIdentifier = ParsedText.substr(Pos, IdentifierSize); - return true; -} - -// ----------------------------------------------------------------------------- -// ::= [0-9A-Z]+ - -/// \brief Matches mangled sequential id and advances position if succeeded. -/// -/// \tparam ResultT Result type for matching (unsigned integral recommended). -/// \param ParsedText Input text for match. -/// \param ParsePos Start position of matching. -/// \param MatchedSeqId Placeholder for matched identifier. -/// \return Indicates that match succeeded. -template -inline static bool matchSeqIdAndAdvance(const std::string& ParsedText, - ParsePosT& ParsePos, - ResultT& MatchedSeqId) { - const auto ResultTMax = std::numeric_limits::max(); - - auto TextLen = ParsedText.size(); - auto Pos = ParsePos; - ResultT Result = 0; - - while (Pos < TextLen) { - auto ParsedDigit = ParsedText[Pos]; // base-36 digit. - if (ParsedDigit >= '0' && ParsedDigit <= '9') - ParsedDigit -= '0'; - else if (ParsedDigit >= 'A' && ParsedDigit <= 'Z') - ParsedDigit = ParsedDigit - 'A' + 10; - else - break; - - assert(Result <= ResultTMax / 36 && - Result * 36 + ParsedDigit >= Result * 36 && - "Matched sequence id cannot be stored in result type."); - Result = Result * 36 + ParsedDigit; - ++Pos; - } - if (Pos == ParsePos) - return false; - - ParsePos = Pos; - MatchedSeqId = Result; - return true; -} - -// ----------------------------------------------------------------------------- -// ::= v # void -// ::= w # wchar_t -// ::= b # bool -// ::= c # char -// ::= a # signed char -// ::= h # unsigned char -// ::= s # short -// ::= t # unsigned short -// ::= i # int -// ::= j # unsigned int -// ::= l # long -// ::= m # unsigned long -// ::= x # long long, __int64 -// ::= y # unsigned long long, __int64 -// ::= n # __int128 -// ::= o # unsigned __int128 -// ::= f # float -// ::= d # double -// ::= e # long double, __float80 -// ::= g # __float128 -// ::= z # ellipsis -// ::= Dd # IEEE 754r decimal floating point (64 bits) -// ::= De # IEEE 754r decimal floating point (128 bits) -// ::= Df # IEEE 754r decimal floating point (32 bits) -// ::= Dh # IEEE 754r half-prec floating point (16 bits) -// ::= Di # char32_t -// ::= Ds # char16_t -// ::= Da # auto -// ::= Dc # decltype(auto) -// ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) - -/// C++ names for fixed built-in types (index corresponds DmngBuiltinType -/// enum value). -static const std::string FixedBuiltinTypeNames[] = { -#define OCLCXX_MENC_BITYPE_FIXED(name, encName, cxxName) cxxName, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_BITYPE_FIXED -}; - -/// Itanium-encoded names for fixed built-in types (index corresponds -/// DmngBuiltinType enum value). -static const std::string EncFixedBuiltinTypeNames[] = { -#define OCLCXX_MENC_BITYPE_FIXED(name, encName, cxxName) encName, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_BITYPE_FIXED -}; - - -/// \brief Returns C++ name of built-in type. -const std::string &oclcxx::adaptation::getFixedBuiltinTypeName( - DmngBuiltinType Type) { - assert(Type >= 0 && Type < sizeof(FixedBuiltinTypeNames) / - sizeof(FixedBuiltinTypeNames[0]) - && "Name of built-in type is not fixed name."); - - return FixedBuiltinTypeNames[Type]; -} - -/// \brief Returns Itanium-encoded name of built-in type. -const std::string &oclcxx::adaptation::getEncFixedBuiltinTypeName( - DmngBuiltinType Type) { - assert(Type >= 0 && Type < sizeof(EncFixedBuiltinTypeNames) / - sizeof(EncFixedBuiltinTypeNames[0]) - && "Name of built-in type is not fixed name."); - - return EncFixedBuiltinTypeNames[Type]; -} - -/// \brief Matches built-in type and advances if succeeded. -static bool matchFixedBiTypeAndAdvance(const std::string &ParsedText, - ParsePosT &ParsePos, - DmngBuiltinType &MatchedType) { - auto TextLen = ParsedText.length(); - auto Pos = ParsePos; - if (Pos >= TextLen) - return false; - - if (ParsedText[Pos] == 'D') { - if (++Pos >= TextLen) - return false; - - switch (ParsedText[Pos]) { - case 'd': MatchedType = DBT_Float64R; - break; - case 'e': MatchedType = DBT_Float128R; - break; - case 'f': MatchedType = DBT_Float32R; - break; - case 'h': MatchedType = DBT_Half; - break; - case 'i': MatchedType = DBT_Char32; - break; - case 's': MatchedType = DBT_Char16; - break; - case 'a': MatchedType = DBT_Auto; - break; - case 'c': MatchedType = DBT_DecltypeAuto; - break; - case 'n': MatchedType = DBT_NullPtr; - break; - case 'F': MatchedType = DBT_Half; Pos += 3; // _Float16 -> DF16_ - break; - default: - return false; - } - - ParsePos = Pos + 1; - return true; - } - - switch (ParsedText[Pos]) { - case 'v': MatchedType = DBT_Void; - break; - case 'w': MatchedType = DBT_WChar; - break; - case 'b': MatchedType = DBT_Bool; - break; - case 'c': MatchedType = DBT_Char; - break; - case 'a': MatchedType = DBT_SChar; - break; - case 'h': MatchedType = DBT_UChar; - break; - case 's': MatchedType = DBT_Short; - break; - case 't': MatchedType = DBT_UShort; - break; - case 'i': MatchedType = DBT_Int; - break; - case 'j': MatchedType = DBT_UInt; - break; - case 'l': MatchedType = DBT_Long; - break; - case 'm': MatchedType = DBT_ULong; - break; - case 'x': MatchedType = DBT_LongLong; - break; - case 'y': MatchedType = DBT_ULongLong; - break; - case 'n': MatchedType = DBT_Int128; - break; - case 'o': MatchedType = DBT_UInt128; - break; - case 'f': MatchedType = DBT_Float; - break; - case 'd': MatchedType = DBT_Double; - break; - case 'e': MatchedType = DBT_LongDouble; - break; - case 'g': MatchedType = DBT_Float128; - break; - case 'z': MatchedType = DBT_Ellipsis; - break; - default: - return false; - } - - ParsePos = Pos + 1; - return true; -} - -// ----------------------------------------------------------------------------- -// ::= [r] [V] [K] # restrict (C99), volatile, const -// -// Correct production: -// ::= r [V] [K] -// ::= [r] V [K] -// ::= [r] [V] K - -/// \brief Matches cvr-qualifiers and advances position if succeeded. -inline static bool matchCvrQualsAndAdvance(const std::string &ParsedText, - ParsePosT &ParsePos, - DmngCvrQuals &MatchedQuals) { - auto TextLen = ParsedText.length(); - auto Pos = ParsePos; - auto Quals = DCVQ_None; - - if (Pos >= TextLen) { - ParsePos = Pos; - MatchedQuals = Quals; - return false; - } - - if (ParsedText[Pos] == 'r') { - Quals = Quals | DCVQ_Restrict; - if (++Pos >= TextLen) { - ParsePos = Pos; - MatchedQuals = Quals; - return true; - } - } - - if (ParsedText[Pos] == 'V') { - Quals = Quals | DCVQ_Volatile; - if (++Pos >= TextLen) { - ParsePos = Pos; - MatchedQuals = Quals; - return true; - } - } - - if (ParsedText[Pos] == 'K') { - Quals = Quals | DCVQ_Const; - ParsePos = Pos + 1; - MatchedQuals = Quals; - return true; - } - - return false; -} - -// ----------------------------------------------------------------------------- -// ::= R # & ref-qualifier -// ::= O # && ref-qualifier - -/// \brief Matches ref-qualifiers and advances position if succeeded. -inline static bool matchRefQualsAndAdvance(const std::string &ParsedText, - ParsePosT &ParsePos, - DmngRefQuals &MatchedQuals) { - auto TextLen = ParsedText.length(); - auto Pos = ParsePos; - if (Pos >= TextLen) - return false; - - switch(ParsedText[Pos]) { - case 'R': MatchedQuals = DRQ_LValueRef; - break; - case 'O': MatchedQuals = DRQ_RValueRef; - break; - default: - return false; - } - - ParsePos = Pos + 1; - return true; -} - -// ----------------------------------------------------------------------------- -// ::= nw # new -// ::= na # new[] -// ::= dl # delete -// ::= da # delete[] -// ::= ps # + (unary) -// ::= ng # - (unary) -// ::= ad # & (unary) -// ::= de # * (unary) -// ::= co # ~ -// ::= pl # + -// ::= mi # - -// ::= ml # * -// ::= dv # / -// ::= rm # % -// ::= an # & -// ::= or # | -// ::= eo # ^ -// ::= aS # = -// ::= pL # += -// ::= mI # -= -// ::= mL # *= -// ::= dV # /= -// ::= rM # %= -// ::= aN # &= -// ::= oR # |= -// ::= eO # ^= -// ::= ls # << -// ::= rs # >> -// ::= lS # <<= -// ::= rS # >>= -// ::= eq # == -// ::= ne # != -// ::= lt # < -// ::= gt # > -// ::= le # <= -// ::= ge # >= -// ::= nt # ! -// ::= aa # && -// ::= oo # || -// ::= pp # ++ (postfix in context) -// ::= mm # -- (postfix in context) -// ::= cm # , -// ::= pm # ->* -// ::= pt # -> -// ::= cl # () -// ::= ix # [] -// ::= qu # ? - -/* -NOTE: Cases created with simple PS script: - -$a = @("nw", "na", "dl", "da", "ps", "ng", "ad", "de", "co", "pl", "mi", "ml", - "dv", "rm", "an", "or", "eo", "aS", "pL", "mI", "mL", "dV", "rM", "aN", - "oR", "eO", "ls", "rs", "lS", "rS", "eq", "ne", "lt", "gt", "le", "ge", - "nt", "aa", "oo", "pp", "mm", "cm", "pm", "pt", "cl", "ix", "qu") - -[string]::join("`n", @($a | % { $_[0] } | sort -Unique | % { - $c = $_; - $sc = [string]::join("`n", @($a | ?{ $_[0] -eq $c} | sort | % { - " case '{0}':`n break;" -f $_[1] - })); - "case '{0}':`n if (++Pos >= TextLen)`n return false;`n" + - " switch(ParsedText[Pos]) {{`n{1}`n default:`n return false;`n }}" + - "`n break;" -f ($c, $sc) -})) -*/ - -/// C++ names for fixed operator names (index corresponds DmngOperatorName -/// enum value). -static const std::string FixedOperatorNames[] = { -#define OCLCXX_MENC_OPR_FIXED(name, encName, arity, cxxName) cxxName, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_OPR_FIXED -}; - -/// Itanium-encoded names for fixed operator names (index corresponds -/// DmngOperatorName enum value). -static const std::string EncFixedOperatorNames[] = { -#define OCLCXX_MENC_OPR_FIXED(name, encName, arity, cxxName) encName, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_OPR_FIXED -}; - -static const int InExprOperatorFixedArities[] = { -#define OCLCXX_MENC_OPR_FIXED(name, encName, arity, cxxName) arity, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_OPR_FIXED - -#define OCLCXX_MENC_OPR(name, arity) arity, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_OPR -}; - - -/// \brief Returns C++ name of operator (without "operator" prefix). -const std::string &oclcxx::adaptation::getFixedOperatorName( - DmngOperatorName NameCode) { - assert(NameCode >= 0 && NameCode < sizeof(FixedOperatorNames) / - sizeof(FixedOperatorNames[0]) - && "Operator name is not fixed name."); - - return FixedOperatorNames[NameCode]; -} - -/// \brief Returns Itanium-encoded name of operator. -const std::string &oclcxx::adaptation::getEncFixedOperatorName( - DmngOperatorName NameCode) { - assert(NameCode >= 0 && NameCode < sizeof(EncFixedOperatorNames) / - sizeof(EncFixedOperatorNames[0]) - && "Operator name is not fixed name."); - - return EncFixedOperatorNames[NameCode]; -} - -/// \brief Returns fixed arity of operator in context. -/// -/// \return Arity of operator, or 0 if arity is unknown, operator requires -/// special form in or number of operands is variable. -int oclcxx::adaptation::getInExprOperatorFixedArity(DmngOperatorName NameCode) { - assert(NameCode >= 0 && NameCode < sizeof(InExprOperatorFixedArities) / - sizeof(InExprOperatorFixedArities[0]) - && "Operator name is invalid / has no arity defined."); - - return InExprOperatorFixedArities[NameCode]; -} - -/// \brief Matches operator name and advances if succeeded. -/// -/// \tparam InExpression Removes operators from matching which require special -/// treatment in expressions. -template -static bool matchFixedOperatorAndAdvance(const std::string &ParsedText, - ParsePosT &ParsePos, - DmngOperatorName &MatchedOperator) { - auto TextLen = ParsedText.length(); - auto Pos = ParsePos; - if (Pos >= TextLen) - return false; - - switch (ParsedText[Pos]) { - case 'a': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'a': MatchedOperator = DON_LogicalAnd; - break; - case 'd': MatchedOperator = DON_AddressOf; - break; - case 'N': MatchedOperator = DON_BitwiseAndAssign; - break; - case 'n': MatchedOperator = DON_BitwiseAnd; - break; - case 'S': MatchedOperator = DON_Assign; - break; - default: - return false; - } - break; - case 'c': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'l': - if (InExpression) - return false; - MatchedOperator = DON_Call; - break; - case 'm': MatchedOperator = DON_Comma; - break; - case 'o': MatchedOperator = DON_BitwiseComplement; - break; - default: - return false; - } - break; - case 'd': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'a': - if (InExpression) - return false; - MatchedOperator = DON_DeleteArray; - break; - case 'e': MatchedOperator = DON_Dereference; - break; - case 'l': - if (InExpression) - return false; - MatchedOperator = DON_Delete; - break; - case 'V': MatchedOperator = DON_DivideAssign; - break; - case 'v': MatchedOperator = DON_Divide; - break; - default: - return false; - } - break; - case 'e': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'O': MatchedOperator = DON_BitwiseExclusiveOrAssign; - break; - case 'o': MatchedOperator = DON_BitwiseExclusiveOr; - break; - case 'q': MatchedOperator = DON_Equal; - break; - default: - return false; - } - break; - case 'g': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'e': MatchedOperator = DON_GreaterEqual; - break; - case 't': MatchedOperator = DON_GreaterThan; - break; - default: - return false; - } - break; - case 'i': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'x': MatchedOperator = DON_Index; - break; - default: - return false; - } - break; - case 'l': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'e': MatchedOperator = DON_LessEqual; - break; - case 's': MatchedOperator = DON_LeftShift; - break; - case 'S': MatchedOperator = DON_LeftShiftAssign; - break; - case 't': MatchedOperator = DON_LessThan; - break; - default: - return false; - } - break; - case 'm': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'I': MatchedOperator = DON_MinusAssign; - break; - case 'i': MatchedOperator = DON_Minus; - break; - case 'L': MatchedOperator = DON_MultiplyAssign; - break; - case 'l': MatchedOperator = DON_Multiply; - break; - case 'm': - if (InExpression) - return false; - MatchedOperator = DON_MinusMinus; - break; - default: - return false; - } - break; - case 'n': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'a': - if (InExpression) - return false; - MatchedOperator = DON_NewArray; - break; - case 'e': MatchedOperator = DON_NotEqual; - break; - case 'g': MatchedOperator = DON_Negative; - break; - case 't': MatchedOperator = DON_LogicalNegate; - break; - case 'w': - if (InExpression) - return false; - MatchedOperator = DON_New; - break; - default: - return false; - } - break; - case 'o': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'o': MatchedOperator = DON_LogicalOr; - break; - case 'r': MatchedOperator = DON_BitwiseOr; - break; - case 'R': MatchedOperator = DON_BitwiseOrAssign; - break; - default: - return false; - } - break; - case 'p': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'l': MatchedOperator = DON_Plus; - break; - case 'L': MatchedOperator = DON_PlusAssign; - break; - case 'm': MatchedOperator = DON_PointerToMemberAccess; - break; - case 'p': - if (InExpression) - return false; - MatchedOperator = DON_PlusPlus; - break; - case 's': MatchedOperator = DON_Positive; - break; - case 't': MatchedOperator = DON_MemberAccess; - break; - default: - return false; - } - break; - case 'q': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'u': MatchedOperator = DON_Conditional; - break; - default: - return false; - } - break; - case 'r': - if (++Pos >= TextLen) - return false; - switch (ParsedText[Pos]) { - case 'M': MatchedOperator = DON_RemainderAssign; - break; - case 'm': MatchedOperator = DON_Remainder; - break; - case 'S': MatchedOperator = DON_RightShiftAssign; - break; - case 's': MatchedOperator = DON_RightShift; - break; - default: - return false; - } - break; - default: - return false; - } - - ParsePos = Pos + 1; - return true; -} - -// ----------------------------------------------------------------------------- -// ::= C1 # complete object constructor -// ::= C2 # base object constructor -// ::= C3 # complete object allocating constructor -// ::= D0 # deleting destructor -// ::= D1 # complete object destructor -// ::= D2 # base object destructor - -/// \brief Matches constructor or destructor name and advances if succeeded. -inline static bool matchCtorDtorAndAdvance(const std::string &ParsedText, - ParsePosT &ParsePos, - bool & IsCtor, - DmngCtorDtorType &CtorDtorType) { - auto TextLen = ParsedText.length(); - auto Pos = ParsePos; - if (Pos >= TextLen) - return false; - - if (ParsedText[Pos] == 'C') { - if (++Pos >= TextLen) - return false; - - switch (ParsedText[Pos]) { - case '1': CtorDtorType = DCDT_CompleteObj; - break; - case '2': CtorDtorType = DCDT_BaseObj; - break; - case '3': CtorDtorType = DCDT_DynMemObj; - break; - default: - return false; - } - - ParsePos = Pos + 1; - IsCtor = true; - return true; - } - - if (ParsedText[Pos] == 'D') { - if (++Pos >= TextLen) - return false; - - switch (ParsedText[Pos]) { - case '0': CtorDtorType = DCDT_DynMemObj; - break; - case '1': CtorDtorType = DCDT_CompleteObj; - break; - case '2': CtorDtorType = DCDT_BaseObj; - break; - default: - return false; - } - - ParsePos = Pos + 1; - IsCtor = false; - return true; - } - - return false; -} - -// ----------------------------------------------------------------------------- -// ::= St # ::std -// ::= Sa # ::std::allocator -// ::= Sb # ::std::basic_string -// ::= Ss # ::std::basic_string , ::std::allocator> -// ::= Si # ::std::basic_istream> -// ::= So # ::std::basic_ostream> -// ::= Sd # ::std::basic_iostream> - -/// \brief Matches standard substitution identifier and advances if succeeded. -inline static bool matchStdSubAndAdvance(const std::string &ParsedText, - ParsePosT &ParsePos, - std::string &SubId) { - auto TextLen = ParsedText.length(); - auto Pos = ParsePos; - if (Pos >= TextLen) - return false; - - if (ParsedText[Pos] != 'S' || ++Pos >= TextLen) - return false; - - switch (ParsedText[Pos]) { - case 't': - case 'a': - case 'b': - case 's': - case 'i': - case 'o': - case 'd': - SubId = ParsedText.substr(ParsePos, 2); - break; - default: - return false; - } - - ParsePos = Pos + 1; - return true; -} - - -// ----------------------------------------------------------------------------- -// RESULT NODES ADAPTERS AND CONVERTERS -// ----------------------------------------------------------------------------- - -/// \brief Adapts node to specific node kind. -/// -/// \param Node Node to adapt. -/// \return Adapted node, or empty shared pointer if node cannot be adapted. -template -static std::shared_ptr adaptNode( - const std::shared_ptr &Node) { - static_assert(AlwaysFalse::value, - "adaptNode() cannot adapt to selected TargetType."); - return nullptr; -} - -template <> -std::shared_ptr adaptNode( - const std::shared_ptr &Node) { - if (Node == nullptr) - return nullptr; - - switch (Node->getNodeKind()) { - case DNDK_Name: { - auto &&NdName = Node->getAs(); - if (NdName->getKind() == DNK_Ordinary) { - return std::make_shared( - NdName->getAs()); - } - return nullptr; - } - case DNDK_NamePart: - return std::make_shared( - std::make_shared(Node->getAs())); - case DNDK_Type: - return Node->getAs(); - case DNDK_Expr: { - auto &&NdExpr = Node->getAs(); - if (NdExpr->getKind() == DXK_TemplateParam) { - return std::make_shared( - NdExpr->getAs()); - } - if (NdExpr->getKind() == DXK_Decltype) { - return std::make_shared( - NdExpr->getAs()); - } - // ReSharper disable once CppUnreachableCode - assert(false && "Other expressions should not be substitutions."); - return nullptr; - } - case DNDK_NameParts: - return std::make_shared( - std::make_shared(Node->getAs())); - default: - return nullptr; - } -} - -template <> -std::shared_ptr adaptNode( - const std::shared_ptr &Node) { - if (Node == nullptr) - return nullptr; - - switch (Node->getNodeKind()) { - case DNDK_Name: - return nullptr; - case DNDK_NamePart: - return std::make_shared(Node->getAs()); - case DNDK_Type: - return nullptr; - case DNDK_Expr: { - auto &&NdExpr = Node->getAs(); - if (NdExpr->getKind() == DXK_TemplateParam) { - return std::make_shared( - std::make_shared( - NdExpr->getAs())); - } - if (NdExpr->getKind() == DXK_Decltype) { - return std::make_shared( - std::make_shared( - NdExpr->getAs())); - } - // ReSharper disable once CppUnreachableCode - assert(false && "Other expressions should not be substitutions."); - return nullptr; - } - case DNDK_NameParts: - return Node->getAs(); - default: - return nullptr; - } -} - - -/// \brief Creates clone of template parameter expression based on -/// node which contains a possibly wrapped template parameter expression. -/// -/// \param Node Node with possibly wrapped template parameter expression. -/// \return Cloned expression node, or empty shared pointer if Node -/// does not contain the expression. -static std::shared_ptr createUnwrappedTParamExpr( - const std::shared_ptr &Node) { - if (Node == nullptr) - return nullptr; - - switch (Node->getNodeKind()) { - case DNDK_Name: - return nullptr; - case DNDK_NamePart: { - const auto &NdTParamNPart = - Node->getAs()->getAs(); - if (NdTParamNPart == nullptr) - return nullptr; - return std::static_pointer_cast( - NdTParamNPart->getTemplateParam()->clone()); - } - case DNDK_Type: { - const auto &NdTParamType = - Node->getAs()->getAs(); - if (NdTParamType == nullptr) - return nullptr; - return std::static_pointer_cast( - NdTParamType->getTemplateParam()->clone()); - } - case DNDK_Expr: - return Node->clone()->getAs()->getAs(); - case DNDK_NameParts: { - const auto &NdNParts = Node->getAs(); - if (NdNParts->getParts().size() != 1) - return nullptr; - const auto &NdNPart = NdNParts->getParts()[0]; - if (NdNPart == nullptr) - return nullptr; - const auto &NdTParamNPart = NdNPart->getAs(); - if (NdTParamNPart == nullptr) - return nullptr; - return std::static_pointer_cast( - NdTParamNPart->getTemplateParam()->clone()); - } - default: - return nullptr; - } -} - - -// ----------------------------------------------------------------------------- -// PARSING CONTEXT AND STATE -// ----------------------------------------------------------------------------- - -namespace { - -/// \brief Parsing conext (forward-declaration). -struct ParseContext; - -/// \brief Identifier of parse state. -enum ParseStateId { - PSI_Start, - PSI_MangledName, - PSI_Encoding, - PSI_Name, - PSI_BareFunctionType, - PSI_SpecialName, - PSI_NestedName, - PSI_UnscopedName, - PSI_UnscopedTemplateName, - PSI_TemplateArgs, - PSI_LocalName, - PSI_Type, - PSI_CallOffset, - PSI_VendorQuals, - PSI_UnqualifiedName, - PSI_Substitution, - PSI_TemplateArg, - PSI_Discriminator, - PSI_BuiltinType, - PSI_FunctionType, - PSI_ClassEnumType, - PSI_ArrayType, - PSI_VectorType, - PSI_PointerToMemberType, - PSI_TemplateParam, - PSI_TemplateTemplateParam, - PSI_Decltype, - PSI_VendorQual, - PSI_DataMemberPrefix, - PSI_UnnamedTypeName, - PSI_OperatorName, - PSI_Expression, - PSI_ExprPrimary, - - // Helper states (to minimize reparses). - PSI_MangledName_Bug, // For bug in clang 3.6 mangling. - PSI_NestedName_Sfx, - PSI_LocalName_Enty, - PSI_NestedName_Start, - PSI_NestedName_Step, - PSI_TemplateArg_Pack, // Different action -> do not add to TArgs. -}; - -/// \brief Parse state in simple demangling parser. -struct ParseState { - /// Type of scope for template parameter resolution. - /// - /// The entry contains triple - boolean value and pair of indices: - /// First boolean value indicates that the template argument scope requires - /// late-referencing of template arguments. - /// The second value: index that identifies parent scope, - /// or -1 (converted to unsigned size type) if the scope has no parent scope; - /// The third value: index that identifies argument group referred in selected - /// scope, or -1 (converted to unsigned size type) if scope does not have - /// argument group (yet). - using TArgScopeT = std::tuple; - - - /// \brief Advances dot for one position (without moving parse position). - void advance() { - ++DotPos; - DotSuccess = true; - } - - /// \brief Advances dot for one position (with moving parse position). - void advance(ParsePosT NewPos) { - assert(NewPos >= StartPos && - "Advance position move parse position before start position."); - Pos = NewPos; - advance(); - } - - /// \brief Moves dot to position of next production and optionally resets - /// parse position to start position for state. - void moveToProduction(unsigned ProdDotPos, bool ResetPosToStartPos = true) { - assert(ProdDotPos >= DotPos && - "Move must advance checked dot position to next production."); - DotPos = ProdDotPos; - DotSuccess = true; - if (ResetPosToStartPos) { - Pos = StartPos; - resetContext(); - } - } - - /// \brief Resets state dot and (optionally) parse position. - void reset(bool ResetPosToStartPos = true) { - DotPos = 0; - DotSuccess = true; - if (ResetPosToStartPos) { - Pos = StartPos; - resetContext(); - } - } - - /// \brief Mark state as failed (try parse). - void fail() { - DotSuccess = false; - } - - - /// \brief Resets variables of parse context to the state from the start of - /// current state (simplified). - /// - /// It resizes all collections to state from start of current parse state - /// (if possible). This solution works only correctly if no elements - /// are removed beyond size when parse state was created. - void resetContext(); - - - /// \brief Adds substitution for current state. - /// - /// It uses current state's parsing positions (start and current) to - /// create identifier of substitution. - /// - /// \param SubRepr Representation for substitution. It will be cloned to - /// collection of substitutions. - void addSubstitute(const std::shared_ptr &SubRepr); - - /// \brief Adds substitution for current state (by move). - /// - /// It uses current state's parsing positions (start and current) to - /// create identifier of substitution. - /// - /// \param SubRepr Representation for substitution. It will be moved to - /// collection of substitutions (it will NOT BE cloned). - void addSubstituteNoClone(std::shared_ptr &&SubRepr); - - - /// \brief Adds new group of template arguments. - /// - /// The method must be called before calling any addTArgToGroup or - /// assignTArgGroupToScope in current state or in any substates. - void addTArgGroup(); - - /// \brief Adds template argument to current argument group (by copy). - /// - /// The method should only be called after addTArgGroup in current or - /// ancestor state. - /// - /// \param Arg Template argument to add. - void addTArg(const std::shared_ptr &Arg); - - /// \brief Adds template argument to current argument group (by move). - /// - /// The method should only be called after addTArgGroup in current or - /// ancestor state. - /// - /// \param Arg Template argument to add. - void addTArg(std::shared_ptr &&Arg); - - /// \brief Indicates that state has created its own scope of template - /// arguments. - /// - /// \return true if state has its own scope; otherwise, false. - bool hasOwnTArgScope() const { - return TArgScopeIdx != TArgScopeStartIdx; - } - - /// \brief Adds new scope for template arguments (for current state and - /// substates). - /// - /// The method must be called before calling any assignTArgGroupToScope - /// in current state or in any substates. - /// - /// The method creates new scope for template arguments for current state and - /// its children. The scope defines range in which assigned template argument - /// group can be referred from template parameters existing in that scope. - /// Subscopes that do not have group assigned by default inherit referred - /// group from parent. If they have group assigned it will hide selection - /// from parent until end of subscope. - /// Normally the assignment of new group into scope will affect only template - /// parameters added after this assignment, but when scope with - /// late-referencing of template parameters is created, the assignment of new - /// group will affect all template parameters in that scope. - /// - /// \param LateReferencing Indicates that scope requires late referencing - /// of template arguments (to partially support - /// bizzare case of convesion operator). - void addTArgScope(bool LateReferencing = false); - - /// \brief Changes behavior of referencing inside current scope. - /// - /// Only template parameters added after change are affected. - /// - /// \param LateReferencing Indicates that scope requires late referencing - /// of template arguments (to partially support - /// bizzare case of convesion operator). - void setTArgScope(bool LateReferencing = false); - - /// \brief Assigns current template argument group to current scope. - /// - /// Both argument group and argument scope must be created before use of - /// this method. - void assignTArgGroupToScope(); - - /// \brief Prepares referencing context for template paramater. - /// - /// \return Pair with values needed to identify referencing context - /// for template parameter (boolean value indicating that - /// late-referencing should be done and index of scope or group - /// (depending on late-referencing flag). - std::pair getTParamReferencingContext() const; - - /// \brief Adds template parameter to current scope (by copy). - /// - /// The method should only be called after addTArgScope in current or - /// ancestor state. - /// - /// \param Param Template parameter to add (for referencing). - void addTParam(const std::shared_ptr &Param); - - /// \brief Adds template parameter to current scope (by move). - /// - /// The method should only be called after addTArgScope in current or - /// ancestor state. - /// - /// \param Param Template parameter to add (for referencing). - void addTParam(std::shared_ptr &&Param); - - - /// \brief Creates new parse state. - explicit ParseState(ParseContext &Ctx, ParseStateId Id, ParsePosT Pos = 0, - std::size_t TArgGrpIdx = static_cast(-1), - std::size_t TArgScopeIdx = static_cast(-1), - bool GatherSubsEnabled = true); - - - /// Parse context. - ParseContext &Ctx; - - /// Position in parsed text at start of parsing of current non-terminal. - const ParsePosT StartPos; - /// Current position in parsed text. - ParsePosT Pos; - - /// State identifier (currently checked non-terminal). - const ParseStateId Id; - - /// Currently checked position in productions of current non-terminal. - /// (start dot position is always 0). - unsigned DotPos; - /// Indicates that parsing of last (non-)terminal was successful and - /// checked position in productions changed. - bool DotSuccess; - - /// Indicates that substition gathering is allowed in current context. - bool GatherSubsEnabled; - - // Functionality for resetting parse position. - - /// Size of Substitutions collection at start of parsing current non-terminal. - const std::size_t SubsSize; - /// Size of TParams collection at start of parsing current non-terminal. - const std::size_t TParamsSize; - /// Size of TArgs collection at start of parsing current non-terminal. - const std::size_t TArgsSize; - /// Size of argument group at start of parsing current non-terminal (used to - /// reset position in cooperation with TArgCurGrpStartIdx). - const std::size_t TArgCurGrpSize; - /// Size of TArgScopes collection at start of parsing current non-terminal. - const std::size_t TArgScopesSize; - /// Initial value of scope at start of parsing current non-terminal (used to - /// reset scope in cooperation with TArgScopeStartIdx). - const TArgScopeT TArgScopeStartVal; - /// Size of Variables collection at start of parsing current non-terminal. - const std::size_t VarsSize; - - // Functionality for referencing template arguments in nested scopes. - - /// Current template argument group (currently extended) at start of current - /// non-terminal. - const std::size_t TArgCurGrpStartIdx; - /// Current template argument group (currently extended). - std::size_t TArgCurGrpIdx; - - /// Current template argument scope index (for template parameters) at start - /// of current non-terminal. - const std::size_t TArgScopeStartIdx; - /// Current template argument scope index (for template parameters). - std::size_t TArgScopeIdx; -}; - -/// Parse context for parser (demangler). -struct ParseContext { - /// Type of collection with parse states. - using StatesT = std::stack; - - /// Type of substitutions collection. - /// - /// Pair represents part of mangled name and corresponding demangled name - /// node that represent the substitution in mangling. - using SubsT = std::vector>>; - - /// Type of helper set which contains parts of mangled names that allow to - /// quickly detect and elimnate duplicates in substitutions. - using SubsStrsT = std::unordered_set; - - /// Type of collection with all template parameters (for late referencing). - /// - /// The collection contains triplets: - /// First boolean value indicates that the template parameter will be - /// late-referenced to template argument. - /// The second value is an index for either template argument group (when - /// first value is false / no late-referencing) or for template argument scope - /// (when first value is true / late-referencing). - /// The last value identifies result node of template parameter expression - /// which will be linked to proper template argument node. - using TParamsT = std::vector>>; - - /// Type of collection with all template arguments (for late referencing). - /// - /// Parameters are resolved in later phase to specific template arguments. - /// - /// First-level collection marks each group of template arguments - /// (group contains template arguments that can be referred at the same time); - /// second-level contains collection of template arguments in current group. - using TArgsT = std::vector>>; - - /// Type of collection with all scopes for resolution of template arguments. - /// - /// Parameters are resolved in later phase to specific template arguments. - /// - /// Each entry contains triple - boolean value and pair of indices: - /// First boolean value indicates that the template argument scope requires - /// late-referencing of template arguments. - /// The second value: index that identifies parent scope, - /// or -1 (converted to unsigned size type) if the scope has no parent scope; - /// The third value: index that identifies argument group referred in selected - /// scope, or -1 (converted to unsigned size type) if scope does not have - /// argument group (yet). - using TArgScopesT = std::vector; - - /// Type of variant temporary variable used by parser. - using VariableT = ParseVariant< - bool, - int, - unsigned int, - long, - unsigned long, - long long, - unsigned long long, - - DmngCvrQuals, - DmngRefQuals, - DmngTypeNameKind, - - std::string, - std::shared_ptr, - - DmngRsltAdjustOffset, - DmngRsltVendorQual, - DmngRsltTArg - >; - - /// Type of collection with variant temporary variables. - using VariablesT = std::vector; - - - /// \brief Report failure and switches to parent state. - /// - /// Invalidates current state. After this function current state may - /// refer to invalid/non-existing state (dangling reference). Please use with - /// caution. - /// - /// This function is intended to be used as state transition function. After - /// this function control flow of parsing should move to end of iteration of - /// parsing loop. - void reportFailToParent() { - assert(!States.empty() && - "This helper function is intended to be used only in parse loop."); - if (!States.empty()) { - States.top().resetContext(); - States.pop(); - if (!States.empty()) - States.top().fail(); - } - } - - /// \brief Reports success to parent state, moves parse position to parse - /// position of current state and switches to parent state (in next - /// iteration). - /// - /// Invalidates current state. After this function current state may - /// refer to invalid/non-existing state (dangling reference). Please use with - /// caution. - /// - /// This function is intended to be used as state transition function. After - /// this function control flow of parsing should move to end of iteration of - /// parsing loop. - void reportSuccessToParent() { - assert(!States.empty() && - "This helper function is intended to be used only in parse loop."); - if (!States.empty()) { - auto NewPos = States.top().Pos; - States.pop(); - if (!States.empty()) - States.top().advance(NewPos); - } - } - - /// \brief Reports success to parent state, moves parse position to specific - /// value and switches to parent state (in next iteration). - /// - /// Invalidates current state. After this function current state may - /// refer to invalid/non-existing state (dangling reference). Please use with - /// caution. - /// - /// This function is intended to be used as state transition function. After - /// this function control flow of parsing should move to end of iteration of - /// parsing loop. - void reportSuccessToParent(ParsePosT NewPos) { - assert(!States.empty() && - "This helper function is intended to be used only in parse loop."); - if (!States.empty()) { - States.pop(); - if (!States.empty()) - States.top().advance(NewPos); - } - } - - /// \brief Parses child state. - /// - /// Adds new child state. If child state failed, in next parsing loop - /// iteration, it will detect failure and report it to parent. - /// - /// - /// Invalidates current state. After this function current state may - /// refer to invalid/non-existing state (dangling reference). Please use with - /// caution. - /// - /// This function is intended to be used as state transition function. After - /// this function control flow of parsing should move to end of iteration of - /// parsing loop. - void parseChildState(ParseStateId StateToParse) { - if (States.empty()) { - // ReSharper disable once CppUnreachableCode - assert(false && "There is no current state."); - return; - } - if (!States.top().DotSuccess) { - reportFailToParent(); - return; - } - - States.emplace(*this, StateToParse, States.top().Pos, - States.top().TArgCurGrpIdx, States.top().TArgScopeIdx, - States.top().GatherSubsEnabled); - } - - /// \brief Parses child state. - /// - /// Adds new child state. If child state failed, in next parsing loop - /// iteration, it will detect failure and move current state to next - /// production. - /// - /// Invalidates current state. After this function current state may - /// refer to invalid/non-existing state (dangling reference). Please use with - /// caution. - /// - /// This function is intended to be used as state transition function. After - /// this function control flow of parsing should move to end of iteration of - /// parsing loop. - void tryParseChildState(ParseStateId StateToParse, - unsigned NextProdDotPos, - bool ResetPosToStartPos = true) { - if (States.empty()) { - // ReSharper disable once CppUnreachableCode - assert(false && "There is no current state."); - return; - } - if (!States.top().DotSuccess) { - States.top().moveToProduction(NextProdDotPos, ResetPosToStartPos); - return; - } - - States.emplace(*this, StateToParse, States.top().Pos, - States.top().TArgCurGrpIdx, States.top().TArgScopeIdx, - States.top().GatherSubsEnabled); - } - - - /// \brief Gets number of variables created for current (and child states). - std::size_t getStateVarsCount() const { - std::size_t Off = States.empty() ? 0 : States.top().VarsSize; - - return Variables.size() > Off ? Variables.size() - Off : 0; - } - - /// \brief Gets variable of current state. - const VariableT &getStateVar(std::size_t Idx) const { - std::size_t Off = States.empty() ? 0 : States.top().VarsSize; - - assert(Idx + Off < Variables.size() && "Accessing variable out of bounds."); - return Variables[Idx + Off]; - } - - /// \brief Gets variable of current state. - VariableT &getStateVar(std::size_t Idx) { - std::size_t Off = States.empty() ? 0 : States.top().VarsSize; - - assert(Idx + Off < Variables.size() && "Accessing variable out of bounds."); - return Variables[Idx + Off]; - } - - /// \brief Tries to remove all variables added after current state - /// was created. - void resetStateVars() { - std::size_t Off = States.empty() ? 0 : States.top().VarsSize; - - if (Variables.size() > Off) - Variables.resize(Off); - } - - - /// Constructs new instance of parse context with set mangled name in result. - explicit ParseContext(const std::string &MangledName) - : Result(MangledName) {} - - /// Constructs new instance of parse context with set mangled name in result. - explicit ParseContext(std::string &&MangledName) - : Result(std::move(MangledName)) {} - - /// Connects template parameters with template arguments referred by them. - bool referenceTParams() { - bool Success = true; - - const auto GroupsCount = TArgs.size(); - const auto ScopesCount = TArgScopes.size(); - - // Resolve group-scope connections by tracking parent scope groups if - // necessary. - for (auto &&Scope : TArgScopes) { - // The group is valid - no necessary to track ancestors. - if (std::get<2>(Scope) < GroupsCount) - continue; - - // Track ancestors scopes until scope with valid group is found. - const auto *TrackedScope = &Scope; - while (std::get<1>(*TrackedScope) < ScopesCount) { - TrackedScope = &TArgScopes[std::get<1>(*TrackedScope)]; - - if (std::get<2>(*TrackedScope) < GroupsCount) { - std::get<2>(Scope) = std::get<2>(*TrackedScope); - break; - } - } - } - - // Resolve template parameters. - for (auto &&TParam : TParams) { - auto LateReferencing = std::get<0>(TParam); - std::size_t GroupIdx; - if (LateReferencing) { - auto ScopeIdx = std::get<1>(TParam); - if (ScopeIdx >= ScopesCount) { - Success = false; - // ReSharper disable once CppUnreachableCode - assert(false && "Invalid template parameter (scope invalid)."); - continue; - } - - GroupIdx = std::get<2>(TArgScopes[ScopeIdx]); - } - else { - // Finish resolving early-referenced parameters. - GroupIdx = std::get<1>(TParam); - } - - if (GroupIdx >= GroupsCount) { - Success = false; - // ReSharper disable once CppUnreachableCode - assert(false && "Invalid template parameter (group invalid)."); - continue; - } - - const auto &TArgGroup = TArgs[GroupIdx]; - auto ArgIdx = std::get<2>(TParam)->getReferredTArgIdx(); - if (ArgIdx >= TArgGroup.size()) { - Success = false; - // ReSharper disable once CppUnreachableCode - assert(false && "Invalid template parameter (arg invalid)."); - continue; - } - - std::get<2>(TParam)->setReferredTArg(TArgGroup[ArgIdx]); - } - - return Success; - } - - /// Parse result. - DmngRslt Result; - - /// Parse states. - StatesT States; - /// Mangling substitutions. - SubsT Substitutions; - /// Substitution identifiers (to provide uniqueness). - SubsStrsT SubstitutionIds; - /// Template parameters. - TParamsT TParams; - /// Template arguments (grouped values for template parameters). - TArgsT TArgs; - /// Scopes for template arguments referencing. - TArgScopesT TArgScopes; - /// Parse temporary variables. - VariablesT Variables; -}; - -} - -// ----------------------------------------------------------------------------- -// Implementation - -inline void ParseState::resetContext() { - while (Ctx.Substitutions.size() > SubsSize) { - Ctx.SubstitutionIds.erase(Ctx.Substitutions.back().first); - Ctx.Substitutions.pop_back(); - } - - if (Ctx.TParams.size() > TParamsSize) - Ctx.TParams.resize(TParamsSize); - if (Ctx.TArgs.size() > TArgsSize) - Ctx.TArgs.resize(TArgsSize); - if (TArgCurGrpStartIdx < Ctx.TArgs.size() && - Ctx.TArgs[TArgCurGrpStartIdx].size() > TArgCurGrpSize) - Ctx.TArgs[TArgCurGrpStartIdx].resize(TArgCurGrpSize); - if (Ctx.TArgScopes.size() > TArgScopesSize) - Ctx.TArgScopes.resize(TArgScopesSize); - if (TArgScopeStartIdx < Ctx.TArgScopes.size()) - Ctx.TArgScopes[TArgScopeStartIdx] = TArgScopeStartVal; - if (Ctx.Variables.size() > VarsSize) - Ctx.Variables.resize(VarsSize); - - TArgCurGrpIdx = TArgCurGrpStartIdx; - TArgScopeIdx = TArgScopeStartIdx; -} - -inline void ParseState::addSubstitute( - const std::shared_ptr &SubRepr) { - if (GatherSubsEnabled) { - std::string SubId = Ctx.Result.getMangledName().substr(StartPos, - Pos - StartPos); - - if (Ctx.SubstitutionIds.insert(SubId).second) { - Ctx.Substitutions.emplace_back(std::move(SubId), SubRepr->clone()); - } - } -} - -inline void ParseState::addSubstituteNoClone( - std::shared_ptr &&SubRepr) { - if (GatherSubsEnabled) { - std::string SubId = Ctx.Result.getMangledName().substr(StartPos, - Pos - StartPos); - - if (Ctx.SubstitutionIds.insert(SubId).second) { - Ctx.Substitutions.emplace_back(std::move(SubId), std::move(SubRepr)); - } - } -} - -inline void ParseState::addTArgGroup() { - Ctx.TArgs.emplace_back(); - TArgCurGrpIdx = Ctx.TArgs.size() - 1; -} - -inline void ParseState::addTArg(const std::shared_ptr &Arg) { - if (TArgCurGrpIdx >= Ctx.TArgs.size()) { - // ReSharper disable once CppUnreachableCode - assert(false && "There is no group to insert template argument into."); - return; - } - - Ctx.TArgs[TArgCurGrpIdx].push_back(Arg); -} - -inline void ParseState::addTArg(std::shared_ptr &&Arg) { - if (TArgCurGrpIdx >= Ctx.TArgs.size()) { - // ReSharper disable once CppUnreachableCode - assert(false && "There is no group to insert template argument into."); - return; - } - - Ctx.TArgs[TArgCurGrpIdx].push_back(std::move(Arg)); -} - -inline void ParseState::addTArgScope(bool LateReferencing) { - Ctx.TArgScopes.push_back(std::make_tuple(LateReferencing, - TArgScopeIdx, - static_cast(-1))); - TArgScopeIdx = Ctx.TArgScopes.size() - 1; -} - -inline void ParseState::setTArgScope(bool LateReferencing) { - if (TArgScopeIdx >= Ctx.TArgScopes.size()) { - // ReSharper disable once CppUnreachableCode - assert(false && "Current scope for template parameters is invalid."); - return; - } - - std::get<0>(Ctx.TArgScopes[TArgScopeIdx]) = LateReferencing; -} - -inline void ParseState::assignTArgGroupToScope() { - if (TArgCurGrpIdx >= Ctx.TArgs.size() || - TArgScopeIdx >= Ctx.TArgScopes.size()) { - // ReSharper disable once CppUnreachableCode - assert(false && "Template argument scope or group is invalid."); - return; - } - - std::get<2>(Ctx.TArgScopes[TArgScopeIdx]) = TArgCurGrpIdx; -} - -std::pair ParseState::getTParamReferencingContext() const { - const auto GroupsCount = Ctx.TArgs.size(); - const auto ScopesCount = Ctx.TArgScopes.size(); - - if (TArgScopeIdx >= ScopesCount) { - assert(false && "Template argument scope is invalid / undefined."); - return std::make_pair(true, static_cast(-1)); - } - - // Resolve group-scope connections by tracking parent scope groups if - // necessary (early-referencing). - auto TrackedScopeIdx = TArgScopeIdx; - do { - const auto &TrackedScope = Ctx.TArgScopes[TrackedScopeIdx]; - - if (std::get<0>(TrackedScope)) // late-referencing case - return std::make_pair(true, TrackedScopeIdx); - if (std::get<2>(TrackedScope) < GroupsCount) // already referenced case - return std::make_pair(false, std::get<2>(TrackedScope)); - - TrackedScopeIdx = std::get<1>(TrackedScope); // parent scope tracking - } while(TrackedScopeIdx < ScopesCount); - - // Fall-back to late-referencing if current attempt failed. - return std::make_pair(true, TArgScopeIdx); -} - -inline void ParseState::addTParam( - const std::shared_ptr &Param) { - auto RefCtx = getTParamReferencingContext(); - - Ctx.TParams.push_back(std::make_tuple(RefCtx.first, RefCtx.second, Param)); -} - -inline void ParseState::addTParam(std::shared_ptr &&Param) { - auto RefCtx = getTParamReferencingContext(); - - Ctx.TParams.push_back(std::make_tuple(RefCtx.first, RefCtx.second, - std::move(Param))); -} - -inline ParseState::ParseState(ParseContext& Ctx, ParseStateId Id, ParsePosT Pos, - std::size_t TArgGrpIdx, std::size_t TArgScopeIdx, - bool GatherSubsEnabled) - : Ctx(Ctx), StartPos(Pos), Pos(Pos), Id(Id), DotPos(0), DotSuccess(true), - GatherSubsEnabled(GatherSubsEnabled), SubsSize(Ctx.Substitutions.size()), - TParamsSize(Ctx.TParams.size()), TArgsSize(Ctx.TArgs.size()), - TArgCurGrpSize(TArgGrpIdx < Ctx.TArgs.size() ? Ctx.TArgs[TArgGrpIdx].size() - : 0), - TArgScopesSize(Ctx.TArgScopes.size()), - TArgScopeStartVal(TArgScopeIdx < Ctx.TArgScopes.size() - ? Ctx.TArgScopes[TArgScopeIdx] - : TArgScopeT()), - VarsSize(Ctx.Variables.size()), - TArgCurGrpStartIdx(TArgGrpIdx), TArgCurGrpIdx(TArgGrpIdx), - TArgScopeStartIdx(TArgScopeIdx), TArgScopeIdx(TArgScopeIdx) {} - - -// ----------------------------------------------------------------------------- -// PARSE ROUTINE -// ----------------------------------------------------------------------------- - -// <> ::= -// -// ::= _Z -// -// ::= # function name -// ::= # data name -// ::= -// -// ::= -// ::= -// ::= -// ::= -// -// ::= # signature types -// ::= -// -// ::= TV # virtual table -// ::= TT # VTT structure (construction vtable index) -// ::= TI # typeinfo structure -// ::= TS # typeinfo name (null-terminated byte string) -// ::= T # base is the nominal target -// # function of thunk -// ::= Tc -// # base is the nominal target function of thunk -// # first call-offset is 'this' adjustment -// # second call-offset is result adjustment -// ::= GV # Guard variable for one-time -// # initialization (no , only object name) -// ::= GR _ # First LE temporary -// # name is object name initialized by temporary -// ::= GR _ # Subsequent LE temporaries -// -// -// ::= N [] [] -// [] [] -// [] E -// ::= N [] [] -// [] [] -// [] E -// -// ::= -// ::= St # ::std:: -// -// ::= -// ::= -// -// ::= I + E -// -// ::= Z E [] -// ::= Z E s [] # string literal -// ::= Z Ed [ ] _ -// # contains function name, describes -// # local entity, is non-negative index of -// # parameter in reverse order (last has no index) -// -// ::= -// ::= -// ::= -// ::= -// ::= -// ::= -// ::= -// ::= -// ::= -// ::= -// ::= # substitute as group with vendor-extended -// # qualifiers, is not empty. -// ::= P # pointer-to -// ::= R # reference-to -// ::= O # rvalue reference-to (C++0x) -// ::= C # complex pair (C 2000) -// ::= G # imaginary (C 2000) -// ::= -// # vendor-extended type qualifier (set is substituted as group -// # with cvr-qualifiers). -// ::= Dp # pack expansion (C++0x) -// -// ::= h _ -// ::= v _ -// -// ::= # non-virtual base override -// -// ::= _ -// # virtual base override, with vcall offset -// -// ::= + -// -// ::= # global class or namespace -// ::= # nested class or namespace -// ::= # class template -// # specialization -// ::= # template type parameter -// ::= # decltype qualifier -// ::= # initializer of a data -// # member -// ::= -// -// ::= -// ::= -// ::= -// ::= -// -// ::= # global template -// ::= # nested template -// ::= # template template parameter -// ::= -// -// -// ::= S _ -// ::= S_ -// ::= St # ::std:: -// ::= Sa # ::std::allocator -// ::= Sb # ::std::basic_string -// ::= Ss # ::std::basic_string , ::std::allocator> -// ::= Si # ::std::basic_istream> -// ::= So # ::std::basic_ostream> -// ::= Sd # ::std::basic_iostream> -// -// ::= # type or template -// ::= X E # expression -// ::= # simple expressions -// ::= J * E # argument pack -// -// ::= _ # when non-negative number < 10 -// ::= __ _ # when non-negative number >= 10 -// -// ::= -// ::= u # vendor-extended type -// -// ::= [] [] -// [] F [Y] -// [] E -// -// ::= # non-dependent type name, dependent type -// # name, or dependent typename-specifier -// ::= Ts # dependent elaborated type specifier -// # using 'struct' or 'class' -// ::= Tu # dependent elaborated type specifier -// # using 'union' -// ::= Te # dependent elaborated type specifier -// # using 'enum' -// -// ::= A _ -// ::= A [] _ -// # array of element types with dimension expression or -// # positive dimension number -// -// ::= Dv _ -// ::= Dv [] _ -// # vector of element types with dimension expression or -// # positive dimension number -// -// ::= -// ::= p # AltiVec pixel -// -// ::= M # class and member types -// -// ::= T_ # first template parameter -// ::= T _ # parameter-2 non-negative number -// -// ::= -// ::= -// -// ::= Dt E # decltype of an id-expression -// # or class member access (C++0x) -// ::= DT E # decltype of an expression (C++0x) -// -// ::= U [] -// -// ::= M # name of member -// -// ::= Ut [] _ # non-negative number -// ::= -// -// ::= Ul E [] _ # non-negative number -// -// ::= + -// # Parameter types or "v" if the lambda has no parameters -// -// ::= -// ::= cv # (cast) -// ::= li # operator "" -// ::= v # vendor extended operator -// -// Limited expression support: -// - only primary non-floating point. -// -// ::= # only primary expressions and -// ::= # template parameters are supported -// -// ::= L E # integer literal -// ::= L E # string literal -// ::= L E # nullptr literal (i.e., "LDnE") -// ::= L 0 E # null pointer template argument -// ::= L E # external name - -/// \brief Parses mangled name (by move). -DmngRslt ItaniumNameParser::parse(std::string &&MangledName) { - using ParseNodeT = std::shared_ptr; - - ParseContext Ctx(std::move(MangledName)); - - - // Standard substitutions. - std::unordered_map> - StdSubstitutions; - { - // [NamePart] ::std - auto StNdPart = std::make_shared("std"); - - // [NameParts] ::std::allocator - auto SaNdParts = std::make_shared(StNdPart); - SaNdParts->addPart(std::make_shared("allocator")); - - // [NameParts] ::std::basic_string - auto SbNdParts = std::make_shared(StNdPart); - SbNdParts->addPart(std::make_shared("basic_string")); - - // [Type] char - auto CharNdType = std::make_shared(DBT_Char); - - // [NameParts, Type] ::std::char_traits - auto CTraitsCNdParts = std::make_shared(StNdPart); - auto CTraitsCNdLPart = std::make_shared("char_traits"); - CTraitsCNdLPart->addTemplateArg(DmngRsltTArg(CharNdType)); - CTraitsCNdParts->addPart(std::move(CTraitsCNdLPart)); - auto CTraitsCNdType = adaptNode(CTraitsCNdParts); - - // [NameParts, Type] ::std::allocator - auto AllocCNdParts = SaNdParts->clone(true)->getAs(); - AllocCNdParts->getModifiableLastPart() - ->addTemplateArg(DmngRsltTArg(CharNdType)); - auto AllocCNdType = adaptNode(AllocCNdParts); - - // [NameParts] ::std::basic_string, - // ::std::allocator> - auto SsNdParts = SbNdParts->clone(true)->getAs(); - auto &&SsNdLPart = SsNdParts->getModifiableLastPart(); - SsNdLPart->addTemplateArg(DmngRsltTArg(CharNdType)); - SsNdLPart->addTemplateArg(DmngRsltTArg(CTraitsCNdType)); - SsNdLPart->addTemplateArg(DmngRsltTArg(AllocCNdType)); - - // [NameParts] ::std::basic_istream> - auto SiNdParts = std::make_shared(StNdPart); - auto SiNdLPart = std::make_shared("basic_istream"); - SiNdLPart->addTemplateArg(DmngRsltTArg(CharNdType)); - SiNdLPart->addTemplateArg(DmngRsltTArg(CTraitsCNdType)); - SiNdParts->addPart(std::move(SiNdLPart)); - - // [NameParts] ::std::basic_ostream> - auto SoNdParts = std::make_shared(StNdPart); - auto SoNdLPart = std::make_shared("basic_ostream"); - SoNdLPart->addTemplateArg(DmngRsltTArg(CharNdType)); - SoNdLPart->addTemplateArg(DmngRsltTArg(CTraitsCNdType)); - SoNdParts->addPart(std::move(SoNdLPart)); - - // [NameParts] ::std::basic_iostream> - auto SdNdParts = std::make_shared(StNdPart); - auto SdNdLPart = std::make_shared("basic_iostream"); - SdNdLPart->addTemplateArg(DmngRsltTArg(CharNdType)); - SdNdLPart->addTemplateArg(DmngRsltTArg(CTraitsCNdType)); - SdNdParts->addPart(std::move(SdNdLPart)); - - - // ::= St # ::std - // ::= Sa # ::std::allocator - // ::= Sb # ::std::basic_string - // ::= Ss # ::std::basic_string , ::std::allocator> - // ::= Si # ::std::basic_istream> - // ::= So # ::std::basic_ostream> - // ::= Sd # ::std::basic_iostream> - StdSubstitutions["St"] = StNdPart; - StdSubstitutions["Sa"] = SaNdParts; - StdSubstitutions["Sb"] = SbNdParts; - StdSubstitutions["Ss"] = SsNdParts; - StdSubstitutions["Si"] = SiNdParts; - StdSubstitutions["So"] = SoNdParts; - StdSubstitutions["Sd"] = SdNdParts; - } - - #define INP_ENSURE_TMP_SIZE(Size_) \ - do { \ - if (Ctx.getStateVarsCount() < (Size_)) { \ - assert(false && "Not enough temporary variables to generate result."); \ - return Ctx.Result.setFailed(); \ - } \ - } while(false) - - - Ctx.States.emplace(Ctx, PSI_Start); - - int CC = 0; - - while (Ctx.States.size() > 0 && Ctx.Result.isSuccessful()) { - ++CC; - auto& State = Ctx.States.top(); // Current state. - - switch (State.Id) { - - // <> ::= - case PSI_Start: - if (!State.DotSuccess) - return Ctx.Result.setFailed(); - - switch (State.DotPos) { - // <> ::= @ - case 0: - Ctx.parseChildState(PSI_MangledName); - break; - // <> ::= @ - case 1: - if (State.Pos == Ctx.Result.getMangledName().size()) { - INP_ENSURE_TMP_SIZE(1); - - const auto& NdMName = - Ctx.getStateVar(0).unsafeGetAsExact(); - Ctx.Result.setName(NdMName->getAs()); - - Ctx.resetStateVars(); - - Ctx.reportSuccessToParent(); // Ending parsing. - break; - } - return Ctx.Result.setFailed(); - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= _Z - // - // Result variables: DmngRsltName - case PSI_MangledName: - switch (State.DotPos) { - // ::= @ _Z - case 0: - State.addTArgScope(); - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_Z")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= _Z @ - case 1: - Ctx.parseChildState(PSI_Encoding); - break; - // ::= _Z @ - case 2: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - // MC*** - // ::= ( _Z | Z ) - // - // Result variables: DmngRsltName - case PSI_MangledName_Bug: - switch (State.DotPos) { - // ::= @ ( _Z | Z ) - case 0: - State.addTArgScope(); - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_Z")) - State.advance(); - else if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Z")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= ( _Z | Z ) @ - case 1: - Ctx.parseChildState(PSI_Encoding); - break; - // ::= ( _Z | Z ) @ - case 2: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= # function name - // ::= # data name - // ::= - // - // Result variables: DmngRsltName - case PSI_Encoding: - switch (State.DotPos) { - // ::= @ - // ::= @ - case 0: - Ctx.tryParseChildState(PSI_Name, 4); - break; - // ::= @ - case 1: - Ctx.tryParseChildState(PSI_BareFunctionType, 3, false); - break; - // ::= @ - case 2: { - INP_ENSURE_TMP_SIZE(2); - - auto NdOName = Ctx.getStateVar(0).unsafeGetAsExact() - ->getAs()->getAs(); - - for (std::size_t I = 1, E = Ctx.getStateVarsCount(); I < E; ++I) { - const auto& NdType = - Ctx.getStateVar(I).unsafeGetAsExact(); - NdOName->addSignatureType(NdType->getAs()); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdOName)); - - Ctx.reportSuccessToParent(); - } - break; - // ::= @ - case 3: - // If result node has no signature, it is treated as data node. - Ctx.reportSuccessToParent(); - break; - - // ::= @ - case 4: - Ctx.parseChildState(PSI_SpecialName); - break; - // ::= @ - case 5: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - // MC*** - // ::= - // ::= # before - // ::= - // ::= - // - // Result variables: DmngRsltName (DmngRsltOrdinaryName) - case PSI_Name: - switch (State.DotPos) { - // ::= @ - case 0: - Ctx.tryParseChildState(PSI_NestedName, 2); - break; - // ::= @ - case 1: - Ctx.reportSuccessToParent(); - break; - - // ::= @ - case 2: - Ctx.tryParseChildState(PSI_UnscopedTemplateName, 5); - break; - // ::= @ - case 3: - Ctx.tryParseChildState(PSI_TemplateArgs, 5); - break; - // ::= @ - case 4: { - INP_ENSURE_TMP_SIZE(2); - - auto NdOName = Ctx.getStateVar(0).unsafeGetAsExact() - ->getAs()->getAs(); - auto NdONameCopy = NdOName->clone(true); - auto &&NdTNPart = NdONameCopy->getModifiableLastPart(); - - for (std::size_t I = 1, E = Ctx.getStateVarsCount(); I < E; ++I) { - auto TArg = Ctx.getStateVar(I).unsafeGetAsExact(); - NdTNPart->addTemplateArg(std::move(TArg)); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdONameCopy)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 5: - Ctx.tryParseChildState(PSI_UnscopedName, 7); - break; - // ::= @ - case 6: - Ctx.reportSuccessToParent(); - break; - - // ::= @ - case 7: - Ctx.parseChildState(PSI_LocalName); - break; - // ::= @ - case 8: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= + - // - // Result variables: DmngRsltType+ - case PSI_BareFunctionType: - switch (State.DotPos) { - // ::= @ + - case 0: - Ctx.parseChildState(PSI_Type); - break; - // ::= + @ * - case 1: - Ctx.tryParseChildState(PSI_Type, 3, false); - break; - case 2: - // Flattening recursive production. - State.reset(false); - State.moveToProduction(1, false); - break; - // ::= + @ - case 3: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= TV - // ::= TT - // ::= TI - // ::= TS - // ::= T - // ::= Tc - // ::= GV - // ::= GR [] _ - // - // Result variables: DmngRsltName (DmngRsltSpecialName) - case PSI_SpecialName: - switch (State.DotPos) { - // ::= @ TV - case 0: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "TV")) - State.advance(); - else - State.moveToProduction(3); - break; - // ::= TV @ - case 1: - Ctx.tryParseChildState(PSI_Type, 3); - break; - // ::= TV @ - case 2: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - auto NdSName = std::make_shared( - DmngRsltSpecialName::createVirtualTable( - NdType->getAs())); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdSName)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ TT - case 3: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "TT")) - State.advance(); - else - State.moveToProduction(6); - break; - // ::= TT @ - case 4: - Ctx.tryParseChildState(PSI_Type, 6); - break; - // ::= TT @ - case 5: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - auto NdSName = std::make_shared( - DmngRsltSpecialName::createVirtualTableTable( - NdType->getAs())); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdSName)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ TI - case 6: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "TI")) - State.advance(); - else - State.moveToProduction(9); - break; - // ::= TI @ - case 7: - Ctx.tryParseChildState(PSI_Type, 9); - break; - // ::= TI @ - case 8: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - auto NdSName = std::make_shared( - DmngRsltSpecialName::createTypeInfoStruct( - NdType->getAs())); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdSName)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ TS - case 9: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "TS")) - State.advance(); - else - State.moveToProduction(12); - break; - // ::= TS @ - case 10: - Ctx.tryParseChildState(PSI_Type, 12); - break; - // ::= TS @ - case 11: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - auto NdSName = std::make_shared( - DmngRsltSpecialName::createTypeInfoNameString( - NdType->getAs())); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdSName)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ T - case 12: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), State.Pos, "T")) - State.advance(); - else - State.moveToProduction(16); - break; - // ::= T @ - case 13: - Ctx.tryParseChildState(PSI_CallOffset, 16); - break; - // ::= T @ - case 14: - Ctx.tryParseChildState(PSI_Encoding, 16); - break; - // ::= T @ - case 15: { - INP_ENSURE_TMP_SIZE(2); - - const auto &ThisOff = - Ctx.getStateVar(0).unsafeGetAsExact(); - const auto &NdEnc = - Ctx.getStateVar(1).unsafeGetAsExact(); - - auto NdSName = std::make_shared( - DmngRsltSpecialName::createVirtualThunk( - NdEnc->getAs(), ThisOff)); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdSName)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ Tc - case 16: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Tc")) - State.advance(); - else - State.moveToProduction(21); - break; - // ::= Tc @ - case 17: - Ctx.tryParseChildState(PSI_CallOffset, 21); - break; - // ::= Tc @ - case 18: - Ctx.tryParseChildState(PSI_CallOffset, 21); - break; - // ::= Tc @ - case 19: - Ctx.tryParseChildState(PSI_Encoding, 21); - break; - // ::= Tc @ - case 20: { - INP_ENSURE_TMP_SIZE(3); - - const auto &ThisOff = - Ctx.getStateVar(0).unsafeGetAsExact(); - const auto &RetOff = - Ctx.getStateVar(1).unsafeGetAsExact(); - const auto &NdEnc = - Ctx.getStateVar(2).unsafeGetAsExact(); - - auto NdSName = std::make_shared( - DmngRsltSpecialName::createVirtualThunk( - NdEnc->getAs(), ThisOff, RetOff)); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdSName)); - - Ctx.reportSuccessToParent(); - } - break; - - - // ::= @ GV - case 21: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "GV")) - State.advance(); - else - State.moveToProduction(24); - break; - // ::= GV @ - case 22: - Ctx.tryParseChildState(PSI_Name, 24); - break; - // ::= GV @ - case 23: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdName = - Ctx.getStateVar(0).unsafeGetAsExact(); - - auto NdSName = std::make_shared( - DmngRsltSpecialName::createGuardVariable( - NdName->getAs()->getAs())); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdSName)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ GR [] _ - case 24: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "GR")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= GR @ [] _ - case 25: - Ctx.parseChildState(PSI_Name); - break; - // ::= GR @ [] _ - case 26: { - unsigned long long TemporaryId = 0; - if (matchSeqIdAndAdvance(Ctx.Result.getMangledName(), - State.Pos, TemporaryId)) { - assert(TemporaryId + 1 > TemporaryId && "Id out of bounds."); - ++TemporaryId; - } - Ctx.Variables.emplace_back(TemporaryId); - State.advance(); - } - break; - // ::= GR [] @ _ - case 27: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= GR [] _ @ - case 28: { - INP_ENSURE_TMP_SIZE(2); - - const auto &NdName = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto Id = - Ctx.getStateVar(1).unsafeGetAsExact(); - - auto NdSName = std::make_shared( - DmngRsltSpecialName::createLifeExtTemporary( - NdName->getAs()->getAs(), Id)); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdSName)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= N [] [] - // [] [] - // [] - // - // Nested name suffix reflows: , , , - // - // in in more relaxed way - it requires final semantic - // check: - // - name parts: at least 2 or 1 if last part is template - // - last part is not data member name. - // - // ::= - // ::= - // ::= - // - // ::= - // ::= - // - // ::= ( [() ] | - // [] ) - // (() [() ])* E - // () - position to register prefix as substitution. - // - // Result variables: DmngRsltOrdinaryName - case PSI_NestedName: - switch (State.DotPos) { - // ::= @ N [] [] ... - case 0: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "N")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= N @ [] [] ... - case 1: - // Phase 1 of collecting all vendor-extended qualifiers. - Ctx.tryParseChildState(PSI_VendorQuals, 2, false); - break; - // ::= N [] @ [] ... - case 2: { - DmngCvrQuals CvrQuals; - if (matchCvrQualsAndAdvance(Ctx.Result.getMangledName(), - State.Pos, CvrQuals)) { - Ctx.Variables.emplace_back(CvrQuals); - } - State.advance(); - } - break; - // ::= N [] [] @ - // [] ... - case 3: - // Phase 2 of collecting all vendor-extended qualifiers. - Ctx.tryParseChildState(PSI_VendorQuals, 4, false); - break; - // ::= ... [] @ [] ... - case 4: { - DmngRefQuals RefQuals; - if (matchRefQualsAndAdvance(Ctx.Result.getMangledName(), - State.Pos, RefQuals)) { - Ctx.Variables.emplace_back(RefQuals); - } - State.advance(); - } - break; - // ::= ... [] @ [] ... - case 5: - // Phase 3 of collecting all vendor-extended qualifiers. - Ctx.tryParseChildState(PSI_VendorQuals, 6, false); - break; - // ::= ... [] @ - case 6: - Ctx.parseChildState(PSI_NestedName_Sfx); - break; - // ::= ... [] @ - case 7: { - INP_ENSURE_TMP_SIZE(1); - - std::size_t QualsCount = Ctx.getStateVarsCount() - 1; - - auto &&NdNParts = - Ctx.getStateVar(QualsCount).unsafeGetAsExact() - ->getAs(); - - // Check semantics of nested name. - if (NdNParts->getParts().empty() || - NdNParts->getLastPart()->isDataMember() || - (!NdNParts->getLastPart()->isTemplate() && - NdNParts->getParts().size() < 2)) { - Ctx.reportFailToParent(); - break; - } - - auto NdOName = - std::make_shared(std::move(NdNParts)); - - for (std::size_t I = 0; I < QualsCount; ++I) { - const auto& Qual = Ctx.getStateVar(I); - - if (Qual.isAExact()) { - const auto &VQual = Qual.unsafeGetAsExact(); - auto ASQual = ASExtractFunc(VQual); - - if (ASQual != DASQ_None) - NdOName->setAsQuals(ASQual); - NdOName->addVendorQual(VQual); - } - else if(Qual.isAExact()) - NdOName->setCvrQuals(Qual.unsafeGetAsExact()); - else if(Qual.isAExact()) - NdOName->setRefQuals(Qual.unsafeGetAsExact()); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdOName)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - // MC*** - // ::= ( [() ] | - // [] ) - // (() [() ])* E - // - // Result variables: DmngRsltNameParts - case PSI_NestedName_Sfx: - switch (State.DotPos) { - // ::= ( @ [() ] - // | [] ) ( ... )* E - case 0: - Ctx.tryParseChildState(PSI_NestedName_Start, 2); - break; - // ::= ( @ [() ] - // | [] ) ( ... )* E - case 1: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdNode = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdNParts = adaptNode(NdNode); - - if (NdNParts == nullptr) { - Ctx.reportFailToParent(); - break; - } - - // Simple check to omit last non-terminal in substitution set. - if (!matchPrefix(Ctx.Result.getMangledName(), State.Pos, "E")) { - // Add original non-adapted as substitute (to allow correct - // template parameter/decltype() referencing). - State.addSubstitute(NdNode); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdNParts)); - - State.moveToProduction(4, false); - } - break; - - // ::= ( [() ] - // | @ [] ) ( ... )* E - case 2: - Ctx.parseChildState(PSI_Substitution); - break; - // ::= ( [() ] - // | @ [] ) ( ... )* E - case 3: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdNode = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdNParts = adaptNode(NdNode); - - if (NdNParts == nullptr) { - Ctx.reportFailToParent(); - break; - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdNParts)); - - State.moveToProduction(4, false); - } - break; - - // ::= ( [() @ ] - // | [@ ] ) ( ... )* E - case 4: - Ctx.tryParseChildState(PSI_TemplateArgs, 6, false); - break; - - // ::= ( [() ] - // | [] ) @ - // ( () - // [() ] )* E - case 5: { - INP_ENSURE_TMP_SIZE(2); - - auto NdNParts = Ctx.getStateVar(0).unsafeGetAsExact() - ->getAs(); - auto NdNPartsCopy = NdNParts->clone(true)->getAs(); - auto &&NdTNPart = NdNPartsCopy->getModifiableLastPart(); - - for (std::size_t I = 1, E = Ctx.getStateVarsCount(); I < E; ++I) { - auto TArg = Ctx.getStateVar(I).unsafeGetAsExact(); - NdTNPart->addTemplateArg(std::move(TArg)); - } - - // Simple check to omit last non-terminal in substitution set. - if (!matchPrefix(Ctx.Result.getMangledName(), State.Pos, "E")) { - State.addSubstitute(NdNPartsCopy); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdNPartsCopy)); - - State.advance(); - } - break; - - // ::= ( ... ) ( () @ - // [() ] )* E - case 6: - Ctx.tryParseChildState(PSI_NestedName_Step, 11, false); - break; - // ::= ( ... ) ( () @ - // [() ] )* E - case 7: { - INP_ENSURE_TMP_SIZE(2); - - auto NdNParts = Ctx.getStateVar(0).unsafeGetAsExact() - ->getAs(); - auto &&NdLPart = Ctx.getStateVar(1).unsafeGetAsExact() - ->getAs(); - - NdNParts->addPart(std::move(NdLPart)); - - // Simple check to omit last non-terminal in substitution set. - if (!matchPrefix(Ctx.Result.getMangledName(), State.Pos, "E")) { - State.addSubstitute(NdNParts); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdNParts)); - - State.advance(); - } - break; - // ::= ( ... ) ( () - // [() @ ] )* E - case 8: - Ctx.tryParseChildState(PSI_TemplateArgs, 10, false); - break; - // ::= ( ... ) ( () - // [() @] )* E - case 9: - State.reset(false); - State.moveToProduction(5, false); - break; - case 10: - State.reset(false); - State.moveToProduction(6, false); - break; - - // ::= ( ... ) ( () - // [() ] )* @ E - case 11: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) { - // ::= ( ... ) ( ... )* E @ - Ctx.reportSuccessToParent(); - break; - } - Ctx.reportFailToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - // MC*** - // ::= - // ::= - // ::= - // - // Result variables: DmngRsltNode (same set as ) - case PSI_NestedName_Start: - switch (State.DotPos) { - // ::= - case 0: - Ctx.tryParseChildState(PSI_UnqualifiedName, 2); - break; - // ::= - case 1: - Ctx.reportSuccessToParent(); - break; - - // ::= @ - case 2: - Ctx.tryParseChildState(PSI_TemplateParam, 4); - break; - // ::= @ - case 3: - Ctx.reportSuccessToParent(); - break; - - // ::= @ - case 4: - Ctx.parseChildState(PSI_Decltype); - break; - // ::= @ - case 5: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - // MC*** - // ::= - // ::= - // - // Result variables: DmngRsltNamePart - case PSI_NestedName_Step: - switch (State.DotPos) { - // ::= @ - case 0: - Ctx.tryParseChildState(PSI_DataMemberPrefix, 2); - break; - // ::= @ - case 1: - Ctx.reportSuccessToParent(); - break; - - - // ::= @ - case 2: - Ctx.parseChildState(PSI_UnqualifiedName); - break; - // ::= @ - case 3: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= [St] - // - // Result variables: DmngRsltName (DmngRsltOrdinaryName) - case PSI_UnscopedName: - switch (State.DotPos) { - // ::= @ [St] - case 0: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "St")) { - // Assuming DNDK_NamePart node: "::std::" - auto ElemIt = StdSubstitutions.find("St"); - if (ElemIt == StdSubstitutions.end()) { - // ReSharper disable once CppUnreachableCode - assert(false && "Missing standard substitution."); - Ctx.reportFailToParent(); - break; - } - Ctx.Variables.emplace_back(ElemIt->second->clone()); - } - State.advance(); - break; - // ::= [St] @ - case 1: - Ctx.parseChildState(PSI_UnqualifiedName); - break; - // ::= [St] @ - case 2: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdNPart = - Ctx.getStateVar(0).unsafeGetAsExact(); - - auto NdOName = std::make_shared( - NdNPart->getAs()); - - for (std::size_t I = 1, E = Ctx.getStateVarsCount(); I < E; ++I) { - const auto &NdNSubpart = - Ctx.getStateVar(I).unsafeGetAsExact(); - NdOName->addPart(NdNSubpart->getAs()); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdOName)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= - // ::= - // - // Result variables: DmngRsltName (DmngRsltOrdinaryName) - case PSI_UnscopedTemplateName: - switch (State.DotPos) { - // ::= @ - case 0: - Ctx.tryParseChildState(PSI_UnscopedName, 2); - break; - // ::= @ - case 1: { - INP_ENSURE_TMP_SIZE(1); - - const auto& NdOName = - Ctx.getStateVar(0).unsafeGetAsExact(); - - State.addSubstituteNoClone(std::make_shared( - *NdOName->getAs()->getAs())); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 2: - Ctx.parseChildState(PSI_Substitution); - break; - // ::= @ - case 3: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdNode = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdNParts = adaptNode(NdNode); - - if (NdNParts == nullptr) { - Ctx.reportFailToParent(); - break; - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::make_shared( - NdNParts->getAs())); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= I + E - // - // Result variables: DmngRsltTArg+ - case PSI_TemplateArgs: - switch (State.DotPos) { - // ::= @ I + E - case 0: - State.addTArgGroup(); - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "I")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= I @ + E - case 1: - Ctx.parseChildState(PSI_TemplateArg); - break; - // ::= I + @ * E - case 2: - Ctx.tryParseChildState(PSI_TemplateArg, 4, false); - break; - case 3: - // Flattening recursive production from step 2. - State.reset(false); - State.moveToProduction(2, false); - break; - // ::= I + @ E - case 4: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= I + E @ - case 5: - State.assignTArgGroupToScope(); - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= Z E - // ::= [] - // ::= s [] - // ::= d [ ] _ - // - // Result variables: DmngRsltName (DmngRsltOrdinaryName) - case PSI_LocalName: - switch (State.DotPos) { - // ::= @ Z E - case 0: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Z")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= Z @ E - case 1: - Ctx.parseChildState(PSI_Encoding); - break; - // ::= Z @ E - case 2: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= Z E @ - case 3: - Ctx.parseChildState(PSI_LocalName_Enty); - break; - // ::= Z E @ - case 4: { - // Type of local name (0 - local class, 1 - string literal, - // 2 - parameter scope). - INP_ENSURE_TMP_SIZE(2); - - auto TypeSelIdx = Ctx.getStateVarsCount() - 1; - - auto NdScope = Ctx.getStateVar(0).unsafeGetAsExact() - ->getAs(); - auto TypeSel = Ctx.getStateVar(TypeSelIdx).unsafeGetAsExact(); - - // Local scope element. - if (TypeSel == 0) { - auto NdOName = Ctx.getStateVar(1).unsafeGetAsExact() - ->getAs()->getAs(); - - NdOName->setLocalScope(std::move(NdScope)); - - if (TypeSelIdx > 2) { - auto Id = Ctx.getStateVar(2).unsafeGetAsExact(); - NdOName->setInLocalScopeIdx(Id + 1); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdOName)); - - Ctx.reportSuccessToParent(); - break; - } - // String literal. - if (TypeSel == 1) { - auto NdOName = std::make_shared(); - - NdOName->setLocalScope(std::move(NdScope)); - - if (TypeSelIdx > 1) { - auto Id = Ctx.getStateVar(1).unsafeGetAsExact(); - NdOName->setInLocalScopeIdx(Id + 1); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdOName)); - - Ctx.reportSuccessToParent(); - break; - } - // Default value of parameter. - if (TypeSel == 2) { - auto ParamIdx = Ctx.getStateVar(1).unsafeGetAsExact(); - auto NdOName = Ctx.getStateVar(2).unsafeGetAsExact() - ->getAs()->getAs(); - - NdOName->setLocalScope(std::move(NdScope)); - NdOName->setDefaultValueParamRIdx(ParamIdx); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdOName)); - - Ctx.reportSuccessToParent(); - break; - } - - Ctx.reportFailToParent(); - } - break; - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - // MC*** - // ::= [] - // ::= s [] - // ::= d [ ] _ - case PSI_LocalName_Enty: - switch (State.DotPos) { - // ::= @ [] - case 0: - Ctx.tryParseChildState(PSI_Name, 3); - break; - // ::= @ [] - case 1: - Ctx.tryParseChildState(PSI_Discriminator, 2, false); - break; - // ::= [] @ - case 2: - Ctx.Variables.emplace_back(0); - Ctx.reportSuccessToParent(); - break; - - // ::= @ s [] - case 3: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "s")) - State.advance(); - else - State.moveToProduction(6); - break; - // ::= s @ [] - case 4: - Ctx.tryParseChildState(PSI_Discriminator, 5, false); - break; - // ::= s [] @ - case 5: - Ctx.Variables.emplace_back(1); - Ctx.reportSuccessToParent(); - break; - - // ::= @ d [ ] _ - case 6: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "d")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= d @ [ ] _ - case 7: { - int ParamRIdx = 0; - - if (matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, ParamRIdx)) { - assert(ParamRIdx + 1 > ParamRIdx && "Param idx out of bounds."); - ++ParamRIdx; - } - Ctx.Variables.emplace_back(ParamRIdx); - State.advance(); - } - break; - // ::= d [ ] @ _ - case 8: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= d [ ] _ @ - case 9: - Ctx.parseChildState(PSI_Name); - break; - // ::= d [ ] _ @ - case 10: - Ctx.Variables.emplace_back(2); - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= # before - // ::= # before qual type - // ::= - // ::= - // ::= - // ::= - // ::= #before - // ::= - // ::= - // ::= P - // ::= R - // ::= O - // ::= C - // ::= G - // ::= Dp - // ::= ( | )+ - // ::= - // - // Result variables: DmngRsltType - case PSI_Type: - // Restrict scope of template parameters to type definition. - if (!State.hasOwnTArgScope()) - State.addTArgScope(); - - switch (State.DotPos) { - // TODO: If special one-time preinitialization is no longer necessary, - // remove it in the future. - case 0: - State.advance(); - break; - - // ::= @ - case 1: - Ctx.tryParseChildState(PSI_BuiltinType, 3); - break; - // ::= @ - case 2: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - if (NdType->getAs()->getAs() - ->isVendorBuiltinType()) - State.addSubstitute(NdType); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 3: - Ctx.tryParseChildState(PSI_FunctionType, 5); - break; - // ::= @ - case 4: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - // Exception from substitution: function type when parent entity - // is pointer to member is not candidate. - auto CurrentState = State; - Ctx.States.pop(); - - if (Ctx.States.top().Id != PSI_PointerToMemberType) - CurrentState.addSubstitute(NdType); - - Ctx.States.push(std::move(CurrentState)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 5: - Ctx.tryParseChildState(PSI_ClassEnumType, 7); - break; - // ::= @ - case 6: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - State.addSubstitute(NdType); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 7: - Ctx.tryParseChildState(PSI_ArrayType, 9); - break; - // ::= @ - case 8: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - State.addSubstitute(NdType); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 9: - Ctx.tryParseChildState(PSI_VectorType, 11); - break; - // ::= @ - case 10: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - State.addSubstitute(NdType); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 11: - Ctx.tryParseChildState(PSI_PointerToMemberType, 13); - break; - // ::= @ - case 12: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - State.addSubstitute(NdType); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 13: - Ctx.tryParseChildState(PSI_TemplateTemplateParam, 16); - break; - // ::= @ - case 14: - Ctx.tryParseChildState(PSI_TemplateArgs, 16); - break; - // ::= @ - case 15: { - INP_ENSURE_TMP_SIZE(2); - - auto NdType = Ctx.getStateVar(0).unsafeGetAsExact() - ->getAs(); - - DmngRsltTArgsBase *TArgsElem = nullptr; - if (NdType->getKind() == DTK_TemplateParam) - TArgsElem = NdType->getAs().get(); - if (NdType->getKind() == DTK_TypeName) { - TArgsElem = const_cast( - NdType->getAs()->getTypeName() - ->getLastPart().get()); - } - - if (TArgsElem == nullptr) { - Ctx.reportFailToParent(); - break; - } - - for (std::size_t I = 1, E = Ctx.getStateVarsCount(); I < E; ++I) { - auto TArg = Ctx.getStateVar(I).unsafeGetAsExact(); - TArgsElem->addTemplateArg(std::move(TArg)); - } - - State.addSubstitute(NdType); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 16: - Ctx.tryParseChildState(PSI_TemplateParam, 18); - break; - // ::= @ - case 17: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdExpr = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdType = std::make_shared( - NdExpr->getAs()->getAs()); - - State.addSubstitute(NdExpr); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 18: - Ctx.tryParseChildState(PSI_Decltype, 20); - break; - // ::= @ - case 19: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdExpr = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdType = std::make_shared( - NdExpr->getAs()->getAs()); - - State.addSubstitute(NdExpr); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ P - case 20: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "P")) - State.advance(); - else - State.moveToProduction(23); - break; - // ::= P @ - case 21: - Ctx.tryParseChildState(PSI_Type, 23); - break; - // ::= P @ - case 22: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdQType = std::make_shared( - DmngRsltQualType::createPointer(NdType->getAs())); - - State.addSubstitute(NdQType); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdQType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ R - case 23: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "R")) - State.advance(); - else - State.moveToProduction(26); - break; - // ::= R @ - case 24: - Ctx.tryParseChildState(PSI_Type, 26); - break; - // ::= R @ - case 25: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdQType = std::make_shared( - DmngRsltQualType::createLValueRef(NdType->getAs())); - - State.addSubstitute(NdQType); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdQType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ O - case 26: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "O")) - State.advance(); - else - State.moveToProduction(29); - break; - // ::= O @ - case 27: - Ctx.tryParseChildState(PSI_Type, 29); - break; - // ::= O @ - case 28: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdQType = std::make_shared( - DmngRsltQualType::createRValueRef(NdType->getAs())); - - State.addSubstitute(NdQType); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdQType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ C - case 29: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "C")) - State.advance(); - else - State.moveToProduction(32); - break; - // ::= C @ - case 30: - Ctx.tryParseChildState(PSI_Type, 32); - break; - // ::= C @ - case 31: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdQType = std::make_shared( - DmngRsltQualType::createComplex(NdType->getAs())); - - State.addSubstitute(NdQType); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdQType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ G - case 32: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "G")) - State.advance(); - else - State.moveToProduction(35); - break; - // ::= G @ - case 33: - Ctx.tryParseChildState(PSI_Type, 35); - break; - // ::= G @ - case 34: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdQType = std::make_shared( - DmngRsltQualType::createImaginary(NdType->getAs())); - - State.addSubstitute(NdQType); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdQType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ Dp - case 35: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Dp")) - State.advance(); - else - State.moveToProduction(38); - break; - // ::= Dp @ - case 36: - Ctx.tryParseChildState(PSI_Type, 38); - break; - // ::= Dp @ - case 37: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdQType = std::make_shared( - DmngRsltQualType::createPackExpansion( - NdType->getAs())); - - State.addSubstitute(NdQType); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdQType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= ( @ | )+ - case 38: { - DmngCvrQuals CvrQuals; - if (matchCvrQualsAndAdvance(Ctx.Result.getMangledName(), - State.Pos, CvrQuals)) { - Ctx.Variables.emplace_back(CvrQuals); - State.advance(); - } - else - State.moveToProduction(42); - } - break; - // ::= ( | )+ - // ( @ | )* - case 39: { - DmngCvrQuals CvrQuals; - if (matchCvrQualsAndAdvance(Ctx.Result.getMangledName(), - State.Pos, CvrQuals)) { - Ctx.Variables.emplace_back(CvrQuals); - } - else - State.advance(); - } - break; - // ::= ( | )+ - // ( | @ )* - case 40: - Ctx.tryParseChildState(PSI_VendorQuals, 44, false); - break; - case 41: - // Flattening recursive production. - State.reset(false); - State.moveToProduction(39, false); - break; - // ::= ( | @ )+ - case 42: - Ctx.tryParseChildState(PSI_VendorQuals, 46); - break; - case 43: - // Flattening recursive production. - State.reset(false); - State.moveToProduction(39, false); - break; - // ::= ( | )+ @ - case 44: - Ctx.tryParseChildState(PSI_Type, 46); - break; - // ::= ( | )+ @ - case 45: { - INP_ENSURE_TMP_SIZE(2); - - auto QualsCount = Ctx.getStateVarsCount() - 1; - - const auto &NdType = - Ctx.getStateVar(QualsCount).unsafeGetAsExact(); - auto NdQType = std::make_shared( - NdType->getAs()); - - DmngCvrQuals CvrQuals = DCVQ_None; - for (std::size_t I = 0; I < QualsCount; ++I) { - const auto &Qual = Ctx.getStateVar(I); - - if (Qual.isAExact()) { - const auto &VQual = Qual.unsafeGetAsExact(); - auto ASQual = ASExtractFunc(VQual); - - if (ASQual != DASQ_None) - NdQType->setAsQuals(ASQual); - NdQType->addVendorQual(std::move(VQual)); - } - else if(Qual.isAExact()) - CvrQuals = CvrQuals | Qual.unsafeGetAsExact(); - } - NdQType->setCvrQuals(CvrQuals); - - State.addSubstitute(NdQType); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdQType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 46: - Ctx.parseChildState(PSI_Substitution); - break; - // ::= @ - case 47: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdNode = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdType = adaptNode(NdNode); - - if (NdType == nullptr) { - Ctx.reportFailToParent(); - break; - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdType)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= h _ - // ::= v _ - // ::= - // ::= _ - // - // Result variables: DmngRsltAdjustOffset - case PSI_CallOffset: - switch (State.DotPos) { - // ::= @ h _ - case 0: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "h")) { - State.moveToProduction(1); - break; - } - - // ::= h @ _ - unsigned long long Offset; - if (!matchIntNumberAndAdvance(Ctx.Result.getMangledName(), - State.Pos, Offset)) { - State.moveToProduction(1); - break; - } - - // ::= h @ _ - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - State.moveToProduction(1); - break; - } - - // ::= h _ @ - Ctx.Variables.emplace_back(DmngRsltAdjustOffset(Offset)); - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ v _ _ - case 1: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "v")) { - Ctx.reportFailToParent(); - break; - } - - // ::= v @ _ _ - unsigned long long BaseOffset; - if (!matchIntNumberAndAdvance(Ctx.Result.getMangledName(), - State.Pos, BaseOffset)) { - Ctx.reportFailToParent(); - break; - } - - // ::= v @ _ _ - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - Ctx.reportFailToParent(); - break; - } - - // ::= v _ @ _ - unsigned long long VCallOffset; - if (!matchIntNumberAndAdvance(Ctx.Result.getMangledName(), - State.Pos, VCallOffset)) { - Ctx.reportFailToParent(); - break; - } - - // ::= v _ @ _ - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - Ctx.reportFailToParent(); - break; - } - - // ::= v _ _ @ - Ctx.Variables.emplace_back( - DmngRsltAdjustOffset(BaseOffset, VCallOffset)); - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= + - // - // Result variables: DmngRsltVendorQual+ - case PSI_VendorQuals: - switch (State.DotPos) { - // ::= @ + - case 0: - Ctx.parseChildState(PSI_VendorQual); - break; - // ::= + @ * - case 1: - Ctx.tryParseChildState(PSI_VendorQual, 3, false); - break; - case 2: - // Flattening recursive production. - State.reset(false); - State.moveToProduction(1, false); - break; - // ::= + @ - case 3: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= - // ::= - // ::= - // ::= - // - // Result variables: DmngRsltNamePart - case PSI_UnqualifiedName: - switch (State.DotPos) { - // ::= @ - case 0: - Ctx.tryParseChildState(PSI_OperatorName, 2); - break; - // ::= @ - case 1: - Ctx.reportSuccessToParent(); - break; - - // ::= @ - case 2: { - bool IsCtor = false; - DmngCtorDtorType CtorDtorType; - if (matchCtorDtorAndAdvance(Ctx.Result.getMangledName(), State.Pos, - IsCtor, CtorDtorType)) { - // ::= @ - Ctx.Variables.emplace_back( - std::make_shared(IsCtor, - CtorDtorType)); - - Ctx.reportSuccessToParent(); - break; - } - - State.moveToProduction(3); - } - break; - - // ::= @ - case 3: { - std::string SrcName; - if (matchSourceNameAndAdvance(Ctx.Result.getMangledName(), - State.Pos, SrcName)) { - // ::= @ - Ctx.Variables.emplace_back( - std::make_shared(SrcName)); - - Ctx.reportSuccessToParent(); - break; - } - - State.moveToProduction(4); - } - break; - - // ::= @ - case 4: - Ctx.parseChildState(PSI_UnnamedTypeName); - break; - // ::= @ - case 5: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= S [] _ - // ::= - // - // Result variables: DmngRsltNode (DmngRsltNamePart | DmngRsltNameParts - // | DmngRsltTParamExpr | DmngRsltDecltypeExpr - // | DmngRsltType ) - case PSI_Substitution: - switch (State.DotPos) { - // ::= @ S [] _ - case 0: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "S")) { - State.moveToProduction(1); - break; - } - - // ::= S @ [] _ - ParseContext::SubsT::size_type SubId = 0; - if (matchSeqIdAndAdvance(Ctx.Result.getMangledName(), - State.Pos, SubId)) { - assert(SubId + 1 > SubId && "Id out of bounds."); - ++SubId; - } - - // ::= S [] @ _ - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - // ::= S [] _ @ - if (SubId >= Ctx.Substitutions.size()) { - // ReSharper disable once CppUnreachableCode - assert(false && "Missing substitution."); - State.moveToProduction(1); - break; - } - - // Direct substitutions for template parameters need to be - // registered for referencing. - auto NdTParamExpr = createUnwrappedTParamExpr( - Ctx.Substitutions[SubId].second); - if (NdTParamExpr != nullptr) { - State.addTParam(NdTParamExpr); - Ctx.Variables.emplace_back(std::move(NdTParamExpr)); - - Ctx.reportSuccessToParent(); - break; - } - - Ctx.Variables.emplace_back( - Ctx.Substitutions[SubId].second->clone()); - - Ctx.reportSuccessToParent(); - break; - } - - State.moveToProduction(1); - } - break; - - // ::= @ - case 1: { - std::string StdSubId; - if (matchStdSubAndAdvance(Ctx.Result.getMangledName(), - State.Pos, StdSubId)) { - // ::= @ - auto ElemIt = StdSubstitutions.find(StdSubId); - if (ElemIt == StdSubstitutions.end()) { - // ReSharper disable once CppUnreachableCode - assert(false && "Missing standard substitution."); - Ctx.reportFailToParent(); - break; - } - - Ctx.Variables.emplace_back(ElemIt->second->clone()); - - Ctx.reportSuccessToParent(); - break; - } - - Ctx.reportFailToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= - // ::= X E - // ::= - // ::= J * E - // - // Result variables: DmngRsltTArg - case PSI_TemplateArg: - case PSI_TemplateArg_Pack: - switch (State.DotPos) { - // ::= @ - case 0: - Ctx.tryParseChildState(PSI_Type, 2); - break; - // ::= @ - case 1: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - DmngRsltTArg Arg(NdType->getAs()); - - Ctx.resetStateVars(); - if (State.Id != PSI_TemplateArg_Pack) - State.addTArg(std::make_shared(Arg)); - Ctx.Variables.emplace_back(std::move(Arg)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ X E - case 2: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "X")) { - State.advance(); - break; - } - State.moveToProduction(5); - break; - // ::= X @ E - case 3: - Ctx.tryParseChildState(PSI_Expression, 5); - break; - // ::= X @ E - case 4: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) { - // ::= X E @ - INP_ENSURE_TMP_SIZE(1); - - const auto &NdExpr = - Ctx.getStateVar(0).unsafeGetAsExact(); - - DmngRsltTArg Arg(NdExpr->getAs()); - - Ctx.resetStateVars(); - if (State.Id != PSI_TemplateArg_Pack) - State.addTArg(std::make_shared(Arg)); - Ctx.Variables.emplace_back(std::move(Arg)); - - Ctx.reportSuccessToParent(); - break; - } - State.moveToProduction(5); - break; - - // ::= @ - case 5: - Ctx.tryParseChildState(PSI_ExprPrimary, 7); - break; - // ::= @ - case 6: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdPExpr = - Ctx.getStateVar(0).unsafeGetAsExact(); - - DmngRsltTArg Arg(NdPExpr->getAs()); - - Ctx.resetStateVars(); - if (State.Id != PSI_TemplateArg_Pack) - State.addTArg(std::make_shared(Arg)); - Ctx.Variables.emplace_back(std::move(Arg)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ J * E - case 7: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "J")) { - State.advance(); - break; - } - Ctx.reportFailToParent(); - break; - // ::= J * @ * E - case 8: - Ctx.tryParseChildState(PSI_TemplateArg_Pack, 10, false); - break; - case 9: - // Flattening recursive production. - State.reset(false); - State.moveToProduction(8, false); - break; - // ::= J * @ E - case 10: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) { - // ::= J * E @ - DmngRsltTArg Arg; - for (std::size_t I = 0, E = Ctx.getStateVarsCount(); I < E; ++I) { - const auto &PackArg = - Ctx.getStateVar(I).unsafeGetAsExact(); - - Arg.addPackArg(PackArg); - } - - Ctx.resetStateVars(); - if (State.Id != PSI_TemplateArg_Pack) - State.addTArg(std::make_shared(Arg)); - Ctx.Variables.emplace_back(std::move(Arg)); - - Ctx.reportSuccessToParent(); - break; - } - Ctx.reportFailToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= __ _ - // ::= _ # two characters - // - // Result variables: int - case PSI_Discriminator: - switch (State.DotPos) { - // ::= @ __ _ - case 0: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "__")) { - State.moveToProduction(1); - break; - } - - // ::= __ @ _ - int DiscriminatorIdx = 0; - if (!matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, DiscriminatorIdx)) { - State.moveToProduction(1); - break; - } - - // ::= __ @ _ - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - // ::= __ _ @ - Ctx.Variables.emplace_back(DiscriminatorIdx); - - Ctx.reportSuccessToParent(); - break; - } - - State.moveToProduction(1); - } - break; - - // ::= @ _ # two characters - case 1: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - Ctx.reportFailToParent(); - break; - } - - // ::= _ @ # two characters - int DiscriminatorIdx = 0; - if (matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, DiscriminatorIdx)) { - // ::= _ @ # two characters - Ctx.Variables.emplace_back(DiscriminatorIdx); - - Ctx.reportSuccessToParent(); - break; - } - - Ctx.reportFailToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= - // ::= u - // - // Result variables: DmngRsltType (DmngRsltBuiltinType) - case PSI_BuiltinType: - switch (State.DotPos) { - // ::= @ - case 0: { - DmngBuiltinType FixedType = DBT_Void; - if (matchFixedBiTypeAndAdvance(Ctx.Result.getMangledName(), - State.Pos, FixedType)) { - // ::= @ - Ctx.Variables.emplace_back( - std::make_shared(FixedType)); - - Ctx.reportSuccessToParent(); - break; - } - State.moveToProduction(1); - } - break; - - // ::= @ u - case 1: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "u")) { - Ctx.reportFailToParent(); - break; - } - - // ::= u @ - std::string VendorType; - if (matchSourceNameAndAdvance(Ctx.Result.getMangledName(), - State.Pos, VendorType)) { - // ::= u @ - Ctx.Variables.emplace_back( - std::make_shared(VendorType)); - - Ctx.reportSuccessToParent(); - break; - } - - Ctx.reportFailToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= [] [] - // [] F [Y] - // [] E - // - // Result variables: DmngRsltType (DmngRsltFuncType) - case PSI_FunctionType: - switch (State.DotPos) { - case 0: - // Initializing helper variables. - Ctx.Variables.emplace_back(); // Position of first type. - State.advance(); - break; - // ::= @ [] [] ... - case 1: - Ctx.tryParseChildState(PSI_VendorQuals, 2, false); - break; - // ::= [] @ [] ... - case 2: { - DmngCvrQuals CvrQuals = DCVQ_None; - if (matchCvrQualsAndAdvance(Ctx.Result.getMangledName(), - State.Pos, CvrQuals)) { - Ctx.Variables.emplace_back(CvrQuals); - } - State.advance(); - } - break; - // ::= ... [] @ [] ... - case 3: - Ctx.tryParseChildState(PSI_VendorQuals, 4, false); - break; - // ::= ... [] @ F [Y] ... - case 4: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "F")) { - Ctx.reportFailToParent(); - break; - } - - // ::= ... [] F @ [Y] ... - bool IsExternC = matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Y"); - Ctx.Variables.emplace_back(IsExternC); - Ctx.getStateVar(0) = Ctx.getStateVarsCount(); - State.advance(); - } - break; - // ::=... [Y] @ [] E - case 5: - Ctx.parseChildState(PSI_BareFunctionType); - break; - // ::= ... @ [] E - case 6: { - DmngRefQuals RefQuals = DRQ_None; - matchRefQualsAndAdvance(Ctx.Result.getMangledName(), State.Pos, - RefQuals); - - // ::= ... [] @ E - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) { - Ctx.reportFailToParent(); - break; - } - - // ::= ... [] E @ - INP_ENSURE_TMP_SIZE(3); - auto SignatureStart = Ctx.getStateVar(0).unsafeGetAs(); - INP_ENSURE_TMP_SIZE(SignatureStart + 1); - - const auto &NdArg0Type = - Ctx.getStateVar(SignatureStart).unsafeGetAsExact(); - - auto NdFuncType = std::make_shared( - NdArg0Type->getAs()); - - for (std::size_t I = SignatureStart + 1, - E = Ctx.getStateVarsCount(); I < E; ++I) { - const auto &NdArgType = - Ctx.getStateVar(I).unsafeGetAsExact(); - NdFuncType->addSignatureType(NdArgType->getAs()); - } - - for (std::size_t I = 0; I < SignatureStart - 1; ++I) { - const auto &Qual = Ctx.getStateVar(I); - - if (Qual.isAExact()) { - const auto &VQual = Qual.unsafeGetAsExact(); - auto ASQual = ASExtractFunc(VQual); - - if (ASQual != DASQ_None) - NdFuncType->setAsQuals(ASQual); - NdFuncType->addVendorQual(VQual); - } - else if(Qual.isAExact()) - NdFuncType->setCvrQuals(Qual.unsafeGetAsExact()); - } - - NdFuncType->setRefQuals(RefQuals); - NdFuncType->setIsExternC( - Ctx.getStateVar(SignatureStart - 1).unsafeGetAsExact()); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdFuncType)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= - // ::= Ts - // ::= Tu - // ::= Te - // - // Result variables: DmngRsltType (DmngRsltTypeNameType) - case PSI_ClassEnumType: - switch (State.DotPos) { - // ::= @ [ Ts | Tu | Te ] - case 0: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Ts")) { - Ctx.Variables.emplace_back(DTNK_ElaboratedClass); - State.advance(); - break; - } - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Tu")) { - Ctx.Variables.emplace_back(DTNK_ElaboratedUnion); - State.advance(); - break; - } - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Te")) { - Ctx.Variables.emplace_back(DTNK_ElaboratedEnum); - State.advance(); - break; - } - Ctx.Variables.emplace_back(DTNK_None); - State.advance(); - break; - // ::= [ Ts | Tu | Te ] @ - case 1: - Ctx.parseChildState(PSI_Name); - break; - // ::= [ Ts | Tu | Te ] @ - case 2: { - INP_ENSURE_TMP_SIZE(2); - - auto ElaborationType = - Ctx.getStateVar(0).unsafeGetAsExact(); - const auto &NdOName = - Ctx.getStateVar(1).unsafeGetAsExact(); - - auto NdTypeName = std::make_shared( - NdOName->getAs()->getAs(), - ElaborationType); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdTypeName)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= A _ - // ::= A [] _ - // - // Result variables: DmngRsltType (DmngRsltArrayVecType) - case PSI_ArrayType: - switch (State.DotPos) { - // ::= @ A [ | ] _ - case 0: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "A")) { - Ctx.reportFailToParent(); - break; - } - - // ::= A @ [] _ - unsigned long long ElemsCount = 0; - if (matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, ElemsCount)) { - Ctx.Variables.emplace_back(ElemsCount); - State.moveToProduction(2, false); - break; - } - State.advance(); - } - break; - // ::= A @ [] _ - case 1: - Ctx.tryParseChildState(PSI_Expression, 2, false); - break; - // ::= A [ | ] @ _ - case 2: - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - Ctx.reportFailToParent(); - break; - } - State.advance(); - break; - // ::= A [ | ] _ @ - case 3: - Ctx.parseChildState(PSI_Type); - break; - // ::= A [ | ] _ @ - case 4: { - INP_ENSURE_TMP_SIZE(1); - - ParseNodeT NdArrayType; - if (Ctx.getStateVarsCount() == 1) { - const auto &NdElemType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - NdArrayType = std::make_shared( - NdElemType->getAs()); - } - else { - const auto &Dims = Ctx.getStateVar(0); - const auto &NdElemType = - Ctx.getStateVar(1).unsafeGetAsExact(); - - if (Dims.isAExact()) { - NdArrayType = std::make_shared( - NdElemType->getAs(), - Dims.unsafeGetAsExact()->getAs()); - } - else { - NdArrayType = std::make_shared( - NdElemType->getAs(), - Dims.unsafeGetAsExact()); - } - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdArrayType)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= Dv _ - // ::= Dv [] _ - // ::= - // ::= p - // - // Result variables: DmngRsltType (DmngRsltArrayVecType) - case PSI_VectorType: - switch (State.DotPos) { - // ::= @ Dv [ | ] _ - case 0: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Dv")) { - Ctx.reportFailToParent(); - break; - } - - // ::= Dv @ [] _ - unsigned long long ElemsCount = 0; - if (matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, ElemsCount)) { - Ctx.Variables.emplace_back(ElemsCount); - State.moveToProduction(2, false); - break; - } - State.advance(); - } - break; - // ::= Dv @ [] _ - case 1: - Ctx.tryParseChildState(PSI_Expression, 2, false); - break; - // ::= Dv [ | ] @ _ - case 2: - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - Ctx.reportFailToParent(); - break; - } - - // ::= Dv [ | ] _ @ p - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "p")) { - Ctx.Variables.emplace_back( - std::make_shared(DBT_Pixel)); - State.moveToProduction(4, false); - break; - } - State.advance(); - break; - // ::= Dv [ | ] _ @ - case 3: - Ctx.parseChildState(PSI_Type); - break; - // ::= A [ | ] _ @ - case 4: { - INP_ENSURE_TMP_SIZE(1); - - ParseNodeT NdVecType; - if (Ctx.getStateVarsCount() == 1) { - const auto &NdElemType = - Ctx.getStateVar(0).unsafeGetAsExact(); - - NdVecType = std::make_shared( - NdElemType->getAs(), true); - } - else { - const auto &Dims = Ctx.getStateVar(0); - const auto &NdElemType = - Ctx.getStateVar(1).unsafeGetAsExact(); - - if (Dims.isAExact()) { - NdVecType = std::make_shared( - NdElemType->getAs(), - Dims.unsafeGetAsExact()->getAs(), - true); - } - else { - NdVecType = std::make_shared( - NdElemType->getAs(), - Dims.unsafeGetAsExact(), true); - } - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdVecType)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= M - // - // Result variables: DmngRsltType (DmngRsltPtr2MmbrType) - case PSI_PointerToMemberType: - switch (State.DotPos) { - // ::= @ M - case 0: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "M")) { - State.advance(); - break; - } - Ctx.reportFailToParent(); - break; - // ::= M @ - case 1: - Ctx.parseChildState(PSI_Type); - break; - // ::= M @ - case 2: - Ctx.parseChildState(PSI_Type); - break; - // ::= M @ - case 3: { - INP_ENSURE_TMP_SIZE(2); - - const auto &NdClassType = - Ctx.getStateVar(0).unsafeGetAsExact(); - const auto &NdMemberType = - Ctx.getStateVar(1).unsafeGetAsExact(); - - auto NdPtr2MembType = std::make_shared( - NdClassType->getAs(), - NdMemberType->getAs()); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdPtr2MembType)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= T [] _ - // - // Result variables: DmngRsltExpr (DmngRsltTParamExpr) - case PSI_TemplateParam: - switch (State.DotPos) { - // ::= @ T [] _ - case 0: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "T")) { - Ctx.reportFailToParent(); - break; - } - - // ::= T @ [] _ - unsigned ArgIdx = 0; - if (matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, ArgIdx)) { - assert(ArgIdx + 1 > ArgIdx && "Argument index is out of bounds."); - ++ArgIdx; - } - - // ::= T [] @ _ - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - Ctx.reportFailToParent(); - break; - } - - // ::= T [] _ @ - auto NdTParam = std::make_shared(ArgIdx); - - State.addTParam(NdTParam); - Ctx.Variables.emplace_back(std::move(NdTParam)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= - // ::= - // - // Result variables: DmngRsltType - case PSI_TemplateTemplateParam: - switch (State.DotPos) { - // ::= @ - case 0: - Ctx.tryParseChildState(PSI_TemplateParam, 2); - break; - // ::= @ - case 1: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdExpr = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdType = std::make_shared( - NdExpr->getAs()->getAs()); - - State.addSubstitute(NdExpr); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdType)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= @ - case 2: - Ctx.parseChildState(PSI_Substitution); - break; - // ::= @ - case 3: { - INP_ENSURE_TMP_SIZE(1); - - const auto &NdNode = - Ctx.getStateVar(0).unsafeGetAsExact(); - auto NdType = adaptNode(NdNode); - - if (NdType == nullptr) { - Ctx.reportFailToParent(); - break; - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdType)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= Dt E - // ::= DT E - // - // Result variables: DmngRsltExpr (DmngRsltDecltypeExpr) - case PSI_Decltype: - switch (State.DotPos) { - // ::= @ ( Dt | DT ) E - case 0: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Dt")) { - Ctx.Variables.emplace_back(true); - State.advance(); - break; - } - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "DT")) { - Ctx.Variables.emplace_back(false); - State.advance(); - break; - } - Ctx.reportFailToParent(); - break; - // ::= ( Dt | DT ) @ E - case 1: - Ctx.parseChildState(PSI_Expression); - break; - // ::= ( Dt | DT ) @ E - case 2: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) { - Ctx.reportFailToParent(); - break; - } - - // ::= ( Dt | DT ) E @ - INP_ENSURE_TMP_SIZE(2); - - auto IsSimple = Ctx.getStateVar(0).unsafeGetAsExact(); - const auto &NdExpr = - Ctx.getStateVar(1).unsafeGetAsExact(); - - auto NdDecltype = std::make_shared( - NdExpr->getAs(), IsSimple); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdDecltype)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= U [] - // - // Result variables: DmngRsltVendorQual - case PSI_VendorQual: - switch (State.DotPos) { - // ::= @ U [] - case 0: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "U")) { - Ctx.reportFailToParent(); - break; - } - - // ::= U @ [] - std::string QualName; - if (!matchSourceNameAndAdvance(Ctx.Result.getMangledName(), - State.Pos, QualName)) { - Ctx.reportFailToParent(); - break; - } - - Ctx.Variables.emplace_back(QualName); - State.addTArgScope(); - State.advance(); - } - break; - // ::= U @ [] - case 1: - Ctx.tryParseChildState(PSI_TemplateArgs, 2, false); - break; - // ::= U [] @ - case 2: { - INP_ENSURE_TMP_SIZE(1); - - const auto &QualName = - Ctx.getStateVar(0).unsafeGetAsExact(); - - DmngRsltVendorQual Qual(QualName); - - for (std::size_t I = 1, E = Ctx.getStateVarsCount(); I < E; ++I) { - const auto &Arg = - Ctx.getStateVar(I).unsafeGetAsExact(); - - Qual.addTemplateArg(Arg); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(Qual)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= M - // - // Result variables: DmngRsltNamePart (DmngRsltSrcNamePart) - case PSI_DataMemberPrefix: - switch (State.DotPos) { - // ::= @ M - case 0: { - std::string MemberName; - if (!matchSourceNameAndAdvance(Ctx.Result.getMangledName(), - State.Pos, MemberName)) { - Ctx.reportFailToParent(); - break; - } - - // ::= @ M - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "M")) { - Ctx.reportFailToParent(); - break; - } - - // ::= M @ - Ctx.Variables.emplace_back( - std::make_shared(MemberName, true)); - - Ctx.reportSuccessToParent(); - } - break; - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= Ut [] _ - // ::= Ul + E [] _ - // - // Result variables: DmngRsltNamePart (DmngRsltUnmTypeNamePart) - case PSI_UnnamedTypeName: - switch (State.DotPos) { - // ::= @ Ut [] _ - // Discriminable by prefix -> selecting production in first step. - case 0: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Ut")) { - - // ::= @ Ul + E [] _ - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "Ul")) { - State.moveToProduction(1, false); - break; - } - - Ctx.reportFailToParent(); - break; - } - - // ::= Ut @ [] _ - unsigned long long DiscriminatorIdx = 0; - if (matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, DiscriminatorIdx)) { - assert(DiscriminatorIdx + 1 > DiscriminatorIdx && - "Discrimantor index is out of bounds."); - ++DiscriminatorIdx; - } - - // ::= Ut [] @ _ - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - Ctx.reportFailToParent(); - break; - } - - // ::= Ut [] _ @ - Ctx.Variables.emplace_back( - std::make_shared(DiscriminatorIdx)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= Ul @ + E [] _ - case 1: - Ctx.parseChildState(PSI_BareFunctionType); - break; - // ::= Ul + @ E [] _ - case 2: { - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) { - Ctx.reportFailToParent(); - break; - } - - // ::= Ul + E @ [] _ - unsigned long long DiscriminatorIdx = 0; - if (matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, DiscriminatorIdx)) { - assert(DiscriminatorIdx + 1 > DiscriminatorIdx && - "Discrimantor index is out of bounds."); - ++DiscriminatorIdx; - } - - // ::= Ul + E [] @ _ - if (!matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "_")) { - Ctx.reportFailToParent(); - break; - } - - // ::= Ul + E [] _ @ - INP_ENSURE_TMP_SIZE(1); - - auto NdClosureType = - std::make_shared(DiscriminatorIdx); - - for (std::size_t I = 0, E = Ctx.getStateVarsCount(); I < E; ++I) { - const auto &NdArgType = - Ctx.getStateVar(I).unsafeGetAsExact(); - NdClosureType->addSignatureType(NdArgType->getAs()); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdClosureType)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= - // ::= cv - // ::= li - // ::= v - // - // Result variables: DmngRsltNamePart (DmngRsltOpNamePart) - case PSI_OperatorName: - switch (State.DotPos) { - // ::= @ - // Discriminable by prefix -> selecting production in first step. - case 0: { - DmngOperatorName OperatorCode = DON_New; - if (!matchFixedOperatorAndAdvance(Ctx.Result.getMangledName(), - State.Pos, OperatorCode)) { - - // ::= @ cv - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "cv")) { - State.setTArgScope(true); - State.moveToProduction(1, false); - break; - } - - // ::= @ li - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "li")) { - State.moveToProduction(3, false); - break; - } - - // ::= @ v - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "v")) { - State.moveToProduction(4, false); - break; - } - - Ctx.reportFailToParent(); - break; - } - - // ::= @ - Ctx.Variables.emplace_back( - std::make_shared(OperatorCode)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= cv @ - case 1: - Ctx.parseChildState(PSI_Type); - break; - // ::= cv @ - case 2: { - INP_ENSURE_TMP_SIZE(1); - - auto NdType = Ctx.getStateVar(0).unsafeGetAsExact(); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back( - std::make_shared(NdType->getAs())); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= li @ - case 3: { - std::string LiteralSuffix; - if (!matchSourceNameAndAdvance(Ctx.Result.getMangledName(), - State.Pos, LiteralSuffix)) { - Ctx.reportFailToParent(); - break; - } - - // ::= li @ - Ctx.Variables.emplace_back( - std::make_shared(LiteralSuffix)); - - Ctx.reportSuccessToParent(); - } - break; - - // ::= v @ - case 4: { - int Arity = 0; - if (!matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, Arity)) { - Ctx.reportFailToParent(); - break; - } - - // ::= v @ - std::string VendorOpName; - if (!matchSourceNameAndAdvance(Ctx.Result.getMangledName(), - State.Pos, VendorOpName)) { - Ctx.reportFailToParent(); - break; - } - - // ::= v @ - Ctx.Variables.emplace_back( - std::make_shared(VendorOpName, Arity)); - - Ctx.reportSuccessToParent(); - } - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= - // ::= - // - // Result variables: DmngRsltExpr - case PSI_Expression: - switch (State.DotPos) { - // ::= @ - case 0: - Ctx.tryParseChildState(PSI_ExprPrimary, 2); - break; - // ::= @ - case 1: - Ctx.reportSuccessToParent(); - break; - - // ::= @ - case 2: - Ctx.parseChildState(PSI_TemplateParam); - break; - // ::= @ - case 3: - Ctx.reportSuccessToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - // MC*** - // ::= L E - // ::= L [] E - // - // NOTE: Bug in clang 3.6 with taken into consideration. - // - // Result variables: DmngRsltExpr (DmngRsltPrimaryExpr) - case PSI_ExprPrimary: - switch (State.DotPos) { - // ::= @ L E - case 0: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "L")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= L @ E - case 1: - Ctx.tryParseChildState(PSI_MangledName_Bug, 4, false); - break; - // ::= L @ E - case 2: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) { - // ::= L E @ - INP_ENSURE_TMP_SIZE(1); - - const auto &NdExternalName = - Ctx.getStateVar(0).unsafeGetAsExact(); - - auto NdExternNameExpr = std::make_shared( - NdExternalName->getAs()); - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdExternNameExpr)); - - Ctx.reportSuccessToParent(); - break; - } - State.moveToProduction(3); - break; - - // ::= @ L [] E - case 3: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "L")) - State.advance(); - else - Ctx.reportFailToParent(); - break; - // ::= L @ [] E - case 4: - Ctx.parseChildState(PSI_Type); - break; - // ::= L @ [] E - case 5: { - unsigned long long UIntContent = 0; - if (matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, UIntContent)) { - Ctx.Variables.emplace_back(UIntContent); - } - - long long SIntContent = 0; - if (matchIntNumberAndAdvance( - Ctx.Result.getMangledName(), State.Pos, SIntContent)) { - Ctx.Variables.emplace_back(SIntContent); - } - - State.advance(); - } - break; - // ::= L @ [] @ E - case 6: - if (matchPrefixAndAdvance(Ctx.Result.getMangledName(), - State.Pos, "E")) { - // ::= L [] E @ - INP_ENSURE_TMP_SIZE(1); - - auto &&NdLiteralType = - Ctx.getStateVar(0).unsafeGetAsExact() - ->getAs(); - - std::shared_ptr NdLiteralExpr; - if (Ctx.getStateVarsCount() > 1) { - if (Ctx.getStateVar(1).isAExact()) { - auto Content = - Ctx.getStateVar(1).unsafeGetAsExact(); - - if (NdLiteralType->getKind() == DTK_Builtin && - NdLiteralType->getAs() - ->getBuiltinType() == DBT_Bool) { - NdLiteralExpr = std::make_shared( - std::move(NdLiteralType), Content != 0); - } - else { - NdLiteralExpr = std::make_shared( - std::move(NdLiteralType), Content); - } - } - else if (Ctx.getStateVar(1).isAExact()) { - auto Content = - Ctx.getStateVar(1).unsafeGetAsExact(); - NdLiteralExpr = std::make_shared( - std::move(NdLiteralType), Content); - } - else { - // ReSharper disable once CppUnreachableCode - assert(false && "Content type is not supported."); - NdLiteralExpr = std::make_shared( - std::move(NdLiteralType)); - } - } - else { - NdLiteralExpr = std::make_shared( - std::move(NdLiteralType)); - } - - Ctx.resetStateVars(); - Ctx.Variables.emplace_back(std::move(NdLiteralExpr)); - - Ctx.reportSuccessToParent(); - break; - } - Ctx.reportFailToParent(); - break; - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - break; - - - default: - // ReSharper disable once CppUnreachableCode - assert(false && "Unexpected state."); - return Ctx.Result.setFailed(); - } - } - - // Connect template parameters with arguments. - if(!Ctx.referenceTParams()) - return Ctx.Result.setFailed(); - - return Ctx.Result; - - #undef INP_ENSURE_TMP_SIZE -} diff --git a/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemangler.h b/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemangler.h deleted file mode 100644 index bb852f1b07466..0000000000000 --- a/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemangler.h +++ /dev/null @@ -1,139 +0,0 @@ -//===- OclCxxDemangler.h - OCLC++ simple demangler -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// -// -// Copyright (c) 2015 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and/or associated documentation files (the -// "Materials"), to deal in the Materials without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Materials, and to -// permit persons to whom the Materials are furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Materials. -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -// -//===----------------------------------------------------------------------===// - - -#ifndef CLANG_LIB_CODEGEN_OCLCXXREWRITE_OCLCXXDEMANGLER_H -#define CLANG_LIB_CODEGEN_OCLCXXREWRITE_OCLCXXDEMANGLER_H - -#include "OclCxxDemanglerResult.h" - -#include - - -namespace oclcxx { -namespace adaptation { - -/// \brief Returns C++ name of built-in type. -/// -/// Handles all built-in types except vendor-extended types. -const std::string &getFixedBuiltinTypeName(DmngBuiltinType Type); - -/// \brief Returns Itanium-encoded name of built-in type. -/// -/// Handles all built-in types except vendor-extended types. -const std::string &getEncFixedBuiltinTypeName(DmngBuiltinType Type); - -/// \brief Returns C++ name of operator (without "operator" prefix). -/// -/// Handles all operator names except convert, literal and vendor-extended -/// operators. -const std::string &getFixedOperatorName(DmngOperatorName NameCode); - -/// \brief Returns Itanium-encoded name of operator. -/// -/// Handles all operator names except convert, literal and vendor-extended -/// operators. -const std::string &getEncFixedOperatorName(DmngOperatorName NameCode); - -/// \brief Returns fixed arity of operator in context. -/// -/// \return Arity of operator, or 0 if arity is unknown, operator requires -/// special form in or number of operands is variable. -int getInExprOperatorFixedArity(DmngOperatorName NameCode); - - -/// \brief Parser for Itanium-mangled names. -class ItaniumNameParser { -public: - /// Function type which can return address space based on vendor-extended - /// qualifier. - using AddressSpaceExtractFuncT = - DmngAddressSpaceQuals (const DmngRsltVendorQual &); - - - /// \brief Parses mangled name (by copy). - DmngRslt parse(const std::string &MangledName) { - return parse(std::string(MangledName)); - } - - /// \brief Parses mangled name (by move). - DmngRslt parse(std::string &&MangledName); - - - /// \brief Creates new instance of parser for Itanium-mangled names. - /// - /// \param ASExtractFunc Address-space extract function. Function return - /// address-space, or DASQ_None if vendor-extended - /// qualifier does not contain address space. - explicit ItaniumNameParser(AddressSpaceExtractFuncT &ASExtractFunc) - : ASExtractFunc(ASExtractFunc) {} - -private: - /// Address-space extract function. - AddressSpaceExtractFuncT &ASExtractFunc; -}; - - -/// \brief Address space extract function for OpenCL C++. -inline DmngAddressSpaceQuals OclASExtract(const DmngRsltVendorQual &Qual) { - if (Qual.getName().size() < 3) - return DASQ_None; - - switch (Qual.getName()[0]) { - case 'A': - if (Qual.getName()[1] == 'S' && Qual.getName().size() == 3) { - switch (Qual.getName()[2]) { - case '0': return DASQ_Private; - case '3': return DASQ_Local; - case '1': return DASQ_Global; - case '2': return DASQ_Constant; - case '4': return DASQ_Generic; - default: return DASQ_None; - } - } - break; - case 'C': - if (Qual.getName() == "CLlocal") - return DASQ_Local; - if (Qual.getName() == "CLglobal") - return DASQ_Global; - if (Qual.getName() == "CLconstant") - return DASQ_Constant; - break; - } - return DASQ_None; -} - -} // adaptation -} // oclcxx - -#endif // CLANG_LIB_CODEGEN_OCLCXXREWRITE_OCLCXXDEMANGLER_H diff --git a/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemanglerResult.cpp b/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemanglerResult.cpp deleted file mode 100644 index 41f39eb04bc8f..0000000000000 --- a/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemanglerResult.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===- OclCxxDemanglerResult.cpp - OCLC++ demangler result -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// -// -// Copyright (c) 2015 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and/or associated documentation files (the -// "Materials"), to deal in the Materials without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Materials, and to -// permit persons to whom the Materials are furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Materials. -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -// -//===----------------------------------------------------------------------===// - - -#include "OclCxxDemanglerResult.h" - -using namespace oclcxx::adaptation; - - -// ----------------------------------------------------------------------------- -// HELPERS FOR RESULT OBJECTS -// ----------------------------------------------------------------------------- - -const std::string oclcxx::adaptation::DmngRsltEmptyString; - -const DmngRsltTArg::TArgsPackColT DmngRsltTArg::EmpyPack; -const DmngRsltTArg DmngRsltTArg::EmptyArg; diff --git a/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemanglerResult.h b/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemanglerResult.h deleted file mode 100644 index d2e859ecee56d..0000000000000 --- a/clang/lib/CodeGen/OclCxxRewrite/OclCxxDemanglerResult.h +++ /dev/null @@ -1,3318 +0,0 @@ -//===- OclCxxDemanglerResult.h - OCLC++ demangler result object -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// -// -// Copyright (c) 2015 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and/or associated documentation files (the -// "Materials"), to deal in the Materials without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Materials, and to -// permit persons to whom the Materials are furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Materials. -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -// -//===----------------------------------------------------------------------===// - - -#ifndef CLANG_LIB_CODEGEN_OCLCXXREWRITE_OCLCXXDEMANGLERRESULT_H -#define CLANG_LIB_CODEGEN_OCLCXXREWRITE_OCLCXXDEMANGLERRESULT_H - -#include -#include -#include -#include -#include -#include - -namespace oclcxx { -namespace adaptation { - -// ----------------------------------------------------------------------------- -// HELPERS FOR RESULT OBJECTS -// ----------------------------------------------------------------------------- - -/// Helper entity for returning empty string by const reference. -extern const std::string DmngRsltEmptyString; - -/// \brief Iterator range helper class (for const_iterator). -/// -/// Helper class which allows to iterate over range of iterators using -/// for-each C++ construct. -template -class DmngRsltConstItRange { -public: - using iterator = ConstItT; - using const_iterator = ConstItT; - - const_iterator begin() const { return Begin; } - const_iterator end() const { return End; } - - const_iterator cbegin() const { return Begin; } - const_iterator cend() const { return End; } - - - DmngRsltConstItRange(const const_iterator& Begin, const const_iterator& End) - : Begin(Begin), End(End) {} - - -private: - const_iterator Begin; - const_iterator End; -}; - -/// \brief SFINAE enabler for sub-node (shared) pointers passed as paramaters. -/// -/// This version is for parameters using std::forward pattern. -template -using SubnodeEnablerT = typename std::enable_if< - std::is_constructible, ValueT &&>::value, - void>::type; - -/// \brief Helper class that creates type-dependant type which always returns -/// false. -/// -/// Used in static_assert to force late evalution of condition. -template - struct AlwaysFalse : std::integral_constant {}; - - -// ----------------------------------------------------------------------------- -// ENUMERATIONS FOR RESULT OBJECTS -// ----------------------------------------------------------------------------- - -/// \brief Kind of node in demangled name (node category). -enum DmngNodeKind { - DNDK_Name, - DNDK_NamePart, - DNDK_Type, - DNDK_Expr, - DNDK_NameParts, -}; - -/// \brief Kind of expression in demangled name. -enum DmngExprKind { - DXK_TemplateParam, ///< Template parameter expression. - DXK_Decltype, ///< decltype() expression. - DXK_Primary, ///< Primary expression (literals). -}; - -/// \brief Code that identifies additional operator name in expression. -enum DmngExprOpName { - DXON_SuffixPlusPlus, ///< # (E++) - DXON_SuffixMinusMinus, ///< # (E--) - DXON_PrefixPlusPlus, ///< # (++E) - DXON_PrefixMinusMinus, ///< # (--E) -}; - - -/// \brief Kind of demangled types in result. -enum DmngTypeKind { - DTK_Builtin, ///< Built-in types. - // NOTE: It is not substitution when it is component of pointer 2 member. - DTK_Function, ///< Function types. - /// Dependent and non-dependent type names or dependent typename-specifiers - /// (optionally elaborated with specific keyword). - DTK_TypeName, - DTK_Array, ///< Array types (including variable size). - DTK_Vector, ///< Vector types. - DTK_PointerToMember, ///< Pointer to member type. - DTK_TemplateParam, ///< Template parameters. - DTK_Decltype, ///< decltype() expressions. - - DTK_Pointer, ///< Pointer to type (E *). - DTK_LValueRef, ///< l-value reference to type (E &). - DTK_RValueRef, ///< r-value reference to type (E &&). - DTK_C2000Complex, ///< C2000 complex (complex E). - DTK_C2000Imaginary, ///< C2000 imaginary (imaginary E). - DTK_PackExpansion, ///< Pack expansion of type. - - /// Type qualified with set of qualifiers (cvr-quals, address space, vendor). - DTK_QualGroup -}; - -/// \brief Type name kind (elaboration). -enum DmngTypeNameKind { - DTNK_None, ///< No elaboration. - DTNK_ElaboratedClass, ///< Elaborated with "class" or "struct" keyword. - DTNK_ElaboratedUnion, ///< Elaborated with "union" keyword. - DTNK_ElaboratedEnum ///< Elaborated with "enum" keyword. -}; - -/// Enumeration that describes built-in types in mangling. -enum DmngBuiltinType { -#define OCLCXX_MENC_BITYPE_FIXED(name, encName, cxxName) DBT_##name, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_BITYPE_FIXED - -#define OCLCXX_MENC_BITYPE(name) DBT_##name, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_BITYPE - -#define OCLCXX_MENC_BITYPE_ALIAS(aliasName, origName) \ - DBT_##aliasName = DBT_##origName, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_BITYPE_ALIAS -}; - - -/// \brief Kind of demangled name. -enum DmngNameKind { - /// Name referes to ordinary data (global variable, etc.) or function - /// (function, member function, etc.). - DNK_Ordinary, - /// Special names (virtual table entries, VTT, type_info, etc.). - /// They have sub-kind: DmngSpecialNameKind - DNK_Special -}; - -/// \brief Sub-kind of special demangled names. -enum DmngSpecialNameKind { - /// Virtual type for specific. type (data structure with pointers - /// to functions). - DSNK_VirtualTable, - /// Virtual table that describes adjustments for virtual tables in cases - /// of muliple inheritence (data structure which points to another virtual - /// tables generated for object-base object relations). - DSNK_VirtualTableTable, - /// Data structure with type information for specific type. - DSNK_TypeInfoStruct, - /// Global variable (data) with name string that identifies specific type. - DSNK_TypeInfoNameString, - /// Special function which adjust "this" and delagtes call to the - /// real function. - DSNK_VirtualThunk, - /// Guard variable for one-time initialization of (inline) static object. - DSNK_GuardVariable, - /// Temporary variable which is bound (directly or indirectly) to reference - /// that have static storage duration and, because of that, life extended to - /// static storage duration as well. - DSNK_LifeExtTemporary -}; - -/// \brief cvr-qualifiers (const, volatile, restrict or any mix of thereof). -/// -/// This is flags enum and has bitwise operation provided. -enum DmngCvrQuals { - DCVQ_None = 0, ///< (no qualifiers) - DCVQ_Const = 1, ///< const - DCVQ_Volatile = 2, ///< volatile - DCVQ_Restrict = 4 ///< restrict (C99 extension) -}; - -inline DmngCvrQuals operator |(DmngCvrQuals LHS, DmngCvrQuals RHS) { - using UTypeT = std::underlying_type::type; - - return static_cast( - static_cast(LHS) | static_cast(RHS)); -} - -inline DmngCvrQuals operator &(DmngCvrQuals LHS, DmngCvrQuals RHS) { - using UTypeT = std::underlying_type::type; - - return static_cast( - static_cast(LHS) & static_cast(RHS)); -} - -inline DmngCvrQuals operator ^(DmngCvrQuals LHS, DmngCvrQuals RHS) { - using UTypeT = std::underlying_type::type; - - return static_cast( - static_cast(LHS) ^ static_cast(RHS)); -} - -inline DmngCvrQuals operator ~(DmngCvrQuals RHS) { - using UTypeT = std::underlying_type::type; - const DmngCvrQuals FullSet = DCVQ_Const | DCVQ_Volatile | DCVQ_Restrict; - - return static_cast( - static_cast(FullSet) ^ static_cast(RHS)); -} - -/// \brief Reference qualifiers (for functions and references). -enum DmngRefQuals { - DRQ_None, ///< (none). - DRQ_LValueRef, ///< & - DRQ_RValueRef ///< && -}; - -/// \brief Address space qualifiers (clang mangling extension). -/// -/// Result from parsing vendor-extended mangling in form: "U3AS[0-9]". -enum DmngAddressSpaceQuals { - DASQ_None, ///< (none). - DASQ_Private, ///< __private - DASQ_Local, ///< __local - DASQ_Global, ///< __global - DASQ_Constant, ///< __constant - DASQ_Generic ///< __generic -}; - -/// \brief Kind of name part (one or multiple name parts form name -/// or nested name). -enum DmngNamePartKind { - DNPK_Operator, ///< Operators (operator +, etc.). - DNPK_Constructor, ///< Constructors (S::S(), etc.). - DNPK_Destructor, ///< Destructors (S::~S(), etc.). - DNPK_Source, ///< Source names (namespace and class names, etc.). - DNPK_UnnamedType, ///< Unnamed types (closure/lambda classes, etc.). - DNPK_TemplateParam, ///< Template parameters (inherit from template arg). - DNPK_Decltype, ///< decltype(...) elements. - DNPK_DataMember ///< Data member initializers. -}; - -/// \brief Code that identifies operator name. -enum DmngOperatorName { -#define OCLCXX_MENC_OPR_FIXED(name, encName, arity, cxxName) DON_##name, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_OPR_FIXED - -#define OCLCXX_MENC_OPR(name, arity) DON_##name, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_OPR - -#define OCLCXX_MENC_OPR_ALIAS(aliasName, origName) \ - DON_##aliasName = DON_##origName, -#include "OclCxxMangleEncodings.inc" -#undef OCLCXX_MENC_OPR_ALIAS -}; - -/// \brief Type of constructor or destructor. -enum DmngCtorDtorType { - DCDT_BaseObj, ///< Base object constructor or destructor. - DCDT_CompleteObj, ///< Complete object constructor or destructor. - DCDT_DynMemObj ///< Complete object allocating ctor or deleting dtor. -}; - - -// ----------------------------------------------------------------------------- -// FORWARD DECLARATIONS FOR RESULT OBJECTS -// ----------------------------------------------------------------------------- - -class DmngRsltNode; - -class DmngRsltExpr; -class DmngRsltDecltypeExpr; -class DmngRsltTParamExpr; -class DmngRsltPrimaryExpr; - -class DmngRsltType; -class DmngRsltBuiltinType; -class DmngRsltFuncType; -class DmngRsltTypeNameType; -class DmngRsltArrayVecType; -class DmngRsltPtr2MmbrType; -class DmngRsltTParamType; -class DmngRsltDecltypeType; -class DmngRsltQualType; -class DmngRsltQualGrpType; - -class DmngRsltNamePart; -class DmngRsltOpNamePart; -class DmngRsltCtorDtorNamePart; -class DmngRsltSrcNamePart; -class DmngRsltUnmTypeNamePart; -class DmngRsltTParamNamePart; -class DmngRsltDecltypeNamePart; - -class DmngRsltNameParts; - -class DmngRsltName; -class DmngRsltOrdinaryName; -class DmngRsltSpecialName; - - -// ----------------------------------------------------------------------------- -// TYPE SELECTORS FOR RESULT OBJECTS -// ----------------------------------------------------------------------------- - -/// \brief Kind selector helper for derivates of DmngRsltNode. -/// -/// It allows to select derived type from DmngRsltNode based on node kind. -/// -/// \tparam Kind Kind of derived type which will be selected. -template -struct DmngRsltNodeKSel { - /// Type selected by kind selector (fall-back: base type). - using Type = DmngRsltNode; -}; - -template <> -struct DmngRsltNodeKSel { - using Type = DmngRsltName; -}; - -template <> -struct DmngRsltNodeKSel { - using Type = DmngRsltNamePart; -}; - -template <> -struct DmngRsltNodeKSel { - using Type = DmngRsltNameParts; -}; - -template <> -struct DmngRsltNodeKSel { - using Type = DmngRsltType; -}; - -template <> -struct DmngRsltNodeKSel { - using Type = DmngRsltExpr; -}; - -template -using DmngRsltNodeKSelT = typename DmngRsltNodeKSel::Type; - - -/// \brief Kind selector helper for derivates of DmngRsltName. -/// -/// It allows to select derived type from DmngRsltName based on name kind. -/// -/// \tparam Kind Kind of derived type which will be selected. -template -struct DmngRsltNameKSel { - /// Type selected by kind selector (fall-back: base type). - using Type = DmngRsltName; -}; - -template <> -struct DmngRsltNameKSel { - using Type = DmngRsltOrdinaryName; -}; - -template <> -struct DmngRsltNameKSel { - using Type = DmngRsltSpecialName; -}; - -template -using DmngRsltNameKSelT = typename DmngRsltNameKSel::Type; - - -/// \brief Kind selector helper for derivates of DmngRsltNamePart. -/// -/// It allows to select derived type from DmngRsltNamePart based on name kind. -/// -/// \tparam Kind Kind of derived type which will be selected. -template -struct DmngRsltNamePartKSel { - /// Type selected by kind selector (fall-back: base type). - using Type = DmngRsltNamePart; -}; - -template <> -struct DmngRsltNamePartKSel { - using Type = DmngRsltOpNamePart; -}; - -template <> -struct DmngRsltNamePartKSel { - using Type = DmngRsltCtorDtorNamePart; -}; - -template <> -struct DmngRsltNamePartKSel { - using Type = DmngRsltCtorDtorNamePart; -}; - -template <> -struct DmngRsltNamePartKSel { - using Type = DmngRsltSrcNamePart; -}; - -template <> -struct DmngRsltNamePartKSel { - using Type = DmngRsltUnmTypeNamePart; -}; - -template <> -struct DmngRsltNamePartKSel { - using Type = DmngRsltTParamNamePart; -}; - -template <> -struct DmngRsltNamePartKSel { - using Type = DmngRsltDecltypeNamePart; -}; - -template <> -struct DmngRsltNamePartKSel { - using Type = DmngRsltSrcNamePart; -}; - -template -using DmngRsltNamePartKSelT = typename DmngRsltNamePartKSel::Type; - - -/// \brief Kind selector helper for derivates of DmngRsltType. -/// -/// It allows to select derived type from DmngRsltType based on name kind. -/// -/// \tparam Kind Kind of derived type which will be selected. -template -struct DmngRsltTypeKSel { - /// Type selected by kind selector (fall-back: base type). - using Type = DmngRsltType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltBuiltinType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltFuncType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltTypeNameType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltArrayVecType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltArrayVecType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltPtr2MmbrType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltTParamType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltDecltypeType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltQualType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltQualType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltQualType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltQualType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltQualType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltQualType; -}; - -template <> -struct DmngRsltTypeKSel { - using Type = DmngRsltQualGrpType; -}; - -template -using DmngRsltTypeKSelT = typename DmngRsltTypeKSel::Type; - - -/// \brief Kind selector helper for derivates of DmngRsltExpr. -/// -/// It allows to select derived type from DmngRsltExpr based on name kind. -/// -/// \tparam Kind Kind of derived type which will be selected. -template -struct DmngRsltExprKSel { - /// Type selected by kind selector (fall-back: base type). - using Type = DmngRsltExpr; -}; - -template <> -struct DmngRsltExprKSel { - using Type = DmngRsltTParamExpr; -}; - -template <> -struct DmngRsltExprKSel { - using Type = DmngRsltDecltypeExpr; -}; - -template <> -struct DmngRsltExprKSel { - using Type = DmngRsltPrimaryExpr; -}; - -template -using DmngRsltExprKSelT = typename DmngRsltExprKSel::Type; - - -// ----------------------------------------------------------------------------- -// BASE AND VALUE CLASSES FOR RESULT OBJECTS (COLLECTION WRAPPERS) -// ----------------------------------------------------------------------------- - -/// \brief Information about name parts in result (name parts collection). -/// -/// This class is abstract. -class DmngRsltNamePartsBase { -public: - /// Ordered collection type containing name parts. - using NamePartsColT = std::vector>; - - /// \brief Gets last part of name. - std::shared_ptr getLastPart() const { - return Parts.empty() ? nullptr : Parts.back(); - } - - /// \brief Gets name parts. - const NamePartsColT &getParts() const { - return Parts; - } - - - // Manipulators. - - /// \brief Gets last part of name. - std::shared_ptr getModifiableLastPart() { - // Static collection with pointers have really no good way to create - // read-only interface (collections are not covariant). - return Parts.empty() - ? nullptr - : std::const_pointer_cast(Parts.back()); - } - - /// \brief Adds name part (by copy). - /// - /// Function asserts and does nothing if name part is null. - void addPart(const std::shared_ptr &Part) { - assert(Part != nullptr && "Name part must exist in order to be added."); - if (Part != nullptr) - Parts.push_back(Part); - } - - /// \brief Adds name part (by move). - /// - /// Function asserts and does nothing if name part is null. - void addPart(std::shared_ptr &&Part) { - assert(Part != nullptr && "Name part must exist in order to be added."); - if (Part != nullptr) - Parts.push_back(std::move(Part)); - } - - /// \brief Adds name part (bind pointer). - /// - /// Function asserts and does nothing if name part is null. - void addPart(const DmngRsltNamePart *Part) { - assert(Part != nullptr && "Name part must exist in order to be added."); - if (Part != nullptr) - Parts.push_back(std::shared_ptr(Part)); - } - - /// \brief Sets name part (by copy). - /// - /// After calling this method name parts have only one part set to value - /// passsed as parameter. - /// - /// Function asserts and does nothing if name part is null. - void setPart(const std::shared_ptr &Part) { - assert(Part != nullptr && "Name part must exist in order to be added."); - if (Part != nullptr) { - Parts.clear(); - Parts.push_back(Part); - } - } - - /// \brief Sets name part (by move). - /// - /// After calling this method name parts have only one part set to value - /// passsed as parameter. - /// - /// Function asserts and does nothing if name part is null. - void setPart(std::shared_ptr &&Part) { - assert(Part != nullptr && "Name part must exist in order to be added."); - if (Part != nullptr) { - Parts.clear(); - Parts.push_back(std::move(Part)); - } - } - - /// \brief Sets name part (bind pointer). - /// - /// After calling this method name parts have only one part set to value - /// passsed as parameter. - /// - /// Function asserts and does nothing if name part is null. - void setPart(const DmngRsltNamePart *Part) { - assert(Part != nullptr && "Name part must exist in order to be added."); - if (Part != nullptr) { - Parts.clear(); - Parts.push_back(std::shared_ptr(Part)); - } - } - -protected: - /// \brief Creates instance with one name part (by copy). - explicit DmngRsltNamePartsBase( - const std::shared_ptr &Part) { - addPart(Part); - } - - /// \brief Creates instance with one name part (by move). - explicit DmngRsltNamePartsBase( - std::shared_ptr &&Part) { - addPart(std::move(Part)); - } - - /// \brief Creates instance with one name part (bind pointer). - explicit DmngRsltNamePartsBase(const DmngRsltNamePart *Part) { - addPart(Part); - } - - /// \brief Creates empty instance (for example string literal names). - DmngRsltNamePartsBase() = default; - - - /// \brief Creates instance that is a copy of other instance. - /// - /// \param Other Other instance which will be copied. - /// \param DeepCopy Indicates that name parts should be cloned as well. - DmngRsltNamePartsBase(const DmngRsltNamePartsBase &Other, bool DeepCopy); - -public: - /// \brief Ensure proper destruction in some inheritance scenarios. - virtual ~DmngRsltNamePartsBase() = default; - - -private: - /// Name parts. - NamePartsColT Parts; -}; - -/// \brief Information about types participating in function/closure signature -/// in result (bare function type/signature type collection). -/// -/// This class is abstract. -class DmngRsltSignatureTypesBase { -public: - /// Ordered collection type containing information about types. - using TypesColT = std::vector>; - /// Iterator range for parameter types. - using ParamTypesItRangeT = DmngRsltConstItRange; - - - /// \brief Gets ordered collection of types which describes function/closure - /// parameters and possibly return type. - /// - /// Collection is empty if current name/type is not function name/type. - /// For function names/types, it contains possibly return type and parameter - /// types information (return type at beginning, if exists). - /// This collection will is non-empty for function names. If function has - /// no parameters, it is treated as containg one parameter of void type. - const TypesColT &getSignatureTypes() const { - return SignatureTypes; - } - - /// \brief Gets value indicating that current (function or closure) name/type - /// has return type encoded in signature. - /// - /// Default implementation always return false. - virtual bool hasReturnType() const { - return false; - } - - /// \brief Gets information about return type of current (function or closure) - /// name/type. - /// - /// \return Information about return type, or nullptr if name is not function - /// name/type or return type was not encoded in function signature. - std::shared_ptr getReturnType() const { - if (hasReturnType()) - return SignatureTypes.front(); - return nullptr; - } - - /// \brief Gets start iterator for parameter types in signature (ordered). - TypesColT::const_iterator getParamTypeBegin() const { - auto Begin = SignatureTypes.begin(); - return hasReturnType() ? ++Begin : Begin; - } - - /// \brief Gets end iterator for parameter types in signature. - TypesColT::const_iterator getParamTypeEnd() const { - return SignatureTypes.end(); - } - - /// \brief Gets iterator range for parameter types (for for-each). - ParamTypesItRangeT getParamTypes() const { - return ParamTypesItRangeT(getParamTypeBegin(), getParamTypeEnd()); - } - - // Manipulators. - - /// \brief Adds signature type (by copy). - /// - /// Function asserts and does nothing if type is null. - void addSignatureType(const std::shared_ptr &Type) { - assert(Type != nullptr && "Type must exist in order to be added."); - if (Type != nullptr) - SignatureTypes.push_back(Type); - } - - /// \brief Adds signature type (by move). - /// - /// Function asserts and does nothing if type is null. - void addSignatureType(std::shared_ptr &&Type) { - assert(Type != nullptr && "Type must exist in order to be added."); - if (Type != nullptr) - SignatureTypes.push_back(std::move(Type)); - } - - /// \brief Adds signature type (bind pointer). - /// - /// Function asserts and does nothing if type is null. - void addSignatureType(const DmngRsltType *Type) { - assert(Type != nullptr && "Type must exist in order to be added."); - if (Type != nullptr) - SignatureTypes.push_back(std::shared_ptr(Type)); - } - - /// \brief Resets signature. - /// - /// Removes all signature types. - void resetSignature() { - SignatureTypes.clear(); - } - - -protected: - /// \brief Creates new instance of base class. - DmngRsltSignatureTypesBase() = default; -public: - /// \brief Ensure proper destruction in some inheritance scenarios. - virtual ~DmngRsltSignatureTypesBase() = default; - - -private: - /// Function signature (consist at least one element, i.e. void). - TypesColT SignatureTypes; -}; - -/// \brief Template argument information. -class DmngRsltTArg { -public: - /// Type of collection which contains information about template argument - /// pack. - using TArgsPackColT = std::vector; - - - /// \brief Indicates that template argument is an expression. - bool isExpression() const; - - /// \brief Indicates that template argument is a type. - bool isType() const; - - /// \brief Indicates that template argument is argument pack. - bool isPack() const; - - - /// \brief Gets value of template argument as expression. - /// - /// \return Shared pointer with value of argument, or empty pointer if - /// template argument is not expression. - std::shared_ptr getExpression() const; - - /// \brief Gets value of template argument as type. - /// - /// \return Shared pointer with value of argument, or empty pointer if - /// template argument is not type. - std::shared_ptr getType() const; - - /// \brief Gets value of template argument. - /// - /// \return Shared pointer with value of argument, or empty pointer if - /// template argument is argument pack. - std::shared_ptr getValue() const; - - /// \brief Gets template argument pack. - /// - /// \return Collection with argument pack, or empty pack if - /// template argument is not argument pack. - const TArgsPackColT &getPack() const; - - - /// \brief Gets empty template argument. - static const DmngRsltTArg &getEmpty() { - return EmptyArg; - } - - // Manipulators. - - /// \brief Adds argument to current argument pack (by copy). - void addPackArg(const DmngRsltTArg &Arg); - - /// \brief Adds argument to current argument pack (by move). - void addPackArg(DmngRsltTArg &&Arg); - - - /// \brief Creates new instance of template argument (expression). - explicit DmngRsltTArg(const std::shared_ptr &Value); - /// \brief Creates new instance of template argument (expression). - explicit DmngRsltTArg(std::shared_ptr &&Value); - - /// \brief Creates new instance of template argument (type). - explicit DmngRsltTArg(const std::shared_ptr &Value); - /// \brief Creates new instance of template argument (type). - explicit DmngRsltTArg(std::shared_ptr &&Value); - - /// \brief Creates new instance of template argument (pack). - DmngRsltTArg() = default; - - -private: - /// Value of current template argument. - std::shared_ptr Value; - /// Template argument pack. - TArgsPackColT Pack; - - /// Represents empty template parameter pack. - static const TArgsPackColT EmpyPack; - /// Represents empty template argument. - static const DmngRsltTArg EmptyArg; -}; - -/// \brief Information about template arguments in result (template args -/// collection). -/// -/// This class is abstract. -class DmngRsltTArgsBase { -public: - /// Type of collection which contains information about template arguments. - using TArgsColT = std::vector; - - - /// \brief Gets value indicating that current entity is template instance - /// or specialization. - bool isTemplate() const { - return !TemplateArgs.empty(); - } - - /// \brief Gets collection with information about template arguments - /// of current entity. - const TArgsColT &getTemplateArgs() const { - return TemplateArgs; - } - - // Manipulators. - - /// \brief Adds information about template argument (by copy). - /// - /// Function asserts and does nothing if template argument is null. - void addTemplateArg(const DmngRsltTArg &Arg) { - TemplateArgs.push_back(Arg); - } - - /// \brief Adds information about template argument (by move). - /// - /// Function asserts and does nothing if template argument is null. - void addTemplateArg(DmngRsltTArg &&Arg) { - TemplateArgs.push_back(std::move(Arg)); - } - - -protected: - /// \brief Creates new instance of base class. - DmngRsltTArgsBase() = default; -public: - /// \brief Ensure proper destruction in some inheritance scenarios. - virtual ~DmngRsltTArgsBase() = default; - - -private: - /// Collection of template arguments. If it is empty, the current entity - /// is not a template. - TArgsColT TemplateArgs; -}; - -/// \brief Vendor-extended qualifier information. -class DmngRsltVendorQual : public DmngRsltTArgsBase { -public: - /// \brief Gets vendor-extended qualfier name. - const std::string &getName() const { - return Name; - } - - // Manipulators. - - /// \brief Creates new instance of qualifier with specific name. - DmngRsltVendorQual(const std::string &Name) - : Name(Name) { - assert(!this->Name.empty() && "Qualifier name must exist."); - } - - /// \brief Creates new instance of qualifier with specific name. - DmngRsltVendorQual(std::string &&Name) - : Name(std::move(Name)) { - assert(!this->Name.empty() && "Qualifier name must exist."); - } - - /// \brief Creates empty qualifier (no name). - DmngRsltVendorQual() = default; - -private: - /// Vendor-extended qualifier name. - std::string Name; -}; - -/// \brief Information about vendor-extended qualifiers and specifiers in result -/// (qualifiers collection). -/// -/// This class is abstract. -class DmngRsltVendorQualsBase { -public: - /// Type of collection which conatins information about vendor qualifiers. - using VQualsT = std::vector; - - - /// \brief Gets value indicating that current entity has got vendor-extended - /// qualifiers. - bool hasVendorQuals() const { - return !Quals.empty() || AsQuals != DASQ_None; - } - - /// \brief Gets collection with information about vendor-extended qualifiers - /// of current entity. - const VQualsT& getVendorQuals() const { - return Quals; - } - - /// \brief Gets address space qualifiers. - DmngAddressSpaceQuals getAsQuals() const { - return AsQuals; - } - - // Manipulators. - - /// \brief Adds information about vendor-extended qualifier (by copy). - /// - /// Function asserts and does nothing if qualifier is empty. - void addVendorQual(const std::string &Qual) { - assert(!Qual.empty() && "Qualifier must exist in order to be added."); - if (!Qual.empty()) - Quals.push_back(Qual); - } - - /// \brief Adds information about vendor-extended qualifier (by move). - /// - /// Function asserts and does nothing if qualifier is empty. - void addVendorQual(std::string &&Qual) { - assert(!Qual.empty() && "Qualifier must exist in order to be added."); - if (!Qual.empty()) - Quals.push_back(std::move(Qual)); - } - - /// \brief Adds information about vendor-extended qualifier (by copy). - void addVendorQual(const DmngRsltVendorQual &Qual) { - if (!Qual.getName().empty()) - Quals.push_back(Qual); - } - - /// \brief Adds information about vendor-extended qualifier (by move). - void addVendorQual(DmngRsltVendorQual &&Qual) { - if (!Qual.getName().empty()) - Quals.push_back(std::move(Qual)); - } - - /// \brief Sets address space qualifiers (__local, __global, etc.). - void setAsQuals(DmngAddressSpaceQuals Quals) { - AsQuals = Quals; - } - - /// \brief Resets vendor qualifiers. - void resetVendorQuals() { - Quals.clear(); - AsQuals = DASQ_None; - } - -protected: - /// \brief Creates new instance of base class. - DmngRsltVendorQualsBase() : AsQuals(DASQ_None) {} -public: - /// \brief Ensure proper destruction in some inheritance scenarios. - virtual ~DmngRsltVendorQualsBase() = default; - - -private: - /// Collection of vendor-extended qualifiers that do not have special - /// parsing (i.e. address space has special treatment). - VQualsT Quals; - /// Address space qualifiers. - DmngAddressSpaceQuals AsQuals; -}; - -/// \brief Adjustment offset (of "this"/result pointer) in demangled result. -/// -/// The class is immutable. Use constructor to set to proper value. -// Nodes: -class DmngRsltAdjustOffset { -public: - /// \brief Indicates that adjustment is zero. - /// - /// Returnts value indicating that current adjustment does not adjust - /// anything. It is non-virtual with no base offset. - bool isZero() const { - return !IsVirtual && BaseOffset == 0; - } - - /// \brief Indicates that adjustment is done via virtual base. - /// - /// Virtual adjustment uses two offset to adjust pointer to target base. - /// First, non-virtual offset is used to find nearest virtual base of full - /// object (that is non-virtual base from perspecive of current object). - /// Second, is vcall offset in virtual base table that is used for final - /// adjustment of pointer to target base. - /// - /// If it is true, both getBaseOffset() and getVCallOffset() are valid; - /// otherwise, only getBaseOffset() is valid - getVCallOffset() returns 0. - bool isVirtual() const { - return IsVirtual; - } - - /// \brief Non-virtual offset used to adjust pointer to base. - /// - /// If isVirtual() is true, the offset is used to locate nearest virtual - /// base of full object that is non-virtual from point of current object. - /// If isVirtual() is false, the offset is used directly to adjust to - /// target base. - long long getBaseOffset() const { - return BaseOffset; - } - - /// \brief Virtual (vcall) offset in virtual base table. - /// - /// vcall offset in virtual base that is used for final adjustment of pointer - /// to target base. - long long getVCallOffset() const { - return IsVirtual ? VCallOffset : 0; - } - - - /// \brief Creates default instance (with no adjustment). - DmngRsltAdjustOffset() : BaseOffset(0), VCallOffset(0), IsVirtual(false) {} - - /// \brief Creates instance with non-virtual adjustment. - /// - /// \param BaseOffset Offset to target base. - explicit DmngRsltAdjustOffset(long long BaseOffset) - : BaseOffset(BaseOffset), VCallOffset(0), IsVirtual(false) {} - - /// \brief Creates instance with virtual (base) adjustment. - /// - /// \param VBaseOffset Offset to nearest virtual base. - /// \param VCallOffset vcall offset in virtual base table. - DmngRsltAdjustOffset(long long VBaseOffset, long long VCallOffset) - : BaseOffset(VBaseOffset), VCallOffset(VCallOffset), IsVirtual(true) {} - - -protected: - /// Non-virtual offset for adjustment (either direct adjustment to target - /// base or adjustment to nearest virtual base of full object that is - /// non-virtual for current object). - long long BaseOffset; - /// Virtual offset (vcall offset in virtual base for final adjustment). - long long VCallOffset; - /// Indicates that adjustment is done via virtual base. - bool IsVirtual; -}; - - -// ----------------------------------------------------------------------------- -// NODE CLASSES FOR RESULT OBJECTS -// ----------------------------------------------------------------------------- - -/// \brief Generic information node in result. -/// -/// The class is intended for inheritance. -class DmngRsltNode : public std::enable_shared_from_this { -public: - /// \brief Gets kind of current node. - DmngNodeKind getNodeKind() const { - return NodeKind; - } - - /// \brief Gets current node information. - /// - /// \return Name information (as shared pointer). - std::shared_ptr getNode() const { - return shared_from_this(); - } - - /// \brief Gets node specific information. - /// - /// \tparam Kind Kind of node for which information will be retrieved. - /// \return Specific node information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() const { - using DerivedT = DmngRsltNodeKSelT; - - if (NodeKind == this->NodeKind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - virtual std::shared_ptr clone() const = 0; - - // Manipulators. - - /// \brief Gets current node information. - /// - /// \return Name information (as shared pointer). - std::shared_ptr getNode() { - return shared_from_this(); - } - - /// \brief Gets node specific information. - /// - /// \tparam Kind Kind of node for which information will be retrieved. - /// \return Specific node information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() { - using DerivedT = DmngRsltNodeKSelT; - - if (NodeKind == this->NodeKind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - - -protected: - /// \brief Creates (base) instance of information node with specific kind. - explicit DmngRsltNode(DmngNodeKind NodeKind) - : NodeKind(NodeKind) {} - -public: - /// \brief Ensure proper destruction. - virtual ~DmngRsltNode() = default; - - -private: - /// Kind of node. - DmngNodeKind NodeKind; -}; - - -/// \brief Information about expression. -class DmngRsltExpr : public DmngRsltNode { -public: - /// \brief Get kind of expression information. - DmngExprKind getKind() const { - return ExprKind; - } - - - /// \brief Gets expression specific information. - /// - /// \tparam ExprKind Kind of expression for which information - /// will be retrieved. - /// \return Specific expression information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() const { - using DerivedT = DmngRsltExprKSelT; - - if (ExprKind == this->ExprKind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - - // Manipulators. - - /// \brief Gets expression specific information. - /// - /// \tparam ExprKind Kind of expression for which information - /// will be retrieved. - /// \return Specific expression information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() { - using DerivedT = DmngRsltExprKSelT; - - if (ExprKind == this->ExprKind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - - -protected: - /// \brief Creates new instance of base for information about expressions. - DmngRsltExpr(DmngExprKind Kind) - : DmngRsltNode(DNDK_Expr), ExprKind(Kind) {} - - -private: - /// Kind of demangled expression represented by current node. - DmngExprKind ExprKind; -}; - -/// \brief Information about decltype() expression. -class DmngRsltDecltypeExpr : public DmngRsltExpr { -public: - /// \brief Gets expression inside decltype(). - std::shared_ptr getExpression() const { - return Expression; - } - - /// \brief Indicates that decltype() is based on simple expression - /// (id expression or member access). - bool isSimple() const { - return IsSimple; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates instance of information about decltype() expression - /// (by copy). - explicit DmngRsltDecltypeExpr( - const std::shared_ptr &Expression, - bool IsSimple = false) - : DmngRsltExpr(DXK_Decltype), Expression(Expression), IsSimple(IsSimple) { - assert(this->Expression != nullptr && - "Expression in decltype() must exist."); - } - - /// \brief Creates instance of information about decltype() expression - /// (by move). - explicit DmngRsltDecltypeExpr( - std::shared_ptr &&Expression, bool IsSimple = false) - : DmngRsltExpr(DXK_Decltype), Expression(std::move(Expression)), - IsSimple(IsSimple) { - assert(this->Expression != nullptr && - "Expression in decltype() must exist."); - } - - -private: - /// Expression in decltype(). - std::shared_ptr Expression; - /// Indicates that decltype() is base on simple expression (id expression or - /// class member access). - bool IsSimple; -}; - -/// \brief Information about template parameter expression. -class DmngRsltTParamExpr : public DmngRsltExpr { -public: - /// \brief Gets index of referred template argument by current parameter. - unsigned getReferredTArgIdx() const { - return ReferredTArgIdx; - } - - /// \brief Gets referred template argument by current parameter. - /// - /// \return Pointer to referred template argument, or empty shared pointer - /// if template parameter refers to invalid argument. - std::shared_ptr getReferredTArg() const { - return ReferredTArg; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Sets referred template argument by current parameter (by copy). - void setReferredTArg(const std::shared_ptr &Arg) { - ReferredTArg = Arg; - } - - /// \brief Sets referred template argument by current parameter (by move). - void setReferredTArg(std::shared_ptr &&Arg) { - ReferredTArg = Arg; - } - - /// \brief Creates information about template parameter expression. - /// - /// \param TArgIdx Index of referred template argument by newly created - /// parameter. - explicit DmngRsltTParamExpr(unsigned TArgIdx) - : DmngRsltExpr(DXK_TemplateParam), ReferredTArgIdx(TArgIdx) {} - - -private: - /// Index or referred template argument. - unsigned ReferredTArgIdx; - /// Resolved referred template argument. - std::shared_ptr ReferredTArg; -}; - -/// \brief Information about primary expression (literals). -class DmngRsltPrimaryExpr : public DmngRsltExpr { -public: - /// \brief Type of content that represents value of literal. - enum LiteralContentType { - Void, ///< No value/content is used (literal has only type or name). - UInt, ///< Unsigned integer. - SInt, ///< Signed integer. - Bool, ///< Boolean. - // NOTE: There is no need to handle floating-points here (for now). - //Float, - //Double, - //FloatComplex, - //DoubleComplex, - }; - - /// \brief Gets value indicating that primary expression is external name - /// (name of function/entity used as reference). - bool isExternalName() const { - return TypeOrName->getNodeKind() == DNDK_Name; - } - - /// \brief Gets value indicating that primary expression is ordinary literal - /// with optional content and type. - bool isLiteral() const { - return TypeOrName->getNodeKind() == DNDK_Type; - } - - /// \brief Gets external name identified by current primary expression - /// (name of function/entity used as reference). - /// - /// \return External name information (shared pointer), or empty pointer - /// if current primary expression does not refer to external name. - std::shared_ptr getExternalName() const { - return TypeOrName->getAs(); - } - - /// \brief Gets type of literal in primary expression. - /// - /// \return Type information (shared pointer), or empty pointer - /// if current primary expression does not refer to ordinary literal. - std::shared_ptr getLiteralType() const { - return TypeOrName->getAs(); - } - - /// \brief Gets content type of literal. - LiteralContentType getContentType() const { - return ContentType; - } - - /// \brief Gets content as unsigned integer. - /// - /// \return Content of literal interpreted as unsigned integer. - unsigned long long getContentAsUInt() const { - return UIntValue; - } - - /// \brief Gets content as signed integer. - /// - /// \return Content of literal interpreted as signed integer. - long long getContentAsSInt() const { - return SIntValue; - } - - /// \brief Gets content as boolean. - /// - /// \return Content of literal interpreted as boolean. - bool getContentAsBool() const { - return UIntValue != 0; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates instance of information about primary expression - /// which is external name (of function/entity). - template > - explicit DmngRsltPrimaryExpr(ExternalNameT &&ExternalName) - : DmngRsltExpr(DXK_Primary), - TypeOrName(std::forward(ExternalName)), - ContentType(Void) { - assert(this->TypeOrName != nullptr && - "External name referred in primary expression must exist."); - } - - /// \brief Creates instance of information about primary expression - /// which is ordinary literal (with no content). - template , - typename = void> - explicit DmngRsltPrimaryExpr(LiteralTypeT &&LiteralType) - : DmngRsltExpr(DXK_Primary), - TypeOrName(std::forward(LiteralType)), - ContentType(Void) { - assert(this->TypeOrName != nullptr && - "Type of literal must exist."); - } - - /// \brief Creates instance of information about primary expression - /// which is ordinary literal (with unsigned integer content). - template > - DmngRsltPrimaryExpr(LiteralTypeT &&LiteralType, unsigned long long Content) - : DmngRsltExpr(DXK_Primary), - TypeOrName(std::forward(LiteralType)), - UIntValue(Content), ContentType(UInt) { - assert(this->TypeOrName != nullptr && - "Type of literal must exist."); - } - - /// \brief Creates instance of information about primary expression - /// which is ordinary literal (with signed integer content). - template > - DmngRsltPrimaryExpr(LiteralTypeT &&LiteralType, long long Content) - : DmngRsltExpr(DXK_Primary), - TypeOrName(std::forward(LiteralType)), - SIntValue(Content), ContentType(SInt) { - assert(this->TypeOrName != nullptr && - "Type of literal must exist."); - } - - /// \brief Creates instance of information about primary expression - /// which is ordinary literal (with boolean content). - template > - DmngRsltPrimaryExpr(LiteralTypeT &&LiteralType, bool Content) - : DmngRsltExpr(DXK_Primary), - TypeOrName(std::forward(LiteralType)), - UIntValue(Content), ContentType(Bool) { - assert(this->TypeOrName != nullptr && - "Type of literal must exist."); - } - - -private: - /// Type of literal value or name that names literal entity in current - /// primary expression. - std::shared_ptr TypeOrName; - union { - unsigned long long UIntValue; ///< Content as unsigned integer. - long long SIntValue; ///< Content as signed integer. - // NOTE: There is no need to handle floating-points here (for now). - //float SFValue; - //double DFValue; - //float SCValue[2]; - //double DCValue[2]; - }; - /// Type of content for literal. - LiteralContentType ContentType; -}; - - -/// \brief Information about type. -class DmngRsltType : public DmngRsltNode { -public: - /// \brief Get kind of type information. - DmngTypeKind getKind() const { - return TypeKind; - } - - /// \brief Gets type specific information. - /// - /// \tparam TypeKind Kind of type for which information will be retrieved. - /// \return Specific type information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() const { - using DerivedT = DmngRsltTypeKSelT; - - if (TypeKind == this->TypeKind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - - // Manipulators. - - /// \brief Gets type specific information. - /// - /// \tparam TypeKind Kind of type for which information will be retrieved. - /// \return Specific type information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() { - using DerivedT = DmngRsltTypeKSelT; - - if (TypeKind == this->TypeKind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - - -protected: - /// \brief Creates new instance of base for information about types. - explicit DmngRsltType(DmngTypeKind TypeKind) - : DmngRsltNode(DNDK_Type), TypeKind(TypeKind) {} - - -private: - /// Kind of demangled type represented by current node. - DmngTypeKind TypeKind; -}; - -/// \brief Information about type which represents built-in type. -class DmngRsltBuiltinType : public DmngRsltType { -public: - /// \brief Gets numeric identifier of built-in type. - DmngBuiltinType getBuiltinType() const { - return Type; - } - - /// \brief Indicates that built-in is vendor-extended built-in type. - bool isVendorBuiltinType() const { - return Type == DBT_Vendor; - } - - /// \brief Gets name of vendor-extended built-in. - /// - /// \return Name of built-in, or empty string if built-in is not - /// vendor-extended. - const std::string &getVendorName() const { - return isVendorBuiltinType() ? VendorName : DmngRsltEmptyString; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates (non-vendor-extended) built-in type. - explicit DmngRsltBuiltinType(DmngBuiltinType BuiltinType) - : DmngRsltType(DTK_Builtin), Type(BuiltinType) { - assert(!isVendorBuiltinType() && "Vendor built-in type requires name."); - } - - /// \brief Creates vendor-extended built-in type (by copy). - explicit DmngRsltBuiltinType(const std::string &VendorName) - : DmngRsltType(DTK_Builtin), Type(DBT_Vendor), VendorName(VendorName) { - assert(!VendorName.empty() && "Vendor built-in type requires name."); - } - - /// \brief Creates vendor-extended built-in type (by move). - explicit DmngRsltBuiltinType(std::string &&VendorName) - : DmngRsltType(DTK_Builtin), Type(DBT_Vendor), - VendorName(std::move(VendorName)) { - assert(!this->VendorName.empty() && "Vendor built-in type requires name."); - } - - -private: - /// Identification of built-in type. - DmngBuiltinType Type; - /// For vendor-specific built-in types, name of the type. - std::string VendorName; -}; - -/// \brief Information about type which represents function type. -class DmngRsltFuncType : public DmngRsltType, - public DmngRsltSignatureTypesBase, - public DmngRsltVendorQualsBase { -public: - /// \brief Gets cvr-qualifiers for current (member) function type. - DmngCvrQuals getCvrQuals() const { - return CvrQuals; - } - - /// \brief Gets reference qualifier of current (member) function type. - DmngRefQuals getRefQuals() const { - return RefQuals; - } - - /// \brief Indicates that function type was marked with: extern "C". - bool isExternC() const { - return IsExternC; - } - - /// \brief Indicates that function type has return type in signature. - bool hasReturnType() const override - { - // Function types have return type except rare encoding: FvE (usually - // instead of FvvE) for: void (). - return getSignatureTypes().size() > 1; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Sets cvr-qualifiers (const, volatile, restrict, etc.) for - /// current (member) function type. - void setCvrQuals(DmngCvrQuals Quals) { - CvrQuals = Quals; - } - - /// \brief Sets reference qualifiers (&, &&, etc.) for current (member) - /// function type. - void setRefQuals(DmngRefQuals Quals) { - RefQuals = Quals; - } - - /// \brief Marks function type with: extern "C". - void setIsExternC(bool IsExternC = true) { - this->IsExternC = IsExternC; - } - - - /// \brief Creates function type with initial single type (by copy). - explicit DmngRsltFuncType(const std::shared_ptr &Type) - : DmngRsltType(DTK_Function), CvrQuals(DCVQ_None), RefQuals(DRQ_None), - IsExternC(false) { - addSignatureType(Type); - } - - /// \brief Creates function type with initial single type (by move). - explicit DmngRsltFuncType(std::shared_ptr &&Type) - : DmngRsltType(DTK_Function), CvrQuals(DCVQ_None), RefQuals(DRQ_None), - IsExternC(false) { - addSignatureType(std::move(Type)); - } - - /// \brief Creates function type with initial single type (bind pointer). - explicit DmngRsltFuncType(const DmngRsltType *Type) - : DmngRsltType(DTK_Function), CvrQuals(DCVQ_None), RefQuals(DRQ_None), - IsExternC(false) { - addSignatureType(Type); - } - - -private: - /// \brief cvr-qualifiers of function (not separable). - DmngCvrQuals CvrQuals; - /// \brief Reference qualifier of function (not separable). - DmngRefQuals RefQuals; - /// \brief Indicates that function is marked as: extern "C". - bool IsExternC; -}; - -/// \brief Information about type which represents named or unnamed type. -class DmngRsltTypeNameType : public DmngRsltType { -public: - /// \brief Gets optional elaboration of type name. - DmngTypeNameKind getElaboration() const { - return Elaboration; - } - - /// \brief Get name node that describes current named or unnamed type. - std::shared_ptr getTypeName() const { - return TypeName; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates type which represents type name (by copy). - explicit DmngRsltTypeNameType( - const std::shared_ptr &Name, - DmngTypeNameKind Elaboration = DTNK_None) - : DmngRsltType(DTK_TypeName), TypeName(Name), Elaboration(Elaboration) { - assert(this->TypeName != nullptr && - "Type name refered by type node must exist."); - } - - /// \brief Creates type which represents type name (by move). - explicit DmngRsltTypeNameType( - std::shared_ptr &&Name, - DmngTypeNameKind Elaboration = DTNK_None) - : DmngRsltType(DTK_TypeName), TypeName(std::move(Name)), - Elaboration(Elaboration) { - assert(this->TypeName != nullptr && - "Type name refered by type node must exist."); - } - - -private: - /// Name of the type (class, struct, union, closure, enum names). - std::shared_ptr TypeName; - /// Type of elaboration keyword used. - DmngTypeNameKind Elaboration; -}; - -/// \brief Information about type which represents array or vector type. -class DmngRsltArrayVecType : public DmngRsltType { -public: - /// \brief Gets element type of array or vector. - std::shared_ptr getElemType() const { - return ElemType; - } - - /// \brief Indicates that array / vector has specified fixed size - /// (direct size of compile-time expression). - /// - /// It allows to differentiate 0-sized arrays from VLA, etc. - bool isSizeSpecified() const { - return IsSizeSpecified; - } - - /// \brief Gets size of array or vector in elements. - /// - /// \return Size of collection type in elements, or 0 if size is unknown, - /// unspecified, run-time variable-length or specified by expression. - unsigned long long getSize() const { - return IsSizeSpecified && SizeExpr == nullptr ? Size : 0; - } - - /// \brief Gets expression that describes size of array / vector. - /// - /// \return Expression, or empty shared pointer if size is unspecified, - /// unknown or VLA. - std::shared_ptr getSizeExpr() const { - return IsSizeSpecified ? SizeExpr : nullptr; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - -private: - /// \brief Creates new instance (unified constructor). - template - DmngRsltArrayVecType(bool IsVector, ElemTypeT &&ElemType, - bool IsSizeSpecified, unsigned long long Size, - SizeExprT &&SizeExpr) - : DmngRsltType(IsVector ? DTK_Vector : DTK_Array), - ElemType(std::forward(ElemType)), Size(Size), - SizeExpr(std::forward(SizeExpr)), - IsSizeSpecified(IsSizeSpecified) { - assert(this->ElemType != nullptr && "Element type must exist."); - } - -public: - /// \brief Creates new instance of vector/array type with unspecified - /// size (for VLA, etc.). - template > - explicit DmngRsltArrayVecType(ElemTypeT &&ElemType, bool IsVector = false) - : DmngRsltArrayVecType(IsVector, std::forward(ElemType), - false, 0, nullptr) {} - - /// \brief Creates new instance of vector/array type with fixed size - /// (size as direct number). - template > - DmngRsltArrayVecType(ElemTypeT &&ElemType, unsigned long long Size, - bool IsVector = false) - : DmngRsltArrayVecType(IsVector, std::forward(ElemType), - true, Size, nullptr) {} - - /// \brief Creates new instance of vector/array type with fixed size - /// (size as compile-time instance-dependent expression). - template , - typename = SubnodeEnablerT> - DmngRsltArrayVecType(ElemTypeT &&ElemType, SizeExprT &&SizeExpr, - bool IsVector = false) - : DmngRsltArrayVecType(IsVector, std::forward(ElemType), - true, 0, std::forward(SizeExpr)) {} - - -private: - /// Type of element in array or vector. - std::shared_ptr ElemType; - /// Size of array or vector in elements (if fixed, not-dependent size). - unsigned long long Size; - std::shared_ptr SizeExpr; - /// Indicates whether size and size expression is specified. - /// false for array of undetermined or variable-length (VLA). - bool IsSizeSpecified; -}; - -/// \brief Information about type which represents pointer to member. -class DmngRsltPtr2MmbrType : public DmngRsltType { -public: - /// \brief Gets class type of current pointer to member. - std::shared_ptr getClassType() const { - return ClassType; - } - - /// \brief Gets member type of current pointer to member. - std::shared_ptr getMemberType() const { - return MemberType; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates new instance of information about pointer to member type. - template , - typename = SubnodeEnablerT> - DmngRsltPtr2MmbrType(ClassTypeT &&ClassType, MemberTypeT &&MemberType) - : DmngRsltType(DTK_PointerToMember), - ClassType(std::forward(ClassType)), - MemberType(std::forward(MemberType)) { - assert(this->ClassType != nullptr && - "Class type of pointer to member must exist."); - assert(this->MemberType != nullptr && - "Member type of pointer to member must exist."); - } - -private: - /// Class type. - std::shared_ptr ClassType; - /// Type of member (member in class specified by class type). - std::shared_ptr MemberType; -}; - -/// \brief Information about type which represents template parameter or -/// template template parameter. -class DmngRsltTParamType : public DmngRsltType, public DmngRsltTArgsBase { -public: - /// \brief Gets information about template parameter used as current - /// type. - std::shared_ptr getTemplateParam() const { - return TemplateParam; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Sets template parameter information (by copy). - void setTemplateParam( - const std::shared_ptr &Param) { - assert(Param != nullptr && "Template parameter must be defined."); - TemplateParam = Param; - } - - /// \brief Sets template parameter information (by move). - void setTemplateParam(std::shared_ptr &&Param) { - assert(Param != nullptr && "Template parameter must be defined."); - TemplateParam = std::move(Param); - } - - /// \brief Sets template parameter information (bind pointer). - void setTemplateParam(const DmngRsltTParamExpr *Param) { - assert(Param != nullptr && "Template parameter must be defined."); - TemplateParam = std::shared_ptr(Param); - } - - /// \brief Creates instance of information about type with template or - /// template template parameter info (by copy). - explicit DmngRsltTParamType( - const std::shared_ptr &Param) - : DmngRsltType(DTK_TemplateParam) { - setTemplateParam(Param); - } - - /// \brief Creates instance of information about type with template or - /// template template parameter info (by move). - explicit DmngRsltTParamType( - std::shared_ptr &&Param) - : DmngRsltType(DTK_TemplateParam) { - setTemplateParam(std::move(Param)); - } - - /// \brief Creates instance of information about type with template or - /// template template parameter info (bind pointer). - explicit DmngRsltTParamType(const DmngRsltTParamExpr *Param) - : DmngRsltType(DTK_TemplateParam) { - setTemplateParam(Param); - } - - -private: - /// Template parameter used as a type (its referred type is used). - std::shared_ptr TemplateParam; -}; - -/// \brief Information about type which represents (result of) decltype() -/// expression. -class DmngRsltDecltypeType : public DmngRsltType { -public: - /// \brief Gets information about decltype() expression used as current - /// type information. - std::shared_ptr getDecltype() const { - return Decltype; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates instance with decltype() expression info (by copy). - explicit DmngRsltDecltypeType( - const std::shared_ptr &Decltype) - : DmngRsltType(DTK_Decltype), Decltype(Decltype) { - assert(this->Decltype != nullptr && "Decltype expression must be defined."); - } - - /// \brief Creates instance with decltype() expression info (by move). - explicit DmngRsltDecltypeType( - std::shared_ptr &&Decltype) - : DmngRsltType(DTK_Decltype), Decltype(std::move(Decltype)) { - assert(this->Decltype != nullptr && "Decltype expression must be defined."); - } - - /// \brief Creates instance with decltype() expression info (bind pointer). - explicit DmngRsltDecltypeType(const DmngRsltDecltypeExpr *Decltype) - : DmngRsltType(DTK_Decltype), Decltype(Decltype) { - assert(this->Decltype != nullptr && "Decltype expression must be defined."); - } - - -private: - /// decltype() expression used as a type (its result type is used). - std::shared_ptr Decltype; -}; - -/// \brief Information about type which represents type qualifed by single -/// qualifier (usually order-sensitive qualifier). -class DmngRsltQualType : public DmngRsltType { -public: - /// \brief Gets inner type qualified by current qualification. - std::shared_ptr getInnerType() const { - return InnerType; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - -private: - /// \brief Creates new instance of qualified type (information). - /// - /// \param Type Inner type which will be qualified. - template - DmngRsltQualType(DmngTypeKind TypeKind, InnerTypeT &&Type) - : DmngRsltType(TypeKind), InnerType(std::forward(Type)) { - assert(this->InnerType != nullptr && "Inner type must be defined."); - } - -public: - /// \brief Creates pointer qualified type (T -> T*). - template - static DmngRsltQualType createPointer(InnerTypeT &&Type) { - return DmngRsltQualType(DTK_Pointer, std::forward(Type)); - } - - /// \brief Creates lvalue reference qualified type (T -> T&). - template - static DmngRsltQualType createLValueRef(InnerTypeT &&Type) { - return DmngRsltQualType(DTK_LValueRef, std::forward(Type)); - } - - /// \brief Creates lvalue reference qualified type (T -> T&&). - template - static DmngRsltQualType createRValueRef(InnerTypeT &&Type) { - return DmngRsltQualType(DTK_RValueRef, std::forward(Type)); - } - - /// \brief Creates 'complex' qualified type (T -> complex T). - template - static DmngRsltQualType createComplex(InnerTypeT &&Type) { - return DmngRsltQualType(DTK_C2000Complex, std::forward(Type)); - } - - /// \brief Creates 'imaginary' qualified type (T -> imaginary T). - template - static DmngRsltQualType createImaginary(InnerTypeT &&Type) { - return DmngRsltQualType(DTK_C2000Imaginary, std::forward(Type)); - } - - /// \brief Creates pack expansion of type (T -> T ...). - template - static DmngRsltQualType createPackExpansion(InnerTypeT &&Type) { - return DmngRsltQualType(DTK_PackExpansion, std::forward(Type)); - } - - -private: - /// Inner type which is qualified. - std::shared_ptr InnerType; -}; - -/// \brief Information about type which represents type qualifed by group of -/// qualifier (usually order-insensitive qualifiers). -class DmngRsltQualGrpType : public DmngRsltType, - public DmngRsltVendorQualsBase { -public: - /// \brief Gets inner type qualified by current qualification. - std::shared_ptr getInnerType() const { - return InnerType; - } - - /// \brief Gets cvr-qualifiers for current name (usually used with member - /// functions). - DmngCvrQuals getCvrQuals() const { - return CvrQuals; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Sets cvr-qualifiers (const, volatile, restrict, etc.). - void setCvrQuals(DmngCvrQuals Quals) { - CvrQuals = Quals; - } - - /// \brief Creates new instance of qualified type (information). - /// - /// \param Type Inner type which will be qualified. - template > - explicit DmngRsltQualGrpType(InnerTypeT &&Type, - DmngCvrQuals Quals = DCVQ_None) - : DmngRsltType(DTK_QualGroup), InnerType(std::forward(Type)), - CvrQuals(Quals) { - assert(this->InnerType != nullptr && "Inner type must be defined."); - } - - -private: - /// Inner type which is qualified (by set of qualifiers). - std::shared_ptr InnerType; - /// \brief cvr-qualifiers of inner type. - DmngCvrQuals CvrQuals; -}; - - -/// \brief Information about name part in result. -// Nodes: , , -class DmngRsltNamePart : public DmngRsltNode, public DmngRsltTArgsBase { -public: - /// \brief Gets kind of name part. - DmngNamePartKind getPartKind() const { - return PartKind; - } - - /// \brief Indicates that current part describes data member. - bool isDataMember() const { - return PartKind == DNPK_DataMember; - } - - /// \brief Gets name part specific information. - /// - /// \tparam Kind Kind of name part for which information will be retrieved. - /// \return Specific name part information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() const { - using DerivedT = DmngRsltNamePartKSelT; - - if (PartKind == this->PartKind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - - // Manipulators. - - /// \brief Gets name part specific information. - /// - /// \tparam Kind Kind of name part for which information will be retrieved. - /// \return Specific name part information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() { - using DerivedT = DmngRsltNamePartKSelT; - - if (PartKind == this->PartKind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - - -protected: - /// \brief Creates instance of base class with specific kind of name part. - explicit DmngRsltNamePart(DmngNamePartKind PartKind) - : DmngRsltNode(DNDK_NamePart), PartKind(PartKind) {} - - -private: - /// Kind of name part. - DmngNamePartKind PartKind; -}; - -/// \brief Name part that describes operator (function). -class DmngRsltOpNamePart : public DmngRsltNamePart { -public: - /// \brief Gets enum value that identifies current operator. - DmngOperatorName getNameCode() const { - return NameCode; - } - - - /// \brief Gets value indicating that current operator is conversion operator. - bool isConversionOperator() const { - return NameCode == DON_Convert; - } - - /// \brief Gets destination type of conversion operator. - /// - /// \return Type which convert operator converts to, or empty shared pointer - /// if current operator is not conversion operator. - std::shared_ptr getConvertTargetType() const { - return isConversionOperator() ? ConvType : nullptr; - } - - /// \brief Gets value indicating that current operator is literal operator. - bool isLiteralOperator() const { - return NameCode == DON_Literal; - } - - /// \brief Gets suffix used by literal operator. - /// - /// \return Literal operator suffix, or empty string if current operator - /// is not literal operator. - const std::string &getLiteralOperatorSuffix() const { - return isLiteralOperator() ? ExtName : DmngRsltEmptyString; - } - - /// \brief Gets value indicating that current operator is vendor-specific - /// operator. - bool isVendorOperator() const { - return NameCode == DON_Vendor; - } - - /// \brief Gets name of vendor-specific operator. - /// - /// \return Name for custom operator, or empty string if current operator - /// is not vendor-specific. - const std::string &getVendorOperatorName() const { - return isVendorOperator() ? ExtName : DmngRsltEmptyString; - } - - /// \brief Gets arity of vendor-specific operator (as stated in mangling). - /// - /// \return Arity from mangling, or 0 if current operator is not - /// vendor-specific. - int getVendorOperatorArity() const { - return isVendorOperator() ? Arity : 0; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates operator (non-conversion/-literal/-vendor case). - explicit DmngRsltOpNamePart(DmngOperatorName NameCode) - : DmngRsltNamePart(DNPK_Operator), NameCode(NameCode), Arity(0) { - assert(!isConversionOperator() && !isLiteralOperator() && - !isVendorOperator() && - "Conversion/literal/vendor operator is created with another ctors."); - } - - /// \brief Creates conversion operator. - explicit DmngRsltOpNamePart( - const std::shared_ptr &ConvertTargetType) - : DmngRsltNamePart(DNPK_Operator), NameCode(DON_Convert), - ConvType(ConvertTargetType), Arity(0) { - assert(ConvType != nullptr && - "Type to convert to must be defined."); - } - - /// \brief Creates literal operator. - explicit DmngRsltOpNamePart(const std::string &LiteralSuffix) - : DmngRsltNamePart(DNPK_Operator), NameCode(DON_Literal), - ExtName(LiteralSuffix), Arity(0) { - assert(!ExtName.empty() && "Literal suffix must be specified."); - } - - /// \brief Creates vendor-specific operator. - DmngRsltOpNamePart(const std::string &VendorOperatorName, int Arity) - : DmngRsltNamePart(DNPK_Operator), NameCode(DON_Vendor), - ExtName(VendorOperatorName), Arity(Arity > 0 ? Arity : 1) { - assert(this->Arity > 0 && "Vendor operator arity must be at least one."); - assert(!ExtName.empty() && "Operator name must be specified."); - } - -private: - /// Code which identifies operator name. - DmngOperatorName NameCode; - /// Extended name for operator (either vendor operator name or suffix for - /// literal operator). - std::string ExtName; - /// Target type for conversion operator. - std::shared_ptr ConvType; - /// Arity (1 - unary, 2 - binary, etc.) of vendor operator. - int Arity; -}; - -/// \brief Name part that describes constructor / destructor (special function). -class DmngRsltCtorDtorNamePart : public DmngRsltNamePart { -public: - /// \brief Gets type of constructor or destructor. - DmngCtorDtorType getType() const { - return Type; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates constructor or destructor information. - DmngRsltCtorDtorNamePart(bool IsConstructor, DmngCtorDtorType Type) - : DmngRsltNamePart(IsConstructor ? DNPK_Constructor : DNPK_Destructor), - Type(Type) {} - - -private: - /// Constructor/Destructor type. - DmngCtorDtorType Type; -}; - -/// \brief Name part that describes in-source names (namespace names, -/// class names, data member names, etc.). -class DmngRsltSrcNamePart : public DmngRsltNamePart { -public: - /// \brief Gets in-source name (name as stated in source). - const std::string& getSourceName() const { - return SourceName; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates name part which contains in-source name. - explicit DmngRsltSrcNamePart(const std::string &SourceName, - bool IsDataMember = false) - : DmngRsltNamePart(IsDataMember ? DNPK_DataMember : DNPK_Source), - SourceName(SourceName) { - assert(!this->SourceName.empty() && - "Name (from source code) must be specified."); - } - -private: - /// Name of the part (the same as in source). - std::string SourceName; -}; - -/// \brief Name part that represents unnamed type names (including closures). -class DmngRsltUnmTypeNamePart : public DmngRsltNamePart, - public DmngRsltSignatureTypesBase { -public: - /// \brief Gets discriminating identifier which allows to differentiate - /// between two unnamed types. - /// - /// The identifier is unique for all unnamed types in specific scope. In - /// namespace or global scope the identifier ordering is unspecified as long - /// it does not cause collisions between unnamed types (even in different - /// translation units). In local/class/member/parameter scope it is usually - /// applied in lexical order. - unsigned long long getId() const { - return Id; - } - - /// \brief Indicates that unnamed type is closure type. - bool isClosure() const { - return !getSignatureTypes().empty(); - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// Creates unnamed type (either normal or closure type). - explicit DmngRsltUnmTypeNamePart(unsigned long long Id = 0) - : DmngRsltNamePart(DNPK_UnnamedType), Id(Id) {} - -private: - /// Discriminator. - unsigned long long Id; -}; - -/// \brief Name part that represents (unresolved) template parameter. -/// -/// Template parameter refers to template argument. The argument in some -/// cases can be defined after template parameter. -class DmngRsltTParamNamePart : public DmngRsltNamePart { -public: - /// \brief Gets information about template parameter used as current - /// name part. - std::shared_ptr getTemplateParam() const { - return TemplateParam; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Sets template parameter information (by copy). - void setTemplateParam( - const std::shared_ptr &Param) { - assert(Param != nullptr && "Template parameter must be defined."); - TemplateParam = Param; - } - - /// \brief Sets template parameter information (by move). - void setTemplateParam(std::shared_ptr &&Param) { - assert(Param != nullptr && "Template parameter must be defined."); - TemplateParam = std::move(Param); - } - - /// \brief Sets template parameter information (bind pointer). - void setTemplateParam(const DmngRsltTParamExpr *Param) { - assert(Param != nullptr && "Template parameter must be defined."); - TemplateParam = std::shared_ptr(Param); - } - - /// \brief Creates instance with template parameter info (by copy). - explicit DmngRsltTParamNamePart( - const std::shared_ptr &Param) - : DmngRsltNamePart(DNPK_TemplateParam) { - setTemplateParam(Param); - } - - /// \brief Creates instance with template parameter info (by move). - explicit DmngRsltTParamNamePart( - std::shared_ptr &&Param) - : DmngRsltNamePart(DNPK_TemplateParam) { - setTemplateParam(std::move(Param)); - } - - /// \brief Creates instance with new template parameter info (bind pointer). - explicit DmngRsltTParamNamePart(const DmngRsltTParamExpr *Param) - : DmngRsltNamePart(DNPK_TemplateParam) { - setTemplateParam(Param); - } - - -private: - /// Template parameter expression. - std::shared_ptr TemplateParam; -}; - -/// \brief Name part that contains decltype() expression. -class DmngRsltDecltypeNamePart : public DmngRsltNamePart { -public: - /// \brief Gets information about decltype() expression used as current - /// name part. - std::shared_ptr getDecltype() const { - return Decltype; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - - /// \brief Creates instance with decltype() expression info (by copy). - explicit DmngRsltDecltypeNamePart( - const std::shared_ptr &Decltype) - : DmngRsltNamePart(DNPK_Decltype), Decltype(Decltype) { - assert(this->Decltype != nullptr && "Decltype expression must be defined."); - } - - /// \brief Creates instance with decltype() expression info (by move). - explicit DmngRsltDecltypeNamePart( - std::shared_ptr &&Decltype) - : DmngRsltNamePart(DNPK_Decltype), Decltype(std::move(Decltype)) { - assert(this->Decltype != nullptr && "Decltype expression must be defined."); - } - - /// \brief Creates instance with decltype() expression info (bind pointer). - explicit DmngRsltDecltypeNamePart(const DmngRsltDecltypeExpr *Decltype) - : DmngRsltNamePart(DNPK_Decltype), Decltype(Decltype) { - assert(this->Decltype != nullptr && "Decltype expression must be defined."); - } - - -private: - /// decltype() expression. - std::shared_ptr Decltype; -}; - - -/// \brief Information about name parts (name prefix). -/// -/// This collection is used only for substitution functionality. -/// It is not used in result. -class DmngRsltNameParts : public DmngRsltNode, public DmngRsltNamePartsBase { -public: - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - /// \brief Creates copy of node with name parts (with optional - /// deep copy of parts). - std::shared_ptr clone(bool DeepCopyNameParts) const { - return std::make_shared(*this, DeepCopyNameParts); - } - - - /// \brief Creates instance with one name part (by copy). - explicit DmngRsltNameParts( - const std::shared_ptr& Part) - : DmngRsltNode(DNDK_NameParts), DmngRsltNamePartsBase(Part) {} - - /// \brief Creates instance with one name part (by move). - explicit DmngRsltNameParts(std::shared_ptr&& Part) - : DmngRsltNode(DNDK_NameParts), DmngRsltNamePartsBase(Part) {} - - /// \brief Creates instance with one name part (bind pointer). - explicit DmngRsltNameParts(const DmngRsltNamePart* Part) - : DmngRsltNode(DNDK_NameParts), DmngRsltNamePartsBase(Part) {} - - /// \brief Creates instance with multiple parts (by copy). - explicit DmngRsltNameParts(const DmngRsltNamePartsBase &NameParts) - : DmngRsltNode(DNDK_NameParts), DmngRsltNamePartsBase(NameParts) {} - - /// \brief Creates instance with multiple parts (by move). - explicit DmngRsltNameParts(DmngRsltNamePartsBase &&NameParts) - : DmngRsltNode(DNDK_NameParts), - DmngRsltNamePartsBase(std::move(NameParts)) {} - - /// \brief Creates instance that is a copy of other instance. - /// - /// \param Other Other instance which will be copied. - /// \param DeepCopy Indicates that name parts should be cloned as well. - DmngRsltNameParts(const DmngRsltNameParts &Other, bool DeepCopy) - : DmngRsltNode(Other), DmngRsltNamePartsBase(Other, DeepCopy) {} -}; - - -/// \brief Demangled name information in result. -/// -/// The class is intended for inheritance. -// Nodes: -class DmngRsltName : public DmngRsltNode { -public: - /// \brief Gets name kind. - /// - /// \return Enumeration which describes main kind of name. - DmngNameKind getKind() const { - return Kind; - } - - /// \brief Gets name specific information. - /// - /// \tparam Kind Kind of name for which information will be retrieved. - /// \return Specific name information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() const { - using DerivedT = DmngRsltNameKSelT; - - if (Kind == this->Kind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - - /// \brief Gets value indicating that name is ordinary function or data name. - bool isOrdinary() const { - return Kind == DNK_Ordinary; - } - - /// \brief Gets value indicating that name is special. - bool isSpecial() const { - return Kind == DNK_Special; - } - - /// \brief Gets value indicating that name refers to ordinary data. - bool isOrdinaryData() const { - return Kind == DNK_Ordinary && isData(); - } - - /// \brief Gets value indicating that name refers to special data - /// (virtual tables, type information, etc.). - bool isSpecialData() const { - return Kind == DNK_Special && isData(); - } - - /// \brief Gets value indicating that name refers to data. - virtual bool isData() const = 0; - - /// \brief Gets value indicating that name refers to ordinary function. - bool isOrdinaryFunction() const { - return Kind == DNK_Ordinary && isFunction(); - } - - /// \brief Gets value indicating that name refers to special function - /// (virtual thunk, etc.). - bool isSpecialFunction() const { - return Kind == DNK_Special && isFunction(); - } - - /// \brief Gets value indicating that name refers to function. - virtual bool isFunction() const = 0; - - // Manipulators. - - /// \brief Gets name specific information. - /// - /// \tparam Kind Kind of name for which information will be retrieved. - /// \return Specific name information, or empty shared pointer - /// if there is no information connected to selected Kind. - template - std::shared_ptr> getAs() { - using DerivedT = DmngRsltNameKSelT; - - if (Kind == this->Kind) - return std::static_pointer_cast(getNode()); - return nullptr; - } - -protected: - /// \brief Creates instance of base class with specific kind. - explicit DmngRsltName(DmngNameKind Kind) - : DmngRsltNode(DNDK_Name), Kind(Kind) {} - - -private: - /// Main kind of name. - DmngNameKind Kind; -}; - -/// \brief Information about ordinary (non-special) demangled name in result. -// Nodes: , , , , -// -class DmngRsltOrdinaryName : public DmngRsltName, - public DmngRsltNamePartsBase, - public DmngRsltSignatureTypesBase, - public DmngRsltVendorQualsBase { -public: - /// \brief Gets value indicating that name refers to (ordinary) data. - bool isData() const override { - return getSignatureTypes().empty(); - } - - /// \brief Gets value indicating that name refers to (ordinary) function. - bool isFunction() const override { - return !getSignatureTypes().empty(); - } - - - /// \brief Indicates that name is local. - bool isLocal() const { - return LocalScope != nullptr; - } - - /// \brief Gets local scope for local name. - /// - /// \return Name of local scope, or empty shared pointer if name is not local. - std::shared_ptr getLocalScope() const { - return LocalScope; - } - - /// \brief Gets discriminator index in local scope of entity. - /// - /// Gets 0-based index in local scope for entities with the same name located - /// in unnamed subscopes of the same local scope (in lexical order). - /// If entity is string literal the index discrimanates literals that have - /// different values. - /// - /// \return 0-based index, or -1 if current name is not local name. - int getInLocalScopeIdx() const { - return isLocal() ? InLocalScopeIdx : -1; - } - - /// \brief Gets index of parameter (in reversed order) which default value - /// contains entity described by current name (usually closure type). - /// - /// Gets 0-based index of parameter in reverse order (0 refers to last - /// parameter, 1 - to second to last, etc.). If current name does not refer - /// to default value, the -1 is returned instead. - /// - /// If index is valid (non-negative), getInLocalScopeIdx() treates it as - /// another qualification of local scope (so the returned in-scope index is - /// local to function parameter). - /// - /// \return 0-based index (reverse order), or -1 if name does not refer - /// to default value. - int getDefaultValueParamRIdx() const { - return isLocal() ? DefaultValueParamRIdx : -1; - } - - /// \brief Indicates that current name refers to string literal. - bool isStringLiteral() const { - return IsStringLiteral; - } - - - /// \brief Gets cvr-qualifiers for current name (usually used with member - /// functions). - DmngCvrQuals getCvrQuals() const { - return CvrQuals; - } - - /// \brief Gets reference qualifier for current name (usually used with member - /// functions). - DmngRefQuals getRefQuals() const { - return RefQuals; - } - - - /// \brief Gets value indicating that current (function) name has return - /// type encoded in signature. - bool hasReturnType() const override { - if (getSignatureTypes().empty() || getParts().empty()) - return false; - - const auto& LPart = getParts().back(); - if(LPart == nullptr || !LPart->isTemplate() || - LPart->getPartKind() == DNPK_Constructor || - LPart->getPartKind() == DNPK_Destructor) - return false; - - const auto& LPartAsOp = LPart->getAs(); - return LPartAsOp == nullptr || !LPartAsOp->isConversionOperator(); - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - /// \brief Creates copy of node with name parts (with optional - /// deep copy of parts). - std::shared_ptr clone(bool DeepCopyNameParts) const { - return std::make_shared(*this, DeepCopyNameParts); - } - - // Manipulators. - - /// \brief Sets name that identifies local scope (by copy). - void setLocalScope(const std::shared_ptr &ScopeName) { - LocalScope = ScopeName; - } - - /// \brief Sets name that identifies local scope (by move). - void setLocalScope(std::shared_ptr &&ScopeName) { - LocalScope = std::move(ScopeName); - } - - /// \brief Sets name that identifies local scope (bind pointer). - void setLocalScope(const DmngRsltName *ScopeName) { - LocalScope = std::shared_ptr(ScopeName); - } - - /// \brief Sets discriminator index in local scope. - /// - /// If Idx is negative, the function asserts and sets it to 0. - void setInLocalScopeIdx(int Idx) { - assert(InLocalScopeIdx >= 0 && - "Local index must be non-negative for valid local name."); - InLocalScopeIdx = Idx >= 0 ? Idx : 0; - } - - /// \brief Sets index (in reversed order) of parameter which default value - /// forms the scope for current name. - /// - /// \param ReversedIdx Index (in reversed order) of parameter. If index - /// is negative it is set -1 (not in parameters). - void setDefaultValueParamRIdx(int ReversedIdx) { - DefaultValueParamRIdx = ReversedIdx >= 0 ? ReversedIdx : -1; - } - - /// \brief Sets value indicating that current name refers to string literal. - void setIsStringLiteral(bool IsStringLiteral) { - this->IsStringLiteral = IsStringLiteral; - } - - /// \brief Sets cvr-qualifiers (const, volatile, restrict, etc.). - void setCvrQuals(DmngCvrQuals Quals) { - CvrQuals = Quals; - } - - /// \brief Sets reference qualifiers (&, &&, etc.). - void setRefQuals(DmngRefQuals Quals) { - RefQuals = Quals; - } - - /// \brief Resets all qualifiers. - void resetQuals() { - resetVendorQuals(); - setCvrQuals(DCVQ_None); - setRefQuals(DRQ_None); - } - -private: - /// \brief Creates instance of ordinary name (for function or data). - explicit DmngRsltOrdinaryName(DmngRsltNamePartsBase &&NameParts) - : DmngRsltName(DNK_Ordinary), DmngRsltNamePartsBase(std::move(NameParts)), - InLocalScopeIdx(0), DefaultValueParamRIdx(-1), - IsStringLiteral(false), CvrQuals(DCVQ_None), RefQuals(DRQ_None) {} -public: - /// \brief Creates instance of ordinary name (for function or data) with one - /// part (by copy). - explicit DmngRsltOrdinaryName( - const std::shared_ptr &Part) - : DmngRsltOrdinaryName(DmngRsltNameParts(Part)) {} - - /// \brief Creates instance of ordinary name (for function or data) with one - /// part (by move). - explicit DmngRsltOrdinaryName(std::shared_ptr &&Part) - : DmngRsltOrdinaryName(DmngRsltNameParts(std::move(Part))) {} - - /// \brief Creates instance of ordinary name (for function or data) with one - /// part (bind pointer). - explicit DmngRsltOrdinaryName(const DmngRsltNamePart *Part) - : DmngRsltOrdinaryName(DmngRsltNameParts(Part)) {} - - /// \brief Creates instance of ordinary name (for function or data) with - /// multiple parts (by copy). - explicit DmngRsltOrdinaryName( - const std::shared_ptr &Parts) - : DmngRsltOrdinaryName(Parts != nullptr ? DmngRsltNameParts(*Parts) : - DmngRsltNameParts(nullptr)) {} - - /// \brief Creates instance of ordinary name for string literal (no parts). - DmngRsltOrdinaryName() - : DmngRsltName(DNK_Ordinary), InLocalScopeIdx(0), DefaultValueParamRIdx(-1), - IsStringLiteral(true), CvrQuals(DCVQ_None), RefQuals(DRQ_None) {} - - /// \brief Creates instance that is a copy of other instance. - /// - /// \param Other Other instance which will be copied. - /// \param DeepCopyNameParts Indicates that name parts should be cloned as - /// well. - DmngRsltOrdinaryName(const DmngRsltOrdinaryName &Other, - bool DeepCopyNameParts) - : DmngRsltName(Other), DmngRsltNamePartsBase(Other, DeepCopyNameParts), - DmngRsltSignatureTypesBase(Other), DmngRsltVendorQualsBase(Other), - LocalScope(Other.LocalScope), InLocalScopeIdx(Other.InLocalScopeIdx), - DefaultValueParamRIdx(Other.DefaultValueParamRIdx), - IsStringLiteral(Other.IsStringLiteral), CvrQuals(Other.CvrQuals), - RefQuals(Other.RefQuals) {} - - -private: - /// Name of local scope in which current name is located (usually function - /// name. - std::shared_ptr LocalScope; - /// 0-based index in local scope (to discriminate similarly named declarations - /// from unnamed sub-scopes). Index is applied in lexical order. - int InLocalScopeIdx; - /// 0-based index of parameter (in reversed order) which default value - /// contains entity referred by current name (usually closure type). - int DefaultValueParamRIdx; - /// Indicates that current name relates to string literal. - bool IsStringLiteral; - - /// cvr-qualifiers. - DmngCvrQuals CvrQuals; - /// Reference qualifiers. - DmngRefQuals RefQuals; -}; - -/// \brief Information about special demangled name in result. -// Nodes: -class DmngRsltSpecialName : public DmngRsltName { -public: - /// Type of information used to describe related objects (sub-type - /// of related names). - using RelatedObjT = DmngRsltOrdinaryName; - - - /// \brief Gets sub-kind of special name. - DmngSpecialNameKind getSpecialKind() const { - return SpecialKind; - } - - /// \brief Gets value indicating that name refers to (special) data - /// (virtual tables, type information, etc.). - bool isData() const override { - switch (SpecialKind) { - case DSNK_VirtualTable: - case DSNK_VirtualTableTable: - case DSNK_TypeInfoStruct: - case DSNK_TypeInfoNameString: - case DSNK_GuardVariable: - case DSNK_LifeExtTemporary: - return true; - default: - return false; - } - } - - /// \brief Gets value indicating that name refers to special function - /// (virtual thunk, etc.). - bool isFunction() const override { - switch (SpecialKind) { - case DSNK_VirtualThunk: - return true; - default: - return false; - } - } - - /// \brief Indicates that name is connected to virtual functions, - /// virtual inheritance and/or polymorphism. - bool isVirtual() const { - switch (SpecialKind) { - case DSNK_VirtualTable: - case DSNK_VirtualTableTable: - case DSNK_VirtualThunk: - return true; - default: - return false; - } - } - - /// \brief Indicates that name is connected to runtime type information, - /// type_info structures, etc. - bool isRtti() const { - switch (SpecialKind) { - case DSNK_TypeInfoStruct: - case DSNK_TypeInfoNameString: - return true; - default: - return false; - } - } - - - /// \brief Gets related type connected to special data (virtual table, etc.). - /// - /// Gets name of the type for which current special entity was created. - /// - /// \brief Name of the related type, or nullptr if special entity does not - /// relate to any type. - std::shared_ptr getRelatedType() const { - switch (SpecialKind) { - case DSNK_VirtualTable: - case DSNK_VirtualTableTable: - case DSNK_TypeInfoStruct: - case DSNK_TypeInfoNameString: - return RelatedType; - default: - return nullptr; - } - } - - - /// \brief Gets origin function or data delegated/accessed via virtual thunk. - /// - /// \return Name of origin object, or nullptr if current special entity - /// is not thunk. - std::shared_ptr getOrigin() const { - switch (SpecialKind) { - case DSNK_VirtualThunk: - return RelatedName; - default: - return nullptr; - } - } - - /// \brief Gets adjustment information for this pointer (for thunk). - const DmngRsltAdjustOffset &getThisAdjustment() const { - return ThisAdjustment; - } - - /// \brief Gets adjustment information for return type (for thunk when - /// covariant return is used). - const DmngRsltAdjustOffset &getReturnAdjustment() const { - return ReturnAdjustment; - } - - - /// \brief Gets object related to life-extended temporary or guard variable. - /// - /// \return Ordinary name of object related to current special entity, or - /// nullptr if special entity is not temporary nor guard variable. - std::shared_ptr - getRelatedObject() const { - switch (SpecialKind) { - case DSNK_GuardVariable: - case DSNK_LifeExtTemporary: - if (RelatedName != nullptr) - return RelatedName->getAs(); - default: - return nullptr; - } - } - - /// \brief Gets identifier of life-extended temporary (to discriminate beteen - /// them when they all relate to single object). - /// - /// \return Discriminator number for temporaries. - unsigned long long getId() const { - return Id; - } - - /// \brief Creates shallow copy of node (or any derived type of node). - std::shared_ptr clone() const override { - return std::make_shared(*this); - } - - // Manipulators. - -private: - /// \brief Creates new instance for special name information (unified ctor). - DmngRsltSpecialName(DmngSpecialNameKind SpecialKind, - const std::shared_ptr &RelType, - const std::shared_ptr &RelName, - const DmngRsltAdjustOffset &ThisAdjustment, - const DmngRsltAdjustOffset &ReturnAdjustment, - unsigned long long Id) - : DmngRsltName(DNK_Special), SpecialKind(SpecialKind), - RelatedType(RelType), RelatedName(RelName), - ThisAdjustment(ThisAdjustment), ReturnAdjustment(ReturnAdjustment), - Id(Id) {} - -public: - /// \brief Creates special name as virtual table for specific type. - static DmngRsltSpecialName createVirtualTable( - const std::shared_ptr &VTableType) { - assert(VTableType != nullptr && "Related type must exist."); - return DmngRsltSpecialName(DSNK_VirtualTable, VTableType, nullptr, - DmngRsltAdjustOffset(), DmngRsltAdjustOffset(), - 0); - } - - /// \brief Creates special name as VTT for specific type. - static DmngRsltSpecialName createVirtualTableTable( - const std::shared_ptr &VTTType) { - assert(VTTType != nullptr && "Related type must exist."); - return DmngRsltSpecialName(DSNK_VirtualTableTable, VTTType, nullptr, - DmngRsltAdjustOffset(), DmngRsltAdjustOffset(), - 0); - } - - /// \brief Creates special name as type_info structure for specific type. - static DmngRsltSpecialName createTypeInfoStruct( - const std::shared_ptr &DescribedType) { - assert(DescribedType != nullptr && "Related type must exist."); - return DmngRsltSpecialName(DSNK_TypeInfoStruct, DescribedType, nullptr, - DmngRsltAdjustOffset(), DmngRsltAdjustOffset(), - 0); - } - - /// \brief Creates special name as type_info name string for specific type. - static DmngRsltSpecialName createTypeInfoNameString( - const std::shared_ptr &DescribedType) { - assert(DescribedType != nullptr && "Related type must exist."); - return DmngRsltSpecialName(DSNK_TypeInfoNameString, DescribedType, nullptr, - DmngRsltAdjustOffset(), DmngRsltAdjustOffset(), - 0); - } - - /// \brief Creates special name as virtual thunk delegating to origin data - /// or function and adjusting "this" pointer to proper base. - static DmngRsltSpecialName createVirtualThunk( - const std::shared_ptr &Origin, - const DmngRsltAdjustOffset &ThisAdjustment) { - assert(Origin != nullptr && "Origin of thunk must exist."); - return DmngRsltSpecialName(DSNK_VirtualThunk, nullptr, Origin, - ThisAdjustment, DmngRsltAdjustOffset(), 0); - } - - /// \brief Creates special name as virtual thunk delegating to origin data - /// or function, adjusting "this" pointer to proper base and adjusting - /// return object as well (return value covariance). - static DmngRsltSpecialName createVirtualThunk( - const std::shared_ptr &Origin, - const DmngRsltAdjustOffset &ThisAdjustment, - const DmngRsltAdjustOffset &ReturnAdjustment) { - return DmngRsltSpecialName(DSNK_VirtualThunk, nullptr, Origin, - ThisAdjustment, ReturnAdjustment, 0); - } - - /// \brief Creates special name as guard variable for one-time initialization - /// of releated object (inline static initialization). - static DmngRsltSpecialName createGuardVariable( - const std::shared_ptr &GuardedObj) { - assert(GuardedObj != nullptr && "Related object must exist."); - return DmngRsltSpecialName(DSNK_GuardVariable, nullptr, GuardedObj, - DmngRsltAdjustOffset(), DmngRsltAdjustOffset(), - 0); - } - - /// \brief Formats special name as life-extended temporary binded directly - /// or indirectly to related static object (its reference). - /// - /// \param RelatedObj Related object which extends lifetime of temporary. - /// \param Id Discriminator value (allows to differentiate two - /// temporaries binded to the same object). - static DmngRsltSpecialName createLifeExtTemporary( - const std::shared_ptr &RelatedObj, - unsigned long long Id = 0) { - assert(RelatedObj != nullptr && "Related object must exist."); - return DmngRsltSpecialName(DSNK_LifeExtTemporary, nullptr, RelatedObj, - DmngRsltAdjustOffset(), DmngRsltAdjustOffset(), - Id); - } - - -private: - /// Sub-kind of special name. - DmngSpecialNameKind SpecialKind; - - /// Type described by special data name. - std::shared_ptr RelatedType; - /// Name of related or origin entity (data or function). - /// - /// The name can identify function which is delegated via virtual thunk, - /// object guarded by guard variable or object which temporary is bound to. - std::shared_ptr RelatedName; - - /// Adjustment for this pointer in virtual thunk. - DmngRsltAdjustOffset ThisAdjustment; - /// Adjustment for return type in virtual thunk (return type covariance). - DmngRsltAdjustOffset ReturnAdjustment; - - /// Identifier that allows to differentiate between life-extended temporaries - /// connected to the same object (in case of partial/multi-level - /// initialization). - unsigned long long Id; -}; - - -/// \brief Result of name parsing from C++ demangler (clang OCL C++ flavor). -/// -/// Represents result returned from demangling. -class DmngRslt { -public: - /// \brief Gets "mangled" name. - /// - /// \return Original name before mangling. - const std::string& getMangledName() const { - return MangledName; - } - - /// \brief Gets demangled name information. - /// - /// \return Structure that describes demangled name with all additional - /// information. - std::shared_ptr getName() const { - return DemangledName; - } - - /// \brief Gets value indicating that demangling was successful. - bool isSuccessful() const { - return IsSuccessful; - } - - /// \brief Gets value indicating that demangling has failed. - bool isFailed() const { - return !IsSuccessful; - } - - /// \brief Returns the same as isSuccessful(). - explicit operator bool() const - { - return IsSuccessful; - } - - /// \brief Returns the same as isFailed(). - bool operator !() const - { - return !IsSuccessful; - } - - // Manipulators. - - /// \brief Marks result as failed. - /// - /// Result marked as failed indicates failure of entire parsing. After - /// marking collection as failed, it success state cannot be changed. - DmngRslt &setFailed() { - IsSuccessful = false; - return *this; - } - - /// \brief Sets demangled name (by copy). - void setName(const std::shared_ptr &Name) { - assert(Name != nullptr && "Name must exist (in order to set)."); - DemangledName = Name; - } - - /// \brief Sets demangled name (by move). - void setName(std::shared_ptr &&Name) { - assert(Name != nullptr && "Name must exist (in order to set)."); - DemangledName = std::move(Name); - } - - /// \brief Sets demangled name (bind pointer). - void setName(const DmngRsltName *Name) { - assert(Name != nullptr && "Name must exist (in order to set)."); - DemangledName = std::shared_ptr(Name); - } - - /// \brief Constructs result of parsing done by demangler. - /// - /// \param MangledName Name that will be demangled (via copy). - explicit DmngRslt(const std::string &MangledName) - : MangledName(MangledName), IsSuccessful(true) {} - /// \brief Constructs result of parsing done by demangler. - /// - /// \param MangledName Name that will be demangled (via move). - explicit DmngRslt(std::string &&MangledName) - : MangledName(std::move(MangledName)), IsSuccessful(true) {} - - -private: - /// Original name (name to parse). - std::string MangledName; - /// Information about demangled name. - std::shared_ptr DemangledName; - bool IsSuccessful; -}; - - -// ----------------------------------------------------------------------------- -// IMPLEMENTATION (WHEN ALL RESULT OBJECTS ARE COMPLETE) -// ----------------------------------------------------------------------------- - -inline DmngRsltNamePartsBase::DmngRsltNamePartsBase( - const DmngRsltNamePartsBase& Other, bool DeepCopy) { - if (!DeepCopy) { - Parts = Other.Parts; - return; - } - - for (const auto &Part : Other.Parts) { - Parts.push_back(Part->clone()->getAs()); - } -} - -inline bool DmngRsltTArg::isExpression() const { - return Value != nullptr && Value->getNodeKind() == DNDK_Expr; -} - -inline bool DmngRsltTArg::isType() const { - return Value != nullptr && Value->getNodeKind() == DNDK_Type; -} - -inline bool DmngRsltTArg::isPack() const { - return Value == nullptr; -} - -inline std::shared_ptr DmngRsltTArg::getExpression() const { - return Value == nullptr ? nullptr : Value->getAs(); -} - -inline std::shared_ptr DmngRsltTArg::getType() const { - return Value == nullptr ? nullptr : Value->getAs(); -} - -inline std::shared_ptr DmngRsltTArg::getValue() const { - return Value; -} - -inline const DmngRsltTArg::TArgsPackColT &DmngRsltTArg::getPack() const { - return Value == nullptr ? Pack : EmpyPack; -} - -inline void DmngRsltTArg::addPackArg(const DmngRsltTArg &Arg) { - assert(Value == nullptr && - "Adding pack element to non-pack template argument."); - Pack.push_back(Arg); -} - -inline void DmngRsltTArg::addPackArg(DmngRsltTArg &&Arg) { - assert(Value == nullptr && - "Adding pack element to non-pack template argument."); - Pack.push_back(std::move(Arg)); -} - -inline DmngRsltTArg::DmngRsltTArg( - const std::shared_ptr &Value) - : Value(Value) { - assert(this->Value != nullptr && "Template arg expression must exist."); -} - -inline DmngRsltTArg::DmngRsltTArg(std::shared_ptr &&Value) - : Value(std::move(Value)) { - assert(this->Value != nullptr && "Template arg expression must exist."); -} - -inline DmngRsltTArg::DmngRsltTArg( - const std::shared_ptr &Value) - : Value(Value) { - assert(this->Value != nullptr && "Template arg type must exist."); -} - -inline DmngRsltTArg::DmngRsltTArg(std::shared_ptr &&Value) - : Value(std::move(Value)) { - assert(this->Value != nullptr && "Template arg type must exist."); -} - -} // oclcxx_adaptation -} // spirv - -#endif // CLANG_LIB_CODEGEN_OCLCXXREWRITE_OCLCXXDEMANGLERRESULT_H diff --git a/clang/lib/CodeGen/OclCxxRewrite/OclCxxMangleEncodings.inc b/clang/lib/CodeGen/OclCxxRewrite/OclCxxMangleEncodings.inc deleted file mode 100644 index 021bb8c3a9f58..0000000000000 --- a/clang/lib/CodeGen/OclCxxRewrite/OclCxxMangleEncodings.inc +++ /dev/null @@ -1,331 +0,0 @@ -//===- OclCxxMangleEncodings.inc - Encoding tabs of fixed names -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// -// -// Copyright (c) 2015 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and/or associated documentation files (the -// "Materials"), to deal in the Materials without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Materials, and to -// permit persons to whom the Materials are furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Materials. -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -// -//===----------------------------------------------------------------------===// - - -// ----------------------------------------------------------------------------- -// BUILT-IN TYPES -// ----------------------------------------------------------------------------- - -/// \def OCLCXX_MENC_BITYPE(name) -/// Describes built-in type with custom name encoding. -/// -/// \param name Token with name of built-in type (used with prefix -/// as enum value). -/// -/// Used only to generate enum. Custom parsing must be synchronized separately. -#ifndef OCLCXX_MENC_BITYPE - #define OCLCXX_MENC_BITYPE(name) - #define OCLCXX_MENC_BITYPE_DEFAULTED_ -#endif - -/// \def OCLCXX_MENC_BITYPE_FIXED(name, encName, cxxName) -/// Describes built-in type with fixed name encoding (fixed string to match). -/// -/// \param name Token with name of built-in type (used with prefix -/// as enum value). -/// \param encName String literal which contains name in Itanium encoding. -/// \param cxxName String literal with C++-like name (human readable). -/// -/// The information is not used in matchFixedBiTypeAndAdvance function, only -/// to generate enum and corresponding name functions. Please synchronize -/// matcher separately. -#ifndef OCLCXX_MENC_BITYPE_FIXED - #define OCLCXX_MENC_BITYPE_FIXED(name, encName, cxxName) - #define OCLCXX_MENC_BITYPE_FIXED_DEFAULTED_ -#endif - -/// \def OCLCXX_MENC_BITYPE_ALIAS(aliasName, origName) -/// Describes alias name for built-in type. -/// -/// \param aliasName Token with alias name of built-in type (used with prefix -/// as enum value). -/// \param origName Token with original name referred by alias. -/// -/// Used only to generate enum. Custom parsing must be synchronized separately. -#ifndef OCLCXX_MENC_BITYPE_ALIAS - #define OCLCXX_MENC_BITYPE_ALIAS(aliasName, origName) - #define OCLCXX_MENC_BITYPE_ALIAS_DEFAULTED_ -#endif - -// ----------------------------------------------------------------------------- - -OCLCXX_MENC_BITYPE_FIXED(Void, "v", "void") ///< void -OCLCXX_MENC_BITYPE_FIXED(WChar, "w", "wchar_t") ///< wchar_t -OCLCXX_MENC_BITYPE_FIXED(Bool, "b", "bool") ///< bool -OCLCXX_MENC_BITYPE_FIXED(Char, "c", "char") ///< char -OCLCXX_MENC_BITYPE_FIXED(SChar, "a", "signed char") ///< signed char -OCLCXX_MENC_BITYPE_FIXED(UChar, "h", "unsigned char") - ///< unsigned char -OCLCXX_MENC_BITYPE_FIXED(Short, "s", "short") ///< short -OCLCXX_MENC_BITYPE_FIXED(UShort, "t", "unsigned short") - ///< unsigned short -OCLCXX_MENC_BITYPE_FIXED(Int, "i", "int") ///< int -OCLCXX_MENC_BITYPE_FIXED(UInt, "j", "unsigned int") ///< unsigned int -OCLCXX_MENC_BITYPE_FIXED(Long, "l", "long") ///< long -OCLCXX_MENC_BITYPE_FIXED(ULong, "m", "unsigned long") - ///< unsigned long -OCLCXX_MENC_BITYPE_FIXED(LongLong, "x", "long long") - ///< long long, __int64 -OCLCXX_MENC_BITYPE_ALIAS(Int64, LongLong) -OCLCXX_MENC_BITYPE_FIXED(ULongLong, "y", "unsigned long long") - ///< unsigned long long, __int64 -OCLCXX_MENC_BITYPE_ALIAS(UInt64, ULongLong) -OCLCXX_MENC_BITYPE_FIXED(Int128, "n", "__int128") ///< __int128 -OCLCXX_MENC_BITYPE_FIXED(UInt128, "o", "unsigned __int128") - ///< unsigned __int128 -OCLCXX_MENC_BITYPE_FIXED(Float, "f", "float") ///< float -OCLCXX_MENC_BITYPE_FIXED(Double, "d", "double") ///< double -OCLCXX_MENC_BITYPE_FIXED(LongDouble, "e", "long double") - ///< long double, __float80 -OCLCXX_MENC_BITYPE_ALIAS(Float80, LongDouble) -OCLCXX_MENC_BITYPE_FIXED(Float128, "g", "__float128") ///< __float128 -OCLCXX_MENC_BITYPE_FIXED(Ellipsis, "z", "...") ///< ellipsis -OCLCXX_MENC_BITYPE_FIXED(Float64R, "Dd", "__fp64r") - ///< IEEE 754r decimal floating point (64 bits) -OCLCXX_MENC_BITYPE_FIXED(Float128R, "De", "__fp128r") - ///< IEEE 754r decimal floating point (128 bits) -OCLCXX_MENC_BITYPE_FIXED(Float32R, "Df", "__fp32r") - ///< IEEE 754r decimal floating point (32 bits) -OCLCXX_MENC_BITYPE_FIXED(Float16R, "DF16_", "_Float16") - ///< IEEE 754r half-prec floating point (16 bits) -OCLCXX_MENC_BITYPE_ALIAS(Half, Float16R) -OCLCXX_MENC_BITYPE_FIXED(Char32, "Di", "char32_t") ///< char32_t -OCLCXX_MENC_BITYPE_FIXED(Char16, "Ds", "char16_t") ///< char16_t -OCLCXX_MENC_BITYPE_FIXED(Auto, "Da", "auto") ///< auto -OCLCXX_MENC_BITYPE_FIXED(DecltypeAuto, "Dc", "decltype(auto)") - ///< decltype(auto) -OCLCXX_MENC_BITYPE_FIXED(NullPtr, "Dn", "decltype(nullptr)") - ///< std::nullptr_t (i.e., decltype(nullptr)) -OCLCXX_MENC_BITYPE_FIXED(Pixel, "p", "pixel") - ///< pixel (only for altivec vectors). - -OCLCXX_MENC_BITYPE(Vendor) ///< vendor-extended (`source-name`) - -// ----------------------------------------------------------------------------- - -#ifdef OCLCXX_MENC_BITYPE_DEFAULTED_ - #undef OCLCXX_MENC_BITYPE - #undef OCLCXX_MENC_BITYPE_DEFAULTED_ -#endif - -#ifdef OCLCXX_MENC_BITYPE_FIXED_DEFAULTED_ - #undef OCLCXX_MENC_BITYPE_FIXED - #undef OCLCXX_MENC_BITYPE_FIXED_DEFAULTED_ -#endif - -#ifdef OCLCXX_MENC_BITYPE_ALIAS_DEFAULTED_ - #undef OCLCXX_MENC_BITYPE_ALIAS - #undef OCLCXX_MENC_BITYPE_ALIAS_DEFAULTED_ -#endif - - -// ----------------------------------------------------------------------------- -// OPERATORS -// ----------------------------------------------------------------------------- - - -/// \def OCLCXX_MENC_OPR(name, arity) -/// Describes operator with custom name encoding. -/// -/// \param name Token with name of operator (used with prefix -/// as enum value). -/// \param arity Integral literal with operator arity in context. -/// Specify 0 if arity is not fixed (variable, unknown or special -/// treatment). -/// -/// Used only to generate enum and arity functions. Custom parsing must be -/// synchronized separately. -#ifndef OCLCXX_MENC_OPR - #define OCLCXX_MENC_OPR(name, arity) - #define OCLCXX_MENC_OPR_DEFAULTED_ -#endif - -/// \def OCLCXX_MENC_OPR_FIXED(name, encName, arity, cxxName) -/// Describes operator with fixed name encoding (fixed string to match). -/// -/// \param name Token with name of operator (used with prefix -/// as enum value). -/// \param encName String literal which contains name in Itanium encoding. -/// \param arity Integral literal with operator arity in context. -/// Specify 0 if arity is not fixed (variable, unknown or special -/// treatment). -/// \param cxxName String literal with C++-like name (human readable without -/// "operator" prefix). -/// -/// The information is not used in matchFixedOperatorAndAdvance function, only -/// to generate enum and corresponding name/arity functions. Please synchronize -/// matcher separately. -#ifndef OCLCXX_MENC_OPR_FIXED - #define OCLCXX_MENC_OPR_FIXED(name, encName, arity, cxxName) - #define OCLCXX_MENC_OPR_FIXED_DEFAULTED_ -#endif - -/// \def OCLCXX_MENC_OPR_ALIAS(aliasName, origName) -/// Describes alias name for built-in type. -/// -/// \param aliasName Token with alias name of operator (used with prefix -/// as enum value). -/// \param origName Token with original name referred by alias. -/// -/// Used only to generate enum. Custom parsing must be synchronized separately. -#ifndef OCLCXX_MENC_OPR_ALIAS - #define OCLCXX_MENC_OPR_ALIAS(aliasName, origName) - #define OCLCXX_MENC_OPR_ALIAS_DEFAULTED_ -#endif - -// ----------------------------------------------------------------------------- - -/// | operator new | (new (E1 ...) E) | special, variable arity | -OCLCXX_MENC_OPR_FIXED(New, "nw", 0, "new") -/// | operator new[] | (new (E2 ...) E[E1]) | special, variable arity | -OCLCXX_MENC_OPR_FIXED(NewArray, "na", 0, "new[]") -/// | operator delete | delete E | special, unary in expr. | -OCLCXX_MENC_OPR_FIXED(Delete, "dl", 0, "delete") -/// | operator delete[] | delete E[] | special, unary in expr. | -OCLCXX_MENC_OPR_FIXED(DeleteArray, "da", 0, "delete[]") -/// | operator + | (+E) | unary in expr. | -OCLCXX_MENC_OPR_FIXED(Positive, "ps", 1, "+") -/// | operator - | (-E) | unary in expr. | -OCLCXX_MENC_OPR_FIXED(Negative, "ng", 1, "-") -/// | operator & | (&E) | unary in expr. | -OCLCXX_MENC_OPR_FIXED(AddressOf, "ad", 1, "&") -// Indirection operator. -/// | operator * | (*E) | unary in expr. | -OCLCXX_MENC_OPR_FIXED(Dereference, "de", 1, "*") -/// | operator ~ | (~E) | | -OCLCXX_MENC_OPR_FIXED(BitwiseComplement, "co", 1, "~") -/// | operator + | (E + E1) | | -OCLCXX_MENC_OPR_FIXED(Plus, "pl", 2, "+") -/// | operator - | (E - E1) | | -OCLCXX_MENC_OPR_FIXED(Minus, "mi", 2, "-") -/// | operator * | (E * E1) | | -OCLCXX_MENC_OPR_FIXED(Multiply, "ml", 2, "*") -/// | operator / | (E / E1) | | -OCLCXX_MENC_OPR_FIXED(Divide, "dv", 2, "/") -// Modulus operator. -/// | operator % | (E % E1) | | -OCLCXX_MENC_OPR_FIXED(Remainder, "rm", 2, "%") -/// | operator & | (E & E1) | | -OCLCXX_MENC_OPR_FIXED(BitwiseAnd, "an", 2, "&") -/// | operator | | (E | E1) | | -OCLCXX_MENC_OPR_FIXED(BitwiseOr, "or", 2, "|") -/// | operator ^ | (E ^ E1) | | -OCLCXX_MENC_OPR_FIXED(BitwiseExclusiveOr, "eo", 2, "^") -/// | operator = | (E = E1) | | -OCLCXX_MENC_OPR_FIXED(Assign, "aS", 2, "=") -/// | operator += | (E += E1) | | -OCLCXX_MENC_OPR_FIXED(PlusAssign, "pL", 2, "+=") -/// | operator -= | (E -= E1) | | -OCLCXX_MENC_OPR_FIXED(MinusAssign, "mI", 2, "-=") -/// | operator *= | (E *= E1) | | -OCLCXX_MENC_OPR_FIXED(MultiplyAssign, "mL", 2, "*=") -/// | operator /= | (E /= E1) | | -OCLCXX_MENC_OPR_FIXED(DivideAssign, "dV", 2, "/=") -/// | operator %= | (E %= E1) | | -OCLCXX_MENC_OPR_FIXED(RemainderAssign, "rM", 2, "%=") -/// | operator &= | (E &= E1) | | -OCLCXX_MENC_OPR_FIXED(BitwiseAndAssign, "aN", 2, "&=") -/// | operator |= | (E |= E1) | | -OCLCXX_MENC_OPR_FIXED(BitwiseOrAssign, "oR", 2, "|=") -/// | operator ^= | (E ^= E1) | | -OCLCXX_MENC_OPR_FIXED(BitwiseExclusiveOrAssign, "eO", 2, "^=") -/// | operator << | (E << E1) | | -OCLCXX_MENC_OPR_FIXED(LeftShift, "ls", 2, "<<") -/// | operator >> | (E >> E1) | | -OCLCXX_MENC_OPR_FIXED(RightShift, "rs", 2, ">>") -/// | operator <<= | (E <<= E1) | | -OCLCXX_MENC_OPR_FIXED(LeftShiftAssign, "lS", 2, "<<=") -/// | operator >>= | (E >>= E1) | | -OCLCXX_MENC_OPR_FIXED(RightShiftAssign, "rS", 2, ">>=") -/// | operator == | (E == E1) | | -OCLCXX_MENC_OPR_FIXED(Equal, "eq", 2, "==") -/// | operator != | (E != E1) | | -OCLCXX_MENC_OPR_FIXED(NotEqual, "ne", 2, "!=") -/// | operator < | (E < E1) | | -OCLCXX_MENC_OPR_FIXED(LessThan, "lt", 2, "<") -/// | operator > | (E > E1) | | -OCLCXX_MENC_OPR_FIXED(GreaterThan, "gt", 2, ">") -/// | operator <= | (E <= E1) | | -OCLCXX_MENC_OPR_FIXED(LessEqual, "le", 2, "<=") -/// | operator >= | (E >= E1) | | -OCLCXX_MENC_OPR_FIXED(GreaterEqual, "ge", 2, ">=") -/// | operator ! | (!E) | | -OCLCXX_MENC_OPR_FIXED(LogicalNegate, "nt", 1, "!") -/// | operator && | (E && E1) | | -OCLCXX_MENC_OPR_FIXED(LogicalAnd, "aa", 2, "&&") -/// | operator || | (E || E1) | | -OCLCXX_MENC_OPR_FIXED(LogicalOr, "oo", 2, "||") -/// | operator ++ | (E++) or (++E) | postfix in expr. | -OCLCXX_MENC_OPR_FIXED(PlusPlus, "pp", 1, "++") -/// | operator -- | (E--) or (--E) | postfix in expr. | -OCLCXX_MENC_OPR_FIXED(MinusMinus, "mm", 1, "--") -/// | operator , | (E, E1) | | -OCLCXX_MENC_OPR_FIXED(Comma, "cm", 2, ",") -/// | operator ->* | (E->*E1) | | -OCLCXX_MENC_OPR_FIXED(PointerToMemberAccess, "pm", 2, "->*") -// Arrow operator ("->"). Special treatment required because second operand -// is not an expression, but name. -/// | operator -> | (E->E1) | special, binary | -OCLCXX_MENC_OPR_FIXED(MemberAccess, "pt", 0, "->") -/// | operator () | (E(E1 ...)) | variable arity | -OCLCXX_MENC_OPR_FIXED(Call, "cl", 0, "()") - // Subscript operator. -/// | operator [] | (E[E1]) | | -OCLCXX_MENC_OPR_FIXED(Index, "ix", 2, "[]") - // Ternary operator. -/// | operator ? | (E ? E1 : E2) | | -OCLCXX_MENC_OPR_FIXED(Conditional, "qu", 3, "?") - -// Operators with names of variable size. -/// | operator | ((E ...)) or (()E) | variable arity | -OCLCXX_MENC_OPR(Convert, 0) -/// | operator "" | (E) | | -OCLCXX_MENC_OPR(Literal, 1) -/// | operator | (operator ``(E ...)) | arity from parsing | -OCLCXX_MENC_OPR(Vendor, 0) - -// ----------------------------------------------------------------------------- - -#ifdef OCLCXX_MENC_OPR_DEFAULTED_ - #undef OCLCXX_MENC_OPR - #undef OCLCXX_MENC_OPR_DEFAULTED_ -#endif - -#ifdef OCLCXX_MENC_OPR_FIXED_DEFAULTED_ - #undef OCLCXX_MENC_OPR_FIXED - #undef OCLCXX_MENC_OPR_FIXED_DEFAULTED_ -#endif - -#ifdef OCLCXX_MENC_OPR_ALIAS_DEFAULTED_ - #undef OCLCXX_MENC_OPR_ALIAS - #undef OCLCXX_MENC_OPR_ALIAS_DEFAULTED_ -#endif diff --git a/clang/lib/CodeGen/OclCxxRewrite/OclCxxParseVariant.h b/clang/lib/CodeGen/OclCxxRewrite/OclCxxParseVariant.h deleted file mode 100644 index 52896468ee20e..0000000000000 --- a/clang/lib/CodeGen/OclCxxRewrite/OclCxxParseVariant.h +++ /dev/null @@ -1,685 +0,0 @@ -//===- OclCxxParseVariant.h - Parse variant in OCLC++ demangler -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// -// -// Copyright (c) 2015 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and/or associated documentation files (the -// "Materials"), to deal in the Materials without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Materials, and to -// permit persons to whom the Materials are furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Materials. -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -// -//===----------------------------------------------------------------------===// - - -#ifndef CLANG_LIB_CODEGEN_OCLCXXREWRITE_OCLCXXPARSEVARIANT_H -#define CLANG_LIB_CODEGEN_OCLCXXREWRITE_OCLCXXPARSEVARIANT_H - -#include -#include -#include - - -namespace oclcxx { -namespace adaptation { - -// ----------------------------------------------------------------------------- -// HELPERS FOR ALIGNED UNION STORAGE -// ----------------------------------------------------------------------------- -// Replacement for std::aligned_union which is curiously not defined in -// libstdc++ until version 4 (gcc 5). -// TODO: Use std::aligned_union once all used compilers will support it. - -/// \brief Helper trait calculating maximal value from given compile-time -/// constants. -template -struct MaxHelper - : std::integral_constant MaxHelper::value - ? Val - : MaxHelper::value)> {}; - -template -struct MaxHelper - : std::integral_constant ValB - ? ValA - : ValB)> {}; - - -/// \brief Trait generating a POD type that has size and suitable alignment to -/// store object of any type listed in TypesT. -template -struct AlignedUnion -{ - static const std::size_t alignment_value = - MaxHelper::value ...>::value; - using type = typename std::aligned_storage< - MaxHelper::value, - alignment_value>::type; -}; - -// ----------------------------------------------------------------------------- -// PARSE VARIANT HELPERS -// ----------------------------------------------------------------------------- - -/// \brief Scorer for input value (in relation to stored type). -template ::type, - typename RawSTypeT = typename std::decay::type, - bool Cond = std::is_constructible::value, - int CondId = 0> -struct ParseVarValScorer; - -// [T] Condition 0: Can we construct storage type from value type. -// Check whether input type is the same as storage type (max score) or -// whether input type is converted to class/struct/union type. -template -struct ParseVarValScorer { - static const int Value = std::is_same::value - ? 6 - : (std::is_class::value || std::is_union::value - ? 5 - : ParseVarValScorer::value, 1>::Value); -}; - -// [F] Condition 0: Can we construct storage type from value type. -// Score is 0, if we cannot (no match). -template -struct ParseVarValScorer { - static const int Value = 0; -}; - -// [T] Condition 1: Input value is enum. -// Switch to underlying type and do the arithmetic tests. -template -struct ParseVarValScorer { - static const int Value = - ParseVarValScorer::type, STypeT, - typename std::underlying_type::type, RawSTypeT, - false, 1>::Value; -}; - -// [F] Condition 1: Input value is enum. -// Check if we have simple integer-integer or fp-fp conversions. -template -struct ParseVarValScorer { - static const int Value = - ParseVarValScorer::value && - std::is_integral::value) || - (std::is_floating_point::value && - std::is_floating_point::value), 2>::Value; -}; - -// [T] Condition 2: Simple arithmetic conversions. -// Switch to underlying type and do the arithmetic tests. -template -struct ParseVarValScorer { - static const int Value = sizeof(RawValT) == sizeof(RawSTypeT) - ? (std::is_signed::value == std::is_signed::value - ? 4 - : 3) - : (sizeof(RawValT) < sizeof(RawSTypeT) - ? (std::is_unsigned::value - ? 4 - : 3) - : 2); -}; - -// [F] Condition 2: Simple arithmetic conversions. -template -struct ParseVarValScorer { - static const int Value = 1; -}; - - -/// \brief Input value matcher for ParseVariant. -/// -/// This is a raw helper, please use ParseVarValMatcherT alias instead. -template -struct ParseVarValMatcher; - -// Value got maximal score (early return). -template -struct ParseVarValMatcher { - static const bool Value = true; - using Type = typename std::decay::type; - static const int Index = BestIdx; -}; - -template -struct ParseVarValMatcher - : ParseVarValMatcher {}; - -// Any non-zero score is good at the end (return first with maximal score). -template -struct ParseVarValMatcher - : ParseVarValMatcher {}; - -template -struct ParseVarValMatcher - : ParseVarValMatcher {}; - -template -struct ParseVarValMatcher - : ParseVarValMatcher {}; - -template -struct ParseVarValMatcher - : ParseVarValMatcher {}; - -template -struct ParseVarValMatcher - : ParseVarValMatcher {}; - -// Zero score at the end (matched failed). -template -struct ParseVarValMatcher { - static const bool Value = false; - static const int Index = -1; -}; - -// Scan recursively through stored types. -template -struct ParseVarValMatcher - : ParseVarValMatcher< - ValueT, (ParseVarValScorer::Value > Score) - ? ParseVarValScorer::Value - : Score, - Idx + 1, (ParseVarValScorer::Value > Score) - ? Idx - : BestIdx, - typename std::conditional< - (ParseVarValScorer::Value > Score), - StoredTypeT, - BestMatchTypeT>::type, - StoredTypesT ...> {}; - -/// \brief Matcher for input value type for ParseVariant. -/// -/// Returns the match object with: -/// - Value - indicating that match was found. -/// - Type - matched type (field does not exist if match was not found). -/// - Index - index of matched type (or -1 if there is no match). -template -using ParseVarValMatcherT = - ParseVarValMatcher; - -/// \brief SFINAE enabler for input value type for ParseVariant. -/// -/// Works like enable_if. -template -using ParseVarValEnablerT = - typename ParseVarValMatcherT::Type; - - -/// \brief Checks for standard is_ traits in stored types of ParseVariant. -// If there is no stored types return false as Value. -template