Merge pull request #23538 from davezarzycki/diag_qoi_SelfAccessKind
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index c053052..cf59e91 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -4715,7 +4715,7 @@
/// Set \p v to be the pattern produced VarDecl that is the parent of this
/// var decl.
void setParentVarDecl(VarDecl *v) {
- assert(v);
+ assert(v && v != this);
Parent = v;
}
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 7148c1a..408c2ce 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1518,6 +1518,8 @@
"type %0 with constraints specified by a 'where' clause", (Identifier))
ERROR(extension_stored_property,none,
"extensions must not contain stored properties", ())
+NOTE(extension_stored_property_fixit,none,
+ "Remove '=' to make %0 a computed property", (Identifier))
ERROR(extension_nongeneric_trailing_where,none,
"trailing 'where' clause for extension of non-generic type %0",
(DeclName))
diff --git a/include/swift/AST/Stmt.h b/include/swift/AST/Stmt.h
index 18c90e9..4bc0c29 100644
--- a/include/swift/AST/Stmt.h
+++ b/include/swift/AST/Stmt.h
@@ -17,12 +17,13 @@
#ifndef SWIFT_AST_STMT_H
#define SWIFT_AST_STMT_H
+#include "swift/AST/ASTNode.h"
#include "swift/AST/Availability.h"
#include "swift/AST/AvailabilitySpec.h"
-#include "swift/AST/ASTNode.h"
#include "swift/AST/IfConfigClause.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/Basic/NullablePtr.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/TrailingObjects.h"
namespace swift {
@@ -984,24 +985,22 @@
SourceLoc CaseLoc;
SourceLoc ColonLoc;
- llvm::PointerIntPair<Stmt *, 1, bool> BodyAndHasBoundDecls;
+ llvm::PointerIntPair<Stmt *, 1, bool> BodyAndHasFallthrough;
- /// Set to true if we have a fallthrough.
- ///
- /// TODO: Once we have CaseBodyVarDecls, use the bit in BodyAndHasBoundDecls
- /// for this instead. This is separate now for staging reasons.
- bool hasFallthrough;
+ Optional<MutableArrayRef<VarDecl *>> CaseBodyVariables;
CaseStmt(SourceLoc CaseLoc, ArrayRef<CaseLabelItem> CaseLabelItems,
- bool HasBoundDecls, SourceLoc UnknownAttrLoc, SourceLoc ColonLoc,
- Stmt *Body, Optional<bool> Implicit,
+ SourceLoc UnknownAttrLoc, SourceLoc ColonLoc, Stmt *Body,
+ Optional<MutableArrayRef<VarDecl *>> CaseBodyVariables,
+ Optional<bool> Implicit,
NullablePtr<FallthroughStmt> fallthroughStmt);
public:
static CaseStmt *
create(ASTContext &C, SourceLoc CaseLoc,
- ArrayRef<CaseLabelItem> CaseLabelItems, bool HasBoundDecls,
- SourceLoc UnknownAttrLoc, SourceLoc ColonLoc, Stmt *Body,
+ ArrayRef<CaseLabelItem> CaseLabelItems, SourceLoc UnknownAttrLoc,
+ SourceLoc ColonLoc, Stmt *Body,
+ Optional<MutableArrayRef<VarDecl *>> CaseBodyVariables,
Optional<bool> Implicit = None,
NullablePtr<FallthroughStmt> fallthroughStmt = nullptr);
@@ -1020,18 +1019,18 @@
}
NullablePtr<CaseStmt> getFallthroughDest() {
- if (!hasFallthrough)
+ if (!hasFallthroughDest())
return nullptr;
return (*getTrailingObjects<FallthroughStmt *>())->getFallthroughDest();
}
- bool hasFallthroughDest() const { return hasFallthrough; }
+ bool hasFallthroughDest() const { return BodyAndHasFallthrough.getInt(); }
- Stmt *getBody() const { return BodyAndHasBoundDecls.getPointer(); }
- void setBody(Stmt *body) { BodyAndHasBoundDecls.setPointer(body); }
+ Stmt *getBody() const { return BodyAndHasFallthrough.getPointer(); }
+ void setBody(Stmt *body) { BodyAndHasFallthrough.setPointer(body); }
/// True if the case block declares any patterns with local variable bindings.
- bool hasBoundDecls() const { return BodyAndHasBoundDecls.getInt(); }
+ bool hasBoundDecls() const { return CaseBodyVariables.hasValue(); }
/// Get the source location of the 'case' or 'default' of the first label.
SourceLoc getLoc() const { return CaseLoc; }
@@ -1056,6 +1055,30 @@
return UnknownAttrLoc.isValid();
}
+ Optional<ArrayRef<VarDecl *>> getCaseBodyVariables() const {
+ if (!CaseBodyVariables)
+ return None;
+ ArrayRef<VarDecl *> a = *CaseBodyVariables;
+ return a;
+ }
+
+ Optional<MutableArrayRef<VarDecl *>> getCaseBodyVariables() {
+ return CaseBodyVariables;
+ }
+
+ ArrayRef<VarDecl *> getCaseBodyVariablesOrEmptyArray() const {
+ if (!CaseBodyVariables)
+ return ArrayRef<VarDecl *>();
+ ArrayRef<VarDecl *> a = *CaseBodyVariables;
+ return a;
+ }
+
+ MutableArrayRef<VarDecl *> getCaseBodyVariablesOrEmptyArray() {
+ if (!CaseBodyVariables)
+ return MutableArrayRef<VarDecl *>();
+ return *CaseBodyVariables;
+ }
+
static bool classof(const Stmt *S) { return S->getKind() == StmtKind::Case; }
size_t numTrailingObjects(OverloadToken<CaseLabelItem>) const {
@@ -1063,7 +1086,7 @@
}
size_t numTrailingObjects(OverloadToken<FallthroughStmt *>) const {
- return hasFallthrough ? 1 : 0;
+ return hasFallthroughDest() ? 1 : 0;
}
};
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 62df272..a3e80f1 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -1619,6 +1619,24 @@
printCommon(S, "case_stmt");
if (S->hasUnknownAttr())
OS << " @unknown";
+
+ if (auto caseBodyVars = S->getCaseBodyVariables()) {
+ OS << '\n';
+ OS.indent(Indent + 2);
+ PrintWithColorRAII(OS, ParenthesisColor) << '(';
+ PrintWithColorRAII(OS, StmtColor) << "case_body_variables";
+ OS << '\n';
+ for (auto *vd : *caseBodyVars) {
+ OS.indent(2);
+ // TODO: Printing a var decl does an Indent ... dump(vd) ... '\n'. We
+ // should see if we can factor this dumping so that the caller of
+ // printRec(VarDecl) has more control over the printing.
+ printRec(vd);
+ }
+ OS.indent(Indent + 2);
+ PrintWithColorRAII(OS, ParenthesisColor) << ')';
+ }
+
for (const auto &LabelItem : S->getCaseLabelItems()) {
OS << '\n';
OS.indent(Indent + 2);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 110228d..aa63c1d 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -4931,11 +4931,22 @@
static Optional<std::pair<CaseStmt *, Pattern *>>
findParentPatternCaseStmtAndPattern(const VarDecl *inputVD) {
auto getMatchingPattern = [&](CaseStmt *cs) -> Pattern * {
+ // Check if inputVD is in our case body var decls if we have any. If we do,
+ // treat its pattern as our first case label item pattern.
+ for (auto *vd : cs->getCaseBodyVariablesOrEmptyArray()) {
+ if (vd == inputVD) {
+ return cs->getMutableCaseLabelItems().front().getPattern();
+ }
+ }
+
+ // Then check the rest of our case label items.
for (auto &item : cs->getMutableCaseLabelItems()) {
if (isVarInPattern(inputVD, item.getPattern())) {
return item.getPattern();
}
}
+
+ // Otherwise return false if we do not find anything.
return nullptr;
};
@@ -4969,9 +4980,16 @@
if (!vd)
return cur;
+#ifndef NDEBUG
+ // Make sure that we don't get into an infinite loop.
+ SmallPtrSet<VarDecl *, 8> visitedDecls;
+ visitedDecls.insert(vd);
+ visitedDecls.insert(cur);
+#endif
while (vd) {
cur = vd;
vd = vd->getParentVarDecl();
+ assert((!vd || visitedDecls.insert(vd).second) && "Infinite loop ?!");
}
return cur;
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 7af14c4..4ae975a 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -386,43 +386,50 @@
}
CaseStmt::CaseStmt(SourceLoc caseLoc, ArrayRef<CaseLabelItem> caseLabelItems,
- bool hasBoundDecls, SourceLoc unknownAttrLoc,
- SourceLoc colonLoc, Stmt *body, Optional<bool> implicit,
+ SourceLoc unknownAttrLoc, SourceLoc colonLoc, Stmt *body,
+ Optional<MutableArrayRef<VarDecl *>> caseBodyVariables,
+ Optional<bool> implicit,
NullablePtr<FallthroughStmt> fallthroughStmt)
: Stmt(StmtKind::Case, getDefaultImplicitFlag(implicit, caseLoc)),
UnknownAttrLoc(unknownAttrLoc), CaseLoc(caseLoc), ColonLoc(colonLoc),
- BodyAndHasBoundDecls(body, hasBoundDecls),
- hasFallthrough(fallthroughStmt.isNonNull()) {
+ BodyAndHasFallthrough(body, fallthroughStmt.isNonNull()),
+ CaseBodyVariables(caseBodyVariables) {
Bits.CaseStmt.NumPatterns = caseLabelItems.size();
assert(Bits.CaseStmt.NumPatterns > 0 &&
"case block must have at least one pattern");
- if (hasFallthrough) {
+ if (hasFallthroughDest()) {
*getTrailingObjects<FallthroughStmt *>() = fallthroughStmt.get();
}
MutableArrayRef<CaseLabelItem> items{getTrailingObjects<CaseLabelItem>(),
Bits.CaseStmt.NumPatterns};
+ // At the beginning mark all of our var decls as being owned by this
+ // statement. In the typechecker we wireup the case stmt var decl list since
+ // we know everything is lined up/typechecked then.
for (unsigned i : range(Bits.CaseStmt.NumPatterns)) {
new (&items[i]) CaseLabelItem(caseLabelItems[i]);
items[i].getPattern()->markOwnedByStatement(this);
}
+ for (auto *vd : caseBodyVariables.getValueOr(MutableArrayRef<VarDecl *>())) {
+ vd->setParentPatternStmt(this);
+ }
}
CaseStmt *CaseStmt::create(ASTContext &ctx, SourceLoc caseLoc,
ArrayRef<CaseLabelItem> caseLabelItems,
- bool hasBoundDecls, SourceLoc unknownAttrLoc,
- SourceLoc colonLoc, Stmt *body,
+ SourceLoc unknownAttrLoc, SourceLoc colonLoc,
+ Stmt *body,
+ Optional<MutableArrayRef<VarDecl *>> caseVarDecls,
Optional<bool> implicit,
NullablePtr<FallthroughStmt> fallthroughStmt) {
void *mem =
ctx.Allocate(totalSizeToAlloc<FallthroughStmt *, CaseLabelItem>(
fallthroughStmt.isNonNull(), caseLabelItems.size()),
alignof(CaseStmt));
- return ::new (mem)
- CaseStmt(caseLoc, caseLabelItems, hasBoundDecls, unknownAttrLoc, colonLoc,
- body, implicit, fallthroughStmt);
+ return ::new (mem) CaseStmt(caseLoc, caseLabelItems, unknownAttrLoc, colonLoc,
+ body, caseVarDecls, implicit, fallthroughStmt);
}
SwitchStmt *SwitchStmt::create(LabeledStmtInfo LabelInfo, SourceLoc SwitchLoc,
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 6b3adaf..54c54c9 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -2295,10 +2295,11 @@
return Status;
}
-static ParserStatus parseStmtCase(Parser &P, SourceLoc &CaseLoc,
- SmallVectorImpl<CaseLabelItem> &LabelItems,
- SmallVectorImpl<VarDecl *> &BoundDecls,
- SourceLoc &ColonLoc) {
+static ParserStatus
+parseStmtCase(Parser &P, SourceLoc &CaseLoc,
+ SmallVectorImpl<CaseLabelItem> &LabelItems,
+ SmallVectorImpl<VarDecl *> &BoundDecls, SourceLoc &ColonLoc,
+ Optional<MutableArrayRef<VarDecl *>> &CaseBodyDecls) {
SyntaxParsingContext CaseContext(P.SyntaxContext,
SyntaxKind::SwitchCaseLabel);
ParserStatus Status;
@@ -2314,13 +2315,28 @@
GuardedPattern PatternResult;
parseGuardedPattern(P, PatternResult, Status, BoundDecls,
GuardedPatternContext::Case, isFirst);
- LabelItems.push_back(
- CaseLabelItem(PatternResult.ThePattern, PatternResult.WhereLoc,
- PatternResult.Guard));
+ LabelItems.emplace_back(PatternResult.ThePattern, PatternResult.WhereLoc,
+ PatternResult.Guard);
isFirst = false;
if (!P.consumeIf(tok::comma))
break;
}
+
+ // Grab the first case label item pattern and use it to initialize the case
+ // body var decls.
+ SmallVector<VarDecl *, 4> tmp;
+ LabelItems.front().getPattern()->collectVariables(tmp);
+ auto Result = P.Context.AllocateUninitialized<VarDecl *>(tmp.size());
+ for (unsigned i : indices(tmp)) {
+ auto *vOld = tmp[i];
+ auto *vNew = new (P.Context) VarDecl(
+ /*IsStatic*/ false, vOld->getSpecifier(), false /*IsCaptureList*/,
+ vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
+ vNew->setHasNonPatternBindingInit();
+ vNew->setImplicit();
+ Result[i] = vNew;
+ }
+ CaseBodyDecls.emplace(Result);
}
ColonLoc = P.Tok.getLoc();
@@ -2448,9 +2464,10 @@
SourceLoc CaseLoc;
SourceLoc ColonLoc;
+ Optional<MutableArrayRef<VarDecl *>> CaseBodyDecls;
if (Tok.is(tok::kw_case)) {
- Status |=
- ::parseStmtCase(*this, CaseLoc, CaseLabelItems, BoundDecls, ColonLoc);
+ Status |= ::parseStmtCase(*this, CaseLoc, CaseLabelItems, BoundDecls,
+ ColonLoc, CaseBodyDecls);
} else if (Tok.is(tok::kw_default)) {
Status |= parseStmtCaseDefault(*this, CaseLoc, CaseLabelItems, ColonLoc);
} else {
@@ -2480,10 +2497,9 @@
}
return makeParserResult(
- Status,
- CaseStmt::create(Context, CaseLoc, CaseLabelItems, !BoundDecls.empty(),
- UnknownAttrLoc, ColonLoc, Body, None,
- FallthroughFinder::findFallthrough(Body)));
+ Status, CaseStmt::create(Context, CaseLoc, CaseLabelItems, UnknownAttrLoc,
+ ColonLoc, Body, CaseBodyDecls, None,
+ FallthroughFinder::findFallthrough(Body)));
}
/// stmt-pound-assert:
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 4200a6f..a5adb30 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -4184,7 +4184,16 @@
auto keyPathTy = cs.getType(E)->castTo<BoundGenericType>();
Type baseTy = keyPathTy->getGenericArgs()[0];
Type leafTy = keyPathTy->getGenericArgs()[1];
-
+
+ // We do not allow keypaths to go through AnyObject
+ if (baseTy->isAnyObject()) {
+ auto rootTyRepr = E->getRootType();
+ cs.TC.diagnose(rootTyRepr->getLoc(),
+ diag::expr_swift_keypath_invalid_component)
+ .highlight(rootTyRepr->getSourceRange());
+ return nullptr;
+ }
+
for (unsigned i : indices(E->getComponents())) {
auto &origComponent = E->getMutableComponents()[i];
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 0f4f99a..fd43424 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -2315,16 +2315,21 @@
exprType->isEqual(contextualType)) {
return false;
}
-
+
// If we're trying to convert something of type "() -> T" to T, then we
// probably meant to call the value.
if (auto srcFT = exprType->getAs<AnyFunctionType>()) {
if (srcFT->getParams().empty() &&
!isUnresolvedOrTypeVarType(srcFT->getResult()) &&
CS.TC.isConvertibleTo(srcFT->getResult(), contextualType, CS.DC)) {
- diagnose(expr->getLoc(), diag::missing_nullary_call, srcFT->getResult())
- .highlight(expr->getSourceRange())
- .fixItInsertAfter(expr->getEndLoc(), "()");
+
+ auto locator =
+ CS.getConstraintLocator(expr, ConstraintLocator::ContextualType);
+ ContextualFailure failure =
+ ContextualFailure(nullptr, CS, srcFT, contextualType, locator);
+ auto diagnosed = failure.diagnoseAsError();
+ assert(diagnosed && "Failed to produce contextual failure diagnostic");
+ (void)diagnosed;
return true;
}
}
diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp
index d8dafda..7ebacdf 100644
--- a/lib/Sema/CSDiagnostics.cpp
+++ b/lib/Sema/CSDiagnostics.cpp
@@ -22,6 +22,7 @@
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericSignature.h"
+#include "swift/AST/Initializer.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/ProtocolConformance.h"
@@ -1348,6 +1349,9 @@
srcFT->getResult())
.highlight(anchor->getSourceRange())
.fixItInsertAfter(anchor->getEndLoc(), "()");
+
+ tryComputedPropertyFixIts(anchor);
+
return true;
}
@@ -1378,6 +1382,53 @@
return false;
}
+void ContextualFailure::tryComputedPropertyFixIts(Expr *expr) const {
+ if (!isa<ClosureExpr>(expr))
+ return;
+
+ // It is possible that we're looking at a stored property being
+ // initialized with a closure. Something like:
+ //
+ // var foo: Int = { return 0 }
+ //
+ // Let's offer another fix-it to remove the '=' to turn the stored
+ // property into a computed property. If the variable is immutable, then
+ // replace the 'let' with a 'var'.
+
+ PatternBindingDecl *PBD = nullptr;
+
+ if (auto TLCD = dyn_cast<TopLevelCodeDecl>(getDC())) {
+ if (TLCD->getBody()->isImplicit()) {
+ if (auto decl = TLCD->getBody()->getElement(0).dyn_cast<Decl *>()) {
+ if (auto binding = dyn_cast<PatternBindingDecl>(decl)) {
+ PBD = binding;
+ }
+ }
+ }
+ } else if (auto PBI = dyn_cast<PatternBindingInitializer>(getDC())) {
+ PBD = PBI->getBinding();
+ }
+
+ if (PBD) {
+ if (auto VD = PBD->getSingleVar()) {
+ auto entry = PBD->getPatternEntryForVarDecl(VD);
+
+ if (!VD->isStatic() &&
+ !VD->getAttrs().getAttribute<DynamicReplacementAttr>() &&
+ entry.getInit() && isa<ClosureExpr>(entry.getInit())) {
+ auto diag = emitDiagnostic(expr->getLoc(),
+ diag::extension_stored_property_fixit,
+ VD->getName());
+ diag.fixItRemove(entry.getEqualLoc());
+
+ if (VD->isLet()) {
+ diag.fixItReplace(PBD->getStartLoc(), getTokenText(tok::kw_var));
+ }
+ }
+ }
+ }
+}
+
bool AutoClosureForwardingFailure::diagnoseAsError() {
auto path = getLocator()->getPath();
assert(!path.empty());
diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h
index ddf802e..aa2fb07 100644
--- a/lib/Sema/CSDiagnostics.h
+++ b/lib/Sema/CSDiagnostics.h
@@ -681,6 +681,10 @@
}
return type;
}
+
+ /// Try to add a fix-it to convert a stored property into a computed
+ /// property
+ void tryComputedPropertyFixIts(Expr *expr) const;
};
/// Diagnose situations when @autoclosure argument is passed to @autoclosure
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 32adf08..a4af6bd 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1989,6 +1989,17 @@
break;
}
+ case ConstraintLocator::ContextualType: {
+ if (lhs->is<FunctionType>() && !rhs->is<AnyFunctionType>() &&
+ isa<ClosureExpr>(anchor)) {
+ auto *fix = ContextualMismatch::create(cs, lhs, rhs,
+ cs.getConstraintLocator(locator));
+ conversionsOrFixes.push_back(fix);
+ }
+
+ break;
+ }
+
default:
return;
}
diff --git a/lib/Sema/DerivedConformanceCodingKey.cpp b/lib/Sema/DerivedConformanceCodingKey.cpp
index 6d019f4..3e03e99 100644
--- a/lib/Sema/DerivedConformanceCodingKey.cpp
+++ b/lib/Sema/DerivedConformanceCodingKey.cpp
@@ -235,9 +235,9 @@
auto *returnStmt = new (C) ReturnStmt(SourceLoc(), caseValue);
auto *caseBody = BraceStmt::create(C, SourceLoc(), ASTNode(returnStmt),
SourceLoc());
- cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem,
- /*HasBoundDecls=*/false, SourceLoc(),
- SourceLoc(), caseBody));
+ cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, SourceLoc(),
+ SourceLoc(), caseBody,
+ /*case body var decls*/ None));
}
auto *selfRef = DerivedConformance::createSelfDeclRef(strValDecl);
@@ -303,9 +303,9 @@
auto *body = BraceStmt::create(C, SourceLoc(), ASTNode(assignment),
SourceLoc());
- cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem,
- /*HasBoundDecls=*/false, SourceLoc(),
- SourceLoc(), body));
+ cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, SourceLoc(),
+ SourceLoc(), body,
+ /*case body var decls*/ None));
}
auto *anyPat = new (C) AnyPattern(SourceLoc());
@@ -315,9 +315,9 @@
auto *dfltReturnStmt = new (C) FailStmt(SourceLoc(), SourceLoc());
auto *dfltBody = BraceStmt::create(C, SourceLoc(), ASTNode(dfltReturnStmt),
SourceLoc());
- cases.push_back(CaseStmt::create(C, SourceLoc(), dfltLabelItem,
- /*HasBoundDecls=*/false, SourceLoc(),
- SourceLoc(), dfltBody));
+ cases.push_back(CaseStmt::create(C, SourceLoc(), dfltLabelItem, SourceLoc(),
+ SourceLoc(), dfltBody,
+ /*case body var decls*/ None));
auto *stringValueDecl = initDecl->getParameters()->get(0);
auto *stringValueRef = new (C) DeclRefExpr(stringValueDecl, DeclNameLoc(),
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 8ba8b0a..0e4ee57 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -246,9 +246,9 @@
indexExpr, /*implicit*/ true);
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(assignExpr),
SourceLoc());
- cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem,
- /*HasBoundDecls=*/false, SourceLoc(),
- SourceLoc(), body));
+ cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, SourceLoc(),
+ SourceLoc(), body,
+ /*case body vardecls*/ None));
}
// generate: switch enumVar { }
@@ -434,6 +434,22 @@
rhsElemPat->setImplicit();
auto hasBoundDecls = !lhsPayloadVars.empty();
+ Optional<MutableArrayRef<VarDecl *>> caseBodyVarDecls;
+ if (hasBoundDecls) {
+ // We allocated a direct copy of our lhs var decls for the case
+ // body.
+ auto copy = C.Allocate<VarDecl *>(lhsPayloadVars.size());
+ for (unsigned i : indices(lhsPayloadVars)) {
+ auto *vOld = lhsPayloadVars[i];
+ auto *vNew = new (C) VarDecl(
+ /*IsStatic*/ false, vOld->getSpecifier(), false /*IsCaptureList*/,
+ vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
+ vNew->setHasNonPatternBindingInit();
+ vNew->setImplicit();
+ copy[i] = vNew;
+ }
+ caseBodyVarDecls.emplace(copy);
+ }
// case (.<elt>(let l0, let l1, ...), .<elt>(let r0, let r1, ...))
auto caseTuplePattern = TuplePattern::create(C, SourceLoc(), {
@@ -469,8 +485,8 @@
auto body = BraceStmt::create(C, SourceLoc(), statementsInCase,
SourceLoc());
- cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, hasBoundDecls,
- SourceLoc(), SourceLoc(), body));
+ cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, SourceLoc(),
+ SourceLoc(), body, caseBodyVarDecls));
}
// default: result = false
@@ -486,9 +502,9 @@
auto returnStmt = new (C) ReturnStmt(SourceLoc(), falseExpr);
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(returnStmt),
SourceLoc());
- cases.push_back(CaseStmt::create(C, SourceLoc(), defaultItem,
- /*HasBoundDecls*/ false,
- SourceLoc(), SourceLoc(), body));
+ cases.push_back(CaseStmt::create(C, SourceLoc(), defaultItem, SourceLoc(),
+ SourceLoc(), body,
+ /*case body var decls*/ None));
}
// switch (a, b) { <case statements> }
@@ -960,9 +976,24 @@
}
auto hasBoundDecls = !payloadVars.empty();
+ Optional<MutableArrayRef<VarDecl *>> caseBodyVarDecls;
+ if (hasBoundDecls) {
+ auto copy = C.Allocate<VarDecl *>(payloadVars.size());
+ for (unsigned i : indices(payloadVars)) {
+ auto *vOld = payloadVars[i];
+ auto *vNew = new (C) VarDecl(
+ /*IsStatic*/ false, vOld->getSpecifier(), false /*IsCaptureList*/,
+ vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
+ vNew->setHasNonPatternBindingInit();
+ vNew->setImplicit();
+ copy[i] = vNew;
+ }
+ caseBodyVarDecls.emplace(copy);
+ }
+
auto body = BraceStmt::create(C, SourceLoc(), statements, SourceLoc());
- cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, hasBoundDecls,
- SourceLoc(), SourceLoc(), body,
+ cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, SourceLoc(),
+ SourceLoc(), body, caseBodyVarDecls,
/*implicit*/ true));
}
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index 25b9887..5e26678 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -129,9 +129,9 @@
auto body = BraceStmt::create(C, SourceLoc(),
ASTNode(returnStmt), SourceLoc());
- cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem,
- /*HasBoundDecls=*/false, SourceLoc(),
- SourceLoc(), body));
+ cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, SourceLoc(),
+ SourceLoc(), body,
+ /*case body var decls*/ None));
}
auto selfRef = DerivedConformance::createSelfDeclRef(toRawDecl);
@@ -368,8 +368,8 @@
// cases.append("case \(litPat): \(body)")
cases.push_back(CaseStmt::create(C, SourceLoc(), CaseLabelItem(litPat),
- /*HasBoundDecls=*/false, SourceLoc(),
- SourceLoc(), body));
+ SourceLoc(), SourceLoc(), body,
+ /*case body var decls*/ None));
Idx++;
}
@@ -380,9 +380,9 @@
auto dfltReturnStmt = new (C) FailStmt(SourceLoc(), SourceLoc());
auto dfltBody = BraceStmt::create(C, SourceLoc(),
ASTNode(dfltReturnStmt), SourceLoc());
- cases.push_back(CaseStmt::create(C, SourceLoc(), dfltLabelItem,
- /*HasBoundDecls=*/false, SourceLoc(),
- SourceLoc(), dfltBody));
+ cases.push_back(CaseStmt::create(C, SourceLoc(), dfltLabelItem, SourceLoc(),
+ SourceLoc(), dfltBody,
+ /*case body var decls*/ None));
auto rawDecl = initDecl->getParameters()->get(0);
auto rawRef = new (C) DeclRefExpr(rawDecl, DeclNameLoc(), /*implicit*/true);
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 6fe996a..b2e09ea 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -1121,13 +1121,12 @@
SmallVector<VarDecl *, 4> vars;
firstPattern->collectVariables(vars);
- // We know that the typechecker will guarantee that all of the case label
- // items in the fallthrough match. So if we match the last case label item,
- // transitively we will match all of the other case label items.
- auto &labelItem = previousBlock->getCaseLabelItems().back();
- const Pattern *pattern = labelItem.getPattern();
- SmallVector<VarDecl *, 4> previousVars;
- pattern->collectVariables(previousVars);
+ // We know that the typechecker has already guaranteed that all of
+ // the case label items in the fallthrough have the same var
+ // decls. So if we match against the case body var decls,
+ // transitively we will match all of the other case label items in
+ // the fallthrough destination as well.
+ auto previousVars = previousBlock->getCaseBodyVariablesOrEmptyArray();
for (auto *expected : vars) {
bool matched = false;
if (!expected->hasName())
@@ -1228,6 +1227,21 @@
}
}
+ // Setup the types of our case body var decls.
+ for (auto *expected : caseBlock->getCaseBodyVariablesOrEmptyArray()) {
+ assert(expected->hasName());
+ for (auto *prev : *prevCaseDecls) {
+ if (!prev->hasName() || expected->getName() != prev->getName()) {
+ continue;
+ }
+ if (prev->hasType())
+ expected->setType(prev->getType());
+ if (prev->hasInterfaceType())
+ expected->setInterfaceType(prev->getInterfaceType());
+ break;
+ }
+ }
+
// Then check the rest.
for (auto &labelItem : caseLabelItemArray.drop_front()) {
// Resolve the pattern in our case label if it has not been resolved
@@ -1241,6 +1255,32 @@
}
}
+ // Our last CaseLabelItem's VarDecls are now in
+ // prevCaseDecls. Wire them up as parents of our case body var
+ // decls.
+ //
+ // NOTE: We know that the two lists of var decls must be in sync. Remember
+ // that we constructed our case body VarDecls from the first
+ // CaseLabelItems var decls. Just now we proved that all other
+ // CaseLabelItems have matching var decls of the first meaning
+ // transitively that our last case label item must have matching var decls
+ // for our case stmts CaseBodyVarDecls.
+ //
+ // NOTE: We do not check that we matched everything here. That is because
+ // the check has already been done by comparing the 1st CaseLabelItem var
+ // decls. If we insert a check here, we will emit the same error multiple
+ // times.
+ for (auto *expected : caseBlock->getCaseBodyVariablesOrEmptyArray()) {
+ assert(expected->hasName());
+ for (auto *prev : *prevCaseDecls) {
+ if (!prev->hasName() || expected->getName() != prev->getName()) {
+ continue;
+ }
+ expected->setParentVarDecl(prev);
+ break;
+ }
+ }
+
// Check restrictions on '@unknown'.
if (caseBlock->hasUnknownAttr()) {
checkUnknownAttrRestrictions(caseBlock, limitExhaustivityChecks);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b985d12..539a0c2 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -305,10 +305,15 @@
set(test_mode_target_suffix "-${test_mode}")
endif()
+ set(maybe_command_upload_stdlib)
+ if(NOT test_mode STREQUAL "only_non_executable")
+ set(maybe_command_upload_stdlib ${command_upload_stdlib})
+ endif()
+
set(test_target_name
"check-swift${test_subset_target_suffix}${test_mode_target_suffix}${VARIANT_SUFFIX}")
add_custom_target("${test_target_name}"
- ${command_upload_stdlib}
+ ${maybe_command_upload_stdlib}
${command_upload_swift_reflection_test}
${command_clean_test_results_dir}
COMMAND
diff --git a/test/Parse/objc_enum.swift b/test/Parse/objc_enum.swift
index c506dee..ee8da9a 100644
--- a/test/Parse/objc_enum.swift
+++ b/test/Parse/objc_enum.swift
@@ -8,7 +8,7 @@
case Zim, Zang, Zung
}
-@objc(EnumRuntimeName) enum RuntimeNamed: Int {
+@objc(EnumRuntimeName) enum RuntimeNamed: Int32 {
case Zim, Zang, Zung
}
diff --git a/test/decl/var/properties.swift b/test/decl/var/properties.swift
index 40a457e..4dc7294 100644
--- a/test/decl/var/properties.swift
+++ b/test/decl/var/properties.swift
@@ -1277,3 +1277,32 @@
let sr8811c = (16, fatalError()) // expected-warning {{constant 'sr8811c' inferred to have type '(Int, Never)', which contains an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}}
let sr8811d: (Int, Never) = (16, fatalError()) // Ok
+
+// SR-9267
+
+class SR_9267 {}
+extension SR_9267 {
+ var foo: String = { // expected-error {{extensions must not contain stored properties}} // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'foo' a computed property}}{{19-21=}}
+ return "Hello"
+ }
+}
+
+enum SR_9267_E {
+ var SR_9267_prop: String = { // expected-error {{enums must not contain stored properties}} // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop' a computed property}}{{28-30=}}
+ return "Hello"
+ }
+}
+
+var SR_9267_prop_1: Int = { // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_1' a computed property}}{{25-27=}}
+ return 0
+}
+
+class SR_9267_C {
+ var SR_9267_prop_2: String = { // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_2' a computed property}}{{30-32=}}
+ return "Hello"
+ }
+}
+
+class SR_9267_C2 {
+ let SR_9267_prop_3: Int = { return 0 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_3' a computed property}}{{3-6=var}}{{27-29=}}
+}
diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift
index 4fa45e8..f116a0e 100644
--- a/test/expr/closure/closures.swift
+++ b/test/expr/closure/closures.swift
@@ -20,8 +20,7 @@
var closure6 = $0 // expected-error {{anonymous closure argument not contained in a closure}}
-var closure7 : Int =
- { 4 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} {{9-9=()}}
+var closure7 : Int = { 4 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} {{27-27=()}} // expected-note {{Remove '=' to make 'closure7' a computed property}}{{20-22=}}
var capturedVariable = 1
var closure8 = { [capturedVariable] in
diff --git a/test/lit.cfg b/test/lit.cfg
index 3ea7670..abde2f9 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -946,7 +946,7 @@
def get_architecture_value(**kwargs):
result = kwargs[run_cpu]
if result is None:
- if run_cpu == "armv7s" or run_cpu == "armv7k":
+ if run_cpu.startswith("armv7"):
result = kwargs["armv7"]
elif run_cpu == "arm64":
result = kwards["aarch64"]
@@ -957,9 +957,22 @@
ndk_platform_triple = get_architecture_value(armv7="arm-linux-androideabi",
aarch64="aarch64-linux-android")
toolchain_directory_name = "{}-{}".format(ndk_platform_triple, config.android_ndk_gcc_version)
- tools_directory = make_path(config.android_ndk_path, "toolchains",
- toolchain_directory_name, "prebuilt", "linux-x86_64",
- ndk_platform_triple, "bin")
+ if platform.system() == 'Linux':
+ prebuilt_directory = 'linux-x86_64'
+ elif platform.system() == 'Darwin':
+ prebuilt_directory = 'darwin-x86_64'
+ elif platform.system() == 'Windows':
+ # TODO: NDK distributes for Windows 32 and 64 bits. platform.machine()
+ # should allow us to find out the word size, but I don't have a
+ # machine to test right now. I think the values are AMD64 and x86, but
+ # I'm not sure. Everybody gets the 64 bits version for now.
+ prebuilt_directory = 'windows-x86_64'
+
+ toolchain_directory = make_path(
+ config.android_ndk_path, "toolchains", toolchain_directory_name,
+ "prebuilt", prebuilt_directory)
+ tools_directory = pipes.quote(make_path(
+ toolchain_directory, ndk_platform_triple, "bin"))
lit_config.note("Testing Android " + config.variant_triple)
config.target_object_format = "elf"
config.target_shared_library_prefix = 'lib'
@@ -971,69 +984,85 @@
config.target_runtime = "native"
config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract")
config.target_sdk_name = "android"
- android_link_paths_opt = "-L {libcxx} -L {libgcc}".format(
- libcxx=make_path(config.android_ndk_path,
- "sources", "cxx-stl", "llvm-libc++", "libs", ndk_platform_tuple),
- libgcc=make_path(config.android_ndk_path,
- "toolchains", toolchain_directory_name, "prebuilt",
- "linux-x86_64", "lib", "gcc", ndk_platform_triple,
- "{}.x".format(config.android_ndk_gcc_version)))
+ android_link_paths_opt = "-L {} -L {} -L {}".format(
+ pipes.quote(make_path(
+ config.android_ndk_path, "sources", "cxx-stl", "llvm-libc++",
+ "libs", ndk_platform_tuple)),
+ pipes.quote(make_path(
+ toolchain_directory, "lib", "gcc", ndk_platform_triple,
+ "{}.x".format(config.android_ndk_gcc_version))),
+ pipes.quote(make_path(
+ toolchain_directory, ndk_platform_triple, "lib")))
# Since NDK r14 the headers are unified under $NDK_PATH/sysroot, so the -sdk
# switch is not enough. Additionally we have to include both the unified
# sysroot, and the architecture sysroot.
- android_include_paths_opt = "-I {sysroot} -I {sysroot_arch}".format(
- sysroot=make_path(config.android_ndk_path, "sysroot", "usr", "include"),
- sysroot_arch=make_path(config.android_ndk_path, "sysroot", "usr",
- "include", ndk_platform_triple))
- config.target_build_swift = (
- '%s -target %s -sdk %r -tools-directory %r %s %s '
- '-use-ld=%s %s %s %s %s %s'
- % (config.swiftc,
- config.variant_triple, config.variant_sdk,
- tools_directory, android_include_paths_opt, android_link_paths_opt,
- config.android_linker_name,
- resource_dir_opt, mcp_opt, config.swift_test_options,
- config.swift_driver_test_options, swift_execution_tests_extra_flags))
+ unified_android_include_path = pipes.quote(make_path(
+ config.android_ndk_path, "sysroot", "usr", "include"))
+ architecture_android_include_path = pipes.quote(make_path(
+ config.android_ndk_path, "sysroot", "usr", "include",
+ ndk_platform_triple))
+ android_include_paths_opt = "-I {} -I {}".format(
+ unified_android_include_path, architecture_android_include_path)
+ # clang can use -isystem, but Swift cannot.
+ android_include_system_paths_opt = "-isystem {} -isystem {}".format(
+ unified_android_include_path, architecture_android_include_path)
+ config.target_build_swift = ' '.join([
+ config.swiftc,
+ '-target', config.variant_triple,
+ '-sdk', config.variant_sdk,
+ '-tools-directory', tools_directory,
+ android_include_paths_opt, android_link_paths_opt,
+ '-use-ld=%s' % config.android_linker_name,
+ resource_dir_opt, mcp_opt, config.swift_test_options,
+ config.swift_driver_test_options, swift_execution_tests_extra_flags])
config.target_codesign = "echo"
- config.target_build_swift_dylib = (
- "%s -parse-as-library -emit-library -o '\\1'"
- % (config.target_build_swift))
+ config.target_build_swift_dylib = ' '.join([
+ config.target_build_swift,
+ '-parse-as-library', '-emit-library',
+ '-o', "'\\1'"])
config.target_add_rpath = r'-Xlinker -rpath -Xlinker \1'
- config.target_swift_frontend = (
- '%s -frontend -target %s -sdk %r %s %s %s %s %s %s'
- % (config.swift, config.variant_triple, config.variant_sdk,
- android_include_paths_opt, android_link_paths_opt, resource_dir_opt,
- mcp_opt, config.swift_test_options,
- config.swift_frontend_test_options))
+ config.target_swift_frontend = ' '.join([
+ config.swift,
+ '-frontend',
+ '-target', config.variant_triple,
+ '-sdk', config.variant_sdk,
+ android_include_paths_opt, android_link_paths_opt,
+ resource_dir_opt, mcp_opt, config.swift_test_options,
+ config.swift_frontend_test_options])
subst_target_swift_frontend_mock_sdk = config.target_swift_frontend
subst_target_swift_frontend_mock_sdk_after = ""
config.target_run = make_path(config.swift_src_root, 'utils', 'android', 'adb_test_runner.py')
# FIXME: Include -sdk in this invocation.
- config.target_sil_opt = (
- '%s -target %s %s %s %s' %
- (config.sil_opt, config.variant_triple, resource_dir_opt, mcp_opt, config.sil_test_options))
- config.target_swift_ide_test = (
- '%s -target %s %s %s %s' %
- (config.swift_ide_test, config.variant_triple, resource_dir_opt,
- mcp_opt, ccp_opt))
+ config.target_sil_opt = ' '.join([
+ config.sil_opt,
+ '-target', config.variant_triple,
+ resource_dir_opt, mcp_opt, config.sil_test_options])
+ config.target_swift_ide_test = ' '.join([
+ config.swift_ide_test,
+ '-target', config.variant_triple,
+ resource_dir_opt, mcp_opt, ccp_opt])
subst_target_swift_ide_test_mock_sdk = config.target_swift_ide_test
subst_target_swift_ide_test_mock_sdk_after = ""
- config.target_swiftc_driver = (
- "%s -target %s -sdk %r -tools-directory %s %s %s %s -use-ld=%s" %
- (config.swiftc, config.variant_triple, config.variant_sdk,
- tools_directory, android_link_paths_opt, resource_dir_opt, mcp_opt,
- config.android_linker_name))
- config.target_swift_modulewrap = (
- '%s -modulewrap -target %s' %
- (config.swiftc, config.variant_triple))
- config.target_clang = (
- "clang++ -target %s %s %s" %
- (config.variant_triple, clang_mcp_opt, android_include_paths_opt))
- config.target_ld = "{} -L{}".format(
+ config.target_swiftc_driver = ' '.join([
+ config.swiftc,
+ '-target', config.variant_triple,
+ '-sdk', config.variant_sdk,
+ '-tools-directory', tools_directory,
+ android_link_paths_opt, resource_dir_opt, mcp_opt,
+ '-use-ld=%s' % config.android_linker_name])
+ config.target_swift_modulewrap = ' '.join([
+ config.swiftc, '-modulewrap',
+ '-target', config.variant_triple])
+ config.target_clang = ' '.join([
+ 'clang++',
+ '-target', config.variant_triple,
+ clang_mcp_opt, android_include_system_paths_opt])
+ config.target_ld = ' '.join([
tools_directory,
- make_path(test_resource_dir, config.target_sdk_name))
+ '-L%s' % make_path(test_resource_dir, config.target_sdk_name)])
# The Swift interpreter is not available when targeting Android.
- config.available_features.remove('swift_interpreter')
+ if 'swift_interpreter' in config.available_features:
+ config.available_features.remove('swift_interpreter')
else:
lit_config.fatal("Don't know how to define target_run and "
diff --git a/tools/SourceKit/CMakeLists.txt b/tools/SourceKit/CMakeLists.txt
index a57fdf7..31e808f 100644
--- a/tools/SourceKit/CMakeLists.txt
+++ b/tools/SourceKit/CMakeLists.txt
@@ -4,6 +4,31 @@
list(APPEND CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ message(SEND_ERROR "SourceKit cannot be built standalone")
+endif()
+
+if(NOT CMAKE_C_COMPILER_ID MATCHES Clang)
+ if(CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME)
+ get_target_property(CLANG_LOCATION clang LOCATION)
+ get_filename_component(CLANG_LOCATION ${CLANG_LOCATION} DIRECTORY)
+
+ if(CMAKE_C_COMPILER_ID STREQUAL MSVC OR CMAKE_C_SIMULATE_ID STREQUAL MSVC)
+ set(CMAKE_C_COMPILER_ID
+ ${CLANG_LOCATION}/clang-cl${CMAKE_EXECUTABLE_SUFFIX})
+ set(CMAKE_CXX_COMPILER_ID
+ ${CLANG_LOCATION}/clang-cl${CMAKE_EXECUTABLE_SUFFIX})
+ else()
+ set(CMAKE_C_COMPILER_ID
+ ${CLANG_LOCATION}/clang${CMAKE_EXECUTABLE_SUFFIX})
+ set(CMAKE_CXX_COMPILER_ID
+ ${CLANG_LOCATION}/clang++${CMAKE_EXECUTABLE_SUFFIX})
+ endif()
+ else()
+ message(SEND_ERROR "SourceKit requires a clang based compiler")
+ endif()
+endif()
+
if (DARWIN_TOOLCHAIN_VERSION)
set(SOURCEKIT_VERSION_STRING "${DARWIN_TOOLCHAIN_VERSION}")
else()
diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index efa1779..5fdcce9 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -804,6 +804,8 @@
[preset: buildbot_linux_crosscompile_android,tools=RA,stdlib=RD,build]
mixin-preset=buildbot_linux
+host-test
+
release
assertions
extra-cmake-options=-DSWIFT_ENABLE_LLD_LINKER:BOOL=OFF
@@ -819,6 +821,8 @@
android-icu-i18n-include=%(arm_dir)s/icu/source/i18n
android-icu-data=%(arm_dir)s/libicudataswift.so
+skip-test-linux
+
[preset: buildbot_linux_crosscompile_android,tools=RA,stdlib=RD,build,aarch64]
mixin-preset=buildbot_linux_crosscompile_android,tools=RA,stdlib=RD,build
diff --git a/utils/build-script b/utils/build-script
index 8db8b26..582f4ce 100755
--- a/utils/build-script
+++ b/utils/build-script
@@ -137,15 +137,10 @@
# For platforms which normally require a connected device to
# test, the default behavior is to run tests that only require
# the host (i.e., they do not attempt to execute).
- if deployment_platform.is_darwin and \
- deployment_platform.is_embedded and \
- not deployment_platform.is_simulator:
- if deployment_platform not in \
- invocation.platforms_to_skip_test_host:
- test_host_only = True
- test = True
- else:
- test = False
+ if deployment_platform.uses_host_tests and \
+ deployment_platform not in \
+ invocation.platforms_to_skip_test_host:
+ test_host_only = True
name = deployment_target.name
@@ -181,7 +176,7 @@
"check-swift-benchmark-{}-external".format(name))
if test:
if test_host_only:
- suffix = "-non-executable"
+ suffix = "-only_non_executable"
else:
suffix = ""
subset_suffix = ""
@@ -407,11 +402,13 @@
if not args.test_watchos_simulator:
self.platforms_to_skip_test.add(
StdlibDeploymentTarget.AppleWatchSimulator)
-
- if not args.test_android_host:
+ if not args.test_android:
self.platforms_to_skip_test.add(StdlibDeploymentTarget.Android)
self.platforms_to_skip_test_host = set()
+ if not args.test_android_host:
+ self.platforms_to_skip_test_host.add(
+ StdlibDeploymentTarget.Android)
if not args.test_ios_host:
self.platforms_to_skip_test_host.add(StdlibDeploymentTarget.iOS)
if not args.test_tvos_host:
@@ -709,6 +706,8 @@
impl_args += ["--skip-test-watchos-host"]
if not args.test_watchos_simulator:
impl_args += ["--skip-test-watchos-simulator"]
+ if not args.test_android:
+ impl_args += ["--skip-test-android"]
if not args.test_android_host:
impl_args += ["--skip-test-android-host"]
if args.build_runtime_with_host_compiler:
diff --git a/utils/build-script-impl b/utils/build-script-impl
index aec8786..5b42241 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -166,6 +166,7 @@
skip-test-tvos-host "" "set to skip testing the host parts of the tvOS toolchain"
skip-test-watchos-simulator "" "set to skip testing Swift stdlibs for Apple watchOS simulators (i.e. test devices only)"
skip-test-watchos-host "" "set to skip testing the host parts of the watchOS toolchain"
+ skip-test-android "" "set to skip testing Swift stdlibs for Android"
skip-test-android-host "" "set to skip testing the host parts of the Android toolchain"
validation-test "0" "set to run the validation test suite"
long-test "0" "set to run the long test suite"
@@ -1435,7 +1436,11 @@
android-*)
swift_sdk="ANDROID"
build_for_this_target=$(not ${SKIP_BUILD_ANDROID})
- test_this_target=$(not ${SKIP_TEST_ANDROID_HOST})
+ if [[ ! "${SKIP_TEST_ANDROID_HOST}" ]] ; then
+ test_host_only=1
+ else
+ test_this_target=$(not ${SKIP_TEST_ANDROID})
+ fi
;;
*)
echo "Unknown compiler deployment target: ${stdlib_deployment_target}"
@@ -1476,7 +1481,7 @@
if [[ "${test_this_target}" ]] && [[ "${is_in_build_list}" ]]; then
test_target_suffix=""
if [[ -n "${test_host_only}" ]] ; then
- test_target_suffix="-non-executable"
+ test_target_suffix="-only_non_executable"
fi
test_subset_target_suffix=""
diff --git a/utils/build_swift/driver_arguments.py b/utils/build_swift/driver_arguments.py
index 7cf7a0e..ce61b79 100644
--- a/utils/build_swift/driver_arguments.py
+++ b/utils/build_swift/driver_arguments.py
@@ -202,6 +202,7 @@
args.test_ios = False
args.test_tvos = False
args.test_watchos = False
+ args.test_android = False
args.test_indexstoredb = False
args.test_sourcekitlsp = False
@@ -237,6 +238,10 @@
args.test_watchos_simulator = False
if not args.build_android:
+ args.test_android = False
+ args.test_android_host = False
+
+ if not args.test_android:
args.test_android_host = False
if not args.host_test:
@@ -899,6 +904,9 @@
help='skip testing watchOS device targets on the host machine (the '
'watch itself)')
+ option('--skip-test-android',
+ toggle_false('test_android'),
+ help='skip testing all Android targets.')
option('--skip-test-android-host',
toggle_false('test_android_host'),
help='skip testing Android device targets on the host machine (the '
diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py
index 9ca27d2..5c09b57 100644
--- a/utils/build_swift/tests/expected_options.py
+++ b/utils/build_swift/tests/expected_options.py
@@ -174,6 +174,7 @@
'swift_user_visible_version': defaults.SWIFT_USER_VISIBLE_VERSION,
'symbols_package': None,
'test': None,
+ 'test_android': False,
'test_android_host': False,
'test_cygwin': False,
'test_freebsd': False,
@@ -479,6 +480,7 @@
dest='build_watchos_device'),
DisableOption('--skip-build-watchos-simulator',
dest='build_watchos_simulator'),
+ DisableOption('--skip-test-android', dest='test_android'),
DisableOption('--skip-test-android-host', dest='test_android_host'),
DisableOption('--skip-test-cygwin', dest='test_cygwin'),
DisableOption('--skip-test-freebsd', dest='test_freebsd'),
diff --git a/utils/run-test b/utils/run-test
index 19e43c0..8300e8e 100755
--- a/utils/run-test
+++ b/utils/run-test
@@ -202,7 +202,8 @@
upload_stdlib_targets = []
need_validation = any('/validation-test-' in path for path in paths)
for target in targets:
- upload_stdlib_targets += ["upload-stdlib-%s" % target]
+ if args.mode != 'only_non_executable':
+ upload_stdlib_targets += ["upload-stdlib-%s" % target]
if need_validation:
dependency_targets += ["swift-stdlib-%s" % target]
else:
diff --git a/utils/swift_build_support/swift_build_support/targets.py b/utils/swift_build_support/swift_build_support/targets.py
index 35e425d..e5877fa 100644
--- a/utils/swift_build_support/swift_build_support/targets.py
+++ b/utils/swift_build_support/swift_build_support/targets.py
@@ -42,6 +42,15 @@
# By default, we don't support benchmarks on most platforms.
return False
+ @property
+ def uses_host_tests(self):
+ """
+ Check if this is a Darwin platform that needs a connected device
+ for tests.
+ """
+ # By default, we don't use connected devices on most platforms.
+ return False
+
def contains(self, target_name):
"""
Returns True if the given target name belongs to a one of this
@@ -69,6 +78,24 @@
# platforms.
return not self.is_simulator
+ @property
+ def uses_host_tests(self):
+ """
+ Check if this is a Darwin platform that needs a connected device
+ for tests.
+ """
+ return self.is_embedded and not self.is_simulator
+
+
+class AndroidPlatform(Platform):
+ @property
+ def uses_host_tests(self):
+ """
+ Check if this is a Darwin platform that needs a connected device
+ for tests.
+ """
+ return True
+
class Target(object):
"""
@@ -125,7 +152,7 @@
Cygwin = Platform("cygwin", archs=["x86_64"])
- Android = Platform("android", archs=["armv7", "aarch64"])
+ Android = AndroidPlatform("android", archs=["armv7", "aarch64"])
Windows = Platform("windows", archs=["x86_64"])
diff --git a/validation-test/compiler_crashers_2_fixed/sr10146.swift b/validation-test/compiler_crashers_2_fixed/sr10146.swift
new file mode 100644
index 0000000..dcabe24
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/sr10146.swift
@@ -0,0 +1,12 @@
+// RUN: not %target-swift-frontend -emit-sil %s
+// REQUIRES: OS=ios
+
+import UIKit
+
+// Just make sure we don't crash.
+
+class Foo: NSObject {
+ func crash() {
+ let kp = \AnyObject.accessibilityFrame
+ }
+}