Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions include/swift/AST/Attr.def
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,20 @@
DECL_ATTR_ALIAS(SPELLING, CLASS)
#endif

#ifndef TYPE_ATTR
#define TYPE_ATTR(X)
#ifndef TYPE_ATTR_WITH_NAME
#define TYPE_ATTR_WITH_NAME(Name, IdStr)
#endif

#define TYPE_ATTR(Name) TYPE_ATTR_WITH_NAME(Name, #Name)
#define TYPE_ATTR_(Name) TYPE_ATTR_WITH_NAME(Name, "_" #Name)

// Type attributes
TYPE_ATTR(autoclosure)
TYPE_ATTR(convention)
TYPE_ATTR(noreturn)
TYPE_ATTR(noescape)
TYPE_ATTR(escaping)
TYPE_ATTR_(nonEphemeral)

// SIL-specific attributes
TYPE_ATTR(block_storage)
Expand Down Expand Up @@ -379,7 +383,7 @@ SIMPLE_DECL_ATTR(_nonoverride, NonOverride,
UserInaccessible | NotSerialized,
79)

#undef TYPE_ATTR
#undef TYPE_ATTR_WITH_NAME
#undef DECL_ATTR_ALIAS
#undef CONTEXTUAL_DECL_ATTR_ALIAS
#undef SIMPLE_DECL_ATTR
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/AttrKind.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ enum : unsigned { NumDeclAttrKindBits =

// Define enumerators for each type attribute, e.g. TAK_weak.
enum TypeAttrKind {
#define TYPE_ATTR(X) TAK_##X,
#define TYPE_ATTR_WITH_NAME(Name, IdStr) TAK_##Name,
#include "swift/AST/Attr.def"
TAK_Count
};
Expand Down
45 changes: 37 additions & 8 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3015,6 +3015,14 @@ static inline bool isRawPointerKind(PointerTypeKind PTK) {
llvm_unreachable("Unhandled PointerTypeKind in switch.");
}

// Kinds of buffer pointer types.
enum BufferPointerTypeKind : unsigned {
BPTK_UnsafeMutableRawBufferPointer,
BPTK_UnsafeRawBufferPointer,
BPTK_UnsafeMutableBufferPointer,
BPTK_UnsafeBufferPointer,
};

/// NominalTypeDecl - a declaration of a nominal type, like a struct.
class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
SourceRange Braces;
Expand Down Expand Up @@ -4832,9 +4840,15 @@ class ParamDecl : public VarDecl {
StringRef StringRepresentation;
};

/// The default value, if any, along with whether this is varargs.
llvm::PointerIntPair<StoredDefaultArgument *, 1> DefaultValueAndIsVariadic;

enum class Flags {
IsVariadic = 1 << 0,
IsNonEphemeral = 1 << 1,
};

/// The default value, if any, along with flags.
llvm::PointerIntPair<StoredDefaultArgument *, 2, OptionSet<Flags>>
DefaultValueAndFlags;

public:
ParamDecl(VarDecl::Specifier specifier,
SourceLoc specifierLoc, SourceLoc argumentNameLoc,
Expand Down Expand Up @@ -4874,15 +4888,15 @@ class ParamDecl : public VarDecl {
}

Expr *getDefaultValue() const {
if (auto stored = DefaultValueAndIsVariadic.getPointer())
if (auto stored = DefaultValueAndFlags.getPointer())
return stored->DefaultArg;
return nullptr;
}

void setDefaultValue(Expr *E);

Initializer *getDefaultArgumentInitContext() const {
if (auto stored = DefaultValueAndIsVariadic.getPointer())
if (auto stored = DefaultValueAndFlags.getPointer())
return stored->InitContext;
return nullptr;
}
Expand Down Expand Up @@ -4916,9 +4930,24 @@ class ParamDecl : public VarDecl {
void setDefaultValueStringRepresentation(StringRef stringRepresentation);

/// Whether or not this parameter is varargs.
bool isVariadic() const { return DefaultValueAndIsVariadic.getInt(); }
void setVariadic(bool value = true) {DefaultValueAndIsVariadic.setInt(value);}

bool isVariadic() const {
return DefaultValueAndFlags.getInt().contains(Flags::IsVariadic);
}
void setVariadic(bool value = true) {
auto flags = DefaultValueAndFlags.getInt();
DefaultValueAndFlags.setInt(value ? flags | Flags::IsVariadic
: flags - Flags::IsVariadic);
}

bool isNonEphemeral() const {
return DefaultValueAndFlags.getInt().contains(Flags::IsNonEphemeral);
}
void setNonEphemeral(bool value = true) {
auto flags = DefaultValueAndFlags.getInt();
DefaultValueAndFlags.setInt(value ? flags | Flags::IsNonEphemeral
: flags - Flags::IsNonEphemeral);
}

/// Remove the type of this varargs element designator, without the array
/// type wrapping it. A parameter like "Int..." will have formal parameter
/// type of "[Int]" and this returns "Int".
Expand Down
21 changes: 21 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,24 @@ ERROR(cannot_convert_argument_value_generic,none,
"cannot convert value of type %0 (%1) to expected argument type %2 (%3)",
(Type, StringRef, Type, StringRef))

ERROR(cannot_convert_non_ephemeral,none,
"cannot pass temporary pointer argument of type %0 to parameter "
"expecting a pointer that outlives the duration of the call", (Type))
WARNING(cannot_convert_non_ephemeral_warning,none,
"passing temporary pointer argument of type %0 to parameter expecting "
"a pointer that outlives the duration of the call leads to undefined "
"behaviour; this will be an error in a future release", (Type))
ERROR(cannot_construct_dangling_pointer,none,
"initialization of %0 results in a dangling %select{|buffer }1pointer",
(Type, unsigned))
WARNING(cannot_construct_dangling_pointer_warning,none,
"initialization of %0 results in a dangling %select{|buffer }1pointer; "
"this will be an error in a future release",
(Type, unsigned))
NOTE(ephemeral_pointer_argument_conversion_note,none,
"implicit argument conversion from %0 to %1 produces a pointer valid only "
"for the duration of the call", (Type, Type))

ERROR(cannot_convert_argument_value_protocol,none,
"argument type %0 does not conform to expected type %1", (Type, Type))
ERROR(cannot_convert_partial_argument_value_protocol,none,
Expand Down Expand Up @@ -2540,6 +2558,9 @@ ERROR(escaping_non_function_parameter,none,
NOTE(escaping_optional_type_argument, none,
"closure is already escaping in optional type argument", ())

ERROR(non_ephemeral_non_pointer_type,none,
"@_nonEphemeral attribute currently only applies to pointer types", ())

// NSManaged attribute
ERROR(attr_NSManaged_not_instance_member,none,
"@NSManaged only allowed on an instance property or method", ())
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/KnownStdlibTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ KNOWN_STDLIB_TYPE_DECL(UnsafePointer, NominalTypeDecl, 1)
KNOWN_STDLIB_TYPE_DECL(OpaquePointer, NominalTypeDecl, 0)
KNOWN_STDLIB_TYPE_DECL(AutoreleasingUnsafeMutablePointer, NominalTypeDecl, 1)

KNOWN_STDLIB_TYPE_DECL(UnsafeBufferPointer, NominalTypeDecl, 1)
KNOWN_STDLIB_TYPE_DECL(UnsafeMutableBufferPointer, NominalTypeDecl, 1)
KNOWN_STDLIB_TYPE_DECL(UnsafeRawBufferPointer, NominalTypeDecl, 0)
KNOWN_STDLIB_TYPE_DECL(UnsafeMutableRawBufferPointer, NominalTypeDecl, 0)

KNOWN_STDLIB_TYPE_DECL(Unmanaged, NominalTypeDecl, 1)

KNOWN_STDLIB_TYPE_DECL(Never, NominalTypeDecl, 0)
Expand Down
41 changes: 33 additions & 8 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace swift {
class ArchetypeType;
class AssociatedTypeDecl;
class ASTContext;
enum BufferPointerTypeKind : unsigned;
class ClassDecl;
class DependentMemberType;
class GenericTypeParamDecl;
Expand Down Expand Up @@ -685,7 +686,13 @@ class alignas(1 << TypeAlignInBits) TypeBase {
PointerTypeKind Ignore;
return getAnyPointerElementType(Ignore);
}


Type getAnyBufferPointerElementType(BufferPointerTypeKind &BPTK);
Type getAnyBufferPointerElementType() {
BufferPointerTypeKind Ignore;
return getAnyBufferPointerElementType(Ignore);
}

/// \brief Determine whether the given type is "specialized", meaning that
/// it involves generic types for which generic arguments have been provided.
/// For example, the types Vector<Int> and Vector<Int>.Element are both
Expand Down Expand Up @@ -1721,8 +1728,9 @@ class ParameterTypeFlags {
Escaping = 1 << 2,
OwnershipShift = 3,
Ownership = 7 << OwnershipShift,
NonEphemeral = 1 << 6,

NumBits = 6
NumBits = 7
};
OptionSet<ParameterFlags> value;
static_assert(NumBits < 8*sizeof(OptionSet<ParameterFlags>), "overflowed");
Expand All @@ -1736,19 +1744,22 @@ class ParameterTypeFlags {
}

ParameterTypeFlags(bool variadic, bool autoclosure, bool escaping,
ValueOwnership ownership)
bool nonEphemeral, ValueOwnership ownership)
: value((variadic ? Variadic : 0) | (autoclosure ? AutoClosure : 0) |
(escaping ? Escaping : 0) |
(escaping ? Escaping : 0) | (nonEphemeral ? NonEphemeral : 0) |
uint8_t(ownership) << OwnershipShift) {}

/// Create one from what's present in the parameter type
inline static ParameterTypeFlags
fromParameterType(Type paramTy, bool isVariadic, ValueOwnership ownership);
inline static ParameterTypeFlags fromParameterType(Type paramTy,
bool isVariadic,
bool isNonEphemeral,
ValueOwnership ownership);

bool isNone() const { return !value; }
bool isVariadic() const { return value.contains(Variadic); }
bool isAutoClosure() const { return value.contains(AutoClosure); }
bool isEscaping() const { return value.contains(Escaping); }
bool isNonEphemeral() const { return value.contains(NonEphemeral); }
bool isInOut() const { return getValueOwnership() == ValueOwnership::InOut; }
bool isShared() const { return getValueOwnership() == ValueOwnership::Shared;}
bool isOwned() const { return getValueOwnership() == ValueOwnership::Owned; }
Expand Down Expand Up @@ -1793,6 +1804,12 @@ class ParameterTypeFlags {
: value - ParameterTypeFlags::AutoClosure);
}

ParameterTypeFlags withNonEphemeral(bool isNonEphemeral) const {
return ParameterTypeFlags(isNonEphemeral
? value | ParameterTypeFlags::NonEphemeral
: value - ParameterTypeFlags::NonEphemeral);
}

bool operator ==(const ParameterTypeFlags &other) const {
return value.toRaw() == other.value.toRaw();
}
Expand Down Expand Up @@ -1860,6 +1877,7 @@ class YieldTypeFlags {
return ParameterTypeFlags(/*variadic*/ false,
/*autoclosure*/ false,
/*escaping*/ false,
/*non-ephemeral*/false,
getValueOwnership());
}

Expand Down Expand Up @@ -1935,7 +1953,10 @@ class TupleTypeElt {

/// Determine whether this field is marked 'inout'.
bool isInOut() const { return Flags.isInOut(); }


/// Determine whether this field is marked '@_nonEphemeral'.
bool isNonEphemeral() const { return Flags.isNonEphemeral(); }

/// Remove the type of this varargs element designator, without the array
/// type wrapping it.
Type getVarargBaseTy() const;
Expand Down Expand Up @@ -2748,6 +2769,9 @@ class AnyFunctionType : public TypeBase {
/// Whether the parameter is marked 'owned'
bool isOwned() const { return Flags.isOwned(); }

/// Whether the parameter is marked '@_nonEphemeral'
bool isNonEphemeral() const { return Flags.isNonEphemeral(); }

ValueOwnership getValueOwnership() const {
return Flags.getValueOwnership();
}
Expand Down Expand Up @@ -5325,6 +5349,7 @@ inline TupleTypeElt TupleTypeElt::getWithType(Type T) const {
/// Create one from what's present in the parameter decl and type
inline ParameterTypeFlags
ParameterTypeFlags::fromParameterType(Type paramTy, bool isVariadic,
bool isNonEphemeral,
ValueOwnership ownership) {
bool autoclosure = paramTy->is<AnyFunctionType>() &&
paramTy->castTo<AnyFunctionType>()->isAutoClosure();
Expand All @@ -5339,7 +5364,7 @@ ParameterTypeFlags::fromParameterType(Type paramTy, bool isVariadic,
ownership == ValueOwnership::InOut);
ownership = ValueOwnership::InOut;
}
return {isVariadic, autoclosure, escaping, ownership};
return {isVariadic, autoclosure, escaping, isNonEphemeral, ownership};
}

inline const Type *BoundGenericType::getTrailingObjectsPointer() const {
Expand Down
4 changes: 3 additions & 1 deletion include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
const uint16_t SWIFTMODULE_VERSION_MINOR = 458; // Last change: enrich FILE_DEPENDENCY records.
const uint16_t SWIFTMODULE_VERSION_MINOR = 459; // Last change: non ephemeral

using DeclIDField = BCFixed<31>;

Expand Down Expand Up @@ -753,6 +753,7 @@ namespace decls_block {
BCFixed<1>, // vararg?
BCFixed<1>, // autoclosure?
BCFixed<1>, // escaping?
BCFixed<1>, // non-ephemeral?
ValueOwnershipField // inout, shared or owned?
>;

Expand Down Expand Up @@ -1026,6 +1027,7 @@ namespace decls_block {
VarDeclSpecifierField, // specifier
TypeIDField, // interface type
BCFixed<1>, // isVariadic?
BCFixed<1>, // isNonEphemeral?
DefaultArgumentField, // default argument kind
BCBlob // default argument text
>;
Expand Down
6 changes: 5 additions & 1 deletion lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1380,6 +1380,10 @@ bool ASTContext::hasPointerArgumentIntrinsics(LazyResolver *resolver) const {
&& getUnsafeMutablePointerDecl()
&& getUnsafePointerDecl()
&& (!LangOpts.EnableObjCInterop || getAutoreleasingUnsafeMutablePointerDecl())
&& getUnsafeBufferPointerDecl()
&& getUnsafeMutableBufferPointerDecl()
&& getUnsafeRawBufferPointerDecl()
&& getUnsafeMutableRawBufferPointerDecl()
&& getConvertPointerToPointerArgument(resolver)
&& getConvertMutableArrayToPointerArgument(resolver)
&& getConvertConstArrayToPointerArgument(resolver)
Expand Down Expand Up @@ -3722,7 +3726,7 @@ void AnyFunctionType::decomposeInput(
default:
result.emplace_back(type->getInOutObjectType(), Identifier(),
ParameterTypeFlags::fromParameterType(
type, false, ValueOwnership::Default));
type, false, false, ValueOwnership::Default));
return;
}
}
Expand Down
4 changes: 4 additions & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,9 @@ namespace {
if (P->isVariadic())
OS << " variadic";

if (P->isNonEphemeral())
OS << " non-ephemeral";

if (P->getDefaultArgumentKind() != DefaultArgumentKind::None)
printField("default_arg",
getDefaultArgumentKindString(P->getDefaultArgumentKind()));
Expand Down Expand Up @@ -3150,6 +3153,7 @@ namespace {
printFlag(paramFlags.isVariadic(), "vararg");
printFlag(paramFlags.isAutoClosure(), "autoclosure");
printFlag(paramFlags.isEscaping(), "escaping");
printFlag(paramFlags.isNonEphemeral(), "non_ephemeral");
switch (paramFlags.getValueOwnership()) {
case ValueOwnership::Default: break;
case ValueOwnership::Owned: printFlag("owned"); break;
Expand Down
8 changes: 6 additions & 2 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1822,8 +1822,12 @@ void ASTMangler::appendTypeList(Type listTy) {
return appendOperator("y");
bool firstField = true;
for (auto &field : tuple->getElements()) {
// FIXME: We shouldn't put @escaping in non-parameter list tuples
auto flags = field.getParameterFlags().withEscaping(false);
// FIXME: We shouldn't have these parameter flags in non-parameter list
// tuples.
auto flags = field.getParameterFlags()
.withEscaping(false)
.withAutoClosure(false)
.withNonEphemeral(false);

assert(flags.isNone());
appendTypeListElement(field.getName(), field.getRawType(), flags);
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2329,6 +2329,8 @@ static void printParameterFlags(ASTPrinter &printer, PrintOptions options,
printer << "@autoclosure ";
if (!options.excludeAttrKind(TAK_escaping) && flags.isEscaping())
printer << "@escaping ";
if (!options.excludeAttrKind(TAK_nonEphemeral) && flags.isNonEphemeral())
printer << "@_nonEphemeral ";

switch (flags.getValueOwnership()) {
case ValueOwnership::Default:
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ StringRef swift::getAccessLevelSpelling(AccessLevel value) {
///
TypeAttrKind TypeAttributes::getAttrKindFromString(StringRef Str) {
return llvm::StringSwitch<TypeAttrKind>(Str)
#define TYPE_ATTR(X) .Case(#X, TAK_##X)
#define TYPE_ATTR_WITH_NAME(Name, IdStr) .Case(IdStr, TAK_##Name)
#include "swift/AST/Attr.def"
.Default(TAK_Count);
}
Expand All @@ -70,7 +70,7 @@ TypeAttrKind TypeAttributes::getAttrKindFromString(StringRef Str) {
const char *TypeAttributes::getAttrName(TypeAttrKind kind) {
switch (kind) {
default: llvm_unreachable("Invalid attribute ID");
#define TYPE_ATTR(X) case TAK_##X: return #X;
#define TYPE_ATTR_WITH_NAME(Name, IdStr) case TAK_##Name: return IdStr;
#include "swift/AST/Attr.def"
}
}
Expand Down
Loading