Skip to content

Commit 963c64e

Browse files
committed
Add @_private(from: "SourceFile.swift") imports
A module compiled with `-enable-private-imports` allows other modules to import private declarations if the importing source file uses an ``@_private(from: "SourceFile.swift") import statement. rdar://29318654
1 parent a952514 commit 963c64e

33 files changed

+605
-47
lines changed

include/swift/AST/Attr.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,10 @@ DECL_ATTR(_dynamicReplacement, DynamicReplacement,
384384
SIMPLE_DECL_ATTR(_borrowed, Borrowed,
385385
OnVar | OnSubscript | UserInaccessible |
386386
NotSerialized, 81)
387+
DECL_ATTR(_private, PrivateImport,
388+
OnImport |
389+
UserInaccessible |
390+
NotSerialized, 82)
387391

388392
#undef TYPE_ATTR
389393
#undef DECL_ATTR_ALIAS

include/swift/AST/Attr.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,26 @@ class ObjCAttr final : public DeclAttribute,
901901
}
902902
};
903903

904+
class PrivateImportAttr final
905+
: public DeclAttribute {
906+
StringRef SourceFile;
907+
908+
PrivateImportAttr(SourceLoc atLoc, SourceRange baseRange,
909+
StringRef sourceFile, SourceRange parentRange);
910+
911+
public:
912+
static PrivateImportAttr *create(ASTContext &Ctxt, SourceLoc AtLoc,
913+
SourceLoc PrivateLoc, SourceLoc LParenLoc,
914+
StringRef sourceFile, SourceLoc RParenLoc);
915+
916+
StringRef getSourceFile() const {
917+
return SourceFile;
918+
}
919+
static bool classof(const DeclAttribute *DA) {
920+
return DA->getKind() == DAK_PrivateImport;
921+
}
922+
};
923+
904924
/// The @_dynamicReplacement(for:) attribute.
905925
class DynamicReplacementAttr final
906926
: public DeclAttribute,

include/swift/AST/Decl.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ class alignas(1 << DeclAlignInBits) Decl {
573573
HasAnyUnavailableValues : 1
574574
);
575575

576-
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1,
576+
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1,
577577
/// If the module was or is being compiled with `-enable-testing`.
578578
TestingEnabled : 1,
579579

@@ -586,7 +586,10 @@ class alignas(1 << DeclAlignInBits) Decl {
586586
RawResilienceStrategy : 1,
587587

588588
/// Whether all imports have been resolved. Used to detect circular imports.
589-
HasResolvedImports : 1
589+
HasResolvedImports : 1,
590+
591+
// If the module was or is being compiled with `-enable-private-imports`.
592+
PrivateImportsEnabled : 1
590593
);
591594

592595
SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,

include/swift/AST/DiagnosticsParse.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,15 @@ ERROR(attr_dynamic_replacement_expected_for,none,
14171417
ERROR(attr_dynamic_replacement_expected_colon,none,
14181418
"expected ':' after @_dynamicReplacement(for", ())
14191419

1420+
ERROR(attr_private_import_expected_rparen,none,
1421+
"expected ')' after function name for @_private", ())
1422+
ERROR(attr_private_import_expected_sourcefile, none,
1423+
"expected 'sourceFile' in '_private' attribute", ())
1424+
ERROR(attr_private_import_expected_sourcefile_name,none,
1425+
"expected a source file name in @_private(sourceFile:)", ())
1426+
ERROR(attr_private_import_expected_colon,none,
1427+
"expected ':' after @_private(sourceFile", ())
1428+
14201429
// opened
14211430
ERROR(opened_attribute_expected_lparen,none,
14221431
"expected '(' after 'opened' attribute", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,10 @@ ERROR(ambiguous_decl_in_module,none,
759759
ERROR(module_not_testable,none,
760760
"module %0 was not compiled for testing", (Identifier))
761761

762+
ERROR(module_not_compiled_for_private_import,none,
763+
"module %0 was not compiled for private import", (Identifier))
764+
765+
762766
// Operator decls
763767
ERROR(ambiguous_operator_decls,none,
764768
"ambiguous operator declarations found for operator", ())

include/swift/AST/Module.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,15 @@ class ModuleDecl : public DeclContext, public TypeDecl {
283283
Bits.ModuleDecl.TestingEnabled = enabled;
284284
}
285285

286+
/// Returns true if this module was or is begin compile with
287+
/// `-enable-private-imports`.
288+
bool arePrivateImportsEnabled() const {
289+
return Bits.ModuleDecl.PrivateImportsEnabled;
290+
}
291+
void setPrivateImportsEnabled(bool enabled = true) {
292+
Bits.ModuleDecl.PrivateImportsEnabled = true;
293+
}
294+
286295
/// Returns true if there was an error trying to load this module.
287296
bool failedToLoad() const {
288297
return Bits.ModuleDecl.FailedToLoad;
@@ -844,7 +853,11 @@ class SourceFile final : public FileUnit {
844853

845854
/// This source file has access to testable declarations in the imported
846855
/// module.
847-
Testable = 0x2
856+
Testable = 0x2,
857+
858+
/// This source file has access to private declarations in the imported
859+
/// moduled.
860+
PrivateImport = 0x4,
848861
};
849862

850863
/// \see ImportFlags
@@ -857,7 +870,9 @@ class SourceFile final : public FileUnit {
857870
/// This is the list of modules that are imported by this module.
858871
///
859872
/// This is filled in by the Name Binding phase.
860-
ArrayRef<std::pair<ModuleDecl::ImportedModule, ImportOptions>> Imports;
873+
ArrayRef<std::pair<ModuleDecl::ImportedModule,
874+
std::pair<ImportOptions, StringRef>>>
875+
Imports;
861876

862877
/// A unique identifier representing this file; used to mark private decls
863878
/// within the file to keep them from conflicting with other files in the
@@ -961,11 +976,14 @@ class SourceFile final : public FileUnit {
961976
ImplicitModuleImportKind ModImpKind, bool KeepParsedTokens = false,
962977
bool KeepSyntaxTree = false);
963978

964-
void
965-
addImports(ArrayRef<std::pair<ModuleDecl::ImportedModule, ImportOptions>> IM);
979+
void addImports(ArrayRef<std::pair<ModuleDecl::ImportedModule,
980+
std::pair<ImportOptions, StringRef>>>
981+
IM);
966982

967983
bool hasTestableImport(const ModuleDecl *module) const;
968984

985+
bool hasPrivateImport(AccessLevel accessLevel, const ValueDecl *ofDecl) const;
986+
969987
void clearLookupCache();
970988

971989
void cacheVisibleDecls(SmallVectorImpl<ValueDecl *> &&globals) const;
@@ -1224,12 +1242,29 @@ class LoadedFile : public FileUnit {
12241242
assert(classof(this) && "invalid kind");
12251243
}
12261244

1245+
/// A map from private/fileprivate decls to the file they were defined in.
1246+
llvm::DenseMap<const ValueDecl *, Identifier> FilenameForPrivateDecls;
1247+
12271248
public:
1249+
12281250
/// Returns an arbitrary string representing the storage backing this file.
12291251
///
12301252
/// This is usually a filesystem path.
12311253
virtual StringRef getFilename() const;
12321254

1255+
void addFilenameForPrivateDecl(const ValueDecl *decl, Identifier id) {
1256+
assert(!FilenameForPrivateDecls.count(decl) ||
1257+
FilenameForPrivateDecls[decl] == id);
1258+
FilenameForPrivateDecls[decl] = id;
1259+
}
1260+
1261+
StringRef getFilenameForPrivateDecl(const ValueDecl *decl) {
1262+
auto it = FilenameForPrivateDecls.find(decl);
1263+
if (it == FilenameForPrivateDecls.end())
1264+
return StringRef();
1265+
else return it->second.str();
1266+
}
1267+
12331268
/// Look up an operator declaration.
12341269
///
12351270
/// \param name The operator name ("+", ">>", etc.)

include/swift/Frontend/FrontendOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ class FrontendOptions {
192192
/// \see ModuleDecl::isTestingEnabled
193193
bool EnableTesting = false;
194194

195+
/// Indicates whether we are compiling for testing.
196+
///
197+
/// \see ModuleDecl::arePrivateImportsEnabled
198+
bool EnablePrivateImports = false;
199+
195200
/// Enables the "fully resilient" resilience strategy.
196201
///
197202
/// \see ResilienceStrategy::Resilient

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,10 @@ def enable_testing : Flag<["-"], "enable-testing">,
791791
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
792792
HelpText<"Allows this module's internal API to be accessed for testing">;
793793

794+
def enable_private_imports : Flag<["-"], "enable-private-imports">,
795+
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
796+
HelpText<"Allows this module's internal and private API to be accessed">;
797+
794798
def sanitize_EQ : CommaJoined<["-"], "sanitize=">,
795799
Flags<[FrontendOption, NoInteractiveOption]>, MetaVarName<"<check>">,
796800
HelpText<"Turn on runtime checks for erroneous behavior.">;

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ OTHER(SUBSTITUTION_MAP, 236)
168168

169169
OTHER(LOCAL_DISCRIMINATOR, 237)
170170
OTHER(PRIVATE_DISCRIMINATOR, 238)
171+
OTHER(FILENAME_FOR_PRIVATE, 239)
171172

172173
OTHER(ABSTRACT_PROTOCOL_CONFORMANCE, 240)
173174
OTHER(NORMAL_PROTOCOL_CONFORMANCE, 241)

include/swift/Serialization/ModuleFormat.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 462; // Last change: Add dynamicReplacement(for:)
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 463; // Last change: enable-private-imports
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -592,7 +592,8 @@ namespace options_block {
592592
XCC,
593593
IS_SIB,
594594
IS_TESTABLE,
595-
RESILIENCE_STRATEGY
595+
RESILIENCE_STRATEGY,
596+
ARE_PRIVATE_IMPORTS_ENABLED
596597
};
597598

598599
using SDKPathLayout = BCRecordLayout<
@@ -614,6 +615,10 @@ namespace options_block {
614615
IS_TESTABLE
615616
>;
616617

618+
using ArePrivateImportsEnabledLayout = BCRecordLayout<
619+
ARE_PRIVATE_IMPORTS_ENABLED
620+
>;
621+
617622
using ResilienceStrategyLayout = BCRecordLayout<
618623
RESILIENCE_STRATEGY,
619624
BCFixed<2>
@@ -1309,6 +1314,11 @@ namespace decls_block {
13091314
BCVBR<2> // context-scoped discriminator counter
13101315
>;
13111316

1317+
using FilenameForPrivateLayout = BCRecordLayout<
1318+
FILENAME_FOR_PRIVATE,
1319+
IdentifierIDField // the file name, as an identifier
1320+
>;
1321+
13121322
/// A placeholder for lack of concrete conformance information.
13131323
using AbstractProtocolConformanceLayout = BCRecordLayout<
13141324
ABSTRACT_PROTOCOL_CONFORMANCE,
@@ -1513,6 +1523,7 @@ namespace decls_block {
15131523
= BCRecordLayout<RestatedObjCConformance_DECL_ATTR>;
15141524
using ClangImporterSynthesizedTypeDeclAttrLayout
15151525
= BCRecordLayout<ClangImporterSynthesizedType_DECL_ATTR>;
1526+
using PrivateImportDeclAttrLayout = BCRecordLayout<PrivateImport_DECL_ATTR>;
15161527

15171528
using InlineDeclAttrLayout = BCRecordLayout<
15181529
Inline_DECL_ATTR,

include/swift/Serialization/Validation.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class ExtendedValidationInfo {
9393
SmallVector<StringRef, 4> ExtraClangImporterOpts;
9494
StringRef SDKPath;
9595
struct {
96+
unsigned ArePrivateImportsEnabled : 1;
9697
unsigned IsSIB : 1;
9798
unsigned IsTestable : 1;
9899
unsigned ResilienceStrategy : 2;
@@ -117,6 +118,10 @@ class ExtendedValidationInfo {
117118
void setIsSIB(bool val) {
118119
Bits.IsSIB = val;
119120
}
121+
bool arePrivateImportsEnabled() { return Bits.ArePrivateImportsEnabled; }
122+
void setPrivateImportsEnabled(bool enabled) {
123+
Bits.ArePrivateImportsEnabled = enabled;
124+
}
120125
bool isTestable() const { return Bits.IsTestable; }
121126
void setIsTestable(bool val) {
122127
Bits.IsTestable = val;

lib/AST/Attr.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,12 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
468468
}
469469
break;
470470
}
471+
472+
case DAK_PrivateImport: {
473+
Printer.printAttrName("@_private(sourceFile: \"");
474+
Printer << cast<PrivateImportAttr>(this)->getSourceFile() << "\")";
475+
break;
476+
}
471477

472478
case DAK_SwiftNativeObjCRuntimeBase: {
473479
auto *attr = cast<SwiftNativeObjCRuntimeBaseAttr>(this);
@@ -621,6 +627,8 @@ StringRef DeclAttribute::getAttrName() const {
621627
return "objc";
622628
case DAK_DynamicReplacement:
623629
return "_dynamicReplacement";
630+
case DAK_PrivateImport:
631+
return "_private";
624632
case DAK_RestatedObjCConformance:
625633
return "_restatedObjCConformance";
626634
case DAK_Inline: {
@@ -785,6 +793,22 @@ ObjCAttr *ObjCAttr::clone(ASTContext &context) const {
785793
return attr;
786794
}
787795

796+
PrivateImportAttr::PrivateImportAttr(SourceLoc atLoc, SourceRange baseRange,
797+
StringRef sourceFile,
798+
SourceRange parenRange)
799+
: DeclAttribute(DAK_PrivateImport, atLoc, baseRange, /*Implicit=*/false),
800+
SourceFile(sourceFile) {}
801+
802+
PrivateImportAttr *PrivateImportAttr::create(ASTContext &Ctxt, SourceLoc AtLoc,
803+
SourceLoc PrivateLoc,
804+
SourceLoc LParenLoc,
805+
StringRef sourceFile,
806+
SourceLoc RParenLoc) {
807+
return new (Ctxt)
808+
PrivateImportAttr(AtLoc, SourceRange(PrivateLoc, LParenLoc), sourceFile,
809+
SourceRange(LParenLoc, RParenLoc));
810+
}
811+
788812
DynamicReplacementAttr::DynamicReplacementAttr(SourceLoc atLoc,
789813
SourceRange baseRange,
790814
DeclName name,

0 commit comments

Comments
 (0)