Merge pull request #17313 from slavapestov/inlinable-warning-tweak-4.2
Small @inlinable tweaks for [4.2]
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index 6511fb4..cbd6400 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -348,6 +348,11 @@
SIMPLE_DECL_ATTR(_frozen, Frozen, OnEnum | UserInaccessible, 76)
+SIMPLE_DECL_ATTR(_forbidSerializingReference, ForbidSerializingReference,
+ OnAnyDecl |
+ LongAttribute | RejectByParser | UserInaccessible | NotSerialized,
+ 77)
+
#undef TYPE_ATTR
#undef DECL_ATTR_ALIAS
#undef CONTEXTUAL_DECL_ATTR_ALIAS
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index 300e594..77bb843 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -625,6 +625,13 @@
return static_cast<Status>(Bits.Status);
}
+ /// Transfers ownership of a buffer that might contain source code where
+ /// other parts of the compiler could have emitted diagnostics, to keep them
+ /// alive even if the ModuleFile is destroyed.
+ ///
+ /// Should only be called when getStatus() indicates a failure.
+ std::unique_ptr<llvm::MemoryBuffer> takeBufferForDiagnostics();
+
/// Returns the list of modules this module depends on.
ArrayRef<Dependency> getDependencies() const {
return Dependencies;
diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h
index 13db711..00fa1d5 100644
--- a/include/swift/Serialization/SerializedModuleLoader.h
+++ b/include/swift/Serialization/SerializedModuleLoader.h
@@ -29,6 +29,8 @@
using LoadedModulePair = std::pair<std::unique_ptr<ModuleFile>, unsigned>;
std::vector<LoadedModulePair> LoadedModuleFiles;
+ SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 2> OrphanedMemoryBuffers;
+
explicit SerializedModuleLoader(ASTContext &ctx, DependencyTracker *tracker);
public:
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index ef48703..f681109 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -4617,6 +4617,8 @@
"This Objective-C class has only been forward-declared; "
"import its owning module to use it");
result->getAttrs().add(attr);
+ result->getAttrs().add(
+ new (Impl.SwiftContext) ForbidSerializingReferenceAttr(true));
return result;
}
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index bb93081..7aa453b 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -80,6 +80,7 @@
IGNORED_ATTR(Effects)
IGNORED_ATTR(Exported)
IGNORED_ATTR(FixedLayout)
+ IGNORED_ATTR(ForbidSerializingReference)
IGNORED_ATTR(Frozen)
IGNORED_ATTR(Implements)
IGNORED_ATTR(ImplicitlyUnwrappedOptional)
@@ -804,6 +805,7 @@
IGNORED_ATTR(Dynamic)
IGNORED_ATTR(Effects)
IGNORED_ATTR(Exported)
+ IGNORED_ATTR(ForbidSerializingReference)
IGNORED_ATTR(GKInspectable)
IGNORED_ATTR(IBDesignable)
IGNORED_ATTR(IBInspectable)
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 889a997..8d15c25 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -5717,6 +5717,7 @@
UNINTERESTING_ATTR(DynamicMemberLookup)
UNINTERESTING_ATTR(SILGenName)
UNINTERESTING_ATTR(Exported)
+ UNINTERESTING_ATTR(ForbidSerializingReference)
UNINTERESTING_ATTR(GKInspectable)
UNINTERESTING_ATTR(IBAction)
UNINTERESTING_ATTR(IBDesignable)
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 5b00159..1dd34c9 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -1198,6 +1198,10 @@
return true;
if (value->isStatic() != isStatic)
return true;
+
+ if (value->getAttrs().hasAttribute<ForbidSerializingReferenceAttr>())
+ return true;
+
// FIXME: Should be able to move a value from an extension in a derived
// module to the original definition in a base module.
if (expectedModule && !value->hasClangNode() &&
diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp
index eca8558..9f143d6 100644
--- a/lib/Serialization/ModuleFile.cpp
+++ b/lib/Serialization/ModuleFile.cpp
@@ -1468,6 +1468,17 @@
return getStatus();
}
+std::unique_ptr<llvm::MemoryBuffer> ModuleFile::takeBufferForDiagnostics() {
+ assert(getStatus() != Status::Valid);
+
+ // Today, the only buffer that might have diagnostics in them is the input
+ // buffer, and even then only if it has imported module contents.
+ if (!importedHeaderInfo.contents.empty())
+ return std::move(ModuleInputBuffer);
+
+ return nullptr;
+}
+
ModuleFile::~ModuleFile() { }
void ModuleFile::lookupValue(DeclName name,
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index ae1ece9..e6cb2e4 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -609,6 +609,10 @@
isa<PrecedenceGroupDecl>(D)) &&
"cannot cross-reference this decl");
+ assert((!isDeclXRef(D) ||
+ !D->getAttrs().hasAttribute<ForbidSerializingReferenceAttr>()) &&
+ "cannot cross-reference this decl");
+
assert((allowTypeAliasXRef || !isa<TypeAliasDecl>(D) ||
D->getModuleContext() == M) &&
"cannot cross-reference typealiases directly (use the NameAliasType)");
@@ -1070,28 +1074,38 @@
publicImportSet.insert(publicImports.begin(), publicImports.end());
removeDuplicateImports(allImports);
+
auto clangImporter =
static_cast<ClangImporter *>(M->getASTContext().getClangModuleLoader());
- ModuleDecl *importedHeaderModule = clangImporter->getImportedHeaderModule();
+ ModuleDecl *bridgingHeaderModule = clangImporter->getImportedHeaderModule();
+ ModuleDecl::ImportedModule bridgingHeaderImport{{}, bridgingHeaderModule};
+
+ // Make sure the bridging header module is always at the top of the import
+ // list, mimicking how it is processed before any module imports when
+ // compiling source files.
+ if (llvm::is_contained(allImports, bridgingHeaderImport)) {
+ off_t importedHeaderSize = 0;
+ time_t importedHeaderModTime = 0;
+ std::string contents;
+ if (!options.ImportedHeader.empty()) {
+ contents = clangImporter->getBridgingHeaderContents(
+ options.ImportedHeader, importedHeaderSize, importedHeaderModTime);
+ }
+ assert(publicImportSet.count(bridgingHeaderImport));
+ ImportedHeader.emit(ScratchRecord,
+ publicImportSet.count(bridgingHeaderImport),
+ importedHeaderSize, importedHeaderModTime,
+ options.ImportedHeader);
+ if (!contents.empty()) {
+ contents.push_back('\0');
+ ImportedHeaderContents.emit(ScratchRecord, contents);
+ }
+ }
+
ModuleDecl *theBuiltinModule = M->getASTContext().TheBuiltinModule;
for (auto import : allImports) {
- if (import.second == theBuiltinModule)
- continue;
-
- if (import.second == importedHeaderModule) {
- off_t importedHeaderSize = 0;
- time_t importedHeaderModTime = 0;
- std::string contents;
- if (!options.ImportedHeader.empty())
- contents = clangImporter->getBridgingHeaderContents(
- options.ImportedHeader, importedHeaderSize, importedHeaderModTime);
- ImportedHeader.emit(ScratchRecord, publicImportSet.count(import),
- importedHeaderSize, importedHeaderModTime,
- options.ImportedHeader);
- if (!contents.empty()) {
- contents.push_back('\0');
- ImportedHeaderContents.emit(ScratchRecord, contents);
- }
+ if (import.second == theBuiltinModule ||
+ import.second == bridgingHeaderModule) {
continue;
}
diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp
index d7f8729..02edb2e 100644
--- a/lib/Serialization/SerializedModuleLoader.cpp
+++ b/lib/Serialization/SerializedModuleLoader.cpp
@@ -223,7 +223,14 @@
M.removeFile(*fileUnit);
}
- // This is the failure path. If we have a location, diagnose the issue.
+ // From here on is the failure path.
+
+ // Even though the module failed to load, it's possible its contents include
+ // a source buffer that need to survive because it's already been used for
+ // diagnostics.
+ if (auto orphanedBuffer = loadedModuleFile->takeBufferForDiagnostics())
+ OrphanedMemoryBuffers.push_back(std::move(orphanedBuffer));
+
if (!diagLoc)
return nullptr;
diff --git a/test/ClangImporter/Inputs/custom-modules/ForwardDeclarationsHelper.h b/test/ClangImporter/Inputs/custom-modules/ForwardDeclarationsHelper.h
new file mode 100644
index 0000000..c1f02bf
--- /dev/null
+++ b/test/ClangImporter/Inputs/custom-modules/ForwardDeclarationsHelper.h
@@ -0,0 +1,4 @@
+@class Confusing;
+
+@protocol Confusing
+@end
diff --git a/test/ClangImporter/Inputs/custom-modules/module.map b/test/ClangImporter/Inputs/custom-modules/module.map
index f7c389a..d9c458e 100644
--- a/test/ClangImporter/Inputs/custom-modules/module.map
+++ b/test/ClangImporter/Inputs/custom-modules/module.map
@@ -212,3 +212,7 @@
module Warnings7 { header "Warnings7.h" }
module Warnings8 { header "Warnings8.h" }
module Warnings9 { header "Warnings9.h" }
+
+module ForwardDeclarationsHelper {
+ header "ForwardDeclarationsHelper.h"
+}
diff --git a/test/ClangImporter/objc_forward_declarations.swift b/test/ClangImporter/objc_forward_declarations.swift
new file mode 100644
index 0000000..045cfb4
--- /dev/null
+++ b/test/ClangImporter/objc_forward_declarations.swift
@@ -0,0 +1,9 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t -I %S/Inputs/custom-modules -enable-objc-interop %s
+// RUN: %target-swift-ide-test -print-module -module-to-print objc_forward_declarations -I %t -I %S/Inputs/custom-modules -enable-objc-interop -enable-objc-forward-declarations -source-filename x | %FileCheck %s
+
+// CHECK: class Innocuous : Confusing {
+
+import ForwardDeclarationsHelper
+
+public class Innocuous: Confusing {}
diff --git a/validation-test/Serialization/Inputs/bridging-header-first/AmbivalentProtocol.h b/validation-test/Serialization/Inputs/bridging-header-first/AmbivalentProtocol.h
new file mode 100644
index 0000000..230d8c9
--- /dev/null
+++ b/validation-test/Serialization/Inputs/bridging-header-first/AmbivalentProtocol.h
@@ -0,0 +1,2 @@
+@protocol AmbivalentProtocol
+@end
diff --git a/validation-test/Serialization/Inputs/bridging-header-first/Module/modular.h b/validation-test/Serialization/Inputs/bridging-header-first/Module/modular.h
new file mode 100644
index 0000000..3c52813
--- /dev/null
+++ b/validation-test/Serialization/Inputs/bridging-header-first/Module/modular.h
@@ -0,0 +1 @@
+#import <AmbivalentProtocol.h>
diff --git a/validation-test/Serialization/Inputs/bridging-header-first/Module/module.modulemap b/validation-test/Serialization/Inputs/bridging-header-first/Module/module.modulemap
new file mode 100644
index 0000000..d380519
--- /dev/null
+++ b/validation-test/Serialization/Inputs/bridging-header-first/Module/module.modulemap
@@ -0,0 +1,4 @@
+module Module {
+ umbrella header "modular.h"
+ module * { export * }
+}
diff --git a/validation-test/Serialization/Inputs/bridging-header-first/bridging.h b/validation-test/Serialization/Inputs/bridging-header-first/bridging.h
new file mode 100644
index 0000000..4c894e1
--- /dev/null
+++ b/validation-test/Serialization/Inputs/bridging-header-first/bridging.h
@@ -0,0 +1 @@
+#import "AmbivalentProtocol.h"
diff --git a/validation-test/Serialization/Inputs/bridging-header-first/mangled.txt b/validation-test/Serialization/Inputs/bridging-header-first/mangled.txt
new file mode 100644
index 0000000..4fdc28b
--- /dev/null
+++ b/validation-test/Serialization/Inputs/bridging-header-first/mangled.txt
@@ -0,0 +1 @@
+$S4main1CCACycfc
diff --git a/validation-test/Serialization/bridging-header-first.swift b/validation-test/Serialization/bridging-header-first.swift
new file mode 100644
index 0000000..8465323
--- /dev/null
+++ b/validation-test/Serialization/bridging-header-first.swift
@@ -0,0 +1,32 @@
+// RUN: %empty-directory(%t)
+
+// RUN: %target-build-swift -emit-module -emit-executable %s -g -I %S/Inputs/bridging-header-first/ -import-objc-header %S/Inputs/bridging-header-first/bridging.h -o %t/main
+// RUN: llvm-bcanalyzer -dump %t/main.swiftmodule | %FileCheck -check-prefix CHECK-DUMP %s
+// RUN: %lldb-moduleimport-test %t/main -type-from-mangled %S/Inputs/bridging-header-first/mangled.txt 2>&1 | %FileCheck -check-prefix CHECK-RESOLVED-TYPE %s
+
+// RUN: %target-build-swift -emit-module -emit-executable %s -g -I %S/Inputs/bridging-header-first/ -import-objc-header %S/Inputs/bridging-header-first/bridging.h -o %t/main -whole-module-optimization
+// RUN: llvm-bcanalyzer -dump %t/main.swiftmodule | %FileCheck -check-prefix CHECK-DUMP %s
+// RUN: %lldb-moduleimport-test %t/main -type-from-mangled %S/Inputs/bridging-header-first/mangled.txt 2>&1 | %FileCheck -check-prefix CHECK-RESOLVED-TYPE %s
+
+// REQUIRES: objc_interop
+
+// CHECK-DUMP-LABEL: CONTROL_BLOCK
+// CHECK-DUMP: MODULE_NAME
+// CHECK-DUMP-SAME: 'main'
+
+// CHECK-DUMP-LABEL: INPUT_BLOCK
+// CHECK-DUMP: IMPORTED_HEADER
+// CHECK-DUMP-SAME: '{{.+}}/bridging.h'
+// CHECK-DUMP: IMPORTED_MODULE
+// CHECK-DUMP-SAME: 'Module'
+// CHECK-DUMP: IMPORTED_MODULE
+// CHECK-DUMP-SAME: 'Swift'
+
+
+// CHECK-RESOLVED-TYPE: @convention(method) (C.Type) -> () -> C
+
+import Module
+class C {}
+extension C: AmbivalentProtocol {
+ func f() {}
+}