mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #78332 from DougGregor/strict-safety-improvements
Strict safety improvements
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "swift/AST/Evaluator.h"
|
||||
#include "swift/AST/Identifier.h"
|
||||
#include "swift/AST/Import.h"
|
||||
#include "swift/AST/ProtocolConformanceOptions.h"
|
||||
#include "swift/AST/SILOptions.h"
|
||||
#include "swift/AST/SearchPathOptions.h"
|
||||
#include "swift/AST/Type.h"
|
||||
@@ -1299,8 +1300,7 @@ public:
|
||||
SourceLoc loc,
|
||||
DeclContext *dc,
|
||||
ProtocolConformanceState state,
|
||||
bool isUnchecked,
|
||||
bool isPreconcurrency,
|
||||
ProtocolConformanceOptions options,
|
||||
SourceLoc preconcurrencyLoc = SourceLoc());
|
||||
|
||||
/// Produce a self-conformance for the given protocol.
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "swift/AST/Initializer.h"
|
||||
#include "swift/AST/LayoutConstraint.h"
|
||||
#include "swift/AST/LifetimeAnnotation.h"
|
||||
#include "swift/AST/ProtocolConformanceOptions.h"
|
||||
#include "swift/AST/ReferenceCounting.h"
|
||||
#include "swift/AST/RequirementSignature.h"
|
||||
#include "swift/AST/StorageImpl.h"
|
||||
@@ -725,7 +726,7 @@ protected:
|
||||
HasAnyUnavailableDuringLoweringValues : 1
|
||||
);
|
||||
|
||||
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8,
|
||||
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8,
|
||||
/// If the module is compiled as static library.
|
||||
StaticLibrary : 1,
|
||||
|
||||
@@ -791,7 +792,10 @@ protected:
|
||||
AllowNonResilientAccess : 1,
|
||||
|
||||
/// Whether this module has been built with -package-cmo.
|
||||
SerializePackageEnabled : 1
|
||||
SerializePackageEnabled : 1,
|
||||
|
||||
/// Whether this module has enabled strict memory safety checking.
|
||||
StrictMemorySafety : 1
|
||||
);
|
||||
|
||||
SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,
|
||||
@@ -1782,14 +1786,8 @@ public:
|
||||
/// An entry in the "inherited" list of a type or extension.
|
||||
struct InheritedEntry : public TypeLoc {
|
||||
private:
|
||||
/// Whether there was an @unchecked attribute.
|
||||
bool IsUnchecked : 1;
|
||||
|
||||
/// Whether there was an @retroactive attribute.
|
||||
bool IsRetroactive : 1;
|
||||
|
||||
/// Whether there was an @preconcurrency attribute.
|
||||
bool IsPreconcurrency : 1;
|
||||
/// Options on a protocol conformance that are expressed as attributes.
|
||||
unsigned RawOptions: 8;
|
||||
|
||||
/// Whether there was a ~ indicating suppression.
|
||||
///
|
||||
@@ -1799,17 +1797,38 @@ private:
|
||||
public:
|
||||
InheritedEntry(const TypeLoc &typeLoc);
|
||||
|
||||
InheritedEntry(const TypeLoc &typeLoc, bool isUnchecked, bool isRetroactive,
|
||||
bool isPreconcurrency, bool isSuppressed = false)
|
||||
: TypeLoc(typeLoc), IsUnchecked(isUnchecked),
|
||||
IsRetroactive(isRetroactive), IsPreconcurrency(isPreconcurrency),
|
||||
InheritedEntry(const TypeLoc &typeLoc, ProtocolConformanceOptions options,
|
||||
bool isSuppressed = false)
|
||||
: TypeLoc(typeLoc), RawOptions(options.toRaw()),
|
||||
IsSuppressed(isSuppressed) {}
|
||||
|
||||
bool isUnchecked() const { return IsUnchecked; }
|
||||
bool isRetroactive() const { return IsRetroactive; }
|
||||
bool isPreconcurrency() const { return IsPreconcurrency; }
|
||||
ProtocolConformanceOptions getOptions() const {
|
||||
return ProtocolConformanceOptions(RawOptions);
|
||||
}
|
||||
|
||||
bool isUnchecked() const {
|
||||
return getOptions().contains(ProtocolConformanceFlags::Unchecked);
|
||||
}
|
||||
bool isRetroactive() const {
|
||||
return getOptions().contains(ProtocolConformanceFlags::Retroactive);
|
||||
}
|
||||
bool isPreconcurrency() const {
|
||||
return getOptions().contains(ProtocolConformanceFlags::Preconcurrency);
|
||||
}
|
||||
bool isUnsafe() const {
|
||||
return getOptions().contains(ProtocolConformanceFlags::Unsafe);
|
||||
}
|
||||
|
||||
bool isSafe() const {
|
||||
return getOptions().contains(ProtocolConformanceFlags::Safe);
|
||||
}
|
||||
|
||||
bool isSuppressed() const { return IsSuppressed; }
|
||||
|
||||
void setOption(ProtocolConformanceFlags flag) {
|
||||
RawOptions = (getOptions() | flag).toRaw();
|
||||
}
|
||||
|
||||
void setSuppressed() {
|
||||
assert(!IsSuppressed && "setting suppressed again!?");
|
||||
IsSuppressed = true;
|
||||
|
||||
@@ -529,7 +529,7 @@ SIMPLE_DECL_ATTR(_addressableSelf, AddressableSelf,
|
||||
|
||||
DECL_ATTR(safe, Safe,
|
||||
OnAbstractFunction | OnSubscript | OnVar | OnMacro | OnNominalType |
|
||||
OnExtension | OnTypeAlias | UserInaccessible |
|
||||
OnExtension | OnTypeAlias | OnImport | UserInaccessible |
|
||||
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
|
||||
163)
|
||||
|
||||
|
||||
@@ -589,5 +589,9 @@ ERROR(experimental_not_supported_in_production,none,
|
||||
"experimental feature '%0' cannot be enabled in production compiler",
|
||||
(StringRef))
|
||||
|
||||
GROUPED_WARNING(Ounchecked_with_strict_safety,Unsafe,none,
|
||||
"'-Ounchecked' is not memory-safe and should not be combined with "
|
||||
"strict memory safety checking", ())
|
||||
|
||||
#define UNDEFINE_DIAGNOSTIC_MACROS
|
||||
#include "DefineDiagnosticMacros.h"
|
||||
|
||||
@@ -5792,22 +5792,19 @@ ERROR(non_sendable_type,none,
|
||||
ERROR(sendable_raw_storage,none,
|
||||
"struct %0 with @_rawLayout does not conform to the 'Sendable' protocol", (DeclName))
|
||||
|
||||
ERROR(typeattr_not_inheritance_clause,none,
|
||||
"'%0' attribute only applies in inheritance clauses", (StringRef))
|
||||
ERROR(typeattr_not_existential,none,
|
||||
"'%0' attribute cannot apply to non-protocol type %1", (StringRef, Type))
|
||||
|
||||
WARNING(unchecked_conformance_not_special,none,
|
||||
"@unchecked conformance to %0 has no meaning", (Type))
|
||||
WARNING(restate_unchecked_sendable,none,
|
||||
"class %0 must restate inherited '@unchecked Sendable' conformance",
|
||||
(DeclName))
|
||||
ERROR(unchecked_not_inheritance_clause,none,
|
||||
"'unchecked' attribute only applies in inheritance clauses", ())
|
||||
ERROR(unchecked_not_existential,none,
|
||||
"'unchecked' attribute cannot apply to non-protocol type %0", (Type))
|
||||
|
||||
WARNING(preconcurrency_conformance_not_used,none,
|
||||
"@preconcurrency attribute on conformance to %0 has no effect", (Type))
|
||||
ERROR(preconcurrency_not_inheritance_clause,none,
|
||||
"'preconcurrency' attribute only applies in inheritance clauses", ())
|
||||
ERROR(preconcurrency_not_existential,none,
|
||||
"'preconcurrency' attribute cannot apply to non-protocol type %0", (Type))
|
||||
|
||||
ERROR(redundant_any_in_existential,none,
|
||||
"redundant 'any' in type %0",
|
||||
@@ -8084,22 +8081,33 @@ NOTE(note_reference_to_unsafe_decl,none,
|
||||
NOTE(note_reference_to_unsafe_typed_decl,none,
|
||||
"%select{reference|call}0 to %kind1 involves unsafe type %2",
|
||||
(bool, const ValueDecl *, Type))
|
||||
NOTE(note_reference_to_unsafe_through_typealias,none,
|
||||
"reference to %kind0 whose underlying type involves unsafe type %1",
|
||||
(const ValueDecl *, Type))
|
||||
NOTE(note_reference_to_nonisolated_unsafe,none,
|
||||
"reference to nonisolated(unsafe) %kind0 is unsafe in concurrently-executing code",
|
||||
(const ValueDecl *))
|
||||
NOTE(note_reference_unowned_unsafe,none,
|
||||
"reference to unowned(unsafe) %kind0 is unsafe", (const ValueDecl *))
|
||||
NOTE(note_use_of_unsafe_conformance_is_unsafe,none,
|
||||
"@unsafe conformance of %0 to %kind1 involves unsafe code",
|
||||
(Type, const ValueDecl *))
|
||||
GROUPED_WARNING(conformance_involves_unsafe,Unsafe,none,
|
||||
"conformance of %0 to %kind1 involves unsafe code; use '@unsafe' to "
|
||||
"indicate that the conformance is not memory-safe",
|
||||
(Type, const ValueDecl *))
|
||||
NOTE(note_witness_unsafe,none,
|
||||
"unsafe %0 %1 cannot satisfy safe requirement",
|
||||
(DescriptiveDeclKind, DeclName))
|
||||
NOTE(note_type_witness_unsafe,none,
|
||||
"unsafe type %0 cannot satisfy safe associated type %1",
|
||||
(Type, DeclName))
|
||||
|
||||
GROUPED_WARNING(override_safe_withunsafe,Unsafe,none,
|
||||
"override of safe %0 with unsafe %0", (DescriptiveDeclKind))
|
||||
GROUPED_WARNING(witness_unsafe,Unsafe,none,
|
||||
"unsafe %0 %1 cannot satisfy safe requirement",
|
||||
(DescriptiveDeclKind, DeclName))
|
||||
GROUPED_WARNING(type_witness_unsafe,Unsafe,none,
|
||||
"unsafe type %0 cannot satisfy safe associated type %1",
|
||||
(Type, DeclName))
|
||||
GROUPED_WARNING(unchecked_conformance_is_unsafe,Unsafe,none,
|
||||
"@unchecked conformance involves unsafe code", ())
|
||||
GROUPED_WARNING(use_of_unsafe_conformance_is_unsafe,Unsafe,none,
|
||||
"@unsafe conformance of %0 to %kind1 involves unsafe code",
|
||||
(Type, const ValueDecl *))
|
||||
GROUPED_WARNING(reference_unowned_unsafe,Unsafe,none,
|
||||
"reference to unowned(unsafe) %kind0 is unsafe", (const ValueDecl *))
|
||||
GROUPED_WARNING(reference_to_nonisolated_unsafe,Unsafe,none,
|
||||
@@ -8111,8 +8119,13 @@ GROUPED_WARNING(reference_to_unsafe_decl,Unsafe,none,
|
||||
GROUPED_WARNING(reference_to_unsafe_typed_decl,Unsafe,none,
|
||||
"%select{reference|call}0 to %kindbase1 involves unsafe type %2",
|
||||
(bool, const ValueDecl *, Type))
|
||||
NOTE(unsafe_decl_here,none,
|
||||
"unsafe %kindbase0 declared here", (const ValueDecl *))
|
||||
GROUPED_WARNING(reference_to_unsafe_through_typealias,Unsafe,none,
|
||||
"reference to %kind0 whose underlying type involves unsafe type %1",
|
||||
(const ValueDecl *, Type))
|
||||
GROUPED_WARNING(preconcurrency_import_unsafe,Unsafe,none,
|
||||
"@preconcurrency import is not memory-safe because it can silently "
|
||||
"introduce data races; use '@safe(unchecked)' to assert that the "
|
||||
"code is memory-safe", ())
|
||||
NOTE(encapsulate_unsafe_in_enclosing_context,none,
|
||||
"make %kindbase0 @safe(unchecked) to allow it to use unsafe constructs in its definition",
|
||||
(const Decl *))
|
||||
|
||||
@@ -830,6 +830,15 @@ public:
|
||||
Bits.ModuleDecl.IsConcurrencyChecked = value;
|
||||
}
|
||||
|
||||
/// Whether this module has enable strict memory safety checking.
|
||||
bool strictMemorySafety() const {
|
||||
return Bits.ModuleDecl.StrictMemorySafety;
|
||||
}
|
||||
|
||||
void setStrictMemorySafety(bool value = true) {
|
||||
Bits.ModuleDecl.StrictMemorySafety = value;
|
||||
}
|
||||
|
||||
bool isObjCNameLookupCachePopulated() const {
|
||||
return Bits.ModuleDecl.ObjCNameLookupCachePopulated;
|
||||
}
|
||||
|
||||
@@ -609,6 +609,12 @@ struct InheritedNominalEntry : Located<NominalTypeDecl *> {
|
||||
/// The location of the "preconcurrency" attribute if present.
|
||||
SourceLoc preconcurrencyLoc;
|
||||
|
||||
/// The location of the "unsafe" attribute if present.
|
||||
SourceLoc unsafeLoc;
|
||||
|
||||
/// The range of the "safe(unchecked)" attribute if present.
|
||||
SourceRange safeRange;
|
||||
|
||||
/// Whether this inherited entry was suppressed via "~".
|
||||
bool isSuppressed;
|
||||
|
||||
@@ -616,9 +622,11 @@ struct InheritedNominalEntry : Located<NominalTypeDecl *> {
|
||||
|
||||
InheritedNominalEntry(NominalTypeDecl *item, SourceLoc loc,
|
||||
SourceLoc uncheckedLoc, SourceLoc preconcurrencyLoc,
|
||||
SourceLoc unsafeLoc, SourceRange safeRange,
|
||||
bool isSuppressed)
|
||||
: Located(item, loc), uncheckedLoc(uncheckedLoc),
|
||||
preconcurrencyLoc(preconcurrencyLoc), isSuppressed(isSuppressed) {}
|
||||
preconcurrencyLoc(preconcurrencyLoc), unsafeLoc(unsafeLoc),
|
||||
safeRange(safeRange), isSuppressed(isSuppressed) {}
|
||||
};
|
||||
|
||||
/// Retrieve the set of nominal type declarations that are directly
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "swift/AST/ConcreteDeclRef.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/ProtocolConformanceOptions.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/AST/TypeAlignments.h"
|
||||
@@ -146,20 +147,21 @@ protected:
|
||||
SWIFT_INLINE_BITFIELD_EMPTY(RootProtocolConformance, ProtocolConformance);
|
||||
|
||||
SWIFT_INLINE_BITFIELD_FULL(NormalProtocolConformance, RootProtocolConformance,
|
||||
1+1+1+1+bitmax(NumProtocolConformanceStateBits,8)+
|
||||
1+1+
|
||||
bitmax(NumProtocolConformanceOptions,8)+
|
||||
bitmax(NumProtocolConformanceStateBits,8)+
|
||||
bitmax(NumConformanceEntryKindBits,8),
|
||||
/// Indicates whether the conformance is invalid.
|
||||
IsInvalid : 1,
|
||||
/// The conformance was labeled with @unchecked.
|
||||
IsUnchecked : 1,
|
||||
/// The conformance was labeled with @preconcurrency.
|
||||
IsPreconcurrency : 1,
|
||||
/// We have allocated the AssociatedConformances array (but not necessarily
|
||||
/// populated any of its elements).
|
||||
HasComputedAssociatedConformances : 1,
|
||||
|
||||
: NumPadBits,
|
||||
|
||||
/// Options.
|
||||
Options : bitmax(NumProtocolConformanceOptions, 8),
|
||||
|
||||
/// The current state of the conformance.
|
||||
State : bitmax(NumProtocolConformanceStateBits, 8),
|
||||
/// The reason that this conformance exists.
|
||||
@@ -567,8 +569,8 @@ class NormalProtocolConformance : public RootProtocolConformance,
|
||||
public:
|
||||
NormalProtocolConformance(Type conformingType, ProtocolDecl *protocol,
|
||||
SourceLoc loc, DeclContext *dc,
|
||||
ProtocolConformanceState state, bool isUnchecked,
|
||||
bool isPreconcurrency,
|
||||
ProtocolConformanceState state,
|
||||
ProtocolConformanceOptions options,
|
||||
SourceLoc preconcurrencyLoc)
|
||||
: RootProtocolConformance(ProtocolConformanceKind::Normal,
|
||||
conformingType),
|
||||
@@ -577,12 +579,12 @@ public:
|
||||
Context(dc) {
|
||||
assert(!conformingType->hasArchetype() &&
|
||||
"ProtocolConformances should store interface types");
|
||||
assert((preconcurrencyLoc.isInvalid() || isPreconcurrency) &&
|
||||
assert((preconcurrencyLoc.isInvalid() ||
|
||||
options.contains(ProtocolConformanceFlags::Preconcurrency)) &&
|
||||
"Cannot have a @preconcurrency location without isPreconcurrency");
|
||||
setState(state);
|
||||
Bits.NormalProtocolConformance.IsInvalid = false;
|
||||
Bits.NormalProtocolConformance.IsUnchecked = isUnchecked;
|
||||
Bits.NormalProtocolConformance.IsPreconcurrency = isPreconcurrency;
|
||||
Bits.NormalProtocolConformance.Options = options.toRaw();
|
||||
Bits.NormalProtocolConformance.HasComputedAssociatedConformances = false;
|
||||
Bits.NormalProtocolConformance.SourceKind =
|
||||
unsigned(ConformanceEntryKind::Explicit);
|
||||
@@ -626,27 +628,42 @@ public:
|
||||
/// Mark this conformance as invalid.
|
||||
void setInvalid() { Bits.NormalProtocolConformance.IsInvalid = true; }
|
||||
|
||||
ProtocolConformanceOptions getOptions() const {
|
||||
return ProtocolConformanceOptions(Bits.NormalProtocolConformance.Options);
|
||||
}
|
||||
|
||||
/// Whether this is an "unchecked" conformance.
|
||||
bool isUnchecked() const {
|
||||
return Bits.NormalProtocolConformance.IsUnchecked;
|
||||
return getOptions().contains(ProtocolConformanceFlags::Unchecked);
|
||||
}
|
||||
|
||||
/// Mark the conformance as unchecked (equivalent to the @unchecked
|
||||
/// conformance attribute).
|
||||
void setUnchecked() {
|
||||
// OK to mutate because the flags are not part of the folding set node ID.
|
||||
Bits.NormalProtocolConformance.IsUnchecked = true;
|
||||
Bits.NormalProtocolConformance.Options =
|
||||
(getOptions() | ProtocolConformanceFlags::Unchecked).toRaw();
|
||||
}
|
||||
|
||||
/// Whether this is an preconcurrency conformance.
|
||||
bool isPreconcurrency() const {
|
||||
return Bits.NormalProtocolConformance.IsPreconcurrency;
|
||||
return getOptions().contains(ProtocolConformanceFlags::Preconcurrency);
|
||||
}
|
||||
|
||||
/// Retrieve the location of `@preconcurrency`, if there is one and it is
|
||||
/// known.
|
||||
SourceLoc getPreconcurrencyLoc() const { return PreconcurrencyLoc; }
|
||||
|
||||
/// Whether this is an "unsafe" conformance.
|
||||
bool isUnsafe() const {
|
||||
return getOptions().contains(ProtocolConformanceFlags::Unsafe);
|
||||
}
|
||||
|
||||
/// Whether this is an "safe(unchecked)" conformance.
|
||||
bool isSafe() const {
|
||||
return getOptions().contains(ProtocolConformanceFlags::Safe);
|
||||
}
|
||||
|
||||
/// Determine whether we've lazily computed the associated conformance array
|
||||
/// already.
|
||||
bool hasComputedAssociatedConformances() const {
|
||||
@@ -684,8 +701,8 @@ public:
|
||||
if (auto implying = implyingConformance) {
|
||||
ImplyingConformance = implying;
|
||||
PreconcurrencyLoc = implying->getPreconcurrencyLoc();
|
||||
Bits.NormalProtocolConformance.IsPreconcurrency =
|
||||
implying->isPreconcurrency();
|
||||
Bits.NormalProtocolConformance.Options =
|
||||
implyingConformance->getOptions().toRaw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
60
include/swift/AST/ProtocolConformanceOptions.h
Normal file
60
include/swift/AST/ProtocolConformanceOptions.h
Normal file
@@ -0,0 +1,60 @@
|
||||
//===--- ProtocolConformanceOptions.h - Conformance Options -----*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the options for protocol conformances.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef SWIFT_AST_PROTOCOLCONFORMANCEOPTIONS_H
|
||||
#define SWIFT_AST_PROTOCOLCONFORMANCEOPTIONS_H
|
||||
|
||||
#include "swift/Basic/OptionSet.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// Flags that describe extra attributes on protocol conformances.
|
||||
enum class ProtocolConformanceFlags {
|
||||
/// @unchecked conformance
|
||||
Unchecked = 0x01,
|
||||
|
||||
/// @preconcurrency conformance
|
||||
Preconcurrency = 0x02,
|
||||
|
||||
/// @unsafe conformance
|
||||
Unsafe = 0x04,
|
||||
|
||||
/// @safe(unchecked) conformance
|
||||
Safe = 0x08,
|
||||
|
||||
/// @retroactive conformance
|
||||
Retroactive = 0x10,
|
||||
|
||||
// Note: whenever you add a bit here, update
|
||||
// NumProtocolConformanceOptions below.
|
||||
};
|
||||
|
||||
/// Options that describe extra attributes on protocol conformances.
|
||||
using ProtocolConformanceOptions =
|
||||
OptionSet<ProtocolConformanceFlags>;
|
||||
|
||||
inline ProtocolConformanceOptions operator|(
|
||||
ProtocolConformanceFlags flag1,
|
||||
ProtocolConformanceFlags flag2) {
|
||||
return ProtocolConformanceOptions(flag1) | flag2;
|
||||
}
|
||||
|
||||
enum : unsigned {
|
||||
NumProtocolConformanceOptions = 5
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif
|
||||
@@ -60,6 +60,8 @@ SIMPLE_TYPE_ATTR(Sendable, Sendable)
|
||||
SIMPLE_TYPE_ATTR(retroactive, Retroactive)
|
||||
SIMPLE_TYPE_ATTR(unchecked, Unchecked)
|
||||
SIMPLE_TYPE_ATTR(preconcurrency, Preconcurrency)
|
||||
SIMPLE_TYPE_ATTR(unsafe, Unsafe)
|
||||
SIMPLE_TYPE_ATTR(safe, Safe)
|
||||
SIMPLE_TYPE_ATTR(_local, Local)
|
||||
SIMPLE_TYPE_ATTR(_noMetadata, NoMetadata)
|
||||
TYPE_ATTR(_opaqueReturnTypeOf, OpaqueReturnTypeOf)
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/ProtocolConformance.h"
|
||||
#include "swift/AST/ProtocolConformanceRef.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/Basic/SourceLoc.h"
|
||||
#include "swift/Basic/Unreachable.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
class NormalProtocolConformance;
|
||||
|
||||
/// Describes a use of an unsafe construct.
|
||||
///
|
||||
/// Every use of an unsafe construct that should be diagnosed will be captured
|
||||
@@ -44,8 +43,13 @@ public:
|
||||
NonisolatedUnsafe,
|
||||
/// A reference to an unsafe declaration.
|
||||
ReferenceToUnsafe,
|
||||
/// A reference to a typealias that is not itself unsafe, but has
|
||||
/// an unsafe underlying type.
|
||||
ReferenceToUnsafeThroughTypealias,
|
||||
/// A call to an unsafe declaration.
|
||||
CallToUnsafe,
|
||||
/// A @preconcurrency import.
|
||||
PreconcurrencyImport,
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -66,7 +70,8 @@ private:
|
||||
} typeWitness;
|
||||
|
||||
struct {
|
||||
NormalProtocolConformance *conformance;
|
||||
TypeBase *type;
|
||||
void *conformanceRef;
|
||||
DeclContext *declContext;
|
||||
const void *location;
|
||||
} conformance;
|
||||
@@ -77,6 +82,8 @@ private:
|
||||
TypeBase *type;
|
||||
const void *location;
|
||||
} entity;
|
||||
|
||||
const ImportDecl *importDecl;
|
||||
} storage;
|
||||
|
||||
UnsafeUse(Kind kind) : kind(kind) { }
|
||||
@@ -106,6 +113,7 @@ private:
|
||||
assert(kind == UnownedUnsafe ||
|
||||
kind == NonisolatedUnsafe ||
|
||||
kind == ReferenceToUnsafe ||
|
||||
kind == ReferenceToUnsafeThroughTypealias ||
|
||||
kind == CallToUnsafe);
|
||||
|
||||
UnsafeUse result(kind);
|
||||
@@ -139,11 +147,14 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
static UnsafeUse forConformance(NormalProtocolConformance *conformance,
|
||||
static UnsafeUse forConformance(Type subjectType,
|
||||
ProtocolConformanceRef conformance,
|
||||
SourceLoc location,
|
||||
DeclContext *dc) {
|
||||
assert(subjectType);
|
||||
UnsafeUse result(UnsafeConformance);
|
||||
result.storage.conformance.conformance = conformance;
|
||||
result.storage.conformance.type = subjectType.getPointer();
|
||||
result.storage.conformance.conformanceRef = conformance.getOpaqueValue();
|
||||
result.storage.conformance.declContext = dc;
|
||||
result.storage.conformance.location = location.getOpaquePointerValue();
|
||||
return result;
|
||||
@@ -170,6 +181,20 @@ public:
|
||||
decl, type, location);
|
||||
}
|
||||
|
||||
static UnsafeUse forReferenceToUnsafeThroughTypealias(const Decl *decl,
|
||||
DeclContext *dc,
|
||||
Type type,
|
||||
SourceLoc location) {
|
||||
return forReference(ReferenceToUnsafeThroughTypealias, dc,
|
||||
decl, type, location);
|
||||
}
|
||||
|
||||
static UnsafeUse forPreconcurrencyImport(const ImportDecl *importDecl) {
|
||||
UnsafeUse result(PreconcurrencyImport);
|
||||
result.storage.importDecl = importDecl;
|
||||
return result;
|
||||
}
|
||||
|
||||
Kind getKind() const { return kind; }
|
||||
|
||||
/// The location at which this use will be diagnosed.
|
||||
@@ -180,7 +205,9 @@ public:
|
||||
return getDecl()->getLoc();
|
||||
|
||||
case UnsafeConformance:
|
||||
return getConformance()->getLoc();
|
||||
return SourceLoc(
|
||||
llvm::SMLoc::getFromPointer(
|
||||
(const char *)storage.conformance.location));
|
||||
|
||||
case TypeWitness:
|
||||
return SourceLoc(
|
||||
@@ -190,9 +217,13 @@ public:
|
||||
case UnownedUnsafe:
|
||||
case NonisolatedUnsafe:
|
||||
case ReferenceToUnsafe:
|
||||
case ReferenceToUnsafeThroughTypealias:
|
||||
case CallToUnsafe:
|
||||
return SourceLoc(
|
||||
llvm::SMLoc::getFromPointer((const char *)storage.entity.location));
|
||||
|
||||
case PreconcurrencyImport:
|
||||
return storage.importDecl->getLoc();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,11 +240,15 @@ public:
|
||||
case UnownedUnsafe:
|
||||
case NonisolatedUnsafe:
|
||||
case ReferenceToUnsafe:
|
||||
case ReferenceToUnsafeThroughTypealias:
|
||||
case CallToUnsafe:
|
||||
return storage.entity.decl;
|
||||
|
||||
case UnsafeConformance:
|
||||
return nullptr;
|
||||
|
||||
case PreconcurrencyImport:
|
||||
return storage.importDecl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,6 +264,7 @@ public:
|
||||
case UnownedUnsafe:
|
||||
case NonisolatedUnsafe:
|
||||
case ReferenceToUnsafe:
|
||||
case ReferenceToUnsafeThroughTypealias:
|
||||
case CallToUnsafe:
|
||||
return storage.entity.declContext;
|
||||
|
||||
@@ -237,10 +273,13 @@ public:
|
||||
|
||||
case Witness:
|
||||
case TypeWitness:
|
||||
return getConformance()->getDeclContext();
|
||||
return getConformance().getConcrete()->getDeclContext();
|
||||
|
||||
case UnsafeConformance:
|
||||
return storage.conformance.declContext;
|
||||
|
||||
case PreconcurrencyImport:
|
||||
return storage.importDecl->getDeclContext();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,8 +296,10 @@ public:
|
||||
case UnownedUnsafe:
|
||||
case NonisolatedUnsafe:
|
||||
case ReferenceToUnsafe:
|
||||
case ReferenceToUnsafeThroughTypealias:
|
||||
case CallToUnsafe:
|
||||
case UnsafeConformance:
|
||||
case PreconcurrencyImport:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -268,38 +309,45 @@ public:
|
||||
switch (getKind()) {
|
||||
case Override:
|
||||
case Witness:
|
||||
case UnsafeConformance:
|
||||
case PreconcurrencyImport:
|
||||
return nullptr;
|
||||
|
||||
case UnsafeConformance:
|
||||
return storage.conformance.type;
|
||||
|
||||
case TypeWitness:
|
||||
return storage.typeWitness.type;
|
||||
|
||||
case UnownedUnsafe:
|
||||
case NonisolatedUnsafe:
|
||||
case ReferenceToUnsafe:
|
||||
case ReferenceToUnsafeThroughTypealias:
|
||||
case CallToUnsafe:
|
||||
return storage.entity.type;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the protocol conformance, if there is one.
|
||||
NormalProtocolConformance *getConformance() const {
|
||||
ProtocolConformanceRef getConformance() const {
|
||||
switch (getKind()) {
|
||||
case UnsafeConformance:
|
||||
return storage.conformance.conformance;
|
||||
return ProtocolConformanceRef::getFromOpaqueValue(
|
||||
storage.conformance.conformanceRef);
|
||||
|
||||
case Witness:
|
||||
return storage.polymorphic.conformance;
|
||||
return ProtocolConformanceRef(storage.polymorphic.conformance);
|
||||
|
||||
case TypeWitness:
|
||||
return storage.typeWitness.conformance;
|
||||
return ProtocolConformanceRef(storage.typeWitness.conformance);
|
||||
|
||||
case Override:
|
||||
case UnownedUnsafe:
|
||||
case NonisolatedUnsafe:
|
||||
case ReferenceToUnsafe:
|
||||
case ReferenceToUnsafeThroughTypealias:
|
||||
case CallToUnsafe:
|
||||
return nullptr;
|
||||
case PreconcurrencyImport:
|
||||
return ProtocolConformanceRef::forInvalid();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -149,6 +149,7 @@ class ExtendedValidationInfo {
|
||||
unsigned HasCxxInteroperability : 1;
|
||||
unsigned AllowNonResilientAccess: 1;
|
||||
unsigned SerializePackageEnabled: 1;
|
||||
unsigned StrictMemorySafety: 1;
|
||||
} Bits;
|
||||
public:
|
||||
ExtendedValidationInfo() : Bits() {}
|
||||
@@ -246,6 +247,13 @@ public:
|
||||
void setIsConcurrencyChecked(bool val = true) {
|
||||
Bits.IsConcurrencyChecked = val;
|
||||
}
|
||||
bool strictMemorySafety() const {
|
||||
return Bits.StrictMemorySafety;
|
||||
}
|
||||
void setStrictMemorySafety(bool val = true) {
|
||||
Bits.StrictMemorySafety = val;
|
||||
}
|
||||
|
||||
bool hasCxxInteroperability() const { return Bits.HasCxxInteroperability; }
|
||||
void setHasCxxInteroperability(bool val) {
|
||||
Bits.HasCxxInteroperability = val;
|
||||
|
||||
Reference in New Issue
Block a user