Merge pull request #15040 from ikesyo/gardening-not-empty
[gardening] Use `!empty()` over `size() > 0`
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index 96c7f80..99a927d 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -396,7 +396,7 @@
type-list ::= empty-list
// FIXME: Consider replacing 'h' with a two-char code
- list-type ::= type identifier? 'z'? 'h'? 'd'? // type with optional label, inout convention, shared convention, and variadic specifier
+ list-type ::= type identifier? 'z'? 'h'? 'n'? 'd'? // type with optional label, inout convention, shared convention, owned convention, and variadic specifier
METATYPE-REPR ::= 't' // Thin metatype representation
METATYPE-REPR ::= 'T' // Thick metatype representation
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index eb400b9..3226c5e 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -644,11 +644,7 @@
template <typename int_type>
class TargetParameterTypeFlags {
- enum : int_type {
- InOutMask = 1 << 0,
- SharedMask = 1 << 1,
- VariadicMask = 1 << 2,
- };
+ enum : int_type { ValueOwnershipMask = 0x7F, VariadicMask = 0x80 };
int_type Data;
constexpr TargetParameterTypeFlags(int_type Data) : Data(Data) {}
@@ -656,14 +652,10 @@
public:
constexpr TargetParameterTypeFlags() : Data(0) {}
- constexpr TargetParameterTypeFlags<int_type> withInOut(bool isInOut) const {
- return TargetParameterTypeFlags<int_type>((Data & ~InOutMask) |
- (isInOut ? InOutMask : 0));
- }
-
- constexpr TargetParameterTypeFlags<int_type> withShared(bool isShared) const {
- return TargetParameterTypeFlags<int_type>((Data & ~SharedMask) |
- (isShared ? SharedMask : 0));
+ constexpr TargetParameterTypeFlags<int_type>
+ withValueOwnership(ValueOwnership ownership) const {
+ return TargetParameterTypeFlags<int_type>((Data & ~ValueOwnershipMask) |
+ (int_type)ownership);
}
constexpr TargetParameterTypeFlags<int_type>
@@ -673,10 +665,12 @@
}
bool isNone() const { return Data == 0; }
- bool isInOut() const { return Data & InOutMask; }
- bool isShared() const { return Data & SharedMask; }
bool isVariadic() const { return Data & VariadicMask; }
+ ValueOwnership getValueOwnership() const {
+ return (ValueOwnership)(Data & ValueOwnershipMask);
+ }
+
int_type getIntValue() const { return Data; }
static TargetParameterTypeFlags<int_type> fromIntValue(int_type Data) {
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index c974d92..938f651 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -316,14 +316,14 @@
StorageKind : 4
);
- SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+2+1+1+1,
+ SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+4+1+1+1,
/// \brief Whether this property is a type property (currently unfortunately
/// called 'static').
IsStatic : 1,
/// \brief The specifier associated with this variable or parameter. This
/// determines the storage semantics of the value e.g. mutability.
- Specifier : 2,
+ Specifier : 4,
/// \brief Whether this declaration was an element of a capture list.
IsCaptureList : 1,
@@ -4445,17 +4445,18 @@
public:
enum class Specifier : uint8_t {
// For Var Decls
-
- Let = 0,
- Var = 1,
-
+
+ Let = 0,
+ Var = 1,
+
// For Param Decls
-
- Owned = Let,
+
+ Default = Let,
InOut = 2,
Shared = 3,
+ Owned = 4,
};
-
+
protected:
llvm::PointerUnion<PatternBindingDecl*, Stmt*> ParentPattern;
@@ -4602,10 +4603,23 @@
/// \returns the way 'static'/'class' should be spelled for this declaration.
StaticSpellingKind getCorrectStaticSpelling() const;
+ bool isImmutable() const {
+ switch (getSpecifier()) {
+ case Specifier::Let:
+ case Specifier::Shared:
+ case Specifier::Owned:
+ return true;
+ case Specifier::Var:
+ case Specifier::InOut:
+ return false;
+ }
+ }
/// Is this an immutable 'let' property?
bool isLet() const { return getSpecifier() == Specifier::Let; }
/// Is this an immutable 'shared' property?
bool isShared() const { return getSpecifier() == Specifier::Shared; }
+ /// Is this an immutable 'owned' property?
+ bool isOwned() const { return getSpecifier() == Specifier::Owned; }
ValueOwnership getValueOwnership() const {
switch (getSpecifier()) {
@@ -4617,6 +4631,8 @@
return ValueOwnership::InOut;
case Specifier::Shared:
return ValueOwnership::Shared;
+ case Specifier::Owned:
+ return ValueOwnership::Owned;
}
}
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index c176e11..52d3320 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -855,8 +855,8 @@
"only a single variadic parameter '...' is permitted", ())
ERROR(parameter_vararg_default,none,
"variadic parameter cannot have a default value", ())
-ERROR(inout_as_attr_disallowed,none,
- "%0 before a parameter name is not allowed, place it before the parameter type instead",
+ERROR(parameter_specifier_as_attr_disallowed,none,
+ "'%0' before a parameter name is not allowed, place it before the parameter type instead",
(StringRef))
ERROR(parameter_specifier_repeated,none,
"parameter must not have multiple '__owned', 'inout', '__shared',"
diff --git a/include/swift/AST/Ownership.h b/include/swift/AST/Ownership.h
index 2d8f3de..a3dbfe5 100644
--- a/include/swift/AST/Ownership.h
+++ b/include/swift/AST/Ownership.h
@@ -42,12 +42,15 @@
/// Different kinds of value ownership supported by Swift.
enum class ValueOwnership : uint8_t {
- /// \brief the default ownership (owned)
+ /// \brief the context-dependent default ownership (sometimes shared,
+ /// sometimes owned)
Default,
/// \brief an 'inout' mutating pointer-like value
InOut,
/// \brief a '__shared' non-mutating pointer-like value
- Shared
+ Shared,
+ /// \brief an '__owned' value
+ Owned
};
} // end namespace swift
diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h
index 0d6c6b0..b731336 100644
--- a/include/swift/AST/TypeRepr.h
+++ b/include/swift/AST/TypeRepr.h
@@ -901,8 +901,9 @@
SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
static bool classof(const TypeRepr *T) {
- return T->getKind() == TypeReprKind::InOut
- || T->getKind() == TypeReprKind::Shared;
+ return T->getKind() == TypeReprKind::InOut ||
+ T->getKind() == TypeReprKind::Shared ||
+ T->getKind() == TypeReprKind::Owned;
}
static bool classof(const SpecifierTypeRepr *T) { return true; }
@@ -943,6 +944,20 @@
static bool classof(const SharedTypeRepr *T) { return true; }
};
+/// \brief A 'owned' type.
+/// \code
+/// x : owned Int
+/// \endcode
+class OwnedTypeRepr : public SpecifierTypeRepr {
+public:
+ OwnedTypeRepr(TypeRepr *Base, SourceLoc OwnedLoc)
+ : SpecifierTypeRepr(TypeReprKind::Owned, Base, OwnedLoc) {}
+
+ static bool classof(const TypeRepr *T) {
+ return T->getKind() == TypeReprKind::Owned;
+ }
+ static bool classof(const OwnedTypeRepr *T) { return true; }
+};
/// \brief A TypeRepr for a known, fixed type.
///
@@ -1080,6 +1095,7 @@
case TypeReprKind::Array:
case TypeReprKind::SILBox:
case TypeReprKind::Shared:
+ case TypeReprKind::Owned:
return true;
}
llvm_unreachable("bad TypeRepr kind");
diff --git a/include/swift/AST/TypeReprNodes.def b/include/swift/AST/TypeReprNodes.def
index a664e4c..f5ebe09 100644
--- a/include/swift/AST/TypeReprNodes.def
+++ b/include/swift/AST/TypeReprNodes.def
@@ -56,6 +56,7 @@
ABSTRACT_TYPEREPR(Specifier, TypeRepr)
TYPEREPR(InOut, SpecifierTypeRepr)
TYPEREPR(Shared, SpecifierTypeRepr)
+ TYPEREPR(Owned, SpecifierTypeRepr)
TYPEREPR(Fixed, TypeRepr)
TYPEREPR(SILBox, TypeRepr)
LAST_TYPEREPR(SILBox)
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 4b5324b..b57ee74 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -1580,8 +1580,9 @@
Escaping = 1 << 2,
InOut = 1 << 3,
Shared = 1 << 4,
+ Owned = 1 << 5,
- NumBits = 5
+ NumBits = 6
};
OptionSet<ParameterFlags> value;
static_assert(NumBits < 8*sizeof(OptionSet<ParameterFlags>), "overflowed");
@@ -1599,7 +1600,8 @@
: value((variadic ? Variadic : 0) | (autoclosure ? AutoClosure : 0) |
(escaping ? Escaping : 0) |
(ownership == ValueOwnership::InOut ? InOut : 0) |
- (ownership == ValueOwnership::Shared ? Shared : 0)) {}
+ (ownership == ValueOwnership::Shared ? Shared : 0) |
+ (ownership == ValueOwnership::Owned ? Owned : 0)) {}
/// Create one from what's present in the parameter type
inline static ParameterTypeFlags
@@ -1611,12 +1613,15 @@
bool isEscaping() const { return value.contains(Escaping); }
bool isInOut() const { return value.contains(InOut); }
bool isShared() const { return value.contains(Shared); }
+ bool isOwned() const { return value.contains(Owned); }
ValueOwnership getValueOwnership() const {
if (isInOut())
return ValueOwnership::InOut;
else if (isShared())
return ValueOwnership::Shared;
+ else if (isOwned())
+ return ValueOwnership::Owned;
return ValueOwnership::Default;
}
@@ -1641,6 +1646,11 @@
: value - ParameterTypeFlags::Shared);
}
+ ParameterTypeFlags withOwned(bool isOwned) const {
+ return ParameterTypeFlags(isOwned ? value | ParameterTypeFlags::Owned
+ : value - ParameterTypeFlags::Owned);
+ }
+
bool operator ==(const ParameterTypeFlags &other) const {
return value.toRaw() == other.value.toRaw();
}
@@ -2530,6 +2540,9 @@
/// Whether the parameter is marked 'shared'
bool isShared() const { return Flags.isShared(); }
+
+ /// Whether the parameter is marked 'owned'
+ bool isOwned() const { return Flags.isOwned(); }
};
class CanParam : public Param {
diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def
index 845b16d..d209d38 100644
--- a/include/swift/Demangling/DemangleNodes.def
+++ b/include/swift/Demangling/DemangleNodes.def
@@ -150,6 +150,7 @@
NODE(RetroactiveConformance)
NODE(ReturnType)
NODE(Shared)
+NODE(Owned)
NODE(SILBoxType)
NODE(SILBoxTypeWithLayout)
NODE(SILBoxLayout)
diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h
index d2bd7dd..a98fab4 100644
--- a/include/swift/Demangling/TypeDecoder.h
+++ b/include/swift/Demangling/TypeDecoder.h
@@ -56,8 +56,9 @@
void setType(BuiltType type) { Type = type; }
void setVariadic() { Flags = Flags.withVariadic(true); }
- void setShared() { Flags = Flags.withShared(true); }
- void setInOut() { Flags = Flags.withInOut(true); }
+ void setValueOwnership(ValueOwnership ownership) {
+ Flags = Flags.withValueOwnership(ownership);
+ }
void setFlags(ParameterFlags flags) { Flags = flags; };
FunctionParam withLabel(StringRef label) const {
@@ -531,17 +532,23 @@
[&](const Demangle::NodePointer &typeNode,
FunctionParam<BuiltType> ¶m) -> bool {
Demangle::NodePointer node = typeNode;
- switch (node->getKind()) {
- case NodeKind::InOut:
- param.setInOut();
+
+ auto setOwnership = [&](ValueOwnership ownership) {
+ param.setValueOwnership(ownership);
node = node->getFirstChild();
hasParamFlags = true;
+ };
+ switch (node->getKind()) {
+ case NodeKind::InOut:
+ setOwnership(ValueOwnership::InOut);
break;
case NodeKind::Shared:
- param.setShared();
- hasParamFlags = true;
- node = node->getFirstChild();
+ setOwnership(ValueOwnership::Shared);
+ break;
+
+ case NodeKind::Owned:
+ setOwnership(ValueOwnership::Owned);
break;
default:
diff --git a/include/swift/Parse/Lexer.h b/include/swift/Parse/Lexer.h
index 3a9550f..90b544c 100644
--- a/include/swift/Parse/Lexer.h
+++ b/include/swift/Parse/Lexer.h
@@ -64,8 +64,8 @@
class Lexer {
const LangOptions &LangOpts;
const SourceManager &SourceMgr;
- DiagnosticEngine *Diags;
const unsigned BufferID;
+ DiagnosticEngine *Diags;
using State = LexerState;
@@ -137,20 +137,18 @@
Lexer(const Lexer&) = delete;
void operator=(const Lexer&) = delete;
+ struct PrincipalTag {};
+
/// The principal constructor used by public constructors below.
/// Don't use this constructor for other purposes, it does not initialize
/// everything.
- Lexer(const LangOptions &Options,
- const SourceManager &SourceMgr, DiagnosticEngine *Diags,
- unsigned BufferID, bool InSILMode,
+ Lexer(const PrincipalTag &, const LangOptions &LangOpts,
+ const SourceManager &SourceMgr, unsigned BufferID,
+ DiagnosticEngine *Diags, bool InSILMode,
CommentRetentionMode RetainComments,
TriviaRetentionMode TriviaRetention);
- /// @{
- /// Helper routines used in \c Lexer constructors.
- void primeLexer();
- void initSubLexer(Lexer &Parent, State BeginState, State EndState);
- /// @}
+ void initialize(unsigned Offset, unsigned EndOffset);
public:
/// \brief Create a normal lexer that scans the whole source buffer.
@@ -166,31 +164,18 @@
/// means that APIs like getLocForEndOfToken really ought to take
/// this flag; it's just that we don't care that much about fidelity
/// when parsing SIL files.
- Lexer(const LangOptions &Options,
- const SourceManager &SourceMgr, unsigned BufferID,
- DiagnosticEngine *Diags, bool InSILMode,
- CommentRetentionMode RetainComments = CommentRetentionMode::None,
- TriviaRetentionMode TriviaRetention = TriviaRetentionMode::WithoutTrivia)
- : Lexer(Options, SourceMgr, Diags, BufferID, InSILMode, RetainComments,
- TriviaRetention) {
- primeLexer();
- }
+ Lexer(
+ const LangOptions &Options, const SourceManager &SourceMgr,
+ unsigned BufferID, DiagnosticEngine *Diags, bool InSILMode,
+ CommentRetentionMode RetainComments = CommentRetentionMode::None,
+ TriviaRetentionMode TriviaRetention = TriviaRetentionMode::WithoutTrivia);
/// \brief Create a lexer that scans a subrange of the source buffer.
- Lexer(const LangOptions &Options,
- const SourceManager &SourceMgr, unsigned BufferID,
- DiagnosticEngine *Diags, bool InSILMode,
+ Lexer(const LangOptions &Options, const SourceManager &SourceMgr,
+ unsigned BufferID, DiagnosticEngine *Diags, bool InSILMode,
CommentRetentionMode RetainComments,
- TriviaRetentionMode TriviaRetention,
- unsigned Offset, unsigned EndOffset)
- : Lexer(Options, SourceMgr, Diags, BufferID, InSILMode, RetainComments,
- TriviaRetention) {
- assert(Offset <= EndOffset && "invalid range");
- initSubLexer(
- *this,
- State(getLocForStartOfBuffer().getAdvancedLoc(Offset)),
- State(getLocForStartOfBuffer().getAdvancedLoc(EndOffset)));
- }
+ TriviaRetentionMode TriviaRetention, unsigned Offset,
+ unsigned EndOffset);
/// \brief Create a sub-lexer that lexes from the same buffer, but scans
/// a subrange of the buffer.
@@ -198,12 +183,7 @@
/// \param Parent the parent lexer that scans the whole buffer
/// \param BeginState start of the subrange
/// \param EndState end of the subrange
- Lexer(Lexer &Parent, State BeginState, State EndState)
- : Lexer(Parent.LangOpts, Parent.SourceMgr, Parent.Diags, Parent.BufferID,
- Parent.InSILMode, Parent.RetainComments,
- Parent.TriviaRetention) {
- initSubLexer(Parent, BeginState, EndState);
- }
+ Lexer(Lexer &Parent, State BeginState, State EndState);
/// \brief Returns true if this lexer will produce a code completion token.
bool isCodeCompletion() const {
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 599aec4..9759253 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -1005,7 +1005,7 @@
SourceLoc SpecifierLoc;
/// The parsed specifier kind, if present.
- VarDecl::Specifier SpecifierKind = VarDecl::Specifier::Owned;
+ VarDecl::Specifier SpecifierKind = VarDecl::Specifier::Default;
/// The location of the first name.
///
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 914a7f6..3c85170 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -2353,9 +2353,6 @@
Indices(indices),
IndexEquality{indicesEqual, indicesHash},
ComponentType(ComponentType) {
- assert(indices.empty() == !indicesEqual
- && indices.empty() == !indicesHash
- && "must have equals/hash functions iff there are indices");
}
KeyPathPatternComponent(AbstractStorageDecl *externalStorage,
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 7cd3c72..aada1b9 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -210,9 +210,10 @@
Var,
InOut,
Shared,
+ Owned,
};
-using VarDeclSpecifierField = BCFixed<2>;
-
+using VarDeclSpecifierField = BCFixed<3>;
+
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
enum class ParameterConvention : uint8_t {
@@ -325,6 +326,7 @@
Default = 0,
InOut,
Shared,
+ Owned
};
using ValueOwnershipField = BCFixed<2>;
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 88d4d15..f493842 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -950,12 +950,23 @@
PrintWithColorRAII(OS, InterfaceTypeColor) << "'";
}
- if (P->getSpecifier() == VarDecl::Specifier::Var)
+ switch (P->getSpecifier()) {
+ case VarDecl::Specifier::Let:
+ /* nothing */
+ break;
+ case VarDecl::Specifier::Var:
OS << " mutable";
- if (P->getSpecifier() == VarDecl::Specifier::InOut)
+ break;
+ case VarDecl::Specifier::InOut:
OS << " inout";
- if (P->isShared())
+ break;
+ case VarDecl::Specifier::Shared:
OS << " shared";
+ break;
+ case VarDecl::Specifier::Owned:
+ OS << " owned";
+ break;
+ }
if (P->isVariadic())
OS << " variadic";
@@ -2750,6 +2761,12 @@
printRec(T->getBase());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
+
+ void visitOwnedTypeRepr(OwnedTypeRepr *T) {
+ printCommon("type_owned") << '\n';
+ printRec(T->getBase());
+ PrintWithColorRAII(OS, ParenthesisColor) << ')';
+ }
};
} // end anonymous namespace
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index 1c00e72..ddc5cc7 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -1724,10 +1724,20 @@
void ASTMangler::appendTypeListElement(Identifier name, Type elementType,
ParameterTypeFlags flags) {
appendType(elementType->getInOutObjectType());
- if (flags.isInOut())
+ switch (flags.getValueOwnership()) {
+ case ValueOwnership::Default:
+ /* nothing */
+ break;
+ case ValueOwnership::InOut:
appendOperator("z");
- if (flags.isShared())
+ break;
+ case ValueOwnership::Shared:
appendOperator("h");
+ break;
+ case ValueOwnership::Owned:
+ appendOperator("n");
+ break;
+ }
if (!name.empty())
appendIdentifier(name.str());
if (flags.isVariadic())
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 1035c66..569745e 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -2132,8 +2132,21 @@
printer << "@autoclosure ";
if (!options.excludeAttrKind(TAK_escaping) && flags.isEscaping())
printer << "@escaping ";
- if (flags.isShared())
+
+ switch (flags.getValueOwnership()) {
+ case ValueOwnership::Default:
+ /* nothing */
+ break;
+ case ValueOwnership::InOut:
+ /* handled as part of an InOutType */
+ break;
+ case ValueOwnership::Shared:
printer << "__shared ";
+ break;
+ case ValueOwnership::Owned:
+ printer << "__owned ";
+ break;
+ }
}
void PrintAST::visitVarDecl(VarDecl *decl) {
@@ -2154,14 +2167,15 @@
// Map all non-let specifiers to 'var'. This is not correct, but
// SourceKit relies on this for info about parameter decls.
switch (decl->getSpecifier()) {
- case VarDecl::Specifier::Owned:
- Printer << tok::kw_let;
- break;
- case VarDecl::Specifier::Var:
- case VarDecl::Specifier::InOut:
- case VarDecl::Specifier::Shared:
- Printer << tok::kw_var;
- break;
+ case VarDecl::Specifier::Let:
+ Printer << tok::kw_let;
+ break;
+ case VarDecl::Specifier::Var:
+ case VarDecl::Specifier::InOut:
+ case VarDecl::Specifier::Shared:
+ case VarDecl::Specifier::Owned:
+ Printer << tok::kw_var;
+ break;
}
Printer << " ";
}
diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp
index e2ff5ae..49ac696 100644
--- a/lib/AST/ASTWalker.cpp
+++ b/lib/AST/ASTWalker.cpp
@@ -1697,6 +1697,10 @@
return doIt(T->getBase());
}
+bool Traversal::visitOwnedTypeRepr(OwnedTypeRepr *T) {
+ return doIt(T->getBase());
+}
+
bool Traversal::visitFixedTypeRepr(FixedTypeRepr *T) {
return false;
}
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index 875a932..6d2a220 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -160,10 +160,9 @@
SmallVector<ParamDecl*, 4> params;
for (Type argType : argTypes) {
- auto PD = new (Context) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(),
- Identifier(), SourceLoc(),
- Identifier(), argType,
- DC);
+ auto PD = new (Context)
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ Identifier(), SourceLoc(), Identifier(), argType, DC);
PD->setInterfaceType(argType);
PD->setValidationStarted();
PD->setImplicit();
@@ -221,8 +220,8 @@
auto paramType = ArgBodyTypes[i];
auto paramIfaceType = ArgParamTypes[i].getType();
auto specifier = (ArgParamTypes[i].getParameterFlags().isInOut())
- ? VarDecl::Specifier::InOut
- : VarDecl::Specifier::Owned;
+ ? VarDecl::Specifier::InOut
+ : VarDecl::Specifier::Default;
auto PD = new (Context) ParamDecl(specifier,
SourceLoc(), SourceLoc(),
Identifier(), SourceLoc(),
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 1c59fda..69cebce 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -4047,7 +4047,7 @@
const DeclRefExpr *base) const {
// If this is a 'var' decl, then we're settable if we have storage or a
// setter.
- if (!isLet() && !isShared())
+ if (!isImmutable())
return ::isSettable(this);
// If the decl has a value bound to it but has no PBD, then it is
@@ -4377,8 +4377,9 @@
/// generic parameters.
ParamDecl *ParamDecl::createUnboundSelf(SourceLoc loc, DeclContext *DC) {
ASTContext &C = DC->getASTContext();
- auto *selfDecl = new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(),
- Identifier(), loc, C.Id_self, Type(), DC);
+ auto *selfDecl =
+ new (C) ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ Identifier(), loc, C.Id_self, Type(), DC);
selfDecl->setImplicit();
return selfDecl;
}
@@ -4396,7 +4397,7 @@
bool isStaticMethod, bool isInOut) {
ASTContext &C = DC->getASTContext();
auto selfInterfaceType = DC->getSelfInterfaceType();
- auto specifier = VarDecl::Specifier::Owned;
+ auto specifier = VarDecl::Specifier::Default;
assert(selfInterfaceType);
if (isStaticMethod) {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 5e5c65e..d9cb741 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1020,8 +1020,11 @@
return inputType;
auto flags = ParameterTypeFlags().withInOut(inputType->is<InOutType>());
- if (auto *parenTy = dyn_cast<ParenType>(origInputType.getPointer()))
- flags = flags.withShared(parenTy->getParameterFlags().isShared());
+ if (auto *parenTy = dyn_cast<ParenType>(origInputType.getPointer())) {
+ auto parenFlags = parenTy->getParameterFlags();
+ flags =
+ flags.withShared(parenFlags.isShared()).withOwned(parenFlags.isOwned());
+ }
inputType = ParenType::get(inputType->getASTContext(),
inputType->getInOutObjectType(), flags);
diff --git a/lib/AST/TypeRepr.cpp b/lib/AST/TypeRepr.cpp
index 7ff0d50..f848364 100644
--- a/lib/AST/TypeRepr.cpp
+++ b/lib/AST/TypeRepr.cpp
@@ -224,6 +224,10 @@
return new (Ctx) SharedTypeRepr(visit(T->getBase()), T->getSpecifierLoc());
}
+TypeRepr *CloneVisitor::visitOwnedTypeRepr(OwnedTypeRepr *T) {
+ return new (Ctx) OwnedTypeRepr(visit(T->getBase()), T->getSpecifierLoc());
+}
+
TypeRepr *CloneVisitor::visitFixedTypeRepr(FixedTypeRepr *T) {
return new (Ctx) FixedTypeRepr(T->getType(), T->getLoc());
}
@@ -557,11 +561,19 @@
void SpecifierTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
- if (getKind() == TypeReprKind::InOut) {
+ switch (getKind()) {
+ case TypeReprKind::InOut:
Printer.printKeyword("inout");
- } else {
- assert((getKind() == TypeReprKind::Shared) && "Unknown kind");
+ break;
+ case TypeReprKind::Shared:
Printer.printKeyword("shared");
+ break;
+ case TypeReprKind::Owned:
+ Printer.printKeyword("owned");
+ break;
+ default:
+ llvm_unreachable("unknown specifier type repr");
+ break;
}
Printer << " ";
printTypeRepr(Base, Printer, Opts);
diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index 53d526a..146bee5 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/lib/Basic/LangOptions.cpp
@@ -172,25 +172,25 @@
// Set the "os" platform condition.
if (Target.isMacOSX())
addPlatformConditionValue(PlatformConditionKind::OS, "OSX");
- else if (triple.isTvOS())
+ else if (Target.isTvOS())
addPlatformConditionValue(PlatformConditionKind::OS, "tvOS");
- else if (triple.isWatchOS())
+ else if (Target.isWatchOS())
addPlatformConditionValue(PlatformConditionKind::OS, "watchOS");
- else if (triple.isiOS())
+ else if (Target.isiOS())
addPlatformConditionValue(PlatformConditionKind::OS, "iOS");
- else if (triple.isAndroid())
+ else if (Target.isAndroid())
addPlatformConditionValue(PlatformConditionKind::OS, "Android");
- else if (triple.isOSLinux())
+ else if (Target.isOSLinux())
addPlatformConditionValue(PlatformConditionKind::OS, "Linux");
- else if (triple.isOSFreeBSD())
+ else if (Target.isOSFreeBSD())
addPlatformConditionValue(PlatformConditionKind::OS, "FreeBSD");
- else if (triple.isOSWindows())
+ else if (Target.isOSWindows())
addPlatformConditionValue(PlatformConditionKind::OS, "Windows");
- else if (triple.isWindowsCygwinEnvironment())
+ else if (Target.isWindowsCygwinEnvironment())
addPlatformConditionValue(PlatformConditionKind::OS, "Cygwin");
- else if (triple.isPS4())
+ else if (Target.isPS4())
addPlatformConditionValue(PlatformConditionKind::OS, "PS4");
- else if (triple.isOSHaiku())
+ else if (Target.isOSHaiku())
addPlatformConditionValue(PlatformConditionKind::OS, "Haiku");
else
UnsupportedOS = true;
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index d02ea72..9f022db 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -434,7 +434,7 @@
auto selfDecl = ParamDecl::createSelf(SourceLoc(), enumDecl,
/*static*/false, /*inout*/true);
- auto param = new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),
+ auto param = new (C) ParamDecl(VarDecl::Specifier::Default, SourceLoc(),
SourceLoc(), C.Id_rawValue,
SourceLoc(), C.Id_rawValue,
rawTy,
@@ -708,7 +708,7 @@
auto &C = Impl.SwiftContext;
auto selfDecl = ParamDecl::createSelf(SourceLoc(), importedDecl,
/*isStatic*/false, /*isInOut*/true);
- auto newValueDecl = new (C) ParamDecl(VarDecl::Specifier::Owned,
+ auto newValueDecl = new (C) ParamDecl(VarDecl::Specifier::Default,
SourceLoc(), SourceLoc(),
Identifier(), SourceLoc(), C.Id_value,
importedFieldDecl->getType(),
@@ -1267,7 +1267,7 @@
Identifier argName = generateParamName ? var->getName() : Identifier();
auto param = new (context)
- ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(), argName,
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(), argName,
SourceLoc(), var->getName(), var->getType(), structDecl);
param->setInterfaceType(var->getInterfaceType());
param->setValidationStarted();
@@ -1689,7 +1689,7 @@
auto elementTy = dc->mapTypeIntoContext(elementInterfaceTy);
auto paramVarDecl =
- new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(),
+ new (C) ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
Identifier(), loc, valueIndex->get(0)->getName(),
elementTy, dc);
paramVarDecl->setInterfaceType(elementInterfaceTy);
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index 2b53fc0..c1b09ad 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -1660,7 +1660,7 @@
// imported header unit.
auto paramInfo = createDeclWithClangNode<ParamDecl>(
param, AccessLevel::Private,
- VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(), name,
+ VarDecl::Specifier::Default, SourceLoc(), SourceLoc(), name,
importSourceLoc(param->getLocation()), bodyName,
dc->mapTypeIntoContext(swiftParamTy),
ImportedHeaderUnit);
@@ -1678,7 +1678,7 @@
BoundGenericType::get(SwiftContext.getArrayDecl(), Type(),
{SwiftContext.TheAnyType});
auto name = SwiftContext.getIdentifier("varargs");
- auto param = new (SwiftContext) ParamDecl(VarDecl::Specifier::Owned,
+ auto param = new (SwiftContext) ParamDecl(VarDecl::Specifier::Default,
SourceLoc(), SourceLoc(),
Identifier(), SourceLoc(),
name, paramTy,
@@ -1979,7 +1979,7 @@
// It doesn't actually matter which DeclContext we use, so just
// use the imported header unit.
auto type = TupleType::getEmpty(SwiftContext);
- auto var = new (SwiftContext) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),
+ auto var = new (SwiftContext) ParamDecl(VarDecl::Specifier::Default, SourceLoc(),
SourceLoc(), argName,
SourceLoc(), argName, type,
ImportedHeaderUnit);
@@ -2105,7 +2105,7 @@
// Set up the parameter info.
auto paramInfo
= createDeclWithClangNode<ParamDecl>(param, AccessLevel::Private,
- VarDecl::Specifier::Owned,
+ VarDecl::Specifier::Default,
SourceLoc(), SourceLoc(), name,
importSourceLoc(param->getLocation()),
bodyName,
@@ -2225,7 +2225,7 @@
Identifier argLabel = functionName.getDeclName().getArgumentNames().front();
auto paramInfo
= createDeclWithClangNode<ParamDecl>(param, AccessLevel::Private,
- VarDecl::Specifier::Owned,
+ VarDecl::Specifier::Default,
/*let loc*/SourceLoc(),
/*label loc*/SourceLoc(),
argLabel, nameLoc, bodyName,
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index ea4ec7a..ae82735 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -596,6 +596,9 @@
case 'l': return demangleGenericSignature(/*hasParamCounts*/ false);
case 'm': return createType(createWithChild(Node::Kind::Metatype,
popNode(Node::Kind::Type)));
+ case 'n':
+ return createType(
+ createWithChild(Node::Kind::Owned, popTypeAndGetChild()));
case 'o': return demangleOperatorIdentifier();
case 'p': return demangleProtocolListType();
case 'q': return createType(demangleGenericParamIndex());
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index ed38fc1..f1620f7 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -386,6 +386,7 @@
case Node::Kind::Number:
case Node::Kind::ObjCAttribute:
case Node::Kind::ObjCBlock:
+ case Node::Kind::Owned:
case Node::Kind::OwningAddressor:
case Node::Kind::OwningMutableAddressor:
case Node::Kind::PartialApplyForwarder:
@@ -1128,6 +1129,10 @@
Printer << "__shared ";
print(Node->getChild(0));
return nullptr;
+ case Node::Kind::Owned:
+ Printer << "__owned ";
+ print(Node->getChild(0));
+ return nullptr;
case Node::Kind::NonObjCAttribute:
Printer << "@nonobjc ";
return nullptr;
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
index 95c0f61..a5c3cfb 100644
--- a/lib/Demangling/OldRemangler.cpp
+++ b/lib/Demangling/OldRemangler.cpp
@@ -1470,6 +1470,11 @@
mangleSingleChildNode(node); // type
}
+void Remangler::mangleOwned(Node *node) {
+ Out << 'n';
+ mangleSingleChildNode(node); // type
+}
+
void Remangler::mangleInOut(Node *node) {
Out << 'R';
mangleSingleChildNode(node); // type
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 991cb29..0090b6b 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -1307,6 +1307,11 @@
Buffer << 'h';
}
+void Remangler::mangleOwned(Node *node) {
+ mangleSingleChildNode(node);
+ Buffer << 'n';
+}
+
void Remangler::mangleInfixOperator(Node *node) {
mangleIdentifierImpl(node, /*isOperator*/ true);
Buffer << "oi";
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index b83b771..041886c 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -512,22 +512,22 @@
const SILModule& Module) {
auto &C = Stats.getFrontendCounters();
// FIXME: calculate these in constant time, via the dense maps.
- C.NumSILGenFunctions = Module.getFunctionList().size();
- C.NumSILGenVtables = Module.getVTableList().size();
- C.NumSILGenWitnessTables = Module.getWitnessTableList().size();
- C.NumSILGenDefaultWitnessTables = Module.getDefaultWitnessTableList().size();
- C.NumSILGenGlobalVariables = Module.getSILGlobalList().size();
+ C.NumSILGenFunctions += Module.getFunctionList().size();
+ C.NumSILGenVtables += Module.getVTableList().size();
+ C.NumSILGenWitnessTables += Module.getWitnessTableList().size();
+ C.NumSILGenDefaultWitnessTables += Module.getDefaultWitnessTableList().size();
+ C.NumSILGenGlobalVariables += Module.getSILGlobalList().size();
}
static void countStatsPostSILOpt(UnifiedStatsReporter &Stats,
const SILModule& Module) {
auto &C = Stats.getFrontendCounters();
// FIXME: calculate these in constant time, via the dense maps.
- C.NumSILOptFunctions = Module.getFunctionList().size();
- C.NumSILOptVtables = Module.getVTableList().size();
- C.NumSILOptWitnessTables = Module.getWitnessTableList().size();
- C.NumSILOptDefaultWitnessTables = Module.getDefaultWitnessTableList().size();
- C.NumSILOptGlobalVariables = Module.getSILGlobalList().size();
+ C.NumSILOptFunctions += Module.getFunctionList().size();
+ C.NumSILOptVtables += Module.getVTableList().size();
+ C.NumSILOptWitnessTables += Module.getWitnessTableList().size();
+ C.NumSILOptDefaultWitnessTables += Module.getDefaultWitnessTableList().size();
+ C.NumSILOptGlobalVariables += Module.getSILGlobalList().size();
}
static std::unique_ptr<llvm::raw_fd_ostream>
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 34c67cc..3ed7bce 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -838,10 +838,10 @@
auto param = params[index];
auto flags = param.getParameterFlags();
- auto parameterFlags = ParameterFlags()
- .withInOut(flags.isInOut())
- .withShared(flags.isShared())
- .withVariadic(flags.isVariadic());
+ auto parameterFlags =
+ ParameterFlags()
+ .withValueOwnership(flags.getValueOwnership())
+ .withVariadic(flags.isVariadic());
processor(index, getFunctionParameterRef(param), parameterFlags);
}
diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp
index 79f4b6d..e886b90 100644
--- a/lib/Migrator/APIDiffMigratorPass.cpp
+++ b/lib/Migrator/APIDiffMigratorPass.cpp
@@ -160,6 +160,10 @@
return visit(T->getBase());
}
+ FoundResult visitOwnedTypeRepr(OwnedTypeRepr *T) {
+ return visit(T->getBase());
+ }
+
FoundResult visitArrayTypeRepr(ArrayTypeRepr *T) {
return handleParent(T, T->getBase());
}
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index d18855b..66829cd 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -168,38 +168,44 @@
// Setup and Helper Methods
//===----------------------------------------------------------------------===//
-Lexer::Lexer(const LangOptions &Options,
- const SourceManager &SM, DiagnosticEngine *Diags,
- unsigned BufferID, bool InSILMode,
+Lexer::Lexer(const PrincipalTag &, const LangOptions &LangOpts,
+ const SourceManager &SourceMgr, unsigned BufferID,
+ DiagnosticEngine *Diags, bool InSILMode,
CommentRetentionMode RetainComments,
TriviaRetentionMode TriviaRetention)
- : LangOpts(Options), SourceMgr(SM), Diags(Diags), BufferID(BufferID),
- InSILMode(InSILMode), RetainComments(RetainComments),
- TriviaRetention(TriviaRetention) {
+ : LangOpts(LangOpts), SourceMgr(SourceMgr), BufferID(BufferID),
+ Diags(Diags), InSILMode(InSILMode), RetainComments(RetainComments),
+ TriviaRetention(TriviaRetention) {}
+
+void Lexer::initialize(unsigned Offset, unsigned EndOffset) {
+ assert(Offset <= EndOffset);
+
// Initialize buffer pointers.
- StringRef contents = SM.extractText(SM.getRangeForBuffer(BufferID));
+ StringRef contents =
+ SourceMgr.extractText(SourceMgr.getRangeForBuffer(BufferID));
BufferStart = contents.data();
BufferEnd = contents.data() + contents.size();
+ assert(*BufferEnd == 0);
+ assert(BufferStart + Offset <= BufferEnd);
+ assert(BufferStart + EndOffset <= BufferEnd);
// Check for Unicode BOM at start of file (Only UTF-8 BOM supported now).
- size_t BOMLength = llvm::StringSwitch<size_t>(contents)
- .StartsWith("\xEF\xBB\xBF", 3)
- .Default(0);
+ size_t BOMLength = contents.startswith("\xEF\xBB\xBF") ? 3 : 0;
// Keep information about existance of UTF-8 BOM for transparency source code
// editing with libSyntax.
- CurPtr = BufferStart;
ContentStart = BufferStart + BOMLength;
// Initialize code completion.
- if (BufferID == SM.getCodeCompletionBufferID()) {
- const char *Ptr = BufferStart + SM.getCodeCompletionOffset();
+ if (BufferID == SourceMgr.getCodeCompletionBufferID()) {
+ const char *Ptr = BufferStart + SourceMgr.getCodeCompletionOffset();
if (Ptr >= BufferStart && Ptr <= BufferEnd)
CodeCompletionPtr = Ptr;
}
-}
-void Lexer::primeLexer() {
+ ArtificialEOF = BufferStart + EndOffset;
+ CurPtr = BufferStart + Offset;
+
assert(NextToken.is(tok::NUM_TOKENS));
lexImpl();
assert((NextToken.isAtStartOfLine() || CurPtr != BufferStart) &&
@@ -207,25 +213,38 @@
"or we should be lexing from the middle of the buffer");
}
-void Lexer::initSubLexer(Lexer &Parent, State BeginState, State EndState) {
+Lexer::Lexer(const LangOptions &Options, const SourceManager &SourceMgr,
+ unsigned BufferID, DiagnosticEngine *Diags, bool InSILMode,
+ CommentRetentionMode RetainComments,
+ TriviaRetentionMode TriviaRetention)
+ : Lexer(PrincipalTag(), Options, SourceMgr, BufferID, Diags, InSILMode,
+ RetainComments, TriviaRetention) {
+ unsigned EndOffset = SourceMgr.getRangeForBuffer(BufferID).getByteLength();
+ initialize(/*Offset=*/0, EndOffset);
+}
+
+Lexer::Lexer(const LangOptions &Options, const SourceManager &SourceMgr,
+ unsigned BufferID, DiagnosticEngine *Diags, bool InSILMode,
+ CommentRetentionMode RetainComments,
+ TriviaRetentionMode TriviaRetention, unsigned Offset,
+ unsigned EndOffset)
+ : Lexer(PrincipalTag(), Options, SourceMgr, BufferID, Diags, InSILMode,
+ RetainComments, TriviaRetention) {
+ initialize(Offset, EndOffset);
+}
+
+Lexer::Lexer(Lexer &Parent, State BeginState, State EndState)
+ : Lexer(PrincipalTag(), Parent.LangOpts, Parent.SourceMgr, Parent.BufferID,
+ Parent.Diags, Parent.InSILMode, Parent.RetainComments,
+ Parent.TriviaRetention) {
assert(BufferID == SourceMgr.findBufferContainingLoc(BeginState.Loc) &&
"state for the wrong buffer");
assert(BufferID == SourceMgr.findBufferContainingLoc(EndState.Loc) &&
"state for the wrong buffer");
- // If the parent lexer should stop prematurely, and the ArtificialEOF
- // position is in this subrange, then we should stop at that point, too.
- const char *BeginStatePtr = getBufferPtrForSourceLoc(BeginState.Loc);
- const char *EndStatePtr = getBufferPtrForSourceLoc(EndState.Loc);
- if (Parent.ArtificialEOF &&
- Parent.ArtificialEOF >= BeginStatePtr &&
- Parent.ArtificialEOF <= EndStatePtr) {
- ArtificialEOF = Parent.ArtificialEOF;
- } else
- ArtificialEOF = EndStatePtr;
-
- primeLexer();
- restoreState(BeginState);
+ unsigned Offset = SourceMgr.getLocOffsetInBuffer(BeginState.Loc, BufferID);
+ unsigned EndOffset = SourceMgr.getLocOffsetInBuffer(EndState.Loc, BufferID);
+ initialize(Offset, EndOffset);
}
InFlightDiagnostic Lexer::diagnose(const char *Loc, Diagnostic Diag) {
@@ -255,7 +274,7 @@
// When we are lexing a subrange from the middle of a file buffer, we will
// run past the end of the range, but will stay within the file. Check if
// we are past the imaginary EOF, and synthesize a tok::eof in this case.
- if (Kind != tok::eof && ArtificialEOF && TokStart >= ArtificialEOF) {
+ if (Kind != tok::eof && TokStart >= ArtificialEOF) {
Kind = tok::eof;
}
unsigned CommentLength = 0;
@@ -2365,7 +2384,7 @@
Restart:
const char *TriviaStart = CurPtr;
- switch (*CurPtr++) {
+ switch ((signed char)*CurPtr++) {
case '\n':
if (IsForTrailingTrivia)
break;
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 84b15c3..e134a65 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1895,7 +1895,7 @@
bool Parser::parseTypeAttributeListPresent(VarDecl::Specifier &Specifier,
SourceLoc &SpecifierLoc,
TypeAttributes &Attributes) {
- Specifier = VarDecl::Specifier::Owned;
+ Specifier = VarDecl::Specifier::Default;
while (Tok.is(tok::kw_inout) ||
(Tok.is(tok::identifier) &&
(Tok.getRawText().equals("__shared") ||
@@ -3676,10 +3676,9 @@
name = P.Context.getIdentifier(implName);
}
- auto result = new (P.Context) ParamDecl(VarDecl::Specifier::Owned,
- SourceLoc(),SourceLoc(),
- Identifier(), nameLoc, name,
- Type(), P.CurDeclContext);
+ auto result = new (P.Context)
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ Identifier(), nameLoc, name, Type(), P.CurDeclContext);
if (isNameImplicit)
result->setImplicit();
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 68b673c..cbc527d 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -2628,9 +2628,9 @@
Identifier name = Tok.is(tok::identifier) ?
Context.getIdentifier(Tok.getText()) : Identifier();
- auto var = new (Context) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),
- SourceLoc(), Identifier(),
- Tok.getLoc(), name, Type(), nullptr);
+ auto var = new (Context)
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ Identifier(), Tok.getLoc(), name, Type(), nullptr);
elements.push_back(var);
consumeToken();
@@ -2929,9 +2929,9 @@
StringRef varName = ("$" + Twine(nextIdx)).toStringRef(StrBuf);
Identifier ident = Context.getIdentifier(varName);
SourceLoc varLoc = leftBraceLoc;
- auto *var = new (Context) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),SourceLoc(),
- Identifier(), varLoc, ident, Type(),
- closure);
+ auto *var = new (Context)
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ Identifier(), varLoc, ident, Type(), closure);
var->setImplicit();
decls.push_back(var);
}
diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp
index 70b89d3..3a30a39 100644
--- a/lib/Parse/ParsePattern.cpp
+++ b/lib/Parse/ParsePattern.cpp
@@ -212,6 +212,12 @@
// better fixits.
param.SpecifierKind = VarDecl::Specifier::Shared;
param.SpecifierLoc = consumeToken();
+ } else if (Tok.is(tok::identifier) &&
+ Tok.getRawText().equals("__owned")) {
+ // This case is handled later when mapping to ParamDecls for
+ // better fixits.
+ param.SpecifierKind = VarDecl::Specifier::Owned;
+ param.SpecifierLoc = consumeToken();
} else {
diagnose(Tok, diag::parameter_let_var_as_attr, Tok.getText())
.fixItRemove(Tok.getLoc());
@@ -352,6 +358,28 @@
return status;
});
}
+template <typename T>
+static TypeRepr *
+validateParameterWithSpecifier(Parser &parser,
+ Parser::ParsedParameter ¶mInfo,
+ StringRef specifierName) {
+ auto type = paramInfo.Type;
+ auto loc = paramInfo.SpecifierLoc;
+ if (isa<SpecifierTypeRepr>(type)) {
+ parser.diagnose(loc, diag::parameter_specifier_repeated).fixItRemove(loc);
+ } else {
+ llvm::SmallString<128> replacement(specifierName);
+ replacement += " ";
+ parser
+ .diagnose(loc, diag::parameter_specifier_as_attr_disallowed,
+ specifierName)
+ .fixItRemove(loc)
+ .fixItInsert(type->getStartLoc(), replacement);
+ type = new (parser.Context) T(type, loc);
+ }
+
+ return type;
+}
/// Map parsed parameters to a ParameterList.
static ParameterList *
@@ -384,28 +412,14 @@
if (auto type = paramInfo.Type) {
// If 'inout' was specified, turn the type into an in-out type.
if (paramInfo.SpecifierKind == VarDecl::Specifier::InOut) {
- auto InOutLoc = paramInfo.SpecifierLoc;
- if (isa<InOutTypeRepr>(type)) {
- parser.diagnose(InOutLoc, diag::parameter_specifier_repeated)
- .fixItRemove(InOutLoc);
- } else {
- parser.diagnose(InOutLoc, diag::inout_as_attr_disallowed, "'inout'")
- .fixItRemove(InOutLoc)
- .fixItInsert(type->getStartLoc(), "inout ");
- type = new (ctx) InOutTypeRepr(type, InOutLoc);
- }
+ type = validateParameterWithSpecifier<InOutTypeRepr>(parser, paramInfo,
+ "inout");
} else if (paramInfo.SpecifierKind == VarDecl::Specifier::Shared) {
- auto SpecifierLoc = paramInfo.SpecifierLoc;
- if (isa<SharedTypeRepr>(type)) {
- parser.diagnose(SpecifierLoc, diag::parameter_specifier_repeated)
- .fixItRemove(SpecifierLoc);
- } else {
- parser.diagnose(SpecifierLoc, diag::inout_as_attr_disallowed,
- "'__shared'")
- .fixItRemove(SpecifierLoc)
- .fixItInsert(type->getStartLoc(), "__shared ");
- type = new (ctx) SharedTypeRepr(type, SpecifierLoc);
- }
+ type = validateParameterWithSpecifier<SharedTypeRepr>(parser, paramInfo,
+ "__shared");
+ } else if (paramInfo.SpecifierKind == VarDecl::Specifier::Owned) {
+ type = validateParameterWithSpecifier<OwnedTypeRepr>(parser, paramInfo,
+ "__owned");
}
param->getTypeLoc() = TypeLoc(type);
} else if (paramContext != Parser::ParameterContextKind::Closure) {
@@ -424,14 +438,18 @@
case VarDecl::Specifier::Shared:
specifier = "'shared'";
break;
+ case VarDecl::Specifier::Owned:
+ specifier = "'owned'";
+ break;
case VarDecl::Specifier::Let:
case VarDecl::Specifier::Var:
llvm_unreachable("can't have let or var here");
+ break;
}
parser.diagnose(paramInfo.SpecifierLoc, diag::specifier_must_have_type,
specifier);
paramInfo.SpecifierLoc = SourceLoc();
- paramInfo.SpecifierKind = VarDecl::Specifier::Owned;
+ paramInfo.SpecifierKind = VarDecl::Specifier::Default;
}
return param;
};
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index ca557a6..350b17d 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -42,7 +42,7 @@
if (!attrs.empty())
ty = new (Context) AttributedTypeRepr(attrs, ty);
- // Apply 'inout' or '__shared'
+ // Apply 'inout' or '__shared' or '__owned'
if (specifierLoc.isValid()) {
if (auto *fnTR = dyn_cast<FunctionTypeRepr>(ty)) {
// If the input to the function isn't parenthesized, apply the inout
@@ -64,6 +64,7 @@
}
switch (specifier) {
case VarDecl::Specifier::Owned:
+ ty = new (Context) OwnedTypeRepr(ty, specifierLoc);
break;
case VarDecl::Specifier::InOut:
ty = new (Context) InOutTypeRepr(ty, specifierLoc);
@@ -71,6 +72,8 @@
case VarDecl::Specifier::Shared:
ty = new (Context) SharedTypeRepr(ty, specifierLoc);
break;
+ case VarDecl::Specifier::Default:
+ break;
case VarDecl::Specifier::Var:
llvm_unreachable("cannot have var as specifier");
break;
@@ -904,15 +907,15 @@
return makeParserError();
element.Type = type.get();
- // Complain obsoleted 'inout' position; (inout name: Ty)
+ // Complain obsoleted 'inout' etc. position; (inout name: Ty)
if (ObsoletedInOutLoc.isValid()) {
- if (isa<InOutTypeRepr>(element.Type) ||
- isa<SharedTypeRepr>(element.Type)) {
+ if (isa<SpecifierTypeRepr>(element.Type)) {
// If the parsed type is already a inout type et al, just remove it.
diagnose(Tok, diag::parameter_specifier_repeated)
.fixItRemove(ObsoletedInOutLoc);
} else {
- diagnose(ObsoletedInOutLoc, diag::inout_as_attr_disallowed, "'inout'")
+ diagnose(ObsoletedInOutLoc,
+ diag::parameter_specifier_as_attr_disallowed, "inout")
.fixItRemove(ObsoletedInOutLoc)
.fixItInsert(element.Type->getStartLoc(), "inout ");
// Build inout type. Note that we bury the inout locator within the
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index 1d3fdd1..8b7452a 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -350,9 +350,11 @@
auto label = Ctx.getIdentifier(param.getLabel());
auto flags = param.getFlags();
+ auto ownership = flags.getValueOwnership();
auto parameterFlags = ParameterTypeFlags()
- .withInOut(flags.isInOut())
- .withShared(flags.isShared())
+ .withInOut(ownership == ValueOwnership::InOut)
+ .withShared(ownership == ValueOwnership::Shared)
+ .withOwned(ownership == ValueOwnership::Owned)
.withVariadic(flags.isVariadic());
funcParams.push_back(AnyFunctionType::Param(type, label, parameterFlags));
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index da75cf4..76694cc 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -268,6 +268,42 @@
getIndirectSelfParameter(const AbstractionPattern &type) const = 0;
virtual ParameterConvention
getDirectSelfParameter(const AbstractionPattern &type) const = 0;
+
+ // Helpers that branch based on a value ownership.
+ ParameterConvention getIndirect(ValueOwnership ownership, bool forSelf,
+ unsigned index,
+ const AbstractionPattern &type,
+ const TypeLowering &substTL) const {
+ switch (ownership) {
+ case ValueOwnership::Default:
+ if (forSelf)
+ return getIndirectSelfParameter(type);
+ return getIndirectParameter(index, type, substTL);
+ case ValueOwnership::InOut:
+ return ParameterConvention::Indirect_Inout;
+ case ValueOwnership::Shared:
+ return ParameterConvention::Indirect_In_Guaranteed;
+ case ValueOwnership::Owned:
+ return ParameterConvention::Indirect_In;
+ }
+ }
+
+ ParameterConvention getDirect(ValueOwnership ownership, bool forSelf,
+ unsigned index, const AbstractionPattern &type,
+ const TypeLowering &substTL) const {
+ switch (ownership) {
+ case ValueOwnership::Default:
+ if (forSelf)
+ return getDirectSelfParameter(type);
+ return getDirectParameter(index, type, substTL);
+ case ValueOwnership::InOut:
+ return ParameterConvention::Indirect_Inout;
+ case ValueOwnership::Shared:
+ return ParameterConvention::Direct_Guaranteed;
+ case ValueOwnership::Owned:
+ return ParameterConvention::Direct_Owned;
+ }
+ }
};
/// A visitor for breaking down formal result types into a SILResultInfo
@@ -523,40 +559,6 @@
}
}
- void visitSharedType(AbstractionPattern origType, CanType substType,
- SILFunctionTypeRepresentation rep) {
- NextOrigParamIndex++;
-
- auto &substTL =
- M.Types.getTypeLowering(origType, substType);
- ParameterConvention convention;
- if (origType.getAs<InOutType>()) {
- convention = ParameterConvention::Indirect_Inout;
- } else if (isa<TupleType>(substType) && !origType.isTypeParameter()) {
- // Do not lower tuples @guaranteed. This can create conflicts with
- // substitutions for witness thunks e.g. we take $*(T, T)
- // @in_guaranteed and try to substitute it for $*T.
- return visit(origType, substType);
- } else if (isFormallyPassedIndirectly(origType, substType, substTL)) {
- if (rep == SILFunctionTypeRepresentation::WitnessMethod)
- convention = ParameterConvention::Indirect_In_Guaranteed;
- else
- convention = Convs.getIndirectSelfParameter(origType);
- assert(isIndirectFormalParameter(convention));
-
- } else if (substTL.isTrivial()) {
- convention = ParameterConvention::Direct_Unowned;
- } else {
- convention = Convs.getDirectSelfParameter(origType);
- assert(!isIndirectFormalParameter(convention));
- }
-
- auto loweredType = substTL.getLoweredType().getSwiftRValueType();
- Inputs.push_back(SILParameterInfo(loweredType, convention));
-
- maybeAddForeignParameters();
- }
-
/// This is a special entry point that allows destructure inputs to handle
/// self correctly.
void visitTopLevelParams(AbstractionPattern origType,
@@ -565,11 +567,15 @@
unsigned numEltTypes = params.size();
unsigned numNonSelfParams = numEltTypes - 1;
+ auto silRepresentation = extInfo.getSILRepresentation();
+
// We have to declare this out here so that the lambda scope lasts for
// the duration of the loop below.
auto handleForeignSelf = [&] {
- visit(origType.getTupleElementType(numNonSelfParams),
- params[numNonSelfParams].getType());
+ // This is a "self", but it's not a Swift self, we handle it differently.
+ visit(ValueOwnership::Default,
+ /*forSelf=*/false, origType.getTupleElementType(numNonSelfParams),
+ params[numNonSelfParams].getType(), silRepresentation);
};
// If we have a foreign-self, install handleSelf as the handler.
@@ -587,7 +593,8 @@
// to substitute.
if (params.empty()) {
if (origType.isTypeParameter())
- visit(origType, M.getASTContext().TheEmptyTupleType);
+ visit(ValueOwnership::Default, /*forSelf=*/false, origType,
+ M.getASTContext().TheEmptyTupleType, silRepresentation);
return;
}
@@ -599,13 +606,9 @@
// If the abstraction pattern is opaque, and the tuple type is
// materializable -- if it doesn't contain an l-value type -- then it's
// a valid target for substitution and we should not expand it.
- auto silExtInfo = extInfo.getSILRepresentation();
if (!tty || (pattern.isTypeParameter() && !tty->hasInOutElement())) {
- if (paramFlags.isShared()) {
- visitSharedType(pattern, ty, silExtInfo);
- } else {
- visit(pattern, ty);
- }
+ visit(paramFlags.getValueOwnership(), /*forSelf=*/false, pattern, ty,
+ silRepresentation);
return;
}
@@ -613,11 +616,8 @@
auto patternEltTy = pattern.getTupleElementType(i);
auto trueEltTy = tty.getElementType(i);
auto flags = tty->getElement(i).getParameterFlags();
- if (flags.isShared()) {
- visitSharedType(patternEltTy, trueEltTy, silExtInfo);
- } else {
- visit(patternEltTy, trueEltTy);
- }
+ visit(flags.getValueOwnership(), /*forSelf=*/false, patternEltTy,
+ trueEltTy, silRepresentation);
}
};
@@ -647,25 +647,41 @@
// Process the self parameter. Note that we implicitly drop self
// if this is a static foreign-self import.
if (!Foreign.Self.isImportAsMember()) {
- visitSharedType(origType.getTupleElementType(numNonSelfParams),
- params[numNonSelfParams].getType(),
- extInfo.getSILRepresentation());
+ visit(ValueOwnership::Default, /*forSelf=*/true,
+ origType.getTupleElementType(numNonSelfParams),
+ params[numNonSelfParams].getType(), silRepresentation);
}
// Clear the foreign-self handler for safety.
HandleForeignSelf.reset();
}
- void visit(AbstractionPattern origType, CanType substType) {
- // Expand tuples.
+ void visit(ValueOwnership ownership, bool forSelf,
+ AbstractionPattern origType, CanType substType,
+ SILFunctionTypeRepresentation rep) {
+ // Tuples get handled specially, in some cases:
CanTupleType substTupleTy = dyn_cast<TupleType>(substType);
if (substTupleTy && !origType.isTypeParameter()) {
assert(origType.getNumTupleElements() == substTupleTy->getNumElements());
- for (auto i : indices(substTupleTy.getElementTypes())) {
- visit(origType.getTupleElementType(i),
- substTupleTy.getElementType(i));
+ switch (ownership) {
+ case ValueOwnership::Default:
+ case ValueOwnership::Owned:
+ // Expand the tuple.
+ for (auto i : indices(substTupleTy.getElementTypes())) {
+ visit(ownership, forSelf, origType.getTupleElementType(i),
+ substTupleTy.getElementType(i), rep);
+ }
+ return;
+ case ValueOwnership::Shared:
+ // Do not lower tuples @guaranteed. This can create conflicts with
+ // substitutions for witness thunks e.g. we take $*(T, T)
+ // @in_guaranteed and try to substitute it for $*T.
+ return visit(ValueOwnership::Default, forSelf, origType, substType,
+ rep);
+ case ValueOwnership::InOut:
+ // handled below
+ break;
}
- return;
}
unsigned origParamIndex = NextOrigParamIndex++;
@@ -676,14 +692,17 @@
assert(origType.isTypeParameter() || origType.getAs<InOutType>());
convention = ParameterConvention::Indirect_Inout;
} else if (isFormallyPassedIndirectly(origType, substType, substTL)) {
- convention = Convs.getIndirectParameter(origParamIndex,
- origType, substTL);
+ if (forSelf && rep == SILFunctionTypeRepresentation::WitnessMethod)
+ convention = ParameterConvention::Indirect_In_Guaranteed;
+ else
+ convention = Convs.getIndirect(ownership, forSelf, origParamIndex,
+ origType, substTL);
assert(isIndirectFormalParameter(convention));
} else if (substTL.isTrivial()) {
convention = ParameterConvention::Direct_Unowned;
} else {
- convention = Convs.getDirectParameter(origParamIndex, origType,
- substTL);
+ convention = Convs.getDirect(ownership, forSelf, origParamIndex, origType,
+ substTL);
assert(!isIndirectFormalParameter(convention));
}
auto loweredType = substTL.getLoweredType().getSwiftRValueType();
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index aa511b8..37a0957 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -118,9 +118,9 @@
// If this is a non-address-only stored 'let' constant, we can capture it
// by value. If it is address-only, then we can't load it, so capture it
// by its address (like a var) instead.
- if ((var->isLet() || var->isShared())
- && (!SILModuleConventions(M).useLoweredAddresses() ||
- !getTypeLowering(var->getType()).isAddressOnly()))
+ if (var->isImmutable() &&
+ (!SILModuleConventions(M).useLoweredAddresses() ||
+ !getTypeLowering(var->getType()).isAddressOnly()))
return CaptureKind::Constant;
// In-out parameters are captured by address.
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index 088b97b..6702ccf 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -15,6 +15,7 @@
#include "Scope.h"
#include "swift/Strings.h"
#include "swift/AST/DiagnosticsSIL.h"
+#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/PrettyStackTrace.h"
@@ -1204,7 +1205,69 @@
}
void SILGenModule::tryEmitPropertyDescriptor(AbstractStorageDecl *decl) {
- // TODO
+ // TODO: Key path code emission doesn't handle opaque values properly yet.
+ if (!SILModuleConventions(M).useLoweredAddresses())
+ return;
+
+ if (!doesPropertyNeedDescriptor(decl))
+ return;
+
+ auto genericEnv = decl->getInnermostDeclContext()
+ ->getGenericEnvironmentOfContext();
+ unsigned baseOperand = 0;
+ bool needsGenericContext = true;
+
+ Type baseTy;
+ if (decl->getDeclContext()->isTypeContext()) {
+ baseTy = decl->getDeclContext()->getSelfInterfaceType();
+ if (decl->isStatic()) {
+ // TODO: Static properties should eventually be referenceable as
+ // keypaths from T.Type -> Element
+ //baseTy = MetatypeType::get(baseTy);
+ return;
+ }
+ } else {
+ // TODO: Global variables should eventually be referenceable as
+ // key paths from ()
+ //baseTy = TupleType::getEmpty(getASTContext());
+ return;
+ }
+
+ SubstitutionList subs = {};
+ if (genericEnv)
+ subs = genericEnv->getForwardingSubstitutions();
+
+ // TODO: The hashable conformances for the indices need to be provided by the
+ // client, since they may be post-hoc conformances, or a generic subscript
+ // may be invoked with hashable substitutions. We may eventually allow for
+ // non-hashable keypaths as well.
+ SmallVector<ProtocolConformanceRef, 4> indexHashables;
+ if (auto sub = dyn_cast<SubscriptDecl>(decl)) {
+ auto hashable = getASTContext().getProtocol(KnownProtocolKind::Hashable);
+ for (auto *index : *sub->getIndices()) {
+ if (index->isInOut())
+ return;
+ auto indexTy = index->getInterfaceType();
+ if (genericEnv)
+ indexTy = genericEnv->mapTypeIntoContext(indexTy);
+
+ auto conformance = sub->getModuleContext()
+ ->lookupConformance(indexTy, hashable);
+ if (!conformance)
+ return;
+ if (!conformance->getConditionalRequirements().empty())
+ return;
+ indexHashables.push_back(*conformance);
+ }
+ }
+
+ auto component = emitKeyPathComponentForDecl(SILLocation(decl),
+ genericEnv,
+ baseOperand, needsGenericContext,
+ subs, decl, indexHashables,
+ baseTy->getCanonicalType());
+
+ (void)SILProperty::create(M, /*serialized*/ false, decl, component);
}
void SILGenModule::emitPropertyBehavior(VarDecl *vd) {
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index 0a8275d..7ae1bf7 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -339,6 +339,16 @@
AccessKind accessKind);
SILDeclRef getMaterializeForSetDeclRef(AbstractStorageDecl *decl);
+ KeyPathPatternComponent
+ emitKeyPathComponentForDecl(SILLocation loc,
+ GenericEnvironment *genericEnv,
+ unsigned &baseOperand,
+ bool &needsGenericContext,
+ SubstitutionList subs,
+ AbstractStorageDecl *storage,
+ ArrayRef<ProtocolConformanceRef> indexHashables,
+ CanType baseTy);
+
/// Known functions for bridging.
SILDeclRef getStringToNSStringFn();
SILDeclRef getNSStringToStringFn();
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 3f8a2f2..aa265e3 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -5013,6 +5013,9 @@
ManagedValue base,
CanType baseFormalType,
SILDeclRef accessor) {
+ if (!base)
+ return ArgumentSource();
+
AccessorBaseArgPreparer Preparer(*this, loc, base, baseFormalType, accessor);
return Preparer.prepare();
}
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 946640b..2adb634 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -34,10 +34,10 @@
Type metatype = ctor->getInterfaceType()->castTo<AnyFunctionType>()->getInput();
auto *DC = ctor->getInnermostDeclContext();
auto &AC = SGF.getASTContext();
- auto VD = new (AC) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(),
- AC.getIdentifier("$metatype"), SourceLoc(),
- AC.getIdentifier("$metatype"), Type(),
- DC);
+ auto VD =
+ new (AC) ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ AC.getIdentifier("$metatype"), SourceLoc(),
+ AC.getIdentifier("$metatype"), Type(), DC);
VD->setInterfaceType(metatype);
SGF.AllocatorMetatype = SGF.F.begin()->createFunctionArgument(
@@ -61,7 +61,7 @@
}
auto &AC = SGF.getASTContext();
- auto VD = new (AC) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(),
+ auto VD = new (AC) ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
AC.getIdentifier("$implicit_value"),
SourceLoc(),
AC.getIdentifier("$implicit_value"), Type(),
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 72d725b7..5128020 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -2983,6 +2983,11 @@
CanType &baseType,
SubstitutionList &subs,
SmallVectorImpl<Substitution> &subsBuf) {
+ // If the storage is at global scope, then the base value () is a formality.
+ // There no real argument to pass to the underlying accessors.
+ if (!storage->getDeclContext()->isTypeContext())
+ return ManagedValue();
+
auto paramOrigValue = subSGF.emitManagedRValueWithCleanup(paramArg);
auto paramSubstValue = subSGF.emitOrigToSubstValue(loc, paramOrigValue,
AbstractionPattern::getOpaque(),
@@ -3147,7 +3152,7 @@
SmallVector<Substitution, 2> subsBuf;
- auto paramSubstValue = emitKeyPathRValueBase(subSGF, property,
+ auto baseSubstValue = emitKeyPathRValueBase(subSGF, property,
loc, baseArg,
baseType, subs, subsBuf);
@@ -3155,7 +3160,7 @@
indexes,
indexPtrArg);
- auto resultSubst = subSGF.emitRValueForStorageLoad(loc, paramSubstValue,
+ auto resultSubst = subSGF.emitRValueForStorageLoad(loc, baseSubstValue,
baseType, /*super*/false,
property, std::move(indexValue),
subs, AccessSemantics::Ordinary,
@@ -3448,6 +3453,11 @@
auto equatable = *subMap
.lookupConformance(CanType(hashableSig->getGenericParams()[0]),
equatableProtocol);
+
+ assert(equatable.isAbstract() == hashable.isAbstract());
+ if (equatable.isConcrete())
+ assert(equatable.getConcrete()->getType()->isEqual(
+ hashable.getConcrete()->getType()));
auto equatableSub = Substitution(formalTy,
C.AllocateCopy(ArrayRef<ProtocolConformanceRef>(equatable)));
@@ -3690,15 +3700,21 @@
bool &needsGenericContext) {
// Capturing an index value dependent on the generic context means we
// need the generic context captured in the key path.
- auto subMap =
- subscript->getGenericSignature()->getSubstitutionMap(subscriptSubs);
- auto subscriptSubstTy = subscript->getInterfaceType().subst(subMap);
+ auto subscriptSubstTy = subscript->getInterfaceType();
+ SubstitutionMap subMap;
+ auto sig = subscript->getGenericSignature();
+ if (sig) {
+ subMap = sig->getSubstitutionMap(subscriptSubs);
+ subscriptSubstTy = subscriptSubstTy.subst(subMap);
+ }
needsGenericContext |= subscriptSubstTy->hasArchetype();
unsigned i = 0;
for (auto *index : *subscript->getIndices()) {
- auto indexTy = index->getInterfaceType().subst(subMap)
- ->getCanonicalType();
+ auto indexTy = index->getInterfaceType();
+ if (sig) {
+ indexTy = indexTy.subst(subMap);
+ }
auto hashable = indexHashables[i++];
assert(hashable.isAbstract() ||
hashable.getConcrete()->getType()->isEqual(indexTy));
@@ -3718,20 +3734,24 @@
}
};
-static KeyPathPatternComponent
-emitKeyPathComponentForDecl(SILGenModule &SGM,
- SILLocation loc,
- GenericEnvironment *genericEnv,
- unsigned &baseOperand,
- bool &needsGenericContext,
- SubstitutionList subs,
- AbstractStorageDecl *storage,
- ArrayRef<ProtocolConformanceRef> indexHashables,
- CanType baseTy) {
+KeyPathPatternComponent
+SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
+ GenericEnvironment *genericEnv,
+ unsigned &baseOperand,
+ bool &needsGenericContext,
+ SubstitutionList subs,
+ AbstractStorageDecl *storage,
+ ArrayRef<ProtocolConformanceRef> indexHashables,
+ CanType baseTy) {
if (auto var = dyn_cast<VarDecl>(storage)) {
- auto componentTy = baseTy->getTypeOfMember(SGM.SwiftModule, var)
- ->getReferenceStorageReferent()
- ->getCanonicalType();
+ CanType componentTy;
+ if (!var->getDeclContext()->isTypeContext()) {
+ componentTy = storage->getStorageInterfaceType()->getCanonicalType();
+ } else {
+ componentTy = baseTy->getTypeOfMember(SwiftModule, var)
+ ->getReferenceStorageReferent()
+ ->getCanonicalType();
+ }
switch (auto strategy = var->getAccessStrategy(AccessSemantics::Ordinary,
AccessKind::ReadWrite)) {
@@ -3741,9 +3761,9 @@
auto componentObjTy = componentTy->getWithoutSpecifierType();
if (genericEnv)
componentObjTy = genericEnv->mapTypeIntoContext(componentObjTy);
- auto storageTy = SGM.Types.getSubstitutedStorageType(var,
+ auto storageTy = Types.getSubstitutedStorageType(var,
componentObjTy);
- auto opaqueTy = SGM.Types
+ auto opaqueTy = Types
.getLoweredType(AbstractionPattern::getOpaque(), componentObjTy);
if (storageTy.getAddressType() == opaqueTy.getAddressType()) {
@@ -3756,9 +3776,9 @@
case AccessStrategy::DispatchToAccessor: {
// We need thunks to bring the getter and setter to the right signature
// expected by the key path runtime.
- auto id = getIdForKeyPathComponentComputedProperty(SGM, var,
+ auto id = getIdForKeyPathComponentComputedProperty(*this, var,
strategy);
- auto getter = getOrCreateKeyPathGetter(SGM, loc,
+ auto getter = getOrCreateKeyPathGetter(*this, loc,
var, subs,
strategy,
needsGenericContext ? genericEnv : nullptr,
@@ -3766,7 +3786,7 @@
baseTy, componentTy);
if (var->isSettable(var->getDeclContext())) {
- auto setter = getOrCreateKeyPathSetter(SGM, loc,
+ auto setter = getOrCreateKeyPathSetter(*this, loc,
var, subs,
strategy,
needsGenericContext ? genericEnv : nullptr,
@@ -3796,28 +3816,30 @@
auto componentTy = baseSubscriptInterfaceTy.getResult();
SmallVector<KeyPathPatternComponent::Index, 4> indexPatterns;
- lowerKeyPathSubscriptIndexPatterns(SGM, indexPatterns,
+ lowerKeyPathSubscriptIndexPatterns(*this, indexPatterns,
decl, subs, indexHashables,
baseOperand,
needsGenericContext);
SILFunction *indexEquals = nullptr, *indexHash = nullptr;
- getOrCreateKeyPathEqualsAndHash(SGM, loc,
+ // TODO: Property descriptors for external key paths should get their
+ // equality and hashing from the client.
+ getOrCreateKeyPathEqualsAndHash(*this, loc,
needsGenericContext ? genericEnv : nullptr,
indexPatterns,
indexEquals, indexHash);
- auto id = getIdForKeyPathComponentComputedProperty(SGM, decl, strategy);
- auto getter = getOrCreateKeyPathGetter(SGM, loc,
+ auto id = getIdForKeyPathComponentComputedProperty(*this, decl, strategy);
+ auto getter = getOrCreateKeyPathGetter(*this, loc,
decl, subs,
strategy,
needsGenericContext ? genericEnv : nullptr,
indexPatterns,
baseTy, componentTy);
- auto indexPatternsCopy = SGM.getASTContext().AllocateCopy(indexPatterns);
+ auto indexPatternsCopy = getASTContext().AllocateCopy(indexPatterns);
if (decl->isSettable()) {
- auto setter = getOrCreateKeyPathSetter(SGM, loc,
+ auto setter = getOrCreateKeyPathSetter(*this, loc,
decl, subs,
strategy,
needsGenericContext ? genericEnv : nullptr,
@@ -3952,7 +3974,7 @@
} else {
unsigned numOperands = operands.size();
loweredComponents.push_back(
- emitKeyPathComponentForDecl(SGF.SGM, SILLocation(E),
+ SGF.SGM.emitKeyPathComponentForDecl(SILLocation(E),
SGF.F.getGenericEnvironment(),
numOperands,
needsGenericContext,
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 2314db6..7ffecf9 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -1573,9 +1573,6 @@
///
/// Valid: reabstraction info, InnerResult, OuterResult.
ReabstractDirectToDirect,
-
- /// Ignore the next direct inner result, since the outer is 'Void'.
- IgnoreDirectResult,
};
Operation(Kind kind) : TheKind(kind) {}
@@ -1720,24 +1717,6 @@
SILResultInfo outerResult,
SILValue optOuterResultAddr);
- void planIgnoredResult(AbstractionPattern innerOrigType,
- CanType innerSubstType, PlanData &planData) {
- if (innerOrigType.isTuple()) {
- auto innerSubstTuple = cast<TupleType>(innerSubstType);
- for (unsigned i = 0, n = innerSubstTuple->getNumElements(); i != n; ++i)
- planIgnoredResult(innerOrigType.getTupleElementType(i),
- innerSubstTuple.getElementType(i), planData);
- return;
- }
-
- auto innerResult = claimNextInnerResult(planData);
- if (innerResult.isFormalIndirect() &&
- SGF.silConv.isSILIndirect(innerResult))
- (void)addInnerIndirectResultTemporary(planData, innerResult);
- else
- addIgnoreDirectResult();
- }
-
/// Claim the next inner result from the plan data.
SILResultInfo claimNextInnerResult(PlanData &data) {
return claimNext(data.InnerResults);
@@ -1887,10 +1866,6 @@
op.OuterOrigType = outerOrigType;
op.OuterSubstType = outerSubstType;
}
-
- void addIgnoreDirectResult() {
- (void)addOperation(Operation::IgnoreDirectResult);
- }
};
} // end anonymous namespace
@@ -1901,13 +1876,6 @@
AbstractionPattern outerOrigType,
CanType outerSubstType,
PlanData &planData) {
- // Conversion from `() -> T` to `() -> Void` is allowed when
- // the argument is a closure.
- if (!innerSubstType->isVoid() && outerSubstType->isVoid()) {
- planIgnoredResult(innerOrigType, innerSubstType, planData);
- return;
- }
-
// The substituted types must match up in tuple-ness and arity.
assert(
isa<TupleType>(innerSubstType) == isa<TupleType>(outerSubstType) ||
@@ -2616,10 +2584,6 @@
case Operation::InjectOptionalIndirect:
SGF.B.createInjectEnumAddr(Loc, op.OuterResultAddr, op.SomeDecl);
continue;
-
- case Operation::IgnoreDirectResult:
- (void)claimNext(innerDirectResults);
- continue;
}
llvm_unreachable("bad operation kind");
}
diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp
index 8953613..5299b8a 100644
--- a/lib/SILGen/SILGenProlog.cpp
+++ b/lib/SILGen/SILGenProlog.cpp
@@ -283,8 +283,7 @@
}
}
} else {
- assert((vd->isLet() || vd->isShared())
- && "expected parameter to be immutable!");
+ assert(vd->isImmutable() && "expected parameter to be immutable!");
// If the variable is immutable, we can bind the value as is.
// Leave the cleanup on the argument, if any, in place to consume the
// argument if we're responsible for it.
diff --git a/lib/SILOptimizer/SILCombiner/SILCombiner.h b/lib/SILOptimizer/SILCombiner/SILCombiner.h
index e0299cb..068f3d6 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombiner.h
+++ b/lib/SILOptimizer/SILCombiner/SILCombiner.h
@@ -283,9 +283,6 @@
SILValue ConcreteTypeDef,
ProtocolConformanceRef Conformance,
ArchetypeType *OpenedArchetype);
-
- FullApplySite rewriteApplyCallee(FullApplySite apply, SILValue callee);
-
SILInstruction *
propagateConcreteTypeOfInitExistential(FullApplySite AI,
ProtocolDecl *Protocol,
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index 393ab1f..b885c70 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -1305,27 +1305,6 @@
return true;
}
-// Return a new apply with the specified callee. This creates a new apply rather
-// than simply rewriting the callee operand because the apply's SubstCalleeType,
-// derived from the callee and substitution list, may change.
-FullApplySite SILCombiner::rewriteApplyCallee(FullApplySite apply,
- SILValue callee) {
- SmallVector<SILValue, 4> arguments;
- for (SILValue arg : apply.getArguments())
- arguments.push_back(arg);
-
- Builder.addOpenedArchetypeOperands(apply.getInstruction());
- if (auto *TAI = dyn_cast<TryApplyInst>(apply)) {
- return Builder.createTryApply(TAI->getLoc(), callee,
- TAI->getSubstitutions(), arguments,
- TAI->getNormalBB(), TAI->getErrorBB());
- } else {
- return Builder.createApply(apply.getLoc(), callee, apply.getSubstitutions(),
- arguments,
- cast<ApplyInst>(apply)->isNonThrowing());
- }
-}
-
SILInstruction *SILCombiner::visitApplyInst(ApplyInst *AI) {
Builder.setCurrentDebugScope(AI->getDebugScope());
// apply{partial_apply(x,y)}(z) -> apply(z,x,y) is triggered
@@ -1367,11 +1346,20 @@
// (apply (thin_to_thick_function f)) to (apply f)
if (auto *TTTFI = dyn_cast<ThinToThickFunctionInst>(AI->getCallee())) {
- // We currently don't remove any possible retain associated with the thick
- // function when rewriting the callsite. This should be ok because the
- // ABI normally expects a guaranteed callee.
- if (!AI->getOrigCalleeType()->isCalleeConsumed())
- return rewriteApplyCallee(AI, TTTFI->getOperand()).getInstruction();
+ // TODO: Handle substitutions and indirect results
+ if (AI->hasSubstitutions() || AI->hasIndirectResults())
+ return nullptr;
+ SmallVector<SILValue, 4> Arguments;
+ for (auto &Op : AI->getArgumentOperands()) {
+ Arguments.push_back(Op.get());
+ }
+ // The type of the substitution is the source type of the thin to thick
+ // instruction.
+ Builder.addOpenedArchetypeOperands(AI);
+ auto *NewAI = Builder.createApply(AI->getLoc(), TTTFI->getOperand(),
+ AI->getSubstitutions(), Arguments,
+ AI->isNonThrowing());
+ return NewAI;
}
// (apply (witness_method)) -> propagate information about
@@ -1489,12 +1477,21 @@
// (try_apply (thin_to_thick_function f)) to (try_apply f)
if (auto *TTTFI = dyn_cast<ThinToThickFunctionInst>(AI->getCallee())) {
- // We currently don't remove any possible retain associated with the thick
- // function when rewriting the callsite. This should be ok because the
- // ABI normally expects a guaranteed callee.
- if (!AI->getOrigCalleeType()->isCalleeConsumed())
- return rewriteApplyCallee(AI, TTTFI->getOperand()).getInstruction();
+ // TODO: Handle substitutions and indirect results
+ if (AI->hasSubstitutions() || AI->hasIndirectResults())
+ return nullptr;
+ SmallVector<SILValue, 4> Arguments;
+ for (auto &Op : AI->getArgumentOperands()) {
+ Arguments.push_back(Op.get());
+ }
+ // The type of the substitution is the source type of the thin to thick
+ // instruction.
+ auto *NewAI = Builder.createTryApply(AI->getLoc(), TTTFI->getOperand(),
+ AI->getSubstitutions(), Arguments,
+ AI->getNormalBB(), AI->getErrorBB());
+ return NewAI;
}
+
// (apply (witness_method)) -> propagate information about
// a concrete type from init_existential_addr or init_existential_ref.
if (auto *WMI = dyn_cast<WitnessMethodInst>(AI->getCallee())) {
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 4773f3e..0318c5b 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -1998,12 +1998,14 @@
patternElt.first->setType(patternElt.second);
for (auto paramDeclElt : ParamDeclTypes) {
- assert(!paramDeclElt.first->isLet() || !paramDeclElt.second->is<InOutType>());
+ assert(!paramDeclElt.first->isImmutable() ||
+ !paramDeclElt.second->is<InOutType>());
paramDeclElt.first->setType(paramDeclElt.second->getInOutObjectType());
}
for (auto paramDeclIfaceElt : ParamDeclInterfaceTypes) {
- assert(!paramDeclIfaceElt.first->isLet() || !paramDeclIfaceElt.second->is<InOutType>());
+ assert(!paramDeclIfaceElt.first->isImmutable() ||
+ !paramDeclIfaceElt.second->is<InOutType>());
paramDeclIfaceElt.first->setInterfaceType(paramDeclIfaceElt.second->getInOutObjectType());
}
@@ -6471,10 +6473,10 @@
// 'inout' from type because that might help to diagnose actual problem
// e.g. type inference doesn't give us much information anyway.
if (param->isInOut() && paramType->hasUnresolvedType()) {
- assert(!param->isLet() || !paramType->is<InOutType>());
+ assert(!param->isImmutable() || !paramType->is<InOutType>());
param->setType(CS.getASTContext().TheUnresolvedType);
param->setInterfaceType(paramType->getInOutObjectType());
- param->setSpecifier(swift::VarDecl::Specifier::Owned);
+ param->setSpecifier(swift::VarDecl::Specifier::Default);
}
}
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index a66963f..497f0ce 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -1954,7 +1954,7 @@
if (auto type = param->getTypeLoc().getType()) {
// FIXME: Need a better locator for a pattern as a base.
Type openedType = CS.openUnboundGenericType(type, locator);
- assert(!param->isLet() || !openedType->is<InOutType>());
+ assert(!param->isImmutable() || !openedType->is<InOutType>());
param->setType(openedType->getInOutObjectType());
param->setInterfaceType(openedType->getInOutObjectType());
continue;
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index f506284..451f047 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -1007,32 +1007,14 @@
// Compare the type variable bindings.
auto &tc = cs.getTypeChecker();
for (auto &binding : diff.typeBindings) {
- auto type1 = binding.bindings[idx1];
- auto type2 = binding.bindings[idx2];
-
- auto &impl = binding.typeVar->getImpl();
-
- if (auto *locator = impl.getLocator()) {
- auto path = locator->getPath();
- if (!path.empty() &&
- path.back().getKind() == ConstraintLocator::ClosureResult) {
- // Since we support `() -> T` to `() -> Void` and
- // `() -> Never` to `() -> T` conversions, it's always
- // preferable to pick `T` rather than `Never` with
- // all else being equal.
- if (type2->isUninhabited())
- ++score1;
-
- if (type1->isUninhabited())
- ++score2;
- }
- }
-
// If the type variable isn't one for which we should be looking at the
// bindings, don't.
- if (!impl.prefersSubtypeBinding())
+ if (!binding.typeVar->getImpl().prefersSubtypeBinding())
continue;
+ auto type1 = binding.bindings[idx1];
+ auto type2 = binding.bindings[idx2];
+
// If the types are equivalent, there's nothing more to do.
if (type1->isEqual(type2))
continue;
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index e3eddf2..a2b3578 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1212,8 +1212,10 @@
return result;
// Result type can be covariant (or equal).
- return matchTypes(func1->getResult(), func2->getResult(), subKind, subflags,
- locator.withPathElement(ConstraintLocator::FunctionResult));
+ return matchTypes(func1->getResult(), func2->getResult(), subKind,
+ subflags,
+ locator.withPathElement(
+ ConstraintLocator::FunctionResult));
}
ConstraintSystem::TypeMatchResult
@@ -1499,8 +1501,6 @@
ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator) {
- auto origType1 = type1;
-
bool isArgumentTupleConversion
= kind == ConstraintKind::ArgumentTupleConversion ||
kind == ConstraintKind::OperatorArgumentTupleConversion;
@@ -2243,32 +2243,7 @@
// Allow '() -> T' to '() -> ()' and '() -> Never' to '() -> T' for closure
// literals.
if (auto elt = locator.last()) {
- auto isClosureResult = [&]() {
- if (elt->getKind() == ConstraintLocator::ClosureResult)
- return true;
-
- // If constraint is matching function results where
- // left-hand side is a 'closure result' we need to allow
- // certain implicit conversions.
- if (elt->getKind() != ConstraintLocator::FunctionResult)
- return false;
-
- if (auto *typeVar = origType1->getAs<TypeVariableType>()) {
- auto *locator = typeVar->getImpl().getLocator();
- if (!locator)
- return false;
-
- auto path = locator->getPath();
- if (path.empty())
- return false;
-
- return path.back().getKind() == ConstraintLocator::ClosureResult;
- }
-
- return false;
- };
-
- if (isClosureResult()) {
+ if (elt->getKind() == ConstraintLocator::ClosureResult) {
if (concrete && kind >= ConstraintKind::Subtype &&
(type1->isUninhabited() || type2->isVoid())) {
increaseScore(SK_FunctionConversion);
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 836b3cd..2dcc3fb 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -203,11 +203,9 @@
// Add a "(value : T, indices...)" argument list.
auto storageType = getTypeOfStorage(storage, false);
auto storageInterfaceType = getTypeOfStorage(storage, true);
- valueDecl = buildArgument(storage->getLoc(),
- storage->getDeclContext(), "value",
- storageType,
- storageInterfaceType,
- VarDecl::Specifier::Owned);
+ valueDecl = buildArgument(storage->getLoc(), storage->getDeclContext(),
+ "value", storageType, storageInterfaceType,
+ VarDecl::Specifier::Default);
params.push_back(buildIndexForwardingParamList(storage, valueDecl));
Type setterRetTy = TupleType::getEmpty(TC.Context);
@@ -314,15 +312,10 @@
// inout storage: Builtin.UnsafeValueBuffer,
// indices...).
ParamDecl *bufferElements[] = {
- buildArgument(loc, DC, "buffer",
- ctx.TheRawPointerType,
- ctx.TheRawPointerType,
- VarDecl::Specifier::Owned),
- buildArgument(loc, DC, "callbackStorage",
- ctx.TheUnsafeValueBufferType,
- ctx.TheUnsafeValueBufferType,
- VarDecl::Specifier::InOut)
- };
+ buildArgument(loc, DC, "buffer", ctx.TheRawPointerType,
+ ctx.TheRawPointerType, VarDecl::Specifier::Default),
+ buildArgument(loc, DC, "callbackStorage", ctx.TheUnsafeValueBufferType,
+ ctx.TheUnsafeValueBufferType, VarDecl::Specifier::InOut)};
params.push_back(buildIndexForwardingParamList(storage, bufferElements));
// The accessor returns (temporary: Builtin.RawPointer,
@@ -1369,18 +1362,16 @@
assert(interfaceTy);
auto contextTy = declaredParamTy.subst(contextMap);
assert(contextTy);
+ auto declaredSpecifier = declaredParam->getSpecifier();
SmallString<64> ParamNameBuf;
{
llvm::raw_svector_ostream names(ParamNameBuf);
names << "%arg." << i;
}
- auto param = new (Context) ParamDecl(VarDecl::Specifier::Owned,
- SourceLoc(), SourceLoc(),
- Identifier(),
- SourceLoc(),
- Context.getIdentifier(ParamNameBuf),
- contextTy, DC);
+ auto param = new (Context) ParamDecl(
+ declaredSpecifier, SourceLoc(), SourceLoc(), Identifier(), SourceLoc(),
+ Context.getIdentifier(ParamNameBuf), contextTy, DC);
param->setInterfaceType(interfaceTy);
param->setImplicit();
Params.push_back(param);
@@ -1936,9 +1927,9 @@
}
// Create the parameter.
- auto *arg = new (context) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),
- Loc, var->getName(),
- Loc, var->getName(), varType, decl);
+ auto *arg = new (context)
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), Loc,
+ var->getName(), Loc, var->getName(), varType, decl);
arg->setInterfaceType(varInterfaceType);
arg->setImplicit();
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 62cfdfc..d53187a 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1433,7 +1433,7 @@
overloads.push_back(bindOverloadConstraint);
}
- for (auto choice : choices) {
+ for (auto &choice : choices) {
if (favoredChoice && (favoredChoice == &choice))
continue;
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index d96e8c7..b6ad8fa 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -484,9 +484,9 @@
Expr *base, Type returnType,
NominalTypeDecl *param) {
// (keyedBy:)
- auto *keyedByDecl = new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),
- SourceLoc(), C.Id_keyedBy, SourceLoc(),
- C.Id_keyedBy, returnType, DC);
+ auto *keyedByDecl = new (C)
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ C.Id_keyedBy, SourceLoc(), C.Id_keyedBy, returnType, DC);
keyedByDecl->setImplicit();
keyedByDecl->setInterfaceType(returnType);
@@ -727,9 +727,9 @@
// Params: (self [implicit], Encoder)
auto *selfDecl = ParamDecl::createSelf(SourceLoc(), target);
- auto *encoderParam = new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),
- SourceLoc(), C.Id_to, SourceLoc(),
- C.Id_encoder, encoderType, target);
+ auto *encoderParam = new (C)
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(), C.Id_to,
+ SourceLoc(), C.Id_encoder, encoderType, target);
encoderParam->setInterfaceType(encoderType);
ParameterList *params[] = {ParameterList::createWithoutLoc(selfDecl),
@@ -1065,11 +1065,9 @@
auto *selfDecl = ParamDecl::createSelf(SourceLoc(), target,
/*isStatic=*/false,
/*isInOut=*/inOut);
- auto *decoderParamDecl = new (C) ParamDecl(VarDecl::Specifier::Owned,
- SourceLoc(),
- SourceLoc(), C.Id_from,
- SourceLoc(), C.Id_decoder,
- decoderType, target);
+ auto *decoderParamDecl = new (C)
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ C.Id_from, SourceLoc(), C.Id_decoder, decoderType, target);
decoderParamDecl->setImplicit();
decoderParamDecl->setInterfaceType(decoderType);
diff --git a/lib/Sema/DerivedConformanceCodingKey.cpp b/lib/Sema/DerivedConformanceCodingKey.cpp
index 2a03c5b..d1eb3fa 100644
--- a/lib/Sema/DerivedConformanceCodingKey.cpp
+++ b/lib/Sema/DerivedConformanceCodingKey.cpp
@@ -74,10 +74,9 @@
DeclNameLoc(), /*Implicit=*/true);
// rawValue param to init(rawValue:)
- auto *rawValueDecl = new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),
- SourceLoc(), C.Id_rawValue,
- SourceLoc(), C.Id_rawValue,
- valueParam->getType(), parentDC);
+ auto *rawValueDecl = new (C) ParamDecl(
+ VarDecl::Specifier::Default, SourceLoc(), SourceLoc(), C.Id_rawValue,
+ SourceLoc(), C.Id_rawValue, valueParam->getType(), parentDC);
rawValueDecl->setInterfaceType(C.getIntDecl()->getDeclaredType());
rawValueDecl->setImplicit();
auto *paramList = ParameterList::createWithoutLoc(rawValueDecl);
@@ -124,9 +123,9 @@
auto *parentDC = cast<DeclContext>(parentDecl);
// rawValue
- auto *rawDecl = new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(),
- paramName, SourceLoc(), paramName,
- paramType, parentDC);
+ auto *rawDecl =
+ new (C) ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ paramName, SourceLoc(), paramName, paramType, parentDC);
rawDecl->setInterfaceType(paramType);
rawDecl->setImplicit();
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 8cb788c..abf95b5 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -591,10 +591,10 @@
auto enumTy = parentDC->getDeclaredTypeInContext();
auto enumIfaceTy = parentDC->getDeclaredInterfaceType();
- auto getParamDecl = [&](StringRef s) -> ParamDecl* {
- auto *param = new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(),
- Identifier(), SourceLoc(), C.getIdentifier(s),
- enumTy, parentDC);
+ auto getParamDecl = [&](StringRef s) -> ParamDecl * {
+ auto *param = new (C) ParamDecl(VarDecl::Specifier::Default, SourceLoc(),
+ SourceLoc(), Identifier(), SourceLoc(),
+ C.getIdentifier(s), enumTy, parentDC);
param->setInterfaceType(enumIfaceTy);
return param;
};
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index 43a12a8..e3aaa99 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -292,9 +292,9 @@
auto *selfDecl = ParamDecl::createSelf(SourceLoc(), parentDC,
/*static*/false, /*inout*/true);
- auto *rawDecl = new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(),
- C.Id_rawValue, SourceLoc(),
- C.Id_rawValue, rawType, parentDC);
+ auto *rawDecl = new (C)
+ ParamDecl(VarDecl::Specifier::Default, SourceLoc(), SourceLoc(),
+ C.Id_rawValue, SourceLoc(), C.Id_rawValue, rawType, parentDC);
rawDecl->setInterfaceType(rawInterfaceType);
rawDecl->setImplicit();
auto paramList = ParameterList::createWithoutLoc(rawDecl);
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 7c5c911..548bbe7 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -2411,7 +2411,7 @@
// If this is a 'let' value, any stores to it are actually initializations,
// not mutations.
auto isWrittenLet = false;
- if (var->isLet() || var->isShared()) {
+ if (var->isImmutable()) {
isWrittenLet = (access & RK_Written) != 0;
access &= ~RK_Written;
}
@@ -2550,7 +2550,7 @@
// If this is a mutable 'var', and it was never written to, suggest
// upgrading to 'let'. We do this even for a parameter.
- if (!(var->isLet() || var->isShared()) && (access & RK_Written) == 0 &&
+ if (!var->isImmutable() && (access & RK_Written) == 0 &&
// Don't warn if we have something like "let (x,y) = ..." and 'y' was
// never mutated, but 'x' was.
!isVarDeclPartOfPBDThatHadSomeMutation(var)) {
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 0410e3e..879d4c0 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -693,7 +693,7 @@
storageKind = SK_Subscript;
else if (storage->getDeclContext()->isTypeContext())
storageKind = SK_Property;
- else if (cast<VarDecl>(storage)->isLet())
+ else if (cast<VarDecl>(storage)->isImmutable())
storageKind = SK_Constant;
else
storageKind = SK_Variable;
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 09d7ce0..d7ddff3 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -1219,8 +1219,8 @@
// 'self' is 'let' for reference types (i.e., classes) or when 'self' is
// neither inout.
auto specifier = selfParam.getParameterFlags().isInOut()
- ? VarDecl::Specifier::InOut
- : VarDecl::Specifier::Owned;
+ ? VarDecl::Specifier::InOut
+ : VarDecl::Specifier::Default;
selfDecl->setSpecifier(specifier);
selfDecl->setInterfaceType(selfParam.getPlainType());
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 4bfcae2..414f497 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -787,10 +787,8 @@
// If the param is not a 'let' and it is not an 'inout'.
// It must be a 'var'. Provide helpful diagnostics like a shadow copy
// in the function body to fix the 'var' attribute.
- if (!decl->isLet() &&
- !decl->isImplicit() &&
- (Ty.isNull() || !Ty->is<InOutType>()) &&
- !hadError) {
+ if (!decl->isImmutable() && !decl->isImplicit() &&
+ (Ty.isNull() || !Ty->is<InOutType>()) && !hadError) {
decl->setInvalid();
hadError = true;
}
@@ -866,6 +864,8 @@
param->setSpecifier(VarDecl::Specifier::InOut);
} else if (isa<SharedTypeRepr>(typeRepr)) {
param->setSpecifier(VarDecl::Specifier::Shared);
+ } else if (isa<OwnedTypeRepr>(typeRepr)) {
+ param->setSpecifier(VarDecl::Specifier::Owned);
}
}
}
@@ -1616,7 +1616,7 @@
// Coerce explicitly specified argument type to contextual type
// only if both types are valid and do not match.
if (!hadError && isValidType(ty) && !ty->isEqual(paramType)) {
- assert(!param->isLet() || !ty->is<InOutType>());
+ assert(!param->isImmutable() || !ty->is<InOutType>());
param->setType(ty->getInOutObjectType());
param->setInterfaceType(ty->mapTypeOutOfContext()->getInOutObjectType());
}
@@ -1636,7 +1636,7 @@
// trying to coerce argument to contextual type would mean erasing
// valuable diagnostic information.
if (isValidType(ty) || shouldOverwriteParam(param)) {
- assert(!param->isLet() || !ty->is<InOutType>());
+ assert(!param->isImmutable() || !ty->is<InOutType>());
param->setType(ty->getInOutObjectType());
param->setInterfaceType(ty->mapTypeOutOfContext()->getInOutObjectType());
}
diff --git a/lib/Sema/TypeCheckREPL.cpp b/lib/Sema/TypeCheckREPL.cpp
index 5caea72..f9a54dc 100644
--- a/lib/Sema/TypeCheckREPL.cpp
+++ b/lib/Sema/TypeCheckREPL.cpp
@@ -229,10 +229,9 @@
TopLevelCodeDecl *newTopLevel = new (Context) TopLevelCodeDecl(&SF);
// Build function of type T->() which prints the operand.
- auto *Arg = new (Context) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),
- SourceLoc(), Identifier(),
- Loc, Context.getIdentifier("arg"),
- E->getType(), /*DC*/ newTopLevel);
+ auto *Arg = new (Context) ParamDecl(
+ VarDecl::Specifier::Default, SourceLoc(), SourceLoc(), Identifier(), Loc,
+ Context.getIdentifier("arg"), E->getType(), /*DC*/ newTopLevel);
Arg->setInterfaceType(E->getType());
auto params = ParameterList::createWithoutLoc(Arg);
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 3675890..a6b7ced 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -1655,11 +1655,8 @@
// Strip the "is function input" bits unless this is a type that knows about
// them.
- if (!isa<InOutTypeRepr>(repr) &&
- !isa<SharedTypeRepr>(repr) &&
- !isa<TupleTypeRepr>(repr) &&
- !isa<AttributedTypeRepr>(repr) &&
- !isa<FunctionTypeRepr>(repr) &&
+ if (!isa<SpecifierTypeRepr>(repr) && !isa<TupleTypeRepr>(repr) &&
+ !isa<AttributedTypeRepr>(repr) && !isa<FunctionTypeRepr>(repr) &&
!isa<IdentTypeRepr>(repr)) {
options -= TypeResolutionFlags::ImmediateFunctionInput;
options -= TypeResolutionFlags::FunctionInput;
@@ -1677,6 +1674,7 @@
return resolveAttributedType(cast<AttributedTypeRepr>(repr), options);
case TypeReprKind::InOut:
case TypeReprKind::Shared:
+ case TypeReprKind::Owned:
return resolveSpecifierTypeRepr(cast<SpecifierTypeRepr>(repr), options);
case TypeReprKind::SimpleIdent:
@@ -2656,10 +2654,21 @@
} else {
diagID = diag::attr_only_on_parameters;
}
- TC.diagnose(repr->getSpecifierLoc(), diagID,
- (repr->getKind() == TypeReprKind::InOut)
- ? "'inout'"
- : "'__shared'");
+ StringRef name;
+ switch (repr->getKind()) {
+ case TypeReprKind::InOut:
+ name = "'inout'";
+ break;
+ case TypeReprKind::Shared:
+ name = "'__shared'";
+ break;
+ case TypeReprKind::Owned:
+ name = "'__owned'";
+ break;
+ default:
+ llvm_unreachable("unknown SpecifierTypeRepr kind");
+ }
+ TC.diagnose(repr->getSpecifierLoc(), diagID, name);
repr->setInvalid();
return ErrorType::get(Context);
}
@@ -2860,6 +2869,9 @@
case TypeReprKind::InOut:
ownership = ValueOwnership::InOut;
break;
+ case TypeReprKind::Owned:
+ ownership = ValueOwnership::Owned;
+ break;
default:
ownership = ValueOwnership::Default;
break;
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 8d0c1db..4d215a0 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2090,6 +2090,7 @@
CASE(Var)
CASE(InOut)
CASE(Shared)
+ CASE(Owned)
}
#undef CASE
return None;
@@ -4055,6 +4056,7 @@
CASE(Default)
CASE(InOut)
CASE(Shared)
+ CASE(Owned)
#undef CASE
}
return None;
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 2135e46..56072c7 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -2607,7 +2607,8 @@
// Another SIL_VTABLE record means the end of this VTable.
while (kind != SIL_VTABLE && kind != SIL_WITNESS_TABLE &&
kind != SIL_DEFAULT_WITNESS_TABLE &&
- kind != SIL_FUNCTION) {
+ kind != SIL_FUNCTION &&
+ kind != SIL_PROPERTY) {
assert(kind == SIL_VTABLE_ENTRY &&
"Content of Vtable should be in SIL_VTABLE_ENTRY.");
ArrayRef<uint64_t> ListOfValues;
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index dfeb917..7833007 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -2523,6 +2523,8 @@
return uint8_t(serialization::VarDeclSpecifier::InOut);
case swift::VarDecl::Specifier::Shared:
return uint8_t(serialization::VarDeclSpecifier::Shared);
+ case swift::VarDecl::Specifier::Owned:
+ return uint8_t(serialization::VarDeclSpecifier::Owned);
}
llvm_unreachable("bad variable decl specifier kind");
}
@@ -3495,6 +3497,7 @@
SIMPLE_CASE(ValueOwnership, Default)
SIMPLE_CASE(ValueOwnership, InOut)
SIMPLE_CASE(ValueOwnership, Shared)
+ SIMPLE_CASE(ValueOwnership, Owned)
}
llvm_unreachable("bad ownership kind");
}
diff --git a/stdlib/public/Reflection/TypeRef.cpp b/stdlib/public/Reflection/TypeRef.cpp
index e9cc98f..db1d588 100644
--- a/stdlib/public/Reflection/TypeRef.cpp
+++ b/stdlib/public/Reflection/TypeRef.cpp
@@ -145,15 +145,24 @@
OS << '\n';
}
- if (flags.isInOut())
+ switch (flags.getValueOwnership()) {
+ case ValueOwnership::Default:
+ /* nothing */
+ break;
+ case ValueOwnership::InOut:
printHeader("inout");
+ break;
+ case ValueOwnership::Shared:
+ printHeader("shared");
+ break;
+ case ValueOwnership::Owned:
+ printHeader("owned");
+ break;
+ }
if (flags.isVariadic())
printHeader("variadic");
- if (flags.isShared())
- printHeader("shared");
-
printRec(param.getType());
if (!flags.isNone()) {
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index f2d0eab..39cdc31 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -625,7 +625,16 @@
/// almost never is.
@_inlineable // FIXME(sil-serialize-all)
public var ulp: ${Self} {
- if !isFinite { return ${Self}.nan }
+%if bits != 80:
+ guard _fastPath(isFinite) else { return .nan }
+ if _fastPath(isNormal) {
+ let bitPattern_ = bitPattern & ${Self}.infinity.bitPattern
+ return ${Self}(bitPattern: bitPattern_) * 0x1p-${SignificandBitCount}
+ }
+ // On arm, flush subnormal values to 0.
+ return .leastNormalMagnitude * 0x1p-${SignificandBitCount}
+%else:
+ guard _fastPath(isFinite) else { return .nan }
if exponentBitPattern > UInt(${Self}.significandBitCount) {
// self is large enough that self.ulp is normal, so we just compute its
// exponent and construct it with a significand of zero.
@@ -645,6 +654,7 @@
return ${Self}(sign: .plus,
exponentBitPattern: 0,
significandBitPattern: 1)
+%end
}
/// The least positive normal number.
@@ -917,17 +927,23 @@
/// - If `x` is `greatestFiniteMagnitude`, then `x.nextUp` is `infinity`.
@_inlineable // FIXME(sil-serialize-all)
public var nextUp: ${Self} {
- if isNaN { return self }
- if sign == .minus {
+%if bits != 80:
+ // Silence signaling NaNs, map -0 to +0.
+ let x = self + 0
#if arch(arm)
- // On arm, subnormals are flushed to zero.
- if (exponentBitPattern == 1 && significandBitPattern == 0) ||
- (exponentBitPattern == 0 && significandBitPattern != 0) {
- return ${Self}(sign: .minus,
- exponentBitPattern: 0,
- significandBitPattern: 0)
- }
+ // On arm, treat subnormal values as zero.
+ if _slowPath(x == 0) { return .leastNonzeroMagnitude }
+ if _slowPath(x == -.leastNonzeroMagnitude) { return -0.0 }
#endif
+ if _fastPath(x < .infinity) {
+ let increment = Int${bits}(bitPattern: x.bitPattern) &>> ${bits - 1} | 1
+ let bitPattern_ = x.bitPattern &+ UInt${bits}(bitPattern: increment)
+ return ${Self}(bitPattern: bitPattern_)
+ }
+ return x
+%else:
+ if isNaN { /* Silence signaling NaNs. */ return self + 0 }
+ if sign == .minus {
if significandBitPattern == 0 {
if exponentBitPattern == 0 {
return .leastNonzeroMagnitude
@@ -946,15 +962,10 @@
exponentBitPattern: exponentBitPattern + 1,
significandBitPattern: 0)
}
-#if arch(arm)
- // On arm, subnormals are skipped.
- if exponentBitPattern == 0 {
- return .leastNonzeroMagnitude
- }
-#endif
return ${Self}(sign: .plus,
exponentBitPattern: exponentBitPattern,
significandBitPattern: significandBitPattern + 1)
+%end
}
/// Rounds the value to an integral value using the specified rounding rule.
@@ -1360,7 +1371,19 @@
/// // y.exponent == 4
@_inlineable // FIXME(sil-serialize-all)
public var binade: ${Self} {
- if !isFinite { return .nan }
+%if bits != 80:
+ guard _fastPath(isFinite) else { return .nan }
+#if !arch(arm)
+ if _slowPath(isSubnormal) {
+ let bitPattern_ =
+ (self * 0x1p${SignificandBitCount}).bitPattern
+ & (-${Self}.infinity).bitPattern
+ return ${Self}(bitPattern: bitPattern_) * 0x1p-${SignificandBitCount}
+ }
+#endif
+ return ${Self}(bitPattern: bitPattern & (-${Self}.infinity).bitPattern)
+%else:
+ guard _fastPath(isFinite) else { return .nan }
if exponentBitPattern != 0 {
return ${Self}(sign: sign, exponentBitPattern: exponentBitPattern,
significandBitPattern: 0)
@@ -1370,6 +1393,7 @@
let index = significandBitPattern._binaryLogarithm()
return ${Self}(sign: sign, exponentBitPattern: 0,
significandBitPattern: 1 &<< index)
+%end
}
/// The number of bits required to represent the value's significand.
@@ -1481,6 +1505,7 @@
% if bits == builtinFloatLiteralBits:
self = ${Self}(_bits: value)
% elif bits < builtinFloatLiteralBits:
+ // FIXME: This can result in double rounding errors (SR-7124).
self = ${Self}(_bits: Builtin.fptrunc_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
% else:
// FIXME: This is actually losing precision <rdar://problem/14073102>.
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index af0d7fe..760dd58 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -495,14 +495,24 @@
auto flags = func->getParameterFlags(i);
auto input = _swift_buildDemanglingForMetadata(param, Dem);
- if (flags.isInOut()) {
- NodePointer inout = Dem.createNode(Node::Kind::InOut);
- inout->addChild(input, Dem);
- input = inout;
- } else if (flags.isShared()) {
- NodePointer shared = Dem.createNode(Node::Kind::Shared);
- shared->addChild(input, Dem);
- input = shared;
+ auto wrapInput = [&](Node::Kind kind) {
+ auto parent = Dem.createNode(kind);
+ parent->addChild(input, Dem);
+ input = parent;
+ };
+ switch (flags.getValueOwnership()) {
+ case ValueOwnership::Default:
+ /* nothing */
+ break;
+ case ValueOwnership::InOut:
+ wrapInput(Node::Kind::InOut);
+ break;
+ case ValueOwnership::Shared:
+ wrapInput(Node::Kind::Shared);
+ break;
+ case ValueOwnership::Owned:
+ wrapInput(Node::Kind::Owned);
+ break;
}
inputs.push_back({input, flags.isVariadic()});
diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift
index ed45e11..005ba6c 100644
--- a/test/Constraints/closures.swift
+++ b/test/Constraints/closures.swift
@@ -630,6 +630,7 @@
let iter = I_33429010()
var acc: Int = 0 // expected-warning {{}}
let _: Int = AnySequence { iter }.rdar33429010(into: acc, { $0 + $1 })
+ // expected-warning@-1 {{result of operator '+' is unused}}
let _: Int = AnySequence { iter }.rdar33429010(into: acc, { $0.rdar33429010_incr($1) })
}
@@ -651,38 +652,3 @@
str.replaceSubrange(range, with: str[range].reversed())
}])
}
-
-protocol P_37790062 {
- associatedtype T
- var elt: T { get }
-}
-
-func rdar37790062() {
- struct S<T> {
- init(_ a: () -> T, _ b: () -> T) {}
- }
-
- class C1 : P_37790062 {
- typealias T = Int
- var elt: T { return 42 }
- }
-
- class C2 : P_37790062 {
- typealias T = (String, Int, Void)
- var elt: T { return ("question", 42, ()) }
- }
-
- func foo() -> Int { return 42 }
- func bar() -> Void {}
- func baz() -> (String, Int) { return ("question", 42) }
- func bzz<T>(_ a: T) -> T { return a }
- func faz<T: P_37790062>(_ a: T) -> T.T { return a.elt }
-
- _ = S({ foo() }, { bar() }) // Ok, should infer T to be 'Void'
- _ = S({ baz() }, { bar() }) // Ok, should infer T to be 'Void'
- _ = S({ bzz(("question", 42)) }, { bar() }) // Ok
- _ = S({ bzz(String.self) }, { bar() }) // Ok
- _ = S({ bzz(((), (()))) }, { bar() }) // Ok
- _ = S({ bzz(C1()) }, { bar() }) // Ok
- _ = S({ faz(C2()) }, { bar() }) // Ok
-}
diff --git a/test/Constraints/rdar37790062.swift b/test/Constraints/rdar37790062.swift
deleted file mode 100644
index 13d2f8c..0000000
--- a/test/Constraints/rdar37790062.swift
+++ /dev/null
@@ -1,46 +0,0 @@
-// RUN: %target-typecheck-verify-swift
-
-protocol A {
- associatedtype V
- associatedtype E: Error
-
- init(value: V)
- init(error: E)
-
- func foo<U>(value: (V) -> U, error: (E) -> U) -> U
-}
-
-enum R<T, E: Error> : A {
- case foo(T)
- case bar(E)
-
- init(value: T) { self = .foo(value) }
- init(error: E) { self = .bar(error) }
-
- func foo<R>(value: (T) -> R, error: (E) -> R) -> R {
- fatalError()
- }
-}
-
-protocol P {
- associatedtype V
-
- @discardableResult
- func baz(callback: @escaping (V) -> Void) -> Self
-}
-
-class C<V> : P {
- func baz(callback: @escaping (V) -> Void) -> Self { return self }
-}
-class D<T, E: Error> : C<R<T, E>> {
- init(fn: (_ ret: @escaping (V) -> Void) -> Void) {}
-}
-
-extension A where V: P, V.V: A, E == V.V.E {
- func bar() -> D<V.V.V, V.V.E> {
- return D { complete in
- foo(value: { promise in promise.baz { result in } },
- error: { complete(R(error: $0)) })
- }
- }
-}
diff --git a/test/IRGen/objc_retainAutoreleasedReturnValue.swift b/test/IRGen/objc_retainAutoreleasedReturnValue.swift
index 204c791..a8d1a27 100644
--- a/test/IRGen/objc_retainAutoreleasedReturnValue.swift
+++ b/test/IRGen/objc_retainAutoreleasedReturnValue.swift
@@ -24,15 +24,13 @@
// popq %rbp ;<== Blocks the handshake from objc_autoreleaseReturnValue
// jmp 0x01ec20 ; symbol stub for: objc_retainAutoreleasedReturnValue
-// CHECK-LABEL: define {{.*}}swiftcc %TSo12NSEnumeratorC* @"$S34objc_retainAutoreleasedReturnValue4testyySo12NSDictionaryCFSo12NSEnumeratorCADXEfU_"(%TSo12NSDictionaryC*)
+// CHECK-LABEL: define {{.*}}swiftcc void @"$S34objc_retainAutoreleasedReturnValue4testyySo12NSDictionaryCFyADXEfU_"(%TSo12NSDictionaryC*)
// CHECK: entry:
// CHECK: call {{.*}}@objc_msgSend
// CHECK: notail call i8* @objc_retainAutoreleasedReturnValue
-// CHECK: ret %TSo12NSEnumeratorC*
+// CHECK: ret void
-// CHECK-LABEL: define {{.*}}swiftcc void @"$SSo12NSDictionaryCSo12NSEnumeratorCIgxo_ABIegx_TR"(%TSo12NSDictionaryC*, i8*, %swift.opaque*)
-
-// OPT-LABEL: define {{.*}}swiftcc void @"$S34objc_retainAutoreleasedReturnValue10useClosureyySo12NSDictionaryC_yADXEtF06$SSo12h44CSo12NSEnumeratorCIgxo_ABIegx_TR049$S34objc_bcD42Value4testyySo12a6CFSo12B8CADXEfU_Tf3npf_nTf1nc_nTf4g_n"(%TSo12NSDictionaryC*)
+// OPT-LABEL: define {{.*}}swiftcc void @"$S34objc_retainAutoreleasedReturnValue4testyySo12NSDictionaryCFyADXEfU_"(%TSo12NSDictionaryC*)
// OPT: entry:
// OPT: call {{.*}}@objc_msgSend
// OPT: notail call i8* @objc_retainAutoreleasedReturnValue
diff --git a/test/Interpreter/protocol_initializers.swift b/test/Interpreter/protocol_initializers.swift
index 48826cf..513fa36 100644
--- a/test/Interpreter/protocol_initializers.swift
+++ b/test/Interpreter/protocol_initializers.swift
@@ -4,6 +4,9 @@
// RUN: %target-run %t/a.out
// REQUIRES: executable_test
+// FIXME: <https://bugs.swift.org/browse/SR-7138> 2 tests are failing on linux in optimized mode
+// UNSUPPORTED: OS=linux-gnu
+
import StdlibUnittest
var ProtocolInitTestSuite = TestSuite("ProtocolInit")
diff --git a/test/Parse/invalid.swift b/test/Parse/invalid.swift
index fdfe9b3..3cb9fc7 100644
--- a/test/Parse/invalid.swift
+++ b/test/Parse/invalid.swift
@@ -13,9 +13,9 @@
// expected-error @-1 {{'__shared' before a parameter name is not allowed, place it before the parameter type instead}} {{13-21=}} {{30-30=__shared }}
func test1o(__owned var x : Int) {} // expected-error {{parameter must not have multiple '__owned', 'inout', '__shared', 'var', or 'let' specifiers}} {{21-25=}}
-// expected-error @-1 {{'__owned' as a parameter attribute is not allowed}} {{13-20=}}
+// expected-error @-1 {{'__owned' before a parameter name is not allowed, place it before the parameter type instead}} {{13-20=}}
func test2o(__owned let x : Int) {} // expected-error {{parameter must not have multiple '__owned', 'inout', '__shared', 'var', or 'let' specifiers}} {{21-25=}}
-// expected-error @-1 {{'__owned' as a parameter attribute is not allowed}} {{13-20=}}
+// expected-error @-1 {{'__owned' before a parameter name is not allowed, place it before the parameter type instead}} {{13-20=}}
func test3() {
undeclared_func( // expected-error {{use of unresolved identifier 'undeclared_func'}}
diff --git a/test/SILGen/keypath_property_descriptors.swift b/test/SILGen/keypath_property_descriptors.swift
new file mode 100644
index 0000000..61f306d
--- /dev/null
+++ b/test/SILGen/keypath_property_descriptors.swift
@@ -0,0 +1,80 @@
+// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+
+// TODO: globals should get descriptors
+public var a: Int = 0
+
+@_inlineable
+public var b: Int { return 0 }
+
+@_versioned
+internal var c: Int = 0
+
+// no descriptor
+// CHECK-NOT: sil_property #d
+internal var d: Int = 0
+// CHECK-NOT: sil_property #e
+private var e: Int = 0
+
+public struct A {
+ // CHECK-LABEL: sil_property #A.a
+ public var a: Int = 0
+
+ // CHECK-LABEL: sil_property #A.b
+ @_inlineable
+ public var b: Int { return 0 }
+
+ // CHECK-LABEL: sil_property #A.c
+ @_versioned
+ internal var c: Int = 0
+
+ // no descriptor
+ // CHECK-NOT: sil_property #A.d
+ internal var d: Int = 0
+ // CHECK-NOT: sil_property #A.e
+ fileprivate var e: Int = 0
+ // CHECK-NOT: sil_property #A.f
+ private var f: Int = 0
+
+ // TODO: static vars should get descriptors
+ public static var a: Int = 0
+ @_inlineable
+ public static var b: Int { return 0 }
+ @_versioned
+ internal static var c: Int = 0
+
+ // no descriptor
+ // CHECK-NOT: sil_property #A.d
+ internal static var d: Int = 0
+ // CHECK-NOT: sil_property #A.e
+ fileprivate static var e: Int = 0
+ // CHECK-NOT: sil_property #A.f
+ private static var f: Int = 0
+
+ // CHECK-LABEL: sil_property #A.subscript
+ public subscript(a x: Int) -> Int { return x }
+ // CHECK-LABEL: sil_property #A.subscript
+ @_inlineable
+ public subscript(b x: Int) -> Int { return x }
+ // CHECK-LABEL: sil_property #A.subscript
+ @_versioned
+ internal subscript(c x: Int) -> Int { return x }
+
+ // no descriptor
+ // CHECK-NOT: sil_property #A.subscript
+ internal subscript(d x: Int) -> Int { return x }
+ fileprivate subscript(e x: Int) -> Int { return x }
+ private subscript(f x: Int) -> Int { return x }
+
+ // TODO: Subscripts with non-hashable subscripts should get descriptors
+ public subscript<T>(a x: T) -> T { return x }
+ @_inlineable
+ public subscript<T>(b x: T) -> T { return x }
+ @_versioned
+ internal subscript<T>(c x: T) -> T { return x }
+
+ // no descriptor
+ internal subscript<T>(d x: T) -> T { return x }
+ fileprivate subscript<T>(e x: T) -> T { return x }
+ private subscript<T>(f x: T) -> T { return x }
+}
+
diff --git a/test/SILGen/owned.swift b/test/SILGen/owned.swift
new file mode 100644
index 0000000..bee04be
--- /dev/null
+++ b/test/SILGen/owned.swift
@@ -0,0 +1,24 @@
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership -enable-guaranteed-normal-arguments | %FileCheck %s
+
+// see shared.swift for thunks/conversions between __shared and __owned.
+
+class RefAggregate {}
+struct ValueAggregate { let x = RefAggregate() }
+
+// CHECK-LABEL: sil hidden @$S5owned0A10_arguments7trivial5value3refySin_AA14ValueAggregateVnAA03RefG0CntF : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> () {
+func owned_arguments(trivial : __owned Int, value : __owned ValueAggregate, ref : __owned RefAggregate) {
+ let t = trivial
+ let v = value
+ let r = ref
+}
+
+struct Foo {
+ var x: ValueAggregate
+
+ // CHECK-LABEL: sil hidden @$S5owned3FooV20methodOwnedArguments7trivial5value3refySin_AA14ValueAggregateVnAA03RefJ0CntF : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @guaranteed Foo) -> () {
+ func methodOwnedArguments(trivial : __owned Int, value : __owned ValueAggregate, ref : __owned RefAggregate) {
+ let t = trivial
+ let v = value
+ let r = ref
+ }
+}
diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil
index 0f4a3af..b87ca63 100644
--- a/test/SILOptimizer/sil_combine.sil
+++ b/test/SILOptimizer/sil_combine.sil
@@ -1522,8 +1522,8 @@
sil @eliminate_thin_to_thick_apply : $@convention(thin) () -> () {
bb0:
%0 = function_ref @eliminate_dead_thin_to_thick_function_fun : $@convention(thin) () -> ()
- %1 = thin_to_thick_function %0 : $@convention(thin) () -> () to $@callee_guaranteed () -> ()
- %2 = apply %1() : $@callee_guaranteed () -> ()
+ %1 = thin_to_thick_function %0 : $@convention(thin) () -> () to $@callee_owned () -> ()
+ %2 = apply %1() : $@callee_owned () -> ()
return %2 : $()
}
diff --git a/test/SILOptimizer/sil_combine_apply.sil b/test/SILOptimizer/sil_combine_apply.sil
index d091147..241c6a7 100644
--- a/test/SILOptimizer/sil_combine_apply.sil
+++ b/test/SILOptimizer/sil_combine_apply.sil
@@ -517,56 +517,3 @@
%return = tuple ()
return %return : $()
}
-
-sil shared [transparent] [thunk] @genericClosure : $@convention(thin) <T> (@in T) -> @out T {
-bb0(%0 : $*T, %1 : $*T):
- %12 = tuple ()
- return %12 : $()
-}
-
-// CHECK-LABEL: sil shared @genericThinToThick : $@convention(thin) () -> ()
-// CHECK: [[F:%.*]] = function_ref @genericClosure : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
-// CHECK: apply [[F]]<Builtin.Int64>(%{{.*}}, %{{.*}}) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
-// CHECK-LABEL: } // end sil function 'genericThinToThick'
-sil shared @genericThinToThick : $@convention(thin) () -> () {
-bb0:
- %fn = function_ref @genericClosure : $@convention(thin) <T> (@in T) -> @out T
- %thick = thin_to_thick_function %fn : $@convention(thin) <T> (@in T) -> @out T to $@noescape @callee_guaranteed <T> (@in T) -> @out T
- %in = alloc_stack $Builtin.Int64
- %out = alloc_stack $Builtin.Int64
- %c3 = integer_literal $Builtin.Int64, 3
- store %c3 to %in : $*Builtin.Int64
- %call = apply %thick<Builtin.Int64>(%out, %in) : $@noescape @callee_guaranteed <T> (@in T) -> @out T
- dealloc_stack %out : $*Builtin.Int64
- dealloc_stack %in : $*Builtin.Int64
- %999 = tuple ()
- return %999 : $()
-}
-
-sil shared [transparent] [thunk] @indirectClosure : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64 {
-bb0(%0 : $*Builtin.Int64, %1 : $*Builtin.Int64):
- %val = load %1 : $*Builtin.Int64
- store %val to %0 : $*Builtin.Int64
- %999 = tuple ()
- return %999 : $()
-}
-
-// CHECK-LABEL: sil shared @appliedEscapeToNoEscape : $@convention(thin) () -> () {
-// CHECK: [[F:%.*]] = function_ref @indirectClosure : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64 // user: %5
-// CHECK: apply [[F]](%{{.*}}, %{{.*}}) : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
-sil shared @appliedEscapeToNoEscape : $@convention(thin) () -> () {
-bb0:
- %fn = function_ref @indirectClosure : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
- %pa = partial_apply [callee_guaranteed] %fn() : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
- %cvt = convert_escape_to_noescape %pa : $@callee_guaranteed (@in Builtin.Int64) -> @out Builtin.Int64 to $@noescape @callee_guaranteed (@in Builtin.Int64) -> @out Builtin.Int64
- %out = alloc_stack $Builtin.Int64
- %in = alloc_stack $Builtin.Int64
- %c3 = integer_literal $Builtin.Int64, 3
- store %c3 to %in : $*Builtin.Int64
- %call = apply %cvt(%out, %in) : $@noescape @callee_guaranteed (@in Builtin.Int64) -> @out Builtin.Int64
- dealloc_stack %in : $*Builtin.Int64
- dealloc_stack %out : $*Builtin.Int64
- strong_release %pa : $@callee_guaranteed (@in Builtin.Int64) -> @out Builtin.Int64
- %999 = tuple ()
- return %999 : $()
-}
diff --git a/test/SwiftSyntax/Inputs/closure.swift b/test/SwiftSyntax/Inputs/closure.swift
new file mode 100644
index 0000000..64b2c2a
--- /dev/null
+++ b/test/SwiftSyntax/Inputs/closure.swift
@@ -0,0 +1,3 @@
+// A closure without a signature. The test will ensure it stays the same after
+// applying a rewriting pass.
+let x: () -> Void = {}
\ No newline at end of file
diff --git a/test/SwiftSyntax/VisitorTest.swift b/test/SwiftSyntax/VisitorTest.swift
index 4a8ade8..7d9b0ae 100644
--- a/test/SwiftSyntax/VisitorTest.swift
+++ b/test/SwiftSyntax/VisitorTest.swift
@@ -37,4 +37,20 @@
})
}
+VisitorTests.test("RewritingNodeWithEmptyChild") {
+ class ClosureRewriter: SyntaxRewriter {
+ override func visit(_ node: ClosureExprSyntax) -> ExprSyntax {
+ // Perform a no-op transform that requires rebuilding the node.
+ return node.withSignature(node.signature)
+ }
+ }
+ expectDoesNotThrow({
+ let parsed = try SourceFileSyntax.decodeSourceFileSyntax(try
+ SwiftLang.parse(getInput("closure.swift")))
+ let rewriter = ClosureRewriter()
+ let rewritten = rewriter.visit(parsed)
+ expectEqual(parsed.description, rewritten.description)
+ })
+}
+
runAllTests()
diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift
index 2539461..6d043e9 100644
--- a/test/expr/closure/closures.swift
+++ b/test/expr/closure/closures.swift
@@ -259,6 +259,7 @@
func takesVoidFunc(_ f: () -> ()) {}
var i: Int = 1
+// expected-warning @+1 {{expression of type 'Int' is unused}}
takesVoidFunc({i})
// expected-warning @+1 {{expression of type 'Int' is unused}}
var f1: () -> () = {i}
diff --git a/test/stdlib/ErrorHandling.swift b/test/stdlib/ErrorHandling.swift
index ea5d427..a45d0a6 100644
--- a/test/stdlib/ErrorHandling.swift
+++ b/test/stdlib/ErrorHandling.swift
@@ -1,6 +1,9 @@
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
+// FIXME: <https://bugs.swift.org/browse/SR-7138> 2 tests are failing on linux in optimized mode
+// UNSUPPORTED: OS=linux-gnu
+
//
// Tests for error handling in standard library APIs.
//
diff --git a/test/stdlib/FloatingPoint.swift.gyb b/test/stdlib/FloatingPoint.swift.gyb
index 9b23ece..24cd535 100644
--- a/test/stdlib/FloatingPoint.swift.gyb
+++ b/test/stdlib/FloatingPoint.swift.gyb
@@ -529,7 +529,6 @@
%end
let floatNextUpDownTests: [(Float, Float)] = [
- (.nan, .nan),
(.greatestFiniteMagnitude, .infinity),
(0x1.ffff_fe__p-1, 1.0), (1.0, 0x1.0000_02__p+0),
(0.0, .leastNonzeroMagnitude),
@@ -553,7 +552,6 @@
}
let doubleNextUpDownTests: [(Double, Double)] = [
- (.nan, .nan),
(.greatestFiniteMagnitude, .infinity),
(0x1.ffff_ffff_ffff_fp-1, 1.0), (1.0, 0x1.0000_0000_0000_1p+0),
(0.0, .leastNonzeroMagnitude),
@@ -576,6 +574,16 @@
expectBitwiseEqual(-prev, (-succ).nextUp)
}
+%for Self in ['Float', 'Double']:
+FloatingPoint.test("${Self}.nextUp, .nextDown/nan") {
+ let x = ${Self}.nan
+ expectBitwiseEqual(x, x.nextUp)
+ expectBitwiseEqual(x, x.nextDown)
+ expectTrue((-x).nextDown.isNaN)
+ expectTrue((-x).nextUp.isNaN)
+}
+%end
+
#if arch(i386) || arch(x86_64)
FloatingPoint.test("Float80/ExpressibleByIntegerLiteral") {
diff --git a/test/type/types.swift b/test/type/types.swift
index c542f0c..f03fcca 100644
--- a/test/type/types.swift
+++ b/test/type/types.swift
@@ -51,8 +51,8 @@
var bad_is : (Int) -> (__shared Int, Int) // expected-error {{'__shared' may only be used on parameters}}
func bad_is2(_ a: (__shared Int, Int)) {} // expected-error {{'__shared' may only be used on parameters}}
- var bad_iow : (Int) -> (__owned Int, Int)
- func bad_iow2(_ a: (__owned Int, Int)) {}
+ var bad_iow : (Int) -> (__owned Int, Int) // expected-error {{'__owned' may only be used on parameters}}
+ func bad_iow2(_ a: (__owned Int, Int)) {} // expected-error {{'__owned' may only be used on parameters}}
}
// <rdar://problem/15588967> Array type sugar default construction syntax doesn't work
diff --git a/tools/SwiftSyntax/CMakeLists.txt b/tools/SwiftSyntax/CMakeLists.txt
index f098baf..ed83610 100644
--- a/tools/SwiftSyntax/CMakeLists.txt
+++ b/tools/SwiftSyntax/CMakeLists.txt
@@ -21,7 +21,7 @@
SyntaxNodes.swift.gyb
SyntaxRewriter.swift.gyb
TokenKind.swift.gyb
- Trivia.swift
+ Trivia.swift.gyb
SWIFT_MODULE_DEPENDS Foundation
INSTALL_IN_COMPONENT swift-syntax
diff --git a/tools/SwiftSyntax/Syntax.swift b/tools/SwiftSyntax/Syntax.swift
index 33595f2..efce76f 100644
--- a/tools/SwiftSyntax/Syntax.swift
+++ b/tools/SwiftSyntax/Syntax.swift
@@ -68,6 +68,12 @@
return SyntaxChildren(node: self)
}
+ /// The number of children, `present` or `missing`, in this node.
+ /// This value can be used safely with `child(at:)`.
+ public var numberOfChildren: Int {
+ return data.childCaches.count
+ }
+
/// Whether or not this node it marked as `present`.
public var isPresent: Bool {
return raw.presence == .present
diff --git a/tools/SwiftSyntax/SyntaxRewriter.swift.gyb b/tools/SwiftSyntax/SyntaxRewriter.swift.gyb
index 15ba796..ea5ecce 100644
--- a/tools/SwiftSyntax/SyntaxRewriter.swift.gyb
+++ b/tools/SwiftSyntax/SyntaxRewriter.swift.gyb
@@ -64,7 +64,17 @@
}
func visitChildren(_ node: Syntax) -> Syntax {
- let newLayout = node.children.map { visit($0).raw }
+ // Visit all children of this node, returning `nil` if child is not
+ // present. This will ensure that there are always the same number
+ // of children after transforming.
+ let newLayout = (0..<node.numberOfChildren).map { (i: Int) -> RawSyntax? in
+ guard let child = node.child(at: i) else { return nil }
+ return visit(child).raw
+ }
+
+ // Sanity check, ensure the new children are the same length.
+ assert(newLayout.count == node.raw.layout.count)
+
return makeSyntax(node.raw.replacingLayout(newLayout))
}
}
diff --git a/tools/SwiftSyntax/Trivia.swift b/tools/SwiftSyntax/Trivia.swift
deleted file mode 100644
index 1a78a40..0000000
--- a/tools/SwiftSyntax/Trivia.swift
+++ /dev/null
@@ -1,401 +0,0 @@
-//===------------------- Trivia.swift - Source Trivia Enum ----------------===//
-//
-// 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 Foundation
-
-/// A contiguous stretch of a single kind of trivia. The constituent part of
-/// a `Trivia` collection.
-///
-/// For example, four spaces would be represented by
-/// `.spaces(4)`
-///
-/// In general, you should deal with the actual Trivia collection instead
-/// of individual pieces whenever possible.
-public enum TriviaPiece: Codable {
- enum CodingKeys: CodingKey {
- case kind, value
- }
- public init(from decoder: Decoder) throws {
- let container = try decoder.container(keyedBy: CodingKeys.self)
- let kind = try container.decode(String.self, forKey: .kind)
- switch kind {
- case "Space":
- let value = try container.decode(Int.self, forKey: .value)
- self = .spaces(value)
- case "Tab":
- let value = try container.decode(Int.self, forKey: .value)
- self = .tabs(value)
- case "VerticalTab":
- let value = try container.decode(Int.self, forKey: .value)
- self = .verticalTabs(value)
- case "Formfeed":
- let value = try container.decode(Int.self, forKey: .value)
- self = .formfeeds(value)
- case "Newline":
- let value = try container.decode(Int.self, forKey: .value)
- self = .newlines(value)
- case "CarriageReturn":
- let value = try container.decode(Int.self, forKey: .value)
- self = .carriageReturns(value)
- case "CarriageReturnLineFeed":
- let value = try container.decode(Int.self, forKey: .value)
- self = .carriageReturnLineFeeds(value)
- case "Backtick":
- let value = try container.decode(Int.self, forKey: .value)
- self = .backticks(value)
- case "LineComment":
- let value = try container.decode(String.self, forKey: .value)
- self = .lineComment(value)
- case "BlockComment":
- let value = try container.decode(String.self, forKey: .value)
- self = .blockComment(value)
- case "DocLineComment":
- let value = try container.decode(String.self, forKey: .value)
- self = .docLineComment(value)
- case "DocBlockComment":
- let value = try container.decode(String.self, forKey: .value)
- self = .docLineComment(value)
- case "GarbageText":
- let value = try container.decode(String.self, forKey: .value)
- self = .garbageText(value)
- default:
- let context =
- DecodingError.Context(codingPath: [CodingKeys.kind],
- debugDescription: "invalid TriviaPiece kind \(kind)")
- throw DecodingError.valueNotFound(String.self, context)
- }
- }
-
- public func encode(to encoder: Encoder) throws {
- var container = encoder.container(keyedBy: CodingKeys.self)
- switch self {
- case .blockComment(let comment):
- try container.encode("BlockComment", forKey: .kind)
- try container.encode(comment, forKey: .value)
- case .docBlockComment(let comment):
- try container.encode("DocBlockComment", forKey: .kind)
- try container.encode(comment, forKey: .value)
- case .docLineComment(let comment):
- try container.encode("DocLineComment", forKey: .kind)
- try container.encode(comment, forKey: .value)
- case .lineComment(let comment):
- try container.encode("LineComment", forKey: .kind)
- try container.encode(comment, forKey: .value)
- case .garbageText(let text):
- try container.encode("GarbageText", forKey: .kind)
- try container.encode(text, forKey: .value)
- case .formfeeds(let count):
- try container.encode("Formfeed", forKey: .kind)
- try container.encode(count, forKey: .value)
- case .backticks(let count):
- try container.encode("Backtick", forKey: .kind)
- try container.encode(count, forKey: .value)
- case .newlines(let count):
- try container.encode("Newline", forKey: .kind)
- try container.encode(count, forKey: .value)
- case .carriageReturns(let count):
- try container.encode("CarriageReturn", forKey: .kind)
- try container.encode(count, forKey: .value)
- case .carriageReturnLineFeeds(let count):
- try container.encode("CarriageReturnLineFeeds", forKey: .kind)
- try container.encode(count, forKey: .value)
- case .spaces(let count):
- try container.encode("Space", forKey: .kind)
- try container.encode(count, forKey: .value)
- case .tabs(let count):
- try container.encode("Tab", forKey: .kind)
- try container.encode(count, forKey: .value)
- case .verticalTabs(let count):
- try container.encode("VerticalTab", forKey: .kind)
- try container.encode(count, forKey: .value)
-
- }
- }
-
- /// A space ' ' character.
- case spaces(Int)
-
- /// A tab '\t' character.
- case tabs(Int)
-
- /// A vertical tab '\v' character.
- case verticalTabs(Int)
-
- /// A form-feed '\f' character.
- case formfeeds(Int)
-
- /// A newline '\n' character.
- case newlines(Int)
-
- /// A carriage-return '\r' character.
- case carriageReturns(Int)
-
- /// A newline two bytes sequence consists of '\r' and '\n' characters.
- case carriageReturnLineFeeds(Int)
-
- /// A backtick '`' character, used to escape identifiers.
- case backticks(Int)
-
- /// A developer line comment, starting with '//'
- case lineComment(String)
-
- /// A developer block comment, starting with '/*' and ending with '*/'.
- case blockComment(String)
-
- /// A documentation line comment, starting with '///'.
- case docLineComment(String)
-
- /// A documentation block comment, starting with '/**' and ending with '*/.
- case docBlockComment(String)
-
- /// Any skipped text.
- case garbageText(String)
-}
-
-extension TriviaPiece: TextOutputStreamable {
- /// Prints the provided trivia as they would be written in a source file.
- ///
- /// - Parameter stream: The stream to which to print the trivia.
- public func write<Target>(to target: inout Target)
- where Target: TextOutputStream {
- func printRepeated(_ character: String, count: Int) {
- for _ in 0..<count { target.write(character) }
- }
- switch self {
- case let .spaces(count): printRepeated(" ", count: count)
- case let .tabs(count): printRepeated("\t", count: count)
- case let .verticalTabs(count): printRepeated("\u{2B7F}", count: count)
- case let .formfeeds(count): printRepeated("\u{240C}", count: count)
- case let .newlines(count): printRepeated("\n", count: count)
- case let .carriageReturns(count): printRepeated("\r", count: count)
- case let .carriageReturnLineFeeds(count): printRepeated("\r\n", count: count)
- case let .backticks(count): printRepeated("`", count: count)
- case let .lineComment(text),
- let .blockComment(text),
- let .docLineComment(text),
- let .docBlockComment(text),
- let .garbageText(text):
- target.write(text)
- }
- }
-
- /// Computes the information from this trivia to inform the source locations
- /// of the associated tokens.
- /// Specifically, walks through the trivia and keeps track of every newline
- /// to give a number of how many newlines and UTF8 characters appear in the
- /// trivia, along with the UTF8 offset of the last column.
- func characterSizes() -> (lines: Int, lastColumn: Int, utf8Length: Int) {
- switch self {
- case .spaces(let n),
- .tabs(let n),
- .verticalTabs(let n),
- .formfeeds(let n),
- .backticks(let n):
- return (lines: 0, lastColumn: n, utf8Length: n)
- case .newlines(let n):
- return (lines: n, lastColumn: 0, utf8Length: n)
- case .carriageReturns(let n):
- return (lines: n, lastColumn: 0, utf8Length: n)
- case .carriageReturnLineFeeds(let n):
- return (lines: n, lastColumn: 0, utf8Length: n * 2)
- case .lineComment(let text),
- .docLineComment(let text):
- let length = text.utf8.count
- return (lines: 0, lastColumn: length, utf8Length: length)
- case .blockComment(let text),
- .docBlockComment(let text),
- .garbageText(let text):
- var lines = 0
- var col = 0
- var total = 0
- var prevChar: UInt8? = nil
- // TODO: CR + LF should be regarded as one newline
- for char in text.utf8 {
- total += 1
- switch char {
- case 0x0a:
- if prevChar == 0x0d {
- /* ASCII CR LF */
- assert(col == 0)
- } else {
- /* ASCII newline */
- col = 0
- lines += 1
- }
- /* ASCII carriage-return */
- case 0x0d:
- col = 0
- lines += 1
-
- default:
- col += 1
- }
- prevChar = char
- }
- return (lines: lines, lastColumn: col, utf8Length: total)
- }
- }
-}
-
-/// A collection of leading or trailing trivia. This is the main data structure
-/// for thinking about trivia.
-public struct Trivia: Codable {
- let pieces: [TriviaPiece]
-
- /// Creates Trivia with the provided underlying pieces.
- public init(pieces: [TriviaPiece]) {
- self.pieces = pieces
- }
-
- public init(from decoder: Decoder) throws {
- var container = try decoder.unkeyedContainer()
- var pieces = [TriviaPiece]()
- while let piece = try container.decodeIfPresent(TriviaPiece.self) {
- pieces.append(piece)
- }
- self.pieces = pieces
- }
-
- public func encode(to encoder: Encoder) throws {
- var container = encoder.unkeyedContainer()
- for piece in pieces {
- try container.encode(piece)
- }
- }
-
- /// Creates Trivia with no pieces.
- public static var zero: Trivia {
- return Trivia(pieces: [])
- }
-
- /// Creates a new `Trivia` by appending the provided `TriviaPiece` to the end.
- public func appending(_ piece: TriviaPiece) -> Trivia {
- var copy = pieces
- copy.append(piece)
- return Trivia(pieces: copy)
- }
-
- /// Return a piece of trivia for some number of space characters in a row.
- public static func spaces(_ count: Int) -> Trivia {
- return [.spaces(count)]
- }
-
- /// Return a piece of trivia for some number of tab characters in a row.
- public static func tabs(_ count: Int) -> Trivia {
- return [.tabs(count)]
- }
-
- /// A vertical tab '\v' character.
- public static func verticalTabs(_ count: Int) -> Trivia {
- return [.verticalTabs(count)]
- }
-
- /// A form-feed '\f' character.
- public static func formfeeds(_ count: Int) -> Trivia {
- return [.formfeeds(count)]
- }
-
- /// Return a piece of trivia for some number of newline characters
- /// in a row.
- public static func newlines(_ count: Int) -> Trivia {
- return [.newlines(count)]
- }
-
- /// Return a piece of trivia for some number of carriage-return characters
- /// in a row.
- public static func carriageReturns(_ count: Int) -> Trivia {
- return [.carriageReturns(count)]
- }
-
- /// Return a piece of trivia for some number of two bytes sequence
- /// consists of CR and LF in a row.
- public static func carriageReturnLineFeeds(_ count: Int) -> Trivia {
- return [.carriageReturnLineFeeds(count)]
- }
-
- /// Return a piece of trivia for some number of backtick '`' characters
- /// in a row.
- public static func backticks(_ count: Int) -> Trivia {
- return [.backticks(count)]
- }
-
- /// Return a piece of trivia for a single line of ('//') developer comment.
- public static func lineComment(_ text: String) -> Trivia {
- return [.lineComment(text)]
- }
-
- /// Return a piece of trivia for a block comment ('/* ... */')
- public static func blockComment(_ text: String) -> Trivia {
- return [.blockComment(text)]
- }
-
- /// Return a piece of trivia for a single line of ('///') doc comment.
- public static func docLineComment(_ text: String) -> Trivia {
- return [.docLineComment(text)]
- }
-
- /// Return a piece of trivia for a documentation block comment ('/** ... */')
- public static func docBlockComment(_ text: String) -> Trivia {
- return [.docBlockComment(text)]
- }
-
- /// Return a piece of trivia for any garbage text.
- public static func garbageText(_ text: String) -> Trivia {
- return [.garbageText(text)]
- }
-
- /// Computes the total sizes and offsets of all pieces in this Trivia.
- func characterSizes() -> (lines: Int, lastColumn: Int, utf8Length: Int) {
- var lines = 0
- var lastColumn = 0
- var length = 0
- for piece in pieces {
- let (ln, col, len) = piece.characterSizes()
- lines += ln
- lastColumn = col
- length += len
- }
- return (lines: lines, lastColumn: lastColumn, utf8Length: length)
- }
-}
-
-/// Conformance for Trivia to the Collection protocol.
-extension Trivia: Collection {
- public var startIndex: Int {
- return pieces.startIndex
- }
-
- public var endIndex: Int {
- return pieces.endIndex
- }
-
- public func index(after i: Int) -> Int {
- return pieces.index(after: i)
- }
-
- public subscript(_ index: Int) -> TriviaPiece {
- return pieces[index]
- }
-}
-
-
-extension Trivia: ExpressibleByArrayLiteral {
- /// Creates Trivia from the provided pieces.
- public init(arrayLiteral elements: TriviaPiece...) {
- self.pieces = elements
- }
-}
-
-/// Concatenates two collections of `Trivia` into one collection.
-public func +(lhs: Trivia, rhs: Trivia) -> Trivia {
- return Trivia(pieces: lhs.pieces + rhs.pieces)
-}
diff --git a/tools/SwiftSyntax/Trivia.swift.gyb b/tools/SwiftSyntax/Trivia.swift.gyb
new file mode 100644
index 0000000..29f765b
--- /dev/null
+++ b/tools/SwiftSyntax/Trivia.swift.gyb
@@ -0,0 +1,258 @@
+%{
+ # -*- mode: Swift -*-
+ from gyb_syntax_support.Trivia import TRIVIAS
+ # Ignore the following admonition it applies to the resulting .swift file only
+}%
+//// Automatically Generated From Trivia.swift.gyb.
+//// Do Not Edit Directly!
+//===------------------- Trivia.swift - Source Trivia Enum ----------------===//
+//
+// 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 Foundation
+
+/// A contiguous stretch of a single kind of trivia. The constituent part of
+/// a `Trivia` collection.
+///
+/// For example, four spaces would be represented by
+/// `.spaces(4)`
+///
+/// In general, you should deal with the actual Trivia collection instead
+/// of individual pieces whenever possible.
+public enum TriviaPiece: Codable {
+ enum CodingKeys: CodingKey {
+ case kind, value
+ }
+ public init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: CodingKeys.self)
+ let kind = try container.decode(String.self, forKey: .kind)
+ switch kind {
+% for trivia in TRIVIAS:
+ case "${trivia.name}":
+% if trivia.is_collection():
+ let value = try container.decode(Int.self, forKey: .value)
+ self = .${trivia.lower_name}s(value)
+% else:
+ let value = try container.decode(String.self, forKey: .value)
+ self = .${trivia.lower_name}(value)
+% end
+% end
+ default:
+ let context =
+ DecodingError.Context(codingPath: [CodingKeys.kind],
+ debugDescription: "invalid TriviaPiece kind \(kind)")
+ throw DecodingError.valueNotFound(String.self, context)
+ }
+ }
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ switch self {
+% for trivia in TRIVIAS:
+% if trivia.is_collection():
+ case .${trivia.lower_name}s(let count):
+ try container.encode("${trivia.name}", forKey: .kind)
+ try container.encode(count, forKey: .value)
+% else:
+ case .${trivia.lower_name}(let text):
+ try container.encode("${trivia.name}", forKey: .kind)
+ try container.encode(text, forKey: .value)
+% end
+% end
+ }
+ }
+
+% for trivia in TRIVIAS:
+ /// ${trivia.comment}
+% if trivia.is_collection():
+ case ${trivia.lower_name}s(Int)
+% else:
+ case ${trivia.lower_name}(String)
+% end
+% end
+}
+
+extension TriviaPiece: TextOutputStreamable {
+ /// Prints the provided trivia as they would be written in a source file.
+ ///
+ /// - Parameter stream: The stream to which to print the trivia.
+ public func write<Target>(to target: inout Target)
+ where Target: TextOutputStream {
+ func printRepeated(_ character: String, count: Int) {
+ for _ in 0..<count { target.write(character) }
+ }
+ switch self {
+% for trivia in TRIVIAS:
+% if trivia.is_collection():
+% joined = ''.join(trivia.swift_characters)
+ case let .${trivia.lower_name}s(count):
+ printRepeated("${joined}", count: count)
+% else:
+ case let .${trivia.lower_name}(text):
+ target.write(text)
+% end
+% end
+ }
+ }
+
+ /// Computes the information from this trivia to inform the source locations
+ /// of the associated tokens.
+ /// Specifically, walks through the trivia and keeps track of every newline
+ /// to give a number of how many newlines and UTF8 characters appear in the
+ /// trivia, along with the UTF8 offset of the last column.
+ func characterSizes() -> (lines: Int, lastColumn: Int, utf8Length: Int) {
+ func calculateTextSizes(_ text: String) ->
+ (lines: Int, lastColumn: Int, utf8Length: Int) {
+ var lines = 0
+ var col = 0
+ var total = 0
+ var prevChar: UInt8? = nil
+ // TODO: CR + LF should be regarded as one newline
+ for char in text.utf8 {
+ total += 1
+ switch char {
+ case 0x0a:
+ if prevChar == 0x0d {
+ /* ASCII CR LF */
+ assert(col == 0)
+ } else {
+ /* ASCII newline */
+ col = 0
+ lines += 1
+ }
+ /* ASCII carriage-return */
+ case 0x0d:
+ col = 0
+ lines += 1
+
+ default:
+ col += 1
+ }
+ prevChar = char
+ }
+ return (lines: lines, lastColumn: col, utf8Length: total)
+ }
+ switch self {
+% for trivia in TRIVIAS:
+% if trivia.is_new_line:
+ case let .${trivia.lower_name}s(n):
+ return (lines: n, lastColumn: 0, utf8Length: n * ${trivia.characters_len()})
+% elif trivia.is_collection():
+ case let .${trivia.lower_name}s(n):
+ return (lines: 0, lastColumn: n, utf8Length: n * ${trivia.characters_len()})
+% else:
+ case let .${trivia.lower_name}(text):
+ return calculateTextSizes(text)
+% end
+% end
+ }
+ }
+}
+
+/// A collection of leading or trailing trivia. This is the main data structure
+/// for thinking about trivia.
+public struct Trivia: Codable {
+ let pieces: [TriviaPiece]
+
+ /// Creates Trivia with the provided underlying pieces.
+ public init(pieces: [TriviaPiece]) {
+ self.pieces = pieces
+ }
+
+ public init(from decoder: Decoder) throws {
+ var container = try decoder.unkeyedContainer()
+ var pieces = [TriviaPiece]()
+ while let piece = try container.decodeIfPresent(TriviaPiece.self) {
+ pieces.append(piece)
+ }
+ self.pieces = pieces
+ }
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.unkeyedContainer()
+ for piece in pieces {
+ try container.encode(piece)
+ }
+ }
+
+ /// Creates Trivia with no pieces.
+ public static var zero: Trivia {
+ return Trivia(pieces: [])
+ }
+
+ /// Creates a new `Trivia` by appending the provided `TriviaPiece` to the end.
+ public func appending(_ piece: TriviaPiece) -> Trivia {
+ var copy = pieces
+ copy.append(piece)
+ return Trivia(pieces: copy)
+ }
+
+% for trivia in TRIVIAS:
+% if trivia.is_collection():
+% joined = ''.join(trivia.swift_characters)
+ /// Return a piece of trivia for some number of '${joined}' characters.
+ public static func ${trivia.lower_name}s(_ count: Int) -> Trivia {
+ return [.${trivia.lower_name}s(count)]
+ }
+% else:
+ /// Return a piece of trivia for ${trivia.name}.
+ public static func ${trivia.lower_name}(_ text: String) -> Trivia {
+ return [.${trivia.lower_name}(text)]
+ }
+% end
+% end
+
+ /// Computes the total sizes and offsets of all pieces in this Trivia.
+ func characterSizes() -> (lines: Int, lastColumn: Int, utf8Length: Int) {
+ var lines = 0
+ var lastColumn = 0
+ var length = 0
+ for piece in pieces {
+ let (ln, col, len) = piece.characterSizes()
+ lines += ln
+ lastColumn = col
+ length += len
+ }
+ return (lines: lines, lastColumn: lastColumn, utf8Length: length)
+ }
+}
+
+/// Conformance for Trivia to the Collection protocol.
+extension Trivia: Collection {
+ public var startIndex: Int {
+ return pieces.startIndex
+ }
+
+ public var endIndex: Int {
+ return pieces.endIndex
+ }
+
+ public func index(after i: Int) -> Int {
+ return pieces.index(after: i)
+ }
+
+ public subscript(_ index: Int) -> TriviaPiece {
+ return pieces[index]
+ }
+}
+
+
+extension Trivia: ExpressibleByArrayLiteral {
+ /// Creates Trivia from the provided pieces.
+ public init(arrayLiteral elements: TriviaPiece...) {
+ self.pieces = elements
+ }
+}
+
+/// Concatenates two collections of `Trivia` into one collection.
+public func +(lhs: Trivia, rhs: Trivia) -> Trivia {
+ return Trivia(pieces: lhs.pieces + rhs.pieces)
+}
diff --git a/unittests/Parse/LexerTests.cpp b/unittests/Parse/LexerTests.cpp
index c64aa40..3350182 100644
--- a/unittests/Parse/LexerTests.cpp
+++ b/unittests/Parse/LexerTests.cpp
@@ -1,3 +1,5 @@
+#include "swift/AST/DiagnosticConsumer.h"
+#include "swift/AST/DiagnosticEngine.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/Lexer.h"
@@ -703,3 +705,76 @@
std::vector<Token> Toks = checkLex(Source, ExpectedTokens);
EXPECT_EQ("<#aa#>", Toks[2].getText());
}
+
+class StringCaptureDiagnosticConsumer : public DiagnosticConsumer {
+public:
+ virtual void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
+ DiagnosticKind Kind, StringRef FormatString,
+ ArrayRef<DiagnosticArgument> FormatArgs,
+ const swift::DiagnosticInfo &Info) override {
+ std::string DiagMsg;
+ llvm::raw_string_ostream DiagOS(DiagMsg);
+ DiagnosticEngine::formatDiagnosticText(DiagOS, FormatString, FormatArgs);
+ auto LC = SM.getLineAndColumn(Loc);
+ std::ostringstream StrOS;
+ StrOS << LC.first << ", " << LC.second << ": " << DiagOS.str();
+ messages.push_back(StrOS.str());
+ }
+
+ std::vector<std::string> messages;
+};
+
+bool containsPrefix(const std::vector<std::string> &strs,
+ const std::string &prefix) {
+ for (auto &str : strs) {
+ if (StringRef(str).startswith(StringRef(prefix))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+TEST_F(LexerTest, DiagnoseEmbeddedNul) {
+ const char Source[] = " \0 \0 aaa \0 \0 bbb";
+ size_t SourceLen = sizeof(Source) - 1;
+
+ LangOptions LangOpts;
+ SourceManager SourceMgr;
+ unsigned BufferID = SourceMgr.addMemBufferCopy(StringRef(Source, SourceLen));
+
+ StringCaptureDiagnosticConsumer DiagConsumer;
+ DiagnosticEngine Diags(SourceMgr);
+ Diags.addConsumer(DiagConsumer);
+
+ Lexer L(LangOpts, SourceMgr, BufferID, &Diags,
+ /*InSILMode=*/false, CommentRetentionMode::None,
+ TriviaRetentionMode::WithTrivia);
+
+ ASSERT_TRUE(containsPrefix(DiagConsumer.messages,
+ "1, 2: nul character embedded in middle of file"));
+ ASSERT_TRUE(containsPrefix(DiagConsumer.messages,
+ "1, 4: nul character embedded in middle of file"));
+}
+
+TEST_F(LexerTest, DiagnoseEmbeddedNulOffset) {
+ const char Source[] = " \0 \0 aaa \0 \0 bbb";
+ size_t SourceLen = sizeof(Source) - 1;
+
+ LangOptions LangOpts;
+ SourceManager SourceMgr;
+ unsigned BufferID = SourceMgr.addMemBufferCopy(StringRef(Source, SourceLen));
+
+ StringCaptureDiagnosticConsumer DiagConsumer;
+ DiagnosticEngine Diags(SourceMgr);
+ Diags.addConsumer(DiagConsumer);
+
+ Lexer L(LangOpts, SourceMgr, BufferID, &Diags,
+ /*InSILMode=*/false, CommentRetentionMode::None,
+ TriviaRetentionMode::WithTrivia,
+ /*Offset=*/5, /*EndOffset=*/SourceLen);
+
+ ASSERT_FALSE(containsPrefix(
+ DiagConsumer.messages, "1, 2: nul character embedded in middle of file"));
+ ASSERT_FALSE(containsPrefix(
+ DiagConsumer.messages, "1, 4: nul character embedded in middle of file"));
+}
diff --git a/unittests/Reflection/TypeRef.cpp b/unittests/Reflection/TypeRef.cpp
index 5e0df43..f9cba95 100644
--- a/unittests/Reflection/TypeRef.cpp
+++ b/unittests/Reflection/TypeRef.cpp
@@ -148,9 +148,10 @@
// Test parameter with and without inout/shared/variadic and/or label.
ParameterFlags paramFlags;
- auto inoutFlags = paramFlags.withInOut(true);
+ auto inoutFlags = paramFlags.withValueOwnership(ValueOwnership::InOut);
auto variadicFlags = paramFlags.withVariadic(true);
- auto sharedFlags = paramFlags.withShared(true);
+ auto sharedFlags = paramFlags.withValueOwnership(ValueOwnership::Shared);
+ auto ownedFlags = paramFlags.withValueOwnership(ValueOwnership::Owned);
auto F6 = Builder.createFunctionType({Param1.withFlags(inoutFlags)}, Result,
FunctionTypeFlags());
@@ -170,17 +171,27 @@
Result, FunctionTypeFlags());
EXPECT_EQ(F8, F8_1);
- auto F9 = Builder.createFunctionType({Param1}, Result, FunctionTypeFlags());
- auto F9_1 = Builder.createFunctionType({Param1.withLabel("foo")}, Result,
+ auto F9 = Builder.createFunctionType({Param1.withFlags(ownedFlags)}, Result,
+ FunctionTypeFlags());
+ auto F9_1 = Builder.createFunctionType({Param1.withFlags(ownedFlags)},
+ Result, FunctionTypeFlags());
+ EXPECT_EQ(F9, F9_1);
+
+ auto F10 = Builder.createFunctionType({Param1}, Result, FunctionTypeFlags());
+ auto F10_1 = Builder.createFunctionType({Param1.withLabel("foo")}, Result,
FunctionTypeFlags());
- EXPECT_NE(F9, F9_1);
+ EXPECT_NE(F10, F10_1);
EXPECT_NE(F6, F7);
EXPECT_NE(F6, F8);
EXPECT_NE(F6, F9);
+ EXPECT_NE(F6, F10);
EXPECT_NE(F7, F8);
EXPECT_NE(F7, F9);
+ EXPECT_NE(F7, F10);
EXPECT_NE(F8, F9);
+ EXPECT_NE(F8, F10);
+ EXPECT_NE(F9, F10);
auto VoidVoid1 =
Builder.createFunctionType(VoidParams, VoidResult, FunctionTypeFlags());
@@ -191,14 +202,14 @@
EXPECT_NE(VoidVoid1, F1);
// Test escaping.
- auto F10 = Builder.createFunctionType(Parameters1, Result,
- FunctionTypeFlags().withEscaping(true));
auto F11 = Builder.createFunctionType(Parameters1, Result,
FunctionTypeFlags().withEscaping(true));
- auto F12 = Builder.createFunctionType(
+ auto F12 = Builder.createFunctionType(Parameters1, Result,
+ FunctionTypeFlags().withEscaping(true));
+ auto F13 = Builder.createFunctionType(
Parameters1, Result, FunctionTypeFlags().withEscaping(false));
- EXPECT_EQ(F10, F11);
- EXPECT_NE(F10, F12);
+ EXPECT_EQ(F11, F12);
+ EXPECT_NE(F11, F13);
}
TEST(TypeRefTest, UniqueProtocolTypeRef) {
diff --git a/utils/gyb_syntax_support/Trivia.py b/utils/gyb_syntax_support/Trivia.py
index 6a24081..fe32541 100644
--- a/utils/gyb_syntax_support/Trivia.py
+++ b/utils/gyb_syntax_support/Trivia.py
@@ -2,13 +2,20 @@
class Trivia(object):
- def __init__(self, name, comment, characters=[], is_new_line=False):
+ def __init__(self, name, comment, characters=[], swift_characters=[],
+ is_new_line=False):
self.name = name
self.comment = comment
self.characters = characters
self.lower_name = lowercase_first_word(name)
self.is_new_line = is_new_line
+ # Swift sometimes doesn't support escaped characters like \f or \v;
+ # we should allow specifying alternatives explicitly.
+ self.swift_characters = swift_characters if swift_characters else\
+ characters
+ assert len(self.swift_characters) == len(self.characters)
+
def characters_len(self):
return len(self.characters)
@@ -20,8 +27,9 @@
Trivia('Space', 'A space \' \' character.', characters=[' ']),
Trivia('Tab', 'A tab \'\\t\' character.', characters=['\\t']),
Trivia('VerticalTab', 'A vertical tab \'\\v\' character.',
- characters=['\\v']),
- Trivia('Formfeed', 'A form-feed \'f\' character.', characters=['\\f']),
+ characters=['\\v'], swift_characters=['\\u{2B7F}']),
+ Trivia('Formfeed', 'A form-feed \'f\' character.', characters=['\\f'],
+ swift_characters=['\\u{240C}']),
Trivia('Newline', 'A newline \'\\n\' character.', characters=['\\n'],
is_new_line=True),
Trivia('CarriageReturn', 'A newline \'\\r\' character.',