Merge pull request #9407 from slavapestov/use-objc-msgsend-for-overrides-of-imported-methods
Use objc_msgSend() for overrides of imported methods [4.0]
diff --git a/include/swift/AST/Witness.h b/include/swift/AST/Witness.h
index 738e2f1..e81c5ea 100644
--- a/include/swift/AST/Witness.h
+++ b/include/swift/AST/Witness.h
@@ -108,6 +108,16 @@
/// not generic (excepting \c Self) and the conforming type is non-generic.
Witness(ValueDecl *witness) : storage(witness) { assert(witness != nullptr); }
+ /// Create an opaque witness for the given requirement.
+ ///
+ /// This indicates that a witness exists, but is not visible to the current
+ /// module.
+ static Witness forOpaque(ValueDecl *requirement) {
+ // TODO: It's probably a good idea to have a separate 'opaque' bit.
+ // Making req == witness is kind of a hack.
+ return Witness(requirement);
+ }
+
/// Create a witness that requires substitutions.
///
/// \param decl The declaration for the witness.
diff --git a/include/swift/Basic/Version.h b/include/swift/Basic/Version.h
index 9c36999..9d157dc 100644
--- a/include/swift/Basic/Version.h
+++ b/include/swift/Basic/Version.h
@@ -144,6 +144,9 @@
bool operator>=(const Version &lhs, const Version &rhs);
bool operator==(const Version &lhs, const Version &rhs);
+inline bool operator!=(const Version &lhs, const Version &rhs) {
+ return !(lhs == rhs);
+}
raw_ostream &operator<<(raw_ostream &os, const Version &version);
diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h
index 263941a..6401709 100644
--- a/include/swift/ClangImporter/ClangImporter.h
+++ b/include/swift/ClangImporter/ClangImporter.h
@@ -308,10 +308,12 @@
Optional<std::string>
getOrCreatePCH(const ClangImporterOptions &ImporterOptions,
- const std::string &SwiftPCHHash);
+ StringRef SwiftPCHHash);
Optional<std::string>
+ /// \param isExplicit true if the PCH filename was passed directly
+ /// with -import-objc-header option.
getPCHFilename(const ClangImporterOptions &ImporterOptions,
- const std::string &SwiftPCHHash);
+ StringRef SwiftPCHHash, bool &isExplicit);
};
ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN,
diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h
index d7106e6..0904510 100644
--- a/include/swift/Demangling/Demangle.h
+++ b/include/swift/Demangling/Demangle.h
@@ -409,6 +409,12 @@
/// This should always round-trip perfectly with demangleSymbolAsNode.
std::string mangleNode(const NodePointer &root);
+/// Remangle in the old mangling scheme.
+///
+/// This is only used for objc-runtime names and should be removed as soon as
+/// we switch to the new mangling for those names as well.
+std::string mangleNodeOld(const NodePointer &root);
+
/// \brief Transform the node structure to a string.
///
/// Typical usage:
diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h
index d53c555..a3293e7 100644
--- a/include/swift/IDE/Utils.h
+++ b/include/swift/IDE/Utils.h
@@ -13,6 +13,7 @@
#ifndef SWIFT_IDE_UTILS_H
#define SWIFT_IDE_UTILS_H
+#include "llvm/ADT/PointerIntPair.h"
#include "swift/Basic/LLVM.h"
#include "swift/AST/ASTNode.h"
#include "swift/AST/Module.h"
@@ -243,9 +244,12 @@
Break,
Continue,
};
+
+typedef llvm::PointerIntPair<TypeBase*, 1, bool> ReturnTyAndWhetherExit;
+
struct ResolvedRangeInfo {
RangeKind Kind;
- Type Ty;
+ ReturnTyAndWhetherExit ExitInfo;
StringRef Content;
bool HasSingleEntry;
bool ThrowingUnhandledError;
@@ -256,23 +260,26 @@
ArrayRef<DeclaredDecl> DeclaredDecls;
ArrayRef<ReferencedDecl> ReferencedDecls;
DeclContext* RangeContext;
- ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content,
+ ResolvedRangeInfo(RangeKind Kind, ReturnTyAndWhetherExit ExitInfo, StringRef Content,
DeclContext* RangeContext,
bool HasSingleEntry, bool ThrowingUnhandledError,
OrphanKind Orphan, ArrayRef<ASTNode> ContainedNodes,
ArrayRef<DeclaredDecl> DeclaredDecls,
ArrayRef<ReferencedDecl> ReferencedDecls): Kind(Kind),
- Ty(Ty), Content(Content), HasSingleEntry(HasSingleEntry),
+ ExitInfo(ExitInfo), Content(Content),
+ HasSingleEntry(HasSingleEntry),
ThrowingUnhandledError(ThrowingUnhandledError),
Orphan(Orphan), ContainedNodes(ContainedNodes),
DeclaredDecls(DeclaredDecls),
ReferencedDecls(ReferencedDecls),
RangeContext(RangeContext) {}
ResolvedRangeInfo(StringRef Content) :
- ResolvedRangeInfo(RangeKind::Invalid, Type(), Content, nullptr,
+ ResolvedRangeInfo(RangeKind::Invalid, {nullptr, false}, Content, nullptr,
/*Single entry*/true, /*unhandled error*/false,
OrphanKind::None, {}, {}, {}) {}
void print(llvm::raw_ostream &OS);
+ bool exit() const { return ExitInfo.getInt(); }
+ Type getType() const { return ExitInfo.getPointer(); }
};
class RangeResolver : public SourceEntityWalker {
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index 429aec1..6c4c320 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -73,7 +73,7 @@
StringRef TargetTriple;
/// The Swift compatibility version in use when this module was built.
- StringRef CompatibilityVersion;
+ version::Version CompatibilityVersion;
/// The data blob containing all of the module's identifiers.
StringRef IdentifierData;
diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h
index 76b279b..dbd86e1 100644
--- a/include/swift/Serialization/Validation.h
+++ b/include/swift/Serialization/Validation.h
@@ -71,7 +71,7 @@
StringRef name = {};
StringRef targetTriple = {};
StringRef shortVersion = {};
- StringRef compatibilityVersion = {};
+ version::Version compatibilityVersion = {};
size_t bytes = 0;
Status status = Status::Malformed;
};
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index 93d5a07..fa9a543 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -24,6 +24,7 @@
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/Demangling/ManglingUtils.h"
+#include "swift/Demangling/Demangler.h"
#include "swift/Strings.h"
#include "clang/Basic/CharInfo.h"
#include "clang/AST/Attr.h"
@@ -301,12 +302,18 @@
return finalize();
}
+#ifdef USE_NEW_MANGLING_FOR_OBJC_RUNTIME_NAMES
static bool isPrivate(const NominalTypeDecl *Nominal) {
return Nominal->hasAccessibility() &&
Nominal->getFormalAccess() <= Accessibility::FilePrivate;
}
+#endif
std::string ASTMangler::mangleObjCRuntimeName(const NominalTypeDecl *Nominal) {
+#ifdef USE_NEW_MANGLING_FOR_OBJC_RUNTIME_NAMES
+ // Using the new mangling for ObjC runtime names (except for top-level
+ // classes). This is currently disabled to support old archives.
+ // TODO: re-enable this as we switch to the new mangling for ObjC names.
DeclContext *Ctx = Nominal->getDeclContext();
if (Ctx->isModuleScopeContext() && !isPrivate(Nominal)) {
@@ -338,6 +345,34 @@
beginMangling();
appendAnyGenericType(Nominal);
return finalize();
+#else
+ // Use the old mangling for ObjC runtime names.
+ beginMangling();
+ appendAnyGenericType(Nominal);
+ std::string NewName = finalize();
+ Demangle::Demangler Dem;
+ Demangle::Node *Root = Dem.demangleSymbol(NewName);
+ assert(Root->getKind() == Node::Kind::Global);
+ Node *NomTy = Root->getFirstChild();
+ if (NomTy->getKind() == Node::Kind::Protocol) {
+ // Protocols are actually mangled as protocol lists.
+ Node *PTy = Dem.createNode(Node::Kind::Type);
+ PTy->addChild(NomTy, Dem);
+ Node *TList = Dem.createNode(Node::Kind::TypeList);
+ TList->addChild(PTy, Dem);
+ NomTy = Dem.createNode(Node::Kind::ProtocolList);
+ NomTy->addChild(TList, Dem);
+ }
+ // Add a TypeMangling node at the top
+ Node *Ty = Dem.createNode(Node::Kind::Type);
+ Ty->addChild(NomTy, Dem);
+ Node *TyMangling = Dem.createNode(Node::Kind::TypeMangling);
+ TyMangling->addChild(Ty, Dem);
+ Node *NewGlobal = Dem.createNode(Node::Kind::Global);
+ NewGlobal->addChild(TyMangling, Dem);
+ std::string OldName = mangleNodeOld(NewGlobal);
+ return OldName;
+#endif
}
std::string ASTMangler::mangleTypeAsContextUSR(const NominalTypeDecl *type) {
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index aebcb27..9ca9f7c 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -226,6 +226,11 @@
return isValidVersion ? Optional<Version>(TheVersion) : None;
}
+Version::Version(StringRef VersionString,
+ SourceLoc Loc,
+ DiagnosticEngine *Diags)
+ : Version(*parseVersionString(VersionString, Loc, Diags))
+{}
Version Version::getCurrentCompilerVersion() {
#ifdef SWIFT_COMPILER_VERSION
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 5847118..236f4e0 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -711,22 +711,73 @@
}
bool ClangImporter::canReadPCH(StringRef PCHFilename) {
- return clang::ASTReader::isAcceptableASTFile(PCHFilename,
- Impl.Instance->getFileManager(),
- Impl.Instance->getPCHContainerReader(),
- Impl.Instance->getLangOpts(),
- Impl.Instance->getTargetOpts(),
- Impl.Instance->getPreprocessorOpts(),
- Impl.Instance->getSpecificModuleCachePath());
+ if (!llvm::sys::fs::exists(PCHFilename))
+ return false;
+
+ // FIXME: The following attempts to do an initial ReadAST invocation to verify
+ // the PCH, without affecting the existing CompilerInstance.
+ // Look into combining creating the ASTReader along with verification + update
+ // if necesary, so that we can create and use one ASTReader in the common case
+ // when there is no need for update.
+
+ CompilerInstance &CI = *Impl.Instance;
+ auto clangDiags = CompilerInstance::createDiagnostics(
+ new clang::DiagnosticOptions());
+ clang::SourceManager clangSrcMgr(*clangDiags, CI.getFileManager());
+ auto FID = clangSrcMgr.createFileID(
+ llvm::make_unique<ZeroFilledMemoryBuffer>(1, "<main>"));
+ clangSrcMgr.setMainFileID(FID);
+ clang::Preprocessor PP(CI.getInvocation().getPreprocessorOptsPtr(),
+ *clangDiags,
+ CI.getLangOpts(),
+ clangSrcMgr,
+ CI.getPCMCache(),
+ CI.getPreprocessor().getHeaderSearchInfo(), CI,
+ /*IILookup=*/nullptr,
+ /*OwnsHeaderSearch=*/false);
+ PP.Initialize(CI.getTarget());
+ clang::ASTContext ctx(CI.getLangOpts(), clangSrcMgr,
+ PP.getIdentifierTable(), PP.getSelectorTable(),
+ PP.getBuiltinInfo());
+
+ std::unique_ptr<clang::ASTReader> Reader(new clang::ASTReader(
+ PP, ctx, CI.getPCHContainerReader(),
+ CI.getFrontendOpts().ModuleFileExtensions,
+ CI.getHeaderSearchOpts().Sysroot,
+ /*DisableValidation*/ false,
+ /*AllowPCHWithCompilerErrors*/ false,
+ /*AllowConfigurationMismatch*/ false,
+ /*ValidateSystemInputs*/ true));
+ ctx.InitBuiltinTypes(CI.getTarget());
+
+ auto result = Reader->ReadAST(PCHFilename,
+ clang::serialization::MK_PCH,
+ clang::SourceLocation(),
+ clang::ASTReader::ARR_None);
+ switch (result) {
+ case clang::ASTReader::Success:
+ return true;
+ case clang::ASTReader::Failure:
+ case clang::ASTReader::Missing:
+ case clang::ASTReader::OutOfDate:
+ case clang::ASTReader::VersionMismatch:
+ return false;
+ case clang::ASTReader::ConfigurationMismatch:
+ case clang::ASTReader::HadErrors:
+ assert(0 && "unexpected ASTReader failure for PCH validation");
+ return false;
+ }
}
Optional<std::string>
ClangImporter::getPCHFilename(const ClangImporterOptions &ImporterOptions,
- const std::string &SwiftPCHHash) {
+ StringRef SwiftPCHHash, bool &isExplicit) {
if (llvm::sys::path::extension(ImporterOptions.BridgingHeader)
.endswith(PCH_EXTENSION)) {
+ isExplicit = true;
return ImporterOptions.BridgingHeader;
}
+ isExplicit = false;
const auto &BridgingHeader = ImporterOptions.BridgingHeader;
const auto &PCHOutputDir = ImporterOptions.PrecompiledHeaderOutputDir;
@@ -749,18 +800,27 @@
Optional<std::string>
ClangImporter::getOrCreatePCH(const ClangImporterOptions &ImporterOptions,
- const std::string &SwiftPCHHash) {
- auto PCHFilename = getPCHFilename(ImporterOptions, SwiftPCHHash);
+ StringRef SwiftPCHHash) {
+ bool isExplicit;
+ auto PCHFilename = getPCHFilename(ImporterOptions, SwiftPCHHash,
+ isExplicit);
if (!PCHFilename.hasValue()) {
return None;
}
- if (!canReadPCH(PCHFilename.getValue())) {
+ if (!isExplicit && !canReadPCH(PCHFilename.getValue())) {
SmallString<256> Message;
llvm::raw_svector_ostream OS(Message);
auto Diags = new clang::TextDiagnosticPrinter {
llvm::errs(),
&Impl.Instance->getDiagnosticOpts()
};
+ StringRef parentDir = llvm::sys::path::parent_path(PCHFilename.getValue());
+ std::error_code EC = llvm::sys::fs::create_directories(parentDir);
+ if (EC) {
+ llvm::errs() << "failed to create directory '" << parentDir << "': "
+ << EC.message();
+ return None;
+ }
auto FailedToEmit = emitBridgingPCH(ImporterOptions.BridgingHeader,
PCHFilename.getValue(),
Diags);
diff --git a/lib/Demangling/CMakeLists.txt b/lib/Demangling/CMakeLists.txt
index d92b3e0..8f83b92 100644
--- a/lib/Demangling/CMakeLists.txt
+++ b/lib/Demangling/CMakeLists.txt
@@ -5,6 +5,7 @@
NodeDumper.cpp
NodePrinter.cpp
OldDemangler.cpp
+ OldRemangler.cpp
Punycode.cpp
Remangler.cpp
)
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
new file mode 100644
index 0000000..fc4be9c
--- /dev/null
+++ b/lib/Demangling/OldRemangler.cpp
@@ -0,0 +1,1753 @@
+//===--- OldRemangler.cpp - Old Swift Re-mangler --------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the remangler, which turns a demangling parse
+// tree back into a mangled string. This is useful for tools which
+// want to extract subtrees from mangled strings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/Demangling/Demangler.h"
+#include "swift/Demangling/Punycode.h"
+#include "swift/Strings.h"
+#include <vector>
+#include <cstdio>
+#include <cstdlib>
+#include <unordered_map>
+
+using namespace swift;
+using namespace Demangle;
+
+[[noreturn]]
+static void unreachable(const char *Message) {
+ fprintf(stderr, "fatal error: %s\n", Message);
+ std::abort();
+}
+
+/// Translate the given operator character into its mangled form.
+///
+/// Current operator characters: @/=-+*%<>!&|^~ and the special operator '..'
+static char mangleOperatorChar(char op) {
+ switch (op) {
+ case '&': return 'a'; // 'and'
+ case '@': return 'c'; // 'commercial at sign'
+ case '/': return 'd'; // 'divide'
+ case '=': return 'e'; // 'equal'
+ case '>': return 'g'; // 'greater'
+ case '<': return 'l'; // 'less'
+ case '*': return 'm'; // 'multiply'
+ case '!': return 'n'; // 'negate'
+ case '|': return 'o'; // 'or'
+ case '+': return 'p'; // 'plus'
+ case '?': return 'q'; // 'question'
+ case '%': return 'r'; // 'remainder'
+ case '-': return 's'; // 'subtract'
+ case '~': return 't'; // 'tilde'
+ case '^': return 'x'; // 'xor'
+ case '.': return 'z'; // 'zperiod' (the z is silent)
+ default:
+ return op;
+ }
+}
+
+static bool isNonAscii(StringRef str) {
+ for (unsigned char c : str) {
+ if (c >= 0x80)
+ return true;
+ }
+ return false;
+}
+
+static char mangleOperatorKind(OperatorKind operatorKind) {
+ switch (operatorKind) {
+ case OperatorKind::NotOperator: unreachable("invalid");
+ case OperatorKind::Infix: return 'i';
+ case OperatorKind::Prefix: return 'p';
+ case OperatorKind::Postfix: return 'P';
+ }
+ unreachable("invalid");
+}
+
+static void mangleIdentifier(StringRef ident, OperatorKind operatorKind,
+ bool usePunycode, DemanglerPrinter &out) {
+ std::string punycodeBuf;
+ if (usePunycode) {
+ // If the identifier contains non-ASCII character, we mangle
+ // with an initial X and Punycode the identifier string.
+ if (isNonAscii(ident)) {
+ out << 'X';
+ Punycode::encodePunycodeUTF8(ident, punycodeBuf);
+ ident = punycodeBuf;
+ }
+ }
+
+ // Mangle normal identifiers as
+ // count identifier-char+
+ // where the count is the number of characters in the identifier,
+ // and where individual identifier characters represent themselves.
+ if (operatorKind == OperatorKind::NotOperator) {
+ out << ident.size() << ident;
+ return;
+ }
+
+ // Mangle operator identifiers as
+ // operator ::= 'o' operator-fixity count operator-char+
+ // operator-fixity ::= 'p' // prefix
+ // operator-fixity ::= 'P' // postfix
+ // operator-fixity ::= 'i' // infix
+ // where the count is the number of characters in the operator,
+ // and where the individual operator characters are translated.
+ out << 'o' << mangleOperatorKind(operatorKind);
+
+ // Mangle ASCII operators directly.
+ out << ident.size();
+ for (char ch : ident) {
+ out << mangleOperatorChar(ch);
+ }
+}
+
+void Demangle::mangleIdentifier(const char *data, size_t length,
+ OperatorKind operatorKind,
+ std::string &out, bool usePunycode) {
+ DemanglerPrinter printer;
+ ::mangleIdentifier(StringRef(data, length), operatorKind,
+ usePunycode, printer);
+ out = std::move(printer).str();
+}
+
+namespace {
+ struct DeepHasher {
+ size_t value = 0;
+
+ void combine(size_t newValue) {
+ value = 33 * value + newValue;
+ }
+
+ void hash(Node *node) {
+ combine((size_t) node->getKind());
+ if (node->hasIndex()) {
+ combine(node->getIndex());
+ } else if (node->hasText()) {
+ StringRef text = node->getText();
+ for (char c : text) {
+ combine((unsigned char) c);
+ }
+ }
+ for (const auto &child : *node) {
+ hash(child);
+ }
+ }
+ };
+} // end anonymous namespace
+
+static size_t deepHash(Node *node) {
+ DeepHasher hasher;
+ hasher.hash(node);
+ return hasher.value;
+}
+
+static bool deepEquals(Node *lhs, Node *rhs) {
+ if (lhs->getKind() != rhs->getKind())
+ return false;
+ if (lhs->hasIndex()) {
+ if (!rhs->hasIndex())
+ return false;
+ if (lhs->getIndex() != rhs->getIndex())
+ return false;
+ } else if (lhs->hasText()) {
+ if (!rhs->hasText())
+ return false;
+ if (lhs->getText() != rhs->getText())
+ return false;
+ } else if (rhs->hasIndex() || rhs->hasText()) {
+ return false;
+ }
+
+ if (lhs->getNumChildren() != rhs->getNumChildren())
+ return false;
+
+ for (auto li = lhs->begin(), ri = lhs->begin(), le = lhs->end();
+ li != le; ++li, ++ri) {
+ if (!deepEquals(*li, *ri))
+ return false;
+ }
+
+ return true;
+}
+
+namespace {
+ struct SubstitutionEntry {
+ Node *TheNode;
+ size_t StoredHash;
+
+ // Note that the constructor leaves this uninitialized.
+
+ struct Hasher {
+ size_t operator()(const SubstitutionEntry &entry) const {
+ return entry.StoredHash;
+ }
+ };
+ friend bool operator==(const SubstitutionEntry &lhs,
+ const SubstitutionEntry &rhs) {
+ return (lhs.StoredHash == rhs.StoredHash &&
+ deepEquals(lhs.TheNode, lhs.TheNode));
+ }
+ };
+
+ class Remangler {
+ DemanglerPrinter &Out;
+
+ // We have to cons up temporary nodes sometimes when remangling
+ // nested generics. This factory owns them.
+ NodeFactory Factory;
+
+ std::unordered_map<SubstitutionEntry, unsigned,
+ SubstitutionEntry::Hasher> Substitutions;
+ public:
+ Remangler(DemanglerPrinter &out) : Out(out) {}
+
+ class EntityContext {
+ bool AsContext = false;
+ public:
+ bool isAsContext() const {
+ return AsContext;
+ }
+
+ class ManglingContextRAII {
+ EntityContext &Ctx;
+ bool SavedValue;
+ public:
+ ManglingContextRAII(EntityContext &ctx)
+ : Ctx(ctx), SavedValue(ctx.AsContext) {
+ ctx.AsContext = true;
+ }
+
+ ~ManglingContextRAII() {
+ Ctx.AsContext = SavedValue;
+ }
+ };
+ };
+
+ void mangle(Node *node) {
+ switch (node->getKind()) {
+#define NODE(ID) case Node::Kind::ID: return mangle##ID(node);
+#include "swift/Demangling/DemangleNodes.def"
+ }
+ unreachable("bad demangling tree node");
+ }
+
+ void mangleGenericArgs(Node *node, EntityContext &ctx);
+ void mangleAnyNominalType(Node *node, EntityContext &ctx);
+
+#define NODE(ID) \
+ void mangle##ID(Node *node);
+#define CONTEXT_NODE(ID) \
+ void mangle##ID(Node *node); \
+ void mangle##ID(Node *node, EntityContext &ctx);
+#include "swift/Demangling/DemangleNodes.def"
+
+ void mangleIndex(Node::IndexType index);
+ void mangleIdentifier(StringRef name, OperatorKind operatorKind);
+
+ void mangleChildNodes(Node *node) { mangleNodes(node->begin(), node->end()); }
+ void mangleNodes(Node::iterator i, Node::iterator e) {
+ for (; i != e; ++i) {
+ mangle(*i);
+ }
+ }
+ void mangleSingleChildNode(Node *node) {
+ assert(node->getNumChildren() == 1);
+ mangle(*node->begin());
+ }
+ void mangleChildNode(Node *node, unsigned index) {
+ assert(index < node->getNumChildren());
+ mangle(node->begin()[index]);
+ }
+
+ void mangleSimpleEntity(Node *node, char basicKind, StringRef entityKind,
+ EntityContext &ctx);
+ void mangleNamedEntity(Node *node, char basicKind, StringRef entityKind,
+ EntityContext &ctx);
+ void mangleTypedEntity(Node *node, char basicKind, StringRef entityKind,
+ EntityContext &ctx);
+ void mangleNamedAndTypedEntity(Node *node, char basicKind,
+ StringRef entityKind,
+ EntityContext &ctx);
+ void mangleNominalType(Node *node, char basicKind, EntityContext &ctx);
+
+ void mangleProtocolWithoutPrefix(Node *node);
+ void mangleProtocolListWithoutPrefix(Node *node,
+ Node *additionalProto = nullptr);
+
+ void mangleEntityContext(Node *node, EntityContext &ctx);
+ void mangleEntityType(Node *node, EntityContext &ctx);
+ void mangleEntityGenericType(Node *node, EntityContext &ctx);
+
+ bool trySubstitution(Node *node, SubstitutionEntry &entry);
+ bool mangleStandardSubstitution(Node *node);
+ void addSubstitution(const SubstitutionEntry &entry);
+ void resetSubstitutions();
+
+ void mangleDependentGenericParamIndex(Node *node);
+ void mangleConstrainedType(Node *node);
+ };
+} // end anonymous namespace
+
+#define NODE(ID)
+#define CONTEXT_NODE(ID) \
+void Remangler::mangle##ID(Node *node) { \
+ EntityContext ctx; \
+ mangle##ID(node, ctx); \
+}
+#include "swift/Demangling/DemangleNodes.def"
+
+/// Reset the currently-active set of substitutions. This is useful
+/// when part of the mangling is done independently, e.g. when an
+/// optimization pass modifies a pass.
+void Remangler::resetSubstitutions() {
+ Substitutions.clear();
+}
+
+bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry) {
+ if (mangleStandardSubstitution(node))
+ return true;
+
+ // Go ahead and initialize the substitution entry.
+ entry.TheNode = node;
+ entry.StoredHash = deepHash(node);
+
+ auto it = Substitutions.find(entry);
+ if (it == Substitutions.end())
+ return false;
+
+ Out << 'S';
+ mangleIndex(it->second);
+ return true;
+}
+
+static bool isInSwiftModule(Node *node) {
+ Node *context = node->getFirstChild();
+ return (context->getKind() == Node::Kind::Module &&
+ context->getText() == STDLIB_NAME);
+};
+
+bool Remangler::mangleStandardSubstitution(Node *node) {
+ // Look for known substitutions.
+ switch (node->getKind()) {
+#define SUCCESS_IF_IS(VALUE, EXPECTED, SUBSTITUTION) \
+ do { \
+ if ((VALUE) == (EXPECTED)) { \
+ Out << SUBSTITUTION; \
+ return true; \
+ } \
+ } while (0)
+#define SUCCESS_IF_TEXT_IS(EXPECTED, SUBSTITUTION) \
+ SUCCESS_IF_IS(node->getText(), EXPECTED, SUBSTITUTION)
+#define SUCCESS_IF_DECLNAME_IS(EXPECTED, SUBSTITUTION) \
+ SUCCESS_IF_IS(node->getChild(1)->getText(), EXPECTED, SUBSTITUTION)
+
+ case Node::Kind::Module:
+ SUCCESS_IF_TEXT_IS(STDLIB_NAME, "s");
+ SUCCESS_IF_TEXT_IS(MANGLING_MODULE_OBJC, "So");
+ SUCCESS_IF_TEXT_IS(MANGLING_MODULE_CLANG_IMPORTER, "SC");
+ break;
+ case Node::Kind::Structure:
+ if (isInSwiftModule(node)) {
+ SUCCESS_IF_DECLNAME_IS("Array", "Sa");
+ SUCCESS_IF_DECLNAME_IS("Bool", "Sb");
+ SUCCESS_IF_DECLNAME_IS("UnicodeScalar", "Sc");
+ SUCCESS_IF_DECLNAME_IS("Double", "Sd");
+ SUCCESS_IF_DECLNAME_IS("Float", "Sf");
+ SUCCESS_IF_DECLNAME_IS("Int", "Si");
+ SUCCESS_IF_DECLNAME_IS("UnsafeRawPointer", "SV");
+ SUCCESS_IF_DECLNAME_IS("UnsafeMutableRawPointer", "Sv");
+ SUCCESS_IF_DECLNAME_IS("UnsafePointer", "SP");
+ SUCCESS_IF_DECLNAME_IS("UnsafeMutablePointer", "Sp");
+ SUCCESS_IF_DECLNAME_IS("UnsafeBufferPointer", "SR");
+ SUCCESS_IF_DECLNAME_IS("UnsafeMutableBufferPointer", "Sr");
+ SUCCESS_IF_DECLNAME_IS("String", "SS");
+ SUCCESS_IF_DECLNAME_IS("UInt", "Su");
+ }
+ break;
+ case Node::Kind::Enum:
+ if (isInSwiftModule(node)) {
+ SUCCESS_IF_DECLNAME_IS("Optional", "Sq");
+ SUCCESS_IF_DECLNAME_IS("ImplicitlyUnwrappedOptional", "SQ");
+ }
+ break;
+
+ default:
+ break;
+
+#undef SUCCESS_IF_DECLNAME_IS
+#undef SUCCESS_IF_TEXT_IS
+#undef SUCCESS_IF_IS
+ }
+ return false;
+}
+
+void Remangler::addSubstitution(const SubstitutionEntry &entry) {
+ auto result = Substitutions.insert({entry, Substitutions.size()});
+ assert(result.second);
+ (void) result;
+}
+
+void Remangler::mangleIdentifier(Node *node) {
+ mangleIdentifier(node->getText(), OperatorKind::NotOperator);
+}
+void Remangler::manglePrefixOperator(Node *node) {
+ mangleIdentifier(node->getText(), OperatorKind::Prefix);
+}
+void Remangler::manglePostfixOperator(Node *node) {
+ mangleIdentifier(node->getText(), OperatorKind::Postfix);
+}
+void Remangler::mangleInfixOperator(Node *node) {
+ mangleIdentifier(node->getText(), OperatorKind::Infix);
+}
+void Remangler::mangleIdentifier(StringRef ident, OperatorKind operatorKind) {
+ ::mangleIdentifier(ident, operatorKind, /*usePunycode*/ false, Out);
+}
+
+void Remangler::mangleNumber(Node *node) {
+ mangleIndex(node->getIndex());
+}
+void Remangler::mangleIndex(Node::IndexType value) {
+ if (value == 0) {
+ Out << '_';
+ } else {
+ Out << (value - 1) << '_';
+ }
+}
+
+void Remangler::mangleGlobal(Node *node) {
+ Out << "_T";
+ mangleChildNodes(node);
+}
+
+void Remangler::mangleSuffix(Node *node) {
+ // Just add the suffix back on.
+ Out << node->getText();
+}
+
+void Remangler::mangleGenericSpecialization(Node *node) {
+ Out << "TSg";
+ mangleChildNodes(node); // GenericSpecializationParams
+
+ // Specializations are just prepended to already-mangled names.
+ resetSubstitutions();
+
+ // Start another mangled name.
+ Out << "__T";
+}
+void Remangler::mangleGenericSpecializationNotReAbstracted(Node *node) {
+ Out << "TSr";
+ mangleChildNodes(node); // GenericSpecializationParams
+
+ // Specializations are just prepended to already-mangled names.
+ resetSubstitutions();
+
+ // Start another mangled name.
+ Out << "__T";
+}
+
+void Remangler::mangleGenericPartialSpecialization(Node *node) {
+ unreachable("todo");
+}
+
+void Remangler::mangleGenericPartialSpecializationNotReAbstracted(Node *node) {
+ unreachable("todo");
+}
+
+void Remangler::mangleGenericSpecializationParam(Node *node) {
+ // Should be a type followed by a series of protocol conformances.
+ mangleChildNodes(node);
+ Out << '_';
+}
+
+void Remangler::mangleFunctionSignatureSpecialization(Node *node) {
+ Out << "TSf";
+ mangleChildNodes(node); // FunctionSignatureSpecializationParams
+
+ // Specializations are just prepended to already-mangled names.
+ resetSubstitutions();
+
+ // Start another mangled name.
+ Out << "__T";
+}
+
+void Remangler::mangleSpecializationPassID(Node *node) {
+ Out << node->getIndex();
+}
+
+void Remangler::mangleSpecializationIsFragile(Node *node) {
+ Out << "q";
+}
+
+void Remangler::mangleFunctionSignatureSpecializationParam(Node *node) {
+ if (!node->hasChildren()) {
+ Out << "n_";
+ return;
+ }
+
+ // The first child is always a kind that specifies the type of param that we
+ // have.
+ NodePointer firstChild = node->getChild(0);
+ unsigned kindValue = firstChild->getIndex();
+ auto kind = FunctionSigSpecializationParamKind(kindValue);
+
+ switch (kind) {
+ case FunctionSigSpecializationParamKind::ConstantPropFunction:
+ Out << "cpfr";
+ mangleIdentifier(node->getChild(1));
+ Out << '_';
+ return;
+ case FunctionSigSpecializationParamKind::ConstantPropGlobal:
+ Out << "cpg";
+ mangleIdentifier(node->getChild(1));
+ Out << '_';
+ return;
+ case FunctionSigSpecializationParamKind::ConstantPropInteger:
+ Out << "cpi" << node->getChild(1)->getText() << '_';
+ return;
+ case FunctionSigSpecializationParamKind::ConstantPropFloat:
+ Out << "cpfl" << node->getChild(1)->getText() << '_';
+ return;
+ case FunctionSigSpecializationParamKind::ConstantPropString: {
+ Out << "cpse";
+ StringRef encodingStr = node->getChild(1)->getText();
+ if (encodingStr == "u8")
+ Out << '0';
+ else if (encodingStr == "u16")
+ Out << '1';
+ else
+ unreachable("Unknown encoding");
+ Out << 'v';
+ mangleIdentifier(node->getChild(2));
+ Out << '_';
+ return;
+ }
+ case FunctionSigSpecializationParamKind::ClosureProp:
+ Out << "cl";
+ mangleIdentifier(node->getChild(1));
+ for (unsigned i = 2, e = node->getNumChildren(); i != e; ++i) {
+ mangleType(node->getChild(i));
+ }
+ Out << '_';
+ return;
+ case FunctionSigSpecializationParamKind::BoxToValue:
+ Out << "i_";
+ return;
+ case FunctionSigSpecializationParamKind::BoxToStack:
+ Out << "k_";
+ return;
+ default:
+ if (kindValue &
+ unsigned(FunctionSigSpecializationParamKind::Dead))
+ Out << 'd';
+ if (kindValue &
+ unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed))
+ Out << 'g';
+ if (kindValue & unsigned(FunctionSigSpecializationParamKind::SROA))
+ Out << 's';
+ Out << '_';
+ return;
+ }
+}
+
+void Remangler::mangleFunctionSignatureSpecializationParamPayload(Node *node) {
+ // This should never be called since mangling parameter payloads require
+ // knowing what the parameter kind is.
+ unreachable("This should never be called");
+}
+
+void Remangler::mangleFunctionSignatureSpecializationParamKind(Node *node) {
+ // This should never be called since mangling parameter kinds have influence
+ // on the payloads.
+ unreachable("This should never be called");
+}
+
+void Remangler::mangleProtocolConformance(Node *node) {
+ // type, protocol name, context
+ assert(node->getNumChildren() == 3);
+ mangleChildNode(node, 0);
+ mangleProtocolWithoutPrefix(node->begin()[1]);
+ mangleChildNode(node, 2);
+}
+
+void Remangler::mangleObjCAttribute(Node *node) {
+ Out << "To";
+}
+
+void Remangler::mangleNonObjCAttribute(Node *node) {
+ Out << "TO";
+}
+
+void Remangler::mangleDirectMethodReferenceAttribute(Node *node) {
+ Out << "Td";
+}
+
+void Remangler::mangleDynamicAttribute(Node *node) {
+ Out << "TD";
+}
+
+void Remangler::mangleVTableAttribute(Node *node) {
+ Out << "TV";
+}
+
+void Remangler::mangleGenericTypeMetadataPattern(Node *node) {
+ Out << "MP";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleTypeMetadataAccessFunction(Node *node) {
+ Out << "Ma";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleTypeMetadataLazyCache(Node *node) {
+ Out << "ML";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleMetaclass(Node *node) {
+ Out << "Mm";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleNominalTypeDescriptor(Node *node) {
+ Out << "Mn";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleTypeMetadata(Node *node) {
+ Out << "M";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleFullTypeMetadata(Node *node) {
+ Out << "Mf";
+ mangleChildNodes(node); // type
+}
+
+void Remangler::mangleProtocolDescriptor(Node *node) {
+ Out << "Mp";
+ mangleProtocolWithoutPrefix(node->begin()[0]);
+}
+
+void Remangler::manglePartialApplyForwarder(Node *node) {
+ Out << "PA__T";
+ mangleSingleChildNode(node); // global
+}
+
+void Remangler::manglePartialApplyObjCForwarder(Node *node) {
+ Out << "PAo__T";
+ mangleSingleChildNode(node); // global
+}
+
+void Remangler::mangleDirectness(Node *node) {
+ auto getChar = [](Directness d) -> char {
+ switch (d) {
+ case Directness::Direct: return 'd';
+ case Directness::Indirect: return 'i';
+ }
+ unreachable("bad directness kind");
+ };
+ Out << getChar(Directness(node->getIndex()));
+}
+
+void Remangler::mangleValueWitness(Node *node) {
+ const char *Code = nullptr;
+ switch (ValueWitnessKind(node->getIndex())) {
+#define VALUE_WITNESS(MANGLING, NAME) \
+ case ValueWitnessKind::NAME: Code = #MANGLING; break;
+#include "swift/Demangling/ValueWitnessMangling.def"
+ }
+ Out << 'w' << Code;
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleValueWitnessTable(Node *node) {
+ Out << "WV";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleThrowsAnnotation(Node *node) {
+ Out << "z";
+}
+
+void Remangler::mangleFieldOffset(Node *node) {
+ Out << "Wv";
+ mangleChildNodes(node); // directness, entity
+}
+
+void Remangler::mangleProtocolWitnessTable(Node *node) {
+ Out << "WP";
+ mangleSingleChildNode(node); // protocol conformance
+}
+
+void Remangler::mangleGenericProtocolWitnessTable(Node *node) {
+ Out << "WG";
+ mangleSingleChildNode(node); // protocol conformance
+}
+
+void Remangler::mangleGenericProtocolWitnessTableInstantiationFunction(
+ Node *node) {
+ Out << "WI";
+ mangleSingleChildNode(node); // protocol conformance
+}
+
+void Remangler::mangleProtocolWitnessTableAccessor(Node *node) {
+ Out << "Wa";
+ mangleSingleChildNode(node); // protocol conformance
+}
+
+void Remangler::mangleLazyProtocolWitnessTableAccessor(Node *node) {
+ Out << "Wl";
+ mangleChildNodes(node); // type, protocol conformance
+}
+
+void Remangler::mangleLazyProtocolWitnessTableCacheVariable(Node *node) {
+ Out << "WL";
+ mangleChildNodes(node); // type, protocol conformance
+}
+
+void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) {
+ Out << "Wt";
+ mangleChildNodes(node); // protocol conformance, identifier
+}
+
+void Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node) {
+ Out << "WT";
+ assert(node->getNumChildren() == 3);
+ mangleChildNode(node, 0); // protocol conformance
+ mangleChildNode(node, 1); // identifier
+ mangleProtocolWithoutPrefix(node->begin()[2]); // type
+}
+
+void Remangler::mangleReabstractionThunkHelper(Node *node) {
+ Out << "TR";
+ if (node->getNumChildren() == 3) Out << 'G';
+ mangleChildNodes(node); // generic signature?, type, type
+}
+
+void Remangler::mangleReabstractionThunk(Node *node) {
+ Out << "Tr";
+ if (node->getNumChildren() == 3) Out << 'G';
+ mangleChildNodes(node); // generic signature?, type, type
+}
+
+void Remangler::mangleProtocolWitness(Node *node) {
+ Out << "TW";
+ mangleChildNodes(node); // protocol conformance, entity
+}
+
+void Remangler::mangleFunction(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "", ctx);
+}
+
+void Remangler::mangleVariable(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'v', "", ctx);
+}
+
+void Remangler::mangleSubscript(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'i', "", ctx);
+}
+
+void Remangler::mangleInitializer(Node *node, EntityContext &ctx) {
+ mangleSimpleEntity(node, 'I', "i", ctx);
+}
+
+void Remangler::mangleDefaultArgumentInitializer(Node *node,
+ EntityContext &ctx) {
+ mangleNamedEntity(node, 'I', "A", ctx);
+}
+
+void Remangler::mangleDeallocator(Node *node, EntityContext &ctx) {
+ mangleSimpleEntity(node, 'F', "D", ctx);
+}
+
+void Remangler::mangleDestructor(Node *node, EntityContext &ctx) {
+ mangleSimpleEntity(node, 'F', "d", ctx);
+}
+
+void Remangler::mangleAllocator(Node *node, EntityContext &ctx) {
+ mangleTypedEntity(node, 'F', "C", ctx);
+}
+
+void Remangler::mangleConstructor(Node *node, EntityContext &ctx) {
+ mangleTypedEntity(node, 'F', "c", ctx);
+}
+
+void Remangler::mangleIVarInitializer(Node *node, EntityContext &ctx) {
+ mangleSimpleEntity(node, 'F', "e", ctx);
+}
+
+void Remangler::mangleIVarDestroyer(Node *node, EntityContext &ctx) {
+ mangleSimpleEntity(node, 'F', "E", ctx);
+}
+
+void Remangler::mangleGetter(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "g", ctx);
+}
+
+void Remangler::mangleGlobalGetter(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "G", ctx);
+}
+
+void Remangler::mangleSetter(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "s", ctx);
+}
+
+void Remangler::mangleMaterializeForSet(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "m", ctx);
+}
+
+void Remangler::mangleWillSet(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "w", ctx);
+}
+
+void Remangler::mangleDidSet(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "W", ctx);
+}
+
+void Remangler::mangleOwningMutableAddressor(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "aO", ctx);
+}
+
+void Remangler::mangleNativeOwningMutableAddressor(Node *node,
+ EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "ao", ctx);
+}
+
+void Remangler::mangleNativePinningMutableAddressor(Node *node,
+ EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "ap", ctx);
+}
+
+void Remangler::mangleUnsafeMutableAddressor(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "au", ctx);
+}
+
+void Remangler::mangleOwningAddressor(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "lO", ctx);
+}
+
+void Remangler::mangleNativeOwningAddressor(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "lo", ctx);
+}
+
+void Remangler::mangleNativePinningAddressor(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "lp", ctx);
+}
+
+void Remangler::mangleUnsafeAddressor(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "lu", ctx);
+}
+
+void Remangler::mangleExplicitClosure(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "U", ctx); // name is index
+}
+
+void Remangler::mangleImplicitClosure(Node *node, EntityContext &ctx) {
+ mangleNamedAndTypedEntity(node, 'F', "u", ctx); // name is index
+}
+
+void Remangler::mangleStatic(Node *node, EntityContext &ctx) {
+ Out << 'Z';
+ mangleEntityContext(node->getChild(0), ctx);
+}
+
+void Remangler::mangleSimpleEntity(Node *node, char basicKind,
+ StringRef entityKind,
+ EntityContext &ctx) {
+ assert(node->getNumChildren() == 1);
+ Out << basicKind;
+ mangleEntityContext(node->begin()[0], ctx);
+ Out << entityKind;
+}
+
+void Remangler::mangleNamedEntity(Node *node, char basicKind,
+ StringRef entityKind,
+ EntityContext &ctx) {
+ assert(node->getNumChildren() == 2);
+ if (basicKind != '\0') Out << basicKind;
+ mangleEntityContext(node->begin()[0], ctx);
+ Out << entityKind;
+ mangleChildNode(node, 1); // decl name / index
+}
+
+void Remangler::mangleTypedEntity(Node *node, char basicKind,
+ StringRef entityKind,
+ EntityContext &ctx) {
+ assert(node->getNumChildren() == 2);
+ Out << basicKind;
+ mangleEntityContext(node->begin()[0], ctx);
+ Out << entityKind;
+ mangleEntityType(node->begin()[1], ctx);
+}
+
+void Remangler::mangleNamedAndTypedEntity(Node *node, char basicKind,
+ StringRef entityKind,
+ EntityContext &ctx) {
+ assert(node->getNumChildren() == 3);
+ Out << basicKind;
+ mangleEntityContext(node->begin()[0], ctx);
+ Out << entityKind;
+ mangleChildNode(node, 1); // decl name / index
+ mangleEntityType(node->begin()[2], ctx);
+}
+
+void Remangler::mangleEntityContext(Node *node, EntityContext &ctx) {
+ // Remember that we're mangling a context.
+ EntityContext::ManglingContextRAII raii(ctx);
+
+ switch (node->getKind()) {
+#define NODE(ID) \
+ case Node::Kind::ID:
+#define CONTEXT_NODE(ID)
+#include "swift/Demangling/DemangleNodes.def"
+ unreachable("not a context node");
+
+#define NODE(ID)
+#define CONTEXT_NODE(ID) \
+ case Node::Kind::ID: \
+ return mangle##ID(node, ctx);
+#include "swift/Demangling/DemangleNodes.def"
+ }
+ unreachable("bad node kind");
+}
+
+void Remangler::mangleEntityType(Node *node, EntityContext &ctx) {
+ assert(node->getKind() == Node::Kind::Type);
+ assert(node->getNumChildren() == 1);
+ node = node->begin()[0];
+
+ // Expand certain kinds of type within the entity context.
+ switch (node->getKind()) {
+ case Node::Kind::FunctionType:
+ case Node::Kind::UncurriedFunctionType: {
+ Out << (node->getKind() == Node::Kind::FunctionType ? 'F' : 'f');
+ unsigned inputIndex = node->getNumChildren() - 2;
+ assert(inputIndex <= 1);
+ for (unsigned i = 0; i <= inputIndex; ++i)
+ mangle(node->begin()[i]);
+ auto returnType = node->begin()[inputIndex+1];
+ assert(returnType->getKind() == Node::Kind::ReturnType);
+ assert(returnType->getNumChildren() == 1);
+ mangleEntityType(returnType->begin()[0], ctx);
+ return;
+ }
+ default:
+ mangle(node);
+ return;
+ }
+}
+
+void Remangler::mangleLocalDeclName(Node *node) {
+ Out << 'L';
+ mangleChildNodes(node); // index, identifier
+}
+
+void Remangler::manglePrivateDeclName(Node *node) {
+ Out << 'P';
+ mangleChildNodes(node); // identifier, identifier
+}
+
+void Remangler::mangleTypeMangling(Node *node) {
+ Out << 't';
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleType(Node *node) {
+ mangleSingleChildNode(node);
+}
+
+template <size_t N>
+static bool stripPrefix(StringRef &string, const char (&data)[N]) {
+ constexpr size_t prefixLength = N - 1;
+ if (!string.startswith(StringRef(data, prefixLength)))
+ return false;
+ string = string.drop_front(prefixLength);
+ return true;
+}
+
+void Remangler::mangleBuiltinTypeName(Node *node) {
+ Out << 'B';
+ StringRef text = node->getText();
+
+ if (text == "Builtin.BridgeObject") {
+ Out << 'b';
+ } else if (text == "Builtin.UnsafeValueBuffer") {
+ Out << 'B';
+ } else if (text == "Builtin.UnknownObject") {
+ Out << 'O';
+ } else if (text == "Builtin.NativeObject") {
+ Out << 'o';
+ } else if (text == "Builtin.RawPointer") {
+ Out << 'p';
+ } else if (text == "Builtin.Word") {
+ Out << 'w';
+ } else if (stripPrefix(text, "Builtin.Int")) {
+ Out << 'i' << text << '_';
+ } else if (stripPrefix(text, "Builtin.Float")) {
+ Out << 'f' << text << '_';
+ } else if (stripPrefix(text, "Builtin.Vec")) {
+ auto split = text.split('x');
+ Out << 'v' << split.first << 'B';
+ if (split.second == "RawPointer") {
+ Out << 'p';
+ } else if (stripPrefix(split.second, "Float")) {
+ Out << 'f' << split.second << '_';
+ } else if (stripPrefix(split.second, "Int")) {
+ Out << 'i' << split.second << '_';
+ } else {
+ unreachable("unexpected builtin vector type");
+ }
+ } else {
+ unreachable("unexpected builtin type");
+ }
+}
+
+void Remangler::mangleTypeAlias(Node *node, EntityContext &ctx) {
+ SubstitutionEntry entry;
+ if (trySubstitution(node, entry)) return;
+ Out << 'a';
+ mangleChildNodes(node); // context, identifier
+ addSubstitution(entry);
+}
+
+void Remangler::mangleFunctionType(Node *node) {
+ Out << 'F';
+ mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleUncurriedFunctionType(Node *node) {
+ Out << 'f';
+ mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleObjCBlock(Node *node) {
+ Out << 'b';
+ mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleCFunctionPointer(Node *node) {
+ Out << 'c';
+ mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleAutoClosureType(Node *node) {
+ Out << 'K';
+ mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleThinFunctionType(Node *node) {
+ Out << "Xf";
+ mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleArgumentTuple(Node *node) {
+ mangleSingleChildNode(node);
+}
+
+void Remangler::mangleReturnType(Node *node) {
+ mangleSingleChildNode(node);
+}
+
+void Remangler::mangleImplFunctionType(Node *node) {
+ Out << "XF";
+ auto i = node->begin(), e = node->end();
+ if (i != e && (*i)->getKind() == Node::Kind::ImplConvention) {
+ StringRef text = (*i)->getText();
+ i++;
+ if (text == "@callee_unowned") {
+ Out << 'd';
+ } else if (text == "@callee_guaranteed") {
+ Out << 'g';
+ } else if (text == "@callee_owned") {
+ Out << 'o';
+ } else {
+ unreachable("bad callee convention");
+ }
+ } else {
+ Out << 't';
+ }
+ for (; i != e &&
+ (*i)->getKind() == Node::Kind::ImplFunctionAttribute; ++i) {
+ mangle(*i); // impl function attribute
+ }
+ if (i != e &&
+ ((*i)->getKind() == Node::Kind::DependentGenericSignature ||
+ (*i)->getKind() == Node::Kind::DependentPseudogenericSignature)) {
+ Out << ((*i)->getKind() == Node::Kind::DependentGenericSignature
+ ? 'G' : 'g');
+ mangleDependentGenericSignature((*i));
+ i++;
+ }
+ Out << '_';
+ for (; i != e && (*i)->getKind() == Node::Kind::ImplParameter; ++i) {
+ mangleImplParameter(*i);
+ }
+ Out << '_';
+ mangleNodes(i, e); // impl results
+ Out << '_';
+}
+
+void Remangler::mangleImplFunctionAttribute(Node *node) {
+ StringRef text = node->getText();
+ if (text == "@convention(block)") {
+ Out << "Cb";
+ } else if (text == "@convention(c)") {
+ Out << "Cc";
+ } else if (text == "@convention(method)") {
+ Out << "Cm";
+ } else if (text == "@convention(objc_method)") {
+ Out << "CO";
+ } else if (text == "@convention(witness_method)") {
+ Out << "Cw";
+ } else {
+ unreachable("bad impl-function-attribute");
+ }
+}
+
+void Remangler::mangleImplParameter(Node *node) {
+ assert(node->getNumChildren() == 2);
+ mangleChildNodes(node); // impl convention, type
+}
+
+void Remangler::mangleImplErrorResult(Node *node) {
+ assert(node->getNumChildren() == 2);
+ Out << 'z';
+ mangleChildNodes(node); // impl convention, type
+}
+
+void Remangler::mangleImplResult(Node *node) {
+ assert(node->getNumChildren() == 2);
+ mangleChildNodes(node); // impl convention, type
+}
+
+void Remangler::mangleImplConvention(Node *node) {
+ assert(node->getKind() == Node::Kind::ImplConvention);
+ StringRef text = node->getText();
+ if (text == "@autoreleased") {
+ Out << 'a';
+ } else if (text == "@unowned") {
+ Out << 'd';
+ } else if (text == "@unowned_inner_pointer") {
+ Out << 'D'; // only in results
+ } else if (text == "@guaranteed") {
+ Out << 'g';
+ } else if (text == "@deallocating") {
+ Out << 'e';
+ } else if (text == "@in") {
+ Out << 'i'; // only in parameters
+ } else if (text == "@out") {
+ Out << 'i'; // only in results
+ } else if (text == "@inout") {
+ Out << 'l';
+ } else if (text == "@owned") {
+ Out << 'o';
+ } else {
+ unreachable("invalid impl convention");
+ }
+}
+
+void Remangler::mangleDynamicSelf(Node *node) {
+ Out << 'D';
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleErrorType(Node *node) {
+ Out << "ERR";
+}
+
+void Remangler::mangleSILBoxType(Node *node) {
+ Out << 'X' << 'b';
+ mangleSingleChildNode(node);
+}
+
+void Remangler::mangleMetatype(Node *node) {
+ if (node->getNumChildren() == 1) {
+ Out << 'M';
+ mangleSingleChildNode(node); // type
+ } else {
+ assert(node->getNumChildren() == 2);
+ Out << "XM";
+ mangleChildNodes(node); // metatype representation, type
+ }
+}
+
+void Remangler::mangleExistentialMetatype(Node *node) {
+ if (node->getNumChildren() == 1) {
+ Out << "PM";
+ mangleSingleChildNode(node); // type
+ } else {
+ assert(node->getNumChildren() == 2);
+ Out << "XPM";
+ mangleChildNodes(node); // metatype representation, type
+ }
+}
+
+void Remangler::mangleMetatypeRepresentation(Node *node) {
+ StringRef text = node->getText();
+ if (text == "@thin") {
+ Out << 't';
+ } else if (text == "@thick") {
+ Out << 'T';
+ } else if (text == "@objc_metatype") {
+ Out << 'o';
+ } else {
+ unreachable("bad metatype representation");
+ }
+}
+
+void Remangler::mangleProtocolList(Node *node) {
+ // In its usual use as a type, this gets a prefix 'P'.
+ Out << 'P';
+ mangleProtocolListWithoutPrefix(node);
+}
+
+void Remangler::mangleProtocolListWithoutPrefix(Node *node,
+ Node *additionalProto) {
+ assert(node->getKind() == Node::Kind::ProtocolList);
+ assert(node->getNumChildren() == 1);
+ auto typeList = node->begin()[0];
+ assert(typeList->getKind() == Node::Kind::TypeList);
+ for (auto &child : *typeList) {
+ mangleProtocolWithoutPrefix(child);
+ }
+ if (additionalProto) {
+ mangleProtocolWithoutPrefix(additionalProto);
+ }
+ Out << '_';
+}
+
+void Remangler::mangleUnowned(Node *node) {
+ Out << "Xo";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleUnmanaged(Node *node) {
+ Out << "Xu";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleWeak(Node *node) {
+ Out << "Xw";
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleInOut(Node *node) {
+ Out << 'R';
+ mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleTuple(Node *node) {
+ size_t NumElems = node->getNumChildren();
+ if (NumElems > 0 &&
+ node->getChild(NumElems - 1)->getFirstChild()->getKind() ==
+ Node::Kind::VariadicMarker) {
+ Out << 't';
+ } else {
+ Out << 'T';
+ }
+ mangleChildNodes(node); // tuple elements
+ Out << '_';
+}
+
+void Remangler::mangleTupleElement(Node *node) {
+ mangleChildNodes(node); // tuple element name?, type
+}
+
+void Remangler::mangleTupleElementName(Node *node) {
+ mangleIdentifier(node->getText(), OperatorKind::NotOperator);
+}
+
+void Remangler::mangleDependentGenericType(Node *node) {
+ Out << 'u';
+ mangleChildNodes(node); // generic signature, type
+}
+
+void Remangler::mangleDependentPseudogenericSignature(Node *node) {
+ mangleDependentGenericSignature(node);
+}
+
+void Remangler::mangleDependentGenericSignature(Node *node) {
+ auto i = node->begin(), e = node->end();
+
+ // If there's only one generic param, mangle nothing.
+ if (node->getNumChildren() >= 1
+ && node->getChild(0)->getKind() == Node::Kind::DependentGenericParamCount
+ && node->getChild(0)->getIndex() == 1
+ && (node->getNumChildren() == 1
+ || node->getChild(1)->getKind() != Node::Kind::DependentGenericParamCount))
+ {
+ ++i;
+ goto mangle_requirements;
+ }
+
+ // Remangle generic params.
+ for (; i != e &&
+ (*i)->getKind() == Node::Kind::DependentGenericParamCount; ++i) {
+ auto count = *i;
+ if (count->getIndex() > 0)
+ mangleIndex(count->getIndex() - 1);
+ else
+ Out << 'z';
+ }
+
+mangle_requirements:
+ if (i == e) { // no generic requirements
+ Out << 'r';
+ return;
+ }
+
+ Out << 'R';
+ mangleNodes(i, e); // generic requirements
+ Out << 'r';
+}
+
+void Remangler::mangleDependentGenericParamCount(Node *node) {
+ unreachable("handled inline in DependentGenericSignature");
+}
+
+void Remangler::mangleDependentGenericConformanceRequirement(Node *node) {
+ mangleConstrainedType(node->getChild(0));
+ // If the constraint represents a protocol, use the shorter mangling.
+ if (node->getNumChildren() == 2
+ && node->getChild(1)->getKind() == Node::Kind::Type
+ && node->getChild(1)->getNumChildren() == 1
+ && node->getChild(1)->getChild(0)->getKind() == Node::Kind::Protocol) {
+ mangleProtocolWithoutPrefix(node->getChild(1)->getChild(0));
+ return;
+ }
+
+ mangle(node->getChild(1));
+}
+
+void Remangler::mangleDependentGenericSameTypeRequirement(Node *node) {
+ mangleConstrainedType(node->getChild(0));
+ Out << 'z';
+ mangle(node->getChild(1));
+}
+
+void Remangler::mangleDependentGenericLayoutRequirement(Node *node) {
+ mangleConstrainedType(node->getChild(0));
+ Out << 'l';
+ auto id = node->getChild(1)->getText();
+ auto size = -1;
+ if (node->getNumChildren() > 2) {
+ size = node->getChild(2)->getIndex();
+ }
+ int alignment = -1;
+ if (node->getNumChildren() > 3) {
+ alignment = node->getChild(3)->getIndex();
+ }
+ Out << id;
+ if (size >= 0)
+ Out << size;
+ if (alignment >= 0) {
+ Out << "_" << alignment;
+ }
+}
+
+void Remangler::mangleConstrainedType(Node *node) {
+ if (node->getFirstChild()->getKind()
+ == Node::Kind::DependentGenericParamType) {
+ // Can be mangled without an introducer.
+ mangleDependentGenericParamIndex(node->getFirstChild());
+ } else {
+ mangle(node);
+ }
+}
+
+void Remangler::mangleAssociatedType(Node *node) {
+ if (node->hasChildren()) {
+ assert(node->getNumChildren() == 1);
+ mangleProtocolListWithoutPrefix(*node->begin());
+ } else {
+ Out << '_';
+ }
+}
+
+void Remangler::mangleQualifiedArchetype(Node *node) {
+ Out << "Qq";
+ mangleChildNodes(node); // index, declcontext
+}
+
+void Remangler::mangleDeclContext(Node *node) {
+ mangleSingleChildNode(node);
+}
+
+void Remangler::mangleExtension(Node *node, EntityContext &ctx) {
+ assert(node->getNumChildren() == 2 || node->getNumChildren() == 3);
+ if (node->getNumChildren() == 3) {
+ Out << 'e';
+ } else {
+ Out << 'E';
+ }
+ mangleEntityContext(node->begin()[0], ctx); // module
+ if (node->getNumChildren() == 3) {
+ mangleDependentGenericSignature(node->begin()[2]); // generic sig
+ }
+ mangleEntityContext(node->begin()[1], ctx); // context
+}
+
+void Remangler::mangleModule(Node *node, EntityContext &ctx) {
+ SubstitutionEntry entry;
+ if (trySubstitution(node, entry)) return;
+
+ // Module types get an M prefix, but module contexts don't.
+ if (!ctx.isAsContext()) Out << 'M';
+ mangleIdentifier(node->getText(), OperatorKind::NotOperator);
+ addSubstitution(entry);
+}
+
+void Remangler::mangleAssociatedTypeRef(Node *node) {
+ SubstitutionEntry entry;
+ if (trySubstitution(node, entry)) return;
+ Out << "Q";
+ mangleChildNodes(node); // type, identifier
+ addSubstitution(entry);
+}
+
+void Remangler::mangleDependentMemberType(Node *node) {
+ std::vector<Node *> members;
+ Node *base = node;
+ do {
+ members.push_back(base);
+ base = base->getFirstChild()->getFirstChild();
+ } while (base->getKind() == Node::Kind::DependentMemberType);
+
+ assert(base->getKind() == Node::Kind::DependentGenericParamType
+ && "dependent members not based on a generic param are non-canonical"
+ " and shouldn't need remangling");
+ assert(members.size() >= 1);
+ if (members.size() == 1) {
+ Out << 'w';
+ mangleDependentGenericParamIndex(base);
+ mangle(members[0]->getChild(1));
+ } else {
+ Out << 'W';
+ mangleDependentGenericParamIndex(base);
+
+ for (unsigned i = 1, n = members.size(); i <= n; ++i) {
+ Node *member = members[n - i];
+ mangle(member->getChild(1));
+ }
+ Out << '_';
+ }
+}
+
+void Remangler::mangleDependentAssociatedTypeRef(Node *node) {
+ SubstitutionEntry entry;
+ if (trySubstitution(node, entry)) return;
+
+ if (node->getNumChildren() > 0) {
+ Out << 'P';
+ mangleProtocolWithoutPrefix(node->getFirstChild());
+ }
+ mangleIdentifier(node);
+
+ addSubstitution(entry);
+}
+
+void Remangler::mangleDependentGenericParamIndex(Node *node) {
+ auto depth = node->getChild(0)->getIndex();
+ auto index = node->getChild(1)->getIndex();
+
+ if (depth != 0) {
+ Out << 'd';
+ mangleIndex(depth - 1);
+ mangleIndex(index);
+ return;
+ }
+ if (index != 0) {
+ mangleIndex(index - 1);
+ return;
+ }
+
+ // depth == index == 0
+ Out << 'x';
+}
+
+void Remangler::mangleDependentGenericParamType(Node *node) {
+ if (node->getChild(0)->getIndex() == 0
+ && node->getChild(1)->getIndex() == 0) {
+ Out << 'x';
+ return;
+ }
+
+ Out << 'q';
+ mangleDependentGenericParamIndex(node);
+}
+
+void Remangler::mangleIndex(Node *node) {
+ mangleIndex(node->getIndex());
+}
+
+void Remangler::mangleProtocol(Node *node, EntityContext &ctx) {
+ mangleNominalType(node, 'P', ctx);
+}
+
+void Remangler::mangleProtocolWithoutPrefix(Node *node) {
+ if (node->getKind() == Node::Kind::Type) {
+ assert(node->getNumChildren() == 1);
+ node = node->begin()[0];
+ }
+
+ assert(node->getKind() == Node::Kind::Protocol);
+ EntityContext ctx;
+ mangleNominalType(node, '\0', ctx);
+}
+
+void Remangler::mangleGenericArgs(Node *node, EntityContext &ctx) {
+ switch (node->getKind()) {
+ case Node::Kind::Structure:
+ case Node::Kind::Enum:
+ case Node::Kind::Class: {
+ NodePointer parentOrModule = node->getChild(0);
+ mangleGenericArgs(parentOrModule, ctx);
+
+ // No generic arguments at this level
+ Out << '_';
+ break;
+ }
+
+ case Node::Kind::BoundGenericStructure:
+ case Node::Kind::BoundGenericEnum:
+ case Node::Kind::BoundGenericClass: {
+ NodePointer unboundType = node->getChild(0);
+ assert(unboundType->getKind() == Node::Kind::Type);
+ NodePointer nominalType = unboundType->getChild(0);
+ NodePointer parentOrModule = nominalType->getChild(0);
+ mangleGenericArgs(parentOrModule, ctx);
+
+ mangleTypeList(node->getChild(1));
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+void Remangler::mangleAnyNominalType(Node *node, EntityContext &ctx) {
+ if (isSpecialized(node)) {
+ Out << 'G';
+
+ NodePointer unboundType = getUnspecialized(node, Factory);
+
+ mangleAnyNominalType(unboundType, ctx);
+ mangleGenericArgs(node, ctx);
+ return;
+ }
+
+ switch (node->getKind()) {
+ case Node::Kind::Structure:
+ mangleNominalType(node, 'V', ctx);
+ break;
+ case Node::Kind::Enum:
+ mangleNominalType(node, 'O', ctx);
+ break;
+ case Node::Kind::Class:
+ mangleNominalType(node, 'C', ctx);
+ break;
+ default:
+ unreachable("bad nominal type kind");
+ }
+}
+
+void Remangler::mangleStructure(Node *node, EntityContext &ctx) {
+ mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleEnum(Node *node, EntityContext &ctx) {
+ mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleClass(Node *node, EntityContext &ctx) {
+ mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleNominalType(Node *node, char kind, EntityContext &ctx) {
+ SubstitutionEntry entry;
+ if (trySubstitution(node, entry)) return;
+ mangleNamedEntity(node, kind, "", ctx);
+ addSubstitution(entry);
+}
+
+void Remangler::mangleBoundGenericClass(Node *node) {
+ EntityContext ctx;
+ mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleBoundGenericStructure(Node *node) {
+ EntityContext ctx;
+ mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleBoundGenericEnum(Node *node) {
+ EntityContext ctx;
+ mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleTypeList(Node *node) {
+ mangleChildNodes(node); // all types
+ Out << '_';
+}
+
+void Remangler::mangleReflectionMetadataBuiltinDescriptor(Node *node) {
+ Out << "MRb";
+}
+
+void Remangler::mangleReflectionMetadataFieldDescriptor(Node *node) {
+ Out << "MRf";
+}
+
+void Remangler::mangleReflectionMetadataAssocTypeDescriptor(Node *node) {
+ Out << "MRa";
+}
+
+void Remangler::mangleReflectionMetadataSuperclassDescriptor(Node *node) {
+ Out << "MRc";
+}
+
+void Remangler::mangleGenericTypeParamDecl(Node *node) {
+ unreachable("todo");
+}
+
+void Remangler::mangleCurryThunk(Node *node, EntityContext &ctx) {
+ Out << "<curry-thunk>";
+}
+
+void Remangler::mangleEmptyList(Node *node) {
+ Out << "<empty>";
+}
+
+void Remangler::mangleFirstElementMarker(Node *node) {
+ Out << "<first>";
+}
+
+void Remangler::mangleVariadicMarker(Node *node) {
+ // Handled in mangleTuple
+}
+
+void Remangler::mangleOutlinedCopy(Node *node) {
+ Out << "Wy";
+ mangleChildNodes(node);
+}
+
+void Remangler::mangleOutlinedConsume(Node *node) {
+ Out << "We";
+ mangleChildNodes(node);
+}
+
+void Remangler::mangleOutlinedRetain(Node *node) {
+ Out << "Wr";
+ mangleSingleChildNode(node);
+}
+
+void Remangler::mangleOutlinedRelease(Node *node) {
+ Out << "Ws";
+ mangleSingleChildNode(node);
+}
+
+void Remangler::mangleKeyPathGetterThunkHelper(Node *node) {
+ Out << "TK";
+ mangleChildNodes(node);
+}
+
+void Remangler::mangleKeyPathSetterThunkHelper(Node *node) {
+ Out << "Tk";
+ mangleChildNodes(node);
+}
+
+void Remangler::mangleProtocolListWithClass(Node *node) {
+ Out << "Xc";
+ mangleChildNode(node, 1);
+ mangleProtocolListWithoutPrefix(node->getChild(0));
+}
+
+void Remangler::mangleProtocolListWithAnyObject(Node *node) {
+ Node *P = Factory.createNode(Node::Kind::Protocol);
+ P->addChild(Factory.createNode(Node::Kind::Module, "Swift"), Factory);
+ P->addChild(Factory.createNode(Node::Kind::Identifier, "AnyObject"), Factory);
+ Out << "P";
+ mangleProtocolListWithoutPrefix(node->getChild(0), /*additionalProto*/ P);
+}
+
+void Remangler::mangleVTableThunk(Node *node) {
+ Out << "TV";
+ mangleChildNodes(node);
+}
+
+void Remangler::mangleSILBoxTypeWithLayout(Node *node) {
+ assert(node->getKind() == Node::Kind::SILBoxTypeWithLayout);
+ assert(node->getNumChildren() == 1 || node->getNumChildren() == 3);
+ Out << "XB";
+ auto layout = node->getChild(0);
+ assert(layout->getKind() == Node::Kind::SILBoxLayout);
+ NodePointer genericArgs = nullptr;
+ if (node->getNumChildren() == 3) {
+ NodePointer signature = node->getChild(1);
+ assert(signature->getKind() == Node::Kind::DependentGenericSignature);
+ genericArgs = node->getChild(2);
+ assert(genericArgs->getKind() == Node::Kind::TypeList);
+
+ Out << 'G';
+ mangleDependentGenericSignature(signature);
+ }
+ mangleSILBoxLayout(layout);
+ if (genericArgs) {
+ for (unsigned i = 0; i < genericArgs->getNumChildren(); ++i) {
+ auto type = genericArgs->getChild(i);
+ assert(genericArgs->getKind() == Node::Kind::Type);
+ mangleType(type);
+ }
+ Out << '_';
+ }
+}
+
+void Remangler::mangleSILBoxLayout(Node *node) {
+ assert(node->getKind() == Node::Kind::SILBoxLayout);
+ for (unsigned i = 0; i < node->getNumChildren(); ++i) {
+ assert(node->getKind() == Node::Kind::SILBoxImmutableField
+ || node->getKind() == Node::Kind::SILBoxMutableField);
+ mangle(node->getChild(i));
+
+ }
+ Out << '_';
+}
+
+void Remangler::mangleSILBoxMutableField(Node *node) {
+ Out << 'm';
+ assert(node->getNumChildren() == 1
+ && node->getChild(0)->getKind() == Node::Kind::Type);
+ mangleType(node->getChild(0));
+}
+
+void Remangler::mangleSILBoxImmutableField(Node *node) {
+ Out << 'i';
+ assert(node->getNumChildren() == 1
+ && node->getChild(0)->getKind() == Node::Kind::Type);
+ mangleType(node->getChild(0));
+}
+
+/// The top-level interface to the remangler.
+std::string Demangle::mangleNodeOld(const NodePointer &node) {
+ if (!node) return "";
+
+ DemanglerPrinter printer;
+ Remangler(printer).mangle(node);
+ return std::move(printer).str();
+}
diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp
index d47d801..d5a2adb 100644
--- a/lib/IDE/SwiftSourceDocInfo.cpp
+++ b/lib/IDE/SwiftSourceDocInfo.cpp
@@ -227,10 +227,15 @@
OS << "</Kind>\n";
OS << "<Content>" << Content << "</Content>\n";
- if (Ty) {
+
+ if (auto Ty = ExitInfo.getPointer()) {
OS << "<Type>";
Ty->print(OS);
- OS << "</Type>\n";
+ OS << "</Type>";
+ if (ExitInfo.getInt()) {
+ OS << "<Exit>true</Exit>";
+ }
+ OS << "\n";
}
if (RangeContext) {
@@ -382,7 +387,10 @@
std::vector<ASTNode> ContainedASTNodes;
/// Collect the type that an ASTNode should be evaluated to.
- Type resolveNodeType(ASTNode N, RangeKind Kind) {
+ ReturnTyAndWhetherExit resolveNodeType(ASTNode N, RangeKind Kind) {
+ auto *VoidTy = Ctx.getVoidDecl()->getDeclaredInterfaceType().getPointer();
+ if (N.isNull())
+ return {VoidTy, false};
switch(Kind) {
case RangeKind::Invalid:
case RangeKind::SingleDecl:
@@ -390,14 +398,18 @@
// For a single expression, its type is apparent.
case RangeKind::SingleExpression:
- return N.get<Expr*>()->getType();
+ return {N.get<Expr*>()->getType().getPointer(), false};
// For statements, we either resolve to the returning type or Void.
case RangeKind::SingleStatement:
case RangeKind::MultiStatement: {
if (N.is<Stmt*>()) {
if (auto RS = dyn_cast<ReturnStmt>(N.get<Stmt*>())) {
- return resolveNodeType(RS->getResult(), RangeKind::SingleExpression);
+ return {
+ resolveNodeType(RS->hasResult() ? RS->getResult() : nullptr,
+ RangeKind::SingleExpression).getPointer(),
+ true
+ };
}
// Unbox the brace statement to find its type.
@@ -407,9 +419,25 @@
RangeKind::SingleStatement);
}
}
+
+ // Unbox the if statement to find its type.
+ if (auto *IS = dyn_cast<IfStmt>(N.get<Stmt*>())) {
+ auto ThenTy = resolveNodeType(IS->getThenStmt(),
+ RangeKind::SingleStatement);
+ auto ElseTy = resolveNodeType(IS->getElseStmt(),
+ RangeKind::SingleStatement);
+
+ // If two branches agree on the return type, return that type.
+ if (ThenTy.getPointer()->isEqual(ElseTy.getPointer()) &&
+ ThenTy.getInt() == ElseTy.getInt())
+ return ThenTy;
+
+ // Otherwise, return the error type.
+ return {Ctx.TheErrorType.getPointer(), false};
+ }
}
// For other statements, the type should be void.
- return Ctx.getVoidDecl()->getDeclaredInterfaceType();
+ return {VoidTy, false};
}
}
}
@@ -440,7 +468,7 @@
llvm::makeArrayRef(ReferencedDecls));
else {
assert(Node.is<Decl*>());
- return ResolvedRangeInfo(RangeKind::SingleDecl, Type(), Content,
+ return ResolvedRangeInfo(RangeKind::SingleDecl, {nullptr, false}, Content,
getImmediateContext(), SingleEntry,
UnhandledError, Kind,
llvm::makeArrayRef(ContainedASTNodes),
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 1a8f4e2..0c849fd 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -3266,6 +3266,12 @@
}
Type TypeChecker::getSuperClassOf(Type type) {
+ if (auto *parenTy = dyn_cast<ParenType>(type.getPointer())) {
+ auto superclassTy = getSuperClassOf(parenTy->getUnderlyingType());
+ if (!superclassTy)
+ return Type();
+ return ParenType::get(Context, superclassTy);
+ }
return type->getSuperclass();
}
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 940b9d1..d2c8caf 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -165,13 +165,20 @@
getContext().Diags.diagnose(SourceLoc(), diag::serialization_fatal, Name);
if (!CompatibilityVersion.empty()) {
- SmallString<16> buffer;
- llvm::raw_svector_ostream out(buffer);
- out << getContext().LangOpts.EffectiveLanguageVersion;
- if (out.str() != CompatibilityVersion) {
+ if (getContext().LangOpts.EffectiveLanguageVersion
+ != CompatibilityVersion) {
+ SmallString<16> effectiveVersionBuffer, compatVersionBuffer;
+ {
+ llvm::raw_svector_ostream out(effectiveVersionBuffer);
+ out << getContext().LangOpts.EffectiveLanguageVersion;
+ }
+ {
+ llvm::raw_svector_ostream out(compatVersionBuffer);
+ out << CompatibilityVersion;
+ }
getContext().Diags.diagnose(
SourceLoc(), diag::serialization_compatibility_version_mismatch,
- out.str(), Name, CompatibilityVersion);
+ effectiveVersionBuffer, Name, compatVersionBuffer);
}
}
}
@@ -4464,20 +4471,69 @@
ArrayRef<uint64_t>::iterator rawIDIter = rawIDs.begin();
+ // An imported requirement may have changed type between Swift versions.
+ // In this situation we need to do a post-pass to fill in missing
+ // requirements with opaque witnesses.
+ bool needToFillInOpaqueValueWitnesses = false;
while (valueCount--) {
- auto req = cast<ValueDecl>(getDecl(*rawIDIter++));
- auto witness = cast_or_null<ValueDecl>(getDecl(*rawIDIter++));
- assert(witness ||
+ ValueDecl *req;
+
+ auto trySetWitness = [&](Witness w) {
+ if (req)
+ conformance->setWitness(req, w);
+ };
+
+ auto deserializedReq = getDeclChecked(*rawIDIter++);
+ if (deserializedReq) {
+ req = cast<ValueDecl>(*deserializedReq);
+ } else if (getContext().LangOpts.EnableDeserializationRecovery) {
+ consumeError(deserializedReq.takeError());
+ req = nullptr;
+ needToFillInOpaqueValueWitnesses = true;
+ } else {
+ fatal(deserializedReq.takeError());
+ }
+
+ bool isOpaque = false;
+ ValueDecl *witness;
+ auto deserializedWitness = getDeclChecked(*rawIDIter++);
+ if (deserializedWitness) {
+ witness = cast<ValueDecl>(*deserializedWitness);
+ // Across language compatibility versions, the witnessing decl may have
+ // changed its signature as seen by the current compatibility version.
+ // In that case, we want the conformance to still be available, but
+ // we can't make use of the relationship to the underlying decl.
+ } else if (getContext().LangOpts.EnableDeserializationRecovery) {
+ consumeError(deserializedWitness.takeError());
+ isOpaque = true;
+ witness = nullptr;
+ } else {
+ fatal(deserializedWitness.takeError());
+ }
+
+ assert(!req || isOpaque || witness ||
req->getAttrs().hasAttribute<OptionalAttr>() ||
req->getAttrs().isUnavailable(getContext()));
- if (!witness) {
- conformance->setWitness(req, Witness());
+ if (!witness && !isOpaque) {
+ trySetWitness(Witness());
continue;
}
// Generic signature and environment.
GenericSignature *syntheticSig = nullptr;
GenericEnvironment *syntheticEnv = nullptr;
+
+ auto trySetOpaqueWitness = [&]{
+ if (!req)
+ return;
+
+ // We shouldn't yet need to worry about generic requirements, since
+ // an imported ObjC method should never be generic.
+ assert(syntheticSig == nullptr && syntheticEnv == nullptr &&
+ "opaque witness shouldn't be generic yet. when this is "
+ "possible, it should use forwarding substitutions");
+ conformance->setWitness(req, Witness::forOpaque(req));
+ };
// Requirement -> synthetic map.
SmallVector<Substitution, 4> reqToSyntheticSubs;
@@ -4518,16 +4574,22 @@
}
}
+ // Handle opaque witnesses that couldn't be deserialized.
+ if (isOpaque) {
+ trySetOpaqueWitness();
+ continue;
+ }
+
// Handle simple witnesses.
if (witnessSubstitutions.empty() && !syntheticSig && !syntheticEnv &&
reqToSyntheticSubs.empty()) {
- conformance->setWitness(req, Witness(witness));
+ trySetWitness(Witness(witness));
continue;
}
// Set the witness.
- conformance->setWitness(req, Witness(witness, witnessSubstitutions,
- syntheticEnv, reqToSyntheticSubs));
+ trySetWitness(Witness(witness, witnessSubstitutions,
+ syntheticEnv, reqToSyntheticSubs));
}
assert(rawIDIter <= rawIDs.end() && "read too much");
@@ -4558,6 +4620,20 @@
conformance->setTypeWitness(typeWitness.first, typeWitness.second.first,
typeWitness.second.second);
}
+
+ // Fill in opaque value witnesses if we need to.
+ if (needToFillInOpaqueValueWitnesses) {
+ for (auto member : proto->getMembers()) {
+ // We only care about non-associated-type requirements.
+ auto valueMember = dyn_cast<ValueDecl>(member);
+ if (!valueMember || !valueMember->isProtocolRequirement()
+ || isa<AssociatedTypeDecl>(valueMember))
+ continue;
+
+ if (!conformance->hasWitness(valueMember))
+ conformance->setWitness(valueMember, Witness::forOpaque(valueMember));
+ }
+ }
}
GenericEnvironment *ModuleFile::loadGenericEnvironment(const DeclContext *decl,
diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp
index 02bc030..d5cf782 100644
--- a/lib/Serialization/ModuleFile.cpp
+++ b/lib/Serialization/ModuleFile.cpp
@@ -200,7 +200,9 @@
default:
// Add new cases here, in descending order.
case 4:
- result.compatibilityVersion = blobData.substr(scratch[2]+1, scratch[3]);
+ result.compatibilityVersion =
+ version::Version(blobData.substr(scratch[2]+1, scratch[3]),
+ SourceLoc(), nullptr);
LLVM_FALLTHROUGH;
case 3:
result.shortVersion = blobData.slice(0, scratch[2]);
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
index 3bb4871..f4dea7b 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
@@ -257,8 +257,7 @@
${TRACE},
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
sameValue: (${Element}, ${Element}) -> Bool
-) where C.Iterator.Element == ${Element},
- C.SubSequence : Collection {
+) where C.Iterator.Element == ${Element} {
checkForwardCollection(expected, collection, message(),
stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
@@ -278,7 +277,6 @@
resiliencyChecks: CollectionMisuseResiliencyChecks = .all
) where
C.Iterator.Element == ${Element},
- C.SubSequence : ${TraversalCollection},
${Element} : Equatable {
check${Traversal}Collection(
@@ -298,8 +296,7 @@
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
sameValue: (${Element}, ${Element}) -> Bool
) where
- C.Iterator.Element == ${Element},
- C.SubSequence : ${TraversalCollection} {
+ C.Iterator.Element == ${Element} {
checkOneLevelOf${Traversal}Collection(expected, collection, ${trace},
resiliencyChecks: resiliencyChecks, sameValue: sameValue)
@@ -504,8 +501,7 @@
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
sameValue: (${Element}, ${Element}) -> Bool
) where
- S.Iterator.Element == ${Element},
- S.SubSequence : ${TraversalCollection} {
+ S.Iterator.Element == ${Element} {
let expectedArray = Array(expected)
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
index 8ce2040..a550216 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
@@ -471,16 +471,9 @@
%{
from gyb_stdlib_support import collectionForTraversal
def testConstraints(protocol):
- if protocol == 'Collection':
- subseq_as_collection = 'CollectionWithEquatableElement.SubSequence : Collection,'
- else:
- subseq_as_collection=''
return '''
C : %(protocol)s,
CollectionWithEquatableElement : %(protocol)s,
- %(subseq_as_collection)s
- C.SubSequence : %(protocol)s,
- C.Indices : %(protocol)s,
CollectionWithEquatableElement.Iterator.Element : Equatable
''' % locals()
@@ -494,6 +487,7 @@
[CollectionWithEquatableElement.Iterator.Element]
) -> CollectionWithEquatableElement,
+
wrapValueIntoEquatable: @escaping (
MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
index c20f755..fb13a1a 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
@@ -121,8 +121,6 @@
isFixedLengthCollection: Bool,
collectionIsBidirectional: Bool = false
) where
- C.SubSequence : MutableCollection,
- C.Indices : Collection,
CollectionWithEquatableElement.Iterator.Element : Equatable,
CollectionWithComparableElement.Iterator.Element : Comparable {
@@ -783,8 +781,6 @@
withUnsafeMutableBufferPointerIsSupported: Bool,
isFixedLengthCollection: Bool
) where
- C.SubSequence : BidirectionalCollection & MutableCollection,
- C.Indices : BidirectionalCollection,
CollectionWithEquatableElement.Iterator.Element : Equatable,
CollectionWithComparableElement.Iterator.Element : Comparable {
@@ -929,8 +925,6 @@
withUnsafeMutableBufferPointerIsSupported: Bool,
isFixedLengthCollection: Bool
) where
- C.SubSequence : RandomAccessCollection & MutableCollection,
- C.Indices : RandomAccessCollection,
CollectionWithEquatableElement.Iterator.Element : Equatable,
CollectionWithComparableElement.Iterator.Element : Comparable {
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift
index 14363c6..245f486 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift
+++ b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift
@@ -462,10 +462,7 @@
outOfBoundsIndexOffset: Int = 1,
collectionIsBidirectional: Bool = false
) where
- C.SubSequence : Collection,
- C.Indices : Collection,
- CollectionWithEquatableElement.Iterator.Element : Equatable,
- CollectionWithEquatableElement.SubSequence : Collection {
+ CollectionWithEquatableElement.Iterator.Element : Equatable {
var testNamePrefix = testNamePrefix
@@ -1180,8 +1177,6 @@
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
outOfBoundsIndexOffset: Int = 1
) where
- C.SubSequence : BidirectionalCollection & RangeReplaceableCollection,
- C.Indices : BidirectionalCollection,
CollectionWithEquatableElement.Iterator.Element : Equatable {
var testNamePrefix = testNamePrefix
@@ -1302,8 +1297,6 @@
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
outOfBoundsIndexOffset: Int = 1
) where
- C.SubSequence : RandomAccessCollection & RangeReplaceableCollection,
- C.Indices : RandomAccessCollection,
CollectionWithEquatableElement.Iterator.Element : Equatable {
var testNamePrefix = testNamePrefix
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift
index fb10e30..28a802e 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift
+++ b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift
@@ -33,7 +33,6 @@
collectionIsBidirectional: Bool = false
) where
C.SubSequence == C,
- C.Indices : Collection,
CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement,
CollectionWithEquatableElement.Iterator.Element : Equatable {
@@ -165,7 +164,6 @@
outOfBoundsIndexOffset: Int = 1
) where
C.SubSequence == C,
- C.Indices : BidirectionalCollection,
CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement,
CollectionWithEquatableElement.Iterator.Element : Equatable {
@@ -310,7 +308,6 @@
outOfBoundsIndexOffset: Int = 1
) where
C.SubSequence == C,
- C.Indices : RandomAccessCollection,
CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement,
CollectionWithEquatableElement.Iterator.Element : Equatable {
diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
index 2d61bee..02b1df0 100644
--- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
+++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
@@ -376,14 +376,7 @@
% for Mutable in ['', 'Mutable']:
public func expect${Mutable}CollectionType<X : ${Mutable}Collection>(
_ x: X.Type
-) where
- // FIXME(ABI)#2 (Associated Types with where clauses): there should be no constraints in
- // the 'where' clause, all of these should be required by the protocol.
-% if Mutable == '':
- X.SubSequence : Collection,
-% end
- // X.SubSequence.Indices == X.Indices, // FIXME(ABI)#3 (Recursive Protocol Constraints): can't have this constraint now.
- X.Indices : Collection {}
+) { }
% end
/// A slice is a `Collection` that when sliced returns an instance of
@@ -421,12 +414,7 @@
indexType: X.Index.Type,
indexDistanceType: X.IndexDistance.Type,
indicesType: X.Indices.Type
-) where
- // FIXME(ABI)#6 (Associated Types with where clauses): there should be no constraints in
- // the 'where' clause, all of these should be required by the protocol.
- X.SubSequence : Collection,
- // X.SubSequence.Indices == X.Indices, // FIXME(ABI)#7 (Recursive Protocol Constraints): can't have this constraint now.
- X.Indices : Collection {}
+) { }
/// Check that all associated types of a `BidirectionalCollection` are what we
/// expect them to be.
@@ -437,12 +425,7 @@
indexType: X.Index.Type,
indexDistanceType: X.IndexDistance.Type,
indicesType: X.Indices.Type
-) where
- // FIXME(ABI)#8 (Associated Types with where clauses): there should be no constraints in
- // the 'where' clause, all of these should be required by the protocol.
- X.SubSequence : BidirectionalCollection,
- // X.SubSequence.Indices == X.Indices, // FIXME(ABI)#9 (Recursive Protocol Constraints): can't have this constraint now.
- X.Indices : BidirectionalCollection {}
+) { }
/// Check that all associated types of a `RandomAccessCollection` are what we
/// expect them to be.
@@ -453,12 +436,7 @@
indexType: X.Index.Type,
indexDistanceType: X.IndexDistance.Type,
indicesType: X.Indices.Type
-) where
- // FIXME(ABI)#10 (Associated Types with where clauses): there should be no constraints in
- // the 'where' clause, all of these should be required by the protocol.
- X.SubSequence : RandomAccessCollection,
- // X.SubSequence.Indices == X.Indices, // FIXME(ABI)#11 (Recursive Protocol Constraints): can't have this constraint now.
- X.Indices : RandomAccessCollection {}
+) { }
public struct AssertionResult : CustomStringConvertible {
init(isPass: Bool) {
diff --git a/stdlib/public/core/ArrayBufferProtocol.swift b/stdlib/public/core/ArrayBufferProtocol.swift
index 2748e6d..c5a248c 100644
--- a/stdlib/public/core/ArrayBufferProtocol.swift
+++ b/stdlib/public/core/ArrayBufferProtocol.swift
@@ -16,7 +16,7 @@
internal protocol _ArrayBufferProtocol
: MutableCollection, RandomAccessCollection {
- associatedtype Indices : RandomAccessCollection = CountableRange<Int>
+ associatedtype Indices = CountableRange<Int>
/// The type of elements stored in the buffer.
associatedtype Element
diff --git a/stdlib/public/core/BidirectionalCollection.swift b/stdlib/public/core/BidirectionalCollection.swift
index f7349e2..0668e05 100644
--- a/stdlib/public/core/BidirectionalCollection.swift
+++ b/stdlib/public/core/BidirectionalCollection.swift
@@ -65,8 +65,8 @@
/// `c.index(before: c.index(after: i)) == i`.
/// - If `i > c.startIndex && i <= c.endIndex`
/// `c.index(after: c.index(before: i)) == i`.
-public protocol BidirectionalCollection
- : _BidirectionalIndexable, Collection {
+public protocol BidirectionalCollection : _BidirectionalIndexable, Collection
+where SubSequence: BidirectionalCollection, Indices: BidirectionalCollection {
// TODO: swift-3-indexing-model - replaces functionality in BidirectionalIndex
/// Returns the position immediately before the given index.
@@ -84,17 +84,11 @@
/// A sequence that can represent a contiguous subrange of the collection's
/// elements.
- associatedtype SubSequence : _BidirectionalIndexable, Collection
- = BidirectionalSlice<Self>
- // FIXME(ABI)#93 (Recursive Protocol Constraints):
- // associatedtype SubSequence : BidirectionalCollection
+ associatedtype SubSequence = BidirectionalSlice<Self>
/// A type that represents the indices that are valid for subscripting the
/// collection, in ascending order.
- associatedtype Indices : _BidirectionalIndexable, Collection
- = DefaultBidirectionalIndices<Self>
- // FIXME(ABI)#95 (Recursive Protocol Constraints):
- // associatedtype Indices : BidirectionalCollection
+ associatedtype Indices = DefaultBidirectionalIndices<Self>
/// The indices that are valid for subscripting the collection, in ascending
/// order.
diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift
index f7a8175..fb8f0f9 100644
--- a/stdlib/public/core/Collection.swift
+++ b/stdlib/public/core/Collection.swift
@@ -642,7 +642,10 @@
/// forward or bidirectional collection must traverse the entire collection to
/// count the number of contained elements, accessing its `count` property is
/// an O(*n*) operation.
-public protocol Collection : _Indexable, Sequence {
+public protocol Collection : _Indexable, Sequence
+where SubSequence: Collection, Indices: Collection,
+ SubSequence.Index == Index
+{
/// A type that represents the number of steps between a pair of
/// indices.
associatedtype IndexDistance = Int
@@ -668,10 +671,10 @@
/// This associated type appears as a requirement in the `Sequence`
/// protocol, but it is restated here with stricter constraints. In a
/// collection, the subsequence should also conform to `Collection`.
- associatedtype SubSequence : _IndexableBase, Sequence = Slice<Self>
- where Self.SubSequence.Index == Index,
- Self.Iterator.Element == Self.SubSequence.Iterator.Element,
+ associatedtype SubSequence = Slice<Self>
+ where Iterator.Element == SubSequence.Iterator.Element,
SubSequence.SubSequence == SubSequence
+
// FIXME(ABI)#98 (Recursive Protocol Constraints):
// FIXME(ABI)#99 (Associated Types with where clauses):
// associatedtype SubSequence : Collection
@@ -732,10 +735,9 @@
/// A type that represents the indices that are valid for subscripting the
/// collection, in ascending order.
- associatedtype Indices : _Indexable, Sequence = DefaultIndices<Self>
+ associatedtype Indices = DefaultIndices<Self>
where Indices.Iterator.Element == Index,
- Indices.Index == Index,
- Indices.SubSequence == Indices
+ Indices.Index == Index
// FIXME(ABI)#100 (Recursive Protocol Constraints):
// associatedtype Indices : Collection
diff --git a/stdlib/public/core/ExistentialCollection.swift.gyb b/stdlib/public/core/ExistentialCollection.swift.gyb
index 6cdb79d..204ca5c 100644
--- a/stdlib/public/core/ExistentialCollection.swift.gyb
+++ b/stdlib/public/core/ExistentialCollection.swift.gyb
@@ -426,14 +426,11 @@
@_fixed_layout
@_versioned
internal final class _${Kind}Box<S : ${Kind}> : _Any${Kind}Box<S.Iterator.Element>
+% if Kind == 'Sequence':
where
S.SubSequence : ${Kind},
-% if Kind == 'Sequence':
S.SubSequence.Iterator.Element == S.Iterator.Element,
S.SubSequence.SubSequence == S.SubSequence
-% else:
- S.SubSequence.Indices : ${Kind},
- S.Indices : ${Kind}
% end
{
internal typealias Element = S.Iterator.Element
@@ -1040,10 +1037,7 @@
where
// FIXME(ABI)#101 (Associated Types with where clauses): these constraints should be applied to
// associated types of Collection.
- C.SubSequence : ${SubProtocol},
- C.SubSequence.Iterator.Element == Element,
- C.SubSequence.Indices : ${SubProtocol},
- C.Indices : ${SubProtocol}
+ C.SubSequence.Iterator.Element == Element
{
// Traversal: ${Traversal}
// SubTraversal: ${SubTraversal}
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index c2d319e..37d95d8 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -214,13 +214,7 @@
children: C,
displayStyle: DisplayStyle? = nil,
ancestorRepresentation: AncestorRepresentation = .generated
- ) where
- C.Iterator.Element == Child,
- // FIXME(ABI)#47 (Associated Types with where clauses): these constraints should be applied to
- // associated types of Collection.
- C.SubSequence : Collection,
- C.SubSequence.Indices : Collection,
- C.Indices : Collection {
+ ) where C.Iterator.Element == Child {
self.subjectType = Subject.self
self._makeSuperclassMirror = Mirror._superclassIterator(
@@ -267,11 +261,7 @@
unlabeledChildren: C,
displayStyle: DisplayStyle? = nil,
ancestorRepresentation: AncestorRepresentation = .generated
- ) where
- // FIXME(ABI)#48 (Associated Types with where clauses): these constraints should be applied to
- // associated types of Collection.
- C.SubSequence : Collection,
- C.Indices : Collection {
+ ) {
self.subjectType = Subject.self
self._makeSuperclassMirror = Mirror._superclassIterator(
diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift
index 4c424d8..14c47eb 100644
--- a/stdlib/public/core/MutableCollection.swift
+++ b/stdlib/public/core/MutableCollection.swift
@@ -217,14 +217,9 @@
/// // Must be equivalent to:
/// a[i] = x
/// let y = x
-public protocol MutableCollection : _MutableIndexable, Collection {
- // FIXME(ABI)#181: should be constrained to MutableCollection
- // (<rdar://problem/20715009> Implement recursive protocol
- // constraints)
- /// A collection that represents a contiguous subrange of the collection's
- /// elements.
- associatedtype SubSequence : Collection /*: MutableCollection*/
- = MutableSlice<Self>
+public protocol MutableCollection : _MutableIndexable, Collection
+where SubSequence: MutableCollection {
+ associatedtype SubSequence = MutableSlice<Self>
/// Accesses the element at the specified position.
///
diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift
index 88f4253..8a4dec0 100644
--- a/stdlib/public/core/RandomAccessCollection.swift
+++ b/stdlib/public/core/RandomAccessCollection.swift
@@ -48,20 +48,15 @@
/// `distance(from:to:)` methods with O(1) efficiency.
public protocol RandomAccessCollection :
_RandomAccessIndexable, BidirectionalCollection
+ where SubSequence: RandomAccessCollection, Indices: RandomAccessCollection
{
/// A collection that represents a contiguous subrange of the collection's
/// elements.
- associatedtype SubSequence : _RandomAccessIndexable, BidirectionalCollection
- = RandomAccessSlice<Self>
- // FIXME(ABI)#102 (Recursive Protocol Constraints):
- // associatedtype SubSequence : RandomAccessCollection
+ associatedtype SubSequence = RandomAccessSlice<Self>
/// A type that represents the indices that are valid for subscripting the
/// collection, in ascending order.
- associatedtype Indices : _RandomAccessIndexable, BidirectionalCollection
- = DefaultRandomAccessIndices<Self>
- // FIXME(ABI)#103 (Recursive Protocol Constraints):
- // associatedtype Indices : RandomAccessCollection
+ associatedtype Indices = DefaultRandomAccessIndices<Self>
/// The indices that are valid for subscripting the collection, in ascending
/// order.
diff --git a/stdlib/public/core/SequenceAlgorithms.swift.gyb b/stdlib/public/core/SequenceAlgorithms.swift.gyb
index a5b99de..5be151b 100644
--- a/stdlib/public/core/SequenceAlgorithms.swift.gyb
+++ b/stdlib/public/core/SequenceAlgorithms.swift.gyb
@@ -729,13 +729,6 @@
}
return result
}
-
- @available(*, deprecated, message: "This call uses implicit promotion to optional. Please use map instead.")
- public func flatMap<T>(
- _ transform: (${GElement}) throws -> T
- ) rethrows -> [T] {
- return try map(transform)
- }
}
extension Sequence {
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
index d06cb92..1201400 100644
--- a/stdlib/public/core/StringCharacterView.swift
+++ b/stdlib/public/core/StringCharacterView.swift
@@ -445,7 +445,14 @@
let relativeOffset = i._base._position - _coreOffset
if _core.isASCII {
let asciiBuffer = _core.asciiBuffer._unsafelyUnwrappedUnchecked
- return Character(UnicodeScalar(asciiBuffer[relativeOffset]))
+ // Bounds checks in an UnsafeBufferPointer (asciiBuffer) are only
+ // performed in Debug mode, so they need to be duplicated here.
+ // Falling back to the non-optimal behavior in the case they don't
+ // pass.
+ if relativeOffset >= asciiBuffer.startIndex &&
+ relativeOffset < asciiBuffer.endIndex {
+ return Character(UnicodeScalar(asciiBuffer[relativeOffset]))
+ }
} else if _core._baseAddress != nil {
let cu = _core._nthContiguous(relativeOffset)
// Only constructible if sub-surrogate
diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt
index a471e5f..5263c15 100644
--- a/stdlib/public/runtime/CMakeLists.txt
+++ b/stdlib/public/runtime/CMakeLists.txt
@@ -49,6 +49,7 @@
SwiftObject.mm
SwiftValue.mm
Reflection.mm
+ "${SWIFT_SOURCE_DIR}/lib/Demangling/OldRemangler.cpp"
"${SWIFT_SOURCE_DIR}/lib/Demangling/Remangler.cpp")
set(swift_runtime_sources
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 583178f..b7ee950 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -1532,7 +1532,7 @@
auto globalNode = Dem.createNode(Demangle::Node::Kind::Global);
globalNode->addChild(typeNode, Dem);
- auto string = Demangle::mangleNode(globalNode);
+ auto string = Demangle::mangleNodeOld(globalNode);
auto fullNameBuf = (char*)swift_slowAlloc(string.size() + 1, 0);
memcpy(fullNameBuf, string.c_str(), string.size() + 1);
diff --git a/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.apinotes b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.apinotes
new file mode 100644
index 0000000..adad67b
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.apinotes
@@ -0,0 +1,9 @@
+Name: SomeObjCModule
+Classes:
+- Name: NSRuncibleSpoon
+ SwiftBridge: RuncibleSpoon
+SwiftVersions:
+- Version: 3
+ Classes:
+ - Name: NSRuncibleSpoon
+ SwiftBridge: ""
diff --git a/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.h b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.h
new file mode 100644
index 0000000..a12b1af
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.h
@@ -0,0 +1,24 @@
+// Swift 3 sees the ObjC class NSRuncibleSpoon as the class, and uses methods
+// with type signatures involving NSRuncibleSpoon to conform to protocols
+// across the language boundary. Swift 4 sees the type as bridged to
+// a RuncibleSpoon value type, but still needs to be able to use conformances
+// declared by Swift 3.
+
+@import Foundation;
+
+@interface NSRuncibleSpoon: NSObject
+@end
+
+@interface SomeObjCClass: NSObject
+- (instancetype _Nonnull)initWithSomeSwiftInitRequirement:(NSRuncibleSpoon* _Nonnull)s;
+- (void)someSwiftMethodRequirement:(NSRuncibleSpoon* _Nonnull)s;
+@property NSRuncibleSpoon * _Nonnull someSwiftPropertyRequirement;
+@end
+
+@protocol SomeObjCProtocol
+- (instancetype _Nonnull)initWithSomeObjCInitRequirement:(NSRuncibleSpoon * _Nonnull)string;
+- (void)someObjCMethodRequirement:(NSRuncibleSpoon * _Nonnull)string;
+@property NSRuncibleSpoon * _Nonnull someObjCPropertyRequirement;
+@end
+
+
diff --git a/test/Compatibility/MixAndMatch/Inputs/SomeObjCModuleX.swift b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModuleX.swift
new file mode 100644
index 0000000..2abcabe
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModuleX.swift
@@ -0,0 +1,22 @@
+// NB: This file is not named SomeObjCModule.swift to avoid getting picked up
+// by -enable-source-import
+
+@_exported import SomeObjCModule
+
+public struct RuncibleSpoon: _ObjectiveCBridgeable {
+ public init() {}
+
+ public func _bridgeToObjectiveC() -> NSRuncibleSpoon {
+ fatalError()
+ }
+ public static func _forceBridgeFromObjectiveC(_: NSRuncibleSpoon, result: inout RuncibleSpoon?) {
+ fatalError()
+ }
+ public static func _conditionallyBridgeFromObjectiveC(_: NSRuncibleSpoon, result: inout RuncibleSpoon?) -> Bool {
+ fatalError()
+ }
+ public static func _unconditionallyBridgeFromObjectiveC(_: NSRuncibleSpoon?) -> RuncibleSpoon {
+ fatalError()
+ }
+}
+
diff --git a/test/Compatibility/MixAndMatch/Inputs/module.modulemap b/test/Compatibility/MixAndMatch/Inputs/module.modulemap
new file mode 100644
index 0000000..154dc37
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/module.modulemap
@@ -0,0 +1,4 @@
+module SomeObjCModule {
+ header "SomeObjCModule.h"
+ export *
+}
diff --git a/test/Compatibility/MixAndMatch/Inputs/witness_change_swift3_leaf.swift b/test/Compatibility/MixAndMatch/Inputs/witness_change_swift3_leaf.swift
new file mode 100644
index 0000000..89a5a70
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/witness_change_swift3_leaf.swift
@@ -0,0 +1,71 @@
+
+// Swift 3 sees the ObjC class NSRuncibleSpoon as the class, and uses methods
+// with type signatures involving NSRuncibleSpoon to conform to protocols
+// across the language boundary. Swift 4 sees the type as bridged to
+// a RuncibleSpoon value type, but still needs to be able to use conformances
+// declared by Swift 3.
+
+// Swift 3, importing Swift 3 and Swift 4 code
+
+import SomeObjCModule
+import SomeSwift3Module
+import SomeSwift4Module
+
+func testMatchAndMix(bridged: RuncibleSpoon, unbridged: NSRuncibleSpoon) {
+ let objcInstanceViaClass
+ = SomeObjCClass(someSwiftInitRequirement: unbridged)
+
+ let objcClassAsS3Protocol: SomeSwift3Protocol.Type = SomeObjCClass.self
+ let objcInstanceViaS3Protocol
+ = objcClassAsS3Protocol.init(someSwiftInitRequirement: unbridged)
+
+ let objcClassAsS4Protocol: SomeSwift4Protocol.Type = SomeObjCClass.self
+ let objcInstanceViaS4Protocol
+ = objcClassAsS4Protocol.init(someSwiftInitRequirement: bridged)
+
+ var bridgedSink: RuncibleSpoon
+ var unbridgedSink: NSRuncibleSpoon
+
+ let swiftPropertyViaClass = objcInstanceViaClass.someSwiftPropertyRequirement
+ unbridgedSink = swiftPropertyViaClass
+ let swiftPropertyViaS3Protocol = objcInstanceViaS3Protocol.someSwiftPropertyRequirement
+ unbridgedSink = swiftPropertyViaS3Protocol
+ let swiftPropertyViaS4Protocol = objcInstanceViaS4Protocol.someSwiftPropertyRequirement
+ bridgedSink = swiftPropertyViaS4Protocol
+
+ objcInstanceViaClass.someSwiftMethodRequirement(unbridged)
+ objcInstanceViaS3Protocol.someSwiftMethodRequirement(unbridged)
+ objcInstanceViaS4Protocol.someSwiftMethodRequirement(bridged)
+
+ let swift3InstanceViaClass
+ = SomeSwift3Class(someObjCInitRequirement: unbridged)
+ let swift3ClassAsProtocol: SomeObjCProtocol.Type = SomeSwift3Class.self
+ let swift3InstanceViaProtocol
+ = swift3ClassAsProtocol.init(someObjCInitRequirement: unbridged)
+
+ let objcPropertyViaClassS3 = swift3InstanceViaClass.someObjCPropertyRequirement
+ unbridgedSink = objcPropertyViaClassS3
+ let objcPropertyViaProtocolS3 = swift3InstanceViaProtocol.someObjCPropertyRequirement
+ unbridgedSink = objcPropertyViaProtocolS3
+
+ swift3InstanceViaClass.someObjCMethodRequirement(unbridged)
+ swift3InstanceViaProtocol.someObjCMethodRequirement(unbridged)
+
+ let swift4InstanceViaClass
+ = SomeSwift4Class(someObjCInitRequirement: bridged)
+ let swift4ClassAsProtocol: SomeObjCProtocol.Type = SomeSwift4Class.self
+ let swift4InstanceViaProtocol
+ = swift4ClassAsProtocol.init(someObjCInitRequirement: unbridged)
+
+ let objcPropertyViaClassS4 = swift4InstanceViaClass.someObjCPropertyRequirement
+ bridgedSink = objcPropertyViaClassS4
+ let objcPropertyViaProtocolS4 = swift4InstanceViaProtocol.someObjCPropertyRequirement
+ unbridgedSink = objcPropertyViaProtocolS4
+
+ swift4InstanceViaClass.someObjCMethodRequirement(bridged)
+ swift4InstanceViaProtocol.someObjCMethodRequirement(unbridged)
+
+ _ = bridgedSink
+ _ = unbridgedSink
+}
+
diff --git a/test/Compatibility/MixAndMatch/Inputs/witness_change_swift4.swift b/test/Compatibility/MixAndMatch/Inputs/witness_change_swift4.swift
new file mode 100644
index 0000000..0ebad72
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/witness_change_swift4.swift
@@ -0,0 +1,65 @@
+
+// Swift 3 sees the ObjC class NSRuncibleSpoon as the class, and uses methods
+// with type signatures involving NSRuncibleSpoon to conform to protocols
+// across the language boundary. Swift 4 sees the type as bridged to
+// a RuncibleSpoon value type, but still needs to be able to use conformances
+// declared by Swift 3.
+
+// Swift 4
+
+import SomeObjCModule
+import SomeSwift3Module
+
+public func testMixAndMatch(bridged: RuncibleSpoon, unbridged: NSRuncibleSpoon) {
+ let objcInstanceViaClass
+ = SomeObjCClass(someSwiftInitRequirement: bridged)
+ let objcClassAsProtocol: SomeSwift3Protocol.Type = SomeObjCClass.self
+ let objcInstanceViaProtocol
+ = objcClassAsProtocol.init(someSwiftInitRequirement: unbridged)
+
+ var bridgedSink: RuncibleSpoon
+ var unbridgedSink: NSRuncibleSpoon
+
+ let swiftPropertyViaClass = objcInstanceViaClass.someSwiftPropertyRequirement
+ bridgedSink = swiftPropertyViaClass
+ let swiftPropertyViaProtocol = objcInstanceViaProtocol.someSwiftPropertyRequirement
+ unbridgedSink = swiftPropertyViaProtocol
+
+ objcInstanceViaClass.someSwiftMethodRequirement(bridged)
+ objcInstanceViaProtocol.someSwiftMethodRequirement(unbridged)
+
+ let swiftInstanceViaClass
+ = SomeSwift3Class(someObjCInitRequirement: unbridged)
+ let swiftClassAsProtocol: SomeObjCProtocol.Type = SomeSwift3Class.self
+ let swiftInstanceViaProtocol
+ = swiftClassAsProtocol.init(someObjCInitRequirement: bridged)
+
+ let objcPropertyViaClass = swiftInstanceViaClass.someObjCPropertyRequirement
+ unbridgedSink = objcPropertyViaClass
+ let objcPropertyViaProtocol = swiftInstanceViaProtocol.someObjCPropertyRequirement
+ bridgedSink = objcPropertyViaProtocol
+
+ swiftInstanceViaClass.someObjCMethodRequirement(unbridged)
+ swiftInstanceViaProtocol.someObjCMethodRequirement(bridged)
+
+ _ = bridgedSink
+ _ = unbridgedSink
+}
+
+public protocol SomeSwift4Protocol {
+ init(someSwiftInitRequirement: RuncibleSpoon)
+ func someSwiftMethodRequirement(_: RuncibleSpoon)
+ var someSwiftPropertyRequirement: RuncibleSpoon { get }
+}
+
+extension SomeObjCClass: SomeSwift4Protocol {}
+
+public class SomeSwift4Class: NSObject {
+ public required init(someObjCInitRequirement x: RuncibleSpoon) {
+ someObjCPropertyRequirement = x
+ }
+ public func someObjCMethodRequirement(_: RuncibleSpoon) {}
+ public var someObjCPropertyRequirement: RuncibleSpoon
+}
+
+extension SomeSwift4Class: SomeObjCProtocol {}
diff --git a/test/Compatibility/MixAndMatch/witness_change.swift b/test/Compatibility/MixAndMatch/witness_change.swift
new file mode 100644
index 0000000..f384cd8
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/witness_change.swift
@@ -0,0 +1,37 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-deserialization-recovery -emit-module -o %t/SomeObjCModule.swiftmodule -module-name SomeObjCModule -I %t -I %S/Inputs -swift-version 3 %S/Inputs/SomeObjCModuleX.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-deserialization-recovery -emit-module -o %t/SomeSwift3Module.swiftmodule -module-name SomeSwift3Module -I %t -I %S/Inputs -swift-version 3 %s
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-deserialization-recovery -emit-module -o %t/SomeSwift4Module.swiftmodule -module-name SomeSwift4Module -I %t -I %S/Inputs -swift-version 4 %S/Inputs/witness_change_swift4.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-deserialization-recovery -c -I %t -I %S/Inputs -swift-version 3 %S/Inputs/witness_change_swift3_leaf.swift
+
+// REQUIRES: objc_interop
+
+// Swift 3 sees the ObjC class NSRuncibleSpoon as the class, and uses methods
+// with type signatures involving NSRuncibleSpoon to conform to protocols
+// across the language boundary. Swift 4 sees the type as bridged to
+// a RuncibleSpoon value type, but still needs to be able to use conformances
+// declared by Swift 3.
+
+// Swift 3
+
+import SomeObjCModule
+
+_ = RuncibleSpoon()
+
+public class SomeSwift3Class: NSObject {
+ public required init(someObjCInitRequirement x: NSRuncibleSpoon) {
+ someObjCPropertyRequirement = x
+ }
+ public func someObjCMethodRequirement(_: NSRuncibleSpoon) {}
+ public var someObjCPropertyRequirement: NSRuncibleSpoon
+}
+extension SomeSwift3Class: SomeObjCProtocol {}
+
+public protocol SomeSwift3Protocol {
+ init(someSwiftInitRequirement: NSRuncibleSpoon)
+ func someSwiftMethodRequirement(_: NSRuncibleSpoon)
+ var someSwiftPropertyRequirement: NSRuncibleSpoon { get }
+}
+extension SomeObjCClass: SomeSwift3Protocol {}
+
diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift
index a78ab61..8bd3650 100644
--- a/test/Constraints/closures.swift
+++ b/test/Constraints/closures.swift
@@ -512,8 +512,7 @@
returnsArray().flatMap { $0 }.flatMap { }
// expected-warning@-1 {{expression of type 'Int' is unused}}
-// expected-warning@-2 {{Please use map instead.}}
-// expected-warning@-3 {{result of call to 'flatMap' is unused}}
+// expected-warning@-2 {{result of call to 'flatMap' is unused}}
// rdar://problem/30271695
_ = ["hi"].flatMap { $0.isEmpty ? nil : $0 }
diff --git a/test/Constraints/function_conversion.swift b/test/Constraints/function_conversion.swift
new file mode 100644
index 0000000..58375e5
--- /dev/null
+++ b/test/Constraints/function_conversion.swift
@@ -0,0 +1,23 @@
+// RUN: %target-typecheck-verify-swift -swift-version 3
+// RUN: %target-typecheck-verify-swift -swift-version 4
+
+// rdar://problem/31969605
+
+class Base {}
+class Derived : Base {}
+
+protocol Refined {}
+protocol Proto : Refined {}
+extension Base : Refined {}
+
+func baseFn(_: Base) {}
+
+func superclassConversion(fn: @escaping (Base) -> ()) {
+ let _: (Derived) -> () = fn
+}
+
+func existentialConversion(fn: @escaping (Refined) -> ()) {
+ let _: (Proto) -> () = fn
+ let _: (Base) -> () = fn
+ let _: (Derived) -> () = fn
+}
diff --git a/test/IDE/complete_with_header_import.swift b/test/IDE/complete_with_header_import.swift
index 2da9189..3ba7ab9 100644
--- a/test/IDE/complete_with_header_import.swift
+++ b/test/IDE/complete_with_header_import.swift
@@ -4,6 +4,11 @@
// RUN: %target-swift-ide-test -code-completion -pch-output-dir %t -source-filename %s -code-completion-token=TOP -import-objc-header %S/Inputs/header.h | %FileCheck %s -check-prefix=CHECK-TOP
// RUN: %target-swift-ide-test -code-completion -pch-output-dir %t -source-filename %s -code-completion-token=TYPE -import-objc-header %S/Inputs/header.h | %FileCheck %s -check-prefix=CHECK-TYPE
// RUN: stat %t/*.pch
+// RUN: cp %S/Inputs/header.h %t
+// RUN: %target-swift-ide-test -code-completion -pch-output-dir %t/pch -source-filename %s -code-completion-token=TOP -import-objc-header %t/header.h | %FileCheck %s -check-prefix=CHECK-TOP
+// RUN: stat %t/pch/*.pch
+// RUN: echo '// new stuff' >> %t/header.h
+// RUN: %target-swift-ide-test -code-completion -pch-output-dir %t/pch -source-filename %s -code-completion-token=TOP -import-objc-header %t/header.h | %FileCheck %s -check-prefix=CHECK-TOP
// REQUIRES: objc_interop
diff --git a/test/IDE/range_info_branches.swift b/test/IDE/range_info_branches.swift
new file mode 100644
index 0000000..049eea8
--- /dev/null
+++ b/test/IDE/range_info_branches.swift
@@ -0,0 +1,40 @@
+func foo(_ a: Bool) -> Int{
+ if a {
+ return 1
+ } else {
+ }
+ if a {
+ return 0
+ } else {
+ return 1
+ }
+}
+
+func foo1(_ a: Bool) {
+ if a {}
+ if a {}
+ else {}
+ if a {
+ return
+ } else {
+ return
+ }
+}
+
+// RUN: %target-swift-ide-test -range -pos=2:1 -end-pos 5:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-ERR
+// RUN: %target-swift-ide-test -range -pos=6:1 -end-pos 10:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-INT
+// RUN: %target-swift-ide-test -range -pos=14:1 -end-pos 14:10 -source-filename %s | %FileCheck %s -check-prefix=CHECK-VOID-NO-RETURN
+// RUN: %target-swift-ide-test -range -pos=15:1 -end-pos 16:10 -source-filename %s | %FileCheck %s -check-prefix=CHECK-VOID-NO-RETURN
+// RUN: %target-swift-ide-test -range -pos=17:1 -end-pos 21:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-VOID-RETURN
+
+// CHECK-ERR: <Type><<error type>></Type>
+// CHECK-ERR-NOT: <Exit>true</Exit>
+
+// CHECK-INT: <Type>Int</Type>
+// CHECK-INT: <Exit>true</Exit>
+
+// CHECK-VOID-NO-RETURN: <Type>Void</Type>
+// CHECK-VOID-NO-RETURN-NOT: <Exit>true</Exit>
+
+// CHECK-VOID-RETURN: <Type>Void</Type>
+// CHECK-VOID-RETURN: <Exit>true</Exit>
diff --git a/test/Interpreter/SDK/Inputs/test.arc b/test/Interpreter/SDK/Inputs/test.arc
new file mode 100644
index 0000000..780fd62
--- /dev/null
+++ b/test/Interpreter/SDK/Inputs/test.arc
Binary files differ
diff --git a/test/Interpreter/SDK/archive_compatibility.swift b/test/Interpreter/SDK/archive_compatibility.swift
new file mode 100644
index 0000000..19875d2
--- /dev/null
+++ b/test/Interpreter/SDK/archive_compatibility.swift
@@ -0,0 +1,131 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %target-build-swift %s -module-name=test -o %t/a.out
+// RUN: %target-run %t/a.out %S/Inputs/test.arc | %FileCheck %s
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+// UNSUPPORTED: OS=tvos
+// UNSUPPORTED: OS=watchos
+
+// This test checks if an archive, produced with the swift 3.1 compiler, can
+// still be read with the current compiler.
+
+import Foundation
+
+struct ABC {
+ class NestedClass : NSObject, NSCoding {
+ var i : Int
+
+ init(_ ii: Int) {
+ i = ii
+ }
+
+ required init(coder aDecoder: NSCoder) {
+ i = aDecoder.decodeInteger(forKey: "i")
+ }
+
+ func encode(with aCoder: NSCoder) {
+ aCoder.encode(i, forKey: "i")
+ }
+ }
+}
+
+private class PrivateClass : NSObject, NSCoding {
+ var pi : Int
+
+ init(_ ii: Int) {
+ pi = ii
+ }
+
+ required init(coder aDecoder: NSCoder) {
+ pi = aDecoder.decodeInteger(forKey: "pi")
+ }
+
+ func encode(with aCoder: NSCoder) {
+ aCoder.encode(pi, forKey: "pi")
+ }
+}
+
+class GenericClass<T> : NSObject, NSCoding {
+ var gi : Int
+
+ init(_ ii: Int) {
+ gi = ii
+ }
+
+ required init(coder aDecoder: NSCoder) {
+ gi = aDecoder.decodeInteger(forKey: "gi")
+ }
+
+ func encode(with aCoder: NSCoder) {
+ aCoder.encode(gi, forKey: "gi")
+ }
+}
+
+class TopLevel : NSObject, NSCoding {
+ var tli : Int
+
+ var nested: ABC.NestedClass?
+ fileprivate var priv: PrivateClass?
+ var generic : GenericClass<Int>?
+
+ init(_ ii: Int) {
+ tli = ii
+ }
+
+ required init(coder aDecoder: NSCoder) {
+ tli = aDecoder.decodeInteger(forKey: "tli")
+ nested = aDecoder.decodeObject(forKey: "nested") as? ABC.NestedClass
+ priv = aDecoder.decodeObject(forKey: "priv") as? PrivateClass
+ generic = aDecoder.decodeObject(forKey: "generic") as? GenericClass<Int>
+ }
+
+ func encode(with aCoder: NSCoder) {
+ aCoder.encode(tli, forKey: "tli")
+ aCoder.encode(nested, forKey: "nested")
+ aCoder.encode(priv, forKey: "priv")
+ aCoder.encode(generic, forKey: "generic")
+ }
+}
+
+func main() {
+
+ let args = CommandLine.arguments
+
+ let g = GenericClass<Int>(42)
+#if ENCODE
+ // This is how the archive was created with the swift 3.1 compiler.
+ let c = TopLevel(27)
+ c.nested = ABC.NestedClass(28)
+ c.priv = PrivateClass(29)
+ c.generic = g
+
+ NSKeyedArchiver.archiveRootObject(c, toFile: args[1])
+#else
+ if let u = NSKeyedUnarchiver.unarchiveObject(withFile: args[1]) {
+ if let x = u as? TopLevel {
+ // CHECK: top-level: 27
+ print("top-level: \(x.tli)")
+ if let n = x.nested {
+ // CHECK: nested: 28
+ print("nested: \(n.i)")
+ }
+ if let p = x.priv {
+ // CHECK: private: 29
+ print("private: \(p.pi)")
+ }
+ if let g = x.generic {
+ // CHECK: generic: 42
+ print("generic: \(g.gi)")
+ }
+ } else {
+ print(u)
+ }
+ } else {
+ print("nil")
+ }
+#endif
+}
+
+main()
+
diff --git a/test/Interpreter/SDK/archiving_generic_swift_class.swift b/test/Interpreter/SDK/archiving_generic_swift_class.swift
index 52c3bd6..b862e60 100644
--- a/test/Interpreter/SDK/archiving_generic_swift_class.swift
+++ b/test/Interpreter/SDK/archiving_generic_swift_class.swift
@@ -190,10 +190,10 @@
fatalError("unable to unarchive Foo<NSNumber>")
}
- // CHECK-LABEL: <_T04main3FooCySo8NSStringCGD: {{0x[0-9a-f]+}}> #0
+ // CHECK-LABEL: <_TtGC4main3FooCSo8NSString_: {{0x[0-9a-f]+}}> #0
// CHECK: one: one
// CHECK: two: two
- // CHECK-LABEL: <_T04main3FooCySo8NSNumberCGD: {{0x[0-9a-f]+}}> #0
+ // CHECK-LABEL: <_TtGC4main3FooCSo8NSNumber_: {{0x[0-9a-f]+}}> #0
// CHECK: one: 1
// CHECK: two: 2
dump(strings)
diff --git a/test/stdlib/FlatMapDiagnostics.swift.gyb b/test/stdlib/FlatMapDiagnostics.swift.gyb
deleted file mode 100644
index 0183eda..0000000
--- a/test/stdlib/FlatMapDiagnostics.swift.gyb
+++ /dev/null
@@ -1,39 +0,0 @@
-//===--- FlatMapDiagnostics.swift -----------------------------*- swift -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: %gyb %s -o %t/FlatMapDiagnostics.swift
-// RUN: %target-swift-frontend -typecheck -verify %t/FlatMapDiagnostics.swift
-
-
-% for Type in [
-% 'Sequence',
-% 'Collection',
-% 'LazySequenceProtocol',
-% 'LazyCollectionProtocol']:
-
-func testGeneric${Type}<T : ${Type}>(xs: T) {
- _ = xs.flatMap { $0 } // expected-warning {{Please use map instead.}}
-}
-
-% end
-
-func testArray(xs: [Int]) {
- _ = xs.flatMap { $0 } // expected-warning {{Please use map instead.}}
- _ = xs.lazy.flatMap { $0 } // expected-warning {{Please use map instead.}}
-}
-
-func testGenericLazyBidirectionalCollection<
- T : LazyCollectionProtocol & BidirectionalCollection
->(xs: T) where T.Elements : BidirectionalCollection {
- _ = xs.flatMap { $0 } // expected-warning {{Please use map instead.}}
-}
-
diff --git a/test/stdlib/RuntimeObjC.swift b/test/stdlib/RuntimeObjC.swift
index 055b937..78c3d1a 100644
--- a/test/stdlib/RuntimeObjC.swift
+++ b/test/stdlib/RuntimeObjC.swift
@@ -334,47 +334,54 @@
protocol ProtocolB {}
Runtime.test("Generic class ObjC runtime names") {
- expectEqual("_T01a12GenericClassCySiGD",
+ expectEqual("_TtGC1a12GenericClassSi_",
NSStringFromClass(GenericClass<Int>.self))
- expectEqual("_T01a12GenericClassCyAA11PlainStructVGD",
+ expectEqual("_TtGC1a12GenericClassVS_11PlainStruct_",
NSStringFromClass(GenericClass<PlainStruct>.self))
- expectEqual("_T01a12GenericClassCyAA9PlainEnumOGD",
+ expectEqual("_TtGC1a12GenericClassOS_9PlainEnum_",
NSStringFromClass(GenericClass<PlainEnum>.self))
- expectEqual("_T01a12GenericClassCyAA11PlainStructV_AA0C4EnumOAEtGD",
+ expectEqual("_TtGC1a12GenericClassTVS_11PlainStructOS_9PlainEnumS1___",
NSStringFromClass(GenericClass<(PlainStruct, PlainEnum, PlainStruct)>.self))
- expectEqual("_T01a12GenericClassCyAA11PlainStructVmGD",
+ expectEqual("_TtGC1a12GenericClassMVS_11PlainStruct_",
NSStringFromClass(GenericClass<PlainStruct.Type>.self))
- expectEqual("_T01a12GenericClassCyAA11PlainStructVAEmcGD",
+ expectEqual("_TtGC1a12GenericClassFMVS_11PlainStructS1__",
NSStringFromClass(GenericClass<(PlainStruct.Type) -> PlainStruct>.self))
- expectEqual("_T01a12GenericClassCyAA11PlainStructVAEmKcGD",
+ expectEqual("_TtGC1a12GenericClassFzMVS_11PlainStructS1__",
NSStringFromClass(GenericClass<(PlainStruct.Type) throws -> PlainStruct>.self))
- expectEqual("_T01a12GenericClassCySiAA11PlainStructV_AA0C4EnumOztcGD",
+ expectEqual("_TtGC1a12GenericClassFTVS_11PlainStructROS_9PlainEnum_Si_",
NSStringFromClass(GenericClass<(PlainStruct, inout PlainEnum) -> Int>.self))
- expectEqual("_T01a12GenericClassCyAA9ProtocolA_pGD",
+ expectEqual("_TtGC1a12GenericClassPS_9ProtocolA__",
NSStringFromClass(GenericClass<ProtocolA>.self))
- expectEqual("_T01a12GenericClassCyAA9ProtocolA_AA0C1BpGD",
+ expectEqual("_TtGC1a12GenericClassPS_9ProtocolAS_9ProtocolB__",
NSStringFromClass(GenericClass<ProtocolA & ProtocolB>.self))
- expectEqual("_T01a12GenericClassCyAA9ProtocolA_AA0C1BpXpGD",
+ expectEqual("_TtGC1a12GenericClassPMPS_9ProtocolAS_9ProtocolB__",
NSStringFromClass(GenericClass<(ProtocolA & ProtocolB).Type>.self))
- expectEqual("_T01a12GenericClassCyAA9ProtocolA_AA0C1BpmGD",
+ expectEqual("_TtGC1a12GenericClassMPS_9ProtocolAS_9ProtocolB__",
NSStringFromClass(GenericClass<(ProtocolB & ProtocolA).Protocol>.self))
- expectEqual("_T01a12GenericClassCySo7CFArrayCGD",
+ expectEqual("_TtGC1a12GenericClassCSo7CFArray_",
NSStringFromClass(GenericClass<CFArray>.self))
- expectEqual("_T01a12GenericClassCySo7DecimalVGD",
+ expectEqual("_TtGC1a12GenericClassVSo7Decimal_",
NSStringFromClass(GenericClass<Decimal>.self))
- expectEqual("_T01a12GenericClassCySo8NSObjectCGD",
+ expectEqual("_TtGC1a12GenericClassCSo8NSObject_",
NSStringFromClass(GenericClass<NSObject>.self))
- expectEqual("_T01a12GenericClassCySo8NSObjectCGD",
+ expectEqual("_TtGC1a12GenericClassCSo8NSObject_",
NSStringFromClass(GenericClass<NSObject>.self))
- expectEqual("_T01a12GenericClassCySo9NSCopying_pGD",
+ expectEqual("_TtGC1a12GenericClassPSo9NSCopying__",
NSStringFromClass(GenericClass<NSCopying>.self))
- expectEqual("_T01a12GenericClassCySo9NSCopying_AA9ProtocolAAA0D1BpGD",
+ expectEqual("_TtGC1a12GenericClassPSo9NSCopyingS_9ProtocolAS_9ProtocolB__",
NSStringFromClass(GenericClass<ProtocolB & NSCopying & ProtocolA>.self))
- expectEqual("_T01a17MultiGenericClassCyAA0B6StructVySiGAA0B4EnumOyAHySiGGGD",
+ expectEqual("_TtGC1a12GenericClassXcCS_9SomeClassS_9ProtocolA__",
+ NSStringFromClass(GenericClass<ProtocolA & SomeClass>.self))
+ expectEqual("_TtGC1a12GenericClassPS_9ProtocolAs9AnyObject__",
+ NSStringFromClass(GenericClass<ProtocolA & AnyObject>.self))
+ expectEqual("_TtGC1a12GenericClassPs9AnyObject__",
+ NSStringFromClass(GenericClass<AnyObject>.self))
+
+ expectEqual("_TtGC1a17MultiGenericClassGVS_13GenericStructSi_GOS_11GenericEnumGS2_Si___",
NSStringFromClass(MultiGenericClass<GenericStruct<Int>,
GenericEnum<GenericEnum<Int>>>.self))
}
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
index cea03ff..e4f3c86 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
@@ -1337,7 +1337,7 @@
case RangeKind::SingleExpression: {
SmallString<64> SS;
llvm::raw_svector_ostream OS(SS);
- Info.Ty.print(OS);
+ Info.ExitInfo.getPointer()->print(OS);
Result.ExprType = OS.str();
Receiver(Result);
return;
diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index d295197..355bda1 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -960,6 +960,8 @@
dash-dash
+skip-test-lldb
+
swift-install-components=compiler;clang-builtin-headers;stdlib;sdk-overlay;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers
llvm-install-components=libclang;libclang-headers
diff --git a/validation-test/stdlib/CollectionDiagnostics.swift b/validation-test/stdlib/CollectionDiagnostics.swift
index 775fcee..f83e8b4 100644
--- a/validation-test/stdlib/CollectionDiagnostics.swift
+++ b/validation-test/stdlib/CollectionDiagnostics.swift
@@ -23,7 +23,7 @@
fatalError("unreachable")
}
- // expected-note@+3 {{possibly intended match 'CollectionWithBadSubSequence.SubSequence' (aka 'OpaqueValue<Int8>') does not conform to 'Sequence'}}
+ // expected-note@+3 {{possibly intended match}}
// expected-note@+2 {{possibly intended match}}
// expected-note@+1 {{possibly intended match}}
typealias SubSequence = OpaqueValue<Int8>
diff --git a/validation-test/stdlib/String.swift b/validation-test/stdlib/String.swift
index 5ca97e8..a0a8a5b 100644
--- a/validation-test/stdlib/String.swift
+++ b/validation-test/stdlib/String.swift
@@ -192,9 +192,7 @@
expectEqual("a", acceptor[donor.startIndex])
}
-StringTests.test("ForeignIndexes/subscript(Index)/OutOfBoundsTrap")
- .skip(.always("<rdar://problem/31992473>"))
- .code {
+StringTests.test("ForeignIndexes/subscript(Index)/OutOfBoundsTrap") {
let donor = "abcdef"
let acceptor = "uvw"