Skip to content

Commit 36a5254

Browse files
authored
---
yaml --- r: 343791 b: refs/heads/master-rebranch c: 1f0e2da h: refs/heads/master i: 343789: 19242d5 343787: 77a0366 343783: 1dfc424 343775: cea0c1f
1 parent 49e228f commit 36a5254

File tree

17 files changed

+273
-95
lines changed

17 files changed

+273
-95
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1455,7 +1455,7 @@ refs/tags/swift-DEVELOPMENT-SNAPSHOT-2019-08-02-a: ddd2b2976aa9bfde5f20fe37f6bd2
14551455
refs/tags/swift-DEVELOPMENT-SNAPSHOT-2019-08-03-a: 171cc166f2abeb5ca2a4003700a8a78a108bd300
14561456
refs/heads/benlangmuir-patch-1: baaebaf39d52f3bf36710d4fe40cf212e996b212
14571457
refs/heads/i-do-redeclare: 8c4e6d5de5c1e3f0a2cedccf319df713ea22c48e
1458-
refs/heads/master-rebranch: 6329fc0a92aa0881e578f1f85dd9952a4b7d84dc
1458+
refs/heads/master-rebranch: 1f0e2da9a09648b6065e099a75ae4b7d6a010707
14591459
refs/heads/rdar-53901732: 9bd06af3284e18a109cdbf9aa59d833b24eeca7b
14601460
refs/heads/revert-26776-subst-always-returns-a-type: 1b8e18fdd391903a348970a4c848995d4cdd789c
14611461
refs/heads/tensorflow-merge: 8b854f62f80d4476cb383d43c4aac2001dde3cec

branches/master-rebranch/docs/CToSwiftNameTranslation.md

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
This document gives a high-level description of how C and Objective-C declarations are translated to Swift, with particular focus on how names are adjusted. It is not attempting to be a *complete* description of everything the compiler does except with regards to how *names* are transformed; even there, some special cases that only apply to Apple's SDKs have been omitted.
44

5+
## Word boundaries
6+
7+
Several forms of name translation are defined in terms of word boundaries. The word-splitting algorithm used by the Swift compiler is as follows: there is a boundary after
8+
9+
1. An underscore ("\_").
10+
2. A series of two or more uppercase ASCII characters and the suffix "s", "es", or "ies" (e.g. "URLs", "VAXes")...unless the last uppercase letter is "I" and the suffix is "s", in which case it's just as likely to be an acronym followed by "Is" (i.e. "URLIs" is treated as "URL Is").
11+
2. A series of two or more uppercase ASCII characters followed by an uppercase ASCII character and then a lowercase ASCII character ("XMLReader" becomes "XML Reader").
12+
3. A series of two or more uppercase ASCII characters followed by a non-ASCII-alphabetic character. ("UTF8" becomes "UTF 8")
13+
4. A series of two or more uppercase ASCII characters at the end of the string.
14+
5. An uppercase ASCII character and any number of non-ASCII-uppercase, non-underscore characters ("ContrivedExample" becomes "Contrived Example").
15+
6. Any number of non-ASCII-uppercase, non-underscore characters ("lowercase\_example" becomes "lowercase \_ example").
16+
17+
518
## Enums
619

720
1. Anonymous? Import elements as constants of the underlying type, *except* that Int is used for an inferred underlying type if all the cases fit in an Int32, since integer conversions are explicit in Swift.
@@ -114,15 +127,7 @@ In C, enumerators (enum cases) aren't namespaced under their enum type, so their
114127

115128
1. Collect all *available, non-deprecated* enum cases *without custom names.* If there are no such cases, collect all cases without custom names, whether available or not.
116129

117-
2. Find the common word-boundary prefix __CP__ of these cases. There is a word boundary after
118-
119-
1. An underscore ("\_").
120-
2. A series of two or more uppercase ASCII characters and the suffix "s", "es", or "ies" (e.g. "URLs", "VAXes")...unless the last uppercase letter is "I" and the suffix is "s", in which case it's just as likely to be an acronym followed by "Is" (i.e. "URLIs" is treated as "URL Is").
121-
2. A series of two or more uppercase ASCII characters followed by an uppercase ASCII character and then a lowercase ASCII character ("XMLReader" becomes "XML Reader").
122-
3. A series of two or more uppercase ASCII characters followed by a non-ASCII-alphabetic character. ("UTF8" becomes "UTF 8")
123-
4. A series of two or more uppercase ASCII characters at the end of the string.
124-
5. An uppercase ASCII character and any number of non-ASCII-uppercase, non-underscore characters ("ContrivedExample" becomes "Contrived Example").
125-
6. Any number of non-ASCII-uppercase, non-underscore characters ("lowercase\_example" becomes "lowercase \_ example").
130+
2. Find the common word-boundary prefix __CP__ of these cases.
126131

127132
3. If __CP__ starts with "k" followed by an uppercase letter, or if it's *just* "k" and none of the cases have a non-identifier-start character immediately after the 'k', treat that as meaning "constant" and ignore it for the next step.
128133

@@ -144,7 +149,7 @@ In C, enumerators (enum cases) aren't namespaced under their enum type, so their
144149

145150
9. ASCII-lowercase the first word of the remaining name if it starts with an uppercase ASCII character.
146151

147-
_There's a bug here where the special case for "Is" is missing, so "URLIs" will be lowercased to "urlis"._
152+
_There's a bug in this step where the special case for "Is" is missing, so "URLIs" will be lowercased to "urlis"._
148153

149154
## `swift_wrapper` typedefs
150155

@@ -190,4 +195,48 @@ extension SecretResourceID {
190195

191196
On Apple platforms, whenever Foundation is imported, constants with the type "NSNotificationName" additionally have the suffix "Notification" stripped before performing the above rules unless they have a custom name. Global NSString constants whose name ends in "Notification" will also automatically be treated as if they were declared with the type NSNotificationName unless they have a custom name.
192197

198+
199+
## Objective-C Protocols
200+
201+
Protocols in Objective-C are normally in a separate namespace from the "ordinary" identifier namespace used by typedefs and classes. Swift does not have separate namespaces, so if the protocol has the same name as another declaration in the same module, the suffix "Protocol" is appended. (Example: NSObjectProtocol in the ObjectiveC module.)
202+
203+
204+
## CF Types
205+
206+
"Core Foundation" is a C-based object-oriented system with strong conventions built around pointers to opaque structs. Creating new Core Foundation types is not generally supported, but Swift will recognize those in Apple's SDKs. If a struct has the `objc_bridge`, `objc_mutable_bridge`, or `objc_bridge_related` Clang attributes, it will be treated as a CF type and a typedef of a pointer to that struct will be imported as a class in Swift. The suffix "Ref" will be dropped from the class's name if present unless doing so would conflict with another declaration in the same module as the typedef.
207+
208+
If the class name contains the word "Mutable" exactly once per the usual word-boundary rules, a corresponding class name without the word "Mutable" will be used as the superclass if present. Otherwise, the CF type is taken to be a root object.
209+
210+
Additionally, typedefs for `void *` or `const void *` that are themselves annotated with `objc_bridge` will be treated as CFTypeRef-like and imported as `Any` rather than `Unsafe[Mutable]RawPointer`.
211+
212+
If a typedef's underlying type is itself a "CF pointer" typedef, the "alias" typedef will be imported as a regular typealias, with the suffix "Ref" still dropped from its name (if present) unless doing so would conflict with another declaration in the same module as the typedef.
213+
214+
215+
## `swift_private`
216+
217+
The `swift_private` Clang attribute prepends `__` onto the base name of any declaration being imported except initializers. For initializers with no arguments, a dummy `Void` argument with the name `__` is inserted; otherwise, the label for the first argument has `__` prepended. This transformation takes place after any other name manipulation, unless the declaration has a custom name. It will not occur if the declaration is an override; in that case the name needs to match the overridden declaration.
218+
219+
```objc
220+
@interface Example : NSObject
221+
- (instancetype)initWithValue:(int)value __attribute__((swift_private));
222+
@property(readonly) int value __attribute__((swift_private));
223+
@end
224+
225+
// Usually seen as NS_REFINED_FOR_SWIFT
226+
```
227+
228+
```swift
229+
class Example: NSObject {
230+
init(__value: Int32)
231+
var __value: Int32 { get }
232+
}
233+
```
234+
235+
The purpose of this annotation is to allow a more idiomatic implementation to be provided in Swift. The effect of `swift_private` is inherited from an enum onto its elements if the enum is not imported as an error code enum, an `@objc` enum, or an option set.
236+
237+
_The original intent of the `swift_private` attribute was additionally to limit access to a Swift module with the same name as the owning Clang module, e.g. the Swift half of a mixed-source framework. However, this restriction has not been implemented as of Swift 5.1._
238+
239+
_For "historical reasons", the `swift_private` attribute is ignored on factory methods with no arguments imported as initializers. This is essentially matching the behavior of older Swift compilers for source compatibility in case someone has marked such a factory method as `swift_private`._
240+
241+
193242
## More to come...

branches/master-rebranch/include/swift/AST/Attr.def

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,12 @@ DECL_ATTR(available, Available,
121121
1)
122122
CONTEXTUAL_SIMPLE_DECL_ATTR(final, Final,
123123
OnClass | OnFunc | OnAccessor | OnVar | OnSubscript |
124-
DeclModifier,
124+
DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove |
125+
APIBreakingToAdd,
125126
2)
126127
DECL_ATTR(objc, ObjC,
127128
OnAbstractFunction | OnClass | OnProtocol | OnExtension | OnVar |
128-
OnSubscript | OnEnum | OnEnumElement,
129+
OnSubscript | OnEnum | OnEnumElement | ABIBreakingToAdd | ABIBreakingToRemove,
129130
3)
130131
CONTEXTUAL_SIMPLE_DECL_ATTR(required, Required,
131132
OnConstructor |
@@ -187,7 +188,7 @@ DECL_ATTR(_semantics, Semantics,
187188
21)
188189
CONTEXTUAL_SIMPLE_DECL_ATTR(dynamic, Dynamic,
189190
OnFunc | OnAccessor | OnVar | OnSubscript | OnConstructor |
190-
DeclModifier,
191+
DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove,
191192
22)
192193
CONTEXTUAL_SIMPLE_DECL_ATTR(infix, Infix,
193194
OnFunc | OnOperator |
@@ -212,7 +213,7 @@ SIMPLE_DECL_ATTR(nonobjc, NonObjC,
212213
30)
213214
SIMPLE_DECL_ATTR(_fixed_layout, FixedLayout,
214215
OnVar | OnClass | OnStruct |
215-
UserInaccessible,
216+
UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove,
216217
31)
217218
SIMPLE_DECL_ATTR(inlinable, Inlinable,
218219
OnVar | OnSubscript | OnAbstractFunction,
@@ -362,7 +363,7 @@ SIMPLE_DECL_ATTR(_weakLinked, WeakLinked,
362363
OnSubscript | OnConstructor | OnEnumElement | OnExtension | UserInaccessible,
363364
75)
364365
SIMPLE_DECL_ATTR(frozen, Frozen,
365-
OnEnum | OnStruct,
366+
OnEnum | OnStruct | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToRemove,
366367
76)
367368
DECL_ATTR_ALIAS(_frozen, Frozen)
368369
SIMPLE_DECL_ATTR(_forbidSerializingReference, ForbidSerializingReference,

branches/master-rebranch/include/swift/AST/Attr.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,18 @@ class DeclAttribute : public AttributeBase {
353353

354354
/// Whether client code cannot use the attribute.
355355
UserInaccessible = 1ull << (unsigned(DeclKindIndex::Last_Decl) + 7),
356+
357+
/// Whether adding this attribute can break API
358+
APIBreakingToAdd = 1ull << (unsigned(DeclKindIndex::Last_Decl) + 8),
359+
360+
/// Whether removing this attribute can break API
361+
APIBreakingToRemove = 1ull << (unsigned(DeclKindIndex::Last_Decl) + 9),
362+
363+
/// Whether adding this attribute can break ABI
364+
ABIBreakingToAdd = 1ull << (unsigned(DeclKindIndex::Last_Decl) + 10),
365+
366+
/// Whether removing this attribute can break ABI
367+
ABIBreakingToRemove = 1ull << (unsigned(DeclKindIndex::Last_Decl) + 11),
356368
};
357369

358370
LLVM_READNONE
@@ -435,6 +447,21 @@ class DeclAttribute : public AttributeBase {
435447
return getOptions(DK) & UserInaccessible;
436448
}
437449

450+
static bool isAddingBreakingABI(DeclAttrKind DK) {
451+
return getOptions(DK) & ABIBreakingToAdd;
452+
}
453+
454+
static bool isAddingBreakingAPI(DeclAttrKind DK) {
455+
return getOptions(DK) & APIBreakingToAdd;
456+
}
457+
458+
static bool isRemovingBreakingABI(DeclAttrKind DK) {
459+
return getOptions(DK) & ABIBreakingToRemove;
460+
}
461+
static bool isRemovingBreakingAPI(DeclAttrKind DK) {
462+
return getOptions(DK) & APIBreakingToRemove;
463+
}
464+
438465
bool isDeclModifier() const {
439466
return isDeclModifier(getKind());
440467
}

branches/master-rebranch/include/swift/SILOptimizer/Utils/StackNesting.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,13 @@ class StackNesting {
155155
return bitNumberForAlloc(AllocInst);
156156
}
157157

158+
/// Insert deallocations at block boundaries.
159+
Changes insertDeallocsAtBlockBoundaries();
160+
158161
/// Modifies the SIL to end up with a correct stack nesting.
159162
///
160163
/// Returns the status of what changes were made.
161-
Changes adaptDeallocs();
164+
bool adaptDeallocs();
162165
};
163166

164167
} // end namespace swift

branches/master-rebranch/lib/SILOptimizer/Utils/StackNesting.cpp

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ void StackNesting::setup(SILFunction *F) {
2424

2525
// We use pointers to BlockInfo structs. Therefore it's important that the
2626
// BlockInfos vector is never re-allocated.
27+
BlockInfos.clear();
2728
BlockInfos.reserve(F->size());
2829

2930
// Start with the function entry block and add blocks while walking down along
@@ -231,36 +232,26 @@ bool StackNesting::insertDeallocs(const BitVector &AliveBefore,
231232
return changesMade;
232233
}
233234

234-
StackNesting::Changes StackNesting::adaptDeallocs() {
235-
236-
bool InstChanged = false;
237-
bool CFGChanged = false;
238-
BitVector Bits(StackLocs.size());
239-
240-
// Visit all blocks. Actually the order doesn't matter, but let's to it in
241-
// the same order as in solve().
235+
// Insert deallocations at block boundaries.
236+
// This can be necessary for unreachable blocks. Example:
237+
//
238+
// %1 = alloc_stack
239+
// %2 = alloc_stack
240+
// cond_br %c, bb2, bb3
241+
// bb2: <--- need to insert a dealloc_stack %2 at the begin of bb2
242+
// dealloc_stack %1
243+
// unreachable
244+
// bb3:
245+
// dealloc_stack %2
246+
// dealloc_stack %1
247+
StackNesting::Changes StackNesting::insertDeallocsAtBlockBoundaries() {
248+
Changes changes = Changes::None;
242249
for (const BlockInfo &BI : reversed(BlockInfos)) {
243-
// Collect the alive-bits (at the block exit) from the successor blocks.
244-
Bits = BI.AliveStackLocsAtExit;
245-
246-
// Insert deallocations at block boundaries.
247-
// This can be necessary for unreachable blocks. Example:
248-
//
249-
// %1 = alloc_stack
250-
// %2 = alloc_stack
251-
// cond_br %c, bb2, bb3
252-
// bb2: <--- need to insert a dealloc_stack %2 at the begin of bb2
253-
// dealloc_stack %1
254-
// unreachable
255-
// bb3:
256-
// dealloc_stack %2
257-
// dealloc_stack %1
258-
//
259250
for (unsigned SuccIdx = 0, NumSuccs = BI.Successors.size();
260-
SuccIdx < NumSuccs; ++ SuccIdx) {
261-
BlockInfo *SuccBI = BI.Successors[SuccIdx];
251+
SuccIdx < NumSuccs; ++SuccIdx) {
262252

263-
if (SuccBI->AliveStackLocsAtEntry == Bits)
253+
BlockInfo *SuccBI = BI.Successors[SuccIdx];
254+
if (SuccBI->AliveStackLocsAtEntry == BI.AliveStackLocsAtExit)
264255
continue;
265256

266257
// Insert deallocations for all locations which are alive at the end of
@@ -271,11 +262,26 @@ StackNesting::Changes StackNesting::adaptDeallocs() {
271262
// block, we have to insert a new block where we can add the
272263
// deallocations.
273264
InsertionBlock = splitEdge(BI.Block->getTerminator(), SuccIdx);
274-
CFGChanged = true;
265+
changes = Changes::CFG;
266+
}
267+
if (insertDeallocs(BI.AliveStackLocsAtExit, SuccBI->AliveStackLocsAtEntry,
268+
&InsertionBlock->front(), None)) {
269+
if (changes == Changes::None)
270+
changes = Changes::Instructions;
275271
}
276-
InstChanged |= insertDeallocs(Bits, SuccBI->AliveStackLocsAtEntry,
277-
&InsertionBlock->front(), None);
278272
}
273+
}
274+
return changes;
275+
}
276+
277+
bool StackNesting::adaptDeallocs() {
278+
bool InstChanged = false;
279+
BitVector Bits(StackLocs.size());
280+
281+
// Visit all blocks. Actually the order doesn't matter, but let's to it in
282+
// the same order as in solve().
283+
for (const BlockInfo &BI : reversed(BlockInfos)) {
284+
Bits = BI.AliveStackLocsAtExit;
279285

280286
// Insert/remove deallocations inside blocks.
281287
for (SILInstruction *StackInst : reversed(BI.StackInsts)) {
@@ -310,19 +316,29 @@ StackNesting::Changes StackNesting::adaptDeallocs() {
310316
}
311317
assert(Bits == BI.AliveStackLocsAtEntry && "dataflow didn't converge");
312318
}
313-
if (CFGChanged)
314-
return Changes::CFG;
315-
if (InstChanged)
316-
return Changes::Instructions;
317-
return Changes::None;
319+
return InstChanged;
318320
}
319321

320322
StackNesting::Changes StackNesting::correctStackNesting(SILFunction *F) {
321323
setup(F);
322-
if (solve()) {
323-
return adaptDeallocs();
324+
if (!solve())
325+
return Changes::None;
326+
327+
// Insert deallocs at block boundaries. This might be necessary in CFG sub
328+
// graphs which don't reach a function exit, but only an unreachable.
329+
Changes changes = insertDeallocsAtBlockBoundaries();
330+
if (changes != Changes::None) {
331+
// Those inserted deallocs make it necessary to re-compute the analysis.
332+
setup(F);
333+
solve();
334+
}
335+
// Do the real work: extend lifetimes by moving deallocs.
336+
if (adaptDeallocs()) {
337+
if (changes == Changes::None)
338+
changes = Changes::Instructions;
324339
}
325-
return Changes::None;
340+
341+
return changes;
326342
}
327343

328344
void StackNesting::dump() const {

branches/master-rebranch/lib/Sema/CSGen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2478,11 +2478,11 @@ namespace {
24782478
}
24792479

24802480
Type visitDefaultArgumentExpr(DefaultArgumentExpr *expr) {
2481-
llvm_unreachable("Already type checked");
2481+
return expr->getType();
24822482
}
24832483

24842484
Type visitCallerDefaultArgumentExpr(CallerDefaultArgumentExpr *expr) {
2485-
llvm_unreachable("Already type checked");
2485+
return expr->getType();
24862486
}
24872487

24882488
Type visitApplyExpr(ApplyExpr *expr) {

branches/master-rebranch/lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4713,7 +4713,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
47134713
// as representing "dynamic lookup" unless it's a direct call
47144714
// to such subscript (in that case label is expected to match).
47154715
if (auto *subscript = dyn_cast<SubscriptDecl>(cand)) {
4716-
if (::hasDynamicMemberLookupAttribute(instanceTy,
4716+
if (memberLocator &&
4717+
::hasDynamicMemberLookupAttribute(instanceTy,
47174718
DynamicMemberLookupCache) &&
47184719
isValidKeyPathDynamicMemberLookup(subscript, TC)) {
47194720
auto info = getArgumentInfo(memberLocator);

branches/master-rebranch/lib/Sema/ConstraintSystem.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2880,6 +2880,9 @@ ConstraintSystem::getArgumentInfoLocator(ConstraintLocator *locator) {
28802880

28812881
Optional<ConstraintSystem::ArgumentInfo>
28822882
ConstraintSystem::getArgumentInfo(ConstraintLocator *locator) {
2883+
if (!locator)
2884+
return None;
2885+
28832886
if (auto *infoLocator = getArgumentInfoLocator(locator)) {
28842887
auto known = ArgumentInfos.find(infoLocator);
28852888
if (known != ArgumentInfos.end())

branches/master-rebranch/lib/Sema/TypeCheckCaptures.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,12 @@ void TypeChecker::computeCaptures(AnyFunctionRef AFR) {
645645
}
646646
}
647647

648+
static bool isLazy(PatternBindingDecl *PBD) {
649+
if (auto var = PBD->getSingleVar())
650+
return var->getAttrs().hasAttribute<LazyAttr>();
651+
return false;
652+
}
653+
648654
void TypeChecker::checkPatternBindingCaptures(NominalTypeDecl *typeDecl) {
649655
auto &ctx = typeDecl->getASTContext();
650656

@@ -669,7 +675,7 @@ void TypeChecker::checkPatternBindingCaptures(NominalTypeDecl *typeDecl) {
669675
/*ObjC=*/false);
670676
init->walk(finder);
671677

672-
if (finder.getDynamicSelfCaptureLoc().isValid()) {
678+
if (finder.getDynamicSelfCaptureLoc().isValid() && !isLazy(PBD)) {
673679
ctx.Diags.diagnose(finder.getDynamicSelfCaptureLoc(),
674680
diag::dynamic_self_stored_property_init);
675681
}

0 commit comments

Comments
 (0)