Merge pull request #1156 from tkremenek/SR-650

[Swift 2.2] fix SR-650: REGRESSION: Assertion failed
diff --git a/CHANGELOG.md b/CHANGELOG.md
index edc11a0..c6baa9b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -142,6 +142,29 @@
 
   For more information, see [SE-0020](https://github.com/apple/swift-evolution/blob/master/proposals/0020-if-swift-version.md).
 
+* The Objective-C selector of a Swift method can now be determined
+  directly with the #selector expression, e.g.,:
+
+      let sel = #selector(insertSubview(_:aboveSubview:)) // sel has type Selector
+
+  Along with this change, the use of string literals as selectors has
+  been deprecated, e.g.,
+
+      let sel: Selector = "insertSubview:aboveSubview:"
+
+  Generally, such string literals should be replaced with uses of
+  `#selector`, and the compiler will provide Fix-Its that use
+  `#selector`. In cases where they is not possible (e.g., when referring
+  to the getter of a property), one can still directly construct
+  selectors, e.g.,:
+
+      let sel = Selector("propertyName")
+
+  Note that the compiler is now checking the string literals used to
+  construct Selectors to ensure that they are well-formed Objective-C
+  selectors and that there is an '@objc' method with that selector.
+
+
 2015-09-17 [Xcode 7.1, Swift 2.1]
 ----------
 
diff --git a/docs/SIL.rst b/docs/SIL.rst
index 0b1232f..68c8760 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -2452,6 +2452,7 @@
   sil-instruction ::= 'string_literal' encoding string-literal
   encoding ::= 'utf8'
   encoding ::= 'utf16'
+  encoding ::= 'objc_selector'
 
   %1 = string_literal "asdf"
   // %1 has type $Builtin.RawPointer
@@ -2459,7 +2460,10 @@
 Creates a reference to a string in the global string table. The result
 is a pointer to the data.  The referenced string is always null-terminated. The
 string literal value is specified using Swift's string
-literal syntax (though ``\()`` interpolations are not allowed).
+literal syntax (though ``\()`` interpolations are not allowed). When
+the encoding is ``objc_selector``, the string literal produces a
+reference to a UTF-8-encoded Objective-C selector in the Objective-C
+method name segment.
 
 Dynamic Dispatch
 ~~~~~~~~~~~~~~~~
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index a131ad4..34dbb0a 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -405,6 +405,12 @@
                        LazyResolver *typeResolver,
                        SmallVectorImpl<ValueDecl *> &decls) const;
 
+  /// Look up all Objective-C methods with the given selector visible
+  /// in the enclosing module.
+  void lookupAllObjCMethods(
+         ObjCSelector selector,
+         SmallVectorImpl<AbstractFunctionDecl *> &results) const;
+
   /// Return the ASTContext for a specified DeclContext by
   /// walking up to the enclosing module and returning its ASTContext.
   ASTContext &getASTContext() const;
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 508e07b..e085d87 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -1017,6 +1017,14 @@
 ERROR(string_interpolation_extra,none,
       "extra tokens after interpolated string expression", ())
 
+// Selector expressions.
+ERROR(expr_selector_expected_lparen,PointsToFirstBadToken,
+      "expected '(' following '#selector'", ())
+ERROR(expr_selector_expected_expr,PointsToFirstBadToken,
+      "expected expression naming a method within '#selector(...)'", ())
+ERROR(expr_selector_expected_rparen,PointsToFirstBadToken,
+      "expected ')' to complete '#selector' expression", ())
+
 //------------------------------------------------------------------------------
 // Attribute-parsing diagnostics
 //------------------------------------------------------------------------------
diff --git a/include/swift/AST/DiagnosticsSIL.def b/include/swift/AST/DiagnosticsSIL.def
index fa0c6b1..f202e89 100644
--- a/include/swift/AST/DiagnosticsSIL.def
+++ b/include/swift/AST/DiagnosticsSIL.def
@@ -88,6 +88,9 @@
       "C function pointer signature %0 is not compatible with expected type %1",
       (Type, Type))
 
+ERROR(objc_selector_malformed,none,"the type ObjectiveC.Selector is malformed",
+      ())
+
 // Definite initialization diagnostics.
 NOTE(variable_defined_here,none,
      "%select{variable|constant}0 defined here", (bool))
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index f7a4448..7058ad3 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -336,8 +336,38 @@
       "invalid conversion from non-escaping function of type %0 to "
       "potentially escaping function type %1", (Type, Type))
 
+// Selector expressions.
+ERROR(expr_selector_no_objc_runtime,none,
+      "'#selector' can only be used with the Objective-C runtime", ())
+ERROR(expr_selector_module_missing,none,
+      "import the 'ObjectiveC' module to use '#selector'", ())
+ERROR(expr_selector_no_declaration,none,
+      "argument of '#selector' does not refer to an initializer or method", ())
+ERROR(expr_selector_property,none,
+      "argument of '#selector' cannot refer to a property", ())
+ERROR(expr_selector_not_method_or_init,none,
+      "argument of '#selector' does not refer to a method or initializer", ())
+ERROR(expr_selector_not_objc,none,
+      "argument of '#selector' refers to %select{a method|an initializer}0 "
+      "that is not exposed to Objective-C",
+      (bool))
+NOTE(expr_selector_make_objc,none,
+     "add '@objc' to expose this %select{method|initializer}0 to Objective-C",
+     (bool))
 
-
+// Selectors-as-string-literals.
+WARNING(selector_literal_invalid,none,
+        "string literal is not a valid Objective-C selector", ())
+WARNING(selector_literal_undeclared,none,
+        "no method declared with Objective-C selector %0", (ObjCSelector))
+WARNING(selector_literal_deprecated,none,
+        "use of string literal for Objective-C selectors is deprecated; "
+        "use '#selector' or explicitly construct a 'Selector'", ())
+WARNING(selector_literal_deprecated_suggest,none,
+        "use of string literal for Objective-C selectors is deprecated; "
+        "use '#selector' instead", ())
+WARNING(selector_construction_suggest,none,
+        "use '#selector' instead of explicitly constructing a 'Selector'", ())
 
 ERROR(cannot_return_value_from_void_func,none,
       "unexpected non-void return value in void function", ())
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index cd882e3..a5da8f5 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -3679,6 +3679,44 @@
   void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
 };
 
+/// Produces the Objective-C selector of the referenced method.
+///
+/// \code
+/// #selector(UIView.insertSubview(_:aboveSubview:))
+/// \endcode
+class ObjCSelectorExpr : public Expr {
+  SourceLoc KeywordLoc;
+  SourceLoc LParenLoc;
+  Expr *SubExpr;
+  SourceLoc RParenLoc;
+  AbstractFunctionDecl *Method = nullptr;
+
+public:
+  ObjCSelectorExpr(SourceLoc keywordLoc, SourceLoc lParenLoc,
+                   Expr *subExpr, SourceLoc rParenLoc)
+    : Expr(ExprKind::ObjCSelector, /*Implicit=*/false),
+      KeywordLoc(keywordLoc), LParenLoc(lParenLoc), SubExpr(subExpr),
+      RParenLoc(rParenLoc) { }
+
+  Expr *getSubExpr() const { return SubExpr; }
+  void setSubExpr(Expr *expr) { SubExpr = expr; }
+
+  /// Retrieve the Objective-C method to which this expression refers.
+  AbstractFunctionDecl *getMethod() const { return Method; }
+
+  /// Set the Objective-C method to which this expression refers.
+  void setMethod(AbstractFunctionDecl *method) { Method = method; }
+
+  SourceLoc getLoc() const { return KeywordLoc; }
+  SourceRange getSourceRange() const {
+    return SourceRange(KeywordLoc, RParenLoc);
+  }
+
+  static bool classof(const Expr *E) {
+    return E->getKind() == ExprKind::ObjCSelector;
+  }
+};
+
 #undef SWIFT_FORWARD_SOURCE_LOCS_TO
   
 } // end namespace swift
diff --git a/include/swift/AST/ExprNodes.def b/include/swift/AST/ExprNodes.def
index f378930..66387b9 100644
--- a/include/swift/AST/ExprNodes.def
+++ b/include/swift/AST/ExprNodes.def
@@ -155,6 +155,7 @@
 EXPR(CodeCompletion, Expr)
 UNCHECKED_EXPR(UnresolvedPattern, Expr)
 EXPR(EditorPlaceholder, Expr)
+EXPR(ObjCSelector, Expr)
 
 #undef EXPR_RANGE
 #undef UNCHECKED_EXPR
diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def
index 1e5393f..fed0999 100644
--- a/include/swift/AST/KnownIdentifiers.def
+++ b/include/swift/AST/KnownIdentifiers.def
@@ -50,6 +50,7 @@
 IDENTIFIER(Protocol)
 IDENTIFIER(rawValue)
 IDENTIFIER(RawValue)
+IDENTIFIER(Selector)
 IDENTIFIER(self)
 IDENTIFIER(Self)
 IDENTIFIER(setObject)
diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h
index ec8b5cc..9636087 100644
--- a/include/swift/AST/Module.h
+++ b/include/swift/AST/Module.h
@@ -409,6 +409,11 @@
                     DeclContext *container, DeclName name,
                     Identifier privateDiscriminator) const;
 
+  /// Find all Objective-C methods with the given selector.
+  void lookupObjCMethods(
+         ObjCSelector selector,
+         SmallVectorImpl<AbstractFunctionDecl *> &results) const;
+
   /// \sa getImportedModules
   enum class ImportFilter {
     All,
@@ -639,6 +644,11 @@
                                  DeclName name,
                                  SmallVectorImpl<ValueDecl*> &results) const {}
 
+  /// Find all Objective-C methods with the given selector.
+  virtual void lookupObjCMethods(
+                 ObjCSelector selector,
+                 SmallVectorImpl<AbstractFunctionDecl *> &results) const = 0;
+
   /// Returns the comment attached to the given declaration.
   ///
   /// This function is an implementation detail for comment serialization.
@@ -804,6 +814,10 @@
   
   void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
 
+  void lookupObjCMethods(
+         ObjCSelector selector,
+         SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
+
   Identifier
   getDiscriminatorForPrivateValue(const ValueDecl *D) const override {
     llvm_unreachable("no private decls in the derived file unit");
@@ -903,6 +917,11 @@
   /// complete, we diagnose.
   std::map<DeclAttrKind, const DeclAttribute *> AttrsRequiringFoundation;
 
+  /// A mapping from Objective-C selectors to the methods that have
+  /// those selectors.
+  llvm::DenseMap<ObjCSelector, llvm::TinyPtrVector<AbstractFunctionDecl *>>
+    ObjCMethods;
+
   template <typename T>
   using OperatorMap = llvm::DenseMap<Identifier,llvm::PointerIntPair<T,1,bool>>;
 
@@ -959,6 +978,10 @@
   lookupClassMember(ModuleDecl::AccessPathTy accessPath, DeclName name,
                     SmallVectorImpl<ValueDecl*> &results) const override;
 
+  void lookupObjCMethods(
+         ObjCSelector selector,
+         SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
+
   virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
 
   virtual void
@@ -1120,6 +1143,11 @@
                            NLKind lookupKind,
                            SmallVectorImpl<ValueDecl*> &result) const override;
 
+  /// Find all Objective-C methods with the given selector.
+  void lookupObjCMethods(
+         ObjCSelector selector,
+         SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
+
   Identifier
   getDiscriminatorForPrivateValue(const ValueDecl *D) const override {
     llvm_unreachable("no private values in the Builtin module");
diff --git a/include/swift/ClangImporter/ClangModule.h b/include/swift/ClangImporter/ClangModule.h
index 8fcc9f5..c12eef8 100644
--- a/include/swift/ClangImporter/ClangModule.h
+++ b/include/swift/ClangImporter/ClangModule.h
@@ -73,6 +73,10 @@
   lookupClassMember(ModuleDecl::AccessPathTy accessPath, DeclName name,
                     SmallVectorImpl<ValueDecl*> &decls) const override;
 
+  void lookupObjCMethods(
+         ObjCSelector selector,
+         SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
+
   virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
 
   virtual void getDisplayDecls(SmallVectorImpl<Decl*> &results) const override;
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index dee2702..47e0283 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -1097,6 +1097,7 @@
                                               bool isExprBasic);
   ParserResult<Expr> parseExprPostfix(Diag<> ID, bool isExprBasic);
   ParserResult<Expr> parseExprUnary(Diag<> ID, bool isExprBasic);
+  ParserResult<Expr> parseExprSelector();
   ParserResult<Expr> parseExprSuper();
   ParserResult<Expr> parseExprConfiguration();
   Expr *parseExprStringLiteral();
diff --git a/include/swift/Parse/Token.h b/include/swift/Parse/Token.h
index 4107cd7..a6f2a3a 100644
--- a/include/swift/Parse/Token.h
+++ b/include/swift/Parse/Token.h
@@ -44,6 +44,7 @@
   pound_endif,
   pound_line,
   pound_available,
+  pound_selector,
   comment,
   
 #define KEYWORD(X) kw_ ## X,
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 2d177fb..367383c 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -1254,7 +1254,9 @@
 public:
   enum class Encoding {
     UTF8,
-    UTF16
+    UTF16,
+    /// UTF-8 encoding of an Objective-C selector.
+    ObjCSelector,
   };
 
 private:
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index 78bbbdb..fbf4181 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -553,6 +553,11 @@
                          DeclName name,
                          SmallVectorImpl<ValueDecl*> &results);
 
+  /// Find all Objective-C methods with the given selector.
+  void lookupObjCMethods(
+         ObjCSelector selector,
+         SmallVectorImpl<AbstractFunctionDecl *> &results);
+
   /// Reports all link-time dependencies.
   void collectLinkLibraries(Module::LinkLibraryCallback callback) const;
 
diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h
index ac19024..174e2c4 100644
--- a/include/swift/Serialization/SerializedModuleLoader.h
+++ b/include/swift/Serialization/SerializedModuleLoader.h
@@ -131,6 +131,11 @@
   lookupClassMember(Module::AccessPathTy accessPath, DeclName name,
                     SmallVectorImpl<ValueDecl*> &decls) const override;
 
+  /// Find all Objective-C methods with the given selector.
+  void lookupObjCMethods(
+         ObjCSelector selector,
+         SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
+
   Optional<BriefAndRawComment> getCommentForDecl(const Decl *D) const override;
 
   virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 3ab4821..c0e8d7e 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -2161,6 +2161,16 @@
     }
     OS << ')';
   }
+  void visitObjCSelectorExpr(ObjCSelectorExpr *E) {
+    printCommon(E, "objc_selector_expr") << " decl=";
+    if (auto method = E->getMethod())
+      method->dumpRef(OS);
+    else
+      OS << "<unresolved>";
+    OS << '\n';
+    printRec(E->getSubExpr());
+    OS << ')';
+  }
 };
 
 } // end anonymous namespace.
diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp
index 15ea22a..5ee65cf 100644
--- a/lib/AST/ASTWalker.cpp
+++ b/lib/AST/ASTWalker.cpp
@@ -811,6 +811,14 @@
     return E;
   }
 
+  Expr *visitObjCSelectorExpr(ObjCSelectorExpr *E) {
+    Expr *sub = doIt(E->getSubExpr());
+    if (!sub) return nullptr;
+
+    E->setSubExpr(sub);
+    return E;
+  }
+
   //===--------------------------------------------------------------------===//
   //                           Everything Else
   //===--------------------------------------------------------------------===//
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index bad8808..7163581 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -314,6 +314,7 @@
     NON_LVALUE_EXPR(Assign)
     NON_LVALUE_EXPR(DefaultValue)
     NON_LVALUE_EXPR(CodeCompletion)
+    NON_LVALUE_EXPR(ObjCSelector)
 
 #define UNCHECKED_EXPR(KIND, BASE) \
     NON_LVALUE_EXPR(KIND)
@@ -487,6 +488,7 @@
   case ExprKind::StringLiteral:
   case ExprKind::InterpolatedStringLiteral:
   case ExprKind::MagicIdentifierLiteral:
+  case ExprKind::ObjCSelector:
     return true;
 
   case ExprKind::ObjectLiteral:
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index 3d4c24d..387c801 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -519,12 +519,24 @@
   }
 }
 
+void Module::lookupObjCMethods(
+       ObjCSelector selector,
+       SmallVectorImpl<AbstractFunctionDecl *> &results) const {
+  FORWARD(lookupObjCMethods, (selector, results));
+}
+
 void BuiltinUnit::lookupValue(Module::AccessPathTy accessPath, DeclName name,
                               NLKind lookupKind,
                               SmallVectorImpl<ValueDecl*> &result) const {
   getCache().lookupValue(name.getBaseName(), lookupKind, *this, result);
 }
 
+void BuiltinUnit::lookupObjCMethods(
+       ObjCSelector selector,
+       SmallVectorImpl<AbstractFunctionDecl *> &results) const {
+  // No @objc methods in the Builtin module.
+}
+
 DerivedFileUnit::DerivedFileUnit(Module &M)
     : FileUnit(FileUnitKind::Derived, M) {
   M.getASTContext().addDestructorCleanup(*this);
@@ -561,6 +573,17 @@
   }
 }
 
+void DerivedFileUnit::lookupObjCMethods(
+       ObjCSelector selector,
+       SmallVectorImpl<AbstractFunctionDecl *> &results) const {
+  for (auto D : DerivedDecls) {
+    if (auto func = dyn_cast<AbstractFunctionDecl>(D)) {
+      if (func->isObjC() && func->getObjCSelector() == selector)
+        results.push_back(func);
+    }
+  }
+}
+
 void DerivedFileUnit::getTopLevelDecls(SmallVectorImpl<swift::Decl *> &results)
 const {
   results.append(DerivedDecls.begin(), DerivedDecls.end());
@@ -606,6 +629,15 @@
   getCache().lookupClassMember(accessPath, name, results, *this);
 }
 
+void SourceFile::lookupObjCMethods(
+       ObjCSelector selector,
+       SmallVectorImpl<AbstractFunctionDecl *> &results) const {
+  // FIXME: Make sure this table is complete, somehow.
+  auto known = ObjCMethods.find(selector);
+  if (known == ObjCMethods.end()) return;
+  results.append(known->second.begin(), known->second.end());
+}
+
 void Module::getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &Results) const {
   FORWARD(getLocalTypeDecls, (Results));
 }
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index cb4fdf6..c031577 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -1374,3 +1374,21 @@
   // We're done. Report success/failure.
   return !decls.empty();
 }
+
+void DeclContext::lookupAllObjCMethods(
+       ObjCSelector selector,
+       SmallVectorImpl<AbstractFunctionDecl *> &results) const {
+  // Collect all of the methods with this selector.
+  forAllVisibleModules(this, [&](Module::ImportedModule import) {
+    import.second->lookupObjCMethods(selector, results);
+  });
+
+  // Filter out duplicates.
+  llvm::SmallPtrSet<AbstractFunctionDecl *, 8> visited;
+  results.erase(
+    std::remove_if(results.begin(), results.end(),
+                   [&](AbstractFunctionDecl *func) -> bool {
+                     return !visited.insert(func).second;
+                   }),
+    results.end());
+}
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index bcdb625..9877756 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -3809,6 +3809,59 @@
   }
 }
 
+void ClangModuleUnit::lookupObjCMethods(
+       ObjCSelector selector,
+       SmallVectorImpl<AbstractFunctionDecl *> &results) const {
+  // FIXME: Ignore submodules, which are empty for now.
+  if (clangModule && clangModule->isSubModule())
+    return;
+
+  // Map the selector into a Clang selector.
+  auto clangSelector = owner.Impl.exportSelector(selector);
+  if (clangSelector.isNull()) return;
+
+  // Collect all of the Objective-C methods with this selector.
+  SmallVector<clang::ObjCMethodDecl *, 8> objcMethods;
+  auto &clangSema = owner.Impl.getClangSema();
+  clangSema.CollectMultipleMethodsInGlobalPool(clangSelector,
+                                               objcMethods,
+                                               /*instance=*/true);
+  clangSema.CollectMultipleMethodsInGlobalPool(clangSelector,
+                                               objcMethods,
+                                               /*instance=*/false);
+
+  // Import the methods.
+  auto &clangCtx = clangSema.getASTContext();
+  for (auto objcMethod : objcMethods) {
+    // Verify that this method came from this module.
+    auto owningClangModule = getClangOwningModule(objcMethod, clangCtx);
+    if (owningClangModule)
+      owningClangModule = owningClangModule->getTopLevelModule();
+
+    if (owningClangModule != clangModule) continue;
+
+    // If we found a property accessor, import the property.
+    if (objcMethod->isPropertyAccessor())
+      (void)owner.Impl.importDecl(objcMethod->findPropertyDecl(true));
+
+    // Import it.
+    // FIXME: Retrying a failed import works around recursion bugs in the Clang
+    // importer.
+    auto imported = owner.Impl.importDecl(objcMethod);
+    if (!imported) imported = owner.Impl.importDecl(objcMethod);
+    if (!imported) continue;
+
+    if (auto func = dyn_cast<AbstractFunctionDecl>(imported))
+      results.push_back(func);
+
+    // If there is an alternate declaration, also look at it.
+    if (auto alternate = owner.Impl.getAlternateDecl(imported)) {
+      if (auto func = dyn_cast<AbstractFunctionDecl>(alternate))
+        results.push_back(func);
+    }
+  }
+}
+
 void ClangModuleUnit::collectLinkLibraries(
     Module::LinkLibraryCallback callback) const {
   if (!clangModule)
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index 6e63839..c2f8173 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -1985,6 +1985,21 @@
     Builder.addRightParen();
   }
 
+  void addPoundSelector() {
+    // #selector is only available when the Objective-C runtime is.
+    if (!Ctx.LangOpts.EnableObjCInterop) return;
+
+    CodeCompletionResultBuilder Builder(
+                                  Sink,
+                                  CodeCompletionResult::ResultKind::Keyword,
+                                  SemanticContextKind::ExpressionSpecific,
+                                  ExpectedTypes);
+    Builder.addTextChunk("selector");
+    Builder.addLeftParen();
+    Builder.addSimpleTypedParameter("@objc method", /*isVarArg=*/false);
+    Builder.addRightParen();
+  }
+
   void addFunctionCallPattern(const AnyFunctionType *AFT,
                               const AbstractFunctionDecl *AFD = nullptr) {
     foundFunction(AFT);
@@ -4569,6 +4584,7 @@
 
   case CompletionKind::AfterPound: {
     Lookup.addPoundAvailable(ParentStmtKind);
+    Lookup.addPoundSelector();
     break;
   }
   }
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index 73f75e4..70ab7e7 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -98,6 +98,7 @@
 #define KEYWORD(X) case tok::kw_##X: Kind = SyntaxNodeKind::Keyword; break;
 #include "swift/Parse/Tokens.def"
 #undef KEYWORD
+      case tok::pound_selector: Kind = SyntaxNodeKind::Keyword; break;
       case tok::pound_line:
       case tok::pound_available: Kind =
           SyntaxNodeKind::BuildConfigKeyword; break;
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 8807914..3e8c646 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -456,6 +456,30 @@
     this->addLinkLibrary(LinkLibrary("objc", LibraryKind::Library));
 }
 
+/// Collect elements of an already-existing global list with the given
+/// \c name into \c list.
+///
+/// We use this when Clang code generation might populate the list.
+static void collectGlobalList(IRGenModule &IGM,
+                              SmallVectorImpl<llvm::WeakVH> &list,
+                              StringRef name) {
+  if (auto *existing = IGM.Module.getGlobalVariable(name)) {
+    auto *globals = cast<llvm::ConstantArray>(existing->getInitializer());
+    for (auto &use : globals->operands()) {
+      auto *global = use.get();
+      list.push_back(global);
+    }
+    existing->eraseFromParent();
+  }
+
+  std::for_each(list.begin(), list.end(),
+                [](const llvm::WeakVH &global) {
+    assert(!isa<llvm::GlobalValue>(global) ||
+           !cast<llvm::GlobalValue>(global)->isDeclaration() &&
+           "all globals in the 'used' list must be definitions");
+  });
+}
+
 /// Emit a global list, i.e. a global constant array holding all of a
 /// list of values.  Generally these lists are for various LLVM
 /// metadata or runtime purposes.
@@ -630,6 +654,13 @@
   LLVMUsed.push_back(global);
 }
 
+/// Add the given global value to @llvm.compiler.used.
+///
+/// This value must have a definition by the time the module is finalized.
+void IRGenModule::addCompilerUsedGlobal(llvm::GlobalValue *global) {
+  LLVMCompilerUsed.push_back(global);
+}
+
 /// Add the given global value to the Objective-C class list.
 void IRGenModule::addObjCClass(llvm::Constant *classPtr, bool nonlazy) {
   ObjCClasses.push_back(classPtr);
@@ -674,27 +705,19 @@
   // @llvm.used
 
   // Collect llvm.used globals already in the module (coming from ClangCodeGen).
-  auto *ExistingLLVMUsed = Module.getGlobalVariable("llvm.used");
-  if (ExistingLLVMUsed) {
-    auto *Globals =
-        cast<llvm::ConstantArray>(ExistingLLVMUsed->getInitializer());
-    for (auto &Use : Globals->operands()) {
-      auto *Global = Use.get();
-      LLVMUsed.push_back(Global);
-    }
-    ExistingLLVMUsed->eraseFromParent();
-  }
-
-  std::for_each(LLVMUsed.begin(), LLVMUsed.end(),
-                [](const llvm::WeakVH &global) {
-    assert(!isa<llvm::GlobalValue>(global) ||
-           !cast<llvm::GlobalValue>(global)->isDeclaration() &&
-           "all globals in the 'used' list must be definitions");
-  });
+  collectGlobalList(*this, LLVMUsed, "llvm.used");
   emitGlobalList(*this, LLVMUsed, "llvm.used", "llvm.metadata",
                  llvm::GlobalValue::AppendingLinkage,
                  Int8PtrTy,
                  false);
+
+  // Collect llvm.compiler.used globals already in the module (coming
+  // from ClangCodeGen).
+  collectGlobalList(*this, LLVMCompilerUsed, "llvm.compiler.used");
+  emitGlobalList(*this, LLVMCompilerUsed, "llvm.compiler.used", "llvm.metadata",
+                 llvm::GlobalValue::AppendingLinkage,
+                 Int8PtrTy,
+                 false);
 }
 
 void IRGenModuleDispatcher::emitGlobalTopLevel() {
diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp
index 1ff9b27..f494e93 100644
--- a/lib/IRGen/GenObjC.cpp
+++ b/lib/IRGen/GenObjC.cpp
@@ -292,12 +292,13 @@
 
   // If not, create it.  This implicitly adds a trailing null.
   auto init = llvm::ConstantDataArray::getString(LLVMContext, selector);
-  auto global = new llvm::GlobalVariable(Module, init->getType(), true,
-                                         llvm::GlobalValue::InternalLinkage,
+  auto global = new llvm::GlobalVariable(Module, init->getType(), false,
+                                         llvm::GlobalValue::PrivateLinkage,
                                          init,
                           llvm::Twine("\01L_selector_data(") + selector + ")");
   global->setSection("__TEXT,__objc_methname,cstring_literals");
   global->setAlignment(1);
+  addCompilerUsedGlobal(global);
 
   // Drill down to make an i8*.
   auto zero = llvm::ConstantInt::get(SizeTy, 0);
@@ -323,16 +324,17 @@
   // choose something descriptive to make the IR readable.
   auto init = getAddrOfObjCMethodName(selector);
   auto global = new llvm::GlobalVariable(Module, init->getType(), false,
-                                         llvm::GlobalValue::InternalLinkage,
+                                         llvm::GlobalValue::PrivateLinkage,
                                          init,
                                 llvm::Twine("\01L_selector(") + selector + ")");
+  global->setExternallyInitialized(true);
   global->setAlignment(getPointerAlignment().getValue());
 
   // This section name is magical for the Darwin static and dynamic linkers.
   global->setSection("__DATA,__objc_selrefs,literal_pointers,no_dead_strip");
 
   // Make sure that this reference does not get optimized away.
-  addUsedGlobal(global);
+  addCompilerUsedGlobal(global);
 
   // Cache and return.
   entry = global;
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index df93401..d0c164e 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -542,6 +542,7 @@
   llvm::Constant *getAddrOfObjCProtocolRef(ProtocolDecl *proto,
                                            ForDefinition_t forDefinition);
   void addUsedGlobal(llvm::GlobalValue *global);
+  void addCompilerUsedGlobal(llvm::GlobalValue *global);
   void addObjCClass(llvm::Constant *addr, bool nonlazy);
   void addProtocolConformanceRecord(NormalProtocolConformance *conformance);
 
@@ -571,6 +572,14 @@
   /// out.
   SmallVector<llvm::WeakVH, 4> LLVMUsed;
 
+  /// LLVMCompilerUsed - List of global values which are required to be
+  /// present in the object file; bitcast to i8*. This is used for
+  /// forcing visibility of symbols which may otherwise be optimized
+  /// out.
+  ///
+  /// Similar to LLVMUsed, but emitted as llvm.compiler.used.
+  SmallVector<llvm::WeakVH, 4> LLVMCompilerUsed;
+
   /// Metadata nodes for autolinking info.
   ///
   /// This is typed using llvm::Value instead of llvm::MDNode because it
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index d066fbe..4017692 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -2236,18 +2236,28 @@
   case swift::StringLiteralInst::Encoding::UTF8:
     return IGM.getAddrOfGlobalString(string);
 
-  case swift::StringLiteralInst::Encoding::UTF16:
+  case swift::StringLiteralInst::Encoding::UTF16: {
     // This is always a GEP of a GlobalVariable with a nul terminator.
     auto addr = IGM.getAddrOfGlobalUTF16String(string);
 
     // Cast to Builtin.RawPointer.
     return llvm::ConstantExpr::getBitCast(addr, IGM.Int8PtrTy);
   }
+
+  case swift::StringLiteralInst::Encoding::ObjCSelector:
+    llvm_unreachable("cannot get the address of an Objective-C selector");
+  }
   llvm_unreachable("bad string encoding");
 }
 
 void IRGenSILFunction::visitStringLiteralInst(swift::StringLiteralInst *i) {
-  auto addr = getAddrOfString(IGM, i->getValue(), i->getEncoding());
+  llvm::Value *addr;
+
+  // Emit a load of a selector.
+  if (i->getEncoding() == swift::StringLiteralInst::Encoding::ObjCSelector)
+    addr = emitObjCSelectorRefLoad(i->getValue());
+  else
+    addr = getAddrOfString(IGM, i->getValue(), i->getEncoding());
 
   Explosion e;
   e.add(addr);
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index dc4c2ab..fdd5ca1 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -1611,6 +1611,11 @@
       return formToken(tok::pound_available, TokStart);
     }
 
+    if (getSubstring(TokStart + 1, 8).equals("selector")) {
+      CurPtr += 8;
+      return formToken(tok::pound_selector, TokStart);
+    }
+
     // Allow a hashbang #! line at the beginning of the file.
     if (CurPtr - 1 == BufferStart && *CurPtr == '!') {
       CurPtr--;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index cab8211..5ae1eef 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -417,6 +417,7 @@
 ///     expr-postfix(Mode)
 ///     operator-prefix expr-unary(Mode)
 ///     '&' expr-unary(Mode)
+///     expr-selector
 ///
 ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
   UnresolvedDeclRefExpr *Operator;
@@ -437,6 +438,9 @@
         new (Context) InOutExpr(Loc, SubExpr.get(), Type()));
   }
 
+  case tok::pound_selector:
+    return parseExprSelector();
+
   case tok::oper_postfix:
     // Postfix operators cannot start a subexpression, but can happen
     // syntactically because the operator may just follow whatever precedes this
@@ -482,6 +486,50 @@
       new (Context) PrefixUnaryExpr(Operator, SubExpr.get()));
 }
 
+/// parseExprSelector
+///
+///   expr-selector:
+///     '#selector' '(' expr ')'
+///
+ParserResult<Expr> Parser::parseExprSelector() {
+  // Consume '#selector'.
+  SourceLoc keywordLoc = consumeToken(tok::pound_selector);
+
+  // Parse the leading '('.
+  if (!Tok.is(tok::l_paren)) {
+    diagnose(Tok, diag::expr_selector_expected_lparen);
+    return makeParserError();
+  }
+  SourceLoc lParenLoc = consumeToken(tok::l_paren);
+
+  // Parse the subexpression.
+  ParserResult<Expr> subExpr = parseExpr(diag::expr_selector_expected_expr);
+  if (subExpr.hasCodeCompletion())
+    return subExpr;
+
+  // Parse the closing ')'
+  SourceLoc rParenLoc;
+  if (subExpr.isParseError()) {
+    skipUntilDeclStmtRBrace(tok::r_paren);
+    if (Tok.is(tok::r_paren))
+      rParenLoc = consumeToken();
+    else
+      rParenLoc = Tok.getLoc();
+  } else {
+    parseMatchingToken(tok::r_paren, rParenLoc,
+                       diag::expr_selector_expected_rparen, lParenLoc);
+  }
+
+  // If the subexpression was in error, just propagate the error.
+  if (subExpr.isParseError())
+    return makeParserResult<Expr>(
+             new (Context) ErrorExpr(SourceRange(keywordLoc, rParenLoc)));
+
+  return makeParserResult<Expr>(
+    new (Context) ObjCSelectorExpr(keywordLoc, lParenLoc, subExpr.get(),
+                                   rParenLoc));
+}
+
 static DeclRefKind getDeclRefKindForOperator(tok kind) {
   switch (kind) {
   case tok::oper_binary_spaced:
diff --git a/lib/Parse/ParseSIL.cpp b/lib/Parse/ParseSIL.cpp
index de946f2..ed8aa44 100644
--- a/lib/Parse/ParseSIL.cpp
+++ b/lib/Parse/ParseSIL.cpp
@@ -1772,6 +1772,8 @@
       encoding = StringLiteralInst::Encoding::UTF8;
     } else if (P.Tok.getText() == "utf16") {
       encoding = StringLiteralInst::Encoding::UTF16;
+    } else if (P.Tok.getText() == "objc_selector") {
+      encoding = StringLiteralInst::Encoding::ObjCSelector;
     } else {
       P.diagnose(P.Tok, diag::sil_string_invalid_encoding, P.Tok.getText());
       return true;
diff --git a/lib/SIL/SILGlobalVariable.cpp b/lib/SIL/SILGlobalVariable.cpp
index 773de01..d72be17 100644
--- a/lib/SIL/SILGlobalVariable.cpp
+++ b/lib/SIL/SILGlobalVariable.cpp
@@ -111,12 +111,24 @@
         }
       }
 
+      // Objective-C selector string literals cannot be used in static
+      // initializers.
+      if (auto *stringLit = dyn_cast<StringLiteralInst>(&I)) {
+        switch (stringLit->getEncoding()) {
+        case StringLiteralInst::Encoding::UTF8:
+        case StringLiteralInst::Encoding::UTF16:
+          continue;
+
+        case StringLiteralInst::Encoding::ObjCSelector:
+          return false;
+        }
+      }
+
       if (I.getKind() != ValueKind::ReturnInst &&
           I.getKind() != ValueKind::StructInst &&
           I.getKind() != ValueKind::TupleInst &&
           I.getKind() != ValueKind::IntegerLiteralInst &&
-          I.getKind() != ValueKind::FloatLiteralInst &&
-          I.getKind() != ValueKind::StringLiteralInst)
+          I.getKind() != ValueKind::FloatLiteralInst)
         return false;
     }
   }
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 7c25075..cfc5127 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -856,6 +856,7 @@
     switch (kind) {
     case StringLiteralInst::Encoding::UTF8: return "utf8 ";
     case StringLiteralInst::Encoding::UTF16: return "utf16 ";
+    case StringLiteralInst::Encoding::ObjCSelector: return "objc_selector ";
     }
     llvm_unreachable("bad string literal encoding");
   }
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 8d34399..9864cb92 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -197,6 +197,7 @@
                                               SGFContext C);
     RValue visitObjectLiteralExpr(ObjectLiteralExpr *E, SGFContext C);
     RValue visitEditorPlaceholderExpr(EditorPlaceholderExpr *E, SGFContext C);
+    RValue visitObjCSelectorExpr(ObjCSelectorExpr *E, SGFContext C);
     RValue visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E,
                                            SGFContext C);
     RValue visitCollectionExpr(CollectionExpr *E, SGFContext C);
@@ -822,6 +823,9 @@
   case StringLiteralInst::Encoding::UTF8:
     Elts = EltsArray;
     break;
+
+  case StringLiteralInst::Encoding::ObjCSelector:
+    llvm_unreachable("Objective-C selectors cannot be formed here");
   }
 
   return RValue(Elts, ty);
@@ -1957,6 +1961,46 @@
   return visit(E->getSemanticExpr(), C);
 }
 
+RValue RValueEmitter::visitObjCSelectorExpr(ObjCSelectorExpr *e, SGFContext C) {
+  SILType loweredSelectorTy = SGF.getLoweredType(e->getType());
+
+  // Dig out the declaration of the Selector type.
+  auto selectorDecl = e->getType()->getAs<StructType>()->getDecl();
+
+  // Dig out the type of its pointer.
+  Type selectorMemberTy;
+  for (auto member : selectorDecl->getMembers()) {
+    if (auto var = dyn_cast<VarDecl>(member)) {
+      if (!var->isStatic() && var->hasStorage()) {
+        selectorMemberTy = var->getInterfaceType()->getRValueType();
+        break;
+      }
+    }
+  }
+  if (!selectorMemberTy) {
+    SGF.SGM.diagnose(e, diag::objc_selector_malformed);
+    return RValue(SGF, e, SGF.emitUndef(e, loweredSelectorTy));
+  }
+
+  // Form the selector string.
+  llvm::SmallString<64> selectorScratch;
+  auto selectorString =
+    e->getMethod()->getObjCSelector().getString(selectorScratch);
+
+  // Create an Objective-C selector string literal.
+  auto selectorLiteral =
+    SGF.B.createStringLiteral(e, selectorString,
+                              StringLiteralInst::Encoding::ObjCSelector);
+
+  // Create the pointer struct from the raw pointer.
+  SILType loweredPtrTy = SGF.getLoweredType(selectorMemberTy);
+  auto ptrValue = SGF.B.createStruct(e, loweredPtrTy, { selectorLiteral });
+
+  // Wrap that up in a Selector and return it.
+  auto selectorValue = SGF.B.createStruct(e, loweredSelectorTy, { ptrValue });
+  return RValue(SGF, e, ManagedValue::forUnmanaged(selectorValue));
+}
+
 static StringRef
 getMagicFunctionString(SILGenFunction &gen) {
   assert(gen.MagicFunctionName
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index e33cf15..dd679ad 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -216,6 +216,12 @@
   if (CD->isFinal())
     return true;
 
+  // If the class has an @objc ancestry it can be dynamically subclassed and we
+  // can't therefore statically know the default case.
+  auto Ancestry = CD->checkObjCAncestry();
+  if (Ancestry != ObjCClassKind::NonObjC)
+    return false;
+
   // Without an associated context we cannot perform any
   // access-based optimizations.
   if (!DC)
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 86e38c8..159c29c 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -3262,6 +3262,147 @@
       return E;
     }
 
+    Expr *visitObjCSelectorExpr(ObjCSelectorExpr *E) {
+      // Dig out the reference to a declaration.
+      Expr *subExpr = E->getSubExpr();
+      ValueDecl *foundDecl = nullptr;
+      while (subExpr) {
+        // Declaration reference.
+        if (auto declRef = dyn_cast<DeclRefExpr>(subExpr)) {
+          foundDecl = declRef->getDecl();
+          break;
+        }
+
+        // Constructor reference.
+        if (auto ctorRef = dyn_cast<OtherConstructorDeclRefExpr>(subExpr)) {
+          foundDecl = ctorRef->getDecl();
+          break;
+        }
+
+        // Member reference.
+        if (auto memberRef = dyn_cast<MemberRefExpr>(subExpr)) {
+          foundDecl = memberRef->getMember().getDecl();
+          break;
+        }
+
+        // Dynamic member reference.
+        if (auto dynMemberRef = dyn_cast<DynamicMemberRefExpr>(subExpr)) {
+          foundDecl = dynMemberRef->getMember().getDecl();
+          break;
+        }
+
+        // Look through parentheses.
+        if (auto paren = dyn_cast<ParenExpr>(subExpr)) {
+          subExpr = paren->getSubExpr();
+          continue;
+        }
+
+        // Look through "a.b" to "b".
+        if (auto dotSyntax = dyn_cast<DotSyntaxBaseIgnoredExpr>(subExpr)) {
+          subExpr = dotSyntax->getRHS();
+          continue;
+        }
+
+        // Look through self-rebind expression.
+        if (auto rebindSelf = dyn_cast<RebindSelfInConstructorExpr>(subExpr)) {
+          subExpr = rebindSelf->getSubExpr();
+          continue;
+        }
+
+        // Look through optional binding within the monadic "?".
+        if (auto bind = dyn_cast<BindOptionalExpr>(subExpr)) {
+          subExpr = bind->getSubExpr();
+          continue;
+        }
+
+        // Look through optional evaluation of the monadic "?".
+        if (auto optEval = dyn_cast<OptionalEvaluationExpr>(subExpr)) {
+          subExpr = optEval->getSubExpr();
+          continue;
+        }
+
+        // Look through an implicit force-value.
+        if (auto force = dyn_cast<ForceValueExpr>(subExpr)) {
+          subExpr = force->getSubExpr();
+          continue;
+        }
+
+        // Look through implicit open-existential operations.
+        if (auto open = dyn_cast<OpenExistentialExpr>(subExpr)) {
+          if (open->isImplicit()) {
+            subExpr = open->getSubExpr();
+            continue;
+          }
+          break;
+        }
+
+        // Look to the referenced member in a self-application.
+        if (auto selfApply = dyn_cast<SelfApplyExpr>(subExpr)) {
+          subExpr = selfApply->getFn();
+          continue;
+        }
+
+        // Look through implicit conversions.
+        if (auto conversion = dyn_cast<ImplicitConversionExpr>(subExpr)) {
+          subExpr = conversion->getSubExpr();
+          continue;
+        }
+
+        // Look through explicit coercions.
+        if (auto coercion = dyn_cast<CoerceExpr>(subExpr)) {
+          subExpr = coercion->getSubExpr();
+          continue;
+        }
+
+        break;
+      }
+
+      if (!subExpr) return nullptr;
+
+      // If we didn't find any declaration at all, we're stuck.
+      auto &tc = cs.getTypeChecker();
+      if (!foundDecl) {
+        tc.diagnose(E->getLoc(), diag::expr_selector_no_declaration)
+          .highlight(subExpr->getSourceRange());
+        return E;
+      }
+
+      // If the declaration we found was not a method or initializer,
+      // complain.
+      auto func = dyn_cast<AbstractFunctionDecl>(foundDecl);
+      if (!func) {
+        tc.diagnose(E->getLoc(),
+                    isa<VarDecl>(foundDecl)
+                      ? diag::expr_selector_property
+                      : diag::expr_selector_not_method_or_init)
+          .highlight(subExpr->getSourceRange());
+        tc.diagnose(foundDecl, diag::decl_declared_here,
+                    foundDecl->getFullName());
+        return E;
+      }
+
+      // The declaration we found must be exposed to Objective-C.
+      if (!func->isObjC()) {
+        tc.diagnose(E->getLoc(), diag::expr_selector_not_objc,
+                    isa<ConstructorDecl>(func))
+          .highlight(subExpr->getSourceRange());
+        if (foundDecl->getLoc().isValid()) {
+          tc.diagnose(foundDecl,
+                      diag::expr_selector_make_objc,
+                      isa<ConstructorDecl>(func))
+            .fixItInsert(foundDecl->getAttributeInsertionLoc(false),
+                         "@objc ");
+        } else {
+          tc.diagnose(foundDecl, diag::decl_declared_here,
+                      foundDecl->getFullName());
+        }
+        return E;
+      }
+
+      E->setMethod(func);
+      return E;
+    }
+
     /// Interface for ExprWalker
     void walkToExprPre(Expr *expr) {
       ExprStack.push_back(expr);
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index d99e3c0..a962e58 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -2479,6 +2479,26 @@
       // case we return the null type.
       return E->getType();
     }
+
+    Type visitObjCSelectorExpr(ObjCSelectorExpr *E) {
+      // #selector only makes sense when we have the Objective-C
+      // runtime.
+      auto &tc = CS.getTypeChecker();
+      if (!tc.Context.LangOpts.EnableObjCInterop) {
+        tc.diagnose(E->getLoc(), diag::expr_selector_no_objc_runtime);
+        return nullptr;
+      }
+
+      // Make sure we can reference ObjectiveC.Selector.
+      // FIXME: Fix-It to add the import?
+      auto type = CS.getTypeChecker().getObjCSelectorType(CS.DC);
+      if (!type) {
+        tc.diagnose(E->getLoc(), diag::expr_selector_module_missing);
+        return nullptr;
+      }
+
+      return type;
+    }
   };
 
   /// \brief AST walker that "sanitizes" an expression for the
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 203ad72..7ad9814 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -1825,6 +1825,365 @@
    .fixItRemoveChars(FS->getSecondSemicolonLoc(), endOfIncrementLoc);
 }
 
+static Optional<ObjCSelector>
+parseObjCSelector(ASTContext &ctx, StringRef string) {
+  // Find the first colon.
+  auto colonPos = string.find(':');
+
+  // If there is no colon, we have a nullary selector.
+  if (colonPos == StringRef::npos) {
+    if (string.empty() || !Lexer::isIdentifier(string)) return None;
+    return ObjCSelector(ctx, 0, { ctx.getIdentifier(string) });
+  }
+
+  SmallVector<Identifier, 2> pieces;
+  do {
+    // Check whether we have a valid selector piece.
+    auto piece = string.substr(0, colonPos);
+    if (piece.empty()) {
+      pieces.push_back(Identifier());
+    } else {
+      if (!Lexer::isIdentifier(piece)) return None;
+      pieces.push_back(ctx.getIdentifier(piece));
+    }
+
+    // Move to the next piece.
+    string = string.substr(colonPos+1);
+    colonPos = string.find(':');
+  } while (colonPos != StringRef::npos);
+
+  // If anything remains of the string, it's not a selector.
+  if (!string.empty()) return None;
+
+  return ObjCSelector(ctx, pieces.size(), pieces);
+}
+
+
+namespace {
+
+class ObjCSelectorWalker : public ASTWalker {
+  TypeChecker &TC;
+  const DeclContext *DC;
+  Type SelectorTy;
+
+  /// Determine whether a reference to the given method via its
+  /// enclosing class/protocol is ambiguous (and, therefore, needs to
+  /// be disambiguated with a coercion).
+  bool isSelectorReferenceAmbiguous(AbstractFunctionDecl *method) {
+    // Determine the name we would search for. If there are no
+    // argument names, our lookup will be based solely on the base
+    // name.
+    DeclName lookupName = method->getFullName();
+    if (lookupName.getArgumentNames().empty())
+      lookupName = lookupName.getBaseName();
+
+    // Look for members with the given name.
+    auto nominal =
+      method->getDeclContext()->isNominalTypeOrNominalTypeExtensionContext();
+    auto result = TC.lookupMember(const_cast<DeclContext *>(DC),
+                                  nominal->getInterfaceType(), lookupName,
+                                  (defaultMemberLookupOptions |
+                                   NameLookupFlags::KnownPrivate));
+
+    // If we didn't find multiple methods, there is no ambiguity.
+    if (result.size() < 2) return false;
+
+    // If we found more than two methods, it's ambiguous.
+    if (result.size() > 2) return true;
+
+    // Dig out the methods.
+    auto firstMethod = dyn_cast<FuncDecl>(result[0].Decl);
+    auto secondMethod = dyn_cast<FuncDecl>(result[1].Decl);
+    if (!firstMethod || !secondMethod) return true;
+
+    // If one is a static/class method and the other is not...
+    if (firstMethod->isStatic() == secondMethod->isStatic()) return true;
+
+    // ... overload resolution will prefer the static method. Check
+    // that it has the correct selector. We don't even care that it's
+    // the same method we're asking for, just that it has the right
+    // selector.
+    FuncDecl *staticMethod =
+      firstMethod->isStatic() ? firstMethod : secondMethod;
+    return staticMethod->getObjCSelector() != method->getObjCSelector();
+  }
+
+public:
+  ObjCSelectorWalker(TypeChecker &tc, const DeclContext *dc, Type selectorTy)
+    : TC(tc), DC(dc), SelectorTy(selectorTy) { }
+
+  virtual std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
+    // Only diagnose calls.
+    auto call = dyn_cast<CallExpr>(expr);
+    if (!call) return { true, expr };
+
+    // That produce Selectors.
+    if (!call->getType() || !call->getType()->isEqual(SelectorTy))
+      return { true, expr };
+
+    // Via a constructor.
+    ConstructorDecl *ctor = nullptr;
+    if (auto ctorRefCall = dyn_cast<ConstructorRefCallExpr>(call->getFn())) {
+      if (auto ctorRef = dyn_cast<DeclRefExpr>(ctorRefCall->getFn()))
+        ctor = dyn_cast<ConstructorDecl>(ctorRef->getDecl());
+      else if (auto otherCtorRef =
+                 dyn_cast<OtherConstructorDeclRefExpr>(ctorRefCall->getFn()))
+        ctor = otherCtorRef->getDecl();
+    }
+
+    if (!ctor) return { true, expr };
+
+    // Make sure the constructor is within Selector.
+    auto ctorContextType = ctor->getDeclContext()->getDeclaredTypeOfContext();
+    if (!ctorContextType || !ctorContextType->isEqual(SelectorTy))
+      return { true, expr };
+
+    auto argNames = ctor->getFullName().getArgumentNames();
+    if (argNames.size() != 1) return { true, expr };
+
+    // Is this the init(stringLiteral:) initializer or init(_:) initializer?
+    bool fromStringLiteral = false;
+    if (argNames[0] == TC.Context.Id_stringLiteral)
+      fromStringLiteral = true;
+    else if (!argNames[0].empty())
+      return { true, expr };
+
+    // Dig out the argument.
+    Expr *arg = call->getArg()->getSemanticsProvidingExpr();
+    if (auto tupleExpr = dyn_cast<TupleExpr>(arg)) {
+      if (tupleExpr->getNumElements() == 1 &&
+          tupleExpr->getElementName(0) == TC.Context.Id_stringLiteral)
+        arg = tupleExpr->getElement(0)->getSemanticsProvidingExpr();
+    }
+
+    // If the argument is a call, it might be to
+    // init(__builtinStringLiteral:byteSize:isASCII:). If so, dig
+    // through that.
+    if (auto argCall = dyn_cast<CallExpr>(arg)) {
+      if (auto ctorRefCall =
+            dyn_cast<ConstructorRefCallExpr>(argCall->getFn())) {
+        if (auto argCtor =
+              dyn_cast_or_null<ConstructorDecl>(ctorRefCall->getCalledValue())){
+          auto argArgumentNames = argCtor->getFullName().getArgumentNames();
+          if (argArgumentNames.size() == 3 &&
+              argArgumentNames[0] == TC.Context.Id_builtinStringLiteral) {
+            arg = argCall->getArg()->getSemanticsProvidingExpr();
+          }
+        }
+      }
+    }
+
+    // Check whether we have a string literal.
+    auto stringLiteral = dyn_cast<StringLiteralExpr>(arg);
+    if (!stringLiteral) return { true, expr };
+
+    /// Retrieve the parent expression that coerces to Selector, if
+    /// there is one.
+    auto getParentCoercion = [&]() -> CoerceExpr * {
+      auto parentExpr = Parent.getAsExpr();
+      if (!parentExpr) return nullptr;
+
+      auto coerce = dyn_cast<CoerceExpr>(parentExpr);
+      if (!coerce) return nullptr;
+
+      if (coerce->getType() && coerce->getType()->isEqual(SelectorTy))
+        return coerce;
+
+      return nullptr;
+    };
+
+    // Local function that adds the constructor syntax around string
+    // literals implicitly treated as a Selector.
+    auto addSelectorConstruction = [&](InFlightDiagnostic &diag) {
+      if (!fromStringLiteral) return;
+
+      // Introduce the beginning part of the Selector construction.
+      diag.fixItInsert(stringLiteral->getLoc(), "Selector(");
+
+      if (auto coerce = getParentCoercion()) {
+        // If the string literal was coerced to Selector, replace the
+        // coercion with the ")".
+        SourceLoc endLoc = Lexer::getLocForEndOfToken(TC.Context.SourceMgr,
+                                                      expr->getEndLoc());
+        diag.fixItReplace(SourceRange(endLoc, coerce->getEndLoc()), ")");
+      } else {
+        // Otherwise, just insert the closing ")".
+        diag.fixItInsertAfter(stringLiteral->getEndLoc(), ")");
+      }
+    };
+
+    // Try to parse the string literal as an Objective-C selector, and complain
+    // if it isn't one.
+    auto selector = parseObjCSelector(TC.Context, stringLiteral->getValue());
+    if (!selector) {
+      auto diag = TC.diagnose(stringLiteral->getLoc(),
+                              diag::selector_literal_invalid);
+      diag.highlight(stringLiteral->getSourceRange());
+      addSelectorConstruction(diag);
+      return { true, expr };
+    }
+
+    // Look for methods with this selector.
+    SmallVector<AbstractFunctionDecl *, 8> allMethods;
+    DC->lookupAllObjCMethods(*selector, allMethods);
+
+    // If we didn't find any methods, complain.
+    if (allMethods.empty()) {
+      auto diag =
+        TC.diagnose(stringLiteral->getLoc(), diag::selector_literal_undeclared,
+                    *selector);
+      addSelectorConstruction(diag);
+      return { true, expr };
+    }
+
+    // Separate out the accessor methods.
+    auto splitPoint =
+      std::stable_partition(allMethods.begin(), allMethods.end(),
+                            [](AbstractFunctionDecl *abstractFunc) -> bool {
+                              if (auto func = dyn_cast<FuncDecl>(abstractFunc))
+                                return !func->isAccessor();
+
+                              return true;
+                            });
+    ArrayRef<AbstractFunctionDecl *> methods(allMethods.begin(), splitPoint);
+    ArrayRef<AbstractFunctionDecl *> accessors(splitPoint, allMethods.end());
+
+    // Find the "best" method that has this selector, so we can report
+    // that.
+    AbstractFunctionDecl *bestMethod = nullptr;
+    for (auto method : methods) {
+      // If this is the first method, use it.
+      if (!bestMethod) {
+        bestMethod = method;
+        continue;
+      }
+
+      // If referencing the best method would produce an ambiguity and
+      // referencing the new method would not, we have a new "best".
+      if (isSelectorReferenceAmbiguous(bestMethod) &&
+          !isSelectorReferenceAmbiguous(method)) {
+        bestMethod = method;
+        continue;
+      }
+
+      // If this method is within a protocol...
+      if (auto proto =
+            method->getDeclContext()->isProtocolOrProtocolExtensionContext()) {
+        // If the best so far is not from a protocol, or is from a
+        // protocol that inherits this protocol, we have a new best.
+        auto bestProto = bestMethod->getDeclContext()
+          ->isProtocolOrProtocolExtensionContext();
+        if (!bestProto || bestProto->inheritsFrom(proto))
+          bestMethod = method;
+        continue;
+      }
+
+      // This method is from a class.
+      auto classDecl =
+        method->getDeclContext()->isClassOrClassExtensionContext();
+
+      // If the best method was from a protocol, keep it.
+      auto bestClassDecl =
+        bestMethod->getDeclContext()->isClassOrClassExtensionContext();
+      if (!bestClassDecl) continue;
+
+      // If the best method was from a subclass of the place where
+      // this method was declared, we have a new best.
+      while (auto superclassTy = bestClassDecl->getSuperclass()) {
+        auto superclassDecl = superclassTy->getClassOrBoundGenericClass();
+        if (!superclassDecl) break;
+
+        if (classDecl == superclassDecl) {
+          bestMethod = method;
+          break;
+        }
+
+        bestClassDecl = superclassDecl;
+      }
+    }
+
+    // If we have a best method, reference it.
+    if (bestMethod) {
+      // Form the replacement #selector expression.
+      SmallString<32> replacement;
+      {
+        llvm::raw_svector_ostream out(replacement);
+        auto nominal = bestMethod->getDeclContext()
+                         ->isNominalTypeOrNominalTypeExtensionContext();
+        auto name = bestMethod->getFullName();
+        out << "#selector(" << nominal->getName().str() << "."
+            << name.getBaseName().str();
+        auto argNames = name.getArgumentNames();
+
+        // Only print the parentheses if there are some argument
+        // names, because "()" would indicate a call.
+        if (argNames.size() > 0) {
+          out << "(";
+          for (auto argName : argNames) {
+            if (argName.empty()) out << "_";
+            else out << argName.str();
+            out << ":";
+          }
+          out << ")";
+        }
+
+        // If there will be an ambiguity when referring to the method,
+        // introduce a coercion to resolve it to the method we found.
+        if (isSelectorReferenceAmbiguous(bestMethod)) {
+          if (auto fnType =
+                bestMethod->getInterfaceType()->getAs<FunctionType>()) {
+            // For static/class members, drop the metatype argument.
+            if (bestMethod->isStatic())
+              fnType = fnType->getResult()->getAs<FunctionType>();
+
+            // Drop the argument labels.
+            // FIXME: They never should have been in the type anyway.
+            Type type = fnType->getUnlabeledType(TC.Context);
+
+            // Coerce to this type.
+            out << " as ";
+            type.print(out);
+          }
+        }
+
+        out << ")";
+      }
+
+      // Emit the diagnostic.
+      SourceRange replacementRange = expr->getSourceRange();
+      if (auto coerce = getParentCoercion())
+        replacementRange.End = coerce->getEndLoc();
+
+      TC.diagnose(expr->getLoc(),
+                  fromStringLiteral ? diag::selector_literal_deprecated_suggest
+                                    : diag::selector_construction_suggest)
+        .fixItReplace(replacementRange, replacement);
+      return { true, expr };
+    }
+
+    // If we couldn't pick a method to use for #selector, just wrap
+    // the string literal in Selector(...).
+    if (fromStringLiteral) {
+      auto diag = TC.diagnose(stringLiteral->getLoc(),
+                              diag::selector_literal_deprecated);
+      addSelectorConstruction(diag);
+      return { true, expr };
+    }
+
+    return { true, expr };
+  }
+
+};
+}
+
+static void diagDeprecatedObjCSelectors(TypeChecker &tc, const DeclContext *dc,
+                                        const Expr *expr) {
+  auto selectorTy = tc.getObjCSelectorType(const_cast<DeclContext *>(dc));
+  if (!selectorTy) return;
+
+  const_cast<Expr *>(expr)->walk(ObjCSelectorWalker(tc, dc, selectorTy));
+}
+
 //===----------------------------------------------------------------------===//
 // High-level entry points.
 //===----------------------------------------------------------------------===//
@@ -1838,6 +2197,8 @@
   diagRecursivePropertyAccess(TC, E, DC);
   diagnoseImplicitSelfUseInClosure(TC, E, DC);
   diagAvailability(TC, E, const_cast<DeclContext*>(DC));
+  if (TC.Context.LangOpts.EnableObjCInterop)
+    diagDeprecatedObjCSelectors(TC, DC, E);
 }
 
 void swift::performStmtDiagnostics(TypeChecker &TC, const Stmt *S) {
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index cbffef8..1f6d04e 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -2387,6 +2387,14 @@
       method->setForeignErrorConvention(*errorConvention);
     }
   }
+
+  // Record this method in the source-file-specific Objective-C method
+  // table.
+  if (auto method = dyn_cast<AbstractFunctionDecl>(D)) {
+    if (auto sourceFile = method->getParentSourceFile()) {
+      sourceFile->ObjCMethods[method->getObjCSelector()].push_back(method);
+    }
+  }
 }
 
 namespace {
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 1d8165e..6cc1459 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -110,11 +110,11 @@
   return Type();
 }
 
-static Type getObjectiveCClassType(TypeChecker &TC,
-                                   Type &cache,
-                                   Identifier ModuleName,
-                                   Identifier TypeName,
-                                   DeclContext *dc) {
+static Type getObjectiveCNominalType(TypeChecker &TC,
+                                     Type &cache,
+                                     Identifier ModuleName,
+                                     Identifier TypeName,
+                                     DeclContext *dc) {
   if (cache)
     return cache;
 
@@ -141,17 +141,24 @@
 }
 
 Type TypeChecker::getNSObjectType(DeclContext *dc) {
-  return getObjectiveCClassType(*this, NSObjectType, Context.Id_ObjectiveC,
+  return getObjectiveCNominalType(*this, NSObjectType, Context.Id_ObjectiveC,
                                 Context.getSwiftId(
                                   KnownFoundationEntity::NSObject),
                                 dc);
 }
 
 Type TypeChecker::getNSErrorType(DeclContext *dc) {
-  return getObjectiveCClassType(*this, NSObjectType, Context.Id_Foundation,
-                                Context.getSwiftId(
-                                  KnownFoundationEntity::NSError),
-                                dc);
+  return getObjectiveCNominalType(*this, NSObjectType, Context.Id_Foundation,
+                                  Context.getSwiftId(
+                                    KnownFoundationEntity::NSError),
+                                  dc);
+}
+
+Type TypeChecker::getObjCSelectorType(DeclContext *dc) {
+  return getObjectiveCNominalType(*this, ObjCSelectorType,
+                                  Context.Id_ObjectiveC,
+                                  Context.Id_Selector,
+                                  dc);
 }
 
 Type TypeChecker::getBridgedToObjC(const DeclContext *dc, Type type) {
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index af8d983..aa0dafe 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -508,6 +508,7 @@
   Type UInt8Type;
   Type NSObjectType;
   Type NSErrorType;
+  Type ObjCSelectorType;
   Type ExceptionType;
 
   /// The \c Swift.UnsafeMutablePointer<T> declaration.
@@ -582,6 +583,7 @@
   Type getUInt8Type(DeclContext *dc);
   Type getNSObjectType(DeclContext *dc);
   Type getNSErrorType(DeclContext *dc);
+  Type getObjCSelectorType(DeclContext *dc);
   Type getExceptionType(DeclContext *dc, SourceLoc loc);
 
   /// \brief Try to resolve an IdentTypeRepr, returning either the referenced
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index d66e4e2..1ed3c07 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -38,6 +38,7 @@
   switch (value) {
   case SIL_UTF8: return StringLiteralInst::Encoding::UTF8;
   case SIL_UTF16: return StringLiteralInst::Encoding::UTF16;
+  case SIL_OBJC_SELECTOR: return StringLiteralInst::Encoding::ObjCSelector;
   default: return None;
   }
 }
diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp
index f4cf604..f856cd8 100644
--- a/lib/Serialization/ModuleFile.cpp
+++ b/lib/Serialization/ModuleFile.cpp
@@ -1405,6 +1405,25 @@
   }
 }
 
+void ModuleFile::lookupObjCMethods(
+       ObjCSelector selector,
+       SmallVectorImpl<AbstractFunctionDecl *> &results) {
+  // If we don't have an Objective-C method table, there's nothing to do.
+  if (!ObjCMethods) return;
+
+  // Look for all methods in the module file with this selector.
+  auto known = ObjCMethods->find(selector);
+  if (known == ObjCMethods->end()) return;
+
+  auto found = *known;
+  for (const auto &result : found) {
+    // Deserialize the method and add it to the list.
+    if (auto func = dyn_cast_or_null<AbstractFunctionDecl>(
+                      getDecl(std::get<2>(result))))
+      results.push_back(func);
+  }
+}
+
 void
 ModuleFile::collectLinkLibraries(Module::LinkLibraryCallback callback) const {
   for (auto &lib : LinkLibraries)
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index 4cba484..7b3ec1d 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -32,7 +32,8 @@
 
 enum SILStringEncoding : uint8_t {
   SIL_UTF8,
-  SIL_UTF16
+  SIL_UTF16,
+  SIL_OBJC_SELECTOR,
 };
 
 enum SILLinkageEncoding : uint8_t {
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 333d35d..ae0d561 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -37,6 +37,7 @@
   switch (encoding) {
   case StringLiteralInst::Encoding::UTF8: return SIL_UTF8;
   case StringLiteralInst::Encoding::UTF16: return SIL_UTF16;
+  case StringLiteralInst::Encoding::ObjCSelector: return SIL_OBJC_SELECTOR;
   }
   llvm_unreachable("bad string encoding");
 }
diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp
index 96a14b6..3e769fb 100644
--- a/lib/Serialization/SerializedModuleLoader.cpp
+++ b/lib/Serialization/SerializedModuleLoader.cpp
@@ -476,6 +476,12 @@
   File.lookupClassMember(accessPath, name, decls);
 }
 
+void SerializedASTFile::lookupObjCMethods(
+       ObjCSelector selector,
+       SmallVectorImpl<AbstractFunctionDecl *> &results) const {
+  File.lookupObjCMethods(selector, results);
+}
+
 Optional<BriefAndRawComment>
 SerializedASTFile::getCommentForDecl(const Decl *D) const {
   return File.getCommentForDecl(D);
diff --git a/stdlib/private/StdlibUnittestFoundationExtras/StdlibUnittestFoundationExtras.swift b/stdlib/private/StdlibUnittestFoundationExtras/StdlibUnittestFoundationExtras.swift
index 5966470..2514722 100644
--- a/stdlib/private/StdlibUnittestFoundationExtras/StdlibUnittestFoundationExtras.swift
+++ b/stdlib/private/StdlibUnittestFoundationExtras/StdlibUnittestFoundationExtras.swift
@@ -27,11 +27,11 @@
   @noescape _ body: () -> Result
 ) -> Result {
   let oldMethod = class_getClassMethod(
-    NSLocale.self, Selector("currentLocale"))
+    NSLocale.self, #selector(NSLocale.currentLocale))
   precondition(oldMethod != nil, "could not find +[NSLocale currentLocale]")
 
   let newMethod = class_getClassMethod(
-    NSLocale.self, Selector("_swiftUnittest_currentLocale"))
+    NSLocale.self, #selector(NSLocale._swiftUnittest_currentLocale))
   precondition(newMethod != nil, "could not find +[NSLocale _swiftUnittest_currentLocale]")
 
   precondition(_temporaryNSLocaleCurrentLocale == nil,
diff --git a/test/ClangModules/objc_ir.swift b/test/ClangModules/objc_ir.swift
index 72c7ca7..d96ca24 100644
--- a/test/ClangModules/objc_ir.swift
+++ b/test/ClangModules/objc_ir.swift
@@ -11,9 +11,9 @@
 import TestProtocols
 import ObjCIRExtras
 
-// CHECK: @"\01L_selector_data(method:withFloat:)" = internal constant [18 x i8] c"method:withFloat:\00"
-// CHECK: @"\01L_selector_data(method:withDouble:)" = internal constant [19 x i8] c"method:withDouble:\00"
-// CHECK: @"\01L_selector_data(method:separateExtMethod:)" = internal constant [26 x i8] c"method:separateExtMethod:\00", section "__TEXT,__objc_methname,cstring_literals"
+// CHECK: @"\01L_selector_data(method:withFloat:)" = private global [18 x i8] c"method:withFloat:\00"
+// CHECK: @"\01L_selector_data(method:withDouble:)" = private global [19 x i8] c"method:withDouble:\00"
+// CHECK: @"\01L_selector_data(method:separateExtMethod:)" = private global [26 x i8] c"method:separateExtMethod:\00", section "__TEXT,__objc_methname,cstring_literals"
 
 // Instance method invocation
 // CHECK: define hidden void @_TF7objc_ir15instanceMethodsFCSo1BT_([[B]]*
diff --git a/test/ClangModules/objc_parse.swift b/test/ClangModules/objc_parse.swift
index 43fb81a..b9003bc 100644
--- a/test/ClangModules/objc_parse.swift
+++ b/test/ClangModules/objc_parse.swift
@@ -37,8 +37,8 @@
   b.setEnabled(true)
 
   // SEL
-  b.performSelector("isEqual:", withObject:b)
-  if let result = b.performSelector("getAsProto", withObject:nil) {
+  b.performSelector(#selector(NSObject.isEqual(_:)), withObject:b)
+  if let result = b.performSelector(#selector(B.getAsProto), withObject:nil) {
     _ = result.takeUnretainedValue()
   }
 
@@ -208,7 +208,7 @@
 }
 
 func testId(x: AnyObject) {
-  x.performSelector!("foo:", withObject: x)
+  x.performSelector!("foo:", withObject: x) // expected-warning{{no method declared with Objective-C selector 'foo:'}}
 
   x.performAdd(1, withValue: 2, withValue: 3, withValue2: 4)
   x.performAdd!(1, withValue: 2, withValue: 3, withValue2: 4)
@@ -377,10 +377,10 @@
 func testPropertyAndMethodCollision(obj: PropertyAndMethodCollision,
                                     rev: PropertyAndMethodReverseCollision) {
   obj.object = nil
-  obj.object(obj, doSomething:"action")
+  obj.object(obj, doSomething:Selector("action"))
 
   rev.object = nil
-  rev.object(rev, doSomething:"action")
+  rev.object(rev, doSomething:Selector("action"))
 
   var value: AnyObject = obj.protoProp()
   value = obj.protoPropRO()
diff --git a/test/IDE/complete_pound_selector.swift b/test/IDE/complete_pound_selector.swift
new file mode 100644
index 0000000..74fe893
--- /dev/null
+++ b/test/IDE/complete_pound_selector.swift
@@ -0,0 +1,10 @@
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=AFTER_POUND | FileCheck %s
+
+// REQUIRES: objc_interop
+
+{
+  if ##^AFTER_POUND^#
+}
+
+// CHECK: Keyword/ExprSpecific:               available({#Platform...#}, *); name=available(Platform..., *)
+// CHECK: Keyword/ExprSpecific:               selector({#@objc method#}); name=selector(@objc method)
diff --git a/test/IRGen/objc.swift b/test/IRGen/objc.swift
index c278ce2..b89ea97 100644
--- a/test/IRGen/objc.swift
+++ b/test/IRGen/objc.swift
@@ -18,8 +18,8 @@
 // CHECK: [[RECT:%VSC4Rect]] = type
 // CHECK: [[FLOAT:%Sf]] = type
 
-// CHECK: @"\01L_selector_data(bar)" = internal constant [4 x i8] c"bar\00", section "__TEXT,__objc_methname,cstring_literals", align 1
-// CHECK: @"\01L_selector(bar)" = internal global i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_selector_data(bar)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
+// CHECK: @"\01L_selector_data(bar)" = private global [4 x i8] c"bar\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+// CHECK: @"\01L_selector(bar)" = private externally_initialized global i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_selector_data(bar)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
 
 // CHECK: @_TMnVSC4Rect = linkonce_odr hidden constant
 // CHECK: @_TMVSC4Rect = linkonce_odr hidden global
diff --git a/test/IRGen/objc_selector.sil b/test/IRGen/objc_selector.sil
new file mode 100644
index 0000000..9dfb851
--- /dev/null
+++ b/test/IRGen/objc_selector.sil
@@ -0,0 +1,19 @@
+// RUN: %target-swift-frontend -emit-ir %s | FileCheck %s
+
+// REQUIRES: objc_interop
+
+sil_stage canonical
+
+import Builtin
+
+// CHECK: @"\01L_selector_data(help:me:)" = private global [9 x i8] c"help:me:\00", section "__TEXT,__objc_methname,cstring_literals"
+// CHECK: @"\01L_selector(help:me:)" = private externally_initialized global i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01L_selector_data(help:me:)", {{i(32|64)}} 0, {{i(32|64)}} 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip"
+
+// CHECK-LABEL: define i8* @objc_selector_literal() #0 {
+sil @objc_selector_literal : $@convention(thin) () -> Builtin.RawPointer {
+bb0:
+  // CHECK: [[SEL:%[0-9]+]] = load i8*, i8** @"\01L_selector(help:me:)"
+  %0 = string_literal objc_selector "help:me:"
+  // CHECK-NEXT: ret i8* [[SEL]]
+  return %0 : $Builtin.RawPointer
+}
diff --git a/test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift b/test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift
index 79db467..11a4afd 100644
--- a/test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift
+++ b/test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift
@@ -221,6 +221,10 @@
   public var _code: Int { return code }
 }
 
+extension NSArray {
+  @objc(methodIntroducedInOverlay) public func introducedInOverlay() { }
+}
+
 @_silgen_name("swift_convertNSErrorToErrorType")
 func _convertNSErrorToErrorType(string: NSError?) -> ErrorType
 
diff --git a/test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift b/test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift
index bfb5f66..8ff5b9e 100644
--- a/test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift
+++ b/test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift
@@ -46,6 +46,10 @@
 public struct Selector : StringLiteralConvertible {
   private var ptr : COpaquePointer
 
+  public init(_ value: String) {
+    self.init(stringLiteral: value)
+  }
+
   public init(unicodeScalarLiteral value: String) {
     self.init(stringLiteral: value)
   }
diff --git a/test/Interpreter/SDK/objc_extensions.swift b/test/Interpreter/SDK/objc_extensions.swift
index 19e9bdd..3fd32ac 100644
--- a/test/Interpreter/SDK/objc_extensions.swift
+++ b/test/Interpreter/SDK/objc_extensions.swift
@@ -40,6 +40,10 @@
 // CHECK: true
 print(o.respondsToSelector("setBlackHoleWithHawkingRadiation:"))
 
+// Test #selector for referring to methods.
+// CHECK: true
+print(o.respondsToSelector(#selector(NSObject.frob)))
+
 // CHECK: I've been frobbed!
 o.frob()
 // CHECK: true
diff --git a/test/SILGen/objc_selector.swift b/test/SILGen/objc_selector.swift
new file mode 100644
index 0000000..7ffa4e9
--- /dev/null
+++ b/test/SILGen/objc_selector.swift
@@ -0,0 +1,19 @@
+// RUN: %target-swift-frontend -emit-sil -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | FileCheck %s
+
+// REQUIRES: objc_interop
+
+import ObjectiveC
+import Foundation
+
+class Foo {
+  @objc(methodForInt:) func method(a: Int32) { }
+}
+
+// CHECK-LABEL: sil hidden @_TF13objc_selector14createSelector
+func createSelector(foo: Foo) -> Selector {
+  // CHECK: [[LITERAL:%[0-9]+]] = string_literal objc_selector "methodForInt:"
+  // CHECK-NEXT: [[PTR:%[0-9]+]] = struct $COpaquePointer ([[LITERAL]] : $Builtin.RawPointer)
+  // CHECK-NEXT: [[SEL:%[0-9]+]] = struct $Selector (%3 : $COpaquePointer)
+  // CHECK-: return [[SEL]] : $Selector
+  return #selector(foo.method)
+}
diff --git a/test/SILOptimizer/devirt_speculative.sil b/test/SILOptimizer/devirt_speculative.sil
new file mode 100644
index 0000000..99fc383
--- /dev/null
+++ b/test/SILOptimizer/devirt_speculative.sil
@@ -0,0 +1,106 @@
+// RUN: %target-sil-opt -enable-sil-verify-all %s -specdevirt  | FileCheck %s
+
+sil_stage canonical
+
+@objc class MyNSObject {}
+private class Base : MyNSObject {
+   override init()
+  @inline(never) func foo()
+}
+
+private class Sub : Base {
+  override init()
+  @inline(never) override func foo()
+}
+
+sil private [noinline] @_TBaseFooFun : $@convention(method) (@guaranteed Base) -> () {
+bb0(%0 : $Base):
+  %1 = tuple()
+  return %1 : $()
+}
+
+sil private [noinline] @_TSubFooFun : $@convention(method) (@guaranteed Sub) -> () {
+bb0(%0 : $Sub):
+  %1 = tuple()
+  return %1 : $()
+}
+
+sil_vtable Base {
+  #Base.foo!1: _TBaseFooFun
+}
+
+sil_vtable Sub {
+  #Base.foo!1: _TSubFooFun
+}
+
+sil @test_objc_ancestry : $@convention(thin) (@guaranteed Base) -> () {
+bb0(%0: $Base):
+  %1 = class_method %0 : $Base, #Base.foo!1 : (Base) -> () -> () , $@convention(method) (@guaranteed Base) -> ()
+  %2 = apply %1(%0) : $@convention(method) (@guaranteed Base) -> ()
+  %3 = tuple()
+  return %3 : $()
+}
+
+// Make sure we leave the generic method call because an objc derived class can be extended at runtime.
+
+// CHECK-LABEL: sil @test_objc_ancestry
+// CHECK: bb0
+// CHECK:  [[METH:%.*]] = class_method %0 : $Base, #Base.foo!1 : (Base) -> () -> () , $@convention(method) (@guaranteed Base) -> ()
+// CHECK:  checked_cast_br [exact] %0 : $Base to $Base, bb{{.*}}, bb[[CHECK2:[0-9]+]]
+// CHECK: bb[[CHECK2]]{{.*}}:
+// CHECK:  checked_cast_br [exact] %0 : $Base to $Sub, bb{{.*}}, bb[[GENCALL:[0-9]+]]
+// CHECK: bb[[GENCALL]]{{.*}}:
+// CHECK:  apply [[METH]]
+
+struct MyValue {}
+
+private class Generic<T> : MyNSObject {
+  override init()
+}
+
+private class Base2 : Generic<MyValue> {
+   override init()
+  @inline(never) func foo()
+}
+
+private class Sub2 : Base2 {
+  override init()
+  @inline(never) override func foo()
+}
+
+sil private [noinline] @_TBase2FooFun : $@convention(method) (@guaranteed Base2) -> () {
+bb0(%0 : $Base2):
+  %1 = tuple()
+  return %1 : $()
+}
+
+sil private [noinline] @_TSub2FooFun : $@convention(method) (@guaranteed Sub2) -> () {
+bb0(%0 : $Sub2):
+  %1 = tuple()
+  return %1 : $()
+}
+
+sil_vtable Base2 {
+  #Base2.foo!1: _TBase2FooFun
+}
+
+sil_vtable Sub2 {
+  #Base2.foo!1: _TSub2FooFun
+}
+
+sil @test_objc_ancestry2 : $@convention(thin) (@guaranteed Base2) -> () {
+bb0(%0: $Base2):
+  %1 = class_method %0 : $Base2, #Base2.foo!1 : (Base2) -> () -> () , $@convention(method) (@guaranteed Base2) -> ()
+  %2 = apply %1(%0) : $@convention(method) (@guaranteed Base2) -> ()
+  %3 = tuple()
+  return %3 : $()
+}
+
+// CHECK-LABEL: sil @test_objc_ancestry2
+// CHECK: bb0
+// CHECK:  [[METH:%.*]] = class_method %0 : $Base2, #Base2.foo!1 : (Base2) -> () -> () , $@convention(method) (@guaranteed Base2) -> ()
+// CHECK:  checked_cast_br [exact] %0 : $Base2 to $Base2, bb{{.*}}, bb[[CHECK2:[0-9]+]]
+// CHECK: bb[[CHECK2]]{{.*}}:
+// CHECK:  checked_cast_br [exact] %0 : $Base2 to $Sub2, bb{{.*}}, bb[[GENCALL:[0-9]+]]
+// CHECK: bb[[GENCALL]]{{.*}}:
+// CHECK:  apply [[METH]]
diff --git a/test/SourceKit/CodeComplete/complete_filter.swift b/test/SourceKit/CodeComplete/complete_filter.swift
index 9856628..7684e34 100644
--- a/test/SourceKit/CodeComplete/complete_filter.swift
+++ b/test/SourceKit/CodeComplete/complete_filter.swift
@@ -106,3 +106,20 @@
 // GROUP-NEXT: ]
 // GROUP-LABEL: Results for filterText: overloadp [
 // GROUP-NEXT: ]
+
+struct UnnamedArgs {
+  func dontMatchAgainst(unnamed: Int, arguments: Int, _ unnamed2:Int) {}
+  func test() {
+    self.#^UNNAMED_ARGS_0,dont,arguments,unnamed^#
+  }
+}
+
+// RUN: %complete-test -tok=UNNAMED_ARGS_0 %s | FileCheck %s -check-prefix=UNNAMED_ARGS_0
+// UNNAMED_ARGS_0: Results for filterText: dont [
+// UNNAMED_ARGS_0-NEXT:   dontMatchAgainst(unnamed: Int, arguments: Int, unnamed2: Int)
+// UNNAMED_ARGS_0-NEXT: ]
+// UNNAMED_ARGS_0-NEXT: Results for filterText: arguments [
+// UNNAMED_ARGS_0-NEXT:   dontMatchAgainst(unnamed: Int, arguments: Int, unnamed2: Int)
+// UNNAMED_ARGS_0-NEXT: ]
+// UNNAMED_ARGS_0-NEXT: Results for filterText: unnamed [
+// UNNAMED_ARGS_0-NEXT: ]
diff --git a/test/SourceKit/CodeComplete/complete_member.swift.response b/test/SourceKit/CodeComplete/complete_member.swift.response
index bc604ec..e508eb0 100644
--- a/test/SourceKit/CodeComplete/complete_member.swift.response
+++ b/test/SourceKit/CodeComplete/complete_member.swift.response
@@ -13,7 +13,7 @@
     },
     {
       key.kind: source.lang.swift.decl.function.method.instance,
-      key.name: "fooInstanceFunc1(a:)",
+      key.name: "fooInstanceFunc1(:)",
       key.sourcetext: "fooInstanceFunc1(<#T##a: Int##Int#>)",
       key.description: "fooInstanceFunc1(a: Int)",
       key.typename: "Double",
diff --git a/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift b/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift
index 521fdb3..c6d30a1 100644
--- a/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift
+++ b/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift
@@ -9,7 +9,7 @@
 // RUN: FileCheck %s < %t
 
 // Swift == 1
-// CHECK-LABEL:  key.name: "abs(x:)",
+// CHECK-LABEL:  key.name: "abs(:)",
 // CHECK-NEXT:   key.sourcetext: "abs(<#T##x: T##T#>)",
 // CHECK-NEXT:   key.description: "abs(x: T)",
 // CHECK-NEXT:   key.typename: "T",
@@ -22,7 +22,7 @@
 // CHECK-NEXT: },
 
 // FooHelper.FooHelperExplicit == 1
-// CHECK-LABEL:  key.name: "fooHelperExplicitFrameworkFunc1(a:)",
+// CHECK-LABEL:  key.name: "fooHelperExplicitFrameworkFunc1(:)",
 // CHECK-NEXT:   key.sourcetext: "fooHelperExplicitFrameworkFunc1(<#T##a: Int32##Int32#>)",
 // CHECK-NEXT:   key.description: "fooHelperExplicitFrameworkFunc1(a: Int32)",
 // CHECK-NEXT:   key.typename: "Int32",
diff --git a/test/SourceKit/CodeComplete/complete_name.swift b/test/SourceKit/CodeComplete/complete_name.swift
index 9dfced4..fb606da 100644
--- a/test/SourceKit/CodeComplete/complete_name.swift
+++ b/test/SourceKit/CodeComplete/complete_name.swift
@@ -2,16 +2,19 @@
 // RUN: %complete-test -raw -tok=METHOD_NAME %s | FileCheck %s -check-prefix=METHOD_NAME
 
 struct S {
-  init(a: Int, b: Int) {}
-  func foo(a: Int, b: Int) {}
+  init(a: Int, b: Int, _ c: Int) {}
+  init(_ a: Int, _ b: Int) {}
+  func foo1(a: Int, _ b: Int, _ c: Int) {}
+  func foo2(a a: Int, b: Int, c: Int) {}
 }
 
 func test01() {
   S(#^INIT_NAME^#)
 }
-// INIT_NAME: key.name: "a:b:)"
+// INIT_NAME: key.name: "a:b::)"
 
 func test02(x: S) {
   x.#^METHOD_NAME^#
 }
-// METHOD_NAME: key.name: "foo(a:b:)"
+// METHOD_NAME: key.name: "foo1(:::)"
+// METHOD_NAME: key.name: "foo2(a:b:c:)"
diff --git a/test/SourceKit/CodeComplete/complete_with_closure_param.swift b/test/SourceKit/CodeComplete/complete_with_closure_param.swift
index 1886871..d8ad143 100644
--- a/test/SourceKit/CodeComplete/complete_with_closure_param.swift
+++ b/test/SourceKit/CodeComplete/complete_with_closure_param.swift
@@ -9,12 +9,12 @@
 // RUN: %sourcekitd-test -req=complete -pos=7:5 %s -- %s | FileCheck %s
 
 // CHECK:      key.kind: source.lang.swift.decl.function.method.instance,
-// CHECK-NEXT: key.name: "foo(x:)",
+// CHECK-NEXT: key.name: "foo(:)",
 // CHECK-NEXT: key.sourcetext: "foo(<#T##x: Int -> Int##Int -> Int#>)",
 // CHECK-NEXT: key.description: "foo(x: Int -> Int)",
 // CHECK-NEXT: key.typename: "Void",
 
 // CHECK:      key.kind: source.lang.swift.decl.function.method.instance,
-// CHECK-NEXT: key.name: "foo2(x:)",
+// CHECK-NEXT: key.name: "foo2(:)",
 // CHECK-NEXT: key.sourcetext: "foo2(<#T##x: MyFnTy##MyFnTy##Int -> Int#>)",
 // CHECK-NEXT: key.description: "foo2(x: MyFnTy)",
diff --git a/test/SourceKit/CodeFormat/indent-computed-property.swift b/test/SourceKit/CodeFormat/indent-computed-property.swift
index 7ed582a..4614d6a 100644
--- a/test/SourceKit/CodeFormat/indent-computed-property.swift
+++ b/test/SourceKit/CodeFormat/indent-computed-property.swift
@@ -16,6 +16,22 @@
         }
 }
 
+class C1 {
+  var total: Int = 0 {
+didSet {
+print()
+    }
+  }
+}
+
+class C2 {
+  var total: Int = 0 {
+    didSet {
+print()
+    }
+  }
+}
+
 // RUN: %sourcekitd-test -req=format -line=1 -length=1 %s >%t.response
 // RUN: %sourcekitd-test -req=format -line=2 -length=1 %s >>%t.response
 // RUN: %sourcekitd-test -req=format -line=3 -length=1 %s >>%t.response
@@ -29,6 +45,8 @@
 // RUN: %sourcekitd-test -req=format -line=14 -length=1 %s >>%t.response
 // RUN: %sourcekitd-test -req=format -line=15 -length=1 %s >>%t.response
 // RUN: %sourcekitd-test -req=format -line=16 -length=1 %s >>%t.response
+// RUN: %sourcekitd-test -req=format -line=21 -length=1 %s >>%t.response
+// RUN: %sourcekitd-test -req=format -line=30 -length=1 %s >>%t.response
 // RUN: FileCheck --strict-whitespace %s <%t.response
 
 // CHECK: key.sourcetext: "class Foo {"
@@ -45,3 +63,6 @@
 // CHECK: key.sourcetext: "    {"
 // CHECK: key.sourcetext: "        return 0"
 // CHECK: key.sourcetext: "    }"
+// CHECK: key.sourcetext: "    didSet {"
+                          "    didSet {"
+// CHECK: key.sourcetext: "        print()"
diff --git a/test/SourceKit/CodeFormat/indent-sibling.swift b/test/SourceKit/CodeFormat/indent-sibling.swift
index 4407b9f..ecd2d8a 100644
--- a/test/SourceKit/CodeFormat/indent-sibling.swift
+++ b/test/SourceKit/CodeFormat/indent-sibling.swift
@@ -1,41 +1,39 @@
-// XFAIL: *
-
 class Foo {
   func foo(Value1 : Int,
     Value2 : Int) {
-	}
+  }
 func bar(value1 : Int,
 value2 : Int,
-	      value3 : Int) {
-	}
-		func foo1(Value1 : Int,
-		Value2 : Int) {}
-		func foo3() {
-			foo(1,
-	2)
-		foo(2,
+        value3 : Int) {
+  }
+    func foo1(Value1 : Int,
+    Value2 : Int) {}
+    func foo3() {
+      foo(1,
+  2)
+    foo(2,
 3)
-		    foo(3,
+        foo(3,
 4)
-		}
-		func intGen() -> Int { return 0 }
-		func foo4() {
-			var a = [1,
-			2,
-						3,
-	1 + 2,
-					intGen()]
-		}
-		func foo5() {
-			var a = [1 : 1,
-						2 : 2,
-					3 + 2 : 3,
-				intGen() : intGen()]
+    }
+    func intGen() -> Int { return 0 }
+    func foo4() {
+      var a = [1,
+      2,
+            3,
+  1 + 2,
+          intGen()]
+    }
+    func foo5() {
+      var a = [1 : 1,
+            2 : 2,
+          3 + 2 : 3,
+        intGen() : intGen()]
         var b = (2,
                    3,
                      4,
                        5)
-		}
+    }
     func foo6<T1: Testable,
      T2: Testable,
            T3: Testable,
@@ -112,38 +110,38 @@
 //                        "value2 : Int,"
 // CHECK: key.sourcetext: "value3 : Int) {"
 
-//                        "		func foo1(Value1 : Int,"
-// CHECK: key.sourcetext: "		          Value2 : Int) {}"
+//                        "    func foo1(Value1 : Int,"
+// CHECK: key.sourcetext: "              Value2 : Int) {}"
 
-//                        "			foo(1,"
-// CHECK: key.sourcetext: "			    2)"
+//                        "      foo(1,"
+// CHECK: key.sourcetext: "          2)"
 
-//                        "		foo(2,"
-// CHECK: key.sourcetext: "		    3)"
+//                        "    foo(2,"
+// CHECK: key.sourcetext: "        3)"
 
-//                        "		    foo(3,"
-// CHECK: key.sourcetext: "		        4)"
+//                        "        foo(3,"
+// CHECK: key.sourcetext: "            4)"
 
-//                        "			var a = [1,"
-// CHECK: key.sourcetext: "			         2,"
+//                        "      var a = [1,"
+// CHECK: key.sourcetext: "               2,"
 
-//                        "			2,"
-// CHECK: key.sourcetext: "			3,"
+//                        "      2,"
+// CHECK: key.sourcetext: "      3,"
 
-//                        "						3,"
-// CHECK: key.sourcetext: "						1 + 2,"
+//                        "            3,"
+// CHECK: key.sourcetext: "            1 + 2,"
 
-//                        "	1 + 2,"
-// CHECK: key.sourcetext: "	intGen()]"
+//                        "  1 + 2,"
+// CHECK: key.sourcetext: "  intGen()]"
 
-//                        "			var a = [1 : 1,"
-// CHECK: key.sourcetext: "			         2 : 2,"
+//                        "      var a = [1 : 1,"
+// CHECK: key.sourcetext: "               2 : 2,"
 
-//                        "						2 : 2,"
-// CHECK: key.sourcetext: "						3 + 2 : 3,"
+//                        "            2 : 2,"
+// CHECK: key.sourcetext: "            3 + 2 : 3,"
 
-//                        "					3 + 2 : 3,"
-// CHECK: key.sourcetext: "					intGen() : intGen()]"
+//                        "          3 + 2 : 3,"
+// CHECK: key.sourcetext: "          intGen() : intGen()]"
 
 //                        "        var b = (2,"
 // CHECK: key.sourcetext: "                 3,"
diff --git a/test/expr/unary/selector/fixits.swift b/test/expr/unary/selector/fixits.swift
new file mode 100644
index 0000000..f80174a
--- /dev/null
+++ b/test/expr/unary/selector/fixits.swift
@@ -0,0 +1,107 @@
+// REQUIRES: objc_interop
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: rm -rf %t.overlays
+// RUN: mkdir -p %t.overlays
+
+// FIXME: BEGIN -enable-source-import hackaround
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %clang-importer-sdk-path/swift-modules/ObjectiveC.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %clang-importer-sdk-path/swift-modules/CoreGraphics.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %clang-importer-sdk-path/swift-modules/Foundation.swift
+// FIXME: END -enable-source-import hackaround
+
+// Make sure we get the right diagnostics.
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t.overlays) -parse %s -verify
+
+// Copy the source, apply the Fix-Its, and compile it again, making
+// sure that we've cleaned up all of the deprecation warnings.
+// RUN: mkdir -p %t.sources
+// RUN: mkdir -p %t.remapping
+// RUN: cp %s %t.sources/fixits.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t.overlays) -parse %t.sources/fixits.swift -fixit-all -emit-fixits-path %t.remapping/fixits.remap
+// RUN: %S/../../../../utils/apply-fixit-edits.py %t.remapping
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t.overlays) -parse %t.sources/fixits.swift 2> %t.result
+
+// RUN: FileCheck %s < %t.result
+// RUN: grep -c "warning:" %t.result | grep 4
+
+// CHECK: warning: no method declared with Objective-C selector 'unknownMethodWithValue:label:'
+// CHECK: warning: string literal is not a valid Objective-C selector
+// CHECK: warning: no method declared with Objective-C selector 'unknownMethodWithValue:label:'
+// CHECK: warning: string literal is not a valid Objective-C selector
+
+import Foundation
+
+class Bar : Foo {
+  @objc(method2WithValue:) override func method2(value: Int) { }
+
+  @objc(overloadedWithInt:) func overloaded(x: Int) { }
+  @objc(overloadedWithString:) func overloaded(x: String) { }
+
+  @objc(staticOverloadedWithInt:) static func staticOverloaded(x: Int) { }
+  @objc(staticOverloadedWithString:) static func staticOverloaded(x: String) { }
+
+  @objc(staticOrNonStatic:) func staticOrNonStatic(x: Int) { }
+  @objc(staticOrNonStatic:) static func staticOrNonStatic(x: Int) { }
+
+  @objc(theInstanceOne:) func staticOrNonStatic2(x: Int) { }
+  @objc(theStaticOne:) static func staticOrNonStatic2(x: Int) { }
+}
+
+class Foo {
+  @objc(methodWithValue:label:) func method(value: Int, label: String) { }
+
+  @objc(method2WithValue:) func method2(value: Int) { }
+
+  @objc func method3() { }
+
+  @objc var property: String = ""
+}
+
+
+func testDeprecatedStringLiteralSelector() {
+  let sel1: Selector = "methodWithValue:label:" // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{24-48=#selector(Foo.method(_:label:))}}
+  _ = sel1
+
+  _ = "methodWithValue:label:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-43=#selector(Foo.method(_:label:))}}
+  _ = "property" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' or explicitly construct a 'Selector'}}{{7-7=Selector(}}{{17-29=)}}
+  _ = "setProperty:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' or explicitly construct a 'Selector'}}{{7-7=Selector(}}{{21-33=)}}
+  _ = "unknownMethodWithValue:label:" as Selector // expected-warning{{no method declared with Objective-C selector 'unknownMethodWithValue:label:'}}{{7-7=Selector(}}{{38-50=)}}
+  _ = "badSelector:label" as Selector // expected-warning{{string literal is not a valid Objective-C selector}}
+  _ = "method2WithValue:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-38=#selector(Foo.method2(_:))}}
+  _ = "method3" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-28=#selector(Foo.method3)}}
+
+  // Overloaded cases
+  _ = "overloadedWithInt:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-39=#selector(Bar.overloaded(_:) as (Bar) -> (Int) -> ())}}
+  _ = "overloadedWithString:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-42=#selector(Bar.overloaded(_:) as (Bar) -> (String) -> ())}}
+
+  _ = "staticOverloadedWithInt:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-45=#selector(Bar.staticOverloaded(_:) as (Int) -> ())}}
+  _ = "staticOverloadedWithString:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-48=#selector(Bar.staticOverloaded(_:) as (String) -> ())}}
+
+  // We don't need coercion here because we get the right selector
+  // from the static method.
+  _ = "staticOrNonStatic:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-39=#selector(Bar.staticOrNonStatic(_:))}}
+
+  // We need coercion here because we asked for a selector from an
+  // instance method with the same name as (but a different selector
+  // from) a static method.
+  _ = "theInstanceOne:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-36=#selector(Bar.staticOrNonStatic2(_:) as (Bar) -> (Int) -> ())}}
+
+  // Note: from Foundation
+  _ = "initWithArray:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-35=#selector(NSSet.init(array:))}}
+
+  // Note: from Foundation overlay
+  _ = "methodIntroducedInOverlay" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-46=#selector(NSArray.introducedInOverlay)}}
+}
+
+func testSelectorConstruction() {
+  _ = Selector("methodWithValue:label:") // expected-warning{{use '#selector' instead of explicitly constructing a 'Selector'}}{{7-41=#selector(Foo.method(_:label:))}}
+  _ = Selector("unknownMethodWithValue:label:") // expected-warning{{no method declared with Objective-C selector 'unknownMethodWithValue:label:'}}
+  _ = Selector("badSelector:label") // expected-warning{{string literal is not a valid Objective-C selector}}
+  _ = Selector("method2WithValue:") // expected-warning{{use '#selector' instead of explicitly constructing a 'Selector'}}{{7-36=#selector(Foo.method2(_:))}}
+  _ = Selector("method3") // expected-warning{{use '#selector' instead of explicitly constructing a 'Selector'}}{{7-26=#selector(Foo.method3)}}
+
+  // Note: from Foundation
+  _ = Selector("initWithArray:") // expected-warning{{use '#selector' instead of explicitly constructing a 'Selector'}}{{7-33=#selector(NSSet.init(array:))}}
+}
diff --git a/test/expr/unary/selector/selector.swift b/test/expr/unary/selector/selector.swift
new file mode 100644
index 0000000..bf3c55d
--- /dev/null
+++ b/test/expr/unary/selector/selector.swift
@@ -0,0 +1,102 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -disable-objc-attr-requires-foundation-module -parse %s -verify
+import ObjectiveC
+
+// REQUIRES: objc_interop
+
+@objc class A { }
+@objc class B { }
+
+class C1 {
+  @objc init(a: A, b: B) { }
+
+  @objc func method1(a: A, b: B) { }
+  @objc(someMethodWithA:B:) func method2(a: A, b: B) { }
+
+  @objc class func method3(a: A, b: B) { } // expected-note{{found this candidate}}
+  @objc class func method3(a a: A, b: B) { } // expected-note{{found this candidate}}
+
+  @objc var a: A = A() // expected-note{{'a' declared here}}
+
+  @objc func getC1() -> AnyObject { return self }
+}
+
+@objc protocol P1 {
+  func method4(a: A, b: B)
+  static func method5(a: B, b: B)
+}
+
+extension C1 {
+  final func method6() { } // expected-note{{add '@objc' to expose this method to Objective-C}}{{3-3=@objc }}
+}
+
+func testSelector(c1: C1, p1: P1, obj: AnyObject) {
+  // Instance methods on an instance
+  let sel1 = #selector(c1.method1)
+  _ = #selector(c1.method1(_:b:))
+  _ = #selector(c1.method2)
+
+  // Instance methods on a class.
+  _ = #selector(C1.method1)
+  _ = #selector(C1.method1(_:b:))
+  _ = #selector(C1.method2)
+
+  // Class methods on a class.
+  _ = #selector(C1.method3(_:b:))
+  _ = #selector(C1.method3(a:b:))
+
+  // Methods on a protocol.
+  _ = #selector(P1.method4)
+  _ = #selector(P1.method4(_:b:))
+  _ = #selector(P1.method5) // FIXME: expected-error{{static member 'method5' cannot be used on instance of type 'P1.Protocol'}}
+  _ = #selector(P1.method5(_:b:)) // FIXME: expected-error{{static member 'method5(_:b:)' cannot be used on instance of type 'P1.Protocol'}}
+  _ = #selector(p1.method4)
+  _ = #selector(p1.method4(_:b:))
+  _ = #selector(p1.dynamicType.method5)
+  _ = #selector(p1.dynamicType.method5(_:b:))
+
+  // Interesting expressions that refer to methods.
+  _ = #selector(Swift.AnyObject.method1)
+  _ = #selector(AnyObject.method1!)
+  _ = #selector(obj.getC1?().method1)
+
+  // Initializers
+  _ = #selector(C1.init(a:b:))
+
+  // Make sure the result has type "ObjectiveC.Selector"
+  let sel2: Selector
+  sel2 = sel1
+  _ = sel2
+}
+
+func testAmbiguity() {
+  _ = #selector(C1.method3) // expected-error{{ambiguous use of 'method3(_:b:)'}}
+}
+
+func testProperties(c1: C1) {
+  _ = #selector(c1.a) // expected-error{{argument of '#selector' cannot refer to a property}}
+  _ = #selector(C1.a) // FIXME poor diagnostic: expected-error{{instance member 'a' cannot be used on type 'C1'}}
+}
+
+func testNonObjC(c1: C1) {
+  _ = #selector(c1.method6) // expected-error{{argument of '#selector' refers to a method that is not exposed to Objective-C}}
+}
+
+func testParseErrors1() {
+  #selector foo // expected-error{{expected '(' following '#selector'}}
+}
+
+func testParseErrors2() {
+  #selector( // expected-error{{expected expression naming a method within '#selector(...)'}}
+}
+
+func testParseErrors3(c1: C1) {
+  #selector( // expected-note{{to match this opening '('}}
+      c1.method1(_:b:) // expected-error{{expected ')' to complete '#selector' expression}}
+}
+
+func testParseErrors4() {
+  // Subscripts
+  _ = #selector(C1.subscript) // expected-error{{expected member name following '.'}}
+  // expected-error@-1{{consecutive statements on a line must be separated by ';'}}
+  // expected-error@-2{{expected '(' for subscript parameters}}
+}
diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp
index 34a4663..b459247 100644
--- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp
+++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp
@@ -873,6 +873,7 @@
       bool shouldPrint = !C.isAnnotation();
       switch (C.getKind()) {
       case ChunkKind::TypeAnnotation:
+      case ChunkKind::CallParameterInternalName:
       case ChunkKind::CallParameterClosureType:
       case ChunkKind::CallParameterType:
       case ChunkKind::DeclAttrParamEqual:
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index 057528c..0edbf10 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -1642,7 +1642,8 @@
         // }
         if (auto VD = dyn_cast_or_null<VarDecl>(Cursor->getAsDecl())) {
           if (auto Getter = VD->getGetter()) {
-            if (Getter->getAccessorKeywordLoc().isInvalid()) {
+            if (!Getter->isImplicit() &&
+                Getter->getAccessorKeywordLoc().isInvalid()) {
               LineAndColumn = ParentLineAndColumn;
               continue;
             }
@@ -1898,7 +1899,7 @@
           if (EleStart.isInvalid()) {
             EleStart = TE->getElement(I)->getStartLoc();
           }
-          addPair(TE->getElement(I)->getEndLoc(), EleStart, tok::comma);
+          addPair(TE->getElement(I)->getEndLoc(), FindAlignLoc(EleStart), tok::comma);
         }
       }
 
@@ -1916,8 +1917,9 @@
         // Function parameters are siblings.
         for (auto P : AFD->getParameterLists()) {
           for (auto param : *P) {
-            addPair(param->getEndLoc(),
-                    FindAlignLoc(param->getStartLoc()), tok::comma);
+           if (!param->isSelfParameter())
+              addPair(param->getEndLoc(), FindAlignLoc(param->getStartLoc()),
+                      tok::comma);
           }
         }
       }
diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index 916c3be..6911bcc 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -582,3 +582,16 @@
 
 release-debuginfo
 assertions
+
+#===------------------------------------------------------------------------===#
+# Test all platforms on OS X builder
+#===------------------------------------------------------------------------===#
+
+[preset: buildbot_all_platforms,tools=RA,stdlib=RA]
+mixin-preset=buildbot_incremental_base
+
+build-subdir=buildbot_incremental
+
+# Build Release without debug info, because it is faster to build.
+release
+assertions
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 07d6b53..52a2edd 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -378,6 +378,7 @@
                 -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING="${cmake_osx_deployment_target}"
                 -DCMAKE_OSX_SYSROOT:PATH="$(xcrun --sdk ${xcrun_sdk_name} --show-sdk-path)"
                 -DLLVM_HOST_TRIPLE:STRING="${llvm_host_triple}"
+                -DLLVM_ENABLE_LIBCXX:BOOL=TRUE
             )
             swift_cmake_options=(
                 "${swift_cmake_options[@]}"
@@ -385,6 +386,7 @@
                 -DSWIFT_DARWIN_DEPLOYMENT_VERSION_IOS="${DARWIN_DEPLOYMENT_VERSION_IOS}"
                 -DSWIFT_DARWIN_DEPLOYMENT_VERSION_TVOS="${DARWIN_DEPLOYMENT_VERSION_TVOS}"
                 -DSWIFT_DARWIN_DEPLOYMENT_VERSION_WATCHOS="${DARWIN_DEPLOYMENT_VERSION_WATCHOS}"
+                -DLLVM_ENABLE_LIBCXX:BOOL=TRUE
             )
 
             if [[ "${llvm_target_arch}" ]] ; then
diff --git a/utils/update-checkout b/utils/update-checkout
index a0ba5d8..a8a262b 100755
--- a/utils/update-checkout
+++ b/utils/update-checkout
@@ -21,41 +21,49 @@
     SWIFT_SOURCE_ROOT,
     WorkingDirectory,
     check_call,
+    check_output,
 )
 
-def update_working_copy(repo_path):
+def update_working_copy(repo_path, branch):
     if not os.path.isdir(repo_path):
         return
 
     print("--- Updating '" + repo_path + "' ---")
     with WorkingDirectory(repo_path):
+        if branch:
+            status = check_output(['git', 'status', '--porcelain'])
+            if status:
+                print("Please, commit your changes.")
+                print(status)
+                exit(1)
+            check_call(['git', 'checkout', branch])
+
         # Prior to Git 2.6, this is the way to do a "git pull
         # --rebase" that respects rebase.autostash.  See
         # http://stackoverflow.com/a/30209750/125349
-        check_call([ "git", "fetch" ])
-        check_call([ "git", "rebase", "FETCH_HEAD" ])
+        check_call(["git", "fetch"])
+        check_call(["git", "rebase", "FETCH_HEAD"])
 
-def obtain_additional_swift_sources(opts = {'with_ssh': False}):
+def obtain_additional_swift_sources(with_ssh, branch):
     additional_repos = {
         'llvm': 'apple/swift-llvm',
         'clang': 'apple/swift-clang',
         'lldb': 'apple/swift-lldb',
         'cmark': 'apple/swift-cmark',
-        'llbuild': 'apple/swift-llbuild',
-        'swiftpm': 'apple/swift-package-manager',
-        'swift-corelibs-xctest': 'apple/swift-corelibs-xctest',
-        'swift-corelibs-foundation': 'apple/swift-corelibs-foundation',
         'swift-integration-tests': 'apple/swift-integration-tests',
     }
     for dir_name, repo in additional_repos.items():
         with WorkingDirectory(SWIFT_SOURCE_ROOT):
             if not os.path.isdir(os.path.join(dir_name, ".git")):
                 print("--- Cloning '" + dir_name + "' ---")
-                if opts['with_ssh'] is True:
+                if with_ssh is True:
                     remote = "git@github.com:" + repo + '.git'
                 else:
                     remote = "https://github.com/" + repo + '.git'
                 check_call(['git', 'clone', remote, dir_name])
+                if branch:
+                    src_path = SWIFT_SOURCE_ROOT + "/" + dir_name + "/" + ".git"
+                    check_call(['git', '--git-dir', src_path, '--work-tree', os.path.join(SWIFT_SOURCE_ROOT, dir_name), 'checkout', branch])
 
 def main():
     parser = argparse.ArgumentParser(
@@ -63,9 +71,9 @@
         description="""
 repositories.
 
-By default, updates your checkouts of Swift, SourceKit, LLDB, and SwiftPM.""")
+By default, updates your checkouts of Swift, and LLDB.""")
     parser.add_argument("-a", "--all",
-        help="also update checkouts of llbuild, LLVM, and Clang",
+        help="also update checkouts of LLVM, and Clang",
         action="store_true")
     parser.add_argument("--clone",
         help="Obtain Sources for Swift and Related Projects",
@@ -73,31 +81,28 @@
     parser.add_argument("--clone-with-ssh",
         help="Obtain Sources for Swift and Related Projects via SSH",
         action="store_true")
+    parser.add_argument("--branch",
+        help="Obtain Sources for specific branch")
     args = parser.parse_args()
 
-    if args.clone:
-        obtain_additional_swift_sources()
-        return 0
+    clone = args.clone
+    clone_with_ssh = args.clone_with_ssh
+    branch = args.branch
 
-    if args.clone_with_ssh:
-        obtain_additional_swift_sources({'with_ssh': True})
+    if clone or clone_with_ssh:
+        obtain_additional_swift_sources(clone_with_ssh, branch)
         return 0
 
     if args.all:
-        update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "llbuild"))
-        update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "llvm"))
-        update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "clang"))
+        update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "llvm"), branch)
+        update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "clang"), branch)
 
-    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "swift"))
+    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "swift"), branch)
     update_working_copy(
-        os.path.join(SWIFT_SOURCE_ROOT, "swift", "benchmark", "PerfTestSuite"))
-    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "SourceKit"))
-    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "cmark"))
-    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "lldb"))
-    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "swiftpm"))
-    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "swift-corelibs-foundation"))
-    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "swift-corelibs-xctest"))
-    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "swift-integration-tests"))
+        os.path.join(SWIFT_SOURCE_ROOT, "swift", "benchmark", "PerfTestSuite"), branch)
+    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "cmark"), branch)
+    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "lldb"), branch)
+    update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "swift-integration-tests"), branch)
 
     return 0