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
+  }
+}