diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 532c43cc84d23..3438ed60f625a 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -5174,7 +5174,9 @@ bool Parser::delayParsingDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, if (Tok.is(tok::r_brace)) { RBLoc = consumeToken(); } else { - RBLoc = Tok.getLoc(); + // Non-delayed parsing would set the RB location to the LB if it is missing, + // match that behaviour here + RBLoc = LBLoc; error = true; } return error; diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index eb2e409f8f72c..b4fb042fe29b7 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -4505,6 +4505,9 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() { skipAttr = true; } else return deserialized.takeError(); + } else if (!deserialized.get() && MF.allowCompilerErrors()) { + // Serialized an invalid attribute, just skip it when allowing errors + skipAttr = true; } else { auto *TE = TypeExpr::createImplicit(deserialized.get(), ctx); auto custom = CustomAttr::create(ctx, SourceLoc(), TE, isImplicit); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 79c8bc99fbfaa..52817127e42f3 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1460,7 +1460,8 @@ void Serializer::writeASTBlockEntity( data.push_back(addDeclRef(req)); data.push_back(addDeclRef(witness.getDecl())); assert(witness.getDecl() || req->getAttrs().hasAttribute() - || req->getAttrs().isUnavailable(req->getASTContext())); + || req->getAttrs().isUnavailable(req->getASTContext()) + || allowCompilerErrors()); // If there is no witness, we're done. if (!witness.getDecl()) return; @@ -2012,6 +2013,8 @@ getStableSelfAccessKind(swift::SelfAccessKind MM) { # define DECL(KIND, PARENT)\ LLVM_ATTRIBUTE_UNUSED \ static void verifyAttrSerializable(const KIND ## Decl *D) {\ + if (D->Decl::getASTContext().LangOpts.AllowModuleWithCompilerErrors)\ + return;\ for (auto Attr : D->getAttrs()) {\ assert(Attr->canAppearOnDecl(D) && "attribute cannot appear on a " #KIND);\ }\ @@ -3933,6 +3936,9 @@ class Serializer::DeclSerializer : public DeclVisitor { using namespace decls_block; verifyAttrSerializable(dtor); + if (S.allowCompilerErrors() && dtor->isInvalid()) + return; + auto contextID = S.addDeclContextRef(dtor->getDeclContext()); unsigned abbrCode = S.DeclTypeAbbrCodes[DestructorLayout::Code]; @@ -4163,6 +4169,13 @@ class Serializer::TypeSerializer : public TypeVisitor { } void visitUnresolvedType(const UnresolvedType *) { + // If for some reason we have an unresolved type while compiling with + // errors, just serialize an ErrorType and continue. + if (S.getASTContext().LangOpts.AllowModuleWithCompilerErrors) { + visitErrorType( + cast(ErrorType::get(S.getASTContext()).getPointer())); + return; + } llvm_unreachable("should not serialize an UnresolvedType"); } diff --git a/validation-test/Parse/delayed-members-open-if.swift b/validation-test/Parse/delayed-members-open-if.swift new file mode 100644 index 0000000000000..96f72bd0c7aed --- /dev/null +++ b/validation-test/Parse/delayed-members-open-if.swift @@ -0,0 +1,4 @@ +// RUN: not %target-swift-frontend -typecheck -experimental-skip-all-function-bodies %s + +#if os( +struct Anything { diff --git a/validation-test/Parse/delayed-members-open-prop-scope.swift b/validation-test/Parse/delayed-members-open-prop-scope.swift new file mode 100644 index 0000000000000..8af5f82897b52 --- /dev/null +++ b/validation-test/Parse/delayed-members-open-prop-scope.swift @@ -0,0 +1,6 @@ +// RUN: not %target-swift-frontend -typecheck -experimental-skip-all-function-bodies %s + +struct A { + let prop: Int = { + +struct B { diff --git a/validation-test/Serialization/AllowErrors/invalid-attr-refs.swift b/validation-test/Serialization/AllowErrors/invalid-attr-refs.swift new file mode 100644 index 0000000000000..dfcf6cfeeed23 --- /dev/null +++ b/validation-test/Serialization/AllowErrors/invalid-attr-refs.swift @@ -0,0 +1,14 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -module-name errors -emit-module -o %t/errors.swiftmodule -experimental-allow-module-with-compiler-errors %s + +// Property wrappers are invalid on top level code, check allowing errors +// does not crash + +@propertyWrapper +public struct Wrapper { + public var wrappedValue: T + public init() {} +} +@Wrapper +public var topLevelVar: Int = 10 diff --git a/validation-test/Serialization/AllowErrors/invalid-attr.swift b/validation-test/Serialization/AllowErrors/invalid-attr.swift new file mode 100644 index 0000000000000..93a0b2ed9e58b --- /dev/null +++ b/validation-test/Serialization/AllowErrors/invalid-attr.swift @@ -0,0 +1,9 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -module-name errors -emit-module -o %t/errors.swiftmodule -experimental-allow-module-with-compiler-errors %s + +// @discardableResult is not allowed on a struct, make sure we don't crash +// when allowing errors + +@discardableResult +struct SomeStruct {} diff --git a/validation-test/Serialization/AllowErrors/invalid-deinit.swift b/validation-test/Serialization/AllowErrors/invalid-deinit.swift new file mode 100644 index 0000000000000..17dc6e06f4be3 --- /dev/null +++ b/validation-test/Serialization/AllowErrors/invalid-deinit.swift @@ -0,0 +1,8 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -module-name errors -emit-module -o %t/errors.swiftmodule -experimental-allow-module-with-compiler-errors %s + +// deinit is only valid on a class, make sure we don't crash when allowing +// errors + +deinit {} diff --git a/validation-test/Serialization/AllowErrors/invalid-witness.swift b/validation-test/Serialization/AllowErrors/invalid-witness.swift new file mode 100644 index 0000000000000..909edec222bb8 --- /dev/null +++ b/validation-test/Serialization/AllowErrors/invalid-witness.swift @@ -0,0 +1,14 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -module-name errors -emit-module -o %t/errors.swiftmodule -experimental-allow-module-with-compiler-errors %s + +public protocol SomeProto { + init(from: SomeProto) +} + +struct A {} +struct B: SomeProto { + let a: A +} + +let thing = B(a: A()) diff --git a/validation-test/Serialization/AllowErrors/unresolved-type.swift b/validation-test/Serialization/AllowErrors/unresolved-type.swift new file mode 100644 index 0000000000000..137df41cf53a3 --- /dev/null +++ b/validation-test/Serialization/AllowErrors/unresolved-type.swift @@ -0,0 +1,12 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -module-name errors -emit-module -o %t/errors.swiftmodule -experimental-allow-module-with-compiler-errors %s + +protocol SomeProto {} + +extension SomeProto { + func someFunc(arg: + +enum SomeEnum { + case a +}