Merge pull request #10739 from jrose-apple/4.0-conditional-surrender

[4.0] Do stricter checking of -D command line arguments
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index c422d7d..44d0f18 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -462,6 +462,8 @@
   /// protocol, which line up with the conformance constraints in the
   /// protocol's requirement signature.
   ArrayRef<ProtocolConformanceRef> getSignatureConformances() const {
+    if (Resolver)
+      resolveLazyInfo();
     return SignatureConformances;
   }
 
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 93c92fa..7d6a172 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -6348,7 +6348,8 @@
     auto conformance = ctx.getConformance(dc->getDeclaredTypeInContext(),
                                           protocols[i], SourceLoc(), dc,
                                           ProtocolConformanceState::Incomplete);
-    Impl.scheduleFinishProtocolConformance(conformance);
+    conformance->setLazyLoader(&Impl, /*context*/0);
+    conformance->setState(ProtocolConformanceState::Complete);
     conformances.push_back(conformance);
   }
 
@@ -7286,6 +7287,9 @@
 
 void ClangImporter::Implementation::finishPendingActions() {
   while (true) {
+    // The odd shape of this loop comes from previously having more than one
+    // possible kind of pending action. It's left this way to make it easy to
+    // add another one back in an `else if` clause.
     if (!RegisteredExternalDecls.empty()) {
       if (hasFinishedTypeChecking()) {
         RegisteredExternalDecls.clear();
@@ -7297,22 +7301,22 @@
             if (!nominal->hasDelayedMembers())
               typeResolver->resolveExternalDeclImplicitMembers(nominal);
       }
-    } else if (!DelayedProtocolConformances.empty()) {
-      NormalProtocolConformance *conformance =
-          DelayedProtocolConformances.pop_back_val();
-      finishProtocolConformance(conformance);
     } else {
       break;
     }
   }
 }
 
-/// Finish the given protocol conformance (for an imported type)
-/// by filling in any missing witnesses.
-void ClangImporter::Implementation::finishProtocolConformance(
-    NormalProtocolConformance *conformance) {
+void ClangImporter::Implementation::finishNormalConformance(
+    NormalProtocolConformance *conformance,
+    uint64_t unused) {
+  (void)unused;
   const ProtocolDecl *proto = conformance->getProtocol();
 
+  PrettyStackTraceType trace(SwiftContext, "completing conformance for",
+                             conformance->getType());
+  PrettyStackTraceDecl traceTo("... to", proto);
+
   // Create witnesses for requirements not already met.
   for (auto req : proto->getMembers()) {
     auto valueReq = dyn_cast<ValueDecl>(req);
diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h
index 25c964d..174e075 100644
--- a/lib/ClangImporter/ImporterImpl.h
+++ b/lib/ClangImporter/ImporterImpl.h
@@ -496,9 +496,6 @@
   /// External Decls that we have imported but not passed to the ASTContext yet.
   SmallVector<Decl *, 4> RegisteredExternalDecls;
 
-  /// Protocol conformances that may be missing witnesses.
-  SmallVector<NormalProtocolConformance *, 4> DelayedProtocolConformances;
-
   unsigned NumCurrentImportingEntities = 0;
 
   /// Mapping from delayed conformance IDs to the set of delayed
@@ -517,7 +514,6 @@
   void startedImportingEntity();
   void finishedImportingEntity();
   void finishPendingActions();
-  void finishProtocolConformance(NormalProtocolConformance *conformance);
 
   struct ImportingEntityRAII {
     Implementation &Impl;
@@ -567,10 +563,6 @@
     RegisteredExternalDecls.push_back(D);
   }
 
-  void scheduleFinishProtocolConformance(NormalProtocolConformance *C) {
-    DelayedProtocolConformances.push_back(C);
-  }
-
   /// \brief Retrieve the Clang AST context.
   clang::ASTContext &getClangASTContext() const {
     return Instance->getASTContext();
@@ -1115,6 +1107,9 @@
     const Decl *D, uint64_t contextData,
     SmallVectorImpl<ProtocolConformance *> &Conformances) override;
 
+  void finishNormalConformance(NormalProtocolConformance *conformance,
+                               uint64_t unused) override;
+
   template <typename DeclTy, typename ...Targs>
   DeclTy *createDeclWithClangNode(ClangNode ClangN, Accessibility access,
                                   Targs &&... Args) {
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 0449834..42a4640 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1323,6 +1323,27 @@
                                          OI.SelectedSanitizer);
 }
 
+static void
+currentDependsOnPCHIfPresent(JobAction *PCH,
+                             std::unique_ptr<Action> &Current,
+                             ActionList &Actions) {
+  if (PCH) {
+    // FIXME: When we have a PCH job, it's officially owned by the Actions
+    // array; but it's also a secondary input to each of the current
+    // JobActions, which means that we need to flip the "owns inputs" bit
+    // on the JobActions so they don't try to free it. That in turn means
+    // we need to transfer ownership of all the JobActions' existing
+    // inputs to the Actions array, since the JobActions either own or
+    // don't own _all_ of their inputs. Ownership can't vary
+    // input-by-input.
+    auto *job = cast<JobAction>(Current.get());
+    auto inputs = job->getInputs();
+    Actions.append(inputs.begin(), inputs.end());
+    job->setOwnsInputs(false);
+    job->addInput(PCH);
+  }
+}
+
 void Driver::buildActions(const ToolChain &TC,
                           const DerivedArgList &Args,
                           const InputFileList &Inputs,
@@ -1387,6 +1408,7 @@
           Current.reset(new CompileJobAction(Current.release(),
                                              types::TY_LLVM_BC,
                                              previousBuildState));
+          currentDependsOnPCHIfPresent(PCH, Current, Actions);
           AllModuleInputs.push_back(Current.get());
           Current.reset(new BackendJobAction(Current.release(),
                                              OI.CompilerOutputType, 0));
@@ -1394,23 +1416,9 @@
           Current.reset(new CompileJobAction(Current.release(),
                                              OI.CompilerOutputType,
                                              previousBuildState));
+          currentDependsOnPCHIfPresent(PCH, Current, Actions);
           AllModuleInputs.push_back(Current.get());
         }
-        if (PCH) {
-          // FIXME: When we have a PCH job, it's officially owned by the Actions
-          // array; but it's also a secondary input to each of the current
-          // JobActions, which means that we need to flip the "owns inputs" bit
-          // on the JobActions so they don't try to free it. That in turn means
-          // we need to transfer ownership of all the JobActions' existing
-          // inputs to the Actions array, since the JobActions either own or
-          // don't own _all_ of their inputs. Ownership can't vary
-          // input-by-input.
-          auto *job = cast<JobAction>(Current.get());
-          auto inputs = job->getInputs();
-          Actions.append(inputs.begin(), inputs.end());
-          job->setOwnsInputs(false);
-          job->addInput(PCH);
-        }
         AllLinkerInputs.push_back(Current.release());
         break;
       }
diff --git a/test/ClangImporter/Inputs/SwiftPrivateAttr.txt b/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
index 6ea47fa..590c5e9 100644
--- a/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
+++ b/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
@@ -107,7 +107,7 @@
   static var __PrivA: NSOptions { get }
   static var B: NSOptions { get }
 }
-class __PrivCFType : _CFObject {
+class __PrivCFType {
 }
 @available(swift, obsoleted: 3, renamed: "__PrivCFType")
 typealias __PrivCFTypeRef = __PrivCFType
diff --git a/test/ClangImporter/Inputs/custom-modules/Protocols.h b/test/ClangImporter/Inputs/custom-modules/Protocols.h
index 43ad828..552adbd 100644
--- a/test/ClangImporter/Inputs/custom-modules/Protocols.h
+++ b/test/ClangImporter/Inputs/custom-modules/Protocols.h
@@ -9,3 +9,12 @@
 Class <FooProto, AnotherProto> _Nonnull processComboType(Class <FooProto, AnotherProto> _Nonnull);
 Class <AnotherProto, FooProto> _Nonnull processComboType2(Class <AnotherProto, FooProto> _Nonnull);
 
+
+@protocol SubProto <FooProto>
+@end
+
+@interface ProtocolTestingBase
+@end
+
+@interface SubProtoImpl: ProtocolTestingBase <SubProto>
+@end
diff --git a/test/ClangImporter/protocol-conformance-in-extension.swift b/test/ClangImporter/protocol-conformance-in-extension.swift
new file mode 100644
index 0000000..69a4c83
--- /dev/null
+++ b/test/ClangImporter/protocol-conformance-in-extension.swift
@@ -0,0 +1,21 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t/a~partial.swiftmodule -I %S/Inputs/custom-modules -module-name TEST -primary-file %s
+// RUN: %target-swift-frontend -emit-module -o %t/test.swiftmodule -I %S/Inputs/custom-modules -module-name TEST %t/a~partial.swiftmodule
+
+// REQUIRES: objc_interop
+
+import TestProtocols
+
+// The protocol in the extension has to refine something that the base class
+// conforms to to trigger the error in rdar://problem/32346184.
+protocol SomeSwiftProto: Equatable {}
+extension ProtocolTestingBase: Equatable {
+  public static func ==(left: ProtocolTestingBase, right: ProtocolTestingBase) -> Bool {
+    return left === right
+  }
+}
+
+// The extension going through the typealias also makes a difference.
+typealias SpecialObject = SubProtoImpl
+extension SpecialObject: SomeSwiftProto {
+}
diff --git a/test/Driver/bridging-pch.swift b/test/Driver/bridging-pch.swift
index bb3ac15..dbb4a28 100644
--- a/test/Driver/bridging-pch.swift
+++ b/test/Driver/bridging-pch.swift
@@ -32,6 +32,12 @@
 // PERSISTENT-YESPCHACT: 2: input, "{{.*}}bridging-pch.swift", swift
 // PERSISTENT-YESPCHACT: 3: compile, {2, 1}, none
 
+// RUN: %swiftc_driver -c -driver-print-actions -embed-bitcode -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-YESPCHACTBC
+// PERSISTENT-YESPCHACTBC: 0: input, "{{.*}}Inputs/bridging-header.h", objc-header
+// PERSISTENT-YESPCHACTBC: 1: generate-pch, {0}, none
+// PERSISTENT-YESPCHACTBC: 2: input, "{{.*}}bridging-pch.swift", swift
+// PERSISTENT-YESPCHACTBC: 3: compile, {2, 1}, llvm-bc
+
 // RUN: %swiftc_driver -typecheck -disable-bridging-pch -driver-print-actions -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch %s 2>&1 | %FileCheck %s -check-prefix=NOPCHACT
 
 // RUN: %swiftc_driver -typecheck -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch -disable-bridging-pch %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-DISABLED-YESPCHJOB