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