Merge pull request #20005 from DougGregor/more-symbolic-references
[ABI] Introduce indirect symbolic references to context descriptors.
diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake
index a988993..e20e628 100644
--- a/cmake/modules/SwiftSource.cmake
+++ b/cmake/modules/SwiftSource.cmake
@@ -454,13 +454,14 @@
# Then we can compile both the object files and the swiftmodule files
# in parallel in this target for the object file, and ...
- # Windows doesn't support long command line paths, of 8191 chars or over.
- # We need to work around this by avoiding long command line arguments. This can be
- # achieved by writing the list of file paths to a file, then reading that list
- # in the Python script.
+ # Windows doesn't support long command line paths, of 8191 chars or over. We
+ # need to work around this by avoiding long command line arguments. This can
+ # be achieved by writing the list of file paths to a file, then reading that
+ # list in the Python script.
string(RANDOM file_name)
set(file_path "${CMAKE_CURRENT_BINARY_DIR}/${file_name}.txt")
- file(WRITE "${file_path}" "${source_files}")
+ string(REPLACE ";" "'\n'" source_files_quoted "${source_files}")
+ file(WRITE "${file_path}" "'${source_files_quoted}'")
add_custom_command_target(
dependency_target
diff --git a/include/swift/IDE/CodeCompletion.h b/include/swift/IDE/CodeCompletion.h
index fc8176a..293e2d4 100644
--- a/include/swift/IDE/CodeCompletion.h
+++ b/include/swift/IDE/CodeCompletion.h
@@ -899,26 +899,28 @@
} // end namespace ide
} // end namespace swift
-template <> struct llvm::DenseMapInfo<swift::ide::CodeCompletionKeywordKind> {
+namespace llvm {
+template <> struct DenseMapInfo<swift::ide::CodeCompletionKeywordKind> {
using Kind = swift::ide::CodeCompletionKeywordKind;
static Kind getEmptyKey() { return Kind(~0u); }
static Kind getTombstoneKey() { return Kind(~1u); }
static unsigned getHashValue(const Kind &Val) { return unsigned(Val); }
static bool isEqual(const Kind &LHS, const Kind &RHS) { return LHS == RHS; }
};
-template <> struct llvm::DenseMapInfo<swift::ide::CodeCompletionLiteralKind> {
+template <> struct DenseMapInfo<swift::ide::CodeCompletionLiteralKind> {
using Kind = swift::ide::CodeCompletionLiteralKind;
static Kind getEmptyKey() { return Kind(~0u); }
static Kind getTombstoneKey() { return Kind(~1u); }
static unsigned getHashValue(const Kind &Val) { return unsigned(Val); }
static bool isEqual(const Kind &LHS, const Kind &RHS) { return LHS == RHS; }
};
-template <> struct llvm::DenseMapInfo<swift::ide::CodeCompletionDeclKind> {
+template <> struct DenseMapInfo<swift::ide::CodeCompletionDeclKind> {
using Kind = swift::ide::CodeCompletionDeclKind;
static Kind getEmptyKey() { return Kind(~0u); }
static Kind getTombstoneKey() { return Kind(~1u); }
static unsigned getHashValue(const Kind &Val) { return unsigned(Val); }
static bool isEqual(const Kind &LHS, const Kind &RHS) { return LHS == RHS; }
};
+}
#endif // SWIFT_IDE_CODECOMPLETION_H
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index 24983e2..d995632 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -1006,7 +1006,8 @@
}
/// Allow LinkEntity to be used as a key for a DenseMap.
-template <> struct llvm::DenseMapInfo<swift::irgen::LinkEntity> {
+namespace llvm {
+template <> struct DenseMapInfo<swift::irgen::LinkEntity> {
using LinkEntity = swift::irgen::LinkEntity;
static LinkEntity getEmptyKey() {
LinkEntity entity;
@@ -1032,4 +1033,5 @@
LHS.SecondaryPointer == RHS.SecondaryPointer && LHS.Data == RHS.Data;
}
};
+}
#endif
diff --git a/include/swift/SILOptimizer/Analysis/AccessedStorageAnalysis.h b/include/swift/SILOptimizer/Analysis/AccessedStorageAnalysis.h
index e39d0d0..b41c70c 100644
--- a/include/swift/SILOptimizer/Analysis/AccessedStorageAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/AccessedStorageAnalysis.h
@@ -94,9 +94,10 @@
};
} // namespace swift
+namespace llvm {
// Use the same DenseMapInfo for StorageAccessInfo as for AccessedStorage. None
// of the subclass bitfields participate in the Key.
-template <> struct llvm::DenseMapInfo<swift::StorageAccessInfo> {
+template <> struct DenseMapInfo<swift::StorageAccessInfo> {
static swift::StorageAccessInfo getEmptyKey() {
auto key = DenseMapInfo<swift::AccessedStorage>::getEmptyKey();
return static_cast<swift::StorageAccessInfo &>(key);
@@ -114,6 +115,7 @@
return DenseMapInfo<swift::AccessedStorage>::isEqual(LHS, RHS);
}
};
+}
namespace swift {
/// The per-function result of AccessedStorageAnalysis.
diff --git a/include/swift/SILOptimizer/Analysis/AliasAnalysis.h b/include/swift/SILOptimizer/Analysis/AliasAnalysis.h
index 3885627..97d723d 100644
--- a/include/swift/SILOptimizer/Analysis/AliasAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/AliasAnalysis.h
@@ -306,7 +306,7 @@
} // end namespace swift
namespace llvm {
- template <> struct llvm::DenseMapInfo<AliasKeyTy> {
+ template <> struct DenseMapInfo<AliasKeyTy> {
static inline AliasKeyTy getEmptyKey() {
auto Allone = std::numeric_limits<size_t>::max();
return {0, Allone, nullptr, nullptr};
@@ -331,7 +331,7 @@
}
};
- template <> struct llvm::DenseMapInfo<MemBehaviorKeyTy> {
+ template <> struct DenseMapInfo<MemBehaviorKeyTy> {
static inline MemBehaviorKeyTy getEmptyKey() {
auto Allone = std::numeric_limits<size_t>::max();
return {0, Allone, RetainObserveKind::RetainObserveKindEnd};
diff --git a/include/swift/Syntax/SyntaxData.h b/include/swift/Syntax/SyntaxData.h
index 3452772..0f1d4f9 100644
--- a/include/swift/Syntax/SyntaxData.h
+++ b/include/swift/Syntax/SyntaxData.h
@@ -294,7 +294,7 @@
namespace llvm {
using SD = swift::syntax::SyntaxData;
using RCSD = swift::RC<SD>;
- template <> struct llvm::DenseMapInfo<RCSD> {
+ template <> struct DenseMapInfo<RCSD> {
static inline RCSD getEmptyKey() {
return SD::make(nullptr, nullptr, 0);
}
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 23589af..1707011 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -2011,72 +2011,89 @@
return nullptr;
}
+static const clang::Module *
+getClangTopLevelOwningModule(ClangNode Node,
+ const clang::ASTContext &ClangCtx) {
+ const clang::Module *OwningModule = getClangOwningModule(Node, ClangCtx);
+ if (!OwningModule)
+ return nullptr;
+ return OwningModule->getTopLevelModule();
+}
+
static bool isVisibleFromModule(const ClangModuleUnit *ModuleFilter,
const ValueDecl *VD) {
- // Include a value from module X if:
- // * no particular module was requested, or
- // * module X was specifically requested.
- if (!ModuleFilter)
- return true;
+ assert(ModuleFilter);
auto ContainingUnit = VD->getDeclContext()->getModuleScopeContext();
if (ModuleFilter == ContainingUnit)
return true;
+ // The rest of this function is looking to see if the Clang entity that
+ // caused VD to be imported has redeclarations in the filter module.
auto Wrapper = dyn_cast<ClangModuleUnit>(ContainingUnit);
if (!Wrapper)
return false;
auto ClangNode = VD->getClangNode();
- assert(ClangNode);
+ if (!ClangNode) {
+ // If we synthesized a ValueDecl, it won't have a Clang node. But so far
+ // all the situations where we synthesize top-level declarations are
+ // situations where we don't have to worry about C redeclarations.
+ // We should only consider the declaration visible from its owning module.
+ auto *SynthesizedTypeAttr =
+ VD->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>();
+ assert(SynthesizedTypeAttr);
+ // When adding new ClangImporterSynthesizedTypeAttr::Kinds, make sure that
+ // the above statement still holds: "we don't want to allow these
+ // declarations to be treated as present in multiple modules".
+ switch (SynthesizedTypeAttr->getKind()) {
+ case ClangImporterSynthesizedTypeAttr::Kind::NSErrorWrapper:
+ case ClangImporterSynthesizedTypeAttr::Kind::NSErrorWrapperAnon:
+ break;
+ }
+
+ return false;
+ }
+
+ // Macros can be "redeclared" by putting an equivalent definition in two
+ // different modules. (We don't actually check the equivalence.)
+ // FIXME: We're also not checking if the redeclaration is in /this/ module.
+ if (ClangNode.getAsMacro())
+ return true;
+
+ const clang::Decl *D = ClangNode.castAsDecl();
auto &ClangASTContext = ModuleFilter->getClangASTContext();
- auto OwningClangModule = getClangOwningModule(ClangNode, ClangASTContext);
// We don't handle Clang submodules; pop everything up to the top-level
// module.
- if (OwningClangModule)
- OwningClangModule = OwningClangModule->getTopLevelModule();
-
+ auto OwningClangModule = getClangTopLevelOwningModule(ClangNode,
+ ClangASTContext);
if (OwningClangModule == ModuleFilter->getClangModule())
return true;
- if (auto D = ClangNode.getAsDecl()) {
- // Handle redeclared decls.
- if (isa<clang::FunctionDecl>(D) || isa<clang::VarDecl>(D) ||
- isa<clang::TypedefNameDecl>(D)) {
- for (auto Redeclaration : D->redecls()) {
- if (Redeclaration == D)
- continue;
- auto OwningClangModule = getClangOwningModule(Redeclaration,
- ClangASTContext);
- if (OwningClangModule)
- OwningClangModule = OwningClangModule->getTopLevelModule();
-
- if (OwningClangModule == ModuleFilter->getClangModule())
- return true;
- }
- } else if (isa<clang::TagDecl>(D)) {
- for (auto Redeclaration : D->redecls()) {
- if (Redeclaration == D)
- continue;
- if (!cast<clang::TagDecl>(Redeclaration)->isCompleteDefinition())
- continue;
- auto OwningClangModule = getClangOwningModule(Redeclaration,
- ClangASTContext);
- if (OwningClangModule)
- OwningClangModule = OwningClangModule->getTopLevelModule();
-
- if (OwningClangModule == ModuleFilter->getClangModule())
- return true;
- }
- }
+ // Handle redeclarable Clang decls by checking each redeclaration.
+ bool IsTagDecl = isa<clang::TagDecl>(D);
+ if (!(IsTagDecl || isa<clang::FunctionDecl>(D) || isa<clang::VarDecl>(D) ||
+ isa<clang::TypedefNameDecl>(D))) {
+ return false;
}
- // Macros can be "redeclared" too, by putting an equivalent definition in two
- // different modules.
- if (ClangNode.getAsMacro())
- return true;
+ for (auto Redeclaration : D->redecls()) {
+ if (Redeclaration == D)
+ continue;
+
+ // For enums, structs, and unions, only count definitions when looking to
+ // see what other modules they appear in.
+ if (IsTagDecl)
+ if (!cast<clang::TagDecl>(Redeclaration)->isCompleteDefinition())
+ continue;
+
+ auto OwningClangModule = getClangTopLevelOwningModule(Redeclaration,
+ ClangASTContext);
+ if (OwningClangModule == ModuleFilter->getClangModule())
+ return true;
+ }
return false;
}
@@ -2106,12 +2123,14 @@
class FilteringVisibleDeclConsumer : public swift::VisibleDeclConsumer {
swift::VisibleDeclConsumer &NextConsumer;
- const ClangModuleUnit *ModuleFilter = nullptr;
+ const ClangModuleUnit *ModuleFilter;
public:
FilteringVisibleDeclConsumer(swift::VisibleDeclConsumer &consumer,
const ClangModuleUnit *CMU)
- : NextConsumer(consumer), ModuleFilter(CMU) {}
+ : NextConsumer(consumer), ModuleFilter(CMU) {
+ assert(CMU);
+ }
void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) override {
if (isVisibleFromModule(ModuleFilter, VD))
@@ -2121,13 +2140,14 @@
class FilteringDeclaredDeclConsumer : public swift::VisibleDeclConsumer {
swift::VisibleDeclConsumer &NextConsumer;
- const ClangModuleUnit *ModuleFilter = nullptr;
+ const ClangModuleUnit *ModuleFilter;
public:
FilteringDeclaredDeclConsumer(swift::VisibleDeclConsumer &consumer,
const ClangModuleUnit *CMU)
- : NextConsumer(consumer),
- ModuleFilter(CMU) {}
+ : NextConsumer(consumer), ModuleFilter(CMU) {
+ assert(CMU);
+ }
void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) override {
if (isDeclaredInModule(ModuleFilter, VD))
@@ -2868,10 +2888,7 @@
auto &clangCtx = clangSema.getASTContext();
for (auto objcMethod : objcMethods) {
// Verify that this method came from this module.
- auto owningClangModule = getClangOwningModule(objcMethod, clangCtx);
- if (owningClangModule)
- owningClangModule = owningClangModule->getTopLevelModule();
-
+ auto owningClangModule = getClangTopLevelOwningModule(objcMethod, clangCtx);
if (owningClangModule != clangModule) continue;
// If we found a property accessor, import the property.
diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp
index 5d7711e..bcb75fa7 100644
--- a/lib/Driver/UnixToolChains.cpp
+++ b/lib/Driver/UnixToolChains.cpp
@@ -111,6 +111,7 @@
// final executables, as such, unless specified, we default to gold
// linker.
return "gold";
+ case llvm::Triple::x86:
case llvm::Triple::x86_64:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
diff --git a/lib/IRGen/LocalTypeDataKind.h b/lib/IRGen/LocalTypeDataKind.h
index 58bd817..0b32e1a 100644
--- a/lib/IRGen/LocalTypeDataKind.h
+++ b/lib/IRGen/LocalTypeDataKind.h
@@ -190,7 +190,8 @@
}
}
-template <> struct llvm::DenseMapInfo<swift::irgen::LocalTypeDataKey> {
+namespace llvm {
+template <> struct DenseMapInfo<swift::irgen::LocalTypeDataKey> {
using LocalTypeDataKey = swift::irgen::LocalTypeDataKey;
using CanTypeInfo = DenseMapInfo<swift::CanType>;
static inline LocalTypeDataKey getEmptyKey() {
@@ -209,5 +210,6 @@
return a == b;
}
};
+}
#endif
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index f53f386..409d551 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -2046,9 +2046,8 @@
if (value.getOwnershipKind() == ValueOwnershipKind::Trivial)
return ManagedValue::forUnmanaged(value.getValue());
- // Otherwise, retain and enter a release cleanup.
- valueTL.emitCopyValue(B, loc, value.getValue());
- return emitManagedRValueWithCleanup(value.getValue(), valueTL);
+ // Otherwise, copy the value and return.
+ return value.getFinalManagedValue().copy(*this, loc);
}
// Otherwise, produce a temporary and copy into that.
diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp
index 8944c45..9f5987a 100644
--- a/lib/SILGen/SILGenPattern.cpp
+++ b/lib/SILGen/SILGenPattern.cpp
@@ -741,22 +741,28 @@
auto consumptionKind = outerCMV.getFinalConsumption();
(void)consumptionKind;
+
+ // If we have an object and it is take always, we need to borrow the value
+ // since we do not own the value at this point.
+ if (outerMV.getType().isObject()) {
+ assert(consumptionKind == CastConsumptionKind::TakeAlways &&
+ "Object without cleanup that is not take_always?!");
+ return {outerMV.borrow(SGF, loc), CastConsumptionKind::BorrowAlways};
+ }
+
+ // Only address only values use TakeOnSuccess.
+ assert(outerMV.getType().isAddressOnly(SGF.getModule()) &&
+ "TakeOnSuccess can only be used with address only values");
+
assert((consumptionKind == CastConsumptionKind::TakeAlways ||
consumptionKind == CastConsumptionKind::TakeOnSuccess) &&
"non-+1 consumption with a cleanup?");
scope.pushCleanupState(outerMV.getCleanup(),
CleanupState::PersistentlyActive);
- // If SILOwnership is enabled and we have an object, borrow instead of take on
- // success.
- if (SGF.F.getModule().getOptions().EnableSILOwnership &&
- outerMV.getType().isObject()) {
- return {outerMV.borrow(SGF, loc), CastConsumptionKind::BorrowAlways};
- }
-
// Success means that we won't end up in the other branch,
// but failure doesn't.
- return { outerMV, CastConsumptionKind::TakeOnSuccess };
+ return {outerMV, CastConsumptionKind::TakeOnSuccess};
}
/// Forward a value down into an irrefutable branch of the decision tree.
@@ -2728,9 +2734,39 @@
PatternMatchContext switchContext = { emission };
SwitchStack.push_back(&switchContext);
- // Emit the subject value. Dispatching will consume it.
- ManagedValue subjectMV = emitRValueAsSingleValue(S->getSubjectExpr());
- auto subject = ConsumableManagedValue::forOwned(subjectMV);
+ // Emit the subject value. If at +1, dispatching will consume it. If it is at
+ // +0, we just forward down borrows.
+ ManagedValue subjectMV = emitRValueAsSingleValue(
+ S->getSubjectExpr(), SGFContext::AllowGuaranteedPlusZero);
+
+ // Inline constructor for subject.
+ auto subject = ([&]() -> ConsumableManagedValue {
+ // If we have a plus one value...
+ if (subjectMV.isPlusOne(*this)) {
+ // And we have an address that is loadable, perform a load [take].
+ if (subjectMV.getType().isAddress() &&
+ subjectMV.getType().isLoadable(getModule())) {
+ subjectMV = B.createLoadTake(S, subjectMV);
+ }
+ return {subjectMV, CastConsumptionKind::TakeAlways};
+ }
+
+ // If we have a loadable address and +0, perform a load borrow.
+ if (subjectMV.getType().isAddress() &&
+ subjectMV.getType().isLoadable(getModule())) {
+ subjectMV = B.createLoadBorrow(S, subjectMV);
+ }
+
+ // If then we have an object, return it at +0.
+ if (subjectMV.getType().isObject()) {
+ return {subjectMV, CastConsumptionKind::BorrowAlways};
+ }
+
+ // If we have an address only type returned without a cleanup, we
+ // need to do a copy just to be safe. So for efficiency we pass it
+ // down take_always.
+ return {subjectMV.copy(*this, S), CastConsumptionKind::TakeAlways};
+ }());
auto failure = [&](SILLocation location) {
// If we fail to match anything, we trap. This can happen with a switch
@@ -2855,13 +2891,14 @@
// Set up an initial clause matrix.
ClauseMatrix clauseMatrix(clauseRows);
- ConsumableManagedValue subject;
- if (F.getModule().getOptions().EnableSILOwnership &&
- exn.getType().isObject()) {
- subject = {exn.borrow(*this, S), CastConsumptionKind::BorrowAlways};
- } else {
- subject = {exn, CastConsumptionKind::TakeOnSuccess};
- }
+
+ assert(exn.getType().isObject() &&
+ "Error is special and should always be an object");
+ // Our model is that sub-cases get the exception at +0 and the throw (if we
+ // need to rethrow the exception) gets the exception at +1 since we need to
+ // trampoline it's ownership to our caller.
+ ConsumableManagedValue subject = {exn.borrow(*this, S),
+ CastConsumptionKind::BorrowAlways};
auto failure = [&](SILLocation location) {
// If we fail to match anything, just rethrow the exception.
@@ -2874,7 +2911,10 @@
return;
}
- // Don't actually kill the exception's cleanup.
+ // Since we borrowed exn before sending it to our subcases, we know that it
+ // must be at +1 at this point. That being said, SILGenPattern will
+ // potentially invoke this for each of the catch statements, so we need to
+ // copy before we pass it into the throw.
CleanupStateRestorationScope scope(Cleanups);
if (exn.hasCleanup()) {
scope.pushCleanupState(exn.getCleanup(),
diff --git a/lib/SILGen/SILGenStmt.cpp b/lib/SILGen/SILGenStmt.cpp
index df9f587..5eb7e95 100644
--- a/lib/SILGen/SILGenStmt.cpp
+++ b/lib/SILGen/SILGenStmt.cpp
@@ -800,6 +800,12 @@
// Emit all the catch clauses, branching to the end destination if
// we fall out of one.
SGF.emitCatchDispatch(S, exn, S->getCatches(), endDest);
+
+ // We assume that exn's cleanup is still valid at this point. To ensure that
+ // we do not re-emit it and do a double consume, we rely on us having
+ // finished emitting code and thus unsetting the insertion point here. This
+ // assert is to make sure this invariant is clear in the code and validated.
+ assert(!SGF.B.hasValidInsertionPoint());
}
if (hasLabel) {
diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp
index dd8ff58..d6ea4e7 100644
--- a/lib/Sema/CSDiagnostics.cpp
+++ b/lib/Sema/CSDiagnostics.cpp
@@ -103,10 +103,16 @@
locator = cs.getConstraintLocator(
ctor.withPathElement(PathEltKind::ApplyFunction)
.withPathElement(PathEltKind::ConstructorMember));
- } else if (isa<UnresolvedDotExpr>(anchor)) {
+ } else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
ConstraintLocatorBuilder member(locator);
- locator =
- cs.getConstraintLocator(member.withPathElement(PathEltKind::Member));
+
+ if (UDE->getName().isSimpleName(DeclBaseName::createConstructor())) {
+ member = member.withPathElement(PathEltKind::ConstructorMember);
+ } else {
+ member = member.withPathElement(PathEltKind::Member);
+ }
+
+ locator = cs.getConstraintLocator(member);
} else if (isa<SubscriptExpr>(anchor)) {
ConstraintLocatorBuilder subscript(locator);
locator = cs.getConstraintLocator(
diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h
index b3ea2d2..b871548 100644
--- a/lib/Sema/CSDiagnostics.h
+++ b/lib/Sema/CSDiagnostics.h
@@ -163,6 +163,7 @@
RequirementFailure(Expr *expr, ConstraintSystem &cs,
ConstraintLocator *locator)
: FailureDiagnostic(expr, cs, locator), AffectedDecl(getDeclRef()) {
+ assert(AffectedDecl);
auto *anchor = getAnchor();
expr->forEachChildExpr([&](Expr *subExpr) -> Expr * {
auto *AE = dyn_cast<ApplyExpr>(subExpr);
diff --git a/stdlib/public/SDK/Foundation/AffineTransform.swift b/stdlib/public/SDK/Foundation/AffineTransform.swift
index 80caad0..7978bd9 100644
--- a/stdlib/public/SDK/Foundation/AffineTransform.swift
+++ b/stdlib/public/SDK/Foundation/AffineTransform.swift
@@ -239,7 +239,7 @@
public func inverted() -> AffineTransform? {
let determinant = (m11 * m22) - (m12 * m21)
- if fabs(determinant) <= ε {
+ if abs(determinant) <= ε {
return nil
}
var inverse = AffineTransform()
diff --git a/stdlib/public/SDK/Foundation/CMakeLists.txt b/stdlib/public/SDK/Foundation/CMakeLists.txt
index a42c512..8d07ab8 100644
--- a/stdlib/public/SDK/Foundation/CMakeLists.txt
+++ b/stdlib/public/SDK/Foundation/CMakeLists.txt
@@ -59,7 +59,7 @@
UUID.swift
CheckClass.mm
- SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-Xllvm" "-sil-inline-generics" "-Xllvm" "-sil-partial-specialization" "-swift-version" "3"
+ SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-Xllvm" "-sil-inline-generics" "-Xllvm" "-sil-partial-specialization" "-swift-version" "5"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation CoreGraphics Dispatch IOKit ObjectiveC # auto-updated
diff --git a/stdlib/public/SDK/Foundation/Calendar.swift b/stdlib/public/SDK/Foundation/Calendar.swift
index 4e87045..2d343e3 100644
--- a/stdlib/public/SDK/Foundation/Calendar.swift
+++ b/stdlib/public/SDK/Foundation/Calendar.swift
@@ -357,7 +357,7 @@
/// - parameter component: A component to calculate a range for.
/// - returns: The range, or nil if it could not be calculated.
public func minimumRange(of component: Component) -> Range<Int>? {
- return _handle.map { $0.minimumRange(of: Calendar._toCalendarUnit([component])).toRange() }
+ return _handle.map { Range($0.minimumRange(of: Calendar._toCalendarUnit([component]))) }
}
/// The maximum range limits of the values that a given component can take on in the receive
@@ -366,7 +366,7 @@
/// - parameter component: A component to calculate a range for.
/// - returns: The range, or nil if it could not be calculated.
public func maximumRange(of component: Component) -> Range<Int>? {
- return _handle.map { $0.maximumRange(of: Calendar._toCalendarUnit([component])).toRange() }
+ return _handle.map { Range($0.maximumRange(of: Calendar._toCalendarUnit([component]))) }
}
@@ -383,7 +383,7 @@
/// - parameter date: The absolute time for which the calculation is performed.
/// - returns: The range of absolute time values smaller can take on in larger at the time specified by date. Returns `nil` if larger is not logically bigger than smaller in the calendar, or the given combination of components does not make sense (or is a computation which is undefined).
public func range(of smaller: Component, in larger: Component, for date: Date) -> Range<Int>? {
- return _handle.map { $0.range(of: Calendar._toCalendarUnit([smaller]), in: Calendar._toCalendarUnit([larger]), for: date).toRange() }
+ return _handle.map { Range($0.range(of: Calendar._toCalendarUnit([smaller]), in: Calendar._toCalendarUnit([larger]), for: date)) }
}
@available(*, unavailable, message: "use range(of:in:for:) instead")
diff --git a/stdlib/public/SDK/Foundation/Data.swift b/stdlib/public/SDK/Foundation/Data.swift
index 57e14cb..f666f0f 100644
--- a/stdlib/public/SDK/Foundation/Data.swift
+++ b/stdlib/public/SDK/Foundation/Data.swift
@@ -141,6 +141,8 @@
return d.bytes.advanced(by: -_offset)
case .customMutableReference(let d):
return d.bytes.advanced(by: -_offset)
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
}
@@ -267,6 +269,8 @@
return data.mutableBytes.advanced(by: -_offset)
case .customMutableReference(let d):
return d.mutableBytes.advanced(by: -_offset)
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
}
@@ -287,6 +291,8 @@
return d.length
case .customMutableReference(let d):
return d.length
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
@inlinable
@@ -447,6 +453,8 @@
_backing = .customMutableReference(data)
case .customMutableReference(let d):
d.length = length
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
@@ -478,6 +486,8 @@
_backing = .customMutableReference(data)
case .customMutableReference(let d):
d.append(bytes, length: length)
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
@@ -528,6 +538,8 @@
_backing = .customReference(data)
case .customMutableReference(let d):
d.increaseLength(by: extraLength)
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
@@ -614,6 +626,8 @@
_backing = .customMutableReference(data)
case .customMutableReference(let d):
d.replaceBytes(in: NSRange(location: range.location - _offset, length: range.length), withBytes: bytes!)
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
@@ -664,6 +678,8 @@
_backing = .customMutableReference(data)
case .customMutableReference(let d):
d.replaceBytes(in: range, withBytes: replacementBytes, length: replacementLength)
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
@@ -697,6 +713,8 @@
_backing = .customMutableReference(data)
case .customMutableReference(let d):
d.resetBytes(in: range)
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
@@ -887,6 +905,8 @@
} else {
return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData, offset: range.lowerBound)
}
+ @unknown default:
+ fatalError("Unknown Data backing type")
}
}
diff --git a/stdlib/public/SDK/Foundation/ExtraStringAPIs.swift b/stdlib/public/SDK/Foundation/ExtraStringAPIs.swift
index e6e5a84..6865dcd 100644
--- a/stdlib/public/SDK/Foundation/ExtraStringAPIs.swift
+++ b/stdlib/public/SDK/Foundation/ExtraStringAPIs.swift
@@ -15,19 +15,18 @@
@available(swift, deprecated: 3.2)
@available(swift, obsoleted: 4.0)
public init(_ offset: Int) {
- assert(offset >= 0, "Negative UTF16 index offset not allowed")
- self.init(encodedOffset: offset)
+ fatalError()
}
@available(swift, deprecated: 3.2)
@available(swift, obsoleted: 4.0)
public func distance(to other: String.UTF16View.Index?) -> Int {
- return _offset.distance(to: other!._offset)
+ fatalError()
}
@available(swift, deprecated: 3.2)
@available(swift, obsoleted: 4.0)
public func advanced(by n: Int) -> String.UTF16View.Index {
- return String.UTF16View.Index(_offset.advanced(by: n))
+ fatalError()
}
}
diff --git a/stdlib/public/SDK/Foundation/JSONEncoder.swift b/stdlib/public/SDK/Foundation/JSONEncoder.swift
index 4d1bfc4..8f90826 100644
--- a/stdlib/public/SDK/Foundation/JSONEncoder.swift
+++ b/stdlib/public/SDK/Foundation/JSONEncoder.swift
@@ -1077,7 +1077,7 @@
guard !stringKey.isEmpty else { return stringKey }
// Find the first non-underscore character
- guard let firstNonUnderscore = stringKey.index(where: { $0 != "_" }) else {
+ guard let firstNonUnderscore = stringKey.firstIndex(where: { $0 != "_" }) else {
// Reached the end without finding an _
return stringKey
}
diff --git a/stdlib/public/SDK/Foundation/NSError.swift b/stdlib/public/SDK/Foundation/NSError.swift
index 29aa4a2..598f54d 100644
--- a/stdlib/public/SDK/Foundation/NSError.swift
+++ b/stdlib/public/SDK/Foundation/NSError.swift
@@ -428,16 +428,6 @@
init(_nsError error: NSError)
}
-/// TODO: Better way to do this?
-internal func _stringDictToAnyHashableDict(_ input: [String : Any])
- -> [AnyHashable : Any] {
- var result = [AnyHashable : Any](minimumCapacity: input.count)
- for (k, v) in input {
- result[k] = v
- }
- return result
-}
-
/// Various helper implementations for _BridgedStoredNSError
extension _BridgedStoredNSError {
public var code: Code {
@@ -449,7 +439,7 @@
public init(_ code: Code, userInfo: [String : Any] = [:]) {
self.init(_nsError: NSError(domain: Self.errorDomain,
code: unsafeBinaryIntegerToInt(code.rawValue),
- userInfo: _stringDictToAnyHashableDict(userInfo)))
+ userInfo: userInfo))
}
/// The user-info dictionary for an error that was bridged from
@@ -483,8 +473,7 @@
var errorUserInfo: [String : Any] {
var result: [String : Any] = [:]
for (key, value) in _nsError.userInfo {
- guard let stringKey = key.base as? String else { continue }
- result[stringKey] = value
+ result[key] = value
}
return result
}
@@ -615,7 +604,7 @@
extension CocoaError {
public static func error(_ code: CocoaError.Code, userInfo: [AnyHashable : Any]? = nil, url: URL? = nil) -> Error {
- var info: [AnyHashable : Any] = userInfo ?? [:]
+ var info: [String : Any] = userInfo as? [String : Any] ?? [:]
if let url = url {
info[NSURLErrorKey] = url
}
diff --git a/stdlib/public/SDK/Foundation/NSObject.swift b/stdlib/public/SDK/Foundation/NSObject.swift
index 04e4cd3..e6cde6f 100644
--- a/stdlib/public/SDK/Foundation/NSObject.swift
+++ b/stdlib/public/SDK/Foundation/NSObject.swift
@@ -149,8 +149,8 @@
let bridgeClass: AnyClass = NSKeyValueObservation.self
let observeSel = #selector(NSObject.observeValue(forKeyPath:of:change:context:))
let swapSel = #selector(NSKeyValueObservation._swizzle_me_observeValue(forKeyPath:of:change:context:))
- let rootObserveImpl = class_getInstanceMethod(bridgeClass, observeSel)
- let swapObserveImpl = class_getInstanceMethod(bridgeClass, swapSel)
+ let rootObserveImpl = class_getInstanceMethod(bridgeClass, observeSel)!
+ let swapObserveImpl = class_getInstanceMethod(bridgeClass, swapSel)!
method_exchangeImplementations(rootObserveImpl, swapObserveImpl)
return nil
}()
diff --git a/stdlib/public/SDK/Foundation/NSStringAPI.swift b/stdlib/public/SDK/Foundation/NSStringAPI.swift
index ba2cdff..0e9ebbe 100644
--- a/stdlib/public/SDK/Foundation/NSStringAPI.swift
+++ b/stdlib/public/SDK/Foundation/NSStringAPI.swift
@@ -1217,12 +1217,12 @@
let range = range.relative(to: self)
_ns.enumerateLinguisticTags(
in: _toRelativeNSRange(range),
- scheme: tagScheme._ephemeralString,
+ scheme: NSLinguisticTagScheme(rawValue: tagScheme._ephemeralString),
options: opts,
orthography: orthography != nil ? orthography! : nil
) {
var stop_ = false
- body($0, self._range($1), self._range($2), &stop_)
+ body($0!.rawValue, self._range($1), self._range($2), &stop_)
if stop_ {
$3.pointee = true
}
@@ -1463,7 +1463,7 @@
let result = tokenRanges._withNilOrAddress(of: &nsTokenRanges) {
self._ns.linguisticTags(
in: _toRelativeNSRange(range.relative(to: self)),
- scheme: tagScheme._ephemeralString,
+ scheme: NSLinguisticTagScheme(rawValue: tagScheme._ephemeralString),
options: opts,
orthography: orthography,
tokenRanges: $0) as NSArray
diff --git a/stdlib/public/SwiftShims/DispatchOverlayShims.h b/stdlib/public/SwiftShims/DispatchOverlayShims.h
index fc51383..f677747 100644
--- a/stdlib/public/SwiftShims/DispatchOverlayShims.h
+++ b/stdlib/public/SwiftShims/DispatchOverlayShims.h
@@ -193,9 +193,9 @@
static inline void _swift_dispatch_apply_current(
size_t iterations,
- void SWIFT_DISPATCH_NOESCAPE (^block)(long)) {
+ void SWIFT_DISPATCH_NOESCAPE (^block)(intptr_t)) {
dispatch_apply(iterations, (dispatch_queue_t _Nonnull)0, ^(size_t i){
- block((long)i);
+ block((intptr_t)i);
});
}
diff --git a/test/ClangImporter/Inputs/custom-modules/RedeclaredErrorEnum/Base.h b/test/ClangImporter/Inputs/custom-modules/RedeclaredErrorEnum/Base.h
new file mode 100644
index 0000000..c708209
--- /dev/null
+++ b/test/ClangImporter/Inputs/custom-modules/RedeclaredErrorEnum/Base.h
@@ -0,0 +1,9 @@
+@import Foundation;
+
+extern NSString * const SomeErrorDomain;
+// typedef NS_ERROR_ENUM(SomeErrorDomain, SomeErrorCode) { ... }
+typedef enum SomeErrorCode : long SomeErrorCode;
+enum __attribute__((ns_error_domain(SomeErrorDomain))) SomeErrorCode : long {
+ SomeErrorX,
+ SomeErrorY
+};
diff --git a/test/ClangImporter/Inputs/custom-modules/RedeclaredErrorEnum/Redeclared.h b/test/ClangImporter/Inputs/custom-modules/RedeclaredErrorEnum/Redeclared.h
new file mode 100644
index 0000000..94f733a
--- /dev/null
+++ b/test/ClangImporter/Inputs/custom-modules/RedeclaredErrorEnum/Redeclared.h
@@ -0,0 +1,7 @@
+@import Foundation;
+@import Base;
+
+extern NSString * const SomeErrorDomain;
+// typedef NS_ERROR_ENUM(SomeErrorDomain, SomeErrorCode);
+typedef enum SomeErrorCode : long SomeErrorCode;
+enum __attribute__((ns_error_domain(SomeErrorDomain))) SomeErrorCode : long;
\ No newline at end of file
diff --git a/test/ClangImporter/Inputs/custom-modules/RedeclaredErrorEnum/module.modulemap b/test/ClangImporter/Inputs/custom-modules/RedeclaredErrorEnum/module.modulemap
new file mode 100644
index 0000000..24ea6de
--- /dev/null
+++ b/test/ClangImporter/Inputs/custom-modules/RedeclaredErrorEnum/module.modulemap
@@ -0,0 +1,8 @@
+module Base {
+ header "Base.h"
+}
+
+module Redeclared {
+ header "Redeclared.h"
+ export *
+}
\ No newline at end of file
diff --git a/test/ClangImporter/enum-error-redeclared.swift b/test/ClangImporter/enum-error-redeclared.swift
new file mode 100644
index 0000000..6833908
--- /dev/null
+++ b/test/ClangImporter/enum-error-redeclared.swift
@@ -0,0 +1,11 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -verify -enable-objc-interop -I %S/Inputs/custom-modules/RedeclaredErrorEnum
+
+import Redeclared
+
+// Referencing this error type (defined in Base, redeclared in Redeclared)
+// used to cause a compiler crash (rdar://problem/45414271).
+_ = SomeError.self
+_ = SomeError.Code.self
+
+_ = Redeclared.SomeError.self
+_ = Base.SomeError.self
diff --git a/test/SIL/ownership-verifier/over_consume.sil b/test/SIL/ownership-verifier/over_consume.sil
index f87f5fa..be04631 100644
--- a/test/SIL/ownership-verifier/over_consume.sil
+++ b/test/SIL/ownership-verifier/over_consume.sil
@@ -22,7 +22,12 @@
case none
}
-class SuperKlass {}
+class SuperKlass {
+ func doSomething()
+}
+
+class Klass : SuperKlass {
+}
///////////
// Tests //
@@ -434,3 +439,21 @@
%9999 = tuple()
return %9999 : $()
}
+
+// CHECK-LABEL: Function: 'consume_with_classmethod'
+// CHECK: Found use after free?!
+// CHECK: Value: %2 = upcast %0 : $Klass to $SuperKlass
+// CHECK: Consuming User: store %2 to [init] %1 : $*SuperKlass
+// CHECK: Non Consuming User: %4 = class_method %2 : $SuperKlass, #SuperKlass.doSomething!1 : (SuperKlass) -> () -> (), $@convention(method) (@guaranteed SuperKlass) -> ()
+// CHECK: Block: bb0
+sil @consume_with_classmethod : $@convention(thin) (@owned Klass) -> () {
+bb0(%0 : @owned $Klass):
+ %1 = alloc_stack $SuperKlass
+ %2 = upcast %0 : $Klass to $SuperKlass
+ store %2 to [init] %1 : $*SuperKlass
+ %3 = class_method %2 : $SuperKlass, #SuperKlass.doSomething!1 : (SuperKlass) -> () -> (), $@convention(method) (@guaranteed SuperKlass) -> ()
+ destroy_addr %1 : $*SuperKlass
+ dealloc_stack %1 : $*SuperKlass
+ %9999 = tuple()
+ return %9999 : $()
+}
\ No newline at end of file
diff --git a/test/SILGen/class_bound_protocols.swift b/test/SILGen/class_bound_protocols.swift
index 7de76f1..acbddd8 100644
--- a/test/SILGen/class_bound_protocols.swift
+++ b/test/SILGen/class_bound_protocols.swift
@@ -1,5 +1,5 @@
-// RUN: %target-swift-emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck %s
+// RUN: %target-swift-emit-silgen -enable-sil-ownership -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck %s
enum Optional<T> {
case some(T)
@@ -132,8 +132,9 @@
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[XBOX_PB]] : $*ClassBound
// CHECK: [[X:%.*]] = load [copy] [[READ]] : $*ClassBound
// CHECK: [[PROJ:%.*]] = open_existential_ref [[X]] : $ClassBound to $[[OPENED:@opened(.*) ClassBound]]
+ // CHECK: [[BORROWED_PROJ:%.*]] = begin_borrow [[PROJ]]
// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED]], #ClassBound.classBoundMethod!1
- // CHECK: apply [[METHOD]]<[[OPENED]]>([[PROJ]])
+ // CHECK: apply [[METHOD]]<[[OPENED]]>([[BORROWED_PROJ]])
// CHECK: destroy_value [[PROJ]]
// CHECK: destroy_value [[XBOX]]
}
diff --git a/test/SILGen/errors.swift b/test/SILGen/errors.swift
index 548b19e..4813da3 100644
--- a/test/SILGen/errors.swift
+++ b/test/SILGen/errors.swift
@@ -1,17 +1,5 @@
// RUN: %target-swift-emit-silgen -parse-stdlib -enable-sil-ownership -Xllvm -sil-print-debuginfo -verify -primary-file %s %S/Inputs/errors_other.swift | %FileCheck %s
-// TODO: Turn back on ownership verification. I turned off the verification on
-// this file since it shows an ownership error that does not affect
-// codegen. Specifically when we destroy the temporary array we use for the
-// variadic tuple, we try to borrow the temporary array when we pass it to the
-// destroy function. This makes the ownership verifier think that the owned
-// value we are trying to destroy is not cleaned up. But once ownership is
-// stripped out, the destroy array function still does what it needs to do. The
-// actual fix for this would require a bunch of surgery in SILGenApply around
-// how function types are computed and preserving non-canonical function types
-// through SILGenApply. This is something that can be done after +0 is turned
-// on.
-
import Swift
class Cat {}
@@ -176,6 +164,83 @@
}
}
+// Make sure that if we catch an error in a throwing function we borrow the
+// error and only consume the error in the rethrow block.
+//
+// CHECK-LABEL: sil hidden @$s6errors20all_together_now_twoyAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional<Cat>, @error Error) {
+// CHECK: bb0(
+// CHECK-NOT: bb1
+// CHECK: try_apply {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
+//
+// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error):
+// CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]]
+// CHECK: [[COPIED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]]
+// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*Error
+// CHECK: checked_cast_addr_br copy_on_success Error in [[CAST_INPUT_MEM]] : $*Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]],
+//
+// CHECK: [[CAST_YES_BB]]:
+// CHECK: [[SUBERROR:%.*]] = load [take] [[CAST_OUTPUT_MEM]]
+// CHECK: switch_enum [[SUBERROR]] : $HomeworkError, case #HomeworkError.TooHard!enumelt: {{bb[0-9]+}}, default [[SWITCH_MATCH_FAIL_BB:bb[0-9]+]],
+//
+// CHECK: [[SWITCH_MATCH_FAIL_BB]]([[SUBERROR:%.*]] : @owned $HomeworkError):
+// CHECK: destroy_value [[SUBERROR]]
+// CHECK: end_borrow [[BORROWED_ERROR]]
+// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $Error)
+//
+// CHECK: [[CAST_NO_BB]]:
+// CHECK: end_borrow [[BORROWED_ERROR]]
+// CHECK: br [[RETHROW_BB]]([[ERROR]] : $Error)
+//
+// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $Error):
+// CHECK: throw [[ERROR_FOR_RETHROW]]
+// CHECK: } // end sil function '$s6errors20all_together_now_twoyAA3CatCSgSbKF'
+func all_together_now_two(_ flag: Bool) throws -> Cat? {
+ do {
+ return try dont_return(Cat())
+ } catch HomeworkError.TooHard {
+ return nil
+ }
+}
+
+// Same as the previous test, but with multiple cases instead of just one.
+//
+// CHECK-LABEL: sil hidden @$s6errors22all_together_now_threeyAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional<Cat>, @error Error) {
+// CHECK: bb0(
+// CHECK-NOT: bb1
+// CHECK: try_apply {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
+//
+// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error):
+// CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]]
+// CHECK: [[COPIED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]]
+// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*Error
+// CHECK: checked_cast_addr_br copy_on_success Error in [[CAST_INPUT_MEM]] : $*Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]],
+//
+// CHECK: [[CAST_YES_BB]]:
+// CHECK: [[SUBERROR:%.*]] = load [take] [[CAST_OUTPUT_MEM]]
+// CHECK: switch_enum [[SUBERROR]] : $HomeworkError, case #HomeworkError.TooHard!enumelt: {{bb[0-9]+}}, case #HomeworkError.TooMuch!enumelt: {{bb[0-9]+}}, default [[SWITCH_MATCH_FAIL_BB:bb[0-9]+]],
+//
+// CHECK: [[SWITCH_MATCH_FAIL_BB]]([[SUBERROR:%.*]] : @owned $HomeworkError):
+// CHECK: destroy_value [[SUBERROR]]
+// CHECK: end_borrow [[BORROWED_ERROR]]
+// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $Error)
+//
+// CHECK: [[CAST_NO_BB]]:
+// CHECK: end_borrow [[BORROWED_ERROR]]
+// CHECK: br [[RETHROW_BB]]([[ERROR]] : $Error)
+//
+// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $Error):
+// CHECK: throw [[ERROR_FOR_RETHROW]]
+// CHECK: } // end sil function '$s6errors22all_together_now_threeyAA3CatCSgSbKF'
+func all_together_now_three(_ flag: Bool) throws -> Cat? {
+ do {
+ return try dont_return(Cat())
+ } catch HomeworkError.TooHard {
+ return nil
+ } catch HomeworkError.TooMuch {
+ return nil
+ }
+}
+
// Catch in non-throwing context.
// CHECK-LABEL: sil hidden @$s6errors11catch_a_catAA3CatCyF : $@convention(thin) () -> @owned Cat
// CHECK-NEXT: bb0:
diff --git a/test/SILGen/indirect_enum.swift b/test/SILGen/indirect_enum.swift
index e7615f1..d0d91ed 100644
--- a/test/SILGen/indirect_enum.swift
+++ b/test/SILGen/indirect_enum.swift
@@ -149,10 +149,8 @@
// CHECK-LABEL: sil hidden @$s13indirect_enum11switchTreeAyyAA0D1AOyxGlF : $@convention(thin) <T> (@guaranteed TreeA<T>) -> () {
func switchTreeA<T>(_ x: TreeA<T>) {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $TreeA<T>):
- // -- x +2
- // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
- // CHECK: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[ARG_COPY]]
- // CHECK: switch_enum [[BORROWED_ARG_COPY]] : $TreeA<T>,
+ // -- x +0
+ // CHECK: switch_enum [[ARG]] : $TreeA<T>,
// CHECK: case #TreeA.Nil!enumelt: [[NIL_CASE:bb1]],
// CHECK: case #TreeA.Leaf!enumelt.1: [[LEAF_CASE:bb2]],
// CHECK: case #TreeA.Branch!enumelt.1: [[BRANCH_CASE:bb3]],
@@ -168,7 +166,7 @@
// CHECK: function_ref @$s13indirect_enum1b{{[_0-9a-zA-Z]*}}F
// CHECK: destroy_addr [[X]]
// CHECK: dealloc_stack [[X]]
- // -- x +1
+ // -- x +0
// CHECK: br [[OUTER_CONT]]
case .Leaf(let x):
b(x)
@@ -204,8 +202,7 @@
c(x, y)
// CHECK: [[DEFAULT]]:
- // -- x +1
- // CHECK: destroy_value [[ARG_COPY]]
+ // -- x +0
default:
d()
}
diff --git a/test/SILGen/switch.swift b/test/SILGen/switch.swift
index a6f8a93..18aaace 100644
--- a/test/SILGen/switch.swift
+++ b/test/SILGen/switch.swift
@@ -413,9 +413,7 @@
// CHECK-LABEL: sil hidden @$s6switch16test_isa_class_11xyAA1BC_tF : $@convention(thin) (@guaranteed B) -> () {
func test_isa_class_1(x: B) {
// CHECK: bb0([[X:%.*]] : @guaranteed $B):
- // CHECK: [[X_COPY:%.*]] = copy_value [[X]]
- // CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
- // CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
+ // CHECK: checked_cast_br [[X]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
switch x {
// CHECK: [[IS_D1]]([[CAST_D1:%.*]] : @guaranteed $D1):
@@ -427,8 +425,6 @@
case is D1 where runced():
// CHECK: destroy_value [[CAST_D1_COPY]]
// CHECK: end_borrow [[CAST_D1]]
- // CHECK: end_borrow [[BORROWED_X_COPY]]
- // CHECK: destroy_value [[X_COPY]]
// CHECK: function_ref @$s6switch1ayyF
// CHECK: br [[CONT:bb[0-9]+]]
a()
@@ -436,31 +432,25 @@
// CHECK: [[NO_CASE1]]:
// CHECK-NEXT: destroy_value [[CAST_D1_COPY]]
// CHECK-NEXT: end_borrow [[CAST_D1]]
- // CHECK-NEXT: end_borrow [[BORROWED_X_COPY]]
// CHECK: br [[NEXT_CASE:bb[0-9]+]]
// CHECK: [[IS_NOT_D1]]([[CASTFAIL_D1:%.*]] : @guaranteed $B):
// CHECK-NEXT: end_borrow [[CASTFAIL_D1]]
- // CHECK-NEXT: end_borrow [[BORROWED_X_COPY]]
// CHECK-NEXT: br [[NEXT_CASE]]
// CHECK: [[NEXT_CASE]]:
- // CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
- // CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $D2, [[IS_D2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
+ // CHECK: checked_cast_br [[X]] : $B to $D2, [[IS_D2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
case is D2:
// CHECK: [[IS_D2]]([[CAST_D2:%.*]] : @guaranteed $D2):
// CHECK: [[CAST_D2_COPY:%.*]] = copy_value [[CAST_D2]]
// CHECK: destroy_value [[CAST_D2_COPY]]
- // CHECK: end_borrow [[BORROWED_X_COPY]]
- // CHECK: destroy_value [[X_COPY]]
// CHECK: function_ref @$s6switch1byyF
// CHECK: br [[CONT]]
b()
// CHECK: [[IS_NOT_D2]]([[CASTFAIL_D2:%.*]] : @guaranteed $B):
// CHECK: end_borrow [[CASTFAIL_D2]]
- // CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
- // CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
+ // CHECK: checked_cast_br [[X]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
case is E where funged():
// CHECK: [[IS_E]]([[CAST_E:%.*]] : @guaranteed $E):
// CHECK: [[CAST_E_COPY:%.*]] = copy_value [[CAST_E]]
@@ -469,8 +459,6 @@
// CHECK: [[CASE3]]:
// CHECK: destroy_value [[CAST_E_COPY]]
- // CHECK: end_borrow [[BORROWED_X_COPY]]
- // CHECK: destroy_value [[X_COPY]]
// CHECK: function_ref @$s6switch1cyyF
// CHECK: br [[CONT]]
c()
@@ -478,7 +466,6 @@
// CHECK: [[NO_CASE3]]:
// CHECK-NEXT: destroy_value [[CAST_E_COPY]]
// CHECK-NEXT: end_borrow
- // CHECK-NEXT: end_borrow [[BORROWED_X_COPY]]
// CHECK: br [[NEXT_CASE:bb[0-9]+]]
// CHECK: [[IS_NOT_E]]([[NOTCAST_E:%.*]] : @guaranteed $B):
@@ -486,15 +473,13 @@
// CHECK: br [[NEXT_CASE]]
// CHECK: [[NEXT_CASE]]:
- // CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
- // CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $C, [[IS_C:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
+ // CHECK: checked_cast_br [[X]] : $B to $C, [[IS_C:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
case is C:
// CHECK: [[IS_C]]([[CAST_C:%.*]] : @guaranteed $C):
// CHECK: [[CAST_C_COPY:%.*]] = copy_value [[CAST_C]]
// CHECK: destroy_value [[CAST_C_COPY]]
// CHECK: end_borrow [[CAST_C]]
- // CHECK: destroy_value [[X_COPY]]
// CHECK: function_ref @$s6switch1dyyF
// CHECK: br [[CONT]]
d()
@@ -502,7 +487,6 @@
// CHECK: [[IS_NOT_C]]([[NOCAST_C:%.*]] : @guaranteed $B):
// CHECK: end_borrow [[NOCAST_C]]
default:
- // CHECK: destroy_value [[X_COPY]]
// CHECK: function_ref @$s6switch1eyyF
// CHECK: br [[CONT]]
e()
@@ -517,11 +501,9 @@
// CHECK-LABEL: sil hidden @$s6switch16test_isa_class_21xyXlAA1BC_tF : $@convention(thin)
func test_isa_class_2(x: B) -> AnyObject {
// CHECK: bb0([[X:%.*]] : @guaranteed $B):
- // CHECK: [[X_COPY:%.*]] = copy_value [[X]]
- // CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
switch x {
- // CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
+ // CHECK: checked_cast_br [[X]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
case let y as D1 where runced():
// CHECK: [[IS_D1]]([[CAST_D1:%.*]] : @guaranteed $D1):
// CHECK: [[CAST_D1_COPY:%.*]] = copy_value [[CAST_D1]]
@@ -535,8 +517,6 @@
// CHECK: [[RET:%.*]] = init_existential_ref [[CAST_D1_COPY_COPY]]
// CHECK: end_borrow [[BORROWED_CAST_D1_COPY]]
// CHECK: destroy_value [[CAST_D1_COPY]]
- // CHECK: end_borrow [[BORROWED_X_COPY]]
- // CHECK: destroy_value [[X_COPY]] : $B
// CHECK: br [[CONT:bb[0-9]+]]([[RET]] : $AnyObject)
a()
return y
@@ -550,8 +530,7 @@
// CHECK: br [[NEXT_CASE]]
// CHECK: [[NEXT_CASE]]:
- // CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
- // CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $D2, [[CASE2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
+ // CHECK: checked_cast_br [[X]] : $B to $D2, [[CASE2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
case let y as D2:
// CHECK: [[CASE2]]([[CAST_D2:%.*]] : @guaranteed $D2):
// CHECK: [[CAST_D2_COPY:%.*]] = copy_value [[CAST_D2]]
@@ -561,16 +540,13 @@
// CHECK: [[RET:%.*]] = init_existential_ref [[CAST_D2_COPY_COPY]]
// CHECK: end_borrow [[BORROWED_CAST_D2_COPY]]
// CHECK: destroy_value [[CAST_D2_COPY]]
- // CHECK: end_borrow [[BORROWED_X_COPY]]
- // CHECK: destroy_value [[X_COPY]]
// CHECK: br [[CONT]]([[RET]] : $AnyObject)
b()
return y
// CHECK: [[IS_NOT_D2]]([[NOCAST_D2:%.*]] : @guaranteed $B):
// CHECK: end_borrow [[NOCAST_D2]]
- // CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
- // CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
+ // CHECK: checked_cast_br [[X]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
case let y as E where funged():
// CHECK: [[IS_E]]([[CAST_E:%.*]] : @guaranteed $E):
// CHECK: [[CAST_E_COPY:%.*]] = copy_value [[CAST_E]]
@@ -585,7 +561,6 @@
// CHECK: end_borrow [[BORROWED_CAST_E_COPY]]
// CHECK: destroy_value [[CAST_E_COPY]]
// CHECK: end_borrow [[CAST_E]]
- // CHECK: destroy_value [[X_COPY]] : $B
// CHECK: br [[CONT]]([[RET]] : $AnyObject)
c()
return y
@@ -599,8 +574,7 @@
// CHECK: br [[NEXT_CASE]]
// CHECK: [[NEXT_CASE]]
- // CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
- // CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $C, [[CASE4:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
+ // CHECK: checked_cast_br [[X]] : $B to $C, [[CASE4:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
case let y as C:
// CHECK: [[CASE4]]([[CAST_C:%.*]] : @guaranteed $C):
// CHECK: [[CAST_C_COPY:%.*]] = copy_value [[CAST_C]]
@@ -610,8 +584,6 @@
// CHECK: [[RET:%.*]] = init_existential_ref [[CAST_C_COPY_COPY]]
// CHECK: end_borrow [[BORROWED_CAST_C_COPY]]
// CHECK: destroy_value [[CAST_C_COPY]]
- // CHECK: end_borrow [[BORROWED_X_COPY]]
- // CHECK: destroy_value [[X_COPY]]
// CHECK: br [[CONT]]([[RET]] : $AnyObject)
d()
return y
@@ -619,7 +591,6 @@
// CHECK: [[IS_NOT_C]]([[NOCAST_C:%.*]] : @guaranteed $B):
// CHECK: end_borrow [[NOCAST_C]]
default:
- // CHECK: destroy_value [[X_COPY]]
// CHECK: function_ref @$s6switch1eyyF
// CHECK: [[X_COPY_2:%.*]] = copy_value [[X]]
// CHECK: [[RET:%.*]] = init_existential_ref [[X_COPY_2]]
@@ -663,17 +634,15 @@
// CHECK: br [[CONT]]
b()
- // CHECK: [[IS_RIGHT]]([[STR:%.*]] : @owned $String):
+ // CHECK: [[IS_RIGHT]]([[STR:%.*]] : @guaranteed $String):
case var .Right:
- // CHECK: destroy_value [[STR]] : $String
// CHECK: function_ref @$s6switch1cyyF
// CHECK: br [[CONT]]
c()
- // CHECK: [[IS_BOTH]]([[TUP:%.*]] : @owned $(Int, String)):
+ // CHECK: [[IS_BOTH]]([[TUP:%.*]] : @guaranteed $(Int, String)):
case .Both:
// CHECK: ({{%.*}}, [[TUP_STR:%.*]]) = destructure_tuple [[TUP]]
- // CHECK: destroy_value [[TUP_STR]] : $String
// CHECK: function_ref @$s6switch1dyyF
// CHECK: br [[CONT]]
d()
@@ -688,9 +657,7 @@
// CHECK-LABEL: sil hidden @$s6switch12test_union_31uyAA9MaybePairO_tF : $@convention(thin) (@guaranteed MaybePair) -> () {
func test_union_3(u: MaybePair) {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $MaybePair):
- // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
- // CHECK: [[SUBJECT:%.*]] = begin_borrow [[ARG_COPY]]
- // CHECK: switch_enum [[SUBJECT]] : $MaybePair,
+ // CHECK: switch_enum [[ARG]] : $MaybePair,
// CHECK: case #MaybePair.Neither!enumelt: [[IS_NEITHER:bb[0-9]+]],
// CHECK: case #MaybePair.Left!enumelt.1: [[IS_LEFT:bb[0-9]+]],
// CHECK: case #MaybePair.Right!enumelt.1: [[IS_RIGHT:bb[0-9]+]],
@@ -716,7 +683,6 @@
// CHECK: [[DEFAULT]](
// -- Ensure the fully-opaque value is destroyed in the default case.
- // CHECK: destroy_value [[ARG_COPY]] :
// CHECK: function_ref @$s6switch1dyyF
// CHECK: br [[CONT]]
diff --git a/test/SILGen/switch_abstraction.swift b/test/SILGen/switch_abstraction.swift
index 5dfdbd4..4e63cc8 100644
--- a/test/SILGen/switch_abstraction.swift
+++ b/test/SILGen/switch_abstraction.swift
@@ -9,8 +9,11 @@
}
// CHECK-LABEL: sil hidden @$s18switch_abstraction18enum_reabstraction1x1ayAA10OptionableOyAA1AVAHcG_AHtF : $@convention(thin) (@guaranteed Optionable<(A) -> A>, A) -> ()
-// CHECK: switch_enum {{%.*}} : $Optionable<(A) -> A>, case #Optionable.Summn!enumelt.1: [[DEST:bb[0-9]+]]
-// CHECK: [[DEST]]([[ORIG:%.*]] : @owned $@callee_guaranteed (@in_guaranteed A) -> @out A):
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Optionable<(A) -> A>,
+// CHECK: switch_enum [[ARG]] : $Optionable<(A) -> A>, case #Optionable.Summn!enumelt.1: [[DEST:bb[0-9]+]]
+//
+// CHECK: [[DEST]]([[ARG:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed A) -> @out A):
+// CHECK: [[ORIG:%.*]] = copy_value [[ARG]]
// CHECK: [[REABSTRACT:%.*]] = function_ref @$s{{.*}}TR :
// CHECK: [[SUBST:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT]]([[ORIG]])
func enum_reabstraction(x x: Optionable<(A) -> A>, a: A) {
diff --git a/test/SILGen/types.swift b/test/SILGen/types.swift
index f4f5f14..ec258e5 100644
--- a/test/SILGen/types.swift
+++ b/test/SILGen/types.swift
@@ -85,8 +85,8 @@
}
// CHECK-LABEL: sil hidden @$s5types32referencedFromFunctionEnumFieldsyyAA010ReferencedcdE0OcSg_yAA0gcD6StructVcSgtADF
-// CHECK: bb{{[0-9]+}}([[F:%.*]] : @owned $@callee_guaranteed (@guaranteed ReferencedFromFunctionEnum) -> ()):
-// CHECK: bb{{[0-9]+}}([[G:%.*]] : @owned $@callee_guaranteed (@guaranteed ReferencedFromFunctionStruct) -> ()):
+// CHECK: bb{{[0-9]+}}([[F:%.*]] : @guaranteed $@callee_guaranteed (@guaranteed ReferencedFromFunctionEnum) -> ()):
+// CHECK: bb{{[0-9]+}}([[G:%.*]] : @guaranteed $@callee_guaranteed (@guaranteed ReferencedFromFunctionStruct) -> ()):
func referencedFromFunctionEnumFields(_ x: ReferencedFromFunctionEnum)
-> (
((ReferencedFromFunctionEnum) -> ())?,
diff --git a/test/SILOptimizer/access_marker_verify.swift b/test/SILOptimizer/access_marker_verify.swift
index eeb8218..8d5fb8f 100644
--- a/test/SILOptimizer/access_marker_verify.swift
+++ b/test/SILOptimizer/access_marker_verify.swift
@@ -379,7 +379,7 @@
// CHECK-LABEL: sil hidden @$s20access_marker_verify7IntEnumO8getValueSivg : $@convention(method) (@guaranteed IntEnum) -> Int {
// CHECK: bb0(%0 : @guaranteed $IntEnum):
// CHECK: switch_enum %{{.*}} : $IntEnum, case #IntEnum.int!enumelt.1: bb1
-// CHECK: bb1(%{{.*}} : @owned ${ var Int }):
+// CHECK: bb1(%{{.*}} : @guaranteed ${ var Int }):
// CHECK: [[PROJ:%.*]] = project_box
// CHECK-NOT: begin_access
// CHECK: load [trivial] [[PROJ]] : $*Int
@@ -398,7 +398,7 @@
// CHECK-LABEL: sil hidden @$s20access_marker_verify7RefEnumO8getValueAA9BaseClassCvg : $@convention(method) (@guaranteed RefEnum) -> @owned BaseClass {
// CHECK: bb0(%0 : @guaranteed $RefEnum):
// CHECK: switch_enum %{{.*}} : $RefEnum, case #RefEnum.ref!enumelt.1: bb1
-// CHECK: bb1(%{{.*}} : @owned ${ var BaseClass }):
+// CHECK: bb1(%{{.*}} : @guaranteed ${ var BaseClass }):
// CHECK: [[PROJ:%.*]] = project_box %{{.*}} : ${ var BaseClass }, 0
// CHECK-NOT: begin_access
// CHECK: load_borrow [[PROJ]] : $*BaseClass
diff --git a/test/Serialization/transparent.swift b/test/Serialization/transparent.swift
index 99db1e6..1b82fa0 100644
--- a/test/Serialization/transparent.swift
+++ b/test/Serialization/transparent.swift
@@ -42,7 +42,6 @@
// SIL-LABEL: sil public_external [transparent] [serialized] @$s15def_transparent9do_switch1uyAA9MaybePairO_tF : $@convention(thin) (@guaranteed MaybePair) -> () {
// SIL: bb0(%0 : $MaybePair):
-// SIL: retain_value %0 : $MaybePair
// SIL: switch_enum %0 : $MaybePair, case #MaybePair.Neither!enumelt: bb[[CASE1:[0-9]+]], case #MaybePair.Left!enumelt.1: bb[[CASE2:[0-9]+]], case #MaybePair.Right!enumelt.1: bb[[CASE3:[0-9]+]], case #MaybePair.Both!enumelt.1: bb[[CASE4:[0-9]+]]
// SIL: bb[[CASE4]](%{{.*}} : $(Int32, String)):
// SIL: bb[[CASE3]](%{{.*}} : $String):
diff --git a/test/lit.cfg b/test/lit.cfg
index 8937f12..39aa0b5 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -932,7 +932,8 @@
ENV_VAR_PREFIXES = {
'iphonesimulator': SIMULATOR_ENV_PREFIX,
'watchsimulator': SIMULATOR_ENV_PREFIX,
- 'appletvsimulator': SIMULATOR_ENV_PREFIX
+ 'appletvsimulator': SIMULATOR_ENV_PREFIX,
+ 'android': 'ANDROID_CHILD_'
}
TARGET_ENV_PREFIX = ENV_VAR_PREFIXES.get(config.target_sdk_name, "")
diff --git a/utils/android/adb/commands.py b/utils/android/adb/commands.py
index d9595a5..3823d33 100644
--- a/utils/android/adb/commands.py
+++ b/utils/android/adb/commands.py
@@ -17,6 +17,7 @@
from __future__ import print_function
+import os
import subprocess
import tempfile
import uuid
@@ -24,6 +25,7 @@
# A temporary directory on the Android device.
DEVICE_TEMP_DIR = '/data/local/tmp'
+ENV_PREFIX = 'ANDROID_CHILD_'
def shell(args):
@@ -93,6 +95,10 @@
executable = '{}/__executable'.format(uuid_dir)
push(executable_path, executable)
+ child_environment = ['{}="{}"'.format(k.replace(ENV_PREFIX, '', 1), v)
+ for (k, v) in os.environ.items()
+ if k.startswith(ENV_PREFIX)]
+
# When running the executable on the device, we need to pass it the same
# arguments, as well as specify the correct LD_LIBRARY_PATH. Save these
# to a file we can easily call multiple times.
@@ -100,9 +106,10 @@
_create_executable_on_device(
executable_with_args,
'LD_LIBRARY_PATH={uuid_dir}:{tmp_dir} '
- '{executable} {executable_arguments}'.format(
+ '{child_environment} {executable} {executable_arguments}'.format(
uuid_dir=uuid_dir,
tmp_dir=DEVICE_TEMP_DIR,
+ child_environment=' '.join(child_environment),
executable=executable,
executable_arguments=' '.join(executable_arguments)))
@@ -146,7 +153,7 @@
# the executable on the device.
return 1
- print(stdout)
+ print(stdout, end='')
shell(['rm', '-rf', uuid_dir])
return 0
diff --git a/utils/build-script-impl b/utils/build-script-impl
index e390c50..20e3e33 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -3081,7 +3081,7 @@
fi
# If libdispatch is being built, TestFoundation will need access to it
if [[ ! "${SKIP_BUILD_LIBDISPATCH}" ]] ; then
- LIBDISPATCH_LIB_DIR=":$(build_directory ${host} libdispatch)/src/.libs"
+ LIBDISPATCH_LIB_DIR=":$(build_directory ${host} libdispatch):$(build_directory ${host} libdispatch)/src"
else
LIBDISPATCH_LIB_DIR=""
fi
diff --git a/utils/line-directive b/utils/line-directive
index 238073c..87d0ef8 100755
--- a/utils/line-directive
+++ b/utils/line-directive
@@ -21,6 +21,7 @@
import bisect
import os
import re
+import shlex
import subprocess
import sys
@@ -178,7 +179,11 @@
def read_response_file(file_path):
with open(file_path, 'r') as files:
- return filter(None, files.read().split(';'))
+ # "Make an iterator out of shlex.shlex.get_token, then consume items
+ # until it returns None." (Then eagerly convert the result to a list so
+ # that we can close the file.)
+ return list(iter(shlex.shlex(files, file_path, posix=True).get_token,
+ None))
def expand_response_files(files):
diff --git a/validation-test/Sema/type_checker_crashers_fixed/rdar45470505.swift b/validation-test/Sema/type_checker_crashers_fixed/rdar45470505.swift
new file mode 100644
index 0000000..9a760e5
--- /dev/null
+++ b/validation-test/Sema/type_checker_crashers_fixed/rdar45470505.swift
@@ -0,0 +1,16 @@
+// RUN: %target-typecheck-verify-swift
+
+extension BinaryInteger {
+ init(bytes: [UInt8]) { fatalError() }
+
+ init<S: Sequence>(bytes: S) where S.Iterator.Element == UInt8 {
+ self.init(bytes // expected-error {{ambiguous reference to initializer 'init(_:)'}}
+// expected-note@-1 {{}}
+
+extension
+// expected-error@-1 {{declaration is only valid at file scope}}
+// expected-error@-2 {{expected ')' in expression list}}
+// expected-error@-3 {{expected '{' in extension}}
+ }
+// expected-error@-1 {{expected type name in extension declaration}}
+}