//===--- ASTDemangler.cpp ----------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // Defines a builder concept for the TypeDecoder and MetadataReader which builds // AST Types, and a utility function wrapper which takes a mangled string and // feeds it through the TypeDecoder instance. // // The RemoteAST library defines a MetadataReader instance that uses this // concept, together with some additional utilities. // //===----------------------------------------------------------------------===// #include "swift/AST/ASTDemangler.h" #include "swift/AST/ASTContext.h" #include "swift/AST/ClangModuleLoader.h" #include "swift/AST/Decl.h" #include "swift/AST/GenericSignature.h" #include "swift/AST/Module.h" #include "swift/AST/NameLookup.h" #include "swift/AST/SILLayout.h" #include "swift/AST/Type.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/AST/Types.h" #include "swift/Basic/Assertions.h" #include "swift/Basic/Defer.h" #include "swift/Demangling/Demangler.h" #include "swift/Demangling/ManglingMacros.h" #include "llvm/ADT/StringSwitch.h" using namespace swift; Type swift::Demangle::getTypeForMangling(ASTContext &ctx, StringRef mangling, GenericSignature genericSig) { Demangle::Context Dem; auto node = Dem.demangleSymbolAsNode(mangling); if (!node) return Type(); ASTBuilder builder(ctx, genericSig); return builder.decodeMangledType(node); } TypeDecl *swift::Demangle::getTypeDeclForMangling(ASTContext &ctx, StringRef mangling, GenericSignature genericSig) { Demangle::Context Dem; auto node = Dem.demangleSymbolAsNode(mangling); if (!node) return nullptr; ASTBuilder builder(ctx, genericSig); return builder.createTypeDecl(node); } TypeDecl *swift::Demangle::getTypeDeclForUSR(ASTContext &ctx, StringRef usr, GenericSignature genericSig) { if (!usr.starts_with("s:")) return nullptr; std::string mangling(usr); mangling.replace(0, 2, MANGLING_PREFIX_STR); return getTypeDeclForMangling(ctx, mangling, genericSig); } Type ASTBuilder::decodeMangledType(NodePointer node, bool forRequirement) { return swift::Demangle::decodeMangledType(*this, node, forRequirement) .getType(); } TypeDecl *ASTBuilder::createTypeDecl(NodePointer node) { if (node->getKind() == Node::Kind::Global) return createTypeDecl(node->getChild(0)); // Special case: associated types are not DeclContexts. if (node->getKind() == Node::Kind::AssociatedTypeRef) { if (node->getNumChildren() != 2) return nullptr; auto *DC = findDeclContext(node->getChild(0)); auto *proto = dyn_cast_or_null<ProtocolDecl>(DC); if (proto == nullptr) return nullptr; auto name = getIdentifier(node->getChild(1)->getText()); return proto->getAssociatedType(name); } auto *DC = findDeclContext(node); return dyn_cast_or_null<GenericTypeDecl>(DC); } Type ASTBuilder::createBuiltinType(StringRef builtinName, StringRef mangledName) { if (builtinName.starts_with(BUILTIN_TYPE_NAME_PREFIX)) { SmallVector<ValueDecl *, 1> decls; StringRef strippedName = builtinName.drop_front(BUILTIN_TYPE_NAME_PREFIX.size()); Ctx.TheBuiltinModule->lookupValue(getIdentifier(strippedName), NLKind::QualifiedLookup, decls); if (decls.size() == 1 && isa<TypeDecl>(decls[0])) return cast<TypeDecl>(decls[0])->getDeclaredInterfaceType(); } return Type(); } GenericTypeDecl *ASTBuilder::createTypeDecl(StringRef mangledName, bool &typeAlias) { Demangle::Demangler Dem; Demangle::NodePointer node = Dem.demangleType(mangledName); if (!node) return nullptr; return createTypeDecl(node, typeAlias); } ProtocolDecl * ASTBuilder::createProtocolDecl(NodePointer node) { bool typeAlias; return dyn_cast_or_null<ProtocolDecl>( createTypeDecl(node, typeAlias)); } Type ASTBuilder::createNominalType(GenericTypeDecl *decl) { auto *nominalDecl = dyn_cast<NominalTypeDecl>(decl); if (!nominalDecl) return Type(); // If the declaration is generic, fail. if (nominalDecl->isGenericContext()) return Type(); return nominalDecl->getDeclaredType(); } Type ASTBuilder::createNominalType(GenericTypeDecl *decl, Type parent) { auto *nominalDecl = dyn_cast<NominalTypeDecl>(decl); if (!nominalDecl) return Type(); // If the declaration is generic, fail. if (nominalDecl->isGeneric()) return Type(); // Imported types can be renamed to be members of other (non-generic) // types, but the mangling does not have a parent type. Just use the // declared type directly in this case and skip the parent check below. bool isImported = nominalDecl->hasClangNode() || nominalDecl->getAttrs().hasAttribute<ClangImporterSynthesizedTypeAttr>(); if (isImported && !nominalDecl->isGenericContext()) return nominalDecl->getDeclaredInterfaceType(); // Validate the parent type. if (!validateParentType(nominalDecl, parent)) return Type(); return NominalType::get(nominalDecl, parent, Ctx); } Type ASTBuilder::createTypeAliasType(GenericTypeDecl *decl, Type parent) { auto *aliasDecl = dyn_cast<TypeAliasDecl>(decl); if (!aliasDecl) return Type(); // If the declaration is generic, fail. if (aliasDecl->getGenericParams()) return Type(); // Imported types can be renamed to be members of other (non-generic) // types, but the mangling does not have a parent type. Just use the // declared type directly in this case and skip the parent check below. bool isImported = aliasDecl->hasClangNode() || aliasDecl->getAttrs().hasAttribute<ClangImporterSynthesizedTypeAttr>(); if (isImported && !aliasDecl->isGenericContext()) return aliasDecl->getDeclaredInterfaceType(); // Validate the parent type. if (!validateParentType(aliasDecl, parent)) return Type(); auto declaredType = aliasDecl->getDeclaredInterfaceType(); if (!parent) return declaredType; auto *dc = aliasDecl->getDeclContext(); auto subs = parent->getContextSubstitutionMap(dc); return declaredType.subst(subs); } static SubstitutionMap createSubstitutionMapFromGenericArgs(GenericSignature genericSig, ArrayRef<Type> args, LookupConformanceFn lookupConformance) { if (!genericSig) return SubstitutionMap(); if (genericSig.getGenericParams().size() != args.size()) return SubstitutionMap(); return SubstitutionMap::get( genericSig, [&](SubstitutableType *t) -> Type { auto *gp = cast<GenericTypeParamType>(t); unsigned ordinal = genericSig->getGenericParamOrdinal(gp); if (ordinal < args.size()) return args[ordinal]; return Type(); }, lookupConformance); } Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl, ArrayRef<Type> args) { auto *nominalDecl = dyn_cast<NominalTypeDecl>(decl); if (!nominalDecl) return Type(); // If the declaration isn't generic, fail. if (!nominalDecl->isGenericContext()) return Type(); // Build a SubstitutionMap. auto genericSig = nominalDecl->getGenericSignature(); auto subs = createSubstitutionMapFromGenericArgs( genericSig, args, LookUpConformanceInModule()); if (!subs) return Type(); auto origType = nominalDecl->getDeclaredInterfaceType(); // FIXME: We're not checking that the type satisfies the generic // requirements of the signature here. return origType.subst(subs); } Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor, ArrayRef<ArrayRef<Type>> args, unsigned ordinal) { if (opaqueDescriptor->getKind() == Node::Kind::OpaqueReturnTypeOf) { auto definingDecl = opaqueDescriptor->getChild(0); auto definingGlobal = Factory.createNode(Node::Kind::Global); definingGlobal->addChild(definingDecl, Factory); auto mangling = mangleNode(definingGlobal, ManglingFlavor); if (!mangling.isSuccess()) return Type(); auto mangledName = mangling.result(); auto moduleNode = findModuleNode(definingDecl); if (!moduleNode) return Type(); auto potentialParentModules = findPotentialModules(moduleNode); if (potentialParentModules.empty()) return Type(); OpaqueTypeDecl *opaqueDecl = nullptr; for (auto module : potentialParentModules) if (auto decl = module->lookupOpaqueResultType(mangledName)) opaqueDecl = decl; if (!opaqueDecl) return Type(); SmallVector<Type, 8> allArgs; for (auto argSet : args) { allArgs.append(argSet.begin(), argSet.end()); } SubstitutionMap subs = createSubstitutionMapFromGenericArgs( opaqueDecl->getGenericSignature(), allArgs, LookUpConformanceInModule()); Type interfaceType = opaqueDecl->getOpaqueGenericParams()[ordinal]; return OpaqueTypeArchetypeType::get(opaqueDecl, interfaceType, subs); } // TODO: named opaque types return Type(); } Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl, ArrayRef<Type> args, Type parent) { // If the declaration isn't generic, fail. if (!decl->getGenericParams()) return Type(); // Validate the parent type. if (!validateParentType(decl, parent)) return Type(); if (auto *nominalDecl = dyn_cast<NominalTypeDecl>(decl)) return BoundGenericType::get(nominalDecl, parent, args); auto *aliasDecl = cast<TypeAliasDecl>(decl); auto *dc = aliasDecl->getDeclContext(); SmallVector<Type, 2> subs; // Combine the substitutions from our parent type with our generic // arguments. if (dc->isLocalContext()) { for (auto *param : dc->getGenericSignatureOfContext().getGenericParams()) { subs.push_back(param); } } else if (parent) { auto parentSubs = parent->getContextSubstitutionMap( dc).getReplacementTypes(); subs.append(parentSubs.begin(), parentSubs.end()); } auto genericSig = aliasDecl->getGenericSignature(); ASSERT(genericSig.getInnermostGenericParams().size() == args.size()); subs.append(args.begin(), args.end()); auto subMap = SubstitutionMap::get(genericSig, subs, LookUpConformanceInModule()); return aliasDecl->getDeclaredInterfaceType().subst(subMap); } Type ASTBuilder::createTupleType(ArrayRef<Type> eltTypes, ArrayRef<StringRef> labels) { // Unwrap unlabeled one-element tuples. // // FIXME: The behavior of one-element labeled tuples is inconsistent // throughout the different re-implementations of type substitution // and pack expansion. if (eltTypes.size() == 1 && !eltTypes[0]->is<PackExpansionType>() && labels[0].empty()) { return eltTypes[0]; } SmallVector<TupleTypeElt, 4> elements; elements.reserve(eltTypes.size()); for (unsigned i : indices(eltTypes)) { Identifier label; if (!labels[i].empty()) label = getIdentifier(labels[i]); elements.emplace_back(eltTypes[i], label); } return TupleType::get(elements, Ctx); } Type ASTBuilder::createPackType(ArrayRef<Type> eltTypes) { return PackType::get(Ctx, eltTypes); } Type ASTBuilder::createSILPackType(ArrayRef<Type> eltTypes, bool isElementAddress) { auto extInfo = SILPackType::ExtInfo(isElementAddress); SmallVector<CanType, 4> elements; for (auto eltType : eltTypes) elements.push_back(eltType->getCanonicalType()); return SILPackType::get(Ctx, extInfo, elements); } size_t ASTBuilder::beginPackExpansion(Type countType) { ActivePackExpansions.push_back(countType); return 1; } void ASTBuilder::advancePackExpansion(size_t index) { assert(index == 0); } Type ASTBuilder::createExpandedPackElement(Type patternType) { assert(!ActivePackExpansions.empty()); auto countType = ActivePackExpansions.back(); return PackExpansionType::get(patternType, countType); } void ASTBuilder::endPackExpansion() { ActivePackExpansions.pop_back(); } Type ASTBuilder::createFunctionType( ArrayRef<Demangle::FunctionParam<Type>> params, Type output, FunctionTypeFlags flags, ExtendedFunctionTypeFlags extFlags, FunctionMetadataDifferentiabilityKind diffKind, Type globalActor, Type thrownError) { // The result type must be materializable. if (!output->isMaterializable()) return Type(); bool hasIsolatedParameter = false; llvm::SmallVector<AnyFunctionType::Param, 8> funcParams; for (const auto ¶m : params) { auto type = param.getType(); // All the argument types must be materializable. if (!type->isMaterializable()) return Type(); auto label = getIdentifier(param.getLabel()); auto flags = param.getFlags(); auto ownership = ParamDecl::getParameterSpecifierForValueOwnership(asValueOwnership(flags.getOwnership())); auto parameterFlags = ParameterTypeFlags() .withOwnershipSpecifier(ownership) .withVariadic(flags.isVariadic()) .withAutoClosure(flags.isAutoClosure()) .withNoDerivative(flags.isNoDerivative()) .withIsolated(flags.isIsolated()) .withSending(flags.isSending()); hasIsolatedParameter |= flags.isIsolated(); funcParams.push_back(AnyFunctionType::Param(type, label, parameterFlags)); } FunctionTypeRepresentation representation; switch (flags.getConvention()) { case FunctionMetadataConvention::Swift: representation = FunctionTypeRepresentation::Swift; break; case FunctionMetadataConvention::Block: representation = FunctionTypeRepresentation::Block; break; case FunctionMetadataConvention::Thin: representation = FunctionTypeRepresentation::Thin; break; case FunctionMetadataConvention::CFunctionPointer: representation = FunctionTypeRepresentation::CFunctionPointer; break; } DifferentiabilityKind resultDiffKind; switch (diffKind.Value) { #define SIMPLE_CASE(CASE) \ case FunctionMetadataDifferentiabilityKind::CASE: \ resultDiffKind = DifferentiabilityKind::CASE; break; SIMPLE_CASE(NonDifferentiable) SIMPLE_CASE(Forward) SIMPLE_CASE(Reverse) SIMPLE_CASE(Normal) SIMPLE_CASE(Linear) #undef SIMPLE_CASE } FunctionTypeIsolation isolation = FunctionTypeIsolation::forNonIsolated(); if (hasIsolatedParameter) { isolation = FunctionTypeIsolation::forParameter(); } else if (globalActor) { isolation = FunctionTypeIsolation::forGlobalActor(globalActor); } else if (extFlags.isIsolatedAny()) { isolation = FunctionTypeIsolation::forErased(); } else if (extFlags.isNonIsolatedCaller()) { isolation = FunctionTypeIsolation::forNonIsolatedCaller(); } auto noescape = (representation == FunctionTypeRepresentation::Swift || representation == FunctionTypeRepresentation::Block) && !flags.isEscaping(); const clang::Type *clangFunctionType = nullptr; if (shouldStoreClangType(representation)) clangFunctionType = Ctx.getClangFunctionType(funcParams, output, representation); // TODO: Handle LifetimeDependenceInfo here. auto einfo = FunctionType::ExtInfoBuilder( representation, noescape, flags.isThrowing(), thrownError, resultDiffKind, clangFunctionType, isolation, /*LifetimeDependenceInfo*/ std::nullopt, extFlags.hasSendingResult()) .withAsync(flags.isAsync()) .withSendable(flags.isSendable()) .build(); return FunctionType::get(funcParams, output, einfo); } static ParameterConvention getParameterConvention(ImplParameterConvention conv) { switch (conv) { case Demangle::ImplParameterConvention::Indirect_In: case Demangle::ImplParameterConvention::Indirect_In_Constant: return ParameterConvention::Indirect_In; case Demangle::ImplParameterConvention::Indirect_In_Guaranteed: return ParameterConvention::Indirect_In_Guaranteed; case Demangle::ImplParameterConvention::Indirect_Inout: return ParameterConvention::Indirect_Inout; case Demangle::ImplParameterConvention::Indirect_InoutAliasable: return ParameterConvention::Indirect_InoutAliasable; case Demangle::ImplParameterConvention::Direct_Owned: return ParameterConvention::Direct_Owned; case Demangle::ImplParameterConvention::Direct_Unowned: return ParameterConvention::Direct_Unowned; case Demangle::ImplParameterConvention::Direct_Guaranteed: return ParameterConvention::Direct_Guaranteed; case Demangle::ImplParameterConvention::Pack_Owned: return ParameterConvention::Pack_Owned; case Demangle::ImplParameterConvention::Pack_Guaranteed: return ParameterConvention::Pack_Guaranteed; case Demangle::ImplParameterConvention::Pack_Inout: return ParameterConvention::Pack_Inout; } llvm_unreachable("covered switch"); } static std::optional<SILParameterInfo::Options> getParameterOptions(ImplParameterInfoOptions implOptions) { SILParameterInfo::Options result; if (implOptions.contains(ImplParameterInfoFlags::NotDifferentiable)) { implOptions -= ImplParameterInfoFlags::NotDifferentiable; result |= SILParameterInfo::NotDifferentiable; } if (implOptions.contains(ImplParameterInfoFlags::Sending)) { implOptions -= ImplParameterInfoFlags::Sending; result |= SILParameterInfo::Sending; } // If we did not handle all flags in implOptions, this code was not updated // appropriately. Return None to signal error. if (bool(implOptions)) return {}; return result; } static ResultConvention getResultConvention(ImplResultConvention conv) { switch (conv) { case Demangle::ImplResultConvention::Indirect: return ResultConvention::Indirect; case Demangle::ImplResultConvention::Owned: return ResultConvention::Owned; case Demangle::ImplResultConvention::Unowned: return ResultConvention::Unowned; case Demangle::ImplResultConvention::UnownedInnerPointer: return ResultConvention::UnownedInnerPointer; case Demangle::ImplResultConvention::Autoreleased: return ResultConvention::Autoreleased; case Demangle::ImplResultConvention::Pack: return ResultConvention::Pack; } llvm_unreachable("covered switch"); } static std::optional<SILResultInfo::Options> getResultOptions(ImplResultInfoOptions implOptions) { SILResultInfo::Options result; if (implOptions.contains(ImplResultInfoFlags::NotDifferentiable)) { implOptions -= ImplResultInfoFlags::NotDifferentiable; result |= SILResultInfo::NotDifferentiable; } if (implOptions.contains(ImplResultInfoFlags::IsSending)) { implOptions -= ImplResultInfoFlags::IsSending; result |= SILResultInfo::IsSending; } // If we did not remove all of the options from implOptions, someone forgot to // update this code for a new type of flag. Return none to signal error! if (bool(implOptions)) return {}; return result; } static SILCoroutineKind getCoroutineKind(ImplCoroutineKind kind) { switch (kind) { case ImplCoroutineKind::None: return SILCoroutineKind::None; case ImplCoroutineKind::YieldOnce: return SILCoroutineKind::YieldOnce; case ImplCoroutineKind::YieldOnce2: return SILCoroutineKind::YieldOnce2; case ImplCoroutineKind::YieldMany: return SILCoroutineKind::YieldMany; } llvm_unreachable("unknown coroutine kind"); } Type ASTBuilder::createImplFunctionType( Demangle::ImplParameterConvention calleeConvention, Demangle::ImplCoroutineKind coroutineKind, ArrayRef<Demangle::ImplFunctionParam<Type>> params, ArrayRef<Demangle::ImplFunctionYield<Type>> yields, ArrayRef<Demangle::ImplFunctionResult<Type>> results, std::optional<Demangle::ImplFunctionResult<Type>> errorResult, ImplFunctionTypeFlags flags) { GenericSignature genericSig; ParameterConvention funcCalleeConvention = getParameterConvention(calleeConvention); SILCoroutineKind funcCoroutineKind = getCoroutineKind(coroutineKind); SILFunctionTypeRepresentation representation; switch (flags.getRepresentation()) { case ImplFunctionRepresentation::Thick: representation = SILFunctionTypeRepresentation::Thick; break; case ImplFunctionRepresentation::Block: representation = SILFunctionTypeRepresentation::Block; break; case ImplFunctionRepresentation::Thin: representation = SILFunctionTypeRepresentation::Thin; break; case ImplFunctionRepresentation::CFunctionPointer: representation = SILFunctionTypeRepresentation::CFunctionPointer; break; case ImplFunctionRepresentation::Method: representation = SILFunctionTypeRepresentation::Method; break; case ImplFunctionRepresentation::ObjCMethod: representation = SILFunctionTypeRepresentation::ObjCMethod; break; case ImplFunctionRepresentation::WitnessMethod: representation = SILFunctionTypeRepresentation::WitnessMethod; break; case ImplFunctionRepresentation::Closure: representation = SILFunctionTypeRepresentation::Closure; break; } swift::DifferentiabilityKind diffKind; switch (flags.getDifferentiabilityKind()) { #define SIMPLE_CASE(CASE) \ case ImplFunctionDifferentiabilityKind::CASE: \ diffKind = swift::DifferentiabilityKind::CASE; break; SIMPLE_CASE(NonDifferentiable) SIMPLE_CASE(Forward) SIMPLE_CASE(Reverse) SIMPLE_CASE(Normal) SIMPLE_CASE(Linear) #undef SIMPLE_CASE } auto isolation = SILFunctionTypeIsolation::forUnknown(); if (flags.hasErasedIsolation()) isolation = SILFunctionTypeIsolation::forErased(); // There's no representation of this in the mangling because it can't // occur in well-formed programs. bool unimplementable = false; llvm::SmallVector<SILParameterInfo, 8> funcParams; llvm::SmallVector<SILYieldInfo, 8> funcYields; llvm::SmallVector<SILResultInfo, 8> funcResults; std::optional<SILResultInfo> funcErrorResult; for (const auto ¶m : params) { auto type = param.getType()->getCanonicalType(); auto conv = getParameterConvention(param.getConvention()); auto options = *getParameterOptions(param.getOptions()); funcParams.emplace_back(type, conv, options); } for (const auto &yield : yields) { auto type = yield.getType()->getCanonicalType(); auto conv = getParameterConvention(yield.getConvention()); auto options = *getParameterOptions(yield.getOptions()); funcParams.emplace_back(type, conv, options); } for (const auto &result : results) { auto type = result.getType()->getCanonicalType(); auto conv = getResultConvention(result.getConvention()); auto options = *getResultOptions(result.getOptions()); // We currently set sending result at the function level, but we set sending // result on each result. if (flags.hasSendingResult()) options |= SILResultInfo::IsSending; funcResults.emplace_back(type, conv, options); } if (errorResult) { auto type = errorResult->getType()->getCanonicalType(); auto conv = getResultConvention(errorResult->getConvention()); funcErrorResult.emplace(type, conv); } const clang::Type *clangFnType = nullptr; if (shouldStoreClangType(representation)) { assert(funcResults.size() <= 1 && funcYields.size() == 0 && "C functions and blocks have at most 1 result and 0 yields."); auto result = funcResults.empty() ? std::optional<SILResultInfo>() : funcResults[0]; clangFnType = getASTContext().getCanonicalClangFunctionType( funcParams, result, representation); } auto einfo = SILFunctionType::ExtInfoBuilder( representation, flags.isPseudogeneric(), !flags.isEscaping(), flags.isSendable(), flags.isAsync(), unimplementable, isolation, diffKind, clangFnType, /*LifetimeDependenceInfo*/ std::nullopt) .build(); return SILFunctionType::get(genericSig, einfo, funcCoroutineKind, funcCalleeConvention, funcParams, funcYields, funcResults, funcErrorResult, SubstitutionMap(), SubstitutionMap(), Ctx); } Type ASTBuilder::createProtocolCompositionType( ArrayRef<ProtocolDecl *> protocols, Type superclass, bool isClassBound, bool forRequirement) { std::vector<Type> members; for (auto protocol : protocols) members.push_back(protocol->getDeclaredInterfaceType()); if (superclass && superclass->getClassOrBoundGenericClass()) members.push_back(superclass); // FIXME: move-only generics InvertibleProtocolSet inverses; Type composition = ProtocolCompositionType::get(Ctx, members, inverses, isClassBound); if (forRequirement) return composition; return ExistentialType::get(composition); } Type ASTBuilder::createProtocolTypeFromDecl(ProtocolDecl *protocol) { return protocol->getDeclaredInterfaceType(); } static MetatypeRepresentation getMetatypeRepresentation(ImplMetatypeRepresentation repr) { switch (repr) { case Demangle::ImplMetatypeRepresentation::Thin: return MetatypeRepresentation::Thin; case Demangle::ImplMetatypeRepresentation::Thick: return MetatypeRepresentation::Thick; case Demangle::ImplMetatypeRepresentation::ObjC: return MetatypeRepresentation::ObjC; } llvm_unreachable("covered switch"); } Type ASTBuilder::createExistentialMetatypeType( Type instance, std::optional<Demangle::ImplMetatypeRepresentation> repr) { if (auto existential = instance->getAs<ExistentialType>()) instance = existential->getConstraintType(); if (!instance->isAnyExistentialType()) return Type(); if (!repr) return ExistentialMetatypeType::get(instance); return ExistentialMetatypeType::get(instance, getMetatypeRepresentation(*repr)); } Type ASTBuilder::createConstrainedExistentialType( Type base, ArrayRef<BuiltRequirement> constraints, ArrayRef<BuiltInverseRequirement> inverseRequirements) { Type constrainedBase; if (auto baseTy = base->getAs<ProtocolType>()) { auto baseDecl = baseTy->getDecl(); llvm::SmallDenseMap<Identifier, Type> cmap; for (const auto &req : constraints) { switch (req.getKind()) { case RequirementKind::SameShape: llvm_unreachable("Same-shape requirement not supported here"); case RequirementKind::Conformance: case RequirementKind::Superclass: case RequirementKind::Layout: continue; case RequirementKind::SameType: if (auto *DMT = req.getFirstType()->getAs<DependentMemberType>()) cmap[DMT->getName()] = req.getSecondType(); } } llvm::SmallVector<Type, 4> args; for (auto *assocTy : baseDecl->getPrimaryAssociatedTypes()) { auto argTy = cmap.find(assocTy->getName()); if (argTy == cmap.end()) { return Type(); } args.push_back(argTy->getSecond()); } // We may not have any arguments because the constrained existential is a // plain protocol with an inverse requirement. if (args.empty()) { constrainedBase = ProtocolType::get(baseDecl, baseTy, base->getASTContext()); } else { constrainedBase = ParameterizedProtocolType::get(base->getASTContext(), baseTy, args); } } else if (base->isAny()) { // The only other case should be that we got an empty PCT, which is equal to // the Any type. The other constraints should have been encoded in the // existential's generic signature (and arrive as BuiltInverseRequirement). constrainedBase = base; } else { return Type(); } assert(constrainedBase); // Handle inverse requirements. if (!inverseRequirements.empty()) { InvertibleProtocolSet inverseSet; for (const auto &inverseReq : inverseRequirements) { inverseSet.insert(inverseReq.getKind()); } constrainedBase = ProtocolCompositionType::get( Ctx, { constrainedBase }, inverseSet, /*hasExplicitAnyObject=*/false); } return ExistentialType::get(constrainedBase); } Type ASTBuilder::createSymbolicExtendedExistentialType(NodePointer shapeNode, ArrayRef<Type> genArgs) { return Type(); } Type ASTBuilder::createMetatypeType( Type instance, std::optional<Demangle::ImplMetatypeRepresentation> repr) { if (!repr) return MetatypeType::get(instance); return MetatypeType::get(instance, getMetatypeRepresentation(*repr)); } void ASTBuilder::pushGenericParams(ArrayRef<std::pair<unsigned, unsigned>> parameterPacks) { ParameterPackStack.push_back(ParameterPacks); ParameterPacks.clear(); ParameterPacks.append(parameterPacks.begin(), parameterPacks.end()); } void ASTBuilder::popGenericParams() { ParameterPacks = ParameterPackStack.back(); ParameterPackStack.pop_back(); if (!ValueParametersStack.empty()) { ValueParameters = ValueParametersStack.back(); ValueParametersStack.pop_back(); } } Type ASTBuilder::createGenericTypeParameterType(unsigned depth, unsigned index) { if (!ParameterPacks.empty()) { for (auto pair : ParameterPacks) { if (pair.first == depth && pair.second == index) { return GenericTypeParamType::getPack(depth, index, Ctx); } } } if (!ValueParameters.empty()) { for (auto tuple : ValueParameters) { auto pair = std::get<std::pair<unsigned, unsigned>>(tuple); auto type = std::get<Type>(tuple); if (pair.first == depth && pair.second == index) { return GenericTypeParamType::getValue(depth, index, type, Ctx); } } } return GenericTypeParamType::getType(depth, index, Ctx); } Type ASTBuilder::createDependentMemberType(StringRef member, Type base) { auto identifier = getIdentifier(member); if (auto *archetype = base->getAs<ArchetypeType>()) { if (Type memberType = archetype->getNestedTypeByName(identifier)) return memberType; } if (base->isTypeParameter()) { return DependentMemberType::get(base, identifier); } return Type(); } Type ASTBuilder::createDependentMemberType(StringRef member, Type base, ProtocolDecl *protocol) { auto identifier = getIdentifier(member); if (auto *archetype = base->getAs<ArchetypeType>()) { if (auto assocType = protocol->getAssociatedType(identifier)) return archetype->getNestedType(assocType); } if (base->isTypeParameter()) { if (auto assocType = protocol->getAssociatedType(identifier)) return DependentMemberType::get(base, assocType); } return Type(); } #define REF_STORAGE(Name, ...) \ Type ASTBuilder::create##Name##StorageType(Type base) { \ return Name##StorageType::get(base, Ctx); \ } #include "swift/AST/ReferenceStorage.def" Type ASTBuilder::createSILBoxType(Type base) { return SILBoxType::get(base->getCanonicalType()); } /// Utility function to produce a Requirement from an InverseRequirement. static Requirement inverseAsRequirement(const InverseRequirement &inverseReq) { ASTContext &ctx = inverseReq.subject->getASTContext(); InvertibleProtocolSet inverses; inverses.insert(inverseReq.getKind()); Type constraintType = ProtocolCompositionType::get( ctx, { }, inverses, /*hasExplicitAnyObject=*/false); return Requirement( RequirementKind::Conformance, inverseReq.subject, constraintType); } /// Utility function to append Requirements produced from the given set of /// InverseRequirements to the `requirements` vector. static void appendInversesAsRequirements( ArrayRef<InverseRequirement> inverseRequirements, SmallVectorImpl<Requirement> &requirements) { for (const auto &inverseReq : inverseRequirements) requirements.push_back(inverseAsRequirement(inverseReq)); } Type ASTBuilder::createSILBoxTypeWithLayout( ArrayRef<BuiltSILBoxField> fields, ArrayRef<BuiltSubstitution> Substitutions, ArrayRef<BuiltRequirement> Requirements, ArrayRef<BuiltInverseRequirement> InverseRequirements) { SmallVector<Type, 4> replacements; SmallVector<GenericTypeParamType *, 2> genericTypeParams; for (const auto &s : Substitutions) { if (auto *t = dyn_cast_or_null<GenericTypeParamType>(s.first.getPointer())) genericTypeParams.push_back(t); replacements.push_back(s.second); } GenericSignature signature; if (!genericTypeParams.empty()) { SmallVector<BuiltRequirement, 2> RequirementsVec(Requirements); appendInversesAsRequirements(InverseRequirements, RequirementsVec); signature = swift::buildGenericSignature(Ctx, signature, genericTypeParams, std::move(RequirementsVec), /*allowInverses=*/true); } SmallVector<SILField, 4> silFields; for (auto field: fields) silFields.emplace_back(field.getPointer()->getCanonicalType(), field.getInt()); SILLayout *layout = SILLayout::get(Ctx, signature.getCanonicalSignature(), silFields, /*captures generics*/ false); SubstitutionMap substs; if (signature) substs = createSubstitutionMapFromGenericArgs( signature, replacements, LookUpConformanceInModule()); return SILBoxType::get(Ctx, layout, substs); } Type ASTBuilder::createObjCClassType(StringRef name) { auto typeDecl = findForeignTypeDecl(name, /*relatedEntityKind*/{}, ForeignModuleKind::Imported, Demangle::Node::Kind::Class); if (!typeDecl) return Type(); return typeDecl->getDeclaredInterfaceType(); } Type ASTBuilder::createBoundGenericObjCClassType(StringRef name, ArrayRef<Type> args) { auto typeDecl = findForeignTypeDecl(name, /*relatedEntityKind*/{}, ForeignModuleKind::Imported, Demangle::Node::Kind::Class); if (!typeDecl || !isa<ClassDecl>(typeDecl)) return Type(); if (!typeDecl->getGenericParams() || typeDecl->getGenericParams()->size() != args.size()) return Type(); Type parent; auto *dc = typeDecl->getDeclContext(); if (dc->isTypeContext()) { if (dc->isGenericContext()) return Type(); parent = dc->getDeclaredInterfaceType(); } return BoundGenericClassType::get(cast<ClassDecl>(typeDecl), parent, args); } ProtocolDecl *ASTBuilder::createObjCProtocolDecl(StringRef name) { auto typeDecl = findForeignTypeDecl(name, /*relatedEntityKind*/{}, ForeignModuleKind::Imported, Demangle::Node::Kind::Protocol); if (auto *protocolDecl = dyn_cast_or_null<ProtocolDecl>(typeDecl)) return protocolDecl; return nullptr; } Type ASTBuilder::createDynamicSelfType(Type selfType) { return DynamicSelfType::get(selfType, Ctx); } Type ASTBuilder::createForeignClassType(StringRef mangledName) { bool typeAlias = false; auto typeDecl = createTypeDecl(mangledName, typeAlias); if (!typeDecl) return Type(); return typeDecl->getDeclaredInterfaceType(); } Type ASTBuilder::getUnnamedForeignClassType() { return Type(); } Type ASTBuilder::getOpaqueType() { return Type(); } Type ASTBuilder::createOptionalType(Type base) { return OptionalType::get(base); } Type ASTBuilder::createArrayType(Type base) { return ArraySliceType::get(base); } Type ASTBuilder::createInlineArrayType(Type count, Type element) { return InlineArrayType::get(count, element); } Type ASTBuilder::createDictionaryType(Type key, Type value) { return DictionaryType::get(key, value); } Type ASTBuilder::createIntegerType(intptr_t value) { return IntegerType::get(std::to_string(value), /*isNegative*/ false, Ctx); } Type ASTBuilder::createNegativeIntegerType(intptr_t value) { return IntegerType::get(std::to_string(value), /*isNegative*/ true, Ctx); } Type ASTBuilder::createBuiltinFixedArrayType(Type size, Type element) { return BuiltinFixedArrayType::get(size->getCanonicalType(), element->getCanonicalType()); } GenericSignature ASTBuilder::createGenericSignature(ArrayRef<BuiltType> builtParams, ArrayRef<BuiltRequirement> requirements) { std::vector<GenericTypeParamType *> params; for (auto ¶m : builtParams) { auto paramTy = param->getAs<GenericTypeParamType>(); if (!paramTy) return GenericSignature(); params.push_back(paramTy); } return GenericSignature::get(params, requirements); } SubstitutionMap ASTBuilder::createSubstitutionMap(BuiltGenericSignature sig, ArrayRef<BuiltType> replacements) { return SubstitutionMap::get(sig, replacements, LookUpConformanceInModule()); } Type ASTBuilder::subst(Type subject, const BuiltSubstitutionMap &Subs) const { return subject.subst(Subs); } bool ASTBuilder::validateParentType(TypeDecl *decl, Type parent) { auto parentDecl = decl->getDeclContext()->getSelfNominalTypeDecl(); // If we don't have a parent type, fast-path. if (!parent) { return parentDecl == nullptr; } // We do have a parent type. If our type doesn't, it's an error. if (!parentDecl) { return false; } if (isa<NominalTypeDecl>(decl)) { // The parent should be a nominal type when desugared. auto *parentNominal = parent->getAnyNominal(); if (!parentNominal || parentNominal != parentDecl) { return false; } } // FIXME: validate that the parent is a correct application of the // enclosing context? return true; } GenericTypeDecl * ASTBuilder::getAcceptableTypeDeclCandidate(ValueDecl *decl, Demangle::Node::Kind kind) { if (kind == Demangle::Node::Kind::Class) { return dyn_cast<ClassDecl>(decl); } else if (kind == Demangle::Node::Kind::Enum) { return dyn_cast<EnumDecl>(decl); } else if (kind == Demangle::Node::Kind::Protocol) { return dyn_cast<ProtocolDecl>(decl); } else if (kind == Demangle::Node::Kind::Structure) { return dyn_cast<StructDecl>(decl); } else { assert(kind == Demangle::Node::Kind::TypeAlias); return dyn_cast<TypeAliasDecl>(decl); } } DeclContext *ASTBuilder::getNotionalDC() { if (!NotionalDC) { NotionalDC = ModuleDecl::createEmpty(getIdentifier(".RemoteAST"), Ctx); NotionalDC = new (Ctx) TopLevelCodeDecl(NotionalDC); } return NotionalDC; } GenericTypeDecl * ASTBuilder::createTypeDecl(NodePointer node, bool &typeAlias) { auto DC = findDeclContext(node); if (!DC) return nullptr; typeAlias = isa<TypeAliasDecl>(DC); return dyn_cast<GenericTypeDecl>(DC); } llvm::ArrayRef<ModuleDecl *> ASTBuilder::findPotentialModules(NodePointer node) { assert(node->getKind() == Demangle::Node::Kind::Module); const auto moduleName = node->getText(); return Ctx.getModulesByRealOrABIName(moduleName); } Demangle::NodePointer ASTBuilder::findModuleNode(NodePointer node) { auto child = node; while (child->hasChildren() && child->getKind() != Demangle::Node::Kind::Module) { child = child->getFirstChild(); } if (child->getKind() != Demangle::Node::Kind::Module) return nullptr; return child; } std::optional<ASTBuilder::ForeignModuleKind> ASTBuilder::getForeignModuleKind(NodePointer node) { if (node->getKind() == Demangle::Node::Kind::DeclContext) return getForeignModuleKind(node->getFirstChild()); if (node->getKind() != Demangle::Node::Kind::Module) return std::nullopt; return llvm::StringSwitch<std::optional<ForeignModuleKind>>(node->getText()) .Case(MANGLING_MODULE_OBJC, ForeignModuleKind::Imported) .Case(MANGLING_MODULE_CLANG_IMPORTER, ForeignModuleKind::SynthesizedByImporter) .Default(std::nullopt); } LayoutConstraint ASTBuilder::getLayoutConstraint(LayoutConstraintKind kind) { return LayoutConstraint::getLayoutConstraint(kind, getASTContext()); } LayoutConstraint ASTBuilder::getLayoutConstraintWithSizeAlign( LayoutConstraintKind kind, unsigned size, unsigned alignment) { return LayoutConstraint::getLayoutConstraint(kind, size, alignment, getASTContext()); } InverseRequirement ASTBuilder::createInverseRequirement( Type subject, InvertibleProtocolKind kind) { auto knownProtoKind = getKnownProtocolKind(kind); auto proto = subject->getASTContext().getProtocol(knownProtoKind); return InverseRequirement(subject, proto, SourceLoc()); } CanGenericSignature ASTBuilder::demangleGenericSignature( NominalTypeDecl *nominalDecl, NodePointer node) { auto baseGenericSig = nominalDecl->getGenericSignature(); // The generic signature is for a constrained extension of nominalDecl, so // we introduce the parameter packs from the nominal's generic signature. ParameterPackStack.push_back(ParameterPacks); ParameterPacks.clear(); ValueParametersStack.push_back(ValueParameters); ValueParameters.clear(); for (auto *paramTy : baseGenericSig.getGenericParams()) { if (paramTy->isParameterPack()) ParameterPacks.emplace_back(paramTy->getDepth(), paramTy->getIndex()); if (paramTy->isValue()) { auto pair = std::make_pair(paramTy->getDepth(), paramTy->getIndex()); auto tuple = std::make_tuple(pair, paramTy->getValueType()); ValueParameters.emplace_back(tuple); } } SWIFT_DEFER { popGenericParams(); }; // Constrained extensions mangle the subset of requirements not satisfied // by the nominal's generic signature. SmallVector<Requirement, 2> requirements; SmallVector<InverseRequirement, 2> inverseRequirements; decodeRequirement<BuiltType, BuiltRequirement, BuiltInverseRequirement, BuiltLayoutConstraint, ASTBuilder>( node, requirements, inverseRequirements, *this); appendInversesAsRequirements(inverseRequirements, requirements); return buildGenericSignature(Ctx, baseGenericSig, {}, std::move(requirements), /*allowInverses=*/true) .getCanonicalSignature(); } DeclContext * ASTBuilder::findDeclContext(NodePointer node) { switch (node->getKind()) { case Demangle::Node::Kind::DeclContext: case Demangle::Node::Kind::Type: case Demangle::Node::Kind::BoundGenericClass: case Demangle::Node::Kind::BoundGenericEnum: case Demangle::Node::Kind::BoundGenericProtocol: case Demangle::Node::Kind::BoundGenericStructure: case Demangle::Node::Kind::BoundGenericTypeAlias: return findDeclContext(node->getFirstChild()); case Demangle::Node::Kind::Module: { // A Module node is not enough information to find the decl context. // The reason being that the module name in a mangled name can either be // the module's ABI name, which is potentially not unique (due to the // -module-abi-name flag), or the module's real name, if mangling for the // debugger or USR together with the OriginallyDefinedIn attribute for // example. assert(false && "Looked up module as decl context directly!"); auto modules = findPotentialModules(node); return modules.empty() ? nullptr : modules[0]; } case Demangle::Node::Kind::Class: case Demangle::Node::Kind::Enum: case Demangle::Node::Kind::Protocol: case Demangle::Node::Kind::Structure: case Demangle::Node::Kind::TypeAlias: { const auto &declNameNode = node->getChild(1); // Handle local declarations. if (declNameNode->getKind() == Demangle::Node::Kind::LocalDeclName) { // Find the AST node for the defining module. auto moduleNode = findModuleNode(node); if (!moduleNode) return nullptr; auto potentialModules = findPotentialModules(moduleNode); if (potentialModules.empty()) return nullptr; // Look up the local type by its mangling. auto mangling = Demangle::mangleNode(node, ManglingFlavor); if (!mangling.isSuccess()) return nullptr; auto mangledName = mangling.result(); for (auto *module : potentialModules) if (auto *decl = module->lookupLocalType(mangledName)) return dyn_cast<DeclContext>(decl); return nullptr; } StringRef name; StringRef relatedEntityKind; Identifier privateDiscriminator; if (declNameNode->getKind() == Demangle::Node::Kind::Identifier) { name = declNameNode->getText(); } else if (declNameNode->getKind() == Demangle::Node::Kind::PrivateDeclName) { name = declNameNode->getChild(1)->getText(); privateDiscriminator = getIdentifier(declNameNode->getChild(0)->getText()); } else if (declNameNode->getKind() == Demangle::Node::Kind::RelatedEntityDeclName) { name = declNameNode->getChild(1)->getText(); relatedEntityKind = declNameNode->getFirstChild()->getText(); // Ignore any other decl-name productions for now. } else { return nullptr; } // Do some special logic for foreign type declarations. if (privateDiscriminator.empty()) { if (auto foreignModuleKind = getForeignModuleKind(node->getChild(0))) { return findForeignTypeDecl(name, relatedEntityKind, foreignModuleKind.value(), node->getKind()); } } auto child = node->getFirstChild(); if (child->getKind() == Node::Kind::Module) { auto potentialModules = findPotentialModules(child); if (potentialModules.empty()) return nullptr; for (auto *module : potentialModules) if (auto typeDecl = findTypeDecl(module, getIdentifier(name), privateDiscriminator, node->getKind())) return typeDecl; return nullptr; } if (auto *dc = findDeclContext(child)) if (auto typeDecl = findTypeDecl(dc, getIdentifier(name), privateDiscriminator, node->getKind())) return typeDecl; return nullptr; } case Demangle::Node::Kind::Global: return findDeclContext(node->getChild(0)); case Demangle::Node::Kind::Extension: { auto moduleDecls = findPotentialModules(node->getFirstChild()); if (moduleDecls.empty()) return nullptr; auto *nominalDecl = dyn_cast_or_null<NominalTypeDecl>( findDeclContext(node->getChild(1))); if (!nominalDecl) return nullptr; CanGenericSignature genericSig; bool genericSigMatchesNominal = false; if (node->getNumChildren() > 2) { genericSig = demangleGenericSignature(nominalDecl, node->getChild(2)); // If the generic signature are equivalent to that of the nominal type, // we're either in another module or the nominal type is generic and // involves inverse requirements on its generic parameters. genericSigMatchesNominal = genericSig && genericSig == nominalDecl->getGenericSignatureOfContext().getCanonicalSignature(); // If the generic signature is equivalent to that of the nominal type, // and we're in the same module, it's due to inverse requirements. // Just return the nominal declaration. for (auto *moduleDecl : moduleDecls) { if (genericSigMatchesNominal && nominalDecl->getParentModule() == moduleDecl) { return nominalDecl;; } } } for (auto *ext : nominalDecl->getExtensions()) { bool found = false; for (ModuleDecl *module : moduleDecls) { if (ext->getParentModule() == module) { found = true; break; } } if (!found) continue; if (!ext->isConstrainedExtension()) { if (!genericSig || genericSigMatchesNominal) return ext; continue; } if (!ext->isWrittenWithConstraints() && !genericSig) return ext; auto extSig = ext->getGenericSignature().getCanonicalSignature(); if (extSig == genericSig) { return ext; } // If the extension mangling doesn't include a generic signature, it // might be because the nominal type suppresses conformance. if (!genericSig) { SmallVector<Requirement, 2> requirements; SmallVector<InverseRequirement, 2> inverses; extSig->getRequirementsWithInverses(requirements, inverses); if (requirements.empty()) return ext; } } return nullptr; } // Bail out on other kinds of contexts. default: return nullptr; } } GenericTypeDecl * ASTBuilder::findTypeDecl(DeclContext *dc, Identifier name, Identifier privateDiscriminator, Demangle::Node::Kind kind) { auto module = dc->getParentModule(); // When looking into an extension, look into the nominal instead; the // important thing is that the module, obtained above, is the module // containing the extension and not the module containing the nominal if (isa<ExtensionDecl>(dc)) dc = dc->getSelfNominalTypeDecl(); SmallVector<ValueDecl *, 4> lookupResults; module->lookupMember(lookupResults, dc, name, privateDiscriminator); GenericTypeDecl *result = nullptr; for (auto decl : lookupResults) { // Ignore results that are not the right kind of type declaration. auto *candidate = getAcceptableTypeDeclCandidate(decl, kind); if (!candidate) continue; // Ignore results that aren't actually from the defining module. if (candidate->getParentModule() != module) continue; // This is a viable result. // If we already have a viable result, it's ambiguous, so give up. if (result) return nullptr; result = candidate; } // If we looked into the standard library module, but didn't find anything, // try the _Concurrency module, which is also mangled into the Swift module. if (!result && !dc->getParent() && module->isStdlibModule()) { ASTContext &ctx = module->getASTContext(); if (auto concurrencyModule = ctx.getLoadedModule(ctx.Id_Concurrency)) { return findTypeDecl(concurrencyModule, name, privateDiscriminator, kind); } } return result; } static std::optional<ClangTypeKind> getClangTypeKindForNodeKind(Demangle::Node::Kind kind) { switch (kind) { case Demangle::Node::Kind::Protocol: return ClangTypeKind::ObjCProtocol; case Demangle::Node::Kind::Class: return ClangTypeKind::ObjCClass; case Demangle::Node::Kind::TypeAlias: return ClangTypeKind::Typedef; case Demangle::Node::Kind::Structure: case Demangle::Node::Kind::Enum: return ClangTypeKind::Tag; default: return std::nullopt; } } GenericTypeDecl *ASTBuilder::findForeignTypeDecl(StringRef name, StringRef relatedEntityKind, ForeignModuleKind foreignKind, Demangle::Node::Kind kind) { // Check to see if we have an importer loaded. auto importer = Ctx.getClangModuleLoader(); if (!importer) return nullptr; // Find the unique declaration that has the right kind. struct Consumer : VisibleDeclConsumer { Demangle::Node::Kind ExpectedKind; GenericTypeDecl *Result = nullptr; bool HadError = false; explicit Consumer(Demangle::Node::Kind kind) : ExpectedKind(kind) {} void foundDecl(ValueDecl *decl, DeclVisibilityKind reason, DynamicLookupInfo dynamicLookupInfo = {}) override { if (HadError) return; if (decl == Result) return; if (!Result) { Result = dyn_cast<GenericTypeDecl>(decl); HadError |= !Result; } else { HadError = true; Result = nullptr; } } } consumer(kind); auto found = [&](TypeDecl *found) { consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel); }; std::optional<ClangTypeKind> lookupKind = getClangTypeKindForNodeKind(kind); if (!lookupKind) return nullptr; switch (foreignKind) { case ForeignModuleKind::SynthesizedByImporter: if (!relatedEntityKind.empty()) { importer->lookupRelatedEntity(name, *lookupKind, relatedEntityKind, found); break; } importer->lookupValue(getIdentifier(name), consumer); if (consumer.Result) consumer.Result = getAcceptableTypeDeclCandidate(consumer.Result, kind); break; case ForeignModuleKind::Imported: importer->lookupTypeDecl(name, *lookupKind, found); } return consumer.Result; } Identifier ASTBuilder::getIdentifier(StringRef name) { if (name.size() > 1 && name.front() == '`' && name.back() == '`') { // Raw identifiers have backticks affixed before mangling. We need to // remove those before creating the Identifier for the AST, which doesn't // encode the backticks. std::string fixedName; for (size_t i = 1; i < name.size() - 1; ++i) { unsigned char ch = name[i]; // Raw identifiers have the space (U+0020) replaced with a non-breaking // space (U+00A0, UTF-8: 0xC2 0xA0) in their mangling so that parts of // the runtime that use space as a delimiter remain compatible with // these identifiers. Flip it back. if (ch == 0xc2 && i < name.size() - 2 && (unsigned char)name[i + 1] == 0xa0) { fixedName.push_back(' '); ++i; } else { fixedName.push_back(ch); } } return Ctx.getIdentifier(fixedName); } return Ctx.getIdentifier(name); }