Merge pull request #11159 from airspeedswift/4.0-substring-filter
[4.0]Have Substring.filter return a String
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index a7b4f7f..f8f70dd 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -281,6 +281,10 @@
OnClass | NotSerialized | LongAttribute | RejectByParser,
/*Not serialized */ 69)
+DECL_ATTR(_restatedObjCConformance, RestatedObjCConformance,
+ OnProtocol | NotSerialized | LongAttribute | RejectByParser,
+ /*Not serialized */ 70)
+
// 70 is available; it was not a serialized attribute.
// HACK: Attribute needed to preserve source compatibility by downgrading errors
diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h
index 04ffd62..fe71f6a 100644
--- a/include/swift/AST/Attr.h
+++ b/include/swift/AST/Attr.h
@@ -1184,6 +1184,23 @@
}
};
+/// Attribute that specifies a protocol conformance that has been restated
+/// (i.e., is redundant) but should still be emitted in Objective-C metadata.
+class RestatedObjCConformanceAttr : public DeclAttribute {
+public:
+ explicit RestatedObjCConformanceAttr(ProtocolDecl *proto)
+ : DeclAttribute(DAK_RestatedObjCConformance, SourceLoc(), SourceRange(),
+ /*Implicit=*/true),
+ Proto(proto) {}
+
+ /// The protocol to which this type conforms.
+ ProtocolDecl * const Proto;
+
+ static bool classof(const DeclAttribute *DA) {
+ return DA->getKind() == DAK_RestatedObjCConformance;
+ }
+};
+
/// \brief Attributes that may be applied to declarations.
class DeclAttributes {
/// Linked list of declaration attributes.
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index bb53dff..26f6e31 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -142,6 +142,8 @@
"should match %select{space|tab}0 here", (unsigned))
NOTE(lex_multiline_string_indent_change_line,none,
"change indentation of %select{this line|these lines}0 to match closing delimiter", (bool))
+ERROR(lex_escaped_newline_at_lastline,none,
+ "escaped newline at the last line is not allowed", ())
ERROR(lex_invalid_character,none,
"invalid character in source file", ())
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index e9d3eaf..37be2cc 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -2081,6 +2081,20 @@
"cannot automatically synthesize %0 because 'CodingKeys' is not an enum", (Type))
NOTE(codable_codingkeys_type_does_not_conform_here,none,
"cannot automatically synthesize %0 because 'CodingKeys' does not conform to CodingKey", (Type))
+NOTE(decodable_no_super_init_here,none,
+ "cannot automatically synthesize %0 because superclass does not have a callable %1", (DeclName, DeclName))
+NOTE(decodable_super_init_not_designated_here,none,
+ "cannot automatically synthesize %0 because implementation would need to call %1, which is not designated", (DeclName, DeclName))
+NOTE(decodable_inaccessible_super_init_here,none,
+ "cannot automatically synthesize %0 because implementation would need to call %1, which is inaccessible due to "
+ "'%select{private|fileprivate|internal|%error|%error}2' protection level",
+ (DeclName, DeclName, Accessibility))
+NOTE(decodable_super_init_is_failable_here,none,
+ "cannot automatically synthesize %0 because implementation would need to call %1, which is failable", (DeclName, DeclName))
+NOTE(decodable_suggest_overriding_init_here,none,
+ "did you mean to override 'init(from:)'?", ())
+NOTE(codable_suggest_overriding_init_here,none,
+ "did you mean to override 'init(from:)' and 'encode(to:)'?", ())
// Dynamic Self
ERROR(dynamic_self_non_method,none,
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index 154454b..bd13eee 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -347,6 +347,22 @@
enum { NumTupleShuffleExprBits = NumImplicitConversionExprBits + 1 };
static_assert(NumTupleShuffleExprBits <= 32, "fits in an unsigned");
+ class InOutToPointerExprBitfields {
+ friend class InOutToPointerExpr;
+ unsigned : NumImplicitConversionExprBits;
+ unsigned IsNonAccessing : 1;
+ };
+ enum { NumInOutToPointerExprBits = NumImplicitConversionExprBits + 1 };
+ static_assert(NumInOutToPointerExprBits <= 32, "fits in an unsigned");
+
+ class ArrayToPointerExprBitfields {
+ friend class ArrayToPointerExpr;
+ unsigned : NumImplicitConversionExprBits;
+ unsigned IsNonAccessing : 1;
+ };
+ enum { NumArrayToPointerExprBits = NumImplicitConversionExprBits + 1 };
+ static_assert(NumArrayToPointerExprBits <= 32, "fits in an unsigned");
+
class ApplyExprBitfields {
friend class ApplyExpr;
unsigned : NumExprBits;
@@ -434,6 +450,8 @@
CheckedCastExprBitfields CheckedCastExprBits;
CollectionUpcastConversionExprBitfields CollectionUpcastConversionExprBits;
TupleShuffleExprBitfields TupleShuffleExprBits;
+ InOutToPointerExprBitfields InOutToPointerExprBits;
+ ArrayToPointerExprBitfields ArrayToPointerExprBits;
ObjCSelectorExprBitfields ObjCSelectorExprBits;
KeyPathExprBitfields KeyPathExprBits;
};
@@ -2745,8 +2763,19 @@
class InOutToPointerExpr : public ImplicitConversionExpr {
public:
InOutToPointerExpr(Expr *subExpr, Type ty)
- : ImplicitConversionExpr(ExprKind::InOutToPointer, subExpr, ty) {}
-
+ : ImplicitConversionExpr(ExprKind::InOutToPointer, subExpr, ty) {
+ InOutToPointerExprBits.IsNonAccessing = false;
+ }
+
+ /// Is this conversion "non-accessing"? That is, is it only using the
+ /// pointer for its identity, as opposed to actually accessing the memory?
+ bool isNonAccessing() const {
+ return InOutToPointerExprBits.IsNonAccessing;
+ }
+ void setNonAccessing(bool nonAccessing = true) {
+ InOutToPointerExprBits.IsNonAccessing = nonAccessing;
+ }
+
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::InOutToPointer;
}
@@ -2756,8 +2785,19 @@
class ArrayToPointerExpr : public ImplicitConversionExpr {
public:
ArrayToPointerExpr(Expr *subExpr, Type ty)
- : ImplicitConversionExpr(ExprKind::ArrayToPointer, subExpr, ty) {}
+ : ImplicitConversionExpr(ExprKind::ArrayToPointer, subExpr, ty) {
+ ArrayToPointerExprBits.IsNonAccessing = false;
+ }
+ /// Is this conversion "non-accessing"? That is, is it only using the
+ /// pointer for its identity, as opposed to actually accessing the memory?
+ bool isNonAccessing() const {
+ return ArrayToPointerExprBits.IsNonAccessing;
+ }
+ void setNonAccessing(bool nonAccessing = true) {
+ ArrayToPointerExprBits.IsNonAccessing = nonAccessing;
+ }
+
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ArrayToPointer;
}
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index 32bfdc2..90abcb3 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -591,8 +591,9 @@
std::vector<Constraint<T>> &constraints,
llvm::function_ref<bool(const Constraint<T> &)>
isSuitableRepresentative,
- llvm::function_ref<ConstraintRelation(const T&)>
- checkConstraint,
+ llvm::function_ref<
+ ConstraintRelation(const Constraint<T>&)>
+ checkConstraint,
Optional<Diag<unsigned, Type, T, T>>
conflictingDiag,
Diag<Type, T> redundancyDiag,
@@ -615,8 +616,9 @@
std::vector<Constraint<T>> &constraints,
llvm::function_ref<bool(const Constraint<T> &)>
isSuitableRepresentative,
- llvm::function_ref<ConstraintRelation(const T&)>
- checkConstraint,
+ llvm::function_ref<
+ ConstraintRelation(const Constraint<T>&)>
+ checkConstraint,
Optional<Diag<unsigned, Type, DiagT, DiagT>>
conflictingDiag,
Diag<Type, DiagT> redundancyDiag,
diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h
index 9e85dcf..85801e2 100644
--- a/include/swift/AST/Identifier.h
+++ b/include/swift/AST/Identifier.h
@@ -68,6 +68,8 @@
}
bool empty() const { return Pointer == nullptr; }
+
+ bool is(StringRef string) const { return str().equals(string); }
/// isOperator - Return true if this identifier is an operator, false if it is
/// a normal identifier.
@@ -239,7 +241,7 @@
}
bool operator==(StringRef Str) const {
- return !isSpecial() && getIdentifier().str() == Str;
+ return !isSpecial() && getIdentifier().is(Str);
}
bool operator!=(StringRef Str) const { return !(*this == Str); }
@@ -325,7 +327,7 @@
MutableArrayRef<Identifier> getArgumentNames() {
return {getTrailingObjects<Identifier>(), NumArgs};
}
-
+
/// Uniquing for the ASTContext.
static void Profile(llvm::FoldingSetNodeID &id, DeclBaseName baseName,
ArrayRef<Identifier> argumentNames);
@@ -430,14 +432,16 @@
/// True if this name is a simple one-component name equal to the
/// given string.
bool isSimpleName(StringRef name) const {
- if (!isSimpleName())
- return false;
-
- if (getBaseName().isSpecial())
- return false;
-
- return getBaseIdentifier().str().equals(name);
+ return isSimpleName() && getBaseName() == name;
}
+
+ /// True if this name is a compound name equal to the given base name and
+ /// argument names.
+ bool isCompoundName(DeclBaseName base, ArrayRef<StringRef> args) const;
+
+ /// True if this name is a compound name equal to the given normal
+ /// base name and argument names.
+ bool isCompoundName(StringRef base, ArrayRef<StringRef> args) const;
/// True if this name is an operator.
bool isOperator() const {
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 8305984..3f2815b 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -1210,11 +1210,11 @@
ARGS(ErrorPtrTy, Int8PtrPtrTy, OpenedErrorTriplePtrTy),
ATTRS(NoUnwind))
-// void __tsan_write1(void *addr);
+// void __tsan_external_write(void *addr, void *caller_pc, void *tag);
// This is a Thread Sanitizer instrumentation entry point in compiler-rt.
-FUNCTION(TSanInoutAccess, __tsan_write1, C_CC,
+FUNCTION(TSanInoutAccess, __tsan_external_write, C_CC,
RETURNS(VoidTy),
- ARGS(Int8PtrTy),
+ ARGS(Int8PtrTy, Int8PtrTy, Int8PtrTy),
ATTRS(NoUnwind))
FUNCTION(GetKeyPath, swift_getKeyPath, C_CC,
diff --git a/include/swift/SIL/SILVTableVisitor.h b/include/swift/SIL/SILVTableVisitor.h
index fd29b83..1f06d80 100644
--- a/include/swift/SIL/SILVTableVisitor.h
+++ b/include/swift/SIL/SILVTableVisitor.h
@@ -56,7 +56,7 @@
bool needsAllocatingEntry = cd->needsNewVTableEntry();
if (!needsAllocatingEntry)
if (auto *baseCD = cd->getOverriddenDecl())
- needsAllocatingEntry = !baseCD->isRequired();
+ needsAllocatingEntry = !baseCD->isRequired() || baseCD->hasClangNode();
maybeAddEntry(SILDeclRef(cd, SILDeclRef::Kind::Allocator),
needsAllocatingEntry);
}
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index a876a2b..c9fb27d 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 346; // Last change: dependency types for enums
+const uint16_t VERSION_MINOR = 347; // Last change: count inherited conformances
using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
@@ -1147,10 +1147,11 @@
DeclContextIDField, // the decl that provided this conformance
BCVBR<5>, // value mapping count
BCVBR<5>, // type mapping count
+ BCVBR<5>, // requirement signature conformance count
BCArray<DeclIDField>
// The array contains archetype-value pairs, then type declarations.
- // Inherited conformances follow, then the substitution records for the
- // associated types.
+ // Requirement signature conformances follow, then the substitution records
+ // for the associated types.
>;
using SpecializedProtocolConformanceLayout = BCRecordLayout<
@@ -1323,6 +1324,8 @@
using ImplementsDeclAttrLayout = BCRecordLayout<Implements_DECL_ATTR>;
using ObjCRuntimeNameDeclAttrLayout
= BCRecordLayout<ObjCRuntimeName_DECL_ATTR>;
+ using RestatedObjCConformanceDeclAttrLayout
+ = BCRecordLayout<RestatedObjCConformance_DECL_ATTR>;
using InlineDeclAttrLayout = BCRecordLayout<
Inline_DECL_ATTR,
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 1240c95..5f99b20 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -2111,12 +2111,14 @@
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
void visitInOutToPointerExpr(InOutToPointerExpr *E) {
- printCommon(E, "inout_to_pointer") << '\n';
+ printCommon(E, "inout_to_pointer")
+ << (E->isNonAccessing() ? " nonaccessing" : "") << '\n';
printRec(E->getSubExpr());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
void visitArrayToPointerExpr(ArrayToPointerExpr *E) {
- printCommon(E, "array_to_pointer") << '\n';
+ printCommon(E, "array_to_pointer")
+ << (E->isNonAccessing() ? " nonaccessing" : "") << '\n';
printRec(E->getSubExpr());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index 64f5314..8443119 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -573,6 +573,8 @@
case DAK_ObjC:
case DAK_ObjCRuntimeName:
return "objc";
+ case DAK_RestatedObjCConformance:
+ return "_restatedObjCConformance";
case DAK_Inline: {
switch (cast<InlineAttr>(this)->getKind()) {
case InlineKind::Never:
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index fcc45eb..c0bc196 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -4058,8 +4058,9 @@
std::vector<Constraint<T>> &constraints,
llvm::function_ref<bool(const Constraint<T> &)>
isSuitableRepresentative,
- llvm::function_ref<ConstraintRelation(const T&)>
- checkConstraint,
+ llvm::function_ref<
+ ConstraintRelation(const Constraint<T>&)>
+ checkConstraint,
Optional<Diag<unsigned, Type, T, T>>
conflictingDiag,
Diag<Type, T> redundancyDiag,
@@ -4123,8 +4124,9 @@
std::vector<Constraint<T>> &constraints,
llvm::function_ref<bool(const Constraint<T> &)>
isSuitableRepresentative,
- llvm::function_ref<ConstraintRelation(const T&)>
- checkConstraint,
+ llvm::function_ref<
+ ConstraintRelation(const Constraint<T>&)>
+ checkConstraint,
Optional<Diag<unsigned, Type, DiagT, DiagT>>
conflictingDiag,
Diag<Type, DiagT> redundancyDiag,
@@ -4161,7 +4163,7 @@
// Leave the representative alone.
if (constraint == *representativeConstraint) continue;
- switch (checkConstraint(constraint.value)) {
+ switch (checkConstraint(constraint)) {
case ConstraintRelation::Unrelated:
continue;
@@ -4240,6 +4242,42 @@
return *representativeConstraint;
}
+/// Determine whether this is a redundantly inheritable Objective-C protocol.
+///
+/// If we do have a redundantly inheritable Objective-C protocol, record that
+/// the conformance was restated on the protocol whose requirement signature
+/// we are computing.
+///
+/// At present, there is only one such protocol that we know about:
+/// JavaScriptCore's JSExport.
+static bool isRedundantlyInheritableObjCProtocol(
+ ProtocolDecl *proto,
+ const RequirementSource *source) {
+ if (!proto->isObjC()) return false;
+
+ // Only JSExport protocol behaves this way.
+ if (!proto->getName().str().equals("JSExport")) return false;
+
+ // Only do this for the requirement signature computation.
+ auto parentSource = source->parent;
+ if (!parentSource ||
+ parentSource->kind != RequirementSource::RequirementSignatureSelf)
+ return false;
+
+ // If the inheriting protocol already has @_restatedObjCConformance with
+ // this protocol, we're done.
+ auto inheritingProto = parentSource->getProtocolDecl();
+ for (auto *attr : inheritingProto->getAttrs()
+ .getAttributes<RestatedObjCConformanceAttr>()) {
+ if (attr->Proto == proto) return true;
+ }
+
+ // Otherwise, add @_restatedObjCConformance.
+ auto &ctx = proto->getASTContext();
+ inheritingProto->getAttrs().add(new (ctx) RestatedObjCConformanceAttr(proto));
+ return true;
+}
+
void GenericSignatureBuilder::checkConformanceConstraints(
ArrayRef<GenericTypeParamType *> genericParams,
PotentialArchetype *pa) {
@@ -4285,8 +4323,16 @@
[](const Constraint<ProtocolDecl *> &constraint) {
return true;
},
- [&](ProtocolDecl *proto) {
+ [&](const Constraint<ProtocolDecl *> &constraint) {
+ auto proto = constraint.value;
assert(proto == entry.first && "Mixed up protocol constraints");
+
+ // If this is a redundantly inherited Objective-C protocol, treat it
+ // as "unrelated" to silence the warning about the redundant
+ // conformance.
+ if (isRedundantlyInheritableObjCProtocol(proto, constraint.source))
+ return ConstraintRelation::Unrelated;
+
return ConstraintRelation::Redundant;
},
None,
@@ -4594,7 +4640,7 @@
checkConstraintList<PotentialArchetype *, Type>(
genericParams, constraints,
[](const Constraint<PotentialArchetype *> &) { return true; },
- [](PotentialArchetype *) {
+ [](const Constraint<PotentialArchetype *> &) {
return ConstraintRelation::Redundant;
},
None,
@@ -4721,7 +4767,9 @@
[&](const ConcreteConstraint &constraint) {
return constraint.value->isEqual(equivClass->concreteType);
},
- [&](Type concreteType) {
+ [&](const Constraint<Type> &constraint) {
+ Type concreteType = constraint.value;
+
// If the concrete type is equivalent, the constraint is redundant.
// FIXME: Should check this constraint after substituting in the
// archetype anchors for each dependent type.
@@ -4768,7 +4816,9 @@
[&](const ConcreteConstraint &constraint) {
return constraint.value->isEqual(equivClass->superclass);
},
- [&](Type superclass) {
+ [&](const Constraint<Type> &constraint) {
+ Type superclass = constraint.value;
+
// If this class is a superclass of the "best"
if (superclass->isExactSuperclassOf(equivClass->superclass))
return ConstraintRelation::Redundant;
@@ -4835,7 +4885,9 @@
[&](const Constraint<LayoutConstraint> &constraint) {
return constraint.value == equivClass->layout;
},
- [&](LayoutConstraint layout) {
+ [&](const Constraint<LayoutConstraint> &constraint) {
+ auto layout = constraint.value;
+
// If the layout constraints are mergable, i.e. compatible,
// it is a redundancy.
if (layout.merge(equivClass->layout)->isKnownLayout())
diff --git a/lib/AST/Identifier.cpp b/lib/AST/Identifier.cpp
index 7d7df37..9df4375 100644
--- a/lib/AST/Identifier.cpp
+++ b/lib/AST/Identifier.cpp
@@ -104,6 +104,30 @@
return argNames.size() < otherArgNames.size() ? -1 : 1;
}
+static bool equals(ArrayRef<Identifier> idents, ArrayRef<StringRef> strings) {
+ if (idents.size() != strings.size())
+ return false;
+ for (size_t i = 0, e = idents.size(); i != e; ++i) {
+ if (!idents[i].is(strings[i]))
+ return false;
+ }
+ return true;
+}
+
+bool DeclName::isCompoundName(DeclBaseName baseName,
+ ArrayRef<StringRef> argNames) const {
+ return (isCompoundName() &&
+ getBaseName() == baseName &&
+ equals(getArgumentNames(), argNames));
+}
+
+bool DeclName::isCompoundName(StringRef baseName,
+ ArrayRef<StringRef> argNames) const {
+ return (isCompoundName() &&
+ getBaseName() == baseName &&
+ equals(getArgumentNames(), argNames));
+}
+
void DeclName::dump() const {
llvm::errs() << *this << "\n";
}
diff --git a/lib/Basic/Unicode.cpp b/lib/Basic/Unicode.cpp
index 6e33133..332b9c8 100644
--- a/lib/Basic/Unicode.cpp
+++ b/lib/Basic/Unicode.cpp
@@ -16,6 +16,20 @@
using namespace swift;
+// HACK: Allow support for many newer emoji by overriding behavior of ZWJ and
+// emoji modifiers. This does not make the breaks correct for any version of
+// Unicode, but shifts the ways in which it is incorrect to be less harmful.
+//
+// TODO: Remove this hack and reevaluate whether we should have any static
+// notion of what a grapheme is.
+//
+// Returns true if lhs and rhs shouldn't be considered as having a grapheme
+// break between them. That is, whether we're overriding the behavior of the
+// hard coded Unicode 8 rules surrounding ZWJ and emoji modifiers.
+static inline bool graphemeBreakOverride(llvm::UTF32 lhs, llvm::UTF32 rhs) {
+ return lhs == 0x200D || (rhs >= 0x1F3FB && rhs <= 0x1F3FF);
+}
+
StringRef swift::unicode::extractFirstExtendedGraphemeCluster(StringRef S) {
// Extended grapheme cluster segmentation algorithm as described in Unicode
// Standard Annex #29.
@@ -53,7 +67,8 @@
GraphemeClusterBreakProperty GCBForC1 =
getGraphemeClusterBreakProperty(C[1]);
- if (isExtendedGraphemeClusterBoundary(GCBForC0, GCBForC1))
+ if (isExtendedGraphemeClusterBoundary(GCBForC0, GCBForC1) &&
+ !graphemeBreakOverride(C[0], C[1]))
return S.slice(0, C1Offset);
C[0] = C[1];
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 9a04080..4bb5870 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -7092,8 +7092,13 @@
return;
}
- // Map Clang's swift_objc_members attribute to @objcMembers.
- if (ID->hasAttr<clang::SwiftObjCMembersAttr>()) {
+ // Map Clang's swift_objc_members attribute to @objcMembers. Also handle
+ // inheritance of @objcMembers by looking at the superclass.
+ if (ID->hasAttr<clang::SwiftObjCMembersAttr>() ||
+ (isa<ClassDecl>(MappedDecl) &&
+ cast<ClassDecl>(MappedDecl)->hasSuperclass() &&
+ cast<ClassDecl>(MappedDecl)->getSuperclassDecl()
+ ->getAttrs().hasAttribute<ObjCMembersAttr>())) {
if (!MappedDecl->getAttrs().hasAttribute<ObjCMembersAttr>()) {
auto attr = new (C) ObjCMembersAttr(/*IsImplicit=*/true);
MappedDecl->getAttrs().add(attr);
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index 56e7402..a250a8a 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -1159,14 +1159,23 @@
ClassDataBuilder(IRGenModule &IGM, ProtocolDecl *theProtocol)
: IGM(IGM), TheEntity(theProtocol), TheExtension(nullptr)
{
- // Gather protocol references for all of the explicitly-specified
+ llvm::SmallSetVector<ProtocolDecl *, 2> protocols;
+
+ // Gather protocol references for all of the directly inherited
// Objective-C protocol conformances.
- // FIXME: We can't use visitConformances() because there are no
- // conformances for protocols to protocols right now.
for (ProtocolDecl *p : theProtocol->getInheritedProtocols()) {
- if (!p->isObjC())
- continue;
- Protocols.push_back(p);
+ getObjCProtocols(p, protocols);
+ }
+
+ // Add any restated Objective-C protocol conformances.
+ for (auto *attr :
+ theProtocol
+ ->getAttrs().getAttributes<RestatedObjCConformanceAttr>()) {
+ getObjCProtocols(attr->Proto, protocols);
+ }
+
+ for (ProtocolDecl *proto : protocols) {
+ Protocols.push_back(proto);
}
for (Decl *member : theProtocol->getMembers())
diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp
index 15fd6af..bc818d6 100644
--- a/lib/IRGen/GenFunc.cpp
+++ b/lib/IRGen/GenFunc.cpp
@@ -698,6 +698,41 @@
}
}
+static bool isABIIgnoredParameterWithoutStorage(IRGenModule &IGM,
+ IRGenFunction &IGF,
+ CanSILFunctionType substType,
+ unsigned paramIdx) {
+ auto param = substType->getParameters()[paramIdx];
+ SILType argType = IGM.silConv.getSILType(param);
+ auto argLoweringTy =
+ getArgumentLoweringType(argType.getSwiftRValueType(), param);
+ auto &ti = IGF.getTypeInfoForLowered(argLoweringTy);
+ // Empty values don't matter.
+ return ti.getSchema().size() == 0 && !param.isFormalIndirect();
+}
+
+/// Find the parameter index for the one (assuming there was only one) partially
+/// applied argument ignoring empty types that are not passed as part of the
+/// ABI.
+static unsigned findSinglePartiallyAppliedParameterIndexIgnoringEmptyTypes(
+ IRGenFunction &IGF, CanSILFunctionType substType,
+ CanSILFunctionType outType) {
+ auto substParameters = substType->getParameters();
+ auto outParamters = outType->getParameters();
+ unsigned firstNonEmpty = -1U;
+ for (unsigned paramIdx = outParamters.size() ; paramIdx != substParameters.size(); ++paramIdx) {
+ bool isEmpty =
+ isABIIgnoredParameterWithoutStorage(IGF.IGM, IGF, substType, paramIdx);
+ assert((isEmpty || firstNonEmpty == -1U) && "Expect at most one partially "
+ "applied that is passed as an "
+ "ABI argument");
+ if (!isEmpty)
+ firstNonEmpty = paramIdx;
+ }
+ assert(firstNonEmpty != -1U);
+ return firstNonEmpty;
+}
+
/// Emit the forwarding stub function for a partial application.
///
/// If 'layout' is null, there is a single captured value of
@@ -919,11 +954,9 @@
// care for the former for the purpose of reconstructing polymorphic
// parameters from regular arguments.
if (!calleeHasContext) {
- unsigned paramI = substType->getParameters().size() - 1;
- assert(substType->getParameters().size() -
- outType->getParameters().size() ==
- 1 &&
- "Expect one partially applied argument");
+ unsigned paramI =
+ findSinglePartiallyAppliedParameterIndexIgnoringEmptyTypes(
+ subIGF, substType, outType);
auto paramInfo = substType->getParameters()[paramI];
auto &ti = IGM.getTypeInfoForLowered(paramInfo.getType());
Explosion param;
@@ -1095,13 +1128,8 @@
// Skip empty parameters.
while (origParamI < origType->getParameters().size()) {
- auto param = substType->getParameters()[origParamI];
- SILType argType = IGM.silConv.getSILType(param);
- auto argLoweringTy =
- getArgumentLoweringType(argType.getSwiftRValueType(), param);
- auto &ti = subIGF.getTypeInfoForLowered(argLoweringTy);
- // Empty values don't matter.
- if (ti.getSchema().size() != 0 || param.isFormalIndirect())
+ if (!isABIIgnoredParameterWithoutStorage(IGM, subIGF, substType,
+ origParamI))
break;
origParamI++;
}
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index e9a95db..1d726bf 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -250,7 +250,18 @@
llvm::Function *fn = cast<llvm::Function>(IGM.getTSanInoutAccessFn());
llvm::Value *castAddress = Builder.CreateBitCast(address, IGM.Int8PtrTy);
- Builder.CreateCall(fn, {castAddress});
+
+ // Passing 0 as the caller PC causes compiler-rt to get our PC.
+ llvm::Value *callerPC = llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
+
+ // A magic number agreed upon with compiler-rt to indicate a modifying
+ // access.
+ const unsigned kExternalTagSwiftModifyingAccess = 0x1;
+ llvm::Value *tagValue =
+ llvm::ConstantInt::get(IGM.SizeTy, kExternalTagSwiftModifyingAccess);
+ llvm::Value *castTag = Builder.CreateIntToPtr(tagValue, IGM.Int8PtrTy);
+
+ Builder.CreateCall(fn, {castAddress, callerPC, castTag});
}
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index 9170c23..f2a3845 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -1122,6 +1122,27 @@
return CharValue;
}
+/// maybeConsumeNewlineEscape - Check for valid elided newline escape and
+/// move pointer passed in to the character after the end of the line.
+static bool maybeConsumeNewlineEscape(const char *&CurPtr, ssize_t Offset) {
+ const char *TmpPtr = CurPtr + Offset;
+ while (true) {
+ switch (*TmpPtr++) {
+ case ' ': case '\t':
+ continue;
+ case '\r':
+ if (*TmpPtr == '\n')
+ TmpPtr++;
+ LLVM_FALLTHROUGH;
+ case '\n':
+ CurPtr = TmpPtr;
+ return true;
+ case 0:
+ default:
+ return false;
+ }
+ }
+}
/// lexCharacter - Read a character and return its UTF32 code. If this is the
/// end of enclosing string/character sequence (i.e. the character is equal to
@@ -1187,6 +1208,10 @@
unsigned CharValue = 0;
// Escape processing. We already ate the "\".
switch (*CurPtr) {
+ case ' ': case '\t': case '\n': case '\r':
+ if (MultilineString && maybeConsumeNewlineEscape(CurPtr, 0))
+ return '\n';
+ LLVM_FALLTHROUGH;
default: // Invalid escape.
if (EmitDiagnostics)
diagnose(CurPtr, diag::lex_invalid_escape);
@@ -1313,7 +1338,11 @@
// Entering a recursive interpolated expression
OpenDelimiters.push_back('(');
continue;
- case '\n': case '\r': case 0:
+ case '\n': case '\r':
+ if (AllowNewline.back())
+ continue;
+ LLVM_FALLTHROUGH;
+ case 0:
// Don't jump over newline/EOF due to preceding backslash!
return CurPtr-1;
default:
@@ -1395,13 +1424,28 @@
continue;
case '\n':
case '\r': {
- auto bytes = start + 1;
- auto length = end-(start+1);
-
- auto bytesLoc = Lexer::getSourceLoc(bytes);
- auto string = StringRef(bytes, length);
-
- return std::make_tuple(string, bytesLoc);
+ start++;
+ auto startLoc = Lexer::getSourceLoc(start);
+ auto string = StringRef(start, end - start);
+
+ // Disallow escaped newline in the last line.
+ if (Diags) {
+ auto *Ptr = start - 1;
+ if (*Ptr == '\n') --Ptr;
+ if (*Ptr == '\r') --Ptr;
+ auto *LineEnd = Ptr + 1;
+ while (Ptr > begin && (*Ptr == ' ' || *Ptr == '\t')) --Ptr;
+ if (*Ptr == '\\') {
+ auto escapeLoc = Lexer::getSourceLoc(Ptr);
+ bool invalid = true;
+ while (*--Ptr == '\\') invalid = !invalid;
+ if (invalid)
+ Diags->diagnose(escapeLoc, diag::lex_escaped_newline_at_lastline)
+ .fixItRemoveChars(escapeLoc, Lexer::getSourceLoc(LineEnd));
+ }
+ }
+
+ return std::make_tuple(string, startLoc);
}
default:
sawNonWhitespace = true;
@@ -1816,12 +1860,14 @@
// we know that there is a terminating " character. Use BytesPtr to avoid a
// range check subscripting on the StringRef.
const char *BytesPtr = Bytes.begin();
+ bool IsEscapedNewline = false;
while (BytesPtr < Bytes.end()) {
char CurChar = *BytesPtr++;
// Multiline string line ending normalization and indent stripping.
if (CurChar == '\r' || CurChar == '\n') {
- bool stripNewline = IsFirstSegment && BytesPtr - 1 == Bytes.begin();
+ bool stripNewline = IsEscapedNewline ||
+ (IsFirstSegment && BytesPtr - 1 == Bytes.begin());
if (CurChar == '\r' && *BytesPtr == '\n')
BytesPtr++;
if (*BytesPtr != '\r' && *BytesPtr != '\n')
@@ -1830,6 +1876,7 @@
stripNewline = true;
if (!stripNewline)
TempString.push_back('\n');
+ IsEscapedNewline = false;
continue;
}
@@ -1854,6 +1901,12 @@
case '\'': TempString.push_back('\''); continue;
case '\\': TempString.push_back('\\'); continue;
+ case ' ': case '\t': case '\n': case '\r':
+ if (maybeConsumeNewlineEscape(BytesPtr, -1)) {
+ IsEscapedNewline = true;
+ BytesPtr--;
+ }
+ continue;
// String interpolation.
case '(':
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 7623365..c23c315 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -570,6 +570,7 @@
case DAK_RawDocComment:
case DAK_ObjCBridged:
case DAK_ObjCRuntimeName:
+ case DAK_RestatedObjCConformance:
case DAK_SynthesizedProtocol:
llvm_unreachable("virtual attributes should not be parsed "
"by attribute parsing code");
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index 6bead03..bb5c5f8 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -1144,6 +1144,7 @@
case tok::code_complete:
case tok::exclaim_postfix:
case tok::question_postfix:
+ case tok::colon:
return true;
case tok::oper_binary_spaced:
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 8cbfb9f..9669777 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -797,8 +797,16 @@
// @NSManaged property, then it won't be in the vtable.
if (overridden.getDecl()->hasClangNode())
return SILDeclRef();
- if (overridden.getDecl()->isDynamic())
+
+ // If we overrode a non-required initializer, there won't be a vtable
+ // slot for the allocator.
+ if (overridden.kind == SILDeclRef::Kind::Allocator) {
+ if (!cast<ConstructorDecl>(overridden.getDecl())->isRequired())
+ return SILDeclRef();
+ } else if (overridden.getDecl()->isDynamic()) {
return SILDeclRef();
+ }
+
if (auto *ovFD = dyn_cast<FuncDecl>(overridden.getDecl()))
if (auto *asd = ovFD->getAccessorStorageDecl()) {
if (asd->hasClangNode())
@@ -812,13 +820,6 @@
if (isa<ExtensionDecl>(overridden.getDecl()->getDeclContext()))
return SILDeclRef();
- // If we overrode a non-required initializer, there won't be a vtable
- // slot for the allocator.
- if (overridden.kind == SILDeclRef::Kind::Allocator &&
- !cast<ConstructorDecl>(overridden.getDecl())->isRequired()) {
- return SILDeclRef();
- }
-
return overridden;
}
return SILDeclRef();
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 2379265..d7da2e8 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -1783,8 +1783,11 @@
return true;
if (method.kind == SILDeclRef::Kind::Allocator) {
auto *ctor = cast<ConstructorDecl>(method.getDecl());
- if (ctor->isRequired() && !ctor->getOverriddenDecl()->isRequired())
- return true;
+ if (ctor->isRequired()) {
+ if (!ctor->getOverriddenDecl()->isRequired()
+ || ctor->getOverriddenDecl()->hasClangNode())
+ return true;
+ }
}
return false;
}
diff --git a/lib/SILGen/LValue.h b/lib/SILGen/LValue.h
index f97251b..f3ec878 100644
--- a/lib/SILGen/LValue.h
+++ b/lib/SILGen/LValue.h
@@ -396,6 +396,7 @@
void addMemberComponent(SILGenFunction &SGF, SILLocation loc,
AbstractStorageDecl *storage,
SubstitutionList subs,
+ LValueOptions options,
bool isSuper,
AccessKind accessKind,
AccessSemantics accessSemantics,
@@ -406,6 +407,7 @@
void addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
VarDecl *var,
SubstitutionList subs,
+ LValueOptions options,
bool isSuper,
AccessKind accessKind,
AccessSemantics accessSemantics,
@@ -415,6 +417,7 @@
void addMemberSubscriptComponent(SILGenFunction &SGF, SILLocation loc,
SubscriptDecl *subscript,
SubstitutionList subs,
+ LValueOptions options,
bool isSuper,
AccessKind accessKind,
AccessSemantics accessSemantics,
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index c0aece8..c4be751 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -2826,7 +2826,10 @@
bool emitDelayedConversion(InOutToPointerExpr *pointerExpr,
OriginalArgument original) {
auto info = SGF.getPointerAccessInfo(pointerExpr->getType());
- LValue lv = SGF.emitLValue(pointerExpr->getSubExpr(), info.AccessKind);
+ LValueOptions options;
+ options.IsNonAccessing = pointerExpr->isNonAccessing();
+ LValue lv = SGF.emitLValue(pointerExpr->getSubExpr(), info.AccessKind,
+ options);
DelayedArguments.emplace_back(info, std::move(lv), pointerExpr, original);
Args.push_back(ManagedValue());
return true;
@@ -2841,7 +2844,9 @@
if (auto inoutType = arrayExpr->getType()->getAs<InOutType>()) {
auto info = SGF.getArrayAccessInfo(pointerExpr->getType(),
inoutType->getObjectType());
- LValue lv = SGF.emitLValue(arrayExpr, info.AccessKind);
+ LValueOptions options;
+ options.IsNonAccessing = pointerExpr->isNonAccessing();
+ LValue lv = SGF.emitLValue(arrayExpr, info.AccessKind, options);
DelayedArguments.emplace_back(info, std::move(lv), pointerExpr,
original);
Args.push_back(ManagedValue());
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 2f002ef..0c2f0c2 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -765,7 +765,7 @@
->getInOutObjectType()->getCanonicalType();
auto self = emitSelfForMemberInit(SGF, loc, selfDecl);
return SGF.emitPropertyLValue(loc, self, selfFormalType, property,
- AccessKind::Write,
+ LValueOptions(), AccessKind::Write,
AccessSemantics::DirectToStorage);
}
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index e97016c..cef65a1 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -962,7 +962,7 @@
// If the base is a reference type, just handle this as loading the lvalue.
if (baseFormalType->hasReferenceSemantics()) {
LValue LV = emitPropertyLValue(loc, base, baseFormalType, field,
- AccessKind::Read,
+ LValueOptions(), AccessKind::Read,
AccessSemantics::DirectToStorage);
return emitLoadOfLValue(loc, std::move(LV), C, isGuaranteedValid);
}
@@ -2673,10 +2673,11 @@
SmallVector<Substitution, 4> subsList;
if (subs.getGenericSignature())
subs.getGenericSignature()->getSubstitutions(subs, subsList);
-
- lv.addMemberVarComponent(subSGF, loc, property, subsList, /*super*/ false,
- AccessKind::Write, AccessSemantics::Ordinary,
- strategy, propertyType);
+
+ LValueOptions lvOptions;
+ lv.addMemberVarComponent(subSGF, loc, property, subsList, lvOptions,
+ /*super*/ false, AccessKind::Write,
+ AccessSemantics::Ordinary, strategy, propertyType);
subSGF.emitAssignToLValue(loc,
RValue(subSGF, loc, propertyType, valueSubst),
diff --git a/lib/SILGen/SILGenForeignError.cpp b/lib/SILGen/SILGenForeignError.cpp
index 89d9185..2f55463 100644
--- a/lib/SILGen/SILGenForeignError.cpp
+++ b/lib/SILGen/SILGenForeignError.cpp
@@ -100,6 +100,7 @@
LValue lvalue =
gen.emitPropertyLValue(loc, ManagedValue::forUnmanaged(foreignErrorSlot),
bridgedErrorPtrType, pointeeProperty,
+ LValueOptions(),
AccessKind::Write,
AccessSemantics::Ordinary);
RValue rvalue(gen, loc, bridgedErrorProto,
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 59ecc38..c6aff6b 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -197,6 +197,28 @@
return (lhs = (lhs - rhs));
}
+struct LValueOptions {
+ bool IsNonAccessing = false;
+
+ /// Derive options for accessing the base of an l-value, given that
+ /// applying the derived component might touch the memory.
+ LValueOptions forComputedBaseLValue() const {
+ auto copy = *this;
+
+ // Assume we're going to access the base.
+ copy.IsNonAccessing = false;
+
+ return copy;
+ }
+
+ /// Derive options for accessing the base of an l-value, given that
+ /// applying the derived component will not touch the memory.
+ LValueOptions forProjectedBaseLValue() const {
+ auto copy = *this;
+ return copy;
+ }
+};
+
class PatternMatchContext;
/// A formal section of the function. This is a SILGen-only concept,
@@ -1740,7 +1762,8 @@
ExistentialRepresentation repr);
/// Evaluate an Expr as an lvalue.
- LValue emitLValue(Expr *E, AccessKind accessKind);
+ LValue emitLValue(Expr *E, AccessKind accessKind,
+ LValueOptions options = LValueOptions());
/// Emit a reference to a variable as an lvalue.
LValue emitLValueForAddressedNonMemberVarDecl(SILLocation loc, VarDecl *var,
@@ -1752,6 +1775,7 @@
/// (without going through getters or setters).
LValue emitPropertyLValue(SILLocation loc, ManagedValue base,
CanType baseFormalType, VarDecl *var,
+ LValueOptions options,
AccessKind accessKind, AccessSemantics semantics);
struct PointerAccessInfo {
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index f5f8a30..98c6383 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -165,42 +165,55 @@
/// SILGenLValue - An ASTVisitor for building logical lvalues.
class LLVM_LIBRARY_VISIBILITY SILGenLValue
- : public Lowering::ExprVisitor<SILGenLValue, LValue, AccessKind>
+ : public Lowering::ExprVisitor<SILGenLValue, LValue,
+ AccessKind, LValueOptions>
{
public:
SILGenFunction &SGF;
SILGenLValue(SILGenFunction &SGF) : SGF(SGF) {}
- LValue visitRec(Expr *e, AccessKind accessKind,
+ LValue visitRec(Expr *e, AccessKind accessKind, LValueOptions options,
AbstractionPattern orig = AbstractionPattern::getInvalid());
/// Dummy handler to log unimplemented nodes.
- LValue visitExpr(Expr *e, AccessKind accessKind);
+ LValue visitExpr(Expr *e, AccessKind accessKind, LValueOptions options);
// Nodes that form the root of lvalue paths
LValue visitDiscardAssignmentExpr(DiscardAssignmentExpr *e,
- AccessKind accessKind);
- LValue visitDeclRefExpr(DeclRefExpr *e, AccessKind accessKind);
- LValue visitOpaqueValueExpr(OpaqueValueExpr *e, AccessKind accessKind);
+ AccessKind accessKind,
+ LValueOptions options);
+ LValue visitDeclRefExpr(DeclRefExpr *e, AccessKind accessKind,
+ LValueOptions options);
+ LValue visitOpaqueValueExpr(OpaqueValueExpr *e, AccessKind accessKind,
+ LValueOptions options);
// Nodes that make up components of lvalue paths
- LValue visitMemberRefExpr(MemberRefExpr *e, AccessKind accessKind);
- LValue visitSubscriptExpr(SubscriptExpr *e, AccessKind accessKind);
- LValue visitTupleElementExpr(TupleElementExpr *e, AccessKind accessKind);
- LValue visitForceValueExpr(ForceValueExpr *e, AccessKind accessKind);
- LValue visitBindOptionalExpr(BindOptionalExpr *e, AccessKind accessKind);
+ LValue visitMemberRefExpr(MemberRefExpr *e, AccessKind accessKind,
+ LValueOptions options);
+ LValue visitSubscriptExpr(SubscriptExpr *e, AccessKind accessKind,
+ LValueOptions options);
+ LValue visitTupleElementExpr(TupleElementExpr *e, AccessKind accessKind,
+ LValueOptions options);
+ LValue visitForceValueExpr(ForceValueExpr *e, AccessKind accessKind,
+ LValueOptions options);
+ LValue visitBindOptionalExpr(BindOptionalExpr *e, AccessKind accessKind,
+ LValueOptions options);
LValue visitOpenExistentialExpr(OpenExistentialExpr *e,
- AccessKind accessKind);
+ AccessKind accessKind,
+ LValueOptions options);
LValue visitKeyPathApplicationExpr(KeyPathApplicationExpr *e,
- AccessKind accessKind);
+ AccessKind accessKind,
+ LValueOptions options);
// Expressions that wrap lvalues
- LValue visitInOutExpr(InOutExpr *e, AccessKind accessKind);
+ LValue visitInOutExpr(InOutExpr *e, AccessKind accessKind,
+ LValueOptions options);
LValue visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *e,
- AccessKind accessKind);
+ AccessKind accessKind,
+ LValueOptions options);
};
static ManagedValue
@@ -529,11 +542,13 @@
class RefElementComponent : public PhysicalPathComponent {
VarDecl *Field;
SILType SubstFieldType;
+ bool IsNonAccessing;
public:
- RefElementComponent(VarDecl *field, SILType substFieldType,
- LValueTypeData typeData)
+ RefElementComponent(VarDecl *field, LValueOptions options,
+ SILType substFieldType, LValueTypeData typeData)
: PhysicalPathComponent(typeData, RefElementKind),
- Field(field), SubstFieldType(substFieldType) {}
+ Field(field), SubstFieldType(substFieldType),
+ IsNonAccessing(options.IsNonAccessing) {}
ManagedValue offset(SILGenFunction &SGF, SILLocation loc, ManagedValue base,
AccessKind accessKind) && override {
@@ -548,9 +563,11 @@
SGF.B.createRefElementAddr(loc, base.getUnmanagedValue(),
Field, SubstFieldType);
- if (auto enforcement = SGF.getDynamicEnforcement(Field)) {
- result = enterAccessScope(SGF, loc, result, getTypeData(),
- accessKind, *enforcement);
+ if (!IsNonAccessing) {
+ if (auto enforcement = SGF.getDynamicEnforcement(Field)) {
+ result = enterAccessScope(SGF, loc, result, getTypeData(),
+ accessKind, *enforcement);
+ }
}
return ManagedValue::forLValue(result);
@@ -890,6 +907,18 @@
return false;
}
+static LValueOptions getBaseOptions(LValueOptions options,
+ AccessStrategy strategy) {
+ return (strategy == AccessStrategy::Storage
+ ? options.forProjectedBaseLValue()
+ : options.forComputedBaseLValue());
+}
+
+static ArgumentSource emitBaseValueForAccessor(SILGenFunction &SGF,
+ SILLocation loc, LValue &&dest,
+ CanType baseFormalType,
+ SILDeclRef accessor);
+
namespace {
/// A helper class for implementing a component that involves
/// calling accessors.
@@ -1843,6 +1872,7 @@
void LValue::addMemberComponent(SILGenFunction &SGF, SILLocation loc,
AbstractStorageDecl *storage,
SubstitutionList subs,
+ LValueOptions options,
bool isSuper,
AccessKind accessKind,
AccessSemantics accessSemantics,
@@ -1851,12 +1881,12 @@
RValue &&indices) {
if (auto var = dyn_cast<VarDecl>(storage)) {
assert(!indices);
- addMemberVarComponent(SGF, loc, var, subs, isSuper,
+ addMemberVarComponent(SGF, loc, var, subs, options, isSuper,
accessKind, accessSemantics, accessStrategy,
formalRValueType);
} else {
auto subscript = cast<SubscriptDecl>(storage);
- addMemberSubscriptComponent(SGF, loc, subscript, subs, isSuper,
+ addMemberSubscriptComponent(SGF, loc, subscript, subs, options, isSuper,
accessKind, accessSemantics, accessStrategy,
formalRValueType, std::move(indices));
}
@@ -1915,13 +1945,14 @@
}
}
-LValue SILGenFunction::emitLValue(Expr *e, AccessKind accessKind) {
+LValue SILGenFunction::emitLValue(Expr *e, AccessKind accessKind,
+ LValueOptions options) {
// Some lvalue nodes (namely BindOptionalExprs) require immediate evaluation
// of their subexpression, so we must have a writeback scope open while
// building an lvalue.
assert(InWritebackScope && "must be in a writeback scope");
- LValue r = SILGenLValue(*this).visit(e, accessKind);
+ LValue r = SILGenLValue(*this).visit(e, accessKind, options);
// If the final component has an abstraction change, introduce a
// reabstraction component.
auto substFormalType = r.getSubstFormalType();
@@ -1936,6 +1967,7 @@
}
LValue SILGenLValue::visitRec(Expr *e, AccessKind accessKind,
+ LValueOptions options,
AbstractionPattern orig) {
// Non-lvalue types (references, values, metatypes, etc) form the root of a
// logical l-value.
@@ -1998,7 +2030,7 @@
return lv;
}
- auto lv = visit(e, accessKind);
+ auto lv = visit(e, accessKind, options);
// If necessary, handle reabstraction with a SubstToOrigComponent that handles
// writeback in the original representation.
if (orig.isValid()) {
@@ -2009,7 +2041,8 @@
return lv;
}
-LValue SILGenLValue::visitExpr(Expr *e, AccessKind accessKind) {
+LValue SILGenLValue::visitExpr(Expr *e, AccessKind accessKind,
+ LValueOptions options) {
e->dump(llvm::errs());
llvm_unreachable("unimplemented lvalue expr");
}
@@ -2053,6 +2086,7 @@
SILLocation loc, VarDecl *var,
CanType formalRValueType,
AccessKind accessKind,
+ LValueOptions options,
AccessSemantics semantics) {
LValue lv;
@@ -2086,7 +2120,9 @@
Optional<SILAccessEnforcement> enforcement;
if (!var->isLet()) {
- if (var->getDeclContext()->isLocalContext()) {
+ if (options.IsNonAccessing) {
+ enforcement = None;
+ } else if (var->getDeclContext()->isLocalContext()) {
enforcement = SGF.getUnknownEnforcement(var);
} else if (var->getDeclContext()->isModuleScopeContext()) {
enforcement = SGF.getDynamicEnforcement(var);
@@ -2114,7 +2150,8 @@
LValue SILGenLValue::visitDiscardAssignmentExpr(DiscardAssignmentExpr *e,
- AccessKind accessKind) {
+ AccessKind accessKind,
+ LValueOptions options) {
LValueTypeData typeData = getValueTypeData(SGF, e);
SILValue address = SGF.emitTemporaryAllocation(e, typeData.TypeOfRValue);
@@ -2127,16 +2164,18 @@
}
-LValue SILGenLValue::visitDeclRefExpr(DeclRefExpr *e, AccessKind accessKind) {
+LValue SILGenLValue::visitDeclRefExpr(DeclRefExpr *e, AccessKind accessKind,
+ LValueOptions options) {
// The only non-member decl that can be an lvalue is VarDecl.
return emitLValueForNonMemberVarDecl(SGF, e, cast<VarDecl>(e->getDecl()),
getSubstFormalRValueType(e),
- accessKind,
+ accessKind, options,
e->getAccessSemantics());
}
LValue SILGenLValue::visitOpaqueValueExpr(OpaqueValueExpr *e,
- AccessKind accessKind) {
+ AccessKind accessKind,
+ LValueOptions options) {
// Handle an opaque lvalue that refers to an opened existential.
auto known = SGF.OpaqueValueExprs.find(e);
if (known != SGF.OpaqueValueExprs.end()) {
@@ -2145,7 +2184,7 @@
SGF.OpaqueValueExprs.erase(known);
// Do formal evaluation of the underlying existential lvalue.
- auto lv = visitRec(opened->getExistentialValue(), accessKind);
+ auto lv = visitRec(opened->getExistentialValue(), accessKind, options);
lv = SGF.emitOpenExistentialLValue(
opened, std::move(lv),
CanArchetypeType(opened->getOpenedArchetype()),
@@ -2168,9 +2207,10 @@
}
LValue SILGenLValue::visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *e,
- AccessKind accessKind) {
+ AccessKind accessKind,
+ LValueOptions options) {
SGF.emitIgnoredExpr(e->getLHS());
- return visitRec(e->getRHS(), accessKind);
+ return visitRec(e->getRHS(), accessKind, options);
}
static AccessKind getBaseAccessKindForAccessor(FuncDecl *accessor) {
@@ -2213,7 +2253,8 @@
}
LValue SILGenLValue::visitMemberRefExpr(MemberRefExpr *e,
- AccessKind accessKind) {
+ AccessKind accessKind,
+ LValueOptions options) {
// MemberRefExpr can refer to type and function members, but the only case
// that can be an lvalue is a VarDecl.
VarDecl *var = cast<VarDecl>(e->getMember().getDecl());
@@ -2221,12 +2262,14 @@
var->getAccessStrategy(e->getAccessSemantics(), accessKind);
LValue lv = visitRec(e->getBase(),
- getBaseAccessKind(var, accessKind, strategy));
+ getBaseAccessKind(var, accessKind, strategy),
+ getBaseOptions(options, strategy));
assert(lv.isValid());
CanType substFormalRValueType = getSubstFormalRValueType(e);
lv.addMemberVarComponent(SGF, e, var, e->getMember().getSubstitutions(),
- e->isSuper(), accessKind, e->getAccessSemantics(),
+ options, e->isSuper(), accessKind,
+ e->getAccessSemantics(),
strategy, substFormalRValueType);
return lv;
}
@@ -2234,6 +2277,7 @@
void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
VarDecl *var,
SubstitutionList subs,
+ LValueOptions options,
bool isSuper,
AccessKind accessKind,
AccessSemantics accessSemantics,
@@ -2270,8 +2314,8 @@
// we ought to evaluate them for side-effects even during the
// formal access?
*this = emitLValueForNonMemberVarDecl(SGF, loc, var,
- formalRValueType,
- accessKind, accessSemantics);
+ formalRValueType, accessKind,
+ options, accessSemantics);
return;
}
@@ -2291,7 +2335,7 @@
add<AddressorComponent>(var, isSuper, /*direct*/ true, subs,
baseFormalType, typeData, varStorageType);
} else if (baseFormalType->mayHaveSuperclass()) {
- add<RefElementComponent>(var, varStorageType, typeData);
+ add<RefElementComponent>(var, options, varStorageType, typeData);
} else {
assert(baseFormalType->getStructOrBoundGenericStruct());
add<StructElementComponent>(var, varStorageType, typeData);
@@ -2304,14 +2348,16 @@
}
LValue SILGenLValue::visitSubscriptExpr(SubscriptExpr *e,
- AccessKind accessKind) {
+ AccessKind accessKind,
+ LValueOptions options) {
auto decl = cast<SubscriptDecl>(e->getDecl().getDecl());
auto accessSemantics = e->getAccessSemantics();
auto strategy = decl->getAccessStrategy(accessSemantics, accessKind);
LValue lv = visitRec(e->getBase(),
- getBaseAccessKind(decl, accessKind, strategy));
+ getBaseAccessKind(decl, accessKind, strategy),
+ getBaseOptions(options, strategy));
assert(lv.isValid());
Expr *indexExpr = e->getIndex();
@@ -2321,14 +2367,16 @@
CanType formalRValueType = getSubstFormalRValueType(e);
lv.addMemberSubscriptComponent(SGF, e, decl, e->getDecl().getSubstitutions(),
- e->isSuper(), accessKind, accessSemantics,
- strategy, formalRValueType, std::move(index),
+ options, e->isSuper(), accessKind,
+ accessSemantics, strategy,
+ formalRValueType, std::move(index),
indexExpr);
return lv;
}
LValue SILGenLValue::visitKeyPathApplicationExpr(KeyPathApplicationExpr *e,
- AccessKind accessKind) {
+ AccessKind accessKind,
+ LValueOptions options) {
// Determine the base access strategy based on the strategy of this access.
auto keyPathTy = e->getKeyPath()->getType()->castTo<BoundGenericType>();
AccessKind subAccess;
@@ -2341,9 +2389,12 @@
// keypath.
subAccess = AccessKind::Read;
}
+
+ // For now, just ignore any options we were given.
+ LValueOptions subOptions = LValueOptions();
// The base should be reabstracted to the maximal abstraction pattern.
- LValue lv = visitRec(e->getBase(), subAccess,
+ LValue lv = visitRec(e->getBase(), subAccess, subOptions,
AbstractionPattern::getOpaque());
// The result will end up projected at the maximal abstraction level too.
@@ -2369,6 +2420,7 @@
void LValue::addMemberSubscriptComponent(SILGenFunction &SGF, SILLocation loc,
SubscriptDecl *decl,
SubstitutionList subs,
+ LValueOptions options,
bool isSuper,
AccessKind accessKind,
AccessSemantics accessSemantics,
@@ -2408,11 +2460,13 @@
}
LValue SILGenLValue::visitTupleElementExpr(TupleElementExpr *e,
- AccessKind accessKind) {
+ AccessKind accessKind,
+ LValueOptions options) {
unsigned index = e->getFieldNumber();
LValue lv = visitRec(e->getBase(),
accessKind == AccessKind::Read
- ? AccessKind::Read : AccessKind::ReadWrite);
+ ? AccessKind::Read : AccessKind::ReadWrite,
+ options.forProjectedBaseLValue());
auto baseTypeData = lv.getTypeData();
LValueTypeData typeData = {
@@ -2426,13 +2480,15 @@
}
LValue SILGenLValue::visitOpenExistentialExpr(OpenExistentialExpr *e,
- AccessKind accessKind) {
+ AccessKind accessKind,
+ LValueOptions options) {
// If the opaque value is not an lvalue, open the existential immediately.
if (!e->getOpaqueValue()->getType()->is<LValueType>()) {
return SGF.emitOpenExistentialExpr<LValue>(e,
[&](Expr *subExpr) -> LValue {
return visitRec(subExpr,
- accessKind);
+ accessKind,
+ options);
});
}
@@ -2443,7 +2499,7 @@
assert(inserted && "already have this opened existential?");
// Visit the subexpression.
- LValue lv = visitRec(e->getSubExpr(), accessKind);
+ LValue lv = visitRec(e->getSubExpr(), accessKind, options);
// Sanity check that we did see the OpaqueValueExpr.
assert(SGF.OpaqueValueExprs.count(e->getOpaqueValue()) == 0 &&
@@ -2464,17 +2520,21 @@
}
LValue SILGenLValue::visitForceValueExpr(ForceValueExpr *e,
- AccessKind accessKind) {
- LValue lv = visitRec(e->getSubExpr(), accessKind);
+ AccessKind accessKind,
+ LValueOptions options) {
+ LValue lv = visitRec(e->getSubExpr(), accessKind,
+ options.forComputedBaseLValue());
LValueTypeData typeData = getOptionalObjectTypeData(SGF, lv.getTypeData());
lv.add<ForceOptionalObjectComponent>(typeData);
return lv;
}
LValue SILGenLValue::visitBindOptionalExpr(BindOptionalExpr *e,
- AccessKind accessKind) {
+ AccessKind accessKind,
+ LValueOptions options) {
// Do formal evaluation of the base l-value.
- LValue optLV = visitRec(e->getSubExpr(), accessKind);
+ LValue optLV = visitRec(e->getSubExpr(), accessKind,
+ options.forComputedBaseLValue());
LValueTypeData optTypeData = optLV.getTypeData();
LValueTypeData valueTypeData = getOptionalObjectTypeData(SGF, optTypeData);
@@ -2498,15 +2558,18 @@
return valueLV;
}
-LValue SILGenLValue::visitInOutExpr(InOutExpr *e, AccessKind accessKind) {
- return visitRec(e->getSubExpr(), accessKind);
+LValue SILGenLValue::visitInOutExpr(InOutExpr *e, AccessKind accessKind,
+ LValueOptions options) {
+ return visitRec(e->getSubExpr(), accessKind, options);
}
/// Emit an lvalue that refers to the given property. This is
/// designed to work with ManagedValue 'base's that are either +0 or +1.
LValue SILGenFunction::emitPropertyLValue(SILLocation loc, ManagedValue base,
CanType baseFormalType,
- VarDecl *ivar, AccessKind accessKind,
+ VarDecl *ivar,
+ LValueOptions options,
+ AccessKind accessKind,
AccessSemantics semantics) {
SILGenLValue sgl(*this);
LValue lv;
@@ -2557,7 +2620,7 @@
lv.add<AddressorComponent>(ivar, /*super*/ false, /*direct*/ true,
subs, baseFormalType, typeData, varStorageType);
} else if (baseFormalType->hasReferenceSemantics()) {
- lv.add<RefElementComponent>(ivar, varStorageType, typeData);
+ lv.add<RefElementComponent>(ivar, options, varStorageType, typeData);
} else {
lv.add<StructElementComponent>(ivar, varStorageType, typeData);
}
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index 752aa0d..11ef6ee 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -467,7 +467,8 @@
WitnessStorage->getAccessStrategy(TheAccessSemantics, accessKind);
// Drill down to the member storage.
- lv.addMemberComponent(gen, loc, WitnessStorage, WitnessSubs, IsSuper,
+ lv.addMemberComponent(gen, loc, WitnessStorage, WitnessSubs,
+ LValueOptions(), IsSuper,
accessKind, TheAccessSemantics, strategy,
SubstStorageType, std::move(indices));
@@ -681,12 +682,12 @@
// the actual materializeForSet function), and so we only need to make sure we
// don't break things in cases when there may be multiple definitions.
auto callbackLinkage =
- hasSharedVisibility(Linkage) ? SILLinkage::Shared : SILLinkage::Private;
+ F.isSerialized() ? SILLinkage::Shared : SILLinkage::Private;
auto callback = SGM.M.createFunction(
callbackLinkage, CallbackName, callbackType, genericEnv,
- SILLocation(Witness), IsBare, F.isTransparent(), F.isSerialized(),
- IsNotThunk, SubclassScope::NotApplicable,
+ SILLocation(Witness), IsBare, F.isTransparent(), F.isSerialized(), IsNotThunk,
+ SubclassScope::NotApplicable,
/*inlineStrategy=*/InlineDefault,
/*EK=*/EffectsKind::Unspecified,
/*InsertBefore=*/&F);
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index 53844f6..9e6a9fe 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -637,18 +637,7 @@
// Create the optimized function !
SILModule &M = F->getModule();
std::string Name = createOptimizedSILFunctionName();
-
- // Any function that can be seen in other compilation units within this module
- // (either because the function is from another module, or because it public
- // or internal) needs to be considered shared, because those compilation units
- // may choose to do exactly the same specialization. However, specializations
- // of serialized functions are serialized too, and so behave more like the
- // original.
- SILLinkage linkage = F->getLinkage();
- auto localVisibleInOtherObjects =
- !hasPrivateVisibility(linkage) && !F->isSerialized();
- if (isAvailableExternally(linkage) || localVisibleInOtherObjects)
- linkage = SILLinkage::Shared;
+ SILLinkage linkage = getSpecializedLinkage(F, F->getLinkage());
DEBUG(llvm::dbgs() << " -> create specialized function " << Name << "\n");
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 9069a94..6113408 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -3387,9 +3387,16 @@
// Nothing else can appear outside of @_specialize yet, and Sema
// doesn't know how to check.
break;
- case RequirementKind::Superclass:
+ case RequirementKind::Superclass: {
createMemberConstraint(Req, ConstraintKind::Subtype);
+
+ auto First = resolveType(Req.getFirstType());
+ CS.addConstraint(ConstraintKind::ConformsTo, First,
+ CS.getASTContext().getAnyObjectType(),
+ Loc);
+
break;
+ }
case RequirementKind::SameType:
createMemberConstraint(Req, ConstraintKind::Equal);
break;
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index 65442fb..2b92616 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -984,7 +984,28 @@
++score1;
else if (isa<VarDecl>(decl2) && isa<FuncDecl>(decl1))
++score2;
-
+
+ // If both are class properties with the same name, prefer
+ // the one attached to the subclass because it could only be
+ // found if requested directly.
+ if (!decl1->isInstanceMember() && !decl2->isInstanceMember()) {
+ if (isa<VarDecl>(decl1) && isa<VarDecl>(decl2)) {
+ auto *nominal1 = dc1->getAsNominalTypeOrNominalTypeExtensionContext();
+ auto *nominal2 = dc2->getAsNominalTypeOrNominalTypeExtensionContext();
+
+ if (nominal1 && nominal2 && nominal1 != nominal2) {
+ auto base1 = nominal1->getDeclaredType();
+ auto base2 = nominal2->getDeclaredType();
+
+ if (isNominallySuperclassOf(base1, base2))
+ ++score2;
+
+ if (isNominallySuperclassOf(base2, base1))
+ ++score1;
+ }
+ }
+ }
+
// If we haven't found a refinement, record whether one overload is in
// any way more constrained than another. We'll only utilize this
// information in the case of a potential ambiguity.
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 9814bfc..791cdad 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1046,6 +1046,9 @@
auto subjectTy = openType(req.getFirstType(), replacements);
auto boundTy = openType(req.getSecondType(), replacements);
addConstraint(ConstraintKind::Subtype, subjectTy, boundTy, locatorPtr);
+ addConstraint(ConstraintKind::ConformsTo, subjectTy,
+ TC.Context.getAnyObjectType(),
+ locatorPtr);
break;
}
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index d5617a5..98c740e 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -184,8 +184,7 @@
validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
NominalTypeDecl *target, ProtocolDecl *proto) {
// Look through all var decls in the given type.
- // * Filter out lazy/computed vars (currently already done by
- // getStoredProperties).
+ // * Filter out lazy/computed vars.
// * Filter out ones which are present in the given decl (by name).
//
// If any of the entries in the CodingKeys decl are not present in the type
@@ -197,6 +196,9 @@
// against its CodingKey entry, it will get removed.
llvm::SmallDenseMap<Identifier, VarDecl *, 8> properties;
for (auto *varDecl : target->getStoredProperties(/*skipInaccessible=*/true)) {
+ if (varDecl->getAttrs().hasAttribute<LazyAttr>())
+ continue;
+
properties[varDecl->getName()] = varDecl;
}
@@ -242,7 +244,7 @@
// we can skip them on encode. On decode, though, we can only skip them if
// they have a default value.
if (!properties.empty() &&
- proto == tc.Context.getProtocol(KnownProtocolKind::Decodable)) {
+ proto->isSpecificProtocol(KnownProtocolKind::Decodable)) {
for (auto it = properties.begin(); it != properties.end(); ++it) {
if (it->second->getParentInitializer() != nullptr) {
// Var has a default value.
@@ -303,6 +305,9 @@
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
}
+ // If the decl hasn't been validated yet, do so.
+ tc.validateDecl(codingKeysTypeDecl);
+
// CodingKeys may be a typealias. If so, follow the alias to its canonical
// type.
auto codingKeysType = codingKeysTypeDecl->getDeclaredInterfaceType();
@@ -381,6 +386,9 @@
// conforms to {En,De}codable, add it to the enum.
bool allConform = true;
for (auto *varDecl : target->getStoredProperties(/*skipInaccessible=*/true)) {
+ if (varDecl->getAttrs().hasAttribute<LazyAttr>())
+ continue;
+
auto conformance = varConformsToCodable(tc, target->getDeclContext(),
varDecl, proto);
switch (conformance) {
@@ -660,8 +668,9 @@
// Need to generate `try super.encode(to: container.superEncoder())`
// superEncoder()
- auto *method = new (C) UnresolvedDeclRefExpr(
- DeclName(C.Id_superEncoder), DeclRefKind::Ordinary, DeclNameLoc());
+ auto *method = new (C) UnresolvedDeclRefExpr(DeclName(C.Id_superEncoder),
+ DeclRefKind::Ordinary,
+ DeclNameLoc());
// container.superEncoder()
auto *superEncoderRef = new (C) DotSyntaxCallExpr(containerExpr,
@@ -940,51 +949,91 @@
/*Implicit=*/true);
auto *selfRef = createSelfDeclRef(initDecl);
- auto *varExpr = new (C) UnresolvedDotExpr(
- selfRef, SourceLoc(), DeclName(varDecl->getName()), DeclNameLoc(),
- /*implicit=*/true);
+ auto *varExpr = new (C) UnresolvedDotExpr(selfRef, SourceLoc(),
+ DeclName(varDecl->getName()),
+ DeclNameLoc(),
+ /*implicit=*/true);
auto *assignExpr = new (C) AssignExpr(varExpr, SourceLoc(), tryExpr,
/*Implicit=*/true);
statements.push_back(assignExpr);
}
}
- // Classes which inherit from something Decodable should decode super as well.
- auto *classDecl = dyn_cast<ClassDecl>(targetDecl);
- if (classDecl && superclassIsDecodable(classDecl)) {
- // Need to generate `try super.init(from: container.superDecoder())`
+ // Classes which have a superclass must call super.init(from:) if the
+ // superclass is Decodable, or super.init() if it is not.
+ if (auto *classDecl = dyn_cast<ClassDecl>(targetDecl)) {
+ if (auto *superclassDecl = classDecl->getSuperclassDecl()) {
+ if (superclassIsDecodable(classDecl)) {
+ // Need to generate `try super.init(from: container.superDecoder())`
- // superDecoder()
- auto *method = new (C) UnresolvedDeclRefExpr(
- DeclName(C.Id_superDecoder), DeclRefKind::Ordinary, DeclNameLoc());
+ // container.superDecoder
+ auto *superDecoderRef =
+ new (C) UnresolvedDotExpr(containerExpr, SourceLoc(),
+ DeclName(C.Id_superDecoder),
+ DeclNameLoc(), /*Implicit=*/true);
- // container.superDecoder()
- auto *superDecoderRef = new (C) DotSyntaxCallExpr(containerExpr,
- SourceLoc(), method);
+ // container.superDecoder()
+ auto *superDecoderCall =
+ CallExpr::createImplicit(C, superDecoderRef, ArrayRef<Expr *>(),
+ ArrayRef<Identifier>());
- // init(from:) expr
- auto *initDeclRef = new (C) DeclRefExpr(ConcreteDeclRef(initDecl),
- DeclNameLoc(), /*Implicit=*/true);
+ // super
+ auto *superRef = new (C) SuperRefExpr(initDecl->getImplicitSelfDecl(),
+ SourceLoc(), /*Implicit=*/true);
- // super
- auto *superRef = new (C) SuperRefExpr(initDecl->getImplicitSelfDecl(),
- SourceLoc(), /*Implicit=*/true);
+ // super.init(from:)
+ auto initName = DeclName(C, C.Id_init, C.Id_from);
+ auto *initCall = new (C) UnresolvedDotExpr(superRef, SourceLoc(),
+ initName, DeclNameLoc(),
+ /*Implicit=*/true);
- // super.init(from:)
- auto *decodeCall = new (C) DotSyntaxCallExpr(superRef, SourceLoc(),
- initDeclRef);
+ // super.decode(from: container.superDecoder())
+ Expr *args[1] = {superDecoderCall};
+ Identifier argLabels[1] = {C.Id_from};
+ auto *callExpr = CallExpr::createImplicit(C, initCall,
+ C.AllocateCopy(args),
+ C.AllocateCopy(argLabels));
- // super.decode(from: container.superDecoder())
- Expr *args[1] = {superDecoderRef};
- Identifier argLabels[1] = {C.Id_from};
- auto *callExpr = CallExpr::createImplicit(C, decodeCall,
- C.AllocateCopy(args),
- C.AllocateCopy(argLabels));
+ // try super.init(from: container.superDecoder())
+ auto *tryExpr = new (C) TryExpr(SourceLoc(), callExpr, Type(),
+ /*Implicit=*/true);
+ statements.push_back(tryExpr);
+ } else {
+ // The explicit constructor name is a compound name taking no arguments.
+ DeclName initName(C, C.Id_init, ArrayRef<Identifier>());
- // try super.init(from: container.superDecoder())
- auto *tryExpr = new (C) TryExpr(SourceLoc(), callExpr, Type(),
- /*Implicit=*/true);
- statements.push_back(tryExpr);
+ // We need to look this up in the superclass to see if it throws.
+ auto result = superclassDecl->lookupDirect(initName);
+
+ // We should have bailed one level up if this were not available.
+ assert(!result.empty());
+
+ // If the init is failable, we should have already bailed one level
+ // above.
+ ConstructorDecl *superInitDecl = cast<ConstructorDecl>(result.front());
+ assert(superInitDecl->getFailability() == OTK_None);
+
+ // super
+ auto *superRef = new (C) SuperRefExpr(initDecl->getImplicitSelfDecl(),
+ SourceLoc(), /*Implicit=*/true);
+
+ // super.init()
+ auto *superInitRef = new (C) UnresolvedDotExpr(superRef, SourceLoc(),
+ initName, DeclNameLoc(),
+ /*Implicit=*/true);
+ // super.init() call
+ Expr *callExpr = CallExpr::createImplicit(C, superInitRef,
+ ArrayRef<Expr *>(),
+ ArrayRef<Identifier>());
+
+ // If super.init throws, try super.init()
+ if (superInitDecl->hasThrows())
+ callExpr = new (C) TryExpr(SourceLoc(), callExpr, Type(),
+ /*Implicit=*/true);
+
+ statements.push_back(callExpr);
+ }
+ }
}
auto *body = BraceStmt::create(C, SourceLoc(), statements, SourceLoc(),
@@ -1048,12 +1097,10 @@
// Func name: init(from: Decoder)
DeclName name(C, C.Id_init, paramList);
- auto *initDecl = new (C) ConstructorDecl(
- name, SourceLoc(),
- /*Failability=*/OTK_None,
- /*FailabilityLoc=*/SourceLoc(),
- /*Throws=*/true, /*ThrowsLoc=*/SourceLoc(), selfDecl, paramList,
- /*GenericParams=*/nullptr, target);
+ auto *initDecl = new (C) ConstructorDecl(name, SourceLoc(), OTK_None,
+ SourceLoc(), /*Throws=*/true,
+ SourceLoc(), selfDecl, paramList,
+ /*GenericParams=*/nullptr, target);
initDecl->setImplicit();
initDecl->setBodySynthesizer(deriveBodyDecodable_init);
@@ -1082,8 +1129,8 @@
initDecl->setInterfaceType(interfaceType);
initDecl->setInitializerInterfaceType(initializerType);
- initDecl->setAccessibility(
- std::max(target->getFormalAccess(), Accessibility::Internal));
+ initDecl->setAccessibility(std::max(target->getFormalAccess(),
+ Accessibility::Internal));
// If the type was not imported, the derived conformance is either from the
// type itself or an extension, in which case we will emit the declaration
@@ -1104,10 +1151,79 @@
///
/// \param target The type to validate.
///
+/// \param requirement The requirement we want to synthesize.
+///
/// \param proto The *codable protocol to check for validity.
static bool canSynthesize(TypeChecker &tc, NominalTypeDecl *target,
- ProtocolDecl *proto) {
- // First, look up if the type has a valid CodingKeys enum we can use.
+ ValueDecl *requirement, ProtocolDecl *proto) {
+ // Before we attempt to look up (or more importantly, synthesize) a CodingKeys
+ // entity on target, we need to make sure the type is otherwise valid.
+ //
+ // If we are synthesizing Decodable and the target is a class with a
+ // superclass, our synthesized init(from:) will need to call either
+ // super.init(from:) or super.init() depending on whether the superclass is
+ // Decodable itself.
+ //
+ // If the required initializer is not available, we shouldn't attempt to
+ // synthesize CodingKeys.
+ ASTContext &C = tc.Context;
+ auto *classDecl = dyn_cast<ClassDecl>(target);
+ if (proto->isSpecificProtocol(KnownProtocolKind::Decodable) && classDecl) {
+ if (auto *superclassDecl = classDecl->getSuperclassDecl()) {
+ DeclName memberName;
+ auto superType = superclassDecl->getDeclaredInterfaceType();
+ if (tc.conformsToProtocol(superType, proto, superclassDecl,
+ ConformanceCheckFlags::Used)) {
+ // super.init(from:) must be accessible.
+ memberName = cast<ConstructorDecl>(requirement)->getFullName();
+ } else {
+ // super.init() must be accessible.
+ // Passing an empty params array constructs a compound name with no
+ // arguments (as opposed to a simple name when omitted).
+ memberName = DeclName(C, DeclBaseName(C.Id_init),
+ ArrayRef<Identifier>());
+ }
+
+ auto result = tc.lookupMember(superclassDecl, superType, memberName);
+
+ if (result.empty()) {
+ // No super initializer for us to call.
+ tc.diagnose(superclassDecl, diag::decodable_no_super_init_here,
+ requirement->getFullName(), memberName);
+ return false;
+ } else if (result.size() > 1) {
+ // There are multiple results for this lookup. We'll end up producing a
+ // diagnostic later complaining about duplicate methods (if we haven't
+ // already), so just bail with a general error.
+ return false;
+ } else {
+ auto *initializer = cast<ConstructorDecl>(result.front().Decl);
+ if (!initializer->isDesignatedInit()) {
+ // We must call a superclass's designated initializer.
+ tc.diagnose(initializer,
+ diag::decodable_super_init_not_designated_here,
+ requirement->getFullName(), memberName);
+ return false;
+ } else if (!initializer->isAccessibleFrom(target)) {
+ // Cannot call an inaccessible method.
+ auto accessScope = initializer->getFormalAccessScope(target);
+ tc.diagnose(initializer, diag::decodable_inaccessible_super_init_here,
+ requirement->getFullName(), memberName,
+ accessScope.accessibilityForDiagnostics());
+ return false;
+ } else if (initializer->getFailability() != OTK_None) {
+ // We can't call super.init() if it's failable, since init(from:)
+ // isn't failable.
+ tc.diagnose(initializer, diag::decodable_super_init_is_failable_here,
+ requirement->getFullName(), memberName);
+ return false;
+ }
+ }
+ }
+ }
+
+ // If the target already has a valid CodingKeys enum, we won't need to
+ // synthesize one.
auto validity = hasValidCodingKeysEnum(tc, target, proto);
// We found a type, but it wasn't valid.
@@ -1165,23 +1281,17 @@
auto diagnosticTransaction = DiagnosticTransaction(tc.Context.Diags);
tc.diagnose(target, diag::type_does_not_conform, target->getDeclaredType(),
encodableType);
+ tc.diagnose(requirement, diag::no_witnesses, diag::RequirementKind::Func,
+ requirement->getFullName(), encodableType, /*AddFixIt=*/false);
// Check other preconditions for synthesized conformance.
// This synthesizes a CodingKeys enum if possible.
- ValueDecl *witness = nullptr;
- if (canSynthesize(tc, target, encodableProto))
- witness = deriveEncodable_encode(tc, parentDecl, target);
-
- if (witness == nullptr) {
- // We didn't end up synthesizing encode(to:).
- tc.diagnose(requirement, diag::no_witnesses, diag::RequirementKind::Func,
- requirement->getFullName(), encodableType, /*AddFixIt=*/false);
- } else {
- // We succeeded -- no need to output the false error generated above.
+ if (canSynthesize(tc, target, requirement, encodableProto)) {
diagnosticTransaction.abort();
+ return deriveEncodable_encode(tc, parentDecl, target);
}
- return witness;
+ return nullptr;
}
ValueDecl *DerivedConformance::deriveDecodable(TypeChecker &tc,
@@ -1215,22 +1325,16 @@
auto diagnosticTransaction = DiagnosticTransaction(tc.Context.Diags);
tc.diagnose(target, diag::type_does_not_conform, target->getDeclaredType(),
decodableType);
+ tc.diagnose(requirement, diag::no_witnesses,
+ diag::RequirementKind::Constructor, requirement->getFullName(),
+ decodableType, /*AddFixIt=*/false);
// Check other preconditions for synthesized conformance.
// This synthesizes a CodingKeys enum if possible.
- ValueDecl *witness = nullptr;
- if (canSynthesize(tc, target, decodableProto))
- witness = deriveDecodable_init(tc, parentDecl, target);
-
- if (witness == nullptr) {
- // We didn't end up synthesizing init(from:).
- tc.diagnose(requirement, diag::no_witnesses,
- diag::RequirementKind::Constructor, requirement->getFullName(),
- decodableType, /*AddFixIt=*/false);
- } else {
- // We succeeded -- no need to output the false error generated above.
+ if (canSynthesize(tc, target, requirement, decodableProto)) {
diagnosticTransaction.abort();
+ return deriveDecodable_init(tc, parentDecl, target);
}
- return witness;
+ return nullptr;
}
diff --git a/lib/Sema/DerivedConformanceCodingKey.cpp b/lib/Sema/DerivedConformanceCodingKey.cpp
index 76e8853..7802255 100644
--- a/lib/Sema/DerivedConformanceCodingKey.cpp
+++ b/lib/Sema/DerivedConformanceCodingKey.cpp
@@ -408,8 +408,9 @@
return false;
}
- if (!enumDecl->getInherited().empty() &&
- enumDecl->getInherited().front().isError())
+ auto inherited = enumDecl->getInherited();
+ if (!inherited.empty() && inherited.front().wasValidated() &&
+ inherited.front().isError())
return false;
// If it meets all of those requirements, we can synthesize CodingKey
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index 72991d7..84fd56d 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -344,8 +344,9 @@
auto parentDC = cast<DeclContext>(parentDecl);
rawType = parentDC->mapTypeIntoContext(rawType);
- if (!enumDecl->getInherited().empty() &&
- enumDecl->getInherited().front().isError())
+ auto inherited = enumDecl->getInherited();
+ if (!inherited.empty() && inherited.front().wasValidated() &&
+ inherited.front().isError())
return false;
// The raw type must be Equatable, so that we have a suitable ~= for
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 07754f4..eef4884 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -257,17 +257,26 @@
checkTupleSplat(Call);
// Check the callee, looking through implicit conversions.
- auto Base = Call->getFn();
- while (auto Conv = dyn_cast<ImplicitConversionExpr>(Base))
- Base = Conv->getSubExpr();
- while (auto ignoredBase = dyn_cast<DotSyntaxBaseIgnoredExpr>(Base))
- Base = ignoredBase->getRHS();
- if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
- checkNoEscapeParameterUse(DRE, Call, OperandKind::Callee);
- checkForSuspiciousBitCasts(DRE, Call);
+ auto base = Call->getFn();
+ unsigned uncurryLevel = 0;
+ while (auto conv = dyn_cast<ImplicitConversionExpr>(base))
+ base = conv->getSubExpr();
+ while (auto ignoredBase = dyn_cast<DotSyntaxBaseIgnoredExpr>(base))
+ base = ignoredBase->getRHS();
+ auto *calleeDRE = dyn_cast<DeclRefExpr>(base);
+ if (calleeDRE) {
+ checkNoEscapeParameterUse(calleeDRE, Call, OperandKind::Callee);
+ checkForSuspiciousBitCasts(calleeDRE, Call);
+
+ // Otherwise, try to drill down through member calls for the purposes
+ // of argument-matching code below.
+ } else if (auto selfApply = dyn_cast<SelfApplyExpr>(base)) {
+ uncurryLevel++;
+ base = selfApply->getSemanticFn();
+ calleeDRE = dyn_cast<DeclRefExpr>(base);
}
- visitArguments(Call, [&](Expr *arg) {
+ visitArguments(Call, [&](unsigned argIndex, Expr *arg) {
// InOutExpr's are allowed in argument lists directly.
if (auto *IOE = dyn_cast<InOutExpr>(arg)) {
if (isa<CallExpr>(Call))
@@ -277,12 +286,24 @@
Expr *unwrapped = arg;
if (auto *IIO = dyn_cast<InjectIntoOptionalExpr>(arg))
unwrapped = IIO->getSubExpr();
- if (auto *ICO = dyn_cast<ImplicitConversionExpr>(unwrapped)) {
- if (isa<InOutToPointerExpr>(ICO) ||
- isa<ArrayToPointerExpr>(ICO) ||
- isa<ErasureExpr>(ICO))
- if (auto *IOE = dyn_cast<InOutExpr>(ICO->getSubExpr()))
- AcceptableInOutExprs.insert(IOE);
+
+ if (isa<InOutToPointerExpr>(unwrapped) ||
+ isa<ArrayToPointerExpr>(unwrapped) ||
+ isa<ErasureExpr>(unwrapped)) {
+ auto operand =
+ cast<ImplicitConversionExpr>(unwrapped)->getSubExpr();
+ if (auto *IOE = dyn_cast<InOutExpr>(operand)) {
+ AcceptableInOutExprs.insert(IOE);
+ operand = IOE->getSubExpr();
+ }
+
+ // Also do some additional work based on how the function uses
+ // the argument.
+ if (calleeDRE) {
+ checkConvertedPointerArgument(calleeDRE->getDeclRef(),
+ uncurryLevel, argIndex,
+ unwrapped, operand);
+ }
}
// Also give special treatment to noescape function arguments.
@@ -332,7 +353,7 @@
}
static void visitArguments(ApplyExpr *apply,
- llvm::function_ref<void(Expr*)> fn) {
+ llvm::function_ref<void(unsigned, Expr*)> fn) {
auto *arg = apply->getArg();
// The argument could be shuffled if it includes default arguments,
@@ -342,12 +363,13 @@
// The argument is either a ParenExpr or TupleExpr.
if (auto *TE = dyn_cast<TupleExpr>(arg)) {
- for (auto elt : TE->getElements())
- fn(elt);
+ auto elts = TE->getElements();
+ for (auto i : indices(elts))
+ fn(i, elts[i]);
} else if (auto *PE = dyn_cast<ParenExpr>(arg)) {
- fn(PE->getSubExpr());
+ fn(0, PE->getSubExpr());
} else {
- fn(arg);
+ fn(0, arg);
}
}
@@ -368,6 +390,58 @@
return E;
}
+ void checkConvertedPointerArgument(ConcreteDeclRef callee,
+ unsigned uncurryLevel,
+ unsigned argIndex,
+ Expr *pointerExpr,
+ Expr *storage) {
+ if (!isPointerIdentityArgument(callee, uncurryLevel, argIndex))
+ return;
+
+ // Flag that the argument is non-accessing.
+ if (auto inout = dyn_cast<InOutToPointerExpr>(pointerExpr)) {
+ inout->setNonAccessing(true);
+ } else if (auto array = dyn_cast<ArrayToPointerExpr>(pointerExpr)) {
+ array->setNonAccessing(true);
+ }
+
+ // TODO: warn if taking the address of 'storage' will definitely
+ // yield a temporary address.
+ }
+
+ /// Is the given call argument, known to be of pointer type, just used
+ /// for its pointer identity?
+ bool isPointerIdentityArgument(ConcreteDeclRef ref, unsigned uncurryLevel,
+ unsigned argIndex) {
+ // FIXME: derive this from an attribute instead of hacking it based
+ // on the target name!
+ auto decl = ref.getDecl();
+
+ // Assume that == and != are non-accessing uses.
+ if (decl->isOperator()) {
+ auto op = decl->getBaseName();
+ if (op == "==" || op == "!=")
+ return true;
+ return false;
+ }
+
+ // NSObject.addObserver(_:forKeyPath:options:context:)
+ if (uncurryLevel == 1 && argIndex == 3) {
+ return decl->getFullName().isCompoundName("addObserver",
+ { "", "forKeyPath",
+ "options", "context" });
+ }
+
+ // NSObject.removeObserver(_:forKeyPath:context:)
+ if (uncurryLevel == 1 && argIndex == 2) {
+ return decl->getFullName().isCompoundName("removeObserver",
+ { "", "forKeyPath",
+ "context" });
+ }
+
+ return false;
+ }
+
/// We have a collection literal with a defaulted type, e.g. of [Any]. Emit
/// an error if it was inferred to this type in an invalid context, which is
/// one in which the parent expression is not itself a collection literal.
@@ -509,7 +583,7 @@
NoEscapeArgument noescapeArgument;
Expr *problematicArg = nullptr;
- visitArguments(apply, [&](Expr *arg) {
+ visitArguments(apply, [&](unsigned argIndex, Expr *arg) {
// Just find the first problematic argument.
if (noescapeArgument) return;
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 8874bce..d8bc420 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -87,6 +87,7 @@
IGNORED_ATTR(ObjCBridged)
IGNORED_ATTR(ObjCNonLazyRealization)
IGNORED_ATTR(ObjCRuntimeName)
+ IGNORED_ATTR(RestatedObjCConformance)
IGNORED_ATTR(Optional)
IGNORED_ATTR(Postfix)
IGNORED_ATTR(Prefix)
@@ -769,6 +770,7 @@
IGNORED_ATTR(ObjCBridged)
IGNORED_ATTR(ObjCNonLazyRealization)
IGNORED_ATTR(ObjCRuntimeName)
+ IGNORED_ATTR(RestatedObjCConformance)
IGNORED_ATTR(Optional)
IGNORED_ATTR(Ownership)
IGNORED_ATTR(Override)
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index b0be11f..a938af4 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -2807,6 +2807,21 @@
ConstraintKind::Subtype, dc);
}
+bool TypeChecker::isSubclassOf(Type type1, Type type2, DeclContext *dc) {
+ assert(type2->getClassOrBoundGenericClass());
+
+ if (!typesSatisfyConstraint(type1,
+ Context.getAnyObjectType(),
+ /*openArchetypes=*/false,
+ ConstraintKind::ConformsTo, dc)) {
+ return false;
+ }
+
+ return typesSatisfyConstraint(type1, type2,
+ /*openArchetypes=*/false,
+ ConstraintKind::Subtype, dc);
+}
+
bool TypeChecker::isConvertibleTo(Type type1, Type type2, DeclContext *dc,
bool *unwrappedIUO) {
return typesSatisfyConstraint(type1, type2,
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index c98daf3..3f21f98 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -6166,6 +6166,7 @@
UNINTERESTING_ATTR(ObjCMembers)
UNINTERESTING_ATTR(ObjCRuntimeName)
+ UNINTERESTING_ATTR(RestatedObjCConformance)
UNINTERESTING_ATTR(Implements)
UNINTERESTING_ATTR(StaticInitializeObjCMetadata)
UNINTERESTING_ATTR(DowngradeExhaustivityCheck)
@@ -7927,6 +7928,67 @@
tc.diagnose(classDecl, diag::class_without_init,
classDecl->getDeclaredType());
+ // HACK: We've got a special case to look out for and diagnose specifically to
+ // improve the experience of seeing this, and mitigate some confusion.
+ //
+ // For a class A which inherits from Decodable class B, class A may have
+ // additional members which prevent default initializer synthesis (and
+ // inheritance of other initializers). The user may have assumed that this
+ // case would synthesize Encodable/Decodable conformance for class A the same
+ // way it may have for class B, or other classes.
+ //
+ // It is helpful to suggest here that the user may have forgotten to override
+ // init(from:) (and encode(to:), if applicable) in a note, before we start
+ // listing the members that prevented initializer synthesis.
+ // TODO: Add a fixit along with this suggestion.
+ if (auto *superclassDecl = classDecl->getSuperclassDecl()) {
+ ASTContext &C = tc.Context;
+ auto *decodableProto = C.getProtocol(KnownProtocolKind::Decodable);
+ auto superclassType = superclassDecl->getDeclaredInterfaceType();
+ if (auto ref = tc.conformsToProtocol(superclassType, decodableProto,
+ superclassDecl,
+ ConformanceCheckOptions(),
+ SourceLoc())) {
+ // super conforms to Decodable, so we've failed to inherit init(from:).
+ // Let's suggest overriding it here.
+ //
+ // We're going to diagnose on the concrete init(from:) decl if it exists
+ // and isn't implicit; otherwise, on the subclass itself.
+ ValueDecl *diagDest = classDecl;
+ auto initFrom = DeclName(C, C.Id_init, C.Id_from);
+ auto result = tc.lookupMember(superclassDecl, superclassType, initFrom,
+ NameLookupFlags::ProtocolMembers |
+ NameLookupFlags::IgnoreAccessibility);
+
+ if (!result.empty() && !result.front()->isImplicit())
+ diagDest = result.front();
+
+ auto diagName = diag::decodable_suggest_overriding_init_here;
+
+ // This is also a bit of a hack, but the best place we've got at the
+ // moment to suggest this.
+ //
+ // If the superclass also conforms to Encodable, it's quite
+ // likely that the user forgot to override its encode(to:). In this case,
+ // we can produce a slightly different diagnostic to suggest doing so.
+ auto *encodableProto = C.getProtocol(KnownProtocolKind::Encodable);
+ if ((ref = tc.conformsToProtocol(superclassType, encodableProto,
+ superclassDecl,
+ ConformanceCheckOptions(),
+ SourceLoc()))) {
+ // We only want to produce this version of the diagnostic if the
+ // subclass doesn't directly implement encode(to:).
+ // The direct lookup here won't see an encode(to:) if it is inherited
+ // from the superclass.
+ auto encodeTo = DeclName(C, C.Id_encode, C.Id_to);
+ if (classDecl->lookupDirect(encodeTo).empty())
+ diagName = diag::codable_suggest_overriding_init_here;
+ }
+
+ tc.diagnose(diagDest, diagName);
+ }
+ }
+
for (auto member : classDecl->getMembers()) {
auto pbd = dyn_cast<PatternBindingDecl>(member);
if (!pbd)
@@ -8114,14 +8176,49 @@
bool FoundMemberwiseInitializedProperty = false;
bool SuppressDefaultInitializer = false;
bool SuppressMemberwiseInitializer = false;
+ bool FoundSynthesizedInit = false;
bool FoundDesignatedInit = false;
decl->setAddedImplicitInitializers();
+
+ // Before we look for constructors, we need to make sure that all synthesized
+ // initializers are properly synthesized.
+ //
+ // NOTE: Lookups of synthesized initializers MUST come after
+ // decl->setAddedImplicitInitializers() in case synthesis requires
+ // protocol conformance checking, which might be recursive here.
+ // FIXME: Disable this code and prevent _any_ implicit constructors from doing
+ // this. Investigate why this hasn't worked otherwise.
+ DeclName synthesizedInitializers[1] = {
+ // init(from:) is synthesized by derived conformance to Decodable.
+ DeclName(Context, DeclBaseName(Context.Id_init), Context.Id_from)
+ };
+
+ auto initializerIsSynthesized = [=](ConstructorDecl *initializer) {
+ if (!initializer->isImplicit())
+ return false;
+
+ for (auto &name : synthesizedInitializers)
+ if (initializer->getFullName() == name)
+ return true;
+
+ return false;
+ };
+
+ for (auto &name : synthesizedInitializers) {
+ synthesizeMemberForLookup(decl, name);
+ }
+
SmallPtrSet<CanType, 4> initializerParamTypes;
llvm::SmallPtrSet<ConstructorDecl *, 4> overriddenInits;
for (auto member : decl->getMembers()) {
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
- if (ctor->isDesignatedInit())
+ // Synthesized initializers others than the default initializer should
+ // not prevent default initializer synthesis.
+ if (initializerIsSynthesized(ctor)) {
+ FoundSynthesizedInit = true;
+ } else if (ctor->isDesignatedInit()) {
FoundDesignatedInit = true;
+ }
if (!ctor->isInvalid())
initializerParamTypes.insert(getInitializerParamType(ctor));
@@ -8216,7 +8313,8 @@
// We can't define these overrides if we have any uninitialized
// stored properties.
- if (SuppressDefaultInitializer && !FoundDesignatedInit) {
+ if (SuppressDefaultInitializer && !FoundDesignatedInit
+ && !FoundSynthesizedInit) {
diagnoseClassWithoutInitializers(*this, classDecl);
return;
}
@@ -8308,7 +8406,9 @@
// ... unless there are uninitialized stored properties.
if (SuppressDefaultInitializer) {
- diagnoseClassWithoutInitializers(*this, classDecl);
+ if (!FoundSynthesizedInit)
+ diagnoseClassWithoutInitializers(*this, classDecl);
+
return;
}
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index dd5ca8c..403f3e9 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -1342,7 +1342,7 @@
case RequirementKind::Superclass:
// Superclass requirements.
- if (!isSubtypeOf(firstType, secondType, dc)) {
+ if (!isSubclassOf(firstType, secondType, dc)) {
if (loc.isValid()) {
// FIXME: Poor source-location information.
diagnose(loc, diag::type_does_not_inherit, owner, firstType,
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index e73db99..88c5771 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -3452,6 +3452,7 @@
switch (reqt.getKind()) {
case RequirementKind::Conformance:
case RequirementKind::Superclass:
+ // FIXME: This is the wrong check
if (selfTy->isEqual(reqt.getFirstType())
&& !TC.isSubtypeOf(Conformance->getType(),reqt.getSecondType(), DC))
return false;
@@ -4064,7 +4065,7 @@
if (!t2)
return true;
- return TC.isSubtypeOf(t1, t2, DC);
+ return TC.isSubclassOf(t1, t2, DC);
};
bool protos1AreSubsetOf2 = protos1.empty();
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index cf69299..7b9b55c 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1124,6 +1124,15 @@
/// \returns true if \c t1 is a subtype of \c t2.
bool isSubtypeOf(Type t1, Type t2, DeclContext *dc);
+ /// \brief Determine whether one type is a subclass of another.
+ ///
+ /// \param t1 The potential subtype.
+ /// \param t2 The potential supertype.
+ /// \param dc The context of the check.
+ ///
+ /// \returns true if \c t1 is a subtype of \c t2.
+ bool isSubclassOf(Type t1, Type t2, DeclContext *dc);
+
/// \brief Determine whether one type is implicitly convertible to another.
///
/// \param t1 The potential source type of the conversion.
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 006fd55..296b120 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -611,7 +611,7 @@
DeclID protoID;
DeclContextID contextID;
- unsigned valueCount, typeCount;
+ unsigned valueCount, typeCount, conformanceCount;
ArrayRef<uint64_t> rawIDs;
SmallVector<uint64_t, 16> scratch;
@@ -622,7 +622,7 @@
}
NormalProtocolConformanceLayout::readRecord(scratch, protoID,
contextID, valueCount,
- typeCount,
+ typeCount, conformanceCount,
rawIDs);
ASTContext &ctx = getContext();
@@ -649,11 +649,54 @@
// Read requirement signature conformances.
SmallVector<ProtocolConformanceRef, 4> reqConformances;
- for (const auto &req : proto->getRequirementSignature()) {
- if (req.getKind() == RequirementKind::Conformance) {
- auto reqConformance = readConformance(DeclTypeCursor);
- reqConformances.push_back(reqConformance);
+
+ if (proto->isObjC() && getContext().LangOpts.EnableDeserializationRecovery) {
+ // Don't crash if inherited protocols are added or removed.
+ // This is limited to Objective-C protocols because we know their only
+ // conformance requirements are on Self. This isn't actually a /safe/ change
+ // even in Objective-C, but we mostly just don't want to crash.
+
+ // FIXME: DenseMap requires that its value type be default-constructible,
+ // which ProtocolConformanceRef is not, hence the extra Optional.
+ llvm::SmallDenseMap<ProtocolDecl *, Optional<ProtocolConformanceRef>, 16>
+ conformancesForProtocols;
+ while (conformanceCount--) {
+ ProtocolConformanceRef nextConformance = readConformance(DeclTypeCursor);
+ ProtocolDecl *confProto = nextConformance.getRequirement();
+ conformancesForProtocols[confProto] = nextConformance;
}
+
+ for (const auto &req : proto->getRequirementSignature()) {
+ if (req.getKind() != RequirementKind::Conformance)
+ continue;
+ ProtocolDecl *proto =
+ req.getSecondType()->castTo<ProtocolType>()->getDecl();
+ auto iter = conformancesForProtocols.find(proto);
+ if (iter != conformancesForProtocols.end()) {
+ reqConformances.push_back(iter->getSecond().getValue());
+ } else {
+ // Put in an abstract conformance as a placeholder. This is a lie, but
+ // there's not much better we can do. We're relying on the fact that
+ // the rest of the compiler doesn't actually need to check the
+ // conformance to an Objective-C protocol for anything important.
+ // There are no associated types and we don't emit a Swift conformance
+ // record.
+ reqConformances.push_back(ProtocolConformanceRef(proto));
+ }
+ }
+
+ } else {
+ auto isConformanceReq = [](const Requirement &req) {
+ return req.getKind() == RequirementKind::Conformance;
+ };
+ if (conformanceCount != llvm::count_if(proto->getRequirementSignature(),
+ isConformanceReq)) {
+ fatal(llvm::make_error<llvm::StringError>(
+ "serialized conformances do not match requirement signature",
+ llvm::inconvertibleErrorCode()));
+ }
+ while (conformanceCount--)
+ reqConformances.push_back(readConformance(DeclTypeCursor));
}
conformance->setSignatureConformances(reqConformances);
@@ -4577,7 +4620,7 @@
DeclID protoID;
DeclContextID contextID;
- unsigned valueCount, typeCount;
+ unsigned valueCount, typeCount, conformanceCount;
ArrayRef<uint64_t> rawIDs;
SmallVector<uint64_t, 16> scratch;
@@ -4587,16 +4630,13 @@
"registered lazy loader incorrectly");
NormalProtocolConformanceLayout::readRecord(scratch, protoID,
contextID, valueCount,
- typeCount,
+ typeCount, conformanceCount,
rawIDs);
// Skip requirement signature conformances.
auto proto = conformance->getProtocol();
- for (const auto &req : proto->getRequirementSignature()) {
- if (req.getKind() == RequirementKind::Conformance) {
- (void)readConformance(DeclTypeCursor);
- }
- }
+ while (conformanceCount--)
+ (void)readConformance(DeclTypeCursor);
ArrayRef<uint64_t>::iterator rawIDIter = rawIDs.begin();
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index cf91da6..3b88075 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1340,6 +1340,9 @@
return false;
});
+ unsigned numSignatureConformances =
+ conformance->getSignatureConformances().size();
+
unsigned abbrCode
= DeclTypeAbbrCodes[NormalProtocolConformanceLayout::Code];
auto ownerID = addDeclContextRef(conformance->getDeclContext());
@@ -1347,6 +1350,7 @@
addDeclRef(protocol), ownerID,
numValueWitnesses,
numTypeWitnesses,
+ numSignatureConformances,
data);
// Write requirement signature conformances.
@@ -1957,6 +1961,7 @@
case DAK_SynthesizedProtocol:
case DAK_Implements:
case DAK_ObjCRuntimeName:
+ case DAK_RestatedObjCConformance:
llvm_unreachable("cannot serialize attribute");
case DAK_Count:
diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp
index 7c2324a..da70abc 100644
--- a/lib/TBDGen/TBDGen.cpp
+++ b/lib/TBDGen/TBDGen.cpp
@@ -44,13 +44,15 @@
bool FileHasEntryPoint;
bool SILSerializeWitnessTables;
+ bool InsideAbstractStorageDecl = false;
+
void addSymbol(StringRef name) {
auto isNewValue = Symbols.insert(name).second;
(void)isNewValue;
assert(isNewValue && "already inserted");
}
- void addSymbol(SILDeclRef declRef, bool checkSILOnly = true);
+ void addSymbol(SILDeclRef declRef);
void addSymbol(LinkEntity entity) {
auto linkage =
@@ -85,8 +87,8 @@
addMembers(ED->getMembers());
else if (auto NTD = dyn_cast<NominalTypeDecl>(D))
addMembers(NTD->getMembers());
- else if (auto VD = dyn_cast<VarDecl>(D))
- VD->getAllAccessorFunctions(members);
+ else if (auto ASD = dyn_cast<AbstractStorageDecl>(D))
+ ASD->getAllAccessorFunctions(members);
for (auto member : members) {
ASTVisitor::visit(member);
@@ -103,20 +105,18 @@
// any information here is encoded elsewhere
}
- void visitSubscriptDecl(SubscriptDecl *SD) {
- // Any getters and setters etc. exist as independent FuncDecls in the AST,
- // so get processed elsewhere; subscripts don't have any symbols other than
- // these.
- }
-
void visitNominalTypeDecl(NominalTypeDecl *NTD);
void visitClassDecl(ClassDecl *CD);
+ void visitConstructorDecl(ConstructorDecl *CD);
+
void visitExtensionDecl(ExtensionDecl *ED);
void visitProtocolDecl(ProtocolDecl *PD);
+ void visitAbstractStorageDecl(AbstractStorageDecl *ASD);
+
void visitVarDecl(VarDecl *VD);
void visitDecl(Decl *D) { visitMembers(D); }
@@ -138,13 +138,13 @@
auto declRef =
SILDeclRef(var, SILDeclRef::Kind::StoredPropertyInitializer);
// Stored property initializers for public properties are currently
- // public, even when the initializer is marked as SIL only (transparent).
- addSymbol(declRef, /*checkSILOnly=*/false);
+ // public.
+ addSymbol(declRef);
}
}
}
-void TBDGenVisitor::addSymbol(SILDeclRef declRef, bool checkSILOnly) {
+void TBDGenVisitor::addSymbol(SILDeclRef declRef) {
bool isPrivate = !hasPublicVisibility(declRef.getLinkage(ForDefinition));
// Even private methods of open classes (specifically, private methods that
// are in the vtable) have public symbols, because external subclasses
@@ -155,7 +155,6 @@
// unconditionally, even if they're theoretically SIL only.
if (isPrivate) {
isPrivate = false;
- checkSILOnly = false;
}
break;
case SubclassScope::Internal:
@@ -165,10 +164,9 @@
if (isPrivate)
return;
- // (Most) transparent things don't exist, even if they're public.
- // FIXME: isTransparent should really be "is SIL only".
- if (checkSILOnly && declRef.isTransparent())
- return;
+ // FIXME: this includes too many symbols. There are some that are considered
+ // SIL-only, but it isn't obvious how to determine this (e.g. it seems that
+ // many, but not all, transparent functions result in object-file symbols)
addSymbol(declRef.mangle());
}
@@ -256,6 +254,14 @@
}
void TBDGenVisitor::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
+ if (auto FD = dyn_cast<FuncDecl>(AFD)) {
+ // Accessors also appear nested inside the storage decl, which we treat as
+ // the canonical location, so skip if we've got an accessor that isn't
+ // inside the var decl.
+ if (FD->getAccessorStorageDecl() && !InsideAbstractStorageDecl)
+ return;
+ }
+
// Default arguments (of public functions) are public symbols, as the default
// values are computed at the call site.
auto index = 0;
@@ -275,25 +281,27 @@
visitValueDecl(AFD);
}
+void TBDGenVisitor::visitAbstractStorageDecl(AbstractStorageDecl *ASD) {
+ assert(!InsideAbstractStorageDecl &&
+ "unexpected nesting of abstract storage decls");
+ InsideAbstractStorageDecl = true;
+ visitMembers(ASD);
+ InsideAbstractStorageDecl = false;
+}
void TBDGenVisitor::visitVarDecl(VarDecl *VD) {
- if (isPrivateDecl(VD))
- return;
-
// statically/globally stored variables have some special handling.
if (VD->hasStorage() && isGlobalOrStaticVar(VD)) {
// The actual variable has a symbol.
Mangle::ASTMangler mangler;
addSymbol(mangler.mangleEntity(VD, false));
- // Variables in the main file don't get accessors, despite otherwise looking
- // like globals.
- if (!FileHasEntryPoint)
+ // Top-level variables (*not* statics) in the main file don't get accessors,
+ // despite otherwise looking like globals.
+ if (!FileHasEntryPoint || VD->isStatic())
addSymbol(SILDeclRef(VD, SILDeclRef::Kind::GlobalAccessor));
-
- // In this case, the members of the VarDecl don't also appear as top-level
- // decls, so we need to explicitly walk them.
- visitMembers(VD);
}
+
+ visitAbstractStorageDecl(VD);
}
void TBDGenVisitor::visitNominalTypeDecl(NominalTypeDecl *NTD) {
@@ -344,8 +352,7 @@
continue;
auto var = dyn_cast<VarDecl>(value);
- auto hasFieldOffset =
- !isGeneric && var && var->hasStorage() && !var->isStatic();
+ auto hasFieldOffset = var && var->hasStorage() && !var->isStatic();
if (hasFieldOffset) {
// FIXME: a field only has one sort of offset, but it is moderately
// non-trivial to compute which one. Including both is less painful than
@@ -354,10 +361,8 @@
addSymbol(LinkEntity::forFieldOffset(var, /*isIndirect=*/true));
}
- // The non-allocating forms of the constructors and destructors.
- if (auto ctor = dyn_cast<ConstructorDecl>(value)) {
- addSymbol(SILDeclRef(ctor, SILDeclRef::Kind::Initializer));
- } else if (auto dtor = dyn_cast<DestructorDecl>(value)) {
+ // The non-allocating forms of the destructors.
+ if (auto dtor = dyn_cast<DestructorDecl>(value)) {
// ObjC classes don't have a symbol for their destructor.
if (!isObjC)
addSymbol(SILDeclRef(dtor, SILDeclRef::Kind::Destroyer));
@@ -367,6 +372,16 @@
visitNominalTypeDecl(CD);
}
+void TBDGenVisitor::visitConstructorDecl(ConstructorDecl *CD) {
+ if (CD->getParent()->getAsClassOrClassExtensionContext()) {
+ // Class constructors come in two forms, allocating and non-allocating. The
+ // default ValueDecl handling gives the allocating one, so we have to
+ // manually include the non-allocating one.
+ addSymbol(SILDeclRef(CD, SILDeclRef::Kind::Initializer));
+ }
+ visitAbstractFunctionDecl(CD);
+}
+
void TBDGenVisitor::visitExtensionDecl(ExtensionDecl *ED) {
if (!ED->getExtendedType()->isExistentialType()) {
addConformances(ED);
@@ -380,14 +395,15 @@
addSymbol(LinkEntity::forProtocolDescriptor(PD));
#ifndef NDEBUG
- // There's no (currently) relevant information about members of a protocol
- // at individual protocols, each conforming type has to handle them
- // individually. Let's assert this fact:
+ // There's no (currently) relevant information about members of a protocol at
+ // individual protocols, each conforming type has to handle them individually
+ // (NB. anything within an active IfConfigDecls also appears outside). Let's
+ // assert this fact:
for (auto *member : PD->getMembers()) {
auto isExpectedKind =
isa<TypeAliasDecl>(member) || isa<AssociatedTypeDecl>(member) ||
isa<AbstractStorageDecl>(member) || isa<PatternBindingDecl>(member) ||
- isa<AbstractFunctionDecl>(member);
+ isa<AbstractFunctionDecl>(member) || isa<IfConfigDecl>(member);
assert(isExpectedKind &&
"unexpected member of protocol during TBD generation");
}
diff --git a/stdlib/public/SDK/AppKit/AppKit.swift b/stdlib/public/SDK/AppKit/AppKit.swift
index d225eec..3346d89 100644
--- a/stdlib/public/SDK/AppKit/AppKit.swift
+++ b/stdlib/public/SDK/AppKit/AppKit.swift
@@ -81,7 +81,7 @@
@nonobjc
public required convenience init(_colorLiteralRed red: Float, green: Float,
blue: Float, alpha: Float) {
- self.init(srgbRed: CGFloat(red), green: CGFloat(green),
+ self.init(red: CGFloat(red), green: CGFloat(green),
blue: CGFloat(blue), alpha: CGFloat(alpha))
}
}
diff --git a/stdlib/public/SDK/Foundation/NSNumber.swift b/stdlib/public/SDK/Foundation/NSNumber.swift
index 9202604..f424d78 100644
--- a/stdlib/public/SDK/Foundation/NSNumber.swift
+++ b/stdlib/public/SDK/Foundation/NSNumber.swift
@@ -647,28 +647,35 @@
// AnyHashable to NSObject.
@nonobjc
public func _toCustomAnyHashable() -> AnyHashable? {
+ // The custom AnyHashable representation here is used when checking for
+ // equality during bridging NSDictionary to Dictionary (or looking up
+ // values in a Dictionary bridged to NSDictionary).
+ //
+ // When we've got NSNumber values as keys that we want to compare
+ // through an AnyHashable box, we want to compare values through the
+ // largest box size we've got available to us (i.e. upcast numbers).
+ // This happens to resemble the representation that NSNumber uses
+ // internally: (long long | unsigned long long | double).
+ //
+ // This allows us to compare things like
+ //
+ // ([Int : Any] as [AnyHashable : Any]) vs. [NSNumber : Any]
+ //
+ // because Int can be upcast to Int64 and compared with the number's
+ // Int64 value.
+ //
+ // If NSNumber adds 128-bit representations, this will need to be
+ // updated to use those.
if let nsDecimalNumber: NSDecimalNumber = self as? NSDecimalNumber {
return AnyHashable(nsDecimalNumber.decimalValue)
} else if self === kCFBooleanTrue as NSNumber {
return AnyHashable(true)
} else if self === kCFBooleanFalse as NSNumber {
return AnyHashable(false)
- } else if NSNumber(value: int8Value) == self {
- return AnyHashable(int8Value)
- } else if NSNumber(value: uint8Value) == self {
- return AnyHashable(uint8Value)
- } else if NSNumber(value: int16Value) == self {
- return AnyHashable(int16Value)
- } else if NSNumber(value: uint16Value) == self {
- return AnyHashable(uint16Value)
- } else if NSNumber(value: int32Value) == self {
- return AnyHashable(int32Value)
- } else if NSNumber(value: uint32Value) == self {
- return AnyHashable(uint32Value)
} else if NSNumber(value: int64Value) == self {
return AnyHashable(int64Value)
- } else if NSNumber(value: floatValue) == self {
- return AnyHashable(floatValue)
+ } else if NSNumber(value: uint64Value) == self {
+ return AnyHashable(uint64Value)
} else if NSNumber(value: doubleValue) == self {
return AnyHashable(doubleValue)
} else {
@@ -676,4 +683,3 @@
}
}
}
-
diff --git a/stdlib/public/SDK/Intents/INSetProfileInCarIntent.swift b/stdlib/public/SDK/Intents/INSetProfileInCarIntent.swift
index 20b5522..b8013f0 100644
--- a/stdlib/public/SDK/Intents/INSetProfileInCarIntent.swift
+++ b/stdlib/public/SDK/Intents/INSetProfileInCarIntent.swift
@@ -123,11 +123,17 @@
}
}
- @available(iOS 11.0, *)
- public final var isDefaultProfile: Bool? {
+ @available(iOS 10.0, *)
+ public var isDefaultProfile: Bool? {
return __defaultProfile?.boolValue
}
+ @available(swift, deprecated: 3.2, obsoleted: 4.0,
+ message: "Please use isDefaultProfile instead")
+ public var defaultProfile: Int? {
+ return __defaultProfile?.intValue
+ }
+
@available(iOS 10.0, *)
public final var profileNumber: Int? {
return __profileNumber?.intValue
diff --git a/stdlib/public/SwiftShims/DispatchOverlayShims.h b/stdlib/public/SwiftShims/DispatchOverlayShims.h
index 7b5a6de..7cdb0d4 100644
--- a/stdlib/public/SwiftShims/DispatchOverlayShims.h
+++ b/stdlib/public/SwiftShims/DispatchOverlayShims.h
@@ -166,7 +166,7 @@
}
SWIFT_DISPATCH_RETURNS_RETAINED
-__swift_shims_dispatch_data_t
+static inline __swift_shims_dispatch_data_t
_swift_dispatch_data_create(
const void *buffer,
size_t size,
@@ -177,7 +177,7 @@
typedef unsigned int (^__swift_shims_dispatch_data_applier)(__swift_shims_dispatch_data_t, size_t, const void *, size_t);
-unsigned int
+static inline unsigned int
_swift_dispatch_data_apply(
__swift_shims_dispatch_data_t data,
__swift_shims_dispatch_data_applier SWIFT_DISPATCH_NOESCAPE applier) {
@@ -186,19 +186,19 @@
});
}
-void _swift_dispatch_source_set_event_handler(
+static inline void _swift_dispatch_source_set_event_handler(
dispatch_source_t source,
__swift_shims_dispatch_block_t _Nullable block) {
dispatch_source_set_event_handler(source, block);
}
-void _swift_dispatch_source_set_cancel_handler(
+static inline void _swift_dispatch_source_set_cancel_handler(
dispatch_source_t source,
__swift_shims_dispatch_block_t _Nullable block) {
dispatch_source_set_cancel_handler(source, block);
}
-void _swift_dispatch_source_set_registration_handler(
+static inline void _swift_dispatch_source_set_registration_handler(
dispatch_source_t source,
__swift_shims_dispatch_block_t _Nullable block) {
dispatch_source_set_registration_handler(source, block);
diff --git a/stdlib/public/SwiftShims/NSIndexSetShims.h b/stdlib/public/SwiftShims/NSIndexSetShims.h
index ee4138e..09abe89 100644
--- a/stdlib/public/SwiftShims/NSIndexSetShims.h
+++ b/stdlib/public/SwiftShims/NSIndexSetShims.h
@@ -20,11 +20,11 @@
- (NSUInteger)_indexOfRangeContainingIndex:(NSUInteger)value;
@end
-extern NSUInteger __NSIndexSetRangeCount(NS_NON_BRIDGED(NSIndexSet *)self_) {
+NS_INLINE NSUInteger __NSIndexSetRangeCount(NS_NON_BRIDGED(NSIndexSet *)self_) {
return [(NSIndexSet *)self_ rangeCount];
}
-extern void __NSIndexSetRangeAtIndex(NS_NON_BRIDGED(NSIndexSet *)self_, NSUInteger rangeIndex, NSUInteger *location, NSUInteger *length) {
+NS_INLINE void __NSIndexSetRangeAtIndex(NS_NON_BRIDGED(NSIndexSet *)self_, NSUInteger rangeIndex, NSUInteger *location, NSUInteger *length) {
NSRange result = [(NSIndexSet *)self_ rangeAtIndex:rangeIndex];
*location = result.location;
*length = result.length;
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index 4e1204f..19472db 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -1426,27 +1426,22 @@
/// - Parameter source: An integer to convert to this type.
init<T : BinaryInteger>(clamping source: T)
- /// Returns the n-th word, counting from the least significant to most
- /// significant, of this value's binary representation.
- ///
- /// The `_word(at:)` method returns negative values in two's complement
- /// representation, regardless of a type's underlying implementation. If `n`
- /// is greater than the number of words in this value's current
- /// representation, the result is `0` for positive numbers and `~0` for
- /// negative numbers.
- ///
- /// - Parameter n: The word to return, counting from the least significant to
- /// most significant. `n` must be greater than or equal to zero.
- /// - Returns: An word-sized, unsigned integer with the bit pattern of the
- /// n-th word of this value.
- func _word(at n: Int) -> UInt
-
- // FIXME(integers): add doc comments
- // FIXME: Should be `Words : Collection where Words.Iterator.Element == UInt`
+ // FIXME: Should be `Words : Collection where Words.Element == UInt`
// See <rdar://problem/31798916> for why it isn't.
- associatedtype Words
+ /// A type that represents the words of a binary integer.
+ /// Must implement the `Collection` protocol with an `UInt` element type.
+ associatedtype Words : Sequence where Words.Element == UInt
+
+ /// Returns a collection containing the words of this value's binary
+ /// representation, in order from the least significant to most significant.
+ ///
+ /// Negative values are returned in two's complement representation,
+ /// regardless of the type's underlying implementation.
var words: Words { get }
+ /// The least significant word in this value's binary representation.
+ var _lowWord: UInt { get }
+
/// The number of bits in the current binary representation of this value.
///
/// This property is a constant for instances of fixed-width integer
@@ -1542,13 +1537,10 @@
return (self > (0 as Self) ? 1 : 0) - (self < (0 as Self) ? 1 : 0)
}
- /// The number of words used for the current binary representation of this
- /// value.
- ///
- /// This property is a constant for instances of fixed-width integer types.
@_transparent
- public var _countRepresentedWords: Int {
- return (self.bitWidth + ${word_bits} - 1) / ${word_bits}
+ public var _lowWord: UInt {
+ var it = words.makeIterator()
+ return it.next() ?? 0
}
public func quotientAndRemainder(dividingBy rhs: Self)
@@ -1886,19 +1878,6 @@
}
#endif
-extension BinaryInteger {
- // FIXME(integers): inefficient. Should get rid of _word(at:) and
- // _countRepresentedWords, and make `words` the basic operation.
- public var words: [UInt] {
- var result = [UInt]()
- result.reserveCapacity(_countRepresentedWords)
- for i in 0..<self._countRepresentedWords {
- result.append(_word(at: i))
- }
- return result
- }
-}
-
//===----------------------------------------------------------------------===//
//===--- FixedWidthInteger ------------------------------------------------===//
//===----------------------------------------------------------------------===//
@@ -2282,21 +2261,21 @@
@inline(__always)
public init<T : BinaryInteger>(extendingOrTruncating source: T) {
if Self.bitWidth <= ${word_bits} {
- self = Self.init(_truncatingBits: source._word(at: 0))
+ self = Self.init(_truncatingBits: source._lowWord)
}
else {
- var result: Self = source < (0 as T) ? ~0 : 0
- // start with the most significant word
- var n = source._countRepresentedWords
- while n >= 0 {
- // masking is OK here because this we have already ensured
- // that Self.bitWidth > ${word_bits}. Not masking results in
+ let neg = source < (0 as T)
+ var result: Self = neg ? ~0 : 0
+ var shift: Self = 0
+ let width = Self(_truncatingBits: Self.bitWidth._lowWord)
+ for word in source.words {
+ guard shift < width else { break }
+ // masking shift is OK here because we have already ensured
+ // that shift < Self.bitWidth. Not masking results in
// infinite recursion.
- result &<<= (${word_bits} as Self)
- result |= Self(_truncatingBits: source._word(at: n))
- n -= 1
+ result ^= Self(_truncatingBits: neg ? ~word : word) &<< shift
+ shift += ${word_bits}
}
-
self = result
}
}
@@ -2740,7 +2719,7 @@
return Int(
${Self}(
Builtin.int_ctlz_Int${bits}(self._value, false._value)
- )._lowUWord._value)
+ )._lowWord._value)
}
@_transparent
@@ -2748,7 +2727,7 @@
return Int(
${Self}(
Builtin.int_cttz_Int${bits}(self._value, false._value)
- )._lowUWord._value)
+ )._lowWord._value)
}
@_transparent
@@ -2756,29 +2735,55 @@
return Int(
${Self}(
Builtin.int_ctpop_Int${bits}(self._value)
- )._lowUWord._value)
+ )._lowWord._value)
+ }
+
+ // FIXME should be RandomAccessCollection
+ public struct Words : BidirectionalCollection {
+ public typealias Indices = CountableRange<Int>
+ public typealias SubSequence = BidirectionalSlice<${Self}.Words>
+
+ var _value: ${Self}
+
+ public init(_ value: ${Self}) {
+ self._value = value
+ }
+
+ public var count: Int {
+ return (${bits} + ${word_bits} - 1) / ${word_bits}
+ }
+
+ public var startIndex: Int { return 0 }
+
+ public var endIndex: Int { return count }
+
+ public var indices: Indices { return startIndex ..< endIndex }
+
+ @_transparent
+ public func index(after i: Int) -> Int { return i + 1 }
+
+ @_transparent
+ public func index(before i: Int) -> Int { return i - 1 }
+
+ public subscript(position: Int) -> UInt {
+ get {
+ _precondition(position >= 0, "Negative word index")
+ _precondition(position < endIndex, "Word index out of range")
+ let shift = UInt(position._value) &* ${word_bits}
+ _sanityCheck(shift < UInt(_value.bitWidth._value))
+ return (_value &>> ${Self}(_truncatingBits: shift))._lowWord
+ }
+ }
}
@_transparent
- public func _word(at n: Int) -> UInt {
- _precondition(n >= 0, "Negative word index")
- if _fastPath(n < _countRepresentedWords) {
- let shift = UInt(n._value) &* ${word_bits}
- let bitWidth = UInt(self.bitWidth._value)
- _sanityCheck(shift < bitWidth)
- return (self &>> ${Self}(_truncatingBits: shift))._lowUWord
- }
-% if signed:
- return self < (0 as ${Self}) ? ~0 : 0
-% else:
- return 0
-% end
+ public var words: Words {
+ return Words(self)
}
-
@_transparent
public // transparent
- var _lowUWord: UInt {
+ var _lowWord: UInt {
% truncOrExt = z + 'ext' if bits <= word_bits else 'trunc'
return UInt(
Builtin.${truncOrExt}OrBitCast_Int${bits}_Int${word_bits}(_value)
diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift
index ffef517..db1d1f4 100644
--- a/stdlib/public/core/String.swift
+++ b/stdlib/public/core/String.swift
@@ -150,13 +150,6 @@
}
return String(String.CharacterView(self))
}
-
- internal var _persistentString : String {
- if _fastPath(self is _SwiftStringView) {
- return (self as! _SwiftStringView)._persistentContent
- }
- return String(String.CharacterView(self))
- }
}
extension String : _SwiftStringView {
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 585245c..560f9c1 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -266,10 +266,16 @@
var _persistentContent : String {
let wholeCore = _slice._base._core
let native = wholeCore.nativeBuffer
- if _fastPath(native != nil), let n = native {
+ if _fastPath(native != nil) {
+ let wholeString = String(wholeCore)
+ let n = native._unsafelyUnwrappedUnchecked
if _fastPath(
- n.start == wholeCore._baseAddress && n.usedCount == wholeCore.count) {
- return String(wholeCore)
+ n.start == wholeCore._baseAddress
+ && n.usedCount == wholeCore.count
+ && _slice.startIndex == wholeString.startIndex
+ && _slice.endIndex == wholeString.endIndex
+ ) {
+ return wholeString
}
}
var r = String()
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h
index c0f387e..c3a23fd 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h
@@ -22,6 +22,12 @@
@interface Base
@end
+@interface B : A
+@end
+
+@interface C : B
+@end
+
#endif // __OBJC__
#import <APINotesFrameworkTest/Classes.h>
diff --git a/test/APINotes/basic.swift b/test/APINotes/basic.swift
index 5e894cf..84903d0 100644
--- a/test/APINotes/basic.swift
+++ b/test/APINotes/basic.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift -I %S/Inputs/custom-modules -F %S/Inputs/custom-frameworks
+// RUN: %target-typecheck-verify-swift -I %S/Inputs/custom-modules -F %S/Inputs/custom-frameworks -swift-version 4
import APINotesTest
import APINotesFrameworkTest
@@ -7,8 +7,18 @@
func implicitlyObjC() { }
}
+extension C {
+ func alsoImplicitlyObjC() { }
+}
+
+class D : C {
+ func yetAnotherImplicitlyObjC() { }
+}
+
func testSelectors(a: AnyObject) {
a.implicitlyObjC?() // okay: would complain without SwiftObjCMembers
+ a.alsoImplicitlyObjC?() // okay: would complain without SwiftObjCMembers
+ a.yetAnotherImplicitlyObjC?() // okay: would complain without SwiftObjCMembers
}
#endif
diff --git a/test/IRGen/partial_apply_forwarder.sil b/test/IRGen/partial_apply_forwarder.sil
index 9c6a173..4734dcc 100644
--- a/test/IRGen/partial_apply_forwarder.sil
+++ b/test/IRGen/partial_apply_forwarder.sil
@@ -70,7 +70,11 @@
public class WeakBox<T> {}
+public struct EmptyType {}
+
sil hidden_external @takingQ : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (@owned WeakBox<τ_0_0>) -> ()
+sil hidden_external @takingQAndEmpty : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (@owned WeakBox<τ_0_0>, EmptyType) -> ()
+sil hidden_external @takingEmptyAndQ : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (EmptyType, @owned WeakBox<τ_0_0>) -> ()
// CHECK-LABEL: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @bind_polymorphic_param_from_context(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_0_1")
// CHECK: entry:
@@ -103,6 +107,35 @@
return %9 : $@callee_owned () -> ()
}
+// CHECK-LABEL: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @bind_polymorphic_param_from_context_2(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_0_1")
+// CHECK: [[OBJ:%.*]] = call {{.*}} @swift_rt_swift_allocObject
+// CHECK: [[WB:%.*]] = bitcast %swift.refcounted* [[OBJ]]
+// CHECK: [[REF:%.*]] = bitcast {{.*}}* [[WB]] to %swift.refcounted*
+// CHECK: [[CLOSURE:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (%swift.refcounted*)* @_T015takingQAndEmptyTA to i8*), %swift.refcounted* undef }, %swift.refcounted* [[REF]], 1
+// CHECK: }
+sil public @bind_polymorphic_param_from_context_2 : $@convention(thin) <τ_0_1>(@in τ_0_1, EmptyType) -> @owned @callee_owned () -> () {
+bb0(%0 : $*τ_0_1, %2: $EmptyType):
+ %1 = alloc_ref $WeakBox<BaseProducer<τ_0_1>>
+ %8 = function_ref @takingQAndEmpty : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (@owned WeakBox<τ_0_0>, EmptyType) -> ()
+ %9 = partial_apply %8<BaseProducer<τ_0_1>>(%1, %2) : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (@owned WeakBox<τ_0_0>, EmptyType) -> ()
+ return %9 : $@callee_owned () -> ()
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @bind_polymorphic_param_from_context_3(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_0_1")
+// CHECK: [[OBJ:%.*]] = call {{.*}} @swift_rt_swift_allocObject
+// CHECK: [[WB:%.*]] = bitcast %swift.refcounted* [[OBJ]]
+// CHECK: [[REF:%.*]] = bitcast {{.*}}* [[WB]] to %swift.refcounted*
+// CHECK: [[CLOSURE:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (%swift.refcounted*)* @_T015takingEmptyAndQTA to i8*), %swift.refcounted* undef }, %swift.refcounted* [[REF]], 1
+// CHECK: }
+
+sil public @bind_polymorphic_param_from_context_3 : $@convention(thin) <τ_0_1>(@in τ_0_1, EmptyType) -> @owned @callee_owned () -> () {
+bb0(%0 : $*τ_0_1, %2: $EmptyType):
+ %1 = alloc_ref $WeakBox<BaseProducer<τ_0_1>>
+ %8 = function_ref @takingEmptyAndQ : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (EmptyType, @owned WeakBox<τ_0_0>) -> ()
+ %9 = partial_apply %8<BaseProducer<τ_0_1>>(%2, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (EmptyType, @owned WeakBox<τ_0_0>) -> ()
+ return %9 : $@callee_owned () -> ()
+}
+
// CHECK-LABEL: define{{( protected)?}} swiftcc void @bind_polymorphic_param_from_forwarder_parameter(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_0_1")
// CHECK: entry:
// CHECK: [[BPTY:%.*]] = call %swift.type* @_T023partial_apply_forwarder12BaseProducerVMa(%swift.type* %"\CF\84_0_1")
diff --git a/test/IRGen/tsan_instrumentation.sil b/test/IRGen/tsan_instrumentation.sil
index 690033a..48c952f 100644
--- a/test/IRGen/tsan_instrumentation.sil
+++ b/test/IRGen/tsan_instrumentation.sil
@@ -23,7 +23,7 @@
bb0:
%0 = global_addr @_T020tsan_instrumentation1gSiv : $*Int
%1 = builtin "tsanInoutAccess"(%0 : $*Int) : $()
-// CHECK: call void @__tsan_write1(i8* bitcast ([[GLOBAL]]* @_T020tsan_instrumentation1gSiv to i8*))
+// CHECK: call void @__tsan_external_write(i8* bitcast ([[GLOBAL]]* @_T020tsan_instrumentation1gSiv to i8*), i8* null, i8* inttoptr ({{(i32|i64)}} 1 to i8*))
%2 = tuple ()
return %2 : $()
diff --git a/test/Inputs/clang-importer-sdk/usr/include/Foundation.h b/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
index 60e92a3..ffd5deb 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
@@ -1110,3 +1110,13 @@
NSLaundryErrorTooMuchSoap = 1,
NSLaundryErrorCatInWasher = 2
};
+
+@interface NSObject ()
+- (void) addObserver: (id) observer
+ forKeyPath: (NSString*) keyPath
+ options: (NSInteger) options
+ context: (void*) context;
+- (void) removeObserver: (id) observer
+ forKeyPath: (NSString*) keyPath
+ context: (void*) options;
+@end
diff --git a/test/Parse/enum.swift b/test/Parse/enum.swift
index df4d7b8..7fb3b50 100644
--- a/test/Parse/enum.swift
+++ b/test/Parse/enum.swift
@@ -193,6 +193,12 @@
case Third = "は"
}
+enum RawTypeWithCharacterValues_Correct : Character {
+ case First = "😅" // ok
+ case Second = "👩👩👧👦" // ok
+ case Third = "👋🏽" // ok
+}
+
enum RawTypeWithCharacterValues_Error1 : Character { // expected-error {{'RawTypeWithCharacterValues_Error1' declares raw type 'Character', but does not conform to RawRepresentable and conformance could not be synthesized}}
case First = "abc" // expected-error {{cannot convert value of type 'String' to raw type 'Character'}}
}
diff --git a/test/Parse/multiline_errors.swift b/test/Parse/multiline_errors.swift
index 21275ee..4fa56d0 100644
--- a/test/Parse/multiline_errors.swift
+++ b/test/Parse/multiline_errors.swift
Binary files differ
diff --git a/test/Parse/multiline_normalize_newline.swift b/test/Parse/multiline_normalize_newline.swift
new file mode 100644
index 0000000..acbaa5a
--- /dev/null
+++ b/test/Parse/multiline_normalize_newline.swift
Binary files differ
diff --git a/test/Parse/multiline_string.swift b/test/Parse/multiline_string.swift
index 03020c2..c2a3d3d 100644
--- a/test/Parse/multiline_string.swift
+++ b/test/Parse/multiline_string.swift
@@ -83,6 +83,11 @@
// CHECK: "\\"
_ = """
+ \\
+ """
+// CHECK: "\\"
+
+_ = """
ABC
"""
@@ -109,6 +114,51 @@
// CHECK: "Twelve\nNu"
_ = """
+ newline \
+ elided
+ """
+// CHECK: "newline elided"
+
+// contains trailing whitepsace
+_ = """
+ trailing \
+ \("""
+ substring1 \
+ \("""
+ substring2 \
+ substring3
+ """)
+ """) \
+ whitepsace
+ """
+// CHECK: "trailing "
+// CHECK: "substring1 "
+// CHECK: "substring2 substring3"
+// CHECK: " whitepsace"
+
+// contains trailing whitepsace
+_ = """
+ foo\
+
+ bar
+ """
+// CHECK: "foo\nbar"
+
+// contains trailing whitepsace
+_ = """
+ foo\
+
+ bar
+ """
+// CHECK: "foo\nbar"
+
+_ = """
+ foo \
+ bar
+ """
+// CHECK: "foo bar"
+
+_ = """
ABC
"""
diff --git a/test/Prototypes/BigInt.swift b/test/Prototypes/BigInt.swift
index c8f0b58..ee81655 100644
--- a/test/Prototypes/BigInt.swift
+++ b/test/Prototypes/BigInt.swift
@@ -121,8 +121,7 @@
// FIXME: This is broken on 32-bit arch w/ Word = UInt64
let wordRatio = UInt.bitWidth / Word.bitWidth
_sanityCheck(wordRatio != 0)
- for i in 0..<source._countRepresentedWords {
- var sourceWord = source._word(at: i)
+ for var sourceWord in source.words {
for _ in 0..<wordRatio {
_data.append(Word(extendingOrTruncating: sourceWord))
sourceWord >>= Word.bitWidth
@@ -660,36 +659,30 @@
}
}
- public func _word(at n: Int) -> UInt {
- let ratio = UInt.bitWidth / Word.bitWidth
- _sanityCheck(ratio != 0)
-
- var twosComplementData = _dataAsTwosComplement()
-
- // Find beginning of range. If we're beyond the value, return 1s or 0s.
- let start = n * ratio
- if start >= twosComplementData.count {
- return isNegative ? UInt.max : 0
+ public var words: [UInt] {
+ _sanityCheck(UInt.bitWidth % Word.bitWidth == 0)
+ let twosComplementData = _dataAsTwosComplement()
+ var words: [UInt] = []
+ words.reserveCapacity((twosComplementData.count * Word.bitWidth
+ + UInt.bitWidth - 1) / UInt.bitWidth)
+ var word: UInt = 0
+ var shift = 0
+ for w in twosComplementData {
+ word |= UInt(extendingOrTruncating: w) << shift
+ shift += Word.bitWidth
+ if shift == UInt.bitWidth {
+ words.append(word)
+ word = 0
+ shift = 0
+ }
}
-
- // Find end of range. If the range extends beyond the representation,
- // add bits to the end.
- let end = (n + 1) * ratio
- if end > twosComplementData.count {
- twosComplementData.append(contentsOf:
- repeatElement(isNegative ? Word.max : 0,
- count: end - twosComplementData.count))
+ if shift != 0 {
+ if isNegative {
+ word |= ~((1 << shift) - 1)
+ }
+ words.append(word)
}
-
- // Build the correct word from the range determined above.
- let wordSlice = twosComplementData[start..<end]
- var result: UInt = 0
- for v in wordSlice.reversed() {
- result <<= Word.bitWidth
- result |= UInt(extendingOrTruncating: v)
- }
-
- return result
+ return words
}
/// The number of bits used for storage of this value. Always a multiple of
@@ -1258,7 +1251,7 @@
}
var trailingZeroBitCount: Int {
- return value.trailingZeroBitCount
+ return Int(~value & 1)
}
static var max: Bit {
@@ -1278,7 +1271,7 @@
}
var leadingZeroBitCount: Int {
- return value.nonzeroBitCount - 7
+ return Int(~value & 1)
}
var bigEndian: Bit {
@@ -1293,8 +1286,8 @@
return self
}
- func _word(at n: Int) -> UInt {
- return UInt(value)
+ var words: UInt.Words {
+ return UInt(value).words
}
// Hashable, CustomStringConvertible
@@ -1499,6 +1492,15 @@
expectEqual(x, x + y)
expectGT(x, x &+ x)
+
+ expectEqual(1, x.nonzeroBitCount)
+ expectEqual(0, y.nonzeroBitCount)
+
+ expectEqual(0, x.leadingZeroBitCount)
+ expectEqual(1, y.leadingZeroBitCount)
+
+ expectEqual(0, x.trailingZeroBitCount)
+ expectEqual(1, y.trailingZeroBitCount)
}
var BigIntTests = TestSuite("BigInt")
@@ -1865,4 +1867,12 @@
expectFalse(set.contains(-x))
}
+BigIntBitTests.test("words") {
+ expectEqualSequence([1], (1 as BigIntBit).words)
+ expectEqualSequence([UInt.max, 0], BigIntBit(UInt.max).words)
+ expectEqualSequence([UInt.max >> 1], BigIntBit(UInt.max >> 1).words)
+ expectEqualSequence([0, 1], (BigIntBit(UInt.max) + 1).words)
+ expectEqualSequence([UInt.max], (-1 as BigIntBit).words)
+}
+
runAllTests()
diff --git a/test/SILGen/Inputs/objc_dynamic_init.h b/test/SILGen/Inputs/objc_dynamic_init.h
new file mode 100644
index 0000000..5a226eb
--- /dev/null
+++ b/test/SILGen/Inputs/objc_dynamic_init.h
@@ -0,0 +1,13 @@
+@import Foundation;
+
+@protocol ObjCInitProto
+
+- initWithProto:(NSInteger)x;
+
+@end
+
+@interface ObjCBaseWithInitProto: NSObject <ObjCInitProto>
+
+- initWithProto:(NSInteger)x NS_DESIGNATED_INITIALIZER;
+
+@end
diff --git a/test/SILGen/constrained_extensions.swift b/test/SILGen/constrained_extensions.swift
index 61aa4ea..f9b9b6c 100644
--- a/test/SILGen/constrained_extensions.swift
+++ b/test/SILGen/constrained_extensions.swift
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -emit-silgen -primary-file %s | %FileCheck %s
-// RUN: %target-swift-frontend -emit-sil -O -primary-file %s
-// RUN: %target-swift-frontend -emit-ir -primary-file %s
+// RUN: %target-swift-frontend -emit-sil -O -primary-file %s > /dev/null
+// RUN: %target-swift-frontend -emit-ir -primary-file %s > /dev/null
extension Array where Element == Int {
// CHECK-LABEL: sil @_T0Sa22constrained_extensionsSiRszlESaySiGyt1x_tcfC : $@convention(method) (@thin Array<Int>.Type) -> @owned Array<Int>
@@ -10,7 +10,7 @@
// CHECK-LABEL: sil @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifg : $@convention(method) (@guaranteed Array<Int>) -> Int
// CHECK-LABEL: sil @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifs : $@convention(method) (Int, @inout Array<Int>) -> ()
- // CHECK-LABEL: sil private [transparent] [serialized] @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array<Int>, @thick Array<Int>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array<Int>, @thick Array<Int>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array<Int>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public var instanceProperty: Element {
@@ -71,7 +71,7 @@
// CHECK-LABEL: sil @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fg : $@convention(method) <Key, Value where Key == Int> (@guaranteed Dictionary<Int, Value>) -> @out Value
// CHECK-LABEL: sil @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fs : $@convention(method) <Key, Value where Key == Int> (@in Value, @inout Dictionary<Int, Value>) -> ()
- // CHECK-LABEL: sil private [transparent] [serialized] @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fmytfU_ : $@convention(method) <Key, Value where Key == Int> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Int, Value>, @thick Dictionary<Int, Value>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fmytfU_ : $@convention(method) <Key, Value where Key == Int> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Int, Value>, @thick Dictionary<Int, Value>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fm : $@convention(method) <Key, Value where Key == Int> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Int, Value>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public var instanceProperty: Value {
get {
@@ -137,7 +137,7 @@
extension GenericClass where Y == () {
// CHECK-LABEL: sil @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5valuexfg : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> @out X
// CHECK-LABEL: sil @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5valuexfs : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
- // CHECK-LABEL: sil private [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5valuexfmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5valuexfmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5valuexfm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public var value: X {
get { while true {} }
@@ -146,7 +146,7 @@
// CHECK-LABEL: sil @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5emptyytfg : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5emptyytfs : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> ()
- // CHECK-LABEL: sil private [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5emptyytfmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5emptyytfmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE5emptyytfm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public var empty: Y {
get { return () }
@@ -155,7 +155,7 @@
// CHECK-LABEL: sil @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptxyt_tcfg : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> @out X
// CHECK-LABEL: sil @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptxyt_tcfs : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
- // CHECK-LABEL: sil private [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptxyt_tcfmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptxyt_tcfmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptxyt_tcfm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public subscript(_: Y) -> X {
get { while true {} }
@@ -164,7 +164,7 @@
// CHECK-LABEL: sil @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptyxcfg : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptyxcfs : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
- // CHECK-LABEL: sil private [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptyxcfmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptyxcfmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @_T022constrained_extensions12GenericClassCAAytRs_r0_lE9subscriptyxcfm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in X, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public subscript(_: X) -> Y {
get { while true {} }
diff --git a/test/SILGen/objc_dynamic_init.swift b/test/SILGen/objc_dynamic_init.swift
index 5ec7197..33c9f85 100644
--- a/test/SILGen/objc_dynamic_init.swift
+++ b/test/SILGen/objc_dynamic_init.swift
@@ -1,20 +1,45 @@
-// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen %s | %FileCheck %s
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -import-objc-header %S/Inputs/objc_dynamic_init.h -emit-silgen %s | %FileCheck %s
// REQUIRES: objc_interop
import Foundation
-protocol Person {
+protocol Hoozit {
init()
}
-class Driver: NSObject, Person {
+protocol Wotsit {
+ init()
+}
+
+class Gadget: NSObject, Hoozit {
required override init() {
super.init()
}
}
-// CHECK-LABEL: sil private [transparent] [thunk] @_T{{.*}}DriverC{{.*}}CTW
-// CHECK: class_method {{%.*}} : $@thick Driver.Type, #Driver.init!allocator.1 :
+class Gizmo: Gadget, Wotsit {
+ required init() {
+ super.init()
+ }
+}
-// CHECK-LABEL: sil_vtable Driver {
-// CHECK: #Driver.init!allocator.1: (Driver.Type) -> () -> Driver : _T{{.*}}DriverC{{.*}}C {{ *}}//
+class Thingamabob: ObjCBaseWithInitProto {
+ required init(proto: Int) {
+ super.init(proto: proto)
+ }
+}
+
+final class Bobamathing: Thingamabob {
+ required init(proto: Int) {
+ super.init(proto: proto)
+ }
+}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @_T{{.*}}GadgetC{{.*}}CTW
+// CHECK: class_method {{%.*}} : $@thick Gadget.Type, #Gadget.init!allocator.1 :
+
+// CHECK-LABEL: sil_vtable Gadget {
+// CHECK: #Gadget.init!allocator.1: (Gadget.Type) -> () -> Gadget : _T{{.*}}GadgetC{{.*}}C {{ *}}//
+
+// CHECK-LABEL: sil_vtable Gizmo {
+// CHECK: #Gadget.init!allocator.1: (Gadget.Type) -> () -> Gadget : _T{{.*}}GizmoC{{.*}}C {{ *}}//
diff --git a/test/SILGen/opaque_values_silgen.swift b/test/SILGen/opaque_values_silgen.swift
index 9ed9dd4..7f82391 100644
--- a/test/SILGen/opaque_values_silgen.swift
+++ b/test/SILGen/opaque_values_silgen.swift
@@ -1071,7 +1071,7 @@
// Tests materializeForSet's createSetterCallback for opaque values
// ---
-// CHECK-LABEL: sil private [transparent] [serialized] @_T0s10DictionaryV20opaque_values_silgenE9subscriptq_Sgq_cfmytfU_ : $@convention(method) <Key, Value where Key : Hashable> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Key, Value>, @thick Dictionary<Key, Value>.Type) -> () {
+// CHECK-LABEL: sil shared [transparent] [serialized] @_T0s10DictionaryV20opaque_values_silgenE9subscriptq_Sgq_cfmytfU_ : $@convention(method) <Key, Value where Key : Hashable> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Key, Value>, @thick Dictionary<Key, Value>.Type) -> () {
// CHECK: bb0([[ARG0:%.*]] : $Builtin.RawPointer, [[ARG1:%.*]] : $*Builtin.UnsafeValueBuffer, [[ARG2:%.*]] : $*Dictionary<Key, Value>, [[ARG3:%.*]] : $@thick Dictionary<Key, Value>.Type):
// CHECK: [[PROJ_VAL1:%.*]] = project_value_buffer $Value in [[ARG1]] : $*Builtin.UnsafeValueBuffer
// CHECK: [[LOAD_VAL1:%.*]] = load [take] [[PROJ_VAL1]] : $*Value
diff --git a/test/SILGen/pointer_conversion_nonaccessing.swift b/test/SILGen/pointer_conversion_nonaccessing.swift
new file mode 100644
index 0000000..e07f860
--- /dev/null
+++ b/test/SILGen/pointer_conversion_nonaccessing.swift
@@ -0,0 +1,64 @@
+// RUN: %target-swift-frontend -swift-version 4 -emit-silgen %s | %FileCheck %s
+
+// rdar://33265254
+
+// Check for the total absence of access markers here.
+// FIXME: probably we should have some markers that just disable even static checking
+
+var global = 0
+
+// CHECK-LABEL: sil hidden @_T031pointer_conversion_nonaccessing6testEqSbSV3ptr_tF
+func testEq(ptr: UnsafeRawPointer) -> Bool {
+ // CHECK: [[T0:%.*]] = global_addr @_T031pointer_conversion_nonaccessing6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ return &global == ptr
+}
+
+// CHECK-LABEL: sil hidden @_T031pointer_conversion_nonaccessing7testNeqSbSV3ptr_tF
+func testNeq(ptr: UnsafeRawPointer) -> Bool {
+ // CHECK: [[T0:%.*]] = global_addr @_T031pointer_conversion_nonaccessing6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ return &global != ptr
+}
+
+// CHECK-LABEL: sil hidden @_T031pointer_conversion_nonaccessing6testEqSbSv3ptr_tF
+func testEq(ptr: UnsafeMutableRawPointer) -> Bool {
+ // CHECK: [[T0:%.*]] = global_addr @_T031pointer_conversion_nonaccessing6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ return &global == ptr
+}
+
+// CHECK-LABEL: sil hidden @_T031pointer_conversion_nonaccessing7testNeqSbSv3ptr_tF
+func testNeq(ptr: UnsafeMutableRawPointer) -> Bool {
+ // CHECK: [[T0:%.*]] = global_addr @_T031pointer_conversion_nonaccessing6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ return &global != ptr
+}
+
+// CHECK-LABEL: sil hidden @_T031pointer_conversion_nonaccessing6testEqSbSPySiG3ptr_tF
+func testEq(ptr: UnsafePointer<Int>) -> Bool {
+ // CHECK: [[T0:%.*]] = global_addr @_T031pointer_conversion_nonaccessing6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ return &global == ptr
+}
+
+// CHECK-LABEL: sil hidden @_T031pointer_conversion_nonaccessing7testNeqSbSPySiG3ptr_tF
+func testNeq(ptr: UnsafePointer<Int>) -> Bool {
+ // CHECK: [[T0:%.*]] = global_addr @_T031pointer_conversion_nonaccessing6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ return &global != ptr
+}
+
+// CHECK-LABEL: sil hidden @_T031pointer_conversion_nonaccessing6testEqSbSpySiG3ptr_tF
+func testEq(ptr: UnsafeMutablePointer<Int>) -> Bool {
+ // CHECK: [[T0:%.*]] = global_addr @_T031pointer_conversion_nonaccessing6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ return &global == ptr
+}
+
+// CHECK-LABEL: sil hidden @_T031pointer_conversion_nonaccessing7testNeqSbSpySiG3ptr_tF
+func testNeq(ptr: UnsafeMutablePointer<Int>) -> Bool {
+ // CHECK: [[T0:%.*]] = global_addr @_T031pointer_conversion_nonaccessing6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ return &global != ptr
+}
diff --git a/test/SILGen/pointer_conversion_nonaccessing_objc.swift b/test/SILGen/pointer_conversion_nonaccessing_objc.swift
new file mode 100644
index 0000000..798d283
--- /dev/null
+++ b/test/SILGen/pointer_conversion_nonaccessing_objc.swift
@@ -0,0 +1,26 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -swift-version 4 -emit-silgen %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+// rdar://33265254
+
+// Check for the total absence of access markers here.
+// FIXME: probably we should have some markers that just disable even static checking
+
+var global = 0
+
+// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc15testAddObserverySo8NSObjectC6object_AD8observertF
+func testAddObserver(object: NSObject, observer: NSObject) {
+ // CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ object.addObserver(observer, forKeyPath: "", options: 0, context: &global)
+}
+
+// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc18testRemoveObserverySo8NSObjectC6object_AD8observertF
+func testRemoveObserver(object: NSObject, observer: NSObject) {
+ // CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
+ // CHECK: address_to_pointer [[T0]]
+ object.removeObserver(observer, forKeyPath: "", context: &global)
+}
diff --git a/test/SILOptimizer/functionsigopts.sil b/test/SILOptimizer/functionsigopts.sil
index 82b6c14..a5c0198 100644
--- a/test/SILOptimizer/functionsigopts.sil
+++ b/test/SILOptimizer/functionsigopts.sil
@@ -1743,7 +1743,7 @@
// Check that we specialized this function by removing the dead argument and
// copied everything appropriately.
-// CHECK-LABEL: sil [serialized] @_T023dead_arg_with_callsitesTfq4dn_n : $@convention(thin) (Builtin.NativeObject) -> () {
+// CHECK-LABEL: sil shared [serialized] @_T023dead_arg_with_callsitesTfq4dn_n : $@convention(thin) (Builtin.NativeObject) -> () {
// CHECK: bb0([[INPUT_ARG:%[0-9]+]] : $Builtin.NativeObject):
// CHECK: cond_br undef, bb1, bb2
// CHECK: bb1:
@@ -1757,16 +1757,16 @@
// CHECK-NEXT: tuple
// CHECK-NEXT: return
-// CHECK-LABEL: sil private [serialized] @_T031private_dead_arg_with_callsitesTfq4dn_n : $@convention(thin) (Builtin.NativeObject) -> () {
+// CHECK-LABEL: sil shared [serialized] @_T031private_dead_arg_with_callsitesTfq4dn_n : $@convention(thin) (Builtin.NativeObject) -> () {
// CHECK: bb0(
-// CHECK-LABEL: sil [serialized] @_T037owned_to_guaranteed_with_error_resultTfq4gn_n : $@convention(thin) (@guaranteed Builtin.NativeObject, Int) -> (Int, @error Error) {
+// CHECK-LABEL: sil shared [serialized] @_T037owned_to_guaranteed_with_error_resultTfq4gn_n : $@convention(thin) (@guaranteed Builtin.NativeObject, Int) -> (Int, @error Error) {
// CHECK-NOT: release
// CHECK: throw
-// CHECK-LABEL: sil [serialized] @_T042owned_to_guaranteed_simple_singlebb_calleeTfq4g_n : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
+// CHECK-LABEL: sil shared [serialized] @_T042owned_to_guaranteed_simple_singlebb_calleeTfq4g_n : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
-// CHECK-LABEL: sil [serialized] @_T055owned_to_guaranteed_multibb_callee_with_release_in_exitTfq4dg_n : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
+// CHECK-LABEL: sil shared [serialized] @_T055owned_to_guaranteed_multibb_callee_with_release_in_exitTfq4dg_n : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
// CHECK: bb0(
// CHECK: function_ref user
// CHECK: function_ref @user
@@ -1784,7 +1784,7 @@
// Also make sure we have change the calling convention to freestanding from
// method because we have changed the self argument.
-// CHECK-LABEL: sil [serialized] @_T014array_semanticTfq4g_n : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
+// CHECK-LABEL: sil shared [serialized] @_T014array_semanticTfq4g_n : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
// CHECK: bb0(%0 : $Builtin.NativeObject)
// CHECK: function_ref user
// CHECK: function_ref @user
diff --git a/test/SILOptimizer/functionsigopts_sroa.sil b/test/SILOptimizer/functionsigopts_sroa.sil
index 87407a0..bf101b0 100644
--- a/test/SILOptimizer/functionsigopts_sroa.sil
+++ b/test/SILOptimizer/functionsigopts_sroa.sil
@@ -908,14 +908,14 @@
// Check Statements for generated code.
-// CHECK-LABEL: sil [serialized] @_T029single_level_dead_root_calleeTfq4x_n : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 {
+// CHECK-LABEL: sil shared [serialized] @_T029single_level_dead_root_calleeTfq4x_n : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 {
// CHECK: bb0([[IN:%.*]] : $Builtin.Int32):
// CHECK: [[UN:%.*]] = struct $S1 (undef : $Builtin.Int16, [[IN]] : $Builtin.Int32)
// CHECK: struct_extract [[UN]] : $S1, #S1.f2
// CHECK: return [[IN]] : $Builtin.Int32
-// CHECK-LABEL: sil [serialized] @_T029single_level_live_root_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int32) -> Builtin.Int32 {
+// CHECK-LABEL: sil shared [serialized] @_T029single_level_live_root_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int32) -> Builtin.Int32 {
// CHECK: bb0([[IN1:%.*]] : $Builtin.Int16, [[IN2:%.*]] : $Builtin.Int32):
// CHECK: [[STRUCT:%.*]] = struct $S1 ([[IN1]] : $Builtin.Int16, [[IN2]] : $Builtin.Int32)
// CHECK: [[STRUCT2:%.*]] = struct $S1 ([[IN1]] : $Builtin.Int16, [[IN2]] : $Builtin.Int32)
@@ -925,7 +925,7 @@
// CHECK: return [[IN2]]
-// CHECK-LABEL: sil [serialized] @_T042multiple_level_all_root_fields_used_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int64) -> (Builtin.Int16, Builtin.Int64) {
+// CHECK-LABEL: sil shared [serialized] @_T042multiple_level_all_root_fields_used_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int64) -> (Builtin.Int16, Builtin.Int64) {
// CHECK: bb0([[IN1:%.*]] : $Builtin.Int16, [[IN2:%.*]] : $Builtin.Int64):
// CHECK: [[STRUCT1:%.*]] = struct $S1 ([[IN1]] : $Builtin.Int16, undef : $Builtin.Int32)
// CHECK: [[STRUCT2:%.*]] = struct $S2 (%2 : $S1, [[IN2]] : $Builtin.Int64)
@@ -936,7 +936,7 @@
// CHECK: return [[OUT]]
-// CHECK-LABEL: sil [serialized] @_T053multiple_level_no_root_fields_have_direct_uses_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int64) -> (Builtin.Int16, Builtin.Int64) {
+// CHECK-LABEL: sil shared [serialized] @_T053multiple_level_no_root_fields_have_direct_uses_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int64) -> (Builtin.Int16, Builtin.Int64) {
// CHECK: bb0([[IN1:%.*]] : $Builtin.Int16, [[IN2:%.*]] : $Builtin.Int64):
// CHECK: [[STRUCT1:%.*]] = struct $S1 ([[IN1]] : $Builtin.Int16, undef : $Builtin.Int32)
// CHECK: [[STRUCT2:%.*]] = struct $S2 ([[STRUCT1]] : $S1, [[IN2]] : $Builtin.Int64)
@@ -946,7 +946,7 @@
// CHECK: return [[OUT]]
-// CHECK-LABEL: sil [serialized] @_T043multiple_level_root_must_be_reformed_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int32, Builtin.Int64) -> (Builtin.Int16, Builtin.Int64) {
+// CHECK-LABEL: sil shared [serialized] @_T043multiple_level_root_must_be_reformed_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int32, Builtin.Int64) -> (Builtin.Int16, Builtin.Int64) {
// CHECK: bb0([[IN1:%.*]] : $Builtin.Int16, [[IN2:%.*]] : $Builtin.Int32, [[IN3:%.*]] : $Builtin.Int64):
// CHECK: [[STRUCT1:%.*]] = struct $S1 ([[IN1]] : $Builtin.Int16, [[IN2]] : $Builtin.Int32)
// CHECK: [[STRUCT3:%.*]] = struct $S2 ([[STRUCT1]] : $S1, [[IN3]] : $Builtin.Int64)
@@ -960,7 +960,7 @@
-// CHECK-LABEL: sil [serialized] @_T021owned_struct_1_calleeTfq4dgX_n : $@convention(thin) (@guaranteed S4, Builtin.Int16, Builtin.Int32) -> (Builtin.Int16, Builtin.Int32, Builtin.Int16, Builtin.Int32) {
+// CHECK-LABEL: sil shared [serialized] @_T021owned_struct_1_calleeTfq4dgX_n : $@convention(thin) (@guaranteed S4, Builtin.Int16, Builtin.Int32) -> (Builtin.Int16, Builtin.Int32, Builtin.Int16, Builtin.Int32) {
// CHECK: bb0([[IN1:%.*]] : $S4, [[IN2:%.*]] : $Builtin.Int16, [[IN3:%.*]] : $Builtin.Int32):
// CHECK: [[STRUCT1:%.*]] = struct $S1 ([[IN2]] : $Builtin.Int16, [[IN3]] : $Builtin.Int32)
// CHECK: [[STRUCT3:%.*]] = struct $S5 ([[IN1]] : $S4, [[STRUCT1]] : $S1)
@@ -970,7 +970,7 @@
// CHECK: [[OUT:%.*]] = tuple ([[IN2]] : $Builtin.Int16, [[IN3]] : $Builtin.Int32, [[IN2]] : $Builtin.Int16, [[IN3]] : $Builtin.Int32)
// CHECK: return [[OUT]] : $(Builtin.Int16, Builtin.Int32, Builtin.Int16, Builtin.Int32)
-// CHECK-LABEL: sil [serialized] @_T021owned_struct_2_calleeTfq4ndgXdn_n : $@convention(thin) (Builtin.Int256, @guaranteed S4, Builtin.Int16, Builtin.Int32, Builtin.Int128) -> (Builtin.Int256, Builtin.Int16, Builtin.Int32, Builtin.Int128) {
+// CHECK-LABEL: sil shared [serialized] @_T021owned_struct_2_calleeTfq4ndgXdn_n : $@convention(thin) (Builtin.Int256, @guaranteed S4, Builtin.Int16, Builtin.Int32, Builtin.Int128) -> (Builtin.Int256, Builtin.Int16, Builtin.Int32, Builtin.Int128) {
// CHECK: bb0([[IN1:%.*]] : $Builtin.Int256, [[IN2:%.*]] : $S4, [[IN3:%.*]] : $Builtin.Int16, [[IN4:%.*]] : $Builtin.Int32, [[IN5:%.*]] : $Builtin.Int128):
// CHECK: [[STRUCT1:%.*]] = struct $S1 ([[IN3]] : $Builtin.Int16, [[IN4]] : $Builtin.Int32)
// CHECK: [[STRUCT3:%.*]] = struct $S5 ([[IN2]] : $S4, [[STRUCT1]] : $S1)
@@ -983,7 +983,7 @@
// CHECK: [[OUT]] : $(Builtin.Int256, Builtin.Int16, Builtin.Int32, Builtin.Int128)
-// CHECK-LABEL: sil [serialized] @_T018ignore_ptrs_calleeTfq4nxx_n : $@convention(thin) (@in S1, Builtin.Int16, Builtin.Int16) -> (Builtin.Int16, Builtin.Int16) {
+// CHECK-LABEL: sil shared [serialized] @_T018ignore_ptrs_calleeTfq4nxx_n : $@convention(thin) (@in S1, Builtin.Int16, Builtin.Int16) -> (Builtin.Int16, Builtin.Int16) {
// CHECK: bb0([[IN1:%.*]] : $*S1, [[IN2:%.*]] : $Builtin.Int16, [[IN3:%.*]] : $Builtin.Int16):
// CHECK: [[STRUCT2:%.*]] = struct $S1 ([[IN2]] : $Builtin.Int16, undef : $Builtin.Int32)
// CHECK: [[STRUCT1:%.*]] = struct $S1 ([[IN3]] : $Builtin.Int16, undef : $Builtin.Int32)
@@ -996,7 +996,7 @@
// CHECK: [[OUT:%.*]] = tuple ([[IN2]] : $Builtin.Int16, [[IN3]] : $Builtin.Int16)
// CHECK: return [[OUT]] : $(Builtin.Int16, Builtin.Int16)
-// CHECK-LABEL: sil [serialized] @_T030check_out_of_order_uses_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int32) -> () {
+// CHECK-LABEL: sil shared [serialized] @_T030check_out_of_order_uses_calleeTfq4x_n : $@convention(thin) (Builtin.Int16, Builtin.Int32) -> () {
// CHECK: bb0([[IN1:%.*]] : $Builtin.Int16, [[IN2:%.*]] : $Builtin.Int32):
// CHECK: [[STRUCT0:%.*]] = struct $S1 ([[IN1]] : $Builtin.Int16, [[IN2]] : $Builtin.Int32)
// CHECK: debug_value [[STRUCT0]]
@@ -1008,6 +1008,6 @@
// CHECK: apply [[FN2]]([[IN1]]) : $@convention(thin) (Builtin.Int16) -> ()
-// CHECK-LABEL: sil [serialized] @_T014class_callee_1Tfq4gn_n : $@convention(thin) (@guaranteed C1, Builtin.Int32) -> Builtin.Int32 {
+// CHECK-LABEL: sil shared [serialized] @_T014class_callee_1Tfq4gn_n : $@convention(thin) (@guaranteed C1, Builtin.Int32) -> Builtin.Int32 {
// CHECK: bb0({{%.*}} : $C1, [[IN:%.*]] : $Builtin.Int32):
// CHECK: return [[IN]] : $Builtin.Int32
diff --git a/test/Sanitizers/tsan-inout.swift b/test/Sanitizers/tsan-inout.swift
index 91d0314..59144c1 100644
--- a/test/Sanitizers/tsan-inout.swift
+++ b/test/Sanitizers/tsan-inout.swift
@@ -80,7 +80,7 @@
thread: { _ = globalForGlobalStructMutatingMethod.read() },
thread: { globalForGlobalStructMutatingMethod.mutate() } )
// CHECK-LABEL: Running GlobalStructMutatingMethod
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is global
var globalForGlobalStructDifferentStoredPropertiesInout = UninstrumentedStruct()
@@ -88,7 +88,7 @@
thread: { uninstrumentedTakesInout(&globalForGlobalStructDifferentStoredPropertiesInout.storedProperty1) },
thread: { uninstrumentedTakesInout(&globalForGlobalStructDifferentStoredPropertiesInout.storedProperty2) } )
// CHECK-LABEL: Running GlobalStructDifferentStoredPropertiesInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is global
var globalForGlobalStructSameStoredPropertyInout = UninstrumentedStruct()
@@ -96,7 +96,7 @@
thread: { uninstrumentedTakesInout(&globalForGlobalStructSameStoredPropertyInout.storedProperty1) },
thread: { uninstrumentedTakesInout(&globalForGlobalStructSameStoredPropertyInout.storedProperty1) } )
// CHECK-LABEL: Running GlobalStructSameStoredPropertyInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
var globalForGlobalStructSubscriptDifferentIndexesInout = UninstrumentedStruct()
@@ -104,7 +104,7 @@
thread: { uninstrumentedTakesInout(&globalForGlobalStructSubscriptDifferentIndexesInout[0]) },
thread: { uninstrumentedTakesInout(&globalForGlobalStructSubscriptDifferentIndexesInout[1]) } )
// CHECK-LABEL: Running GlobalStructSubscriptDifferentIndexes
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is global
@@ -113,7 +113,7 @@
thread: { _ = globalForGlobalStructSubscriptDifferentIndexesGetSet[0] },
thread: { globalForGlobalStructSubscriptDifferentIndexesGetSet[1] = 12 } )
// CHECK-LABEL: Running GlobalStructSubscriptDifferentIndexesGetSet
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is global
var globalForGlobalClassGeneralMethods = UninstrumentedClass()
@@ -121,21 +121,21 @@
thread: { _ = globalForGlobalClassGeneralMethods.read() },
thread: { globalForGlobalClassGeneralMethods.mutate() } )
// CHECK-LABEL: Running GlobalClassGeneralMethods
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
var globalForGlobalClassDifferentStoredPropertiesInout = UninstrumentedClass()
testRace(name: "GlobalClassDifferentStoredPropertiesInout",
thread: { uninstrumentedTakesInout(&globalForGlobalClassDifferentStoredPropertiesInout.storedProperty1) },
thread: { uninstrumentedTakesInout(&globalForGlobalClassDifferentStoredPropertiesInout.storedProperty2) } )
// CHECK-LABEL: Running GlobalClassDifferentStoredPropertiesInout
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
var globalForGlobalClassSubscriptDifferentIndexesInout = UninstrumentedClass()
testRace(name: "GlobalClassSubscriptDifferentIndexesInout",
thread: { uninstrumentedTakesInout(&globalForGlobalClassSubscriptDifferentIndexesInout[0]) },
thread: { uninstrumentedTakesInout(&globalForGlobalClassSubscriptDifferentIndexesInout[1]) } )
// CHECK-LABEL: Running GlobalClassSubscriptDifferentIndexesInout
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
var globalForGlobalClassSameStoredPropertyInout = UninstrumentedClass()
@@ -143,7 +143,7 @@
thread: { uninstrumentedTakesInout(&globalForGlobalClassSameStoredPropertyInout.storedProperty1) },
thread: { uninstrumentedTakesInout(&globalForGlobalClassSameStoredPropertyInout.storedProperty1) } )
// CHECK-LABEL: Running GlobalClassSameStoredPropertyInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is heap block
// These access a global declared in the TSanUninstrumented module
@@ -151,7 +151,7 @@
thread: { uninstrumentedTakesInout(&storedGlobalInUninstrumentedModule1) },
thread: { uninstrumentedTakesInout(&storedGlobalInUninstrumentedModule1) } )
// CHECK-LABEL: Running InoutAccessToStoredGlobalInUninstrumentedModule
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is global
// These access a global declared in the TSanUninstrumented module.
@@ -169,14 +169,14 @@
thread: { uninstrumentedTakesInout(&computedGlobalInUninstrumentedModule1) },
thread: { uninstrumentedTakesInout(&computedGlobalInUninstrumentedModule1) } )
// CHECK-LABEL: Running InoutAccessToComputedGlobalInUninstrumentedModule
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
// These access a computed global declared in the TSanUninstrumented module
testRace(name: "ReadAndWriteToComputedGlobalInUninstrumentedModule",
thread: { computedGlobalInUninstrumentedModule2 = 7 },
thread: { _ = computedGlobalInUninstrumentedModule2 } )
// CHECK-LABEL: Running ReadAndWriteToComputedGlobalInUninstrumentedModule
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
@@ -187,7 +187,7 @@
thread: { _ = globalForGlobalUninstrumentedClassStoredPropertyMutatingMethod.storedStructProperty.read() },
thread: { globalForGlobalUninstrumentedClassStoredPropertyMutatingMethod.storedStructProperty.mutate() } )
// CHECK-LABEL: Running GlobalUninstrumentedClassStoredPropertyMutatingMethod
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
// Note: TSan doesn't see a race above because it doesn't see any load on the
// read side because the getter for the class property is not instrumented.
@@ -198,7 +198,7 @@
thread: { uninstrumentedTakesInout(&globalForGlobalUninstrumentedClassStoredPropertyInout.storedStructProperty.storedProperty1) },
thread: { uninstrumentedTakesInout(&globalForGlobalUninstrumentedClassStoredPropertyInout.storedStructProperty.storedProperty2) } )
// CHECK-LABEL: Running GlobalUninstrumentedClassStoredPropertyInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is heap block
// Note: TSan sees the race above because the inout instrumentation adds an
@@ -210,7 +210,7 @@
thread: { uninstrumentedTakesInout(&globalForGlobalUninstrumentedClassComputedPropertyInout.computedStructProperty.storedProperty1) },
thread: { uninstrumentedTakesInout(&globalForGlobalUninstrumentedClassComputedPropertyInout.computedStructProperty.storedProperty1) } )
// CHECK-LABEL: Running GlobalUninstrumentedClassComputedPropertyInout
-// CHECK-NO: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
// In the above the write in instrumented code is to the value buffer allocated
// at the call site so there is no data race if the getter and setters themselves
@@ -223,7 +223,7 @@
thread: { _ = globalForGlobalInstrumentedClassStoredPropertyMutatingMethod.storedStructProperty.read() },
thread: { globalForGlobalInstrumentedClassStoredPropertyMutatingMethod.storedStructProperty.mutate() } )
// CHECK-LABEL: Running GlobalInstrumentedClassStoredPropertyMutatingMethod
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is heap block
//
// TSan does see this above race because the getter and materializeForSet is instrumented
@@ -254,7 +254,7 @@
thread: { l.mutate() } )
}
// CHECK-LABEL: Running CapturedLocalStructMutatingMethod
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is heap block
@@ -265,7 +265,7 @@
thread: { uninstrumentedTakesInout(&l.storedProperty2) } )
}
// CHECK-LABEL: Running CapturedLocalStructDifferentStoredPropertiesInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is heap block
@@ -276,7 +276,7 @@
thread: { l.mutate() } )
}
// CHECK-LABEL: Running CapturedLocalClassGeneralMethods
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
func runCapturedLocalDifferentStoredPropertiesInout() {
@@ -286,7 +286,7 @@
thread: { uninstrumentedTakesInout(&l.storedProperty2) } )
}
// CHECK-LABEL: Running CapturedLocalClassDifferentStoredPropertiesInout
-// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: {{.*}} race
func runCapturedLocalSameStoredPropertyInout() {
let l = UninstrumentedClass()
@@ -295,7 +295,7 @@
thread: { uninstrumentedTakesInout(&l.storedProperty1) } )
}
// CHECK-LABEL: Running CapturedLocalClassSameStoredPropertyInout
-// CHECK: ThreadSanitizer: data race
+// CHECK: ThreadSanitizer: Swift access race
// CHECK: Location is heap block
runLocalTests()
diff --git a/test/Sema/Inputs/rdar32973206_a.swift b/test/Sema/Inputs/rdar32973206_a.swift
new file mode 100644
index 0000000..351b865
--- /dev/null
+++ b/test/Sema/Inputs/rdar32973206_a.swift
@@ -0,0 +1,8 @@
+public class A {
+}
+
+public class B : A {
+}
+
+public class C : B {
+}
diff --git a/test/Sema/Inputs/rdar32973206_b.swift b/test/Sema/Inputs/rdar32973206_b.swift
new file mode 100644
index 0000000..a437a9c
--- /dev/null
+++ b/test/Sema/Inputs/rdar32973206_b.swift
@@ -0,0 +1,5 @@
+import rdar32973206_a
+
+public extension A {
+ public class var foo: Int { get { return 42 } }
+}
diff --git a/test/Sema/Inputs/rdar32973206_c.swift b/test/Sema/Inputs/rdar32973206_c.swift
new file mode 100644
index 0000000..ab17e1c
--- /dev/null
+++ b/test/Sema/Inputs/rdar32973206_c.swift
@@ -0,0 +1,5 @@
+import rdar32973206_a
+
+public extension B {
+ public class var foo: Int { get { return 0 } }
+}
diff --git a/test/Sema/subclass_property_import.swift b/test/Sema/subclass_property_import.swift
new file mode 100644
index 0000000..42b6563
--- /dev/null
+++ b/test/Sema/subclass_property_import.swift
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: %target-swift-frontend -emit-module -o %t/rdar32973206_a.swiftmodule %S/Inputs/rdar32973206_a.swift
+// RUN: %target-swift-frontend -I %t -emit-module -o %t/rdar32973206_b.swiftmodule %S/Inputs/rdar32973206_b.swift
+// RUN: %target-swift-frontend -I %t -emit-module -o %t/rdar32973206_c.swiftmodule %S/Inputs/rdar32973206_c.swift
+// RUN: %target-swift-frontend -I %t -emit-sil -verify %s | %FileCheck %s
+
+import rdar32973206_a
+import rdar32973206_b
+import rdar32973206_c
+
+// CHECK: A.foo
+let _ = A.foo
+
+// CHECK: B.foo
+let _ = B.foo
+
+// CHECK: B.foo
+let _ = C.foo
diff --git a/test/Serialization/Recovery/Inputs/custom-modules/ProtocolInheritance.h b/test/Serialization/Recovery/Inputs/custom-modules/ProtocolInheritance.h
new file mode 100644
index 0000000..f6700ae
--- /dev/null
+++ b/test/Serialization/Recovery/Inputs/custom-modules/ProtocolInheritance.h
@@ -0,0 +1,42 @@
+@protocol Order2_ConsistentBaseProto
+- (void)consistent;
+@end
+
+@protocol Order4_ConsistentBaseProto
+- (void)consistent;
+@end
+
+@protocol Order1_FickleBaseProto
+- (void)fickle;
+@optional
+- (void)extraFickle;
+@end
+
+@protocol Order3_FickleBaseProto
+- (void)fickle;
+@optional
+- (void)extraFickle;
+@end
+
+@protocol Order5_FickleBaseProto
+- (void)fickle;
+@optional
+- (void)extraFickle;
+@end
+
+// The actual order here is determined by the protocol names.
+#if EXTRA_PROTOCOL_FIRST
+@protocol SubProto <Order1_FickleBaseProto, Order2_ConsistentBaseProto, Order4_ConsistentBaseProto>
+@end
+#elif EXTRA_PROTOCOL_MIDDLE
+@protocol SubProto <Order2_ConsistentBaseProto, Order3_FickleBaseProto, Order4_ConsistentBaseProto>
+@end
+#elif EXTRA_PROTOCOL_LAST
+@protocol SubProto <Order2_ConsistentBaseProto, Order4_ConsistentBaseProto, Order5_FickleBaseProto>
+@end
+#elif NO_EXTRA_PROTOCOLS
+@protocol SubProto <Order2_ConsistentBaseProto, Order4_ConsistentBaseProto>
+@end
+#else
+# error "Missing -D flag"
+#endif
diff --git a/test/Serialization/Recovery/Inputs/custom-modules/module.modulemap b/test/Serialization/Recovery/Inputs/custom-modules/module.modulemap
index c7e6756..8afa992 100644
--- a/test/Serialization/Recovery/Inputs/custom-modules/module.modulemap
+++ b/test/Serialization/Recovery/Inputs/custom-modules/module.modulemap
@@ -1,4 +1,5 @@
module Overrides { header "Overrides.h" }
+module ProtocolInheritance { header "ProtocolInheritance.h" }
module Typedefs { header "Typedefs.h" }
module TypeRemovalObjC { header "TypeRemovalObjC.h" }
module Types { header "Types.h" }
diff --git a/test/Serialization/Recovery/protocol-inheritance.swift b/test/Serialization/Recovery/protocol-inheritance.swift
new file mode 100644
index 0000000..a9419bf
--- /dev/null
+++ b/test/Serialization/Recovery/protocol-inheritance.swift
@@ -0,0 +1,75 @@
+// RUN: %empty-directory(%t)
+
+// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules -Xcc -DNO_EXTRA_PROTOCOLS %s
+// RUN: %target-swift-frontend -typecheck -DTEST -Xcc -DNO_EXTRA_PROTOCOLS -I %t -I %S/Inputs/custom-modules %s
+// RUN: %target-swift-frontend -emit-ir -DTEST -Xcc -DEXTRA_PROTOCOL_FIRST -I %t -I %S/Inputs/custom-modules %s -o /dev/null
+
+// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules -Xcc -DEXTRA_PROTOCOL_FIRST %s
+// RUN: %target-swift-frontend -typecheck -DTEST -Xcc -DEXTRA_PROTOCOL_FIRST -I %t -I %S/Inputs/custom-modules %s
+// RUN: %target-swift-frontend -emit-ir -DTEST -Xcc -DNO_EXTRA_PROTOCOLS -I %t -I %S/Inputs/custom-modules %s -o /dev/null
+
+
+// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules -Xcc -DNO_EXTRA_PROTOCOLS %s
+// RUN: %target-swift-frontend -typecheck -DTEST -Xcc -DNO_EXTRA_PROTOCOLS -I %t -I %S/Inputs/custom-modules %s
+// RUN: %target-swift-frontend -emit-ir -DTEST -Xcc -DEXTRA_PROTOCOL_MIDDLE -I %t -I %S/Inputs/custom-modules %s -o /dev/null
+
+// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules -Xcc -DEXTRA_PROTOCOL_MIDDLE %s
+// RUN: %target-swift-frontend -typecheck -DTEST -Xcc -DEXTRA_PROTOCOL_MIDDLE -I %t -I %S/Inputs/custom-modules %s
+// RUN: %target-swift-frontend -emit-ir -DTEST -Xcc -DNO_EXTRA_PROTOCOLS -I %t -I %S/Inputs/custom-modules %s -o /dev/null
+
+
+// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules -Xcc -DNO_EXTRA_PROTOCOLS %s
+// RUN: %target-swift-frontend -typecheck -DTEST -Xcc -DNO_EXTRA_PROTOCOLS -I %t -I %S/Inputs/custom-modules %s
+// RUN: %target-swift-frontend -emit-ir -DTEST -Xcc -DEXTRA_PROTOCOL_LAST -I %t -I %S/Inputs/custom-modules %s -o /dev/null
+
+// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules -Xcc -DEXTRA_PROTOCOL_LAST %s
+// RUN: %target-swift-frontend -typecheck -DTEST -Xcc -DEXTRA_PROTOCOL_LAST -I %t -I %S/Inputs/custom-modules %s
+// RUN: %target-swift-frontend -emit-ir -DTEST -Xcc -DNO_EXTRA_PROTOCOLS -I %t -I %S/Inputs/custom-modules %s -o /dev/null
+
+
+// REQUIRES: objc_interop
+
+#if TEST
+
+import Lib
+import ProtocolInheritance
+
+func useSubProto<T: SubProto>(_: T) {}
+func useConsistentProto<T: Order2_ConsistentBaseProto>(_: T) {}
+func useFickleProto<T: Order1_FickleBaseProto>(_: T) {}
+
+func test(obj: Impl) {
+ useConsistentProto(obj)
+ useFickleProto(obj)
+ useSubProto(obj)
+}
+
+protocol ForceDeserializationProto: SubProto {}
+extension Impl: ForceDeserializationProto {}
+
+func test(obj: PartialImpl) {
+ useConsistentProto(obj)
+ useSubProto(obj)
+}
+
+extension PartialImpl: ForceDeserializationProto {}
+
+#else // TEST
+
+import ProtocolInheritance
+
+open class Impl: SubProto {
+ public func consistent() {}
+}
+
+extension Impl: Order1_FickleBaseProto, Order3_FickleBaseProto, Order5_FickleBaseProto {
+ public func fickle() {}
+}
+
+open class PartialImpl: SubProto {
+ public func consistent() {}
+ public func fickle() {}
+}
+
+
+#endif // TEST
diff --git a/test/TBD/global.swift b/test/TBD/global.swift
index 183da4e..af400bf 100644
--- a/test/TBD/global.swift
+++ b/test/TBD/global.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
public let publicLet: Int = 0
internal let internalLet: Int = 0
diff --git a/test/TBD/protocol.swift b/test/TBD/protocol.swift
index 72db323..e502486 100644
--- a/test/TBD/protocol.swift
+++ b/test/TBD/protocol.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
public protocol Public {
func publicMethod()
diff --git a/test/TBD/struct.swift b/test/TBD/struct.swift
index d49156a..9bd42bb 100644
--- a/test/TBD/struct.swift
+++ b/test/TBD/struct.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
public struct PublicNothing {}
diff --git a/test/decl/protocol/special/JSExport.swift b/test/decl/protocol/special/JSExport.swift
new file mode 100644
index 0000000..cde8cef
--- /dev/null
+++ b/test/decl/protocol/special/JSExport.swift
@@ -0,0 +1,21 @@
+// RUN: %target-typecheck-verify-swift
+
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -emit-ir | %FileCheck %s
+
+// REQUIRES: objc_interop
+import Foundation
+
+@objc protocol JSExport { }
+
+@objc protocol RootJSExport : JSExport { }
+
+// CHECK: @_PROTOCOL_PROTOCOLS__TtP8JSExport4Sub1_ = private constant{{.*}}_PROTOCOL__TtP8JSExport12RootJSExport_{{.*}}_PROTOCOL__TtP8JSExport8JSExport_
+@objc protocol Sub1 : JSExport, RootJSExport { }
+
+// CHECK: @_PROTOCOL_PROTOCOLS__TtP8JSExport4Sub2_{{.*}}_PROTOCOL__TtP8JSExport4Sub1_{{.*}}_PROTOCOL__TtP8JSExport8JSExport_
+@objc protocol Sub2 : Sub1, JSExport { }
+
+// CHECK: @_PROTOCOL_PROTOCOLS__TtP8JSExport4Sub3_ = private constant{{.*}}@_PROTOCOL__TtP8JSExport4Sub2_
+@objc protocol Sub3 : Sub2 { }
+
+protocol ReexportJSExport : RootJSExport, JSExport { }
diff --git a/test/decl/protocol/special/coding/class_codable_default_initializer.swift b/test/decl/protocol/special/coding/class_codable_default_initializer.swift
new file mode 100644
index 0000000..ae8f01b
--- /dev/null
+++ b/test/decl/protocol/special/coding/class_codable_default_initializer.swift
@@ -0,0 +1,49 @@
+// RUN: %target-typecheck-verify-swift -verify-ignore-unknown
+
+// A class with no initializers (which has non-initialized properties so a
+// default constructor can be synthesized) should produce an error.
+class NoInitializers { // expected-error {{class 'NoInitializers' has no initializers}}
+// expected-note@-1 {{did you mean 'deinit'?}}
+ var x: Double // expected-note {{stored property 'x' without initial value prevents synthesized initializers}}
+
+ func foo() {
+ // The class should not receive a default constructor.
+ let _ = NoInitializers.init() // expected-error {{type 'NoInitializers' has no member 'init'}}
+ }
+}
+
+// A similar class with Codable properties adopting Codable should get a
+// synthesized init(from:), and thus not warn.
+class CodableNoExplicitInitializers : Codable {
+ var x: Double
+
+ func foo() {
+ // The class should receive a synthesized init(from:) and encode(to:)
+ let _ = CodableNoExplicitInitializers.init(from:)
+ let _ = CodableNoExplicitInitializers.encode(to:)
+
+ // It should not, however, receive a default constructor.
+ let _ = CodableNoExplicitInitializers.init() // expected-error {{missing argument for parameter 'from' in call}}
+ }
+}
+
+// A class with all initialized properties should receive a default constructor.
+class DefaultConstructed {
+ var x: Double = .pi
+
+ func foo() {
+ let _ = DefaultConstructed.init()
+ }
+}
+
+// A class with all initialized, Codable properties adopting Codable should get
+// the default constructor, along with a synthesized init(from:).
+class CodableDefaultConstructed : Codable {
+ var x: Double = .pi
+
+ func foo() {
+ let _ = CodableDefaultConstructed.init()
+ let _ = CodableDefaultConstructed.init(from:)
+ let _ = CodableDefaultConstructed.encode(to:)
+ }
+}
diff --git a/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift b/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift
index 3268dbb..c1320ca 100644
--- a/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift
+++ b/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift
@@ -8,12 +8,12 @@
var c: Nested = Nested()
// CHECK: error: type 'C1' does not conform to protocol 'Decodable'
- // CHECK: note: cannot automatically synthesize 'Decodable' because 'C1.Nested' does not conform to 'Decodable'
// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+ // CHECK: note: cannot automatically synthesize 'Decodable' because 'C1.Nested' does not conform to 'Decodable'
// CHECK: error: type 'C1' does not conform to protocol 'Encodable'
- // CHECK: note: cannot automatically synthesize 'Encodable' because 'C1.Nested' does not conform to 'Encodable'
// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
+ // CHECK: note: cannot automatically synthesize 'Encodable' because 'C1.Nested' does not conform to 'Encodable'
}
// Codable class with non-enum CodingKeys.
@@ -30,12 +30,12 @@
}
// CHECK: error: type 'C2' does not conform to protocol 'Decodable'
- // CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' is not an enum
// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+ // CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' is not an enum
// CHECK: error: type 'C2' does not conform to protocol 'Encodable'
- // CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' is not an enum
// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
+ // CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' is not an enum
}
// Codable class with CodingKeys not conforming to CodingKey.
@@ -51,12 +51,12 @@
}
// CHECK: error: type 'C3' does not conform to protocol 'Decodable'
- // CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' does not conform to CodingKey
// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+ // CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' does not conform to CodingKey
// CHECK: error: type 'C3' does not conform to protocol 'Encodable'
- // CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' does not conform to CodingKey
// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
+ // CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' does not conform to CodingKey
}
// Codable class with extraneous CodingKeys
@@ -75,16 +75,16 @@
}
// CHECK: error: type 'C4' does not conform to protocol 'Decodable'
+ // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
// CHECK: note: CodingKey case 'a2' does not match any stored properties
// CHECK: note: CodingKey case 'b2' does not match any stored properties
// CHECK: note: CodingKey case 'c2' does not match any stored properties
- // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
// CHECK: error: type 'C4' does not conform to protocol 'Encodable'
+ // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
// CHECK: note: CodingKey case 'a2' does not match any stored properties
// CHECK: note: CodingKey case 'b2' does not match any stored properties
// CHECK: note: CodingKey case 'c2' does not match any stored properties
- // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
}
// Codable class with non-decoded property (which has no default value).
@@ -98,12 +98,12 @@
case c
}
+ // CHECK: error: type 'C5' does not conform to protocol 'Decodable'
+ // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+ // CHECK: note: cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value
+
// CHECK: error: class 'C5' has no initializers
// CHECK: note: stored property 'b' without initial value prevents synthesized initializers
-
- // CHECK: error: type 'C5' does not conform to protocol 'Decodable'
- // CHECK: note: cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value
- // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
}
// Codable class with non-decoded property (which has no default value).
@@ -122,8 +122,8 @@
}
// CHECK: error: type 'C6' does not conform to protocol 'Decodable'
- // CHECK: note: cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value
// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+ // CHECK: note: cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value
}
// Classes cannot yet synthesize Encodable or Decodable in extensions.
diff --git a/test/decl/protocol/special/coding/class_codable_inheritance_diagnostics.swift b/test/decl/protocol/special/coding/class_codable_inheritance_diagnostics.swift
new file mode 100644
index 0000000..d5d6164
--- /dev/null
+++ b/test/decl/protocol/special/coding/class_codable_inheritance_diagnostics.swift
@@ -0,0 +1,95 @@
+// RUN: %target-typecheck-verify-swift -verify-ignore-unknown
+
+// Non-Decodable superclasses of synthesized Decodable classes must implement
+// init().
+class NonDecodableSuper { // expected-note {{cannot automatically synthesize 'init(from:)' because superclass does not have a callable 'init()'}}
+ init(_: Int) {}
+}
+
+class NonDecodableSub : NonDecodableSuper, Decodable { // expected-error {{type 'NonDecodableSub' does not conform to protocol 'Decodable'}}
+}
+
+// Non-Decodable superclasses of synthesized Decodable classes must have
+// designated init()'s.
+class NonDesignatedNonDecodableSuper {
+ convenience init() { // expected-note {{cannot automatically synthesize 'init(from:)' because implementation would need to call 'init()', which is not designated}}
+ self.init(42)
+ }
+
+ init(_: Int) {}
+}
+
+class NonDesignatedNonDecodableSub : NonDesignatedNonDecodableSuper, Decodable { // expected-error {{type 'NonDesignatedNonDecodableSub' does not conform to protocol 'Decodable'}}
+}
+
+// Non-Decodable superclasses of synthesized Decodable classes must have an
+// accessible init().
+class InaccessibleNonDecodableSuper {
+ private init() {} // expected-note {{cannot automatically synthesize 'init(from:)' because implementation would need to call 'init()', which is inaccessible due to 'private' protection level}}
+}
+
+class InaccessibleNonDecodableSub : InaccessibleNonDecodableSuper, Decodable { // expected-error {{type 'InaccessibleNonDecodableSub' does not conform to protocol 'Decodable'}}
+}
+
+// Non-Decodable superclasses of synthesized Decodable classes must have a
+// non-failable init().
+class FailableNonDecodableSuper {
+ init?() {} // expected-note {{cannot automatically synthesize 'init(from:)' because implementation would need to call 'init()', which is failable}}
+}
+
+class FailableNonDecodableSub : FailableNonDecodableSuper, Decodable { // expected-error {{type 'FailableNonDecodableSub' does not conform to protocol 'Decodable'}}
+}
+
+// Subclasses of classes whose Decodable synthesis fails should not inherit
+// conformance.
+class FailedSynthesisDecodableSuper : Decodable { // expected-error {{type 'FailedSynthesisDecodableSuper' does not conform to protocol 'Decodable'}}
+ enum CodingKeys : String, CodingKey {
+ case nonexistent // expected-note {{CodingKey case 'nonexistent' does not match any stored properties}}
+ }
+}
+
+class FailedSynthesisDecodableSub : FailedSynthesisDecodableSuper { // expected-note {{did you mean 'init'?}}
+ func foo() {
+ // Decodable should fail to synthesis or be inherited.
+ let _ = FailedSynthesisDecodableSub.init(from:) // expected-error {{type 'FailedSynthesisDecodableSub' has no member 'init(from:)'}}
+ }
+}
+
+// Subclasses of Decodable classes which can't inherit their initializers should
+// produce diagnostics.
+class DecodableSuper : Decodable {
+ var value = 5
+}
+
+class DecodableSubWithoutInitialValue : DecodableSuper { // expected-error {{class 'DecodableSubWithoutInitialValue' has no initializers}}
+ // expected-note@-1 {{did you mean to override 'init(from:)'?}}
+ var value2: Int // expected-note {{stored property 'value2' without initial value prevents synthesized initializers}}
+}
+
+class DecodableSubWithInitialValue : DecodableSuper {
+ var value2 = 10
+}
+
+// Subclasses of Codable classes which can't inherit their initializers should
+// produce diagnostics.
+class CodableSuper : Codable {
+ var value = 5
+}
+
+class CodableSubWithoutInitialValue : CodableSuper { // expected-error {{class 'CodableSubWithoutInitialValue' has no initializers}}
+ // expected-note@-1 {{did you mean to override 'init(from:)' and 'encode(to:)'?}}
+ var value2: Int // expected-note {{stored property 'value2' without initial value prevents synthesized initializers}}
+}
+
+// We should only mention encode(to:) in the diagnostic if the subclass does not
+// override it.
+class EncodableSubWithoutInitialValue : CodableSuper { // expected-error {{class 'EncodableSubWithoutInitialValue' has no initializers}}
+ // expected-note@-1 {{did you mean to override 'init(from:)'?}}
+ var value2: Int // expected-note {{stored property 'value2' without initial value prevents synthesized initializers}}
+
+ override func encode(to: Encoder) throws {}
+}
+
+class CodableSubWithInitialValue : CodableSuper {
+ var value2 = 10
+}
diff --git a/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift b/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift
index c456912..2a916d7 100644
--- a/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift
+++ b/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift
@@ -6,14 +6,6 @@
var a: String = ""
var b: Int = 0
var c: Nested = Nested()
-
- // CHECK: error: type 'S1' does not conform to protocol 'Decodable'
- // CHECK: note: cannot automatically synthesize 'Decodable' because 'S1.Nested' does not conform to 'Decodable'
- // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-
- // CHECK: error: type 'S1' does not conform to protocol 'Encodable'
- // CHECK: note: cannot automatically synthesize 'Encodable' because 'S1.Nested' does not conform to 'Encodable'
- // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
}
// Codable struct with non-enum CodingKeys.
@@ -28,14 +20,6 @@
init?(stringValue: String) {}
init?(intValue: Int) {}
}
-
- // CHECK: error: type 'S2' does not conform to protocol 'Decodable'
- // CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' is not an enum
- // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-
- // CHECK: error: type 'S2' does not conform to protocol 'Encodable'
- // CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' is not an enum
- // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
}
// Codable struct with CodingKeys not conforming to CodingKey.
@@ -49,14 +33,6 @@
case b
case c
}
-
- // CHECK: error: type 'S3' does not conform to protocol 'Decodable'
- // CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' does not conform to CodingKey
- // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-
- // CHECK: error: type 'S3' does not conform to protocol 'Encodable'
- // CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' does not conform to CodingKey
- // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
}
// Codable struct with extraneous CodingKeys
@@ -73,18 +49,6 @@
case c
case c2
}
-
- // CHECK: error: type 'S4' does not conform to protocol 'Decodable'
- // CHECK: note: CodingKey case 'a2' does not match any stored properties
- // CHECK: note: CodingKey case 'b2' does not match any stored properties
- // CHECK: note: CodingKey case 'c2' does not match any stored properties
- // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-
- // CHECK: error: type 'S4' does not conform to protocol 'Encodable'
- // CHECK: note: CodingKey case 'a2' does not match any stored properties
- // CHECK: note: CodingKey case 'b2' does not match any stored properties
- // CHECK: note: CodingKey case 'c2' does not match any stored properties
- // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
}
// Codable struct with non-decoded property (which has no default value).
@@ -97,14 +61,60 @@
case a
case c
}
-
- // CHECK: error: type 'S5' does not conform to protocol 'Decodable'
- // CHECK: note: cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value
- // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
}
// Structs cannot yet synthesize Encodable or Decodable in extensions.
struct S6 {}
extension S6 : Codable {}
+
+// Decodable diagnostics are output first here {
+
+// CHECK: error: type 'S1' does not conform to protocol 'Decodable'
+// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+// CHECK: note: cannot automatically synthesize 'Decodable' because 'S1.Nested' does not conform to 'Decodable'
+
+// CHECK: error: type 'S2' does not conform to protocol 'Decodable'
+// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+// CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' is not an enum
+
+// CHECK: error: type 'S3' does not conform to protocol 'Decodable'
+// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+// CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' does not conform to CodingKey
+
+// CHECK: error: type 'S4' does not conform to protocol 'Decodable'
+// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+// CHECK: note: CodingKey case 'a2' does not match any stored properties
+// CHECK: note: CodingKey case 'b2' does not match any stored properties
+// CHECK: note: CodingKey case 'c2' does not match any stored properties
+
+// CHECK: error: type 'S5' does not conform to protocol 'Decodable'
+// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
+// CHECK: note: cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value
+
// CHECK: error: implementation of 'Decodable' cannot be automatically synthesized in an extension yet
+
+// }
+
+// Encodable {
+
+// CHECK: error: type 'S1' does not conform to protocol 'Encodable'
+// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
+// CHECK: note: cannot automatically synthesize 'Encodable' because 'S1.Nested' does not conform to 'Encodable'
+
+// CHECK: error: type 'S2' does not conform to protocol 'Encodable'
+// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
+// CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' is not an enum
+
+// CHECK: error: type 'S3' does not conform to protocol 'Encodable'
+// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
+// CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' does not conform to CodingKey
+
+// CHECK: error: type 'S4' does not conform to protocol 'Encodable'
+// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
+// CHECK: note: CodingKey case 'a2' does not match any stored properties
+// CHECK: note: CodingKey case 'b2' does not match any stored properties
+// CHECK: note: CodingKey case 'c2' does not match any stored properties
+
// CHECK: error: implementation of 'Encodable' cannot be automatically synthesized in an extension yet
+
+// }
diff --git a/test/decl/protocol/special/coding/struct_codable_memberwise_initializer.swift b/test/decl/protocol/special/coding/struct_codable_memberwise_initializer.swift
new file mode 100644
index 0000000..7d4d166
--- /dev/null
+++ b/test/decl/protocol/special/coding/struct_codable_memberwise_initializer.swift
@@ -0,0 +1,55 @@
+// RUN: %target-typecheck-verify-swift -verify-ignore-unknown
+
+// Structs with no initializers should get a memberwise initializer.
+struct NoInitializers {
+ var x: Double // need not have an initial value
+
+ func foo() {
+ // The struct should receive a memberwise initializer.
+ let _ = NoInitializers.init(x:)
+ }
+}
+
+// A similar struct with Codable properties adopting Codable should get a
+// synthesized init(from:), along with the memberwise initializer.
+struct CodableNoExplicitInitializers : Codable {
+ var x: Double
+
+ func foo() {
+ // The struct should receive a synthesized init(from:) and encode(to:).
+ let _ = CodableNoExplicitInitializers.init(from:)
+ let _ = CodableNoExplicitInitializers.encode(to:)
+
+ // It should still receive a memberwise initializer.
+ let _ = CodableNoExplicitInitializers.init(x:)
+ }
+}
+
+// The same should hold for structs whose members all have initial values.
+struct InitialValueNoInitializers {
+ var x: Double = .pi
+
+ func foo() {
+ // The struct should receive a memberwise initializer.
+ let _ = InitialValueNoInitializers.init(x:)
+
+ // The struct should receive a no-argument initializer.
+ let _ = InitialValueNoInitializers.init()
+ }
+}
+
+struct InitialValueCodableNoExplicitInitializers : Codable {
+ var x: Double = .pi
+
+ func foo() {
+ // The struct should receive a synthesized init(from:) and encode(to:).
+ let _ = InitialValueCodableNoExplicitInitializers.init(from:)
+ let _ = InitialValueCodableNoExplicitInitializers.encode(to:)
+
+ // It should still receive a memberwise initializer.
+ let _ = InitialValueCodableNoExplicitInitializers.init(x:)
+
+ // It should still receive a no-argument initializer.
+ let _ = InitialValueCodableNoExplicitInitializers.init()
+ }
+}
diff --git a/test/stdlib/AppKit_Swift4.swift b/test/stdlib/AppKit_Swift4.swift
index 276e1cd..78406fd 100644
--- a/test/stdlib/AppKit_Swift4.swift
+++ b/test/stdlib/AppKit_Swift4.swift
@@ -94,4 +94,15 @@
expectEqual(bitmapImage.colorAt(x: 2, y: 2), blue)
}
+AppKitTests.test("NSColor.Literals") {
+ if #available(macOS 10.12, *) {
+ // Color literal in the extended sRGB color space.
+ let c1 = #colorLiteral(red: 1.358, green: -0.074, blue: -0.012, alpha: 1.0)
+
+ var printedC1 = ""
+ print(c1, to: &printedC1)
+ expectTrue(printedC1.contains("extended"))
+ }
+}
+
runAllTests()
diff --git a/test/stdlib/Inputs/FoundationBridge/FoundationBridge.h b/test/stdlib/Inputs/FoundationBridge/FoundationBridge.h
index c54ef9a..f114a4d 100644
--- a/test/stdlib/Inputs/FoundationBridge/FoundationBridge.h
+++ b/test/stdlib/Inputs/FoundationBridge/FoundationBridge.h
@@ -69,4 +69,10 @@
- (BOOL)verifyAutoupdatingLocale:(NSLocale *)locale;
@end
+#pragma mark - NSNumber verification
+
+@interface NumberBridgingTester : NSObject
+- (BOOL)verifyKeysInRange:(NSRange)range existInDictionary:(NSDictionary *)dictionary;
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/test/stdlib/Inputs/FoundationBridge/FoundationBridge.m b/test/stdlib/Inputs/FoundationBridge/FoundationBridge.m
index 8748f7f..e24e8bd 100644
--- a/test/stdlib/Inputs/FoundationBridge/FoundationBridge.m
+++ b/test/stdlib/Inputs/FoundationBridge/FoundationBridge.m
@@ -264,4 +264,16 @@
@end
+@implementation NumberBridgingTester
+- (BOOL)verifyKeysInRange:(NSRange)range existInDictionary:(NSDictionary *)dictionary {
+ for (NSUInteger i = 0; i < range.length; i += 1) {
+ if (!dictionary[@(range.location + i)]) {
+ return NO;
+ }
+ }
+
+ return YES;
+}
+
+@end
diff --git a/test/stdlib/Integers.swift.gyb b/test/stdlib/Integers.swift.gyb
index 9729be6..9cff2e9 100644
--- a/test/stdlib/Integers.swift.gyb
+++ b/test/stdlib/Integers.swift.gyb
@@ -29,18 +29,7 @@
// print(message())
}
-extension FixedWidthInteger {
- @discardableResult
- // @_transparent
- public mutating func replaceUWord(_ n: Int, with newBits: UInt) -> Bool {
- let flippedBits = _word(at: n) ^ newBits
- self ^= Self(_truncatingBits: flippedBits) << (${word_bits} * n)
- if _word(at: n) != newBits {
- _log("###### overflow replacing word \(n) with \(newBits.hex)")
- }
- return _word(at: n) == newBits
- }
-
+extension FixedWidthInteger where Words : Collection {
/// a hex representation of every bit in the number
func hexBits(_ bitWidth: Int) -> String {
let hexDigits: [Unicode.Scalar] = [
@@ -54,12 +43,11 @@
if nibbles % 4 == 0 && nibbles != 0 {
result.insert("_", at: result.startIndex)
}
- let lowUWord = x._word(at: 0)
+ let lowUWord = x.words.first ?? 0
result.insert(
hexDigits[Int(lowUWord._value) & 0xF],
at: result.startIndex
)
- x.replaceUWord(0, with: lowUWord & ~0xF)
x /= 16
nibbles += 1
}
@@ -84,7 +72,7 @@
stackTrace: SourceLocStack = SourceLocStack(),
showFrame: Bool = true,
file: String = #file, line: UInt = #line
-) {
+) where T.Words : Collection {
if expected != actual {
expectationFailure(
"expected: \(String(reflecting: expected))"
@@ -493,26 +481,45 @@
expectEqual(32, Int32.bitWidth)
}
-tests.test("word") {
- let x = UDWord(Int.max)
- expectEqual(Int.max._lowUWord, x._word(at: 0))
- expectEqual(0, x._word(at: 1))
-
- let y = DWord(Int.min)
- expectEqual(Int.min._lowUWord, y._word(at: 0))
- expectEqual(~0, y._word(at: 1))
-
- let z = UInt(~Int.min) + 1
- expectEqual(Int.min._lowUWord, z._word(at: 0))
- expectEqual(0, z._word(at: 1))
-}
-
tests.test("words") {
+ expectEqualSequence([UInt.max], UInt.max.words)
+ expectEqualSequence([0xFF as UInt], UInt8.max.words)
+ expectEqualSequence([0xFFFF as UInt], UInt16.max.words)
+ expectEqualSequence([0xFFFFFFFF as UInt], UInt32.max.words)
+
+ expectEqualSequence([0 as UInt], UInt.min.words)
+ expectEqualSequence([0 as UInt], UInt8.min.words)
+ expectEqualSequence([0 as UInt], UInt16.min.words)
+ expectEqualSequence([0 as UInt], UInt32.min.words)
+
+ expectEqualSequence([UInt.max >> 1], Int.max.words)
+ expectEqualSequence([0x7F as UInt], Int8.max.words)
+ expectEqualSequence([0x7FFF as UInt], Int16.max.words)
+ expectEqualSequence([0x7FFFFFFF as UInt], Int32.max.words)
+
+ expectEqualSequence([UInt.max << (Int.bitWidth - 1)], Int.min.words)
+ expectEqualSequence([UInt.max << 7], Int8.min.words)
+ expectEqualSequence([UInt.max << 15], Int16.min.words)
+ expectEqualSequence([UInt.max << 31], Int32.min.words)
+
expectEqualSequence([UInt.max], (-1 as Int).words)
expectEqualSequence([UInt.max], (-1 as Int8).words)
expectEqualSequence([UInt.max], (-1 as Int16).words)
expectEqualSequence([UInt.max], (-1 as Int32).words)
+
+% if int(WORD_BITS) == 64:
+ expectEqualSequence([UInt.max], UInt64.max.words)
+ expectEqualSequence([0 as UInt], UInt64.min.words)
+ expectEqualSequence([UInt.max >> 1], Int64.max.words)
+ expectEqualSequence([(1 as UInt) << 63], Int64.min.words)
expectEqualSequence([UInt.max], (-1 as Int64).words)
+% else:
+ expectEqualSequence([UInt.max, UInt.max], Int64.max.words)
+ expectEqualSequence([0 as UInt, 0], UInt64.min.words)
+ expectEqualSequence([UInt.max, UInt.max >> 1], Int64.max.words)
+ expectEqualSequence([0 as UInt, 1 << 31], Int64.min.words)
+ expectEqualSequence([UInt.max, UInt.max], (-1 as Int64).words)
+% end
expectEqualSequence([1], 1.words)
expectEqualSequence([0], 0.words)
diff --git a/test/stdlib/Intents.swift b/test/stdlib/Intents.swift
index a34ece1..e73b85e 100644
--- a/test/stdlib/Intents.swift
+++ b/test/stdlib/Intents.swift
@@ -41,6 +41,17 @@
expectUnreachable()
}
}
+
+ IntentsTestSuite.test("INSetProfileInCarIntent/defaultProfile availability/\(swiftVersion)") {
+ func f(profile: INSetProfileInCarIntent) {
+ var isDefaultProfile = profile.isDefaultProfile
+ expectType(Bool?.self, &isDefaultProfile)
+#if !swift(>=4)
+ var defaultProfile = profile.defaultProfile
+ expectType(Int?.self, &defaultProfile)
+#endif
+ }
+ }
}
#endif
diff --git a/test/stdlib/TestNSNumberBridging.swift b/test/stdlib/TestNSNumberBridging.swift
index 27b04fc..f5c4685 100644
--- a/test/stdlib/TestNSNumberBridging.swift
+++ b/test/stdlib/TestNSNumberBridging.swift
@@ -9,14 +9,20 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
-// RUN: %target-run-simple-swift
+//
+// RUN: %empty-directory(%t)
+//
+// RUN: %target-clang %S/Inputs/FoundationBridge/FoundationBridge.m -c -o %t/FoundationBridgeObjC.o -g
+// RUN: %target-build-swift %s -I %S/Inputs/FoundationBridge/ -Xlinker %t/FoundationBridgeObjC.o -o %t/TestNSNumberBridging
+//
+// RUN: %target-run %t/TestNSNumberBridging
// REQUIRES: executable_test
// REQUIRES: objc_interop
-
import StdlibUnittest
import Foundation
import CoreGraphics
+import FoundationBridgeObjC
extension Float {
init?(reasonably value: Float) {
@@ -873,6 +879,42 @@
}
}
+func testNSNumberBridgeAnyHashable() {
+ var dict = [AnyHashable : Any]()
+ for i in -Int(UInt8.min) ... Int(UInt8.max) {
+ dict[i] = "\(i)"
+ }
+
+ // When bridging a dictionary to NSDictionary, we should be able to access
+ // the keys through either an Int (the original type boxed in AnyHashable)
+ // or NSNumber (the type Int bridged to).
+ let ns_dict = dict as NSDictionary
+ for i in -Int(UInt8.min) ... Int(UInt8.max) {
+ guard let value = ns_dict[i] as? String else {
+ expectUnreachable("Unable to look up value by Int key.")
+ continue
+ }
+
+ guard let ns_value = ns_dict[NSNumber(value: i)] as? String else {
+ expectUnreachable("Unable to look up value by NSNumber key.")
+ continue
+ }
+
+ expectEqual(value, ns_value)
+ }
+}
+
+func testNSNumberBridgeAnyHashableObjc() {
+ let range = -Int(UInt8.min) ... Int(UInt8.max)
+ var dict = [AnyHashable : Any]()
+ for i in range {
+ dict[i] = "\(i)"
+ }
+
+ let verifier = NumberBridgingTester()
+ expectTrue(verifier.verifyKeys(in: NSRange(range), existIn: dict))
+}
+
nsNumberBridging.test("Bridge Int8") { testNSNumberBridgeFromInt8() }
nsNumberBridging.test("Bridge UInt8") { testNSNumberBridgeFromUInt8() }
nsNumberBridging.test("Bridge Int16") { testNSNumberBridgeFromInt16() }
@@ -887,4 +929,6 @@
nsNumberBridging.test("Bridge Double") { testNSNumberBridgeFromDouble() }
nsNumberBridging.test("Bridge CGFloat") { testNSNumberBridgeFromCGFloat() }
nsNumberBridging.test("bitPattern to exactly") { test_numericBitPatterns_to_floatingPointTypes() }
+nsNumberBridging.test("Bridge AnyHashable") { testNSNumberBridgeAnyHashable() }
+nsNumberBridging.test("Bridge AnyHashable (ObjC)") { testNSNumberBridgeAnyHashableObjc() }
runAllTests()
diff --git a/test/stdlib/subString.swift b/test/stdlib/subString.swift
index e1c23cb..c316274 100644
--- a/test/stdlib/subString.swift
+++ b/test/stdlib/subString.swift
@@ -190,4 +190,11 @@
expectEqual("", String(u.dropLast(10))!)
}
+SubstringTests.test("Persistent Content") {
+ var str = "abc"
+ str += "def"
+ expectEqual("bcdefg", str.dropFirst(1) + "g")
+ expectEqual("bcdefg", (str.dropFirst(1) + "g") as String)
+}
+
runAllTests()
diff --git a/test/type/dictionary.swift b/test/type/dictionary.swift
index 1736931..62db7fc 100644
--- a/test/type/dictionary.swift
+++ b/test/type/dictionary.swift
@@ -33,3 +33,13 @@
struct NotHashable { }
var nh1 : [NotHashable : Int] // expected-error{{'NotHashable' does not conform to protocol 'Hashable'}}
+
+struct Y<T> : Hashable {
+ var hashValue: Int { return 0 }
+
+ static func ==(this: Y<T>, other: Y<T>) -> Bool { return true }
+}
+
+let _ = [Y<Int>: Int]()
+let _ = [Y<Int> : Int]()
+let _ = [Y<Int> :Int]()
diff --git a/test/type/subclass_composition.swift b/test/type/subclass_composition.swift
index 933e64b..ed8cf99 100644
--- a/test/type/subclass_composition.swift
+++ b/test/type/subclass_composition.swift
@@ -538,3 +538,13 @@
func passesBaseIntAndPArray() {
takesBaseIntAndPArray([Base<Int> & P2]())
}
+
+//
+// Superclass constrained generic parameters
+//
+
+struct DerivedBox<T : Derived> {}
+// expected-note@-1 {{requirement specified as 'T' : 'Derived' [with T = Derived & P3]}}
+
+func takesBoxWithP3(_: DerivedBox<Derived & P3>) {}
+// expected-error@-1 {{'DerivedBox' requires that 'Derived & P3' inherit from 'Derived'}}
diff --git a/utils/UnicodeData/GraphemeBreakTest.txt b/utils/UnicodeData/GraphemeBreakTest.txt
index 3d8278f..1561f8a 100644
--- a/utils/UnicodeData/GraphemeBreakTest.txt
+++ b/utils/UnicodeData/GraphemeBreakTest.txt
@@ -418,10 +418,10 @@
# NOTE: disabled because Unicode 9.0. TODO: splat in proper file here. Original: ÷ 1F1F7 × 1F1FA × 1F1F8 × 1F1EA ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER R (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER U (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER S (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER E (Regional_Indicator) ÷ [0.3]
÷ 1F1F7 × 1F1FA ÷ 200B ÷ 1F1F8 × 1F1EA ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER R (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER U (Regional_Indicator) ÷ [5.0] ZERO WIDTH SPACE (Control) ÷ [4.0] REGIONAL INDICATOR SYMBOL LETTER S (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER E (Regional_Indicator) ÷ [0.3]
# NOTE: disabled because Unicode 9.0. TODO: splat in proper file here. Original: ÷ 1F1E6 × 1F1E7 × 1F1E8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER B (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER C (Regional_Indicator) ÷ [0.3]
-÷ 1F1E6 × 200D ÷ 1F1E7 × 1F1E8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER B (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER C (Regional_Indicator) ÷ [0.3]
-÷ 1F1E6 × 1F1E7 × 200D ÷ 1F1E8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER B (Regional_Indicator) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (Regional_Indicator) ÷ [0.3]
-÷ 0020 × 200D ÷ 0646 ÷ # ÷ [0.2] SPACE (Other) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] ARABIC LETTER NOON (Other) ÷ [0.3]
-÷ 0646 × 200D ÷ 0020 ÷ # ÷ [0.2] ARABIC LETTER NOON (Other) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] SPACE (Other) ÷ [0.3]
+# NOTE: disabled because Unicode 9.0. ÷ 1F1E6 × 200D ÷ 1F1E7 × 1F1E8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER B (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER C (Regional_Indicator) ÷ [0.3]
+# NOTE: disabled because Unicode 9.0. ÷ 1F1E6 × 1F1E7 × 200D ÷ 1F1E8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER B (Regional_Indicator) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (Regional_Indicator) ÷ [0.3]
+# NOTE: disabled because Unicode 9.0. ÷ 0020 × 200D ÷ 0646 ÷ # ÷ [0.2] SPACE (Other) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] ARABIC LETTER NOON (Other) ÷ [0.3]
+# NOTE: disabled because Unicode 9.0. ÷ 0646 × 200D ÷ 0020 ÷ # ÷ [0.2] ARABIC LETTER NOON (Other) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] SPACE (Other) ÷ [0.3]
#
# Lines: 402
#