Skip to content

Commit ecfff7d

Browse files
authored
Merge pull request #2694 from swiftwasm/release/5.4
[pull] swiftwasm-release/5.4 from release/5.4
2 parents a2eaad3 + 427364c commit ecfff7d

File tree

8 files changed

+246
-39
lines changed

8 files changed

+246
-39
lines changed

include/swift/Demangling/TypeLookupError.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class TypeLookupError {
110110

111111
Fn(Context, Command::DestroyContext, nullptr);
112112
Fn = other.Fn;
113-
Context = Fn(Context, Command::CopyContext, nullptr);
113+
Context = Fn(other.Context, Command::CopyContext, nullptr);
114114

115115
return *this;
116116
}
@@ -181,6 +181,8 @@ template <typename T> class TypeLookupErrorOr {
181181
TaggedUnion<T, TypeLookupError> Value;
182182

183183
public:
184+
TypeLookupErrorOr() : Value(TypeLookupError("freshly constructed error")) {}
185+
184186
TypeLookupErrorOr(const T &t) : Value(t) {
185187
if (!t)
186188
Value = TypeLookupError("unknown error");

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
// This file defines x-macros used for metaprogramming with the set of
1414
// runtime functions.
1515
//
16+
// Runtime functions that read from object arguments cannot be marked
17+
// ReadNone. Otherwise the objects may be freed before the runtime call.
18+
//
1619
//===----------------------------------------------------------------------===//
1720

1821
/// FUNCTION(Id, Name, CC, Availability, ReturnTys, ArgTys, Attrs)
@@ -56,10 +59,11 @@ FUNCTION(DeallocBox, swift_deallocBox, C_CC, AlwaysAvailable,
5659
ARGS(RefCountedPtrTy),
5760
ATTRS(NoUnwind))
5861

62+
// swift_projectBox reads object metadata so cannot be marked ReadNone.
5963
FUNCTION(ProjectBox, swift_projectBox, C_CC, AlwaysAvailable,
6064
RETURNS(OpaquePtrTy),
6165
ARGS(RefCountedPtrTy),
62-
ATTRS(NoUnwind, ReadNone))
66+
ATTRS(NoUnwind, ReadOnly, ArgMemOnly))
6367

6468
FUNCTION(AllocEmptyBox, swift_allocEmptyBox, C_CC, AlwaysAvailable,
6569
RETURNS(RefCountedPtrTy),
@@ -795,11 +799,12 @@ FUNCTION(GetObjCClassFromMetadata, swift_getObjCClassFromMetadata,
795799
ATTRS(NoUnwind, ReadNone))
796800

797801
// Metadata *swift_getObjCClassFromObject(id object);
802+
// This reads object metadata so cannot be marked ReadNone.
798803
FUNCTION(GetObjCClassFromObject, swift_getObjCClassFromObject,
799804
C_CC, AlwaysAvailable,
800805
RETURNS(ObjCClassPtrTy),
801806
ARGS(ObjCPtrTy),
802-
ATTRS(NoUnwind, ReadNone))
807+
ATTRS(NoUnwind, ReadOnly, ArgMemOnly))
803808

804809
// MetadataResponse swift_getTupleTypeMetadata(MetadataRequest request,
805810
// TupleTypeFlags flags,

lib/Sema/BuilderTransform.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -268,14 +268,30 @@ class BuilderClosureVisitor
268268
}
269269

270270
void visitPatternBindingDecl(PatternBindingDecl *patternBinding) {
271-
// If any of the entries lacks an initializer, don't handle this node.
272-
if (!llvm::all_of(range(patternBinding->getNumPatternEntries()),
273-
[&](unsigned index) {
274-
return patternBinding->isExplicitlyInitialized(index);
275-
})) {
276-
if (!unhandledNode)
277-
unhandledNode = patternBinding;
278-
return;
271+
// Enforce some restrictions on local variables inside a result builder.
272+
for (unsigned i : range(patternBinding->getNumPatternEntries())) {
273+
// The pattern binding must have an initial value expression.
274+
if (!patternBinding->isExplicitlyInitialized(i)) {
275+
if (!unhandledNode)
276+
unhandledNode = patternBinding;
277+
return;
278+
}
279+
280+
// Each variable bound by the pattern must be stored, and cannot
281+
// have observers.
282+
SmallVector<VarDecl *, 8> variables;
283+
patternBinding->getPattern(i)->collectVariables(variables);
284+
285+
for (auto *var : variables) {
286+
if (!var->getImplInfo().isSimpleStored()) {
287+
if (!unhandledNode)
288+
unhandledNode = patternBinding;
289+
return;
290+
}
291+
292+
// Also check for invalid attributes.
293+
TypeChecker::checkDeclAttributes(var);
294+
}
279295
}
280296

281297
// If there is a constraint system, generate constraints for the pattern

stdlib/public/runtime/DynamicCast.cpp

Lines changed: 109 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,17 @@ extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(Sh);
110110
/// Nominal type descriptor for Swift.String.
111111
extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(SS);
112112

113+
// If this returns `true`, then we will call `fatalError` when we encounter a
114+
// null reference in a storage locaation whose type does not allow null.
115+
static bool unexpectedNullIsFatal() {
116+
return true; // Placeholder for an upcoming check.
117+
}
118+
119+
/// This issues a fatal error or warning if the srcValue contains a null object
120+
/// reference. It is used when the srcType is a non-nullable reference type, in
121+
/// which case it is dangerous to continue with a null reference. The null
122+
/// reference is returned if we're operating in backwards-compatibility mode, so
123+
/// callers still have to check for null.
113124
static HeapObject * getNonNullSrcObject(OpaqueValue *srcValue,
114125
const Metadata *srcType,
115126
const Metadata *destType) {
@@ -120,12 +131,27 @@ static HeapObject * getNonNullSrcObject(OpaqueValue *srcValue,
120131

121132
std::string srcTypeName = nameForMetadata(srcType);
122133
std::string destTypeName = nameForMetadata(destType);
123-
swift::fatalError(/* flags = */ 0,
124-
"Found unexpected null pointer value"
134+
const char *msg = "Found unexpected null pointer value"
125135
" while trying to cast value of type '%s' (%p)"
126-
" to '%s' (%p)\n",
127-
srcTypeName.c_str(), srcType,
128-
destTypeName.c_str(), destType);
136+
" to '%s' (%p)%s\n";
137+
if (unexpectedNullIsFatal()) {
138+
// By default, Swift 5.4 and later issue a fatal error.
139+
swift::fatalError(/* flags = */ 0, msg,
140+
srcTypeName.c_str(), srcType,
141+
destTypeName.c_str(), destType,
142+
"");
143+
} else {
144+
// In backwards compatibility mode, this code will warn and return the null
145+
// reference anyway: If you examine the calls to the function, you'll see
146+
// that most callers fail the cast in that case, but a few casts (e.g., with
147+
// Obj-C or CF destination type) sill succeed in that case. This is
148+
// dangerous, but necessary for compatibility.
149+
swift::warning(/* flags = */ 0, msg,
150+
srcTypeName.c_str(), srcType,
151+
destTypeName.c_str(), destType,
152+
": Continuing with null object, but expect problems later.");
153+
}
154+
return object;
129155
}
130156

131157
/******************************************************************************/
@@ -310,7 +336,9 @@ tryCastFromClassToObjCBridgeable(
310336
_getBridgedObjectiveCType(MetadataState::Complete, destType,
311337
destBridgeWitness).Value;
312338
void *srcObject = getNonNullSrcObject(srcValue, srcType, destType);
313-
if (nullptr == swift_dynamicCastUnknownClass(srcObject, targetBridgedClass)) {
339+
// Note: srcObject can be null here in compatibility mode
340+
if (nullptr == srcObject
341+
|| nullptr == swift_dynamicCastUnknownClass(srcObject, targetBridgedClass)) {
314342
destFailureType = targetBridgedClass;
315343
return DynamicCastResult::Failure;
316344
}
@@ -422,8 +450,12 @@ tryCastToSwiftClass(
422450
switch (srcType->getKind()) {
423451
case MetadataKind::Class: // Swift class => Swift class
424452
case MetadataKind::ObjCClassWrapper: { // Obj-C class => Swift class
425-
void *object = getNonNullSrcObject(srcValue, srcType, destType);
426-
if (auto t = swift_dynamicCastClass(object, destClassType)) {
453+
void *srcObject = getNonNullSrcObject(srcValue, srcType, destType);
454+
// Note: srcObject can be null in compatibility mode.
455+
if (srcObject == nullptr) {
456+
return DynamicCastResult::Failure;
457+
}
458+
if (auto t = swift_dynamicCastClass(srcObject, destClassType)) {
427459
auto castObject = const_cast<void *>(t);
428460
*(reinterpret_cast<void **>(destLocation)) = castObject;
429461
if (takeOnSuccess) {
@@ -465,6 +497,17 @@ tryCastToObjectiveCClass(
465497
case MetadataKind::ObjCClassWrapper: // Obj-C class => Obj-C class
466498
case MetadataKind::ForeignClass: { // CF class => Obj-C class
467499
auto srcObject = getNonNullSrcObject(srcValue, srcType, destType);
500+
// If object is null, then we're in the compatibility mode.
501+
// Earlier cast logic always succeeded `as!` casts of nil
502+
// class references but failed `as?` and `is`
503+
if (srcObject == nullptr) {
504+
if (mayDeferChecks) {
505+
*reinterpret_cast<const void **>(destLocation) = nullptr;
506+
return DynamicCastResult::SuccessViaCopy;
507+
} else {
508+
return DynamicCastResult::Failure;
509+
}
510+
}
468511
auto destObjCClass = destObjCType->Class;
469512
if (auto resultObject
470513
= swift_dynamicCastObjCClass(srcObject, destObjCClass)) {
@@ -504,6 +547,19 @@ tryCastToForeignClass(
504547
case MetadataKind::ObjCClassWrapper: // Obj-C class => CF class
505548
case MetadataKind::ForeignClass: { // CF class => CF class
506549
auto srcObject = getNonNullSrcObject(srcValue, srcType, destType);
550+
// If srcObject is null, then we're in compatibility mode.
551+
// Earlier cast logic always succeeded `as!` casts of nil
552+
// class references. Yes, this is very dangerous, which
553+
// is why we no longer permit it.
554+
if (srcObject == nullptr) {
555+
if (mayDeferChecks) {
556+
*reinterpret_cast<const void **>(destLocation) = nullptr;
557+
return DynamicCastResult::SuccessViaCopy;
558+
} else {
559+
// `as?` and `is` checks always fail on nil sources
560+
return DynamicCastResult::Failure;
561+
}
562+
}
507563
if (auto resultObject
508564
= swift_dynamicCastForeignClass(srcObject, destClassType)) {
509565
*reinterpret_cast<const void **>(destLocation) = resultObject;
@@ -679,6 +735,10 @@ struct ObjCBridgeMemo {
679735
// Use the dynamic ISA type of the object always (Note that this
680736
// also implicitly gives us the ObjC type for a CF object.)
681737
void *srcObject = getNonNullSrcObject(srcValue, srcType, destType);
738+
// If srcObject is null, then we're in backwards compatibility mode.
739+
if (srcObject == nullptr) {
740+
return DynamicCastResult::Failure;
741+
}
682742
Class srcObjCType = object_getClass((id)srcObject);
683743
// Fail if the ObjC object is not a subclass of the bridge class.
684744
while (srcObjCType != targetBridgedObjCClass) {
@@ -1402,15 +1462,26 @@ tryCastToClassExistential(
14021462
case MetadataKind::ObjCClassWrapper:
14031463
case MetadataKind::Class:
14041464
case MetadataKind::ForeignClass: {
1405-
auto object = getNonNullSrcObject(srcValue, srcType, destType);
1465+
auto srcObject = getNonNullSrcObject(srcValue, srcType, destType);
1466+
// If srcObject is null, then we're in compatibility mode.
1467+
// Earlier cast logic always succeeded `as!` casts of nil
1468+
// class references:
1469+
if (srcObject == nullptr) {
1470+
if (mayDeferChecks) {
1471+
*reinterpret_cast<const void **>(destLocation) = nullptr;
1472+
return DynamicCastResult::SuccessViaCopy;
1473+
} else {
1474+
return DynamicCastResult::Failure;
1475+
}
1476+
}
14061477
if (_conformsToProtocols(srcValue, srcType,
14071478
destExistentialType,
14081479
destExistentialLocation->getWitnessTables())) {
1409-
destExistentialLocation->Value = object;
1480+
destExistentialLocation->Value = srcObject;
14101481
if (takeOnSuccess) {
14111482
return DynamicCastResult::SuccessViaTake;
14121483
} else {
1413-
swift_unknownObjectRetain(object);
1484+
swift_unknownObjectRetain(srcObject);
14141485
return DynamicCastResult::SuccessViaCopy;
14151486
}
14161487
}
@@ -1672,8 +1743,14 @@ tryCastToMetatype(
16721743
case MetadataKind::ObjCClassWrapper: {
16731744
#if SWIFT_OBJC_INTEROP
16741745
// Some classes are actually metatypes
1675-
void *object = getNonNullSrcObject(srcValue, srcType, destType);
1676-
if (auto metatype = _getUnknownClassAsMetatype(object)) {
1746+
void *srcObject = getNonNullSrcObject(srcValue, srcType, destType);
1747+
// If object is null, then we're in compatibility mode.
1748+
// Continuing here at all is dangerous, but that's what the
1749+
// pre-Swift-5.4 casting logic did.
1750+
if (srcObject == nullptr) {
1751+
return DynamicCastResult::Failure;
1752+
}
1753+
if (auto metatype = _getUnknownClassAsMetatype(srcObject)) {
16771754
auto srcInnerValue = reinterpret_cast<OpaqueValue *>(&metatype);
16781755
auto srcInnerType = swift_getMetatypeMetadata(metatype);
16791756
return tryCast(destLocation, destType, srcInnerValue, srcInnerType,
@@ -1783,6 +1860,12 @@ tryCastToExistentialMetatype(
17831860
// Some Obj-C classes are actually metatypes
17841861
#if SWIFT_OBJC_INTEROP
17851862
void *srcObject = getNonNullSrcObject(srcValue, srcType, destType);
1863+
// If srcObject is null, we're in compatibility mode.
1864+
// Continuing here at al is dangerous, but that's what the
1865+
// pre-Swift-5.4 casting logic did.
1866+
if (srcObject == nullptr) {
1867+
return DynamicCastResult::Failure;
1868+
}
17861869
if (auto metatype = _getUnknownClassAsMetatype(srcObject)) {
17871870
return _dynamicCastMetatypeToExistentialMetatype(
17881871
destLocation,
@@ -1947,14 +2030,19 @@ tryCast(
19472030
|| srcKind == MetadataKind::ObjCClassWrapper
19482031
|| srcKind == MetadataKind::ForeignClass) {
19492032
auto srcObject = getNonNullSrcObject(srcValue, srcType, destType);
1950-
auto srcDynamicType = swift_getObjectType(srcObject);
1951-
if (srcDynamicType != srcType) {
1952-
srcFailureType = srcDynamicType;
1953-
auto castResult = tryCastToDestType(
1954-
destLocation, destType, srcValue, srcDynamicType,
1955-
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
1956-
if (isSuccess(castResult)) {
1957-
return castResult;
2033+
// If srcObject is null, we're in compability mode.
2034+
// But we can't lookup dynamic type for a null class reference, so
2035+
// just skip this in that case.
2036+
if (srcObject != nullptr) {
2037+
auto srcDynamicType = swift_getObjectType(srcObject);
2038+
if (srcDynamicType != srcType) {
2039+
srcFailureType = srcDynamicType;
2040+
auto castResult = tryCastToDestType(
2041+
destLocation, destType, srcValue, srcDynamicType,
2042+
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
2043+
if (isSuccess(castResult)) {
2044+
return castResult;
2045+
}
19582046
}
19592047
}
19602048
}

stdlib/public/runtime/Metadata.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5006,7 +5006,7 @@ swift_getAssociatedTypeWitnessSlowImpl(
50065006
Demangle::makeSymbolicMangledNameStringRef(mangledNameBase);
50075007

50085008
// Demangle the associated type.
5009-
TypeLookupErrorOr<TypeInfo> result = TypeInfo();
5009+
TypeLookupErrorOr<TypeInfo> result;
50105010
if (inProtocolContext) {
50115011
// The protocol's Self is the only generic parameter that can occur in the
50125012
// type.

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/Runtime/HeapObject.h"
2323
#include "swift/Runtime/Metadata.h"
2424
#include "swift/Basic/Unreachable.h"
25+
#include "llvm/ADT/DenseMap.h"
2526
#include "CompatibilityOverride.h"
2627
#include "ImageInspection.h"
2728
#include "Private.h"
@@ -470,6 +471,7 @@ swift_conformsToProtocolImpl(const Metadata *const type,
470471
return found.second;
471472

472473
// Scan conformance records.
474+
llvm::SmallDenseMap<const Metadata *, const WitnessTable *> foundWitnesses;
473475
auto processSection = [&](const ConformanceSection &section) {
474476
// Eagerly pull records for nondependent witnesses into our cache.
475477
auto processDescriptor = [&](const ProtocolConformanceDescriptor &descriptor) {
@@ -484,6 +486,7 @@ swift_conformsToProtocolImpl(const Metadata *const type,
484486
if (auto *matchingType = candidate.getMatchingType(type)) {
485487
auto witness = descriptor.getWitnessTable(matchingType);
486488
C.cacheResult(matchingType, protocol, witness, /*always cache*/ 0);
489+
foundWitnesses.insert({matchingType, witness});
487490
}
488491
};
489492

@@ -505,14 +508,23 @@ swift_conformsToProtocolImpl(const Metadata *const type,
505508
processSection(section);
506509
}
507510

508-
// Try the search again to look for the most specific cached conformance.
509-
found = searchInConformanceCache(type, protocol);
511+
// Find the most specific conformance that was scanned.
512+
const WitnessTable *foundWitness = nullptr;
513+
const Metadata *searchType = type;
514+
while (!foundWitness && searchType) {
515+
foundWitness = foundWitnesses.lookup(searchType);
510516

511-
// If it's not authoritative, then add an authoritative entry for this type.
512-
if (!found.first)
513-
C.cacheResult(type, protocol, found.second, snapshot.count());
517+
// If there's no entry here, move up to the superclass (if any).
518+
if (!foundWitness)
519+
searchType = _swift_class_getSuperclass(searchType);
520+
}
521+
522+
// If it's for a superclass or if we didn't find anything, then add an
523+
// authoritative entry for this type.
524+
if (searchType != type)
525+
C.cacheResult(type, protocol, foundWitness, snapshot.count());
514526

515-
return found.second;
527+
return foundWitness;
516528
}
517529

518530
const ContextDescriptor *

0 commit comments

Comments
 (0)