Merge pull request #12602 from phausler/swift-4.0-branch-NSData_isCompact_availability_guard

[Foundation] Guard Data access to NSData._isCompact under availability guards
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index a0a1f3e..7ed2a35 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -2038,10 +2038,17 @@
                  "Storage overrides but setter does not");
         if (ASD->getMaterializeForSetFunc() &&
             baseASD->getMaterializeForSetFunc() &&
-            baseASD->isSetterAccessibleFrom(ASD->getDeclContext()))
-          assert(ASD->getMaterializeForSetFunc()->getOverriddenDecl() ==
-                 baseASD->getMaterializeForSetFunc() &&
-                 "Storage override but materializeForSet does not");
+            baseASD->isSetterAccessibleFrom(ASD->getDeclContext())) {
+          if (baseASD->getMaterializeForSetFunc()->hasForcedStaticDispatch()) {
+            assert(ASD->getMaterializeForSetFunc()->getOverriddenDecl() == nullptr
+                   && "Forced static dispatch materializeForSet should not be "
+                   "overridden");
+          } else {
+            assert(ASD->getMaterializeForSetFunc()->getOverriddenDecl() ==
+                   baseASD->getMaterializeForSetFunc() &&
+                   "Storage override but materializeForSet does not");
+          }
+        }
       } else {
         if (ASD->getGetter())
           assert(!ASD->getGetter()->getOverriddenDecl() &&
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index c4be751..29cf4b4 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -697,12 +697,12 @@
     }
 
     // Allocate the object.
-    return ManagedValue(SGF.B.createAllocRefDynamic(
+    return SGF.emitManagedRValueWithCleanup(
+        SGF.B.createAllocRefDynamic(
                           loc,
                           selfMetaObjC.getValue(),
                           SGF.SGM.getLoweredType(type),
-                          /*objc=*/true, {}, {}),
-                          selfMetaObjC.getCleanup());
+                          /*objc=*/true, {}, {}));
   }
 
   //
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 9fb20e1..cc0aa71 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -872,6 +872,7 @@
     // materializeForSet either.
     auto *baseMFS = baseASD->getMaterializeForSetFunc();
     if (baseMFS != nullptr &&
+        !baseMFS->hasForcedStaticDispatch() &&
         baseASD->isSetterAccessibleFrom(storage->getDeclContext())) {
       materializeForSet->setOverriddenDecl(baseMFS);
     }
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 644cfd2..84f800b 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -623,7 +623,14 @@
   // FIXME: If we reach this point, the program we're being handed is likely
   // very broken, but it's still conceivable that this may happen due to
   // invalid shadowed declarations.
-  // llvm_unreachable("Can't represent lookup result");
+  //
+  // Make sure we emit a diagnostic, since returning an ErrorExpr without
+  // producing one will break things downstream.
+  diagnose(Loc, diag::ambiguous_decl_ref, Name);
+  for (auto Result : Lookup) {
+    auto *Decl = Result.Decl;
+    diagnose(Decl, diag::decl_declared_here, Decl->getFullName());
+  }
   return new (Context) ErrorExpr(UDRE->getSourceRange());
 }
 
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 48b9784..546a2a1 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -6532,6 +6532,13 @@
             !baseASD->isSetterAccessibleFrom(overridingASD->getDeclContext()))
           return;
 
+        // A materializeForSet for an override of storage with a
+        // forced static dispatch materializeForSet is not itself an
+        // override.
+        if (kind == AccessorKind::IsMaterializeForSet &&
+            baseAccessor->hasForcedStaticDispatch())
+          return;
+
         // FIXME: Egregious hack to set an 'override' attribute.
         if (!overridingAccessor->getAttrs().hasAttribute<OverrideAttr>()) {
           auto loc = overridingASD->getOverrideLoc();
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 88c5771..2c0b9e4 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -6059,7 +6059,8 @@
 
 /// Infer the attribute tostatic-initialize the Objective-C metadata for the
 /// given class, if needed.
-static void inferStaticInitializeObjCMetadata(ClassDecl *classDecl) {
+static void inferStaticInitializeObjCMetadata(TypeChecker &tc,
+                                              ClassDecl *classDecl) {
   // If we already have the attribute, there's nothing to do.
   if (classDecl->getAttrs().hasAttribute<StaticInitializeObjCMetadataAttr>())
     return;
@@ -6071,6 +6072,22 @@
     return;
   }
 
+  // If this class isn't always available on the deployment target, don't
+  // mark it as statically initialized.
+  // FIXME: This is a workaround. The proper solution is for IRGen to
+  // only statically initializae the Objective-C metadata when running on
+  // a new-enough OS.
+  if (auto sourceFile = classDecl->getParentSourceFile()) {
+    AvailabilityContext availableInfo = AvailabilityContext::alwaysAvailable();
+    for (Decl *enclosingDecl = classDecl; enclosingDecl;
+         enclosingDecl = enclosingDecl->getDeclContext()
+                           ->getInnermostDeclarationDeclContext()) {
+      if (!tc.isDeclAvailable(enclosingDecl, SourceLoc(), sourceFile,
+                              availableInfo))
+        return;
+    }
+  }
+
   // Infer @_staticInitializeObjCMetadata.
   ASTContext &ctx = classDecl->getASTContext();
   classDecl->getAttrs().add(
@@ -6188,7 +6205,7 @@
         }
 
         // Infer @_staticInitializeObjCMetadata if needed.
-        inferStaticInitializeObjCMetadata(classDecl);
+        inferStaticInitializeObjCMetadata(*this, classDecl);
       }
     }
   }
diff --git a/stdlib/public/runtime/Exclusivity.cpp b/stdlib/public/runtime/Exclusivity.cpp
index a9dbfe3..f363dab 100644
--- a/stdlib/public/runtime/Exclusivity.cpp
+++ b/stdlib/public/runtime/Exclusivity.cpp
@@ -27,12 +27,22 @@
 // If we're using Clang, and Clang claims not to support thread_local,
 // it must be because we're on a platform that doesn't support it.
 // Use pthreads.
-#if __clang__ && !__has_feature(cxx_thread_local)
-#define SWIFT_EXCLUSIVITY_USE_THREADLOCAL 0
-#define SWIFT_EXCLUSIVITY_USE_PTHREAD_SPECIFIC 1
+// Workaround: has_feature(cxx_thread_local) is wrong on two old Apple
+// simulators. clang thinks thread_local works there, but it doesn't.
+#if TARGET_OS_SIMULATOR && !TARGET_RT_64_BIT &&                      \
+  ((TARGET_OS_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \
+   (TARGET_OS_WATCH && __WATCHOS_OS_VERSION_MIN_REQUIRED__ < 30000))
+// 32-bit iOS 9 simulator or 32-bit watchOS 2 simulator - use pthreads
+# define SWIFT_EXCLUSIVITY_USE_THREADLOCAL 0
+# define SWIFT_EXCLUSIVITY_USE_PTHREAD_SPECIFIC 1
+#elif __clang__ && !__has_feature(cxx_thread_local)
+// clang without thread_local support - use pthreads
+# define SWIFT_EXCLUSIVITY_USE_THREADLOCAL 0
+# define SWIFT_EXCLUSIVITY_USE_PTHREAD_SPECIFIC 1
 #else
-#define SWIFT_EXCLUSIVITY_USE_THREADLOCAL 1
-#define SWIFT_EXCLUSIVITY_USE_PTHREAD_SPECIFIC 0
+// Use thread_local
+# define SWIFT_EXCLUSIVITY_USE_THREADLOCAL 1
+# define SWIFT_EXCLUSIVITY_USE_PTHREAD_SPECIFIC 0
 #endif
 
 #endif
diff --git a/test/Constraints/diag_ambiguities.swift b/test/Constraints/diag_ambiguities.swift
index 04dbf66..2bc8432 100644
--- a/test/Constraints/diag_ambiguities.swift
+++ b/test/Constraints/diag_ambiguities.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -verify-ignore-unknown
 
 func f0(_ i: Int, _ d: Double) {} // expected-note{{found this candidate}}
 func f0(_ d: Double, _ i: Int) {} // expected-note{{found this candidate}}
@@ -52,3 +52,21 @@
     take([overloaded]) // no error
   }
 }
+
+// rdar://35116378 - Here the ambiguity is in the pre-check pass; make sure
+// we emit a diagnostic instead of crashing.
+struct Movie {}
+
+protocol P {
+  associatedtype itemType
+  var items: [itemType] { get set }
+}
+
+class MoviesViewController : P {
+  let itemType = [Movie].self // expected-note {{'itemType' declared here}}
+  var items: [Movie] = [Movie]()
+
+  func loadData() {
+    _ = itemType // expected-error {{ambiguous use of 'itemType'}}
+  }
+}
diff --git a/test/Interpreter/objc_protocols.swift b/test/Interpreter/objc_protocols.swift
new file mode 100644
index 0000000..f802024
--- /dev/null
+++ b/test/Interpreter/objc_protocols.swift
@@ -0,0 +1,26 @@
+// RUN: %target-run-simple-swift
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+import StdlibUnittest
+import Foundation
+
+@objc protocol Horse {
+  init()
+}
+
+class Pony : Horse {
+  let x = LifetimeTracked(0)
+
+  required init() {}
+}
+
+var ObjCProtocolsTest = TestSuite("ObjCProtocols")
+
+ObjCProtocolsTest.test("InitRequirement") {
+  let t: Horse.Type = Pony.self
+
+  _ = t.init()
+}
+
+runAllTests()
diff --git a/test/SILGen/objc_protocols.swift b/test/SILGen/objc_protocols.swift
index f29c010..9db52f5 100644
--- a/test/SILGen/objc_protocols.swift
+++ b/test/SILGen/objc_protocols.swift
@@ -267,8 +267,7 @@
   // CHECK:   [[ARCHETYPE_META_OBJC:%[0-9]+]] = thick_to_objc_metatype [[ARCHETYPE_META]] : $@thick (@opened([[N]]) Initializable).Type to $@objc_metatype (@opened([[N]]) Initializable).Type
   // CHECK:   [[I2_ALLOC:%[0-9]+]] = alloc_ref_dynamic [objc] [[ARCHETYPE_META_OBJC]] : $@objc_metatype (@opened([[N]]) Initializable).Type, $@opened([[N]]) Initializable
   // CHECK:   [[INIT_WITNESS:%[0-9]+]] = witness_method [volatile] $@opened([[N]]) Initializable, #Initializable.init!initializer.1.foreign : {{.*}}, [[ARCHETYPE_META]]{{.*}} : $@convention(objc_method) <τ_0_0 where τ_0_0 : Initializable> (Int, @owned τ_0_0) -> @owned τ_0_0
-  // CHECK:   [[I2_COPY:%.*]] = copy_value [[I2_ALLOC]]
-  // CHECK:   [[I2:%[0-9]+]] = apply [[INIT_WITNESS]]<@opened([[N]]) Initializable>([[I]], [[I2_COPY]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Initializable> (Int, @owned τ_0_0) -> @owned τ_0_0
+  // CHECK:   [[I2:%[0-9]+]] = apply [[INIT_WITNESS]]<@opened([[N]]) Initializable>([[I]], [[I2_ALLOC]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Initializable> (Int, @owned τ_0_0) -> @owned τ_0_0
   // CHECK:   [[I2_EXIST_CONTAINER:%[0-9]+]] = init_existential_ref [[I2]] : $@opened([[N]]) Initializable : $@opened([[N]]) Initializable, $Initializable
   // CHECK:   store [[I2_EXIST_CONTAINER]] to [init] [[PB]] : $*Initializable
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*Initializable
diff --git a/test/decl/protocol/conforms/nscoding_availability_osx.swift b/test/decl/protocol/conforms/nscoding_availability_osx.swift
new file mode 100644
index 0000000..b9720cd
--- /dev/null
+++ b/test/decl/protocol/conforms/nscoding_availability_osx.swift
@@ -0,0 +1,22 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -swift-version 4 %s -target x86_64-apple-macosx10.11 -verify
+
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -swift-version 4 %s -target x86_64-apple-macosx10.11 -dump-ast 2> %t.ast
+// RUN: %FileCheck %s < %t.ast
+
+// REQUIRES: objc_interop
+// REQUIRES: OS=macosx
+
+import Foundation
+
+// Nested classes that aren't available in our deployment target.
+@available(OSX 10.12, *)
+class CodingI : NSObject, NSCoding {
+  required init(coder: NSCoder) { }
+  func encode(coder: NSCoder) { }
+}
+
+@available(OSX 10.12, *)
+class OuterCodingJ {
+  // CHECK-NOT: class_decl "NestedJ"{{.*}}@_staticInitializeObjCMetadata
+  class NestedJ : CodingI { }
+}
diff --git a/test/multifile/synthesized-accessors/materialize-for-set-1/Inputs/counter.h b/test/multifile/synthesized-accessors/materialize-for-set-1/Inputs/counter.h
new file mode 100644
index 0000000..930dc7b
--- /dev/null
+++ b/test/multifile/synthesized-accessors/materialize-for-set-1/Inputs/counter.h
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+
+@interface Counter : NSObject
+@property(readwrite) int value;
+@end
diff --git a/test/multifile/synthesized-accessors/materialize-for-set-1/Inputs/library.swift b/test/multifile/synthesized-accessors/materialize-for-set-1/Inputs/library.swift
new file mode 100644
index 0000000..9211695
--- /dev/null
+++ b/test/multifile/synthesized-accessors/materialize-for-set-1/Inputs/library.swift
@@ -0,0 +1,12 @@
+import Foundation
+import CounterFramework
+
+public protocol CounterProtocol {
+  var value: Int32 { get set }
+}
+
+extension Counter : CounterProtocol {}
+
+open class MyCounter : Counter {
+  open override var value: Int32 { didSet { } }
+}
diff --git a/test/multifile/synthesized-accessors/materialize-for-set-1/Inputs/module.map b/test/multifile/synthesized-accessors/materialize-for-set-1/Inputs/module.map
new file mode 100644
index 0000000..ac68c70
--- /dev/null
+++ b/test/multifile/synthesized-accessors/materialize-for-set-1/Inputs/module.map
@@ -0,0 +1,4 @@
+module CounterFramework {
+  header "counter.h"
+  export *
+}
diff --git a/test/multifile/synthesized-accessors/materialize-for-set-1/main.swift b/test/multifile/synthesized-accessors/materialize-for-set-1/main.swift
new file mode 100644
index 0000000..7944043
--- /dev/null
+++ b/test/multifile/synthesized-accessors/materialize-for-set-1/main.swift
@@ -0,0 +1,17 @@
+// RUN: %empty-directory(%t)
+
+// RUN: mkdir -p %t/onone %t/wmo
+// RUN: %target-build-swift -emit-module -emit-module-path %t/onone/library.swiftmodule -I %S/Inputs/ -module-name=library %S/Inputs/library.swift
+// RUN: %target-build-swift %S/main.swift -I %S/Inputs/ -I %t/onone/ -emit-ir > /dev/null
+
+// RUN: %target-build-swift -emit-module -emit-module-path %t/wmo/library.swiftmodule -I %S/Inputs/ -module-name=library -wmo %S/Inputs/library.swift
+// RUN: %target-build-swift %S/main.swift -I %S/Inputs/ -I %t/wmo/ -emit-ir > /dev/null
+
+// REQUIRES: objc_interop
+
+import Foundation
+import library
+
+class CustomCounter : MyCounter {
+  override var value: Int32 { didSet { } }
+}
diff --git a/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/counter.h b/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/counter.h
new file mode 100644
index 0000000..930dc7b
--- /dev/null
+++ b/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/counter.h
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+
+@interface Counter : NSObject
+@property(readwrite) int value;
+@end
diff --git a/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/library1.swift b/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/library1.swift
new file mode 100644
index 0000000..7a2041c
--- /dev/null
+++ b/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/library1.swift
@@ -0,0 +1,8 @@
+import Foundation
+import CounterFramework
+
+public protocol CounterProtocol {
+  var value: Int32 { get set }
+}
+
+extension Counter : CounterProtocol {}
diff --git a/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/library2.swift b/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/library2.swift
new file mode 100644
index 0000000..7ac2f8c
--- /dev/null
+++ b/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/library2.swift
@@ -0,0 +1,6 @@
+import Foundation
+import CounterFramework
+
+open class MyCounter : Counter {
+  open override var value: Int32 { didSet { } }
+}
diff --git a/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/module.map b/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/module.map
new file mode 100644
index 0000000..ac68c70
--- /dev/null
+++ b/test/multifile/synthesized-accessors/materialize-for-set-2/Inputs/module.map
@@ -0,0 +1,4 @@
+module CounterFramework {
+  header "counter.h"
+  export *
+}
diff --git a/test/multifile/synthesized-accessors/materialize-for-set-2/main.swift b/test/multifile/synthesized-accessors/materialize-for-set-2/main.swift
new file mode 100644
index 0000000..a9d3ddc
--- /dev/null
+++ b/test/multifile/synthesized-accessors/materialize-for-set-2/main.swift
@@ -0,0 +1,17 @@
+// RUN: %empty-directory(%t)
+
+// RUN: mkdir -p %t/onone %t/wmo
+// RUN: %target-build-swift -emit-module -emit-module-path %t/onone/library.swiftmodule -I %S/Inputs/ -module-name=library %S/Inputs/library1.swift %S/Inputs/library2.swift
+// RUN: %target-build-swift %S/main.swift -I %S/Inputs/ -I %t/onone/ -emit-ir > /dev/null
+
+// RUN: %target-build-swift -emit-module -emit-module-path %t/wmo/library.swiftmodule -I %S/Inputs/ -module-name=library -wmo %S/Inputs/library1.swift %S/Inputs/library2.swift
+// RUN: %target-build-swift %S/main.swift -I %S/Inputs/ -I %t/wmo/ -emit-ir > /dev/null
+
+// REQUIRES: objc_interop
+
+import Foundation
+import library
+
+class CustomCounter : MyCounter {
+  override var value: Int32 { didSet { } }
+}