Merge remote-tracking branch 'origin/master' into master-next

This commit is contained in:
swift-ci
2017-05-17 18:49:11 -07:00
18 changed files with 854 additions and 111 deletions

View File

@@ -49,6 +49,7 @@ KNOWN_STDLIB_TYPE_DECL(Set, NominalTypeDecl, 1)
KNOWN_STDLIB_TYPE_DECL(Sequence, NominalTypeDecl, 1)
KNOWN_STDLIB_TYPE_DECL(Dictionary, NominalTypeDecl, 2)
KNOWN_STDLIB_TYPE_DECL(AnyHashable, NominalTypeDecl, 0)
KNOWN_STDLIB_TYPE_DECL(MutableCollection, ProtocolDecl, 1)
KNOWN_STDLIB_TYPE_DECL(PartialKeyPath, NominalTypeDecl, 1)
KNOWN_STDLIB_TYPE_DECL(KeyPath, NominalTypeDecl, 2)

View File

@@ -143,10 +143,6 @@ public:
/// Emit compile-time diagnostics when the law of exclusivity is violated.
bool EnforceExclusivityStatic = true;
/// Suppress static diagnostics for violations of exclusive access for calls
/// to the Standard Library's swap() free function.
bool SuppressStaticExclusivitySwap = false;
/// Emit checks to trap at run time when the law of exclusivity is violated.
bool EnforceExclusivityDynamic = false;

View File

@@ -1369,8 +1369,6 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
|= Args.hasArg(OPT_assume_parsing_unqualified_ownership_sil);
Opts.EnableMandatorySemanticARCOpts |=
!Args.hasArg(OPT_disable_mandatory_semantic_arc_opts);
Opts.SuppressStaticExclusivitySwap |=
Args.hasArg(OPT_suppress_static_exclusivity_swap);
if (Args.hasArg(OPT_debug_on_sil)) {
// Derive the name of the SIL file for debugging from

View File

@@ -30,6 +30,7 @@
#include "swift/AST/Expr.h"
#include "swift/AST/Stmt.h"
#include "swift/Basic/SourceLoc.h"
#include "swift/Parse/Lexer.h"
#include "swift/SIL/CFG.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILInstruction.h"
@@ -305,33 +306,48 @@ static ExclusiveOrShared_t getRequiredAccess(const BeginAccessInst *BAI) {
return ExclusiveOrShared_t::ExclusiveAccess;
}
/// Perform a syntactic suppression that returns true when the accesses are for
/// inout arguments to a call that corresponds to one of the passed-in
/// 'apply' instructions.
static bool
isConflictOnInoutArgumentsToSuppressed(const BeginAccessInst *Access1,
const BeginAccessInst *Access2,
ArrayRef<ApplyInst *> CallsToSuppress) {
if (CallsToSuppress.empty())
return false;
/// Extract the text for the given expression.
static StringRef extractExprText(const Expr *E, SourceManager &SM) {
const auto CSR = Lexer::getCharSourceRangeFromSourceRange(SM,
E->getSourceRange());
return SM.extractText(CSR);
}
/// Do a sytactic pattern match to try to safely suggest a Fix-It to rewrite
/// calls like swap(&collection[index1], &collection[index2]) to
///
/// This method takes an array of all the ApplyInsts for calls to swap()
/// in the function to avoid need to construct a parent map over the AST
/// to find the CallExpr for the inout accesses.
static void
tryFixItWithCallToCollectionSwapAt(const BeginAccessInst *Access1,
const BeginAccessInst *Access2,
ArrayRef<ApplyInst *> CallsToSwap,
ASTContext &Ctx,
InFlightDiagnostic &Diag) {
if (CallsToSwap.empty())
return;
// Inout arguments must be modifications.
if (Access1->getAccessKind() != SILAccessKind::Modify ||
Access2->getAccessKind() != SILAccessKind::Modify) {
return false;
return;
}
SILLocation Loc1 = Access1->getLoc();
SILLocation Loc2 = Access2->getLoc();
if (Loc1.isNull() || Loc2.isNull())
return false;
return;
auto *InOut1 = Loc1.getAsASTNode<InOutExpr>();
auto *InOut2 = Loc2.getAsASTNode<InOutExpr>();
if (!InOut1 || !InOut2)
return false;
return;
for (ApplyInst *AI : CallsToSuppress) {
CallExpr *FoundCall = nullptr;
// Look through all the calls to swap() recorded in the function to find
// which one we're diagnosing.
for (ApplyInst *AI : CallsToSwap) {
SILLocation CallLoc = AI->getLoc();
if (CallLoc.isNull())
continue;
@@ -340,21 +356,89 @@ isConflictOnInoutArgumentsToSuppressed(const BeginAccessInst *Access1,
if (!CE)
continue;
bool FoundTarget = false;
CE->forEachChildExpr([=,&FoundTarget](Expr *Child) {
if (Child == InOut1) {
FoundTarget = true;
// Stops the traversal.
return (Expr *)nullptr;
assert(CE->getCalledValue() == Ctx.getSwap(nullptr));
// swap() takes two arguments.
auto *ArgTuple = cast<TupleExpr>(CE->getArg());
const Expr *Arg1 = ArgTuple->getElement(0);
const Expr *Arg2 = ArgTuple->getElement(1);
if ((Arg1 == InOut1 && Arg2 == InOut2)) {
FoundCall = CE;
break;
}
}
if (!FoundCall)
return;
// We found a call to swap(&e1, &e2). Now check to see whether it
// matches the form swap(&someCollection[index1], &someCollection[index2]).
auto *SE1 = dyn_cast<SubscriptExpr>(InOut1->getSubExpr());
if (!SE1)
return;
auto *SE2 = dyn_cast<SubscriptExpr>(InOut2->getSubExpr());
if (!SE2)
return;
// Do the two subscripts refer to the same subscript declaration?
auto *Decl1 = cast<SubscriptDecl>(SE1->getDecl().getDecl());
auto *Decl2 = cast<SubscriptDecl>(SE2->getDecl().getDecl());
if (Decl1 != Decl2)
return;
ProtocolDecl *MutableCollectionDecl = Ctx.getMutableCollectionDecl();
// Is the subcript either (1) on MutableCollection itself or (2) a
// a witness for a subscript on MutableCollection?
bool IsSubscriptOnMutableCollection = false;
ProtocolDecl *ProtocolForDecl =
Decl1->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
if (ProtocolForDecl) {
IsSubscriptOnMutableCollection = (ProtocolForDecl == MutableCollectionDecl);
} else {
for (ValueDecl *Req : Decl1->getSatisfiedProtocolRequirements()) {
DeclContext *ReqDC = Req->getDeclContext();
ProtocolDecl *ReqProto = ReqDC->getAsProtocolOrProtocolExtensionContext();
assert(ReqProto && "Protocol requirement not in a protocol?");
if (ReqProto == MutableCollectionDecl) {
IsSubscriptOnMutableCollection = true;
break;
}
return Child;
}
);
if (FoundTarget)
return true;
}
}
return false;
if (!IsSubscriptOnMutableCollection)
return;
// We're swapping two subscripts on mutable collections -- but are they
// the same collection? Approximate this by checking for textual
// equality on the base expressions. This is just an approximation,
// but is fine for a best-effort Fix-It.
SourceManager &SM = Ctx.SourceMgr;
StringRef Base1Text = extractExprText(SE1->getBase(), SM);
StringRef Base2Text = extractExprText(SE2->getBase(), SM);
if (Base1Text != Base2Text)
return;
auto *Index1 = dyn_cast<ParenExpr>(SE1->getIndex());
if (!Index1)
return;
auto *Index2 = dyn_cast<ParenExpr>(SE2->getIndex());
if (!Index2)
return;
StringRef Index1Text = extractExprText(Index1->getSubExpr(), SM);
StringRef Index2Text = extractExprText(Index2->getSubExpr(), SM);
// Suggest replacing with call with a call to swapAt().
SmallString<64> FixItText;
{
llvm::raw_svector_ostream Out(FixItText);
Out << Base1Text << ".swapAt(" << Index1Text << ", " << Index2Text << ")";
}
Diag.fixItReplace(FoundCall->getSourceRange(), FixItText);
}
/// Emits a diagnostic if beginning an access with the given in-progress
@@ -363,6 +447,7 @@ isConflictOnInoutArgumentsToSuppressed(const BeginAccessInst *Access1,
static void diagnoseExclusivityViolation(const AccessedStorage &Storage,
const BeginAccessInst *PriorAccess,
const BeginAccessInst *NewAccess,
ArrayRef<ApplyInst *> CallsToSwap,
ASTContext &Ctx) {
DEBUG(llvm::dbgs() << "Conflict on " << *PriorAccess
@@ -385,25 +470,29 @@ static void diagnoseExclusivityViolation(const AccessedStorage &Storage,
SourceRange rangeForMain =
AccessForMainDiagnostic->getLoc().getSourceRange();
unsigned AccessKindForMain =
static_cast<unsigned>(AccessForMainDiagnostic->getAccessKind());
if (const ValueDecl *VD = Storage.getStorageDecl()) {
// We have a declaration, so mention the identifier in the diagnostic.
auto DiagnosticID = (Ctx.LangOpts.isSwiftVersion3() ?
diag::exclusivity_access_required_swift3 :
diag::exclusivity_access_required);
diagnose(Ctx, AccessForMainDiagnostic->getLoc().getSourceLoc(),
DiagnosticID,
VD->getDescriptiveKind(),
VD->getName(),
static_cast<unsigned>(AccessForMainDiagnostic->getAccessKind()))
.highlight(rangeForMain);
auto D = diagnose(Ctx, AccessForMainDiagnostic->getLoc().getSourceLoc(),
DiagnosticID,
VD->getDescriptiveKind(),
VD->getName(),
AccessKindForMain);
D.highlight(rangeForMain);
tryFixItWithCallToCollectionSwapAt(PriorAccess, NewAccess,
CallsToSwap, Ctx, D);
} else {
auto DiagnosticID = (Ctx.LangOpts.isSwiftVersion3() ?
diag::exclusivity_access_required_unknown_decl_swift3 :
diag::exclusivity_access_required_unknown_decl);
diagnose(Ctx, AccessForMainDiagnostic->getLoc().getSourceLoc(),
DiagnosticID,
static_cast<unsigned>(AccessForMainDiagnostic->getAccessKind()))
AccessKindForMain)
.highlight(rangeForMain);
}
diagnose(Ctx, AccessForNote->getLoc().getSourceLoc(),
@@ -500,7 +589,8 @@ static AccessedStorage findAccessedStorage(SILValue Source) {
}
/// Returns true when the apply calls the Standard Library swap().
/// Used for diagnostic suppression.
/// Used for fix-its to suggest replacing with Collection.swapAt()
/// on exclusivity violations.
bool isCallToStandardLibrarySwap(ApplyInst *AI, ASTContext &Ctx) {
SILFunction *SF = AI->getReferencedFunction();
if (!SF)
@@ -535,9 +625,8 @@ static void checkStaticExclusivity(SILFunction &Fn, PostOrderFunctionInfo *PO) {
if (Fn.empty())
return;
// Collects calls to functions for which diagnostics about conflicting inout
// arguments should be suppressed.
llvm::SmallVector<ApplyInst *, 8> CallsToSuppress;
// Collects calls the Standard Library swap() for Fix-Its.
llvm::SmallVector<ApplyInst *, 8> CallsToSwap;
// Stores the accesses that have been found to conflict. Used to defer
// emitting diagnostics until we can determine whether they should
@@ -606,11 +695,9 @@ static void checkStaticExclusivity(SILFunction &Fn, PostOrderFunctionInfo *PO) {
}
if (auto *AI = dyn_cast<ApplyInst>(&I)) {
// Suppress for the arguments to the Standard Library's swap()
// function until we can recommend a safe alternative.
if (Fn.getModule().getOptions().SuppressStaticExclusivitySwap &&
isCallToStandardLibrarySwap(AI, Fn.getASTContext()))
CallsToSuppress.push_back(AI);
// Record calls to swap() for potential Fix-Its.
if (isCallToStandardLibrarySwap(AI, Fn.getASTContext()))
CallsToSwap.push_back(AI);
}
// Sanity check to make sure entries are properly removed.
@@ -624,12 +711,9 @@ static void checkStaticExclusivity(SILFunction &Fn, PostOrderFunctionInfo *PO) {
for (auto &Violation : ConflictingAccesses) {
const BeginAccessInst *PriorAccess = Violation.FirstAccess;
const BeginAccessInst *NewAccess = Violation.SecondAccess;
if (isConflictOnInoutArgumentsToSuppressed(PriorAccess, NewAccess,
CallsToSuppress))
continue;
diagnoseExclusivityViolation(Violation.Storage, PriorAccess, NewAccess,
Fn.getASTContext());
CallsToSwap, Fn.getASTContext());
}
}

View File

@@ -111,6 +111,28 @@ double _swift_stdlib_squareRoot(double _self) {
return __builtin_sqrt(_self);
}
// TLS - thread local storage
#if defined(__linux__)
typedef unsigned int __swift_pthread_key_t;
#else
typedef unsigned long __swift_pthread_key_t;
#endif
SWIFT_RUNTIME_STDLIB_INTERFACE
int _swift_stdlib_pthread_key_create(
__swift_pthread_key_t * _Nonnull key, void
(* _Nullable destructor)(void * _Nullable )
);
SWIFT_RUNTIME_STDLIB_INTERFACE
void * _Nullable _swift_stdlib_pthread_getspecific(__swift_pthread_key_t key);
SWIFT_RUNTIME_STDLIB_INTERFACE
int _swift_stdlib_pthread_setspecific(
__swift_pthread_key_t key, const void * _Nullable value
);
// TODO: Remove horrible workaround when importer does Float80 <-> long double.
#if (defined __i386__ || defined __x86_64__) && !defined _MSC_VER
static inline SWIFT_ALWAYS_INLINE

View File

@@ -109,6 +109,218 @@ __swift_int32_t _swift_stdlib_unicode_strToLower(
__swift_uint16_t *Destination, __swift_int32_t DestinationCapacity,
const __swift_uint16_t *Source, __swift_int32_t SourceLength);
typedef enum __swift_stdlib_UErrorCode {
__swift_stdlib_U_USING_FALLBACK_WARNING = -128,
__swift_stdlib_U_ERROR_WARNING_START = -128,
__swift_stdlib_U_USING_DEFAULT_WARNING = -127,
__swift_stdlib_U_SAFECLONE_ALLOCATED_WARNING = -126,
__swift_stdlib_U_STATE_OLD_WARNING = -125,
__swift_stdlib_U_STRING_NOT_TERMINATED_WARNING = -124,
__swift_stdlib_U_SORT_KEY_TOO_SHORT_WARNING = -123,
__swift_stdlib_U_AMBIGUOUS_ALIAS_WARNING = -122,
__swift_stdlib_U_DIFFERENT_UCA_VERSION = -121,
__swift_stdlib_U_PLUGIN_CHANGED_LEVEL_WARNING = -120,
__swift_stdlib_U_ERROR_WARNING_LIMIT,
__swift_stdlib_U_ZERO_ERROR = 0,
__swift_stdlib_U_ILLEGAL_ARGUMENT_ERROR = 1,
__swift_stdlib_U_MISSING_RESOURCE_ERROR = 2,
__swift_stdlib_U_INVALID_FORMAT_ERROR = 3,
__swift_stdlib_U_FILE_ACCESS_ERROR = 4,
__swift_stdlib_U_INTERNAL_PROGRAM_ERROR = 5,
__swift_stdlib_U_MESSAGE_PARSE_ERROR = 6,
__swift_stdlib_U_MEMORY_ALLOCATION_ERROR = 7,
__swift_stdlib_U_INDEX_OUTOFBOUNDS_ERROR = 8,
__swift_stdlib_U_PARSE_ERROR = 9,
__swift_stdlib_U_INVALID_CHAR_FOUND = 10,
__swift_stdlib_U_TRUNCATED_CHAR_FOUND = 11,
__swift_stdlib_U_ILLEGAL_CHAR_FOUND = 12,
__swift_stdlib_U_INVALID_TABLE_FORMAT = 13,
__swift_stdlib_U_INVALID_TABLE_FILE = 14,
__swift_stdlib_U_BUFFER_OVERFLOW_ERROR = 15,
__swift_stdlib_U_UNSUPPORTED_ERROR = 16,
__swift_stdlib_U_RESOURCE_TYPE_MISMATCH = 17,
__swift_stdlib_U_ILLEGAL_ESCAPE_SEQUENCE = 18,
__swift_stdlib_U_UNSUPPORTED_ESCAPE_SEQUENCE = 19,
__swift_stdlib_U_NO_SPACE_AVAILABLE = 20,
__swift_stdlib_U_CE_NOT_FOUND_ERROR = 21,
__swift_stdlib_U_PRIMARY_TOO_LONG_ERROR = 22,
__swift_stdlib_U_STATE_TOO_OLD_ERROR = 23,
__swift_stdlib_U_TOO_MANY_ALIASES_ERROR = 24,
__swift_stdlib_U_ENUM_OUT_OF_SYNC_ERROR = 25,
__swift_stdlib_U_INVARIANT_CONVERSION_ERROR = 26,
__swift_stdlib_U_INVALID_STATE_ERROR = 27,
__swift_stdlib_U_COLLATOR_VERSION_MISMATCH = 28,
__swift_stdlib_U_USELESS_COLLATOR_ERROR = 29,
__swift_stdlib_U_NO_WRITE_PERMISSION = 30,
__swift_stdlib_U_STANDARD_ERROR_LIMIT,
__swift_stdlib_U_BAD_VARIABLE_DEFINITION = 0x10000,
__swift_stdlib_U_PARSE_ERROR_START = 0x10000,
__swift_stdlib_U_MALFORMED_RULE,
__swift_stdlib_U_MALFORMED_SET,
__swift_stdlib_U_MALFORMED_SYMBOL_REFERENCE,
__swift_stdlib_U_MALFORMED_UNICODE_ESCAPE,
__swift_stdlib_U_MALFORMED_VARIABLE_DEFINITION,
__swift_stdlib_U_MALFORMED_VARIABLE_REFERENCE,
__swift_stdlib_U_MISMATCHED_SEGMENT_DELIMITERS,
__swift_stdlib_U_MISPLACED_ANCHOR_START,
__swift_stdlib_U_MISPLACED_CURSOR_OFFSET,
__swift_stdlib_U_MISPLACED_QUANTIFIER,
__swift_stdlib_U_MISSING_OPERATOR,
__swift_stdlib_U_MISSING_SEGMENT_CLOSE,
__swift_stdlib_U_MULTIPLE_ANTE_CONTEXTS,
__swift_stdlib_U_MULTIPLE_CURSORS,
__swift_stdlib_U_MULTIPLE_POST_CONTEXTS,
__swift_stdlib_U_TRAILING_BACKSLASH,
__swift_stdlib_U_UNDEFINED_SEGMENT_REFERENCE,
__swift_stdlib_U_UNDEFINED_VARIABLE,
__swift_stdlib_U_UNQUOTED_SPECIAL,
__swift_stdlib_U_UNTERMINATED_QUOTE,
__swift_stdlib_U_RULE_MASK_ERROR,
__swift_stdlib_U_MISPLACED_COMPOUND_FILTER,
__swift_stdlib_U_MULTIPLE_COMPOUND_FILTERS,
__swift_stdlib_U_INVALID_RBT_SYNTAX,
__swift_stdlib_U_INVALID_PROPERTY_PATTERN,
__swift_stdlib_U_MALFORMED_PRAGMA,
__swift_stdlib_U_UNCLOSED_SEGMENT,
__swift_stdlib_U_ILLEGAL_CHAR_IN_SEGMENT,
__swift_stdlib_U_VARIABLE_RANGE_EXHAUSTED,
__swift_stdlib_U_VARIABLE_RANGE_OVERLAP,
__swift_stdlib_U_ILLEGAL_CHARACTER,
__swift_stdlib_U_INTERNAL_TRANSLITERATOR_ERROR,
__swift_stdlib_U_INVALID_ID,
__swift_stdlib_U_INVALID_FUNCTION,
__swift_stdlib_U_PARSE_ERROR_LIMIT,
__swift_stdlib_U_UNEXPECTED_TOKEN = 0x10100,
__swift_stdlib_U_FMT_PARSE_ERROR_START = 0x10100,
__swift_stdlib_U_MULTIPLE_DECIMAL_SEPARATORS,
__swift_stdlib_U_MULTIPLE_DECIMAL_SEPERATORS =
__swift_stdlib_U_MULTIPLE_DECIMAL_SEPARATORS,
__swift_stdlib_U_MULTIPLE_EXPONENTIAL_SYMBOLS,
__swift_stdlib_U_MALFORMED_EXPONENTIAL_PATTERN,
__swift_stdlib_U_MULTIPLE_PERCENT_SYMBOLS,
__swift_stdlib_U_MULTIPLE_PERMILL_SYMBOLS,
__swift_stdlib_U_MULTIPLE_PAD_SPECIFIERS,
__swift_stdlib_U_PATTERN_SYNTAX_ERROR,
__swift_stdlib_U_ILLEGAL_PAD_POSITION,
__swift_stdlib_U_UNMATCHED_BRACES,
__swift_stdlib_U_UNSUPPORTED_PROPERTY,
__swift_stdlib_U_UNSUPPORTED_ATTRIBUTE,
__swift_stdlib_U_ARGUMENT_TYPE_MISMATCH,
__swift_stdlib_U_DUPLICATE_KEYWORD,
__swift_stdlib_U_UNDEFINED_KEYWORD,
__swift_stdlib_U_DEFAULT_KEYWORD_MISSING,
__swift_stdlib_U_DECIMAL_NUMBER_SYNTAX_ERROR,
__swift_stdlib_U_FORMAT_INEXACT_ERROR,
__swift_stdlib_U_FMT_PARSE_ERROR_LIMIT,
__swift_stdlib_U_BRK_INTERNAL_ERROR = 0x10200,
__swift_stdlib_U_BRK_ERROR_START = 0x10200,
__swift_stdlib_U_BRK_HEX_DIGITS_EXPECTED,
__swift_stdlib_U_BRK_SEMICOLON_EXPECTED,
__swift_stdlib_U_BRK_RULE_SYNTAX,
__swift_stdlib_U_BRK_UNCLOSED_SET,
__swift_stdlib_U_BRK_ASSIGN_ERROR,
__swift_stdlib_U_BRK_VARIABLE_REDFINITION,
__swift_stdlib_U_BRK_MISMATCHED_PAREN,
__swift_stdlib_U_BRK_NEW_LINE_IN_QUOTED_STRING,
__swift_stdlib_U_BRK_UNDEFINED_VARIABLE,
__swift_stdlib_U_BRK_INIT_ERROR,
__swift_stdlib_U_BRK_RULE_EMPTY_SET,
__swift_stdlib_U_BRK_UNRECOGNIZED_OPTION,
__swift_stdlib_U_BRK_MALFORMED_RULE_TAG,
__swift_stdlib_U_BRK_ERROR_LIMIT,
__swift_stdlib_U_REGEX_INTERNAL_ERROR = 0x10300,
__swift_stdlib_U_REGEX_ERROR_START = 0x10300,
__swift_stdlib_U_REGEX_RULE_SYNTAX,
__swift_stdlib_U_REGEX_INVALID_STATE,
__swift_stdlib_U_REGEX_BAD_ESCAPE_SEQUENCE,
__swift_stdlib_U_REGEX_PROPERTY_SYNTAX,
__swift_stdlib_U_REGEX_UNIMPLEMENTED,
__swift_stdlib_U_REGEX_MISMATCHED_PAREN,
__swift_stdlib_U_REGEX_NUMBER_TOO_BIG,
__swift_stdlib_U_REGEX_BAD_INTERVAL,
__swift_stdlib_U_REGEX_MAX_LT_MIN,
__swift_stdlib_U_REGEX_INVALID_BACK_REF,
__swift_stdlib_U_REGEX_INVALID_FLAG,
__swift_stdlib_U_REGEX_LOOK_BEHIND_LIMIT,
__swift_stdlib_U_REGEX_SET_CONTAINS_STRING,
#ifndef __swift_stdlib_U_HIDE_DEPRECATED_API
__swift_stdlib_U_REGEX_OCTAL_TOO_BIG,
#endif
__swift_stdlib_U_REGEX_MISSING_CLOSE_BRACKET =
__swift_stdlib_U_REGEX_SET_CONTAINS_STRING + 2,
__swift_stdlib_U_REGEX_INVALID_RANGE,
__swift_stdlib_U_REGEX_STACK_OVERFLOW,
__swift_stdlib_U_REGEX_TIME_OUT,
__swift_stdlib_U_REGEX_STOPPED_BY_CALLER,
#ifndef __swift_stdlib_U_HIDE_DRAFT_API
__swift_stdlib_U_REGEX_PATTERN_TOO_BIG,
__swift_stdlib_U_REGEX_INVALID_CAPTURE_GROUP_NAME,
#endif
__swift_stdlib_U_REGEX_ERROR_LIMIT =
__swift_stdlib_U_REGEX_STOPPED_BY_CALLER + 3,
__swift_stdlib_U_IDNA_PROHIBITED_ERROR = 0x10400,
__swift_stdlib_U_IDNA_ERROR_START = 0x10400,
__swift_stdlib_U_IDNA_UNASSIGNED_ERROR,
__swift_stdlib_U_IDNA_CHECK_BIDI_ERROR,
__swift_stdlib_U_IDNA_STD3_ASCII_RULES_ERROR,
__swift_stdlib_U_IDNA_ACE_PREFIX_ERROR,
__swift_stdlib_U_IDNA_VERIFICATION_ERROR,
__swift_stdlib_U_IDNA_LABEL_TOO_LONG_ERROR,
__swift_stdlib_U_IDNA_ZERO_LENGTH_LABEL_ERROR,
__swift_stdlib_U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR,
__swift_stdlib_U_IDNA_ERROR_LIMIT,
__swift_stdlib_U_STRINGPREP_PROHIBITED_ERROR =
__swift_stdlib_U_IDNA_PROHIBITED_ERROR,
__swift_stdlib_U_STRINGPREP_UNASSIGNED_ERROR =
__swift_stdlib_U_IDNA_UNASSIGNED_ERROR,
__swift_stdlib_U_STRINGPREP_CHECK_BIDI_ERROR =
__swift_stdlib_U_IDNA_CHECK_BIDI_ERROR,
__swift_stdlib_U_PLUGIN_ERROR_START = 0x10500,
__swift_stdlib_U_PLUGIN_TOO_HIGH = 0x10500,
__swift_stdlib_U_PLUGIN_DIDNT_SET_LEVEL,
__swift_stdlib_U_PLUGIN_ERROR_LIMIT,
__swift_stdlib_U_ERROR_LIMIT = __swift_stdlib_U_PLUGIN_ERROR_LIMIT
} __swift_stdlib_UErrorCode;
typedef enum __swift_stdlib_UBreakIteratorType {
__swift_stdlib_UBRK_CHARACTER = 0,
__swift_stdlib_UBRK_WORD = 1,
__swift_stdlib_UBRK_LINE = 2,
__swift_stdlib_UBRK_SENTENCE = 3,
#ifndef U_HIDE_DEPRECATED_API
__swift_stdlib_UBRK_TITLE = 4,
#endif
__swift_stdlib_UBRK_COUNT = 5
} __swift_stdlib_UBreakIteratorType;
typedef struct __swift_stdlib_UBreakIterator __swift_stdlib_UBreakIterator;
typedef __swift_uint16_t __swift_stdlib_UChar;
SWIFT_RUNTIME_STDLIB_INTERFACE
void __swift_stdlib_ubrk_close(__swift_stdlib_UBreakIterator *bi);
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_stdlib_UBreakIterator *
__swift_stdlib_ubrk_open(__swift_stdlib_UBreakIteratorType type,
const char *_Null_unspecified locale,
const __swift_stdlib_UChar *_Null_unspecified text,
__swift_int32_t textLength,
__swift_stdlib_UErrorCode *status);
SWIFT_RUNTIME_STDLIB_INTERFACE
void __swift_stdlib_ubrk_setText(__swift_stdlib_UBreakIterator *bi,
const __swift_stdlib_UChar *text,
__swift_int32_t textLength,
__swift_stdlib_UErrorCode *status);
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_int32_t __swift_stdlib_ubrk_preceding(__swift_stdlib_UBreakIterator *bi,
__swift_int32_t offset);
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_int32_t __swift_stdlib_ubrk_following(__swift_stdlib_UBreakIterator *bi,
__swift_int32_t offset);
#ifdef __cplusplus
}} // extern "C", namespace swift
#endif

View File

@@ -68,6 +68,7 @@ set(SWIFTLIB_ESSENTIAL
HashedCollectionsAnyHashableExtensions.swift
Hashing.swift
HeapBuffer.swift
ICU.swift
ImplicitlyUnwrappedOptional.swift
Index.swift
Indices.swift.gyb
@@ -132,6 +133,7 @@ set(SWIFTLIB_ESSENTIAL
StringUTF8.swift
Substring.swift.gyb
SwiftNativeNSArray.swift
ThreadLocalStorage.swift
UIntBuffer.swift
UnavailableStringAPIs.swift.gyb
UnicodeEncoding.swift
@@ -176,6 +178,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
list(APPEND swift_core_link_flags "-all_load")
list(APPEND swift_core_framework_depends Foundation)
list(APPEND swift_core_framework_depends CoreFoundation)
list(APPEND swift_core_private_link_libraries icucore)
else()
# With the GNU linker the equivalent of -all_load is to tell the linker
# --whole-archive before the archive and --no-whole-archive after (without

View File

@@ -8,6 +8,7 @@
"CString.swift",
"Character.swift",
"CharacterUnicodeScalars.swift",
"ICU.swift",
"StaticString.swift",
"String.swift",
"StringBridge.swift",
@@ -161,6 +162,7 @@
"REPL.swift",
"Runtime.swift",
"Shims.swift",
"ThreadLocalStorage.swift",
"Unmanaged.swift",
"Availability.swift",
"CommandLine.swift",

View File

@@ -0,0 +1,18 @@
//===--- ICU.swift --------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import SwiftShims
extension __swift_stdlib_UErrorCode {
var isFailure: Bool { return rawValue > __swift_stdlib_U_ZERO_ERROR.rawValue }
var isWarning: Bool { return rawValue < __swift_stdlib_U_ZERO_ERROR.rawValue }
var isSuccess: Bool { return rawValue <= __swift_stdlib_U_ZERO_ERROR.rawValue }
}

View File

@@ -22,6 +22,8 @@
internal let _CR: UInt8 = 0x0d
internal let _LF: UInt8 = 0x0a
import SwiftShims
extension String {
/// A view of a string's contents as a collection of characters.
///
@@ -316,29 +318,34 @@ extension String.CharacterView : BidirectionalCollection {
internal func _measureExtendedGraphemeClusterForward(
from start: UnicodeScalarView.Index
) -> Int {
var start = start
let end = unicodeScalars.endIndex
if start == end {
return 0
}
// Our relative position (offset). If our _core is not a substring, this is
// the same as start._position.
let relativeOffset = start._position - _coreOffset
// Grapheme breaking is much simpler if known ASCII
if _core.isASCII {
_onFastPath() // Please aggressively inline
let asciiBuffer = _core.asciiBuffer._unsafelyUnwrappedUnchecked
let pos = start._position - _coreOffset
// With the exception of CR-LF, ASCII graphemes are single-scalar. Check
// for that one exception.
if _slowPath(
asciiBuffer[pos] == _CR &&
pos+1 < asciiBuffer.endIndex &&
asciiBuffer[pos+1] == _LF
asciiBuffer[relativeOffset] == _CR &&
relativeOffset+1 < asciiBuffer.endIndex &&
asciiBuffer[relativeOffset+1] == _LF
) {
return 2
}
return 1
} else {
// TODO: Check for (potentially non-contiguous) ASCII NSStrings,
// especially small tagged pointers.
}
let startIndexUTF16 = start._position
@@ -350,15 +357,49 @@ extension String.CharacterView : BidirectionalCollection {
// Perform a quick single-code-unit grapheme check
if _core._baseAddress != nil {
let pos = start._position - _coreOffset
if String.CharacterView._quickCheckGraphemeBreakBetween(
_core._nthContiguous(pos),
_core._nthContiguous(pos+1)
_core._nthContiguous(relativeOffset),
_core._nthContiguous(relativeOffset+1)
) {
return 1
}
} else {
// TODO: Check for (potentially non-contiguous) UTF16 NSStrings,
// especially small tagged pointers
}
if _core._baseAddress != nil {
_onFastPath() // Please aggressively inline
let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: _core)
let ubrkFollowing = __swift_stdlib_ubrk_following(
breakIterator, Int32(relativeOffset)
)
// ubrk_following may return UBRK_DONE (-1). Treat that as the rest of the
// string.
let nextPosition =
ubrkFollowing == -1 ? end._position : Int(ubrkFollowing)
return nextPosition - relativeOffset
} else {
// TODO: See if we can get fast character contents.
}
// FIXME: Need to handle the general case correctly with Unicode 9+
// semantics, as opposed to this legacy Unicode 8 path. This gets hit for
// e.g. non-contiguous NSStrings. In such cases, there may be an alternative
// CFString API available, or worst case we can map over it via UTextFuncs.
return legacyGraphemeForward(
start: start, end: end, startIndexUTF16: startIndexUTF16
)
}
@inline(never)
func legacyGraphemeForward(
start: UnicodeScalarView.Index,
end: UnicodeScalarView.Index,
startIndexUTF16: Int
) -> Int {
var start = start
let graphemeClusterBreakProperty =
_UnicodeGraphemeClusterBreakPropertyTrie()
let segmenter = _UnicodeExtendedGraphemeClusterSegmenter()
@@ -400,21 +441,25 @@ extension String.CharacterView : BidirectionalCollection {
return 0
}
// The relative position (offset) to the last code unit.
let lastOffset = end._position - _coreOffset - 1
// The relative position (offset) that is one-past-the-last
let endOffset = lastOffset + 1
// Grapheme breaking is much simpler if known ASCII
if _core.isASCII {
_onFastPath() // Please aggressively inline
let asciiBuffer = _core.asciiBuffer._unsafelyUnwrappedUnchecked
let pos = end._position - _coreOffset - 1
_sanityCheck(
pos >= asciiBuffer.startIndex,
lastOffset >= asciiBuffer.startIndex,
"should of been caught in earlier start-of-scalars check")
// With the exception of CR-LF, ASCII graphemes are single-scalar. Check
// for that one exception.
if _slowPath(
asciiBuffer[pos] == _LF &&
pos-1 >= asciiBuffer.startIndex &&
asciiBuffer[pos-1] == _CR
asciiBuffer[lastOffset] == _LF &&
lastOffset-1 >= asciiBuffer.startIndex &&
asciiBuffer[lastOffset-1] == _CR
) {
return 2
}
@@ -431,15 +476,45 @@ extension String.CharacterView : BidirectionalCollection {
// Perform a quick single-code-unit grapheme check
if _core._baseAddress != nil {
let pos = end._position - _coreOffset - 1
if String.CharacterView._quickCheckGraphemeBreakBetween(
_core._nthContiguous(pos-1),
_core._nthContiguous(pos)
_core._nthContiguous(lastOffset-1),
_core._nthContiguous(lastOffset)
) {
return 1
}
}
if _core._baseAddress != nil {
_onFastPath() // Please aggressively inline
let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: _core)
let ubrkPreceding = __swift_stdlib_ubrk_preceding(
breakIterator, Int32(endOffset)
)
// ubrk_following may return UBRK_DONE (-1). Treat that as the rest of the
// string.
let priorPosition =
ubrkPreceding == -1 ? start._position : Int(ubrkPreceding)
return endOffset - priorPosition
} else {
// TODO: See if we can get fast character contents.
}
// FIXME: Need to handle the general case correctly with Unicode 9+
// semantics, as opposed to this legacy Unicode 8 path. This gets hit for
// e.g. non-contiguous NSStrings. In such cases, there may be an alternative
// CFString API available, or worst case we can map over it via UTextFuncs.
return legacyGraphemeBackward(
start: start, end: end, endIndexUTF16: endIndexUTF16
)
}
@inline(never)
func legacyGraphemeBackward(
start: UnicodeScalarView.Index,
end: UnicodeScalarView.Index,
endIndexUTF16: Int
) -> Int {
let graphemeClusterBreakProperty =
_UnicodeGraphemeClusterBreakPropertyTrie()
let segmenter = _UnicodeExtendedGraphemeClusterSegmenter()

View File

@@ -0,0 +1,153 @@
import SwiftShims
// For testing purposes, a thread-safe counter to guarantee that destructors get
// called by pthread.
#if INTERNAL_CHECKS_ENABLED
public // @testable
let _destroyTLSCounter = _stdlib_AtomicInt()
#endif
// Thread local storage for all of the Swift standard library
//
// @moveonly/@pointeronly: shouldn't be used as a value, only through its
// pointer. Similarly, shouldn't be created, except by
// _initializeThreadLocalStorage.
//
internal struct _ThreadLocalStorage {
// TODO: might be best to absract uBreakIterator handling and caching into
// separate struct. That would also make it easier to maintain multiple ones
// and other TLS entries side-by-side.
// Save a pre-allocated UBreakIterator, as they are very expensive to set up.
// Each thread can reuse their unique break iterator, being careful to reset
// the text when it has changed (see below). Even with a naive always-reset
// policy, grapheme breaking is 30x faster when using a pre-allocated
// UBreakIterator than recreating one.
//
// private
var uBreakIterator: OpaquePointer
// TODO: Consider saving two, e.g. for character-by-character comparison
// The below cache key tries to avoid resetting uBreakIterator's text when
// operating on the same String as before. Avoiding the reset gives a 50%
// speedup on grapheme breaking.
//
// As a invalidation check, save the base address from the last used
// StringCore. We can skip resetting the uBreakIterator's text when operating
// on a given StringCore when both of these associated references/pointers are
// equal to the StringCore's. Note that the owner is weak, to force it to
// compare unequal if a new StringCore happens to be created in the same
// memory.
//
// private
weak var associatedStringOwner: AnyObject? = nil
// private
var associatedBaseAddress: UnsafeMutableRawPointer? = nil
// private
var associatedCountAndFlags: UInt = 0
// private: Should only be called by _initializeThreadLocalStorage
init(_uBreakIterator: OpaquePointer) {
self.uBreakIterator = _uBreakIterator
}
// Get the current thread's TLS pointer. On first call for a given thread,
// creates and initializes a new one.
static internal func getPointer()
-> UnsafeMutablePointer<_ThreadLocalStorage>
{
let tlsRawPtr = _swift_stdlib_pthread_getspecific(_tlsKey)
if _fastPath(tlsRawPtr != nil) {
return tlsRawPtr._unsafelyUnwrappedUnchecked.assumingMemoryBound(
to: _ThreadLocalStorage.self)
}
return _initializeThreadLocalStorage()
}
// Retrieve our thread's local uBreakIterator and set it up for the given
// StringCore. Checks our TLS cache to avoid excess text resetting.
static internal func getUBreakIterator(
for core: _StringCore
) -> OpaquePointer {
let tlsPtr = getPointer()
let brkIter = tlsPtr[0].uBreakIterator
_sanityCheck(core._owner != nil || core._baseAddress != nil,
"invalid StringCore")
// Check if we must reset the text
if tlsPtr[0].associatedStringOwner !== core._owner
|| tlsPtr[0].associatedBaseAddress != core._baseAddress
|| tlsPtr[0].associatedCountAndFlags != core._countAndFlags
{
// cache miss
var err = __swift_stdlib_U_ZERO_ERROR
let corePtr: UnsafeMutablePointer<UTF16.CodeUnit>
corePtr = core.startUTF16
__swift_stdlib_ubrk_setText(brkIter, corePtr, Int32(core.count), &err)
_precondition(err.isSuccess, "unexpected ubrk_setUText failure")
tlsPtr[0].associatedStringOwner = core._owner
tlsPtr[0].associatedBaseAddress = core._baseAddress
tlsPtr[0].associatedCountAndFlags = core._countAndFlags
}
return brkIter
}
}
// Destructor to register with pthreads. Responsible for deallocating any memory
// owned.
internal func _destroyTLS(_ ptr: UnsafeMutableRawPointer?) {
_sanityCheck(ptr != nil,
"_destroyTLS was called, but with nil...")
let tlsPtr = ptr!.assumingMemoryBound(to: _ThreadLocalStorage.self)
__swift_stdlib_ubrk_close(tlsPtr[0].uBreakIterator)
tlsPtr[0].associatedStringOwner = nil
tlsPtr[0].associatedBaseAddress = nil
tlsPtr.deinitialize(count: 1)
tlsPtr.deallocate(capacity: 1)
#if INTERNAL_CHECKS_ENABLED
// Log the fact we've destroyed our storage
_destroyTLSCounter.fetchAndAdd(1)
#endif
}
// Lazily created global key for use with pthread TLS
internal let _tlsKey: __swift_pthread_key_t = {
let sentinelValue = __swift_pthread_key_t.max
var key: __swift_pthread_key_t = sentinelValue
let success = _swift_stdlib_pthread_key_create(&key, _destroyTLS)
_sanityCheck(success == 0, "somehow failed to create TLS key")
_sanityCheck(key != sentinelValue, "Didn't make a new key")
return key
}()
@inline(never)
internal func _initializeThreadLocalStorage()
-> UnsafeMutablePointer<_ThreadLocalStorage>
{
_sanityCheck(_swift_stdlib_pthread_getspecific(_tlsKey) == nil,
"already initialized")
// Create and initialize one.
var err = __swift_stdlib_U_ZERO_ERROR
let newUBreakIterator = __swift_stdlib_ubrk_open(
/*type:*/ __swift_stdlib_UBRK_CHARACTER, /*locale:*/ nil,
/*text:*/ nil, /*textLength:*/ 0, /*status:*/ &err)
_precondition(err.isSuccess, "unexpected ubrk_open failure")
let tlsPtr: UnsafeMutablePointer<_ThreadLocalStorage>
= UnsafeMutablePointer<_ThreadLocalStorage>.allocate(
capacity: 1
)
tlsPtr.initialize(
to: _ThreadLocalStorage(_uBreakIterator: newUBreakIterator)
)
let success = _swift_stdlib_pthread_setspecific(_tlsKey, tlsPtr)
_sanityCheck(success == 0, "setspecific failed")
return tlsPtr
}

View File

@@ -18,6 +18,8 @@
#else
#include <unistd.h>
#endif
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -96,6 +98,35 @@ int swift::_swift_stdlib_close(int fd) {
#endif
}
// Guard compilation on the typedef for __swift_pthread_key_t in LibcShims.h
// being identical to the platform's pthread_key_t
static_assert(std::is_same<__swift_pthread_key_t, pthread_key_t>::value,
"This platform's pthread_key_t differs. If you hit this assert, "
"fix __swift_pthread_key_t's typedef in LibcShims.h by adding an "
"#if guard and definition for your platform");
SWIFT_RUNTIME_STDLIB_INTERFACE
int swift::_swift_stdlib_pthread_key_create(
__swift_pthread_key_t * _Nonnull key,
void (* _Nullable destructor)(void *)
) {
return pthread_key_create(key, destructor);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
void * _Nullable swift::_swift_stdlib_pthread_getspecific(
__swift_pthread_key_t key
) {
return pthread_getspecific(key);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
int swift::_swift_stdlib_pthread_setspecific(
__swift_pthread_key_t key, const void * _Nullable value
) {
return pthread_setspecific(key, value);
}
#if defined(__APPLE__)
#include <malloc/malloc.h>
SWIFT_RUNTIME_STDLIB_INTERFACE

View File

@@ -14,6 +14,8 @@
//
//===----------------------------------------------------------------------===//
#include "../SwiftShims/UnicodeShims.h"
#if !defined(__APPLE__)
#include "swift/Basic/Lazy.h"
#include "swift/Runtime/Config.h"
@@ -30,11 +32,10 @@
#include <unicode/ucol.h>
#include <unicode/ucoleitr.h>
#include <unicode/uiter.h>
#include <unicode/ubrk.h>
#pragma clang diagnostic pop
#include "../SwiftShims/UnicodeShims.h"
static const UCollator *MakeRootCollator() {
UErrorCode ErrorCode = U_ZERO_ERROR;
UCollator *root = ucol_open("", &ErrorCode);
@@ -291,3 +292,60 @@ swift::_swift_stdlib_unicode_strToLower(uint16_t *Destination,
swift::Lazy<ASCIICollation> ASCIICollation::theTable;
#endif
namespace {
template <typename T, typename U> T *ptr_cast(U *p) {
return static_cast<T *>(static_cast<void *>(p));
}
template <typename T, typename U> const T *ptr_cast(const U *p) {
return static_cast<const T *>(static_cast<const void *>(p));
}
}
#if defined(__APPLE__)
#include <stdint.h>
extern "C" {
// Declare a few external functions to avoid a dependency on ICU headers.
typedef struct UBreakIterator UBreakIterator;
typedef enum UBreakIteratorType {} UBreakIteratorType;
typedef enum UErrorCode {} UErrorCode;
typedef uint16_t UChar;
void ubrk_close(UBreakIterator *);
UBreakIterator *ubrk_open(UBreakIteratorType, const char *, const UChar *,
int32_t, UErrorCode *);
int32_t ubrk_preceding(UBreakIterator *, int32_t);
int32_t ubrk_following(UBreakIterator *, int32_t);
void ubrk_setText(UBreakIterator *, const UChar *, int32_t, UErrorCode *);
}
#endif // defined(__APPLE__)
void swift::__swift_stdlib_ubrk_close(
swift::__swift_stdlib_UBreakIterator *bi) {
ubrk_close(ptr_cast<UBreakIterator>(bi));
}
swift::__swift_stdlib_UBreakIterator *swift::__swift_stdlib_ubrk_open(
swift::__swift_stdlib_UBreakIteratorType type, const char *locale,
const UChar *text, int32_t textLength, __swift_stdlib_UErrorCode *status) {
return ptr_cast<swift::__swift_stdlib_UBreakIterator>(
ubrk_open(static_cast<UBreakIteratorType>(type), locale, text, textLength,
ptr_cast<UErrorCode>(status)));
}
int32_t
swift::__swift_stdlib_ubrk_preceding(swift::__swift_stdlib_UBreakIterator *bi,
int32_t offset) {
return ubrk_preceding(ptr_cast<UBreakIterator>(bi), offset);
}
int32_t
swift::__swift_stdlib_ubrk_following(swift::__swift_stdlib_UBreakIterator *bi,
int32_t offset) {
return ubrk_following(ptr_cast<UBreakIterator>(bi), offset);
}
void swift::__swift_stdlib_ubrk_setText(
swift::__swift_stdlib_UBreakIterator *bi, const __swift_stdlib_UChar *text,
__swift_int32_t textLength, __swift_stdlib_UErrorCode *status) {
return ubrk_setText(ptr_cast<UBreakIterator>(bi), ptr_cast<UChar>(text),
textLength, ptr_cast<UErrorCode>(status));
}

View File

@@ -89,6 +89,7 @@ func violationWithGenericType<T>(_ p: T) {
takesTwoInouts(&local, &local)
}
// Helper.
struct StructWithTwoStoredProp {
var f1: Int
@@ -106,3 +107,74 @@ func violationWithUnsafePointer(_ s: inout StructWithTwoStoredProp) {
_ = s.f2
}
}
// Tests for Fix-Its to replace swap(&collection[a], &collection[b]) with
// collection.swapAt(a, b)
struct StructWithField {
var f = 12
}
struct StructWithFixits {
var arrayProp: [Int] = [1, 2, 3]
var dictionaryProp: [Int : Int] = [0 : 10, 1 : 11]
mutating
func shouldHaveFixIts<T>(_ i: Int, _ j: Int, _ param: T, _ paramIndex: T.Index) where T : MutableCollection {
var array1 = [1, 2, 3]
// expected-error@+2{{simultaneous accesses}}{{5-41=array1.swapAt(i + 5, j - 2)}}
// expected-note@+1{{conflicting access is here}}
swap(&array1[i + 5], &array1[j - 2])
// expected-error@+2{{simultaneous accesses}}{{5-49=self.arrayProp.swapAt(i, j)}}
// expected-note@+1{{conflicting access is here}}
swap(&self.arrayProp[i], &self.arrayProp[j])
var localOfGenericType = param
// expected-error@+2{{simultaneous accesses}}{{5-75=localOfGenericType.swapAt(paramIndex, paramIndex)}}
// expected-note@+1{{conflicting access is here}}
swap(&localOfGenericType[paramIndex], &localOfGenericType[paramIndex])
}
mutating
func shouldHaveNoFixIts(_ i: Int, _ j: Int) {
var s = StructWithField()
// expected-error@+2{{simultaneous accesses}}{{none}}
// expected-note@+1{{conflicting access is here}}
swap(&s.f, &s.f)
var array1 = [1, 2, 3]
var array2 = [1, 2, 3]
// Swapping between different arrays should cannot have the
// Fix-It.
swap(&array1[i], &array2[j]) // no-warning no-fixit
swap(&array1[i], &self.arrayProp[j]) // no-warning no-fixit
// Dictionaries aren't MutableCollections so don't support swapAt().
// expected-error@+2{{simultaneous accesses}}{{none}}
// expected-note@+1{{conflicting access is here}}
swap(&dictionaryProp[i], &dictionaryProp[j])
// We could safely Fix-It this but don't now because the left and
// right bases are not textually identical.
// expected-error@+2{{simultaneous accesses}}{{none}}
// expected-note@+1{{conflicting access is here}}
swap(&self.arrayProp[i], &arrayProp[j])
// We could safely Fix-It this but we're not that heroic.
// We don't suppress when swap() is used as a value
let mySwap: (inout Int, inout Int) -> () = swap
// expected-error@+2{{simultaneous accesses}}{{none}}
// expected-note@+1{{conflicting access is here}}
mySwap(&array1[i], &array1[j])
func myOtherSwap<T>(_ a: inout T, _ b: inout T) {
swap(&a, &b) // no-warning
}
// expected-error@+2{{simultaneous accesses}}{{none}}
// expected-note@+1{{conflicting access is here}}
mySwap(&array1[i], &array1[j])
}
}

View File

@@ -1,39 +0,0 @@
// RUN: %target-swift-frontend -enforce-exclusivity=checked -suppress-static-exclusivity-swap -emit-sil -primary-file %s -o /dev/null -verify
import Swift
func takesTwoInouts(_ p1: inout Int, _ p2: inout Int) { }
func swapSuppression(_ i: Int, _ j: Int) {
var a: [Int] = [1, 2, 3]
swap(&a[i], &a[j]) // no-warning
// expected-warning@+2{{simultaneous accesses to var 'a', but modification requires exclusive access; consider copying to a local variable}}
// expected-note@+1{{conflicting access is here}}
takesTwoInouts(&a[i], &a[j])
}
func missedSwapSuppression(_ i: Int, _ j: Int) {
var a: [Int] = [1, 2, 3]
// We don't suppress when swap() is used as a value
let mySwap: (inout Int, inout Int) -> () = swap
// expected-warning@+2{{simultaneous accesses to var 'a', but modification requires exclusive access; consider copying to a local variable}}
// expected-note@+1{{conflicting access is here}}
mySwap(&a[i], &a[j])
}
func dontSuppressUserSwap(_ i: Int, _ j: Int) {
var a: [Int] = [1, 2, 3]
// Don't suppress on user-defined swap.
func swap<T>(_ p1: inout T, _ p2: inout T) {
return (p1, p2) = (p2, p1)
}
// expected-warning@+2{{simultaneous accesses to var 'a', but modification requires exclusive access; consider copying to a local variable}}
// expected-note@+1{{conflicting access is here}}
swap(&a[i], &a[j])
}

View File

@@ -196,7 +196,24 @@ CharacterTests.test("CR-LF") {
let finalAlphaCharacters = unicodeAlphabetString.characters[unicodeAlphabetString.characters.index(unicodeAlphabetString.characters.endIndex, offsetBy: -3)..<unicodeAlphabetString.characters.endIndex]
expectEqualSequence(finalAlphaCharacters, unicodeAlphabetString_final.characters)
expectEqualSequence(finalAlphaCharacters.reversed(), unicodeAlphabetString_final_rev.characters)
}
CharacterTests.test("Unicode 9 grapheme breaking") {
// Only run it on ObjC platforms. Supported Linux versions do not have a
// recent enough ICU for Unicode 9 support.
#if _runtime(_ObjC)
let flags = "🇺🇸🇨🇦🇩🇰🏳️‍🌈"
expectEqual(4, flags.count)
expectEqual(flags.reversed().count, flags.count)
let family = "👪👨‍👧‍👧👩‍👩‍👧‍👦👨‍👨‍👦‍👦👨‍👧👩‍👦‍👦"
expectEqual(6, family.count)
expectEqual(family.reversed().count, family.count)
let skinTone = "👋👋🏻👋🏼👋🏽👋🏾👋🏿"
expectEqual(6, skinTone.count)
expectEqual(skinTone.reversed().count, skinTone.count)
#endif
}
/// Test that a given `String` can be transformed into a `Character` and back

View File

@@ -0,0 +1,40 @@
// RUN: %target-run-stdlib-swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
import StdlibUnittest
import Swift
import SwiftPrivate
import Darwin
var str = "Lorem ipsum dolor sit amet\r\n 🌎 🇺🇸🇨🇦🍁"
func checkString(_unused: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
expectEqual(str.count, str.reversed().count)
return nil
}
var PThreadTests = TestSuite("Thread Local Storage")
// Test that the destructor for our TLS is invoked
PThreadTests.test("destructor") {
#if INTERNAL_CHECKS_ENABLED
let numIters = 100
for _ in 0..<numIters {
var thread : pthread_t? = nil
guard pthread_create(&thread, nil, checkString, &thread) == 0 else {
fatalError("pthread_create failed")
}
guard pthread_join(thread!, nil) == 0 else {
fatalError("pthread_join failed")
}
}
expectEqual(numIters, _destroyTLSCounter.load())
#endif
var x = 1
checkString(_unused: &x)
}
runAllTests()

View File

@@ -414,10 +414,10 @@
÷ D800 ÷ 0308 ÷ D800 ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <surrogate-D800> (Control) ÷ [0.3]
÷ 0061 ÷ 1F1E6 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3]
÷ 1F1F7 × 1F1FA ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER R (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER U (Regional_Indicator) ÷ [0.3]
÷ 1F1F7 × 1F1FA × 1F1F8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER R (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER U (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER S (Regional_Indicator) ÷ [0.3]
÷ 1F1F7 × 1F1FA × 1F1F8 × 1F1EA ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER R (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER U (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER S (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER E (Regional_Indicator) ÷ [0.3]
# NOTE: disabled because Unicode 9.0. TODO: splat in proper file here. Original: ÷ 1F1F7 × 1F1FA × 1F1F8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER R (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER U (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER S (Regional_Indicator) ÷ [0.3]
# NOTE: disabled because Unicode 9.0. TODO: splat in proper file here. Original: ÷ 1F1F7 × 1F1FA × 1F1F8 × 1F1EA ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER R (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER U (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER S (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER E (Regional_Indicator) ÷ [0.3]
÷ 1F1F7 × 1F1FA ÷ 200B ÷ 1F1F8 × 1F1EA ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER R (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER U (Regional_Indicator) ÷ [5.0] ZERO WIDTH SPACE (Control) ÷ [4.0] REGIONAL INDICATOR SYMBOL LETTER S (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER E (Regional_Indicator) ÷ [0.3]
÷ 1F1E6 × 1F1E7 × 1F1E8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER B (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER C (Regional_Indicator) ÷ [0.3]
# NOTE: disabled because Unicode 9.0. TODO: splat in proper file here. Original: ÷ 1F1E6 × 1F1E7 × 1F1E8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER B (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER C (Regional_Indicator) ÷ [0.3]
÷ 1F1E6 × 200D ÷ 1F1E7 × 1F1E8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER B (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER C (Regional_Indicator) ÷ [0.3]
÷ 1F1E6 × 1F1E7 × 200D ÷ 1F1E8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (Regional_Indicator) × [8.1] REGIONAL INDICATOR SYMBOL LETTER B (Regional_Indicator) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (Regional_Indicator) ÷ [0.3]
÷ 0020 × 200D ÷ 0646 ÷ # ÷ [0.2] SPACE (Other) × [9.0] ZERO WIDTH JOINER (Extend) ÷ [999.0] ARABIC LETTER NOON (Other) ÷ [0.3]