Merge pull request #15864 from jrose-apple/get-set-stop
Diagnose unavailable getters and setters
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 310aea1..3ca27c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -311,6 +311,10 @@
"Enable runtime function counters and expose the API."
FALSE)
+option(SWIFT_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING
+ "Build stdlibCore with exclusivity checking enabled"
+ FALSE)
+
#
# End of user-configurable options.
#
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 7d70616..9e5215b 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -1265,6 +1265,8 @@
"expected an attribute name", ())
ERROR(unknown_attribute,none,
"unknown attribute '%0'", (StringRef))
+ERROR(unexpected_lparen_in_attribute,none,
+ "unexpected '(' in attribute '%0'", (StringRef))
ERROR(duplicate_attribute,none,
"duplicate %select{attribute|modifier}0", (bool))
NOTE(previous_attribute,none,
diff --git a/include/swift/Basic/Statistic.h b/include/swift/Basic/Statistic.h
index 7f9e48b..228a139 100644
--- a/include/swift/Basic/Statistic.h
+++ b/include/swift/Basic/Statistic.h
@@ -205,16 +205,16 @@
/// entity type, and produce a tracer that's either active or inert depending
/// on whether the provided \p Reporter is null (nullptr means "tracing is
/// disabled").
- FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName);
- FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
+ FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName);
+ FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
const Decl *D);
- FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
+ FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
const ProtocolConformance *P);
- FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
+ FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
const clang::Decl *D);
- FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
+ FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
const Expr *E);
- FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
+ FrontendStatsTracer(UnifiedStatsReporter *Reporter, StringRef EventName,
const SILFunction *F);
};
@@ -225,20 +225,61 @@
// for those entity types. If you want to trace those types, it's assumed you're
// linking with the object files that define the tracer.
-template<> const UnifiedStatsReporter::TraceFormatter*
+template <>
+const UnifiedStatsReporter::TraceFormatter *
FrontendStatsTracer::getTraceFormatter<const Decl *>();
-template<> const UnifiedStatsReporter::TraceFormatter*
+template <>
+const UnifiedStatsReporter::TraceFormatter *
FrontendStatsTracer::getTraceFormatter<const ProtocolConformance *>();
-template<> const UnifiedStatsReporter::TraceFormatter*
+template <>
+const UnifiedStatsReporter::TraceFormatter *
FrontendStatsTracer::getTraceFormatter<const clang::Decl *>();
-template<> const UnifiedStatsReporter::TraceFormatter*
+template <>
+const UnifiedStatsReporter::TraceFormatter *
FrontendStatsTracer::getTraceFormatter<const Expr *>();
-template<> const UnifiedStatsReporter::TraceFormatter*
+template <>
+const UnifiedStatsReporter::TraceFormatter *
FrontendStatsTracer::getTraceFormatter<const SILFunction *>();
-}
+// Provide inline definitions for the delegating constructors. These avoid
+// introducing a circular dependency between libParse and libSIL. They are
+// marked as `inline` explicitly to prevent ODR violations due to multiple
+// emissions. We cannot force the inlining by defining them in the declaration
+// due to the explicit template specializations of the `getTraceFormatter`,
+// which is declared in the `FrontendStatsTracer` scope (the nested name
+// specifier scope cannot be used to declare them).
+
+inline FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R,
+ StringRef S)
+ : FrontendStatsTracer(R, S, nullptr, nullptr) {}
+
+inline FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R,
+ StringRef S, const Decl *D)
+ : FrontendStatsTracer(R, S, D, getTraceFormatter<const Decl *>()) {}
+
+inline FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R,
+ StringRef S,
+ const ProtocolConformance *P)
+ : FrontendStatsTracer(R, S, P,
+ getTraceFormatter<const ProtocolConformance *>()) {}
+
+inline FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R,
+ StringRef S,
+ const clang::Decl *D)
+ : FrontendStatsTracer(R, S, D, getTraceFormatter<const clang::Decl *>()) {}
+
+inline FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R,
+ StringRef S, const Expr *E)
+ : FrontendStatsTracer(R, S, E, getTraceFormatter<const Expr *>()) {}
+
+inline FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R,
+ StringRef S,
+ const SILFunction *F)
+ : FrontendStatsTracer(R, S, F, getTraceFormatter<const SILFunction *>()) {}
+
+} // namespace swift
#endif // SWIFT_BASIC_STATISTIC_H
diff --git a/include/swift/IRGen/IRGenPublic.h b/include/swift/IRGen/IRGenPublic.h
index d344769..c379919 100644
--- a/include/swift/IRGen/IRGenPublic.h
+++ b/include/swift/IRGen/IRGenPublic.h
@@ -14,9 +14,12 @@
namespace llvm {
class LLVMContext;
+ template<typename T, unsigned N> class SmallVector;
}
namespace swift {
+class ASTContext;
+class LinkLibrary;
class SILModule;
namespace irgen {
@@ -33,6 +36,20 @@
/// Delete the IRGenModule and IRGenerator obtained by the above call.
void deleteIRGenModule(std::pair<IRGenerator *, IRGenModule *> &Module);
+/// Collect the set of libraries to autolink against by mining the
+/// external definitions stored in an AST context.
+///
+/// This entire thing is a hack that we shouldn't need, but it reflects the
+/// fact that we can end up referencing something via an external definition
+/// (e.g., an imported Clang declaration) indirectly via the Clang importer
+/// that would not be visible directly. In such cases, we would fail to
+/// link against the shared library that defines the entity or an overlay that
+/// is needed as part of its import from Clang (e.g., the Foundation overlay
+/// is needed when bridging NSString, even if there is no other mention of
+/// an entity from the Foundation overlay).
+llvm::SmallVector<LinkLibrary, 4> collectLinkLibrariesFromExternals(
+ ASTContext &ctx);
+
} // end namespace irgen
} // end namespace swift
diff --git a/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h b/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h
index 2c9ed07..db62cb1 100644
--- a/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h
@@ -769,12 +769,6 @@
/// address of a contained property escapes, but not the object itself.
bool canEscapeTo(SILValue V, FullApplySite FAS);
- /// Returns true if the value \p V or its content can escape to the
- /// function call \p FAS.
- /// This is the same as above, except that it returns true if an address of
- /// a contained property escapes.
- bool canObjectOrContentEscapeTo(SILValue V, FullApplySite FAS);
-
/// Returns true if the value \p V can escape to the release-instruction \p
/// RI. This means that \p RI may release \p V or any called destructor may
/// access (or release) \p V.
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index b71cb0a..1642439 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -2878,12 +2878,13 @@
}
PrintWithColorRAII(out, ParenthesisColor) << ')';
});
+
+ for (auto conformance : normal->getSignatureConformances()) {
+ out << '\n';
+ conformance.dump(out, indent + 2);
+ }
}
- for (auto conformance : normal->getSignatureConformances()) {
- out << '\n';
- conformance.dump(out, indent + 2);
- }
for (auto requirement : normal->getConditionalRequirements()) {
out << '\n';
out.indent(indent + 2);
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 526d3d3..0c6a1e8 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -1309,7 +1309,7 @@
case Concrete:
return parent->withoutRedundantSubpath(builder, start, end)
- ->viaParent(builder, getAssociatedType());
+ ->viaConcrete(builder, getProtocolConformance());
case Derived:
return parent->withoutRedundantSubpath(builder, start, end)
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index 866018d..6ed4015 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -1208,8 +1208,14 @@
void
SourceFile::collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const {
- for (auto importPair : Imports)
- importPair.first.second->collectLinkLibraries(callback);
+
+ const_cast<SourceFile *>(this)->forAllVisibleModules([&](swift::ModuleDecl::ImportedModule import) {
+ swift::ModuleDecl *next = import.second;
+ if (next->getName() == getParentModule()->getName())
+ return;
+
+ next->collectLinkLibraries(callback);
+ });
}
bool ModuleDecl::walk(ASTWalker &Walker) {
diff --git a/lib/Basic/Statistic.cpp b/lib/Basic/Statistic.cpp
index accc584..35fceb3 100644
--- a/lib/Basic/Statistic.cpp
+++ b/lib/Basic/Statistic.cpp
@@ -453,35 +453,6 @@
FrontendStatsTracer::FrontendStatsTracer() = default;
-FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S)
- : FrontendStatsTracer(R, S, nullptr, nullptr)
-{}
-
-FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
- const Decl *D)
- : FrontendStatsTracer(R, S, D, getTraceFormatter<const Decl *>())
-{}
-
-FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
- const ProtocolConformance *P)
- : FrontendStatsTracer(R, S, P,
- getTraceFormatter<const ProtocolConformance *>()) {}
-
-FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
- const Expr *E)
- : FrontendStatsTracer(R, S, E, getTraceFormatter<const Expr *>())
-{}
-
-FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
- const clang::Decl *D)
- : FrontendStatsTracer(R, S, D, getTraceFormatter<const clang::Decl *>())
-{}
-
-FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
- const SILFunction *F)
- : FrontendStatsTracer(R, S, F, getTraceFormatter<const SILFunction *>())
-{}
-
FrontendStatsTracer&
FrontendStatsTracer::operator=(FrontendStatsTracer&& other)
{
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 3ff4742..bbc4482 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -483,14 +483,8 @@
for (auto *localDecl : SF.LocalTypeDecls)
emitGlobalDecl(localDecl);
- SF.forAllVisibleModules([&](swift::ModuleDecl::ImportedModule import) {
- swift::ModuleDecl *next = import.second;
- if (next->getName() == SF.getParentModule()->getName())
- return;
-
- next->collectLinkLibraries([this](LinkLibrary linkLib) {
+ SF.collectLinkLibraries([this](LinkLibrary linkLib) {
this->addLinkLibrary(linkLib);
- });
});
if (ObjCInterop)
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 70f7308..e66b9b9 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -3348,7 +3348,7 @@
if (auto classType = dyn_cast<ClassType>(type)) {
assert(!classType.getParent());
auto classDecl = classType->getDecl();
- assert(classDecl->isForeign());
+ assert(classDecl->getForeignClassKind() == ClassDecl::ForeignKind::CFType);
ForeignClassMetadataBuilder builder(*this, classDecl, init);
builder.layout();
@@ -3389,7 +3389,8 @@
if (auto enclosing = type->getNominalParent()) {
auto canonicalEnclosing = enclosing->getCanonicalType();
if (requiresForeignTypeMetadata(canonicalEnclosing)) {
- getAddrOfForeignTypeMetadataCandidate(canonicalEnclosing);
+ (void)getTypeMetadataAccessFunction(*this, canonicalEnclosing,
+ ForDefinition);
}
}
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index a7992c9..62ad4e8 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -2187,8 +2187,19 @@
// Trigger the lazy emission of the foreign type metadata.
CanType conformingType = conf->getType()->getCanonicalType();
- if (requiresForeignTypeMetadata(conformingType))
- (void)getAddrOfForeignTypeMetadataCandidate(conformingType);
+ if (requiresForeignTypeMetadata(conformingType)) {
+ // Make sure we emit the metadata access function.
+ (void)getTypeMetadataAccessFunction(*this, conformingType,
+ ForDefinition);
+
+ // Make sure we emit the nominal type descriptor.
+ auto *nominal = conformingType->getAnyNominal();
+ auto entity = LinkEntity::forNominalTypeDescriptor(nominal);
+ if (auto entry = GlobalVars[entity])
+ return;
+
+ emitLazyTypeContextDescriptor(*this, nominal, RequireMetadata);
+ }
}
/// True if a function's signature in LLVM carries polymorphic parameters.
diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp
index 3a7ad3c..92fea19 100644
--- a/lib/IRGen/IRGen.cpp
+++ b/lib/IRGen/IRGen.cpp
@@ -19,6 +19,7 @@
#include "swift/AST/DiagnosticsIRGen.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/LinkLibrary.h"
+#include "swift/AST/ProtocolConformance.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/Dwarf.h"
#include "swift/Basic/Platform.h"
@@ -26,6 +27,7 @@
#include "swift/Basic/Timer.h"
#include "swift/Basic/Version.h"
#include "swift/ClangImporter/ClangImporter.h"
+#include "swift/ClangImporter/ClangModule.h"
#include "swift/IRGen/IRGenPublic.h"
#include "swift/IRGen/IRGenSILPasses.h"
#include "swift/LLVMPasses/Passes.h"
@@ -792,20 +794,8 @@
});
// Hack to handle thunks eagerly synthesized by the Clang importer.
- swift::ModuleDecl *prev = nullptr;
- for (auto external : Ctx.ExternalDefinitions) {
- swift::ModuleDecl *next = external->getModuleContext();
- if (next == prev)
- continue;
- prev = next;
-
- if (next->getName() == M->getName())
- continue;
-
- next->collectLinkLibraries([&](LinkLibrary linkLib) {
- IGM.addLinkLibrary(linkLib);
- });
- }
+ for (const auto &linkLib : collectLinkLibrariesFromExternals(Ctx))
+ IGM.addLinkLibrary(linkLib);
if (!IGM.finalize())
return nullptr;
@@ -977,21 +967,9 @@
});
// Hack to handle thunks eagerly synthesized by the Clang importer.
- swift::ModuleDecl *prev = nullptr;
- for (auto external : Ctx.ExternalDefinitions) {
- swift::ModuleDecl *next = external->getModuleContext();
- if (next == prev)
- continue;
- prev = next;
-
- if (next->getName() == M->getName())
- continue;
-
- next->collectLinkLibraries([&](LinkLibrary linkLib) {
- PrimaryGM->addLinkLibrary(linkLib);
- });
- }
-
+ for (const auto &linkLib : collectLinkLibrariesFromExternals(Ctx))
+ PrimaryGM->addLinkLibrary(linkLib);
+
llvm::StringSet<> referencedGlobals;
for (auto it = irgen.begin(); it != irgen.end(); ++it) {
@@ -1172,3 +1150,20 @@
return true;
return false;
}
+
+SmallVector<LinkLibrary, 4> irgen::collectLinkLibrariesFromExternals(
+ ASTContext &ctx) {
+ SmallVector<LinkLibrary, 4> result;
+ auto addLinkLibrary = [&](LinkLibrary linkLib) {
+ result.push_back(linkLib);
+ };
+
+ llvm::SmallPtrSet<ModuleDecl *, 8> known;
+ for (auto external : ctx.ExternalDefinitions) {
+ swift::ModuleDecl *module = external->getModuleContext();
+ if (known.insert(module).second)
+ module->collectLinkLibraries(addLinkLibrary);
+ }
+
+ return result;
+}
diff --git a/lib/IRGen/MetadataLayout.cpp b/lib/IRGen/MetadataLayout.cpp
index 5d77e7d..bb8eeb8 100644
--- a/lib/IRGen/MetadataLayout.cpp
+++ b/lib/IRGen/MetadataLayout.cpp
@@ -111,7 +111,7 @@
auto &entry = MetadataLayouts[decl];
if (!entry) {
if (auto theClass = dyn_cast<ClassDecl>(decl)) {
- if (theClass->isForeign())
+ if (theClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType)
entry = new ForeignClassMetadataLayout(*this, theClass);
else
entry = new ClassMetadataLayout(*this, theClass);
@@ -456,7 +456,7 @@
Size irgen::getClassFieldOffsetOffset(IRGenModule &IGM, ClassDecl *theClass,
VarDecl *field) {
- if (theClass->isForeign())
+ if (theClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType)
return Size();
return IGM.getClassMetadataLayout(theClass).getStaticFieldOffset(field);
@@ -602,7 +602,8 @@
ForeignClassMetadataLayout::ForeignClassMetadataLayout(IRGenModule &IGM,
ClassDecl *theClass)
: MetadataLayout(Kind::ForeignClass), Class(theClass) {
- assert(theClass->isForeign() && "Not a foreign class");
+ assert(theClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
+ "Not a foreign class");
struct Scanner : LayoutScanner<Scanner, ForeignClassMetadataScanner> {
using super = LayoutScanner;
diff --git a/lib/Immediate/Immediate.cpp b/lib/Immediate/Immediate.cpp
index 6dfe2f5..1396858 100644
--- a/lib/Immediate/Immediate.cpp
+++ b/lib/Immediate/Immediate.cpp
@@ -27,6 +27,7 @@
#include "swift/Basic/LLVM.h"
#include "swift/Basic/LLVMContext.h"
#include "swift/Frontend/Frontend.h"
+#include "swift/IRGen/IRGenPublic.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/config.h"
@@ -224,13 +225,9 @@
});
// Hack to handle thunks eagerly synthesized by the Clang importer.
- swift::ModuleDecl *prev = nullptr;
- for (auto external : CI.getASTContext().ExternalDefinitions) {
- swift::ModuleDecl *next = external->getModuleContext();
- if (next == prev)
- continue;
- next->collectLinkLibraries(addLinkLibrary);
- prev = next;
+ for (const auto &linkLib :
+ irgen::collectLinkLibrariesFromExternals(CI.getASTContext())) {
+ addLinkLibrary(linkLib);
}
tryLoadLibraries(AllLinkLibraries, CI.getASTContext().SearchPathOpts,
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index d6c2e34..d9f35b5 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2522,6 +2522,7 @@
DeclResult = parseDeclOperator(Flags, Attributes);
break;
case tok::kw_precedencegroup:
+ DeclParsingContext.setCreateSyntax(SyntaxKind::PrecedenceGroupDecl);
DeclResult = parseDeclPrecedenceGroup(Flags, Attributes);
break;
case tok::kw_protocol:
@@ -6414,6 +6415,14 @@
diagnose(Tok, diag::expected_precedencegroup_lbrace);
return createInvalid();
}
+ // Empty body.
+ if (Tok.is(tok::r_brace)) {
+ // Create empty attribute list.
+ SyntaxParsingContext(SyntaxContext,
+ SyntaxKind::PrecedenceGroupAttributeList);
+ rbraceLoc = consumeToken(tok::r_brace);
+ return makeParserResult(create());
+ }
auto abortBody = [&] {
skipUntilDeclRBrace();
@@ -6435,8 +6444,9 @@
}
};
+
// Parse the attributes in the body.
- while (!consumeIf(tok::r_brace, rbraceLoc)) {
+ while (!Tok.is(tok::r_brace)) {
if (!Tok.is(tok::identifier)) {
diagnose(Tok, diag::expected_precedencegroup_attribute);
return abortBody();
@@ -6445,6 +6455,8 @@
auto attrName = Tok.getText();
if (attrName == "associativity") {
+ SyntaxParsingContext AttrCtxt(SyntaxContext,
+ SyntaxKind::PrecedenceGroupAssociativity);
// "associativity" is considered as a contextual keyword.
TokReceiver->registerTokenKindChange(Tok.getLoc(),
tok::contextual_keyword);
@@ -6471,6 +6483,8 @@
}
if (attrName == "assignment") {
+ SyntaxParsingContext AttrCtxt(SyntaxContext,
+ SyntaxKind::PrecedenceGroupAssignment);
parseAttributePrefix(assignmentKeywordLoc);
// "assignment" is considered as a contextual keyword.
@@ -6490,6 +6504,8 @@
bool isLowerThan = false;
if (attrName == "higherThan" ||
(isLowerThan = (attrName == "lowerThan"))) {
+ SyntaxParsingContext AttrCtxt(SyntaxContext,
+ SyntaxKind::PrecedenceGroupRelation);
// "lowerThan" and "higherThan" are contextual keywords.
TokReceiver->registerTokenKindChange(Tok.getLoc(),
tok::contextual_keyword);
@@ -6498,6 +6514,8 @@
auto &relations = (isLowerThan ? lowerThan : higherThan);
do {
+ SyntaxParsingContext NameCtxt(SyntaxContext,
+ SyntaxKind::PrecedenceGroupNameElement);
if (!Tok.is(tok::identifier)) {
diagnose(Tok, diag::expected_precedencegroup_relation, attrName);
return abortBody();
@@ -6505,13 +6523,19 @@
auto name = Context.getIdentifier(Tok.getText());
auto loc = consumeToken();
relations.push_back({loc, name, nullptr});
- } while (consumeIf(tok::comma));
+ if (!consumeIf(tok::comma))
+ break;
+ } while (true);
+ SyntaxContext->collectNodesInPlace(SyntaxKind::PrecedenceGroupNameList);
continue;
}
diagnose(Tok, diag::unknown_precedencegroup_attribute, attrName);
return abortBody();
}
+ SyntaxContext->collectNodesInPlace(SyntaxKind::PrecedenceGroupAttributeList);
+ rbraceLoc = consumeToken(tok::r_brace);
+
auto result = create();
if (invalid) result->setInvalid();
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index b71429c..8b1bbe2 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -2187,24 +2187,30 @@
SourceLoc UnknownAttrLoc;
while (Tok.is(tok::at_sign)) {
SyntaxParsingContext AttrCtx(SyntaxContext, SyntaxKind::Attribute);
- UnknownAttrLoc = consumeToken(tok::at_sign);
- if (Tok.isContextualKeyword("unknown")) {
+ if (peekToken().isContextualKeyword("unknown")) {
+ if (!UnknownAttrLoc.isValid()) {
+ UnknownAttrLoc = consumeToken(tok::at_sign);
+ } else {
+ diagnose(Tok, diag::duplicate_attribute, false);
+ diagnose(UnknownAttrLoc, diag::previous_attribute, false);
+ consumeToken(tok::at_sign);
+ }
consumeIdentifier();
- // Form an empty TokenList for the arguments of the 'Attribute' Syntax
- // node.
- SyntaxParsingContext(SyntaxContext, SyntaxKind::TokenList);
+ SyntaxParsingContext Args(SyntaxContext, SyntaxKind::TokenList);
+ if (Tok.is(tok::l_paren)) {
+ diagnose(Tok, diag::unexpected_lparen_in_attribute, "unknown");
+ skipSingle();
+ }
} else {
- UnknownAttrLoc = SourceLoc();
-
+ consumeToken(tok::at_sign);
diagnose(Tok, diag::unknown_attribute, Tok.getText());
consumeIdentifier();
- if (Tok.is(tok::l_paren)) {
- SyntaxParsingContext Args(SyntaxContext, SyntaxKind::TokenList);
+ SyntaxParsingContext Args(SyntaxContext, SyntaxKind::TokenList);
+ if (Tok.is(tok::l_paren))
skipSingle();
- }
}
}
@@ -2213,8 +2219,10 @@
if (Tok.is(tok::kw_case)) {
Status |=
::parseStmtCase(*this, CaseLoc, CaseLabelItems, BoundDecls, ColonLoc);
- } else {
+ } else if (Tok.is(tok::kw_default)) {
Status |= parseStmtCaseDefault(*this, CaseLoc, CaseLabelItems, ColonLoc);
+ } else {
+ llvm_unreachable("isAtStartOfSwitchCase() lied.");
}
assert(!CaseLabelItems.empty() && "did not parse any labels?!");
diff --git a/lib/SIL/Linker.cpp b/lib/SIL/Linker.cpp
index e2d36f8..56b9108 100644
--- a/lib/SIL/Linker.cpp
+++ b/lib/SIL/Linker.cpp
@@ -58,41 +58,11 @@
return true;
}
-/// Deserialize the VTable mapped to C if it exists and all SIL the VTable
-/// transitively references.
-///
-/// This method assumes that the caller made sure that no vtable existed in
-/// Mod.
-SILVTable *SILLinkerVisitor::processClassDecl(const ClassDecl *C) {
- // If we are not linking anything, bail.
- if (Mode == LinkingMode::LinkNone)
- return nullptr;
-
- // Attempt to load the VTable from the SerializedSILLoader. If we
- // fail... bail...
- SILVTable *Vtbl = Loader->lookupVTable(C);
- if (!Vtbl)
- return nullptr;
-
- // Otherwise, add all the vtable functions in Vtbl to the function
- // processing list...
- for (auto &E : Vtbl->getEntries())
- Worklist.push_back(E.Implementation);
-
- // And then transitively deserialize all SIL referenced by those functions.
- process();
-
- // Return the deserialized Vtbl.
- return Vtbl;
-}
-
+/// Deserialize the given VTable all SIL the VTable transitively references.
bool SILLinkerVisitor::linkInVTable(ClassDecl *D) {
// Attempt to lookup the Vtbl from the SILModule.
SILVTable *Vtbl = Mod.lookUpVTable(D);
-
- // If the SILModule does not have the VTable, attempt to deserialize the
- // VTable. If we fail to do that as well, bail.
- if (!Vtbl || !(Vtbl = Loader->lookupVTable(D->getName())))
+ if (!Vtbl)
return false;
// Ok we found our VTable. Visit each function referenced by the VTable. If
@@ -120,16 +90,17 @@
performFuncDeserialization |= visitApplySubstitutions(
sig->getSubstitutionMap(AI->getSubstitutions()));
}
-
- // Ok we have a function ref inst, grab the callee.
- SILFunction *Callee = AI->getReferencedFunction();
- if (!Callee)
- return performFuncDeserialization;
- if (isLinkAll() ||
- hasSharedVisibility(Callee->getLinkage())) {
- addFunctionToWorklist(Callee);
- return true;
+ return performFuncDeserialization;
+}
+
+bool SILLinkerVisitor::visitTryApplyInst(TryApplyInst *TAI) {
+ bool performFuncDeserialization = false;
+
+ if (auto sig = TAI->getCallee()->getType().castTo<SILFunctionType>()
+ ->getGenericSignature()) {
+ performFuncDeserialization |= visitApplySubstitutions(
+ sig->getSubstitutionMap(TAI->getSubstitutions()));
}
return performFuncDeserialization;
@@ -144,16 +115,6 @@
sig->getSubstitutionMap(PAI->getSubstitutions()));
}
- SILFunction *Callee = PAI->getReferencedFunction();
- if (!Callee)
- return performFuncDeserialization;
-
- if (isLinkAll() ||
- hasSharedVisibility(Callee->getLinkage())) {
- addFunctionToWorklist(Callee);
- return true;
- }
-
return performFuncDeserialization;
}
@@ -353,6 +314,9 @@
}
bool SILLinkerVisitor::visitAllocRefInst(AllocRefInst *ARI) {
+ if (!isLinkAll())
+ return false;
+
// Grab the class decl from the alloc ref inst.
ClassDecl *D = ARI->getType().getClassOrBoundGenericClass();
if (!D)
@@ -362,6 +326,9 @@
}
bool SILLinkerVisitor::visitMetatypeInst(MetatypeInst *MI) {
+ if (!isLinkAll())
+ return false;
+
CanType instTy = MI->getType().castTo<MetatypeType>().getInstanceType();
ClassDecl *C = instTy.getClassOrBoundGenericClass();
if (!C)
diff --git a/lib/SIL/Linker.h b/lib/SIL/Linker.h
index 8cb5a3a..07c4fd5 100644
--- a/lib/SIL/Linker.h
+++ b/lib/SIL/Linker.h
@@ -64,6 +64,7 @@
bool visitSILInstruction(SILInstruction *I) { return false; }
bool visitApplyInst(ApplyInst *AI);
+ bool visitTryApplyInst(TryApplyInst *TAI);
bool visitPartialApplyInst(PartialApplyInst *PAI);
bool visitFunctionRefInst(FunctionRefInst *FRI);
bool visitProtocolConformance(ProtocolConformanceRef C,
diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp
index 7eb36f1..32d34fe 100644
--- a/lib/SIL/SILModule.cpp
+++ b/lib/SIL/SILModule.cpp
@@ -614,9 +614,7 @@
return R->second;
// If that fails, try to deserialize it. If that fails, return nullptr.
- SILVTable *Vtbl =
- SILLinkerVisitor(*this, getSILLoader(), SILModule::LinkingMode::LinkAll)
- .processClassDecl(C);
+ SILVTable *Vtbl = getSILLoader()->lookupVTable(C);
if (!Vtbl)
return nullptr;
diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
index 15bf1ec..dd931ce 100644
--- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
@@ -1824,39 +1824,7 @@
return true;
// No hidden escapes: check if the Node is reachable from the UsePoint.
- return ConGraph->isUsePoint(UsePoint, Node);
-}
-
-bool EscapeAnalysis::canEscapeTo(SILValue V, FullApplySite FAS) {
- // If it's not a local object we don't know anything about the value.
- if (!pointsToLocalObject(V))
- return true;
- auto *ConGraph = getConnectionGraph(FAS.getFunction());
- return canEscapeToUsePoint(V, FAS.getInstruction(), ConGraph);
-}
-
-static bool hasReferenceSemantics(SILType T) {
- // Exclude address types.
- return T.isObject() && T.hasReferenceSemantics();
-}
-
-bool EscapeAnalysis::canObjectOrContentEscapeTo(SILValue V, FullApplySite FAS) {
- // If it's not a local object we don't know anything about the value.
- if (!pointsToLocalObject(V))
- return true;
-
- auto *ConGraph = getConnectionGraph(FAS.getFunction());
- CGNode *Node = ConGraph->getNodeOrNull(V, this);
- if (!Node)
- return true;
-
- // First check if there are escape paths which we don't explicitly see
- // in the graph.
- if (Node->escapesInsideFunction(isNotAliasingArgument(V)))
- return true;
-
// Check if the object itself can escape to the called function.
- SILInstruction *UsePoint = FAS.getInstruction();
if (ConGraph->isUsePoint(UsePoint, Node))
return true;
@@ -1880,6 +1848,19 @@
return false;
}
+bool EscapeAnalysis::canEscapeTo(SILValue V, FullApplySite FAS) {
+ // If it's not a local object we don't know anything about the value.
+ if (!pointsToLocalObject(V))
+ return true;
+ auto *ConGraph = getConnectionGraph(FAS.getFunction());
+ return canEscapeToUsePoint(V, FAS.getInstruction(), ConGraph);
+}
+
+static bool hasReferenceSemantics(SILType T) {
+ // Exclude address types.
+ return T.isObject() && T.hasReferenceSemantics();
+}
+
bool EscapeAnalysis::canEscapeTo(SILValue V, RefCountingInst *RI) {
// If it's not a local object we don't know anything about the value.
if (!pointsToLocalObject(V))
diff --git a/lib/SILOptimizer/Analysis/MemoryBehavior.cpp b/lib/SILOptimizer/Analysis/MemoryBehavior.cpp
index 527fb9a..17ebb80 100644
--- a/lib/SILOptimizer/Analysis/MemoryBehavior.cpp
+++ b/lib/SILOptimizer/Analysis/MemoryBehavior.cpp
@@ -227,7 +227,7 @@
MemBehavior MemoryBehaviorVisitor::visitTryApplyInst(TryApplyInst *AI) {
MemBehavior Behavior = MemBehavior::MayHaveSideEffects;
// Ask escape analysis.
- if (!EA->canObjectOrContentEscapeTo(V, AI))
+ if (!EA->canEscapeTo(V, AI))
Behavior = MemBehavior::None;
// Otherwise be conservative and return that we may have side effects.
@@ -290,7 +290,7 @@
Behavior = MemBehavior::MayRead;
// Ask escape analysis.
- if (!EA->canObjectOrContentEscapeTo(V, AI))
+ if (!EA->canEscapeTo(V, AI))
Behavior = MemBehavior::None;
}
DEBUG(llvm::dbgs() << " Found apply, returning " << Behavior << '\n');
diff --git a/lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp b/lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp
index 978d163..2966519 100644
--- a/lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp
@@ -524,28 +524,26 @@
if (!VisitedInsts.insert(User).second)
continue;
- for (auto value : User->getResults()) {
+ if (auto *SVI = dyn_cast<SingleValueInstruction>(User)) {
// Otherwise attempt to strip off one layer of RC identical instructions
// from User.
- SILValue StrippedRCID = stripRCIdentityPreservingInsts(value);
+ SILValue StrippedRCID = stripRCIdentityPreservingInsts(SVI);
- // If StrippedRCID is not V, then we know that User's result is
- // conservatively not RCIdentical to V.
- if (StrippedRCID != V) {
- // If the user is extracting a trivial field of an aggregate structure
- // that does not overlap with the ref counted part of the aggregate, we
- // can ignore it.
- if (isNonOverlappingTrivialAccess(value))
- continue;
-
- // Otherwise, it is an RC user that our user wants.
- Users.push_back(User);
+ // If the User's result has the same RC identity as its operand, V, then
+ // it must still be RC identical to InputValue, so transitively search
+ // for more users.
+ if (StrippedRCID == V) {
+ Worklist.push_back(SVI);
continue;
}
-
- // Otherwise, add the result to our list to continue searching.
- Worklist.push_back(value);
+ // If the user is extracting a trivial field of an aggregate structure
+ // that does not overlap with the ref counted part of the aggregate, we
+ // can ignore it.
+ if (isNonOverlappingTrivialAccess(SVI))
+ continue;
}
+ // Otherwise, stop searching and report this RC user.
+ Users.push_back(User);
}
}
}
diff --git a/lib/SILOptimizer/Transforms/CopyForwarding.cpp b/lib/SILOptimizer/Transforms/CopyForwarding.cpp
index 1ef6e52..485ad41 100644
--- a/lib/SILOptimizer/Transforms/CopyForwarding.cpp
+++ b/lib/SILOptimizer/Transforms/CopyForwarding.cpp
@@ -65,6 +65,7 @@
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
+#include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/CFG.h"
@@ -167,6 +168,19 @@
return Apply->getArgumentConvention(FoundArgIdx.getValue());
}
+/// If the given instruction is a store, return the stored value.
+static SILValue getStoredValue(SILInstruction *I) {
+ switch (I->getKind()) {
+ case SILInstructionKind::StoreInst:
+ case SILInstructionKind::StoreBorrowInst:
+ case SILInstructionKind::StoreUnownedInst:
+ case SILInstructionKind::StoreWeakInst:
+ return I->getOperand(0);
+ default:
+ return SILValue();
+ }
+}
+
//===----------------------------------------------------------------------===//
// Forward and backward copy propagation
//===----------------------------------------------------------------------===//
@@ -481,6 +495,7 @@
// Per-function state.
PostOrderAnalysis *PostOrder;
DominanceAnalysis *DomAnalysis;
+ RCIdentityAnalysis *RCIAnalysis;
bool DoGlobalHoisting;
bool HasChanged;
bool HasChangedCFG;
@@ -495,10 +510,15 @@
// beyond the value's immediate uses.
bool IsSrcLoadedFrom;
+ // Does the address defined by CurrentDef have unrecognized uses of a
+ // nontrivial value stored at its address?
+ bool HasUnknownStoredValue;
+
bool HasForwardedToCopy;
SmallPtrSet<SILInstruction*, 16> SrcUserInsts;
SmallPtrSet<DebugValueAddrInst*, 4> SrcDebugValueInsts;
SmallVector<CopyAddrInst*, 4> TakePoints;
+ SmallPtrSet<SILInstruction *, 16> StoredValueUserInsts;
SmallVector<DestroyAddrInst*, 4> DestroyPoints;
SmallPtrSet<SILBasicBlock*, 32> DeadInBlocks;
@@ -514,6 +534,11 @@
if (isa<LoadInst>(user))
CPF.IsSrcLoadedFrom = true;
+ if (SILValue storedValue = getStoredValue(user)) {
+ if (!CPF.markStoredValueUsers(storedValue))
+ CPF.HasUnknownStoredValue = true;
+ }
+
// Bail on multiple uses in the same instruction to avoid complexity.
return CPF.SrcUserInsts.insert(user).second;
}
@@ -534,10 +559,12 @@
};
public:
- CopyForwarding(PostOrderAnalysis *PO, DominanceAnalysis *DA)
- : PostOrder(PO), DomAnalysis(DA), DoGlobalHoisting(false),
- HasChanged(false), HasChangedCFG(false), IsSrcLoadedFrom(false),
- HasForwardedToCopy(false), CurrentCopy(nullptr) {}
+ CopyForwarding(PostOrderAnalysis *PO, DominanceAnalysis *DA,
+ RCIdentityAnalysis *RCIAnalysis)
+ : PostOrder(PO), DomAnalysis(DA), RCIAnalysis(RCIAnalysis),
+ DoGlobalHoisting(false), HasChanged(false), HasChangedCFG(false),
+ IsSrcLoadedFrom(false), HasUnknownStoredValue(false),
+ HasForwardedToCopy(false), CurrentCopy(nullptr) {}
void reset(SILFunction *F) {
// Don't hoist destroy_addr globally in transparent functions. Avoid cloning
@@ -552,13 +579,16 @@
// We'll invalidate the analysis that are used by other passes at the end.
DomAnalysis->invalidate(F, SILAnalysis::InvalidationKind::Everything);
PostOrder->invalidate(F, SILAnalysis::InvalidationKind::Everything);
+ RCIAnalysis->invalidate(F, SILAnalysis::InvalidationKind::Everything);
}
CurrentDef = SILValue();
IsSrcLoadedFrom = false;
+ HasUnknownStoredValue = false;
HasForwardedToCopy = false;
SrcUserInsts.clear();
SrcDebugValueInsts.clear();
TakePoints.clear();
+ StoredValueUserInsts.clear();
DestroyPoints.clear();
DeadInBlocks.clear();
CurrentCopy = nullptr;
@@ -585,6 +615,8 @@
typedef llvm::SmallSetVector<SILInstruction *, 16> UserVector;
bool doesCopyDominateDestUsers(const UserVector &DirectDestUses);
+
+ bool markStoredValueUsers(SILValue storedValue);
};
class CopyDestUserVisitor : public AddressUserVisitor {
@@ -805,6 +837,51 @@
return true;
}
+// Add all recognized users of storedValue to StoredValueUserInsts. Return true
+// if all users were recgonized.
+//
+// To find all SSA users of storedValue, we first find the RC root, then search
+// past any instructions that may propagate the reference.
+bool CopyForwarding::markStoredValueUsers(SILValue storedValue) {
+ if (storedValue->getType().isTrivial(*storedValue->getModule()))
+ return true;
+
+ // Find the RC root, peeking past things like struct_extract.
+ RCIdentityFunctionInfo *RCI = RCIAnalysis->get(storedValue->getFunction());
+ SILValue root = RCI->getRCIdentityRoot(storedValue);
+
+ SmallVector<SILInstruction *, 8> users;
+ RCI->getRCUsers(root, users);
+
+ for (SILInstruction *user : users) {
+ // Recognize any uses that have no results as normal uses. They cannot
+ // transitively propagate a reference.
+ if (user->getResults().empty()) {
+ StoredValueUserInsts.insert(user);
+ continue;
+ }
+ // Recognize full applies as normal uses. They may transitively retain, but
+ // the caller cannot rely on that.
+ if (FullApplySite::isa(user)) {
+ StoredValueUserInsts.insert(user);
+ continue;
+ }
+ // A single-valued use is nontransitive if its result is trivial.
+ if (auto *SVI = dyn_cast<SingleValueInstruction>(user)) {
+ if (SVI->getType().isTrivial(user->getModule())) {
+ StoredValueUserInsts.insert(user);
+ continue;
+ }
+ }
+ // Conservatively treat everything else as potentially transitively
+ // retaining the stored value.
+ DEBUG(llvm::dbgs() << " Cannot reduce lifetime. May retain " << storedValue
+ << " at: " << *user << "\n");
+ return false;
+ }
+ return true;
+}
+
/// Returns the associated dealloc_stack if \p ASI has a single dealloc_stack.
/// Usually this is the case, but the optimizations may generate something like:
/// %1 = alloc_stack
@@ -1112,10 +1189,10 @@
/// The copy will be eliminated if the original is not accessed between the
/// point of copy and the original's destruction.
///
-/// Def = <uniquely identified> // no aliases
+/// CurrentDef = <uniquely identified> // no aliases
/// ...
/// Copy = copy_addr [init] Def
-/// ... // no access to Def
+/// ... // no access to CurrentDef
/// destroy_addr Def
///
/// Return true if a destroy was inserted, forwarded from a copy, or the
@@ -1137,6 +1214,19 @@
--SI;
SILInstruction *Inst = &*SI;
if (!SrcUserInsts.count(Inst)) {
+ if (StoredValueUserInsts.count(Inst)) {
+ // The current definition may take ownership of a value stored into its
+ // address. Its lifetime cannot end before the last use of that stored
+ // value.
+ // CurrentDef = ...
+ // Copy = copy_addr CurrentDef to ...
+ // store StoredValue to CurrentDef
+ // ... // no access to CurrentDef
+ // retain StoredValue
+ // destroy_addr CurrentDef
+ DEBUG(llvm::dbgs() << " Cannot hoist above stored value use:" << *Inst);
+ return false;
+ }
if (!IsWorthHoisting && isa<ApplyInst>(Inst))
IsWorthHoisting = true;
continue;
@@ -1185,7 +1275,7 @@
// TODO: Record all loads during collectUsers. Implement findRetainPoints to
// peek though projections of the load, like unchecked_enum_data to find the
// true extent of the lifetime including transitively referenced objects.
- if (IsSrcLoadedFrom)
+ if (IsSrcLoadedFrom || HasUnknownStoredValue)
return;
bool HoistedDestroyFound = false;
@@ -1420,7 +1510,8 @@
auto *PO = getAnalysis<PostOrderAnalysis>();
auto *DA = getAnalysis<DominanceAnalysis>();
- auto Forwarding = CopyForwarding(PO, DA);
+ auto *RCIA = getAnalysis<RCIdentityAnalysis>();
+ auto Forwarding = CopyForwarding(PO, DA, RCIA);
for (SILValue Def : CopiedDefs) {
#ifndef NDEBUG
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 7b66e07..83585f9 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -1980,6 +1980,18 @@
auto locator = disjunction->getLocator();
assert(locator && "remembered disjunction doesn't have a locator?");
DisjunctionChoices.push_back({locator, index});
+
+ // Implicit unwraps of optionals are worse solutions than those
+ // not involving implicit unwraps.
+ if (!locator->getPath().empty()) {
+ auto kind = locator->getPath().back().getKind();
+ if (kind == ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice ||
+ kind == ConstraintLocator::DynamicLookupResult) {
+ assert(index == 0 || index == 1);
+ if (index == 1)
+ increaseScore(SK_ForceUnchecked);
+ }
+ }
}
if (auto score = currentChoice.solve(solutions, allowFreeTypeVariables)) {
diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp
index 0411d9c..37fc2c4 100644
--- a/lib/Sema/ConstraintLocator.cpp
+++ b/lib/Sema/ConstraintLocator.cpp
@@ -252,7 +252,7 @@
break;
case ImplicitlyUnwrappedDisjunctionChoice:
- out << "implictly unwrapped disjunction choice";
+ out << "implicitly unwrapped disjunction choice";
break;
case DynamicLookupResult:
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index c3948d4..8e9a29b 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1675,31 +1675,6 @@
choice.getFunctionRefKind(), locator);
}
- if (!isRequirementOrWitness(locator) &&
- choice.getDecl()->getAttrs().hasAttribute<OptionalAttr>() &&
- !isa<SubscriptDecl>(choice.getDecl())) {
- // For a non-subscript declaration that is an optional
- // requirement in a protocol, strip off the lvalue-ness (FIXME:
- // one cannot assign to such declarations for now) and make a
- // reference to that declaration be optional.
- //
- // Subscript declarations are handled within
- // getTypeOfMemberReference(); their result types are optional.
-
- // Deal with values declared as implicitly unwrapped, or
- // functions with return types that are implicitly unwrapped.
- if (choice.isImplicitlyUnwrappedValueOrReturnValue()) {
- // Build the disjunction to attempt binding both T? and T (or
- // function returning T? and function returning T).
- Type ty = createTypeVariable(locator);
- buildDisjunctionForImplicitlyUnwrappedOptional(ty, refType,
- locator);
- addConstraint(ConstraintKind::Bind, boundType,
- OptionalType::get(ty->getRValueType()), locator);
- bindConstraintCreated = true;
- }
- refType = OptionalType::get(refType->getRValueType());
- }
// For a non-subscript declaration found via dynamic lookup, strip
// off the lvalue-ness (FIXME: as a temporary hack. We eventually
// want this to work) and make a reference to that declaration be
@@ -1708,7 +1683,7 @@
// Subscript declarations are handled within
// getTypeOfMemberReference(); their result types are unchecked
// optional.
- else if (isDynamicResult) {
+ if (isDynamicResult) {
if (isa<SubscriptDecl>(choice.getDecl())) {
// We always expect function type for subscripts.
auto fnTy = refType->castTo<AnyFunctionType>();
@@ -1773,8 +1748,31 @@
}
bindConstraintCreated = true;
- }
+ } else if (!isRequirementOrWitness(locator) &&
+ choice.getDecl()->getAttrs().hasAttribute<OptionalAttr>() &&
+ !isa<SubscriptDecl>(choice.getDecl())) {
+ // For a non-subscript declaration that is an optional
+ // requirement in a protocol, strip off the lvalue-ness (FIXME:
+ // one cannot assign to such declarations for now) and make a
+ // reference to that declaration be optional.
+ //
+ // Subscript declarations are handled within
+ // getTypeOfMemberReference(); their result types are optional.
+ // Deal with values declared as implicitly unwrapped, or
+ // functions with return types that are implicitly unwrapped.
+ if (choice.isImplicitlyUnwrappedValueOrReturnValue()) {
+ // Build the disjunction to attempt binding both T? and T (or
+ // function returning T? and function returning T).
+ Type ty = createTypeVariable(locator);
+ buildDisjunctionForImplicitlyUnwrappedOptional(ty, refType, locator);
+ addConstraint(ConstraintKind::Bind, boundType,
+ OptionalType::get(ty->getRValueType()), locator);
+ bindConstraintCreated = true;
+ }
+
+ refType = OptionalType::get(refType->getRValueType());
+ }
// If the declaration is unavailable, note that in the score.
if (choice.getDecl()->getAttrs().isUnavailable(getASTContext())) {
increaseScore(SK_Unavailable);
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 02f8554..2d524d5 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -2414,6 +2414,13 @@
void
buildDisjunctionForOptionalVsUnderlying(Type boundTy, Type type,
ConstraintLocator *locator) {
+ // NOTE: If we use other locator kinds for these disjunctions, we
+ // need to account for it in solution scores for forced-unwraps.
+ assert(locator->getPath().back().getKind() ==
+ ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice ||
+ locator->getPath().back().getKind() ==
+ ConstraintLocator::DynamicLookupResult);
+
// Create the constraint to bind to the optional type and make it
// the favored choice.
auto *bindToOptional =
diff --git a/lib/Syntax/Status.md b/lib/Syntax/Status.md
index 907557e..d37067a 100644
--- a/lib/Syntax/Status.md
+++ b/lib/Syntax/Status.md
@@ -67,9 +67,9 @@
* DestructorDecl
* EnumDecl
* EnumCaseDecl
+ * PrecedenceGroupDecl
### Not-started (UnknownDecl):
- * PrecedenceGroupDecl
* InfixOperatorDecl
* PrefixOperatorDecl
* PostfixOperatorDecl
diff --git a/stdlib/public/Reflection/CMakeLists.txt b/stdlib/public/Reflection/CMakeLists.txt
index 0bb36de..dbbc72c 100644
--- a/stdlib/public/Reflection/CMakeLists.txt
+++ b/stdlib/public/Reflection/CMakeLists.txt
@@ -1,3 +1,12 @@
+set(swift_extra_sources)
+
+# When we're building with assertions, include the demangle node dumper to aid
+# in debugging.
+if (LLVM_ENABLE_ASSERTIONS)
+ list(APPEND swift_extra_sources "${SWIFT_SOURCE_DIR}/lib/Demangling/NodeDumper.cpp")
+endif(LLVM_ENABLE_ASSERTIONS)
+
+
add_swift_library(swiftReflection STATIC TARGET_LIBRARY FORCE_BUILD_FOR_HOST_SDK
MetadataSource.cpp
TypeLowering.cpp
@@ -11,7 +20,8 @@
"${SWIFT_SOURCE_DIR}/lib/Demangling/Punycode.cpp"
"${SWIFT_SOURCE_DIR}/lib/Demangling/Remangler.cpp"
"${SWIFT_SOURCE_DIR}/lib/Demangling/TypeDecoder.cpp"
-
+ ${swift_extra_sources}
C_COMPILE_FLAGS ${SWIFT_RUNTIME_CXX_FLAGS}
LINK_FLAGS ${SWIFT_RUNTIME_LINK_FLAGS}
INSTALL_IN_COMPONENT dev)
+
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 9df70cb..8f116da 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -237,6 +237,9 @@
list(APPEND swift_stdlib_compile_flags "-Xllvm" "-sil-inline-generics")
list(APPEND swift_stdlib_compile_flags "-Xllvm" "-sil-partial-specialization")
list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-enable-sil-ownership")
+if(SWIFT_STDLIB_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING)
+ list(APPEND swift_stdlib_compile_flags "-enforce-exclusivity=checked")
+endif()
if(SWIFT_CHECK_ESSENTIAL_STDLIB)
add_swift_library(swift_stdlib_essential ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB IS_STDLIB_CORE
diff --git a/stdlib/public/core/Codable.swift.gyb b/stdlib/public/core/Codable.swift.gyb
index 807fb17..b51e940 100644
--- a/stdlib/public/core/Codable.swift.gyb
+++ b/stdlib/public/core/Codable.swift.gyb
@@ -1767,7 +1767,8 @@
}
extension RawRepresentable where RawValue == ${type}, Self : Encodable {
- /// Encodes this value into the given encoder.
+ /// Encodes this value into the given encoder, when the type's `RawValue`
+ /// is `${type}`.
///
/// This function throws an error if any values are invalid for the given
/// encoder's format.
@@ -1781,7 +1782,8 @@
}
extension RawRepresentable where RawValue == ${type}, Self : Decodable {
- /// Creates a new instance by decoding from the given decoder.
+ /// Creates a new instance by decoding from the given decoder, when the
+ /// type's `RawValue` is `${type}`.
///
/// This initializer throws an error if reading from the decoder fails, or
/// if the data read is corrupted or otherwise invalid.
diff --git a/stdlib/public/core/CollectionOfOne.swift b/stdlib/public/core/CollectionOfOne.swift
index e4c8084..6bd5a28 100644
--- a/stdlib/public/core/CollectionOfOne.swift
+++ b/stdlib/public/core/CollectionOfOne.swift
@@ -10,7 +10,9 @@
//
//===----------------------------------------------------------------------===//
-/// An iterator that produces one or fewer instances of `Element`.
+/// An iterator that produces one or zero instances of an element.
+///
+/// `IteratorOverOne` is the iterator for the `CollectionOfOne` type.
@_fixed_layout // FIXME(sil-serialize-all)
public struct IteratorOverOne<Element> {
@usableFromInline // FIXME(sil-serialize-all)
@@ -31,8 +33,8 @@
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
///
- /// - Precondition: `next()` has not been applied to a copy of `self`
- /// since the copy was made.
+ /// - Returns: The next element in the underlying sequence, if a next element
+ /// exists; otherwise, `nil`.
@inlinable // FIXME(sil-serialize-all)
public mutating func next() -> Element? {
let result = _elements
@@ -41,13 +43,25 @@
}
}
-/// A collection containing a single element of type `Element`.
+/// A collection containing a single element.
+///
+/// You can use a `CollectionOfOne` instance when you need to efficiently
+/// represent a single value as a collection. For example, you can add a
+/// single element to an array by using a `CollectionOfOne` instance with the
+/// concatenation operator (`+`):
+///
+/// let a = [1, 2, 3, 4]
+/// let toAdd = 100
+/// let b = a + CollectionOfOne(toAdd)
+/// // b == [1, 2, 3, 4, 100]
@_fixed_layout // FIXME(sil-serialize-all)
public struct CollectionOfOne<Element> {
@usableFromInline // FIXME(sil-serialize-all)
internal var _element: Element
- /// Creates an instance containing just `element`.
+ /// Creates an instance containing just the given element.
+ ///
+ /// - Parameter element: The element to store in the collection.
@inlinable // FIXME(sil-serialize-all)
public init(_ element: Element) {
self._element = element
@@ -60,6 +74,8 @@
public typealias Indices = Range<Int>
/// The position of the first element.
+ ///
+ /// In a `CollectionOfOne` instance, `startIndex` is always `0`.
@inlinable // FIXME(sil-serialize-all)
public var startIndex: Int {
return 0
@@ -68,38 +84,44 @@
/// The "past the end" position---that is, the position one greater than the
/// last valid subscript argument.
///
- /// In a `CollectionOfOne` instance, `endIndex` is always identical to
- /// `index(after: startIndex)`.
+ /// In a `CollectionOfOne` instance, `endIndex` is always `1`.
@inlinable // FIXME(sil-serialize-all)
public var endIndex: Int {
return 1
}
- /// Always returns `endIndex`.
+ /// Returns the position immediately after the given index.
+ ///
+ /// - Parameter i: A valid index of the collection. `i` must be `0`.
+ /// - Returns: The index value immediately after `i`.
@inlinable // FIXME(sil-serialize-all)
public func index(after i: Int) -> Int {
_precondition(i == startIndex)
return endIndex
}
- /// Always returns `startIndex`.
+ /// Returns the position immediately before the given index.
+ ///
+ /// - Parameter i: A valid index of the collection. `i` must be `1`.
+ /// - Returns: The index value immediately before `i`.
@inlinable // FIXME(sil-serialize-all)
public func index(before i: Int) -> Int {
_precondition(i == endIndex)
return startIndex
}
- /// Returns an iterator over the elements of this sequence.
+ /// Returns an iterator over the elements of this collection.
///
- /// - Complexity: O(1).
+ /// - Complexity: O(1)
@inlinable // FIXME(sil-serialize-all)
public func makeIterator() -> IteratorOverOne<Element> {
return IteratorOverOne(_elements: _element)
}
- /// Accesses the element at `position`.
+ /// Accesses the element at the specified position.
///
- /// - Precondition: `position == 0`.
+ /// - Parameter position: The position of the element to access. The only
+ /// valid position in a `CollectionOfOne` instance is `0`.
@inlinable // FIXME(sil-serialize-all)
public subscript(position: Int) -> Element {
get {
@@ -129,7 +151,7 @@
}
}
- /// The number of elements (always one).
+ /// The number of elements in the collection, which is always one.
@inlinable // FIXME(sil-serialize-all)
public var count: Int {
return 1
@@ -137,7 +159,7 @@
}
extension CollectionOfOne : CustomDebugStringConvertible {
- /// A textual representation of `self`, suitable for debugging.
+ /// A textual representation of the collection, suitable for debugging.
@inlinable // FIXME(sil-serialize-all)
public var debugDescription: String {
return "CollectionOfOne(\(String(reflecting: _element)))"
diff --git a/stdlib/public/core/CompilerProtocols.swift b/stdlib/public/core/CompilerProtocols.swift
index efc45b8..d49be2c 100644
--- a/stdlib/public/core/CompilerProtocols.swift
+++ b/stdlib/public/core/CompilerProtocols.swift
@@ -178,37 +178,46 @@
return lhs.rawValue != rhs.rawValue
}
-/// A type that can produce a collection of all of its values.
+/// A type that provides a collection of all of its values.
///
-/// Simple Enumerations
-/// ===================
+/// Types that conform to the `CaseIterable` protocol are typically
+/// enumerations without associated values. When using a `CaseIterable` type,
+/// you can access a collection of all of the type's cases by using the type's
+/// `allCases` property.
///
-/// For any Swift enumeration where every case does not have an associated
-/// value, the Swift compiler can automatically fill out the `CaseIterable`
-/// conformance. When defining your own custom enumeration, specify a
-/// conformance to `CaseIterable` to take advantage of this automatic
-/// derivation.
+/// For example, the `CompassDirection` enumeration declared in this example
+/// conforms to `CaseIterable`. You access the number of cases and the cases
+/// themselves through `CompassDirection.allCases`.
///
-/// For example, every case of the `CardinalPoint` enumeration defined here
-/// does not have an associated value:
-///
-/// enum CardinalPoint: CaseIterable {
+/// enum CompassDirection: CaseIterable {
/// case north, south, east, west
/// }
///
-/// So the compiler automatically creates a conformance.
+/// print("There are \(CompassDirection.allCases.count) directions.")
+/// // Prints "There are 4 directions."
+/// let caseList = CompassDirection.allCases
+/// .map({ "\($0)" })
+/// .joined(separator: ", ")
+/// // caseList == "north, south, east, west"
///
-/// for cardinality in CardinalPoint.allCases {
-/// print(cardinality)
-/// }
-/// // Prints "north"
-/// // Prints "south"
-/// // Prints "east"
-/// // Prints "west"
+/// Conforming to the CaseIterable Protocol
+/// =======================================
+///
+/// The compiler can automatically provide an implementation of the
+/// `CaseIterable` requirements for any enumeration without associated values
+/// or `@available` attributes on its cases. The synthesized `allCases`
+/// collection provides the cases in order of their declaration.
+///
+/// You can take advantage of this compiler support when defining your own
+/// custom enumeration by declaring conformance to `CaseIterable` in the
+/// enumeration's original declaration. The `CompassDirection` example above
+/// demonstrates this automatic implementation.
public protocol CaseIterable {
+ /// A type that can represent a collection of all values of this type.
associatedtype AllCases: Collection
where AllCases.Element == Self
- /// Returns a collection of all values of this type.
+
+ /// A collection of all values of this type.
static var allCases: AllCases { get }
}
diff --git a/stdlib/public/core/Dictionary.swift b/stdlib/public/core/Dictionary.swift
index 98be4e3..d090266 100644
--- a/stdlib/public/core/Dictionary.swift
+++ b/stdlib/public/core/Dictionary.swift
@@ -399,16 +399,16 @@
self = Dictionary<Key, Value>(_nativeBuffer: _NativeBuffer())
}
- /// Creates a dictionary with at least the given number of elements worth of
- /// buffer.
+ /// Creates an empty dictionary with preallocated space for at least the
+ /// specified number of elements.
///
- /// Use this initializer to avoid intermediate reallocations when you know
- /// how many key-value pairs you are adding to a dictionary. The actual
- /// capacity of the created dictionary is the smallest power of 2 that
- /// is greater than or equal to `minimumCapacity`.
+ /// Use this initializer to avoid intermediate reallocations of a dictionary's
+ /// storage buffer when you know how many key-value pairs you are adding to a
+ /// dictionary after creation.
///
- /// - Parameter minimumCapacity: The minimum number of key-value pairs to
- /// allocate buffer for in the new dictionary.
+ /// - Parameter minimumCapacity: The minimum number of key-value pairs that
+ /// the newly created dictionary should be able to store without
+ // reallocating its storage buffer.
@inlinable // FIXME(sil-serialize-all)
public init(minimumCapacity: Int) {
_variantBuffer = .native(_NativeBuffer(minimumCapacity: minimumCapacity))
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index b2175bc..0389bf7 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -301,6 +301,7 @@
/// let x: UInt8 = 5 // 0b00000101
/// let y: UInt8 = 14 // 0b00001110
/// let z = x & y // 0b00000100
+ /// // z == 4
///
/// - Parameters:
/// - lhs: An integer value.
@@ -317,6 +318,7 @@
/// let x: UInt8 = 5 // 0b00000101
/// let y: UInt8 = 14 // 0b00001110
/// let z = x | y // 0b00001111
+ /// // z == 15
///
/// - Parameters:
/// - lhs: An integer value.
@@ -333,6 +335,7 @@
/// let x: UInt8 = 5 // 0b00000101
/// let y: UInt8 = 14 // 0b00001110
/// let z = x ^ y // 0b00001011
+ /// // z == 11
///
/// - Parameters:
/// - lhs: An integer value.
@@ -343,9 +346,10 @@
/// specified number of digits to the right, masking the shift amount to the
/// type's bit width.
///
- /// The masking right shift operator (`&>>`) performs a *masking shift*,
- /// where the value passed as `rhs` is masked to produce a value in the
- /// range `0..<lhs.bitWidth`. The shift is performed using this masked
+ /// Use the masking right shift operator (`&>>`) when you need to perform a
+ /// shift and are sure that the shift amount is in the range
+ /// `0..<lhs.bitWidth`. Before shifting, the masking right shift operator
+ /// masks the shift to this range. The shift is performed using this masked
/// value.
///
/// The following example defines `x` as an instance of `UInt8`, an 8-bit,
@@ -356,11 +360,16 @@
/// let y = x &>> 2
/// // y == 7 // 0b00000111
///
- /// However, if you use `19` as `rhs`, the operation first bitmasks `rhs` to
- /// `3`, and then uses that masked value as the number of bits to shift `lhs`.
+ /// However, if you use `8` as the shift amount, the method first masks the
+ /// shift amount to zero, and then performs the shift, resulting in no change
+ /// to the original value.
///
- /// let z = x &>> 19
- /// // z == 3 // 0b00000011
+ /// let z = x &>> 8
+ /// // z == 30 // 0b00011110
+ ///
+ /// If the bit width of the shifted integer type is a power of two, masking
+ /// is performed using a bitmask; otherwise, masking is performed using a
+ /// modulo operation.
///
/// - Parameters:
/// - lhs: The value to shift.
@@ -373,9 +382,11 @@
/// specified number of digits to the left, masking the shift amount to the
/// type's bit width.
///
- /// The masking left shift operator (`&<<`) performs a *masking shift*, where
- /// the value used as `rhs` is masked to produce a value in the range
- /// `0..<lhs.bitWidth`. The shift is performed using this masked value.
+ /// Use the masking left shift operator (`&<<`) when you need to perform a
+ /// shift and are sure that the shift amount is in the range
+ /// `0..<lhs.bitWidth`. Before shifting, the masking left shift operator
+ /// masks the shift to this range. The shift is performed using this masked
+ /// value.
///
/// The following example defines `x` as an instance of `UInt8`, an 8-bit,
/// unsigned integer type. If you use `2` as the right-hand-side value in an
@@ -385,11 +396,16 @@
/// let y = x &<< 2
/// // y == 120 // 0b01111000
///
- /// However, if you pass `19` as `rhs`, the method first bitmasks `rhs` to
- /// `3`, and then uses that masked value as the number of bits to shift `lhs`.
+ /// However, if you use `8` as the shift amount, the method first masks the
+ /// shift amount to zero, and then performs the shift, resulting in no change
+ /// to the original value.
///
- /// let z = x &<< 19
- /// // z == 240 // 0b11110000
+ /// let z = x &<< 8
+ /// // z == 30 // 0b00011110
+ ///
+ /// If the bit width of the shifted integer type is a power of two, masking
+ /// is performed using a bitmask; otherwise, masking is performed using a
+ /// modulo operation.
///
/// - Parameters:
/// - lhs: The value to shift.
@@ -952,9 +968,14 @@
/// Returns the sum of this value and the given value without checking for
/// arithmetic overflow.
///
- /// If an arithmetic overflow occurs, the behavior is undefined. Use this
- /// function only to avoid the cost of overflow checking when you are sure
- /// that the operation won't overflow.
+ /// Use this function only to avoid the cost of overflow checking when you
+ /// are certain that the operation won't overflow. In optimized builds (`-O`)
+ /// the compiler is free to assume that overflow won't occur. Failure to
+ /// satisfy that assumption is a serious programming error and could lead to
+ /// statements being unexpectedly executed or skipped.
+ ///
+ /// In debug builds (`-Onone`) a runtime error is still triggered if the
+ /// operation overflows.
///
/// - Parameter rhs: The value to add to this value.
/// - Returns: The sum of this value and `rhs`.
@@ -963,9 +984,14 @@
/// Returns the difference obtained by subtracting the given value from this
/// value without checking for arithmetic overflow.
///
- /// If an arithmetic overflow occurs, the behavior is undefined. Use this
- /// function only to avoid the cost of overflow checking when you are sure
- /// that the operation won't overflow.
+ /// Use this function only to avoid the cost of overflow checking when you
+ /// are certain that the operation won't overflow. In optimized builds (`-O`)
+ /// the compiler is free to assume that overflow won't occur. Failure to
+ /// satisfy that assumption is a serious programming error and could lead to
+ /// statements being unexpectedly executed or skipped.
+ ///
+ /// In debug builds (`-Onone`) a runtime error is still triggered if the
+ /// operation overflows.
///
/// - Parameter rhs: The value to subtract from this value.
/// - Returns: The result of subtracting `rhs` from this value.
@@ -974,9 +1000,14 @@
/// Returns the product of this value and the given value without checking
/// for arithmetic overflow.
///
- /// If an arithmetic overflow occurs, the behavior is undefined. Use this
- /// function only to avoid the cost of overflow checking when you are sure
- /// that the operation won't overflow.
+ /// Use this function only to avoid the cost of overflow checking when you
+ /// are certain that the operation won't overflow. In optimized builds (`-O`)
+ /// the compiler is free to assume that overflow won't occur. Failure to
+ /// satisfy that assumption is a serious programming error and could lead to
+ /// statements being unexpectedly executed or skipped.
+ ///
+ /// In debug builds (`-Onone`) a runtime error is still triggered if the
+ /// operation overflows.
///
/// - Parameter rhs: The value to multiply by this value.
/// - Returns: The product of this value and `rhs`.
@@ -985,9 +1016,14 @@
/// Returns the quotient obtained by dividing this value by the given value
/// without checking for arithmetic overflow.
///
- /// If an arithmetic overflow occurs, the behavior is undefined. Use this
- /// function only to avoid the cost of overflow checking when you are sure
- /// that the operation won't overflow.
+ /// Use this function only to avoid the cost of overflow checking when you
+ /// are certain that the operation won't overflow. In optimized builds (`-O`)
+ /// the compiler is free to assume that overflow won't occur. Failure to
+ /// satisfy that assumption is a serious programming error and could lead to
+ /// statements being unexpectedly executed or skipped.
+ ///
+ /// In debug builds (`-Onone`) a runtime error is still triggered if the
+ /// operation overflows.
///
/// - Parameter rhs: The value to divide this value by.
/// - Returns: The result of dividing this value by `rhs`.
@@ -2256,23 +2292,23 @@
/// otherwise overflow. Unlike traditional truncating multiplication, the
/// `multipliedFullWidth(by:)` method returns a tuple containing both the
/// `high` and `low` parts of the product of this value and `other`. The
- /// following example uses this method to multiply two `UInt8` values that
+ /// following example uses this method to multiply two `Int8` values that
/// normally overflow when multiplied:
///
- /// let x: UInt8 = 100
- /// let y: UInt8 = 20
+ /// let x: Int8 = 48
+ /// let y: Int8 = -40
/// let result = x.multipliedFullWidth(by: y)
- /// // result.high == 0b00000111
- /// // result.low == 0b11010000
+ /// // result.high == -8
+ /// // result.low == 128
///
- /// The product of `x` and `y` is 2000, which is too large to represent in a
- /// `UInt8` instance. The `high` and `low` properties of the `result` value
- /// represent 2000 when concatenated to form a double-width integer; that
+ /// The product of `x` and `y` is `-1920`, which is too large to represent in
+ /// an `Int8` instance. The `high` and `low` compnents of the `result` value
+ /// represent `-1920` when concatenated to form a double-width integer; that
/// is, using `result.high` as the high byte and `result.low` as the low byte
- /// of a `UInt16` instance.
+ /// of an `Int16` instance.
///
- /// let z = UInt16(result.high) << 8 | UInt16(result.low)
- /// // z == 2000
+ /// let z = Int16(result.high) << 8 | Int16(result.low)
+ /// // z == -1920
///
/// - Parameter other: The value to multiply this value by.
/// - Returns: A tuple containing the high and low parts of the result of
@@ -2286,6 +2322,18 @@
/// type. If the quotient is too large to represent in the type, a runtime
/// error may occur.
///
+ /// The following example divides a value that is too large to be represented
+ /// using a single `Int` instance by another `Int` value. Because the quotient
+ /// is representable as an `Int`, the division succeeds.
+ ///
+ /// // 'dividend' represents the value 0x506f70652053616e74612049494949
+ /// let dividend = (22640526660490081, 7959093232766896457 as UInt)
+ /// let divisor = 2241543570477705381
+ ///
+ /// let (quotient, remainder) = divisor.dividingFullWidth(dividend)
+ /// // quotient == 186319822866995413
+ /// // remainder == 0
+ ///
/// - Parameter dividend: A tuple containing the high and low parts of a
/// double-width integer.
/// - Returns: A tuple containing the quotient and remainder obtained by
diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift
index 0b0a9de..bac7c3e 100644
--- a/stdlib/public/core/Range.swift
+++ b/stdlib/public/core/Range.swift
@@ -606,18 +606,29 @@
{
public typealias Element = Bound
+ /// The iterator for a `PartialRangeFrom` instance.
@_fixed_layout
public struct Iterator: IteratorProtocol {
@usableFromInline
internal var _current: Bound
@inlinable
public init(_current: Bound) { self._current = _current }
+
+ /// Advances to the next element and returns it, or `nil` if no next
+ /// element exists.
+ ///
+ /// Once `nil` has been returned, all subsequent calls return `nil`.
+ ///
+ /// - Returns: The next element in the underlying sequence, if a next
+ /// element exists; otherwise, `nil`.
@inlinable
public mutating func next() -> Bound? {
defer { _current = _current.advanced(by: 1) }
return _current
}
}
+
+ /// Returns an iterator for this sequence.
@inlinable
public func makeIterator() -> Iterator {
return Iterator(_current: lowerBound)
@@ -739,30 +750,33 @@
/// unbounded range is essentially a conversion of a collection instance into
/// its slice type.
///
-/// For example, the following code declares `levenshteinDistance(_:_:)`, a
-/// function that calculates the number of changes required to convert one
-/// string into another. `levenshteinDistance(_:_:)` uses `Substring`, a
-/// string's slice type, for its parameters.
+/// For example, the following code declares `countLetterChanges(_:_:)`, a
+/// function that finds the number of changes required to change one
+/// word or phrase into another. The function uses a recursive approach to
+/// perform the same comparisons on smaller and smaller pieces of the original
+/// strings. In order to use recursion without making copies of the strings at
+/// each step, `countLetterChanges(_:_:)` uses `Substring`, a string's slice
+/// type, for its parameters.
///
-/// func levenshteinDistance(_ s1: Substring, _ s2: Substring) -> Int {
+/// func countLetterChanges(_ s1: Substring, _ s2: Substring) -> Int {
/// if s1.isEmpty { return s2.count }
/// if s2.isEmpty { return s1.count }
///
/// let cost = s1.first == s2.first ? 0 : 1
///
/// return min(
-/// levenshteinDistance(s1.dropFirst(), s2) + 1,
-/// levenshteinDistance(s1, s2.dropFirst()) + 1,
-/// levenshteinDistance(s1.dropFirst(), s2.dropFirst()) + cost)
+/// countLetterChanges(s1.dropFirst(), s2) + 1,
+/// countLetterChanges(s1, s2.dropFirst()) + 1,
+/// countLetterChanges(s1.dropFirst(), s2.dropFirst()) + cost)
/// }
///
-/// To call `levenshteinDistance(_:_:)` with two strings, use an unbounded
-/// range in each string's subscript to convert it to a `Substring`.
+/// To call `countLetterChanges(_:_:)` with two strings, use an unbounded
+/// range in each string's subscript.
///
/// let word1 = "grizzly"
/// let word2 = "grisly"
-/// let distance = levenshteinDistance(word1[...], word2[...])
-/// // distance == 2
+/// let changes = countLetterChanges(word1[...], word2[...])
+/// // changes == 2
@_frozen // FIXME(sil-serialize-all)
public enum UnboundedRange_ {
// FIXME: replace this with a computed var named `...` when the language makes
diff --git a/stdlib/public/core/RangeReplaceableCollection.swift b/stdlib/public/core/RangeReplaceableCollection.swift
index c836848..e9531fe 100644
--- a/stdlib/public/core/RangeReplaceableCollection.swift
+++ b/stdlib/public/core/RangeReplaceableCollection.swift
@@ -553,7 +553,7 @@
/// Removes the elements in the specified subrange from the collection.
///
/// All the elements following the specified position are moved to close the
- /// gap. This example removes two elements from the middle of an array of
+ /// gap. This example removes three elements from the middle of an array of
/// measurements.
///
/// var measurements = [1.2, 1.5, 2.9, 1.2, 1.5]
@@ -754,7 +754,7 @@
/// Removes the elements in the specified subrange from the collection.
///
/// All the elements following the specified position are moved to close the
- /// gap. This example removes two elements from the middle of an array of
+ /// gap. This example removes three elements from the middle of an array of
/// measurements.
///
/// var measurements = [1.2, 1.5, 2.9, 1.2, 1.5]
diff --git a/stdlib/public/core/Set.swift b/stdlib/public/core/Set.swift
index 705505a..2fd512c 100644
--- a/stdlib/public/core/Set.swift
+++ b/stdlib/public/core/Set.swift
@@ -160,17 +160,16 @@
}
extension Set {
- /// Creates a new, empty set with at least the specified number of elements'
- /// worth of buffer.
+ /// Creates an empty set with preallocated space for at least the specified
+ /// number of elements.
///
- /// Use this initializer to avoid repeated reallocations of a set's buffer
- /// if you know you'll be adding elements to the set after creation. The
- /// actual capacity of the created set will be the smallest power of 2 that
- /// is greater than or equal to `minimumCapacity`.
+ /// Use this initializer to avoid intermediate reallocations of a set's
+ /// storage buffer when you know how many elements you'll insert into the set
+ /// after creation.
///
/// - Parameter minimumCapacity: The minimum number of elements that the
/// newly created set should be able to store without reallocating its
- /// buffer.
+ /// storage buffer.
@inlinable // FIXME(sil-serialize-all)
public init(minimumCapacity: Int) {
_variantBuffer =
diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt
index c83e471..3f7a508 100644
--- a/stdlib/public/runtime/CMakeLists.txt
+++ b/stdlib/public/runtime/CMakeLists.txt
@@ -73,6 +73,12 @@
"${SWIFT_SOURCE_DIR}/lib/Demangling/ManglingUtils.cpp"
"${SWIFT_SOURCE_DIR}/lib/Demangling/Punycode.cpp")
+# When we're building with assertions, include the demangle node dumper to aid
+# in debugging.
+if (LLVM_ENABLE_ASSERTIONS)
+ list(APPEND swift_runtime_sources "${SWIFT_SOURCE_DIR}/lib/Demangling/NodeDumper.cpp")
+endif(LLVM_ENABLE_ASSERTIONS)
+
# Acknowledge that the following sources are known.
set(LLVM_OPTIONAL_SOURCES
MutexPThread.cpp
diff --git a/stdlib/public/runtime/SwiftDtoa.cpp b/stdlib/public/runtime/SwiftDtoa.cpp
index 4b253cf..802bb00 100644
--- a/stdlib/public/runtime/SwiftDtoa.cpp
+++ b/stdlib/public/runtime/SwiftDtoa.cpp
@@ -1063,7 +1063,9 @@
int8_t digits[9];
int digitCount =
swift_decompose_float(d, digits, sizeof(digits), &decimalExponent);
- if (decimalExponent < -3 || decimalExponent > 6) {
+ // People use float to model integers <= 2^24, so we use that
+ // as a cutoff for decimal vs. exponential format.
+ if (decimalExponent < -3 || fabsf(d) > 0x1.0p24F) {
return swift_format_exponential(dest, length, signbit(d),
digits, digitCount, decimalExponent);
} else {
@@ -1117,7 +1119,9 @@
int8_t digits[17];
int digitCount =
swift_decompose_double(d, digits, sizeof(digits), &decimalExponent);
- if (decimalExponent < -3 || decimalExponent > 15) {
+ // People use double to model integers <= 2^53, so we use that
+ // as a cutoff for decimal vs. exponential format.
+ if (decimalExponent < -3 || fabs(d) > 0x1.0p53) {
return swift_format_exponential(dest, length, signbit(d),
digits, digitCount, decimalExponent);
} else {
@@ -1167,12 +1171,15 @@
}
// Decimal numeric formatting
- // Decimal numeric formatting
int decimalExponent;
int8_t digits[21];
int digitCount =
swift_decompose_float80(d, digits, sizeof(digits), &decimalExponent);
- if (decimalExponent < -3 || decimalExponent > 18) {
+ // People use long double to model integers <= 2^64, so we use that
+ // as a cutoff for decimal vs. exponential format.
+ // The constant is written out as a float80 (aka "long double") literal
+ // here since it can't be expressed as a 64-bit integer.
+ if (decimalExponent < -3 || fabsl(d) > 0x1.0p64L) {
return swift_format_exponential(dest, length, signbit(d),
digits, digitCount, decimalExponent);
} else {
diff --git a/test/Constraints/iuo.swift b/test/Constraints/iuo.swift
index 554adfa..50641d3 100644
--- a/test/Constraints/iuo.swift
+++ b/test/Constraints/iuo.swift
@@ -213,3 +213,13 @@
return b as? D! // expected-error {{value of optional type 'D?' not unwrapped; did you mean to use '!' or '?'?}}
// expected-warning@-1 {{using '!' here is deprecated and will be removed in a future release}}
}
+
+// Ensure that we select the overload that does *not* involve forcing an IUO.
+func sr6988(x: Int?, y: Int?) -> Int { return x! }
+func sr6988(x: Int, y: Int) -> Float { return Float(x) }
+
+var x: Int! = nil
+var y: Int = 2
+
+let r = sr6988(x: x, y: y)
+let _: Int = r
diff --git a/test/Constraints/sr7098.swift b/test/Constraints/sr7098.swift
new file mode 100644
index 0000000..90005f9
--- /dev/null
+++ b/test/Constraints/sr7098.swift
@@ -0,0 +1,13 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s
+// REQUIRES: objc_interop
+
+import Foundation
+
+class C : NSObject, NSWobbling {
+ func wobble() {}
+ func returnMyself() -> Self { return self }
+}
+
+func testDynamicOptionalRequirement(_ a: AnyObject) {
+ a.optionalRequirement?()
+}
diff --git a/test/IRGen/objc_runtime_visible_conformance.swift b/test/IRGen/objc_runtime_visible_conformance.swift
new file mode 100644
index 0000000..0757081
--- /dev/null
+++ b/test/IRGen/objc_runtime_visible_conformance.swift
@@ -0,0 +1,18 @@
+// REQUIRES: objc_interop
+
+// RUN: %target-swift-frontend -I %S/../Inputs/custom-modules %s -emit-ir | %FileCheck %s
+
+import ObjCRuntimeVisible
+
+protocol MyProtocol {}
+protocol YourProtocol {}
+
+extension A : MyProtocol {}
+extension A : YourProtocol {}
+
+// CHECK-LABEL: @"$SSo1ACMn" = linkonce_odr hidden constant <{ {{.*}} }>, section "__TEXT,__const"
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo1ACMa"({{i32|i64}}) {{.*}} {
+// CHECK: call %objc_class* @objc_lookUpClass
+// CHECK: call %swift.type* @swift_getObjCClassMetadata
+// CHECK: ret
diff --git a/test/Parse/switch.swift b/test/Parse/switch.swift
index 9d6c32f..e3945f6 100644
--- a/test/Parse/switch.swift
+++ b/test/Parse/switch.swift
@@ -502,3 +502,23 @@
case _:
@unknown let _ = 1 // expected-error {{unknown attribute 'unknown'}}
}
+
+switch Whatever.Thing {
+case .Thing:
+ break
+@unknown(garbage) case _: // expected-error {{unexpected '(' in attribute 'unknown'}}
+ break
+}
+switch Whatever.Thing {
+case .Thing:
+ break
+@unknown // expected-note {{attribute already specified here}}
+@unknown // expected-error {{duplicate attribute}}
+case _:
+ break
+}
+switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note {{add missing case: '.Thing'}}
+@unknown @garbage(foobar) // expected-error {{unknown attribute 'garbage'}}
+case _:
+ break
+}
diff --git a/test/SIL/Serialization/Inputs/vtable_deserialization_input.swift b/test/SIL/Serialization/Inputs/vtable_deserialization_input.swift
index 130b297..250b388 100644
--- a/test/SIL/Serialization/Inputs/vtable_deserialization_input.swift
+++ b/test/SIL/Serialization/Inputs/vtable_deserialization_input.swift
@@ -1,22 +1,11 @@
+public func unknown() {}
-public protocol P {
- func doSomething()
-}
-
-@_silgen_name("unknown") public
-func unknown() -> ()
-
-@_fixed_layout
-public class Y : P {
- @inlinable
- public func doAnotherThing() {
+public class Class {
+ @inlinable public class func firstMethod() {
unknown()
}
- @inlinable
- public func doSomething() {
- doAnotherThing()
- }
- @inlinable
- public init() {}
+ @inlinable public class func secondMethod() {}
+
+ @inlinable public class func thirdMethod() {}
}
diff --git a/test/SIL/Serialization/vtable_deserialization.swift b/test/SIL/Serialization/vtable_deserialization.swift
index 2f9c5b8..fb2862e 100644
--- a/test/SIL/Serialization/vtable_deserialization.swift
+++ b/test/SIL/Serialization/vtable_deserialization.swift
@@ -1,32 +1,42 @@
// RUN: %empty-directory(%t)
-// RUN: %target-swift-frontend %S/Inputs/vtable_deserialization_input.swift -o %t/Swift.swiftmodule -emit-module -parse-as-library -parse-stdlib -module-link-name swiftCore -module-name Swift
-// RUN: %target-swift-frontend %s -emit-sil -O -I %t -o - | %FileCheck %s
+// RUN: %target-swift-frontend %S/Inputs/vtable_deserialization_input.swift -emit-module-path %t/vtable_deserialization_input.swiftmodule -emit-module
+// RUN: %target-swift-frontend %s -emit-sil -I %t | %FileCheck %s
+// RUN: %target-swift-frontend %s -emit-sil -O -I %t | %FileCheck %s --check-prefix=OPT
-import Swift
+import vtable_deserialization_input
-@usableFromInline
-@inlinable
-func WhatShouldIDoImBored<T : P>(_ t : T) {
- t.doSomething()
-}
-
-@inline(__always)
-func MakeItNotAGlobal() -> Y {
- let x = Y()
- WhatShouldIDoImBored(x)
- return x
-}
+// Make sure we devirtualized the call and inlined the method body.
+// CHECK: function_ref @$S28vtable_deserialization_input5ClassC11firstMethodyyFZ
+// OPT: function_ref @$S28vtable_deserialization_input7unknownyyF
+Class.firstMethod()
-// Make sure all abstractions have been removed and everything inlined into top_level_method.
-// CHECK-LABEL: sil @main
-// CHECK: bb0({{.*}}):
-// CHECK: [[UNKNOWN:%.*]] = function_ref @unknown
-// CHECK: apply [[UNKNOWN]]
-// CHECK: integer_literal
-// CHECK: return
-MakeItNotAGlobal()
+// For now, we also deserialize the body of firstMethod(), even though it
+// is not transparent.
+// CHECK-LABEL: sil public_external [serialized] @$S28vtable_deserialization_input5ClassC11firstMethodyyFZ : $@convention(method) (@thick Class.Type) -> () {
+// OPT-LABEL: sil public_external @$S28vtable_deserialization_input5ClassC11firstMethodyyFZ : $@convention(method) (@thick Class.Type) -> () {
-// Make sure our vtable/witness tables are properly deserialized.
-// CHECK: sil_vtable Y {
-// CHECK: sil_witness_table public_external Y: P module Swift {
+// The other two methods should not be deserialized in the mandatory
+// pipeline.
+
+// CHECK-LABEL: sil [serialized] @$S28vtable_deserialization_input5ClassC12secondMethodyyFZ : $@convention(method) (@thick Class.Type) -> (){{$}}
+// OPT-LABEL: sil public_external @$S28vtable_deserialization_input5ClassC12secondMethodyyFZ : $@convention(method) (@thick Class.Type) -> () {
+
+// CHECK-LABEL: sil [serialized] @$S28vtable_deserialization_input5ClassC11thirdMethodyyFZ : $@convention(method) (@thick Class.Type) -> (){{$}}
+// OPT-LABEL: sil public_external @$S28vtable_deserialization_input5ClassC11thirdMethodyyFZ : $@convention(method) (@thick Class.Type) -> () {
+
+// Make sure we deserialized the vtable.
+
+// CHECK: sil_vtable [serialized] Class {
+// CHECK-NEXT: #Class.firstMethod!1: (Class.Type) -> () -> () : @$S28vtable_deserialization_input5ClassC11firstMethodyyFZ
+// CHECK-NEXT: #Class.secondMethod!1: (Class.Type) -> () -> () : @$S28vtable_deserialization_input5ClassC12secondMethodyyFZ
+// CHECK-NEXT: #Class.thirdMethod!1: (Class.Type) -> () -> () : @$S28vtable_deserialization_input5ClassC11thirdMethodyyFZ
+// CHECK-NEXT: #Class.deinit!deallocator: @$S28vtable_deserialization_input5ClassCfD
+// CHECK-NEXT: }
+
+// OPT: sil_vtable Class {
+// OPT-NEXT: #Class.firstMethod!1: (Class.Type) -> () -> () : @$S28vtable_deserialization_input5ClassC11firstMethodyyFZ
+// OPT-NEXT: #Class.secondMethod!1: (Class.Type) -> () -> () : @$S28vtable_deserialization_input5ClassC12secondMethodyyFZ
+// OPT-NEXT: #Class.thirdMethod!1: (Class.Type) -> () -> () : @$S28vtable_deserialization_input5ClassC11thirdMethodyyFZ
+// OPT-NEXT: #Class.deinit!deallocator: @$S28vtable_deserialization_input5ClassCfD
+// OPT-NEXT: }
diff --git a/test/SILOptimizer/copyforward.sil b/test/SILOptimizer/copyforward.sil
index 3d1d344..81adc14 100644
--- a/test/SILOptimizer/copyforward.sil
+++ b/test/SILOptimizer/copyforward.sil
@@ -794,3 +794,92 @@
%6 = tuple ()
return %6 : $()
}
+
+// CHECK-LABEL: sil @testKnownStoredValueUser : $@convention(thin) (@guaranteed AClass) -> @out AClass {
+// CHECK: [[ALLOC:%.*]] = alloc_stack $AClass
+// CHECK: copy_addr [[ALLOC]] to %0 : $*AClass
+// CHECK: strong_retain %1 : $AClass
+// CHECK: destroy_addr [[ALLOC]] : $*AClass
+// CHECK-LABEL: } // end sil function 'testKnownStoredValueUser'
+sil @testKnownStoredValueUser : $@convention(thin) (@guaranteed AClass) -> (@out AClass) {
+bb0(%0 : $*AClass, %1 : $AClass):
+ %2 = alloc_stack $AClass
+ store %1 to %2 : $*AClass
+ copy_addr %2 to %0 : $*AClass
+ strong_retain %1 : $AClass
+ destroy_addr %2 : $*AClass
+ dealloc_stack %2 : $*AClass
+ %999 = tuple ()
+ return %999 : $()
+}
+
+// CHECK-LABEL: sil @testExtractedStoredValueUser1 : $@convention(thin) (@guaranteed ObjWrapper) -> @out AnyObject {
+// CHECK: bb0(%0 : $*AnyObject, %1 : $ObjWrapper):
+// CHECK: [[ALLOC:%.*]] = alloc_stack $AnyObject
+// CHECK: [[EXTRACT:%.*]] = struct_extract %1 : $ObjWrapper, #ObjWrapper.obj
+// CHECK: store [[EXTRACT]] to [[ALLOC]] : $*AnyObject
+// CHECK: copy_addr [[ALLOC]] to %0 : $*AnyObject
+// CHECK: strong_retain [[EXTRACT]] : $AnyObject
+// CHECK: destroy_addr [[ALLOC]] : $*AnyObject
+// CHECK-LABEL: } // end sil function 'testExtractedStoredValueUser1'
+sil @testExtractedStoredValueUser1 : $@convention(thin) (@guaranteed ObjWrapper) -> (@out AnyObject) {
+bb0(%0 : $*AnyObject, %1 : $ObjWrapper):
+ %2 = alloc_stack $AnyObject
+ %3 = struct_extract %1 : $ObjWrapper, #ObjWrapper.obj
+ store %3 to %2 : $*AnyObject
+ copy_addr %2 to %0 : $*AnyObject
+ strong_retain %3 : $AnyObject
+ destroy_addr %2 : $*AnyObject
+ dealloc_stack %2 : $*AnyObject
+ %999 = tuple ()
+ return %999 : $()
+}
+
+// CHECK-LABEL: sil @testExtractedStoredValueUser2 : $@convention(thin) (@guaranteed ObjWrapper) -> @out AnyObject {
+// CHECK: bb0(%0 : $*AnyObject, %1 : $ObjWrapper):
+// CHECK: [[ALLOC:%.*]] = alloc_stack $AnyObject
+// CHECK: [[EXTRACT:%.*]] = struct_extract %1 : $ObjWrapper, #ObjWrapper.obj
+// CHECK: store [[EXTRACT]] to [[ALLOC]] : $*AnyObject
+// CHECK: copy_addr [[ALLOC]] to %0 : $*AnyObject
+// CHECK: retain_value %1 : $ObjWrapper
+// CHECK: destroy_addr [[ALLOC]] : $*AnyObject
+// CHECK-LABEL: } // end sil function 'testExtractedStoredValueUser2'
+sil @testExtractedStoredValueUser2 : $@convention(thin) (@guaranteed ObjWrapper) -> (@out AnyObject) {
+bb0(%0 : $*AnyObject, %1 : $ObjWrapper):
+ %2 = alloc_stack $AnyObject
+ %3 = struct_extract %1 : $ObjWrapper, #ObjWrapper.obj
+ store %3 to %2 : $*AnyObject
+ copy_addr %2 to %0 : $*AnyObject
+ retain_value %1 : $ObjWrapper
+ destroy_addr %2 : $*AnyObject
+ dealloc_stack %2 : $*AnyObject
+ %999 = tuple ()
+ return %999 : $()
+}
+
+struct AClassWrapper {
+ var a: AClass
+ var b: AClass
+}
+
+// CHECK-LABEL: sil @testUnknownStoredValueUser : $@convention(thin) (@guaranteed AClass) -> @out AClass {
+// CHECK: bb0(%0 : $*AClass, %1 : $AClass):
+// CHECK: [[ALLOC:%.*]] = alloc_stack $AClass
+// CHECK: store %1 to %2 : $*AClass
+// CHECK: [[STRUCT:%.*]] = struct $AClassWrapper (%1 : $AClass, %1 : $AClass)
+// CHECK: copy_addr [[ALLOC]] to %0 : $*AClass
+// CHECK: retain_value [[STRUCT]] : $AClassWrapper
+// CHECK: destroy_addr [[ALLOC]] : $*AClass
+// CHECK-LABEL: } // end sil function 'testUnknownStoredValueUser'
+sil @testUnknownStoredValueUser : $@convention(thin) (@guaranteed AClass) -> (@out AClass) {
+bb0(%0 : $*AClass, %1 : $AClass):
+ %2 = alloc_stack $AClass
+ store %1 to %2 : $*AClass
+ %3 = struct $AClassWrapper (%1 : $AClass, %1 : $AClass)
+ copy_addr %2 to %0 : $*AClass
+ retain_value %3 : $AClassWrapper
+ destroy_addr %2 : $*AClass
+ dealloc_stack %2 : $*AClass
+ %999 = tuple ()
+ return %999 : $()
+}
diff --git a/test/SILOptimizer/retain_release_code_motion.sil b/test/SILOptimizer/retain_release_code_motion.sil
index 7b5a06b..e10fe72 100644
--- a/test/SILOptimizer/retain_release_code_motion.sil
+++ b/test/SILOptimizer/retain_release_code_motion.sil
@@ -593,3 +593,30 @@
%26 = tuple ()
return %26 : $()
}
+
+// CHECK-LABEL: sil @detect_escape_of_bbarg
+// CHECK: bb3({{.*}}):
+// CHECK-NEXT: strong_retain
+// CHECK-NEXT: apply
+// CHECK-NEXT: strong_release
+sil @detect_escape_of_bbarg : $@convention(thin) () -> () {
+bb0:
+ %f = function_ref @use_C2 : $@convention(thin) (C2) -> ()
+ cond_br undef, bb1, bb2
+
+bb1:
+ %a = alloc_ref $C2
+ br bb3(%a: $C2, %a: $C2)
+
+bb2:
+ %b = alloc_ref $C2
+ br bb3(%b: $C2, %b: $C2)
+
+bb3(%p1: $C2, %p2: $C2):
+ strong_retain %p1: $C2 // This retain must not be moved over the apply
+ %c = apply %f(%p2) : $@convention(thin) (C2) -> ()
+ strong_release %p2: $C2
+ %10 = tuple ()
+ return %10 : $()
+}
+
diff --git a/test/SourceKit/Demangle/demangle.swift b/test/SourceKit/Demangle/demangle.swift
index 874ce28..4f3f215 100644
--- a/test/SourceKit/Demangle/demangle.swift
+++ b/test/SourceKit/Demangle/demangle.swift
@@ -1,15 +1,17 @@
-// RUN: %sourcekitd-test -req=demangle unmangled _TtBf80_ _TtP3foo3bar_ | %FileCheck %s
+// RUN: %sourcekitd-test -req=demangle unmangled _TtBf80_ _TtP3foo3bar_ '$S3Foo11AppDelegateC29applicationDidFinishLaunchingyy10Foundation12NotificationVF' | %FileCheck %s
// CHECK: START DEMANGLE
// CHECK-NEXT: <empty>
// CHECK-NEXT: Builtin.Float80
// CHECK-NEXT: foo.bar
+// CHECK-NEXT: Foo.AppDelegate.applicationDidFinishLaunching(Foundation.Notification) -> ()
// CHECK-NEXT: END DEMANGLE
-// RUN: %sourcekitd-test -req=demangle unmangled _TtBf80_ _TtP3foo3bar_ -simplified-demangling | %FileCheck %s -check-prefix=SIMPLIFIED
+// RUN: %sourcekitd-test -req=demangle unmangled _TtBf80_ _TtP3foo3bar_ '$S3Foo11AppDelegateC29applicationDidFinishLaunchingyy10Foundation12NotificationVF' -simplified-demangling | %FileCheck %s -check-prefix=SIMPLIFIED
// SIMPLIFIED: START DEMANGLE
// SIMPLIFIED-NEXT: <empty>
// SIMPLIFIED-NEXT: Builtin.Float80
// SIMPLIFIED-NEXT: bar
+// SIMPLIFIED-NEXT: AppDelegate.applicationDidFinishLaunching(_:)
// SIMPLIFIED-NEXT: END DEMANGLE
// RUN: %sourcekitd-test -req=mangle Foo.Baru Swift.Beer | %FileCheck %s -check-prefix=MANGLED
diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index ce58dcb..b313dbc 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -401,7 +401,9 @@
switch <IdentifierExpr>foo </IdentifierExpr>{<SwitchCase><SwitchCaseLabel>
case <CaseItem><ExpressionPattern><IntegerLiteralExpr>1</IntegerLiteralExpr></ExpressionPattern>, </CaseItem><CaseItem><ExpressionPattern><IntegerLiteralExpr>2</IntegerLiteralExpr></ExpressionPattern>, </CaseItem><CaseItem><ExpressionPattern><IntegerLiteralExpr>3</IntegerLiteralExpr></ExpressionPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><Attribute>
// This is rejected in Sema, but should be preserved by Syntax.
- @unknown </Attribute><SwitchCaseLabel>case <CaseItem><ExpressionPattern><TupleExpr>(<TupleElement><IntegerLiteralExpr>42</IntegerLiteralExpr>, </TupleElement><TupleElement><PrefixOperatorExpr>-<IntegerLiteralExpr>42</IntegerLiteralExpr></PrefixOperatorExpr></TupleElement>) </TupleExpr></ExpressionPattern><WhereClause>where <SequenceExpr><IntegerLiteralExpr>1 </IntegerLiteralExpr><BinaryOperatorExpr>== </BinaryOperatorExpr><IntegerLiteralExpr>2</IntegerLiteralExpr></SequenceExpr></WhereClause></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase>
+ @unknown </Attribute><SwitchCaseLabel>case <CaseItem><ExpressionPattern><TupleExpr>(<TupleElement><IntegerLiteralExpr>42</IntegerLiteralExpr>, </TupleElement><TupleElement><PrefixOperatorExpr>-<IntegerLiteralExpr>42</IntegerLiteralExpr></PrefixOperatorExpr></TupleElement>) </TupleExpr></ExpressionPattern><WhereClause>where <SequenceExpr><IntegerLiteralExpr>1 </IntegerLiteralExpr><BinaryOperatorExpr>== </BinaryOperatorExpr><IntegerLiteralExpr>2</IntegerLiteralExpr></SequenceExpr></WhereClause></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><Attribute>
+ @garbage </Attribute><SwitchCaseLabel>case <CaseItem><ExpressionPattern><IntegerLiteralExpr>0</IntegerLiteralExpr></ExpressionPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><Attribute>
+ @garbage(foobar) </Attribute><SwitchCaseLabel>case <CaseItem><ExpressionPattern><PrefixOperatorExpr>-<IntegerLiteralExpr>1</IntegerLiteralExpr></PrefixOperatorExpr></ExpressionPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase>
}</SwitchStmt>
}</CodeBlock></FunctionDecl><ExtensionDecl>
@@ -457,4 +459,17 @@
indirect </DeclModifier><DeclModifier>private </DeclModifier>enum E2<GenericParameterClause><<GenericParameter>T</GenericParameter>></GenericParameterClause><TypeInheritanceClause>: <InheritedType><SimpleTypeIdentifier>String </SimpleTypeIdentifier></InheritedType></TypeInheritanceClause><GenericWhereClause>where <ConformanceRequirement><SimpleTypeIdentifier>T</SimpleTypeIdentifier>: <SimpleTypeIdentifier>SomeProtocol </SimpleTypeIdentifier></ConformanceRequirement></GenericWhereClause><MemberDeclBlock>{<EnumCaseDecl>
case <EnumCaseElement>foo, </EnumCaseElement><EnumCaseElement>bar, </EnumCaseElement><EnumCaseElement>baz</EnumCaseElement></EnumCaseDecl>
}</MemberDeclBlock></EnumDecl>
-}</MemberDeclBlock></EnumDecl>
+}</MemberDeclBlock></EnumDecl><PrecedenceGroupDecl>
+
+precedencegroup FooPrecedence {<PrecedenceGroupRelation>
+ higherThan: <PrecedenceGroupNameElement>DefaultPrecedence, </PrecedenceGroupNameElement><PrecedenceGroupNameElement>UnknownPrecedence</PrecedenceGroupNameElement></PrecedenceGroupRelation><PrecedenceGroupAssignment>
+ assignment: false</PrecedenceGroupAssignment><PrecedenceGroupAssociativity>
+ associativity: none</PrecedenceGroupAssociativity>
+}</PrecedenceGroupDecl><PrecedenceGroupDecl>
+precedencegroup BarPrecedence {}</PrecedenceGroupDecl><PrecedenceGroupDecl>
+precedencegroup BazPrecedence {<PrecedenceGroupAssociativity>
+ associativity: left</PrecedenceGroupAssociativity><PrecedenceGroupAssignment>
+ assignment: true</PrecedenceGroupAssignment><PrecedenceGroupAssociativity>
+ associativity: right</PrecedenceGroupAssociativity><PrecedenceGroupRelation>
+ lowerThan: <PrecedenceGroupNameElement>DefaultPrecedence</PrecedenceGroupNameElement></PrecedenceGroupRelation>
+}</PrecedenceGroupDecl>
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index 8ac911f..0b448fe 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -402,6 +402,8 @@
case 1, 2, 3: break
// This is rejected in Sema, but should be preserved by Syntax.
@unknown case (42, -42) where 1 == 2: break
+ @garbage case 0: break
+ @garbage(foobar) case -1: break
}
}
@@ -458,3 +460,16 @@
case foo, bar, baz
}
}
+
+precedencegroup FooPrecedence {
+ higherThan: DefaultPrecedence, UnknownPrecedence
+ assignment: false
+ associativity: none
+}
+precedencegroup BarPrecedence {}
+precedencegroup BazPrecedence {
+ associativity: left
+ assignment: true
+ associativity: right
+ lowerThan: DefaultPrecedence
+}
diff --git a/test/lit.cfg b/test/lit.cfg
index f63128a..437c7cd 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -405,7 +405,7 @@
# Note: %clang is the locally-built clang.
# To get Xcode's clang, use %target-clang.
config.substitutions.append( ('%clang',
- "%r %r" %
+ "%r %s" %
(config.clang, clang_mcp_opt)) )
###
diff --git a/test/multifile/Inputs/rdar-34584596-A.swift b/test/multifile/Inputs/rdar-34584596-A.swift
new file mode 100644
index 0000000..2bb693f
--- /dev/null
+++ b/test/multifile/Inputs/rdar-34584596-A.swift
@@ -0,0 +1,10 @@
+protocol Attributed {
+ var asAttributes: DefaultedAttributes? { get }
+}
+
+extension Attributed {
+ var asAttributes: DefaultedAttributes? { return self as? DefaultedAttributes }
+}
+
+struct Impl: Attributed {
+}
diff --git a/test/multifile/Inputs/rdar-34584596-B.swift b/test/multifile/Inputs/rdar-34584596-B.swift
new file mode 100644
index 0000000..d56b935
--- /dev/null
+++ b/test/multifile/Inputs/rdar-34584596-B.swift
@@ -0,0 +1,12 @@
+protocol DefaultedAttributes: Attributes {
+}
+
+extension DefaultedAttributes {
+ var attributes: [(title: String, description: String)] {
+ var attributes: [(title: String, description: String)] = []
+ return attributes
+ }
+}
+
+extension Impl: DefaultedAttributes {
+}
diff --git a/test/multifile/Inputs/rdar-34584596-C.swift b/test/multifile/Inputs/rdar-34584596-C.swift
new file mode 100644
index 0000000..6007259
--- /dev/null
+++ b/test/multifile/Inputs/rdar-34584596-C.swift
@@ -0,0 +1,3 @@
+protocol Attributes {
+ var attributes: [(title: String, description: String)] { get }
+}
diff --git a/test/multifile/Inputs/sr-285-other.swift b/test/multifile/Inputs/sr-285-other.swift
new file mode 100644
index 0000000..c949408
--- /dev/null
+++ b/test/multifile/Inputs/sr-285-other.swift
@@ -0,0 +1,34 @@
+// Natural numbers encoded as types:
+protocol NaturalNumberType { static var intValue: Int { get } }
+struct NaturalNumberZero : NaturalNumberType {
+ static var intValue: Int { return 0 }
+}
+struct NaturalNumberSuccessorOf<T: NaturalNumberType> : NaturalNumberType {
+ static var intValue: Int { return T.intValue + 1 }
+}
+// See FourFloats below for an example of how to use the following:
+protocol StaticStorageType {
+ associatedtype Element
+ associatedtype Count: NaturalNumberType
+}
+extension StaticStorageType {
+ typealias Successor = StaticStorageSuccessorOf<Self>
+}
+struct StaticStorageOfOne<E> : StaticStorageType {
+ typealias Element = E
+ typealias Count = NaturalNumberZero
+ var storage: Element
+}
+struct StaticStorageSuccessorOf<T: StaticStorageType> : StaticStorageType {
+ typealias Element = T.Element
+ typealias Count = NaturalNumberSuccessorOf<T.Count>
+ var storage: (Element, T)
+}
+// Using the StaticStorage-thing:
+typealias FourFloats = StaticStorageOfOne<Float>.Successor.Successor.Successor
+
+//-----------------------------------------------------------------------------
+// This function works and will print the number of bytes of FourFloats, ie 16.
+// But compiler will crash if an identical function is declared in main.swift.
+//-----------------------------------------------------------------------------
+func definedInOther() { print(MemoryLayout<FourFloats>.size) }
diff --git a/test/multifile/protocol-conformance-rdar-34584596.swift b/test/multifile/protocol-conformance-rdar-34584596.swift
new file mode 100644
index 0000000..5383d62
--- /dev/null
+++ b/test/multifile/protocol-conformance-rdar-34584596.swift
@@ -0,0 +1,2 @@
+// RUN: not --crash %target-swift-frontend -emit-ir -O -o - -primary-file %S/Inputs/rdar-34584596-A.swift %S/Inputs/rdar-34584596-B.swift %S/Inputs/rdar-34584596-C.swift -module-name main
+
diff --git a/test/multifile/protocol-conformance-sr-285.swift b/test/multifile/protocol-conformance-sr-285.swift
new file mode 100644
index 0000000..8febff2
--- /dev/null
+++ b/test/multifile/protocol-conformance-sr-285.swift
@@ -0,0 +1,6 @@
+// RUN: not --crash %target-swift-frontend -emit-ir -o - -primary-file %s %S/Inputs/sr-285-other.swift -module-name main
+
+// SR-285: Crash in IR generation due to missing conformance.
+func definedInMain() { print(MemoryLayout<FourFloats>.size) }
+
+let d = definedInOther()
diff --git a/test/stdlib/PrintFloat.swift.gyb b/test/stdlib/PrintFloat.swift.gyb
index cc3b59e..135841e 100644
--- a/test/stdlib/PrintFloat.swift.gyb
+++ b/test/stdlib/PrintFloat.swift.gyb
@@ -288,6 +288,7 @@
(0x1.63ed4a60c9c91p+324, "4.751595491707413e+97")
]
+#if !os(Windows) && (arch(i386) || arch(x86_64))
// Float80 found via Errol technique.
//
// As with Double, except for Float80. The original list in this
@@ -334,6 +335,7 @@
(0xd.4d512260c548f17p+242, "9.401053474771583868e+73"),
(0xc.9240ee0f9d5e4d6p+252, "9.097859174935622588e+76"),
]
+#endif
let PrintTests = TestSuite("FloatingPointPrinting")
@@ -544,7 +546,7 @@
// Every power of 10 should print with only a single digit '1'
for power in -45 ... 38 {
let s: String
- if power < -4 || power > 5 { // Exponential form
+ if power < -4 || power > 7 { // Exponential form
s = exponentialPowerOfTen(power)
} else if power < 0 { // Fractional decimal form
s = "0." + String(repeating: "0", count: -power - 1) + "1"
@@ -562,8 +564,14 @@
expectAccurateDescription(f.nextUp)
}
- // Check that the formatter chooses exponential
- // format when it should:
+ // Float can represent all integers -(2^24)...(2^24)
+ let maxDecimalForm = Float(1 << 24)
+ expectDescription("16777216.0", maxDecimalForm)
+ expectDescription("-16777216.0", -maxDecimalForm)
+ // Outside of that range, use exponential form
+ expectDescription("1.6777218e+07", maxDecimalForm.nextUp)
+ expectDescription("-1.6777218e+07", -maxDecimalForm.nextUp)
+
expectDescription("1.00001", asFloat32(1.00001))
expectDescription("1.25e+17", asFloat32(125000000000000000.0))
expectDescription("1.25e+16", asFloat32(12500000000000000.0))
@@ -575,8 +583,8 @@
expectDescription("1.25e+10", asFloat32(12500000000.0))
expectDescription("1.25e+09", asFloat32(1250000000.0))
expectDescription("1.25e+08", asFloat32(125000000.0))
- expectDescription("1.25e+07", asFloat32(12500000.0))
- expectDescription("1.25e+06", asFloat32(1250000.0))
+ expectDescription("12500000.0", asFloat32(12500000.0))
+ expectDescription("1250000.0", asFloat32(1250000.0))
expectDescription("125000.0", asFloat32(125000.0))
expectDescription("12500.0", asFloat32(12500.0))
expectDescription("1250.0", asFloat32(1250.0))
@@ -660,7 +668,7 @@
// We know how every power of 10 should print
for power in -323 ... 308 {
let s: String
- if power < -4 || power > 14 { // Exponential form
+ if power < -4 || power > 15 { // Exponential form
s = exponentialPowerOfTen(power)
} else if power < 0 { // Fractional decimal form
s = "0." + String(repeating: "0", count: -power - 1) + "1"
@@ -687,12 +695,18 @@
}
}
- // Check that the formatter chooses exponential
- // format when it should:
+ // Double can represent all integers -(2^53)...(2^53)
+ let maxDecimalForm = Double((1 as Int64) << 53)
+ expectDescription("9007199254740992.0", maxDecimalForm)
+ expectDescription("-9007199254740992.0", -maxDecimalForm)
+ // Outside of that range, we use exponential form:
+ expectDescription("9.007199254740994e+15", maxDecimalForm.nextUp)
+ expectDescription("-9.007199254740994e+15", -maxDecimalForm.nextUp)
+
expectDescription("1.00000000000001", asFloat64(1.00000000000001))
expectDescription("1.25e+17", asFloat64(125000000000000000.0))
expectDescription("1.25e+16", asFloat64(12500000000000000.0))
- expectDescription("1.25e+15", asFloat64(1250000000000000.0))
+ expectDescription("1250000000000000.0", asFloat64(1250000000000000.0))
expectDescription("125000000000000.0", asFloat64(125000000000000.0))
expectDescription("12500000000000.0", asFloat64(12500000000000.0))
expectDescription("1250000000000.0", asFloat64(1250000000000.0))
@@ -769,7 +783,7 @@
// We know how every power of 10 should print
for power in -4950 ... 4932 {
let s: String
- if power < -4 || power > 17 { // Exponential form
+ if power < -4 || power > 19 { // Exponential form
s = exponentialPowerOfTen(power)
} else if power < 0 { // Fractional decimal form
s = "0." + String(repeating: "0", count: -power - 1) + "1"
@@ -794,11 +808,19 @@
}
}
- // Check that the formatter chooses exponential
- // format when it should:
+ // Float80 can represent all integers -(2^64)...(2^64):
+ let maxDecimalForm = Float80(UInt64.max) + 1.0
+ expectDescription("18446744073709551616.0", maxDecimalForm)
+ expectDescription("-18446744073709551616.0", -maxDecimalForm)
+ // Outside of that range, use exponential form
+ expectDescription("1.8446744073709551618e+19", maxDecimalForm.nextUp)
+ expectDescription("-1.8446744073709551618e+19", -maxDecimalForm.nextUp)
+
expectDescription("1.00000000000000001", asFloat80(1.00000000000000001))
- expectDescription("1.25e+19", asFloat80(12500000000000000000.0))
- expectDescription("1.25e+18", asFloat80(1250000000000000000.0))
+ expectDescription("1.25e+21", asFloat80(1250000000000000000000.0))
+ expectDescription("1.25e+20", asFloat80(125000000000000000000.0))
+ expectDescription("12500000000000000000.0", asFloat80(12500000000000000000.0))
+ expectDescription("1250000000000000000.0", asFloat80(1250000000000000000.0))
expectDescription("125000000000000000.0", asFloat80(125000000000000000.0))
expectDescription("12500000000000000.0", asFloat80(12500000000000000.0))
expectDescription("1250000000000000.0", asFloat80(1250000000000000.0))
diff --git a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp
index 6484aef..ae3236a 100644
--- a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp
+++ b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp
@@ -1663,10 +1663,13 @@
llvm::StringRef inputContents = input.get()->getBuffer();
// This doesn't handle Unicode symbols, but maybe that's okay.
- llvm::Regex maybeSymbol("(_T|" MANGLING_PREFIX_STR ")[_a-zA-Z0-9$]+");
+ // Also accept the future mangling prefix.
+ llvm::Regex maybeSymbol("(_T|_?\\$[Ss])[_a-zA-Z0-9$.]+");
llvm::SmallVector<llvm::StringRef, 1> matches;
while (maybeSymbol.match(inputContents, &matches)) {
addName(matches.front());
+ auto offset = matches.front().data() - inputContents.data();
+ inputContents = inputContents.substr(offset + matches.front().size());
}
} else {
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index ffe43af..9df7cba 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -1230,13 +1230,6 @@
};
} // end anonymous namespace
-static bool isSwiftPrefixed(StringRef MangledName) {
- if (MangledName.size() < 2)
- return false;
- return MangledName[0] == '_' &&
- (MangledName[1] == 'T' || MangledName[1] == MANGLING_PREFIX_STR[1]);
-}
-
static sourcekitd_response_t demangleNames(ArrayRef<const char *> MangledNames,
bool Simplified) {
swift::Demangle::DemangleOptions DemangleOptions;
@@ -1246,7 +1239,7 @@
}
auto getDemangledName = [&](StringRef MangledName) -> std::string {
- if (!isSwiftPrefixed(MangledName))
+ if (!swift::Demangle::isSwiftSymbol(MangledName))
return std::string(); // Not a mangled name
std::string Result = swift::Demangle::demangleSymbolAsString(
@@ -2753,4 +2746,4 @@
} else {
trace::unregisterConsumer(&compileConsumer);
}
-}
\ No newline at end of file
+}
diff --git a/tools/swift-demangle/swift-demangle.cpp b/tools/swift-demangle/swift-demangle.cpp
index 00e2160..b6ddf19 100644
--- a/tools/swift-demangle/swift-demangle.cpp
+++ b/tools/swift-demangle/swift-demangle.cpp
@@ -174,7 +174,6 @@
static int demangleSTDIN(const swift::Demangle::DemangleOptions &options) {
// This doesn't handle Unicode symbols, but maybe that's okay.
// Also accept the future mangling prefix.
- // TODO: remove the "_S" as soon as MANGLING_PREFIX_STR gets "_S".
llvm::Regex maybeSymbol("(_T|_?\\$[Ss])[_a-zA-Z0-9$.]+");
swift::Demangle::Context DCtx;
diff --git a/utils/build_swift/driver_arguments.py b/utils/build_swift/driver_arguments.py
index c8364c4..bd99cc4 100644
--- a/utils/build_swift/driver_arguments.py
+++ b/utils/build_swift/driver_arguments.py
@@ -448,6 +448,9 @@
option('--disable-guaranteed-normal-arguments', store_true,
help='Disable guaranteed normal arguments')
+ option('--enable-stdlibcore-exclusivity-checking', store_true,
+ help='Enable exclusivity checking in stdlibCore')
+
option('--force-optimized-typechecker', store_true,
help='Force the type checker to be built with '
'optimization')
diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py
index 3b687b5..7e397ca 100644
--- a/utils/build_swift/tests/expected_options.py
+++ b/utils/build_swift/tests/expected_options.py
@@ -113,6 +113,7 @@
'enable_lsan': False,
'enable_sil_ownership': False,
'disable_guaranteed_normal_arguments': False,
+ 'enable_stdlibcore_exclusivity_checking': False,
'enable_tsan': False,
'enable_tsan_runtime': False,
'enable_ubsan': False,
@@ -384,6 +385,7 @@
SetTrueOption('--dry-run'),
SetTrueOption('--enable-sil-ownership'),
SetTrueOption('--disable-guaranteed-normal-arguments'),
+ SetTrueOption('--enable-stdlibcore-exclusivity-checking'),
SetTrueOption('--force-optimized-typechecker'),
SetTrueOption('--ios'),
SetTrueOption('--llbuild', dest='build_llbuild'),
diff --git a/utils/gyb_syntax_support/DeclNodes.py b/utils/gyb_syntax_support/DeclNodes.py
index 3733aba..02dbd59 100644
--- a/utils/gyb_syntax_support/DeclNodes.py
+++ b/utils/gyb_syntax_support/DeclNodes.py
@@ -591,4 +591,123 @@
The cases and other members of this enum.
''')
]),
+
+ # precedence-group-decl -> attributes? modifiers? 'precedencegroup'
+ # identifier '{' precedence-group-attribute-list
+ # '}'
+ Node('PrecedenceGroupDecl', kind='Decl', traits=['IdentifiedDecl'],
+ description='A Swift `precedencegroup` declaration.',
+ children=[
+ Child('Attributes', kind='AttributeList', is_optional=True,
+ description='''
+ The attributes applied to the 'precedencegroup' declaration.
+ '''),
+ Child('Modifiers', kind='ModifierList', is_optional=True,
+ description='''
+ The declaration modifiers applied to the 'precedencegroup'
+ declaration.
+ '''),
+ Child('PrecedencegroupKeyword', kind='PrecedencegroupToken'),
+ Child('Identifier', kind='IdentifierToken',
+ description='''
+ The name of this precedence group.
+ '''),
+ Child('LeftBrace', kind='LeftBraceToken'),
+ Child('GroupAttributes', kind='PrecedenceGroupAttributeList',
+ description='''
+ The characteristics of this precedence group.
+ '''),
+ Child('RightBrace', kind='RightBraceToken'),
+ ]),
+
+ # precedence-group-attribute-list ->
+ # (precedence-group-relation | precedence-group-assignment |
+ # precedence-group-associativity )*
+ Node('PrecedenceGroupAttributeList', kind='SyntaxCollection',
+ element='Syntax',
+ element_choices=[
+ 'PrecedenceGroupRelation',
+ 'PrecedenceGroupAssignment',
+ 'PrecedenceGroupAssociativity'
+ ]),
+
+ # precedence-group-relation ->
+ # ('higherThan' | 'lowerThan') ':' precedence-group-name-list
+ Node('PrecedenceGroupRelation', kind='Syntax',
+ description='''
+ Specify the new precedence group's relation to existing precedence
+ groups.
+ ''',
+ children=[
+ Child('HigherThanOrLowerThan', kind='IdentifierToken',
+ text_choices=[
+ 'higherThan', 'lowerThan',
+ ],
+ description='''
+ The relation to specified other precedence groups.
+ '''),
+ Child('Colon', kind='ColonToken'),
+ Child('OtherNames', kind='PrecedenceGroupNameList',
+ description='''
+ The name of other precedence group to which this precedence
+ group relates.
+ '''),
+ ]),
+
+ # precedence-group-name-list ->
+ # identifier (',' identifier)*
+ Node('PrecedenceGroupNameList', kind='SyntaxCollection',
+ element='PrecedenceGroupNameElement'),
+ Node('PrecedenceGroupNameElement', kind='Syntax',
+ children=[
+ Child('Name', kind='IdentifierToken'),
+ Child('TrailingComma', kind='CommaToken',
+ is_optional=True),
+ ]),
+
+ # precedence-group-assignment ->
+ # 'assignment' ':' ('true' | 'false')
+ Node('PrecedenceGroupAssignment', kind='Syntax',
+ description='''
+ Specifies the precedence of an operator when used in an operation
+ that includes optional chaining.
+ ''',
+ children=[
+ Child('AssignmentKeyword', kind='IdentifierToken',
+ text_choices=['assignment']),
+ Child('Colon', kind='ColonToken'),
+ Child('Flag', kind='Token',
+ token_choices=[
+ 'TrueToken',
+ 'FalseToken',
+ ],
+ description='''
+ When true, an operator in the corresponding precedence group
+ uses the same grouping rules during optional chaining as the
+ assignment operators from the standard library. Otherwise,
+ operators in the precedence group follows the same optional
+ chaining rules as operators that don't perform assignment.
+ '''),
+ ]),
+
+ # precedence-group-associativity ->
+ # 'associativity' ':' ('left' | 'right' | 'none')
+ Node('PrecedenceGroupAssociativity', kind='Syntax',
+ description='''
+ Specifies how a sequence of operators with the same precedence level
+ are grouped together in the absence of grouping parentheses.
+ ''',
+ children=[
+ Child('AssociativityKeyword', kind='IdentifierToken',
+ text_choices=['associativity']),
+ Child('Colon', kind='ColonToken'),
+ Child('Value', kind='IdentifierToken',
+ text_choices=['left', 'right', 'none'],
+ description='''
+ Operators that are `left`-associative group left-to-right.
+ Operators that are `right`-associative group right-to-left.
+ Operators that are specified with an associativity of `none`
+ don't associate at all
+ '''),
+ ]),
]
diff --git a/utils/gyb_syntax_support/StmtNodes.py b/utils/gyb_syntax_support/StmtNodes.py
index 8bf0d28..1691854 100644
--- a/utils/gyb_syntax_support/StmtNodes.py
+++ b/utils/gyb_syntax_support/StmtNodes.py
@@ -274,13 +274,6 @@
Child('Colon', kind='ColonToken'),
]),
- # switch-unknown-label -> 'unknown' ':'
- Node('SwitchUnknownLabel', kind='Syntax',
- children=[
- Child('UnknownKeyword', kind='Token'),
- Child('Colon', kind='ColonToken'),
- ]),
-
# case-item -> pattern where-clause? ','?
Node('CaseItem', kind='Syntax',
traits=['WithTrailingComma'],
diff --git a/utils/swift_build_support/swift_build_support/products/swift.py b/utils/swift_build_support/swift_build_support/products/swift.py
index 374a0cb..0782249 100644
--- a/utils/swift_build_support/swift_build_support/products/swift.py
+++ b/utils/swift_build_support/swift_build_support/products/swift.py
@@ -43,6 +43,9 @@
# with optimization.
self.cmake_options.extend(self._force_optimized_typechecker_flags)
+ # Add any exclusivity checking flags for stdlibcore.
+ self.cmake_options.extend(self._stdlibcore_exclusivity_checking_flags)
+
@property
def _runtime_sanitizer_flags(self):
sanitizer_list = []
@@ -127,3 +130,11 @@
if not self.args.force_optimized_typechecker:
return ['-DSWIFT_FORCE_OPTIMIZED_TYPECHECKER=FALSE']
return ['-DSWIFT_FORCE_OPTIMIZED_TYPECHECKER=TRUE']
+
+ @property
+ def _stdlibcore_exclusivity_checking_flags(self):
+ # This is just to get around 80 column limitations.
+ result = '-DSWIFT_STDLIB_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING={}'
+ if not self.args.enable_stdlibcore_exclusivity_checking:
+ return [result.format("FALSE")]
+ return [result.format("TRUE")]
diff --git a/utils/swift_build_support/tests/products/test_swift.py b/utils/swift_build_support/tests/products/test_swift.py
index 9048335..a32be03 100644
--- a/utils/swift_build_support/tests/products/test_swift.py
+++ b/utils/swift_build_support/tests/products/test_swift.py
@@ -57,7 +57,8 @@
benchmark_num_o_iterations=3,
enable_sil_ownership=False,
disable_guaranteed_normal_arguments=True,
- force_optimized_typechecker=False)
+ force_optimized_typechecker=False,
+ enable_stdlibcore_exclusivity_checking=False)
# Setup shell
shell.dry_run = True
@@ -84,11 +85,14 @@
toolchain=self.toolchain,
source_dir='/path/to/src',
build_dir='/path/to/build')
- self.assertEqual(set(swift.cmake_options), set([
- '-DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE',
- '-DSWIFT_STDLIB_ENABLE_SIL_OWNERSHIP=FALSE',
- '-DSWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS=FALSE',
- '-DSWIFT_FORCE_OPTIMIZED_TYPECHECKER=FALSE']))
+ expected = [
+ '-DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE',
+ '-DSWIFT_STDLIB_ENABLE_SIL_OWNERSHIP=FALSE',
+ '-DSWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS=FALSE',
+ '-DSWIFT_FORCE_OPTIMIZED_TYPECHECKER=FALSE',
+ '-DSWIFT_STDLIB_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING=FALSE'
+ ]
+ self.assertEqual(set(swift.cmake_options), set(expected))
def test_swift_runtime_tsan(self):
self.args.enable_tsan_runtime = True
@@ -97,12 +101,15 @@
toolchain=self.toolchain,
source_dir='/path/to/src',
build_dir='/path/to/build')
- flags_set = set(['-DSWIFT_RUNTIME_USE_SANITIZERS=Thread',
- '-DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE',
- '-DSWIFT_STDLIB_ENABLE_SIL_OWNERSHIP=FALSE',
- '-DSWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS=FALSE',
- '-DSWIFT_FORCE_OPTIMIZED_TYPECHECKER=FALSE'])
- self.assertEqual(set(swift.cmake_options), flags_set)
+ flags_set = [
+ '-DSWIFT_RUNTIME_USE_SANITIZERS=Thread',
+ '-DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE',
+ '-DSWIFT_STDLIB_ENABLE_SIL_OWNERSHIP=FALSE',
+ '-DSWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS=FALSE',
+ '-DSWIFT_FORCE_OPTIMIZED_TYPECHECKER=FALSE',
+ '-DSWIFT_STDLIB_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING=FALSE'
+ ]
+ self.assertEqual(set(swift.cmake_options), set(flags_set))
def test_swift_compiler_vendor_flags(self):
self.args.compiler_vendor = "none"
@@ -311,3 +318,15 @@
['-DSWIFT_FORCE_OPTIMIZED_TYPECHECKER=TRUE'],
[x for x in swift.cmake_options
if 'SWIFT_FORCE_OPTIMIZED_TYPECHECKER' in x])
+
+ def test_exclusivity_checking_flags(self):
+ self.args.enable_stdlibcore_exclusivity_checking = True
+ swift = Swift(
+ args=self.args,
+ toolchain=self.toolchain,
+ source_dir='/path/to/src',
+ build_dir='/path/to/build')
+ self.assertEqual(
+ ['-DSWIFT_STDLIB_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING=TRUE'],
+ [x for x in swift.cmake_options
+ if 'SWIFT_STDLIB_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING' in x])
diff --git a/validation-test/compiler_crashers_2_fixed/0152-sr-7397.swift b/validation-test/compiler_crashers_2_fixed/0152-sr-7397.swift
new file mode 100644
index 0000000..6717466
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0152-sr-7397.swift
@@ -0,0 +1,19 @@
+// RUN: %target-typecheck-verify-swift %s
+
+protocol _UnicodeParser_ {
+ associatedtype Encoding: _UnicodeEncoding_
+}
+protocol _UnicodeEncoding_ {
+ associatedtype CodeUnit : BinaryInteger_
+ associatedtype ForwardParser : _UnicodeParser_
+ where ForwardParser.Encoding == Self
+
+}
+protocol BinaryInteger_ {
+ associatedtype Words: Collection_ where Words.Index == Int_
+}
+protocol Collection_ {
+ associatedtype Index: Comparable_
+}
+protocol Comparable_ {}
+struct Int_: Comparable_ {}