Merge pull request #7870 from stephentyrone/FloatingPoint-Hashable
FloatingPoint should imply Hashable.
`Hashable` is related to `Equatable`, and `FloatingPoint` is `Equatable`, with enough additional constraints that `Hashable` conformance is practical.
There's *almost* no excuse for any `Equatable` thing not to also be `Hashable`; the exception is when the underlying representation may be denormalized in some way that makes it impossible or expensive to normalize (e.g. `Set`). Floating point numbers have denormalized forms, so this comes down to the cost of normalization. Since we can't imagine a representation whose normalization is much more expensive than the subsequent hashing step, the conformance belongs.
diff --git a/docs/SIL.rst b/docs/SIL.rst
index 6e45602..3b8ad25 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -84,7 +84,7 @@
If an arithmetic overflow occurs during the constant expression computation, a diagnostic
is issued.
- **Return analysis** verifies that each function returns a value on every
- code path and doesn't "fall of the end" of its definition, which is an error.
+ code path and doesn't "fall off the end" of its definition, which is an error.
It also issues an error when a ``noreturn`` function returns.
- **Critical edge splitting** splits all critical edges from terminators that
don't support arbitrary basic block arguments (all non cond_branch
diff --git a/include/swift/AST/AvailabilitySpec.h b/include/swift/AST/AvailabilitySpec.h
index 787f819..d5ebba9 100644
--- a/include/swift/AST/AvailabilitySpec.h
+++ b/include/swift/AST/AvailabilitySpec.h
@@ -31,7 +31,7 @@
/// A platform-version constraint of the form "PlatformName X.Y.Z"
PlatformVersionConstraint,
- /// A wildcard constraint, spelled '*', that is be equivalent
+ /// A wildcard constraint, spelled '*', that is equivalent
/// to CurrentPlatformName >= MinimumDeploymentTargetVersion
OtherPlatform,
diff --git a/include/swift/AST/DiagnosticsCommon.def b/include/swift/AST/DiagnosticsCommon.def
index a000471..678d17f 100644
--- a/include/swift/AST/DiagnosticsCommon.def
+++ b/include/swift/AST/DiagnosticsCommon.def
@@ -58,8 +58,6 @@
// Generic disambiguation
NOTE(while_parsing_as_left_angle_bracket,none,
"while parsing this '<' as a type parameter bracket", ())
-NOTE(while_parsing_as_less_operator,none,
- "while parsing this '<' as an operator", ())
// FIXME: This is used both as a parse error (a literal "super" outside a
diff --git a/include/swift/AST/DiagnosticsDriver.def b/include/swift/AST/DiagnosticsDriver.def
index 65d061a..eed9c38 100644
--- a/include/swift/AST/DiagnosticsDriver.def
+++ b/include/swift/AST/DiagnosticsDriver.def
@@ -113,6 +113,10 @@
"unable to determine when '%0' was last modified: %1",
(StringRef, StringRef))
+WARNING(warn_unable_to_load_dependencies, none,
+ "unable to load dependencies file \"%0\", disabling incremental mode",
+ (StringRef))
+
ERROR(error_input_changed_during_build,none,
"input file '%0' was modified during the build",
(StringRef))
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index c5e2979..0cc1062 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -448,6 +448,10 @@
"expected constant in SIL code", ())
ERROR(referenced_value_no_accessor,none,
"referenced declaration has no %select{getter|setter}0", (unsigned))
+ERROR(expected_sil_value_ownership_kind,none,
+ "expected value ownership kind in SIL code", ())
+ERROR(expected_sil_colon,none,
+ "expected ':' before %0", (StringRef))
// SIL Values
ERROR(sil_value_redefinition,none,
@@ -591,6 +595,8 @@
"sil protocol not found %0", (Identifier))
ERROR(sil_witness_assoc_not_found,none,
"sil associated type decl not found %0", (Identifier))
+ERROR(sil_witness_assoc_conf_not_found,none,
+ "sil associated type path for conformance not found %0", (StringRef))
ERROR(sil_witness_protocol_conformance_not_found,none,
"sil protocol conformance not found", ())
@@ -749,8 +755,6 @@
"default arguments are not allowed in subscripts", ())
ERROR(no_default_arg_curried,none,
"default arguments are not allowed in curried parameter lists", ())
-WARNING(let_on_param_is_redundant, none,
- "'let' keyword is unnecessary; function parameters are immutable by default", (unsigned))
ERROR(var_pattern_in_var,none,
"'%select{var|let}0' cannot appear nested inside another 'var' or "
"'let' pattern", (unsigned))
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 42e442f..221461d 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -45,11 +45,6 @@
NOTE(extended_type_declared_here,none,
"extended type declared here", ())
-NOTE(while_converting_default_tuple_value,none,
- "while converting default tuple value to element type %0", (Type))
-NOTE(while_converting_subscript_index,none,
- "while converting subscript index to expected type %0", (Type))
-
//------------------------------------------------------------------------------
// Constraint solver diagnostics
//------------------------------------------------------------------------------
@@ -915,8 +910,6 @@
"%select{local function|closure}0 that captures "
"%select{context|generic parameters|dynamic Self type}1",
(bool, unsigned))
-NOTE(c_function_pointer_captures_here,none,
- "%0 captured here", (Identifier))
//------------------------------------------------------------------------------
// Type Check Declarations
@@ -1508,8 +1501,6 @@
ERROR(redundant_conformance,none,
"redundant conformance of %0 to protocol %1", (Type, DeclName))
-NOTE(protocol_conformance_implied_here,none,
- "implied protocol conformance %0 here can be made explicit", (Identifier))
// "Near matches"
WARNING(optional_req_near_match,none,
@@ -1517,9 +1508,6 @@
(DescriptiveDeclKind, DeclName, DeclName, DeclName))
NOTE(optional_req_nonobjc_near_match_add_objc,none,
"add '@objc' to provide an Objective-C entrypoint", ())
-NOTE(optional_req_nonobjc_to_objc,none,
- "rename to %0 to satisfy this requirement",
- (DeclName))
NOTE(optional_req_near_match_move,none,
"move %0 to %select{an|another}1 extension to silence this warning",
(DeclName, unsigned))
@@ -1775,8 +1763,6 @@
"static declarations are already final", ())
ERROR(open_decl_cannot_be_final,none,
"%0 cannot be declared both 'final' and 'open'", (DescriptiveDeclKind))
-NOTE(decl_init_here,none,
- "initial value is here", ())
// Inheritance
@@ -2069,9 +2055,6 @@
#define SELECT_APPLICATION_MAIN "select{'UIApplicationMain'|'NSApplicationMain'}"
#define SELECT_APPLICATION_DELEGATE "select{'UIApplicationDelegate'|'NSApplicationDelegate'}"
-ERROR(attr_ApplicationMain_not_class,none,
- "%" SELECT_APPLICATION_MAIN "0 attribute may only be used on classes",
- (unsigned))
ERROR(attr_ApplicationMain_not_ApplicationDelegate,none,
"%" SELECT_APPLICATION_MAIN "0 class must conform to the %" SELECT_APPLICATION_DELEGATE "0 protocol",
(unsigned))
@@ -2125,17 +2108,7 @@
"found this candidate", ())
NOTE(found_candidate_type,none,
"found candidate with type %0", (Type))
-NOTE(first_declaration,none,
- "first declaration", ())
-NOTE(second_declaration,none,
- "second declaration", ())
-ERROR(no_IntegerLiteralType_found,none,
- "standard library error: IntegerLiteralType not defined", ())
-ERROR(no_FloatLiteralType_found,none,
- "standard library error: FloatLiteralType not defined", ())
-ERROR(no_StringLiteralType_found,none,
- "standard library error: StringLiteralType not defined", ())
ERROR(no_MaxBuiltinIntegerType_found,none,
"standard library error: _MaxBuiltinIntegerType is not properly defined", ())
ERROR(no_MaxBuiltinFloatType_found,none,
@@ -2241,9 +2214,6 @@
"'" TRY_KIND_SELECT(0) "' following assignment operator does not cover "
"everything to its right", (unsigned))
-NOTE(subscript_decl_here,none,
- "subscript operator declared here", ())
-
ERROR(broken_bool,none, "type 'Bool' is broken", ())
WARNING(inject_forced_downcast,none,
@@ -3465,10 +3435,6 @@
"%select{variable|parameter}1 %0 was written to, but never read",
(Identifier, unsigned))
-WARNING(extraneous_default_args_in_call, none,
- "call to %0 has extraneous arguments that could use defaults",
- (DeclName))
-
//------------------------------------------------------------------------------
// Circular reference diagnostics
//------------------------------------------------------------------------------
diff --git a/include/swift/AST/GenericEnvironment.h b/include/swift/AST/GenericEnvironment.h
index 0db7f0f..cba8da9 100644
--- a/include/swift/AST/GenericEnvironment.h
+++ b/include/swift/AST/GenericEnvironment.h
@@ -242,6 +242,8 @@
SubstitutionList getForwardingSubstitutions() const;
+ void dump(raw_ostream &os) const;
+
void dump() const;
};
diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h
index a859f92..54f572c 100644
--- a/include/swift/AST/GenericSignature.h
+++ b/include/swift/AST/GenericSignature.h
@@ -123,13 +123,6 @@
return const_cast<GenericSignature *>(this)->getRequirementsBuffer();
}
- /// Check if the generic signature makes all generic parameters
- /// concrete.
- bool areAllParamsConcrete() const {
- auto iter = getAllDependentTypes();
- return iter.begin() == iter.end();
- }
-
/// Only allow allocation by doing a placement new.
void *operator new(size_t Bytes, void *Mem) {
assert(Mem);
@@ -174,11 +167,6 @@
void getSubstitutions(const SubstitutionMap &subMap,
SmallVectorImpl<Substitution> &result) const;
- /// Return a range that iterates through all of the types that require
- /// substitution, which includes the generic parameter types as well as
- /// other dependent types that require additional conformances.
- SmallVector<Type, 4> getAllDependentTypes() const;
-
/// Enumerate all of the dependent types in the type signature that will
/// occur in substitution lists (in order), along with the set of
/// conformance requirements placed on that dependent type.
@@ -191,6 +179,33 @@
bool enumeratePairedRequirements(
llvm::function_ref<bool(Type, ArrayRef<Requirement>)> fn) const;
+ /// Return a vector of all generic parameters that are not subject to
+ /// a concrete same-type constraint.
+ SmallVector<GenericTypeParamType *, 2> getSubstitutableParams() const;
+
+ /// Check if the generic signature makes all generic parameters
+ /// concrete.
+ bool areAllParamsConcrete() const {
+ return !enumeratePairedRequirements(
+ [](Type, ArrayRef<Requirement>) -> bool {
+ return true;
+ });
+ }
+
+ /// Return the size of a SubstitutionList built from this signature.
+ ///
+ /// Don't add new calls of this -- the representation of SubstitutionList
+ /// will be changing soon.
+ unsigned getSubstitutionListSize() const {
+ unsigned result = 0;
+ enumeratePairedRequirements(
+ [&](Type, ArrayRef<Requirement>) -> bool {
+ result++;
+ return false;
+ });
+ return result;
+ }
+
/// Determines whether this GenericSignature is canonical.
bool isCanonical() const;
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index ed575c4..9b2fe86 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -32,6 +32,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TrailingObjects.h"
#include <functional>
#include <memory>
@@ -590,6 +591,8 @@
case Concrete:
return 0;
}
+
+ llvm_unreachable("Unhandled RequirementSourceKind in switch.");
}
/// Determines whether we have been provided with an acceptable storage kind
@@ -618,6 +621,8 @@
case Concrete:
return false;
}
+
+ llvm_unreachable("Unhandled RequirementSourceKind in switch.");
}
public:
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index 3d9f492..0dfdf5f 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -339,6 +339,10 @@
/// the requirements of those protocols.
InheritedConformanceMap InheritedMapping;
+ /// Conformances that satisfy each of conformance requirements of the
+ /// requirement signature of the protocol.
+ ArrayRef<ProtocolConformanceRef> SignatureConformances;
+
LazyMemberLoader *Resolver = nullptr;
uint64_t ResolverContextData;
@@ -440,6 +444,18 @@
const Substitution &substitution,
TypeDecl *typeDecl) const;
+ /// Given a dependent type expressed in terms of the self parameter,
+ /// map it into the context of this conformance.
+ Type getAssociatedType(Type assocType,
+ LazyResolver *resolver = nullptr) const;
+
+ /// Given that the requirement signature of the protocol directly states
+ /// that the given dependent type must conform to the given protocol,
+ /// return its associated conformance.
+ ProtocolConformanceRef
+ getAssociatedConformance(Type assocType, ProtocolDecl *protocol,
+ LazyResolver *resolver = nullptr) const;
+
/// Retrieve the value witness corresponding to the given requirement.
///
/// Note that a generic witness will only be specialized if the conformance
@@ -481,6 +497,17 @@
InheritedMapping[proto] = conformance;
}
+ /// Retrieve the protocol conformances that satisfy the requirements of the
+ /// protocol, which line up with the conformance constraints in the
+ /// protocol's requirement signature.
+ ArrayRef<ProtocolConformanceRef> getSignatureConformances() const {
+ return SignatureConformances;
+ }
+
+ /// Copy the given protocol conformances for the requirement signature into
+ /// the normal conformance.
+ void setSignatureConformances(ArrayRef<ProtocolConformanceRef> conformances);
+
/// Determine whether the witness for the given type requirement
/// is the default definition.
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
diff --git a/include/swift/AST/ProtocolConformanceRef.h b/include/swift/AST/ProtocolConformanceRef.h
index 7972750..1368cff 100644
--- a/include/swift/AST/ProtocolConformanceRef.h
+++ b/include/swift/AST/ProtocolConformanceRef.h
@@ -20,7 +20,6 @@
#include "llvm/ADT/PointerUnion.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/Type.h"
-#include "swift/AST/ProtocolConformance.h"
namespace llvm {
class raw_ostream;
@@ -28,6 +27,8 @@
namespace swift {
+class ProtocolConformance;
+
/// A ProtocolConformanceRef is a handle to a protocol conformance which
/// may be either concrete or abstract.
///
diff --git a/include/swift/AST/Requirement.h b/include/swift/AST/Requirement.h
index b4dfde3..650c0ef 100644
--- a/include/swift/AST/Requirement.h
+++ b/include/swift/AST/Requirement.h
@@ -19,6 +19,7 @@
#include "swift/AST/Type.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/ErrorHandling.h"
namespace swift {
@@ -109,6 +110,8 @@
case RequirementKind::Layout:
return Requirement(getKind(), newFirst, getLayoutConstraint());
}
+
+ llvm_unreachable("Unhandled RequirementKind in switch.");
}
/// \brief Retrieve the layout constraint.
diff --git a/include/swift/AST/SubstitutionMap.h b/include/swift/AST/SubstitutionMap.h
index 8209350..6ecc02c 100644
--- a/include/swift/AST/SubstitutionMap.h
+++ b/include/swift/AST/SubstitutionMap.h
@@ -83,12 +83,6 @@
/// Retrieve the conformances for the given type.
ArrayRef<ProtocolConformanceRef> getConformances(CanType type) const;
- /// Look up the replacement for the given type parameter or interface type.
- /// Note that this only finds replacements for maps that are directly
- /// stored inside the map. In most cases, you should call Type::subst()
- /// instead, since that will resolve member types also.
- Type lookupSubstitution(CanSubstitutableType type) const;
-
bool empty() const {
return subMap.empty();
}
@@ -149,6 +143,13 @@
private:
friend class GenericSignature;
friend class GenericEnvironment;
+ friend struct QuerySubstitutionMap;
+
+ /// Look up the replacement for the given type parameter or interface type.
+ /// Note that this only finds replacements for maps that are directly
+ /// stored inside the map. In most cases, you should call Type::subst()
+ /// instead, since that will resolve member types also.
+ Type lookupSubstitution(CanSubstitutableType type) const;
// You should not need to call these directly to build SubstitutionMaps;
// instead, use GenericSignature::getSubstitutionMap() or
diff --git a/include/swift/Basic/Defer.h b/include/swift/Basic/Defer.h
index 23ba2ea..8b20dce 100644
--- a/include/swift/Basic/Defer.h
+++ b/include/swift/Basic/Defer.h
@@ -23,10 +23,10 @@
namespace swift {
template <typename F>
class DoAtScopeExit {
- F &Fn;
+ F Fn;
void operator=(DoAtScopeExit&) = delete;
public:
- DoAtScopeExit(F &Fn) : Fn(Fn){}
+ DoAtScopeExit(F &&Fn) : Fn(std::move(Fn)) {}
~DoAtScopeExit() {
Fn();
}
@@ -36,7 +36,7 @@
struct DeferTask {};
template<typename F>
DoAtScopeExit<typename std::decay<F>::type> operator+(DeferTask, F&& fn) {
- return DoAtScopeExit<typename std::decay<F>::type>(fn);
+ return DoAtScopeExit<typename std::decay<F>::type>(std::move(fn));
}
}
} // end namespace swift
diff --git a/include/swift/Basic/Demangle.h b/include/swift/Basic/Demangle.h
index 3635a8b..60bd414 100644
--- a/include/swift/Basic/Demangle.h
+++ b/include/swift/Basic/Demangle.h
@@ -207,6 +207,9 @@
// Only to be used by the demangler parsers.
void addChild(NodePointer Child, NodeFactory &Factory);
+
+ // Reverses the order of children.
+ void reverseChildren(size_t StartingAt = 0);
};
/// Returns true if the mangledName starts with the swift mangling prefix.
@@ -289,6 +292,20 @@
/// or ObjC-as-swift thunks.
bool isThunkSymbol(llvm::StringRef MangledName);
+ /// Returns the mangled name of the target of a thunk.
+ ///
+ /// \returns Returns the remaining name after removing the thunk mangling
+ /// characters from \p MangledName. If \p MangledName is not a thunk symbol,
+ /// an empty string is returned.
+ std::string getThunkTarget(llvm::StringRef MangledName);
+
+ /// Returns true if the \p mangledName refers to a function which conforms to
+ /// the Swift calling convention.
+ ///
+ /// The return value is unspecified if the \p MangledName does not refer to a
+ /// function symbol.
+ bool hasSwiftCallingConvention(llvm::StringRef MangledName);
+
/// Deallocates all nodes.
///
/// The memory which is used for nodes is not freed but recycled for the next
diff --git a/include/swift/Basic/Demangler.h b/include/swift/Basic/Demangler.h
index a1ca433..d30736b 100644
--- a/include/swift/Basic/Demangler.h
+++ b/include/swift/Basic/Demangler.h
@@ -35,6 +35,8 @@
namespace swift {
namespace Demangle {
+class CharVector;
+
/// The allocator for demangling nodes and other demangling-internal stuff.
///
/// It implements a simple bump-pointer allocator.
@@ -77,15 +79,15 @@
#endif
}
- ~NodeFactory() {
+ virtual ~NodeFactory() {
freeSlabs(CurrentSlab);
#ifdef NODE_FACTORY_DEBUGGING
std::cerr << "Delete NodeFactory " << this << "\n";
#endif
}
- void clear();
-
+ virtual void clear();
+
/// Allocates an object of type T or an array of objects of type T.
template<typename T> T *Allocate(size_t NumObjects = 1) {
size_t ObjectSize = NumObjects * sizeof(T);
@@ -173,6 +175,12 @@
/// The \p Text string is copied.
NodePointer createNode(Node::Kind K, llvm::StringRef Text);
+ /// Creates a node of kind \p K with a \p Text payload.
+ ///
+ /// The \p Text string is already allocted with the Factory and therefore
+ /// it is _not_ copied.
+ NodePointer createNode(Node::Kind K, const CharVector &Text);
+
/// Creates a node of kind \p K with a \p Text payload, which must be a C
/// string literal.
///
@@ -180,6 +188,92 @@
NodePointer createNode(Node::Kind K, const char *Text);
};
+/// A vector with a storage managed by a NodeFactory.
+///
+/// This Vector class only provides the minimal functionality needed by the
+/// Demangler.
+template<typename T> class Vector {
+
+protected:
+ T *Elems = nullptr;
+ size_t NumElems = 0;
+ size_t Capacity = 0;
+
+public:
+
+ typedef T *iterator;
+
+ Vector() { }
+
+ /// Construct a vector with an inital capacity.
+ explicit Vector(NodeFactory &Factory, size_t InitialCapacity) {
+ init(Factory, InitialCapacity);
+ }
+
+ /// Clears the content and re-allocates the buffer with an initial capacity.
+ void init(NodeFactory &Factory, size_t InitialCapacity) {
+ Elems = Factory.Allocate<T>(InitialCapacity);
+ NumElems = 0;
+ Capacity = InitialCapacity;
+ }
+
+ void free() {
+ Capacity = 0;
+ Elems = 0;
+ }
+
+ iterator begin() { return Elems; }
+ iterator end() { return Elems + NumElems; }
+
+ T &operator[](size_t Idx) {
+ assert(Idx < NumElems);
+ return Elems[Idx];
+ }
+
+ const T &operator[](size_t Idx) const {
+ assert(Idx < NumElems);
+ return Elems[Idx];
+ }
+
+ size_t size() const { return NumElems; }
+
+ bool empty() const { return NumElems == 0; }
+
+ T &back() { return (*this)[NumElems - 1]; }
+
+ void push_back(const T &NewElem, NodeFactory &Factory) {
+ if (NumElems >= Capacity)
+ Factory.Reallocate(Elems, Capacity, /*Growth*/ 1);
+ assert(NumElems < Capacity);
+ Elems[NumElems++] = NewElem;
+ }
+
+ T pop_back_val() {
+ if (empty())
+ return T();
+ T Val = (*this)[NumElems - 1];
+ NumElems--;
+ return Val;
+ }
+};
+
+/// A vector of chars (a string) with a storage managed by a NodeFactory.
+///
+/// This CharVector class only provides the minimal functionality needed by the
+/// Demangler.
+class CharVector : public Vector<char> {
+public:
+ // Append another string.
+ void append(StringRef Rhs, NodeFactory &Factory);
+
+ // Append an integer as readable number.
+ void append(int Number, NodeFactory &Factory);
+
+ StringRef str() const {
+ return StringRef(Elems, NumElems);
+ }
+};
+
/// The demangler.
///
/// It de-mangles a string and it also ownes the returned node-tree. This means
@@ -194,22 +288,14 @@
size_t Pos;
};
- std::vector<NodeWithPos> NodeStack;
- std::vector<NodePointer> Substitutions;
- std::vector<unsigned> PendingSubstitutions;
+ Vector<NodeWithPos> NodeStack;
+ Vector<NodePointer> Substitutions;
+ Vector<unsigned> PendingSubstitutions;
static const int MaxNumWords = 26;
StringRef Words[MaxNumWords];
int NumWords = 0;
- static NodePointer pop_back_val(std::vector<NodePointer> &NodeVector) {
- if (NodeVector.empty())
- return nullptr;
- NodePointer Val = NodeVector.back();
- NodeVector.pop_back();
- return Val;
- }
-
bool nextIf(StringRef str) {
if (!Text.substr(Pos).startswith(str)) return false;
Pos += str.size();
@@ -241,16 +327,11 @@
}
void pushNode(NodePointer Nd) {
- NodeStack.push_back({ Nd, Pos });
+ NodeStack.push_back({ Nd, Pos }, *this);
}
NodePointer popNode() {
- if (!NodeStack.empty()) {
- NodePointer Val = NodeStack.back().Node;
- NodeStack.pop_back();
- return Val;
- }
- return nullptr;
+ return NodeStack.pop_back_val().Node;
}
NodePointer popNode(Node::Kind kind) {
@@ -279,7 +360,7 @@
void addSubstitution(NodePointer Nd) {
if (Nd)
- Substitutions.push_back(Nd);
+ Substitutions.push_back(Nd, *this);
}
NodePointer addChild(NodePointer Parent, NodePointer Child);
@@ -326,7 +407,7 @@
NodePointer popProtocol();
NodePointer demangleBoundGenericType();
NodePointer demangleBoundGenericArgs(NodePointer nominalType,
- const std::vector<NodePointer> &TypeLists,
+ const Vector<NodePointer> &TypeLists,
size_t TypeListIdx);
NodePointer demangleInitializer();
NodePointer demangleImplParamConvention();
@@ -367,6 +448,8 @@
public:
Demangler() {}
+
+ void clear() override;
/// Demangle the given symbol and return the parse tree.
///
diff --git a/include/swift/Basic/Version.h b/include/swift/Basic/Version.h
index 20d6ce5..9c36999 100644
--- a/include/swift/Basic/Version.h
+++ b/include/swift/Basic/Version.h
@@ -52,13 +52,16 @@
/// a: [0 - 999]
/// b: [0 - 999]
class Version {
- SmallVector<uint64_t, 5> Components;
+ SmallVector<unsigned, 5> Components;
public:
/// Create the empty compiler version - this always compares greater
/// or equal to any other CompilerVersion, as in the case of building Swift
/// from latest sources outside of a build/integration/release context.
Version() = default;
+ /// Create a literal version from a list of components.
+ Version(std::initializer_list<unsigned> Values) : Components(Values) {}
+
/// Create a version from a string in source code.
///
/// Must include only groups of digits separated by a dot.
@@ -94,11 +97,15 @@
/// away any 5th component that might be in this version.
operator clang::VersionTuple() const;
- /// Return whether this version is a valid Swift language version number
- /// to set the compiler to using -swift-version; this is not the same as
- /// the set of Swift versions that have ever existed, just those that we
- /// are attempting to maintain backward-compatibility support for.
- bool isValidEffectiveLanguageVersion() const;
+ /// Returns the concrete version to use when \e this version is provided as
+ /// an argument to -swift-version.
+ ///
+ /// This is not the same as the set of Swift versions that have ever existed,
+ /// just those that we are attempting to maintain backward-compatibility
+ /// support for. It's also common for valid versions to produce a different
+ /// result; for example "-swift-version 3" at one point instructed the
+ /// compiler to act as if it is version 3.1.
+ Optional<Version> getEffectiveLanguageVersion() const;
/// Whether this version is in the Swift 3 family
bool isVersion3() const { return !empty() && Components[0] == 3; }
@@ -141,6 +148,10 @@
raw_ostream &operator<<(raw_ostream &os, const Version &version);
/// Retrieves the numeric {major, minor} Swift version.
+///
+/// Note that this is the underlying version of the language, ignoring any
+/// -swift-version flags that may have been used in a particular invocation of
+/// the compiler.
std::pair<unsigned, unsigned> getSwiftNumericVersion();
/// Retrieves a string representing the complete Swift version, which includes
diff --git a/include/swift/Driver/Compilation.h b/include/swift/Driver/Compilation.h
index ef4db3e..ad43cbf 100644
--- a/include/swift/Driver/Compilation.h
+++ b/include/swift/Driver/Compilation.h
@@ -41,6 +41,7 @@
namespace driver {
class Driver;
class ToolChain;
+ class PerformJobsState;
/// An enum providing different levels of output which should be produced
/// by a Compilation.
@@ -56,6 +57,7 @@
};
class Compilation {
+ friend class PerformJobsState;
private:
/// The DiagnosticEngine to which this Compilation should emit diagnostics.
DiagnosticEngine &Diags;
@@ -136,6 +138,10 @@
/// rebuilt.
bool ShowIncrementalBuildDecisions = false;
+ /// When true, traces the lifecycle of each driver job. Provides finer
+ /// detail than ShowIncrementalBuildDecisions.
+ bool ShowJobLifecycle = false;
+
static const Job *unwrap(const std::unique_ptr<const Job> &p) {
return p.get();
}
@@ -194,6 +200,10 @@
ShowIncrementalBuildDecisions = value;
}
+ void setShowJobLifecycle(bool value = true) {
+ ShowJobLifecycle = value;
+ }
+
void setCompilationRecordPath(StringRef path) {
assert(CompilationRecordPath.empty() && "already set");
CompilationRecordPath = path;
diff --git a/include/swift/Driver/Job.h b/include/swift/Driver/Job.h
index 6963f2a..1839506 100644
--- a/include/swift/Driver/Job.h
+++ b/include/swift/Driver/Job.h
@@ -168,6 +168,9 @@
/// terminating output with the given \p terminator.
void printCommandLine(raw_ostream &Stream, StringRef Terminator = "\n") const;
+ /// Print a short summary of this Job to the given \p Stream.
+ void printSummary(raw_ostream &Stream) const;
+
/// Print the command line for this Job to the given \p stream,
/// and include any extra environment variables that will be set.
///
diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td
index 4570b2f..dff7665 100644
--- a/include/swift/Option/Options.td
+++ b/include/swift/Option/Options.td
@@ -91,6 +91,9 @@
def driver_show_incremental : Flag<["-"], "driver-show-incremental">,
InternalDebugOpt,
HelpText<"With -v, dump information about why files are being rebuilt">;
+def driver_show_job_lifecycle : Flag<["-"], "driver-show-job-lifecycle">,
+ InternalDebugOpt,
+ HelpText<"Show every step in the lifecycle of driver jobs">;
def driver_use_filelists : Flag<["-"], "driver-use-filelists">,
InternalDebugOpt, HelpText<"Pass input files as filelists whenever possible">;
diff --git a/include/swift/Runtime/Config.h b/include/swift/Runtime/Config.h
index 2ad75a6..d8683e5 100644
--- a/include/swift/Runtime/Config.h
+++ b/include/swift/Runtime/Config.h
@@ -17,6 +17,9 @@
#ifndef SWIFT_RUNTIME_CONFIG_H
#define SWIFT_RUNTIME_CONFIG_H
+// Bring in visibility attribute macros for library visibility.
+#include "llvm/Support/Compiler.h"
+
/// Does the current Swift platform support "unbridged" interoperation
/// with Objective-C? If so, the implementations of various types must
/// implicitly handle Objective-C pointers.
@@ -185,9 +188,6 @@
#endif
-// Bring in visibility attribute macros for library visibility.
-#include "llvm/Support/Compiler.h"
-
// Generates a name of the runtime entry's implementation by
// adding an underscore as a prefix and a suffix.
#define SWIFT_RT_ENTRY_IMPL(Name) _##Name##_
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 4a8ceb0..ff984f4 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -1993,7 +1993,7 @@
return nullptr;
auto asWords = reinterpret_cast<
- ConstTargetMetadataPointer<Runtime, TargetMetadata> const *>(this);
+ ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *>(this);
return (asWords + Description->GenericParams.Offset);
}
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index 1088268..2f83a47 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -1280,6 +1280,18 @@
getSILDebugLocation(Loc), Operand, atomicity));
}
+ EndLifetimeInst *createEndLifetime(SILLocation Loc, SILValue Operand) {
+ return insert(new (F.getModule())
+ EndLifetimeInst(getSILDebugLocation(Loc), Operand));
+ }
+
+ UncheckedOwnershipConversionInst *
+ createUncheckedOwnershipConversion(SILLocation Loc, SILValue Operand,
+ ValueOwnershipKind Kind) {
+ return insert(new (F.getModule()) UncheckedOwnershipConversionInst(
+ getSILDebugLocation(Loc), Operand, Kind));
+ }
+
FixLifetimeInst *createFixLifetime(SILLocation Loc, SILValue Operand) {
return insert(new (F.getModule())
FixLifetimeInst(getSILDebugLocation(Loc), Operand));
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 9184783..f36f99a 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -1700,9 +1700,30 @@
getOpValue(Inst->getOperand())));
}
-template<typename ImplClass>
-void
-SILCloner<ImplClass>::visitMarkDependenceInst(MarkDependenceInst *Inst) {
+template <typename ImplClass>
+void SILCloner<ImplClass>::visitEndLifetimeInst(EndLifetimeInst *Inst) {
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ doPostProcess(Inst,
+ getBuilder().createEndLifetime(getOpLocation(Inst->getLoc()),
+ getOpValue(Inst->getOperand())));
+}
+
+template <typename ImplClass>
+void SILCloner<ImplClass>::visitUncheckedOwnershipConversionInst(
+ UncheckedOwnershipConversionInst *Inst) {
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ ValueOwnershipKind Kind = SILValue(Inst).getOwnershipKind();
+ if (getOpValue(Inst->getOperand()).getOwnershipKind() ==
+ ValueOwnershipKind::Trivial) {
+ Kind = ValueOwnershipKind::Trivial;
+ }
+ doPostProcess(Inst, getBuilder().createUncheckedOwnershipConversion(
+ getOpLocation(Inst->getLoc()),
+ getOpValue(Inst->getOperand()), Kind));
+}
+
+template <typename ImplClass>
+void SILCloner<ImplClass>::visitMarkDependenceInst(MarkDependenceInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createMarkDependence(getOpLocation(Inst->getLoc()),
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 77766a7..bfd2236 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -4337,6 +4337,48 @@
: UnaryInstructionBase(DebugLoc, Operand) {}
};
+/// EndLifetimeInst - An artificial end lifetime use of a value for the purpose
+/// of working around verification problems.
+///
+/// Specifically, the signature of destroying deinit takes self at +0 and
+/// returns self at +1. This is an issue since a deallocating deinit takes in
+/// self at +1. Previously, we could rely on the deallocating bit being set in
+/// the object header to allow SILGen to statically balance the +1 from the
+/// deallocating deinit. This is because deallocating values used to be
+/// immortal. The runtime now asserts if we release a deallocating value,
+/// meaning such an approach does not work. This instruction acts as a "fake"
+/// lifetime ending use allowing for static verification of deallocating
+/// destroyers, without an actual release being emitted (avoiding the runtime
+/// assert).
+class EndLifetimeInst
+ : public UnaryInstructionBase<ValueKind::EndLifetimeInst, SILInstruction,
+ /*HAS_RESULT*/ false> {
+ friend SILBuilder;
+
+ EndLifetimeInst(SILDebugLocation DebugLoc, SILValue Operand)
+ : UnaryInstructionBase(DebugLoc, Operand) {}
+};
+
+/// An unsafe conversion in between ownership kinds.
+///
+/// This is used today in destructors where due to objective-c legacy
+/// constraints, we need to be able to convert a guaranteed paramter to an owned
+/// parameter.
+class UncheckedOwnershipConversionInst
+ : public UnaryInstructionBase<ValueKind::UncheckedOwnershipConversionInst> {
+ friend SILBuilder;
+
+ ValueOwnershipKind Kind;
+
+ UncheckedOwnershipConversionInst(SILDebugLocation DebugLoc, SILValue operand,
+ ValueOwnershipKind Kind)
+ : UnaryInstructionBase(DebugLoc, operand, operand->getType()),
+ Kind(Kind) {}
+
+public:
+ ValueOwnershipKind getConversionOwnershipKind() const { return Kind; }
+};
+
/// MarkDependenceInst - Marks that one value depends on another for
/// validity in a non-obvious way.
class MarkDependenceInst : public SILInstruction {
diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def
index 770fec1..1c9b8a9 100644
--- a/include/swift/SIL/SILNodes.def
+++ b/include/swift/SIL/SILNodes.def
@@ -164,6 +164,8 @@
INST(UnmanagedAutoreleaseValueInst, RefCountingInst, unmanaged_autorelease_value, MayHaveSideEffects, DoesNotRelease)
INST(CopyUnownedValueInst, SILInstruction, copy_unowned_value, MayHaveSideEffects, DoesNotRelease)
INST(DestroyValueInst, SILInstruction, destroy_value, MayHaveSideEffects, MayRelease)
+ INST(EndLifetimeInst, SILInstruction, end_lifetime, MayHaveSideEffects, MayRelease)
+ INST(UncheckedOwnershipConversionInst, SILInstruction, unchecked_ownership_conversion, MayHaveSideEffects, MayRelease)
// IsUnique does not actually write to memory but should be modeled
// as such. Its operand is a pointer to an object reference. The
diff --git a/include/swift/SIL/SILValue.h b/include/swift/SIL/SILValue.h
index 4909013..f21e166 100644
--- a/include/swift/SIL/SILValue.h
+++ b/include/swift/SIL/SILValue.h
@@ -114,6 +114,11 @@
ValueOwnershipKind(SILModule &M, SILType Type,
SILArgumentConvention Convention);
+ /// Parse Value into a ValueOwnershipKind.
+ ///
+ /// *NOTE* Emits an unreachable if an invalid value is passed in.
+ explicit ValueOwnershipKind(StringRef Value);
+
operator innerty() const { return Value; }
Optional<ValueOwnershipKind> merge(ValueOwnershipKind RHS) const;
diff --git a/include/swift/SIL/SILWitnessTable.h b/include/swift/SIL/SILWitnessTable.h
index 5ded6fa..284d100 100644
--- a/include/swift/SIL/SILWitnessTable.h
+++ b/include/swift/SIL/SILWitnessTable.h
@@ -62,8 +62,9 @@
/// A witness table entry describing the witness for an associated type's
/// protocol requirement.
struct AssociatedTypeProtocolWitness {
- /// The associated type required.
- AssociatedTypeDecl *Requirement;
+ /// The associated type required. A dependent type in the protocol's
+ /// context.
+ CanType Requirement;
/// The protocol requirement on the type.
ProtocolDecl *Protocol;
/// The ProtocolConformance satisfying the requirement. Null if the
diff --git a/include/swift/SIL/SILWitnessVisitor.h b/include/swift/SIL/SILWitnessVisitor.h
index 9d8c266..5d3e9a9 100644
--- a/include/swift/SIL/SILWitnessVisitor.h
+++ b/include/swift/SIL/SILWitnessVisitor.h
@@ -49,27 +49,77 @@
public:
void visitProtocolDecl(ProtocolDecl *protocol) {
- // Visit inherited protocols.
- // TODO: We need to figure out all the guarantees we want here.
- // It would be abstractly good to allow conversion to a base
- // protocol to be trivial, but it's not clear that there's
- // really a structural guarantee we can rely on here.
- for (auto baseProto : protocol->getInheritedProtocols()) {
- // ObjC protocols do not have witnesses.
- if (!Lowering::TypeConverter::protocolRequiresWitnessTable(baseProto))
+ // Associated types get added after the inherited conformances, but
+ // before all the function requirements.
+ bool haveAddedAssociatedTypes = false;
+ auto addAssociatedTypes = [&] {
+ if (haveAddedAssociatedTypes) return;
+ haveAddedAssociatedTypes = true;
+
+ for (Decl *member : protocol->getMembers()) {
+ if (auto associatedType = dyn_cast<AssociatedTypeDecl>(member)) {
+ // TODO: only add associated types when they're new?
+ asDerived().addAssociatedType(associatedType);
+ }
+ }
+ };
+
+ for (auto &reqt : protocol->getRequirementSignature()
+ ->getCanonicalSignature()->getRequirements()) {
+ switch (reqt.getKind()) {
+ // These requirements don't show up in the witness table.
+ case RequirementKind::Superclass:
+ case RequirementKind::SameType:
+ case RequirementKind::Layout:
continue;
- asDerived().addOutOfLineBaseProtocol(baseProto);
+ case RequirementKind::Conformance: {
+ auto type = CanType(reqt.getFirstType());
+ assert(type->isTypeParameter());
+ auto requirement =
+ cast<ProtocolType>(CanType(reqt.getSecondType()))->getDecl();
+
+ // ObjC protocols do not have witnesses.
+ if (!Lowering::TypeConverter::protocolRequiresWitnessTable(requirement))
+ continue;
+
+ // If the type parameter is 'self', consider this to be protocol
+ // inheritance. In the canonical signature, these should all
+ // come before any protocol requirements on associated types.
+ if (auto parameter = dyn_cast<GenericTypeParamType>(type)) {
+ assert(type->isEqual(protocol->getSelfInterfaceType()));
+ assert(!haveAddedAssociatedTypes &&
+ "unexpected ordering of conformances");
+ assert(parameter->getDepth() == 0 && parameter->getIndex() == 0 &&
+ "non-self type parameter in protocol");
+ asDerived().addOutOfLineBaseProtocol(requirement);
+ continue;
+ }
+
+ // Add the associated types if we haven't yet.
+ addAssociatedTypes();
+
+ // Otherwise, add an associated requirement.
+ asDerived().addAssociatedConformance(type, requirement);
+ continue;
+ }
+ }
+ llvm_unreachable("bad requirement kind");
}
- /// Visit the witnesses for the direct members of a protocol.
+ // Add the associated types if we haven't yet.
+ addAssociatedTypes();
+
+ // Visit the witnesses for the direct members of a protocol.
for (Decl *member : protocol->getMembers())
ASTVisitor<T>::visit(member);
}
/// Fallback for unexpected protocol requirements.
void visitDecl(Decl *d) {
+#ifndef NDEBUG
d->print(llvm::errs());
+#endif
llvm_unreachable("unhandled protocol requirement");
}
@@ -94,11 +144,7 @@
}
void visitAssociatedTypeDecl(AssociatedTypeDecl *td) {
- SmallVector<ProtocolDecl *, 4> protos;
- for (auto p : td->getConformingProtocols())
- protos.push_back(p);
- ProtocolType::canonicalizeProtocols(protos);
- asDerived().addAssociatedType(td, protos);
+ // We already visited these in the first pass.
}
void visitTypeAliasDecl(TypeAliasDecl *tad) {
diff --git a/include/swift/SILOptimizer/Utils/Generics.h b/include/swift/SILOptimizer/Utils/Generics.h
index cf4395d..58406b6 100644
--- a/include/swift/SILOptimizer/Utils/Generics.h
+++ b/include/swift/SILOptimizer/Utils/Generics.h
@@ -115,6 +115,15 @@
bool HasUnboundGenericParams);
void createSubstitutedAndSpecializedTypes();
+ bool prepareAndCheck(ApplySite Apply, SILFunction *Callee,
+ SubstitutionList ParamSubs);
+ void specializeConcreteAndGenericSubstitutions(ApplySite Apply,
+ SILFunction *Callee,
+ SubstitutionList ParamSubs);
+ void specializeConcreteSubstitutions(ApplySite Apply, SILFunction *Callee,
+ SubstitutionList ParamSubs);
+
+ ReabstractionInfo() {}
public:
/// Constructs the ReabstractionInfo for generic function \p Orig with
/// substitutions \p ParamSubs.
@@ -219,6 +228,10 @@
/// Returns true if it is a partial generic specialization.
bool isPartialSpecialization() const;
+
+ /// Returns true if a given apply can be specialized.
+ static bool canBeSpecialized(ApplySite Apply, SILFunction *Callee,
+ SubstitutionList ParamSubs);
};
/// Helper class for specializing a generic function given a list of
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index e790e71..3bf2312 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
/// in source control, you should also update the comment to briefly
/// 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.
-const uint16_t VERSION_MINOR = 321; // Last change: restrict to extension
+const uint16_t VERSION_MINOR = 325; // Last change: unchecked_ownership_conver
using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
diff --git a/include/swift/SwiftDemangle/SwiftDemangle.h b/include/swift/SwiftDemangle/SwiftDemangle.h
index eb02d7e..8cf4ca5 100644
--- a/include/swift/SwiftDemangle/SwiftDemangle.h
+++ b/include/swift/SwiftDemangle/SwiftDemangle.h
@@ -53,6 +53,14 @@
char *OutputBuffer,
size_t Length);
+/// \brief Demangles a Swift function name and returns true if the function
+/// conforms to the Swift calling convention.
+///
+/// \returns true if the function conforms to the Swift calling convention.
+/// The return value is unspecified if the \p MangledName does not refer to a
+/// function symbol.
+int swift_demangle_hasSwiftCallingConvention(const char *MangledName);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/include/swift/Syntax/DeclSyntax.h b/include/swift/Syntax/DeclSyntax.h
index eb936fa..e5fa79e 100644
--- a/include/swift/Syntax/DeclSyntax.h
+++ b/include/swift/Syntax/DeclSyntax.h
@@ -18,10 +18,10 @@
#ifndef SWIFT_SYNTAX_DECLSYNTAX_H
#define SWIFT_SYNTAX_DECLSYNTAX_H
-#include "swift/Syntax/GenericSyntax.h"
#include "swift/Syntax/References.h"
#include "swift/Syntax/RawSyntax.h"
#include "swift/Syntax/Syntax.h"
+#include "swift/Syntax/SyntaxCollection.h"
#include "swift/Syntax/SyntaxData.h"
#include "swift/Syntax/TokenSyntax.h"
#include "swift/Syntax/TypeSyntax.h"
@@ -32,6 +32,148 @@
namespace swift {
namespace syntax {
+class ExprSyntax;
+class ExprSyntaxData;
+class CodeBlockStmtSyntax;
+class CodeBlockStmtSyntaxData;
+class TypeAttributesSyntax;
+class TypeAttributesSyntaxData;
+class DeclModifierListSyntax;
+class GenericWhereClauseSyntax;
+class GenericWhereClauseSyntaxData;
+class GenericParameterListSyntax;
+class GenericParameterListSyntaxData;
+
+#pragma mark declaration-modifier Data
+
+class DeclModifierSyntaxData final : public SyntaxData {
+ friend struct SyntaxFactory;
+ friend class SyntaxData;
+ friend class Syntax;
+ friend class DeclModifierSyntax;
+
+ DeclModifierSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ const CursorIndex IndexInParent = 0);
+
+ static RC<DeclModifierSyntaxData> make(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ const CursorIndex IndexInParent = 0);
+
+ static RC<DeclModifierSyntaxData> makeBlank();
+
+public:
+ static bool classof(const SyntaxData *SD) {
+ return SD->getKind() == SyntaxKind::DeclModifier;
+ }
+};
+
+#pragma mark declaration-modifier API
+
+/// declaration-modifier -> access-level-modifier
+/// | mutation-modifier
+/// | 'class'
+/// | 'convenience'
+/// | 'dynamic'
+/// | 'final'
+/// | 'infix'
+/// | 'lazy'
+/// | 'optional'
+/// | 'override'
+/// | 'postfix'
+/// | 'prefix'
+/// | 'required'
+/// | 'static'
+/// | 'unowned'
+/// | 'unowned(safe)'
+/// | 'unowned(unsafe)'
+/// | 'weak'
+/// access-level-modifier -> 'private' | 'private' '(' 'set' ')'
+/// | 'fileprivate' | 'fileprivate' '(' 'set' ')'
+/// | 'internal' | 'internal' '(' 'set' ')'
+/// | 'public' | 'public' '(' 'set' ')'
+/// | 'open' | 'open' '(' 'set' ')'
+/// mutation-modifier -> 'mutating' | 'nonmutating'
+class DeclModifierSyntax final : public Syntax {
+ friend struct SyntaxFactory;
+ friend class Syntax;
+ friend class SyntaxData;
+ friend class DeclModifierSyntaxData;
+
+ enum class Cursor : CursorIndex {
+ Name,
+ LeftParen,
+ Argument,
+ RightParen
+ };
+
+ DeclModifierSyntax(const RC<SyntaxData> Root, const DataType *Data)
+ : Syntax(Root, Data) {}
+
+public:
+ using DataType = DeclModifierSyntaxData;
+
+ /// Return the name of the modifier.
+ RC<TokenSyntax> getName() const;
+
+ /// Return a DeclModifierSyntax with the given name.
+ DeclModifierSyntax withName(RC<TokenSyntax> NewName) const;
+
+ /// Return the left parenthesis '(' token as a part of the argument clause,
+ /// if there is one.
+ RC<TokenSyntax> getLeftParenToken() const;
+
+ /// Return a DeclModifierSyntax with the given left parenthesis '(' token.
+ DeclModifierSyntax withLeftParenToken(RC<TokenSyntax> NewLeftParen) const;
+
+ /// Get the argument to the declaration modifier.
+ ///
+ /// This is either:
+ /// - 'set' for the access modifiers such as 'private' or 'public', or
+ /// - 'safe' / 'unsafe' for the 'unowned' modifier.
+ RC<TokenSyntax> getArgument() const;
+
+ /// Return a DeclModifierSyntax with the given argument.
+ DeclModifierSyntax withArgument(RC<TokenSyntax> NewArgument) const;
+
+ /// Return the right parenthesis ')' token as a part of the argument clause,
+ /// if there is one.
+ RC<TokenSyntax> getRightParenToken() const;
+
+ /// Return a DeclModifierSyntax with the given right parenthesis ')' token.
+ DeclModifierSyntax withRightParenToken(RC<TokenSyntax> NewRightParen) const;
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::DeclModifier;
+ }
+};
+
+#pragma mark declaration-modifiers Data
+
+using DeclModifierListSyntaxData =
+ SyntaxCollectionData<SyntaxKind::DeclModifierList, DeclModifierSyntax>;
+
+#pragma mark declaration-modifiers API
+
+class DeclModifierListSyntax final :
+ public SyntaxCollection<SyntaxKind::DeclModifierList, DeclModifierSyntax> {
+
+ friend struct SyntaxFactory;
+ friend class Syntax;
+ friend class SyntaxData;
+ friend class FunctionDeclSyntax;
+
+ using DataType = DeclModifierListSyntaxData;
+
+ DeclModifierListSyntax(const RC<SyntaxData> Root, const DataType *Data)
+ : SyntaxCollection(Root, Data) {}
+
+public:
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::DeclModifierList;
+ }
+};
+
#pragma mark declaration Data
class DeclSyntaxData : public SyntaxData {
@@ -380,6 +522,368 @@
TypeAliasDeclSyntax build() const;
};
+#pragma mark - function-parameter Data
+
+class FunctionParameterSyntaxData final : public SyntaxData {
+
+ friend struct SyntaxFactory;
+ friend class Syntax;
+ friend class SyntaxData;
+ friend class FunctionParameterSyntax;
+
+ RC<TypeSyntaxData> CachedTypeSyntax;
+ RC<ExprSyntaxData> CachedDefaultValue;
+
+ FunctionParameterSyntaxData(RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+ static RC<FunctionParameterSyntaxData>
+ make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+ static RC<FunctionParameterSyntaxData> makeBlank();
+
+public:
+ static bool classof(const SyntaxData *SD) {
+ return SD->getKind() == SyntaxKind::FunctionParameter;
+ }
+};
+
+#pragma mark - function-parameter API
+
+/// parameter ->
+/// external-parameter-name? local-parameter-name ':'
+/// type '...'? '='? expression? ','?
+class FunctionParameterSyntax final : public Syntax {
+ friend struct SyntaxFactory;
+ friend class Syntax;
+ friend class SyntaxData;
+ friend class FunctionParameterSyntaxData;
+
+ enum class Cursor : CursorIndex {
+ ExternalName,
+ LocalName,
+ Colon,
+ Type,
+ Ellipsis,
+ DefaultEqual,
+ DefaultExpression,
+ TrailingComma,
+ };
+
+public:
+ using DataType = FunctionParameterSyntaxData;
+
+ FunctionParameterSyntax(const RC<SyntaxData> Root, const DataType *Data)
+ : Syntax(Root, Data) {}
+
+ /// Get the external name of the parameter, if there is one.
+ RC<TokenSyntax> getExternalName() const;
+
+ /// Return a FunctionParameterSyntax with the given external name.
+ FunctionParameterSyntax
+ withExternalName(RC<TokenSyntax> NewExternalName) const;
+
+ /// Return the local name of the parameter.
+ RC<TokenSyntax> getLocalName() const;
+
+ /// Return a FunctionParameterSyntax with the given local name.
+ FunctionParameterSyntax
+ withLocalName(RC<TokenSyntax> NewLocalName) const;
+
+ /// Return the colon ':' token between the local name and type of the
+ /// parameter.
+ RC<TokenSyntax> getColonToken() const;
+
+ /// Return a FunctionParameterSyntax with the given colon token between
+ /// the local name and type.
+ FunctionParameterSyntax
+ withColonToken(RC<TokenSyntax> NewColonToken) const;
+
+ /// Return the syntax for the type of this parameter.
+ llvm::Optional<TypeSyntax> getTypeSyntax() const;
+
+ /// Return a FunctionParameterSyntax with the given parameter type syntax.
+ FunctionParameterSyntax
+ withTypeSyntax(llvm::Optional<TypeSyntax> NewType) const;
+
+ /// Return the equal '=' token in between the parameter type and the default
+ /// value, if there is one.
+ RC<TokenSyntax> getEqualToken() const;
+
+ /// Return a FunctionParameterSyntax with the given equal '=' token in
+ /// between the parameter type and the default value.
+ FunctionParameterSyntax withEqualToken(RC<TokenSyntax> NewEqualToken) const;
+
+ /// Return the expresion for the default value of the parameter, if there
+ /// is one.
+ llvm::Optional<ExprSyntax> getDefaultValue() const;
+
+ /// Return a FunctionParameterSyntax with the given default value. To remove
+ /// the default value, pass llvm::None.
+ FunctionParameterSyntax
+ withDefaultValue(llvm::Optional<ExprSyntax> NewDefaultValue) const;
+
+ /// Return the trailing comma on the parameter, if there is one.
+ RC<TokenSyntax> getTrailingComma() const;
+
+ /// Return a FunctionParameterSyntax with the given trailing comma.
+ FunctionParameterSyntax
+ withTrailingComma(RC<TokenSyntax> NewTrailingComma) const;
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::FunctionParameter;
+ }
+};
+
+#pragma mark - function-parameter-list Data
+
+using FunctionParameterListSyntaxData =
+ SyntaxCollectionData<SyntaxKind::FunctionParameterList,
+ FunctionParameterSyntax>;
+
+#pragma mark - function-parameter-list API
+
+/// parameter-list -> parameteter | parameter ',' parameter-list
+class FunctionParameterListSyntax final : public
+ SyntaxCollection<SyntaxKind::FunctionParameterList, FunctionParameterSyntax> {
+ friend struct SyntaxFactory;
+ friend class Syntax;
+ friend class SyntaxData;
+ friend class FunctionSignatureSyntax;
+
+ using DataType = FunctionParameterListSyntaxData;
+
+ FunctionParameterListSyntax(const RC<SyntaxData> Root,
+ const DataType *Data)
+ : SyntaxCollection(Root, Data) {}
+
+public:
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::FunctionParameterList;
+ }
+};
+
+#pragma mark - function-signature Data
+
+class FunctionSignatureSyntaxData final : public SyntaxData {
+ friend struct SyntaxFactory;
+ friend class SyntaxData;
+ friend class FunctionSignatureSyntax;
+
+ RC<FunctionParameterListSyntaxData> CachedParameterList;
+ RC<TypeAttributesSyntaxData> CachedReturnTypeAttributes;
+ RC<TypeSyntaxData> CachedReturnTypeSyntax;
+
+ FunctionSignatureSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ const CursorIndex IndexInParent = 0);
+
+ static RC<FunctionSignatureSyntaxData>
+ make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+ static RC<FunctionSignatureSyntaxData> makeBlank();
+
+public:
+ static bool classof(const SyntaxData *SD) {
+ return SD->getKind() == SyntaxKind::FunctionSignature;
+ }
+};
+
+#pragma mark - function-signature API
+
+/// function-signature ->
+/// '(' parameter-list? ')' (throws | rethrows)? '->' attributes? type
+class FunctionSignatureSyntax final : public Syntax {
+ friend struct SyntaxBuilder;
+ friend class Syntax;
+ friend class SyntaxData;
+ friend class FunctionSignatureSyntaxData;
+
+ enum class Cursor : CursorIndex {
+ LeftParen,
+ ParameterList,
+ RightParen,
+ ThrowsOrRethrows,
+ Arrow,
+ ReturnTypeAttributes,
+ ReturnType,
+ };
+
+public:
+ using DataType = FunctionSignatureSyntaxData;
+
+ FunctionSignatureSyntax(const RC<SyntaxData> Root, const DataType *Data)
+ : Syntax(Root, Data) {}
+
+ /// Return the left parenthesis '(' token enclosing the parameter list.
+ RC<TokenSyntax> getLeftParenToken() const;
+
+ /// Return a FunctionSignatureSyntax with the given left parentesis '(' token
+ /// enclosing the parameter list.
+ FunctionSignatureSyntax
+ withLeftParenToken(RC<TokenSyntax> NewLeftParen) const;
+
+ /// Return the parameter list for this signature.
+ FunctionParameterListSyntax getParameterList() const;
+
+ /// Return the parameter list for this signature.
+ FunctionSignatureSyntax
+ withParameterList(FunctionParameterListSyntax NewParameterList) const;
+
+ /// Return the right parenthesis ')' token enclosing the parameter list.
+ RC<TokenSyntax> getRightParenToken() const;
+
+ /// Return a FunctionSignatureSyntax with the given right parentesis ')' token
+ /// enclosing the parameter list.
+ FunctionSignatureSyntax
+ withRightParenToken(RC<TokenSyntax> NewRightParen) const;
+
+ /// Return the 'throws' token in this signature if it exists.
+ RC<TokenSyntax> getThrowsToken() const;
+
+ /// Return a FunctionSignatureSyntax with the given 'throws' token.
+ FunctionSignatureSyntax withThrowsToken(RC<TokenSyntax> NewThrowsToken) const;
+
+ /// Return the 'rethrows' token in this signature if it exists;
+ RC<TokenSyntax> getRethrowsToken() const;
+
+ /// Return a FunctionSignatureSyntax with the given 'rethrows' token.
+ FunctionSignatureSyntax
+ withRethrowsToken(RC<TokenSyntax> NewRethrowsToken) const;
+
+ /// Return the arrow '->' token for the signature.
+ RC<TokenSyntax> getArrowToken() const;
+
+ /// Return a FunctionSignatureSyntax with the given arrow token
+ FunctionSignatureSyntax withArrowToken(RC<TokenSyntax> NewArrowToken) const;
+
+ /// Return the return type attributes for the signature.
+ TypeAttributesSyntax getReturnTypeAttributes() const;
+
+ /// Return a FunctionSignatureSyntax with the given return type attributes.
+ FunctionSignatureSyntax
+ withReturnTypeAttributes(TypeAttributesSyntax NewReturnTypeAttributes) const;
+
+ /// Return the syntax for the return type of the signature.
+ TypeSyntax getReturnTypeSyntax() const;
+
+ /// Return a FunctionSignatureSyntax with the given return type.
+ FunctionSignatureSyntax withReturnTypeSyntax(TypeSyntax NewReturnType) const;
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::FunctionSignature;
+ }
+};
+
+#pragma mark - function-declaration Data
+
+class FunctionDeclSyntaxData final : public SyntaxData {
+ friend struct SyntaxFactory;
+ friend class SyntaxData;
+ friend class FunctionDeclSyntax;
+
+ RC<TypeAttributesSyntaxData> CachedAttributes;
+ RC<DeclModifierListSyntaxData> CachedModifiers;
+ RC<GenericParameterClauseSyntaxData> CachedGenericParams;
+ RC<FunctionSignatureSyntaxData> CachedSignature;
+ RC<GenericWhereClauseSyntaxData> CachedGenericWhereClause;
+ RC<CodeBlockStmtSyntaxData> CachedBody;
+
+ FunctionDeclSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ const CursorIndex IndexInParent = 0);
+
+ static RC<FunctionDeclSyntaxData> make(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ const CursorIndex IndexInParent = 0);
+ static RC<FunctionDeclSyntaxData> makeBlank();
+
+public:
+ static bool classof(const SyntaxData *SD) {
+ return SD->getKind() == SyntaxKind::FunctionDecl;
+ }
+};
+
+#pragma mark - function-declaration API
+
+class FunctionDeclSyntax final : public Syntax {
+ friend struct SyntaxFactory;
+ friend class Syntax;
+ friend class SyntaxData;
+ friend class FunctionDeclSyntaxData;
+
+ enum class Cursor : CursorIndex {
+ Attributes,
+ Modifiers,
+ FuncKeyword,
+ Identifier,
+ GenericParameterClause,
+ Signature,
+ GenericWhereClause,
+ Body
+ };
+
+ using DataType = FunctionDeclSyntaxData;
+
+ FunctionDeclSyntax(const RC<SyntaxData> Root, const DataType *Data)
+ : Syntax(Root, Data) {}
+
+public:
+ /// Get the attributes of this function declaration.
+ TypeAttributesSyntax getAttributes() const;
+
+ /// Return a FunctionDeclSyntax with the given attributes.
+ FunctionDeclSyntax withAttributes(TypeAttributesSyntax NewAttributes) const;
+
+ /// Get the modifiers of this function declaration.
+ DeclModifierListSyntax getModifiers() const;
+
+ /// Return a FunctionDeclSyntax with the given modifiers.
+ FunctionDeclSyntax withModifiers(DeclModifierListSyntax NewModifiers) const;
+
+ /// Return the 'func' keyword of tis function declaration.
+ RC<TokenSyntax> getFuncKeyword() const;
+
+ /// Return a FunctionDeclSyntax with the given 'func' keyword.
+ FunctionDeclSyntax withFuncKeyword(RC<TokenSyntax> NewFuncKeyword) const;
+
+ /// Return the identifier of the function declaration.
+ RC<TokenSyntax> getIdentifier() const;
+
+ /// Return a FunctionDeclSyntax with the given identifier.
+ FunctionDeclSyntax withIdentifier(RC<TokenSyntax> NewIdentifier) const;
+
+ /// Return the generic parameter clause of the function declaration, if
+ /// there is one. Otherwise, return llvm::None.
+ llvm::Optional<GenericParameterClauseSyntax>
+ getGenericParameterClause() const;
+
+ /// Return a FunctionDeclSyntax with the given generic parameter clause.
+ /// To remove the generic parameters, pass in llvm::None.
+ FunctionDeclSyntax withGenericParameterClause(
+ llvm::Optional<GenericParameterClauseSyntax> NewGenericParams) const;
+
+ /// Return the signature of the function declaration.
+ FunctionSignatureSyntax getSignature() const;
+
+ /// Return a FunctionDeclSyntax with the given function signature.
+ FunctionDeclSyntax withSignature(FunctionSignatureSyntax NewSignature) const;
+
+ /// Return the body of the function declaration, if there is one.
+ ///
+ /// As an example, function declarations in protocols have no body.
+ llvm::Optional<CodeBlockStmtSyntax> getBody() const;
+
+ /// Return a FunctionDeclSyntax with the given body. To remove the body,
+ /// pass in llvm::None.
+ FunctionDeclSyntax
+ withBody(llvm::Optional<CodeBlockStmtSyntax> NewBody) const;
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::FunctionDecl;
+ }
+};
+
} // end namespace syntax
} // end namespace swift
diff --git a/include/swift/Syntax/ExprSyntax.h b/include/swift/Syntax/ExprSyntax.h
index 5dbebda..1dfbf14 100644
--- a/include/swift/Syntax/ExprSyntax.h
+++ b/include/swift/Syntax/ExprSyntax.h
@@ -22,6 +22,8 @@
#include "swift/Syntax/References.h"
#include "swift/Syntax/Syntax.h"
#include "swift/Syntax/SyntaxData.h"
+#include "swift/Syntax/SyntaxCollection.h"
+#include "swift/Syntax/SyntaxCollectionData.h"
#include "swift/Syntax/TokenSyntax.h"
#include "swift/Syntax/UnknownSyntax.h"
@@ -51,6 +53,7 @@
};
class ExprSyntax : public Syntax {
+ friend class FunctionParameterSyntax;
public:
using DataType = ExprSyntaxData;
@@ -248,7 +251,6 @@
/// function-call-argument -> label? ':'? (expression | operator) ','?
class FunctionCallArgumentSyntax : public Syntax {
-
using DataType = FunctionCallArgumentSyntaxData;
friend struct SyntaxFactory;
@@ -256,6 +258,10 @@
friend class Syntax;
friend class FunctionCallArgumentSyntaxData;
friend class FunctionCallArgumentListSyntax;
+ friend class SyntaxCollectionData<SyntaxKind::FunctionCallArgumentList,
+ FunctionCallArgumentSyntax>;
+ friend class SyntaxCollection<SyntaxKind::FunctionCallArgumentList,
+ FunctionCallArgumentSyntax>;
enum class Cursor {
Label,
@@ -305,37 +311,18 @@
#pragma mark - function-call-argument-list Data
-class FunctionCallArgumentListSyntaxData : public SyntaxData {
- friend struct SyntaxFactory;
- friend class FunctionCallArgumentListSyntax;
- friend class FunctionCallExprSyntaxBuilder;
- friend class SyntaxData;
-
- std::vector<RC<FunctionCallArgumentSyntaxData>> CachedArguments;
-
- FunctionCallArgumentListSyntaxData(const RC<RawSyntax> Raw,
- const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
-
- static RC<FunctionCallArgumentListSyntaxData>
- make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
-
- static RC<FunctionCallArgumentListSyntaxData> makeBlank();
-
-public:
- static bool classof(const SyntaxData *S) {
- return S->getKind() == SyntaxKind::FunctionCallArgumentList;
- }
-};
+using FunctionCallArgumentListSyntaxData =
+ SyntaxCollectionData<SyntaxKind::FunctionCallArgumentList,
+ FunctionCallArgumentSyntax>;
#pragma mark - function-call-argument-list API
/// function-call-argument-list -> function-call-argument
/// function-call-argument-list?
-class FunctionCallArgumentListSyntax : public Syntax {
+class FunctionCallArgumentListSyntax
+ : public SyntaxCollection<SyntaxKind::FunctionCallArgumentList,
+ FunctionCallArgumentSyntax> {
friend struct SyntaxFactory;
- friend class FunctionCallArgumentListSyntaxData;
friend class FunctionCallExprSyntax;
friend class Syntax;
friend class SyntaxData;
@@ -346,17 +333,6 @@
const DataType *Data);
public:
- /// Return the number of arguments in this list.
- size_t getNumArguments() const;
-
- /// Get the argument at the given Index.
- FunctionCallArgumentSyntax getArgument(size_t n) const;
-
- /// Returns a new `FunctionCallArgumentListSyntax` with the given
- /// argument added to the end.
- FunctionCallArgumentListSyntax
- withAdditionalArgument(FunctionCallArgumentSyntax AdditionalArgument) const;
-
static bool classof(const Syntax *S) {
return S->getKind() == SyntaxKind::FunctionCallArgumentList;
}
diff --git a/include/swift/Syntax/GenericSyntax.h b/include/swift/Syntax/GenericSyntax.h
index 753018e..d8510db 100644
--- a/include/swift/Syntax/GenericSyntax.h
+++ b/include/swift/Syntax/GenericSyntax.h
@@ -19,6 +19,7 @@
#define SWIFT_SYNTAX_GENERICSYNTAX_H
#include "swift/Syntax/References.h"
+#include "swift/Syntax/SyntaxCollection.h"
#include "swift/Syntax/SyntaxData.h"
#include "swift/Syntax/TokenSyntax.h"
@@ -30,10 +31,50 @@
class TypeIdentifierSyntax;
class TypeIdentifierSyntaxData;
+#pragma mark - generic-requirement Data
+
+class GenericRequirementSyntaxData : public SyntaxData {
+ friend class GenericRequirementSyntax;
+ friend class SyntaxData;
+
+protected:
+ GenericRequirementSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ const CursorIndex IndexInParent = 0)
+ : SyntaxData(Raw, Parent, IndexInParent) {}
+
+public:
+ static bool classof(const SyntaxData *SD) {
+ return SD->getKind() == SyntaxKind::ConformanceRequirement ||
+ SD->getKind() == SyntaxKind::SameTypeRequirement;
+ }
+};
+
+#pragma mark - generic-requirement API
+
+class GenericRequirementSyntax : public Syntax {
+ friend class Syntax;
+ friend class SyntaxData;
+ friend class GenericRequirementSyntaxData;
+
+public:
+ using DataType = GenericRequirementSyntaxData;
+
+ GenericRequirementSyntax(const RC<SyntaxData> Root, const DataType *Data)
+ : Syntax(Root, Data) {}
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::ConformanceRequirement ||
+ S->getKind() == SyntaxKind::SameTypeRequirement;
+ }
+};
+
#pragma mark - conformance-requirement Data
-class ConformanceRequirementSyntaxData final : public SyntaxData {
+class ConformanceRequirementSyntaxData final
+ : public GenericRequirementSyntaxData {
friend class SyntaxData;
+
RC<TypeIdentifierSyntaxData> CachedConformingTypeIdentifier;
RC<TypeSyntaxData> InheritedType;
@@ -44,18 +85,24 @@
make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
CursorIndex IndexInParent = 0);
static RC<ConformanceRequirementSyntaxData> makeBlank();
+
public:
static bool classof(const SyntaxData *S) {
return S->getKind() == SyntaxKind::ConformanceRequirement;
}
+ static bool classof(const GenericRequirementSyntaxData *SD) {
+ return SD->getKind() == SyntaxKind::ConformanceRequirement;
+ }
};
#pragma mark - conformance-requirement API
/// conformance-requirement -> type-identifier : type-identifier
-class ConformanceRequirementSyntax final : public Syntax {
+class ConformanceRequirementSyntax final : public GenericRequirementSyntax {
friend class ConformanceRequirementSyntaxData;
+ friend class SyntaxData;
+ friend class Syntax;
enum Cursor : CursorIndex {
LeftTypeIdentifier,
@@ -73,6 +120,8 @@
static ConformanceRequirementSyntax makeBlank();
public:
+ using DataType = ConformanceRequirementSyntaxData;
+
/// Return the conforming "left-hand" type identifier in the
/// conformance requirement.
TypeIdentifierSyntax getConformingTypeIdentifier() const;
@@ -99,13 +148,18 @@
static bool classof(const Syntax *S) {
return S->getKind() == SyntaxKind::ConformanceRequirement;
}
+ static bool classof(const GenericRequirementSyntax *S) {
+ return S->getKind() == SyntaxKind::ConformanceRequirement;
+ }
};
#pragma mark - same-type-requirement Data
-class SameTypeRequirementSyntaxData final : public SyntaxData {
+class SameTypeRequirementSyntaxData final
+ : public GenericRequirementSyntaxData {
friend struct SyntaxFactory;
friend class SyntaxData;
+
RC<TypeIdentifierSyntaxData> CachedLeftTypeIdentifier;
RC<TypeSyntaxData> CachedRightType;
@@ -129,8 +183,9 @@
/// same-type-requirement -> type-identifier == type
class SameTypeRequirementSyntax final : public Syntax {
friend struct SyntaxFactory;
+ friend class Syntax;
+ friend class SyntaxData;
friend class SameTypeRequirementSyntaxData;
-
enum Cursor : CursorIndex {
LeftTypeIdentifier,
EqualityToken,
@@ -141,6 +196,7 @@
const SameTypeRequirementSyntaxData *Data);
public:
+ using DataType = SameTypeRequirementSyntaxData;
/// Return the type identifier on the left side of the same-type requirement.
TypeIdentifierSyntax getLeftTypeIdentifier() const;
@@ -277,9 +333,9 @@
RC<GenericParameterListSyntaxData> CachedGenericParameterList;
- GenericParameterClauseSyntaxData(RC<RawSyntax> Raw,
+ GenericParameterClauseSyntaxData(const RC<RawSyntax> Raw,
const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
+ const CursorIndex IndexInParent = 0);
static RC<GenericParameterClauseSyntaxData>
make(RC<RawSyntax> Raw,
const SyntaxData *Parent = nullptr,
@@ -299,6 +355,8 @@
friend struct SyntaxFactory;
friend class GenericParameterClauseSyntaxData;
friend class GenericParameterClauseBuilder;
+ friend class FunctionDeclSyntax;
+
enum class Cursor : CursorIndex {
LeftAngleBracketToken,
GenericParameterList,
@@ -478,6 +536,35 @@
}
};
+#pragma mark - generic-requirement-list Data
+
+using GenericRequirementListSyntaxData =
+ SyntaxCollectionData<SyntaxKind::GenericRequirementList,
+ GenericRequirementSyntax>;
+
+#pragma mark - generic-requirement-list API
+
+/// requirement-list -> requirement | requirement ',' requirement-list
+///
+/// requirement -> conformance-requirement | same-type-requirement
+class GenericRequirementListSyntax final
+ : public SyntaxCollection<SyntaxKind::GenericRequirementList,
+ GenericRequirementSyntax> {
+ friend struct SyntaxFactory;
+ friend class Syntax;
+ friend class SyntaxData;
+
+ using DataType = GenericRequirementListSyntaxData;
+
+ GenericRequirementListSyntax(const RC<SyntaxData> Root,
+ const DataType *Data)
+ : SyntaxCollection(Root, Data) {}
+public:
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::GenericRequirementList;
+ }
+};
+
#pragma mark - generic-argument-clause Builder
class GenericArgumentClauseBuilder {
@@ -500,47 +587,6 @@
GenericArgumentClauseSyntax build() const;
};
-#pragma mark - generic-requirement-list Data
-
-class GenericRequirementListSyntaxData final : public SyntaxData {
- friend class SyntaxData;
- GenericRequirementListSyntaxData(RC<RawSyntax> Raw,
- const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
- static RC<GenericRequirementListSyntaxData>
- make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
- static RC<GenericRequirementListSyntaxData> makeBlank();
-public:
- static bool classof(const SyntaxData *S) {
- return S->getKind() == SyntaxKind::GenericRequirementList;
- }
-};
-
-#pragma mark - generic-requirement-list API
-
-/// requirement-list -> requirement | requirement ',' requirement-list
-///
-/// requirement -> conformance-requirement | same-type-requirement
-class GenericRequirementListSyntax final : public Syntax {
- friend struct SyntaxFactory;
-
- GenericRequirementListSyntax(RC<SyntaxData> Root,
- GenericRequirementListSyntaxData *Data);
-
- static GenericRequirementListSyntax make(RC<RawSyntax> Raw);
- static GenericRequirementListSyntax makeBlank();
-
-public:
- // TODO: getRequirement(unsigned n) const;
- // TODO: withAddedRequirement(llvm::Optional<RC<TokenSyntax>> MaybeComma,
- // GenericRequirementSyntax NewRequirement) const;
-
- static bool classof(const Syntax *S) {
- return S->getKind() == SyntaxKind::GenericRequirementList;
- }
-};
-
#pragma mark - generic-where-clause Data
class GenericWhereClauseSyntaxData final : public SyntaxData {
@@ -549,12 +595,12 @@
RC<GenericRequirementListSyntaxData> CachedRequirementList;
- GenericWhereClauseSyntaxData(RC<RawSyntax> Raw,
+ GenericWhereClauseSyntaxData(const RC<RawSyntax> Raw,
const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
- static RC<GenericWhereClauseSyntaxData> make(RC<RawSyntax> Raw,
- const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
+ const CursorIndex IndexInParent = 0);
+ static RC<GenericWhereClauseSyntaxData>
+ make(const RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
+ const CursorIndex IndexInParent = 0);
static RC<GenericWhereClauseSyntaxData> makeBlank();
public:
@@ -568,12 +614,16 @@
/// generic-where-clause -> 'where' requirement-list
class GenericWhereClauseSyntax final : public Syntax {
friend struct SyntaxFactory;
+ friend class Syntax;
+ friend class SyntaxData;
friend class GenericWhereClauseSyntaxData;
enum class Cursor : CursorIndex {
- WhereToken,
+ WhereKeyword,
RequirementList,
};
+ using DataType = GenericWhereClauseSyntaxData;
+
GenericWhereClauseSyntax(RC<SyntaxData> Root,
const GenericWhereClauseSyntaxData *Data);
diff --git a/include/swift/Syntax/Rewriter.h b/include/swift/Syntax/Rewriter.h
index 224373d..ae7c208 100644
--- a/include/swift/Syntax/Rewriter.h
+++ b/include/swift/Syntax/Rewriter.h
@@ -24,6 +24,7 @@
#include "swift/Syntax/References.h"
#include "swift/Syntax/DeclSyntax.h"
+#include "swift/Syntax/GenericSyntax.h"
#include "swift/Syntax/ExprSyntax.h"
#include "swift/Syntax/StmtSyntax.h"
#include "swift/Syntax/Syntax.h"
diff --git a/include/swift/Syntax/StmtSyntax.h b/include/swift/Syntax/StmtSyntax.h
index d4c93a5..f0bba83 100644
--- a/include/swift/Syntax/StmtSyntax.h
+++ b/include/swift/Syntax/StmtSyntax.h
@@ -57,9 +57,11 @@
/// | do-statement ';'?
/// | compiler-control-statement ';'?
class StmtSyntax : public Syntax {
+ friend class Syntax;
protected:
StmtSyntax(const RC<SyntaxData> Root, const StmtSyntaxData *Data);
public:
+ using DataType = StmtSyntaxData;
static bool classof(const Syntax *S) {
return S->isStmt();
}
@@ -130,6 +132,7 @@
};
friend struct SyntaxFactory;
friend class CodeBlockStmtSyntaxData;
+ friend class FunctionDeclSyntax;
CodeBlockStmtSyntax(const RC<SyntaxData> Root, CodeBlockStmtSyntaxData *Data);
@@ -166,58 +169,33 @@
#pragma mark -
#pragma mark statements Data
-class StmtListSyntaxData final : public StmtSyntaxData {
- friend class SyntaxData;
- friend class StmtListSyntax;
- friend class StmtListSyntaxBuilder;
-
- StmtListSyntaxData(RC<RawSyntax> Raw,
- const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
- static RC<StmtListSyntaxData> make(RC<RawSyntax> Raw,
- const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
- static RC<StmtListSyntaxData> makeBlank();
-
-public:
- static bool classof(const SyntaxData *SD) {
- return SD->getKind() == SyntaxKind::StmtList;
- }
-};
+using StmtListSyntaxData =
+ SyntaxCollectionData<SyntaxKind::StmtList, StmtSyntax>;
#pragma mark -
#pragma mark statements API
/// statements -> statement
/// | statement statements
-class StmtListSyntax final : public Syntax {
+class StmtListSyntax final
+ : public SyntaxCollection<SyntaxKind::StmtList, StmtSyntax> {
friend struct SyntaxFactory;
- friend class StmtListSyntaxBuilder;
+ friend class Syntax;
friend class SyntaxData;
+ friend class FunctionDeclSyntax;
using DataType = StmtListSyntaxData;
- StmtListSyntax(const RC<SyntaxData> Root, const StmtListSyntaxData *Data);
-public:
- /// Returns a new statement list with an additional statement.
- StmtListSyntax withAddedStatement(Syntax AdditionalStatement) const;
+ StmtListSyntax(const RC<SyntaxData> Root, const DataType *Data)
+ : SyntaxCollection(Root, Data) {}
+public:
static bool classof(const Syntax *S) {
return S->getKind() == SyntaxKind::StmtList;
}
};
#pragma mark -
-#pragma mark statements Builder
-
-class StmtListSyntaxBuilder final {
- RawSyntax::LayoutList StmtListLayout;
-public:
- StmtListSyntaxBuilder &addStatement(Syntax Statement);
- StmtListSyntax build() const;
-};
-
-#pragma mark -
#pragma mark fallthrough-statement Data
class FallthroughStmtSyntaxData final : public StmtSyntaxData {
diff --git a/include/swift/Syntax/Syntax.h b/include/swift/Syntax/Syntax.h
index 7be6fd9..d1cc24d 100644
--- a/include/swift/Syntax/Syntax.h
+++ b/include/swift/Syntax/Syntax.h
@@ -52,7 +52,6 @@
friend class SyntaxData;
friend class LegacyASTTransformer;
friend class sema::Semantics;
- using DataType = SyntaxData;
#define SYNTAX(Id, Parent) friend class Id##Syntax;
#include "swift/Syntax/SyntaxKinds.def"
@@ -75,6 +74,8 @@
}
public:
+ using DataType = SyntaxData;
+
Syntax(const RC<SyntaxData> Root, const SyntaxData *Data);
/// Get the kind of syntax.
@@ -150,7 +151,7 @@
/// Print a debug representation of the syntax node to standard error.
void dump() const;
- bool hasSameIdentityAs(const Syntax &Other) {
+ bool hasSameIdentityAs(const Syntax &Other) const {
return Root == Other.Root && Data == Other.Data;
}
diff --git a/include/swift/Syntax/SyntaxCollection.h b/include/swift/Syntax/SyntaxCollection.h
new file mode 100644
index 0000000..37b87c8
--- /dev/null
+++ b/include/swift/Syntax/SyntaxCollection.h
@@ -0,0 +1,183 @@
+#ifndef SWIFT_SYNTAX_SYNTAXCOLLECTION_H
+#define SWIFT_SYNTAX_SYNTAXCOLLECTION_H
+
+#include "swift/Syntax/Syntax.h"
+#include "swift/Syntax/SyntaxCollectionData.h"
+
+namespace swift {
+namespace syntax {
+
+template <SyntaxKind CollectionKind, typename Element>
+struct SyntaxCollectionIterator {
+ const SyntaxCollection<CollectionKind, Element> &Collection;
+ size_t Index;
+
+ Element operator*() {
+ return Collection[Index];
+ }
+
+ SyntaxCollectionIterator<CollectionKind, Element> &operator++() {
+ ++Index;
+ return *this;
+ }
+
+ bool
+ operator==(const SyntaxCollectionIterator<CollectionKind, Element> &Other) {
+ return Collection.hasSameIdentityAs(Other.Collection) &&
+ Index == Other.Index;
+ }
+
+ bool
+ operator!=(const SyntaxCollectionIterator<CollectionKind, Element> &Other) {
+ return !operator==(Other);
+
+ }
+};
+
+/// A generic unbounded collection of syntax nodes
+template <SyntaxKind CollectionKind, typename Element>
+class SyntaxCollection : public Syntax {
+ friend struct SyntaxFactory;
+ friend class SyntaxData;
+ friend class Syntax;
+ using DataType = SyntaxCollectionData<CollectionKind, Element>;
+
+protected:
+ SyntaxCollection(const RC<SyntaxData> Root, const DataType *Data)
+ : Syntax(Root, Data) {}
+
+public:
+
+ /// Returns true if the collection is empty.
+ bool empty() const {
+ return size() == 0;
+ }
+
+ /// Returns the number of elements in the collection.
+ size_t size() const {
+ return getRaw()->Layout.size();
+ }
+
+ SyntaxCollectionIterator<CollectionKind, Element> begin() const {
+ return SyntaxCollectionIterator<CollectionKind, Element> {
+ *this,
+ 0,
+ };
+ }
+
+ SyntaxCollectionIterator<CollectionKind, Element> end() const {
+ return SyntaxCollectionIterator<CollectionKind, Element> {
+ *this,
+ getRaw()->Layout.size(),
+ };
+ }
+
+ /// Return the element at the given Index.
+ ///
+ /// Precondition: Index < size()
+ /// Precondition: !empty()
+ Element operator[](const size_t Index) const {
+ assert(Index < size());
+ assert(!empty());
+
+ auto RawElement = getRaw()->Layout[Index];
+ auto *MyData = getUnsafeData<SyntaxCollection<CollectionKind, Element>>();
+
+ if (auto Data = MyData->CachedElements[Index].get()) {
+ return Element { Root, Data };
+ }
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ MyData->CachedElements.data() + Index);
+
+ SyntaxData::realizeSyntaxNode<Element>(ChildPtr, RawElement, MyData, Index);
+
+ return Element {
+ Root,
+ MyData->CachedElements[Index].get()
+ };
+ }
+
+ /// Return a new collection with the given element added to the end.
+ SyntaxCollection<CollectionKind, Element>
+ appending(Element E) const {
+ auto NewLayout = getRaw()->Layout;
+ NewLayout.push_back(E.getRaw());
+ auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence);
+ return Data->replaceSelf<SyntaxCollection<CollectionKind, Element>>(Raw);
+ }
+
+ /// Return a new collection with an element removed from the end.
+ ///
+ /// Precondition: !empty()
+ SyntaxCollection<CollectionKind, Element> removingLast() const {
+ assert(!empty());
+ auto NewLayout = getRaw()->Layout;
+ NewLayout.pop_back();
+ auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence);
+ return Data->replaceSelf<SyntaxCollection<CollectionKind, Element>>(Raw);
+ }
+
+ /// Return a new collection with the given element appended to the front.
+ SyntaxCollection<CollectionKind, Element>
+ prepending(Element E) const {
+ RawSyntax::LayoutList NewLayout = { E.getRaw() };
+ std::copy(getRaw()->Layout.begin(),
+ getRaw()->Layout.end(),
+ std::back_inserter(NewLayout));
+ auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence);
+ return Data->replaceSelf<SyntaxCollection<CollectionKind, Element>>(Raw);
+ }
+
+ /// Return a new collection with an element removed from the end.
+ ///
+ /// Precondition: !empty()
+ SyntaxCollection<CollectionKind, Element> removingFirst() const {
+ assert(!empty());
+ RawSyntax::LayoutList NewLayout;
+ std::copy(getRaw()->Layout.begin() + 1,
+ getRaw()->Layout.end(),
+ std::back_inserter(NewLayout));
+ auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence);
+ return Data->replaceSelf<SyntaxCollection<CollectionKind, Element>>(Raw);
+ }
+
+ /// Return a new collection with the Element inserted at index i.
+ ///
+ /// Precondition: i <= size()
+ SyntaxCollection<CollectionKind, Element>
+ inserting(size_t i, Element E) const {
+ assert(i <= size());
+ RawSyntax::LayoutList NewLayout;
+ std::copy(getRaw()->Layout.begin(), getRaw()->Layout.begin() + i,
+ std::back_inserter(NewLayout));
+ NewLayout.push_back(E.getRaw());
+ std::copy(getRaw()->Layout.begin() + i, getRaw()->Layout.end(),
+ std::back_inserter(NewLayout));
+ auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence);
+ return Data->replaceSelf<SyntaxCollection<CollectionKind, Element>>(Raw);
+ }
+
+ /// Return a new collection with the element removed at index i.
+ SyntaxCollection<CollectionKind, Element> removing(size_t i) const {
+ auto NewLayout = getRaw()->Layout;
+ NewLayout.erase(NewLayout.begin() + i);
+ auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence);
+ return Data->replaceSelf<SyntaxCollection<CollectionKind, Element>>(Raw);
+ }
+
+ /// Return an empty syntax collection of this type.
+ SyntaxCollection<CollectionKind, Element> cleared() const {
+ auto Raw = RawSyntax::make(CollectionKind, {}, getRaw()->Presence);
+ return Data->replaceSelf<SyntaxCollection<CollectionKind, Element>>(Raw);
+ }
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == CollectionKind;
+ }
+};
+
+} // end namespace syntax
+} // end namespace swift
+
+#endif // SWIFT_SYNTAX_SYNTAXCOLLECTION_H
diff --git a/include/swift/Syntax/SyntaxCollectionData.h b/include/swift/Syntax/SyntaxCollectionData.h
new file mode 100644
index 0000000..1970f3b
--- /dev/null
+++ b/include/swift/Syntax/SyntaxCollectionData.h
@@ -0,0 +1,53 @@
+#ifndef SWIFT_SYNTAX_SYNTAXCOLLECTIONDATA_H
+#define SWIFT_SYNTAX_SYNTAXCOLLECTIONDATA_H
+
+#include "swift/Syntax/SyntaxData.h"
+
+namespace swift {
+namespace syntax {
+
+template <SyntaxKind CollectionKind, typename ElementType>
+class SyntaxCollection;
+
+template <SyntaxKind CollectionKind, typename ElementType>
+class SyntaxCollectionData : public SyntaxData {
+ friend class SyntaxCollection<CollectionKind, ElementType>;
+ std::vector<RC<typename ElementType::DataType>> CachedElements;
+
+ friend struct SyntaxFactory;
+ friend class SyntaxData;
+ friend class FunctionCallExprSyntaxBuilder;
+
+ SyntaxCollectionData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0)
+ : SyntaxData(Raw, Parent, IndexInParent),
+ CachedElements(Raw->Layout.size(), nullptr) {
+ assert(Raw->Kind == CollectionKind);
+ }
+
+ static RC<SyntaxCollectionData<CollectionKind, ElementType>>
+ make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0) {
+
+ return RC<SyntaxCollectionData<CollectionKind, ElementType>> {
+ new SyntaxCollectionData<CollectionKind, ElementType> {
+ Raw, Parent, IndexInParent
+ }
+ };
+ }
+
+ static RC<SyntaxCollectionData<CollectionKind, ElementType>> makeBlank() {
+ auto Raw = RawSyntax::make(CollectionKind, {}, SourcePresence::Present);
+ return make(Raw);
+ }
+
+public:
+ static bool classof(const SyntaxData *SD) {
+ return SD->getKind() == CollectionKind;
+ }
+};
+
+} // end namespace syntax
+} // end namespace swift
+
+#endif
diff --git a/include/swift/Syntax/SyntaxData.h b/include/swift/Syntax/SyntaxData.h
index f27e59e..8fcd79b 100644
--- a/include/swift/Syntax/SyntaxData.h
+++ b/include/swift/Syntax/SyntaxData.h
@@ -77,7 +77,7 @@
///
/// If there is no parent, this is 0.
const CursorIndex IndexInParent;
-protected:
+
SyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
CursorIndex IndexInParent = 0)
: Raw(Raw), Parent(Parent), IndexInParent(IndexInParent) {}
diff --git a/include/swift/Syntax/SyntaxFactory.h b/include/swift/Syntax/SyntaxFactory.h
index d1d74c8..c99c8d3 100644
--- a/include/swift/Syntax/SyntaxFactory.h
+++ b/include/swift/Syntax/SyntaxFactory.h
@@ -51,6 +51,26 @@
makeUnknownSyntax(llvm::ArrayRef<RC<TokenSyntax>> Tokens);
#pragma mark - Declarations
+
+#pragma mark - declaration-modifier
+
+ /// Make a declaration modifier with the specified elements.
+ static DeclModifierSyntax
+ makeDeclModifier(RC<TokenSyntax> Name, RC<TokenSyntax> LeftParen,
+ RC<TokenSyntax> Argument, RC<TokenSyntax> RightParen);
+
+ /// Make a declaration modifier with all missing elements.
+ static DeclModifierSyntax makeBlankDeclModifier();
+
+ /// Make a declaration modifier list with the specified modifiers.
+ static DeclModifierListSyntax
+ makeDeclModifierList(const std::vector<DeclModifierSyntax> &Modifiers);
+
+ /// Make an empty declaration modifier list.
+ static DeclModifierListSyntax makeBlankDeclModifierList();
+
+#pragma mark - struct-declaration
+
/// Make a struct declaration with the specified elements.
static StructDeclSyntax
makeStructDecl(RC<TokenSyntax> StructToken, RC<TokenSyntax> Identifier,
@@ -73,6 +93,65 @@
/// Make an empty list of declaration members.
static DeclMembersSyntax makeBlankDeclMembers();
+ /// Make a function declaration with the specified elements.
+ static FunctionDeclSyntax
+ makeFunctionDecl(TypeAttributesSyntax Attributes,
+ DeclModifierListSyntax Modifiers,
+ RC<TokenSyntax> FuncKeyword,
+ RC<TokenSyntax> Identifier,
+ llvm::Optional<GenericParameterClauseSyntax> GenericParams,
+ FunctionSignatureSyntax Signature,
+ llvm::Optional<GenericWhereClauseSyntax> GenericWhereClause,
+ llvm::Optional<CodeBlockStmtSyntax> Body);
+
+ /// Make a function declaration with all missing elements.
+ static FunctionDeclSyntax makeBlankFunctionDecl();
+
+#pragma mark - function-parameter
+
+ /// Make a function parameter with the given elements.
+ static FunctionParameterSyntax
+ makeFunctionParameter(RC<TokenSyntax> ExternalName, RC<TokenSyntax> LocalName,
+ RC<TokenSyntax> Colon,
+ llvm::Optional<TypeSyntax> ParameterTypeSyntax,
+ RC<TokenSyntax> Ellipsis,
+ RC<TokenSyntax> Equal,
+ llvm::Optional<ExprSyntax> DefaultValue,
+ RC<TokenSyntax> TrailingComma);
+
+ /// Make a function parameter with all elements marked as missing.
+ static FunctionParameterSyntax makeBlankFunctionParameter();
+
+#pragma mark - function-parameter-list
+
+ /// Make a function parameter list with the given parameters.
+ static FunctionParameterListSyntax makeFunctionParameterList(
+ const std::vector<FunctionParameterSyntax> &Parameters);
+
+ /// Make an empty function parameter list.
+ static FunctionParameterListSyntax makeBlankFunctionParameterList();
+
+#pragma mark - function-signature
+
+ /// Make a function signature with the given elements.
+ static FunctionSignatureSyntax
+ makeFunctionSignature(RC<TokenSyntax> LeftParen,
+ FunctionParameterListSyntax ParameterList,
+ RC<TokenSyntax> RightParen,
+ RC<TokenSyntax> ThrowsOrRethrows,
+ RC<TokenSyntax> Arrow,
+ TypeAttributesSyntax ReturnTypeAttributes,
+ TypeSyntax ReturnTypeSyntax);
+
+ /// Make a blank function signature.
+ static FunctionSignatureSyntax makeBlankFunctionSignature();
+
+ //-/ Make a function declaration with the given elements.
+ // TODO
+
+ //-/ Make a blank function declaration.
+ // TODO
+
#pragma mark - Statements
/// Make a code block with the specified elements.
@@ -119,6 +198,12 @@
/// marked as missing.
static ReturnStmtSyntax makeBlankReturnStmt();
+ /// Make a statement list from a loosely connected list of statements.
+ static StmtListSyntax makeStmtList(const std::vector<StmtSyntax> &Statements);
+
+ /// Make an empty statement list.
+ static StmtListSyntax makeBlankStmtList();
+
#pragma mark - Expressions
/// Make an integer literal with the given '+'/'-' sign and string of digits.
@@ -168,6 +253,19 @@
#pragma mark - Tokens
+ /// Make a 'static' keyword with the specified leading and trailing trivia.
+ static RC<TokenSyntax> makeStaticKeyword(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia);
+
+
+ /// Make a 'public' keyword with the specified leading and trailing trivia.
+ static RC<TokenSyntax> makePublicKeyword(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia);
+
+ /// Make a 'func' keyword with the specified leading and trailing trivia.
+ static RC<TokenSyntax> makeFuncKeyword(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia);
+
/// Make a 'fallthrough' keyword with the specified leading and
/// trailing trivia.
static RC<TokenSyntax> makeFallthroughKeyword(const Trivia &LeadingTrivia,
@@ -213,6 +311,17 @@
static RC<TokenSyntax> makeRightParenToken(const Trivia &LeadingTrivia,
const Trivia &TrailingTrivia);
+ /// Make a left brace '{' token with the specified leading and
+ /// trailing trivia.
+ static RC<TokenSyntax> makeLeftBraceToken(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia);
+
+ /// Make a right brace '}' token with the specified leading and
+ /// trailing trivia.
+ static RC<TokenSyntax> makeRightBraceToken(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia);
+
+
/// Make a left square bracket '[' token with the specified leading and
/// trailing trivia.
static RC<TokenSyntax>
@@ -333,6 +442,8 @@
/// Make a set of type attributes with all elements marked as missing.
static TypeAttributesSyntax makeBlankTypeAttributes();
+#pragma mark - balanced-tokens
+
/// Make a list of balanced tokens.
static BalancedTokensSyntax
makeBalancedTokens(RawSyntax::LayoutList Tokens);
@@ -340,6 +451,8 @@
/// Make an empty list of balanced tokens.
static BalancedTokensSyntax makeBlankBalancedTokens();
+#pragma mark - type-identifier
+
/// Make a non-generic type identifier with some name.
static TypeIdentifierSyntax
makeTypeIdentifier(OwnedString Name, const Trivia &LeadingTrivia,
@@ -356,6 +469,8 @@
/// Make a bare "Self" type.
static TypeIdentifierSyntax makeSelfTypeIdentifier();
+#pragma mark - tuple-type
+
/// Make a bare "()" void tuple type
static TupleTypeSyntax makeVoidTupleType();
@@ -366,6 +481,8 @@
/// Make a tuple type element without a label.
static TupleTypeElementSyntax makeTupleTypeElement(TypeSyntax ElementType);
+#pragma mark - optional-type
+
/// Make an optional type, such as `Int?`
static OptionalTypeSyntax
makeOptionalType(TypeSyntax BaseType, const Trivia &TrailingTrivia);
@@ -373,6 +490,8 @@
/// Make an optional type with all elements marked as missing.
static OptionalTypeSyntax makeBlankOptionalType();
+#pragma mark - implicitly-unwrapped-optional-type
+
/// Make an implicitly unwrapped optional type, such as `Int!`
static ImplicitlyUnwrappedOptionalTypeSyntax
makeImplicitlyUnwrappedOptionalType(TypeSyntax BaseType,
@@ -381,6 +500,8 @@
static ImplicitlyUnwrappedOptionalTypeSyntax
makeBlankImplicitlyUnwrappedOptionalType();
+#pragma mark - metatype-type
+
/// Make a metatype type, as in `T.Type`
/// `Type` is a terminal token here, not a placeholder for something else.
static MetatypeTypeSyntax makeMetatypeType(TypeSyntax BaseType,
@@ -390,6 +511,8 @@
/// Make a metatype type with all elements marked as missing.
static MetatypeTypeSyntax makeBlankMetatypeType();
+#pragma mark - array-type
+
/// Make a sugared Array type, as in `[MyType]`.
static ArrayTypeSyntax makeArrayType(RC<TokenSyntax> LeftSquareBracket,
TypeSyntax ElementType,
@@ -398,6 +521,8 @@
/// Make an array type with all elements marked as missing.
static ArrayTypeSyntax makeBlankArrayType();
+#pragma mark - dictionary-type
+
/// Make a Dictionary type, as in `[Key : Value]`.
static DictionaryTypeSyntax
makeDictionaryType(RC<TokenSyntax> LeftSquareBracket, TypeSyntax KeyType,
@@ -407,6 +532,8 @@
/// Make an a dictionary type with all elements marked as missing.
static DictionaryTypeSyntax makeBlankDictionaryType();
+#pragma mark - function-type-argument
+
/// Make a function argument type syntax with the specified elements.
static FunctionTypeArgumentSyntax
makeFunctionTypeArgument(RC<TokenSyntax> ExternalParameterName,
@@ -431,6 +558,8 @@
/// Make a function argument type syntax with all elements marked as missing.
static FunctionTypeArgumentSyntax makeBlankFunctionArgumentType();
+#pragma mark - function-type
+
/// Make a function type, for example, `(Int, Int) throws -> Int`
static FunctionTypeSyntax
makeFunctionType(TypeAttributesSyntax TypeAttributes,
@@ -442,6 +571,8 @@
/// Make a function type with all elements marked as missing.
static FunctionTypeSyntax makeBlankFunctionType();
+#pragma mark - type-argument-list
+
/// Make a list of type arguments with all elements marked as missing.
static TypeArgumentListSyntax makeBlankTypeArgumentList();
@@ -464,6 +595,14 @@
makeSameTypeRequirement(TypeIdentifierSyntax LeftTypeIdentifier,
RC<TokenSyntax> EqualityToken, TypeSyntax RightType);
+ /// Make a list of generic requirements with the given loosely collected
+ /// requirements/
+ static GenericRequirementListSyntax makeGenericRequirementList(
+ std::vector<GenericRequirementSyntax> &Requirements);
+
+ /// Make an empty list of generic requirements.
+ static GenericRequirementListSyntax makeBlankGenericRequirementList();
+
/// Make a same-type requirement with all elements marked as missing.
static SameTypeRequirementSyntax makeBlankSameTypeRequirement();
diff --git a/include/swift/Syntax/SyntaxKinds.def b/include/swift/Syntax/SyntaxKinds.def
index 941d50d..2c0fa59 100644
--- a/include/swift/Syntax/SyntaxKinds.def
+++ b/include/swift/Syntax/SyntaxKinds.def
@@ -40,8 +40,9 @@
SYNTAX(UnknownDecl, DeclSyntax)
SYNTAX(StructDecl, DeclSyntax)
SYNTAX(TypeAliasDecl, DeclSyntax)
+ SYNTAX(FunctionDecl, DeclSyntax)
-SYNTAX_RANGE(Decl, MissingDecl, TypeAliasDecl)
+SYNTAX_RANGE(Decl, MissingDecl, FunctionDecl)
SYNTAX(DeclMembers, Syntax)
SYNTAX(GenericParameter, Syntax)
@@ -52,8 +53,9 @@
SYNTAX(GenericRequirementList, Syntax)
SYNTAX(GenericArgumentClause, Syntax)
SYNTAX(GenericArgumentList, Syntax)
-SYNTAX(ConformanceRequirement, Syntax)
-SYNTAX(SameTypeRequirement, Syntax)
+ABSTRACT_SYNTAX(GenericRequirementSyntax, Syntax)
+ SYNTAX(ConformanceRequirement, GenericRequirementSyntax)
+ SYNTAX(SameTypeRequirement, GenericRequirementSyntax)
SYNTAX(TypeArgumentList, Syntax)
// Types
@@ -98,6 +100,11 @@
SYNTAX(FunctionTypeArgument, Syntax)
SYNTAX(FunctionCallArgumentList, Syntax)
SYNTAX(FunctionCallArgument, Syntax)
+SYNTAX(FunctionSignature, Syntax)
+SYNTAX(FunctionParameterList, Syntax)
+SYNTAX(FunctionParameter, Syntax)
+SYNTAX(DeclModifier, Syntax)
+SYNTAX(DeclModifierList, Syntax)
#undef ABSTRACT_SYNTAX
#undef DECL
diff --git a/include/swift/Syntax/TypeSyntax.h b/include/swift/Syntax/TypeSyntax.h
index 07bf362..d8bee68 100644
--- a/include/swift/Syntax/TypeSyntax.h
+++ b/include/swift/Syntax/TypeSyntax.h
@@ -186,13 +186,16 @@
friend struct SyntaxFactory;
friend class TypeAttributesSyntaxData;
friend class SyntaxData;
+ friend class FunctionSignatureSyntax;
+ friend class FunctionDeclSyntax;
using DataType = TypeAttributesSyntaxData;
TypeAttributesSyntax(RC<SyntaxData> Root,
const TypeAttributesSyntaxData *Data);
public:
- // TODO: TODO: TypeAttributesSyntax::getAttribute
+ // TODO: Convert to SyntaxCollection
+ //
TypeAttributesSyntax
addTypeAttribute(TypeAttributeSyntax NewTypeAttribute) const;
@@ -235,6 +238,8 @@
class TypeSyntax : public Syntax {
using DataType = TypeSyntaxData;
friend class SyntaxData;
+ friend class FunctionParameterSyntax;
+ friend class FunctionSignatureSyntax;
protected:
TypeSyntax(const RC<SyntaxData> Root, const TypeSyntaxData *Data);
public:
diff --git a/include/swift/Syntax/UnknownSyntax.h b/include/swift/Syntax/UnknownSyntax.h
index 7158e03..39d265b 100644
--- a/include/swift/Syntax/UnknownSyntax.h
+++ b/include/swift/Syntax/UnknownSyntax.h
@@ -1,4 +1,4 @@
-//===--- UnknownSyntax.h - Swift Unknown Syntax Interface -----------------===//
+//===--- UnknownSyntax.h - Swift Unknown Syntax Interface -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 70f5135..1045062 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -28,6 +28,7 @@
#include "swift/AST/LazyResolver.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/NameLookup.h"
+#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/RawComment.h"
#include "swift/AST/SILLayout.h"
#include "swift/AST/TypeCheckerDebugConsumer.h"
@@ -3606,6 +3607,36 @@
return nullptr;
}
+bool ForeignRepresentationInfo::isRepresentableAsOptional() const {
+ switch (getKind()) {
+ case ForeignRepresentableKind::None:
+ llvm_unreachable("this type is not representable");
+
+ case ForeignRepresentableKind::Trivial:
+ return Storage.getPointer() != 0;
+
+ case ForeignRepresentableKind::Bridged: {
+ auto KPK_ObjectiveCBridgeable = KnownProtocolKind::ObjectiveCBridgeable;
+ ProtocolDecl *proto = getConformance()->getProtocol();
+ assert(proto->isSpecificProtocol(KPK_ObjectiveCBridgeable) &&
+ "unknown protocol; does it support optional?");
+ (void)proto;
+ (void)KPK_ObjectiveCBridgeable;
+
+ return true;
+ }
+
+ case ForeignRepresentableKind::BridgedError:
+ return true;
+
+ case ForeignRepresentableKind::Object:
+ case ForeignRepresentableKind::StaticBridged:
+ llvm_unreachable("unexpected kind in ForeignRepresentableCacheEntry");
+ }
+
+ llvm_unreachable("Unhandled ForeignRepresentableKind in switch.");
+}
+
ForeignRepresentationInfo
ASTContext::getForeignRepresentationInfo(NominalTypeDecl *nominal,
ForeignLanguage language,
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 7be8ea7..9d35f66 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -29,6 +29,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
@@ -207,6 +208,8 @@
case SILFunctionType::Representation::WitnessMethod: return "witness_method";
case SILFunctionType::Representation::Closure: return "closure";
}
+
+ llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
}
static StringRef
getAbstractStorageDeclKindString(AbstractStorageDecl::StorageKindTy value) {
@@ -230,6 +233,8 @@
case AbstractStorageDecl::Computed:
return "computed";
}
+
+ llvm_unreachable("Unhandled AbstractStorageDecl in switch.");
}
static StringRef getImportKindString(ImportKind value) {
switch (value) {
@@ -242,6 +247,8 @@
case ImportKind::Var: return "var";
case ImportKind::Func: return "func";
}
+
+ llvm_unreachable("Unhandled ImportKind in switch.");
}
static StringRef getAccessibilityString(Accessibility value) {
switch (value) {
@@ -251,6 +258,8 @@
case Accessibility::Public: return "public";
case Accessibility::Open: return "open";
}
+
+ llvm_unreachable("Unhandled Accessibility in switch.");
}
static StringRef
getForeignErrorConventionKindString(ForeignErrorConvention::Kind value) {
@@ -261,6 +270,8 @@
case ForeignErrorConvention::NilResult: return "NilResult";
case ForeignErrorConvention::NonNilError: return "NonNilError";
}
+
+ llvm_unreachable("Unhandled ForeignErrorConvention in switch.");
}
static StringRef getDefaultArgumentKindString(DefaultArgumentKind value) {
switch (value) {
@@ -276,6 +287,8 @@
case DefaultArgumentKind::EmptyDictionary: return "[:]";
case DefaultArgumentKind::Normal: return "normal";
}
+
+ llvm_unreachable("Unhandled DefaultArgumentKind in switch.");
}
static StringRef getAccessorKindString(AccessorKind value) {
switch (value) {
@@ -288,6 +301,8 @@
case AccessorKind::IsAddressor: return "addressor";
case AccessorKind::IsMutableAddressor: return "mutableAddressor";
}
+
+ llvm_unreachable("Unhandled AccessorKind in switch.");
}
static StringRef getAccessKindString(AccessKind value) {
switch (value) {
@@ -295,6 +310,8 @@
case AccessKind::Write: return "write";
case AccessKind::ReadWrite: return "readwrite";
}
+
+ llvm_unreachable("Unhandled AccessKind in switch.");
}
static StringRef
getMagicIdentifierLiteralExprKindString(MagicIdentifierLiteralExpr::Kind value) {
@@ -305,6 +322,8 @@
case MagicIdentifierLiteralExpr::Column: return "#column";
case MagicIdentifierLiteralExpr::DSOHandle: return "#dsohandle";
}
+
+ llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch.");
}
static StringRef
getObjCSelectorExprKindString(ObjCSelectorExpr::ObjCSelectorKind value) {
@@ -313,6 +332,8 @@
case ObjCSelectorExpr::Getter: return "getter";
case ObjCSelectorExpr::Setter: return "setter";
}
+
+ llvm_unreachable("Unhandled ObjCSelectorExpr in switch.");
}
static StringRef getAccessSemanticsString(AccessSemantics value) {
switch (value) {
@@ -321,6 +342,8 @@
case AccessSemantics::DirectToAccessor: return "direct_to_accessor";
case AccessSemantics::BehaviorInitialization: return "behavior_init";
}
+
+ llvm_unreachable("Unhandled AccessSemantics in switch.");
}
static StringRef getMetatypeRepresentationString(MetatypeRepresentation value) {
switch (value) {
@@ -328,6 +351,8 @@
case MetatypeRepresentation::Thick: return "thick";
case MetatypeRepresentation::ObjC: return "@objc";
}
+
+ llvm_unreachable("Unhandled MetatypeRepresentation in switch.");
}
static StringRef
getStringLiteralExprEncodingString(StringLiteralExpr::Encoding value) {
@@ -336,6 +361,8 @@
case StringLiteralExpr::UTF16: return "utf16";
case StringLiteralExpr::OneUnicodeScalar: return "unicodeScalar";
}
+
+ llvm_unreachable("Unhandled StringLiteral in switch.");
}
static StringRef getCtorInitializerKindString(CtorInitializerKind value) {
switch (value) {
@@ -344,6 +371,8 @@
case CtorInitializerKind::ConvenienceFactory: return "convenience_factory";
case CtorInitializerKind::Factory: return "factory";
}
+
+ llvm_unreachable("Unhandled CtorInitializerKind in switch.");
}
static StringRef getOptionalTypeKindString(OptionalTypeKind value) {
switch (value) {
@@ -351,6 +380,8 @@
case OTK_Optional: return "Optional";
case OTK_ImplicitlyUnwrappedOptional: return "ImplicitlyUnwrappedOptional";
}
+
+ llvm_unreachable("Unhandled OptionalTypeKind in switch.");
}
static StringRef getAssociativityString(Associativity value) {
switch (value) {
@@ -358,6 +389,8 @@
case Associativity::Left: return "left";
case Associativity::Right: return "right";
}
+
+ llvm_unreachable("Unhandled Associativity in switch.");
}
//===----------------------------------------------------------------------===//
@@ -2615,10 +2648,18 @@
};
switch (getKind()) {
- case ProtocolConformanceKind::Normal:
+ case ProtocolConformanceKind::Normal: {
+ auto normal = cast<NormalProtocolConformance>(this);
+
printCommon("normal");
// Maybe print information about the conforming context?
+
+ for (auto conformance : normal->getSignatureConformances()) {
+ out << '\n';
+ conformance.dump(out, indent + 2);
+ }
break;
+ }
case ProtocolConformanceKind::Inherited: {
auto conf = cast<InheritedProtocolConformance>(this);
@@ -3109,13 +3150,17 @@
Type(const_cast<TypeBase *>(this)).dump(os, indent);
}
-void GenericEnvironment::dump() const {
- llvm::errs() << "Generic environment:\n";
+void GenericEnvironment::dump(raw_ostream &os) const {
+ os << "Generic environment:\n";
for (auto gp : getGenericParams()) {
- gp->dump();
- mapTypeIntoContext(gp)->dump();
+ gp->dump(os);
+ mapTypeIntoContext(gp)->dump(os);
}
- llvm::errs() << "Generic parameters:\n";
+ os << "Generic parameters:\n";
for (auto paramTy : getGenericParams())
- paramTy->dump();
+ paramTy->dump(os);
+}
+
+void GenericEnvironment::dump() const {
+ dump(llvm::errs());
}
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index e70cdfb..03cb39b 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -1997,7 +1997,8 @@
if (auto req = dyn_cast<ValueDecl>(member)) {
if (!normal->hasWitness(req)) {
- if (req->getAttrs().isUnavailable(Ctx) &&
+ if ((req->getAttrs().isUnavailable(Ctx) ||
+ req->getAttrs().hasAttribute<OptionalAttr>()) &&
proto->isObjC()) {
continue;
}
@@ -2025,6 +2026,40 @@
continue;
}
}
+
+ // Make sure we have the right signature conformances.
+ if (!normal->isInvalid()){
+ auto conformances = normal->getSignatureConformances();
+ unsigned idx = 0;
+ for (auto req : proto->getRequirementSignature()->getRequirements()) {
+ if (req.getKind() != RequirementKind::Conformance)
+ continue;
+
+ if (idx >= conformances.size()) {
+ Out << "error: not enough conformances for requirement signature\n";
+ normal->dump(Out);
+ abort();
+ }
+
+ auto reqProto =
+ req.getSecondType()->castTo<ProtocolType>()->getDecl();
+ if (reqProto != conformances[idx].getRequirement()) {
+ Out << "error: wrong protocol in signature conformances: have "
+ << conformances[idx].getRequirement()->getName().str()
+ << ", expected " << reqProto->getName().str()<< "\n";
+ normal->dump(Out);
+ abort();
+ }
+
+ ++idx;
+ }
+
+ if (idx != conformances.size()) {
+ Out << "error: too many conformances for requirement signature\n";
+ normal->dump(Out);
+ abort();
+ }
+ }
}
void verifyGenericEnvironment(Decl *D,
diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp
index 3bdcbe3..e790ae4 100644
--- a/lib/AST/ASTWalker.cpp
+++ b/lib/AST/ASTWalker.cpp
@@ -197,6 +197,10 @@
}
bool visitAbstractTypeParamDecl(AbstractTypeParamDecl *TPD) {
+ for (auto Inherit: TPD->getInherited()) {
+ if (doIt(Inherit))
+ return true;
+ }
return false;
}
@@ -207,10 +211,6 @@
for (auto GP : NTD->getGenericParams()->getParams()) {
if (doIt(GP))
return true;
- for(auto Inherit: GP->getInherited()) {
- if (doIt(Inherit))
- return true;
- }
}
// Visit param conformance
for (auto &Req : NTD->getGenericParams()->getRequirements()) {
@@ -266,10 +266,6 @@
for (auto &P : AFD->getGenericParams()->getParams()) {
if (doIt(P))
return true;
- for (auto Inherit : P->getInherited()) {
- if (doIt(Inherit))
- return true;
- }
}
// Visit param conformance
diff --git a/lib/AST/ForeignRepresentationInfo.h b/lib/AST/ForeignRepresentationInfo.h
index 7dd0629..05fdb94 100644
--- a/lib/AST/ForeignRepresentationInfo.h
+++ b/lib/AST/ForeignRepresentationInfo.h
@@ -13,7 +13,6 @@
#ifndef SWIFT_FOREIGNREPRESENTATIONINFO_H
#define SWIFT_FOREIGNREPRESENTATIONINFO_H
-#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/Type.h"
#include "swift/Basic/LLVM.h"
#include "llvm/ADT/PointerEmbeddedInt.h"
@@ -21,6 +20,8 @@
namespace swift {
+class ProtocolConformance;
+
class ForeignRepresentationInfo {
using PayloadTy =
llvm::PointerEmbeddedInt<uintptr_t, sizeof(uintptr_t) * CHAR_BIT - 3>;
@@ -112,35 +113,7 @@
}
/// Returns true if the optional version of this type is also representable.
- bool isRepresentableAsOptional() const {
- switch (getKind()) {
- case ForeignRepresentableKind::None:
- llvm_unreachable("this type is not representable");
-
- case ForeignRepresentableKind::Trivial:
- return Storage.getPointer() != 0;
-
- case ForeignRepresentableKind::Bridged: {
- auto KPK_ObjectiveCBridgeable = KnownProtocolKind::ObjectiveCBridgeable;
- ProtocolDecl *proto = getConformance()->getProtocol();
- assert(proto->isSpecificProtocol(KPK_ObjectiveCBridgeable) &&
- "unknown protocol; does it support optional?");
- (void)proto;
- (void)KPK_ObjectiveCBridgeable;
-
- return true;
- }
-
- case ForeignRepresentableKind::BridgedError:
- return true;
-
- case ForeignRepresentableKind::Object:
- case ForeignRepresentableKind::StaticBridged:
- llvm_unreachable("unexpected kind in ForeignRepresentableCacheEntry");
- }
-
- llvm_unreachable("Unhandled ForeignRepresentableKind in switch.");
- }
+ bool isRepresentableAsOptional() const;
};
} // end namespace swift
diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp
index a1f739b..e2e805a 100644
--- a/lib/AST/GenericEnvironment.cpp
+++ b/lib/AST/GenericEnvironment.cpp
@@ -395,25 +395,27 @@
getSubstitutionMap(SubstitutionList subs) const {
SubstitutionMap result;
- for (auto depTy : getGenericSignature()->getAllDependentTypes()) {
+ getGenericSignature()->enumeratePairedRequirements(
+ [&](Type depTy, ArrayRef<Requirement> reqts) -> bool {
+ // Map the interface type to a context type.
+ auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this),
+ MakeAbstractConformanceForGenericType());
- // Map the interface type to a context type.
- auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this),
- MakeAbstractConformanceForGenericType());
+ auto sub = subs.front();
+ subs = subs.slice(1);
- auto sub = subs.front();
- subs = subs.slice(1);
+ // Record the replacement type and its conformances.
+ if (auto *archetype = contextTy->getAs<ArchetypeType>()) {
+ result.addSubstitution(CanArchetypeType(archetype), sub.getReplacement());
+ assert(reqts.size() == sub.getConformances().size());
+ for (auto conformance : sub.getConformances())
+ result.addConformance(CanType(archetype), conformance);
+ return false;
+ }
- // Record the replacement type and its conformances.
- if (auto *archetype = contextTy->getAs<ArchetypeType>()) {
- result.addSubstitution(CanArchetypeType(archetype), sub.getReplacement());
- for (auto conformance : sub.getConformances())
- result.addConformance(CanType(archetype), conformance);
- continue;
- }
-
- assert(contextTy->hasError());
- }
+ assert(contextTy->hasError());
+ return false;
+ });
assert(subs.empty() && "did not use all substitutions?!");
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 56747a6..d4c5b3b 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -78,6 +78,20 @@
return params;
}
+
+SmallVector<GenericTypeParamType *, 2>
+GenericSignature::getSubstitutableParams() const {
+ SmallVector<GenericTypeParamType *, 2> result;
+
+ enumeratePairedRequirements([&](Type depTy, ArrayRef<Requirement>) -> bool {
+ if (auto *paramTy = depTy->getAs<GenericTypeParamType>())
+ result.push_back(paramTy);
+ return false;
+ });
+
+ return result;
+}
+
std::string GenericSignature::gatherGenericParamBindingsText(
ArrayRef<Type> types, TypeSubstitutionFn substitutions) const {
llvm::SmallPtrSet<GenericTypeParamType *, 2> knownGenericParams;
@@ -375,21 +389,21 @@
GenericSignature::getSubstitutionMap(SubstitutionList subs) const {
SubstitutionMap result;
- // An empty parameter list gives an empty map.
- if (subs.empty())
- assert(getGenericParams().empty() || areAllParamsConcrete());
+ enumeratePairedRequirements(
+ [&](Type depTy, ArrayRef<Requirement> reqts) -> bool {
+ auto sub = subs.front();
+ subs = subs.slice(1);
- for (auto depTy : getAllDependentTypes()) {
- auto sub = subs.front();
- subs = subs.slice(1);
+ auto canTy = depTy->getCanonicalType();
+ if (isa<SubstitutableType>(canTy))
+ result.addSubstitution(cast<SubstitutableType>(canTy),
+ sub.getReplacement());
+ assert(reqts.size() == sub.getConformances().size());
+ for (auto conformance : sub.getConformances())
+ result.addConformance(canTy, conformance);
- auto canTy = depTy->getCanonicalType();
- if (isa<SubstitutableType>(canTy))
- result.addSubstitution(cast<SubstitutableType>(canTy),
- sub.getReplacement());
- for (auto conformance : sub.getConformances())
- result.addConformance(canTy, conformance);
- }
+ return false;
+ });
assert(subs.empty() && "did not use all substitutions?!");
populateParentMap(result);
@@ -430,16 +444,6 @@
return subMap;
}
-SmallVector<Type, 4> GenericSignature::getAllDependentTypes() const {
- SmallVector<Type, 4> result;
- enumeratePairedRequirements([&](Type type, ArrayRef<Requirement>) {
- result.push_back(type);
- return false;
- });
-
- return result;
-}
-
void GenericSignature::
getSubstitutions(const TypeSubstitutionMap &subs,
GenericSignature::LookupConformanceFn lookupConformance,
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index b3f69c4..71dc8b2 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -160,6 +160,8 @@
return false;
}
}
+
+ llvm_unreachable("Unhandled RequirementSourceKind in switch.");
}
const void *RequirementSource::getOpaqueStorage() const {
@@ -182,6 +184,8 @@
case StorageKind::AssociatedTypeDecl:
return storage.assocType;
}
+
+ llvm_unreachable("Unhandled StorageKind in switch.");
}
const void *RequirementSource::getExtraOpaqueStorage() const {
@@ -210,6 +214,8 @@
// need to keep them for the requirement signature.
return parent->kind != RequirementSignatureSelf;
}
+
+ llvm_unreachable("Unhandled RequirementSourceKind in switch.");
}
bool RequirementSource::isDerivedViaConcreteConformance() const {
@@ -418,6 +424,8 @@
case StorageKind::AssociatedTypeDecl:
return storage.assocType->getProtocol();
}
+
+ llvm_unreachable("Unhandled StorageKind in switch.");
}
SourceLoc RequirementSource::getLoc() const {
@@ -569,6 +577,8 @@
case Inferred:
return RequirementSource::forInferred(pa, storage.get<const TypeRepr *>());
}
+
+ llvm_unreachable("Unhandled FloatingPointRequirementSourceKind in switch.");
}
SourceLoc FloatingRequirementSource::getLoc() const {
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 52e5a4e..aeb4904 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -252,6 +252,25 @@
return getRootNormalConformance()->getBehaviorDecl();
}
+void NormalProtocolConformance::setSignatureConformances(
+ ArrayRef<ProtocolConformanceRef> conformances) {
+ auto &ctx = getProtocol()->getASTContext();
+ SignatureConformances = ctx.AllocateCopy(conformances);
+
+#if !NDEBUG
+ unsigned idx = 0;
+ for (auto req : getProtocol()->getRequirementSignature()->getRequirements()) {
+ if (req.getKind() == RequirementKind::Conformance) {
+ assert(idx < conformances.size());
+ assert(conformances[idx].getRequirement() ==
+ req.getSecondType()->castTo<ProtocolType>()->getDecl());
+ ++idx;
+ }
+ }
+ assert(idx == conformances.size() && "Too many conformances");
+#endif
+}
+
void NormalProtocolConformance::resolveLazyInfo() const {
assert(Resolver);
assert(isComplete());
@@ -317,6 +336,103 @@
TypeWitnesses[assocType] = std::make_pair(substitution, typeDecl);
}
+/// TypeWitnesses is keyed by the protocol's own declarations, but
+/// DependentMemberTypes will sometimes store a base protocol's declaration.
+/// Map to the derived declaration if possible.
+static AssociatedTypeDecl *getOwnAssociatedTypeDecl(ProtocolDecl *protocol,
+ AssociatedTypeDecl *assoc) {
+ // Fast path.
+ if (assoc->getProtocol() == protocol) return assoc;
+
+ // Search the protocol.
+ for (auto member : protocol->getMembers()) {
+ if (auto memberAssoc = dyn_cast<AssociatedTypeDecl>(member)) {
+ if (memberAssoc->getName() == assoc->getName()) {
+ return memberAssoc;
+ }
+ }
+ }
+
+ // Just assume this is fine.
+ return assoc;
+}
+
+Type NormalProtocolConformance::getAssociatedType(Type assocType,
+ LazyResolver *resolver) const {
+ assert(assocType->isTypeParameter() &&
+ "associated type must be a type parameter");
+
+ // Fast path.
+ auto type = assocType->getCanonicalType();
+ if (isa<GenericTypeParamType>(type)) {
+ assert(type->isEqual(getProtocol()->getSelfInterfaceType()) &&
+ "type parameter in protocol was not Self");
+ return getType();
+ }
+
+ auto memberType = cast<DependentMemberType>(type);
+
+ // TODO: make this handle multiple levels of dependent member type.
+ assert(memberType.getBase()->isEqual(getProtocol()->getSelfInterfaceType()) &&
+ "dependent member in protocol was not rooted in Self");
+
+ auto assocTypeDecl =
+ getOwnAssociatedTypeDecl(getProtocol(), memberType->getAssocType());
+ auto &subst = getTypeWitnessSubstAndDecl(assocTypeDecl, resolver).first;
+ return subst.getReplacement();
+}
+
+ProtocolConformanceRef
+NormalProtocolConformance::getAssociatedConformance(Type assocType,
+ ProtocolDecl *protocol,
+ LazyResolver *resolver) const {
+ assert(assocType->isTypeParameter() &&
+ "associated type must be a type parameter");
+
+#ifndef NDEBUG
+ bool foundInRequirements = false;
+ for (auto &reqt :
+ getProtocol()->getRequirementSignature()->getRequirements()) {
+ if (reqt.getKind() == RequirementKind::Conformance &&
+ reqt.getFirstType()->isEqual(assocType) &&
+ reqt.getSecondType()->castTo<ProtocolType>()->getDecl() == protocol) {
+ foundInRequirements = true;
+ break;
+ }
+ }
+ assert(foundInRequirements &&
+ "requested conformance was not a direct requirement of the protocol");
+#endif
+
+ auto type = assocType->getCanonicalType();
+
+ if (isa<GenericTypeParamType>(type)) {
+ assert(type->isEqual(getProtocol()->getSelfInterfaceType()) &&
+ "type parameter in protocol was not Self");
+ auto conf = getInheritedConformance(protocol);
+ assert(conf && "inherited conformances cannot be abstract");
+ return ProtocolConformanceRef(conf);
+ }
+
+ auto memberType = cast<DependentMemberType>(type);
+
+ // For now, NormalProtocolConformance does not store indirect associations.
+ assert(memberType.getBase()->isEqual(getProtocol()->getSelfInterfaceType()) &&
+ "dependent member in protocol was not rooted in Self");
+
+ auto assocTypeDecl =
+ getOwnAssociatedTypeDecl(getProtocol(), memberType->getAssocType());
+ auto &subst = getTypeWitnessSubstAndDecl(assocTypeDecl, resolver).first;
+
+ // Scan the conformances for the exact conformance.
+ // TODO: should we allow indirect conformances for convenience of use?
+ for (auto &conf : subst.getConformances()) {
+ if (conf.getRequirement() == protocol)
+ return conf;
+ }
+ llvm_unreachable("missing conformance to protocol");
+}
+
/// Retrieve the value witness corresponding to the given requirement.
Witness NormalProtocolConformance::getWitness(ValueDecl *requirement,
LazyResolver *resolver) const {
@@ -347,7 +463,11 @@
assert(getProtocol() == cast<ProtocolDecl>(requirement->getDeclContext()) &&
"requirement in wrong protocol");
assert(Mapping.count(requirement) == 0 && "Witness already known");
- assert((!isComplete() || isInvalid()) && "Conformance already complete?");
+ assert((!isComplete() || isInvalid() ||
+ requirement->getAttrs().hasAttribute<OptionalAttr>() ||
+ requirement->getAttrs().isUnavailable(
+ requirement->getASTContext())) &&
+ "Conformance already complete?");
Mapping[requirement] = witness;
}
diff --git a/lib/AST/SourceEntityWalker.cpp b/lib/AST/SourceEntityWalker.cpp
index d6a28c3..5aa4cbf 100644
--- a/lib/AST/SourceEntityWalker.cpp
+++ b/lib/AST/SourceEntityWalker.cpp
@@ -335,6 +335,9 @@
}
std::pair<bool, Pattern *> SemaAnnotator::walkToPatternPre(Pattern *P) {
+ if (P->isImplicit())
+ return { true, P };
+
if (auto *EP = dyn_cast<EnumElementPattern>(P)) {
auto *Element = EP->getElementDecl();
if (!Element)
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 659ad44..e801028 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -23,6 +23,7 @@
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
+#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/TypeLoc.h"
#include "llvm/ADT/APFloat.h"
diff --git a/lib/Basic/Demangle.cpp b/lib/Basic/Demangle.cpp
index 281883f..af9bb55 100644
--- a/lib/Basic/Demangle.cpp
+++ b/lib/Basic/Demangle.cpp
@@ -2331,7 +2331,9 @@
bool
swift::Demangle::isSwiftSymbol(const char *mangledName) {
// The old mangling.
- if (mangledName[0] == '_' && mangledName[1] == 'T')
+ if (mangledName[0] == '_'
+ // Also accept the future mangling prefix.
+ && (mangledName[1] == 'T' || mangledName[1] == 'S'))
return true;
// The new mangling.
diff --git a/lib/Basic/Demangler.cpp b/lib/Basic/Demangler.cpp
index 70ded11..0856944 100644
--- a/lib/Basic/Demangler.cpp
+++ b/lib/Basic/Demangler.cpp
@@ -137,7 +137,10 @@
NodePointer Context::demangleSymbolAsNode(llvm::StringRef MangledName) {
#ifndef NO_NEW_DEMANGLING
- if (MangledName.startswith(MANGLING_PREFIX_STR)) {
+ if (MangledName.startswith(MANGLING_PREFIX_STR)
+ // Also accept the future mangling prefix.
+ // TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
+ || MangledName.startswith("_S")) {
return D->demangleSymbol(MangledName);
}
#endif
@@ -171,7 +174,10 @@
}
bool Context::isThunkSymbol(llvm::StringRef MangledName) {
- if (MangledName.startswith(MANGLING_PREFIX_STR)) {
+ if (MangledName.startswith(MANGLING_PREFIX_STR)
+ // Also accept the future mangling prefix.
+ // TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
+ || MangledName.startswith("_S")) {
// First do a quick check
if (MangledName.endswith("TA") || // partial application forwarder
MangledName.endswith("Ta") || // ObjC partial application forwarder
@@ -202,13 +208,60 @@
StringRef Remaining = MangledName.substr(2);
if (Remaining.startswith("To") || // swift-as-ObjC thunk
Remaining.startswith("TO") || // ObjC-as-swift thunk
- Remaining.startswith("PA")) { // (ObjC) partial application forwarder
+ Remaining.startswith("PA_") || // partial application forwarder
+ Remaining.startswith("PAo_")) { // ObjC partial application forwarder
return true;
}
}
return false;
}
-
+
+std::string Context::getThunkTarget(llvm::StringRef MangledName) {
+ if (!isThunkSymbol(MangledName))
+ return std::string();
+
+ if (MangledName.startswith(MANGLING_PREFIX_STR)
+ // Also accept the future mangling prefix.
+ // TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
+ || MangledName.startswith("_S")) {
+
+ return MangledName.substr(0, MangledName.size() - 2).str();
+ }
+ // Old mangling.
+ assert(MangledName.startswith("_T"));
+ StringRef Remaining = MangledName.substr(2);
+ if (Remaining.startswith("PA_"))
+ return Remaining.substr(3).str();
+ if (Remaining.startswith("PAo_"))
+ return Remaining.substr(4).str();
+ assert(Remaining.startswith("To") || Remaining.startswith("TO"));
+ return std::string("_T") + Remaining.substr(2).str();
+}
+
+bool Context::hasSwiftCallingConvention(llvm::StringRef MangledName) {
+ Node *Global = demangleSymbolAsNode(MangledName);
+ if (!Global || Global->getKind() != Node::Kind::Global ||
+ Global->getNumChildren() == 0)
+ return false;
+
+ Node *TopLevel = Global->getFirstChild();
+ switch (TopLevel->getKind()) {
+ // Functions, which don't have the swift calling conventions:
+ case Node::Kind::TypeMetadataAccessFunction:
+ case Node::Kind::ValueWitness:
+ case Node::Kind::ProtocolWitnessTableAccessor:
+ case Node::Kind::GenericProtocolWitnessTableInstantiationFunction:
+ case Node::Kind::LazyProtocolWitnessTableAccessor:
+ case Node::Kind::AssociatedTypeMetadataAccessor:
+ case Node::Kind::AssociatedTypeWitnessTableAccessor:
+ case Node::Kind::ObjCAttribute:
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
NodePointer Context::createNode(Node::Kind K) {
return D->createNode(K);
}
@@ -257,6 +310,11 @@
addChild(Child, *Ctx.D);
}
+void Node::reverseChildren(size_t StartingAt) {
+ assert(StartingAt <= NumChildren);
+ std::reverse(Children + StartingAt, Children + NumChildren);
+}
+
//////////////////////////////////
// NodeFactory member functions //
//////////////////////////////////
@@ -297,18 +355,49 @@
NodePointer NodeFactory::createNode(Node::Kind K, llvm::StringRef Text) {
return new (Allocate<Node>()) Node(K, Text.copy(*this));
}
+NodePointer NodeFactory::createNode(Node::Kind K, const CharVector &Text) {
+ return new (Allocate<Node>()) Node(K, Text.str());
+}
NodePointer NodeFactory::createNode(Node::Kind K, const char *Text) {
return new (Allocate<Node>()) Node(K, llvm::StringRef(Text));
}
//////////////////////////////////
+// CharVector member functions //
+//////////////////////////////////
+
+void CharVector::append(StringRef Rhs, NodeFactory &Factory) {
+ if (NumElems + Rhs.size() > Capacity)
+ Factory.Reallocate(Elems, Capacity, /*Growth*/ Rhs.size());
+ memcpy(Elems + NumElems, Rhs.data(), Rhs.size());
+ NumElems += Rhs.size();
+ assert(NumElems <= Capacity);
+}
+
+void CharVector::append(int Number, NodeFactory &Factory) {
+ const int MaxIntPrintSize = 8;
+ if (NumElems + MaxIntPrintSize > Capacity)
+ Factory.Reallocate(Elems, Capacity, /*Growth*/ MaxIntPrintSize);
+ int Length = snprintf(Elems + NumElems, MaxIntPrintSize, "%d", Number);
+ assert(Length > 0 && Length < MaxIntPrintSize);
+ NumElems += Length;
+}
+
+//////////////////////////////////
// Demangler member functions //
//////////////////////////////////
+void Demangler::clear() {
+ NodeStack.free();
+ Substitutions.free();
+ PendingSubstitutions.free();
+ NodeFactory::clear();
+}
+
void Demangler::init(StringRef MangledName) {
- NodeStack.clear();
- Substitutions.clear();
- PendingSubstitutions.clear();
+ NodeStack.init(*this, 16);
+ Substitutions.init(*this, 16);
+ PendingSubstitutions.init(*this, 4);
NumWords = 0;
Text = MangledName;
Pos = 0;
@@ -317,7 +406,10 @@
NodePointer Demangler::demangleSymbol(StringRef MangledName) {
init(MangledName);
- if (!nextIf(MANGLING_PREFIX_STR))
+ if (!nextIf(MANGLING_PREFIX_STR)
+ // Also accept the future mangling prefix.
+ // TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
+ && !nextIf("_S"))
return nullptr;
NodePointer topLevel = createNode(Node::Kind::Global);
@@ -625,7 +717,7 @@
hasWordSubsts = true;
}
}
- std::string Identifier;
+ CharVector Identifier;
do {
while (hasWordSubsts && isLetter(peekChar())) {
char c = nextChar();
@@ -641,7 +733,7 @@
return nullptr;
assert(WordIdx < MaxNumWords);
StringRef Slice = Words[WordIdx];
- Identifier.append(Slice.data(), Slice.size());
+ Identifier.append(Slice, *this);
}
if (nextIf('0'))
break;
@@ -654,10 +746,12 @@
return nullptr;
StringRef Slice = StringRef(Text.data() + Pos, numChars);
if (isPunycoded) {
- if (!Punycode::decodePunycodeUTF8(Slice, Identifier))
+ std::string PunycodedString;
+ if (!Punycode::decodePunycodeUTF8(Slice, PunycodedString))
return nullptr;
+ Identifier.append(StringRef(PunycodedString), *this);
} else {
- Identifier.append(Slice.data(), Slice.size());
+ Identifier.append(Slice, *this);
int wordStartPos = -1;
for (int Idx = 0, End = (int)Slice.size(); Idx <= End; ++Idx) {
char c = (Idx < End ? Slice[Idx] : 0);
@@ -688,12 +782,11 @@
static const char op_char_table[] = "& @/= > <*!|+?%-~ ^ .";
- std::string OpStr;
- OpStr.reserve(Ident->getText().size());
+ CharVector OpStr;
for (signed char c : Ident->getText()) {
if (c < 0) {
// Pass through Unicode characters.
- OpStr.push_back(c);
+ OpStr.push_back(c, *this);
continue;
}
if (!isLowerLetter(c))
@@ -701,7 +794,7 @@
char o = op_char_table[c - 'a'];
if (o == ' ')
return nullptr;
- OpStr.push_back(o);
+ OpStr.push_back(o, *this);
}
switch (nextChar()) {
case 'i': return createNode(Node::Kind::InfixOperator, OpStr);
@@ -772,16 +865,20 @@
int size = demangleIndex() - 1;
if (size <= 0)
return nullptr;
- Ty = createNode(Node::Kind::BuiltinTypeName,
- std::move(DemanglerPrinter() << "Builtin.Float" << size).str());
+ CharVector name;
+ name.append("Builtin.Float", *this);
+ name.append(size, *this);
+ Ty = createNode(Node::Kind::BuiltinTypeName, name);
break;
}
case 'i': {
int size = demangleIndex() - 1;
if (size <= 0)
return nullptr;
- Ty = createNode(Node::Kind::BuiltinTypeName,
- (DemanglerPrinter() << "Builtin.Int" << size).str());
+ CharVector name;
+ name.append("Builtin.Int", *this);
+ name.append(size, *this);
+ Ty = createNode(Node::Kind::BuiltinTypeName, name);
break;
}
case 'v': {
@@ -792,9 +889,12 @@
if (!EltType || EltType->getKind() != Node::Kind::BuiltinTypeName ||
!EltType->getText().startswith("Builtin."))
return nullptr;
- Ty = createNode(Node::Kind::BuiltinTypeName,
- (DemanglerPrinter() << "Builtin.Vec" << elts << "x" <<
- EltType->getText().substr(sizeof("Builtin.") - 1)).str());
+ CharVector name;
+ name.append("Builtin.Vec", *this);
+ name.append(elts, *this);
+ name.push_back('x', *this);
+ name.append(EltType->getText().substr(sizeof("Builtin.") - 1), *this);
+ Ty = createNode(Node::Kind::BuiltinTypeName, name);
break;
}
case 'O':
@@ -880,7 +980,6 @@
Node::Kind::NonVariadicTuple);
if (!popNode(Node::Kind::EmptyList)) {
- std::vector<NodePointer> Nodes;
bool firstElem = false;
do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
@@ -893,12 +992,10 @@
if (!Ty)
return nullptr;
TupleElmt->addChild(Ty, *this);
- Nodes.push_back(TupleElmt);
+ Root->addChild(TupleElmt, *this);
} while (!firstElem);
- while (NodePointer TupleElmt = pop_back_val(Nodes)) {
- Root->addChild(TupleElmt, *this);
- }
+ Root->reverseChildren();
}
return createType(Root);
}
@@ -907,18 +1004,16 @@
NodePointer Root = createNode(Node::Kind::TypeList);
if (!popNode(Node::Kind::EmptyList)) {
- std::vector<NodePointer> Nodes;
bool firstElem = false;
do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer Ty = popNode(Node::Kind::Type);
if (!Ty)
return nullptr;
- Nodes.push_back(Ty);
- } while (!firstElem);
- while (NodePointer Ty = pop_back_val(Nodes)) {
Root->addChild(Ty, *this);
- }
+ } while (!firstElem);
+
+ Root->reverseChildren();
}
return Root;
}
@@ -931,17 +1026,15 @@
}
NodePointer Demangler::demangleBoundGenericType() {
- std::vector<NodePointer> TypeListList;
- std::vector<NodePointer> Types;
+ Vector<NodePointer> TypeListList(*this, 4);
for (;;) {
NodePointer TList = createNode(Node::Kind::TypeList);
- TypeListList.push_back(TList);
+ TypeListList.push_back(TList, *this);
while (NodePointer Ty = popNode(Node::Kind::Type)) {
- Types.push_back(Ty);
- }
- while (NodePointer Ty = pop_back_val(Types)) {
TList->addChild(Ty, *this);
}
+ TList->reverseChildren();
+
if (popNode(Node::Kind::EmptyList))
break;
if (!popNode(Node::Kind::FirstElementMarker))
@@ -952,7 +1045,7 @@
}
NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal,
- const std::vector<NodePointer> &TypeLists,
+ const Vector<NodePointer> &TypeLists,
size_t TypeListIdx) {
if (!Nominal || Nominal->getNumChildren() < 2)
return nullptr;
@@ -1001,7 +1094,7 @@
}
NodePointer Demangler::demangleImplParamConvention() {
- StringRef attr;
+ const char *attr = nullptr;
switch (nextChar()) {
case 'i': attr = "@in"; break;
case 'l': attr = "@inout"; break;
@@ -1020,7 +1113,7 @@
}
NodePointer Demangler::demangleImplResultConvention(Node::Kind ConvKind) {
- StringRef attr;
+ const char *attr = nullptr;
switch (nextChar()) {
case 'r': attr = "@out"; break;
case 'o': attr = "@owned"; break;
@@ -1136,19 +1229,6 @@
}
}
-static std::string getArchetypeName(Node::IndexType index,
- Node::IndexType depth) {
- DemanglerPrinter name;
- do {
- name << (char)('A' + (index % 26));
- index /= 26;
- } while (index);
- if (depth != 0)
- name << depth;
- return std::move(name).str();
-}
-
-
NodePointer Demangler::demangleArchetype() {
switch (nextChar()) {
case 'a': {
@@ -1201,19 +1281,19 @@
NodePointer Demangler::demangleAssociatedTypeCompound(
NodePointer GenericParamIdx) {
- std::vector<NodePointer> AssocTyNames;
+ Vector<NodePointer> AssocTyNames(*this, 4);
bool firstElem = false;
do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer AssocTyName = popAssocTypeName();
if (!AssocTyName)
return nullptr;
- AssocTyNames.push_back(AssocTyName);
+ AssocTyNames.push_back(AssocTyName, *this);
} while (!firstElem);
NodePointer Base = GenericParamIdx;
- while (NodePointer AssocTy = pop_back_val(AssocTyNames)) {
+ while (NodePointer AssocTy = AssocTyNames.pop_back_val()) {
NodePointer depTy = createNode(Node::Kind::DependentMemberType);
depTy = addChild(depTy, createType(Base));
Base = addChild(depTy, AssocTy);
@@ -1235,11 +1315,17 @@
NodePointer Demangler::getDependentGenericParamType(int depth, int index) {
if (depth < 0 || index < 0)
return nullptr;
- DemanglerPrinter PrintName;
- PrintName << getArchetypeName(index, depth);
-
- auto paramTy = createNode(Node::Kind::DependentGenericParamType,
- std::move(PrintName).str());
+
+ CharVector name;
+ int idxChar = index;
+ do {
+ name.push_back((char)('A' + (idxChar % 26)), *this);
+ idxChar /= 26;
+ } while (idxChar);
+ if (depth != 0)
+ name.append(depth, *this);
+
+ auto paramTy = createNode(Node::Kind::DependentGenericParamType, name);
paramTy->addChild(createNode(Node::Kind::Index, depth), *this);
paramTy->addChild(createNode(Node::Kind::Index, index), *this);
return paramTy;
@@ -1372,10 +1458,10 @@
case FunctionSigSpecializationParamKind::ConstantPropGlobal:
case FunctionSigSpecializationParamKind::ConstantPropString:
case FunctionSigSpecializationParamKind::ClosureProp: {
- std::vector<NodePointer> Types;
+ size_t FixedChildren = Param->getNumChildren();
while (NodePointer Ty = popNode(Node::Kind::Type)) {
assert(ParamKind == FunctionSigSpecializationParamKind::ClosureProp);
- Types.push_back(Ty);
+ Param = addChild(Param, Ty);
}
NodePointer Name = popNode(Node::Kind::Identifier);
if (!Name)
@@ -1389,9 +1475,7 @@
}
addChild(Param, createNode(
Node::Kind::FunctionSignatureSpecializationParamPayload, Text));
- while (NodePointer Ty = pop_back_val(Types)) {
- Param = addChild(Param, Ty);
- }
+ Param->reverseChildren(FixedChildren);
break;
}
default:
@@ -1499,9 +1583,9 @@
Param->addChild(createNode(
Node::Kind::FunctionSignatureSpecializationParamKind, unsigned(Kind)),
*this);
- std::string Str;
+ CharVector Str;
while (isDigit(peekChar())) {
- Str += nextChar();
+ Str.push_back(nextChar(), *this);
}
if (Str.empty())
return nullptr;
@@ -1801,28 +1885,21 @@
NodePointer TypeList = createNode(Node::Kind::TypeList);
NodePointer ProtoList = createWithChild(Node::Kind::ProtocolList, TypeList);
if (!popNode(Node::Kind::EmptyList)) {
- std::vector<NodePointer> ProtoNames;
bool firstElem = false;
do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer Proto = popProtocol();
if (!Proto)
return nullptr;
- ProtoNames.push_back(Proto);
+ TypeList->addChild(Proto, *this);
} while (!firstElem);
- while (NodePointer Proto = pop_back_val(ProtoNames)) {
- TypeList->addChild(Proto, *this);
- }
+ TypeList->reverseChildren();
}
return createType(ProtoList);
}
NodePointer Demangler::demangleGenericSignature(bool hasParamCounts) {
- std::vector<NodePointer> Requirements;
- while (NodePointer Req = popNode(isRequirement)) {
- Requirements.push_back(Req);
- }
NodePointer Sig = createNode(Node::Kind::DependentGenericSignature);
if (hasParamCounts) {
while (!nextIf('l')) {
@@ -1840,9 +1917,11 @@
}
if (Sig->getNumChildren() == 0)
return nullptr;
- while (NodePointer Req = pop_back_val(Requirements)) {
+ size_t NumCounts = Sig->getNumChildren();
+ while (NodePointer Req = popNode(isRequirement)) {
Sig->addChild(Req, *this);
}
+ Sig->reverseChildren(NumCounts);
return Sig;
}
@@ -1905,7 +1984,7 @@
auto c = nextChar();
NodePointer size = nullptr;
NodePointer alignment = nullptr;
- StringRef name;
+ const char *name = nullptr;
if (c == 'U') {
name = "U";
} else if (c == 'R') {
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index f38da00..220f1e2 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -242,16 +242,11 @@
}
Version Version::getCurrentLanguageVersion() {
-#ifndef SWIFT_VERSION_STRING
-#error Swift language version is not set!
+#if SWIFT_VERSION_PATCHLEVEL
+ return {SWIFT_VERSION_MAJOR, SWIFT_VERSION_MINOR, SWIFT_VERSION_PATCHLEVEL};
+#else
+ return {SWIFT_VERSION_MAJOR, SWIFT_VERSION_MINOR};
#endif
- auto currentVersion = Version::parseVersionString(
- SWIFT_VERSION_STRING, SourceLoc(), nullptr);
- assert(currentVersion.hasValue() &&
- "Embedded Swift language version couldn't be parsed: '"
- SWIFT_VERSION_STRING
- "'");
- return currentVersion.getValue();
}
raw_ostream &operator<<(raw_ostream &os, const Version &version) {
@@ -304,18 +299,35 @@
}
}
-bool Version::isValidEffectiveLanguageVersion() const {
- for (auto verStr : getValidEffectiveVersions()) {
- auto v = parseVersionString(verStr, SourceLoc(), nullptr);
- assert(v.hasValue());
- // In this case, use logical-equality _and_ precision-equality. We do not
- // want to permit users requesting effective language versions more precise
- // than our whitelist (eg. we permit 3 but not 3.0 or 3.0.0), since
- // accepting such an argument promises more than we're able to deliver.
- if (v == *this && v.getValue().size() == size())
- return true;
+Optional<Version> Version::getEffectiveLanguageVersion() const {
+ switch (size()) {
+ case 0:
+ return None;
+ case 1:
+ break;
+ default:
+ // We do not want to permit users requesting more precise effective language
+ // versions since accepting such an argument promises more than we're able
+ // to deliver.
+ return None;
}
- return false;
+
+ // FIXME: When we switch to Swift 4 by default, the "3" case should return
+ // a version newer than any released 3.x compiler (probably "3.2"), and the
+ // "4" case should start returning getCurrentLanguageVersion. We should
+ // also check for the presence of SWIFT_VERSION_PATCHLEVEL, and if that's
+ // set apply it to the "3" case, so that Swift 4.0.1 will automatically
+ // have a compatibility mode of 3.2.1.
+ switch (Components[0]) {
+ case 3:
+ static_assert(SWIFT_VERSION_MAJOR == 3,
+ "getCurrentLanguageVersion is no longer correct here");
+ return Version::getCurrentLanguageVersion();
+ case 4:
+ return Version{4, 0};
+ default:
+ return None;
+ }
}
Version Version::asMajorVersion() const {
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 6fcdebc..8028752 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -6952,6 +6952,7 @@
};
return getDeclName(*left).compare(getDeclName(*right));
});
+
// Schedule any that aren't complete.
for (auto *inherited : inheritedProtos) {
ModuleDecl *M = conformance->getDeclContext()->getParentModule();
@@ -6964,6 +6965,24 @@
inheritedConformance->getConcrete());
}
+ // Collect conformances for the requirement signature.
+ SmallVector<ProtocolConformanceRef, 4> reqConformances;
+ for (auto req : proto->getRequirementSignature()->getRequirements()) {
+ if (req.getKind() != RequirementKind::Conformance)
+ continue;
+
+ assert(req.getFirstType()->isEqual(proto->getSelfInterfaceType()));
+ auto reqProto = req.getSecondType()->castTo<ProtocolType>()->getDecl();
+
+ ModuleDecl *M = conformance->getDeclContext()->getParentModule();
+ auto reqConformance = M->lookupConformance(conformance->getType(),
+ reqProto, /*resolver=*/nullptr);
+ assert(reqConformance && reqConformance->isConcrete() &&
+ "required conformance not found");
+ reqConformances.push_back(*reqConformance);
+ }
+ conformance->setSignatureConformances(reqConformances);
+
conformance->setState(ProtocolConformanceState::Complete);
}
diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp
index b00f41f..e330bfc 100644
--- a/lib/ClangImporter/ImportName.cpp
+++ b/lib/ClangImporter/ImportName.cpp
@@ -37,6 +37,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <memory>
@@ -79,6 +80,8 @@
case ImportNameVersion::Swift4:
return 4;
}
+
+ llvm_unreachable("Unhandled ImportNameVersion in switch.");
}
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index e6f2ca0..7ae5be6 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -44,6 +44,45 @@
using namespace swift::driver;
using namespace llvm::opt;
+struct LogJob {
+ const Job *j;
+ LogJob(const Job *j) : j(j) {}
+};
+
+struct LogJobArray {
+ const ArrayRef<const Job *> js;
+ LogJobArray(const ArrayRef<const Job *> js) : js(js) {}
+};
+
+struct LogJobSet {
+ const SmallPtrSetImpl<const Job*> &js;
+ LogJobSet(const SmallPtrSetImpl<const Job*> &js) : js(js) {}
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const LogJob &lj) {
+ lj.j->printSummary(os);
+ return os;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const LogJobArray &ljs) {
+ os << "[";
+ interleave(ljs.js,
+ [&](Job const *j) { os << LogJob(j); },
+ [&]() { os << ' '; });
+ os << "]";
+ return os;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const LogJobSet &ljs) {
+ os << "{";
+ interleave(ljs.js,
+ [&](Job const *j) { os << LogJob(j); },
+ [&]() { os << ' '; });
+ os << "}";
+ return os;
+}
+
+
Compilation::Compilation(DiagnosticEngine &Diags, OutputLevel Level,
std::unique_ptr<InputArgList> InputArgs,
std::unique_ptr<DerivedArgList> TranslatedArgs,
@@ -65,10 +104,21 @@
ShowDriverTimeCompilation(ShowDriverTimeCompilation) {
};
+static bool writeFilelistIfNecessary(const Job *job, DiagnosticEngine &diags);
+
using CommandSet = llvm::SmallPtrSet<const Job *, 16>;
-namespace {
- struct PerformJobsState {
+
+using InputInfoMap = llvm::SmallMapVector<const llvm::opt::Arg *,
+ CompileJobAction::InputInfo, 16>;
+
+namespace swift {
+namespace driver {
+ class PerformJobsState {
+
+ /// The containing Compilation object.
+ Compilation &Comp;
+
/// All jobs which have been scheduled for execution (whether or not
/// they've finished execution), or which have been determined that they
/// don't need to run.
@@ -89,8 +139,548 @@
///
/// Only intended for source files.
llvm::SmallDenseMap<const Job *, bool, 16> UnfinishedCommands;
+
+ /// Jobs that incremental-mode has decided it can skip.
+ CommandSet DeferredCommands;
+
+ /// Jobs in the initial set with Condition::Always, or lacking existing
+ /// .swiftdeps files.
+ SmallVector<const Job *, 16> InitialOutOfDateCommands;
+
+ /// Dependency graph for deciding which jobs are dirty (need running)
+ /// or clean (can be skipped).
+ using DependencyGraph = DependencyGraph<const Job *>;
+ DependencyGraph DepGraph;
+
+ /// Helper for tracing the propagation of marks in the graph.
+ DependencyGraph::MarkTracer ActualIncrementalTracer;
+ DependencyGraph::MarkTracer *IncrementalTracer = nullptr;
+
+ /// TaskQueue for execution.
+ std::unique_ptr<TaskQueue> TQ;
+
+ /// Cumulative result of PerformJobs(), accumulated from subprocesses.
+ int Result = EXIT_SUCCESS;
+
+ /// Timers for monitoring execution time of subprocesses.
+ llvm::TimerGroup DriverTimerGroup {"driver", "Driver Compilation Time"};
+ llvm::SmallDenseMap<const Job *, std::unique_ptr<llvm::Timer>, 16>
+ DriverTimers;
+
+ void noteBuilding(const Job *cmd, StringRef reason) {
+ if (!Comp.ShowIncrementalBuildDecisions)
+ return;
+ if (ScheduledCommands.count(cmd))
+ return;
+ llvm::outs() << "Queuing " << reason << ": " << LogJob(cmd) << "\n";
+ IncrementalTracer->printPath(
+ llvm::outs(), cmd, [](raw_ostream &out, const Job *base) {
+ out << llvm::sys::path::filename(base->getOutput().getBaseInput(0));
+ });
+ }
+
+ const Job *findUnfinishedJob(ArrayRef<const Job *> JL) {
+ for (const Job *Cmd : JL) {
+ if (!FinishedCommands.count(Cmd))
+ return Cmd;
+ }
+ return nullptr;
+ }
+
+ /// Schedule the given Job if it has not been scheduled and if all of
+ /// its inputs are in FinishedCommands.
+ void scheduleCommandIfNecessaryAndPossible(const Job *Cmd) {
+ if (ScheduledCommands.count(Cmd)) {
+ if (Comp.ShowJobLifecycle) {
+ llvm::outs() << "Already scheduled: " << LogJob(Cmd) << "\n";
+ }
+ return;
+ }
+
+ if (auto Blocking = findUnfinishedJob(Cmd->getInputs())) {
+ BlockingCommands[Blocking].push_back(Cmd);
+ if (Comp.ShowJobLifecycle) {
+ llvm::outs() << "Blocked by: " << LogJob(Blocking)
+ << ", now blocking jobs: "
+ << LogJobArray(BlockingCommands[Blocking]) << "\n";
+ }
+ return;
+ }
+
+ // FIXME: Failing here should not take down the whole process.
+ bool success = writeFilelistIfNecessary(Cmd, Comp.Diags);
+ assert(success && "failed to write filelist");
+ (void)success;
+
+ assert(Cmd->getExtraEnvironment().empty() &&
+ "not implemented for compilations with multiple jobs");
+ ScheduledCommands.insert(Cmd);
+ if (Comp.ShowJobLifecycle)
+ llvm::outs() << "Added to TaskQueue: " << LogJob(Cmd) << "\n";
+ TQ->addTask(Cmd->getExecutable(), Cmd->getArguments(), llvm::None,
+ (void *)Cmd);
+ }
+
+ /// When a task finishes, check other Jobs that may be blocked.
+ void markFinished(const Job *Cmd, bool Skipped=false) {
+ if (Comp.ShowJobLifecycle) {
+ llvm::outs() << "Job "
+ << (Skipped ? "skipped" : "finished")
+ << ": " << LogJob(Cmd) << "\n";
+ }
+ FinishedCommands.insert(Cmd);
+
+ auto BlockedIter = BlockingCommands.find(Cmd);
+ if (BlockedIter != BlockingCommands.end()) {
+ auto AllBlocked = std::move(BlockedIter->second);
+ if (Comp.ShowJobLifecycle) {
+ llvm::outs() << "Scheduling maybe-unblocked jobs: "
+ << LogJobArray(AllBlocked) << "\n";
+ }
+ BlockingCommands.erase(BlockedIter);
+ for (auto *Blocked : AllBlocked)
+ scheduleCommandIfNecessaryAndPossible(Blocked);
+ }
+ }
+
+ /// Callback which will be called immediately after a task has started. This
+ /// callback may be used to provide output indicating that the task began.
+ void taskBegan(ProcessId Pid, void *Context) {
+ // TODO: properly handle task began.
+ const Job *BeganCmd = (const Job *)Context;
+
+ if (Comp.ShowDriverTimeCompilation) {
+ llvm::SmallString<128> TimerName;
+ llvm::raw_svector_ostream OS(TimerName);
+ OS << LogJob(BeganCmd);
+ DriverTimers.insert({
+ BeganCmd,
+ std::unique_ptr<llvm::Timer>(
+ new llvm::Timer("task", OS.str(), DriverTimerGroup))
+ });
+ DriverTimers[BeganCmd]->startTimer();
+ }
+
+ // For verbose output, print out each command as it begins execution.
+ if (Comp.Level == OutputLevel::Verbose)
+ BeganCmd->printCommandLine(llvm::errs());
+ else if (Comp.Level == OutputLevel::Parseable)
+ parseable_output::emitBeganMessage(llvm::errs(), *BeganCmd, Pid);
+ }
+
+ void
+ dependencyLoadFailed(StringRef DependenciesFile, bool Warn=true) {
+ if (Warn && Comp.ShowIncrementalBuildDecisions)
+ Comp.Diags.diagnose(SourceLoc(),
+ diag::warn_unable_to_load_dependencies,
+ DependenciesFile);
+ Comp.disableIncrementalBuild();
+ for (const Job *Cmd : DeferredCommands)
+ scheduleCommandIfNecessaryAndPossible(Cmd);
+ DeferredCommands.clear();
+ }
+
+ /// Helper that reloads a job's .swiftdeps file after the job exits, and
+ /// re-runs transitive marking to ensure everything is properly invalidated
+ /// by any new dependency edges introduced by it.
+ template <unsigned N>
+ void reloadAndRemarkDeps(const Job *FinishedCmd,
+ int ReturnCode,
+ SmallVector<const Job *, N> &Dependents) {
+ const CommandOutput &Output = FinishedCmd->getOutput();
+ StringRef DependenciesFile =
+ Output.getAdditionalOutputForType(types::TY_SwiftDeps);
+
+ if (DependenciesFile.empty()) {
+ // If this job doesn't track dependencies, it must always be run.
+ // Note: In theory CheckDependencies makes sense as well (for a leaf
+ // node in the dependency graph), and maybe even NewlyAdded (for very
+ // coarse dependencies that always affect downstream nodes), but we're
+ // not using either of those right now, and this logic should probably
+ // be revisited when we are.
+ assert(FinishedCmd->getCondition() == Job::Condition::Always);
+ } else {
+ // If we have a dependency file /and/ the frontend task exited normally,
+ // we can be discerning about what downstream files to rebuild.
+ if (ReturnCode == EXIT_SUCCESS || ReturnCode == EXIT_FAILURE) {
+ bool wasCascading = DepGraph.isMarked(FinishedCmd);
+
+ switch (DepGraph.loadFromPath(FinishedCmd, DependenciesFile)) {
+ case DependencyGraphImpl::LoadResult::HadError:
+ if (ReturnCode == EXIT_SUCCESS) {
+ dependencyLoadFailed(DependenciesFile);
+ Dependents.clear();
+ } // else, let the next build handle it.
+ break;
+ case DependencyGraphImpl::LoadResult::UpToDate:
+ if (!wasCascading)
+ break;
+ LLVM_FALLTHROUGH;
+ case DependencyGraphImpl::LoadResult::AffectsDownstream:
+ DepGraph.markTransitive(Dependents, FinishedCmd,
+ IncrementalTracer);
+ break;
+ }
+ } else {
+ // If there's an abnormal exit (a crash), assume the worst.
+ switch (FinishedCmd->getCondition()) {
+ case Job::Condition::NewlyAdded:
+ // The job won't be treated as newly added next time. Conservatively
+ // mark it as affecting other jobs, because some of them may have
+ // completed already.
+ DepGraph.markTransitive(Dependents, FinishedCmd,
+ IncrementalTracer);
+ break;
+ case Job::Condition::Always:
+ // Any incremental task that shows up here has already been marked;
+ // we didn't need to wait for it to finish to start downstream
+ // tasks.
+ assert(DepGraph.isMarked(FinishedCmd));
+ break;
+ case Job::Condition::RunWithoutCascading:
+ // If this file changed, it might have been a non-cascading change
+ // and it might not. Unfortunately, the interface hash has been
+ // updated or compromised, so we don't actually know anymore; we
+ // have to conservatively assume the changes could affect other
+ // files.
+ DepGraph.markTransitive(Dependents, FinishedCmd,
+ IncrementalTracer);
+ break;
+ case Job::Condition::CheckDependencies:
+ // If the only reason we're running this is because something else
+ // changed, then we can trust the dependency graph as to whether
+ // it's a cascading or non-cascading change. That is, if whatever
+ // /caused/ the error isn't supposed to affect other files, and
+ // whatever /fixes/ the error isn't supposed to affect other files,
+ // then there's no need to recompile any other inputs. If either of
+ // those are false, we /do/ need to recompile other inputs.
+ break;
+ }
+ }
+ }
+ }
+
+ /// Callback which will be called immediately after a task has finished
+ /// execution. Determines if execution should continue, and also schedule
+ /// any additional Jobs which we now know we need to run.
+ TaskFinishedResponse
+ taskFinished(ProcessId Pid, int ReturnCode, StringRef Output,
+ StringRef Errors, void *Context) {
+ const Job *FinishedCmd = (const Job *)Context;
+
+ if (Comp.ShowDriverTimeCompilation) {
+ DriverTimers[FinishedCmd]->stopTimer();
+ }
+
+ if (Comp.Level == OutputLevel::Parseable) {
+ // Parseable output was requested.
+ parseable_output::emitFinishedMessage(llvm::errs(), *FinishedCmd, Pid,
+ ReturnCode, Output);
+ } else {
+ // Otherwise, send the buffered output to stderr, though only if we
+ // support getting buffered output.
+ if (TaskQueue::supportsBufferingOutput())
+ llvm::errs() << Output;
+ }
+
+ // In order to handle both old dependencies that have disappeared and new
+ // dependencies that have arisen, we need to reload the dependency file.
+ // Do this whether or not the build succeeded.
+ SmallVector<const Job *, 16> Dependents;
+ if (Comp.getIncrementalBuildEnabled()) {
+ reloadAndRemarkDeps(FinishedCmd, ReturnCode, Dependents);
+ }
+
+ if (ReturnCode != EXIT_SUCCESS) {
+ // The task failed, so return true without performing any further
+ // dependency analysis.
+
+ // Store this task's ReturnCode as our Result if we haven't stored
+ // anything yet.
+ if (Result == EXIT_SUCCESS)
+ Result = ReturnCode;
+
+ if (!isa<CompileJobAction>(FinishedCmd->getSource()) ||
+ ReturnCode != EXIT_FAILURE) {
+ Comp.Diags.diagnose(SourceLoc(), diag::error_command_failed,
+ FinishedCmd->getSource().getClassName(),
+ ReturnCode);
+ }
+
+ return Comp.ContinueBuildingAfterErrors ?
+ TaskFinishedResponse::ContinueExecution :
+ TaskFinishedResponse::StopExecution;
+ }
+
+ // When a task finishes, we need to reevaluate the other commands that
+ // might have been blocked.
+ markFinished(FinishedCmd);
+
+ for (const Job *Cmd : Dependents) {
+ DeferredCommands.erase(Cmd);
+ noteBuilding(Cmd, "because of dependencies discovered later");
+ scheduleCommandIfNecessaryAndPossible(Cmd);
+ }
+
+ return TaskFinishedResponse::ContinueExecution;
+ }
+
+ TaskFinishedResponse
+ taskSignalled(ProcessId Pid, StringRef ErrorMsg, StringRef Output,
+ StringRef Errors, void *Context, Optional<int> Signal) {
+ const Job *SignalledCmd = (const Job *)Context;
+
+ if (Comp.ShowDriverTimeCompilation) {
+ DriverTimers[SignalledCmd]->stopTimer();
+ }
+
+ if (Comp.Level == OutputLevel::Parseable) {
+ // Parseable output was requested.
+ parseable_output::emitSignalledMessage(llvm::errs(), *SignalledCmd,
+ Pid, ErrorMsg, Output, Signal);
+ } else {
+ // Otherwise, send the buffered output to stderr, though only if we
+ // support getting buffered output.
+ if (TaskQueue::supportsBufferingOutput())
+ llvm::errs() << Output;
+ }
+
+ if (!ErrorMsg.empty())
+ Comp.Diags.diagnose(SourceLoc(), diag::error_unable_to_execute_command,
+ ErrorMsg);
+
+ if (Signal.hasValue()) {
+ Comp.Diags.diagnose(SourceLoc(), diag::error_command_signalled,
+ SignalledCmd->getSource().getClassName(),
+ Signal.getValue());
+ } else {
+ Comp.Diags.diagnose(SourceLoc(),
+ diag::error_command_signalled_without_signal_number,
+ SignalledCmd->getSource().getClassName());
+ }
+
+ // Since the task signalled, unconditionally set result to -2.
+ Result = -2;
+
+ return TaskFinishedResponse::StopExecution;
+ }
+
+ public:
+ PerformJobsState(Compilation &Comp) : Comp(Comp) {
+ if (Comp.SkipTaskExecution)
+ TQ.reset(new DummyTaskQueue(Comp.NumberOfParallelCommands));
+ else
+ TQ.reset(new TaskQueue(Comp.NumberOfParallelCommands));
+ if (Comp.ShowIncrementalBuildDecisions)
+ IncrementalTracer = &ActualIncrementalTracer;
+ }
+
+ /// Schedule all jobs we can from the initial list provided by Compilation.
+ void scheduleInitialJobs() {
+ for (const Job *Cmd : Comp.getJobs()) {
+ if (!Comp.getIncrementalBuildEnabled()) {
+ scheduleCommandIfNecessaryAndPossible(Cmd);
+ continue;
+ }
+
+ // Try to load the dependencies file for this job. If there isn't one, we
+ // always have to run the job, but it doesn't affect any other jobs. If
+ // there should be one but it's not present or can't be loaded, we have to
+ // run all the jobs.
+ // FIXME: We can probably do better here!
+ Job::Condition Condition = Job::Condition::Always;
+ StringRef DependenciesFile =
+ Cmd->getOutput().getAdditionalOutputForType(types::TY_SwiftDeps);
+ if (!DependenciesFile.empty()) {
+ if (Cmd->getCondition() == Job::Condition::NewlyAdded) {
+ DepGraph.addIndependentNode(Cmd);
+ } else {
+ switch (DepGraph.loadFromPath(Cmd, DependenciesFile)) {
+ case DependencyGraphImpl::LoadResult::HadError:
+ dependencyLoadFailed(DependenciesFile, /*Warn=*/false);
+ break;
+ case DependencyGraphImpl::LoadResult::UpToDate:
+ Condition = Cmd->getCondition();
+ break;
+ case DependencyGraphImpl::LoadResult::AffectsDownstream:
+ llvm_unreachable("we haven't marked anything in this graph yet");
+ }
+ }
+ }
+
+ switch (Condition) {
+ case Job::Condition::Always:
+ if (Comp.getIncrementalBuildEnabled() && !DependenciesFile.empty()) {
+ InitialOutOfDateCommands.push_back(Cmd);
+ DepGraph.markIntransitive(Cmd);
+ }
+ LLVM_FALLTHROUGH;
+ case Job::Condition::RunWithoutCascading:
+ noteBuilding(Cmd, "(initial)");
+ scheduleCommandIfNecessaryAndPossible(Cmd);
+ break;
+ case Job::Condition::CheckDependencies:
+ DeferredCommands.insert(Cmd);
+ break;
+ case Job::Condition::NewlyAdded:
+ llvm_unreachable("handled above");
+ }
+ }
+ }
+
+ /// Schedule transitive closure of initial jobs, and external jobs.
+ void scheduleAdditionalJobs() {
+ if (Comp.getIncrementalBuildEnabled()) {
+ SmallVector<const Job *, 16> AdditionalOutOfDateCommands;
+
+ // We scheduled all of the files that have actually changed. Now add the
+ // files that haven't changed, so that they'll get built in parallel if
+ // possible and after the first set of files if it's not.
+ for (auto *Cmd : InitialOutOfDateCommands) {
+ DepGraph.markTransitive(AdditionalOutOfDateCommands, Cmd,
+ IncrementalTracer);
+ }
+
+ for (auto *transitiveCmd : AdditionalOutOfDateCommands)
+ noteBuilding(transitiveCmd, "because of the initial set");
+ size_t firstSize = AdditionalOutOfDateCommands.size();
+
+ // Check all cross-module dependencies as well.
+ for (StringRef dependency : DepGraph.getExternalDependencies()) {
+ llvm::sys::fs::file_status depStatus;
+ if (!llvm::sys::fs::status(dependency, depStatus))
+ if (depStatus.getLastModificationTime() < Comp.LastBuildTime)
+ continue;
+
+ // If the dependency has been modified since the oldest built file,
+ // or if we can't stat it for some reason (perhaps it's been deleted?),
+ // trigger rebuilds through the dependency graph.
+ DepGraph.markExternal(AdditionalOutOfDateCommands, dependency);
+ }
+
+ for (auto *externalCmd :
+ llvm::makeArrayRef(AdditionalOutOfDateCommands).slice(firstSize)) {
+ noteBuilding(externalCmd, "because of external dependencies");
+ }
+
+ for (auto *AdditionalCmd : AdditionalOutOfDateCommands) {
+ if (!DeferredCommands.count(AdditionalCmd))
+ continue;
+ scheduleCommandIfNecessaryAndPossible(AdditionalCmd);
+ DeferredCommands.erase(AdditionalCmd);
+ }
+ }
+ }
+
+ void runTaskQueueToCompletion() {
+ do {
+ using namespace std::placeholders;
+ // Ask the TaskQueue to execute.
+ TQ->execute(std::bind(&PerformJobsState::taskBegan, this,
+ _1, _2),
+ std::bind(&PerformJobsState::taskFinished, this,
+ _1, _2, _3, _4, _5),
+ std::bind(&PerformJobsState::taskSignalled, this,
+ _1, _2, _3, _4, _5, _6));
+
+ // Mark all remaining deferred commands as skipped.
+ for (const Job *Cmd : DeferredCommands) {
+ if (Comp.Level == OutputLevel::Parseable) {
+ // Provide output indicating this command was skipped if parseable output
+ // was requested.
+ parseable_output::emitSkippedMessage(llvm::errs(), *Cmd);
+ }
+
+ ScheduledCommands.insert(Cmd);
+ markFinished(Cmd, /*Skipped=*/true);
+ }
+ DeferredCommands.clear();
+
+ // ...which may allow us to go on and do later tasks.
+ } while (Result == 0 && TQ->hasRemainingTasks());
+ }
+
+ void checkUnfinishedJobs() {
+ if (Result == 0) {
+ assert(BlockingCommands.empty() &&
+ "some blocking commands never finished properly");
+ } else {
+ // Make sure we record any files that still need to be rebuilt.
+ for (const Job *Cmd : Comp.getJobs()) {
+ // Skip files that don't use dependency analysis.
+ StringRef DependenciesFile =
+ Cmd->getOutput().getAdditionalOutputForType(types::TY_SwiftDeps);
+ if (DependenciesFile.empty())
+ continue;
+
+ // Don't worry about commands that finished or weren't going to run.
+ if (FinishedCommands.count(Cmd))
+ continue;
+ if (!ScheduledCommands.count(Cmd))
+ continue;
+
+ bool isCascading = true;
+ if (Comp.getIncrementalBuildEnabled())
+ isCascading = DepGraph.isMarked(Cmd);
+ UnfinishedCommands.insert({Cmd, isCascading});
+ }
+ }
+ }
+
+ void populateInputInfoMap(InputInfoMap &inputs) const {
+ for (auto &entry : UnfinishedCommands) {
+ for (auto *action : entry.first->getSource().getInputs()) {
+ auto inputFile = dyn_cast<InputAction>(action);
+ if (!inputFile)
+ continue;
+
+ CompileJobAction::InputInfo info;
+ info.previousModTime = entry.first->getInputModTime();
+ info.status = entry.second ?
+ CompileJobAction::InputInfo::NeedsCascadingBuild :
+ CompileJobAction::InputInfo::NeedsNonCascadingBuild;
+ inputs[&inputFile->getInputArg()] = info;
+ }
+ }
+
+ for (const Job *entry : FinishedCommands) {
+ const auto *compileAction = dyn_cast<CompileJobAction>(&entry->getSource());
+ if (!compileAction)
+ continue;
+
+ for (auto *action : compileAction->getInputs()) {
+ auto inputFile = dyn_cast<InputAction>(action);
+ if (!inputFile)
+ continue;
+
+ CompileJobAction::InputInfo info;
+ info.previousModTime = entry->getInputModTime();
+ info.status = CompileJobAction::InputInfo::UpToDate;
+ inputs[&inputFile->getInputArg()] = info;
+ }
+ }
+
+ // Sort the entries by input order.
+ static_assert(IsTriviallyCopyable<CompileJobAction::InputInfo>::value,
+ "llvm::array_pod_sort relies on trivially-copyable data");
+ using InputInfoEntry = std::decay<decltype(inputs.front())>::type;
+ llvm::array_pod_sort(inputs.begin(), inputs.end(),
+ [](const InputInfoEntry *lhs,
+ const InputInfoEntry *rhs) -> int {
+ auto lhsIndex = lhs->first->getIndex();
+ auto rhsIndex = rhs->first->getIndex();
+ return (lhsIndex < rhsIndex) ? -1 : (lhsIndex > rhsIndex) ? 1 : 0;
+ });
+ }
+
+ int getResult() {
+ if (Result == 0)
+ Result = Comp.Diags.hadAnyError();
+ return Result;
+ }
};
-} // end anonymous namespace
+} // driver
+} // swift
Compilation::~Compilation() = default;
@@ -100,64 +690,6 @@
return result;
}
-static const Job *findUnfinishedJob(ArrayRef<const Job *> JL,
- const CommandSet &FinishedCommands) {
- for (const Job *Cmd : JL) {
- if (!FinishedCommands.count(Cmd))
- return Cmd;
- }
- return nullptr;
-}
-
-using InputInfoMap =
- llvm::SmallMapVector<const llvm::opt::Arg *, CompileJobAction::InputInfo, 16>;
-
-static void populateInputInfoMap(InputInfoMap &inputs,
- const PerformJobsState &endState) {
- for (auto &entry : endState.UnfinishedCommands) {
- for (auto *action : entry.first->getSource().getInputs()) {
- auto inputFile = dyn_cast<InputAction>(action);
- if (!inputFile)
- continue;
-
- CompileJobAction::InputInfo info;
- info.previousModTime = entry.first->getInputModTime();
- info.status = entry.second ?
- CompileJobAction::InputInfo::NeedsCascadingBuild :
- CompileJobAction::InputInfo::NeedsNonCascadingBuild;
- inputs[&inputFile->getInputArg()] = info;
- }
- }
-
- for (const Job *entry : endState.FinishedCommands) {
- const auto *compileAction = dyn_cast<CompileJobAction>(&entry->getSource());
- if (!compileAction)
- continue;
-
- for (auto *action : compileAction->getInputs()) {
- auto inputFile = dyn_cast<InputAction>(action);
- if (!inputFile)
- continue;
-
- CompileJobAction::InputInfo info;
- info.previousModTime = entry->getInputModTime();
- info.status = CompileJobAction::InputInfo::UpToDate;
- inputs[&inputFile->getInputArg()] = info;
- }
- }
-
- // Sort the entries by input order.
- static_assert(IsTriviallyCopyable<CompileJobAction::InputInfo>::value,
- "llvm::array_pod_sort relies on trivially-copyable data");
- using InputInfoEntry = std::decay<decltype(inputs.front())>::type;
- llvm::array_pod_sort(inputs.begin(), inputs.end(),
- [](const InputInfoEntry *lhs,
- const InputInfoEntry *rhs) -> int {
- auto lhsIndex = lhs->first->getIndex();
- auto rhsIndex = rhs->first->getIndex();
- return (lhsIndex < rhsIndex) ? -1 : (lhsIndex > rhsIndex) ? 1 : 0;
- });
-}
static void checkForOutOfDateInputs(DiagnosticEngine &diags,
const InputInfoMap &inputs) {
@@ -274,448 +806,23 @@
}
int Compilation::performJobsImpl() {
- // Create a TaskQueue for execution.
- std::unique_ptr<TaskQueue> TQ;
- if (SkipTaskExecution)
- TQ.reset(new DummyTaskQueue(NumberOfParallelCommands));
- else
- TQ.reset(new TaskQueue(NumberOfParallelCommands));
- PerformJobsState State;
+ PerformJobsState State(*this);
- using DependencyGraph = DependencyGraph<const Job *>;
- DependencyGraph DepGraph;
- SmallPtrSet<const Job *, 16> DeferredCommands;
- SmallVector<const Job *, 16> InitialOutOfDateCommands;
-
- DependencyGraph::MarkTracer ActualIncrementalTracer;
- DependencyGraph::MarkTracer *IncrementalTracer = nullptr;
- if (ShowIncrementalBuildDecisions)
- IncrementalTracer = &ActualIncrementalTracer;
-
- auto noteBuilding = [&] (const Job *cmd, StringRef reason) {
- if (!ShowIncrementalBuildDecisions)
- return;
- if (State.ScheduledCommands.count(cmd))
- return;
- llvm::outs() << "Queuing "
- << llvm::sys::path::filename(cmd->getOutput().getBaseInput(0))
- << " " << reason << "\n";
- IncrementalTracer->printPath(llvm::outs(), cmd,
- [](raw_ostream &out, const Job *base) {
- out << llvm::sys::path::filename(base->getOutput().getBaseInput(0));
- });
- };
-
- // Set up scheduleCommandIfNecessaryAndPossible.
- // This will only schedule the given command if it has not been scheduled
- // and if all of its inputs are in FinishedCommands.
- auto scheduleCommandIfNecessaryAndPossible = [&] (const Job *Cmd) {
- if (State.ScheduledCommands.count(Cmd))
- return;
-
- if (auto Blocking = findUnfinishedJob(Cmd->getInputs(),
- State.FinishedCommands)) {
- State.BlockingCommands[Blocking].push_back(Cmd);
- return;
- }
-
- // FIXME: Failing here should not take down the whole process.
- bool success = writeFilelistIfNecessary(Cmd, Diags);
- assert(success && "failed to write filelist");
- (void)success;
-
- assert(Cmd->getExtraEnvironment().empty() &&
- "not implemented for compilations with multiple jobs");
- State.ScheduledCommands.insert(Cmd);
- TQ->addTask(Cmd->getExecutable(), Cmd->getArguments(), llvm::None,
- (void *)Cmd);
- };
-
- // When a task finishes, we need to reevaluate the other commands that
- // might have been blocked.
- auto markFinished = [&] (const Job *Cmd) {
- State.FinishedCommands.insert(Cmd);
-
- auto BlockedIter = State.BlockingCommands.find(Cmd);
- if (BlockedIter != State.BlockingCommands.end()) {
- auto AllBlocked = std::move(BlockedIter->second);
- State.BlockingCommands.erase(BlockedIter);
- for (auto *Blocked : AllBlocked)
- scheduleCommandIfNecessaryAndPossible(Blocked);
- }
- };
-
- // Schedule all jobs we can.
- for (const Job *Cmd : getJobs()) {
- if (!getIncrementalBuildEnabled()) {
- scheduleCommandIfNecessaryAndPossible(Cmd);
- continue;
- }
-
- // Try to load the dependencies file for this job. If there isn't one, we
- // always have to run the job, but it doesn't affect any other jobs. If
- // there should be one but it's not present or can't be loaded, we have to
- // run all the jobs.
- // FIXME: We can probably do better here!
- Job::Condition Condition = Job::Condition::Always;
- StringRef DependenciesFile =
- Cmd->getOutput().getAdditionalOutputForType(types::TY_SwiftDeps);
- if (!DependenciesFile.empty()) {
- if (Cmd->getCondition() == Job::Condition::NewlyAdded) {
- DepGraph.addIndependentNode(Cmd);
- } else {
- switch (DepGraph.loadFromPath(Cmd, DependenciesFile)) {
- case DependencyGraphImpl::LoadResult::HadError:
- disableIncrementalBuild();
- for (const Job *Cmd : DeferredCommands)
- scheduleCommandIfNecessaryAndPossible(Cmd);
- DeferredCommands.clear();
- break;
- case DependencyGraphImpl::LoadResult::UpToDate:
- Condition = Cmd->getCondition();
- break;
- case DependencyGraphImpl::LoadResult::AffectsDownstream:
- llvm_unreachable("we haven't marked anything in this graph yet");
- }
- }
- }
-
- switch (Condition) {
- case Job::Condition::Always:
- if (getIncrementalBuildEnabled() && !DependenciesFile.empty()) {
- InitialOutOfDateCommands.push_back(Cmd);
- DepGraph.markIntransitive(Cmd);
- }
- LLVM_FALLTHROUGH;
- case Job::Condition::RunWithoutCascading:
- noteBuilding(Cmd, "(initial)");
- scheduleCommandIfNecessaryAndPossible(Cmd);
- break;
- case Job::Condition::CheckDependencies:
- DeferredCommands.insert(Cmd);
- break;
- case Job::Condition::NewlyAdded:
- llvm_unreachable("handled above");
- }
- }
-
- if (getIncrementalBuildEnabled()) {
- SmallVector<const Job *, 16> AdditionalOutOfDateCommands;
-
- // We scheduled all of the files that have actually changed. Now add the
- // files that haven't changed, so that they'll get built in parallel if
- // possible and after the first set of files if it's not.
- for (auto *Cmd : InitialOutOfDateCommands) {
- DepGraph.markTransitive(AdditionalOutOfDateCommands, Cmd,
- IncrementalTracer);
- }
-
- for (auto *transitiveCmd : AdditionalOutOfDateCommands)
- noteBuilding(transitiveCmd, "because of the initial set:");
- size_t firstSize = AdditionalOutOfDateCommands.size();
-
- // Check all cross-module dependencies as well.
- for (StringRef dependency : DepGraph.getExternalDependencies()) {
- llvm::sys::fs::file_status depStatus;
- if (!llvm::sys::fs::status(dependency, depStatus))
- if (depStatus.getLastModificationTime() < LastBuildTime)
- continue;
-
- // If the dependency has been modified since the oldest built file,
- // or if we can't stat it for some reason (perhaps it's been deleted?),
- // trigger rebuilds through the dependency graph.
- DepGraph.markExternal(AdditionalOutOfDateCommands, dependency);
- }
-
- for (auto *externalCmd :
- llvm::makeArrayRef(AdditionalOutOfDateCommands).slice(firstSize)) {
- noteBuilding(externalCmd, "because of external dependencies");
- }
-
- for (auto *AdditionalCmd : AdditionalOutOfDateCommands) {
- if (!DeferredCommands.count(AdditionalCmd))
- continue;
- scheduleCommandIfNecessaryAndPossible(AdditionalCmd);
- DeferredCommands.erase(AdditionalCmd);
- }
- }
-
- int Result = EXIT_SUCCESS;
- llvm::TimerGroup DriverTimerGroup("driver", "Driver Compilation Time");
- llvm::SmallDenseMap<const Job *, std::unique_ptr<llvm::Timer>, 16>
- DriverTimers;
-
- // Set up a callback which will be called immediately after a task has
- // started. This callback may be used to provide output indicating that the
- // task began.
- auto taskBegan = [&] (ProcessId Pid, void *Context) {
- // TODO: properly handle task began.
- const Job *BeganCmd = (const Job *)Context;
-
- if (ShowDriverTimeCompilation) {
- llvm::SmallString<128> TimerName;
- llvm::raw_svector_ostream OS(TimerName);
-
- OS << BeganCmd->getSource().getClassName();
- for (auto A : BeganCmd->getSource().getInputs()) {
- if (const InputAction *IA = dyn_cast<InputAction>(A)) {
- OS << " " << IA->getInputArg().getValue();
- }
- }
- for (auto J : BeganCmd->getInputs()) {
- for (auto A : J->getSource().getInputs()) {
- if (const InputAction *IA = dyn_cast<InputAction>(A)) {
- OS << " " << IA->getInputArg().getValue();
- }
- }
- }
-
- DriverTimers.insert({
- BeganCmd,
- std::unique_ptr<llvm::Timer>(
- new llvm::Timer("task", OS.str(), DriverTimerGroup))
- });
- DriverTimers[BeganCmd]->startTimer();
- }
-
- // For verbose output, print out each command as it begins execution.
- if (Level == OutputLevel::Verbose)
- BeganCmd->printCommandLine(llvm::errs());
- else if (Level == OutputLevel::Parseable)
- parseable_output::emitBeganMessage(llvm::errs(), *BeganCmd, Pid);
- };
-
- // Set up a callback which will be called immediately after a task has
- // finished execution. This callback should determine if execution should
- // continue (if execution should stop, this callback should return true), and
- // it should also schedule any additional commands which we now know need
- // to run.
- auto taskFinished = [&](ProcessId Pid, int ReturnCode, StringRef Output,
- StringRef Errors,
- void *Context) -> TaskFinishedResponse {
- const Job *FinishedCmd = (const Job *)Context;
-
- if (ShowDriverTimeCompilation) {
- DriverTimers[FinishedCmd]->stopTimer();
- }
-
- if (Level == OutputLevel::Parseable) {
- // Parseable output was requested.
- parseable_output::emitFinishedMessage(llvm::errs(), *FinishedCmd, Pid,
- ReturnCode, Output);
- } else {
- // Otherwise, send the buffered output to stderr, though only if we
- // support getting buffered output.
- if (TaskQueue::supportsBufferingOutput())
- llvm::errs() << Output;
- }
-
- // In order to handle both old dependencies that have disappeared and new
- // dependencies that have arisen, we need to reload the dependency file.
- // Do this whether or not the build succeeded.
- SmallVector<const Job *, 16> Dependents;
- if (getIncrementalBuildEnabled()) {
- const CommandOutput &Output = FinishedCmd->getOutput();
- StringRef DependenciesFile =
- Output.getAdditionalOutputForType(types::TY_SwiftDeps);
-
- if (DependenciesFile.empty()) {
- // If this job doesn't track dependencies, it must always be run.
- // Note: In theory CheckDependencies makes sense as well (for a leaf
- // node in the dependency graph), and maybe even NewlyAdded (for very
- // coarse dependencies that always affect downstream nodes), but we're
- // not using either of those right now, and this logic should probably
- // be revisited when we are.
- assert(FinishedCmd->getCondition() == Job::Condition::Always);
- } else {
- // If we have a dependency file /and/ the frontend task exited normally,
- // we can be discerning about what downstream files to rebuild.
- if (ReturnCode == EXIT_SUCCESS || ReturnCode == EXIT_FAILURE) {
- bool wasCascading = DepGraph.isMarked(FinishedCmd);
-
- switch (DepGraph.loadFromPath(FinishedCmd, DependenciesFile)) {
- case DependencyGraphImpl::LoadResult::HadError:
- if (ReturnCode == EXIT_SUCCESS) {
- disableIncrementalBuild();
- for (const Job *Cmd : DeferredCommands)
- scheduleCommandIfNecessaryAndPossible(Cmd);
- DeferredCommands.clear();
- Dependents.clear();
- } // else, let the next build handle it.
- break;
- case DependencyGraphImpl::LoadResult::UpToDate:
- if (!wasCascading)
- break;
- LLVM_FALLTHROUGH;
- case DependencyGraphImpl::LoadResult::AffectsDownstream:
- DepGraph.markTransitive(Dependents, FinishedCmd);
- break;
- }
- } else {
- // If there's an abnormal exit (a crash), assume the worst.
- switch (FinishedCmd->getCondition()) {
- case Job::Condition::NewlyAdded:
- // The job won't be treated as newly added next time. Conservatively
- // mark it as affecting other jobs, because some of them may have
- // completed already.
- DepGraph.markTransitive(Dependents, FinishedCmd);
- break;
- case Job::Condition::Always:
- // Any incremental task that shows up here has already been marked;
- // we didn't need to wait for it to finish to start downstream
- // tasks.
- assert(DepGraph.isMarked(FinishedCmd));
- break;
- case Job::Condition::RunWithoutCascading:
- // If this file changed, it might have been a non-cascading change
- // and it might not. Unfortunately, the interface hash has been
- // updated or compromised, so we don't actually know anymore; we
- // have to conservatively assume the changes could affect other
- // files.
- DepGraph.markTransitive(Dependents, FinishedCmd);
- break;
- case Job::Condition::CheckDependencies:
- // If the only reason we're running this is because something else
- // changed, then we can trust the dependency graph as to whether
- // it's a cascading or non-cascading change. That is, if whatever
- // /caused/ the error isn't supposed to affect other files, and
- // whatever /fixes/ the error isn't supposed to affect other files,
- // then there's no need to recompile any other inputs. If either of
- // those are false, we /do/ need to recompile other inputs.
- break;
- }
- }
- }
- }
-
- if (ReturnCode != EXIT_SUCCESS) {
- // The task failed, so return true without performing any further
- // dependency analysis.
-
- // Store this task's ReturnCode as our Result if we haven't stored
- // anything yet.
- if (Result == EXIT_SUCCESS)
- Result = ReturnCode;
-
- if (!isa<CompileJobAction>(FinishedCmd->getSource()) ||
- ReturnCode != EXIT_FAILURE) {
- Diags.diagnose(SourceLoc(), diag::error_command_failed,
- FinishedCmd->getSource().getClassName(),
- ReturnCode);
- }
-
- return ContinueBuildingAfterErrors ?
- TaskFinishedResponse::ContinueExecution :
- TaskFinishedResponse::StopExecution;
- }
-
- // When a task finishes, we need to reevaluate the other commands that
- // might have been blocked.
- markFinished(FinishedCmd);
-
- for (const Job *Cmd : Dependents) {
- DeferredCommands.erase(Cmd);
- noteBuilding(Cmd, "because of dependencies discovered later");
- scheduleCommandIfNecessaryAndPossible(Cmd);
- }
-
- return TaskFinishedResponse::ContinueExecution;
- };
-
- auto taskSignalled = [&](ProcessId Pid, StringRef ErrorMsg, StringRef Output,
- StringRef Errors,
- void *Context, Optional<int> Signal) -> TaskFinishedResponse {
- const Job *SignalledCmd = (const Job *)Context;
-
- if (ShowDriverTimeCompilation) {
- DriverTimers[SignalledCmd]->stopTimer();
- }
-
- if (Level == OutputLevel::Parseable) {
- // Parseable output was requested.
- parseable_output::emitSignalledMessage(llvm::errs(), *SignalledCmd, Pid,
- ErrorMsg, Output, Signal);
- } else {
- // Otherwise, send the buffered output to stderr, though only if we
- // support getting buffered output.
- if (TaskQueue::supportsBufferingOutput())
- llvm::errs() << Output;
- }
-
- if (!ErrorMsg.empty())
- Diags.diagnose(SourceLoc(), diag::error_unable_to_execute_command,
- ErrorMsg);
-
- if (Signal.hasValue()) {
- Diags.diagnose(SourceLoc(), diag::error_command_signalled,
- SignalledCmd->getSource().getClassName(), Signal.getValue());
- } else {
- Diags.diagnose(SourceLoc(), diag::error_command_signalled_without_signal_number,
- SignalledCmd->getSource().getClassName());
- }
-
- // Since the task signalled, unconditionally set result to -2.
- Result = -2;
-
- return TaskFinishedResponse::StopExecution;
- };
-
- do {
- // Ask the TaskQueue to execute.
- TQ->execute(taskBegan, taskFinished, taskSignalled);
-
- // Mark all remaining deferred commands as skipped.
- for (const Job *Cmd : DeferredCommands) {
- if (Level == OutputLevel::Parseable) {
- // Provide output indicating this command was skipped if parseable output
- // was requested.
- parseable_output::emitSkippedMessage(llvm::errs(), *Cmd);
- }
-
- State.ScheduledCommands.insert(Cmd);
- markFinished(Cmd);
- }
-
- // ...which may allow us to go on and do later tasks.
- } while (Result == 0 && TQ->hasRemainingTasks());
-
- if (Result == 0) {
- assert(State.BlockingCommands.empty() &&
- "some blocking commands never finished properly");
- } else {
- // Make sure we record any files that still need to be rebuilt.
- for (const Job *Cmd : getJobs()) {
- // Skip files that don't use dependency analysis.
- StringRef DependenciesFile =
- Cmd->getOutput().getAdditionalOutputForType(types::TY_SwiftDeps);
- if (DependenciesFile.empty())
- continue;
-
- // Don't worry about commands that finished or weren't going to run.
- if (State.FinishedCommands.count(Cmd))
- continue;
- if (!State.ScheduledCommands.count(Cmd))
- continue;
-
- bool isCascading = true;
- if (getIncrementalBuildEnabled())
- isCascading = DepGraph.isMarked(Cmd);
- State.UnfinishedCommands.insert({Cmd, isCascading});
- }
- }
+ State.scheduleInitialJobs();
+ State.scheduleAdditionalJobs();
+ State.runTaskQueueToCompletion();
+ State.checkUnfinishedJobs();
if (!CompilationRecordPath.empty() && !SkipTaskExecution) {
InputInfoMap InputInfo;
- populateInputInfoMap(InputInfo, State);
+ State.populateInputInfoMap(InputInfo);
checkForOutOfDateInputs(Diags, InputInfo);
writeCompilationRecord(CompilationRecordPath, ArgsHash, BuildStartTime,
InputInfo);
}
- if (Result == 0)
- Result = Diags.hadAnyError();
- return Result;
+ return State.getResult();
}
int Compilation::performSingleCommand(const Job *Cmd) {
diff --git a/lib/Driver/DependencyGraph.cpp b/lib/Driver/DependencyGraph.cpp
index 1b321eb..6db9006 100644
--- a/lib/Driver/DependencyGraph.cpp
+++ b/lib/Driver/DependencyGraph.cpp
@@ -425,10 +425,15 @@
}
StringRef memberPart = name.str().substr(splitPoint+1);
- out << " provides member '" << memberPart << "' of type '"
- << swift::Demangle::demangleTypeAsString(typePart)
- << "'\n";
-
+ if (memberPart.empty()) {
+ out << " provides non-private members of type '"
+ << swift::Demangle::demangleTypeAsString(typePart)
+ << "'\n";
+ } else {
+ out << " provides member '" << memberPart << "' of type '"
+ << swift::Demangle::demangleTypeAsString(typePart)
+ << "'\n";
+ }
} else if (entry.KindMask.contains(DependencyKind::DynamicLookupName)) {
out << " provides AnyObject member '" << entry.Name << "'\n";
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 3990de9..525b511 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -470,6 +470,8 @@
ArgList->hasArg(options::OPT_driver_skip_execution);
bool ShowIncrementalBuildDecisions =
ArgList->hasArg(options::OPT_driver_show_incremental);
+ bool ShowJobLifecycle =
+ ArgList->hasArg(options::OPT_driver_show_job_lifecycle);
bool Incremental = ArgList->hasArg(options::OPT_incremental);
if (ArgList->hasArg(options::OPT_whole_module_optimization)) {
@@ -642,9 +644,12 @@
ContinueBuildingAfterErrors)
C->setContinueBuildingAfterErrors();
- if (ShowIncrementalBuildDecisions)
+ if (ShowIncrementalBuildDecisions || ShowJobLifecycle)
C->setShowsIncrementalBuildDecisions();
+ if (ShowJobLifecycle)
+ C->setShowJobLifecycle();
+
// This has to happen after building jobs, because otherwise we won't even
// emit .swiftdeps files for the next build.
if (rebuildEverything)
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index 10733cf..d4a8beb 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -13,7 +13,9 @@
#include "swift/Basic/STLExtras.h"
#include "swift/Driver/Job.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Option/Arg.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
@@ -106,3 +108,42 @@
printArguments(os, Arguments);
os << Terminator;
}
+
+void Job::printSummary(raw_ostream &os) const {
+ // Deciding how to describe our inputs is a bit subtle; if we are a Job built
+ // from a JobAction that itself has InputActions sources, then we collect
+ // those up. Otherwise it's more correct to talk about our inputs as the
+ // outputs of our input-jobs.
+ SmallVector<std::string, 4> Inputs;
+
+ for (const Action *A : getSource().getInputs())
+ if (const InputAction *IA = dyn_cast<InputAction>(A))
+ Inputs.push_back(IA->getInputArg().getValue());
+
+ for (const Job *J : getInputs())
+ for (const std::string &f : J->getOutput().getPrimaryOutputFilenames())
+ Inputs.push_back(f);
+
+ size_t limit = 3;
+ size_t actual = Inputs.size();
+ if (actual > limit) {
+ Inputs.erase(Inputs.begin() + limit, Inputs.end());
+ }
+
+ os << "{" << getSource().getClassName() << ": ";
+ interleave(getOutput().getPrimaryOutputFilenames(),
+ [&](const std::string &Arg) {
+ os << llvm::sys::path::filename(Arg);
+ },
+ [&] { os << ' '; });
+ os << " <= ";
+ interleave(Inputs,
+ [&](const std::string &Arg) {
+ os << llvm::sys::path::filename(Arg);
+ },
+ [&] { os << ' '; });
+ if (actual > limit) {
+ os << " ... " << (actual-limit) << " more";
+ }
+ os << "}";
+}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 6fbb2a2..49c09b0 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -802,7 +802,7 @@
// Check for an unneeded minor version, otherwise just list valid versions
if (vers.hasValue() && !vers.getValue().empty() &&
- vers.getValue().asMajorVersion().isValidEffectiveLanguageVersion()) {
+ vers.getValue().asMajorVersion().getEffectiveLanguageVersion()) {
diags.diagnose(SourceLoc(), diag::note_swift_version_major,
vers.getValue()[0]);
} else {
@@ -822,12 +822,15 @@
if (auto A = Args.getLastArg(OPT_swift_version)) {
auto vers = version::Version::parseVersionString(
A->getValue(), SourceLoc(), &Diags);
- if (vers.hasValue() &&
- vers.getValue().isValidEffectiveLanguageVersion()) {
- Opts.EffectiveLanguageVersion = vers.getValue();
- } else {
- diagnoseSwiftVersion(vers, A, Args, Diags);
+ bool isValid = false;
+ if (vers.hasValue()) {
+ if (auto effectiveVers = vers.getValue().getEffectiveLanguageVersion()) {
+ Opts.EffectiveLanguageVersion = effectiveVers.getValue();
+ isValid = true;
+ }
}
+ if (!isValid)
+ diagnoseSwiftVersion(vers, A, Args, Diags);
}
Opts.AttachCommentsToDecls |= Args.hasArg(OPT_dump_api_path);
diff --git a/lib/IRGen/DebugTypeInfo.cpp b/lib/IRGen/DebugTypeInfo.cpp
index 551ea82..98f1546 100644
--- a/lib/IRGen/DebugTypeInfo.cpp
+++ b/lib/IRGen/DebugTypeInfo.cpp
@@ -50,16 +50,15 @@
Info.getBestKnownAlignment());
}
-DebugTypeInfo DebugTypeInfo::getLocalVariable(DeclContext *DeclCtx,
+DebugTypeInfo DebugTypeInfo::getLocalVariable(DeclContext *DC,
VarDecl *Decl, swift::Type Ty,
const TypeInfo &Info,
bool Unwrap) {
- auto DeclType = Ty;
- if (DeclCtx)
- DeclType = (Decl->hasType()
- ? Decl->getType()
- : DeclCtx->mapTypeIntoContext(Decl->getInterfaceType()));
+ auto DeclType = (Decl->hasType()
+ ? Decl->getType()
+ : Decl->getDeclContext()->mapTypeIntoContext(
+ Decl->getInterfaceType()));
auto RealType = Ty;
if (Unwrap) {
DeclType = DeclType->getInOutObjectType();
@@ -75,7 +74,7 @@
// the type hasn't been mucked with by an optimization pass.
auto *Type = DeclSelfType->isEqual(RealType) ? DeclType.getPointer()
: RealType.getPointer();
- return getFromTypeInfo(DeclCtx, Type, Info);
+ return getFromTypeInfo(DC, Type, Info);
}
DebugTypeInfo DebugTypeInfo::getMetadata(swift::Type Ty, llvm::Type *StorageTy,
diff --git a/lib/IRGen/DebugTypeInfo.h b/lib/IRGen/DebugTypeInfo.h
index 87d389e..dc398e8 100644
--- a/lib/IRGen/DebugTypeInfo.h
+++ b/lib/IRGen/DebugTypeInfo.h
@@ -37,7 +37,8 @@
/// for a type.
class DebugTypeInfo {
public:
- /// The DeclContext if this is has an Archetype.
+ /// The DeclContext of the function. This might not be the DeclContext of
+ /// the variable if inlining took place.
DeclContext *DeclCtx;
/// The type we need to emit may be different from the type
/// mentioned in the Decl, for example, stripped of qualifiers.
diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp
index 8fc2a0c..88aa338 100644
--- a/lib/IRGen/GenArchetype.cpp
+++ b/lib/IRGen/GenArchetype.cpp
@@ -74,49 +74,70 @@
return metadata;
}
-static bool declaresDirectConformance(AssociatedTypeDecl *associatedType,
- ProtocolDecl *target) {
- for (auto protocol : associatedType->getConformingProtocols()) {
- if (protocol == target)
- return true;
- }
- return false;
+namespace {
+ struct ConformancePath {
+ CanArchetypeType ParentArchetype;
+ ProtocolDecl *ParentProtocol;
+ CanType Path;
+ };
}
-static AssociatedTypeDecl *
-findConformanceDeclaration(ArrayRef<ProtocolDecl*> conformsTo,
- AssociatedTypeDecl *associatedType,
- ProtocolDecl *target) {
- // Fast path: this associated type declaration declares the
- // desired conformance.
- if (declaresDirectConformance(associatedType, target))
- return associatedType;
-
- // Otherwise, look at the conformance list.
- for (auto source : conformsTo) {
- // Do a lookup in this protocol.
- auto results = source->lookupDirect(associatedType->getFullName());
- for (auto lookupResult: results) {
- if (auto sourceAssociatedType =
- dyn_cast<AssociatedTypeDecl>(lookupResult)) {
- if (declaresDirectConformance(sourceAssociatedType, target))
- return sourceAssociatedType;
+static Optional<ConformancePath>
+declaresDirectConformance(ProtocolDecl *source,
+ AssociatedTypeDecl *associatedType,
+ ProtocolDecl *target) {
+ for (auto &reqt : source->getRequirementSignature()->getRequirements()) {
+ if (reqt.getKind() != RequirementKind::Conformance)
+ continue;
+ if (reqt.getSecondType()->castTo<ProtocolType>()->getDecl() != target)
+ continue;
+ auto path = reqt.getFirstType()->getCanonicalType();
+ if (auto memberType = dyn_cast<DependentMemberType>(path)) {
+ if (isa<GenericTypeParamType>(memberType.getBase())) {
+ assert(memberType.getBase()->isEqual(source->getSelfInterfaceType()));
+ if (memberType->getName() == associatedType->getName())
+ return ConformancePath{ CanArchetypeType(), source, path };
}
}
+ }
+ return None;
+}
+
+static Optional<ConformancePath>
+findConformanceRecursive(ArrayRef<ProtocolDecl*> conformsTo,
+ AssociatedTypeDecl *associatedType,
+ ProtocolDecl *target) {
+ for (auto source : conformsTo) {
+ // Check the protocol directly.
+ if (source != associatedType->getProtocol())
+ if (auto result = declaresDirectConformance(source, associatedType,
+ target))
+ return result;
// Recurse into implied protocols.
- if (auto result =
- findConformanceDeclaration(source->getInheritedProtocols(),
- associatedType, target)) {
+ if (auto result = findConformanceRecursive(source->getInheritedProtocols(),
+ associatedType, target))
return result;
- }
}
// Give up.
- return nullptr;
+ return None;
}
-static IRGenFunction::ArchetypeAccessPath
+static Optional<ConformancePath>
+findConformanceDeclaration(ArrayRef<ProtocolDecl*> conformsTo,
+ AssociatedTypeDecl *associatedType,
+ ProtocolDecl *target) {
+ // Fast path: if the protocol that made this associated type
+ // declaration declared the desired conformance, we can use it directly.
+ if (auto result = declaresDirectConformance(associatedType->getProtocol(),
+ associatedType, target))
+ return result;
+
+ return findConformanceRecursive(conformsTo, associatedType, target);
+}
+
+static ConformancePath
findAccessPathDeclaringConformance(IRGenFunction &IGF,
CanArchetypeType archetype,
ProtocolDecl *protocol) {
@@ -128,14 +149,20 @@
auto association =
findConformanceDeclaration(parent->getConformsTo(),
archetype->getAssocType(), protocol);
- if (association) return { parent, association };
+ if (association) {
+ association->ParentArchetype = parent;
+ return *association;
+ }
}
for (auto accessPath : IGF.getArchetypeAccessPaths(archetype)) {
auto association =
findConformanceDeclaration(accessPath.BaseType->getConformsTo(),
accessPath.Association, protocol);
- if (association) return { accessPath.BaseType, association };
+ if (association) {
+ association->ParentArchetype = accessPath.BaseType;
+ return *association;
+ }
}
llvm_unreachable("no relation found that declares conformance to target");
@@ -197,16 +224,30 @@
// If that's not present, this conformance must be implied by some
// associated-type relationship.
+
+ // First, find the right access path.
auto accessPath =
findAccessPathDeclaringConformance(IGF, archetype, protocol);
- // To do this, we need the metadata for the associated type.
- auto associatedMetadata = emitArchetypeTypeMetadataRef(IGF, archetype);
+ // Get the metadata for the parent.
+ llvm::Value *parentMetadata =
+ emitArchetypeTypeMetadataRef(IGF, accessPath.ParentArchetype);
- CanArchetypeType parent = accessPath.BaseType;
- AssociatedTypeDecl *association = accessPath.Association;
- wtable = emitAssociatedTypeWitnessTableRef(IGF, parent, association,
- associatedMetadata,
+ // Get the conformance of the parent to the protocol which declares
+ // the associated conformance.
+ llvm::Value *parentWTable =
+ emitArchetypeWitnessTableRef(IGF, accessPath.ParentArchetype,
+ accessPath.ParentProtocol);
+
+ // Get the metadata for the associated type, i.e. this type.
+ auto archetypeMetadata = emitArchetypeTypeMetadataRef(IGF, archetype);
+
+ // Call the accessor.
+ wtable = emitAssociatedTypeWitnessTableRef(IGF, parentMetadata,
+ parentWTable,
+ accessPath.ParentProtocol,
+ accessPath.Path,
+ archetypeMetadata,
protocol);
setProtocolWitnessTableName(IGF.IGM, wtable, archetype, protocol);
@@ -361,34 +402,6 @@
return emitAssociatedTypeMetadataRef(IGF, originMetadata, wtable, associate);
}
-llvm::Value *
-irgen::emitAssociatedTypeWitnessTableRef(IRGenFunction &IGF,
- CanArchetypeType origin,
- AssociatedTypeDecl *associate,
- llvm::Value *associateMetadata,
- ProtocolDecl *associateProtocol) {
- // We might really be asking for information associated with a more refined
- // associated type declaration.
- associate = findConformanceDeclaration(origin->getConformsTo(),
- associate,
- associateProtocol);
- assert(associate &&
- "didn't find any associatedtype declaration declaring "
- "direct conformance to target protocol");
-
- // Find the conformance of the origin to the associated type's protocol.
- llvm::Value *wtable = emitArchetypeWitnessTableRef(IGF, origin,
- associate->getProtocol());
-
- // Find the origin's type metadata.
- llvm::Value *originMetadata = emitArchetypeTypeMetadataRef(IGF, origin);
-
- // FIXME: will this ever be an indirect requirement?
- return emitAssociatedTypeWitnessTableRef(IGF, originMetadata, wtable,
- associate, associateMetadata,
- associateProtocol);
-}
-
const TypeInfo *TypeConverter::convertArchetypeType(ArchetypeType *archetype) {
assert(isExemplarArchetype(archetype) && "lowering non-exemplary archetype");
diff --git a/lib/IRGen/GenArchetype.h b/lib/IRGen/GenArchetype.h
index c6e495a..6baa977 100644
--- a/lib/IRGen/GenArchetype.h
+++ b/lib/IRGen/GenArchetype.h
@@ -53,14 +53,6 @@
CanArchetypeType origin,
AssociatedTypeDecl *associate);
- /// Emit a witness table reference for a specific conformance of an
- /// associated type of an archetype.
- llvm::Value *emitAssociatedTypeWitnessTableRef(IRGenFunction &IGF,
- CanArchetypeType origin,
- AssociatedTypeDecl *associate,
- llvm::Value *associateMetadata,
- ProtocolDecl *associateProtocol);
-
/// Emit a dynamic metatype lookup for the given archetype.
llvm::Value *emitDynamicTypeOfOpaqueArchetype(IRGenFunction &IGF,
Address archetypeAddr,
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index ac932a7..46c949d 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -3303,16 +3303,15 @@
llvm::Function *
IRGenModule::getAddrOfAssociatedTypeWitnessTableAccessFunction(
const NormalProtocolConformance *conformance,
- AssociatedTypeDecl *associate,
- ProtocolDecl *associateProtocol) {
+ CanType associatedType,
+ ProtocolDecl *associatedProtocol) {
checkEligibleConf(conformance);
auto forDefinition = ForDefinition;
- assert(conformance->getProtocol() == associate->getProtocol());
LinkEntity entity =
LinkEntity::forAssociatedTypeWitnessTableAccessFunction(conformance,
- associate,
- associateProtocol);
+ associatedType,
+ associatedProtocol);
llvm::Function *&entry = GlobalFuncs[entity];
if (entry) {
if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 1102627..b7a5862 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -639,40 +639,31 @@
/// A class which lays out a witness table in the abstract.
class WitnessTableLayout : public SILWitnessVisitor<WitnessTableLayout> {
- unsigned NumWitnesses = 0;
SmallVector<WitnessTableEntry, 16> Entries;
- WitnessIndex getNextIndex() {
- return WitnessIndex(NumWitnesses++, /*isPrefix=*/false);
- }
-
public:
/// The next witness is an out-of-line base protocol.
void addOutOfLineBaseProtocol(ProtocolDecl *baseProto) {
- Entries.push_back(
- WitnessTableEntry::forOutOfLineBase(baseProto, getNextIndex()));
+ Entries.push_back(WitnessTableEntry::forOutOfLineBase(baseProto));
}
void addMethod(FuncDecl *func) {
- Entries.push_back(WitnessTableEntry::forFunction(func, getNextIndex()));
+ Entries.push_back(WitnessTableEntry::forFunction(func));
}
void addConstructor(ConstructorDecl *ctor) {
- Entries.push_back(WitnessTableEntry::forFunction(ctor, getNextIndex()));
+ Entries.push_back(WitnessTableEntry::forFunction(ctor));
}
- void addAssociatedType(AssociatedTypeDecl *ty,
- ArrayRef<ProtocolDecl *> protos) {
- // An associated type takes up a spot for the type metadata and for the
- // witnesses to all its conformances.
+ void addAssociatedType(AssociatedTypeDecl *ty) {
+ Entries.push_back(WitnessTableEntry::forAssociatedType(ty));
+ }
+
+ void addAssociatedConformance(CanType path, ProtocolDecl *protocol) {
Entries.push_back(
- WitnessTableEntry::forAssociatedType(ty, getNextIndex()));
- for (auto *proto : protos)
- if (Lowering::TypeConverter::protocolRequiresWitnessTable(proto))
- ++NumWitnesses;
+ WitnessTableEntry::forAssociatedConformance(path, protocol));
}
- unsigned getNumWitnesses() const { return NumWitnesses; }
ArrayRef<WitnessTableEntry> getEntries() const { return Entries; }
};
@@ -769,12 +760,11 @@
if (!Lowering::TypeConverter::protocolRequiresWitnessTable(base))
continue;
- auto &baseEntry = protoInfo.getWitnessEntry(base);
- assert(baseEntry.isBase());
+ auto baseIndex = protoInfo.getBaseIndex(base);
// Compute the length down to this base.
unsigned lengthToBase = lengthSoFar;
- if (baseEntry.isOutOfLineBase()) {
+ if (!baseIndex.isPrefix()) {
lengthToBase++;
// Don't consider this path if we reach a length that can't
@@ -803,8 +793,8 @@
foundBetter = true;
// Add the link from proto to base if necessary.
- if (baseEntry.isOutOfLineBase()) {
- ReversePath.push_back(baseEntry.getOutOfLineBaseIndex());
+ if (!baseIndex.isPrefix()) {
+ ReversePath.push_back(baseIndex);
// If it isn't necessary, then we might be able to
// short-circuit considering the bases of this protocol.
@@ -1048,8 +1038,8 @@
&& "sil witness table does not match protocol");
assert(entry.getBaseProtocolWitness().Requirement == baseProto
&& "sil witness table does not match protocol");
- auto piEntry = PI.getWitnessEntry(baseProto);
- assert(piEntry.getOutOfLineBaseIndex().getValue() == Table.size()
+ auto piIndex = PI.getBaseIndex(baseProto);
+ assert(piIndex.getValue() == Table.size()
&& "offset doesn't match ProtocolInfo layout");
#endif
@@ -1092,8 +1082,8 @@
&& "sil witness table does not match protocol");
assert(entry.getMethodWitness().Requirement.getDecl() == requirement
&& "sil witness table does not match protocol");
- auto piEntry = PI.getWitnessEntry(requirement);
- assert(piEntry.getFunctionIndex().getValue() == Table.size()
+ auto piIndex = PI.getFunctionIndex(requirement);
+ assert(piIndex.getValue() == Table.size()
&& "offset doesn't match ProtocolInfo layout");
#endif
@@ -1118,16 +1108,15 @@
return addMethodFromSILWitnessTable(requirement);
}
- void addAssociatedType(AssociatedTypeDecl *requirement,
- ArrayRef<ProtocolDecl *> protos) {
+ void addAssociatedType(AssociatedTypeDecl *requirement) {
#ifndef NDEBUG
auto &entry = SILEntries.front();
assert(entry.getKind() == SILWitnessTable::AssociatedType
&& "sil witness table does not match protocol");
assert(entry.getAssociatedTypeWitness().Requirement == requirement
&& "sil witness table does not match protocol");
- auto piEntry = PI.getWitnessEntry(requirement);
- assert(piEntry.getAssociatedTypeIndex().getValue() == Table.size()
+ auto piIndex = PI.getAssociatedTypeIndex(requirement);
+ assert(piIndex.getValue() == Table.size()
&& "offset doesn't match ProtocolInfo layout");
#endif
@@ -1135,7 +1124,6 @@
const Substitution &sub =
Conformance.getTypeWitness(requirement, nullptr);
- assert(protos.size() == sub.getConformances().size());
// This type will be expressed in terms of the archetypes
// of the conforming context.
@@ -1145,34 +1133,41 @@
llvm::Constant *metadataAccessFunction =
getAssociatedTypeMetadataAccessFunction(requirement, associate);
Table.push_back(metadataAccessFunction);
+ }
+ void addAssociatedConformance(Type associatedType, ProtocolDecl *protocol) {
// FIXME: Add static witness tables for type conformances.
- for (auto index : indices(protos)) {
- ProtocolDecl *protocol = protos[index];
- auto associatedConformance = sub.getConformances()[index];
- if (!Lowering::TypeConverter::protocolRequiresWitnessTable(protocol))
- continue;
+ CanType associate = Conformance.getAssociatedType(associatedType)
+ ->getCanonicalType();
+ assert(!associate->hasTypeParameter());
+
+ ProtocolConformanceRef associatedConformance =
+ Conformance.getAssociatedConformance(associatedType, protocol);
#ifndef NDEBUG
- auto &entry = SILEntries.front();
- (void)entry;
- assert(entry.getKind() == SILWitnessTable::AssociatedTypeProtocol
- && "sil witness table does not match protocol");
- auto associatedWitness = entry.getAssociatedTypeProtocolWitness();
- assert(associatedWitness.Requirement == requirement
- && "sil witness table does not match protocol");
- assert(associatedWitness.Protocol == protocol
- && "sil witness table does not match protocol");
+ auto &entry = SILEntries.front();
+ (void)entry;
+ assert(entry.getKind() == SILWitnessTable::AssociatedTypeProtocol
+ && "sil witness table does not match protocol");
+ auto associatedWitness = entry.getAssociatedTypeProtocolWitness();
+ assert(associatedWitness.Requirement->isEqual(associatedType)
+ && "sil witness table does not match protocol");
+ assert(associatedWitness.Protocol == protocol
+ && "sil witness table does not match protocol");
+ auto piIndex =
+ PI.getAssociatedConformanceIndex(associatedType->getCanonicalType(),
+ protocol);
+ assert(piIndex.getValue() == Table.size()
+ && "offset doesn't match ProtocolInfo layout");
#endif
- SILEntries = SILEntries.slice(1);
+ SILEntries = SILEntries.slice(1);
- llvm::Constant *wtableAccessFunction =
- getAssociatedTypeWitnessTableAccessFunction(requirement, associate,
- protocol, associatedConformance);
- Table.push_back(wtableAccessFunction);
- }
+ llvm::Constant *wtableAccessFunction =
+ getAssociatedTypeWitnessTableAccessFunction(CanType(associatedType),
+ associate, protocol, associatedConformance);
+ Table.push_back(wtableAccessFunction);
}
private:
@@ -1183,7 +1178,7 @@
CanType associatedType);
llvm::Constant *
- getAssociatedTypeWitnessTableAccessFunction(AssociatedTypeDecl *requirement,
+ getAssociatedTypeWitnessTableAccessFunction(CanType depAssociatedType,
CanType associatedType,
ProtocolDecl *protocol,
ProtocolConformanceRef conformance);
@@ -1344,8 +1339,19 @@
}
}
+static void buildAssociatedTypeValueName(CanType depAssociatedType,
+ SmallString<128> &name) {
+ if (auto memberType = dyn_cast<DependentMemberType>(depAssociatedType)) {
+ buildAssociatedTypeValueName(memberType.getBase(), name);
+ name += '.';
+ name += memberType->getName().str();
+ } else {
+ assert(isa<GenericTypeParamType>(depAssociatedType)); // Self
+ }
+}
+
llvm::Constant *WitnessTableBuilder::
-getAssociatedTypeWitnessTableAccessFunction(AssociatedTypeDecl *requirement,
+getAssociatedTypeWitnessTableAccessFunction(CanType depAssociatedType,
CanType associatedType,
ProtocolDecl *associatedProtocol,
ProtocolConformanceRef associatedConformance) {
@@ -1359,7 +1365,7 @@
// Otherwise, emit an access function.
llvm::Function *accessor =
IGM.getAddrOfAssociatedTypeWitnessTableAccessFunction(&Conformance,
- requirement,
+ depAssociatedType,
associatedProtocol);
IRGenFunction IGF(IGM, accessor);
@@ -1372,16 +1378,19 @@
// We use a non-standard name for the type that states the association
// requirement rather than the concrete type.
- if (IGM.EnableValueNames)
- associatedTypeMetadata->setName(Twine(ConcreteType->getString())
- + "." + requirement->getNameStr());
+ if (IGM.EnableValueNames) {
+ SmallString<128> name;
+ name += ConcreteType->getString();
+ buildAssociatedTypeValueName(depAssociatedType, name);
+ associatedTypeMetadata->setName(name);
+ }
llvm::Value *self = parameters.claimNext();
setTypeMetadataName(IGM, self, ConcreteType);
Address destTable(parameters.claimNext(), IGM.getPointerAlignment());
setProtocolWitnessTableName(IGM, destTable.getAddress(), ConcreteType,
- requirement->getProtocol());
+ Conformance.getProtocol());
const ConformanceInfo *conformanceI = nullptr;
if (associatedConformance.isConcrete()) {
@@ -1642,8 +1651,7 @@
layout.visitProtocolDecl(protocol);
// Create a ProtocolInfo object from the layout.
- ProtocolInfo *info = ProtocolInfo::create(layout.getNumWitnesses(),
- layout.getEntries());
+ ProtocolInfo *info = ProtocolInfo::create(layout.getEntries());
info->NextConverted = FirstProtocol;
FirstProtocol = info;
@@ -1655,11 +1663,10 @@
}
/// Allocate a new ProtocolInfo.
-ProtocolInfo *ProtocolInfo::create(unsigned numWitnesses,
- ArrayRef<WitnessTableEntry> table) {
+ProtocolInfo *ProtocolInfo::create(ArrayRef<WitnessTableEntry> table) {
size_t bufferSize = totalSizeToAlloc<WitnessTableEntry>(table.size());
void *buffer = ::operator new(bufferSize);
- return new(buffer) ProtocolInfo(numWitnesses, table);
+ return new(buffer) ProtocolInfo(table);
}
ProtocolInfo::~ProtocolInfo() {
@@ -2069,13 +2076,13 @@
if (source) {
auto &pi = IGF.IGM.getProtocolInfo(protocol);
- auto &entry = pi.getWitnessEntry(inheritedProtocol);
- assert(entry.isOutOfLineBase());
- source = emitInvariantLoadOfOpaqueWitness(IGF, source,
- entry.getOutOfLineBaseIndex());
- source = IGF.Builder.CreateBitCast(source, IGF.IGM.WitnessTablePtrTy);
- setProtocolWitnessTableName(IGF.IGM, source, sourceKey.Type,
- inheritedProtocol);
+ auto index = pi.getBaseIndex(inheritedProtocol);
+ if (!index.isPrefix()) {
+ source = emitInvariantLoadOfOpaqueWitness(IGF, source, index);
+ source = IGF.Builder.CreateBitCast(source, IGF.IGM.WitnessTablePtrTy);
+ setProtocolWitnessTableName(IGF.IGM, source, sourceKey.Type,
+ inheritedProtocol);
+ }
}
return source;
}
@@ -2752,7 +2759,7 @@
// Find the witness we're interested in.
auto &fnProtoInfo = IGF.IGM.getProtocolInfo(conformance.getRequirement());
- auto index = fnProtoInfo.getWitnessEntry(fn).getFunctionIndex();
+ auto index = fnProtoInfo.getFunctionIndex(fn);
llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, wtable, index);
// Cast the witness pointer to i8*.
@@ -2779,7 +2786,7 @@
llvm::Value *wtable,
AssociatedTypeDecl *associatedType) {
auto &pi = IGF.IGM.getProtocolInfo(associatedType->getProtocol());
- auto index = pi.getWitnessEntry(associatedType).getAssociatedTypeIndex();
+ auto index = pi.getAssociatedTypeIndex(associatedType);
llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, wtable, index);
// Cast the witness to the appropriate function type.
@@ -2818,12 +2825,13 @@
irgen::emitAssociatedTypeWitnessTableRef(IRGenFunction &IGF,
llvm::Value *parentMetadata,
llvm::Value *wtable,
- AssociatedTypeDecl *associatedType,
+ ProtocolDecl *parentProtocol,
+ CanType associatedType,
llvm::Value *associatedTypeMetadata,
ProtocolDecl *associatedProtocol) {
- auto &pi = IGF.IGM.getProtocolInfo(associatedType->getProtocol());
- auto index = pi.getWitnessEntry(associatedType)
- .getAssociatedTypeWitnessTableIndex(associatedProtocol);
+ auto &pi = IGF.IGM.getProtocolInfo(parentProtocol);
+ auto index =
+ pi.getAssociatedConformanceIndex(associatedType, associatedProtocol);
llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, wtable, index);
// Cast the witness to the appropriate function type.
diff --git a/lib/IRGen/GenProto.h b/lib/IRGen/GenProto.h
index f924346..48b67a6 100644
--- a/lib/IRGen/GenProto.h
+++ b/lib/IRGen/GenProto.h
@@ -71,21 +71,23 @@
llvm::Value *wtable,
AssociatedTypeDecl *associatedType);
- /// Given a type T and an associated type X of a protocol PT to which
+ /// Given a type T and an associated type path X.Y of a protocol PT to which
/// T conforms, where X is required to implement some protocol PX, return
- /// the witness table witnessing the conformance of T.X to PX.
+ /// the witness table witnessing the conformance of T.X.Y to PX.
///
- /// PX must be a direct requirement of X.
+ /// PX must be a direct requirement of PT.
///
/// \param parentMetadata - the type metadata for T
/// \param wtable - the witness table witnessing the conformance of T to PT
- /// \param associatedType - the declaration of X; a member of PT
- /// \param associatedTypeMetadata - the type metadata for T.X
+ /// \param parentProtocol - PT
+ /// \param associatedType - the path X.Y, a dependent type within PT
+ /// \param associatedTypeMetadata - the type metadata for T.X.Y
/// \param associatedProtocol - the declaration of PX
llvm::Value *emitAssociatedTypeWitnessTableRef(IRGenFunction &IGF,
llvm::Value *parentMetadata,
llvm::Value *wtable,
- AssociatedTypeDecl *associatedType,
+ ProtocolDecl *parentProtocol,
+ CanType associatedType,
llvm::Value *associatedTypeMetadata,
ProtocolDecl *associatedProtocol);
diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h
index 33c5245..026d0a0 100644
--- a/lib/IRGen/IRGenMangler.h
+++ b/lib/IRGen/IRGenMangler.h
@@ -120,16 +120,25 @@
std::string mangleAssociatedTypeWitnessTableAccessFunction(
const ProtocolConformance *Conformance,
- StringRef AssocTyName,
+ CanType AssociatedType,
const ProtocolDecl *Proto) {
beginMangling();
appendProtocolConformance(Conformance);
- appendIdentifier(AssocTyName);
+ appendAssociatedTypePath(AssociatedType);
appendNominalType(Proto);
appendOperator("WT");
return finalize();
}
+ void appendAssociatedTypePath(CanType associatedType) {
+ if (auto memberType = dyn_cast<DependentMemberType>(associatedType)) {
+ appendAssociatedTypePath(memberType.getBase());
+ appendIdentifier(memberType->getName().str());
+ } else {
+ assert(isa<GenericTypeParamType>(associatedType));
+ }
+ }
+
std::string mangleReflectionBuiltinDescriptor(Type type) {
return mangleTypeSymbol(type, "MB");
}
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index e5282b1..ede0aae 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -968,7 +968,7 @@
AssociatedTypeDecl *associatedType);
llvm::Function *getAddrOfAssociatedTypeWitnessTableAccessFunction(
const NormalProtocolConformance *C,
- AssociatedTypeDecl *associatedType,
+ CanType depAssociatedType,
ProtocolDecl *requiredProtocol);
Address getAddrOfObjCISAMask();
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index 97e61fb..73408ac 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -898,6 +898,13 @@
void visitInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *i);
void visitFixLifetimeInst(FixLifetimeInst *i);
+ void visitEndLifetimeInst(EndLifetimeInst *i) {
+ llvm_unreachable("unimplemented");
+ }
+ void
+ visitUncheckedOwnershipConversionInst(UncheckedOwnershipConversionInst *i) {
+ llvm_unreachable("unimplemented");
+ }
void visitBeginBorrowInst(BeginBorrowInst *i) {
llvm_unreachable("unimplemented");
}
diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp
index 0fdcbfc..5ecd6c5 100644
--- a/lib/IRGen/Linking.cpp
+++ b/lib/IRGen/Linking.cpp
@@ -80,6 +80,15 @@
buffer.write(Result.data(), Result.size());
}
+static void mangleAssociatedTypePath(Mangler &mangler, CanType assocType) {
+ if (auto memberType = dyn_cast<DependentMemberType>(assocType)) {
+ mangleAssociatedTypePath(mangler, memberType.getBase());
+ mangler.mangleIdentifier(memberType->getName().str());
+ } else {
+ assert(isa<GenericTypeParamType>(assocType));
+ }
+}
+
/// Mangle this entity into the given stream.
std::string LinkEntity::mangleOld() const {
// Almost everything below gets the common prefix:
@@ -209,13 +218,15 @@
mangler.mangleIdentifier(getAssociatedType()->getNameStr());
return mangler.finalize();
- // global ::= 'WT' protocol-conformance identifier nominal-type
- case Kind::AssociatedTypeWitnessTableAccessFunction:
+ // global ::= 'WT' protocol-conformance identifier+ nominal-type
+ case Kind::AssociatedTypeWitnessTableAccessFunction: {
mangler.append("_TWT");
mangler.mangleProtocolConformance(getProtocolConformance());
- mangler.mangleIdentifier(getAssociatedType()->getNameStr());
- mangler.mangleProtocolDecl(getAssociatedProtocol());
+ auto assocConf = getAssociatedConformance();
+ mangleAssociatedTypePath(mangler, assocConf.first);
+ mangler.mangleProtocolDecl(assocConf.second);
return mangler.finalize();
+ }
// For all the following, this rule was imposed above:
// global ::= local-marker? entity // some identifiable thing
@@ -412,11 +423,12 @@
return mangler.mangleAssociatedTypeMetadataAccessFunction(
getProtocolConformance(), getAssociatedType()->getNameStr());
- // global ::= 'WT' protocol-conformance identifier nominal-type
- case Kind::AssociatedTypeWitnessTableAccessFunction:
+ // global ::= protocol-conformance identifier+ nominal-type 'WT'
+ case Kind::AssociatedTypeWitnessTableAccessFunction: {
+ auto assocConf = getAssociatedConformance();
return mangler.mangleAssociatedTypeWitnessTableAccessFunction(
- getProtocolConformance(), getAssociatedType()->getNameStr(),
- getAssociatedProtocol());
+ getProtocolConformance(), assocConf.first, assocConf.second);
+ }
// For all the following, this rule was imposed above:
// global ::= local-marker? entity // some identifiable thing
diff --git a/lib/IRGen/Linking.h b/lib/IRGen/Linking.h
index fce2224..37c30f9 100644
--- a/lib/IRGen/Linking.h
+++ b/lib/IRGen/Linking.h
@@ -83,8 +83,12 @@
MetadataAddressShift = 8, MetadataAddressMask = 0x0300,
IsPatternShift = 10, IsPatternMask = 0x0400,
- // This field appears in associated type access function kinds.
+ // This field appears in associated type access functions.
AssociatedTypeIndexShift = 8, AssociatedTypeIndexMask = ~KindMask,
+
+ // This field appears in associated conformance access functions.
+ AssociatedConformanceIndexShift = 8,
+ AssociatedConformanceIndexMask = ~KindMask,
};
#define LINKENTITY_SET_FIELD(field, value) (value << field##Shift)
#define LINKENTITY_GET_FIELD(value, field) ((value & field##Mask) >> field##Shift)
@@ -160,8 +164,8 @@
/// A function which returns the witness table for a protocol-constrained
/// associated type of a protocol. The secondary pointer is a
- /// ProtocolConformance*. The primary pointer is a ProtocolDecl*.
- /// The index of the associated type declaration is stored in the data.
+ /// ProtocolConformance*. The index of the associated conformance
+ /// requirement is stored in the data.
AssociatedTypeWitnessTableAccessFunction,
/// A reflection metadata descriptor for the associated type witnesses of a
@@ -264,16 +268,28 @@
void setForProtocolConformanceAndAssociatedType(Kind kind,
const ProtocolConformance *c,
- AssociatedTypeDecl *associate,
- ProtocolDecl *associatedProtocol = nullptr) {
+ AssociatedTypeDecl *associate) {
assert(isProtocolConformanceKind(kind));
- Pointer = associatedProtocol;
+ Pointer = nullptr;
SecondaryPointer = const_cast<void*>(static_cast<const void*>(c));
Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)) |
LINKENTITY_SET_FIELD(AssociatedTypeIndex,
getAssociatedTypeIndex(c, associate));
}
+ void setForProtocolConformanceAndAssociatedConformance(Kind kind,
+ const ProtocolConformance *c,
+ CanType associatedType,
+ ProtocolDecl *associatedProtocol) {
+ assert(isProtocolConformanceKind(kind));
+ Pointer = associatedProtocol;
+ SecondaryPointer = const_cast<void*>(static_cast<const void*>(c));
+ Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)) |
+ LINKENTITY_SET_FIELD(AssociatedConformanceIndex,
+ getAssociatedConformanceIndex(c, associatedType,
+ associatedProtocol));
+ }
+
// We store associated types using their index in their parent protocol
// in order to avoid bloating LinkEntity out to three key pointers.
static unsigned getAssociatedTypeIndex(const ProtocolConformance *conformance,
@@ -299,6 +315,37 @@
llvm_unreachable("didn't find associated type in protocol?");
}
+ // We store associated conformances using their index in the requirement
+ // list of the requirement signature of the conformance's protocol.
+ static unsigned getAssociatedConformanceIndex(
+ const ProtocolConformance *conformance,
+ CanType associatedType,
+ ProtocolDecl *requirement) {
+ unsigned index = 0;
+ for (auto &reqt : conformance->getProtocol()->getRequirementSignature()
+ ->getRequirements()) {
+ if (reqt.getKind() == RequirementKind::Conformance &&
+ reqt.getFirstType()->getCanonicalType() == associatedType &&
+ reqt.getSecondType()->castTo<ProtocolType>()->getDecl() ==
+ requirement) {
+ return index;
+ }
+ ++index;
+ }
+ llvm_unreachable("requirement not found in protocol");
+ }
+
+ static std::pair<CanType, ProtocolDecl*>
+ getAssociatedConformanceByIndex(const ProtocolConformance *conformance,
+ unsigned index) {
+ auto &reqt =
+ conformance->getProtocol()->getRequirementSignature()
+ ->getRequirements()[index];
+ assert(reqt.getKind() == RequirementKind::Conformance);
+ return { reqt.getFirstType()->getCanonicalType(),
+ reqt.getSecondType()->castTo<ProtocolType>()->getDecl() };
+ }
+
void setForType(Kind kind, CanType type) {
assert(isTypeKind(kind));
Pointer = type.getPointer();
@@ -493,12 +540,12 @@
static LinkEntity
forAssociatedTypeWitnessTableAccessFunction(const ProtocolConformance *C,
- AssociatedTypeDecl *associate,
- ProtocolDecl *associateProtocol) {
+ CanType associatedType,
+ ProtocolDecl *associatedProtocol){
LinkEntity entity;
- entity.setForProtocolConformanceAndAssociatedType(
- Kind::AssociatedTypeWitnessTableAccessFunction, C, associate,
- associateProtocol);
+ entity.setForProtocolConformanceAndAssociatedConformance(
+ Kind::AssociatedTypeWitnessTableAccessFunction, C,
+ associatedType, associatedProtocol);
return entity;
}
@@ -576,12 +623,17 @@
}
AssociatedTypeDecl *getAssociatedType() const {
- assert(getKind() == Kind::AssociatedTypeMetadataAccessFunction ||
- getKind() == Kind::AssociatedTypeWitnessTableAccessFunction);
+ assert(getKind() == Kind::AssociatedTypeMetadataAccessFunction);
return getAssociatedTypeByIndex(getProtocolConformance(),
LINKENTITY_GET_FIELD(Data, AssociatedTypeIndex));
}
+ std::pair<CanType, ProtocolDecl *> getAssociatedConformance() const {
+ assert(getKind() == Kind::AssociatedTypeWitnessTableAccessFunction);
+ return getAssociatedConformanceByIndex(getProtocolConformance(),
+ LINKENTITY_GET_FIELD(Data, AssociatedConformanceIndex));
+ }
+
ProtocolDecl *getAssociatedProtocol() const {
assert(getKind() == Kind::AssociatedTypeWitnessTableAccessFunction);
return reinterpret_cast<ProtocolDecl*>(Pointer);
diff --git a/lib/IRGen/ProtocolInfo.h b/lib/IRGen/ProtocolInfo.h
index d197b1c..ed7af13 100644
--- a/lib/IRGen/ProtocolInfo.h
+++ b/lib/IRGen/ProtocolInfo.h
@@ -52,92 +52,110 @@
};
/// A witness to a specific element of a protocol. Every
-/// ProtocolTypeInfo stores one of these for each declaration in the
-/// protocol.
-///
-/// The structure of a witness varies by the type of declaration:
-/// - a function requires a single witness, the function;
-/// - a variable requires two witnesses, a getter and a setter;
-/// - a subscript requires two witnesses, a getter and a setter;
-/// - a type requires a pointer to the metadata for that type and
-/// to witness tables for each of the protocols it obeys.
+/// ProtocolTypeInfo stores one of these for each requirement
+/// introduced by the protocol.
class WitnessTableEntry {
- Decl *Member;
- WitnessIndex BeginIndex;
+public:
+ void *MemberOrAssociatedType;
+ ProtocolDecl *Protocol;
- WitnessTableEntry(Decl *member, WitnessIndex begin)
- : Member(member), BeginIndex(begin) {}
+ WitnessTableEntry(void *member, ProtocolDecl *protocol)
+ : MemberOrAssociatedType(member), Protocol(protocol) {}
public:
WitnessTableEntry() = default;
- Decl *getMember() const {
- return Member;
- }
-
- static WitnessTableEntry forPrefixBase(ProtocolDecl *proto) {
- return WitnessTableEntry(proto, WitnessIndex(0, /*isPrefix=*/ true));
- }
-
- static WitnessTableEntry forOutOfLineBase(ProtocolDecl *proto,
- WitnessIndex index) {
- return WitnessTableEntry(proto, index);
+ static WitnessTableEntry forOutOfLineBase(ProtocolDecl *proto) {
+ assert(proto != nullptr);
+ return WitnessTableEntry(nullptr, proto);
}
/// Is this a base-protocol entry?
- bool isBase() const { return isa<ProtocolDecl>(Member); }
+ bool isBase() const { return MemberOrAssociatedType == nullptr; }
- /// Is the table for this base-protocol entry "out of line",
- /// i.e. there is a witness which indirectly points to it, or is
- /// it a prefix of the layout of this protocol?
+ bool matchesBase(ProtocolDecl *proto) const {
+ assert(proto != nullptr);
+ return MemberOrAssociatedType == nullptr && Protocol == proto;
+ }
+
+ /// Given that this is a base-protocol entry, is the table
+ /// "out of line"?
bool isOutOfLineBase() const {
assert(isBase());
- return !BeginIndex.isPrefix();
+ return true;
}
- /// Return the index at which to find the table for this
- /// base-protocol entry.
- WitnessIndex getOutOfLineBaseIndex() const {
- assert(isOutOfLineBase());
- return BeginIndex;
+ ProtocolDecl *getBase() const {
+ assert(isBase());
+ return Protocol;
}
- static WitnessTableEntry forFunction(AbstractFunctionDecl *func,
- WitnessIndex index) {
- return WitnessTableEntry(func, index);
+ static WitnessTableEntry forFunction(AbstractFunctionDecl *func) {
+ assert(func != nullptr);
+ return WitnessTableEntry(func, nullptr);
}
- bool isFunction() const { return isa<AbstractFunctionDecl>(Member); }
+ bool isFunction() const {
+ return Protocol == nullptr &&
+ isa<AbstractFunctionDecl>(
+ static_cast<Decl*>(MemberOrAssociatedType));
+ }
- WitnessIndex getFunctionIndex() const {
+ bool matchesFunction(AbstractFunctionDecl *func) const {
+ assert(func != nullptr);
+ return MemberOrAssociatedType == func && Protocol == nullptr;
+ }
+
+ AbstractFunctionDecl *getFunction() const {
assert(isFunction());
- return BeginIndex;
- }
-
- static WitnessTableEntry forAssociatedType(AssociatedTypeDecl *ty,
- WitnessIndex index) {
- return WitnessTableEntry(ty, index);
- }
-
- bool isAssociatedType() const { return isa<AssociatedTypeDecl>(Member); }
-
- WitnessIndex getAssociatedTypeIndex() const {
- assert(isAssociatedType());
- return BeginIndex;
+ return static_cast<AbstractFunctionDecl*>(MemberOrAssociatedType);
}
- WitnessIndex
- getAssociatedTypeWitnessTableIndex(ProtocolDecl *target) const {
- assert(!BeginIndex.isPrefix());
- auto index = BeginIndex.getValue() + 1;
- for (auto protocol :
- cast<AssociatedTypeDecl>(Member)->getConformingProtocols()) {
- if (protocol == target) {
- return WitnessIndex(index, false);
- }
- index++;
- }
- llvm_unreachable("protocol not in direct conformance list?");
+ static WitnessTableEntry forAssociatedType(AssociatedTypeDecl *ty) {
+ return WitnessTableEntry(ty, nullptr);
+ }
+
+ bool isAssociatedType() const {
+ return Protocol == nullptr &&
+ isa<AssociatedTypeDecl>(
+ static_cast<Decl*>(MemberOrAssociatedType));
+ }
+
+ bool matchesAssociatedType(AssociatedTypeDecl *assocType) const {
+ assert(assocType != nullptr);
+ return MemberOrAssociatedType == assocType && Protocol == nullptr;
+ }
+
+ AssociatedTypeDecl *getAssociatedType() const {
+ assert(isAssociatedType());
+ return static_cast<AssociatedTypeDecl*>(MemberOrAssociatedType);
+ }
+
+ static WitnessTableEntry forAssociatedConformance(CanType path,
+ ProtocolDecl *requirement) {
+ assert(path && requirement != nullptr);
+ return WitnessTableEntry(path.getPointer(), requirement);
+ }
+
+ bool isAssociatedConformance() const {
+ return Protocol != nullptr && MemberOrAssociatedType != nullptr;
+ }
+
+ bool matchesAssociatedConformance(CanType path,
+ ProtocolDecl *requirement) const {
+ assert(path && requirement != nullptr);
+ return MemberOrAssociatedType == path.getPointer() &&
+ Protocol == requirement;
+ }
+
+ CanType getAssociatedConformancePath() const {
+ assert(isAssociatedConformance());
+ return CanType(static_cast<TypeBase *>(MemberOrAssociatedType));
+ }
+
+ ProtocolDecl *getAssociatedConformanceRequirement() const {
+ assert(isAssociatedConformance());
+ return Protocol;
}
};
@@ -150,9 +168,6 @@
const ProtocolInfo *NextConverted;
friend class TypeConverter;
- /// The number of witnesses in the protocol.
- unsigned NumWitnesses;
-
/// The number of table entries in this protocol layout.
unsigned NumTableEntries;
@@ -161,14 +176,13 @@
mutable llvm::SmallDenseMap<const ProtocolConformance*, ConformanceInfo*, 2>
Conformances;
- ProtocolInfo(unsigned numWitnesses, ArrayRef<WitnessTableEntry> table)
- : NumWitnesses(numWitnesses), NumTableEntries(table.size()) {
+ ProtocolInfo(ArrayRef<WitnessTableEntry> table)
+ : NumTableEntries(table.size()) {
std::uninitialized_copy(table.begin(), table.end(),
getTrailingObjects<WitnessTableEntry>());
}
- static ProtocolInfo *create(unsigned numWitnesses,
- ArrayRef<WitnessTableEntry> table);
+ static ProtocolInfo *create(ArrayRef<WitnessTableEntry> table);
public:
const ConformanceInfo &getConformance(IRGenModule &IGM,
@@ -178,20 +192,53 @@
/// The number of witness slots in a conformance to this protocol;
/// in other words, the size of the table in words.
unsigned getNumWitnesses() const {
- return NumWitnesses;
+ return NumTableEntries;
}
ArrayRef<WitnessTableEntry> getWitnessEntries() const {
return {getTrailingObjects<WitnessTableEntry>(), NumTableEntries};
}
- const WitnessTableEntry &getWitnessEntry(Decl *member) const {
- // FIXME: do a binary search if the number of witnesses is large
- // enough.
- for (auto &witness : getWitnessEntries())
- if (witness.getMember() == member)
- return witness;
- llvm_unreachable("didn't find entry for member!");
+ WitnessIndex getBaseIndex(ProtocolDecl *protocol) const {
+ auto entries = getWitnessEntries();
+ for (auto &witness : entries) {
+ if (witness.matchesBase(protocol)) {
+ if (witness.isOutOfLineBase()) {
+ return WitnessIndex(&witness - entries.begin(), false);
+ } else {
+ return WitnessIndex(0, true);
+ }
+ }
+ }
+ llvm_unreachable("didn't find entry for base");
+ }
+
+ WitnessIndex getFunctionIndex(AbstractFunctionDecl *function) const {
+ auto entries = getWitnessEntries();
+ for (auto &witness : entries) {
+ if (witness.matchesFunction(function))
+ return WitnessIndex(&witness - entries.begin(), false);
+ }
+ llvm_unreachable("didn't find entry for function");
+ }
+
+ WitnessIndex getAssociatedTypeIndex(AssociatedTypeDecl *assocType) const {
+ auto entries = getWitnessEntries();
+ for (auto &witness : entries) {
+ if (witness.matchesAssociatedType(assocType))
+ return WitnessIndex(&witness - entries.begin(), false);
+ }
+ llvm_unreachable("didn't find entry for associated type");
+ }
+
+ WitnessIndex getAssociatedConformanceIndex(CanType path,
+ ProtocolDecl *requirement) const {
+ auto entries = getWitnessEntries();
+ for (auto &witness : entries) {
+ if (witness.matchesAssociatedConformance(path, requirement))
+ return WitnessIndex(&witness - entries.begin(), false);
+ }
+ llvm_unreachable("didn't find entry for associated conformance");
}
~ProtocolInfo();
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 52bf53c..dc07a83 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -355,7 +355,7 @@
bool startEntity(Decl *D, IndexSymbol &Info);
bool startEntityDecl(ValueDecl *D);
- bool reportRelatedRef(ValueDecl *D, SourceLoc Loc, SymbolRoleSet Relations, Decl *Related);
+ bool reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit, SymbolRoleSet Relations, Decl *Related);
bool reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations, Decl *Related);
bool reportInheritedTypeRefs(ArrayRef<TypeLoc> Inherited, Decl *Inheritee);
NominalTypeDecl *getTypeLocAsNominalTypeDecl(const TypeLoc &Ty);
@@ -624,13 +624,16 @@
return startEntity(D, Info);
}
-bool IndexSwiftASTWalker::reportRelatedRef(ValueDecl *D, SourceLoc Loc, SymbolRoleSet Relations, Decl *Related) {
+bool IndexSwiftASTWalker::reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit,
+ SymbolRoleSet Relations, Decl *Related) {
if (!shouldIndex(D))
return true;
IndexSymbol Info;
if (addRelation(Info, Relations, Related))
return true;
+ if (isImplicit)
+ Info.roles |= (unsigned)SymbolRole::Implicit;
// don't report this ref again when visitDeclReference reports it
repressRefAtLoc(Loc);
@@ -655,9 +658,24 @@
if (IdentTypeRepr *T = dyn_cast_or_null<IdentTypeRepr>(Ty.getTypeRepr())) {
auto Comps = T->getComponentRange();
- if (auto NTD =
- dyn_cast_or_null<NominalTypeDecl>(Comps.back()->getBoundDecl())) {
- if (!reportRelatedRef(NTD, Comps.back()->getIdLoc(), Relations, Related))
+ SourceLoc IdLoc = Comps.back()->getIdLoc();
+ NominalTypeDecl *NTD = nullptr;
+ bool isImplicit = false;
+ if (auto *VD = Comps.back()->getBoundDecl()) {
+ if (auto *TAD = dyn_cast<TypeAliasDecl>(VD)) {
+ IndexSymbol Info;
+ if (!reportRef(TAD, IdLoc, Info))
+ return false;
+ if (auto Ty = TAD->getUnderlyingTypeLoc().getType()) {
+ NTD = Ty->getAnyNominal();
+ isImplicit = true;
+ }
+ } else {
+ NTD = dyn_cast<NominalTypeDecl>(VD);
+ }
+ }
+ if (NTD) {
+ if (!reportRelatedRef(NTD, IdLoc, isImplicit, Relations, Related))
return false;
}
return true;
@@ -665,7 +683,7 @@
if (Ty.getType()) {
if (auto nominal = Ty.getType()->getAnyNominal())
- if (!reportRelatedRef(nominal, Ty.getLoc(), Relations, Related))
+ if (!reportRelatedRef(nominal, Ty.getLoc(), /*isImplicit=*/false, Relations, Related))
return false;
}
return true;
@@ -752,8 +770,8 @@
if (!startEntity(D, Info))
return false;
- if (!reportRelatedRef(NTD, Loc, (SymbolRoleSet)SymbolRole::RelationExtendedBy,
- D))
+ if (!reportRelatedRef(NTD, Loc, /*isImplicit=*/false,
+ (SymbolRoleSet)SymbolRole::RelationExtendedBy, D))
return false;
if (!reportInheritedTypeRefs(D->getInherited(), D))
return false;
diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp
index f6c064d..378b897 100644
--- a/lib/Parse/ParseIfConfig.cpp
+++ b/lib/Parse/ParseIfConfig.cpp
@@ -1,4 +1,4 @@
-//===--- ParseDecl.cpp - Swift Language Parser for #if directives -- ------===//
+//===--- ParseIfConfig.cpp - Swift Language Parser for #if directives -----===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/Parse/ParseSIL.cpp b/lib/Parse/ParseSIL.cpp
index dedf8c8..0ce7d6c 100644
--- a/lib/Parse/ParseSIL.cpp
+++ b/lib/Parse/ParseSIL.cpp
@@ -200,6 +200,25 @@
return parseSILIdentifier(Result, L, Diagnostic(ID, Args...));
}
+ template <typename T, typename... DiagArgTypes, typename... ArgTypes>
+ bool parseSILIdentifierSwitch(T &Result, ArrayRef<StringRef> Strings,
+ Diag<DiagArgTypes...> ID, ArgTypes... Args) {
+ Identifier TmpResult;
+ SourceLoc L;
+ if (parseSILIdentifier(TmpResult, L, Diagnostic(ID, Args...))) {
+ return true;
+ }
+
+ auto Iter = std::find(Strings.begin(), Strings.end(), TmpResult.str());
+ if (Iter == Strings.end()) {
+ P.diagnose(P.Tok, Diagnostic(ID, Args...));
+ return true;
+ }
+
+ Result = ValueOwnershipKind(*Iter);
+ return false;
+ }
+
template<typename ...DiagArgTypes, typename ...ArgTypes>
bool parseSILIdentifier(Identifier &Result, SourceLoc &L,
Diag<DiagArgTypes...> ID, ArgTypes... Args) {
@@ -226,31 +245,17 @@
TypeLoc = P.Tok.getLoc();
return parseASTType(result);
}
- bool parseSILOwnership(Optional<ValueOwnershipKind> &OwnershipKind) {
- // We pare here @ <identifier>.
- if (P.consumeIf(tok::at_sign) && P.Tok.isNot(tok::identifier)) {
+ bool parseSILOwnership(ValueOwnershipKind &OwnershipKind) {
+ // We parse here @ <identifier>.
+ if (!P.consumeIf(tok::at_sign)) {
// Add error here.
return true;
}
- OwnershipKind =
- llvm::StringSwitch<Optional<ValueOwnershipKind>>(P.Tok.getText())
- .Case("trivial",
- Optional<ValueOwnershipKind>(ValueOwnershipKind::Trivial))
- .Case("unowned",
- Optional<ValueOwnershipKind>(ValueOwnershipKind::Unowned))
- .Case("owned",
- Optional<ValueOwnershipKind>(ValueOwnershipKind::Owned))
- .Case("guaranteed", Optional<ValueOwnershipKind>(
- ValueOwnershipKind::Guaranteed))
- .Default(None);
-
- if (OwnershipKind.hasValue()) {
- P.consumeToken();
- return false;
- }
-
- return true;
+ StringRef AllOwnershipKinds[4] = {"trivial", "unowned", "owned",
+ "guaranteed"};
+ return parseSILIdentifierSwitch(OwnershipKind, AllOwnershipKinds,
+ diag::expected_sil_value_ownership_kind);
}
bool parseSILType(SILType &Result,
GenericEnvironment *&genericEnv,
@@ -1443,41 +1448,41 @@
auto loc = parses[0].loc;
- // Collect conformance requirements in a convenient form.
- llvm::DenseMap<TypeBase *, SmallVector<ProtocolDecl *, 2>> conformsTo;
- for (auto reqt : env->getGenericSignature()->getRequirements()) {
- if (reqt.getKind() == RequirementKind::Conformance) {
- auto canTy = reqt.getFirstType()->getCanonicalType();
- auto nominal = reqt.getSecondType()->getAnyNominal();
- conformsTo[canTy.getPointer()].push_back(cast<ProtocolDecl>(nominal));
- }
- }
-
// The replacement is for the corresponding dependent type by ordering.
- for (auto depTy : env->getGenericSignature()->getAllDependentTypes()) {
+ auto result = env->getGenericSignature()->enumeratePairedRequirements(
+ [&](Type depTy, ArrayRef<Requirement> reqts) -> bool {
+ if (parses.empty()) {
+ SP.P.diagnose(loc, diag::sil_missing_substitutions);
+ return true;
+ }
+ auto parsed = parses.front();
+ parses = parses.slice(1);
- auto canTy = depTy->getCanonicalType().getPointer();
+ SmallVector<ProtocolConformanceRef, 2> conformances;
+ SmallVector<ProtocolDecl *, 2> protocols;
+ for (auto reqt : reqts) {
+ protocols.push_back(reqt.getSecondType()
+ ->castTo<ProtocolType>()->getDecl());
+ }
- if (parses.empty()) {
- SP.P.diagnose(loc, diag::sil_missing_substitutions);
- return true;
- }
- auto parsed = parses.front();
- parses = parses.slice(1);
+ if (getConformancesForSubstitution(SP.P, protocols,
+ parsed.replacement,
+ parsed.loc, conformances))
+ return true;
- SmallVector<ProtocolConformanceRef, 2> conformances;
- if (getConformancesForSubstitution(SP.P, conformsTo[canTy],
- parsed.replacement,
- parsed.loc, conformances))
- return true;
+ subs.push_back({parsed.replacement,
+ SP.P.Context.AllocateCopy(conformances)});
+ return false;
+ });
- subs.push_back({parsed.replacement,
- SP.P.Context.AllocateCopy(conformances)});
- }
+ if (result)
+ return true;
+
if (!parses.empty()) {
SP.P.diagnose(loc, diag::sil_too_many_substitutions);
return true;
}
+
return false;
}
@@ -2124,6 +2129,7 @@
} break;
UNARY_INSTRUCTION(FixLifetime)
+ UNARY_INSTRUCTION(EndLifetime)
UNARY_INSTRUCTION(CopyBlock)
UNARY_INSTRUCTION(IsUnique)
UNARY_INSTRUCTION(IsUniqueOrPinned)
@@ -2164,6 +2170,29 @@
break;
}
+ // unchecked_ownership_conversion <reg> : <type>, <ownership> to <ownership>
+ case ValueKind::UncheckedOwnershipConversionInst: {
+ ValueOwnershipKind LHSKind = ValueOwnershipKind::Any;
+ ValueOwnershipKind RHSKind = ValueOwnershipKind::Any;
+ SourceLoc Loc;
+
+ if (parseTypedValueRef(Val, Loc, B) ||
+ P.parseToken(tok::comma, diag::expected_sil_colon,
+ "unchecked_ownership_conversion value ownership kind "
+ "conversion specification") ||
+ parseSILOwnership(LHSKind) || parseVerbatim("to") ||
+ parseSILOwnership(RHSKind) || parseSILDebugLocation(InstLoc, B)) {
+ return true;
+ }
+
+ if (Val.getOwnershipKind() != LHSKind) {
+ return true;
+ }
+
+ ResultVal = B.createUncheckedOwnershipConversion(InstLoc, Val, RHSKind);
+ break;
+ }
+
case ValueKind::LoadInst: {
LoadOwnershipQualifier Qualifier;
SourceLoc AddrLoc;
@@ -4166,7 +4195,7 @@
if (P.consumeIf(tok::l_paren)) {
do {
SILType Ty;
- Optional<ValueOwnershipKind> OwnershipKind;
+ ValueOwnershipKind OwnershipKind = ValueOwnershipKind::Any;
SourceLoc NameLoc;
StringRef Name = P.Tok.getText();
if (P.parseToken(tok::sil_local_name, NameLoc,
@@ -4190,9 +4219,7 @@
if (IsEntry) {
Arg = BB->createFunctionArgument(Ty);
} else {
- Arg = BB->createPHIArgument(
- Ty, OwnershipKind.getValueOr(
- ValueOwnershipKind(ValueOwnershipKind::Any)));
+ Arg = BB->createPHIArgument(Ty, OwnershipKind);
}
setLocalValue(Arg, Name, NameLoc);
} while (P.consumeIf(tok::comma));
@@ -4566,7 +4593,7 @@
}
static AssociatedTypeDecl *parseAssociatedTypeDecl(Parser &P, SILParser &SP,
- ProtocolDecl *proto) {
+ ProtocolDecl *proto) {
Identifier DeclName;
SourceLoc DeclLoc;
if (SP.parseSILIdentifier(DeclName, DeclLoc, diag::expected_sil_value_name))
@@ -4584,6 +4611,59 @@
return dyn_cast<AssociatedTypeDecl>(VD);
}
+static bool parseAssociatedTypePath(SILParser &SP,
+ SmallVectorImpl<Identifier> &path) {
+ do {
+ Identifier name;
+ SourceLoc loc;
+ if (SP.parseSILIdentifier(name, loc, diag::expected_sil_value_name))
+ return false;
+ path.push_back(name);
+ } while (SP.P.consumeIf(tok::period));
+
+ return true;
+}
+
+static bool matchesAssociatedTypePath(CanType assocType,
+ ArrayRef<Identifier> path) {
+ if (auto memberType = dyn_cast<DependentMemberType>(assocType)) {
+ return (!path.empty() &&
+ memberType->getName() == path.back() &&
+ matchesAssociatedTypePath(memberType.getBase(), path.drop_back()));
+ } else {
+ assert(isa<GenericTypeParamType>(assocType));
+ return path.empty();
+ }
+}
+
+static CanType parseAssociatedTypePath(Parser &P, SILParser &SP,
+ ProtocolDecl *proto) {
+ SourceLoc loc = SP.P.Tok.getLoc();
+ SmallVector<Identifier, 4> path;
+ if (!parseAssociatedTypePath(SP, path))
+ return CanType();
+
+ // This is only used for parsing associated conformances, so we can
+ // go ahead and just search the requirement signature for something that
+ // matches the path.
+ for (auto &reqt : proto->getRequirementSignature()->getRequirements()) {
+ if (reqt.getKind() != RequirementKind::Conformance)
+ continue;
+ CanType assocType = reqt.getFirstType()->getCanonicalType();
+ if (matchesAssociatedTypePath(assocType, path))
+ return assocType;
+ }
+
+ SmallString<128> name;
+ name += path[0].str();
+ for (auto elt : makeArrayRef(path).slice(1)) {
+ name += '.';
+ name += elt.str();
+ }
+ P.diagnose(loc, diag::sil_witness_assoc_conf_not_found, name);
+ return CanType();
+}
+
static NormalProtocolConformance *parseNormalProtocolConformance(Parser &P,
SILParser &SP, Type ConformingTy, ProtocolDecl *&proto) {
Identifier ModuleKeyword, ModuleName;
@@ -4827,8 +4907,7 @@
if (EntryKeyword.str() == "associated_type_protocol") {
if (parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
return true;
- AssociatedTypeDecl *assoc = parseAssociatedTypeDecl(*this,
- WitnessState, proto);
+ CanType assoc = parseAssociatedTypePath(*this, WitnessState, proto);
if (!assoc)
return true;
if (parseToken(tok::colon, diag::expected_sil_witness_colon))
@@ -4851,7 +4930,7 @@
}
witnessEntries.push_back(SILWitnessTable::AssociatedTypeProtocolWitness{
- assoc, proto, ProtocolConformanceRef(conformance)
+ assoc, proto, conformance
});
continue;
}
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index a00630c..cbdd9b7 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -620,7 +620,6 @@
return false;
}
-
/// parseAnyIdentifier - Consume an identifier or operator if present and return
/// its name in Result. Otherwise, emit an error and return true.
bool Parser::parseAnyIdentifier(Identifier &Result, SourceLoc &Loc,
diff --git a/lib/SIL/Mangle.cpp b/lib/SIL/Mangle.cpp
index 9e3b8e2..25a1a25 100644
--- a/lib/SIL/Mangle.cpp
+++ b/lib/SIL/Mangle.cpp
@@ -21,6 +21,7 @@
#include "swift/AST/Mangle.h"
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolConformance.h"
+#include "swift/AST/SubstitutionMap.h"
#include "swift/Basic/Punycode.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILType.h"
@@ -44,33 +45,21 @@
// Generic Specialization
//===----------------------------------------------------------------------===//
-static void mangleSubstitution(Mangler &M, Substitution Sub) {
- M.mangleType(Sub.getReplacement()->getCanonicalType(), 0);
- for (auto C : Sub.getConformances()) {
- if (C.isAbstract())
- return;
- M.mangleProtocolConformance(C.getConcrete());
- }
-}
-
void GenericSpecializationMangler::mangleSpecialization() {
Mangler &M = getMangler();
// This is a full specialization.
SILFunctionType *FTy = Function->getLoweredFunctionType();
CanGenericSignature Sig = FTy->getGenericSignature();
-
- unsigned idx = 0;
- for (Type DepType : Sig->getAllDependentTypes()) {
- // It is sufficient to only mangle the substitutions of the "primary"
- // dependent types. As all other dependent types are just derived from the
- // primary types, this will give us unique symbol names.
- if (DepType->is<GenericTypeParamType>()) {
- mangleSubstitution(M, Subs[idx]);
- M.append('_');
+ auto SubMap = Sig->getSubstitutionMap(Subs);
+ for (Type DepType : Sig->getSubstitutableParams()) {
+ M.mangleType(DepType.subst(SubMap)->getCanonicalType(), 0);
+ for (auto C : SubMap.getConformances(DepType->getCanonicalType())) {
+ if (C.isAbstract())
+ return;
+ M.mangleProtocolConformance(C.getConcrete());
}
- ++idx;
+ M.append('_');
}
- assert(idx == Subs.size() && "subs not parallel to dependent types");
}
void PartialSpecializationMangler::mangleSpecialization() {
diff --git a/lib/SIL/PrettyStackTrace.cpp b/lib/SIL/PrettyStackTrace.cpp
index 633ef3c..e7230ed 100644
--- a/lib/SIL/PrettyStackTrace.cpp
+++ b/lib/SIL/PrettyStackTrace.cpp
@@ -18,6 +18,7 @@
#include "swift/SIL/PrettyStackTrace.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILModule.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index 70da549..c8e7eea 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -383,6 +383,7 @@
CONSTANT_OWNERSHIP_INST(Owned, true, UnownedRelease)
CONSTANT_OWNERSHIP_INST(Owned, true, InitExistentialRef)
CONSTANT_OWNERSHIP_INST(Owned, true, OpenExistentialOpaque)
+CONSTANT_OWNERSHIP_INST(Owned, true, EndLifetime)
CONSTANT_OWNERSHIP_INST(Trivial, false, AddressToPointer)
CONSTANT_OWNERSHIP_INST(Trivial, false, BindMemory)
CONSTANT_OWNERSHIP_INST(Trivial, false, CheckedCastAddrBranch)
@@ -476,6 +477,7 @@
ACCEPTS_ANY_OWNERSHIP_INST(UncheckedTrivialBitCast)
ACCEPTS_ANY_OWNERSHIP_INST(ExistentialMetatype)
ACCEPTS_ANY_OWNERSHIP_INST(ValueMetatype)
+ACCEPTS_ANY_OWNERSHIP_INST(UncheckedOwnershipConversion)
#undef ACCEPTS_ANY_OWNERSHIP_INST
// Trivial if trivial typed, otherwise must accept owned?
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 654a13a..0dc077b 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -1234,6 +1234,13 @@
*this << getIDAndType(operand) << " to " << CI->getType();
}
+ void visitUncheckedOwnershipConversionInst(
+ UncheckedOwnershipConversionInst *UOCI) {
+ *this << getIDAndType(UOCI->getOperand()) << ", "
+ << "@" << UOCI->getOperand().getOwnershipKind() << " to "
+ << "@" << UOCI->getConversionOwnershipKind();
+ }
+
void visitConvertFunctionInst(ConvertFunctionInst *CI) {
printUncheckedConversionInst(CI, CI->getOperand());
}
@@ -1549,6 +1556,11 @@
void visitFixLifetimeInst(FixLifetimeInst *RI) {
*this << getIDAndType(RI->getOperand());
}
+
+ void visitEndLifetimeInst(EndLifetimeInst *ELI) {
+ *this << getIDAndType(ELI->getOperand());
+ }
+
void visitMarkDependenceInst(MarkDependenceInst *MDI) {
*this << getIDAndType(MDI->getValue()) << " on "
<< getIDAndType(MDI->getBase());
@@ -2246,6 +2258,19 @@
print(llvm::errs());
}
+/// Returns true if anything was printed.
+static bool printAssociatedTypePath(llvm::raw_ostream &OS, CanType path) {
+ if (auto memberType = dyn_cast<DependentMemberType>(path)) {
+ if (printAssociatedTypePath(OS, memberType.getBase()))
+ OS << '.';
+ OS << memberType->getName().str();
+ return true;
+ } else {
+ assert(isa<GenericTypeParamType>(path));
+ return false;
+ }
+}
+
void SILWitnessTable::print(llvm::raw_ostream &OS, bool Verbose) const {
PrintOptions Options = PrintOptions::printSIL();
PrintOptions QualifiedSILTypeOptions = PrintOptions::printQualifiedSILType();
@@ -2301,9 +2326,9 @@
case AssociatedTypeProtocol: {
// associated_type_protocol (AssociatedTypeName: Protocol): <conformance>
auto &assocProtoWitness = witness.getAssociatedTypeProtocolWitness();
- OS << "associated_type_protocol ("
- << assocProtoWitness.Requirement->getName() << ": "
- << assocProtoWitness.Protocol->getName() << "): ";
+ OS << "associated_type_protocol (";
+ (void) printAssociatedTypePath(OS, assocProtoWitness.Requirement);
+ OS << ": " << assocProtoWitness.Protocol->getName() << "): ";
if (assocProtoWitness.Witness.isConcrete())
assocProtoWitness.Witness.getConcrete()->printName(OS, Options);
else
diff --git a/lib/SIL/SILType.cpp b/lib/SIL/SILType.cpp
index 1a154c7..1cb2a04 100644
--- a/lib/SIL/SILType.cpp
+++ b/lib/SIL/SILType.cpp
@@ -376,7 +376,6 @@
assert(MetatypeType->is<AnyMetatypeType>() &&
"This method should only be called on SILTypes with an underlying "
"metatype type.");
- assert(isObject() && "Should only be called on object types.");
Type instanceType =
MetatypeType->castTo<AnyMetatypeType>()->getInstanceType();
diff --git a/lib/SIL/SILValue.cpp b/lib/SIL/SILValue.cpp
index f9bf589..9c069b5 100644
--- a/lib/SIL/SILValue.cpp
+++ b/lib/SIL/SILValue.cpp
@@ -16,6 +16,7 @@
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILVisitor.h"
+#include "llvm/ADT/StringSwitch.h"
using namespace swift;
@@ -143,6 +144,19 @@
return (LHSVal == RHSVal) ? Optional<ValueOwnershipKind>(*this) : None;
}
+ValueOwnershipKind::ValueOwnershipKind(StringRef S) {
+ auto Result = llvm::StringSwitch<Optional<ValueOwnershipKind::innerty>>(S)
+ .Case("trivial", ValueOwnershipKind::Trivial)
+ .Case("unowned", ValueOwnershipKind::Unowned)
+ .Case("owned", ValueOwnershipKind::Owned)
+ .Case("guaranteed", ValueOwnershipKind::Guaranteed)
+ .Case("any", ValueOwnershipKind::Any)
+ .Default(None);
+ if (!Result.hasValue())
+ llvm_unreachable("Invalid string representation of ValueOwnershipKind");
+ Value = Result.getValue();
+}
+
//===----------------------------------------------------------------------===//
// Instruction ValueOwnershipKind Computation
//===----------------------------------------------------------------------===//
@@ -333,6 +347,7 @@
NO_RESULT_OWNERSHIP_INST(DeinitExistentialAddr)
NO_RESULT_OWNERSHIP_INST(DeinitExistentialOpaque)
NO_RESULT_OWNERSHIP_INST(CondFail)
+NO_RESULT_OWNERSHIP_INST(EndLifetime)
// Terminators. These do not produce SILValue, so they do not have a
// ValueOwnershipKind. They do have ownership implications in terms of the
@@ -459,6 +474,12 @@
return visitForwardingInst(UBCI);
}
+ValueOwnershipKind
+ValueOwnershipKindVisitor::visitUncheckedOwnershipConversionInst(
+ UncheckedOwnershipConversionInst *I) {
+ return I->getConversionOwnershipKind();
+}
+
// An enum without payload is trivial. One with non-trivial payload is
// forwarding.
ValueOwnershipKind
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 541709a..49d7170 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -1649,14 +1649,8 @@
}
// Is a SIL type a potential lowering of a formal type?
- static bool isLoweringOf(SILType loweredType,
- CanType formalType) {
-
-
- // Dynamic self has the same lowering as its contained type.
- if (auto dynamicSelf = dyn_cast<DynamicSelfType>(formalType))
- formalType = CanType(dynamicSelf->getSelfType());
-
+ bool isLoweringOf(SILType loweredType,
+ CanType formalType) {
// Optional lowers its contained type. The difference between Optional
// and IUO is lowered away.
SILType loweredObjectType = loweredType
@@ -1670,9 +1664,10 @@
}
// Metatypes preserve their instance type through lowering.
- if (auto loweredMT = loweredType.getAs<MetatypeType>()) {
+ if (loweredType.is<MetatypeType>()) {
if (auto formalMT = dyn_cast<MetatypeType>(formalType)) {
- return loweredMT.getInstanceType() == formalMT.getInstanceType();
+ return isLoweringOf(loweredType.getMetatypeInstanceType(F.getModule()),
+ formalMT.getInstanceType());
}
}
if (auto loweredEMT = loweredType.getAs<ExistentialMetatypeType>()) {
@@ -1701,7 +1696,11 @@
}
return true;
}
-
+
+ // Dynamic self has the same lowering as its contained type.
+ if (auto dynamicSelf = dyn_cast<DynamicSelfType>(formalType))
+ formalType = dynamicSelf.getSelfType();
+
// Other types are preserved through lowering.
return loweredType.getSwiftRValueType() == formalType;
}
@@ -3011,7 +3010,7 @@
void checkSwitchValueInst(SwitchValueInst *SVI) {
// TODO: Type should be either integer or function
auto Ty = SVI->getOperand()->getType();
- require(Ty.getAs<BuiltinIntegerType>() || Ty.getAs<SILFunctionType>(),
+ require(Ty.is<BuiltinIntegerType>() || Ty.is<SILFunctionType>(),
"switch_value operand should be either of an integer "
"or function type");
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index dbc9b5d..fefc5ec 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -32,12 +32,10 @@
using namespace Lowering;
/// Retrieve the type to use for a method found via dynamic lookup.
-static CanAnyFunctionType getDynamicMethodFormalType(SILGenModule &SGM,
- SILValue proto,
+static CanAnyFunctionType getDynamicMethodFormalType(SILValue proto,
ValueDecl *member,
- SILDeclRef methodName,
Type memberType) {
- auto &ctx = SGM.getASTContext();
+ auto &ctx = member->getASTContext();
CanType selfTy;
if (member->isInstanceMember()) {
selfTy = ctx.TheUnknownObjectType;
@@ -189,9 +187,6 @@
SILValue SelfValue;
SubstitutionList Substitutions;
CanAnyFunctionType OrigFormalInterfaceType;
- CanFunctionType SubstFormalType;
- Optional<SILLocation> SpecializeLoc;
- bool HasSubstitutions = false;
Optional<SmallVector<ManagedValue, 2>> Captures;
// The pointer back to the AST node that produced the callee.
@@ -201,28 +196,24 @@
Callee(ManagedValue indirectValue,
CanAnyFunctionType origFormalType,
- CanFunctionType substFormalType,
SILLocation L)
: kind(Kind::IndirectValue),
IndirectValue(indirectValue),
OrigFormalInterfaceType(origFormalType),
- SubstFormalType(substFormalType),
Loc(L)
{}
static CanAnyFunctionType getConstantFormalInterfaceType(SILGenFunction &gen,
- SILDeclRef fn) {
+ SILDeclRef fn) {
return gen.SGM.Types.getConstantInfo(fn.atUncurryLevel(0))
.FormalInterfaceType;
}
Callee(SILGenFunction &gen, SILDeclRef standaloneFunction,
- CanFunctionType substFormalType,
SILLocation l)
: kind(Kind::StandaloneFunction), Constant(standaloneFunction),
OrigFormalInterfaceType(getConstantFormalInterfaceType(gen,
standaloneFunction)),
- SubstFormalType(substFormalType),
Loc(l)
{
}
@@ -231,170 +222,86 @@
SILGenFunction &gen,
SILValue selfValue,
SILDeclRef methodName,
- CanFunctionType substFormalType,
SILLocation l)
: kind(methodKind), Constant(methodName), SelfValue(selfValue),
OrigFormalInterfaceType(getConstantFormalInterfaceType(gen, methodName)),
- SubstFormalType(substFormalType),
Loc(l)
{
}
- /// Build a clause that looks like 'origParamType' but uses 'selfType'
- /// in place of the underlying archetype.
- static CanType buildSubstSelfType(CanType origParamType, CanType selfType,
- ASTContext &ctx) {
- assert(!isa<LValueType>(origParamType) && "Self can't be @lvalue");
- if (auto lv = dyn_cast<InOutType>(origParamType)) {
- selfType = buildSubstSelfType(lv.getObjectType(), selfType, ctx);
- return CanInOutType::get(selfType);
- }
-
- if (auto tuple = dyn_cast<TupleType>(origParamType)) {
- assert(tuple->getNumElements() == 1);
- selfType = buildSubstSelfType(tuple.getElementType(0), selfType, ctx);
-
- auto field = tuple->getElement(0).getWithType(selfType);
- return CanType(TupleType::get(field, ctx));
- }
-
- assert(isa<MetatypeType>(origParamType) == isa<MetatypeType>(selfType));
- assert(origParamType->getRValueInstanceType()->isTypeParameter());
- assert(selfType->getRValueInstanceType()->is<ArchetypeType>());
-
- return selfType;
- }
-
CanArchetypeType getWitnessMethodSelfType() const {
- return cast<ArchetypeType>(SubstFormalType.getInput()
+ return cast<ArchetypeType>(getSubstFormalType().getInput()
->getRValueInstanceType()
->getCanonicalType());
}
CanSILFunctionType getSubstFunctionType(SILGenModule &SGM,
CanSILFunctionType origFnType) const {
- if (!HasSubstitutions) return origFnType;
-
return origFnType->substGenericArgs(SGM.M, Substitutions);
}
- /// Add the 'self' clause back to the substituted formal type of
- /// this protocol method.
- void addProtocolSelfToFormalType(SILGenModule &SGM, SILDeclRef name,
- CanType protocolSelfType) {
- // The result types of the expressions yielding protocol values
- // (reflected in SubstFormalType) reflect an implicit level of
- // function application, including some extra polymorphic
- // substitution.
- HasSubstitutions = true;
-
- auto &ctx = SGM.getASTContext();
-
- // Add the 'self' parameter back. We want it to look like a
- // substitution of the appropriate clause from the original type.
- auto selfType = OrigFormalInterfaceType.getInput();
- auto substSelfType =
- buildSubstSelfType(selfType, protocolSelfType, ctx);
-
- auto extInfo = FunctionType::ExtInfo(FunctionType::Representation::Thin,
- /*throws*/ OrigFormalInterfaceType->throws());
-
- SubstFormalType = CanFunctionType::get(substSelfType, SubstFormalType,
- extInfo);
- }
-
/// Add the 'self' type to the substituted function type of this
/// dynamic callee.
- void addDynamicCalleeSelfToFormalType(SILGenModule &SGM,
- CanAnyFunctionType substFormalType) {
+ void addDynamicCalleeSelfToFormalType(Type substFormalType) {
assert(kind == Kind::DynamicMethod);
- // Add the dynamic self type to the substituted type. Even if the dynamic
- // callee came from a generic ObjC class, when we find it on AnyObject the
- // parameters should be substituted with their upper bound types.
OrigFormalInterfaceType
- = getDynamicMethodFormalType(SGM, SelfValue,
+ = getDynamicMethodFormalType(SelfValue,
Constant.getDecl(),
- Constant, substFormalType);
+ substFormalType);
assert(!OrigFormalInterfaceType->hasTypeParameter());
-
- // Add a self clause to the substituted type.
- auto selfType = OrigFormalInterfaceType.getInput();
- SubstFormalType
- = CanFunctionType::get(selfType, SubstFormalType,
- OrigFormalInterfaceType->getExtInfo());
}
public:
static Callee forIndirect(ManagedValue indirectValue,
CanAnyFunctionType origFormalType,
- CanFunctionType substFormalType,
SILLocation l) {
- return Callee(indirectValue,
- origFormalType,
- substFormalType,
- l);
+ return Callee(indirectValue, origFormalType, l);
}
static Callee forDirect(SILGenFunction &gen, SILDeclRef c,
- CanFunctionType substFormalType,
SILLocation l) {
- return Callee(gen, c, substFormalType, l);
+ return Callee(gen, c, l);
}
static Callee forEnumElement(SILGenFunction &gen, SILDeclRef c,
- CanFunctionType substFormalType,
SILLocation l) {
assert(isa<EnumElementDecl>(c.getDecl()));
- return Callee(Kind::EnumElement, gen, SILValue(),
- c, substFormalType, l);
+ return Callee(Kind::EnumElement, gen, SILValue(), c, l);
}
static Callee forClassMethod(SILGenFunction &gen, SILValue selfValue,
SILDeclRef name,
- CanFunctionType substFormalType,
SILLocation l) {
- return Callee(Kind::ClassMethod, gen, selfValue, name,
- substFormalType, l);
+ return Callee(Kind::ClassMethod, gen, selfValue, name, l);
}
static Callee forSuperMethod(SILGenFunction &gen, SILValue selfValue,
SILDeclRef name,
- CanFunctionType substFormalType,
SILLocation l) {
while (auto *UI = dyn_cast<UpcastInst>(selfValue))
selfValue = UI->getOperand();
- return Callee(Kind::SuperMethod, gen, selfValue, name,
- substFormalType, l);
+ return Callee(Kind::SuperMethod, gen, selfValue, name, l);
}
static Callee forArchetype(SILGenFunction &gen,
SILValue optOpeningInstruction,
CanType protocolSelfType,
SILDeclRef name,
- CanFunctionType substFormalType,
SILLocation l) {
- Callee callee(Kind::WitnessMethod, gen, optOpeningInstruction, name,
- substFormalType, l);
- callee.addProtocolSelfToFormalType(gen.SGM, name, protocolSelfType);
+ Callee callee(Kind::WitnessMethod, gen, optOpeningInstruction, name, l);
return callee;
}
static Callee forDynamic(SILGenFunction &gen, SILValue proto,
- SILDeclRef name, CanFunctionType substFormalType,
+ SILDeclRef name, Type substFormalType,
SILLocation l) {
- Callee callee(Kind::DynamicMethod, gen, proto, name,
- substFormalType, l);
- callee.addDynamicCalleeSelfToFormalType(gen.SGM, substFormalType);
+ Callee callee(Kind::DynamicMethod, gen, proto, name, l);
+ callee.addDynamicCalleeSelfToFormalType(substFormalType);
return callee;
}
Callee(Callee &&) = default;
Callee &operator=(Callee &&) = default;
- void setSubstitutions(SILGenFunction &gen,
- SILLocation loc,
- SubstitutionList newSubs) {
+ void setSubstitutions(SubstitutionList newSubs) {
assert(Substitutions.empty() && "Already have substitutions?");
Substitutions = newSubs;
-
- SpecializeLoc = loc;
- HasSubstitutions = true;
}
void setCaptures(SmallVectorImpl<ManagedValue> &&captures) {
@@ -416,7 +323,13 @@
}
CanFunctionType getSubstFormalType() const {
- return SubstFormalType;
+ if (auto *gft = OrigFormalInterfaceType->getAs<GenericFunctionType>()) {
+ return cast<FunctionType>(
+ gft->substGenericArgs(getSubstitutions())
+ ->getCanonicalType());
+ }
+
+ return cast<FunctionType>(OrigFormalInterfaceType);
}
unsigned getNaturalUncurryLevel() const {
@@ -452,7 +365,7 @@
case Kind::IndirectValue:
assert(level == 0 && "can't curry indirect function");
mv = IndirectValue;
- assert(!HasSubstitutions);
+ assert(Substitutions.empty());
break;
case Kind::StandaloneFunction: {
@@ -566,8 +479,9 @@
constant = Constant.atUncurryLevel(level);
// Lower the substituted type from the AST, which should have any generic
// parameters in the original signature erased to their upper bounds.
- auto objcFormalType = SubstFormalType.withExtInfo(
- SubstFormalType->getExtInfo()
+ auto substFormalType = getSubstFormalType();
+ auto objcFormalType = substFormalType.withExtInfo(
+ substFormalType->getExtInfo()
.withSILRepresentation(SILFunctionTypeRepresentation::ObjCMethod));
auto fnType = gen.SGM.M.Types
.getUncachedSILFunctionTypeForConstant(*constant, objcFormalType);
@@ -655,7 +569,6 @@
SILGenFunction &gen;
SILLocation loc;
ArgumentSource &selfValue;
- CanFunctionType substFnType;
SILParameterInfo selfParam;
AbstractFunctionDecl *fd;
ProtocolDecl *protocol;
@@ -663,9 +576,8 @@
public:
ArchetypeCalleeBuilder(SILGenFunction &gen, SILLocation loc,
- SILDeclRef inputConstant, ArgumentSource &selfValue,
- CanFunctionType substFnType)
- : gen(gen), loc(loc), selfValue(selfValue), substFnType(substFnType),
+ SILDeclRef inputConstant, ArgumentSource &selfValue)
+ : gen(gen), loc(loc), selfValue(selfValue),
selfParam(), fd(cast<AbstractFunctionDecl>(inputConstant.getDecl())),
protocol(cast<ProtocolDecl>(fd->getDeclContext())),
constant(inputConstant.asForeign(protocol->isObjC())) {}
@@ -687,11 +599,7 @@
setSelfValueToAddress(selfLoc, address);
}
- // The protocol self is implicitly decurried.
- substFnType = cast<FunctionType>(substFnType.getResult());
-
- return Callee::forArchetype(gen, openingSite, getSelfType(), constant,
- substFnType, loc);
+ return Callee::forArchetype(gen, openingSite, getSelfType(), constant, loc);
}
private:
@@ -773,10 +681,9 @@
static Callee prepareArchetypeCallee(SILGenFunction &gen, SILLocation loc,
SILDeclRef constant,
ArgumentSource &selfValue,
- CanFunctionType substFnType,
SubstitutionList &substitutions) {
// Construct an archetype call.
- ArchetypeCalleeBuilder Builder{gen, loc, constant, selfValue, substFnType};
+ ArchetypeCalleeBuilder Builder{gen, loc, constant, selfValue};
return Builder.build();
}
@@ -863,70 +770,18 @@
visit(e);
}
- /// Get the type of the function for substitution purposes.
- ///
- /// \param otherCtorRefUsesAllocating If true, the OtherConstructorDeclRef
- /// refers to the initializing
- CanFunctionType getSubstFnType(bool otherCtorRefUsesAllocating = false) {
- // TODO: optimize this if there are no specializes in play
- auto getSiteType = [&](ApplyExpr *site, bool otherCtorRefUsesAllocating) {
- if (otherCtorRefUsesAllocating) {
- // We have a reference to an initializing constructor, but we will
- // actually be using the allocating constructor. Update the type
- // appropriately.
- // FIXME: Re-derive the type from the declaration + substitutions?
- auto ctorRef = cast<OtherConstructorDeclRefExpr>(site->getSemanticFn());
- auto fnType = ctorRef->getType()->castTo<FunctionType>();
- auto selfTy = MetatypeType::get(
- fnType->getInput()->getInOutObjectType());
- return CanFunctionType::get(selfTy->getCanonicalType(),
- fnType->getResult()->getCanonicalType(),
- fnType->getExtInfo());
- }
-
- return cast<FunctionType>(site->getFn()->getType()->getCanonicalType());
- };
-
- CanFunctionType fnType;
-
- auto addSite = [&](ApplyExpr *site, bool otherCtorRefUsesAllocating) {
- auto siteType = getSiteType(site, otherCtorRefUsesAllocating);
-
- // If this is the first call site, use its formal type directly.
- if (!fnType) {
- fnType = siteType;
- return;
- }
-
- fnType = CanFunctionType::get(siteType.getInput(), fnType,
- siteType->getExtInfo());
- };
-
- for (auto callSite : CallSites) {
- addSite(callSite, false);
- }
-
- // The self application might be a DynamicMemberRefExpr.
- if (auto selfApply = dyn_cast_or_null<ApplyExpr>(SelfApplyExpr)) {
- addSite(selfApply, otherCtorRefUsesAllocating);
- }
-
- assert(fnType && "found no call sites?");
- return fnType;
- }
-
/// Fall back to an unknown, indirect callee.
void visitExpr(Expr *e) {
ManagedValue fn = SGF.emitRValueAsSingleValue(e);
auto origType = cast<AnyFunctionType>(e->getType()->getCanonicalType());
- setCallee(Callee::forIndirect(fn, origType, getSubstFnType(), e));
+ setCallee(Callee::forIndirect(fn, origType, e));
}
void visitLoadExpr(LoadExpr *e) {
// TODO: preserve the function pointer at its original abstraction level
ManagedValue fn = SGF.emitRValueAsSingleValue(e);
auto origType = cast<AnyFunctionType>(e->getType()->getCanonicalType());
- setCallee(Callee::forIndirect(fn, origType, getSubstFnType(), e));
+ setCallee(Callee::forIndirect(fn, origType, e));
}
/// Add a call site to the curry.
@@ -1005,7 +860,6 @@
// to the +0 value in memory. We just pass in the address since
// archetypes are address-only.
- auto substFnType = getSubstFnType();
assert(!CallSites.empty());
ApplyExpr *thisCallSite = CallSites.back();
CallSites.pop_back();
@@ -1039,7 +893,7 @@
// Prepare the callee. This can modify both selfValue and subs.
Callee theCallee = prepareArchetypeCallee(SGF, e, constant, selfValue,
- substFnType, subs);
+ subs);
AssumedPlusZeroSelf = selfValue.isRValue()
&& selfValue.forceAndPeekRValue(SGF).peekIsPlusZeroRValueOrTrivial();
@@ -1048,7 +902,7 @@
// If there are substitutions, add them now.
if (!subs.empty())
- ApplyCallee->setSubstitutions(SGF, e, subs);
+ ApplyCallee->setSubstitutions(subs);
return;
}
@@ -1127,13 +981,11 @@
SILDeclRef::ConstructAtNaturalUncurryLevel,
requiresForeignEntryPoint(afd));
- setCallee(Callee::forClassMethod(SGF, selfValue,
- constant, getSubstFnType(), e));
+ setCallee(Callee::forClassMethod(SGF, selfValue, constant, e));
// If there are substitutions, add them.
if (e->getDeclRef().isSpecialized()) {
- ApplyCallee->setSubstitutions(SGF, e,
- e->getDeclRef().getSubstitutions());
+ ApplyCallee->setSubstitutions(e->getDeclRef().getSubstitutions());
}
return;
@@ -1154,29 +1006,18 @@
&& requiresForeignEntryPoint(e->getDecl()));
// Otherwise, we have a statically-dispatched call.
- CanFunctionType substFnType = getSubstFnType();
-
- auto afd = dyn_cast<AbstractFunctionDecl>(e->getDecl());
- if (afd) {
- // If there are captures, put the placeholder curry level in the formal
- // type.
- // TODO: Eliminate the need for this.
- if (SGF.SGM.M.Types.hasLoweredLocalCaptures(afd))
- substFnType = CanFunctionType::get(
- SGF.getASTContext().TheEmptyTupleType, substFnType);
- }
-
SubstitutionList subs;
if (e->getDeclRef().isSpecialized())
subs = e->getDeclRef().getSubstitutions();
// Enum case constructor references are open-coded.
if (isa<EnumElementDecl>(e->getDecl()))
- setCallee(Callee::forEnumElement(SGF, constant, substFnType, e));
+ setCallee(Callee::forEnumElement(SGF, constant, e));
else
- setCallee(Callee::forDirect(SGF, constant, substFnType, e));
+ setCallee(Callee::forDirect(SGF, constant, e));
// If the decl ref requires captures, emit the capture params.
+ auto afd = dyn_cast<AbstractFunctionDecl>(e->getDecl());
if (afd) {
// FIXME: We should be checking hasLocalCaptures() on the lowered
// captures in the constant info too, to generate more efficient
@@ -1195,7 +1036,7 @@
(!afd ||
!afd->getDeclContext()->isLocalContext() ||
afd->getCaptureInfo().hasGenericParamCaptures()))
- ApplyCallee->setSubstitutions(SGF, e, subs);
+ ApplyCallee->setSubstitutions(subs);
}
void visitAbstractClosureExpr(AbstractClosureExpr *e) {
@@ -1217,24 +1058,10 @@
if (e->getCaptureInfo().hasGenericParamCaptures())
subs = SGF.getForwardingSubstitutions();
- CanFunctionType substFnType = getSubstFnType();
-
- // FIXME: We should be checking hasLocalCaptures() on the lowered
- // captures in the constant info above, to generate more efficient
- // code for mutually recursive local functions which otherwise
- // capture no state.
-
- // If there are captures, put the placeholder curry level in the formal
- // type.
- // TODO: Eliminate the need for this.
- bool hasCaptures = SGF.SGM.M.Types.hasLoweredLocalCaptures(e);
- if (hasCaptures)
- substFnType = CanFunctionType::get(
- SGF.getASTContext().TheEmptyTupleType, substFnType);
-
- setCallee(Callee::forDirect(SGF, constant, substFnType, e));
+ setCallee(Callee::forDirect(SGF, constant, e));
// If the closure requires captures, emit them.
+ bool hasCaptures = SGF.SGM.M.Types.hasLoweredLocalCaptures(e);
if (hasCaptures) {
SmallVector<ManagedValue, 4> captures;
SGF.emitCaptures(e, e, CaptureEmission::ImmediateApplication,
@@ -1243,7 +1070,7 @@
}
// If there are substitutions, add them.
if (!subs.empty())
- ApplyCallee->setSubstitutions(SGF, e, subs);
+ ApplyCallee->setSubstitutions(subs);
}
void visitOtherConstructorDeclRefExpr(OtherConstructorDeclRefExpr *e) {
@@ -1251,12 +1078,11 @@
// constructors imported from Clang (which won't have a direct entry point)
// or to delegate to a designated initializer.
setCallee(Callee::forDirect(SGF,
- SILDeclRef(e->getDecl(), SILDeclRef::Kind::Initializer),
- getSubstFnType(), e));
+ SILDeclRef(e->getDecl(), SILDeclRef::Kind::Initializer), e));
// If there are substitutions, add them.
if (e->getDeclRef().isSpecialized())
- ApplyCallee->setSubstitutions(SGF, e, e->getDeclRef().getSubstitutions());
+ ApplyCallee->setSubstitutions(e->getDeclRef().getSubstitutions());
}
void visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *e) {
setSideEffect(e->getLHS());
@@ -1338,16 +1164,15 @@
if (!canUseStaticDispatch(SGF, constant)) {
// ObjC super calls require dynamic dispatch.
- setCallee(Callee::forSuperMethod(SGF, super.getValue(), constant,
- getSubstFnType(), fn));
+ setCallee(Callee::forSuperMethod(SGF, super.getValue(), constant, fn));
} else {
// Native Swift super calls to final methods are direct.
- setCallee(Callee::forDirect(SGF, constant, getSubstFnType(), fn));
+ setCallee(Callee::forDirect(SGF, constant, fn));
}
// If there are any substitutions for the callee, apply them now.
if (!substitutions.empty())
- ApplyCallee->setSubstitutions(SGF, fn, substitutions);
+ ApplyCallee->setSubstitutions(substitutions);
}
/// Walk the given \c selfArg expression that produces the appropriate
@@ -1508,9 +1333,7 @@
SILDeclRef::ConstructAtNaturalUncurryLevel,
requiresForeignEntryPoint(ctorRef->getDecl()));
setCallee(Callee::forArchetype(SGF, SILValue(),
- self.getType().getSwiftRValueType(), constant,
- cast<FunctionType>(expr->getType()->getCanonicalType()),
- expr));
+ self.getType().getSwiftRValueType(), constant, expr));
} else if (getMethodDispatch(ctorRef->getDecl())
== MethodDispatch::Class) {
// Dynamic dispatch to the initializer.
@@ -1524,7 +1347,7 @@
SILDeclRef::ConstructAtBestResilienceExpansion,
SILDeclRef::ConstructAtNaturalUncurryLevel,
requiresForeignEntryPoint(ctorRef->getDecl())),
- getSubstFnType(), fn));
+ fn));
} else {
// Directly call the peer constructor.
setCallee(
@@ -1537,13 +1360,12 @@
SILDeclRef::ConstructAtBestResilienceExpansion,
SILDeclRef::ConstructAtNaturalUncurryLevel,
requiresForeignEntryPoint(ctorRef->getDecl())),
- getSubstFnType(useAllocatingCtor), fn));
+ fn));
}
// Set up the substitutions, if we have any.
if (ctorRef->getDeclRef().isSpecialized())
- ApplyCallee->setSubstitutions(SGF, fn,
- ctorRef->getDeclRef().getSubstitutions());
+ ApplyCallee->setSubstitutions(ctorRef->getDeclRef().getSubstitutions());
return true;
}
@@ -1634,8 +1456,10 @@
SILDeclRef::ConstructAtNaturalUncurryLevel,
/*isObjC=*/true);
+ auto substFormalType = dynamicMemberRef->getType()
+ ->getAnyOptionalObjectType();
setCallee(Callee::forDynamic(SGF, base.getValue(), member,
- getSubstFnType(), e));
+ substFormalType, e));
};
// When we have an open existential, open it and then emit the
@@ -4712,19 +4536,12 @@
SubstitutionList subs,
ArrayRef<ManagedValue> args,
SGFContext ctx) {
+ auto callee = Callee::forDirect(*this, SILDeclRef(fn), loc);
+ callee.setSubstitutions(subs);
+
auto origFormalType =
cast<AnyFunctionType>(fn->getInterfaceType()->getCanonicalType());
- CanFunctionType substFormalType;
- if (!subs.empty()) {
- auto genericFnType = cast<GenericFunctionType>(origFormalType);
- auto applied = genericFnType->substGenericArgs(subs);
- substFormalType = cast<FunctionType>(applied->getCanonicalType());
- } else {
- substFormalType = cast<FunctionType>(origFormalType);
- }
-
- auto callee = Callee::forDirect(*this, SILDeclRef(fn), substFormalType, loc);
- callee.setSubstitutions(*this, loc, subs);
+ auto substFormalType = callee.getSubstFormalType();
ManagedValue mv;
CanSILFunctionType substFnType;
@@ -4771,37 +4588,12 @@
SILDeclRef::ConstructAtBestResilienceExpansion,
SILDeclRef::ConstructAtNaturalUncurryLevel,
requiresForeignEntryPoint(ctor));
- SILConstantInfo initConstant = SGF.getConstantInfo(initRef);
+ auto initConstant = SGF.getConstantInfo(initRef);
+ auto subs = init.getSubstitutions();
// Scope any further writeback just within this operation.
FormalEvaluationScope writebackScope(SGF);
- // Determine the formal and substituted types.
- CanFunctionType substFormalType;
- auto subs = init.getSubstitutions();
- if (!subs.empty()) {
- auto genericFnType = cast<GenericFunctionType>(
- initConstant.FormalInterfaceType);
- auto applied = genericFnType->substGenericArgs(subs);
- substFormalType = cast<FunctionType>(applied->getCanonicalType());
- } else {
- substFormalType = cast<FunctionType>(initConstant.FormalInterfaceType);
- }
-
- // For an inheritable initializer, determine whether we'll need to adjust the
- // result type.
- bool requiresDowncast = false;
- if (ctor->isInheritable() && overriddenSelfType) {
- CanType substResultType = substFormalType;
- for (unsigned i : range(ctor->getNumParameterLists())) {
- (void)i;
- substResultType = cast<FunctionType>(substResultType).getResult();
- }
-
- if (!substResultType->isEqual(overriddenSelfType))
- requiresDowncast = true;
- }
-
// Form the metatype argument.
ManagedValue selfMetaVal;
SILType selfMetaTy;
@@ -4841,13 +4633,28 @@
RValue(SGF, loc,
selfMetaVal.getType().getSwiftRValueType(),
selfMetaVal));
- callee.emplace(prepareArchetypeCallee(SGF, loc, initRef, selfSource,
- substFormalType, subs));
+ callee.emplace(prepareArchetypeCallee(SGF, loc, initRef, selfSource, subs));
} else {
- callee.emplace(Callee::forDirect(SGF, initRef, substFormalType, loc));
+ callee.emplace(Callee::forDirect(SGF, initRef, loc));
}
if (!subs.empty())
- callee->setSubstitutions(SGF, loc, subs);
+ callee->setSubstitutions(subs);
+
+ auto substFormalType = callee->getSubstFormalType();
+
+ // For an inheritable initializer, determine whether we'll need to adjust the
+ // result type.
+ bool requiresDowncast = false;
+ if (ctor->isInheritable() && overriddenSelfType) {
+ CanType substResultType = substFormalType;
+ for (unsigned i : range(ctor->getNumParameterLists())) {
+ (void)i;
+ substResultType = cast<FunctionType>(substResultType).getResult();
+ }
+
+ if (!substResultType->isEqual(overriddenSelfType))
+ requiresDowncast = true;
+ }
// Form the call emission.
CallEmission emission(SGF, std::move(*callee), std::move(writebackScope));
@@ -5045,7 +4852,6 @@
ArgumentSource &selfValue,
bool isSuper,
bool isDirectUse,
- CanFunctionType substAccessorType,
SubstitutionList &substitutions){
auto *decl = cast<AbstractFunctionDecl>(constant.getDecl());
@@ -5055,7 +4861,7 @@
assert(!isSuper && "super call to protocol method?");
return prepareArchetypeCallee(gen, loc, constant, selfValue,
- substAccessorType, substitutions);
+ substitutions);
}
bool isClassDispatch = false;
@@ -5072,20 +4878,20 @@
// Dispatch in a struct/enum or to a final method is always direct.
if (!isClassDispatch || decl->isFinal())
- return Callee::forDirect(gen, constant, substAccessorType, loc);
+ return Callee::forDirect(gen, constant, loc);
// Otherwise, if we have a non-final class dispatch to a normal method,
// perform a dynamic dispatch.
auto self = selfValue.forceAndPeekRValue(gen).peekScalarValue();
if (!isSuper)
- return Callee::forClassMethod(gen, self, constant, substAccessorType, loc);
+ return Callee::forClassMethod(gen, self, constant, loc);
// If this is a "super." dispatch, we do a dynamic dispatch for objc methods
// or non-final native Swift methods.
if (!canUseStaticDispatch(gen, constant))
- return Callee::forSuperMethod(gen, self, constant, substAccessorType, loc);
+ return Callee::forSuperMethod(gen, self, constant, loc);
- return Callee::forDirect(gen, constant, substAccessorType, loc);
+ return Callee::forDirect(gen, constant, loc);
}
static Callee
@@ -5097,23 +4903,11 @@
bool isSuper,
bool isDirectUse)
{
- SILConstantInfo constantInfo = gen.getConstantInfo(constant);
-
- // Apply substitutions to the callee type.
- CanFunctionType substAccessorType;
- if (!substitutions.empty()) {
- auto genericFn = cast<GenericFunctionType>(constantInfo.FormalInterfaceType);
- auto substFn = genericFn->substGenericArgs(substitutions);
- substAccessorType = cast<FunctionType>(substFn->getCanonicalType());
- } else {
- substAccessorType = cast<FunctionType>(constantInfo.FormalInterfaceType);
- }
-
// Get the accessor function. The type will be a polymorphic function if
// the Self type is generic.
Callee callee = getBaseAccessorFunctionRef(gen, loc, constant, selfValue,
isSuper, isDirectUse,
- substAccessorType, substitutions);
+ substitutions);
// Collect captures if the accessor has them.
auto accessorFn = cast<AbstractFunctionDecl>(constant.getDecl());
@@ -5126,10 +4920,8 @@
}
// If there are substitutions, specialize the generic accessor.
- // FIXME: Generic subscript operator could add another layer of
- // substitutions.
if (!substitutions.empty()) {
- callee.setSubstitutions(gen, loc, substitutions);
+ callee.setSubstitutions(substitutions);
}
return callee;
}
diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp
index b791ed3..954aafa 100644
--- a/lib/SILGen/SILGenBuilder.cpp
+++ b/lib/SILGen/SILGenBuilder.cpp
@@ -511,3 +511,26 @@
SILBuilder::createCheckedCastBranch(loc, isExact, operand.forward(gen), type,
trueBlock, falseBlock);
}
+
+ManagedValue SILGenBuilder::createUpcast(SILLocation Loc, ManagedValue Original,
+ SILType Type) {
+ bool hadCleanup = Original.hasCleanup();
+ bool isLValue = Original.isLValue();
+
+ SILValue convertedValue =
+ SILBuilder::createUpcast(Loc, Original.forward(gen), Type);
+
+ if (isLValue) {
+ return ManagedValue::forLValue(convertedValue);
+ }
+
+ if (!hadCleanup) {
+ return ManagedValue::forUnmanaged(convertedValue);
+ }
+
+ if (Type.isAddress()) {
+ return gen.emitManagedBufferWithCleanup(convertedValue);
+ }
+
+ return gen.emitManagedRValueWithCleanup(convertedValue);
+}
diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h
index 3e4701c..db837d2 100644
--- a/lib/SILGen/SILGenBuilder.h
+++ b/lib/SILGen/SILGenBuilder.h
@@ -226,6 +226,10 @@
ManagedValue operand, SILType type,
SILBasicBlock *trueBlock,
SILBasicBlock *falseBlock);
+
+ using SILBuilder::createUpcast;
+ ManagedValue createUpcast(SILLocation Loc, ManagedValue Original,
+ SILType Type);
};
} // namespace Lowering
diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp
index c160037..77c8103 100644
--- a/lib/SILGen/SILGenConvert.cpp
+++ b/lib/SILGen/SILGenConvert.cpp
@@ -726,8 +726,7 @@
// Convert to an object reference.
value = B.createObjCMetatypeToObject(loc, value, resultTy);
-
- return ManagedValue::forUnmanaged(value);
+ return emitManagedRValueWithCleanup(value);
}
ManagedValue SILGenFunction::emitExistentialMetatypeToObject(SILLocation loc,
@@ -746,7 +745,7 @@
// Convert to an object reference.
value = B.createObjCExistentialMetatypeToObject(loc, value, resultTy);
- return ManagedValue::forUnmanaged(value);
+ return emitManagedRValueWithCleanup(value);
}
ManagedValue SILGenFunction::emitProtocolMetatypeToObject(SILLocation loc,
@@ -763,7 +762,7 @@
// deallocate itself. It doesn't matter if we ever actually clean up that
// retain though.
value = B.createCopyValue(loc, value);
- return ManagedValue::forUnmanaged(value);
+ return emitManagedRValueWithCleanup(value);
}
SILGenFunction::OpaqueValueState
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index cbe0448..8805540 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -1725,56 +1725,23 @@
SILWitnessTable::MethodWitness{requirementRef, witnessFn});
}
- void addAssociatedType(AssociatedTypeDecl *td,
- ArrayRef<ProtocolDecl *> protos) {
+ void addAssociatedType(AssociatedTypeDecl *td) {
// Find the substitution info for the witness type.
const auto &witness = Conformance->getTypeWitness(td, /*resolver=*/nullptr);
// Emit the record for the type itself.
Entries.push_back(SILWitnessTable::AssociatedTypeWitness{td,
- witness.getReplacement()->getCanonicalType()});
+ witness.getReplacement()->getCanonicalType()});
+ }
- // Emit records for the protocol requirements on the type.
- assert(protos.size() == witness.getConformances().size()
- && "number of conformances in assoc type substitution do not match "
- "number of requirements on assoc type");
- // The conformances should be all abstract or all concrete.
- assert(witness.getConformances().empty()
- || (witness.getConformances()[0].isConcrete()
- ? std::all_of(witness.getConformances().begin(),
- witness.getConformances().end(),
- [&](const ProtocolConformanceRef C) -> bool {
- return C.isConcrete();
- })
- : std::all_of(witness.getConformances().begin(),
- witness.getConformances().end(),
- [&](const ProtocolConformanceRef C) -> bool {
- return C.isAbstract();
- })));
+ void addAssociatedConformance(CanType dependentType, ProtocolDecl *protocol) {
+ auto assocConformance =
+ Conformance->getAssociatedConformance(dependentType, protocol);
- for (auto *protocol : protos) {
- // Only reference the witness if the protocol requires it.
- if (!Lowering::TypeConverter::protocolRequiresWitnessTable(protocol))
- continue;
+ SGM.useConformance(assocConformance);
- ProtocolConformanceRef conformance(protocol);
- // If the associated type requirement is satisfied by an associated type,
- // these will all be abstract conformances.
- if (witness.getConformances()[0].isConcrete()) {
- auto foundConformance = std::find_if(witness.getConformances().begin(),
- witness.getConformances().end(),
- [&](ProtocolConformanceRef c) {
- return c.getRequirement() == protocol;
- });
- assert(foundConformance != witness.getConformances().end());
- conformance = *foundConformance;
- }
- SGM.useConformance(conformance);
-
- Entries.push_back(SILWitnessTable::AssociatedTypeProtocolWitness{
- td, protocol, conformance
- });
- }
+ Entries.push_back(SILWitnessTable::AssociatedTypeProtocolWitness{
+ dependentType, protocol, assocConformance});
}
void visitAbstractStorageDecl(AbstractStorageDecl *d) {
@@ -2098,18 +2065,13 @@
DefaultWitnesses.push_back(entry);
}
- void addAssociatedType(AssociatedTypeDecl *ty,
- ArrayRef<ProtocolDecl *> protos) {
- // Add a dummy entry for the metatype itself, and then for each conformance.
+ void addAssociatedType(AssociatedTypeDecl *ty) {
+ // Add a dummy entry for the metatype itself.
addMissingDefault();
+ }
- for (auto *protocol : protos) {
- // Only reference the witness if the protocol requires it.
- if (!Lowering::TypeConverter::protocolRequiresWitnessTable(protocol))
- continue;
-
- addMissingDefault();
- }
+ void addAssociatedConformance(CanType type, ProtocolDecl *requirement) {
+ addMissingDefault();
}
void visitAbstractStorageDecl(AbstractStorageDecl *d) {
diff --git a/lib/SILGen/SILGenDestructor.cpp b/lib/SILGen/SILGenDestructor.cpp
index e6c897e..0d373a1 100644
--- a/lib/SILGen/SILGenDestructor.cpp
+++ b/lib/SILGen/SILGenDestructor.cpp
@@ -12,6 +12,7 @@
#include "SILGenFunction.h"
#include "RValue.h"
+#include "Scope.h"
#include "swift/AST/AST.h"
#include "swift/SIL/TypeLowering.h"
@@ -49,6 +50,7 @@
// If we have a superclass, invoke its destructor.
SILValue resultSelfValue;
SILType objectPtrTy = SILType::getNativeObjectType(F.getASTContext());
+ SILType classTy = selfValue->getType();
if (cd->hasSuperclass()) {
Type superclassTy = dd->mapTypeIntoContext(cd->getSuperclass());
ClassDecl *superclass = superclassTy->getClassOrBoundGenericClass();
@@ -66,13 +68,33 @@
resultSelfValue = B.createApply(cleanupLoc, dtorValue.forward(*this),
dtorTy, objectPtrTy, subs, baseSelf);
} else {
- resultSelfValue = B.createUncheckedRefCast(cleanupLoc, selfValue,
- objectPtrTy);
+ resultSelfValue = selfValue;
}
- // Release our members.
- emitClassMemberDestruction(selfValue, cd, cleanupLoc);
+ {
+ Scope S(Cleanups, cleanupLoc);
+ ManagedValue borrowedResultSelfValue =
+ emitManagedBeginBorrow(cleanupLoc, resultSelfValue);
+ SILValue borrowedValue = borrowedResultSelfValue.getUnmanagedValue();
+ if (classTy != borrowedValue->getType()) {
+ borrowedValue =
+ B.createUncheckedRefCast(cleanupLoc, borrowedValue, classTy);
+ }
+ // Release our members.
+ emitClassMemberDestruction(borrowedValue, cd, cleanupLoc);
+ }
+
+ if (resultSelfValue->getType() != objectPtrTy) {
+ resultSelfValue =
+ B.createUncheckedRefCast(cleanupLoc, resultSelfValue, objectPtrTy);
+ }
+ if (resultSelfValue.getOwnershipKind() != ValueOwnershipKind::Owned) {
+ assert(resultSelfValue.getOwnershipKind() ==
+ ValueOwnershipKind::Guaranteed);
+ resultSelfValue = B.createUncheckedOwnershipConversion(
+ cleanupLoc, resultSelfValue, ValueOwnershipKind::Owned);
+ }
B.createReturn(returnLoc, resultSelfValue);
}
@@ -84,25 +106,45 @@
loc.markAutoGenerated();
// Emit the prolog.
- SILValue selfValue = emitSelfDecl(dd->getImplicitSelfDecl());
+ SILValue initialSelfValue = emitSelfDecl(dd->getImplicitSelfDecl());
// Form a reference to the destroying destructor.
SILDeclRef dtorConstant(dd, SILDeclRef::Kind::Destroyer);
- auto classTy = selfValue->getType();
+ auto classTy = initialSelfValue->getType();
ManagedValue dtorValue;
SILType dtorTy;
SubstitutionList subs = classTy.gatherAllSubstitutions(SGM.M);
std::tie(dtorValue, dtorTy, subs)
- = emitSiblingMethodRef(loc, selfValue, dtorConstant, subs);
+ = emitSiblingMethodRef(loc, initialSelfValue, dtorConstant, subs);
// Call the destroying destructor.
- SILType objectPtrTy = SILType::getNativeObjectType(F.getASTContext());
- selfValue = B.createApply(loc, dtorValue.forward(*this),
- dtorTy, objectPtrTy, subs, selfValue);
+ SILValue selfForDealloc;
+ {
+ FullExpr CleanupScope(Cleanups, CleanupLocation::get(loc));
+ ManagedValue borrowedSelf = emitManagedBeginBorrow(loc, initialSelfValue);
+ SILType objectPtrTy = SILType::getNativeObjectType(F.getASTContext());
+ selfForDealloc = B.createApply(loc, dtorValue.forward(*this),
+ dtorTy, objectPtrTy, subs, borrowedSelf.getUnmanagedValue());
+ }
+
+ // Balance out the +1 from the self argument using end_lifetime.
+ //
+ // The issue here is that:
+ //
+ // 1. Self is passed into deallocating deinits at +1.
+ // 2. Destroying deinits take in self as a +0 value that is then returned at
+ // +1.
+ //
+ // This means that the lifetime of self can not be modeled statically in a
+ // deallocating deinit without analyzing the body of the destroying deinit
+ // (something that violates semantic sil). Thus we add an artifical destroy of
+ // self before the actual destroy of self so that the verifier can understand
+ // that self is being properly balanced.
+ B.createEndLifetime(loc, initialSelfValue);
// Deallocate the object.
- selfValue = B.createUncheckedRefCast(loc, selfValue, classTy);
- B.createDeallocRef(loc, selfValue, false);
+ selfForDealloc = B.createUncheckedRefCast(loc, selfForDealloc, classTy);
+ B.createDeallocRef(loc, selfForDealloc, false);
// Return.
B.createReturn(loc, emitEmptyTuple(loc));
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 7407c7a..ea697f5 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -3619,15 +3619,18 @@
RValue get(SILGenFunction &gen, SILLocation loc,
ManagedValue base, SGFContext c) && override {
+ FullExpr TightBorrowScope(gen.Cleanups, CleanupLocation::get(loc));
+
// Load the value at +0.
- SILValue owned = gen.B.createLoadBorrow(loc, base.getUnmanagedValue());
+ ManagedValue loadedBase = gen.B.createLoadBorrow(loc, base);
// Convert it to unowned.
- auto refType = owned->getType().getSwiftRValueType();
+ auto refType = loadedBase.getType().getSwiftRValueType();
auto unownedType = SILType::getPrimitiveObjectType(
CanUnmanagedStorageType::get(refType));
- SILValue unowned = gen.B.createRefToUnmanaged(loc, owned, unownedType);
-
+ SILValue unowned = gen.B.createRefToUnmanaged(
+ loc, loadedBase.getUnmanagedValue(), unownedType);
+
// A reference type should never be exploded.
return RValue::withPreExplodedElements(ManagedValue::forUnmanaged(unowned),
refType);
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index 53326de..e03e999 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -456,21 +456,17 @@
// Eagerly loading here could cause an unnecessary
// load+materialize in some cases, but it's not really important.
- SILValue selfValue = self.getValue();
- if (selfValue->getType().isAddress()) {
- // SEMANTIC ARC TODO: We are returning self as a borrowed value. Is this
- // correct?
- selfValue = gen.B.createLoadBorrow(loc, selfValue);
+ if (self.getType().isAddress()) {
+ self = gen.B.createLoadBorrow(loc, self);
}
// Do a derived-to-base conversion if necessary.
if (witnessSelfType != SubstSelfType) {
auto selfSILType = gen.getLoweredType(witnessSelfType);
- selfValue = gen.B.createUpcast(loc, selfValue, selfSILType);
+ self = gen.B.createUpcast(loc, self, selfSILType);
}
// Recreate as a borrowed value.
- self = ManagedValue::forUnmanaged(selfValue);
return LValue::forValue(self, witnessSelfType);
}
diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp
index c53f642..7da97fb 100644
--- a/lib/SILGen/SILGenPattern.cpp
+++ b/lib/SILGen/SILGenPattern.cpp
@@ -1792,8 +1792,11 @@
if (elt->isIndirect() || elt->getParentEnum()->isIndirect()) {
SILValue boxedValue = SGF.B.createProjectBox(loc, origCMV.getValue(), 0);
eltTL = &SGF.getTypeLowering(boxedValue->getType());
- if (eltTL->isLoadable())
- boxedValue = SGF.B.createLoadBorrow(loc, boxedValue);
+ if (eltTL->isLoadable()) {
+ ManagedValue newLoadedBoxValue = SGF.B.createLoadBorrow(
+ loc, ManagedValue::forUnmanaged(boxedValue));
+ boxedValue = newLoadedBoxValue.getUnmanagedValue();
+ }
// The boxed value may be shared, so we always have to copy it.
eltCMV = getManagedSubobject(SGF, boxedValue, *eltTL,
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index b5c39b8..0a857f9 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -248,7 +248,7 @@
SILFunctionType::Representation::Thin);
SILFunction *NewF = OrigF->getModule().createFunction(
SILLinkage::Shared, Name, NewFTy,
- /*contextGenericParams*/ nullptr, OrigF->getLocation(), OrigF->isBare(),
+ OrigF->getGenericEnvironment(), OrigF->getLocation(), OrigF->isBare(),
OrigF->isTransparent(), Fragile, OrigF->isThunk(),
OrigF->getClassVisibility(), OrigF->getInlineStrategy(),
OrigF->getEffectsKind(),
diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
index 3edb44d..bbba5d6 100644
--- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
+++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
@@ -22,6 +22,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
using namespace swift;
diff --git a/lib/SILOptimizer/IPO/EagerSpecializer.cpp b/lib/SILOptimizer/IPO/EagerSpecializer.cpp
index c84965c..40fce0f 100644
--- a/lib/SILOptimizer/IPO/EagerSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/EagerSpecializer.cpp
@@ -337,41 +337,30 @@
// SubstitutableTypes, skipping DependentTypes.
auto GenericSig =
GenericFunc->getLoweredFunctionType()->getGenericSignature();
- auto SubIt = ReInfo.getClonerParamSubstitutions().begin();
- auto SubEnd = ReInfo.getClonerParamSubstitutions().end();
- auto DepTypes = GenericSig->getAllDependentTypes();
- for (auto DepTy : DepTypes) {
- assert(SubIt != SubEnd && "Not enough substitutions.");
- if (auto ParamTy = DepTy->getAs<SubstitutableType>()) {
- auto Replacement = SubIt->getReplacement();
- auto GenericEnv = ReInfo.getSpecializedGenericEnvironment();
- if (!Replacement->hasArchetype()) {
- if (GenericEnv)
- Replacement = GenericEnv->mapTypeIntoContext(Replacement);
- assert(!Replacement->hasTypeParameter());
- // Dispatch on concrete type.
- emitTypeCheck(FailedTypeCheckBB, ParamTy, Replacement);
- } else {
- // If Replacement has a layout constraint, then dispatch based
- // on its size and the fact that it is trivial.
- auto LayoutInfo = Replacement->getLayoutConstraint();
- if (LayoutInfo && LayoutInfo->isTrivial()) {
- // Emit a check that it is a trivial type of a certain size.
- emitTrivialAndSizeCheck(FailedTypeCheckBB, ParamTy,
- GenericEnv->mapTypeIntoContext(Replacement),
- LayoutInfo);
- } else if (LayoutInfo && LayoutInfo->isRefCountedObject()) {
- // Emit a check that it is an object of a reference counted type.
- emitRefCountedObjectCheck(FailedTypeCheckBB, ParamTy,
- GenericEnv->mapTypeIntoContext(Replacement),
- LayoutInfo);
- }
+ auto SubMap = GenericSig->getSubstitutionMap(
+ ReInfo.getClonerParamSubstitutions());
+ for (auto ParamTy : GenericSig->getSubstitutableParams()) {
+ auto Replacement = Type(ParamTy).subst(SubMap);
+ assert(!Replacement->hasTypeParameter());
+
+ if (!Replacement->hasArchetype()) {
+ // Dispatch on concrete type.
+ emitTypeCheck(FailedTypeCheckBB, ParamTy, Replacement);
+ } else {
+ // If Replacement has a layout constraint, then dispatch based
+ // on its size and the fact that it is trivial.
+ auto LayoutInfo = Replacement->getLayoutConstraint();
+ if (LayoutInfo && LayoutInfo->isTrivial()) {
+ // Emit a check that it is a trivial type of a certain size.
+ emitTrivialAndSizeCheck(FailedTypeCheckBB, ParamTy,
+ Replacement, LayoutInfo);
+ } else if (LayoutInfo && LayoutInfo->isRefCountedObject()) {
+ // Emit a check that it is an object of a reference counted type.
+ emitRefCountedObjectCheck(FailedTypeCheckBB, ParamTy,
+ Replacement, LayoutInfo);
}
}
- ++SubIt;
}
- assert(SubIt == SubEnd && "Too many substitutions.");
- (void) SubEnd;
static_cast<void>(FailedTypeCheckBB);
if (OldReturnBB == &EntryBB) {
@@ -709,13 +698,9 @@
DEBUG(auto FT = GenericFunc->getLoweredFunctionType();
dbgs() << " Generic Sig:";
dbgs().indent(2); FT->getGenericSignature()->print(dbgs());
- dbgs() << "\n Substituting: <";
- auto depTypes = FT->getGenericSignature()->getAllDependentTypes();
- interleave(depTypes.begin(), depTypes.end(),
- [&](Type t){
- GenericFunc->mapTypeIntoContext(t).print(dbgs()); },
- []{ dbgs() << ", "; });
- dbgs() << "> with ";
+ dbgs() << " Generic Env:";
+ dbgs().indent(2); GenericFunc->getGenericEnvironment()->dump(dbgs());
+ dbgs() << " Specialize Attr:";
SA.print(dbgs()); dbgs() << "\n");
GenericFuncSpecializer
diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp
index 21ce0d6..413bc8c 100644
--- a/lib/SILOptimizer/IPO/GlobalOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp
@@ -240,7 +240,8 @@
auto LoweredType = SILFunctionType::get(nullptr, EInfo,
ParameterConvention::Direct_Owned, { }, Results, None,
Store->getModule().getASTContext());
- auto *GetterF = Store->getModule().getOrCreateFunction(Store->getLoc(),
+ auto *GetterF = Store->getModule().getOrCreateFunction(
+ Store->getLoc(),
getterName, SILLinkage::Private, LoweredType,
IsBare_t::IsBare, IsTransparent_t::IsNotTransparent,
IsFragile_t::IsFragile);
@@ -493,8 +494,9 @@
auto LoweredType = SILFunctionType::get(nullptr, EInfo,
ParameterConvention::Direct_Owned, { }, Results, None,
InitF->getASTContext());
- auto *GetterF = InitF->getModule().getOrCreateFunction(InitF->getLocation(),
- getterName, SILLinkage::Private, LoweredType,
+ auto *GetterF = InitF->getModule().getOrCreateFunction(
+ InitF->getLocation(),
+ getterName, SILLinkage::Private, LoweredType,
IsBare_t::IsBare, IsTransparent_t::IsNotTransparent,
IsFragile_t::IsFragile);
if (InitF->hasUnqualifiedOwnership())
diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
index 4731fe0..fe648ff 100644
--- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp
+++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
@@ -92,20 +92,6 @@
return valueVector.back().second;
}
-
- // Replace entry for `oldValue` with an entry for `newValue` preserving the
- // the mapped ValueStorage.
- void replaceValue(SILValue oldValue, SILValue newValue) {
- auto hashIter = valueHashMap.find(oldValue);
- assert(hashIter != valueHashMap.end() && "Missing SILValue");
- unsigned idx = hashIter->second;
- valueHashMap.erase(hashIter);
-
- valueVector[idx].first = newValue;
-
- auto hashResult = valueHashMap.insert(std::make_pair(newValue, idx));
- assert(hashResult.second && "SILValue already mapped");
- }
};
} // end anonymous namespace
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index 3d8f05c..54b99d4 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -692,39 +692,26 @@
// replaced by a concrete type.
SmallVector<Substitution, 8> Substitutions;
for (auto Subst : AI.getSubstitutions()) {
- auto *A = Subst.getReplacement()->getAs<ArchetypeType>();
- if (A && A == OpenedArchetype) {
- auto Conformances = AI.getModule().getASTContext()
- .AllocateUninitialized<ProtocolConformanceRef>(1);
- Conformances[0] = Conformance;
- Substitution NewSubst(ConcreteType, Conformances);
- Substitutions.push_back(NewSubst);
- } else
- Substitutions.push_back(Subst);
+ auto NewSubst = Subst.subst(
+ AI.getModule().getSwiftModule(),
+ [&](SubstitutableType *type) -> Type {
+ if (type == OpenedArchetype)
+ return ConcreteType;
+ return type;
+ },
+ [&](Type origTy, Type substTy, ProtocolType *protoType)
+ -> Optional<ProtocolConformanceRef> {
+ assert(origTy->isEqual(OpenedArchetype));
+ return Conformance;
+ });
+ Substitutions.push_back(NewSubst);
}
- SILType SubstCalleeType = AI.getSubstCalleeSILType();
-
- SILType NewSubstCalleeType;
-
auto FnTy = AI.getCallee()->getType().castTo<SILFunctionType>();
- if (FnTy->isPolymorphic()) {
- // Handle polymorphic functions by properly substituting
- // their parameter types.
- CanSILFunctionType SFT = FnTy->substGenericArgs(
- AI.getModule(),
- Substitutions);
- NewSubstCalleeType = SILType::getPrimitiveObjectType(SFT);
- } else {
- NewSubstCalleeType =
- SubstCalleeType.subst(AI.getModule(),
- [&](SubstitutableType *type) -> Type {
- if (type == OpenedArchetype)
- return ConcreteType;
- return type;
- },
- MakeAbstractConformanceForGenericType());
- }
+ assert(FnTy->isPolymorphic());
+
+ auto SFT = FnTy->substGenericArgs(AI.getModule(), Substitutions);
+ auto NewSubstCalleeType = SILType::getPrimitiveObjectType(SFT);
FullApplySite NewAI;
Builder.setCurrentDebugScope(AI.getDebugScope());
@@ -732,14 +719,14 @@
if (auto *TAI = dyn_cast<TryApplyInst>(AI))
NewAI = Builder.createTryApply(AI.getLoc(), AI.getCallee(),
- NewSubstCalleeType,
- Substitutions, Args,
- TAI->getNormalBB(), TAI->getErrorBB());
+ NewSubstCalleeType,
+ Substitutions, Args,
+ TAI->getNormalBB(), TAI->getErrorBB());
else
NewAI = Builder.createApply(AI.getLoc(), AI.getCallee(),
- NewSubstCalleeType,
- AI.getType(), Substitutions, Args,
- cast<ApplyInst>(AI)->isNonThrowing());
+ NewSubstCalleeType,
+ AI.getType(), Substitutions, Args,
+ cast<ApplyInst>(AI)->isNonThrowing());
if (isa<ApplyInst>(NewAI))
replaceInstUsesWith(*AI.getInstruction(), NewAI.getInstruction());
@@ -886,21 +873,6 @@
if (WMI->getConformance().isConcrete())
return nullptr;
- // Don't specialize Apply instructions that return the Self type.
- // Notice that it is sufficient to compare the return type to the
- // substituted type because types that depend on the Self type are
- // not allowed (for example [Self] is not allowed).
- if (AI.getType().getSwiftRValueType() == WMI->getLookupType())
- return nullptr;
-
- // We need to handle the Self return type.
- // In we find arguments that are not the 'self' argument and if
- // they are of the Self type then we abort the optimization.
- for (auto Arg : AI.getArgumentsWithoutSelf()) {
- if (Arg->getType().getSwiftRValueType() == WMI->getLookupType())
- return nullptr;
- }
-
// The lookup type is not an opened existential type,
// thus it cannot be made more concrete.
if (!WMI->getLookupType()->isOpenedExistential())
@@ -916,10 +888,10 @@
// Keep around the dependence on the open instruction unless we've
// actually eliminated the use.
auto *NewWMI = Builder.createWitnessMethod(WMI->getLoc(),
- ConcreteType,
- Conformance, WMI->getMember(),
- WMI->getType(),
- WMI->isVolatile());
+ ConcreteType,
+ Conformance, WMI->getMember(),
+ WMI->getType(),
+ WMI->isVolatile());
// Replace only uses of the witness_method in the apply that is going to
// be changed.
MutableArrayRef<Operand> Operands = AI.getInstruction()->getAllOperands();
@@ -957,15 +929,6 @@
if (!Self)
return nullptr;
- // We need to handle the Self return type.
- // In we find arguments that are not the 'self' argument and if
- // they are of the Self type then we abort the optimization.
- for (auto Arg : AI.getArgumentsWithoutSelf()) {
- if (Arg->getType().getSwiftRValueType() ==
- AI.getArguments().back()->getType().getSwiftRValueType())
- return nullptr;
- }
-
// Obtain the protocol whose which should be used by the conformance.
auto *AFD = dyn_cast<AbstractFunctionDecl>(Callee->getDeclContext());
if (!AFD)
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index ce6a1d1..73d41fb 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -488,10 +488,11 @@
DEBUG(llvm::dbgs() << " -> create specialized function " << Name << "\n");
NewF = M.createFunction(linkage, Name, createOptimizedSILFunctionType(),
- nullptr, F->getLocation(), F->isBare(),
- F->isTransparent(), F->isFragile(), F->isThunk(),
- F->getClassVisibility(), F->getInlineStrategy(),
- F->getEffectsKind(), nullptr, F->getDebugScope());
+ F->getGenericEnvironment(), F->getLocation(),
+ F->isBare(), F->isTransparent(), F->isFragile(),
+ F->isThunk(), F->getClassVisibility(),
+ F->getInlineStrategy(), F->getEffectsKind(), nullptr,
+ F->getDebugScope());
if (F->hasUnqualifiedOwnership()) {
NewF->setUnqualifiedOwnership();
}
diff --git a/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp b/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp
index 0ec3d33..db045e7 100644
--- a/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp
+++ b/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp
@@ -64,6 +64,16 @@
EBI->eraseFromParent();
return true;
}
+ bool visitEndLifetimeInst(EndLifetimeInst *ELI) {
+ ELI->eraseFromParent();
+ return true;
+ }
+ bool visitUncheckedOwnershipConversionInst(
+ UncheckedOwnershipConversionInst *UOCI) {
+ UOCI->replaceAllUsesWith(UOCI->getOperand());
+ UOCI->eraseFromParent();
+ return true;
+ }
bool visitUnmanagedRetainValueInst(UnmanagedRetainValueInst *URVI);
bool visitUnmanagedReleaseValueInst(UnmanagedReleaseValueInst *URVI);
bool visitUnmanagedAutoreleaseValueInst(UnmanagedAutoreleaseValueInst *UAVI);
diff --git a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
index fb14a28..6966f78 100644
--- a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
+++ b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
@@ -316,8 +316,7 @@
// specialization for a given call.
static bool canSpecializeGeneric(ApplySite AI, SILFunction *F,
SubstitutionList Subs) {
- ReabstractionInfo ReInfo(AI, F, Subs);
- return ReInfo.canBeSpecialized();
+ return ReabstractionInfo::canBeSpecialized(AI, F, Subs);
}
bool SILPerformanceInliner::isProfitableToInline(FullApplySite AI,
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index 2adfd48..13e8a6f 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -22,6 +22,18 @@
using namespace swift;
+/// Set to true to enable the support for partial specialization.
+llvm::cl::opt<bool> EnablePartialSpecialization(
+ "sil-partial-specialization", llvm::cl::init(false),
+ llvm::cl::desc("Enable partial specialization of generics"));
+
+/// If set, then generic specialization tries to specialize using
+/// all substitutions, even if they the replacement types are generic.
+llvm::cl::opt<bool> SpecializeGenericSubstitutions(
+ "sil-partial-specialization-with-generic-substitutions",
+ llvm::cl::init(false),
+ llvm::cl::desc("Enable partial specialization with generic substitutions"));
+
// Max depth of a bound generic which can be processed by the generic
// specializer.
// E.g. the depth of Array<Array<Array<T>>> is 3.
@@ -49,40 +61,54 @@
// ReabstractionInfo
// =============================================================================
-// Initialize SpecializedType iff the specialization is allowed.
-ReabstractionInfo::ReabstractionInfo(ApplySite Apply, SILFunction *OrigF,
- SubstitutionList ParamSubs) {
- if (!OrigF->shouldOptimize() ||
- OrigF->hasSemanticsAttr("optimize.sil.specialize.generic.never")) {
- DEBUG(llvm::dbgs() << " Cannot specialize function " << OrigF->getName()
- << " marked to be excluded from optimizations.\n");
- return;
+static bool shouldNotSpecializeCallee(SILFunction *Callee) {
+ if (!Callee->shouldOptimize()) {
+ DEBUG(llvm::dbgs() << " Cannot specialize function " << Callee->getName()
+ << " marked to be excluded from optimizations.\n");
+ return true;
}
- OriginalF = OrigF;
- OriginalParamSubs = ParamSubs;
- ClonerParamSubs = ParamSubs;
- CallerParamSubs = ParamSubs;
- SpecializedGenericSig = nullptr;
+ if (Callee->hasSemanticsAttr("optimize.sil.specialize.generic.never"))
+ return true;
+
+ return false;
+}
+
+/// Prepares the ReabstractionInfo object for further processing and checks
+/// if the current function can be specialized at all.
+/// Returns false, if the current function cannot be specialized.
+/// Returns true otherwise.
+bool ReabstractionInfo::prepareAndCheck(ApplySite Apply, SILFunction *Callee,
+ SubstitutionList ParamSubs) {
+ if (shouldNotSpecializeCallee(Callee))
+ return false;
+
SpecializedGenericEnv = nullptr;
+ SpecializedGenericSig = nullptr;
+ OriginalParamSubs = ParamSubs;
+ auto CalleeGenericSig = Callee->getLoweredFunctionType()->getGenericSignature();
+ auto CalleeGenericEnv = Callee->getGenericEnvironment();
+
+ OriginalF = Callee;
+ this->Apply = Apply;
SubstitutionMap InterfaceSubs;
- if (OrigF->getLoweredFunctionType()->getGenericSignature())
- InterfaceSubs = OrigF->getLoweredFunctionType()->getGenericSignature()
- ->getSubstitutionMap(ParamSubs);
+
+ // Get the original substitution map.
+ if (CalleeGenericSig)
+ InterfaceSubs = CalleeGenericSig->getSubstitutionMap(ParamSubs);
// We do not support partial specialization.
- if (InterfaceSubs.hasArchetypes()) {
- DEBUG(llvm::dbgs() <<
- " Cannot specialize with unbound interface substitutions.\n");
- DEBUG(for (auto Sub : ParamSubs) {
- Sub.dump();
- });
- return;
+ if (!EnablePartialSpecialization && InterfaceSubs.hasArchetypes()) {
+ DEBUG(llvm::dbgs() << " Partial specialization is not supported.\n");
+ DEBUG(for (auto Sub : ParamSubs) { Sub.dump(); });
+ return false;
}
+
+ // Perform some checks to see if we need to bail.
if (InterfaceSubs.hasDynamicSelf()) {
DEBUG(llvm::dbgs() << " Cannot specialize with dynamic self.\n");
- return;
+ return false;
}
// Check if the substitution contains any generic types that are too deep.
@@ -93,46 +119,175 @@
if (Replacement.findIf([](Type ty) -> bool {
return getBoundGenericDepth(ty) >= BoundGenericDepthThreshold;
})) {
- return;
+ DEBUG(llvm::dbgs()
+ << " Cannot specialize because the generic type is too deep.\n");
+ return false;
}
}
- SILModule &M = OrigF->getModule();
- SubstitutedType = OrigF->getLoweredFunctionType()->substGenericArgs(
- M, InterfaceSubs);
+ // Check if we have substitutions which replace generic type parameters with
+ // concrete types or unbound generic types.
+ bool HasConcreteGenericParams = false;
+ bool HasNonArchetypeGenericParams = false;
+ HasUnboundGenericParams = false;
+ for (auto DT : CalleeGenericSig->getGenericParams()) {
+ // Check only the substitutions for the generic parameters.
+ // Ignore any dependent types, etc.
+ auto Replacement = Type(DT).subst(InterfaceSubs);
+ if (!Replacement->is<ArchetypeType>())
+ HasNonArchetypeGenericParams = true;
- NumFormalIndirectResults = SubstitutedType->getNumIndirectFormalResults();
- Conversions.resize(NumFormalIndirectResults
- + SubstitutedType->getParameters().size());
- if (SubstitutedType->getNumDirectFormalResults() == 0) {
- // The original function has no direct result yet. Try to convert the first
- // indirect result to a direct result.
- // TODO: We could also convert multiple indirect results by returning a
- // tuple type and created tuple_extract instructions at the call site.
- SILFunctionConventions substConv(SubstitutedType, M);
- unsigned IdxForResult = 0;
- for (SILResultInfo RI : SubstitutedType->getIndirectFormalResults()) {
- assert(RI.isFormalIndirect());
- if (substConv.getSILType(RI).isLoadable(M) && !RI.getType()->isVoid()) {
- Conversions.set(IdxForResult);
- break;
+ if (Replacement->hasArchetype()) {
+ HasUnboundGenericParams = true;
+ // Check if the replacement is an archetype which is more specific
+ // than the corresponding archetype in the original generic signature.
+ // If this is the case, then specialization makes sense, because
+ // it would produce something more specific.
+ if (CalleeGenericEnv) {
+ if (auto Archetype = Replacement->getAs<ArchetypeType>()) {
+ auto OrigArchetype =
+ CalleeGenericEnv->mapTypeIntoContext(DT)->castTo<ArchetypeType>();
+ if (Archetype->requiresClass() && !OrigArchetype->requiresClass())
+ HasNonArchetypeGenericParams = true;
+ if (Archetype->getLayoutConstraint() &&
+ !OrigArchetype->getLayoutConstraint())
+ HasNonArchetypeGenericParams = true;
+ }
}
- ++IdxForResult;
+ continue;
+ }
+
+ HasConcreteGenericParams = true;
+ }
+
+ if (HasUnboundGenericParams) {
+ if (!HasNonArchetypeGenericParams && !HasConcreteGenericParams) {
+ DEBUG(llvm::dbgs() << " Partial specialization is not supported if "
+ "all substitutions are archetypes.\n");
+ DEBUG(for (auto Sub : ParamSubs) {
+ Sub.dump();
+ });
+ return false;
+ }
+
+ // We need a generic environment for the partial specialization.
+ if (!CalleeGenericEnv)
+ return false;
+ }
+
+ return true;
+}
+
+bool ReabstractionInfo::canBeSpecialized(ApplySite Apply, SILFunction *Callee,
+ SubstitutionList ParamSubs) {
+ ReabstractionInfo ReInfo;
+ return ReInfo.prepareAndCheck(Apply, Callee, ParamSubs);
+}
+
+ReabstractionInfo::ReabstractionInfo(ApplySite Apply, SILFunction *Callee,
+ ArrayRef<Substitution> ParamSubs) {
+ if (!prepareAndCheck(Apply, Callee, ParamSubs))
+ return;
+
+ if (SpecializeGenericSubstitutions) {
+ specializeConcreteAndGenericSubstitutions(Apply, Callee, ParamSubs);
+ } else {
+ specializeConcreteSubstitutions(Apply, Callee, ParamSubs);
+ }
+
+ if (SpecializedGenericSig) {
+ DEBUG(llvm::dbgs() << "\n\nPartially specialized types for function: "
+ << Callee->getName() << "\n\n";
+ llvm::dbgs() << "Original generic function type:\n"
+ << Callee->getLoweredFunctionType() << "\n"
+ << "Partially specialized generic function type:\n"
+ << SpecializedType << "\n\n");
+ }
+
+ // Some sanity checks.
+ auto SpecializedFnTy = getSpecializedType();
+ auto SpecializedSubstFnTy = SpecializedFnTy;
+
+ if (SpecializedFnTy->isPolymorphic() &&
+ !getCallerParamSubstitutions().empty()) {
+ auto CalleeFnTy = Callee->getLoweredFunctionType();
+ assert(CalleeFnTy->isPolymorphic());
+ auto CalleeSubstFnTy = CalleeFnTy->substGenericArgs(
+ Callee->getModule(), getOriginalParamSubstitutions());
+ assert(!CalleeSubstFnTy->isPolymorphic() &&
+ "Substituted callee type should not be polymorphic");
+ assert(!CalleeSubstFnTy->hasTypeParameter() &&
+ "Substituted callee type should not have type parameters");
+
+ SpecializedSubstFnTy = SpecializedFnTy->substGenericArgs(
+ Callee->getModule(), getCallerParamSubstitutions());
+
+ assert(!SpecializedSubstFnTy->isPolymorphic() &&
+ "Substituted callee type should not be polymorphic");
+ assert(!SpecializedSubstFnTy->hasTypeParameter() &&
+ "Substituted callee type should not have type parameters");
+
+ auto SpecializedCalleeSubstFnTy =
+ createSpecializedType(CalleeSubstFnTy, Callee->getModule());
+
+ if (SpecializedSubstFnTy != SpecializedCalleeSubstFnTy) {
+ llvm::dbgs() << "SpecializedFnTy:\n" << SpecializedFnTy << "\n";
+ llvm::dbgs() << "SpecializedSubstFnTy:\n" << SpecializedSubstFnTy << "\n";
+ for (auto Sub : getCallerParamSubstitutions()) {
+ llvm::dbgs() << "Sub:\n";
+ Sub.dump();
+ }
+ llvm::dbgs() << "\n\n";
+
+ llvm::dbgs() << "CalleeFnTy:\n" << CalleeFnTy << "\n";
+ llvm::dbgs() << "SpecializedCalleeSubstFnTy:\n" << SpecializedCalleeSubstFnTy << "\n";
+ for (auto Sub : ParamSubs) {
+ llvm::dbgs() << "Sub:\n";
+ Sub.dump();
+ }
+ llvm::dbgs() << "\n\n";
+ assert(SpecializedSubstFnTy == SpecializedCalleeSubstFnTy &&
+ "Substituted function types should be the same");
}
}
- // Try to convert indirect incoming parameters to direct parameters.
- // The Conversions index domain is
- // [0..<NumFormalIndirectResults + NumParameters]. This is *not* the same as
- // a SubstitutedType's SIL argument index.
- unsigned IdxForParam = NumFormalIndirectResults;
- for (SILParameterInfo PI : SubstitutedType->getParameters()) {
- if (PI.getSILStorageType().isLoadable(M)
- && PI.getConvention() == ParameterConvention::Indirect_In) {
- Conversions.set(IdxForParam);
- }
- ++IdxForParam;
+
+ // If the new type is the same, there is nothing to do and
+ // no specialization should be performed.
+ if (getSubstitutedType() == Callee->getLoweredFunctionType()) {
+ DEBUG(llvm::dbgs() << "The new specialized type is the same as "
+ "the original "
+ "type. Don't specialize!\n";
+ llvm::dbgs() << "The type is: " << getSubstitutedType() << "\n");
+ SpecializedType = CanSILFunctionType();
+ SubstitutedType = CanSILFunctionType();
+ SpecializedGenericSig = nullptr;
+ return;
}
- SpecializedType = createSpecializedType(SubstitutedType, M);
+
+ if (SpecializedGenericSig) {
+ // It is a partial specializaiton.
+ DEBUG(llvm::dbgs() << "Specializing the call:\n";
+ Apply.getInstruction()->dumpInContext();
+ llvm::dbgs() << "\n\nPartially specialized types for function: "
+ << Callee->getName() << "\n\n";
+ llvm::dbgs() << "Original generic function type:\n"
+ << Callee->getLoweredFunctionType() << "\n\n";
+ llvm::dbgs() << "\nOriginal call substitution:\n";
+ for (auto Sub : getOriginalParamSubstitutions()) {
+ llvm::dbgs() << "Sub:\n";
+ Sub.dump();
+ llvm::dbgs() << "\n";
+ }
+
+ llvm::dbgs() << "Partially specialized generic function type:\n"
+ << getSpecializedType() << "\n\n";
+ llvm::dbgs() << "\nSpecialization call substitution:\n";
+ for (auto Sub : getCallerParamSubstitutions()) {
+ llvm::dbgs() << "Sub:\n";
+ Sub.dump();
+ llvm::dbgs() << "\n";
+ });
+ }
}
bool ReabstractionInfo::canBeSpecialized() const {
@@ -210,11 +365,6 @@
const SubstitutionMap &SubstMap,
bool HasUnboundGenericParams) {
auto &M = OrigF->getModule();
- auto OrigFnTy = OrigF->getLoweredFunctionType();
-
- // First substitute concrete types into the existing function type.
- auto FnTy = OrigFnTy->substGenericArgs(M, SubstMap);
-
if ((SpecializedGenericSig &&
SpecializedGenericSig->areAllParamsConcrete()) ||
!HasUnboundGenericParams) {
@@ -222,11 +372,24 @@
SpecializedGenericEnv = nullptr;
}
+ CanGenericSignature CanSpecializedGenericSig;
+ if (SpecializedGenericSig)
+ CanSpecializedGenericSig = SpecializedGenericSig->getCanonicalSignature();
+
+ // First substitute concrete types into the existing function type.
+ CanSILFunctionType FnTy;
+ {
+ Lowering::GenericContextScope GenericScope(M.Types,
+ CanSpecializedGenericSig);
+ FnTy = OrigF->getLoweredFunctionType()->substGenericArgs(M, SubstMap);
+ }
+ assert(FnTy);
+
// Use the new specialized generic signature.
auto NewFnTy = SILFunctionType::get(
- SpecializedGenericSig, FnTy->getExtInfo(), FnTy->getCalleeConvention(),
- FnTy->getParameters(), FnTy->getResults(),
- FnTy->getOptionalErrorResult(), M.getASTContext());
+ CanSpecializedGenericSig, FnTy->getExtInfo(), FnTy->getCalleeConvention(),
+ FnTy->getParameters(), FnTy->getResults(), FnTy->getOptionalErrorResult(),
+ M.getASTContext());
// This is an interface type. It should not have any archetypes.
assert(!NewFnTy->hasArchetype());
@@ -280,6 +443,25 @@
M.getASTContext());
}
+static std::pair<GenericEnvironment *, GenericSignature *>
+getGenericEnvironmentAndSignature(GenericSignatureBuilder &Builder,
+ SILModule &M) {
+ auto *GenericSig =
+ Builder.getGenericSignature()->getCanonicalSignature().getPointer();
+ auto *GenericEnv = GenericSig->createGenericEnvironment(*M.getSwiftModule());
+
+ // FIXME: This is a workaround for the signature minimization bug.
+ GenericSignatureBuilder TmpBuilder(
+ M.getASTContext(), LookUpConformanceInModule(M.getSwiftModule()));
+ TmpBuilder.addGenericSignature(GenericSig);
+ TmpBuilder.finalize(SourceLoc(), GenericSig->getGenericParams());
+ GenericSig =
+ TmpBuilder.getGenericSignature()->getCanonicalSignature().getPointer();
+ GenericEnv = GenericSig->createGenericEnvironment(*M.getSwiftModule());
+
+ return std::make_pair(GenericEnv, GenericSig);
+}
+
std::pair<GenericEnvironment *, GenericSignature *>
getSignatureWithRequirements(GenericSignature *OrigGenSig,
GenericEnvironment *OrigGenericEnv,
@@ -301,11 +483,7 @@
}
Builder.finalize(SourceLoc(), OrigGenSig->getGenericParams());
- auto *GenericSig = Builder.getGenericSignature();
- // Remember the new generic environment.
- auto *GenericEnv = GenericSig->createGenericEnvironment(*M.getSwiftModule());
-
- return std::make_pair(GenericEnv, GenericSig);
+ return getGenericEnvironmentAndSignature(Builder, M);
}
/// Perform some sanity checks for the requirements
@@ -340,11 +518,8 @@
ReabstractionInfo::ReabstractionInfo(SILFunction *OrigF,
ArrayRef<Requirement> Requirements) {
- if (!OrigF->shouldOptimize()) {
- DEBUG(llvm::dbgs() << " Cannot specialize function " << OrigF->getName()
- << " marked to be excluded from optimizations.\n");
+ if (shouldNotSpecializeCallee(OrigF))
return;
- }
// Perform some sanity checks for the requirements
checkSpecializationRequirements(Requirements);
@@ -399,6 +574,138 @@
createSubstitutedAndSpecializedTypes();
}
+static void verifySubstitutionList(SubstitutionList Subs) {
+ for (auto Sub : Subs) {
+ assert(!Sub.getReplacement()->hasError() &&
+ "There should be no error types in substitutions");
+ }
+}
+
+// Builds a new signature based on the old one and adds same type
+// requirements for those generic type parameters that are concrete
+// according to the partial substitution. This way, the signature
+// has exactly the same generic parameter types, just with more
+// requirements.
+// Current issues:
+// - If Sig2 = GenericSignatureBuilder(Sig2 + Req), then GenericSignatureBuilder(Sig2) != Sig2
+// - The set of requirements is not really minimized.
+// - Some requirements are lost, when you add a same type parameter to the builder.
+
+// Initialize SpecializedType if and only if the specialization is allowed.
+void ReabstractionInfo::specializeConcreteSubstitutions(
+ ApplySite Apply, SILFunction *Callee, ArrayRef<Substitution> ParamSubs) {
+
+ SILModule &M = Callee->getModule();
+ auto &Ctx = M.getASTContext();
+
+ OriginalF = Callee;
+
+ auto OrigGenericSig = Callee->getLoweredFunctionType()->getGenericSignature();
+ auto OrigGenericEnv = Callee->getGenericEnvironment();
+
+ SubstitutionMap InterfaceSubs;
+ // Get the original substitution map.
+ if (Callee->getLoweredFunctionType()->getGenericSignature())
+ InterfaceSubs = Callee->getLoweredFunctionType()->getGenericSignature()
+ ->getSubstitutionMap(ParamSubs);
+
+ // This is a workaround for the rdar://30610428
+ if (!EnablePartialSpecialization) {
+ SubstitutedType =
+ Callee->getLoweredFunctionType()->substGenericArgs(M, InterfaceSubs);
+ ClonerParamSubs = OriginalParamSubs;
+ CallerParamSubs = {};
+ createSubstitutedAndSpecializedTypes();
+ return;
+ }
+
+ // Build a set of requirements.
+ SmallVector<Requirement, 4> Requirements;
+
+ for (auto DP : OrigGenericSig->getGenericParams()) {
+ auto Replacement = Type(DP).subst(InterfaceSubs);
+ if (Replacement->hasArchetype())
+ continue;
+ // Replacemengt is concrete. Add a same type requirement.
+ Requirement Req(RequirementKind::SameType, DP, Replacement);
+ Requirements.push_back(Req);
+ }
+
+ std::tie(SpecializedGenericEnv, SpecializedGenericSig) =
+ getSignatureWithRequirements(OrigGenericSig, OrigGenericEnv,
+ Requirements, M);
+ HasUnboundGenericParams = !SpecializedGenericSig->areAllParamsConcrete();
+
+ // No partial specializations!
+ //if (HasUnboundGenericParams)
+ // return;
+
+ {
+ SmallVector<Substitution, 4> List;
+
+ OrigGenericSig->getSubstitutions(
+ [&](SubstitutableType *type) -> Type {
+ return SpecializedGenericEnv->mapTypeIntoContext(type);
+ },
+ LookUpConformanceInSignature(*SpecializedGenericSig),
+ List);
+ ClonerParamSubs = Ctx.AllocateCopy(List);
+ verifySubstitutionList(ClonerParamSubs);
+ }
+
+ {
+ SmallVector<Substitution, 4> List;
+ SpecializedGenericSig->getSubstitutions(InterfaceSubs, List);
+ CallerParamSubs = Ctx.AllocateCopy(List);
+ verifySubstitutionList(CallerParamSubs);
+ }
+
+ {
+ CallerInterfaceSubs = OrigGenericSig->getSubstitutionMap(
+ [&](SubstitutableType *type) -> Type {
+ return SpecializedGenericEnv->mapTypeOutOfContext(
+ SpecializedGenericEnv->mapTypeIntoContext(type));
+ },
+ //LookUpConformanceInSignature(*SpecializedGenericSig));
+ LookUpConformanceInSignature(*OrigGenericSig));
+ }
+
+ HasUnboundGenericParams = !SpecializedGenericSig->areAllParamsConcrete();
+ createSubstitutedAndSpecializedTypes();
+}
+
+// Builds a new generic and function signatures for a partial specialization.
+// Allows for partial specializations even if substitututions contain
+// type parameters.
+//
+// The new generic signature has the following generic parameters:
+// - For each substitution with a concrete type CT as a replacement for a generic
+// type T, it introduces a generic parameter T' and a requirement T' == CT
+// - For all other substitutions that are considered for partial specialization,
+// it collects first the archetypes used in the replacements. Then for each such
+// archetype A a new generic parameter T' introduced.
+// - If there is a substitution for type T and this substitution is execluded from
+// partial specialization (e.g. because it is impossible or would result in a less
+// efficient code), then a new generic parameter T' is introduced, which does not
+// get any additional, more specific requirements based on the substitutions.
+//
+// After all generic parameters are added accoriding to the rules above,
+// the requirements of the callee's signature are re-mapped by re-formulating them
+// in terms of the newly introduced generic parameters. In case a remapped
+// requirement does not contain any generic types, it can be omitted, because
+// it is fulfilled already.
+
+// Current issues:
+// - If Sig2 = GenericSignatureBuilder(Sig2 + Req), then
+// GenericSignatureBuilder(Sig2) != Sig2
+// - The set of requirements is not really minimized.
+// - Some requirements are lost, when you add a same type parameter to the
+// builder.
+void ReabstractionInfo::specializeConcreteAndGenericSubstitutions(
+ ApplySite Apply, SILFunction *Callee, ArrayRef<Substitution> ParamSubs) {
+ llvm_unreachable("Not implemented yet");
+}
+
// =============================================================================
// GenericFuncSpecializer
// =============================================================================
@@ -505,16 +812,13 @@
VoidVal->replaceAllUsesWith(NewVoidVal);
}
-// Create a new apply based on an old one, but with a different
-// function being applied.
-static ApplySite replaceWithSpecializedCallee(ApplySite AI,
- SILValue Callee,
- SILBuilder &Builder,
- const ReabstractionInfo &ReInfo) {
- SILLocation Loc = AI.getLoc();
- SmallVector<SILValue, 4> Arguments;
- SILValue StoreResultTo;
+// Prepare call arguments. Perform re-abstraction if required.
+static void prepareCallArguments(ApplySite AI, SILBuilder &Builder,
+ const ReabstractionInfo &ReInfo,
+ SmallVectorImpl<SILValue> &Arguments,
+ SILValue &StoreResultTo) {
/// SIL function conventions for the original apply site with substitutions.
+ SILLocation Loc = AI.getLoc();
auto substConv = AI.getSubstCalleeConv();
unsigned ArgIdx = AI.getCalleeArgIndexOfFirstAppliedArg();
for (auto &Op : AI.getArgumentOperands()) {
@@ -553,13 +857,58 @@
++ArgIdx;
}
+}
+
+/// Return a substituted callee function type.
+static CanSILFunctionType
+getCalleeSubstFunctionType(SILValue Callee, const ReabstractionInfo &ReInfo) {
+ // Create a substituted callee type.
+ auto CanFnTy =
+ dyn_cast<SILFunctionType>(Callee->getType().getSwiftRValueType());
+ auto CalleeSubstFnTy = CanFnTy;
+
+ if (ReInfo.getSpecializedType()->isPolymorphic() &&
+ !ReInfo.getCallerParamSubstitutions().empty()) {
+ CalleeSubstFnTy = CanFnTy->substGenericArgs(
+ ReInfo.getNonSpecializedFunction()->getModule(),
+ ReInfo.getCallerParamSubstitutions());
+ assert(!CalleeSubstFnTy->isPolymorphic() &&
+ "Substituted callee type should not be polymorphic");
+ assert(!CalleeSubstFnTy->hasTypeParameter() &&
+ "Substituted callee type should not have type parameters");
+ }
+
+ return CalleeSubstFnTy;
+}
+
+// Create a new apply based on an old one, but with a different
+// function being applied.
+static ApplySite replaceWithSpecializedCallee(ApplySite AI,
+ SILValue Callee,
+ SILBuilder &Builder,
+ const ReabstractionInfo &ReInfo) {
+ SILLocation Loc = AI.getLoc();
+ SmallVector<SILValue, 4> Arguments;
+ SILValue StoreResultTo;
+
+ prepareCallArguments(AI, Builder, ReInfo, Arguments, StoreResultTo);
+
+ // Create a substituted callee type.
+ ArrayRef<Substitution> Subs;
+ if (ReInfo.getSpecializedType()->isPolymorphic()) {
+ Subs = ReInfo.getCallerParamSubstitutions();
+ }
+
+ auto CalleeSubstFnTy = getCalleeSubstFunctionType(Callee, ReInfo);
+ auto CalleeSILSubstFnTy = SILType::getPrimitiveObjectType(CalleeSubstFnTy);
+ SILFunctionConventions substConv(CalleeSubstFnTy, Builder.getModule());
if (auto *TAI = dyn_cast<TryApplyInst>(AI)) {
SILBasicBlock *ResultBB = TAI->getNormalBB();
assert(ResultBB->getSinglePredecessorBlock() == TAI->getParent());
auto *NewTAI =
- Builder.createTryApply(Loc, Callee, Callee->getType(), {},
- Arguments, ResultBB, TAI->getErrorBB());
+ Builder.createTryApply(Loc, Callee, CalleeSILSubstFnTy, Subs, Arguments,
+ ResultBB, TAI->getErrorBB());
if (StoreResultTo) {
assert(substConv.useLoweredAddresses());
// The original normal result of the try_apply is an empty tuple.
@@ -577,7 +926,9 @@
return NewTAI;
}
if (auto *A = dyn_cast<ApplyInst>(AI)) {
- auto *NewAI = Builder.createApply(Loc, Callee, Arguments, A->isNonThrowing());
+ auto *NewAI = Builder.createApply(Loc, Callee, CalleeSILSubstFnTy,
+ substConv.getSILResultType(), Subs,
+ Arguments, A->isNonThrowing());
if (StoreResultTo) {
assert(substConv.useLoweredAddresses());
// Store the direct result to the original result address.
@@ -589,12 +940,14 @@
return NewAI;
}
if (auto *PAI = dyn_cast<PartialApplyInst>(AI)) {
- CanSILFunctionType NewPAType =
- ReInfo.createSpecializedType(PAI->getFunctionType(), Builder.getModule());
- SILType PTy = SILType::getPrimitiveObjectType(ReInfo.getSpecializedType());
+ CanSILFunctionType NewPAType = ReInfo.createSpecializedType(
+ PAI->getFunctionType(), Builder.getModule());
+ // SILType PTy =
+ // SILType::getPrimitiveObjectType(ReInfo.getSpecializedType());
+ SILType PTy = CalleeSILSubstFnTy;
auto *NewPAI =
- Builder.createPartialApply(Loc, Callee, PTy, {}, Arguments,
- SILType::getPrimitiveObjectType(NewPAType));
+ Builder.createPartialApply(Loc, Callee, PTy, Subs, Arguments,
+ SILType::getPrimitiveObjectType(NewPAType));
PAI->replaceAllUsesWith(NewPAI);
return NewPAI;
}
@@ -835,6 +1188,9 @@
if (F->isFragile() && !RefF->hasValidLinkageForFragileInline())
return;
+ if (shouldNotSpecializeCallee(RefF))
+ return;
+
// If the caller and callee are both fragile, preserve the fragility when
// cloning the callee. Otherwise, strip it off so that we can optimize
// the body more.
@@ -851,6 +1207,12 @@
bool needAdaptUsers = false;
bool replacePartialApplyWithoutReabstraction = false;
auto *PAI = dyn_cast<PartialApplyInst>(Apply);
+
+ // TODO: Partial specializations of partial applies are
+ // not supported yet.
+ if (PAI && ReInfo.getSpecializedType()->isPolymorphic())
+ return;
+
if (PAI && ReInfo.hasConversions()) {
// If we have a partial_apply and we converted some results/parameters from
// indirect to direct there are 3 cases:
diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp
index a01756c..6d4a293 100644
--- a/lib/SILOptimizer/Utils/SILInliner.cpp
+++ b/lib/SILOptimizer/Utils/SILInliner.cpp
@@ -233,6 +233,8 @@
case ValueKind::FunctionRefInst:
case ValueKind::AllocGlobalInst:
case ValueKind::GlobalAddrInst:
+ case ValueKind::EndLifetimeInst:
+ case ValueKind::UncheckedOwnershipConversionInst:
return InlineCost::Free;
// Typed GEPs are free.
diff --git a/lib/SILOptimizer/Utils/SpecializationMangler.cpp b/lib/SILOptimizer/Utils/SpecializationMangler.cpp
index 76d4be7..00ef34d 100644
--- a/lib/SILOptimizer/Utils/SpecializationMangler.cpp
+++ b/lib/SILOptimizer/Utils/SpecializationMangler.cpp
@@ -12,6 +12,7 @@
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
#include "swift/SIL/SILGlobalVariable.h"
+#include "swift/AST/SubstitutionMap.h"
#include "swift/Basic/Demangler.h"
#include "swift/Basic/ManglingMacros.h"
@@ -60,19 +61,12 @@
SILFunctionType *FTy = Function->getLoweredFunctionType();
CanGenericSignature Sig = FTy->getGenericSignature();
- unsigned idx = 0;
+ auto SubMap = Sig->getSubstitutionMap(Subs);
bool First = true;
- for (Type DepType : Sig->getAllDependentTypes()) {
- // It is sufficient to only mangle the substitutions of the "primary"
- // dependent types. As all other dependent types are just derived from the
- // primary types, this will give us unique symbol names.
- if (DepType->is<GenericTypeParamType>()) {
- appendType(Subs[idx].getReplacement()->getCanonicalType());
- appendListSeparator(First);
- }
- ++idx;
+ for (auto ParamType : Sig->getSubstitutableParams()) {
+ appendType(Type(ParamType).subst(SubMap)->getCanonicalType());
+ appendListSeparator(First);
}
- assert(idx == Subs.size() && "subs not parallel to dependent types");
assert(!First && "no generic substitutions");
appendSpecializationOperator(isReAbstracted ? "Tg" : "TG");
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 4f27b76..58a9796 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -19,6 +19,7 @@
#include "ConstraintSystem.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
+#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/Basic/StringExtras.h"
#include "llvm/ADT/APFloat.h"
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index f84b7dd..b78d05c 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -2507,8 +2507,13 @@
if (!selfDecl->hasType())
return ErrorType::get(tc.Context);
- Type declaredType = selfDecl->getType()->getRValueInstanceType();
- Type superclassTy = declaredType->getSuperclass(&tc);
+ // If the method returns 'Self', the type of 'self' is a
+ // DynamicSelfType. Unwrap it before getting the superclass.
+ auto selfTy = selfDecl->getType()->getRValueInstanceType();
+ if (auto *dynamicSelfTy = selfTy->getAs<DynamicSelfType>())
+ selfTy = dynamicSelfTy->getSelfType();
+
+ auto superclassTy = selfTy->getSuperclass(&tc);
if (selfDecl->getType()->is<MetatypeType>())
superclassTy = MetatypeType::get(superclassTy);
@@ -3367,9 +3372,11 @@
llvm::SmallDenseMap<ValueDecl*, ValueDecl*> &DefaultMap) {
Type BaseTy = PD->getDeclaredInterfaceType();
DeclContext *DC = PD->getDeclContext();
+ std::unique_ptr<TypeChecker> CreatedTC;
auto *TC = static_cast<TypeChecker*>(DC->getASTContext().getLazyResolver());
if (!TC) {
- TC = new TypeChecker(DC->getASTContext());
+ CreatedTC.reset(new TypeChecker(DC->getASTContext()));
+ TC = CreatedTC.get();
}
for (Decl *D : PD->getMembers()) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index 02cc31d..d437e0e 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -15,6 +15,7 @@
//
//===----------------------------------------------------------------------===//
#include "ConstraintSystem.h"
+#include "swift/AST/ProtocolConformance.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index d337194..11bae88 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -3351,9 +3351,10 @@
Type type2,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator) {
- // There's no bridging without ObjC interop.
- if (!TC.Context.LangOpts.EnableObjCInterop)
- return SolutionKind::Error;
+ // There's no bridging without ObjC interop, so we shouldn't have set up
+ // bridging constraints without it.
+ assert(TC.Context.LangOpts.EnableObjCInterop
+ && "bridging constraint w/o ObjC interop?!");
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 2756738..dc02e5e 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -23,6 +23,7 @@
#include "swift/AST/Expr.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/ParameterList.h"
+#include "swift/AST/ProtocolConformance.h"
#include "swift/Basic/Defer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp
index 6dec1cd..23245d9 100644
--- a/lib/Sema/Constraint.cpp
+++ b/lib/Sema/Constraint.cpp
@@ -527,6 +527,10 @@
kind != ConstraintKind::LiteralConformsTo &&
kind != ConstraintKind::SelfObjectOfProtocol) ||
second->is<ProtocolType>());
+
+ // Bridging constraints require bridging to be enabled.
+ assert(kind != ConstraintKind::BridgingConversion
+ || cs.TC.Context.LangOpts.EnableObjCInterop);
// Create the constraint.
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index ef5f386..ee4c66c 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -29,7 +29,6 @@
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/NameLookup.h"
-#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/Types.h"
#include "swift/AST/TypeCheckerDebugConsumer.h"
#include "llvm/ADT/ilist.h"
@@ -1047,8 +1046,10 @@
/// \param scope The scope to associate with current solver state.
void registerScope(SolverScope *scope) {
CS.incrementScopeCounter();
- scopes.insert({ scope, std::make_pair(retiredConstraints.begin(),
- generatedConstraints.size()) });
+ auto scopeInfo =
+ std::make_tuple(scope, retiredConstraints.begin(),
+ generatedConstraints.size());
+ scopes.push_back(scopeInfo);
}
/// \brief Check whether there are any retired constraints present.
@@ -1086,22 +1087,15 @@
///
/// \param constraint The constraint to erase.
void removeGeneratedConstraint(Constraint *constraint) {
- size_t index = 0;
- for (auto generated : generatedConstraints) {
+ for (auto *&generated : generatedConstraints) {
+ // When we find the constraint we're erasing, overwrite its
+ // value with the last element in the generated constraints
+ // vector and then pop that element from the vector.
if (generated == constraint) {
- unsigned last = generatedConstraints.size() - 1;
- auto lastConstraint = generatedConstraints[last];
- if (lastConstraint == generated) {
- generatedConstraints.pop_back();
- break;
- } else {
- generatedConstraints[index] = lastConstraint;
- generatedConstraints[last] = constraint;
- generatedConstraints.pop_back();
- break;
- }
+ generated = generatedConstraints.back();
+ generatedConstraints.pop_back();
+ return;
}
- index++;
}
}
@@ -1113,18 +1107,16 @@
///
/// \param scope The solver scope to rollback.
void rollback(SolverScope *scope) {
- auto entry = scopes.find(scope);
- assert(entry != scopes.end() && "Unknown solver scope");
-
- // Remove given scope from the circulation.
- scopes.erase(scope);
-
+ SolverScope *savedScope;
// The position of last retired constraint before given scope.
ConstraintList::iterator lastRetiredPos;
// The original number of generated constraints before given scope.
unsigned numGenerated;
- std::tie(lastRetiredPos, numGenerated) = entry->getSecond();
+ std::tie(savedScope, lastRetiredPos, numGenerated) =
+ scopes.pop_back_val();
+
+ assert(savedScope == scope && "Scope rollback not in LIFO order!");
// Restore all of the retired constraints.
CS.InactiveConstraints.splice(CS.InactiveConstraints.end(),
@@ -1155,9 +1147,8 @@
/// constraints generated before registration of given scope,
/// this helps to rollback all of the constraints retired/generated
/// each of the registered scopes correct (LIFO) order.
- llvm::SmallDenseMap<SolverScope *,
- std::pair<ConstraintList::iterator, unsigned>>
- scopes;
+ llvm::SmallVector<
+ std::tuple<SolverScope *, ConstraintList::iterator, unsigned>, 4> scopes;
};
class CacheExprTypes : public ASTWalker {
diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp
index acc5e42..10a8190 100644
--- a/lib/Sema/TypeCheckAvailability.cpp
+++ b/lib/Sema/TypeCheckAvailability.cpp
@@ -1186,7 +1186,7 @@
<< OriginalIndent;
}
- TC.diagnose(ReferenceRange.Start, diag::availability_add_attribute,
+ TC.diagnose(D, diag::availability_add_attribute,
KindForDiagnostic)
.fixItInsert(InsertLoc, AttrText);
}
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 11fa677..30e1853 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -1388,6 +1388,11 @@
return true;
}
+void GenericRequirementsCheckListener::satisfiedConformance(
+ Type depTy, Type replacementTy,
+ ProtocolConformanceRef conformance) {
+}
+
bool TypeChecker::
solveForExpression(Expr *&expr, DeclContext *dc, Type convertType,
FreeTypeVariableBinding allowFreeTypeVariables,
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index d324496..643db8d 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -30,6 +30,7 @@
#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/PrettyStackTrace.h"
+#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/ReferencedNameTracker.h"
#include "swift/AST/TypeWalker.h"
#include "swift/Basic/Statistic.h"
@@ -4047,7 +4048,7 @@
TC.validateDecl(ED);
- TC.ValidatedTypes.remove(ED);
+ TC.TypesToFinalize.remove(ED);
{
// Check for circular inheritance of the raw type.
@@ -4103,7 +4104,7 @@
checkUnsupportedNestedType(SD);
TC.validateDecl(SD);
- TC.ValidatedTypes.remove(SD);
+ TC.TypesToFinalize.remove(SD);
TC.addImplicitConstructors(SD);
}
@@ -4235,7 +4236,7 @@
if (!CD->hasValidSignature())
return;
- TC.ValidatedTypes.remove(CD);
+ TC.TypesToFinalize.remove(CD);
{
// Check for circular inheritance.
@@ -7090,7 +7091,7 @@
checkEnumRawValues(*this, ED);
}
- ValidatedTypes.insert(nominal);
+ TypesToFinalize.insert(nominal);
break;
}
@@ -7130,7 +7131,7 @@
markAsObjC(*this, proto, isObjC);
}
- ValidatedTypes.insert(proto);
+ TypesToFinalize.insert(proto);
break;
}
@@ -7301,6 +7302,9 @@
validateDeclForNameLookup(ATD);
}
}
+
+ // Make sure the protocol is fully validated by the end of Sema.
+ TypesToFinalize.insert(proto);
break;
}
case DeclKind::AssociatedType: {
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index a0dc719..3ad9369 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -20,6 +20,7 @@
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Defer.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace swift;
@@ -399,6 +400,8 @@
return false;
}
}
+
+ llvm_unreachable("Unhandled RequirementKind in switch.");
}
void
@@ -1124,10 +1127,13 @@
UnsatisfiedDependency *unsatisfiedDependency,
ConformanceCheckOptions conformanceOptions,
GenericRequirementsCheckListener *listener) {
+ bool valid = true;
+
for (const auto &rawReq : genericSig->getRequirements()) {
auto req = rawReq.subst(substitutions, conformances);
if (!req) {
// Another requirement will fail later; just continue.
+ valid = false;
continue;
}
@@ -1138,8 +1144,10 @@
if (kind != RequirementKind::Layout) {
rawSecondType = rawReq.getSecondType();
secondType = req->getSecondType().subst(substitutions, conformances);
- if (!secondType)
+ if (!secondType) {
+ valid = false;
continue;
+ }
}
if (listener && !listener->shouldCheck(kind, firstType, secondType))
@@ -1165,6 +1173,12 @@
if (!result.second)
return std::make_pair(false, false);
+ // Report the conformance.
+ if (listener) {
+ listener->satisfiedConformance(rawReq.getFirstType(), firstType,
+ *result.second);
+ }
+
continue;
}
@@ -1207,5 +1221,5 @@
}
}
- return std::make_pair(false, true);
+ return std::make_pair(false, valid);
}
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index ddf4d8a..7a92f22 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -28,6 +28,7 @@
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/NameLookup.h"
+#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/ReferencedNameTracker.h"
#include "swift/AST/TypeMatcher.h"
#include "swift/AST/TypeWalker.h"
@@ -38,6 +39,9 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/SaveAndRestore.h"
+#define DEBUG_TYPE "protocol-conformance-checking"
+#include "llvm/Support/Debug.h"
+
using namespace swift;
namespace {
@@ -1705,6 +1709,10 @@
/// Whether we've already complained about problems with this conformance.
bool AlreadyComplained = false;
+ /// Keep track of missing witnesses, either type or value, for later
+ /// diagnosis emits.
+ llvm::SetVector<ValueDecl*> MissingWitnesses;
+
/// Retrieve the associated types that are referenced by the given
/// requirement with a base of 'Self'.
ArrayRef<AssociatedTypeDecl *> getReferencedAssociatedTypes(ValueDecl *req);
@@ -1778,6 +1786,8 @@
llvm::SmallPtrSetImpl<ProtocolConformance *> &visited);
void addUsedConformances(ProtocolConformance *conformance);
+ /// Call this to diagnose currently known missing witnesses.
+ void diagnoseMissingWitnesses();
public:
/// Emit any diagnostics that have been delayed.
void emitDelayedDiags();
@@ -2396,50 +2406,77 @@
return true;
}
-
-/// Generates a note for a protocol requirement for which no witness was found
-/// and provides a fixit to add a stub to the adopter
-static void diagnoseNoWitness(ValueDecl *Requirement, Type RequirementType,
- NormalProtocolConformance *Conformance) {
- // FIXME: Try an ignore-access lookup?
-
- DeclContext *Adopter = Conformance->getDeclContext();
-
- SourceLoc FixitLocation;
- SourceLoc TypeLoc;
- if (auto Extension = dyn_cast<ExtensionDecl>(Adopter)) {
- FixitLocation = Extension->getBraces().Start;
- TypeLoc = Extension->getStartLoc();
- } else if (auto Nominal = dyn_cast<NominalTypeDecl>(Adopter)) {
- FixitLocation = Nominal->getBraces().Start;
- TypeLoc = Nominal->getStartLoc();
- } else {
- llvm_unreachable("Unknown adopter kind");
- }
-
- ASTContext &Ctx = Requirement->getASTContext();
- auto &Diags = Ctx.Diags;
- std::string FixitString;
+/// Print the stubs for an array of witnesses, either type or value, to
+/// FixitString. If for a witness we cannot have stub printed, insert it to
+/// NoStubRequirements.
+static void
+printProtocolStubFixitString(SourceLoc TypeLoc, ProtocolConformance *Conf,
+ ArrayRef<ValueDecl*> MissingWitnesses,
+ std::string &FixitString,
+ llvm::SetVector<ValueDecl*> &NoStubRequirements) {
llvm::raw_string_ostream FixitStream(FixitString);
+ std::for_each(MissingWitnesses.begin(), MissingWitnesses.end(),
+ [&](ValueDecl* VD) {
+ if (!printRequirementStub(VD, Conf->getDeclContext(), Conf->getType(),
+ TypeLoc, FixitStream)) {
+ NoStubRequirements.insert(VD);
+ }
+ });
+}
- bool AddFixit = printRequirementStub(Requirement, Adopter,
- Conformance->getType(), TypeLoc,
- FixitStream);
+void ConformanceChecker::diagnoseMissingWitnesses() {
+ if (MissingWitnesses.empty())
+ return;
- if (auto MissingTypeWitness = dyn_cast<AssociatedTypeDecl>(Requirement)) {
- Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type,
- MissingTypeWitness->getName())
- .fixItInsertAfter(FixitLocation, FixitStream.str());
- } else {
- // Point out the requirement that wasn't met.
- auto diag = Diags.diagnose(Requirement, diag::no_witnesses,
- getRequirementKind(Requirement),
- Requirement->getFullName(),
- RequirementType, AddFixit);
- if (AddFixit) {
- diag.fixItInsertAfter(FixitLocation, FixitStream.str());
- }
- }
+ // Make sure we clear the missing witness bucket when exiting.
+ SWIFT_DEFER { MissingWitnesses.clear(); };
+ llvm::SetVector<ValueDecl*> MissingWitnesses = this->MissingWitnesses;
+ diagnoseOrDefer(MissingWitnesses[0], true,
+ [MissingWitnesses](NormalProtocolConformance *Conf) {
+ DeclContext *DC = Conf->getDeclContext();
+ // The location where to insert stubs.
+ SourceLoc FixitLocation;
+
+ // The location where the type starts.
+ SourceLoc TypeLoc;
+ if (auto Extension = dyn_cast<ExtensionDecl>(DC)) {
+ FixitLocation = Extension->getBraces().Start;
+ TypeLoc = Extension->getStartLoc();
+ } else if (auto Nominal = dyn_cast<NominalTypeDecl>(DC)) {
+ FixitLocation = Nominal->getBraces().Start;
+ TypeLoc = Nominal->getStartLoc();
+ } else {
+ llvm_unreachable("Unknown adopter kind");
+ }
+ std::string FixIt;
+ llvm::SetVector<ValueDecl*> NoStubRequirements;
+
+ // Print stubs for all known missing witnesses.
+ printProtocolStubFixitString(TypeLoc, Conf,
+ MissingWitnesses.getArrayRef(),
+ FixIt, NoStubRequirements);
+ auto &Diags = DC->getASTContext().Diags;
+ for (auto VD : MissingWitnesses) {
+ // Whether this VD has a stub printed.
+ bool AddFixit = !NoStubRequirements.count(VD);
+
+ // Issue diagnostics for witness types.
+ if (auto MissingTypeWitness = dyn_cast<AssociatedTypeDecl>(VD)) {
+ Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type,
+ MissingTypeWitness->getName()).
+ fixItInsertAfter(FixitLocation, FixIt);
+ continue;
+ }
+ // Issue diagnostics for witness values.
+ Type RequirementType =
+ getRequirementTypeForDisplay(DC->getParentModule(), Conf, VD);
+ auto Diag = Diags.diagnose(VD, diag::no_witnesses,
+ getRequirementKind(VD), VD->getFullName(),
+ RequirementType, AddFixit);
+ if (AddFixit)
+ Diag.fixItInsertAfter(FixitLocation, FixIt);
+ }
+ });
}
ResolveWitnessResult
@@ -2753,30 +2790,36 @@
return ResolveWitnessResult::ExplicitFailed;
}
+
+ if (!numViable) {
+ // Save the missing requirement for later diagnosis.
+ MissingWitnesses.insert(requirement);
+ diagnoseOrDefer(requirement, true,
+ [requirement, matches](NormalProtocolConformance *conformance) {
+ auto dc = conformance->getDeclContext();
+ // Diagnose each of the matches.
+ for (const auto &match : matches)
+ diagnoseMatch(dc->getParentModule(), conformance, requirement, match);
+ });
+ return ResolveWitnessResult::ExplicitFailed;
+ }
+
diagnoseOrDefer(requirement, true,
- [requirement, matches, ignoringNames, numViable](
+ [requirement, matches, ignoringNames](
NormalProtocolConformance *conformance) {
auto dc = conformance->getDeclContext();
- auto &diags = dc->getASTContext().Diags;
-
// Determine the type that the requirement is expected to have.
Type reqType = getRequirementTypeForDisplay(dc->getParentModule(),
conformance, requirement);
-
- if (numViable > 0) {
- auto diagnosticMessage = diag::ambiguous_witnesses;
- if (ignoringNames) {
- diagnosticMessage = diag::ambiguous_witnesses_wrong_name;
- }
- diags.diagnose(requirement, diagnosticMessage,
- getRequirementKind(requirement),
- requirement->getFullName(),
- reqType);
- } else {
- // Generate diagnostics for the missing requirement and a fixit to add
- // it
- diagnoseNoWitness(requirement, reqType, conformance);
+ auto &diags = dc->getASTContext().Diags;
+ auto diagnosticMessage = diag::ambiguous_witnesses;
+ if (ignoringNames) {
+ diagnosticMessage = diag::ambiguous_witnesses_wrong_name;
}
+ diags.diagnose(requirement, diagnosticMessage,
+ getRequirementKind(requirement),
+ requirement->getFullName(),
+ reqType);
// Diagnose each of the matches.
for (const auto &match : matches)
@@ -2840,21 +2883,8 @@
recordOptionalWitness(requirement);
return ResolveWitnessResult::Success;
}
-
- diagnoseOrDefer(requirement, true,
- [requirement](NormalProtocolConformance *conformance) {
- auto dc = conformance->getDeclContext();
- auto &diags = dc->getASTContext().Diags;
- // Determine the type that the requirement is expected to have.
- Type reqType = getRequirementTypeForDisplay(dc->getParentModule(),
- conformance, requirement);
-
- // Point out the requirement that wasn't met.
- diags.diagnose(requirement, diag::no_witnesses,
- getRequirementKind(requirement), requirement->getName(),
- reqType, false);
- });
-
+ // Save the missing requirement for later diagnosis.
+ MissingWitnesses.insert(requirement);
return ResolveWitnessResult::ExplicitFailed;
}
@@ -2948,13 +2978,13 @@
return ResolveWitnessResult::ExplicitFailed;
}
+ // Save the missing type witness for later diagnosis.
+ MissingWitnesses.insert(assocType);
// None of the candidates were viable.
diagnoseOrDefer(assocType, true,
- [assocType, nonViable](NormalProtocolConformance *conformance) {
- auto &diags = assocType->getASTContext().Diags;
- diags.diagnose(assocType, diag::no_witnesses_type, assocType->getName());
-
+ [nonViable](NormalProtocolConformance *conformance) {
+ auto &diags = conformance->getDeclContext()->getASTContext().Diags;
for (auto candidate : nonViable) {
if (candidate.first->getDeclaredInterfaceType()->hasError())
continue;
@@ -3037,6 +3067,9 @@
};
for (auto witness : lookupValueWitnesses(req, /*ignoringNames=*/nullptr)) {
+ DEBUG(llvm::dbgs() << "Inferring associated types from decl:\n";
+ witness->dump(llvm::dbgs()));
+
// If the potential witness came from an extension, and our `Self`
// type can't use it regardless of what associated types we end up
// inferring, skip the witness.
@@ -3057,18 +3090,27 @@
}
auto &result = witnessResult.Inferred[i];
+ DEBUG(llvm::dbgs() << "Considering whether " << result.first->getName()
+ << " can infer to:\n";
+ result.second->dump(llvm::dbgs()));
+
// Filter out errors.
- if (result.second->hasError())
+ if (result.second->hasError()) {
+ DEBUG(llvm::dbgs() << "-- has error type\n");
REJECT;
+ }
// Filter out duplicates.
if (!known.insert({result.first, result.second->getCanonicalType()})
- .second)
+ .second) {
+ DEBUG(llvm::dbgs() << "-- duplicate\n");
REJECT;
+ }
// Filter out circular possibilities, e.g. that
// AssocType == S.AssocType or
// AssocType == Foo<S.AssocType>.
+ bool canInferFromOtherAssociatedType = false;
bool containsTautologicalType =
result.second.findIf([&](Type t) -> bool {
auto dmt = t->getAs<DependentMemberType>();
@@ -3080,11 +3122,63 @@
if (!dmt->getBase()->isEqual(Conformance->getType()))
return false;
+ // If this associated type is same-typed to another associated type
+ // on `Self`, then it may still be an interesting candidate if we find
+ // an answer for that other type.
+ auto witnessContext = witness->getDeclContext();
+ if (witnessContext->getAsProtocolExtensionContext()
+ && witnessContext->getGenericSignatureOfContext()) {
+ auto selfTy = witnessContext->getSelfInterfaceType();
+ auto selfAssocTy = DependentMemberType::get(selfTy,
+ dmt->getAssocType());
+ for (auto &reqt : witnessContext->getGenericSignatureOfContext()
+ ->getRequirements()) {
+ switch (reqt.getKind()) {
+ case RequirementKind::Conformance:
+ case RequirementKind::Superclass:
+ case RequirementKind::Layout:
+ break;
+
+ case RequirementKind::SameType:
+ Type other;
+ if (reqt.getFirstType()->isEqual(selfAssocTy)) {
+ other = reqt.getSecondType();
+ } else if (reqt.getSecondType()->isEqual(selfAssocTy)) {
+ other = reqt.getFirstType();
+ } else {
+ break;
+ }
+
+ if (auto otherAssoc = other->getAs<DependentMemberType>()) {
+ if (otherAssoc->getBase()->isEqual(selfTy)) {
+ auto otherDMT = DependentMemberType::get(dmt->getBase(),
+ otherAssoc->getAssocType());
+
+ // We may be able to infer one associated type from the
+ // other.
+ result.second = result.second.transform([&](Type t) -> Type{
+ if (t->isEqual(dmt))
+ return otherDMT;
+ return t;
+ });
+ canInferFromOtherAssociatedType = true;
+ DEBUG(llvm::dbgs() << "++ we can same-type to:\n";
+ result.second->dump(llvm::dbgs()));
+ return false;
+ }
+ }
+ break;
+ }
+ }
+ }
+
return true;
});
- if (containsTautologicalType)
+ if (containsTautologicalType) {
+ DEBUG(llvm::dbgs() << "-- tautological\n");
REJECT;
+ }
// Check that the type witness doesn't contradict an
// explicitly-given type witness. If it does contradict, throw out the
@@ -3101,19 +3195,27 @@
auto newWitness = result.second->getCanonicalType();
if (!newWitness->hasTypeParameter()
&& !existingWitness->isEqual(newWitness)) {
+ DEBUG(llvm::dbgs() << "** contradicts explicit type witness, "
+ "rejecting inference from this decl\n");
goto next_witness;
}
}
- // Check that the type witness meets the
- // requirements on the associated type.
- if (auto failed = checkTypeWitness(TC, DC, result.first,
- result.second)) {
- witnessResult.NonViable.push_back(
- std::make_tuple(result.first,result.second,failed));
- REJECT;
+ // If we same-typed to another unresolved associated type, we won't
+ // be able to check conformances yet.
+ if (!canInferFromOtherAssociatedType) {
+ // Check that the type witness meets the
+ // requirements on the associated type.
+ if (auto failed = checkTypeWitness(TC, DC, result.first,
+ result.second)) {
+ witnessResult.NonViable.push_back(
+ std::make_tuple(result.first,result.second,failed));
+ DEBUG(llvm::dbgs() << "-- doesn't fulfill requirements\n");
+ REJECT;
+ }
}
+ DEBUG(llvm::dbgs() << "++ seems legit\n");
++i;
}
#undef REJECT
@@ -3630,6 +3732,8 @@
// Infer type witnesses from value witnesses.
auto inferred = inferTypeWitnessesViaValueWitnesses(unresolvedAssocTypes);
+ DEBUG(llvm::dbgs() << "Candidates for inference:\n";
+ dumpInferredAssociatedTypes(inferred));
// Compute the set of solutions.
SmallVector<std::pair<ValueDecl *, ValueDecl *>, 4> valueWitnesses;
@@ -3820,6 +3924,9 @@
Type replaced = known->first.transform(foldDependentMemberTypes);
if (replaced.isNull())
return true;
+
+ if (checkTypeWitness(TC, DC, assocType, replaced))
+ return true;
known->first = replaced;
}
@@ -4223,12 +4330,9 @@
return;
}
- for (auto missingTypeWitness : unresolvedAssocTypes) {
- diagnoseOrDefer(missingTypeWitness, true,
- [missingTypeWitness](NormalProtocolConformance *conformance) {
- diagnoseNoWitness(missingTypeWitness, Type(), conformance);
- });
- }
+ // Save the missing type witnesses for later diagnosis.
+ MissingWitnesses.insert(unresolvedAssocTypes.begin(),
+ unresolvedAssocTypes.end());
return;
}
@@ -4302,6 +4406,8 @@
void ConformanceChecker::resolveSingleTypeWitness(
AssociatedTypeDecl *assocType) {
+ // Ensure we diagnose if the witness is missing.
+ SWIFT_DEFER { diagnoseMissingWitnesses(); };
switch (resolveTypeWitnessViaLookup(assocType)) {
case ResolveWitnessResult::Success:
case ResolveWitnessResult::ExplicitFailed:
@@ -4458,23 +4564,40 @@
void ConformanceChecker::ensureRequirementsAreSatisfied() {
auto proto = Conformance->getProtocol();
// Some other problem stopped the signature being computed.
- if (!proto->isRequirementSignatureComputed())
+ if (!proto->isRequirementSignatureComputed()) {
+ Conformance->setInvalid();
return;
+ }
auto reqSig = proto->getRequirementSignature();
auto substitutions = SubstitutionMap::getProtocolSubstitutions(
proto, Conformance->getType(), ProtocolConformanceRef(Conformance));
+ class GatherConformancesListener : public GenericRequirementsCheckListener {
+ public:
+ SmallVector<ProtocolConformanceRef, 4> conformances;
+
+ void satisfiedConformance(Type depTy, Type replacementTy,
+ ProtocolConformanceRef conformance) override {
+ conformances.push_back(conformance);
+ }
+ } listener;
+
auto result = TC.checkGenericArguments(
Conformance->getDeclContext(), Loc, Loc,
// FIXME: maybe this should be the conformance's type
proto->getDeclaredInterfaceType(), reqSig,
QuerySubstitutionMap{substitutions},
- LookUpConformanceInSubstitutionMap{substitutions}, nullptr);
+ LookUpConformanceInSubstitutionMap{substitutions}, nullptr,
+ ConformanceCheckFlags::Used, &listener);
- // Errors are emitted inside the checker.
- (void)result;
+ // If there were no errors, record the conformances.
+ if (result.second) {
+ Conformance->setSignatureConformances(listener.conformances);
+ } else {
+ Conformance->setInvalid();
+ }
}
#pragma mark Protocol conformance checking
@@ -4492,6 +4615,11 @@
// Resolve all of the type witnesses.
resolveTypeWitnesses();
+ // Diagnose missing type witnesses for now.
+ diagnoseMissingWitnesses();
+ // Diagnose missing value witnesses later.
+ SWIFT_DEFER { diagnoseMissingWitnesses(); };
+
// Resolution attempts to have the witnesses be correct by construction, but
// this isn't guaranteed, so let's double check.
ensureRequirementsAreSatisfied();
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 211b3de..32ad28f 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -267,12 +267,46 @@
return LHS->getNameStr().compare(RHS->getNameStr()) < 0;
});
+ auto printPayloads = [](EnumElementDecl *EE, llvm::raw_ostream &OS) {
+ // If the enum element has no payloads, return.
+ auto TL = EE->getArgumentTypeLoc();
+ if (TL.isNull())
+ return;
+ TypeRepr* TR = EE->getArgumentTypeLoc().getTypeRepr();
+ if (auto *TTR = dyn_cast<TupleTypeRepr>(TR)) {
+ SmallVector<Identifier, 4> NameBuffer;
+ ArrayRef<Identifier> Names;
+ if (TTR->hasElementNames()) {
+ // Get the name from the tuple repr, if exist.
+ Names = TTR->getElementNames();
+ } else {
+ // Create same amount of empty names to the elements.
+ NameBuffer.resize(TTR->getNumElements());
+ Names = llvm::makeArrayRef(NameBuffer);
+ }
+ OS << "(";
+ // Print each element in the pattern match.
+ for (unsigned I = 0, N = Names.size(); I < N; I ++) {
+ auto Id = Names[I];
+ if (Id.empty())
+ OS << "_";
+ else
+ OS << tok::kw_let << " " << Id.str();
+ if (I + 1 != N) {
+ OS << ", ";
+ }
+ }
+ OS << ")";
+ }
+ };
+
// Print each enum element name.
std::for_each(SortedElements.begin(), SortedElements.end(),
- [&](EnumElementDecl *EE) {
- OS << tok::kw_case << " ." << EE->getNameStr() << ": " <<
- Placeholder << "\n";
- });
+ [&](EnumElementDecl *EE) {
+ OS << tok::kw_case << " ." << EE->getNameStr();
+ printPayloads(EE, OS);
+ OS <<": " << Placeholder << "\n";
+ });
Context.Diags.diagnose(EndLoc, Id).fixItInsert(EndLoc, Buffer.str());
}
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index e0ee038..1d0bec1 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -2269,7 +2269,7 @@
params = genericSig->getGenericParams();
if (repr->getGenericArguments().size()
- != genericSig->getAllDependentTypes().size()) {
+ != genericSig->getSubstitutionListSize()) {
TC.diagnose(repr->getLoc(), diag::sil_box_arg_mismatch);
return ErrorType::get(Context);
}
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index e681c7a..d33538c 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -410,7 +410,8 @@
::bindExtensionDecl(ext, *this);
}
-static bool shouldValidateDeclForLayout(NominalTypeDecl *nominal, ValueDecl *VD) {
+static bool shouldValidateMemberDuringFinalization(NominalTypeDecl *nominal,
+ ValueDecl *VD) {
// For enums, we only need to validate enum elements to know
// the layout.
if (isa<EnumDecl>(nominal) &&
@@ -440,7 +441,7 @@
return false;
}
-static void validateDeclForLayout(TypeChecker &TC, NominalTypeDecl *nominal) {
+static void finalizeType(TypeChecker &TC, NominalTypeDecl *nominal) {
Optional<bool> lazyVarsAlreadyHaveImplementation;
for (auto *D : nominal->getMembers()) {
@@ -448,7 +449,7 @@
if (!VD)
continue;
- if (!shouldValidateDeclForLayout(nominal, VD))
+ if (!shouldValidateMemberDuringFinalization(nominal, VD))
continue;
TC.validateDecl(VD);
@@ -489,6 +490,15 @@
TC.addImplicitConstructors(CD);
TC.addImplicitDestructor(CD);
}
+
+ // validateDeclForNameLookup will not trigger an immediate full
+ // validation of protocols, but clients will assume that things
+ // like the requirement signature have been set.
+ if (auto PD = dyn_cast<ProtocolDecl>(nominal)) {
+ if (!PD->isRequirementSignatureComputed()) {
+ TC.validateDecl(PD);
+ }
+ }
}
static void typeCheckFunctionsAndExternalDecls(TypeChecker &TC) {
@@ -541,12 +551,12 @@
// Note: if we ever start putting extension members in vtables, we'll need
// to validate those members too.
// FIXME: If we're not planning to run SILGen, this is wasted effort.
- while (!TC.ValidatedTypes.empty()) {
- auto nominal = TC.ValidatedTypes.pop_back_val();
+ while (!TC.TypesToFinalize.empty()) {
+ auto nominal = TC.TypesToFinalize.pop_back_val();
if (nominal->isInvalid() || TC.Context.hadError())
continue;
- validateDeclForLayout(TC, nominal);
+ finalizeType(TC, nominal);
}
// Complete any conformances that we used.
@@ -559,7 +569,7 @@
} while (currentFunctionIdx < TC.definedFunctions.size() ||
currentExternalDef < TC.Context.ExternalDefinitions.size() ||
- !TC.ValidatedTypes.empty() ||
+ !TC.TypesToFinalize.empty() ||
!TC.UsedConformances.empty());
// FIXME: Horrible hack. Store this somewhere more appropriate.
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index aa56685..4dd7713 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -351,6 +351,14 @@
///
/// \returns true if it's ok to validate requirement, false otherwise.
virtual bool shouldCheck(RequirementKind kind, Type first, Type second);
+
+ /// Callback to report the result of a satisfied conformance requirement.
+ ///
+ /// \param depTy The dependent type, from the signature.
+ /// \param replacementTy The type \c depTy was replaced with.
+ /// \param conformance The conformance itself.
+ virtual void satisfiedConformance(Type depTy, Type replacementTy,
+ ProtocolConformanceRef conformance);
};
/// Flags that describe the context of type checking a pattern or
@@ -543,9 +551,10 @@
/// completed before type checking is considered complete.
llvm::SetVector<NormalProtocolConformance *> UsedConformances;
- /// The list of nominal type declarations that have been validated
- /// during type checking.
- llvm::SetVector<NominalTypeDecl *> ValidatedTypes;
+ /// The list of nominal type declarations that we've done at least
+ /// partial validation of during type-checking and which will need
+ /// to be finalized before we can hand off to SILGen etc.
+ llvm::SetVector<NominalTypeDecl *> TypesToFinalize;
using TypeAccessScopeCacheMap = llvm::DenseMap<const ValueDecl *, AccessScope>;
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 65e5ea5..4b091c9 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -715,6 +715,15 @@
dc->getAsNominalTypeOrNominalTypeExtensionContext()
->registerProtocolConformance(conformance);
+ // Read requirement signature conformances.
+ SmallVector<ProtocolConformanceRef, 4> reqConformances;
+ for (auto req : proto->getRequirementSignature()->getRequirements()) {
+ if (req.getKind() == RequirementKind::Conformance) {
+ auto reqConformance = readConformance(DeclTypeCursor);
+ reqConformances.push_back(reqConformance);
+ }
+ }
+ conformance->setSignatureConformances(reqConformances);
// Read inherited conformances.
InheritedConformanceMap inheritedConformances;
@@ -4048,7 +4057,7 @@
SmallVector<Substitution, 4> genericArgs;
if (auto sig = layout->getGenericSignature()) {
- for (unsigned i : range(sig->getAllDependentTypes().size())) {
+ for (unsigned i : range(sig->getSubstitutionListSize())) {
(void)i;
auto sub = maybeReadSubstitution(DeclTypeCursor);
if (!sub) {
@@ -4336,6 +4345,14 @@
typeCount, inheritedCount,
rawIDs);
+ // Skip requirement signature conformances.
+ auto proto = conformance->getProtocol();
+ for (auto req : proto->getRequirementSignature()->getRequirements()) {
+ if (req.getKind() == RequirementKind::Conformance) {
+ (void)readConformance(DeclTypeCursor);
+ }
+ }
+
// Skip trailing inherited conformances.
while (inheritedCount--)
(void)readConformance(DeclTypeCursor);
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 25c7df7..da42e5c 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -1364,6 +1364,7 @@
UNARY_INSTRUCTION(Return)
UNARY_INSTRUCTION(Throw)
UNARY_INSTRUCTION(FixLifetime)
+ UNARY_INSTRUCTION(EndLifetime)
UNARY_INSTRUCTION(CopyBlock)
UNARY_INSTRUCTION(LoadBorrow)
UNARY_INSTRUCTION(BeginBorrow)
@@ -1379,6 +1380,15 @@
#undef UNARY_INSTRUCTION
#undef REFCOUNTING_INSTRUCTION
+ case ValueKind::UncheckedOwnershipConversionInst: {
+ auto Ty = MF->getType(TyID);
+ auto ResultKind = ValueOwnershipKind(Attr);
+ ResultVal = Builder.createUncheckedOwnershipConversion(
+ Loc, getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory)),
+ ResultKind);
+ break;
+ }
+
case ValueKind::LoadInst: {
auto Ty = MF->getType(TyID);
auto Qualifier = LoadOwnershipQualifier(Attr);
@@ -2387,13 +2397,14 @@
proto, conformance.getConcrete()
});
} else if (kind == SIL_WITNESS_ASSOC_PROTOCOL) {
- DeclID assocId, protoId;
+ TypeID assocId;
+ DeclID protoId;
WitnessAssocProtocolLayout::readRecord(scratch, assocId, protoId);
+ CanType type = MF->getType(assocId)->getCanonicalType();
ProtocolDecl *proto = cast<ProtocolDecl>(MF->getDecl(protoId));
auto conformance = MF->readConformance(SILCursor);
witnessEntries.push_back(SILWitnessTable::AssociatedTypeProtocolWitness{
- cast<AssociatedTypeDecl>(MF->getDecl(assocId)), proto,
- conformance
+ type, proto, conformance
});
} else if (kind == SIL_WITNESS_ASSOC_ENTRY) {
DeclID assocId;
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index 3a9576d..6a96a2f 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -200,7 +200,7 @@
using WitnessAssocProtocolLayout = BCRecordLayout<
SIL_WITNESS_ASSOC_PROTOCOL,
- DeclIDField, // ID of AssociatedTypeDecl
+ TypeIDField, // ID of associated type
DeclIDField // ID of ProtocolDecl
// Trailed by the conformance itself if appropriate.
>;
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 85f57eb..aba6f0f 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1318,6 +1318,10 @@
numInheritedConformances,
data);
+ // Write requirement signature conformances.
+ for (auto reqConformance : conformance->getSignatureConformances())
+ writeConformance(reqConformance, DeclTypeAbbrCodes);
+
// Write inherited conformances.
for (auto inheritedProto : inheritedProtos) {
writeConformance(conformance->getInheritedConformance(inheritedProto),
@@ -3287,7 +3291,7 @@
#ifndef NDEBUG
if (auto sig = boxTy->getLayout()->getGenericSignature()) {
- assert(sig->getAllDependentTypes().size()
+ assert(sig->getSubstitutionListSize()
== boxTy->getGenericArgs().size());
}
#endif
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 5e60637..465d0cb 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -1057,6 +1057,7 @@
case ValueKind::LoadWeakInst:
case ValueKind::MarkUninitializedInst:
case ValueKind::FixLifetimeInst:
+ case ValueKind::EndLifetimeInst:
case ValueKind::CopyBlockInst:
case ValueKind::StrongPinInst:
case ValueKind::StrongReleaseInst:
@@ -1068,6 +1069,7 @@
case ValueKind::IsUniqueInst:
case ValueKind::IsUniqueOrPinnedInst:
case ValueKind::ReturnInst:
+ case ValueKind::UncheckedOwnershipConversionInst:
case ValueKind::ThrowInst: {
unsigned Attr = 0;
if (auto *LI = dyn_cast<LoadInst>(&SI))
@@ -1082,6 +1084,9 @@
Attr = (unsigned)DRI->canAllocOnStack();
else if (auto *RCI = dyn_cast<RefCountingInst>(&SI))
Attr = RCI->isNonAtomic();
+ else if (auto *UOCI = dyn_cast<UncheckedOwnershipConversionInst>(&SI)) {
+ Attr = unsigned(SILValue(UOCI).getOwnershipKind());
+ }
writeOneOperandLayout(SI.getKind(), Attr, SI.getOperand(0));
break;
}
@@ -1851,7 +1856,7 @@
WitnessAssocProtocolLayout::emitRecord(
Out, ScratchRecord,
SILAbbrCodes[WitnessAssocProtocolLayout::Code],
- S.addDeclRef(assoc.Requirement),
+ S.addTypeRef(assoc.Requirement),
S.addDeclRef(assoc.Protocol));
S.writeConformance(assoc.Witness, SILAbbrCodes);
diff --git a/lib/SwiftDemangle/SwiftDemangle.cpp b/lib/SwiftDemangle/SwiftDemangle.cpp
index 8c53031..c21fe7b 100644
--- a/lib/SwiftDemangle/SwiftDemangle.cpp
+++ b/lib/SwiftDemangle/SwiftDemangle.cpp
@@ -54,6 +54,13 @@
Length, Opts);
}
+int swift_demangle_hasSwiftCallingConvention(const char *MangledName) {
+ swift::Demangle::Context DCtx;
+ if (DCtx.hasSwiftCallingConvention(llvm::StringRef(MangledName)))
+ return 1;
+ return 0;
+}
+
size_t fnd_get_demangled_name(const char *MangledName, char *OutputBuffer,
size_t Length) {
return swift_demangle_getDemangledName(MangledName, OutputBuffer, Length);
diff --git a/lib/Syntax/DeclSyntax.cpp b/lib/Syntax/DeclSyntax.cpp
index c26d20e..7160508 100644
--- a/lib/Syntax/DeclSyntax.cpp
+++ b/lib/Syntax/DeclSyntax.cpp
@@ -11,8 +11,12 @@
//===----------------------------------------------------------------------===//
#include "swift/Syntax/DeclSyntax.h"
+#include "swift/Syntax/ExprSyntax.h"
+#include "swift/Syntax/GenericSyntax.h"
#include "swift/Syntax/RawSyntax.h"
+#include "swift/Syntax/StmtSyntax.h"
#include "swift/Syntax/SyntaxFactory.h"
+#include "swift/Syntax/TypeSyntax.h"
using namespace swift;
using namespace swift::syntax;
@@ -31,6 +35,101 @@
DeclSyntax::DeclSyntax(const RC<SyntaxData> Root, const DeclSyntaxData *Data)
: Syntax(Root, Data) {}
+#pragma mark - declaration-modifier Data
+
+DeclModifierSyntaxData::
+DeclModifierSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ const CursorIndex IndexInParent)
+ : SyntaxData(Raw, Parent, IndexInParent) {
+ assert(Raw->Kind == SyntaxKind::DeclModifier);
+ assert(Raw->Layout.size() == 4);
+#ifndef NDEBUG
+ auto Name =
+ cast<TokenSyntax>(Raw->getChild(DeclModifierSyntax::Cursor::Name));
+ auto Kind = Name->getTokenKind();
+ assert(Kind == tok::kw_class ||
+ Kind == tok::kw_static ||
+ Kind == tok::identifier ||
+ Kind == tok::kw_public ||
+ Kind == tok::kw_private ||
+ Kind == tok::kw_fileprivate ||
+ Kind == tok::kw_internal);
+#endif
+ syntax_assert_child_token_text(Raw, DeclModifierSyntax::Cursor::LeftParen,
+ tok::l_paren, "(");
+ syntax_assert_child_token(Raw, DeclModifierSyntax::Cursor::Argument,
+ tok::identifier);
+ syntax_assert_child_token_text(Raw, DeclModifierSyntax::Cursor::RightParen,
+ tok::r_paren, ")");
+}
+
+RC<DeclModifierSyntaxData>
+DeclModifierSyntaxData::make(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ const CursorIndex IndexInParent) {
+ return RC<DeclModifierSyntaxData>{
+ new DeclModifierSyntaxData {
+ Raw, Parent, IndexInParent
+ }
+ };
+}
+
+RC<DeclModifierSyntaxData> DeclModifierSyntaxData::makeBlank() {
+ auto Raw = RawSyntax::make(SyntaxKind::DeclModifier,
+ {
+ TokenSyntax::missingToken(tok::identifier, ""),
+ TokenSyntax::missingToken(tok::l_paren, "("),
+ TokenSyntax::missingToken(tok::identifier, ""),
+ TokenSyntax::missingToken(tok::r_paren, ")"),
+ },
+ SourcePresence::Present);
+ return make(Raw);
+}
+
+#pragma mark - declaration-modifier API
+
+RC<TokenSyntax> DeclModifierSyntax::getName() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::Name));
+}
+
+DeclModifierSyntax DeclModifierSyntax::withName(RC<TokenSyntax> NewName) const {
+ assert(NewName->getTokenKind() == tok::identifier);
+ return Data->replaceChild<DeclModifierSyntax>(NewName, Cursor::Name);
+}
+
+RC<TokenSyntax> DeclModifierSyntax::getLeftParenToken() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::LeftParen));
+}
+
+DeclModifierSyntax
+DeclModifierSyntax::withLeftParenToken(RC<TokenSyntax> NewLeftParen) const {
+ syntax_assert_token_is(NewLeftParen, tok::l_paren, "(");
+ return Data->replaceChild<DeclModifierSyntax>(NewLeftParen,
+ Cursor::LeftParen);
+}
+
+RC<TokenSyntax> DeclModifierSyntax::getArgument() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::Argument));
+}
+
+DeclModifierSyntax
+DeclModifierSyntax::withArgument(RC<TokenSyntax> NewArgument) const {
+ assert(NewArgument->getTokenKind() == tok::identifier);
+ return Data->replaceChild<DeclModifierSyntax>(NewArgument, Cursor::Argument);
+}
+
+RC<TokenSyntax> DeclModifierSyntax::getRightParenToken() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::RightParen));
+}
+
+DeclModifierSyntax
+DeclModifierSyntax::withRightParenToken(RC<TokenSyntax> NewRightParen) const {
+ syntax_assert_token_is(NewRightParen, tok::r_paren, ")");
+ return Data->replaceChild<DeclModifierSyntax>(NewRightParen,
+ Cursor::RightParen);
+}
+
#pragma mark - unknown-statement Data
UnknownDeclSyntaxData::UnknownDeclSyntaxData(RC<RawSyntax> Raw,
@@ -364,3 +463,573 @@
auto Data = TypeAliasDeclSyntaxData::make(Raw);
return { Data, Data.get() };
}
+
+#pragma mark - function-parameter Data
+
+FunctionParameterSyntaxData::FunctionParameterSyntaxData(RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ CursorIndex IndexInParent)
+ : SyntaxData(Raw, Parent, IndexInParent) {
+ assert(Raw->Layout.size() == 8);
+ syntax_assert_child_token(Raw, FunctionParameterSyntax::Cursor::ExternalName,
+ tok::identifier);
+ syntax_assert_child_token(Raw, FunctionParameterSyntax::Cursor::LocalName,
+ tok::identifier);
+ syntax_assert_child_token_text(Raw, FunctionParameterSyntax::Cursor::Colon,
+ tok::colon, ":");
+ assert(Raw->getChild(FunctionParameterSyntax::Cursor::Type)->isType());
+ syntax_assert_child_token_text(Raw, FunctionParameterSyntax::Cursor::Ellipsis,
+ tok::identifier, "...");
+ syntax_assert_child_token_text(Raw,
+ FunctionParameterSyntax::Cursor::DefaultEqual,
+ tok::equal, "=");
+ assert(Raw->getChild(
+ FunctionParameterSyntax::Cursor::DefaultExpression)->isExpr());
+ syntax_assert_child_token_text(Raw,
+ FunctionParameterSyntax::Cursor::TrailingComma,
+ tok::comma, ",");
+}
+
+RC<FunctionParameterSyntaxData>
+FunctionParameterSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
+ CursorIndex IndexInParent) {
+ return RC<FunctionParameterSyntaxData> {
+ new FunctionParameterSyntaxData {
+ Raw, Parent, IndexInParent
+ }
+ };
+}
+
+RC<FunctionParameterSyntaxData> FunctionParameterSyntaxData::makeBlank() {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionParameter,
+ {
+ TokenSyntax::missingToken(tok::identifier, ""),
+ TokenSyntax::missingToken(tok::identifier, ""),
+ TokenSyntax::missingToken(tok::colon, ":"),
+ RawSyntax::missing(SyntaxKind::MissingType),
+ TokenSyntax::missingToken(tok::identifier, "..."),
+ TokenSyntax::missingToken(tok::equal, "="),
+ RawSyntax::missing(SyntaxKind::MissingExpr),
+ TokenSyntax::missingToken(tok::comma, ","),
+ },
+ SourcePresence::Present);
+ return make(Raw);
+}
+
+
+#pragma mark - function-parameter API
+
+RC<TokenSyntax> FunctionParameterSyntax::getExternalName() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::ExternalName));
+}
+
+FunctionParameterSyntax FunctionParameterSyntax::
+withExternalName(RC<TokenSyntax> NewExternalName) const {
+ assert(NewExternalName->getTokenKind() == tok::identifier);
+ return Data->replaceChild<FunctionParameterSyntax>(NewExternalName,
+ Cursor::ExternalName);
+}
+
+RC<TokenSyntax> FunctionParameterSyntax::getLocalName() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::LocalName));
+}
+
+FunctionParameterSyntax FunctionParameterSyntax::
+withLocalName(RC<TokenSyntax> NewLocalName) const {
+ assert(NewLocalName->getTokenKind() == tok::identifier);
+ return Data->replaceChild<FunctionParameterSyntax>(NewLocalName,
+ Cursor::LocalName);
+}
+
+RC<TokenSyntax> FunctionParameterSyntax::getColonToken() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::Colon));
+}
+
+FunctionParameterSyntax FunctionParameterSyntax::
+withColonToken(RC<TokenSyntax> NewColonToken) const {
+ syntax_assert_token_is(NewColonToken, tok::colon, ":");
+ return Data->replaceChild<FunctionParameterSyntax>(NewColonToken,
+ Cursor::Colon);
+}
+
+llvm::Optional<TypeSyntax> FunctionParameterSyntax::getTypeSyntax() const {
+ auto RawType = getRaw()->getChild(Cursor::Type);
+ if (RawType->isMissing()) {
+ return llvm::None;
+ }
+
+ auto *MyData = getUnsafeData<FunctionParameterSyntax>();
+
+ if (MyData->CachedTypeSyntax) {
+ return TypeSyntax { Root, MyData->CachedTypeSyntax.get() };
+ }
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedTypeSyntax);
+
+ SyntaxData::realizeSyntaxNode<TypeSyntax>(ChildPtr, RawType, MyData,
+ cursorIndex(Cursor::Type));
+
+ return TypeSyntax { Root, MyData->CachedTypeSyntax.get() };
+}
+
+FunctionParameterSyntax FunctionParameterSyntax::
+withTypeSyntax(llvm::Optional<TypeSyntax> NewType) const {
+ if (!NewType.hasValue()) {
+ auto RawType = RawSyntax::missing(SyntaxKind::MissingType);
+ return Data->replaceChild<FunctionParameterSyntax>(RawType, Cursor::Type);
+ }
+
+ return Data->replaceChild<FunctionParameterSyntax>(
+ NewType.getValue().getRaw(), Cursor::Type);
+}
+
+RC<TokenSyntax> FunctionParameterSyntax::getEqualToken() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::DefaultEqual));
+}
+
+FunctionParameterSyntax FunctionParameterSyntax::
+withEqualToken(RC<TokenSyntax> NewEqualToken) const {
+ assert(NewEqualToken->getTokenKind() == tok::equal);
+ return Data->replaceChild<FunctionParameterSyntax>(NewEqualToken,
+ Cursor::DefaultEqual);
+}
+
+llvm::Optional<ExprSyntax> FunctionParameterSyntax::getDefaultValue() const {
+ auto RawExpr = getRaw()->getChild(Cursor::DefaultExpression);
+ if (RawExpr->isMissing()) {
+ return llvm::None;
+ }
+
+ auto *MyData = getUnsafeData<FunctionParameterSyntax>();
+
+ if (MyData->CachedTypeSyntax) {
+ return ExprSyntax { Root, MyData->CachedDefaultValue.get() };
+ }
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedDefaultValue);
+
+ SyntaxData::realizeSyntaxNode<TypeSyntax>(ChildPtr, RawExpr, MyData,
+ cursorIndex(Cursor::DefaultExpression));
+
+ return ExprSyntax { Root, MyData->CachedDefaultValue.get() };
+}
+
+FunctionParameterSyntax FunctionParameterSyntax::
+withDefaultValue(llvm::Optional<ExprSyntax> NewDefaultValue) const {
+ if (!NewDefaultValue.hasValue()) {
+ auto RawType = RawSyntax::missing(SyntaxKind::MissingExpr);
+ return Data->replaceChild<FunctionParameterSyntax>(RawType,
+ Cursor::DefaultExpression);
+ }
+
+ return Data->replaceChild<FunctionParameterSyntax>(
+ NewDefaultValue.getValue().getRaw(), Cursor::DefaultExpression);
+}
+
+RC<TokenSyntax> FunctionParameterSyntax::getTrailingComma() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::TrailingComma));
+}
+
+FunctionParameterSyntax FunctionParameterSyntax::
+withTrailingComma(RC<TokenSyntax> NewTrailingComma) const {
+ syntax_assert_token_is(NewTrailingComma, tok::comma, ",");
+ return Data->replaceChild<FunctionParameterSyntax>(NewTrailingComma,
+ Cursor::TrailingComma);
+}
+
+#pragma mark - function-signature Data
+
+FunctionSignatureSyntaxData::
+FunctionSignatureSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ const CursorIndex IndexInParent)
+ : SyntaxData(Raw, Parent, IndexInParent) {
+ assert(Raw->Layout.size() == 7);
+ syntax_assert_child_token_text(Raw,
+ FunctionSignatureSyntax::Cursor::LeftParen,
+ tok::l_paren, "(");
+
+ assert(Raw->getChild(FunctionSignatureSyntax::Cursor::ParameterList)->Kind ==
+ SyntaxKind::FunctionParameterList);
+
+ syntax_assert_child_token_text(Raw,
+ FunctionSignatureSyntax::Cursor::RightParen,
+ tok::r_paren, ")");
+#ifndef NDEBUG
+ auto ThrowsRethrows = cast<TokenSyntax>(
+ Raw->getChild(FunctionSignatureSyntax::Cursor::ThrowsOrRethrows));
+ assert(cast<TokenSyntax>(ThrowsRethrows)->getTokenKind() == tok::kw_throws ||
+ cast<TokenSyntax>(ThrowsRethrows)->getTokenKind() == tok::kw_rethrows);
+#endif
+ syntax_assert_child_token_text(Raw, FunctionSignatureSyntax::Cursor::Arrow,
+ tok::arrow, "->");
+ syntax_assert_child_kind(Raw,
+ FunctionSignatureSyntax::Cursor::ReturnTypeAttributes,
+ SyntaxKind::TypeAttributes);
+ assert(Raw->getChild(FunctionSignatureSyntax::Cursor::ReturnType)->isType());
+}
+
+RC<FunctionSignatureSyntaxData>
+FunctionSignatureSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
+ CursorIndex IndexInParent) {
+ return RC<FunctionSignatureSyntaxData> {
+ new FunctionSignatureSyntaxData {
+ Raw, Parent, IndexInParent
+ }
+ };
+}
+
+RC<FunctionSignatureSyntaxData> FunctionSignatureSyntaxData::makeBlank() {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionSignature,
+ {
+ TokenSyntax::missingToken(tok::l_paren, "("),
+ RawSyntax::missing(SyntaxKind::FunctionParameterList),
+ TokenSyntax::missingToken(tok::r_paren, ")"),
+ TokenSyntax::missingToken(tok::kw_throws, "throws"),
+ TokenSyntax::missingToken(tok::arrow, "->"),
+ RawSyntax::missing(SyntaxKind::TypeAttributes),
+ RawSyntax::missing(SyntaxKind::MissingType),
+ },
+ SourcePresence::Present);
+ return make(Raw);
+}
+
+#pragma mark - function-signature API
+
+RC<TokenSyntax> FunctionSignatureSyntax::getLeftParenToken() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::LeftParen));
+}
+
+FunctionSignatureSyntax FunctionSignatureSyntax::
+withLeftParenToken(RC<TokenSyntax> NewLeftParen) const {
+ syntax_assert_token_is(NewLeftParen, tok::l_paren, "(");
+ return Data->replaceChild<FunctionSignatureSyntax>(NewLeftParen,
+ Cursor::LeftParen);
+}
+
+FunctionParameterListSyntax FunctionSignatureSyntax::getParameterList() const {
+ auto RawList = getRaw()->getChild(Cursor::ParameterList);
+
+ auto *MyData = getUnsafeData<FunctionSignatureSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedParameterList);
+
+ SyntaxData::realizeSyntaxNode<FunctionParameterListSyntax>(ChildPtr, RawList,
+ MyData, cursorIndex(Cursor::ParameterList));
+
+ return FunctionParameterListSyntax {
+ Root,
+ MyData->CachedParameterList.get()
+ };
+}
+
+FunctionSignatureSyntax FunctionSignatureSyntax::
+withParameterList(FunctionParameterListSyntax NewParameterList) const {
+ return Data->replaceChild<FunctionSignatureSyntax>(NewParameterList.getRaw(),
+ Cursor::ParameterList);
+}
+
+RC<TokenSyntax> FunctionSignatureSyntax::getRightParenToken() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::RightParen));
+}
+
+FunctionSignatureSyntax FunctionSignatureSyntax::
+withRightParenToken(RC<TokenSyntax> NewRightParen) const {
+ syntax_assert_token_is(NewRightParen, tok::r_paren, ")");
+ return Data->replaceChild<FunctionSignatureSyntax>(NewRightParen,
+ Cursor::RightParen);
+}
+
+RC<TokenSyntax> FunctionSignatureSyntax::getThrowsToken() const {
+ auto Throw = cast<TokenSyntax>(getRaw()->getChild(Cursor::ThrowsOrRethrows));
+ if (Throw->getTokenKind() != tok::kw_throws) {
+ return TokenSyntax::missingToken(tok::kw_throws, "throws");
+ }
+ return Throw;
+}
+
+FunctionSignatureSyntax FunctionSignatureSyntax::
+withThrowsToken(RC<TokenSyntax> NewThrowsToken) const {
+ syntax_assert_token_is(NewThrowsToken, tok::kw_throws, "throws");
+ return Data->replaceChild<FunctionSignatureSyntax>(NewThrowsToken,
+ Cursor::ThrowsOrRethrows);
+}
+
+RC<TokenSyntax> FunctionSignatureSyntax::getRethrowsToken() const {
+ auto Rethrow = cast<TokenSyntax>(
+ getRaw()->getChild(Cursor::ThrowsOrRethrows));
+ if (Rethrow->getTokenKind() != tok::kw_rethrows) {
+ return TokenSyntax::missingToken(tok::kw_rethrows, "rethrows");
+ }
+ return Rethrow;
+}
+
+FunctionSignatureSyntax FunctionSignatureSyntax::
+withRethrowsToken(RC<TokenSyntax> NewRethrowsToken) const {
+ syntax_assert_token_is(NewRethrowsToken, tok::kw_rethrows, "rethrows");
+ return Data->replaceChild<FunctionSignatureSyntax>(NewRethrowsToken,
+ Cursor::ThrowsOrRethrows);
+}
+
+RC<TokenSyntax> FunctionSignatureSyntax::getArrowToken() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::Arrow));
+}
+
+FunctionSignatureSyntax FunctionSignatureSyntax::
+withArrowToken(RC<TokenSyntax> NewArrowToken) const {
+ syntax_assert_token_is(NewArrowToken, tok::arrow, "->");
+ return Data->replaceChild<FunctionSignatureSyntax>(NewArrowToken,
+ Cursor::Arrow);
+}
+
+TypeAttributesSyntax FunctionSignatureSyntax::getReturnTypeAttributes() const {
+ auto RawAttrs = getRaw()->getChild(Cursor::ReturnTypeAttributes);
+
+ auto *MyData = getUnsafeData<FunctionSignatureSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedReturnTypeAttributes);
+
+ SyntaxData::realizeSyntaxNode<TypeAttributesSyntax>(ChildPtr, RawAttrs,
+ MyData, cursorIndex(Cursor::ReturnTypeAttributes));
+
+ return TypeAttributesSyntax {
+ Root,
+ MyData->CachedReturnTypeAttributes.get()
+ };
+}
+
+FunctionSignatureSyntax FunctionSignatureSyntax::
+withReturnTypeAttributes(TypeAttributesSyntax NewAttributes) const {
+ return Data->replaceChild<FunctionSignatureSyntax>(NewAttributes.getRaw(),
+ Cursor::ReturnTypeAttributes);
+}
+
+TypeSyntax FunctionSignatureSyntax::getReturnTypeSyntax() const {
+ auto RawType = getRaw()->getChild(Cursor::ReturnType);
+
+ auto *MyData = getUnsafeData<FunctionSignatureSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedReturnTypeSyntax);
+
+ SyntaxData::realizeSyntaxNode<TypeSyntax>(ChildPtr, RawType,
+ MyData, cursorIndex(Cursor::ReturnType));
+
+ return TypeSyntax {
+ Root,
+ MyData->CachedReturnTypeSyntax.get()
+ };
+}
+
+FunctionSignatureSyntax FunctionSignatureSyntax::
+withReturnTypeSyntax(TypeSyntax NewReturnTypeSyntax) const {
+ return Data->replaceChild<FunctionSignatureSyntax>(
+ NewReturnTypeSyntax.getRaw(), Cursor::ReturnType);
+}
+
+#pragma mark - function-declaration-data
+
+FunctionDeclSyntaxData::
+FunctionDeclSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ const CursorIndex IndexInParent)
+ : SyntaxData(Raw, Parent, IndexInParent) {
+ assert(Raw->Kind == SyntaxKind::FunctionDecl);
+ assert(Raw->Layout.size() == 8);
+ syntax_assert_child_kind(Raw, FunctionDeclSyntax::Cursor::Attributes,
+ SyntaxKind::TypeAttributes);
+ syntax_assert_child_kind(Raw, FunctionDeclSyntax::Cursor::Modifiers,
+ SyntaxKind::DeclModifierList);
+ syntax_assert_child_token_text(Raw, FunctionDeclSyntax::Cursor::FuncKeyword,
+ tok::kw_func, "func");
+ syntax_assert_child_token(Raw, FunctionDeclSyntax::Cursor::Identifier,
+ tok::identifier);
+ syntax_assert_child_kind(Raw,
+ FunctionDeclSyntax::Cursor::GenericParameterClause,
+ SyntaxKind::GenericParameterClause);
+ syntax_assert_child_kind(Raw, FunctionDeclSyntax::Cursor::Signature,
+ SyntaxKind::FunctionSignature);
+ syntax_assert_child_kind(Raw, FunctionDeclSyntax::Cursor::GenericWhereClause,
+ SyntaxKind::GenericWhereClause);
+ syntax_assert_child_kind(Raw, FunctionDeclSyntax::Cursor::Body,
+ SyntaxKind::CodeBlockStmt);
+}
+
+RC<FunctionDeclSyntaxData> FunctionDeclSyntaxData::make(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ const CursorIndex IndexInParent) {
+ return RC<FunctionDeclSyntaxData> {
+ new FunctionDeclSyntaxData {
+ Raw, Parent, IndexInParent
+ }
+ };
+}
+
+RC<FunctionDeclSyntaxData> FunctionDeclSyntaxData::makeBlank() {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionDecl,
+ {
+ RawSyntax::missing(SyntaxKind::TypeAttributes),
+ RawSyntax::missing(SyntaxKind::DeclModifierList),
+ TokenSyntax::missingToken(tok::kw_func, "func"),
+ TokenSyntax::missingToken(tok::identifier, ""),
+ RawSyntax::missing(SyntaxKind::GenericParameterClause),
+ RawSyntax::missing(SyntaxKind::FunctionSignature),
+ RawSyntax::missing(SyntaxKind::GenericWhereClause),
+ RawSyntax::missing(SyntaxKind::CodeBlockStmt),
+ },
+ SourcePresence::Present);
+ return make(Raw);
+}
+
+#pragma mark - function-declaration-API
+
+TypeAttributesSyntax FunctionDeclSyntax::getAttributes() const {
+ auto RawAttrs = getRaw()->getChild(Cursor::Attributes);
+
+ auto *MyData = getUnsafeData<FunctionDeclSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedAttributes);
+
+ SyntaxData::realizeSyntaxNode<ExprSyntax>(ChildPtr, RawAttrs, MyData,
+ cursorIndex(Cursor::Attributes));
+
+ return { Root, MyData->CachedAttributes.get() };
+}
+
+FunctionDeclSyntax
+FunctionDeclSyntax::withAttributes(TypeAttributesSyntax NewAttributes) const {
+ return Data->replaceChild<FunctionDeclSyntax>(NewAttributes.getRaw(),
+ Cursor::Attributes);
+}
+
+DeclModifierListSyntax FunctionDeclSyntax::getModifiers() const {
+ auto RawModifiers = getRaw()->getChild(Cursor::Attributes);
+
+ auto *MyData = getUnsafeData<FunctionDeclSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedModifiers);
+
+ SyntaxData::realizeSyntaxNode<DeclModifierListSyntax>(ChildPtr, RawModifiers,
+ MyData, cursorIndex(Cursor::Modifiers));
+
+ return { Root, MyData->CachedModifiers.get() };
+}
+
+FunctionDeclSyntax
+FunctionDeclSyntax::withModifiers(DeclModifierListSyntax NewModifiers) const {
+ return Data->replaceChild<FunctionDeclSyntax>(NewModifiers.getRaw(),
+ Cursor::Modifiers);
+}
+
+RC<TokenSyntax> FunctionDeclSyntax::getFuncKeyword() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::FuncKeyword));
+}
+
+FunctionDeclSyntax
+FunctionDeclSyntax::withFuncKeyword(RC<TokenSyntax> NewFuncKeyword) const {
+ syntax_assert_token_is(NewFuncKeyword, tok::kw_func, "func");
+ return Data->replaceChild<FunctionDeclSyntax>(NewFuncKeyword,
+ Cursor::FuncKeyword);
+
+}
+
+RC<TokenSyntax> FunctionDeclSyntax::getIdentifier() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::Identifier));
+}
+
+FunctionDeclSyntax
+FunctionDeclSyntax::withIdentifier(RC<TokenSyntax> NewIdentifier) const {
+ assert(NewIdentifier->getTokenKind() == tok::identifier);
+ return Data->replaceChild<FunctionDeclSyntax>(NewIdentifier,
+ Cursor::Identifier);
+}
+
+llvm::Optional<GenericParameterClauseSyntax>
+FunctionDeclSyntax::getGenericParameterClause() const {
+ auto RawGenericParams = getRaw()->getChild(Cursor::Attributes);
+ if (RawGenericParams->isMissing()) {
+ return llvm::None;
+ }
+
+ auto *MyData = getUnsafeData<FunctionDeclSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedGenericParams);
+
+ SyntaxData::realizeSyntaxNode<DeclModifierListSyntax>(ChildPtr,
+ RawGenericParams, MyData, cursorIndex(Cursor::GenericParameterClause));
+
+ GenericParameterClauseSyntax Params {
+ Root,
+ MyData->CachedGenericParams.get()
+ };
+
+ return Params;
+}
+
+FunctionDeclSyntax FunctionDeclSyntax::withGenericParameterClause(
+ llvm::Optional<GenericParameterClauseSyntax> NewGenericParams) const {
+ auto RawParams = NewGenericParams.hasValue()
+ ? NewGenericParams->getRaw()
+ : SyntaxFactory::makeBlankGenericParameterClause().getRaw();
+ return Data->replaceChild<FunctionDeclSyntax>(RawParams,
+ Cursor::GenericParameterClause);
+
+}
+
+FunctionSignatureSyntax FunctionDeclSyntax::getSignature() const {
+ auto RawSig = getRaw()->getChild(Cursor::Attributes);
+
+ auto *MyData = getUnsafeData<FunctionDeclSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedSignature);
+
+ SyntaxData::realizeSyntaxNode<FunctionSignatureSyntax>(ChildPtr, RawSig,
+ MyData, cursorIndex(Cursor::Signature));
+
+ return { Root, MyData->CachedSignature.get() };
+}
+
+FunctionDeclSyntax
+FunctionDeclSyntax::withSignature(FunctionSignatureSyntax NewSignature) const {
+ return Data->replaceChild<FunctionDeclSyntax>(NewSignature.getRaw(),
+ Cursor::Signature);
+}
+
+llvm::Optional<CodeBlockStmtSyntax> FunctionDeclSyntax::getBody() const {
+ auto RawBody = getRaw()->getChild(Cursor::Body);
+ if (RawBody->isMissing()) {
+ return llvm::None;
+ }
+
+ auto *MyData = getUnsafeData<FunctionDeclSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedBody);
+
+ SyntaxData::realizeSyntaxNode<CodeBlockStmtSyntax>(ChildPtr,
+ RawBody, MyData, cursorIndex(Cursor::Body));
+
+ CodeBlockStmtSyntax Body {
+ Root,
+ MyData->CachedBody.get()
+ };
+
+ return Body;
+}
+
+FunctionDeclSyntax FunctionDeclSyntax::
+withBody(llvm::Optional<CodeBlockStmtSyntax> NewBody) const {
+ auto RawBody = NewBody.hasValue()
+ ? NewBody->getRaw()
+ : SyntaxFactory::makeBlankCodeBlock().getRaw();
+ return Data->replaceChild<FunctionDeclSyntax>(RawBody,
+ Cursor::Body);
+}
diff --git a/lib/Syntax/ExprSyntax.cpp b/lib/Syntax/ExprSyntax.cpp
index b7d8be9..9a59dd4 100644
--- a/lib/Syntax/ExprSyntax.cpp
+++ b/lib/Syntax/ExprSyntax.cpp
@@ -301,80 +301,12 @@
FunctionCallArgumentSyntax::Cursor::Comma);
}
-#pragma mark - function-call-argument-list Data
-
-FunctionCallArgumentListSyntaxData::
-FunctionCallArgumentListSyntaxData(const RC<RawSyntax> Raw,
- const SyntaxData *Parent,
- CursorIndex IndexInParent)
- : SyntaxData(Raw, Parent, IndexInParent) {
-#ifndef NDEBUG
- for (auto Child : Raw->Layout) {
- assert(Child->Kind == SyntaxKind::FunctionCallArgument);
- }
-#endif
- for (size_t i = 0; i < Raw->Layout.size(); ++i) {
- CachedArguments.emplace_back(nullptr);
- }
-}
-
-RC<FunctionCallArgumentListSyntaxData>
-FunctionCallArgumentListSyntaxData::make(RC<RawSyntax> Raw,
- const SyntaxData *Parent,
- CursorIndex IndexInParent) {
- return RC<FunctionCallArgumentListSyntaxData> {
- new FunctionCallArgumentListSyntaxData {
- Raw, Parent, IndexInParent
- }
- };
-}
-
-RC<FunctionCallArgumentListSyntaxData>
-FunctionCallArgumentListSyntaxData::makeBlank() {
- auto Raw = RawSyntax::make(SyntaxKind::FunctionCallArgumentList, {},
- SourcePresence::Present);
- return make(Raw);
-}
-
#pragma mark - function-call-argument-list API
FunctionCallArgumentListSyntax::
FunctionCallArgumentListSyntax(const RC<SyntaxData> Root,
const DataType *Data)
- : Syntax(Root, Data) {}
-
-size_t
-FunctionCallArgumentListSyntax::getNumArguments() const {
- return getRaw()->Layout.size();
-}
-
-FunctionCallArgumentSyntax
-FunctionCallArgumentListSyntax::getArgument(size_t Index) const {
- assert(Index <= getRaw()->Layout.size());
-
- auto RawArg = getRaw()->Layout[Index];
-
- auto *MyData = getUnsafeData<FunctionCallArgumentListSyntax>();
-
- auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
- MyData->CachedArguments.data() + Index);
-
- SyntaxData::realizeSyntaxNode<FunctionCallArgumentSyntax>(ChildPtr, RawArg,
- MyData,
- Index);
-
- return FunctionCallArgumentSyntax {
- Root,
- MyData->CachedArguments[Index].get()
- };
-}
-
-FunctionCallArgumentListSyntax
-FunctionCallArgumentListSyntax::withAdditionalArgument(
- FunctionCallArgumentSyntax AdditionalArgument) const {
- auto NewRaw = getRaw()->append(AdditionalArgument.getRaw());
- return Data->replaceSelf<FunctionCallArgumentListSyntax>(NewRaw);
-}
+ : SyntaxCollection(Root, Data) {}
#pragma mark - function-call-expression Data
diff --git a/lib/Syntax/GenericSyntax.cpp b/lib/Syntax/GenericSyntax.cpp
index e48e33a..99a72d8 100644
--- a/lib/Syntax/GenericSyntax.cpp
+++ b/lib/Syntax/GenericSyntax.cpp
@@ -27,7 +27,7 @@
ConformanceRequirementSyntaxData(RC<RawSyntax> Raw,
const SyntaxData *Parent,
CursorIndex IndexInParent)
- : SyntaxData(Raw, Parent, IndexInParent) {
+ : GenericRequirementSyntaxData(Raw, Parent, IndexInParent) {
assert(Raw->Kind == SyntaxKind::ConformanceRequirement);
syntax_assert_child_kind(Raw,
ConformanceRequirementSyntax::Cursor::LeftTypeIdentifier,
@@ -149,9 +149,9 @@
}
RC<GenericParameterClauseSyntaxData>
-GenericParameterClauseSyntaxData::make(RC<RawSyntax> Raw,
+GenericParameterClauseSyntaxData::make(const RC<RawSyntax> Raw,
const SyntaxData *Parent,
- CursorIndex IndexInParent) {
+ const CursorIndex IndexInParent) {
return RC<GenericParameterClauseSyntaxData> {
new GenericParameterClauseSyntaxData {
Raw, Parent, IndexInParent,
@@ -173,7 +173,7 @@
#pragma mark - generic-parameter-clause API
GenericParameterClauseSyntax::
-GenericParameterClauseSyntax(RC<SyntaxData> Root,
+GenericParameterClauseSyntax(const RC<SyntaxData> Root,
const GenericParameterClauseSyntaxData *Data)
: Syntax(Root, Data) {}
@@ -226,52 +226,24 @@
return { Data, Data.get() };
}
-#pragma mark - generic-requirement-list Data
-
-GenericRequirementListSyntaxData::
-GenericRequirementListSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent,
- CursorIndex IndexInParent)
- : SyntaxData(Raw, Parent, IndexInParent) {
- assert(Raw->Kind == SyntaxKind::GenericRequirementList);
-}
-
-RC<GenericRequirementListSyntaxData>
-GenericRequirementListSyntaxData::make(RC<RawSyntax> Raw,
- const SyntaxData *Parent,
- CursorIndex IndexInParent) {
- return RC<GenericRequirementListSyntaxData> {
- new GenericRequirementListSyntaxData {
- Raw, Parent, IndexInParent
- }
- };
-}
-
-RC<GenericRequirementListSyntaxData>
-GenericRequirementListSyntaxData::makeBlank() {
- auto Raw = RawSyntax::make(SyntaxKind::GenericRequirementList,
- {},
- SourcePresence::Present);
- return make(Raw);
-}
-
#pragma mark - generic-where-clause Data
GenericWhereClauseSyntaxData::
-GenericWhereClauseSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent,
- CursorIndex IndexInParent)
+GenericWhereClauseSyntaxData(const RC<RawSyntax> Raw, const SyntaxData *Parent,
+ const CursorIndex IndexInParent)
: SyntaxData(Raw, Parent, IndexInParent) {
assert(Raw->Kind == SyntaxKind::GenericWhereClause);
syntax_assert_child_token_text(Raw,
- GenericWhereClauseSyntax::Cursor::WhereToken, tok::kw_where, "where");
+ GenericWhereClauseSyntax::Cursor::WhereKeyword, tok::kw_where, "where");
syntax_assert_child_kind(Raw,
GenericWhereClauseSyntax::Cursor::RequirementList,
SyntaxKind::GenericRequirementList);
}
RC<GenericWhereClauseSyntaxData>
-GenericWhereClauseSyntaxData::make(RC<RawSyntax> Raw,
+GenericWhereClauseSyntaxData::make(const RC<RawSyntax> Raw,
const SyntaxData *Parent,
- CursorIndex IndexInParent) {
+ const CursorIndex IndexInParent) {
return RC<GenericWhereClauseSyntaxData> {
new GenericWhereClauseSyntaxData { Raw, Parent, IndexInParent }
};
@@ -293,20 +265,34 @@
const GenericWhereClauseSyntaxData *Data)
: Syntax(Root, Data) {}
+GenericWhereClauseSyntax GenericWhereClauseSyntax::
+withWhereKeyword(RC<TokenSyntax> NewWhereKeyword) const {
+ syntax_assert_token_is(NewWhereKeyword, tok::kw_where, "where");
+ return Data->replaceChild<GenericWhereClauseSyntax>(NewWhereKeyword,
+ Cursor::WhereKeyword);
+}
+
+GenericWhereClauseSyntax GenericWhereClauseSyntax::
+withRequirementList(GenericRequirementListSyntax NewRequirements) const {
+ return Data->replaceChild<GenericWhereClauseSyntax>(NewRequirements.getRaw(),
+ Cursor::RequirementList);
+}
+
#pragma mark - same-type-requirement Data
SameTypeRequirementSyntaxData::
SameTypeRequirementSyntaxData(RC<RawSyntax> Raw,
const SyntaxData *Parent,
CursorIndex IndexInParent)
- : SyntaxData(Raw, Parent, IndexInParent) {
+ : GenericRequirementSyntaxData(Raw, Parent, IndexInParent) {
assert(Raw->Kind == SyntaxKind::SameTypeRequirement);
assert(Raw->Layout.size() == 3);
syntax_assert_child_kind(Raw,
SameTypeRequirementSyntax::Cursor::LeftTypeIdentifier,
SyntaxKind::TypeIdentifier);
syntax_assert_child_token_text(Raw,
- SameTypeRequirementSyntax::Cursor::EqualityToken, tok::identifier, "==");
+ SameTypeRequirementSyntax::Cursor::EqualityToken,
+ tok::oper_binary_spaced, "==");
assert(Raw->getChild(SameTypeRequirementSyntax::Cursor::RightType)->isType());
}
diff --git a/lib/Syntax/LegacyASTTransformer.cpp b/lib/Syntax/LegacyASTTransformer.cpp
index 4356df0..2337447 100644
--- a/lib/Syntax/LegacyASTTransformer.cpp
+++ b/lib/Syntax/LegacyASTTransformer.cpp
@@ -443,11 +443,11 @@
BufferID, Tokens)
: TokenSyntax::missingToken(tok::l_brace, "{");
- StmtListSyntaxBuilder StmtsBuilder;
+ std::vector<StmtSyntax> Stmts;
for (auto Node : S->getElements()) {
auto Transformed = transformAST(Node, Sema, SourceMgr, BufferID, Tokens);
if (Transformed.hasValue()) {
- StmtsBuilder.addStatement(Transformed.getValue());
+ Stmts.push_back(Transformed.getValue().castTo<StmtSyntax>());
}
}
@@ -456,8 +456,9 @@
BufferID, Tokens)
: TokenSyntax::missingToken(tok::r_brace, "}");
- return SyntaxFactory::makeCodeBlock(LeftBrace, StmtsBuilder.build(),
- RightBrace).Root;
+ auto StmtList = SyntaxFactory::makeStmtList(Stmts);
+
+ return SyntaxFactory::makeCodeBlock(LeftBrace, StmtList, RightBrace).Root;
}
RC<SyntaxData>
diff --git a/lib/Syntax/Status.md b/lib/Syntax/Status.md
index 1c8a324..a2ed705 100644
--- a/lib/Syntax/Status.md
+++ b/lib/Syntax/Status.md
@@ -16,6 +16,12 @@
### Declarations
+- declaration-modifiers
+ - `DeclModifierListSyntax`
+
+- declaration-modifier
+ - `DeclModifierSyntax`
+
- struct-declaration
- `StructDeclSyntax`
@@ -40,6 +46,27 @@
- `DeclMembersSyntax`
- `StructDeclSyntax` used for the `{` `}` braces.
+- function-declaration
+ - `FunctionDeclSyntax`
+
+- function-body
+ - `CodeBlockSyntax`
+
+- function-result
+ - `TypeSyntax`
+
+- function-signature
+ - `FunctionSignatureSyntax`
+
+- parameter-clause
+ - `FunctionParameterClauseSyntax`
+
+- parameter-list
+ - `FunctionParameterListSyntax`
+
+- parameter
+ - `FunctionParameterSyntax`
+
### Statements
- statement
@@ -209,8 +236,6 @@
- as-pattern
- case-condition
- case-label
-- declaration-modifiers
- - declaration-modifier
- dynamic-type-expression
- floating-point-literal
- forced-value-expression
@@ -317,13 +342,6 @@
- setter-clause
- setter-name
- subscript-declaration
-- function-declaration
- - function-body
- - function-result
- - function-signature
- - parameter-clause
- - parameter-list
- - parameter
- enum-case-pattern
- initializer-declaration
- initializer-head
diff --git a/lib/Syntax/StmtSyntax.cpp b/lib/Syntax/StmtSyntax.cpp
index 89b272c..15890b1 100644
--- a/lib/Syntax/StmtSyntax.cpp
+++ b/lib/Syntax/StmtSyntax.cpp
@@ -380,58 +380,3 @@
CodeBlockStmtSyntax::CodeBlockStmtSyntax(const RC<SyntaxData> Root,
CodeBlockStmtSyntaxData *Data)
: StmtSyntax(Root, Data) {}
-
-
-#pragma mark statements Data
-
-StmtListSyntaxData::StmtListSyntaxData(RC<RawSyntax> Raw,
- const SyntaxData *Parent,
- CursorIndex IndexInParent)
- : StmtSyntaxData(Raw, Parent, IndexInParent) {
- assert(Raw->Kind == SyntaxKind::StmtList);
-}
-
-RC<StmtListSyntaxData> StmtListSyntaxData::make(RC<RawSyntax> Raw,
- const SyntaxData *Parent,
- CursorIndex IndexInParent) {
- return RC<StmtListSyntaxData> {
- new StmtListSyntaxData { Raw, Parent, IndexInParent }
- };
-}
-
-RC<StmtListSyntaxData> StmtListSyntaxData::makeBlank() {
- return make(RawSyntax::make(SyntaxKind::StmtList,
- {},
- SourcePresence::Present));
-}
-
-#pragma mark statements API
-
-StmtListSyntax::StmtListSyntax(const RC<SyntaxData> Root,
- const StmtListSyntaxData *Data)
- : Syntax(Root, Data) {}
-
-StmtListSyntax
-StmtListSyntax::withAddedStatement(Syntax AdditionalStatement) const {
- auto Layout = getRaw()->Layout;
- Layout.push_back(AdditionalStatement.getRaw());
- auto NewRaw = RawSyntax::make(SyntaxKind::StmtList, Layout,
- getRaw()->Presence);
- return Data->replaceSelf<StmtListSyntax>(NewRaw);
-}
-
-#pragma mark statements Builder
-
-StmtListSyntaxBuilder &
-StmtListSyntaxBuilder::addStatement(Syntax Statement) {
- StmtListLayout.push_back(Statement.getRaw());
- return *this;
-}
-
-StmtListSyntax StmtListSyntaxBuilder::build() const {
- auto Raw = RawSyntax::make(SyntaxKind::StmtList, StmtListLayout,
- SourcePresence::Present);
- auto Data = StmtListSyntaxData::make(Raw);
- return StmtListSyntax { Data, Data.get() };
-}
-
diff --git a/lib/Syntax/SyntaxData.cpp b/lib/Syntax/SyntaxData.cpp
index bc21dbf..06b008a 100644
--- a/lib/Syntax/SyntaxData.cpp
+++ b/lib/Syntax/SyntaxData.cpp
@@ -16,6 +16,7 @@
#include "swift/Syntax/TypeSyntax.h"
#include "swift/Syntax/StmtSyntax.h"
#include "swift/Syntax/UnknownSyntax.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace swift;
using namespace swift::syntax;
@@ -44,6 +45,8 @@
case SyntaxKind::Token:
llvm_unreachable("Can't make a SyntaxData from a Token!");
}
+
+ llvm_unreachable("Unhandled SyntaxKind in switch.");
}
bool SyntaxData::isType() const {
diff --git a/lib/Syntax/SyntaxFactory.cpp b/lib/Syntax/SyntaxFactory.cpp
index cd495f2..0350e4e 100644
--- a/lib/Syntax/SyntaxFactory.cpp
+++ b/lib/Syntax/SyntaxFactory.cpp
@@ -35,6 +35,51 @@
#pragma mark - Declarations
+#pragma mark - declaration-modifier
+
+DeclModifierSyntax SyntaxFactory::makeDeclModifier(RC<TokenSyntax> Name,
+ RC<TokenSyntax> LeftParen,
+ RC<TokenSyntax> Argument,
+ RC<TokenSyntax> RightParen) {
+ auto Raw = RawSyntax::make(SyntaxKind::DeclModifier,
+ {
+ Name,
+ LeftParen,
+ Argument,
+ RightParen,
+ },
+ SourcePresence::Present);
+ auto Data = DeclModifierSyntaxData::make(Raw);
+ return { Data, Data.get() };
+}
+
+DeclModifierSyntax SyntaxFactory::makeBlankDeclModifier() {
+ auto Data = DeclModifierSyntaxData::makeBlank();
+ return { Data, Data.get() };
+}
+
+#pragma mark - declaration-modifier-list
+
+DeclModifierListSyntax SyntaxFactory::
+makeDeclModifierList(const std::vector<DeclModifierSyntax> &Modifiers) {
+ RawSyntax::LayoutList Layout;
+ for (auto Modifier : Modifiers) {
+ Layout.push_back(Modifier.getRaw());
+ }
+
+ auto Raw = RawSyntax::make(SyntaxKind::DeclModifierList, Layout,
+ SourcePresence::Present);
+ auto Data = DeclModifierListSyntaxData::make(Raw);
+ return { Data, Data.get() };
+}
+
+DeclModifierListSyntax SyntaxFactory::makeBlankDeclModifierList() {
+ auto Data = DeclModifierListSyntaxData::makeBlank();
+ return { Data, Data.get() };
+}
+
+#pragma mark - struct-declaration
+
StructDeclSyntax
SyntaxFactory::makeStructDecl(RC<TokenSyntax> StructToken,
RC<TokenSyntax> Identifier,
@@ -66,6 +111,8 @@
};
}
+#pragma mark - type-alias-declaration
+
TypeAliasDeclSyntax SyntaxFactory::makeTypealiasDecl(
RC<TokenSyntax> TypealiasToken, RC<TokenSyntax> Identifier,
GenericParameterClauseSyntax GenericParams, RC<TokenSyntax> AssignmentToken,
@@ -88,130 +135,128 @@
return DeclMembersSyntax { Data, Data.get() };
}
-TypeIdentifierSyntax
-SyntaxFactory::makeTypeIdentifier(OwnedString Name,
- const Trivia &LeadingTrivia,
- const Trivia &TrailingTrivia) {
- auto Raw = RawSyntax::make(
- SyntaxKind::TypeIdentifier,
- {
- SyntaxFactory::makeIdentifier(Name, LeadingTrivia, TrailingTrivia),
- RawSyntax::missing(SyntaxKind::GenericArgumentClause),
- TokenSyntax::missingToken(tok::period, "."),
- RawSyntax::missing(SyntaxKind::TypeIdentifier),
- },
- SourcePresence::Present);
- auto Data = TypeIdentifierSyntaxData::make(Raw);
- return TypeIdentifierSyntax { Data, Data.get() };
-}
+#pragma mark - function-parameter
-TupleTypeElementSyntax
-SyntaxFactory::makeTupleTypeElement(TypeSyntax ElementType) {
- auto Data = TupleTypeElementSyntaxData::makeBlank();
- return TupleTypeElementSyntax { Data, Data.get() }
- .withTypeSyntax(ElementType);
-}
-
-TypeIdentifierSyntax
-SyntaxFactory::makeTypeIdentifier(RC<TokenSyntax> Identifier,
- GenericArgumentClauseSyntax GenericArgs) {
- auto Raw = RawSyntax::make(SyntaxKind::TypeIdentifier,
+FunctionParameterSyntax SyntaxFactory::
+makeFunctionParameter(RC<TokenSyntax> ExternalName,
+ RC<TokenSyntax> LocalName,
+ RC<TokenSyntax> Colon,
+ llvm::Optional<TypeSyntax> ParameterTypeSyntax,
+ RC<TokenSyntax> Ellipsis,
+ RC<TokenSyntax> Equal,
+ llvm::Optional<ExprSyntax> DefaultValue,
+ RC<TokenSyntax> TrailingComma) {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionParameter,
{
- Identifier, GenericArgs.getRaw(),
- TokenSyntax::missingToken(tok::period, "."),
- RawSyntax::missing(SyntaxKind::TypeIdentifier),
+ ExternalName,
+ LocalName,
+ Colon,
+ ParameterTypeSyntax.hasValue()
+ ? ParameterTypeSyntax.getValue().getRaw()
+ : RawSyntax::missing(SyntaxKind::MissingType),
+ Ellipsis,
+ Equal,
+ DefaultValue.hasValue()
+ ? DefaultValue.getValue().getRaw()
+ : RawSyntax::missing(SyntaxKind::MissingExpr),
+ TrailingComma,
},
SourcePresence::Present);
- auto Data = TypeIdentifierSyntaxData::make(Raw);
- return TypeIdentifierSyntax { Data, Data.get() };
+ auto Data = FunctionParameterSyntaxData::make(Raw);
+ return { Data, Data.get() };
}
-OptionalTypeSyntax
-SyntaxFactory::makeOptionalType(TypeSyntax BaseType,
- const Trivia &TrailingTrivia) {
- auto Raw = RawSyntax::make(SyntaxKind::OptionalType,
- {
- BaseType.getRaw(),
- SyntaxFactory::makeQuestionPostfixToken(TrailingTrivia),
- },
- SourcePresence::Present);
-
- auto Data = OptionalTypeSyntaxData::make(Raw);
- return OptionalTypeSyntax { Data, Data.get() };
+FunctionParameterSyntax SyntaxFactory::makeBlankFunctionParameter() {
+ auto Data = FunctionParameterSyntaxData::makeBlank();
+ return { Data, Data.get() };
}
-OptionalTypeSyntax SyntaxFactory::makeBlankOptionalType() {
- auto Data = OptionalTypeSyntaxData::makeBlank();
- return OptionalTypeSyntax { Data, Data.get() };
+#pragma mark - function-parameter-list
+
+FunctionParameterListSyntax SyntaxFactory::makeFunctionParameterList(
+ const std::vector<FunctionParameterSyntax> &Parameters) {
+ RawSyntax::LayoutList Layout;
+ for (auto Param : Parameters) {
+ Layout.push_back(Param.getRaw());
+ }
+
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionParameterList, Layout,
+ SourcePresence::Present);
+ auto Data = FunctionParameterListSyntaxData::make(Raw);
+ return { Data, Data.get() };
}
-ImplicitlyUnwrappedOptionalTypeSyntax
-SyntaxFactory::makeImplicitlyUnwrappedOptionalType(
- TypeSyntax BaseType, const Trivia &TrailingTrivia) {
- auto Raw = RawSyntax::make(SyntaxKind::ImplicitlyUnwrappedOptionalType,
- {
- BaseType.getRaw(), SyntaxFactory::makeExclaimPostfixToken(
- TrailingTrivia),
- },
- SourcePresence::Present);
- auto Data = ImplicitlyUnwrappedOptionalTypeSyntaxData::make(Raw);
- return ImplicitlyUnwrappedOptionalTypeSyntax { Data, Data.get() };
+FunctionParameterListSyntax SyntaxFactory::makeBlankFunctionParameterList() {
+ auto Data = FunctionParameterListSyntaxData::makeBlank();
+ return { Data, Data.get() };
}
-ImplicitlyUnwrappedOptionalTypeSyntax
-SyntaxFactory::makeBlankImplicitlyUnwrappedOptionalType() {
- auto Data = ImplicitlyUnwrappedOptionalTypeSyntaxData::makeBlank();
- return ImplicitlyUnwrappedOptionalTypeSyntax { Data, Data.get() };
-}
+#pragma mark - function-signature
-MetatypeTypeSyntax SyntaxFactory::makeMetatypeType(TypeSyntax BaseType,
- RC<TokenSyntax> DotToken,
- RC<TokenSyntax> TypeToken) {
- auto Raw = RawSyntax::make(SyntaxKind::MetatypeType,
- {
- BaseType.getRaw(),
- DotToken,
- TypeToken
- },
- SourcePresence::Present);
- auto Data = MetatypeTypeSyntaxData::make(Raw);
- return MetatypeTypeSyntax { Data, Data.get() };
-}
-
-MetatypeTypeSyntax SyntaxFactory::makeBlankMetatypeType() {
- auto Data = MetatypeTypeSyntaxData::makeBlank();
- return MetatypeTypeSyntax { Data, Data.get() };
-}
-
-TypeIdentifierSyntax SyntaxFactory::makeAnyTypeIdentifier() {
- auto Data = TypeIdentifierSyntaxData::makeBlank();
- return TypeIdentifierSyntax { Data, Data.get() }
- .withIdentifier(makeIdentifier("Any", {}, {}));
-}
-
-TypeIdentifierSyntax SyntaxFactory::makeSelfTypeIdentifier() {
- auto Data = TypeIdentifierSyntaxData::makeBlank();
- return TypeIdentifierSyntax { Data, Data.get() }
- .withIdentifier(makeIdentifier("Self", {}, {}));
-}
-
-SameTypeRequirementSyntax SyntaxFactory::makeSameTypeRequirement(
- TypeIdentifierSyntax LeftTypeIdentifier, RC<TokenSyntax> EqualityToken,
- TypeSyntax RightType) {
- auto Raw = RawSyntax::make(SyntaxKind::SameTypeRequirement,
+FunctionSignatureSyntax
+SyntaxFactory::makeFunctionSignature(RC<TokenSyntax> LeftParen,
+ FunctionParameterListSyntax ParameterList,
+ RC<TokenSyntax> RightParen,
+ RC<TokenSyntax> ThrowsOrRethrows,
+ RC<TokenSyntax> Arrow,
+ TypeAttributesSyntax ReturnTypeAttributes,
+ TypeSyntax ReturnTypeSyntax) {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionSignature,
{
- LeftTypeIdentifier.getRaw(),
- EqualityToken,
- RightType.getRaw()
+ LeftParen,
+ ParameterList.getRaw(),
+ RightParen,
+ ThrowsOrRethrows,
+ Arrow,
+ ReturnTypeAttributes.getRaw(),
+ ReturnTypeSyntax.getRaw()
},
SourcePresence::Present);
- auto Data = SameTypeRequirementSyntaxData::make(Raw);
- return SameTypeRequirementSyntax { Data, Data.get() };
+ auto Data = FunctionSignatureSyntaxData::make(Raw);
+ return { Data, Data.get() };
}
-SameTypeRequirementSyntax SyntaxFactory::makeBlankSameTypeRequirement() {
- auto Data = SameTypeRequirementSyntaxData::makeBlank();
- return SameTypeRequirementSyntax { Data, Data.get() };
+FunctionSignatureSyntax SyntaxFactory::makeBlankFunctionSignature() {
+ auto Data = FunctionSignatureSyntaxData::makeBlank();
+ return { Data, Data.get() };
+}
+
+#pragma mark - function-declaration
+
+FunctionDeclSyntax SyntaxFactory::
+makeFunctionDecl(TypeAttributesSyntax Attributes,
+ DeclModifierListSyntax Modifiers,
+ RC<TokenSyntax> FuncKeyword,
+ RC<TokenSyntax> Identifier,
+ llvm::Optional<GenericParameterClauseSyntax> GenericParams,
+ FunctionSignatureSyntax Signature,
+ llvm::Optional<GenericWhereClauseSyntax> GenericWhereClause,
+ llvm::Optional<CodeBlockStmtSyntax> Body) {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionDecl,
+ {
+ Attributes.getRaw(),
+ Modifiers.getRaw(),
+ FuncKeyword,
+ Identifier,
+ GenericParams.hasValue()
+ ? GenericParams.getValue().getRaw()
+ : SyntaxFactory::makeBlankGenericParameterClause().getRaw(),
+ Signature.getRaw(),
+ GenericWhereClause.hasValue()
+ ? GenericWhereClause.getValue().getRaw()
+ : SyntaxFactory::makeBlankGenericWhereClause().getRaw(),
+ Body.hasValue()
+ ? Body.getValue().getRaw()
+ : SyntaxFactory::makeBlankCodeBlock().getRaw()
+ },
+ SourcePresence::Present);
+ auto Data = FunctionDeclSyntaxData::make(Raw);
+ return { Data, Data.get() };
+}
+
+FunctionDeclSyntax SyntaxFactory::makeBlankFunctionDecl() {
+ auto Data = FunctionDeclSyntaxData::makeBlank();
+ return { Data, Data.get() };
}
#pragma mark - Statements
@@ -323,6 +368,27 @@
return { Data, Data.get() };
}
+/// Make a statement list from a loosely connected list of statements.
+StmtListSyntax
+SyntaxFactory::makeStmtList(const std::vector<StmtSyntax> &Statements) {
+ RawSyntax::LayoutList Layout;
+ for (auto Stmt : Statements) {
+ Layout.push_back(Stmt.getRaw());
+ }
+
+ auto Raw = RawSyntax::make(SyntaxKind::StmtList, Layout,
+ SourcePresence::Present);
+ auto Data = StmtListSyntaxData::make(Raw);
+ return { Data, Data.get() };
+}
+
+/// Make an empty statement list.
+StmtListSyntax SyntaxFactory::makeBlankStmtList() {
+ auto Raw = RawSyntax::make(SyntaxKind::StmtList, {}, SourcePresence::Present);
+ auto Data = StmtListSyntaxData::make(Raw);
+ return { Data, Data.get() };
+}
+
#pragma mark - Expressions
#pragma mark - integer-literal-expression
@@ -446,10 +512,33 @@
return { Data, Data.get() };
}
-
#pragma mark - Tokens
RC<TokenSyntax>
+SyntaxFactory::makeStaticKeyword(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia) {
+ return TokenSyntax::make(tok::kw_static, "static",
+ SourcePresence::Present,
+ LeadingTrivia, TrailingTrivia);
+}
+
+RC<TokenSyntax>
+SyntaxFactory::makePublicKeyword(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia) {
+ return TokenSyntax::make(tok::kw_public, "public",
+ SourcePresence::Present,
+ LeadingTrivia, TrailingTrivia);
+}
+
+RC<TokenSyntax>
+SyntaxFactory::makeFuncKeyword(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia) {
+ return TokenSyntax::make(tok::kw_func, "func",
+ SourcePresence::Present,
+ LeadingTrivia, TrailingTrivia);
+}
+
+RC<TokenSyntax>
SyntaxFactory::makeFallthroughKeyword(const Trivia &LeadingTrivia,
const Trivia &TrailingTrivia) {
return TokenSyntax::make(tok::kw_fallthrough, "fallthrough",
@@ -514,6 +603,19 @@
return TokenSyntax::make(tok::r_paren, ")", SourcePresence::Present,
LeadingTrivia, TrailingTrivia);
}
+RC<TokenSyntax>
+SyntaxFactory::makeLeftBraceToken(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia) {
+ return TokenSyntax::make(tok::l_brace, "{", SourcePresence::Present,
+ LeadingTrivia, TrailingTrivia);
+}
+
+RC<TokenSyntax>
+SyntaxFactory::makeRightBraceToken(const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia) {
+ return TokenSyntax::make(tok::r_brace, "}", SourcePresence::Present,
+ LeadingTrivia, TrailingTrivia);
+}
RC<TokenSyntax>
SyntaxFactory::makeLeftSquareBracketToken(const Trivia &LeadingTrivia,
@@ -731,30 +833,6 @@
};
}
-TupleTypeSyntax SyntaxFactory::makeVoidTupleType() {
- auto Raw = RawSyntax::make(SyntaxKind::TupleType,
- {
- SyntaxFactory::makeLeftParenToken({}, {}),
- RawSyntax::missing(SyntaxKind::TypeArgumentList),
- SyntaxFactory::makeRightParenToken({}, {}),
- },
- SourcePresence::Present);
- auto Data = TupleTypeSyntaxData::make(std::move(Raw));
- return TupleTypeSyntax {
- Data, Data.get()
- };
-}
-
-TupleTypeElementSyntax
-SyntaxFactory::makeTupleTypeElement(RC<TokenSyntax> Name,
- TypeSyntax ElementTypeSyntax) {
- auto Data = TupleTypeElementSyntaxData::makeBlank();
- return TupleTypeElementSyntax { Data, Data.get() }
- .withLabel(Name)
- .withColonToken(SyntaxFactory::makeColonToken({}, Trivia::spaces(1)))
- .withTypeSyntax(ElementTypeSyntax);
-}
-
#pragma mark - Generics
GenericParameterClauseSyntax
@@ -791,48 +869,41 @@
return GenericParameterSyntax { Data, Data.get() };
}
-ArrayTypeSyntax
-SyntaxFactory::makeArrayType(RC<TokenSyntax> LeftSquareBracket,
- TypeSyntax ElementType,
- RC<TokenSyntax> RightSquareBracket) {
- auto Raw = RawSyntax::make(SyntaxKind::ArrayType,
+SameTypeRequirementSyntax SyntaxFactory::
+makeSameTypeRequirement( TypeIdentifierSyntax LeftTypeIdentifier,
+ RC<TokenSyntax> EqualityToken,
+ TypeSyntax RightType) {
+ auto Raw = RawSyntax::make(SyntaxKind::SameTypeRequirement,
{
- LeftSquareBracket,
- ElementType.getRaw(),
- RightSquareBracket
+ LeftTypeIdentifier.getRaw(),
+ EqualityToken,
+ RightType.getRaw()
},
SourcePresence::Present);
- auto Data = ArrayTypeSyntaxData::make(Raw);
- return ArrayTypeSyntax { Data, Data.get() };
+ auto Data = SameTypeRequirementSyntaxData::make(Raw);
+ return SameTypeRequirementSyntax { Data, Data.get() };
}
-ArrayTypeSyntax SyntaxFactory::makeBlankArrayType() {
- auto Data = ArrayTypeSyntaxData::makeBlank();
- return ArrayTypeSyntax { Data, Data.get() };
+SameTypeRequirementSyntax SyntaxFactory::makeBlankSameTypeRequirement() {
+ auto Data = SameTypeRequirementSyntaxData::makeBlank();
+ return SameTypeRequirementSyntax { Data, Data.get() };
}
-DictionaryTypeSyntax
-SyntaxFactory::makeDictionaryType(RC<TokenSyntax> LeftSquareBracket,
- TypeSyntax KeyType,
- RC<TokenSyntax> Colon,
- TypeSyntax ValueType,
- RC<TokenSyntax> RightSquareBracket) {
- auto Raw = RawSyntax::make(SyntaxKind::DictionaryType,
- {
- LeftSquareBracket,
- KeyType.getRaw(),
- Colon,
- ValueType.getRaw(),
- RightSquareBracket
- },
+GenericRequirementListSyntax SyntaxFactory::
+makeGenericRequirementList(std::vector<GenericRequirementSyntax> &Requirements){
+ RawSyntax::LayoutList Layout;
+ for (auto Req : Requirements) {
+ Layout.push_back(Req.getRaw());
+ }
+ auto Raw = RawSyntax::make(SyntaxKind::GenericRequirementList, Layout,
SourcePresence::Present);
- auto Data = DictionaryTypeSyntaxData::make(Raw);
- return DictionaryTypeSyntax { Data, Data.get() };
+ auto Data = GenericRequirementListSyntaxData::make(Raw);
+ return { Data, Data.get() };
}
-DictionaryTypeSyntax SyntaxFactory::makeBlankDictionaryType() {
- auto Data = DictionaryTypeSyntaxData::makeBlank();
- return DictionaryTypeSyntax { Data, Data.get() };
+GenericRequirementListSyntax SyntaxFactory::makeBlankGenericRequirementList() {
+ auto Data = GenericRequirementListSyntaxData::makeBlank();
+ return { Data, Data.get() };
}
#pragma mark - Operators
@@ -891,6 +962,148 @@
return BalancedTokensSyntax { Data, Data.get() };
}
+#pragma mark - type-identifier
+
+TypeIdentifierSyntax
+SyntaxFactory::makeTypeIdentifier(OwnedString Name,
+ const Trivia &LeadingTrivia,
+ const Trivia &TrailingTrivia) {
+ auto Raw = RawSyntax::make(
+ SyntaxKind::TypeIdentifier,
+ {
+ SyntaxFactory::makeIdentifier(Name, LeadingTrivia, TrailingTrivia),
+ RawSyntax::missing(SyntaxKind::GenericArgumentClause),
+ TokenSyntax::missingToken(tok::period, "."),
+ RawSyntax::missing(SyntaxKind::TypeIdentifier),
+ },
+ SourcePresence::Present);
+ auto Data = TypeIdentifierSyntaxData::make(Raw);
+ return TypeIdentifierSyntax { Data, Data.get() };
+}
+
+TypeIdentifierSyntax SyntaxFactory::makeAnyTypeIdentifier() {
+ auto Data = TypeIdentifierSyntaxData::makeBlank();
+ return TypeIdentifierSyntax { Data, Data.get() }
+ .withIdentifier(makeIdentifier("Any", {}, {}));
+}
+
+TypeIdentifierSyntax SyntaxFactory::makeSelfTypeIdentifier() {
+ auto Data = TypeIdentifierSyntaxData::makeBlank();
+ return TypeIdentifierSyntax { Data, Data.get() }
+ .withIdentifier(makeIdentifier("Self", {}, {}));
+}
+
+TypeIdentifierSyntax
+SyntaxFactory::makeTypeIdentifier(RC<TokenSyntax> Identifier,
+ GenericArgumentClauseSyntax GenericArgs) {
+ auto Raw = RawSyntax::make(SyntaxKind::TypeIdentifier,
+ {
+ Identifier, GenericArgs.getRaw(),
+ TokenSyntax::missingToken(tok::period, "."),
+ RawSyntax::missing(SyntaxKind::TypeIdentifier),
+ },
+ SourcePresence::Present);
+ auto Data = TypeIdentifierSyntaxData::make(Raw);
+ return TypeIdentifierSyntax { Data, Data.get() };
+}
+
+#pragma mark - tuple-type
+
+TupleTypeSyntax SyntaxFactory::makeVoidTupleType() {
+ auto Raw = RawSyntax::make(SyntaxKind::TupleType,
+ {
+ SyntaxFactory::makeLeftParenToken({}, {}),
+ RawSyntax::missing(SyntaxKind::TypeArgumentList),
+ SyntaxFactory::makeRightParenToken({}, {}),
+ },
+ SourcePresence::Present);
+ auto Data = TupleTypeSyntaxData::make(std::move(Raw));
+ return TupleTypeSyntax {
+ Data, Data.get()
+ };
+}
+
+TupleTypeElementSyntax
+SyntaxFactory::makeTupleTypeElement(RC<TokenSyntax> Name,
+ TypeSyntax ElementTypeSyntax) {
+ auto Data = TupleTypeElementSyntaxData::makeBlank();
+ return TupleTypeElementSyntax { Data, Data.get() }
+ .withLabel(Name)
+ .withColonToken(SyntaxFactory::makeColonToken({}, Trivia::spaces(1)))
+ .withTypeSyntax(ElementTypeSyntax);
+}
+
+
+TupleTypeElementSyntax
+SyntaxFactory::makeTupleTypeElement(TypeSyntax ElementType) {
+ auto Data = TupleTypeElementSyntaxData::makeBlank();
+ return TupleTypeElementSyntax { Data, Data.get() }
+ .withTypeSyntax(ElementType);
+}
+
+#pragma mark - optional-type
+
+OptionalTypeSyntax
+SyntaxFactory::makeOptionalType(TypeSyntax BaseType,
+ const Trivia &TrailingTrivia) {
+ auto Raw = RawSyntax::make(SyntaxKind::OptionalType,
+ {
+ BaseType.getRaw(),
+ SyntaxFactory::makeQuestionPostfixToken(TrailingTrivia),
+ },
+ SourcePresence::Present);
+
+ auto Data = OptionalTypeSyntaxData::make(Raw);
+ return OptionalTypeSyntax { Data, Data.get() };
+}
+
+OptionalTypeSyntax SyntaxFactory::makeBlankOptionalType() {
+ auto Data = OptionalTypeSyntaxData::makeBlank();
+ return OptionalTypeSyntax { Data, Data.get() };
+}
+
+#pragma mark - implicitly-unwrapped-optional-type
+
+ImplicitlyUnwrappedOptionalTypeSyntax SyntaxFactory::
+makeImplicitlyUnwrappedOptionalType(TypeSyntax BaseType,
+ const Trivia &TrailingTrivia) {
+ auto Raw = RawSyntax::make(SyntaxKind::ImplicitlyUnwrappedOptionalType,
+ {
+ BaseType.getRaw(),
+ SyntaxFactory::makeExclaimPostfixToken(TrailingTrivia),
+ },
+ SourcePresence::Present);
+ auto Data = ImplicitlyUnwrappedOptionalTypeSyntaxData::make(Raw);
+ return ImplicitlyUnwrappedOptionalTypeSyntax { Data, Data.get() };
+}
+
+ImplicitlyUnwrappedOptionalTypeSyntax
+SyntaxFactory::makeBlankImplicitlyUnwrappedOptionalType() {
+ auto Data = ImplicitlyUnwrappedOptionalTypeSyntaxData::makeBlank();
+ return ImplicitlyUnwrappedOptionalTypeSyntax { Data, Data.get() };
+}
+
+#pragma mark - metatype-type
+
+MetatypeTypeSyntax SyntaxFactory::makeMetatypeType(TypeSyntax BaseType,
+ RC<TokenSyntax> DotToken,
+ RC<TokenSyntax> TypeToken) {
+ auto Raw = RawSyntax::make(SyntaxKind::MetatypeType,
+ {
+ BaseType.getRaw(),
+ DotToken,
+ TypeToken
+ },
+ SourcePresence::Present);
+ auto Data = MetatypeTypeSyntaxData::make(Raw);
+ return MetatypeTypeSyntax { Data, Data.get() };
+}
+
+MetatypeTypeSyntax SyntaxFactory::makeBlankMetatypeType() {
+ auto Data = MetatypeTypeSyntaxData::makeBlank();
+ return MetatypeTypeSyntax { Data, Data.get() };
+}
+
#pragma mark - function-type
FunctionTypeSyntax SyntaxFactory::makeFunctionType(
@@ -919,8 +1132,7 @@
return FunctionTypeSyntax { Data, Data.get() };
}
-#pragma mark -
-#pragma mark function-type-argument
+#pragma mark - function-type-argument
FunctionTypeArgumentSyntax SyntaxFactory::
makeFunctionTypeArgument(RC<TokenSyntax> ExternalParameterName,
@@ -986,3 +1198,53 @@
auto Data = TypeArgumentListSyntaxData::makeBlank();
return TypeArgumentListSyntax { Data, Data.get() };
}
+
+#pragma mark - array-type
+
+ArrayTypeSyntax
+SyntaxFactory::makeArrayType(RC<TokenSyntax> LeftSquareBracket,
+ TypeSyntax ElementType,
+ RC<TokenSyntax> RightSquareBracket) {
+ auto Raw = RawSyntax::make(SyntaxKind::ArrayType,
+ {
+ LeftSquareBracket,
+ ElementType.getRaw(),
+ RightSquareBracket
+ },
+ SourcePresence::Present);
+ auto Data = ArrayTypeSyntaxData::make(Raw);
+ return ArrayTypeSyntax { Data, Data.get() };
+}
+
+ArrayTypeSyntax SyntaxFactory::makeBlankArrayType() {
+ auto Data = ArrayTypeSyntaxData::makeBlank();
+ return ArrayTypeSyntax { Data, Data.get() };
+}
+
+#pragma mark - dictionary-type
+
+DictionaryTypeSyntax
+SyntaxFactory::makeDictionaryType(RC<TokenSyntax> LeftSquareBracket,
+ TypeSyntax KeyType,
+ RC<TokenSyntax> Colon,
+ TypeSyntax ValueType,
+ RC<TokenSyntax> RightSquareBracket) {
+ auto Raw = RawSyntax::make(SyntaxKind::DictionaryType,
+ {
+ LeftSquareBracket,
+ KeyType.getRaw(),
+ Colon,
+ ValueType.getRaw(),
+ RightSquareBracket
+ },
+ SourcePresence::Present);
+ auto Data = DictionaryTypeSyntaxData::make(Raw);
+ return DictionaryTypeSyntax { Data, Data.get() };
+}
+
+DictionaryTypeSyntax SyntaxFactory::makeBlankDictionaryType() {
+ auto Data = DictionaryTypeSyntaxData::makeBlank();
+ return DictionaryTypeSyntax { Data, Data.get() };
+}
+
+
diff --git a/stdlib/CMakeLists.txt b/stdlib/CMakeLists.txt
index 4ad01ab..5c24007 100644
--- a/stdlib/CMakeLists.txt
+++ b/stdlib/CMakeLists.txt
@@ -28,6 +28,14 @@
append("-fno-sanitize=all" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
endif()
+# Do not enforce checks for LLVM's ABI-breaking build settings.
+# The Swift runtime uses some header-only code from LLVM's ADT classes,
+# but we do not want to link libSupport into the runtime. These checks rely
+# on the presence of symbols in libSupport to identify how the code was
+# built and cause link failures for mismatches. Without linking that library,
+# we get link failures regardless, so instead, this just disables the checks.
+append("-DLLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING=1" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
+
set(SWIFT_STDLIB_LIBRARY_BUILD_TYPES)
if(SWIFT_BUILD_DYNAMIC_STDLIB)
list(APPEND SWIFT_STDLIB_LIBRARY_BUILD_TYPES SHARED)
diff --git a/stdlib/public/SwiftShims/HeapObject.h b/stdlib/public/SwiftShims/HeapObject.h
index 4762d02..d9bf257 100644
--- a/stdlib/public/SwiftShims/HeapObject.h
+++ b/stdlib/public/SwiftShims/HeapObject.h
@@ -31,7 +31,7 @@
// The members of the HeapObject header that are not shared by a
// standard Objective-C instance
#define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS \
- InlineRefCounts refCounts;
+ InlineRefCounts refCounts
/// The Swift heap-object header.
struct HeapObject {
diff --git a/stdlib/public/SwiftShims/LibcShims.h b/stdlib/public/SwiftShims/LibcShims.h
index 4164231..aebd6a2 100644
--- a/stdlib/public/SwiftShims/LibcShims.h
+++ b/stdlib/public/SwiftShims/LibcShims.h
@@ -91,35 +91,35 @@
_swift_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound);
// Math library functions
-static inline __attribute__((always_inline))
+static inline SWIFT_ALWAYS_INLINE
float _swift_stdlib_remainderf(float _self, float _other) {
return __builtin_remainderf(_self, _other);
}
-static inline __attribute__((always_inline))
+static inline SWIFT_ALWAYS_INLINE
float _swift_stdlib_squareRootf(float _self) {
return __builtin_sqrt(_self);
}
-static inline __attribute__((always_inline))
+static inline SWIFT_ALWAYS_INLINE
double _swift_stdlib_remainder(double _self, double _other) {
return __builtin_remainder(_self, _other);
}
-static inline __attribute__((always_inline))
+static inline SWIFT_ALWAYS_INLINE
double _swift_stdlib_squareRoot(double _self) {
return __builtin_sqrt(_self);
}
// TODO: Remove horrible workaround when importer does Float80 <-> long double.
#if (defined __i386__ || defined __x86_64__) && !defined _MSC_VER
-static inline __attribute__((always_inline))
+static inline SWIFT_ALWAYS_INLINE
void _swift_stdlib_remainderl(void *_self, const void *_other) {
long double *_f80self = (long double *)_self;
*_f80self = __builtin_remainderl(*_f80self, *(const long double *)_other);
}
-static inline __attribute__((always_inline))
+static inline SWIFT_ALWAYS_INLINE
void _swift_stdlib_squareRootl(void *_self) {
long double *_f80self = (long double *)_self;
*_f80self = __builtin_sqrtl(*_f80self);
@@ -135,4 +135,3 @@
#endif
#endif // SWIFT_STDLIB_SHIMS_LIBCSHIMS_H
-
diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h
index 95f102b..0b3b2b7 100644
--- a/stdlib/public/SwiftShims/RefCount.h
+++ b/stdlib/public/SwiftShims/RefCount.h
@@ -12,6 +12,8 @@
#ifndef SWIFT_STDLIB_SHIMS_REFCOUNT_H
#define SWIFT_STDLIB_SHIMS_REFCOUNT_H
+#include "Visibility.h"
+
#if !defined(__cplusplus)
// These definitions are placeholders for importing into Swift.
@@ -20,7 +22,7 @@
#include "SwiftStdint.h"
typedef struct {
- __swift_uint64_t refCounts __attribute__((__unavailable__));
+ __swift_uint64_t refCounts SWIFT_ATTRIBUTE_UNAVAILABLE;
} InlineRefCounts;
// not __cplusplus
@@ -191,10 +193,9 @@
}
// FIXME: HACK: copied from HeapObject.cpp
-extern "C" LLVM_LIBRARY_VISIBILITY void
-_swift_release_dealloc(swift::HeapObject *object)
- SWIFT_CC(RegisterPreservingCC_IMPL)
- __attribute__((__noinline__, __used__));
+extern "C" LLVM_LIBRARY_VISIBILITY LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
+void _swift_release_dealloc(swift::HeapObject *object)
+SWIFT_CC(RegisterPreservingCC_IMPL);
namespace swift {
diff --git a/stdlib/public/SwiftShims/UnicodeShims.h b/stdlib/public/SwiftShims/UnicodeShims.h
index c8c99d8..93253d9 100644
--- a/stdlib/public/SwiftShims/UnicodeShims.h
+++ b/stdlib/public/SwiftShims/UnicodeShims.h
@@ -63,21 +63,21 @@
_swift_stdlib_ExtendedGraphemeClusterNoBoundaryRulesMatrix;
SWIFT_RUNTIME_STDLIB_INTERFACE
-__attribute__((__pure__)) __swift_int32_t
+SWIFT_READONLY __swift_int32_t
_swift_stdlib_unicode_compare_utf16_utf16(const __swift_uint16_t *Left,
__swift_int32_t LeftLength,
const __swift_uint16_t *Right,
__swift_int32_t RightLength);
SWIFT_RUNTIME_STDLIB_INTERFACE
-__attribute__((__pure__)) __swift_int32_t
+SWIFT_READONLY __swift_int32_t
_swift_stdlib_unicode_compare_utf8_utf16(const unsigned char *Left,
__swift_int32_t LeftLength,
const __swift_uint16_t *Right,
__swift_int32_t RightLength);
SWIFT_RUNTIME_STDLIB_INTERFACE
-__attribute__((__pure__)) __swift_int32_t
+SWIFT_READONLY __swift_int32_t
_swift_stdlib_unicode_compare_utf8_utf8(const unsigned char *Left,
__swift_int32_t LeftLength,
const unsigned char *Right,
diff --git a/stdlib/public/SwiftShims/Visibility.h b/stdlib/public/SwiftShims/Visibility.h
index 555e369..1d36a44 100644
--- a/stdlib/public/SwiftShims/Visibility.h
+++ b/stdlib/public/SwiftShims/Visibility.h
@@ -56,6 +56,18 @@
#define SWIFT_READNONE
#endif
+#if __has_attribute(always_inline)
+#define SWIFT_ALWAYS_INLINE __attribute__((always_inline))
+#else
+#define SWIFT_ALWAYS_INLINE
+#endif
+
+#if __has_attribute(unavailable)
+#define SWIFT_ATTRIBUTE_UNAVAILABLE __attribute__((__unavailable__))
+#else
+#define SWIFT_ATTRIBUTE_UNAVAILABLE
+#endif
+
// TODO: support using shims headers in overlays by parameterizing
// SWIFT_RUNTIME_EXPORT on the library it's exported from, then setting
// protected vs. default based on the current value of __SWIFT_CURRENT_DYLIB.
diff --git a/stdlib/public/core/RangeReplaceableCollection.swift.gyb b/stdlib/public/core/RangeReplaceableCollection.swift.gyb
index db2461f..ca34ad5 100644
--- a/stdlib/public/core/RangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/RangeReplaceableCollection.swift.gyb
@@ -237,10 +237,10 @@
/// add an empty initializer and the `replaceSubrange(_:with:)` method to your
/// custom type. `RangeReplaceableCollection` provides default implementations
/// of all its other methods using this initializer and method. For example,
-/// the `removeSubrange` method is implemented by calling `replaceRange` with
-/// an empty collection for the `newElements` parameter. You can override any
-/// of the protocol's required methods to provide your own custom
-/// implementation.
+/// the `removeSubrange(_:)` method is implemented by calling
+/// `replaceSubrange(_:with:)` with an empty collection for the `newElements`
+/// parameter. You can override any of the protocol's required methods to
+/// provide your own custom implementation.
public protocol RangeReplaceableCollection
: _RangeReplaceableIndexable, Collection
{
diff --git a/stdlib/public/runtime/MetadataImpl.h b/stdlib/public/runtime/MetadataImpl.h
index a9ca348..1de0899 100644
--- a/stdlib/public/runtime/MetadataImpl.h
+++ b/stdlib/public/runtime/MetadataImpl.h
@@ -881,6 +881,7 @@
static OpaqueValue *projectBuffer(ValueBuffer *buffer, const Metadata *self) {
auto vwtable = self->getValueWitnesses();
+ (void)vwtable;
if (!IsKnownAllocated && vwtable->isValueInline()) {
return reinterpret_cast<OpaqueValue*>(buffer);
} else {
@@ -900,6 +901,7 @@
ValueBuffer *src,
const Metadata *self) {
auto vwtable = self->getValueWitnesses();
+ (void)vwtable;
if (!IsKnownAllocated && !vwtable->isValueInline()) {
return Impl::initializeWithTake(reinterpret_cast<OpaqueValue*>(dest),
reinterpret_cast<OpaqueValue*>(src),
diff --git a/stdlib/public/runtime/Reflection.mm b/stdlib/public/runtime/Reflection.mm
index ebeed8c..0a55a03 100644
--- a/stdlib/public/runtime/Reflection.mm
+++ b/stdlib/public/runtime/Reflection.mm
@@ -233,6 +233,8 @@
case MetadataKind::ErrorObject:
return "(ErrorType Object)";
}
+
+ swift_runtime_unreachable("Unhandled MetadataKind in switch.");
}
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
diff --git a/stdlib/public/stubs/OptionalBridgingHelper.mm b/stdlib/public/stubs/OptionalBridgingHelper.mm
index f0cc56a..8a71e91 100644
--- a/stdlib/public/stubs/OptionalBridgingHelper.mm
+++ b/stdlib/public/stubs/OptionalBridgingHelper.mm
@@ -36,7 +36,7 @@
- (NSString*)description {
return [NSString stringWithFormat:@"<%@ %p depth = %u>", [self class],
- self,
+ (void*)self,
self->depth];
}
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Types.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Types.h
index c44439f..6a509e5 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Types.h
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Types.h
@@ -1,7 +1,7 @@
#pragma clang assume_nonnull begin
struct __attribute__((swift_name("VeryImportantCStruct"))) SomeCStruct {
- int field;
+ int field;
};
#pragma clang assume_nonnull end
diff --git a/test/ClangImporter/objc_factory_method.swift b/test/ClangImporter/objc_factory_method.swift
index b26ff08..fb3bfc5 100644
--- a/test/ClangImporter/objc_factory_method.swift
+++ b/test/ClangImporter/objc_factory_method.swift
@@ -30,6 +30,7 @@
}
func testFactoryWithLaterIntroducedInit() {
+ // expected-note @-1 4{{add @available attribute to enclosing global function}}
// Prefer importing more available factory initializer over less
// less available convenience initializer
_ = NSHavingConvenienceFactoryAndLaterConvenienceInit(flim:5)
@@ -44,22 +45,19 @@
// available designated initializer
_ = NSHavingConvenienceFactoryAndLaterDesignatedInit(flim:5) // expected-error {{'init(flim:)' is only available on OS X 10.52 or newer}}
// expected-note @-1 {{add 'if #available' version check}}
- // expected-note @-2 {{add @available attribute to enclosing global function}}
_ = NSHavingConvenienceFactoryAndLaterDesignatedInit(flam:5) // expected-error {{'init(flam:)' is only available on OS X 10.52 or newer}}
// expected-note @-1 {{add 'if #available' version check}} {{3-63=if #available(OSX 10.52, *) {\n _ = NSHavingConvenienceFactoryAndLaterDesignatedInit(flam:5)\n \} else {\n // Fallback on earlier versions\n \}}}
- // expected-note @-2 {{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.52, *)\n}}
// Don't prefer more available factory initializer over less
// available designated initializer
_ = NSHavingFactoryAndLaterConvenienceInit(flim:5) // expected-error {{'init(flim:)' is only available on OS X 10.52 or newer}}
// expected-note @-1 {{add 'if #available' version check}}
- // expected-note @-2 {{add @available attribute to enclosing global function}}
+
_ = NSHavingFactoryAndLaterConvenienceInit(flam:5) // expected-error {{'init(flam:)' is only available on OS X 10.52 or newer}}
// expected-note @-1 {{add 'if #available' version check}}
- // expected-note @-2 {{add @available attribute to enclosing global function}}
// When both a convenience factory and a convenience initializer have the
diff --git a/test/Constraints/associated_types.swift b/test/Constraints/associated_types.swift
index 2436e92..6dee6f6 100644
--- a/test/Constraints/associated_types.swift
+++ b/test/Constraints/associated_types.swift
@@ -37,3 +37,75 @@
func spoon<S: Spoon>(_ s: S) {
let _: S.Runcee?
}
+
+// SR-4143
+
+protocol SameTypedDefault {
+ associatedtype X
+ associatedtype Y
+ static var x: X { get }
+ static var y: Y { get }
+}
+extension SameTypedDefault where Y == X {
+ static var x: X {
+ return y
+ }
+}
+
+struct UsesSameTypedDefault: SameTypedDefault {
+ static var y: Int {
+ return 0
+ }
+}
+
+protocol XReqt {}
+protocol YReqt {}
+
+protocol SameTypedDefaultWithReqts {
+ associatedtype X: XReqt // expected-note{{}}
+ associatedtype Y: YReqt // expected-note{{}}
+ static var x: X { get }
+ static var y: Y { get }
+}
+extension SameTypedDefaultWithReqts where Y == X {
+ static var x: X {
+ return y
+ }
+}
+
+struct XYType: XReqt, YReqt {}
+struct YType: YReqt {}
+
+struct UsesSameTypedDefaultWithReqts: SameTypedDefaultWithReqts {
+ static var y: XYType { return XYType() }
+}
+
+// expected-error@+1{{does not conform}}
+struct UsesSameTypedDefaultWithoutSatisfyingReqts: SameTypedDefaultWithReqts {
+ static var y: YType { return YType() }
+}
+
+protocol SameTypedDefaultBaseWithReqts {
+ associatedtype X: XReqt // expected-note{{}}
+ static var x: X { get }
+}
+protocol SameTypedDefaultDerivedWithReqts: SameTypedDefaultBaseWithReqts {
+ associatedtype Y: YReqt
+ static var y: Y { get }
+}
+
+extension SameTypedDefaultDerivedWithReqts where Y == X {
+ static var x: X {
+ return y
+ }
+}
+
+struct UsesSameTypedDefaultDerivedWithReqts: SameTypedDefaultDerivedWithReqts {
+ static var y: XYType { return XYType() }
+}
+
+// expected-error@+1{{does not conform}}
+struct UsesSameTypedDefaultDerivedWithoutSatisfyingReqts: SameTypedDefaultDerivedWithReqts {
+ static var y: YType { return YType() }
+}
+
diff --git a/test/DebugInfo/inlined-generics.swift b/test/DebugInfo/inlined-generics.swift
index fc2c84c..3005ee3 100644
--- a/test/DebugInfo/inlined-generics.swift
+++ b/test/DebugInfo/inlined-generics.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -Xllvm -sil-inline-generics=true %s -O -emit-sil -g -o - -emit-ir | %FileCheck %s
+// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -Xllvm -sil-inline-generics=true %s -O -g -o - -emit-ir | %FileCheck %s
public protocol P {
associatedtype DT1
func getDT() -> DT1
@@ -18,3 +18,38 @@
// T.DT1 should get substituted with S.DT1.
// CHECK: ![[META]] = !DILocalVariable(name: "$swift.type.S.DT1"
}
+
+
+// More complex example -- we inline an alloc_stack that references a VarDecl
+// with generic type.
+
+public protocol Q : class {
+ associatedtype T : Equatable
+
+ var old: T? { get set }
+ var new: T? { get }
+}
+
+@inline(__always)
+public func update<S : Q>(_ s: S) -> (S.T?, S.T?)? {
+ let oldValue = s.old
+ let newValue = s.new
+
+ if oldValue != newValue {
+ s.old = newValue
+ return (oldValue, newValue)
+ } else {
+ return nil
+ }
+}
+
+public class C : Q {
+ public typealias T = String
+
+ public var old: String? = nil
+ public var new: T? = nil
+}
+
+public func updateC(_ c: C) {
+ update(c)
+}
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index 4edae05..17e8779 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -77,10 +77,12 @@
_TF3foog3barSi ---> foo.bar.getter : Swift.Int
_TF3foos3barSi ---> foo.bar.setter : Swift.Int
_TFC3foo3bar3basfT3zimCS_3zim_T_ ---> foo.bar.bas (zim : foo.zim) -> ()
-_TToFC3foo3bar3basfT3zimCS_3zim_T_ ---> {T} @objc foo.bar.bas (zim : foo.zim) -> ()
-_TTOFSC3fooFTSdSd_Sd ---> {T} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
-_T03foo3barC3basyAA3zimCAE_tFTo ---> {T} @objc foo.bar.bas (zim : foo.zim) -> ()
-_T0SC3fooSdSd_SdtFTO ---> {T} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
+_TToFC3foo3bar3basfT3zimCS_3zim_T_ ---> {T:_TFC3foo3bar3basfT3zimCS_3zim_T_,C} @objc foo.bar.bas (zim : foo.zim) -> ()
+_TTOFSC3fooFTSdSd_Sd ---> {T:_TFSC3fooFTSdSd_Sd} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
+_T03foo3barC3basyAA3zimCAE_tFTo ---> {T:_T03foo3barC3basyAA3zimCAE_tF,C} @objc foo.bar.bas (zim : foo.zim) -> ()
+_T0SC3fooSdSd_SdtFTO ---> {T:_T0SC3fooSdSd_SdtF} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
+_S3foo3barC3basyAA3zimCAE_tFTo ---> {T:_S3foo3barC3basyAA3zimCAE_tF,C} @objc foo.bar.bas (zim : foo.zim) -> ()
+_SSC3fooSdSd_SdtFTO ---> {T:_SSC3fooSdSd_SdtF} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
_TTDFC3foo3bar3basfT3zimCS_3zim_T_ ---> dynamic foo.bar.bas (zim : foo.zim) -> ()
_TFC3foo3bar3basfT3zimCS_3zim_T_ ---> foo.bar.bas (zim : foo.zim) -> ()
_TF3foooi1pFTCS_3barVS_3bas_OS_3zim ---> foo.+ infix (foo.bar, foo.bas) -> foo.zim
@@ -94,31 +96,31 @@
_TMmC3foo3bar ---> metaclass for foo.bar
_TMC3foo3bar ---> type metadata for foo.bar
_TMfC3foo3bar ---> full type metadata for foo.bar
-_TwalC3foo3bar ---> allocateBuffer value witness for foo.bar
-_TwcaC3foo3bar ---> assignWithCopy value witness for foo.bar
-_TwtaC3foo3bar ---> assignWithTake value witness for foo.bar
-_TwdeC3foo3bar ---> deallocateBuffer value witness for foo.bar
-_TwxxC3foo3bar ---> destroy value witness for foo.bar
-_TwXXC3foo3bar ---> destroyBuffer value witness for foo.bar
-_TwCPC3foo3bar ---> initializeBufferWithCopyOfBuffer value witness for foo.bar
-_TwCpC3foo3bar ---> initializeBufferWithCopy value witness for foo.bar
-_TwcpC3foo3bar ---> initializeWithCopy value witness for foo.bar
-_TwTKC3foo3bar ---> initializeBufferWithTakeOfBuffer value witness for foo.bar
-_TwTkC3foo3bar ---> initializeBufferWithTake value witness for foo.bar
-_TwtkC3foo3bar ---> initializeWithTake value witness for foo.bar
-_TwprC3foo3bar ---> projectBuffer value witness for foo.bar
+_TwalC3foo3bar ---> {C} allocateBuffer value witness for foo.bar
+_TwcaC3foo3bar ---> {C} assignWithCopy value witness for foo.bar
+_TwtaC3foo3bar ---> {C} assignWithTake value witness for foo.bar
+_TwdeC3foo3bar ---> {C} deallocateBuffer value witness for foo.bar
+_TwxxC3foo3bar ---> {C} destroy value witness for foo.bar
+_TwXXC3foo3bar ---> {C} destroyBuffer value witness for foo.bar
+_TwCPC3foo3bar ---> {C} initializeBufferWithCopyOfBuffer value witness for foo.bar
+_TwCpC3foo3bar ---> {C} initializeBufferWithCopy value witness for foo.bar
+_TwcpC3foo3bar ---> {C} initializeWithCopy value witness for foo.bar
+_TwTKC3foo3bar ---> {C} initializeBufferWithTakeOfBuffer value witness for foo.bar
+_TwTkC3foo3bar ---> {C} initializeBufferWithTake value witness for foo.bar
+_TwtkC3foo3bar ---> {C} initializeWithTake value witness for foo.bar
+_TwprC3foo3bar ---> {C} projectBuffer value witness for foo.bar
_TWVC3foo3bar ---> value witness table for foo.bar
_TWoFC3foo3bar3basFSiSi ---> witness table offset for foo.bar.bas (Swift.Int) -> Swift.Int
_TWvdvC3foo3bar3basSi ---> direct field offset for foo.bar.bas : Swift.Int
_TWvivC3foo3bar3basSi ---> indirect field offset for foo.bar.bas : Swift.Int
_TWPC3foo3barS_8barrables ---> protocol witness table for foo.bar : foo.barrable in Swift
-_TWaC3foo3barS_8barrableS_ ---> protocol witness table accessor for foo.bar : foo.barrable in foo
-_TWlC3foo3barS0_S_8barrableS_ ---> lazy protocol witness table accessor for type foo.bar and conformance foo.bar : foo.barrable in foo
+_TWaC3foo3barS_8barrableS_ ---> {C} protocol witness table accessor for foo.bar : foo.barrable in foo
+_TWlC3foo3barS0_S_8barrableS_ ---> {C} lazy protocol witness table accessor for type foo.bar and conformance foo.bar : foo.barrable in foo
_TWLC3foo3barS0_S_8barrableS_ ---> lazy protocol witness table cache variable for type foo.bar and conformance foo.bar : foo.barrable in foo
_TWGC3foo3barS_8barrableS_ ---> generic protocol witness table for foo.bar : foo.barrable in foo
-_TWIC3foo3barS_8barrableS_ ---> instantiation function for generic protocol witness table for foo.bar : foo.barrable in foo
-_TWtC3foo3barS_8barrableS_4fred ---> associated type metadata accessor for fred in foo.bar : foo.barrable in foo
-_TWTC3foo3barS_8barrableS_4fredS_6thomas ---> associated type witness table accessor for fred : foo.thomas in foo.bar : foo.barrable in foo
+_TWIC3foo3barS_8barrableS_ ---> {C} instantiation function for generic protocol witness table for foo.bar : foo.barrable in foo
+_TWtC3foo3barS_8barrableS_4fred ---> {C} associated type metadata accessor for fred in foo.bar : foo.barrable in foo
+_TWTC3foo3barS_8barrableS_4fredS_6thomas ---> {C} associated type witness table accessor for fred : foo.thomas in foo.bar : foo.barrable in foo
_TFSCg5greenVSC5Color ---> __C.green.getter : __C.Color
_TIF1t1fFT1iSi1sSS_T_A_ ---> t.(f (i : Swift.Int, s : Swift.String) -> ()).(default argument 0)
_TIF1t1fFT1iSi1sSS_T_A0_ ---> t.(f (i : Swift.Int, s : Swift.String) -> ()).(default argument 1)
@@ -141,7 +143,7 @@
_TWa ---> _TWa
_Twal ---> _Twal
_T ---> _T
-_TTo ---> {T} _TTo
+_TTo ---> {T:_T} _TTo
_TC ---> _TC
_TM ---> _TM
_TM ---> _TM
@@ -187,10 +189,10 @@
_TTSgSi__xyz ---> _TTSgSi__xyz
_TTSr5Si___TF4test7genericurFxx ---> generic not re-abstracted specialization <Swift.Int> of test.generic <A> (A) -> A
_TTSrq5Si___TF4test7genericurFxx ---> generic not re-abstracted specialization <preserving fragile attribute, Swift.Int> of test.generic <A> (A) -> A
-_TPA__TTRXFo_oSSoSS_dSb_XFo_iSSiSS_dSb_ ---> {T} partial apply forwarder for reabstraction thunk helper from @callee_owned (@owned Swift.String, @owned Swift.String) -> (@unowned Swift.Bool) to @callee_owned (@in Swift.String, @in Swift.String) -> (@unowned Swift.Bool)
-_TPAo__TTRGrXFo_dGSPx__dGSPx_zoPs5Error__XFo_iGSPx__iGSPx_zoPS___ ---> {T} partial apply ObjC forwarder for reabstraction thunk helper <A> from @callee_owned (@unowned Swift.UnsafePointer<A>) -> (@unowned Swift.UnsafePointer<A>, @error @owned Swift.Error) to @callee_owned (@in Swift.UnsafePointer<A>) -> (@out Swift.UnsafePointer<A>, @error @owned Swift.Error)
-_T0SSSSSbIxxxd_SSSSSbIxiid_TRTA ---> {T} partial apply forwarder for reabstraction thunk helper from @callee_owned (@owned Swift.String, @owned Swift.String) -> (@unowned Swift.Bool) to @callee_owned (@in Swift.String, @in Swift.String) -> (@unowned Swift.Bool)
-_T0SPyxGSPyxGs5Error_pIxydzo_SPyxGSPyxGsAA_pIxirzo_lTRTa ---> {T} partial apply ObjC forwarder for reabstraction thunk helper <A> from @callee_owned (@unowned Swift.UnsafePointer<A>) -> (@unowned Swift.UnsafePointer<A>, @error @owned Swift.Error) to @callee_owned (@in Swift.UnsafePointer<A>) -> (@out Swift.UnsafePointer<A>, @error @owned Swift.Error)
+_TPA__TTRXFo_oSSoSS_dSb_XFo_iSSiSS_dSb_ ---> {T:_TTRXFo_oSSoSS_dSb_XFo_iSSiSS_dSb_} partial apply forwarder for reabstraction thunk helper from @callee_owned (@owned Swift.String, @owned Swift.String) -> (@unowned Swift.Bool) to @callee_owned (@in Swift.String, @in Swift.String) -> (@unowned Swift.Bool)
+_TPAo__TTRGrXFo_dGSPx__dGSPx_zoPs5Error__XFo_iGSPx__iGSPx_zoPS___ ---> {T:_TTRGrXFo_dGSPx__dGSPx_zoPs5Error__XFo_iGSPx__iGSPx_zoPS___} partial apply ObjC forwarder for reabstraction thunk helper <A> from @callee_owned (@unowned Swift.UnsafePointer<A>) -> (@unowned Swift.UnsafePointer<A>, @error @owned Swift.Error) to @callee_owned (@in Swift.UnsafePointer<A>) -> (@out Swift.UnsafePointer<A>, @error @owned Swift.Error)
+_T0SSSSSbIxxxd_SSSSSbIxiid_TRTA ---> {T:_T0SSSSSbIxxxd_SSSSSbIxiid_TR} partial apply forwarder for reabstraction thunk helper from @callee_owned (@owned Swift.String, @owned Swift.String) -> (@unowned Swift.Bool) to @callee_owned (@in Swift.String, @in Swift.String) -> (@unowned Swift.Bool)
+_T0SPyxGSPyxGs5Error_pIxydzo_SPyxGSPyxGsAA_pIxirzo_lTRTa ---> {T:_T0SPyxGSPyxGs5Error_pIxydzo_SPyxGSPyxGsAA_pIxirzo_lTR} partial apply ObjC forwarder for reabstraction thunk helper <A> from @callee_owned (@unowned Swift.UnsafePointer<A>) -> (@unowned Swift.UnsafePointer<A>, @error @owned Swift.Error) to @callee_owned (@in Swift.UnsafePointer<A>) -> (@out Swift.UnsafePointer<A>, @error @owned Swift.Error)
_TiC4Meow5MyCls9subscriptFT1iSi_Sf ---> Meow.MyCls.subscript (i : Swift.Int) -> Swift.Float
_TF8manglingX22egbpdajGbuEbxfgehfvwxnFT_T_ ---> mangling.ليهمابتكلموشعربي؟ () -> ()
_TF8manglingX24ihqwcrbEcvIaIdqgAFGpqjyeFT_T_ ---> mangling.他们为什么不说中文 () -> ()
diff --git a/test/Driver/Dependencies/Inputs/only-skip-once/file1.swift b/test/Driver/Dependencies/Inputs/only-skip-once/file1.swift
new file mode 100644
index 0000000..3ebf6e5
--- /dev/null
+++ b/test/Driver/Dependencies/Inputs/only-skip-once/file1.swift
@@ -0,0 +1,3 @@
+public class Class1 {
+ public var Var1 : Int?
+}
diff --git a/test/Driver/Dependencies/Inputs/only-skip-once/file2.swift b/test/Driver/Dependencies/Inputs/only-skip-once/file2.swift
new file mode 100644
index 0000000..5b579dd
--- /dev/null
+++ b/test/Driver/Dependencies/Inputs/only-skip-once/file2.swift
@@ -0,0 +1,3 @@
+public class Class2 {
+ public var Var2c : Class1?
+}
diff --git a/test/Driver/Dependencies/Inputs/only-skip-once/main.swift b/test/Driver/Dependencies/Inputs/only-skip-once/main.swift
new file mode 100644
index 0000000..214696a
--- /dev/null
+++ b/test/Driver/Dependencies/Inputs/only-skip-once/main.swift
@@ -0,0 +1,2 @@
+var x = Class1()
+var y = Class2()
diff --git a/test/Driver/Dependencies/Inputs/only-skip-once/output-file-map.json b/test/Driver/Dependencies/Inputs/only-skip-once/output-file-map.json
new file mode 100644
index 0000000..32d28d7
--- /dev/null
+++ b/test/Driver/Dependencies/Inputs/only-skip-once/output-file-map.json
@@ -0,0 +1,23 @@
+{
+ "": {
+ "swift-dependencies": "master.swiftdeps"
+ },
+ "main.swift": {
+ "dependencies": "main.d",
+ "object": "main.o",
+ "swiftmodule": "main~partial.swiftmodule",
+ "swift-dependencies": "main.swiftdeps"
+ },
+ "file1.swift": {
+ "dependencies": "file1.d",
+ "object": "file1.o",
+ "swiftmodule": "file1~partial.swiftmodule",
+ "swift-dependencies": "file1.swiftdeps"
+ },
+ "file2.swift": {
+ "dependencies": "file2.d",
+ "object": "file2.o",
+ "swiftmodule": "file2~partial.swiftmodule",
+ "swift-dependencies": "file2.swiftdeps"
+ }
+}
diff --git a/test/Driver/Dependencies/driver-show-incremental-arguments.swift b/test/Driver/Dependencies/driver-show-incremental-arguments.swift
index 19fdb7a..3a4c37f 100644
--- a/test/Driver/Dependencies/driver-show-incremental-arguments.swift
+++ b/test/Driver/Dependencies/driver-show-incremental-arguments.swift
@@ -14,9 +14,9 @@
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-INCREMENTAL %s
// CHECK-INCREMENTAL-NOT: Incremental compilation has been disabled
-// CHECK-INCREMENTAL: Queuing main.swift (initial)
+// CHECK-INCREMENTAL: Queuing (initial): {compile: main.o <= main.swift}
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -g -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-ARGS-MISMATCH %s
// CHECK-ARGS-MISMATCH: Incremental compilation has been disabled{{.*}}different arguments
-// CHECK-ARGS-MISMATCH-NOT: Queuing main.swift (initial)
+// CHECK-ARGS-MISMATCH-NOT: Queuing (initial): {compile: main.o <= main.swift}
diff --git a/test/Driver/Dependencies/driver-show-incremental-conflicting-arguments.swift b/test/Driver/Dependencies/driver-show-incremental-conflicting-arguments.swift
index 8d54095..e9b2e93 100644
--- a/test/Driver/Dependencies/driver-show-incremental-conflicting-arguments.swift
+++ b/test/Driver/Dependencies/driver-show-incremental-conflicting-arguments.swift
@@ -14,18 +14,18 @@
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-INCREMENTAL %s
// CHECK-INCREMENTAL-NOT: Incremental compilation has been disabled
-// CHECK-INCREMENTAL: Queuing main.swift (initial)
+// CHECK-INCREMENTAL: Queuing (initial): {compile: main.o <= main.swift}
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -whole-module-optimization -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-WMO %s
// CHECK-WMO: Incremental compilation has been disabled{{.*}}whole module optimization
-// CHECK-WMO-NOT: Queuing main.swift (initial)
+// CHECK-WMO-NOT: Queuing (initial): {compile: main.o <= main.swift}
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -embed-bitcode -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-BITCODE %s
// CHECK-BITCODE: Incremental compilation has been disabled{{.*}}LLVM IR bitcode
-// CHECK-BITCODE-NOT: Queuing main.swift (initial)
+// CHECK-BITCODE-NOT: Queuing (initial): {compile: main.o <= main.swift}
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -whole-module-optimization -embed-bitcode -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-WMO-AND-BITCODE %s
// CHECK-WMO-AND-BITCODE: Incremental compilation has been disabled{{.*}}whole module optimization
// CHECK-WMO-AND-BITCODE-NOT: Incremental compilation has been disabled
-// CHECK-WMO-AND-BITCODE-NOT: Queuing main.swift (initial)
+// CHECK-WMO-AND-BITCODE-NOT: Queuing (initial): {compile: main.o <= main.swift}
diff --git a/test/Driver/Dependencies/driver-show-incremental-inputs.swift b/test/Driver/Dependencies/driver-show-incremental-inputs.swift
index 27d3e1b..931eff9 100644
--- a/test/Driver/Dependencies/driver-show-incremental-inputs.swift
+++ b/test/Driver/Dependencies/driver-show-incremental-inputs.swift
@@ -14,10 +14,10 @@
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-INCREMENTAL %s
// CHECK-INCREMENTAL-NOT: Incremental compilation has been disabled
-// CHECK-INCREMENTAL: Queuing main.swift (initial)
+// CHECK-INCREMENTAL: Queuing (initial): {compile: main.o <= main.swift}
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-INPUTS-MISMATCH %s
// CHECK-INPUTS-MISMATCH: Incremental compilation has been disabled{{.*}}inputs
// CHECK-INPUTS-MISMATCH: ./other.swift
-// CHECK-INPUTS-MISMATCH-NOT: Queuing main.swift (initial)
+// CHECK-INPUTS-MISMATCH-NOT: Queuing (initial): {compile: main.o <= main.swift}
diff --git a/test/Driver/Dependencies/driver-show-incremental-malformed.swift b/test/Driver/Dependencies/driver-show-incremental-malformed.swift
index 7885c1b..b3911ae 100644
--- a/test/Driver/Dependencies/driver-show-incremental-malformed.swift
+++ b/test/Driver/Dependencies/driver-show-incremental-malformed.swift
@@ -13,7 +13,7 @@
// RUN: echo '{version: "'$(%swiftc_driver_plain -version | head -n1)'", inputs: {"./main.swift": [443865900, 0], "./other.swift": [443865900, 0]}}' > %t/main~buildrecord.swiftdeps
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-INCREMENTAL %s
// CHECK-INCREMENTAL-NOT: Incremental compilation has been disabled
-// CHECK-INCREMENTAL: Queuing main.swift (initial)
+// CHECK-INCREMENTAL: Queuing (initial): {compile: main.o <= main.swift}
// RUN: rm %t/main~buildrecord.swiftdeps && touch %t/main~buildrecord.swiftdeps
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -g -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-MALFORMED %s
@@ -22,7 +22,7 @@
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -g -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-MALFORMED %s
// CHECK-MALFORMED: Incremental compilation has been disabled{{.*}}malformed build record file
-// CHECK-MALFORMED-NOT: Queuing main.swift (initial)
+// CHECK-MALFORMED-NOT: Queuing (initial): {compile: main.o <= main.swift}
// RUN: echo '{version, inputs: {"./main.swift": [443865900, 0], "./other.swift": [443865900, 0]}}' > %t/main~buildrecord.swiftdeps
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -g -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-MISSING-KEY %s
@@ -31,5 +31,5 @@
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -g -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-MISSING-KEY %s
// CHECK-MISSING-KEY: Incremental compilation has been disabled{{.*}}malformed build record file{{.*}}Malformed value for key
-// CHECK-MISSING-KEY-NOT: Queuing main.swift (initial)
+// CHECK-MISSING-KEY-NOT: Queuing (initial): {compile: main.o <= main.swift}
diff --git a/test/Driver/Dependencies/driver-show-incremental-mutual.swift b/test/Driver/Dependencies/driver-show-incremental-mutual.swift
index b9f1765..2b8fd3b 100644
--- a/test/Driver/Dependencies/driver-show-incremental-mutual.swift
+++ b/test/Driver/Dependencies/driver-show-incremental-mutual.swift
@@ -4,14 +4,14 @@
// RUN: touch -t 201401240005 %t/*
// RUN: cd %t && %swiftc_driver -c -driver-use-frontend-path %S/Inputs/update-dependencies.py -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -module-name main -j1 -v -driver-show-incremental 2>&1 | %FileCheck -check-prefix=CHECK-FIRST %s
-// CHECK-FIRST: Queuing main.swift (initial)
+// CHECK-FIRST: Queuing (initial): {compile: main.o <= main.swift}
// RUN: cd %t && %swiftc_driver -c -driver-use-frontend-path %S/Inputs/update-dependencies.py -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -module-name main -j1 -v -driver-show-incremental 2>&1 | %FileCheck -check-prefix=CHECK-SECOND %s
// CHECK-SECOND-NOT: Queuing
// RUN: touch -t 201401240006 %t/other.swift
// RUN: cd %t && %swiftc_driver -c -driver-use-frontend-path %S/Inputs/update-dependencies.py -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -module-name main -j1 -v -driver-show-incremental 2>&1 | %FileCheck -check-prefix=CHECK-THIRD %s
-// CHECK-THIRD: Queuing other.swift (initial)
-// CHECK-THIRD: Queuing main.swift because of the initial set:
+// CHECK-THIRD: Queuing (initial): {compile: other.o <= other.swift}
+// CHECK-THIRD: Queuing because of the initial set: {compile: main.o <= main.swift}
// CHECK-THIRD-NEXT: other.swift provides top-level name 'a'
diff --git a/test/Driver/Dependencies/driver-show-incremental-swift-version.swift b/test/Driver/Dependencies/driver-show-incremental-swift-version.swift
index 46c401e..79d2d37 100644
--- a/test/Driver/Dependencies/driver-show-incremental-swift-version.swift
+++ b/test/Driver/Dependencies/driver-show-incremental-swift-version.swift
@@ -14,12 +14,12 @@
// RUN: echo '{version: "'$(%swiftc_driver_plain -version | head -n1)'", inputs: {"./main.swift": [443865900, 0], "./other.swift": [443865900, 0]}}' > %t/main~buildrecord.swiftdeps
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-INCREMENTAL %s
// CHECK-INCREMENTAL-NOT: Incremental compilation has been disabled
-// CHECK-INCREMENTAL: Queuing main.swift (initial)
+// CHECK-INCREMENTAL: Queuing (initial): {compile: main.o <= main.swift}
// RUN: echo '{version: "bogus", inputs: {"./main.swift": [443865900, 0], "./other.swift": [443865900, 0]}}' > %t/main~buildrecord.swiftdeps
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path %S/Inputs/update-dependencies.py -c ./main.swift ./other.swift -module-name main -incremental -v -driver-show-incremental -output-file-map %t/output.json | %FileCheck --check-prefix CHECK-VERSION-MISMATCH %s
// CHECK-VERSION-MISMATCH: Incremental compilation has been disabled{{.*}}compiler version mismatch
// CHECK-VERSION-MISMATCH: Compiling with:
// CHECK-VERSION-MISMATCH: Previously compiled with: bogus
-// CHECK-VERSION-MISMATCH-NOT: Queuing main.swift (initial)
+// CHECK-VERSION-MISMATCH-NOT: Queuing (initial): {compile: main.o <= main.swift}
diff --git a/test/Driver/Dependencies/only-skip-once.swift b/test/Driver/Dependencies/only-skip-once.swift
new file mode 100644
index 0000000..391e24b
--- /dev/null
+++ b/test/Driver/Dependencies/only-skip-once.swift
@@ -0,0 +1,21 @@
+// XFAIL: linux
+// RUN: rm -rf %t && cp -r %S/Inputs/only-skip-once/ %t
+// RUN: touch -t 201401240005 %t/*
+
+// RUN: cd %t && %swiftc_driver -driver-show-job-lifecycle -output-file-map %t/output-file-map.json -incremental main.swift file1.swift file2.swift -j1 2>&1 | %FileCheck -check-prefix=CHECK-INITIAL %s
+
+// CHECK-INITIAL-NOT: warning
+// CHECK-INITIAL: Job finished: {compile: main.o <= main.swift}
+// CHECK-INITIAL: Job finished: {compile: file1.o <= file1.swift}
+// CHECK-INITIAL: Job finished: {compile: file2.o <= file2.swift}
+// CHECK-INITIAL: Job finished: {link: main <= main.o file1.o file2.o}
+
+// RUN: touch -t 201401240006 %t/file2.swift
+// RUN: cd %t && %swiftc_driver -driver-show-job-lifecycle -output-file-map %t/output-file-map.json -incremental main.swift file1.swift file2.swift -j1 2>&1 | %FileCheck -check-prefix=CHECK-REBUILD %s
+
+// We should skip the main and file1 rebuilds here, but we should only note skipping them _once_
+// CHECK-REBUILD: Job finished: {compile: file2.o <= file2.swift}
+// CHECK-REBUILD: Job skipped: {compile: main.o <= main.swift}
+// CHECK-REBUILD: Job skipped: {compile: file1.o <= file1.swift}
+// CHECK-REBUILD: Job finished: {link: main <= main.o file1.o file2.o}
+// CHECK-REBUILD-NOT: Job skipped:
diff --git a/test/Driver/driver-time-compilation.swift b/test/Driver/driver-time-compilation.swift
index 198ff9b..78a7555 100644
--- a/test/Driver/driver-time-compilation.swift
+++ b/test/Driver/driver-time-compilation.swift
@@ -5,6 +5,6 @@
// CHECK: Total Execution Time: {{[0-9]+}}.{{[0-9]+}} seconds ({{[0-9]+}}.{{[0-9]+}} wall clock)
// CHECK: ---Wall Time---
// CHECK: --- Name ---
-// CHECK: compile {{.*}}driver-time-compilation.swift
-// CHECK-MULTIPLE: compile {{.*}}empty.swift
+// CHECK: {compile: {{.*}}driver-time-compilation.swift}
+// CHECK-MULTIPLE: {compile: {{.*}}empty.swift}
// CHECK: {{[0-9]+}}.{{[0-9]+}} (100.0%) Total
diff --git a/test/Driver/swift-version-default.swift b/test/Driver/swift-version-default.swift
index 6a9ec1f..029496a 100644
--- a/test/Driver/swift-version-default.swift
+++ b/test/Driver/swift-version-default.swift
@@ -11,8 +11,26 @@
jkl
#endif
+#if swift(>=3.1)
+asdf // expected-error {{use of unresolved identifier}}
+#else
+jkl
+#endif
+
#if swift(>=4)
aoeu
#else
htn // expected-error {{use of unresolved identifier}}
#endif
+
+#if swift(>=4.1)
+aoeu
+#else
+htn // expected-error {{use of unresolved identifier}}
+#endif
+
+#if swift(>=5)
+aoeu
+#else
+htn // expected-error {{use of unresolved identifier}}
+#endif
diff --git a/test/Driver/swift-version.swift b/test/Driver/swift-version.swift
index 06817a0..129a2be 100644
--- a/test/Driver/swift-version.swift
+++ b/test/Driver/swift-version.swift
@@ -1,4 +1,3 @@
-// RUN: %target-swiftc_driver -swift-version 3 %s
// RUN: not %target-swiftc_driver -swift-version foo %s 2>&1 | %FileCheck --check-prefix BAD %s
// RUN: not %target-swiftc_driver -swift-version 1 %s 2>&1 | %FileCheck --check-prefix BAD %s
// RUN: not %target-swiftc_driver -swift-version 2 %s 2>&1 | %FileCheck --check-prefix BAD %s
@@ -9,10 +8,50 @@
// RUN: not %target-swiftc_driver -swift-version 3.3 %s 2>&1 | %FileCheck --check-prefix FIXIT_3 %s
// RUN: not %target-swiftc_driver -swift-version 4.3 %s 2>&1 | %FileCheck --check-prefix FIXIT_4 %s
+// RUN: not %target-swiftc_driver -swift-version 3 -typecheck %s 2>&1 | %FileCheck --check-prefix ERROR_3 %s
+// RUN: not %target-swiftc_driver -swift-version 4 -typecheck %s 2>&1 | %FileCheck --check-prefix ERROR_4 %s
+
// BAD: invalid value
// BAD: note: valid arguments to '-swift-version' are '3', '4'
// FIXIT_3: use major version, as in '-swift-version 3'
// FIXIT_4: use major version, as in '-swift-version 4'
-let x = 1
+
+#if swift(>=3)
+asdf
+// ERROR_3: [[@LINE-1]]:1: error: {{use of unresolved identifier}}
+// ERROR_4: [[@LINE-2]]:1: error: {{use of unresolved identifier}}
+#else
+jkl
+#endif
+
+#if swift(>=3.1)
+asdf
+// ERROR_3: [[@LINE-1]]:1: error: {{use of unresolved identifier}}
+// ERROR_4: [[@LINE-2]]:1: error: {{use of unresolved identifier}}
+#else
+jkl
+#endif
+
+#if swift(>=4)
+asdf // ERROR_4: [[@LINE]]:1: error: {{use of unresolved identifier}}
+#else
+jkl // ERROR_3: [[@LINE]]:1: error: {{use of unresolved identifier}}
+#endif
+
+#if swift(>=4.1)
+asdf
+#else
+jkl
+// ERROR_3: [[@LINE-1]]:1: error: {{use of unresolved identifier}}
+// ERROR_4: [[@LINE-2]]:1: error: {{use of unresolved identifier}}
+#endif
+
+#if swift(>=5)
+asdf
+#else
+jkl
+// ERROR_3: [[@LINE-1]]:1: error: {{use of unresolved identifier}}
+// ERROR_4: [[@LINE-2]]:1: error: {{use of unresolved identifier}}
+#endif
diff --git a/test/FixCode/fixits-switch.swift b/test/FixCode/fixits-switch.swift
index 591d5a5..7309a6a 100644
--- a/test/FixCode/fixits-switch.swift
+++ b/test/FixCode/fixits-switch.swift
@@ -33,6 +33,12 @@
case e1(a: Int, s: Int)
case e2(a: Int)
case e3(a: Int)
+ case e4(_: Int)
+ case e5(_: Int, _: Int)
+ case e6(a : Int, _: Int)
+ case e7
+ case e8(a : Int, Int, Int)
+ case e9(Int, Int, Int)
}
func foo4(_ e : E2) -> Int {
diff --git a/test/FixCode/fixits-switch.swift.result b/test/FixCode/fixits-switch.swift.result
index 0b0cfcd..0e6a53e 100644
--- a/test/FixCode/fixits-switch.swift.result
+++ b/test/FixCode/fixits-switch.swift.result
@@ -38,14 +38,26 @@
case e1(a: Int, s: Int)
case e2(a: Int)
case e3(a: Int)
+ case e4(_: Int)
+ case e5(_: Int, _: Int)
+ case e6(a : Int, _: Int)
+ case e7
+ case e8(a : Int, Int, Int)
+ case e9(Int, Int, Int)
}
func foo4(_ e : E2) -> Int {
switch e {
case .e2:
return 1
- case .e1: <#Code#>
-case .e3: <#Code#>
+ case .e1(let a, let s): <#Code#>
+case .e3(let a): <#Code#>
+case .e4(_): <#Code#>
+case .e5(_, _): <#Code#>
+case .e6(let a, _): <#Code#>
+case .e7: <#Code#>
+case .e8(let a, _, _): <#Code#>
+case .e9(_, _, _): <#Code#>
}
}
@@ -61,8 +73,14 @@
switch e {
case let .e1(x, y):
return x + y
- case .e2: <#Code#>
-case .e3: <#Code#>
+ case .e2(let a): <#Code#>
+case .e3(let a): <#Code#>
+case .e4(_): <#Code#>
+case .e5(_, _): <#Code#>
+case .e6(let a, _): <#Code#>
+case .e7: <#Code#>
+case .e8(let a, _, _): <#Code#>
+case .e9(_, _, _): <#Code#>
}
}
@@ -71,6 +89,11 @@
case .e2(1): return 0
case .e1: return 0
case .e3: return 0
- default: <#Code#>
+ case .e4(_): <#Code#>
+case .e5(_, _): <#Code#>
+case .e6(let a, _): <#Code#>
+case .e7: <#Code#>
+case .e8(let a, _, _): <#Code#>
+case .e9(_, _, _): <#Code#>
}
}
\ No newline at end of file
diff --git a/test/IRGen/Inputs/witness_table_multifile_2.swift b/test/IRGen/Inputs/witness_table_multifile_2.swift
index feaf71f..7730f0b 100644
--- a/test/IRGen/Inputs/witness_table_multifile_2.swift
+++ b/test/IRGen/Inputs/witness_table_multifile_2.swift
@@ -9,3 +9,6 @@
}
func go() -> P { return X("hello") }
+
+protocol ProtocolOnlyUsedAsAType {
+}
diff --git a/test/IRGen/witness_table_multifile.swift b/test/IRGen/witness_table_multifile.swift
index 95d727e..f5a9b4b 100644
--- a/test/IRGen/witness_table_multifile.swift
+++ b/test/IRGen/witness_table_multifile.swift
@@ -11,3 +11,9 @@
// CHECK-NEXT: getelementptr inbounds i8*, i8** [[WITNESS_TABLE]], i32 3
go().foo()
}
+
+// Ensure that protocols from other files get fully validated even
+// when they're only used as types.
+func useAProtocol() -> ProtocolOnlyUsedAsAType? {
+ return nil
+}
\ No newline at end of file
diff --git a/test/Index/expressions.swift b/test/Index/expressions.swift
new file mode 100644
index 0000000..bf2c1b1
--- /dev/null
+++ b/test/Index/expressions.swift
@@ -0,0 +1,15 @@
+// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s
+
+protocol P1 {}
+
+// CHECK: [[@LINE+1]]:8 | struct/Swift | S1 | [[S1_USR:.*]] | Def
+struct S1 : P1 {}
+
+func test(_ o: P1?) {
+ switch o {
+ // CHECK-NOT: [[@LINE+2]]:17 | enumerator/Swift | some |
+ // CHECK: [[@LINE+1]]:17 | struct/Swift | S1 | [[S1_USR]] | Ref
+ case let s as S1:
+ test(s)
+ }
+}
diff --git a/test/Index/kinds.swift b/test/Index/kinds.swift
index 1ddd0bf..55d8d43 100644
--- a/test/Index/kinds.swift
+++ b/test/Index/kinds.swift
@@ -214,3 +214,13 @@
@GKInspectable var gkString = "gk"
// CHECK: [[@LINE-1]]:22 | instance-property(GKI)/Swift | gkString |
}
+
+// CHECK: [[@LINE+1]]:7 | class/Swift | C1 | [[C1_USR:.*]] | Def | rel: 0
+class C1 {}
+// CHECK: [[@LINE+1]]:11 | type-alias/Swift | C1Alias | [[C1Alias_USR:.*]] | Def | rel: 0
+typealias C1Alias = C1
+// CHECK: [[@LINE+4]]:7 | class/Swift | SubC1 | [[SubC1_USR:.*]] | Def | rel: 0
+// CHECK: [[@LINE+3]]:15 | type-alias/Swift | C1Alias | [[C1Alias_USR]] | Ref | rel: 0
+// CHECK: [[@LINE+2]]:15 | class/Swift | C1 | [[C1_USR]] | Ref,Impl,RelBase | rel: 1
+// CHECK-NEXT: RelBase | SubC1 | [[SubC1_USR]]
+class SubC1 : C1Alias {}
diff --git a/test/Index/roles.swift b/test/Index/roles.swift
index 757a19a..be4a21b 100644
--- a/test/Index/roles.swift
+++ b/test/Index/roles.swift
@@ -134,27 +134,18 @@
}
}
-class AClass {
+class AClass { // used for references only
var y: AStruct;
var z: [Int]
-
init(x: Int) {
y = AStruct(x: x)
self.z = [1, 2, 3]
}
-
subscript(index: Int) -> Int {
- get {
- return z[0]
- }
- set {
- z[0] = newValue
- }
+ get { return z[0] }
+ set { z[0] = newValue }
}
-
- func foo() -> Int {
- return z[0]
- }
+ func foo() -> Int { return z[0] }
}
let _ = AClass.foo
@@ -168,14 +159,29 @@
// CHECK: [[@LINE-1]]:21 | instance-property/subscript/Swift | subscript(_:) | s:14swift_ide_test6AClassC9subscriptSiSici | Ref,Writ | rel: 0
// CHECK: [[@LINE-2]]:21 | function/acc-set/Swift | setter:subscript(_:) | s:14swift_ide_test6AClassC9subscriptSiSicfs | Ref,Call,Dyn,Impl,RelRec | rel: 1
+// RelationBaseOf, RelationOverrideOf
+
+protocol X {}
+// CHECK: [[@LINE-1]]:10 | protocol/Swift | X | [[X_USR:.*]] | Def | rel: 0
+
+class ImplementsX : X {}
+// CHECK: [[@LINE-1]]:7 | class/Swift | ImplementsX | [[ImplementsX_USR:.*]] | Def | rel: 0
+// CHECK: [[@LINE-2]]:21 | protocol/Swift | X | [[X_USR]] | Ref,RelBase | rel: 1
+// CHECK-NEXT: RelBase | ImplementsX | [[ImplementsX_USR]]
+
protocol AProtocol {
// CHECK: [[@LINE-1]]:10 | protocol/Swift | AProtocol | [[AProtocol_USR:.*]] | Def | rel: 0
+
+ associatedtype T : X
+ // CHECK: [[@LINE-1]]:18 | type-alias/associated-type/Swift | T | s:14swift_ide_test9AProtocolP1T | Def,RelChild | rel: 1
+ // CHECK-NEXT: RelChild | AProtocol | [[AProtocol_USR]]
+ // CHECK: [[@LINE-3]]:22 | protocol/Swift | X | [[X_USR]] | Ref | rel: 0
+
func foo() -> Int
// CHECK: [[@LINE-1]]:8 | instance-method/Swift | foo() | s:14swift_ide_test9AProtocolP3fooSiyF | Def,RelChild | rel: 1
// CHECK-NEXT: RelChild | AProtocol | s:14swift_ide_test9AProtocolP
}
-// RelationBaseOf, RelationOverrideOf
class ASubClass : AClass, AProtocol {
// CHECK: [[@LINE-1]]:7 | class/Swift | ASubClass | s:14swift_ide_test9ASubClassC | Def | rel: 0
// CHECK: [[@LINE-2]]:19 | class/Swift | AClass | s:14swift_ide_test6AClassC | Ref,RelBase | rel: 1
@@ -183,6 +189,8 @@
// CHECK: [[@LINE-4]]:27 | protocol/Swift | AProtocol | s:14swift_ide_test9AProtocolP | Ref,RelBase | rel: 1
// CHECK-NEXT: RelBase | ASubClass | s:14swift_ide_test9ASubClassC
+ typealias T = ImplementsX
+
override func foo() -> Int {
// CHECK: [[@LINE-1]]:17 | instance-method/Swift | foo() | s:14swift_ide_test9ASubClassC3fooSiyF | Def,RelChild,RelOver | rel: 3
// CHECK-NEXT: RelOver | foo() | s:14swift_ide_test6AClassC3fooSiyF
@@ -216,7 +224,9 @@
// CHECK: [[@LINE-4]]:27 | protocol/Swift | AProtocol | [[AProtocol_USR]] | Ref,RelBase | rel: 1
// CHECK-NEXT: RelBase | InnerS | [[EXT_INNERS_USR]]
// CHECK: [[@LINE-6]]:11 | struct/Swift | OuterS | [[OUTERS_USR]] | Ref | rel: 0
- func foo() {}
+
+ typealias T = ImplementsX
+ func foo() -> Int { return 1 }
}
var anInstance = AClass(x: 1)
diff --git a/test/Inputs/clang-importer-sdk/usr/include/dispatch.h b/test/Inputs/clang-importer-sdk/usr/include/dispatch.h
index 63ceaf9..9c0aa3c 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/dispatch.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/dispatch.h
@@ -2,15 +2,21 @@
@protocol OS_dispatch_object <NSObject>
@end
-typedef NSObject <OS_dispatch_object> *dispatch_object_t;
+@interface OS_dispatch_object: NSObject <OS_dispatch_object>
+@end
+typedef OS_dispatch_object *dispatch_object_t;
@protocol OS_dispatch_queue <OS_dispatch_object>
@end
-typedef NSObject <OS_dispatch_queue> *dispatch_queue_t;
+@interface OS_dispatch_queue: OS_dispatch_object <OS_dispatch_object>
+@end
+typedef OS_dispatch_queue *dispatch_queue_t;
@protocol OS_dispatch_source <OS_dispatch_object>
@end
-typedef NSObject <OS_dispatch_source> *dispatch_source_t;
+@interface OS_dispatch_source: OS_dispatch_object <OS_dispatch_object>
+@end
+typedef OS_dispatch_source *dispatch_source_t;
typedef void (^dispatch_block_t)(void);
diff --git a/test/SIL/Parser/basic.sil b/test/SIL/Parser/basic.sil
index ad8b308..4d141b8 100644
--- a/test/SIL/Parser/basic.sil
+++ b/test/SIL/Parser/basic.sil
@@ -1574,6 +1574,22 @@
return %28 : $()
}
+// CHECK-LABEL: sil @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK: end_lifetime {{%.*}} : $Builtin.NativeObject
+sil @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ end_lifetime %0 : $Builtin.NativeObject
+ return undef : $()
+}
+
+// CHECK-LABEL: sil @test_unchecked_ownership_conversion : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
+// CHECK: unchecked_ownership_conversion {{%.*}} : $Builtin.NativeObject, @guaranteed to @owned
+sil @test_unchecked_ownership_conversion : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ %1 = unchecked_ownership_conversion %0 : $Builtin.NativeObject, @guaranteed to @owned
+ return undef : $()
+}
+
// CHECK-LABEL: sil_vtable Foo {
// CHECK: #Foo.subscript!getter.1: {{.*}} : hidden _TFC3tmp3Foog9subscriptFTVs5Int32S1__S1_
// CHECK: #Foo.subscript!setter.1: {{.*}} : _TFC3tmp3Foos9subscriptFTVs5Int32S1__S1_
diff --git a/test/SIL/Serialization/basic.sil b/test/SIL/Serialization/basic.sil
new file mode 100644
index 0000000..9ac3d90
--- /dev/null
+++ b/test/SIL/Serialization/basic.sil
@@ -0,0 +1,24 @@
+// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
+// RUN: rm -rfv %t
+// RUN: mkdir %t
+// RUN: %target-sil-opt %s -emit-sib -o %t/tmp.sib -module-name borrow
+// RUN: %target-sil-opt %t/tmp.sib -o %t/tmp.2.sib -module-name borrow
+// RUN: %target-sil-opt %t/tmp.2.sib -module-name borrow | %FileCheck %s
+
+import Builtin
+
+// CHECK-LABEL: sil @test_unchecked_ownership_conversion : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
+// CHECK: unchecked_ownership_conversion {{%.*}} : $Builtin.NativeObject, @guaranteed to @owned
+sil @test_unchecked_ownership_conversion : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ unchecked_ownership_conversion %0 : $Builtin.NativeObject, @guaranteed to @owned
+ return undef : $()
+}
+
+// CHECK-LABEL: sil @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK: end_lifetime {{%.*}} : $Builtin.NativeObject
+sil @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ end_lifetime %0 : $Builtin.NativeObject
+ return undef : $()
+}
diff --git a/test/SILGen/dynamic_self.swift b/test/SILGen/dynamic_self.swift
index 85097a1..516d34e 100644
--- a/test/SILGen/dynamic_self.swift
+++ b/test/SILGen/dynamic_self.swift
@@ -249,6 +249,75 @@
_ = Factory.staticNewInstance
}
+class FactoryFactory {
+
+ // CHECK-LABEL: sil hidden @_T012dynamic_self07FactoryC0C11newInstanceACXDyFZ : $@convention(method) (@thick FactoryFactory.Type) -> @owned FactoryFactory
+ static func newInstance() -> Self {
+ // CHECK: bb0(%0 : $@thick FactoryFactory.Type):
+
+ // CHECK: [[METATYPE:%.*]] = value_metatype $@thick @dynamic_self FactoryFactory.Type.Type, %0 : $@thick FactoryFactory.Type
+ // CHECK: [[ANY:%.*]] = init_existential_metatype [[METATYPE]] : $@thick @dynamic_self FactoryFactory.Type.Type, $@thick Any.Type
+ let _: Any.Type = type(of: self)
+
+ // CHECK: unreachable
+ }
+}
+
+// Super call to a method returning Self
+class Base {
+ required init() {}
+
+ func returnsSelf() -> Self {
+ return self
+ }
+
+ static func returnsSelfStatic() -> Self {
+ return self.init()
+ }
+}
+
+class Derived : Base {
+ // CHECK-LABEL: sil hidden @_T012dynamic_self7DerivedC9superCallyyF : $@convention(method) (@guaranteed Derived) -> ()
+ // CHECK: [[SELF:%.*]] = copy_value %0
+ // CHECK: [[SUPER:%.*]] = upcast [[SELF]] : $Derived to $Base
+ // CHECK: [[METHOD:%.*]] = function_ref @_T012dynamic_self4BaseC11returnsSelfACXDyF
+ // CHECK: apply [[METHOD]]([[SUPER]])
+ // CHECK: return
+ func superCall() {
+ super.returnsSelf()
+ }
+
+ // CHECK-LABEL: sil hidden @_T012dynamic_self7DerivedC15superCallStaticyyFZ : $@convention(method) (@thick Derived.Type) -> ()
+ // CHECK: [[SUPER:%.*]] = upcast %0 : $@thick Derived.Type to $@thick Base.Type
+ // CHECK: [[METHOD:%.*]] = function_ref @_T012dynamic_self4BaseC17returnsSelfStaticACXDyFZ
+ // CHECK: apply [[METHOD]]([[SUPER]])
+ // CHECK: return
+ static func superCallStatic() {
+ super.returnsSelfStatic()
+ }
+
+ // CHECK-LABEL: sil hidden @_T012dynamic_self7DerivedC32superCallFromMethodReturningSelfACXDyF : $@convention(method) (@guaranteed Derived) -> @owned Derived
+ // CHECK: [[SELF:%.*]] = copy_value %0
+ // CHECK: [[SUPER:%.*]] = upcast [[SELF]] : $Derived to $Base
+ // CHECK: [[METHOD:%.*]] = function_ref @_T012dynamic_self4BaseC11returnsSelfACXDyF
+ // CHECK: apply [[METHOD]]([[SUPER]])
+ // CHECK: return
+ func superCallFromMethodReturningSelf() -> Self {
+ super.returnsSelf()
+ return self
+ }
+
+ // CHECK-LABEL: sil hidden @_T012dynamic_self7DerivedC38superCallFromMethodReturningSelfStaticACXDyFZ : $@convention(method) (@thick Derived.Type) -> @owned Derived
+ // CHECK: [[SUPER:%.*]] = upcast %0 : $@thick Derived.Type to $@thick Base.Type
+ // CHECK: [[METHOD:%.*]] = function_ref @_T012dynamic_self4BaseC17returnsSelfStaticACXDyFZ
+ // CHECK: apply [[METHOD]]([[SUPER]])
+ // CHECK: return
+ static func superCallFromMethodReturningSelfStatic() -> Self {
+ super.returnsSelfStatic()
+ return self.init()
+ }
+}
+
// CHECK-LABEL: sil_witness_table hidden X: P module dynamic_self {
// CHECK: method #P.f!1: {{.*}} : @_T012dynamic_self1XCAA1PAaaDP1f{{[_0-9a-zA-Z]*}}FTW
diff --git a/test/SILGen/lifetime.swift b/test/SILGen/lifetime.swift
index 47cad67..6eff46f 100644
--- a/test/SILGen/lifetime.swift
+++ b/test/SILGen/lifetime.swift
@@ -527,11 +527,17 @@
// CHECK-LABEL: sil hidden @_T08lifetime3FooCfD : $@convention(method) <T> (@owned Foo<T>) -> ()
// CHECK: bb0([[SELF:%[0-9]+]] : $Foo<T>):
// CHECK: [[DESTROYING_REF:%[0-9]+]] = function_ref @_T08lifetime3FooCfd : $@convention(method) <τ_0_0> (@guaranteed Foo<τ_0_0>) -> @owned Builtin.NativeObject
- // CHECK-NEXT: [[RESULT_SELF:%[0-9]+]] = apply [[DESTROYING_REF]]<T>([[SELF]]) : $@convention(method) <τ_0_0> (@guaranteed Foo<τ_0_0>) -> @owned Builtin.NativeObject
+ // CHECK-NEXT: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
+ // CHECK-NEXT: [[RESULT_SELF:%[0-9]+]] = apply [[DESTROYING_REF]]<T>([[BORROWED_SELF]]) : $@convention(method) <τ_0_0> (@guaranteed Foo<τ_0_0>) -> @owned Builtin.NativeObject
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
+ // CHECK-NEXT: end_lifetime [[SELF]]
// CHECK-NEXT: [[SELF:%[0-9]+]] = unchecked_ref_cast [[RESULT_SELF]] : $Builtin.NativeObject to $Foo<T>
// CHECK-NEXT: dealloc_ref [[SELF]] : $Foo<T>
// CHECK-NEXT: [[RESULT:%[0-9]+]] = tuple ()
// CHECK-NEXT: return [[RESULT]] : $()
+ // CHECK-NEXT: } // end sil function '_T08lifetime3FooCfD'
+
+
// CHECK-LABEL: sil hidden @_T08lifetime3FooCfd : $@convention(method) <T> (@guaranteed Foo<T>) -> @owned Builtin.NativeObject
deinit {
@@ -540,8 +546,6 @@
// CHECK: function_ref @_T08lifetime3barSiyF
// CHECK: apply
- // CHECK: [[PTR:%.*]] = unchecked_ref_cast [[THIS]] : ${{.*}} to $Builtin.NativeObject
-
// -- don't need to destroy_value x because it's trivial
// CHECK-NOT: ref_element_addr [[THIS]] : {{.*}}, #Foo.x
// -- destroy_value y
@@ -554,11 +558,32 @@
// CHECK: [[WADDR:%[0-9]+]] = ref_element_addr [[THIS]] : {{.*}}, #Foo.w
// CHECK: destroy_addr [[WADDR]]
// -- return back this
- // CHECK: return [[PTR]]
+ // CHECK: [[PTR:%.*]] = unchecked_ref_cast [[THIS]] : $Foo<T> to $Builtin.NativeObject
+ // CHECK: [[PTR_OWNED:%.*]] = unchecked_ownership_conversion [[PTR]] : $Builtin.NativeObject, @guaranteed to @owned
+ // CHECK: return [[PTR_OWNED]]
+ // CHECK: } // end sil function '_T08lifetime3FooCfd'
}
}
+class FooSubclass<T> : Foo<T> {
+
+ // CHECK-LABEL: sil hidden @_T08lifetime11FooSubclassCfd : $@convention(method) <T> (@guaranteed FooSubclass<T>) -> @owned Builtin.NativeObject
+ // CHECK: bb0([[THIS:%[0-9]+]] : $FooSubclass<T>):
+ // -- base dtor
+ // CHECK: [[BASE:%[0-9]+]] = upcast [[THIS]] : ${{.*}} to $Foo<T>
+ // CHECK: [[BASE_DTOR:%[0-9]+]] = function_ref @_T08lifetime3FooCfd : $@convention(method) <τ_0_0> (@guaranteed Foo<τ_0_0>) -> @owned Builtin.NativeObject
+ // CHECK: [[PTR:%.*]] = apply [[BASE_DTOR]]<T>([[BASE]])
+ // CHECK: [[BORROWED_PTR:%.*]] = begin_borrow [[PTR]]
+ // CHECK: end_borrow [[BORROWED_PTR]] from [[PTR]]
+ // CHECK: return [[PTR]]
+
+
+ deinit {
+ bar()
+ }
+}
+
class ImplicitDtor {
var x:Int
var y:(Int, Ref)
@@ -586,14 +611,22 @@
self.z = z
}
+ // CHECK: sil hidden @_T08lifetime19ImplicitDtorDerivedCfd : $@convention(method) <T> (@guaranteed ImplicitDtorDerived<T>) -> @owned Builtin.NativeObject {
// CHECK: bb0([[THIS:%[0-9]+]] : $ImplicitDtorDerived<T>):
// -- base dtor
// CHECK: [[BASE:%[0-9]+]] = upcast [[THIS]] : ${{.*}} to $ImplicitDtor
// CHECK: [[BASE_DTOR:%[0-9]+]] = function_ref @_T08lifetime12ImplicitDtorCfd
- // CHECK: apply [[BASE_DTOR]]([[BASE]])
+ // CHECK: [[PTR:%.*]] = apply [[BASE_DTOR]]([[BASE]])
// -- destroy_value z
- // CHECK: [[ZADDR:%[0-9]+]] = ref_element_addr [[THIS]] : {{.*}}, #ImplicitDtorDerived.z
+ // CHECK: [[BORROWED_PTR:%.*]] = begin_borrow [[PTR]]
+ // CHECK: [[CAST_BORROWED_PTR:%.*]] = unchecked_ref_cast [[BORROWED_PTR]] : $Builtin.NativeObject to $ImplicitDtorDerived<T>
+ // CHECK: [[ZADDR:%[0-9]+]] = ref_element_addr [[CAST_BORROWED_PTR]] : {{.*}}, #ImplicitDtorDerived.z
// CHECK: destroy_addr [[ZADDR]]
+ // CHECK: end_borrow [[BORROWED_PTR]] from [[PTR]]
+ // -- epilog
+ // CHECK-NOT: unchecked_ref_cast
+ // CHECK-NOT: unchecked_ownership_conversion
+ // CHECK: return [[PTR]]
}
class ImplicitDtorDerivedFromGeneric<T> : ImplicitDtorDerived<Int> {
diff --git a/test/SILGen/materializeForSet.swift b/test/SILGen/materializeForSet.swift
index 7f3d867..55210ee 100644
--- a/test/SILGen/materializeForSet.swift
+++ b/test/SILGen/materializeForSet.swift
@@ -80,6 +80,7 @@
// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [[REABSTRACTOR]]([[VALUE]])
// CHECK-NEXT: [[FN:%.*]] = class_method [[SELF]] : $Base, #Base.storedFunction!setter.1 : (Base) -> (@escaping () -> Int) -> ()
// CHECK-NEXT: apply [[FN]]([[NEWVALUE]], [[SELF]])
+// CHECK-NEXT: end_borrow [[T0]] from %2
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
@@ -100,12 +101,13 @@
// CHECK-NEXT: store [[T1]] to [init] [[RESULT_ADDR]]
// CHECK-NEXT: [[RESULT_PTR:%.*]] = address_to_pointer [[RESULT_ADDR]] : $*@callee_owned () -> @out Int to $Builtin.RawPointer
// CHECK-NEXT: function_ref
-// CHECK-NEXT: [[T0:%.*]] = function_ref @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14storedFunction6ResultQzycfmytfU_TW
-// CHECK-NEXT: [[T1:%.*]] = thin_function_to_pointer [[T0]]
-// CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T1]]
-// CHECK-NEXT: [[T0:%.*]] = tuple ([[RESULT_PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK-NEXT: [[T2:%.*]] = function_ref @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14storedFunction6ResultQzycfmytfU_TW
+// CHECK-NEXT: [[T3:%.*]] = thin_function_to_pointer [[T2]]
+// CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T3]]
+// CHECK-NEXT: [[T4:%.*]] = tuple ([[RESULT_PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
// CHECK-NEXT: dealloc_stack [[TEMP]]
-// CHECK-NEXT: return [[T0]]
+// CHECK-NEXT: end_borrow [[T0]] from %2
+// CHECK-NEXT: return [[T4]]
// CHECK: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP19finalStoredFunction6ResultQzycfmytfU_TW :
// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived, %3 : $@thick Derived.Type):
@@ -118,6 +120,7 @@
// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [[REABSTRACTOR]]([[VALUE]])
// CHECK-NEXT: [[ADDR:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.finalStoredFunction
// CHECK-NEXT: assign [[NEWVALUE]] to [[ADDR]]
+// CHECK-NEXT: end_borrow [[T0]] from %2
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
@@ -134,17 +137,18 @@
// CHECK-NEXT: store [[T1]] to [init] [[RESULT_ADDR]]
// CHECK-NEXT: [[RESULT_PTR:%.*]] = address_to_pointer [[RESULT_ADDR]] : $*@callee_owned () -> @out Int to $Builtin.RawPointer
// CHECK-NEXT: function_ref
-// CHECK-NEXT: [[T0:%.*]] = function_ref @_T017materializeForSet7DerivedCAA12AbstractableAaaDP19finalStoredFunction6ResultQzycfmytfU_TW
-// CHECK-NEXT: [[T1:%.*]] = thin_function_to_pointer [[T0]]
-// CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T1]]
-// CHECK-NEXT: [[T0:%.*]] = tuple ([[RESULT_PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
-// CHECK-NEXT: return [[T0]]
+// CHECK-NEXT: [[T2:%.*]] = function_ref @_T017materializeForSet7DerivedCAA12AbstractableAaaDP19finalStoredFunction6ResultQzycfmytfU_TW
+// CHECK-NEXT: [[T3:%.*]] = thin_function_to_pointer [[T2]]
+// CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T3]]
+// CHECK-NEXT: [[T4:%.*]] = tuple ([[RESULT_PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK-NEXT: end_borrow [[T0]] from %2
+// CHECK-NEXT: return [[T4]]
// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14staticFunction6ResultQzycfmZytfU_TW
-// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*@thick Derived.Type, %3 : $@thick Derived.Type.Type):
-// CHECK-NEXT: [[SELF:%.*]] = load_borrow %2 : $*@thick Derived.Type
+// CHECK: bb0([[ARG1:%.*]] : $Builtin.RawPointer, [[ARG2:%.*]] : $*Builtin.UnsafeValueBuffer, [[ARG3:%.*]] : $*@thick Derived.Type, [[ARG4:%.*]] : $@thick Derived.Type.Type):
+// CHECK-NEXT: [[SELF:%.*]] = load [trivial] [[ARG3]] : $*@thick Derived.Type
// CHECK-NEXT: [[BASE_SELF:%.*]] = upcast [[SELF]] : $@thick Derived.Type to $@thick Base.Type
-// CHECK-NEXT: [[BUFFER:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_owned () -> @out Int
+// CHECK-NEXT: [[BUFFER:%.*]] = pointer_to_address [[ARG1]] : $Builtin.RawPointer to [strict] $*@callee_owned () -> @out Int
// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[BUFFER]] : $*@callee_owned () -> @out Int
// CHECK: [[REABSTRACTOR:%.*]] = function_ref @_T0SiIxr_SiIxd_TR : $@convention(thin) (@owned @callee_owned () -> @out Int) -> Int
// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [[REABSTRACTOR]]([[VALUE]]) : $@convention(thin) (@owned @callee_owned () -> @out Int) -> Int
diff --git a/test/SILGen/objc_properties.swift b/test/SILGen/objc_properties.swift
index a9d0064..f7b7835 100644
--- a/test/SILGen/objc_properties.swift
+++ b/test/SILGen/objc_properties.swift
@@ -4,7 +4,6 @@
import Foundation
-
class A {
dynamic var prop: Int
dynamic var computedProp: Int {
@@ -183,6 +182,31 @@
var ref: Unmanaged<AnyObject>?
}
+@_silgen_name("autoreleasing_user")
+func useAutoreleasingUnsafeMutablePointer(_ a: AutoreleasingUnsafeMutablePointer<NSObject>)
+
+class NonObjCClassWithObjCProperty {
+ var property: NSObject
+
+ init(_ newValue: NSObject) {
+ property = newValue
+ }
+
+ // CHECK-LABEL: sil hidden @_T015objc_properties016NonObjCClassWithD9CPropertyC11usePropertyyyF : $@convention(method) (@guaranteed NonObjCClassWithObjCProperty) -> () {
+ // CHECK: bb0([[ARG:%.*]] : $NonObjCClassWithObjCProperty):
+ // CHECK: [[MATERIALIZE_FOR_SET:%.*]] = class_method [[ARG]] : $NonObjCClassWithObjCProperty, #NonObjCClassWithObjCProperty.property!materializeForSet.1
+ // CHECK: [[TUPLE:%.*]] = apply [[MATERIALIZE_FOR_SET]]({{.*}}, {{.*}}, [[ARG]])
+ // CHECK: [[RAW_POINTER:%.*]] = tuple_extract [[TUPLE]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 0
+ // CHECK: [[OBJECT:%.*]] = pointer_to_address [[RAW_POINTER]] : $Builtin.RawPointer to [strict] $*NSObject
+ // CHECK: [[OBJECT_DEP:%.*]] = mark_dependence [[OBJECT]] : $*NSObject on [[ARG]]
+ // CHECK: [[LOADED_OBJECT:%.*]] = load_borrow [[OBJECT_DEP]]
+ // CHECK: [[UNMANAGED_OBJECT:%.*]] = ref_to_unmanaged [[LOADED_OBJECT]] : $NSObject to $@sil_unmanaged NSObject
+ // CHECK: end_borrow [[LOADED_OBJECT]] from [[OBJECT_DEP]]
+ func useProperty() {
+ useAutoreleasingUnsafeMutablePointer(&property)
+ }
+}
+
// <rdar://problem/21544588> crash when overriding non-@objc property with @objc property.
class NonObjCBaseClass : NSObject {
diff --git a/test/SILOptimizer/devirtualize_existential.swift b/test/SILOptimizer/devirtualize_existential.swift
index 570460b..8072de8 100644
--- a/test/SILOptimizer/devirtualize_existential.swift
+++ b/test/SILOptimizer/devirtualize_existential.swift
@@ -8,12 +8,61 @@
}
// Everything gets devirtualized, inlined, and promoted to the stack.
-//CHECK: @_T024devirtualize_existential17interesting_stuffyyF
-//CHECK-NOT: init_existential_addr
-//CHECK-NOT: apply
-//CHECK: return
+// CHECK-LABEL: @_T024devirtualize_existential17interesting_stuffyyF
+// CHECK-NOT: init_existential_addr
+// CHECK-NOT: apply
+// CHECK: return
public func interesting_stuff() {
- var x : Pingable = Foo()
+ var x: Pingable = Foo()
x.ping(1)
}
+protocol Cloneable {
+ func clone() -> Self
+ func maybeClone() -> Self?
+}
+
+struct Bar : Cloneable {
+ @inline(never)
+ func clone() -> Bar { return self }
+
+ @inline(never)
+ func maybeClone() -> Bar? { return self }
+}
+
+// In this example, we don't eliminate the init_existential_addr, because
+// of the stack allocated existential value used for the return.
+//
+// If the combiner was generalized to replace the opened existential type
+// with the concrete type in all instructions that use it, instead of just
+// special-casing witness_method and apply, we could eliminate the opened
+// existential type completely.
+//
+// However even though IRGen still performs more work at runtime than is
+// necessary here, the call is devirtualized.
+
+// CHECK-LABEL: sil @_T024devirtualize_existential22more_interesting_stuffyyF
+// CHECK: [[EXISTENTIAL:%.*]] = alloc_stack $Cloneable
+// CHECK: [[EXISTENTIAL_ADDR:%.*]] = init_existential_addr [[EXISTENTIAL]]
+// CHECK: [[VALUE:%.*]] = struct $Bar ()
+// CHECK: [[RESULT_ADDR:%.*]] = unchecked_addr_cast [[EXISTENTIAL_ADDR:%.*]]
+// CHECK: [[FN:%.*]] = function_ref @_T024devirtualize_existential3BarV5cloneACyF
+// CHECK: [[RETURN:%.*]] = apply [[FN]]([[VALUE]])
+// CHECK: store [[RETURN]] to [[RESULT_ADDR]]
+
+// CHECK: [[ENUM:%.*]] = alloc_stack $Optional<Cloneable>
+// CHECK: [[ENUM_ADDR:%.*]] = init_enum_data_addr [[ENUM]]
+// CHECK: [[EXISTENTIAL_ADDR:%.*]] = init_existential_addr [[ENUM_ADDR]]
+// CHECK: [[RESULT_ADDR:%.*]] = unchecked_addr_cast [[EXISTENTIAL_ADDR:%.*]]
+// CHECK: [[FN:%.*]] = function_ref @_T024devirtualize_existential3BarV10maybeCloneACSgyF
+// CHECK: [[RETURN:%.*]] = apply [[FN]]([[VALUE]])
+// CHECK: store [[RETURN]] to [[RESULT_ADDR]]
+
+// CHECK: return
+
+public func more_interesting_stuff() {
+ var x: Cloneable = Bar()
+
+ x.clone()
+ x.maybeClone()
+}
diff --git a/test/SILOptimizer/ownership_model_eliminator.sil b/test/SILOptimizer/ownership_model_eliminator.sil
index 70288dd..52ab7b6 100644
--- a/test/SILOptimizer/ownership_model_eliminator.sil
+++ b/test/SILOptimizer/ownership_model_eliminator.sil
@@ -174,3 +174,22 @@
%9999 = tuple()
return %9999 : $()
}
+
+// CHECK-LABEL: sil @end_lifetime_test : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK-NOT: end_lifetime {{%.*}} : $Builtin.NativeObject
+sil @end_lifetime_test : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : @owned $Builtin.NativeObject):
+ end_lifetime %0 : $Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// CHECK-LABEL: sil @unchecked_ownership_conversion_test : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Builtin.NativeObject):
+// CHECK: return [[ARG]] : $Builtin.NativeObject
+sil @unchecked_ownership_conversion_test : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
+bb0(%0 : @guaranteed $Builtin.NativeObject):
+ %1 = unchecked_ownership_conversion %0 : $Builtin.NativeObject, @guaranteed to @owned
+ return %1 : $Builtin.NativeObject
+}
+
diff --git a/test/Sema/availability_versions.swift b/test/Sema/availability_versions.swift
index 4ef62d5..c5e1294 100644
--- a/test/Sema/availability_versions.swift
+++ b/test/Sema/availability_versions.swift
@@ -28,15 +28,15 @@
// Functions without annotations should reflect the minimum deployment target.
func functionWithoutAvailability() {
+ // expected-note@-1 2{{add @available attribute to enclosing global function}}
+
let _: Int = globalFuncAvailableOn10_9()
let _: Int = globalFuncAvailableOn10_51() // expected-error {{'globalFuncAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _: Int = globalFuncAvailableOn10_52() // expected-error {{'globalFuncAvailableOn10_52()' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
// Functions with annotations should refine their bodies.
@@ -123,6 +123,8 @@
// Unavailable methods
class ClassWithUnavailableMethod {
+ // expected-note@-1 {{add @available attribute to enclosing class}}
+
@available(OSX, introduced: 10.9)
func methAvailableOn10_9() {}
@@ -133,84 +135,84 @@
class func classMethAvailableOn10_51() {}
func someOtherMethod() {
+ // expected-note@-1 {{add @available attribute to enclosing instance method}}
+
methAvailableOn10_9()
methAvailableOn10_51() // expected-error {{'methAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing instance method}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
}
func callUnavailableMethods(_ o: ClassWithUnavailableMethod) {
+ // expected-note@-1 2{{add @available attribute to enclosing global function}}
+
let m10_9 = o.methAvailableOn10_9
m10_9()
let m10_51 = o.methAvailableOn10_51 // expected-error {{'methAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
m10_51()
o.methAvailableOn10_9()
o.methAvailableOn10_51() // expected-error {{'methAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
func callUnavailableMethodsViaIUO(_ o: ClassWithUnavailableMethod!) {
+ // expected-note@-1 2{{add @available attribute to enclosing global function}}
+
let m10_9 = o.methAvailableOn10_9
m10_9()
let m10_51 = o.methAvailableOn10_51 // expected-error {{'methAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
+
// expected-note@-2 {{add 'if #available' version check}}
m10_51()
o.methAvailableOn10_9()
o.methAvailableOn10_51() // expected-error {{'methAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
func callUnavailableClassMethod() {
+ // expected-note@-1 2{{add @available attribute to enclosing global function}}
+
ClassWithUnavailableMethod.classMethAvailableOn10_51() // expected-error {{'classMethAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let m10_51 = ClassWithUnavailableMethod.classMethAvailableOn10_51 // expected-error {{'classMethAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
m10_51()
}
class SubClassWithUnavailableMethod : ClassWithUnavailableMethod {
+ // expected-note@-1 {{add @available attribute to enclosing class}}
func someMethod() {
+ // expected-note@-1 {{add @available attribute to enclosing instance method}}
+
methAvailableOn10_9()
methAvailableOn10_51() // expected-error {{'methAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing instance method}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
}
class SubClassOverridingUnavailableMethod : ClassWithUnavailableMethod {
+ // expected-note@-1 2{{add @available attribute to enclosing class}}
override func methAvailableOn10_51() {
+ // expected-note@-1 2{{add @available attribute to enclosing instance method}}
methAvailableOn10_9()
super.methAvailableOn10_51() // expected-error {{'methAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing instance method}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let m10_9 = super.methAvailableOn10_9
m10_9()
let m10_51 = super.methAvailableOn10_51 // expected-error {{'methAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing instance method}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
m10_51()
}
@@ -230,15 +232,18 @@
}
func callUnavailableOverloadedMethod(_ o: ClassWithUnavailableOverloadedMethod) {
+ // expected-note@-1 {{add @available attribute to enclosing global function}}
+
o.overloadedMethod()
o.overloadedMethod(0) // expected-error {{'overloadedMethod' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
// Initializers
class ClassWithUnavailableInitializer {
+ // expected-note@-1 {{add @available attribute to enclosing class}}
+
@available(OSX, introduced: 10.9)
required init() { }
@@ -246,10 +251,10 @@
required init(_ val: Int) { }
convenience init(s: String) {
+ // expected-note@-1 {{add @available attribute to enclosing initializer}}
+
self.init(5) // expected-error {{'init' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing initializer}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
@available(OSX, introduced: 10.51)
@@ -259,16 +264,16 @@
}
func callUnavailableInitializer() {
+ // expected-note@-1 2{{add @available attribute to enclosing global function}}
+
_ = ClassWithUnavailableInitializer()
_ = ClassWithUnavailableInitializer(5) // expected-error {{'init' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let i = ClassWithUnavailableInitializer.self
_ = i.init()
_ = i.init(5) // expected-error {{'init' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
class SuperWithWithUnavailableInitializer {
@@ -280,11 +285,13 @@
}
class SubOfClassWithUnavailableInitializer : SuperWithWithUnavailableInitializer {
+ // expected-note@-1 {{add @available attribute to enclosing class}}
+
override init(_ val: Int) {
+ // expected-note@-1 {{add @available attribute to enclosing initializer}}
+
super.init(5) // expected-error {{'init' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing initializer}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
override init() {
@@ -300,6 +307,7 @@
// Properties
class ClassWithUnavailableProperties {
+ // expected-note@-1 4{{add @available attribute to enclosing class}}
@available(OSX, introduced: 10.9) // expected-error {{stored properties cannot be marked potentially unavailable with '@available'}}
var nonLazyAvailableOn10_9Stored: Int = 9
@@ -313,7 +321,6 @@
// Make sure that we don't emit a Fix-It to mark a stored property as potentially unavailable.
// We don't support potentially unavailable stored properties yet.
var storedPropertyOfUnavailableType: ClassAvailableOn10_51? = nil // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
@available(OSX, introduced: 10.9)
lazy var availableOn10_9Stored: Int = 9
@@ -325,8 +332,7 @@
var availableOn10_9Computed: Int {
get {
let _: Int = availableOn10_51Stored // expected-error {{'availableOn10_51Stored' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
if #available(OSX 10.51, *) {
let _: Int = availableOn10_51Stored
@@ -350,11 +356,10 @@
}
var propWithSetterOnlyAvailableOn10_51 : Int {
+ // expected-note@-1 {{add @available attribute to enclosing var}}
get {
_ = globalFuncAvailableOn10_51() // expected-error {{'globalFuncAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing var}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
return 0
}
@available(OSX, introduced: 10.51)
@@ -364,6 +369,7 @@
}
var propWithGetterOnlyAvailableOn10_51 : Int {
+ // expected-note@-1 {{add @available attribute to enclosing var}}
@available(OSX, introduced: 10.51)
get {
_ = globalFuncAvailableOn10_51()
@@ -371,9 +377,7 @@
}
set(newVal) {
_ = globalFuncAvailableOn10_51() // expected-error {{'globalFuncAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing var}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
}
@@ -419,33 +423,29 @@
}
func accessUnavailableProperties(_ o: ClassWithUnavailableProperties) {
+ // expected-note@-1 17{{add @available attribute to enclosing global function}}
// Stored properties
let _: Int = o.availableOn10_9Stored
let _: Int = o.availableOn10_51Stored // expected-error {{'availableOn10_51Stored' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
o.availableOn10_9Stored = 9
o.availableOn10_51Stored = 10 // expected-error {{'availableOn10_51Stored' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
// Computed Properties
let _: Int = o.availableOn10_9Computed
let _: Int = o.availableOn10_51Computed // expected-error {{'availableOn10_51Computed' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
o.availableOn10_9Computed = 9
o.availableOn10_51Computed = 10 // expected-error {{'availableOn10_51Computed' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
// Getter allowed on 10.9 but setter is not
let _: Int = o.propWithSetterOnlyAvailableOn10_51
o.propWithSetterOnlyAvailableOn10_51 = 5 // expected-error {{setter for 'propWithSetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
if #available(OSX 10.51, *) {
// Setter is allowed on 10.51 and greater
@@ -455,8 +455,7 @@
// Setter allowed on 10.9 but getter is not
o.propWithGetterOnlyAvailableOn10_51 = 5
let _: Int = o.propWithGetterOnlyAvailableOn10_51 // expected-error {{getter for 'propWithGetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
if #available(OSX 10.51, *) {
// Getter is allowed on 10.51 and greater
@@ -467,18 +466,15 @@
// Both getters are potentially unavailable.
let _: Int = o.propWithGetterOnlyAvailableOn10_51ForNestedMemberRef.propWithGetterOnlyAvailableOn10_51 // expected-error {{getter for 'propWithGetterOnlyAvailableOn10_51ForNestedMemberRef' is only available on OS X 10.51 or newer}} expected-error {{getter for 'propWithGetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 2{{add @available attribute to enclosing global function}}
- // expected-note@-2 2{{add 'if #available' version check}}
+ // expected-note@-1 2{{add 'if #available' version check}}
// Nested getter is potentially unavailable, outer getter is available
let _: Int = o.propWithGetterOnlyAvailableOn10_51ForNestedMemberRef.propWithSetterOnlyAvailableOn10_51 // expected-error {{getter for 'propWithGetterOnlyAvailableOn10_51ForNestedMemberRef' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
// Nested getter is available, outer getter is potentially unavailable
let _:Int = o.propWithSetterOnlyAvailableOn10_51ForNestedMemberRef.propWithGetterOnlyAvailableOn10_51 // expected-error {{getter for 'propWithGetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
// Both getters are always available.
let _: Int = o.propWithSetterOnlyAvailableOn10_51ForNestedMemberRef.propWithSetterOnlyAvailableOn10_51
@@ -488,33 +484,27 @@
var v: Int
v = o.propWithGetterOnlyAvailableOn10_51 // expected-error {{getter for 'propWithGetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
v = (o.propWithGetterOnlyAvailableOn10_51) // expected-error {{getter for 'propWithGetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
// Inout requires access to both getter and setter
func takesInout(_ i : inout Int) { }
takesInout(&o.propWithGetterOnlyAvailableOn10_51) // expected-error {{cannot pass as inout because getter for 'propWithGetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
takesInout(&o.propWithSetterOnlyAvailableOn10_51) // expected-error {{cannot pass as inout because setter for 'propWithSetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
takesInout(&o.propWithGetterAndSetterOnlyAvailableOn10_51) // expected-error {{cannot pass as inout because getter for 'propWithGetterAndSetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}} expected-error {{cannot pass as inout because setter for 'propWithGetterAndSetterOnlyAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 2{{add @available attribute to enclosing global function}}
- // expected-note@-2 2{{add 'if #available' version check}}
+ // expected-note@-1 2{{add 'if #available' version check}}
takesInout(&o.availableOn10_9Computed)
takesInout(&o.propWithGetterOnlyAvailableOn10_51ForNestedMemberRef.availableOn10_9Computed) // expected-error {{getter for 'propWithGetterOnlyAvailableOn10_51ForNestedMemberRef' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
// _silgen_name
@@ -563,17 +553,15 @@
func functionTakingEnumIntroducedOn10_52(_ e: EnumIntroducedOn10_52) { }
func useEnums() {
+ // expected-note@-1 3{{add @available attribute to enclosing global function}}
let _: CompassPoint = .North // expected-error {{'CompassPoint' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
if #available(OSX 10.51, *) {
let _: CompassPoint = .North
let _: CompassPoint = .West // expected-error {{'West' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
-
+ // expected-note@-1 {{add 'if #available' version check}}
}
if #available(OSX 10.52, *) {
@@ -595,7 +583,7 @@
// For the moment, we do not incorporate enum element availability into
// TRC construction. Perhaps we should?
functionTakingEnumIntroducedOn10_52(p) // expected-error {{'functionTakingEnumIntroducedOn10_52' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
+
// expected-note@-2 {{add 'if #available' version check}}
}
}
@@ -629,20 +617,18 @@
}
func classAvailability() {
+ // expected-note@-1 3{{add @available attribute to enclosing global function}}
ClassAvailableOn10_9.someClassMethod()
ClassAvailableOn10_51.someClassMethod() // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
_ = ClassAvailableOn10_9.self
_ = ClassAvailableOn10_51.self // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let o10_9 = ClassAvailableOn10_9()
let o10_51 = ClassAvailableOn10_51() // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
o10_9.someMethod()
o10_51.someMethod()
@@ -652,17 +638,15 @@
}
func castingUnavailableClass(_ o : AnyObject) {
+ // expected-note@-1 3{{add @available attribute to enclosing global function}}
let _ = o as! ClassAvailableOn10_51 // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _ = o as? ClassAvailableOn10_51 // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _ = o is ClassAvailableOn10_51 // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
protocol Creatable {
@@ -683,45 +667,39 @@
class ClassWithTwoGenericTypeParameter<T, S> { }
func classViaTypeParameter() {
+ // expected-note@-1 9{{add @available attribute to enclosing global function}}
let _ : ClassAvailableOn10_51_Creatable = // expected-error {{'ClassAvailableOn10_51_Creatable' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
create()
let _ = create() as
ClassAvailableOn10_51_Creatable // expected-error {{'ClassAvailableOn10_51_Creatable' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _ = [ClassAvailableOn10_51]() // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _: ClassWithGenericTypeParameter<ClassAvailableOn10_51> = ClassWithGenericTypeParameter() // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _: ClassWithTwoGenericTypeParameter<ClassAvailableOn10_51, String> = ClassWithTwoGenericTypeParameter() // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _: ClassWithTwoGenericTypeParameter<String, ClassAvailableOn10_51> = ClassWithTwoGenericTypeParameter() // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _: ClassWithTwoGenericTypeParameter<ClassAvailableOn10_51, ClassAvailableOn10_51> = ClassWithTwoGenericTypeParameter() // expected-error 2{{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 2{{add @available attribute to enclosing global function}}
- // expected-note@-2 2{{add 'if #available' version check}}
+ // expected-note@-1 2{{add 'if #available' version check}}
let _: ClassAvailableOn10_51? = nil // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
// Unavailable class used in declarations
class ClassWithDeclarationsOfUnavailableClasses {
+ // expected-note@-1 5{{add @available attribute to enclosing class}}
@available(OSX, introduced: 10.51)
init() {
@@ -730,7 +708,6 @@
}
var propertyOfUnavailableType: ClassAvailableOn10_51 // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
@available(OSX, introduced: 10.51)
lazy var unavailablePropertyOfUnavailableType: ClassAvailableOn10_51 = ClassAvailableOn10_51()
@@ -748,9 +725,7 @@
static var unavailableStaticPropertyOfOptionalUnavailableType: ClassAvailableOn10_51?
func methodWithUnavailableParameterType(_ o : ClassAvailableOn10_51) { // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing instance method}}
-
+ // expected-note@-1 {{add @available attribute to enclosing instance method}}
}
@available(OSX, introduced: 10.51)
@@ -758,13 +733,10 @@
}
func methodWithUnavailableReturnType() -> ClassAvailableOn10_51 { // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing instance method}}
+ // expected-note@-1 2{{add @available attribute to enclosing instance method}}
return ClassAvailableOn10_51() // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing instance method}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
@available(OSX, introduced: 10.51)
@@ -773,10 +745,9 @@
}
func methodWithUnavailableLocalDeclaration() {
+ // expected-note@-1 {{add @available attribute to enclosing instance method}}
let _ : ClassAvailableOn10_51 = methodWithUnavailableReturnType() // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add @available attribute to enclosing instance method}}
- // expected-note@-3 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
@available(OSX, introduced: 10.51)
@@ -786,14 +757,13 @@
}
func referToUnavailableStaticProperty() {
- let _ = ClassWithDeclarationsOfUnavailableClasses.unavailableStaticPropertyOfUnavailableType // expected-error {{'unavailableStaticPropertyOfUnavailableType' is only available on OS X 10.51 or newer}}
// expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ let _ = ClassWithDeclarationsOfUnavailableClasses.unavailableStaticPropertyOfUnavailableType // expected-error {{'unavailableStaticPropertyOfUnavailableType' is only available on OS X 10.51 or newer}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
class ClassExtendingUnavailableClass : ClassAvailableOn10_51 { // expected-error {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-1 {{add @available attribute to enclosing class}}
-
}
@available(OSX, introduced: 10.51)
@@ -860,11 +830,11 @@
}
class SubWithLargerMemberAvailability : SuperWithLimitedMemberAvailability {
+ // expected-note@-1 2{{add @available attribute to enclosing class}}
@available(OSX, introduced: 10.9)
override func someMethod() {
super.someMethod() // expected-error {{'someMethod()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
if #available(OSX 10.51, *) {
super.someMethod()
@@ -875,8 +845,7 @@
override var someProperty: Int {
get {
let _ = super.someProperty // expected-error {{'someProperty' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing class}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
if #available(OSX 10.51, *) {
let _ = super.someProperty
@@ -916,15 +885,14 @@
}
func castToUnavailableProtocol() {
+ // expected-note@-1 2{{add @available attribute to enclosing global function}}
let o: ClassAvailableOn10_9AdoptingProtocolAvailableOn10_51 = ClassAvailableOn10_9AdoptingProtocolAvailableOn10_51()
let _: ProtocolAvailableOn10_51 = o // expected-error {{'ProtocolAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _ = o as ProtocolAvailableOn10_51 // expected-error {{'ProtocolAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
@available(OSX, introduced: 10.9)
@@ -953,10 +921,10 @@
@available(OSX, introduced: 10.51)
extension ClassAvailableOn10_51 {
func m() {
+ // expected-note@-1 {{add @available attribute to enclosing instance method}}
let _ = globalFuncAvailableOn10_51()
let _ = globalFuncAvailableOn10_52() // expected-error {{'globalFuncAvailableOn10_52()' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing instance method}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
}
@@ -991,19 +959,17 @@
}
func useUnavailableExtension() {
+ // expected-note@-1 3{{add @available attribute to enclosing global function}}
let o = ClassToExtend()
o.extensionMethod() // expected-error {{'extensionMethod()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _ = ClassToExtend.ExtensionClass() // expected-error {{'ExtensionClass' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
o.extensionMethod10_52() // expected-error {{'extensionMethod10_52()' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
// Useless #available(...) checks
@@ -1136,11 +1102,11 @@
// Tests for the guard control construct.
func useGuardAvailable() {
+ // expected-note@-1 3{{add @available attribute to enclosing global function}}
// Guard fallthrough should refine context
guard #available(OSX 10.51, *) else { // expected-note {{enclosing scope here}}
let _ = globalFuncAvailableOn10_51() // expected-error {{'globalFuncAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-1 {{add 'if #available' version check}}
- // expected-note@-2 {{add @available attribute to enclosing global function}}
return
}
@@ -1148,7 +1114,6 @@
let _ = globalFuncAvailableOn10_52() // expected-error {{'globalFuncAvailableOn10_52()' is only available on OS X 10.52 or newer}}
// expected-note@-1 {{add 'if #available' version check}}
- // expected-note@-2 {{add @available attribute to enclosing global function}}
if #available(OSX 10.51, *) { // expected-warning {{unnecessary check for 'OSX'; enclosing scope ensures guard will always be true}}
}
@@ -1161,11 +1126,10 @@
let _ = globalFuncAvailableOn10_52() // expected-error {{'globalFuncAvailableOn10_52()' is only available on OS X 10.52 or newer}}
// expected-note@-1 {{add 'if #available' version check}}
- // expected-note@-2 {{add @available attribute to enclosing global function}}
-
}
func twoGuardsInSameBlock(_ p: Int) {
+ // expected-note@-1 {{add @available attribute to enclosing global function}}
if (p > 0) {
guard #available(OSX 10.51, *) else { return }
@@ -1178,7 +1142,6 @@
let _ = globalFuncAvailableOn10_51() // expected-error {{'globalFuncAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-1 {{add 'if #available' version check}}
- // expected-note@-2 {{add @available attribute to enclosing global function}}
}
// Refining while loops
@@ -1219,134 +1182,125 @@
// expected-note@-2 {{add 'if #available' version check}} {{1-57=if #available(OSX 10.51, *) {\n let declForFixitAtTopLevel: ClassAvailableOn10_51? = nil\n} else {\n // Fallback on earlier versions\n}}}
func fixitForReferenceInGlobalFunction() {
+ // expected-note@-1 {{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.51, *)\n}}
functionAvailableOn10_51()
// expected-error@-1 {{'functionAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{3-29=if #available(OSX 10.51, *) {\n functionAvailableOn10_51()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.51, *)\n}}
+
}
public func fixitForReferenceInGlobalFunctionWithDeclModifier() {
+ // expected-note@-1 {{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.51, *)\n}}
functionAvailableOn10_51()
// expected-error@-1 {{'functionAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{3-29=if #available(OSX 10.51, *) {\n functionAvailableOn10_51()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.51, *)\n}}
+
}
func fixitForReferenceInGlobalFunctionWithAttribute() -> Never {
+ // expected-note@-1 {{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.51, *)\n}}
functionAvailableOn10_51()
// expected-error@-1 {{'functionAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{3-29=if #available(OSX 10.51, *) {\n functionAvailableOn10_51()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.51, *)\n}}
+
}
func takesAutoclosure(_ c : @autoclosure () -> ()) {
}
class ClassForFixit {
+ // expected-note@-1 12{{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
func fixitForReferenceInMethod() {
+ // expected-note@-1 {{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
functionAvailableOn10_51()
// expected-error@-1 {{'functionAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{5-31=if #available(OSX 10.51, *) {\n functionAvailableOn10_51()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-4 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
}
func fixitForReferenceNestedInMethod() {
+ // expected-note@-1 3{{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
func inner() {
functionAvailableOn10_51()
// expected-error@-1 {{'functionAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{7-33=if #available(OSX 10.51, *) {\n functionAvailableOn10_51()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-4 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
}
let _: () -> () = { () in
functionAvailableOn10_51()
// expected-error@-1 {{'functionAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{7-33=if #available(OSX 10.51, *) {\n functionAvailableOn10_51()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-4 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
}
takesAutoclosure(functionAvailableOn10_51())
// expected-error@-1 {{'functionAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{5-49=if #available(OSX 10.51, *) {\n takesAutoclosure(functionAvailableOn10_51())\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-4 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
+
}
var fixitForReferenceInPropertyAccessor: Int {
+ // expected-note@-1 {{add @available attribute to enclosing var}} {{3-3=@available(OSX 10.51, *)\n }}
get {
functionAvailableOn10_51()
// expected-error@-1 {{'functionAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{7-33=if #available(OSX 10.51, *) {\n functionAvailableOn10_51()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing var}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-4 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
-
+
return 5
}
}
var fixitForReferenceInPropertyType: ClassAvailableOn10_51? = nil
// expected-error@-1 {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-2 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
lazy var fixitForReferenceInLazyPropertyType: ClassAvailableOn10_51? = nil
// expected-error@-1 {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add @available attribute to enclosing var}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-3 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
private lazy var fixitForReferenceInPrivateLazyPropertyType: ClassAvailableOn10_51? = nil
// expected-error@-1 {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add @available attribute to enclosing var}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-3 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
lazy private var fixitForReferenceInLazyPrivatePropertyType: ClassAvailableOn10_51? = nil
// expected-error@-1 {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add @available attribute to enclosing var}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-3 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
static var fixitForReferenceInStaticPropertyType: ClassAvailableOn10_51? = nil
// expected-error@-1 {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add @available attribute to enclosing static var}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-3 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
var fixitForReferenceInPropertyTypeMultiple: ClassAvailableOn10_51? = nil, other: Int = 7
// expected-error@-1 {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-2 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
func fixitForRefInGuardOfIf() {
+ // expected-note@-1 {{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
if (globalFuncAvailableOn10_51() > 1066) {
let _ = 5
let _ = 6
}
// expected-error@-4 {{'globalFuncAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-5 {{add 'if #available' version check}} {{5-6=if #available(OSX 10.51, *) {\n if (globalFuncAvailableOn10_51() > 1066) {\n let _ = 5\n let _ = 6\n }\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-6 {{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-7 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
}
}
extension ClassToExtend {
+ // expected-note@-1 {{add @available attribute to enclosing extension}}
func fixitForReferenceInExtensionMethod() {
+ // expected-note@-1 {{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
functionAvailableOn10_51()
// expected-error@-1 {{'functionAvailableOn10_51()' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{5-31=if #available(OSX 10.51, *) {\n functionAvailableOn10_51()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing instance method}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-4 {{add @available attribute to enclosing extension}} {{1-1=@available(OSX 10.51, *)\n}}
}
}
enum EnumForFixit {
+ // expected-note@-1 2{{add @available attribute to enclosing enum}} {{1-1=@available(OSX 10.51, *)\n}}
case CaseWithUnavailablePayload(p: ClassAvailableOn10_51)
// expected-error@-1 {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add @available attribute to enclosing case}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-3 {{add @available attribute to enclosing enum}} {{1-1=@available(OSX 10.51, *)\n}}
case CaseWithUnavailablePayload2(p: ClassAvailableOn10_51), WithoutPayload
// expected-error@-1 {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-2 {{add @available attribute to enclosing case}} {{3-3=@available(OSX 10.51, *)\n }}
- // expected-note@-3 {{add @available attribute to enclosing enum}} {{1-1=@available(OSX 10.51, *)\n}}
+
}
@objc
@@ -1360,31 +1314,31 @@
}
func testForFixitWithNestedMemberRefExpr() {
+ // expected-note@-1 2{{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.52, *)\n}}
let x = X()
x.y.z = globalFuncAvailableOn10_52()
// expected-error@-1 {{'globalFuncAvailableOn10_52()' is only available on OS X 10.52 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{3-39=if #available(OSX 10.52, *) {\n x.y.z = globalFuncAvailableOn10_52()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.52, *)\n}}
// Access via dynamic member reference
let anyX: AnyObject = x
anyX.y?.z = globalFuncAvailableOn10_52()
// expected-error@-1 {{'globalFuncAvailableOn10_52()' is only available on OS X 10.52 or newer}}
// expected-note@-2 {{add 'if #available' version check}} {{3-43=if #available(OSX 10.52, *) {\n anyX.y?.z = globalFuncAvailableOn10_52()\n } else {\n // Fallback on earlier versions\n }}}
- // expected-note@-3 {{add @available attribute to enclosing global function}} {{1-1=@available(OSX 10.52, *)\n}}
+
}
// Protocol Conformances
protocol ProtocolWithRequirementMentioningUnavailable {
+ // expected-note@-1 6{{add @available attribute to enclosing protocol}}
func hasUnavailableParameter(_ p: ClassAvailableOn10_51) // expected-error * {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-1 * {{add @available attribute to enclosing instance method}}
- // expected-note@-2 * {{add @available attribute to enclosing protocol}}
+
func hasUnavailableReturn() -> ClassAvailableOn10_51 // expected-error * {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-1 * {{add @available attribute to enclosing instance method}}
- // expected-note@-2 * {{add @available attribute to enclosing protocol}}
@available(OSX 10.51, *)
func hasUnavailableWithAnnotation(_ p: ClassAvailableOn10_51) -> ClassAvailableOn10_51
@@ -1530,15 +1484,15 @@
}
func useUnavailableProtocolMethod(_ h: HasUnavailableMethodF) {
- h.f("Foo") // expected-error {{'f' is only available on OS X 10.51 or newer}}
// expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ h.f("Foo") // expected-error {{'f' is only available on OS X 10.51 or newer}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
func useUnavailableProtocolMethod<H : HasUnavailableMethodF> (_ h: H) {
- h.f("Foo") // expected-error {{'f' is only available on OS X 10.51 or newer}}
// expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ h.f("Foo") // expected-error {{'f' is only available on OS X 10.51 or newer}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
@@ -1569,9 +1523,9 @@
@available(iOS 14.0, *)
func funcWithShortFormAvailableOniOS14() {
+ // expected-note@-1 {{add @available attribute to enclosing global function}}
let _ = ClassWithShortFormAvailableOn10_51() // expected-error {{'ClassWithShortFormAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
@available(iOS 14.0, OSX 10.53, *)
@@ -1601,25 +1555,23 @@
func unavailableWins() { } // expected-note {{'unavailableWins()' has been explicitly marked unavailable here}}
func useShortFormAvailable() {
+ // expected-note@-1 4{{add @available attribute to enclosing global function}}
+
funcWithShortFormAvailableOn10_9()
funcWithShortFormAvailableOn10_51() // expected-error {{'funcWithShortFormAvailableOn10_51()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
funcWithShortFormAvailableOniOS14()
funcWithShortFormAvailableOniOS14AndOSX10_53() // expected-error {{'funcWithShortFormAvailableOniOS14AndOSX10_53()' is only available on OS X 10.53 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
funcWithMultipleShortFormAnnotationsForDifferentPlatforms() // expected-error {{'funcWithMultipleShortFormAnnotationsForDifferentPlatforms()' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
funcWithMultipleShortFormAnnotationsForTheSamePlatform() // expected-error {{'funcWithMultipleShortFormAnnotationsForTheSamePlatform()' is only available on OS X 10.53 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
unavailableWins() // expected-error {{'unavailableWins()' is unavailable}}
-}
+}
\ No newline at end of file
diff --git a/test/Sema/availability_versions_objc_api.swift b/test/Sema/availability_versions_objc_api.swift
index 265e943..8eb9821 100644
--- a/test/Sema/availability_versions_objc_api.swift
+++ b/test/Sema/availability_versions_objc_api.swift
@@ -8,9 +8,9 @@
// Tests for uses of version-based potential unavailability imported from ObjC APIs.
func callUnavailableObjC() {
+ // expected-note@-1 5{{add @available attribute to enclosing global function}}
_ = NSAvailableOn10_51() // expected-error {{'NSAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
if #available(OSX 10.51, *) {
@@ -18,23 +18,19 @@
// Properties
_ = o.propertyOn10_52 // expected-error {{'propertyOn10_52' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
o.propertyOn10_52 = 22 // expected-error {{'propertyOn10_52' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
// Methods
o.methodAvailableOn10_52() // expected-error {{'methodAvailableOn10_52()' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
// Initializers
_ = NSAvailableOn10_51(stringOn10_52:"Hi") // expected-error {{'init(stringOn10_52:)' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
}
@@ -74,50 +70,43 @@
// Differing availability on getters and setters imported from ObjC.
func gettersAndSettersFromObjC(o: NSAvailableOn10_9) {
+ // expected-note@-1 6{{add @available attribute to enclosing global function}}
let _: Int = o.propertyOn10_51WithSetterOn10_52After // expected-error {{'propertyOn10_51WithSetterOn10_52After' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
if #available(OSX 10.51, *) {
// Properties with unavailable accessors declared before property in Objective-C header
o.propertyOn10_51WithSetterOn10_52Before = 5 // expected-error {{setter for 'propertyOn10_51WithSetterOn10_52Before' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _: Int = o.propertyOn10_51WithGetterOn10_52Before // expected-error {{getter for 'propertyOn10_51WithGetterOn10_52Before' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
// Properties with unavailable accessors declared after property in Objective-C header
o.propertyOn10_51WithSetterOn10_52After = 5 // expected-error {{setter for 'propertyOn10_51WithSetterOn10_52After' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
let _: Int = o.propertyOn10_51WithGetterOn10_52After // expected-error {{getter for 'propertyOn10_51WithGetterOn10_52After' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
// Property with unavailable setter redeclared in Objective-C category
o.readOnlyRedeclaredWithSetterInCategory = 5 // expected-error {{setter for 'readOnlyRedeclaredWithSetterInCategory' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
}
// Globals from Objective-C
func useGlobalsFromObjectiveC() {
+ // expected-note@-1 3{{add @available attribute to enclosing global function}}
_ = globalStringAvailableOn10_51 // expected-error {{'globalStringAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
_ = globalStringAvailableOn10_52 // expected-error {{'globalStringAvailableOn10_52' is only available on OS X 10.52 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
_ = globalClassInstanceAvailableOn10_51 // expected-error {{'globalClassInstanceAvailableOn10_51' is only available on OS X 10.51 or newer}}
- // expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ // expected-note@-1 {{add 'if #available' version check}}
if #available(OSX 10.51, *) {
_ = globalStringAvailableOn10_51
@@ -177,9 +166,9 @@
}
func callViaUnannotatedFrameworkProtocol(p: UnannotatedFrameworkProtocol) {
- let _ = p.returnSomething() // expected-error {{'returnSomething()' is only available on OS X 10.51 or newer}}
// expected-note@-1 {{add @available attribute to enclosing global function}}
- // expected-note@-2 {{add 'if #available' version check}}
+ let _ = p.returnSomething() // expected-error {{'returnSomething()' is only available on OS X 10.51 or newer}}
+ // expected-note@-1 {{add 'if #available' version check}}
}
func callViaAnnotatedFrameworkProtocol(p: AnnotatedFrameworkProtocol) {
diff --git a/test/Serialization/Inputs/def_objc_conforming.swift b/test/Serialization/Inputs/def_objc_conforming.swift
new file mode 100644
index 0000000..c229fa7
--- /dev/null
+++ b/test/Serialization/Inputs/def_objc_conforming.swift
@@ -0,0 +1,9 @@
+import Foundation
+
+@objc public protocol Proto {
+ @objc optional func badness()
+}
+
+public class Foo: Proto {
+ public var badness: Int = 0 // unrelated
+}
diff --git a/test/Serialization/objc_optional_reqs.swift b/test/Serialization/objc_optional_reqs.swift
new file mode 100644
index 0000000..998c062
--- /dev/null
+++ b/test/Serialization/objc_optional_reqs.swift
@@ -0,0 +1,16 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+
+// FIXME: BEGIN -enable-source-import hackaround
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t %clang-importer-sdk-path/swift-modules/Foundation.swift
+// FIXME: END -enable-source-import hackaround
+
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %S/Inputs/def_objc_conforming.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -typecheck %s -verify
+
+// REQUIRES: objc_interop
+
+// SR-3917
+import def_objc_conforming
+
+func test(x: Foo) { _ = x.badness }
diff --git a/test/SourceKit/CursorInfo/cursor_info_expressions.swift b/test/SourceKit/CursorInfo/cursor_info_expressions.swift
new file mode 100644
index 0000000..56f1ee3
--- /dev/null
+++ b/test/SourceKit/CursorInfo/cursor_info_expressions.swift
@@ -0,0 +1,14 @@
+protocol P1 {}
+
+struct S1 : P1 {}
+
+func test(_ o: P1?) {
+ switch o {
+ case let s as S1:
+ test(s)
+ }
+}
+
+// RUN: %sourcekitd-test -req=cursor -pos=7:17 %s -- %s | %FileCheck -check-prefix=CHECK1 %s
+// CHECK1: source.lang.swift.ref.struct (3:8-3:10)
+// CHECK1: S1
diff --git a/test/api-digester/Outputs/Cake.txt b/test/api-digester/Outputs/Cake.txt
index 3a7fdcd..b12cbeb 100644
--- a/test/api-digester/Outputs/Cake.txt
+++ b/test/api-digester/Outputs/Cake.txt
@@ -7,8 +7,8 @@
Func S1.foo5(x:y:) has been renamed to Func S1.foo5(x:y:z:)
/* Type Changes */
-Constructor S1.init(_:) has 1st parameter type change from Int to Double
-Func C1.foo2(_:) has 1st parameter type change from Int to () -> ()
+Constructor S1.init(_:) has parameter 0 type change from Int to Double
+Func C1.foo2(_:) has parameter 0 type change from Int to () -> ()
/* Decl Attribute changes */
Var C1.CIIns1 changes from weak to strong
diff --git a/test/api-digester/source-stability.swift.expected b/test/api-digester/source-stability.swift.expected
index 89f7ef7..113fda8 100644
--- a/test/api-digester/source-stability.swift.expected
+++ b/test/api-digester/source-stability.swift.expected
@@ -26,20 +26,20 @@
Var Dictionary.startIndex has declared type change from DictionaryIndex<Key, Value> to Dictionary<Key, Value>.Index
Var Set.endIndex has declared type change from SetIndex<Element> to Set<Element>.Index
Var Set.startIndex has declared type change from SetIndex<Element> to Set<Element>.Index
-Constructor AnyIterator.init(_:) has 1st parameter type change from () -> Element? to () -> AnyIterator.Element?
-Constructor BidirectionalSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<BidirectionalSlice.Index>
-Constructor MutableBidirectionalSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<MutableBidirectionalSlice.Index>
-Constructor MutableRandomAccessSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<MutableRandomAccessSlice.Index>
-Constructor MutableRangeReplaceableBidirectionalSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<MutableRangeReplaceableBidirectionalSlice.Index>
-Constructor MutableRangeReplaceableRandomAccessSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<MutableRangeReplaceableRandomAccessSlice.Index>
-Constructor MutableRangeReplaceableSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<MutableRangeReplaceableSlice.Index>
-Constructor MutableSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<MutableSlice.Index>
-Constructor RandomAccessSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<RandomAccessSlice.Index>
-Constructor RangeReplaceableBidirectionalSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<RangeReplaceableBidirectionalSlice.Index>
-Constructor RangeReplaceableRandomAccessSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<RangeReplaceableRandomAccessSlice.Index>
-Constructor RangeReplaceableSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<RangeReplaceableSlice.Index>
-Constructor Slice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<Slice.Index>
-Constructor String.init(stringInterpolationSegment:) has 1st parameter type change from String to T
+Constructor AnyIterator.init(_:) has parameter 0 type change from () -> Element? to () -> AnyIterator.Element?
+Constructor BidirectionalSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<BidirectionalSlice.Index>
+Constructor MutableBidirectionalSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<MutableBidirectionalSlice.Index>
+Constructor MutableRandomAccessSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<MutableRandomAccessSlice.Index>
+Constructor MutableRangeReplaceableBidirectionalSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<MutableRangeReplaceableBidirectionalSlice.Index>
+Constructor MutableRangeReplaceableRandomAccessSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<MutableRangeReplaceableRandomAccessSlice.Index>
+Constructor MutableRangeReplaceableSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<MutableRangeReplaceableSlice.Index>
+Constructor MutableSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<MutableSlice.Index>
+Constructor RandomAccessSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<RandomAccessSlice.Index>
+Constructor RangeReplaceableBidirectionalSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<RangeReplaceableBidirectionalSlice.Index>
+Constructor RangeReplaceableRandomAccessSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<RangeReplaceableRandomAccessSlice.Index>
+Constructor RangeReplaceableSlice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<RangeReplaceableSlice.Index>
+Constructor Slice.init(base:bounds:) has parameter 1 type change from Range<Base.Index> to Range<Slice.Index>
+Constructor String.init(stringInterpolationSegment:) has parameter 0 type change from String to T
Func AnyBidirectionalCollection.makeIterator() has return type change from AnyIterator<Element> to AnyBidirectionalCollection.Iterator
Func AnyCollection.makeIterator() has return type change from AnyIterator<Element> to AnyCollection.Iterator
Func AnyRandomAccessCollection.makeIterator() has return type change from AnyIterator<Element> to AnyRandomAccessCollection.Iterator
@@ -73,30 +73,30 @@
Func FlattenBidirectionalCollection.index(after:) has return type change from FlattenBidirectionalCollectionIndex<Base> to FlattenBidirectionalCollection.Index
Func FlattenBidirectionalCollection.index(before:) has return type change from FlattenBidirectionalCollectionIndex<Base> to FlattenBidirectionalCollection.Index
Func FlattenCollection.index(after:) has return type change from FlattenCollectionIndex<Base> to FlattenCollection.Index
-Func LazyBidirectionalCollection.distance(from:to:) has 1st parameter type change from Base.Index to LazyBidirectionalCollection.Index
+Func LazyBidirectionalCollection.distance(from:to:) has parameter 0 type change from Base.Index to LazyBidirectionalCollection.Index
Func LazyBidirectionalCollection.index(_:offsetBy:) has return type change from Base.Index to LazyBidirectionalCollection.Index
Func LazyBidirectionalCollection.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to LazyBidirectionalCollection.Index?
-Func LazyCollection.distance(from:to:) has 1st parameter type change from Base.Index to LazyCollection.Index
+Func LazyCollection.distance(from:to:) has parameter 0 type change from Base.Index to LazyCollection.Index
Func LazyCollection.index(_:offsetBy:) has return type change from Base.Index to LazyCollection.Index
Func LazyCollection.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to LazyCollection.Index?
Func LazyFilterBidirectionalCollection.index(after:) has return type change from LazyFilterIndex<Base> to LazyFilterBidirectionalCollection.Index
Func LazyFilterBidirectionalCollection.index(before:) has return type change from LazyFilterIndex<Base> to LazyFilterBidirectionalCollection.Index
Func LazyFilterCollection.index(after:) has return type change from LazyFilterIndex<Base> to LazyFilterCollection.Index
-Func LazyMapBidirectionalCollection.distance(from:to:) has 1st parameter type change from Base.Index to LazyMapBidirectionalCollection.Index
+Func LazyMapBidirectionalCollection.distance(from:to:) has parameter 0 type change from Base.Index to LazyMapBidirectionalCollection.Index
Func LazyMapBidirectionalCollection.index(_:offsetBy:) has return type change from Base.Index to LazyMapBidirectionalCollection.Index
Func LazyMapBidirectionalCollection.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to LazyMapBidirectionalCollection.Index?
Func LazyMapBidirectionalCollection.index(after:) has return type change from Base.Index to LazyMapBidirectionalCollection.Index
Func LazyMapBidirectionalCollection.index(before:) has return type change from Base.Index to LazyMapBidirectionalCollection.Index
-Func LazyMapCollection.distance(from:to:) has 1st parameter type change from Base.Index to LazyMapCollection.Index
+Func LazyMapCollection.distance(from:to:) has parameter 0 type change from Base.Index to LazyMapCollection.Index
Func LazyMapCollection.index(_:offsetBy:) has return type change from Base.Index to LazyMapCollection.Index
Func LazyMapCollection.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to LazyMapCollection.Index?
Func LazyMapCollection.index(after:) has return type change from Base.Index to LazyMapCollection.Index
-Func LazyMapRandomAccessCollection.distance(from:to:) has 1st parameter type change from Base.Index to LazyMapRandomAccessCollection.Index
+Func LazyMapRandomAccessCollection.distance(from:to:) has parameter 0 type change from Base.Index to LazyMapRandomAccessCollection.Index
Func LazyMapRandomAccessCollection.index(_:offsetBy:) has return type change from Base.Index to LazyMapRandomAccessCollection.Index
Func LazyMapRandomAccessCollection.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to LazyMapRandomAccessCollection.Index?
Func LazyMapRandomAccessCollection.index(after:) has return type change from Base.Index to LazyMapRandomAccessCollection.Index
Func LazyMapRandomAccessCollection.index(before:) has return type change from Base.Index to LazyMapRandomAccessCollection.Index
-Func LazyRandomAccessCollection.distance(from:to:) has 1st parameter type change from Base.Index to LazyRandomAccessCollection.Index
+Func LazyRandomAccessCollection.distance(from:to:) has parameter 0 type change from Base.Index to LazyRandomAccessCollection.Index
Func LazyRandomAccessCollection.index(_:offsetBy:) has return type change from Base.Index to LazyRandomAccessCollection.Index
Func LazyRandomAccessCollection.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to LazyRandomAccessCollection.Index?
Func MutableBidirectionalSlice.distance(from:to:) has return type change from Base.IndexDistance to MutableBidirectionalSlice.IndexDistance
@@ -114,30 +114,30 @@
Func MutableRangeReplaceableBidirectionalSlice.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to MutableRangeReplaceableBidirectionalSlice.Index?
Func MutableRangeReplaceableBidirectionalSlice.index(after:) has return type change from Base.Index to MutableRangeReplaceableBidirectionalSlice.Index
Func MutableRangeReplaceableBidirectionalSlice.index(before:) has return type change from Base.Index to MutableRangeReplaceableBidirectionalSlice.Index
-Func MutableRangeReplaceableBidirectionalSlice.insert(_:at:) has 2nd parameter type change from Base.Index to MutableRangeReplaceableBidirectionalSlice.Index
-Func MutableRangeReplaceableBidirectionalSlice.insert(contentsOf:at:) has 2nd parameter type change from Base.Index to MutableRangeReplaceableBidirectionalSlice.Index
-Func MutableRangeReplaceableBidirectionalSlice.remove(at:) has 1st parameter type change from Base.Index to MutableRangeReplaceableBidirectionalSlice.Index
-Func MutableRangeReplaceableBidirectionalSlice.removeSubrange(_:) has 1st parameter type change from Range<Base.Index> to Range<MutableRangeReplaceableBidirectionalSlice.Index>
-Func MutableRangeReplaceableBidirectionalSlice.replaceSubrange(_:with:) has 1st parameter type change from Range<Base.Index> to Range<MutableRangeReplaceableBidirectionalSlice.Index>
+Func MutableRangeReplaceableBidirectionalSlice.insert(_:at:) has parameter 1 type change from Base.Index to MutableRangeReplaceableBidirectionalSlice.Index
+Func MutableRangeReplaceableBidirectionalSlice.insert(contentsOf:at:) has parameter 1 type change from Base.Index to MutableRangeReplaceableBidirectionalSlice.Index
+Func MutableRangeReplaceableBidirectionalSlice.remove(at:) has parameter 0 type change from Base.Index to MutableRangeReplaceableBidirectionalSlice.Index
+Func MutableRangeReplaceableBidirectionalSlice.removeSubrange(_:) has parameter 0 type change from Range<Base.Index> to Range<MutableRangeReplaceableBidirectionalSlice.Index>
+Func MutableRangeReplaceableBidirectionalSlice.replaceSubrange(_:with:) has parameter 0 type change from Range<Base.Index> to Range<MutableRangeReplaceableBidirectionalSlice.Index>
Func MutableRangeReplaceableRandomAccessSlice.distance(from:to:) has return type change from Base.IndexDistance to MutableRangeReplaceableRandomAccessSlice.IndexDistance
Func MutableRangeReplaceableRandomAccessSlice.index(_:offsetBy:) has return type change from Base.Index to MutableRangeReplaceableRandomAccessSlice.Index
Func MutableRangeReplaceableRandomAccessSlice.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to MutableRangeReplaceableRandomAccessSlice.Index?
Func MutableRangeReplaceableRandomAccessSlice.index(after:) has return type change from Base.Index to MutableRangeReplaceableRandomAccessSlice.Index
Func MutableRangeReplaceableRandomAccessSlice.index(before:) has return type change from Base.Index to MutableRangeReplaceableRandomAccessSlice.Index
-Func MutableRangeReplaceableRandomAccessSlice.insert(_:at:) has 2nd parameter type change from Base.Index to MutableRangeReplaceableRandomAccessSlice.Index
-Func MutableRangeReplaceableRandomAccessSlice.insert(contentsOf:at:) has 2nd parameter type change from Base.Index to MutableRangeReplaceableRandomAccessSlice.Index
-Func MutableRangeReplaceableRandomAccessSlice.remove(at:) has 1st parameter type change from Base.Index to MutableRangeReplaceableRandomAccessSlice.Index
-Func MutableRangeReplaceableRandomAccessSlice.removeSubrange(_:) has 1st parameter type change from Range<Base.Index> to Range<MutableRangeReplaceableRandomAccessSlice.Index>
-Func MutableRangeReplaceableRandomAccessSlice.replaceSubrange(_:with:) has 1st parameter type change from Range<Base.Index> to Range<MutableRangeReplaceableRandomAccessSlice.Index>
+Func MutableRangeReplaceableRandomAccessSlice.insert(_:at:) has parameter 1 type change from Base.Index to MutableRangeReplaceableRandomAccessSlice.Index
+Func MutableRangeReplaceableRandomAccessSlice.insert(contentsOf:at:) has parameter 1 type change from Base.Index to MutableRangeReplaceableRandomAccessSlice.Index
+Func MutableRangeReplaceableRandomAccessSlice.remove(at:) has parameter 0 type change from Base.Index to MutableRangeReplaceableRandomAccessSlice.Index
+Func MutableRangeReplaceableRandomAccessSlice.removeSubrange(_:) has parameter 0 type change from Range<Base.Index> to Range<MutableRangeReplaceableRandomAccessSlice.Index>
+Func MutableRangeReplaceableRandomAccessSlice.replaceSubrange(_:with:) has parameter 0 type change from Range<Base.Index> to Range<MutableRangeReplaceableRandomAccessSlice.Index>
Func MutableRangeReplaceableSlice.distance(from:to:) has return type change from Base.IndexDistance to MutableRangeReplaceableSlice.IndexDistance
Func MutableRangeReplaceableSlice.index(_:offsetBy:) has return type change from Base.Index to MutableRangeReplaceableSlice.Index
Func MutableRangeReplaceableSlice.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to MutableRangeReplaceableSlice.Index?
Func MutableRangeReplaceableSlice.index(after:) has return type change from Base.Index to MutableRangeReplaceableSlice.Index
-Func MutableRangeReplaceableSlice.insert(_:at:) has 2nd parameter type change from Base.Index to MutableRangeReplaceableSlice.Index
-Func MutableRangeReplaceableSlice.insert(contentsOf:at:) has 2nd parameter type change from Base.Index to MutableRangeReplaceableSlice.Index
-Func MutableRangeReplaceableSlice.remove(at:) has 1st parameter type change from Base.Index to MutableRangeReplaceableSlice.Index
-Func MutableRangeReplaceableSlice.removeSubrange(_:) has 1st parameter type change from Range<Base.Index> to Range<MutableRangeReplaceableSlice.Index>
-Func MutableRangeReplaceableSlice.replaceSubrange(_:with:) has 1st parameter type change from Range<Base.Index> to Range<MutableRangeReplaceableSlice.Index>
+Func MutableRangeReplaceableSlice.insert(_:at:) has parameter 1 type change from Base.Index to MutableRangeReplaceableSlice.Index
+Func MutableRangeReplaceableSlice.insert(contentsOf:at:) has parameter 1 type change from Base.Index to MutableRangeReplaceableSlice.Index
+Func MutableRangeReplaceableSlice.remove(at:) has parameter 0 type change from Base.Index to MutableRangeReplaceableSlice.Index
+Func MutableRangeReplaceableSlice.removeSubrange(_:) has parameter 0 type change from Range<Base.Index> to Range<MutableRangeReplaceableSlice.Index>
+Func MutableRangeReplaceableSlice.replaceSubrange(_:with:) has parameter 0 type change from Range<Base.Index> to Range<MutableRangeReplaceableSlice.Index>
Func MutableSlice.distance(from:to:) has return type change from Base.IndexDistance to MutableSlice.IndexDistance
Func MutableSlice.index(_:offsetBy:) has return type change from Base.Index to MutableSlice.Index
Func MutableSlice.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to MutableSlice.Index?
@@ -146,7 +146,7 @@
Func OptionSet.remove(_:) has return type change from Self? to Self.Element?
Func OptionSet.update(with:) has return type change from Self? to Self.Element?
Func RandomAccessCollection.distance(from:to:) has return type change from Self.IndexDistance to Self.Index.Stride
-Func RandomAccessCollection.index(_:offsetBy:) has 2nd parameter type change from Self.IndexDistance to Self.Index.Stride
+Func RandomAccessCollection.index(_:offsetBy:) has parameter 1 type change from Self.IndexDistance to Self.Index.Stride
Func RandomAccessSlice.distance(from:to:) has return type change from Base.IndexDistance to RandomAccessSlice.IndexDistance
Func RandomAccessSlice.index(_:offsetBy:) has return type change from Base.Index to RandomAccessSlice.Index
Func RandomAccessSlice.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to RandomAccessSlice.Index?
@@ -157,30 +157,30 @@
Func RangeReplaceableBidirectionalSlice.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to RangeReplaceableBidirectionalSlice.Index?
Func RangeReplaceableBidirectionalSlice.index(after:) has return type change from Base.Index to RangeReplaceableBidirectionalSlice.Index
Func RangeReplaceableBidirectionalSlice.index(before:) has return type change from Base.Index to RangeReplaceableBidirectionalSlice.Index
-Func RangeReplaceableBidirectionalSlice.insert(_:at:) has 2nd parameter type change from Base.Index to RangeReplaceableBidirectionalSlice.Index
-Func RangeReplaceableBidirectionalSlice.insert(contentsOf:at:) has 2nd parameter type change from Base.Index to RangeReplaceableBidirectionalSlice.Index
-Func RangeReplaceableBidirectionalSlice.remove(at:) has 1st parameter type change from Base.Index to RangeReplaceableBidirectionalSlice.Index
-Func RangeReplaceableBidirectionalSlice.removeSubrange(_:) has 1st parameter type change from Range<Base.Index> to Range<RangeReplaceableBidirectionalSlice.Index>
-Func RangeReplaceableBidirectionalSlice.replaceSubrange(_:with:) has 1st parameter type change from Range<Base.Index> to Range<RangeReplaceableBidirectionalSlice.Index>
+Func RangeReplaceableBidirectionalSlice.insert(_:at:) has parameter 1 type change from Base.Index to RangeReplaceableBidirectionalSlice.Index
+Func RangeReplaceableBidirectionalSlice.insert(contentsOf:at:) has parameter 1 type change from Base.Index to RangeReplaceableBidirectionalSlice.Index
+Func RangeReplaceableBidirectionalSlice.remove(at:) has parameter 0 type change from Base.Index to RangeReplaceableBidirectionalSlice.Index
+Func RangeReplaceableBidirectionalSlice.removeSubrange(_:) has parameter 0 type change from Range<Base.Index> to Range<RangeReplaceableBidirectionalSlice.Index>
+Func RangeReplaceableBidirectionalSlice.replaceSubrange(_:with:) has parameter 0 type change from Range<Base.Index> to Range<RangeReplaceableBidirectionalSlice.Index>
Func RangeReplaceableRandomAccessSlice.distance(from:to:) has return type change from Base.IndexDistance to RangeReplaceableRandomAccessSlice.IndexDistance
Func RangeReplaceableRandomAccessSlice.index(_:offsetBy:) has return type change from Base.Index to RangeReplaceableRandomAccessSlice.Index
Func RangeReplaceableRandomAccessSlice.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to RangeReplaceableRandomAccessSlice.Index?
Func RangeReplaceableRandomAccessSlice.index(after:) has return type change from Base.Index to RangeReplaceableRandomAccessSlice.Index
Func RangeReplaceableRandomAccessSlice.index(before:) has return type change from Base.Index to RangeReplaceableRandomAccessSlice.Index
-Func RangeReplaceableRandomAccessSlice.insert(_:at:) has 2nd parameter type change from Base.Index to RangeReplaceableRandomAccessSlice.Index
-Func RangeReplaceableRandomAccessSlice.insert(contentsOf:at:) has 2nd parameter type change from Base.Index to RangeReplaceableRandomAccessSlice.Index
-Func RangeReplaceableRandomAccessSlice.remove(at:) has 1st parameter type change from Base.Index to RangeReplaceableRandomAccessSlice.Index
-Func RangeReplaceableRandomAccessSlice.removeSubrange(_:) has 1st parameter type change from Range<Base.Index> to Range<RangeReplaceableRandomAccessSlice.Index>
-Func RangeReplaceableRandomAccessSlice.replaceSubrange(_:with:) has 1st parameter type change from Range<Base.Index> to Range<RangeReplaceableRandomAccessSlice.Index>
+Func RangeReplaceableRandomAccessSlice.insert(_:at:) has parameter 1 type change from Base.Index to RangeReplaceableRandomAccessSlice.Index
+Func RangeReplaceableRandomAccessSlice.insert(contentsOf:at:) has parameter 1 type change from Base.Index to RangeReplaceableRandomAccessSlice.Index
+Func RangeReplaceableRandomAccessSlice.remove(at:) has parameter 0 type change from Base.Index to RangeReplaceableRandomAccessSlice.Index
+Func RangeReplaceableRandomAccessSlice.removeSubrange(_:) has parameter 0 type change from Range<Base.Index> to Range<RangeReplaceableRandomAccessSlice.Index>
+Func RangeReplaceableRandomAccessSlice.replaceSubrange(_:with:) has parameter 0 type change from Range<Base.Index> to Range<RangeReplaceableRandomAccessSlice.Index>
Func RangeReplaceableSlice.distance(from:to:) has return type change from Base.IndexDistance to RangeReplaceableSlice.IndexDistance
Func RangeReplaceableSlice.index(_:offsetBy:) has return type change from Base.Index to RangeReplaceableSlice.Index
Func RangeReplaceableSlice.index(_:offsetBy:limitedBy:) has return type change from Base.Index? to RangeReplaceableSlice.Index?
Func RangeReplaceableSlice.index(after:) has return type change from Base.Index to RangeReplaceableSlice.Index
-Func RangeReplaceableSlice.insert(_:at:) has 2nd parameter type change from Base.Index to RangeReplaceableSlice.Index
-Func RangeReplaceableSlice.insert(contentsOf:at:) has 2nd parameter type change from Base.Index to RangeReplaceableSlice.Index
-Func RangeReplaceableSlice.remove(at:) has 1st parameter type change from Base.Index to RangeReplaceableSlice.Index
-Func RangeReplaceableSlice.removeSubrange(_:) has 1st parameter type change from Range<Base.Index> to Range<RangeReplaceableSlice.Index>
-Func RangeReplaceableSlice.replaceSubrange(_:with:) has 1st parameter type change from Range<Base.Index> to Range<RangeReplaceableSlice.Index>
+Func RangeReplaceableSlice.insert(_:at:) has parameter 1 type change from Base.Index to RangeReplaceableSlice.Index
+Func RangeReplaceableSlice.insert(contentsOf:at:) has parameter 1 type change from Base.Index to RangeReplaceableSlice.Index
+Func RangeReplaceableSlice.remove(at:) has parameter 0 type change from Base.Index to RangeReplaceableSlice.Index
+Func RangeReplaceableSlice.removeSubrange(_:) has parameter 0 type change from Range<Base.Index> to Range<RangeReplaceableSlice.Index>
+Func RangeReplaceableSlice.replaceSubrange(_:with:) has parameter 0 type change from Range<Base.Index> to Range<RangeReplaceableSlice.Index>
Func ReversedCollection.distance(from:to:) has return type change from Base.IndexDistance to ReversedCollection.IndexDistance
Func ReversedCollection.index(_:offsetBy:) has return type change from ReversedIndex<Base> to ReversedCollection.Index
Func ReversedCollection.index(_:offsetBy:limitedBy:) has return type change from ReversedIndex<Base>? to ReversedCollection.Index?
@@ -191,19 +191,19 @@
Func ReversedRandomAccessCollection.index(_:offsetBy:limitedBy:) has return type change from ReversedRandomAccessIndex<Base>? to ReversedRandomAccessCollection.Index?
Func ReversedRandomAccessCollection.index(after:) has return type change from ReversedRandomAccessIndex<Base> to ReversedRandomAccessCollection.Index
Func ReversedRandomAccessCollection.index(before:) has return type change from ReversedRandomAccessIndex<Base> to ReversedRandomAccessCollection.Index
-Func Set.formSymmetricDifference(_:) has 1st parameter type change from Set<Element> to Set<Set.Element>
+Func Set.formSymmetricDifference(_:) has parameter 0 type change from Set<Element> to Set<Set.Element>
Func Set.index(after:) has return type change from SetIndex<Element> to Set<Element>.Index
Func Set.index(of:) has return type change from SetIndex<Element>? to Set<Element>.Index?
Func Set.intersection(_:) has return type change from Set<Element> to Set<Set.Element>
-Func Set.isDisjoint(with:) has 1st parameter type change from Set<Element> to Set<Set.Element>
-Func Set.isStrictSubset(of:) has 1st parameter type change from Set<Element> to Set<Set.Element>
-Func Set.isStrictSuperset(of:) has 1st parameter type change from Set<Element> to Set<Set.Element>
-Func Set.isSubset(of:) has 1st parameter type change from Set<Element> to Set<Set.Element>
-Func Set.isSuperset(of:) has 1st parameter type change from Set<Element> to Set<Set.Element>
+Func Set.isDisjoint(with:) has parameter 0 type change from Set<Element> to Set<Set.Element>
+Func Set.isStrictSubset(of:) has parameter 0 type change from Set<Element> to Set<Set.Element>
+Func Set.isStrictSuperset(of:) has parameter 0 type change from Set<Element> to Set<Set.Element>
+Func Set.isSubset(of:) has parameter 0 type change from Set<Element> to Set<Set.Element>
+Func Set.isSuperset(of:) has parameter 0 type change from Set<Element> to Set<Set.Element>
Func Set.popFirst() has return type change from Element? to Set.Element?
-Func Set.remove(at:) has 1st parameter type change from SetIndex<Element> to Set<Element>.Index
+Func Set.remove(at:) has parameter 0 type change from SetIndex<Element> to Set<Element>.Index
Func Set.removeFirst() has return type change from Element to Set.Element
-Func Set.subtract(_:) has 1st parameter type change from Set<Element> to Set<Set.Element>
+Func Set.subtract(_:) has parameter 0 type change from Set<Element> to Set<Set.Element>
Func Set.subtracting(_:) has return type change from Set<Element> to Set<Set.Element>
Func Set.symmetricDifference(_:) has return type change from Set<Element> to Set<Set.Element>
Func Set.union(_:) has return type change from Set<Element> to Set<Set.Element>
@@ -213,7 +213,7 @@
Func Slice.index(after:) has return type change from Base.Index to Slice.Index
/* Function type change */
-Func UnsafePointer.withMemoryRebound(to:capacity:_:) has 3rd parameter type change from (UnsafeMutablePointer<T>) throws -> Result to (UnsafePointer<T>) throws -> Result
+Func UnsafePointer.withMemoryRebound(to:capacity:_:) has parameter 2 type change from (UnsafeMutablePointer<T>) throws -> Result to (UnsafePointer<T>) throws -> Result
/* FIXME: Bogus */
Func Zip2Iterator.next() has return type change from (Iterator1.Element, Iterator2.Element)? to Zip2Iterator.Element?
diff --git a/test/attr/attr_availability_narrow.swift b/test/attr/attr_availability_narrow.swift
index 1dee604..836c504 100644
--- a/test/attr/attr_availability_narrow.swift
+++ b/test/attr/attr_availability_narrow.swift
@@ -32,10 +32,10 @@
}
func useFooWayOff() {
+ // expected-note@-1{{add @available attribute to enclosing global function}}
if #available(OSX 10.10, *) {
foo() // expected-error {{'foo()' is only available on OS X 10.12.2 or newer}}
- // expected-note@-1{{add @available attribute to enclosing global function}}
- // expected-note@-2{{add 'if #available' version check}}
+ // expected-note@-1{{add 'if #available' version check}}
}
}
diff --git a/test/decl/protocol/conforms/fixit_stub.swift b/test/decl/protocol/conforms/fixit_stub.swift
index 6fd9a29..95b82c0 100644
--- a/test/decl/protocol/conforms/fixit_stub.swift
+++ b/test/decl/protocol/conforms/fixit_stub.swift
@@ -1,14 +1,14 @@
// RUN: %target-typecheck-verify-swift
protocol Protocol1 {
- func foo(arg1: Int, arg2: String) -> String // expected-note{{protocol requires function 'foo(arg1:arg2:)' with type '(Int, String) -> String'; do you want to add a stub?}} {{27-27=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n}}
- func bar() throws -> String // expected-note{{protocol requires function 'bar()' with type '() throws -> String'; do you want to add a stub?}} {{27-27=\n func bar() throws -> String {\n <#code#>\n \}\n}}
- func generic<T>(t: T) // expected-note{{protocol requires function 'generic(t:)' with type '<T> (t: T) -> ()'; do you want to add a stub?}} {{27-27=\n func generic<T>(t: T) {\n <#code#>\n \}\n}}
- init(arg: Int) // expected-note{{protocol requires initializer 'init(arg:)' with type '(arg: Int)'; do you want to add a stub?}} {{27-27=\n required init(arg: Int) {\n <#code#>\n \}\n}}
- var baz: Int { get } // expected-note{{protocol requires property 'baz' with type 'Int'; do you want to add a stub?}} {{27-27=\n var baz: Int\n}}
- var baz2: Int { get set } // expected-note{{protocol requires property 'baz2' with type 'Int'; do you want to add a stub?}} {{27-27=\n var baz2: Int\n}}
- subscript(arg: Int) -> String { get } //expected-note{{rotocol requires subscript with type '(Int) -> String'; do you want to add a stub?}} {{27-27=\n subscript(arg: Int) -> String {\n <#code#>\n \}\n}}
- subscript(arg1: Int, arg2: Int) -> String { get set } //expected-note{{protocol requires subscript with type '(Int, Int) -> String'; do you want to add a stub?}} {{27-27=\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ func foo(arg1: Int, arg2: String) -> String // expected-note{{protocol requires function 'foo(arg1:arg2:)' with type '(Int, String) -> String'; do you want to add a stub?}} {{27-27=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n func generic<T>(t: T) {\n <#code#>\n \}\n\n required init(arg: Int) {\n <#code#>\n \}\n\n var baz: Int\n\n var baz2: Int\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ func bar() throws -> String // expected-note{{protocol requires function 'bar()' with type '() throws -> String'; do you want to add a stub?}} {{27-27=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n func generic<T>(t: T) {\n <#code#>\n \}\n\n required init(arg: Int) {\n <#code#>\n \}\n\n var baz: Int\n\n var baz2: Int\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ func generic<T>(t: T) // expected-note{{protocol requires function 'generic(t:)' with type '<T> (t: T) -> ()'; do you want to add a stub?}} {{27-27=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n func generic<T>(t: T) {\n <#code#>\n \}\n\n required init(arg: Int) {\n <#code#>\n \}\n\n var baz: Int\n\n var baz2: Int\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ init(arg: Int) // expected-note{{protocol requires initializer 'init(arg:)' with type '(arg: Int)'; do you want to add a stub?}} {{27-27=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n func generic<T>(t: T) {\n <#code#>\n \}\n\n required init(arg: Int) {\n <#code#>\n \}\n\n var baz: Int\n\n var baz2: Int\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ var baz: Int { get } // expected-note{{protocol requires property 'baz' with type 'Int'; do you want to add a stub?}} {{27-27=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n func generic<T>(t: T) {\n <#code#>\n \}\n\n required init(arg: Int) {\n <#code#>\n \}\n\n var baz: Int\n\n var baz2: Int\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ var baz2: Int { get set } // expected-note{{protocol requires property 'baz2' with type 'Int'; do you want to add a stub?}} {{27-27=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n func generic<T>(t: T) {\n <#code#>\n \}\n\n required init(arg: Int) {\n <#code#>\n \}\n\n var baz: Int\n\n var baz2: Int\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ subscript(arg: Int) -> String { get } //expected-note{{rotocol requires subscript with type '(Int) -> String'; do you want to add a stub?}} {{27-27=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n func generic<T>(t: T) {\n <#code#>\n \}\n\n required init(arg: Int) {\n <#code#>\n \}\n\n var baz: Int\n\n var baz2: Int\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ subscript(arg1: Int, arg2: Int) -> String { get set } //expected-note{{protocol requires subscript with type '(Int, Int) -> String'; do you want to add a stub?}} {{27-27=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n func generic<T>(t: T) {\n <#code#>\n \}\n\n required init(arg: Int) {\n <#code#>\n \}\n\n var baz: Int\n\n var baz2: Int\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
}
class Adopter: Protocol1 { // expected-error{{type 'Adopter' does not conform to protocol 'Protocol1'}} expected-note{{candidate has non-matching type '()'}}
@@ -17,13 +17,13 @@
protocol Protocol2 {
- func foo(arg1: Int, arg2: String) -> String // expected-note{{protocol requires function 'foo(arg1:arg2:)' with type '(Int, String) -> String'; do you want to add a stub?}} {{32-32=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n}}
- func bar() throws -> String // expected-note{{protocol requires function 'bar()' with type '() throws -> String'; do you want to add a stub?}} {{32-32=\n func bar() throws -> String {\n <#code#>\n \}\n}}
+ func foo(arg1: Int, arg2: String) -> String // expected-note{{protocol requires function 'foo(arg1:arg2:)' with type '(Int, String) -> String'; do you want to add a stub?}} {{32-32=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n var baz: Int {\n <#code#>\n \}\n\n var baz2: Int {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ func bar() throws -> String // expected-note{{protocol requires function 'bar()' with type '() throws -> String'; do you want to add a stub?}} {{32-32=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n var baz: Int {\n <#code#>\n \}\n\n var baz2: Int {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
init(arg: Int) // expected-note{{protocol requires initializer 'init(arg:)' with type '(arg: Int)'}} {{none}}
- var baz: Int { get } // expected-note{{protocol requires property 'baz' with type 'Int'; do you want to add a stub?}} {{32-32=\n var baz: Int {\n <#code#>\n \}\n}}
- var baz2: Int { get set } // expected-note{{protocol requires property 'baz2' with type 'Int'; do you want to add a stub?}} {{32-32=\n var baz2: Int {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
- subscript(arg: Int) -> String { get } //expected-note{{rotocol requires subscript with type '(Int) -> String'; do you want to add a stub?}} {{32-32=\n subscript(arg: Int) -> String {\n <#code#>\n \}\n}}
- subscript(arg1: Int, arg2: Int) -> String { get set } //expected-note{{protocol requires subscript with type '(Int, Int) -> String'; do you want to add a stub?}} {{32-32=\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ var baz: Int { get } // expected-note{{protocol requires property 'baz' with type 'Int'; do you want to add a stub?}} {{32-32=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n var baz: Int {\n <#code#>\n \}\n\n var baz2: Int {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ var baz2: Int { get set } // expected-note{{protocol requires property 'baz2' with type 'Int'; do you want to add a stub?}} {{32-32=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n var baz: Int {\n <#code#>\n \}\n\n var baz2: Int {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ subscript(arg: Int) -> String { get } //expected-note{{rotocol requires subscript with type '(Int) -> String'; do you want to add a stub?}} {{32-32=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n var baz: Int {\n <#code#>\n \}\n\n var baz2: Int {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
+ subscript(arg1: Int, arg2: Int) -> String { get set } //expected-note{{protocol requires subscript with type '(Int, Int) -> String'; do you want to add a stub?}} {{32-32=\n func foo(arg1: Int, arg2: String) -> String {\n <#code#>\n \}\n\n func bar() throws -> String {\n <#code#>\n \}\n\n var baz: Int {\n <#code#>\n \}\n\n var baz2: Int {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n\n subscript(arg: Int) -> String {\n <#code#>\n \}\n\n subscript(arg1: Int, arg2: Int) -> String {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}}
}
class Adopter2 {} // expected-note{{candidate has non-matching type '()'}}
@@ -55,8 +55,8 @@
protocol ProtocolWithSelfRequirement {
- func foo() -> Self // expected-note{{protocol requires function 'foo()' with type '() -> Adopter5'; do you want to add a stub?}} {{47-47=\n func foo() -> Adopter5 {\n <#code#>\n \}\n}}
- func foo(lhs: Self, rhs: Self) -> Self //expected-note{{protocol requires function 'foo(lhs:rhs:)' with type '(Adopter5, Adopter5) -> Adopter5'; do you want to add a stub?}} {{47-47=\n func foo(lhs: Adopter5, rhs: Adopter5) -> Adopter5 {\n <#code#>\n \}\n}}
+ func foo() -> Self // expected-note{{protocol requires function 'foo()' with type '() -> Adopter5'; do you want to add a stub?}} {{47-47=\n func foo() -> Adopter5 {\n <#code#>\n \}\n\n func foo(lhs: Adopter5, rhs: Adopter5) -> Adopter5 {\n <#code#>\n \}\n}}
+ func foo(lhs: Self, rhs: Self) -> Self //expected-note{{protocol requires function 'foo(lhs:rhs:)' with type '(Adopter5, Adopter5) -> Adopter5'; do you want to add a stub?}} {{47-47=\n func foo() -> Adopter5 {\n <#code#>\n \}\n\n func foo(lhs: Adopter5, rhs: Adopter5) -> Adopter5 {\n <#code#>\n \}\n}}
}
struct Adopter5: ProtocolWithSelfRequirement { //expected-error{{type 'Adopter5' does not conform to protocol 'ProtocolWithSelfRequirement'}}
@@ -65,8 +65,8 @@
protocol ProtocolWithSelfRequirement2 {
- func foo() -> Self // expected-note{{protocol requires function 'foo()' with type '() -> Adopter6'; do you want to add a stub?}} {{51-51=\n func foo() -> Adopter6 {\n <#code#>\n \}\n}}
- func foo(lhs: Self, rhs: Self) -> Self //expected-note{{protocol requires function 'foo(lhs:rhs:)' with type '(Adopter6, Adopter6) -> Adopter6'; do you want to add a stub?}} {{51-51=\n func foo(lhs: Adopter6, rhs: Adopter6) -> Adopter6 {\n <#code#>\n \}\n}}
+ func foo() -> Self // expected-note{{protocol requires function 'foo()' with type '() -> Adopter6'; do you want to add a stub?}} {{51-51=\n func foo() -> Adopter6 {\n <#code#>\n \}\n\n func foo(lhs: Adopter6, rhs: Adopter6) -> Adopter6 {\n <#code#>\n \}\n}}
+ func foo(lhs: Self, rhs: Self) -> Self //expected-note{{protocol requires function 'foo(lhs:rhs:)' with type '(Adopter6, Adopter6) -> Adopter6'; do you want to add a stub?}} {{51-51=\n func foo() -> Adopter6 {\n <#code#>\n \}\n\n func foo(lhs: Adopter6, rhs: Adopter6) -> Adopter6 {\n <#code#>\n \}\n}}
}
struct Adopter6 {}
@@ -76,8 +76,8 @@
protocol ProtocolWithSelfRequirement3 {
- func foo() -> Self // expected-note{{protocol requires function 'foo()' with type '() -> Self'; do you want to add a stub?}} {{47-47=\n func foo() -> Self {\n <#code#>\n \}\n}}
- func foo(lhs: Self, rhs: Self) -> Self //expected-note{{protocol requires function 'foo(lhs:rhs:)' with type '(Adopter7, Adopter7) -> Self'; do you want to add a stub?}} {{47-47=\n func foo(lhs: Adopter7, rhs: Adopter7) -> Self {\n <#code#>\n \}\n}}
+ func foo() -> Self // expected-note{{protocol requires function 'foo()' with type '() -> Self'; do you want to add a stub?}} {{47-47=\n func foo() -> Self {\n <#code#>\n \}\n\n func foo(lhs: Adopter7, rhs: Adopter7) -> Self {\n <#code#>\n \}\n}}
+ func foo(lhs: Self, rhs: Self) -> Self //expected-note{{protocol requires function 'foo(lhs:rhs:)' with type '(Adopter7, Adopter7) -> Self'; do you want to add a stub?}} {{47-47=\n func foo() -> Self {\n <#code#>\n \}\n\n func foo(lhs: Adopter7, rhs: Adopter7) -> Self {\n <#code#>\n \}\n}}
}
class Adopter7: ProtocolWithSelfRequirement3 { //expected-error{{type 'Adopter7' does not conform to protocol 'ProtocolWithSelfRequirement3'}}
diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift
index f82826b..5a188c7 100644
--- a/test/decl/protocol/protocols.swift
+++ b/test/decl/protocol/protocols.swift
@@ -422,7 +422,7 @@
struct X3<T : P1> where T.Assoc : P2 {}
struct X4 : P1 { // expected-error{{type 'X4' does not conform to protocol 'P1'}}
- func getX1() -> X3<X4> { return X3() } // expected-error{{cannot convert return expression of type 'X3<_>' to return type 'X3<X4>'}}
+ func getX1() -> X3<X4> { return X3() }
}
protocol ShouldntCrash {
diff --git a/test/lit.cfg b/test/lit.cfg
index dd05346..a08a49e 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -1079,3 +1079,5 @@
# finishSwigPythonLLDB.py in the lldb repo
python_lib_dir = get_python_lib(True, False, config.lldb_build_root)
config.substitutions.append(('%lldb-python-path', python_lib_dir))
+
+lit_config.note("Available features: " + ", ".join(config.available_features))
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index 7c22c6f..d51b958 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -737,16 +737,10 @@
unsigned Index) {
if (Index == 0) {
return Ctx.buffer("return");
- } else if (Index == 1) {
- return Ctx.buffer("1st parameter");
- } else if (Index == 2) {
- return Ctx.buffer("2nd parameter");
- } else if (Index == 3) {
- return Ctx.buffer("3rd parameter");
} else {
llvm::SmallString<4> Buffer;
- Buffer += std::to_string(Index);
- Buffer += "th parameter";
+ Buffer += "parameter ";
+ Buffer += std::to_string(Index - 1);
return Ctx.buffer(Buffer.str());
}
}
@@ -3497,15 +3491,19 @@
options::ModuleCachePath;
if (!options::SwiftVersion.empty()) {
- if (auto Version = version::Version::
- parseVersionString(options::SwiftVersion, SourceLoc(), nullptr)) {
- if (Version.getValue().isValidEffectiveLanguageVersion())
- InitInvok.getLangOptions().EffectiveLanguageVersion = Version.getValue();
- else {
- llvm::errs() << "Unsupported Swift Version.\n";
- return 1;
+ using version::Version;
+ bool isValid = false;
+ if (auto Version = Version::parseVersionString(options::SwiftVersion,
+ SourceLoc(), nullptr)) {
+ if (auto Effective = Version.getValue().getEffectiveLanguageVersion()) {
+ InitInvok.getLangOptions().EffectiveLanguageVersion = *Effective;
+ isValid = true;
}
}
+ if (!isValid) {
+ llvm::errs() << "Unsupported Swift Version.\n";
+ return 1;
+ }
}
if (!options::ResourceDir.empty()) {
diff --git a/tools/swift-demangle/swift-demangle.cpp b/tools/swift-demangle/swift-demangle.cpp
index e4b1a3e..596fc88 100644
--- a/tools/swift-demangle/swift-demangle.cpp
+++ b/tools/swift-demangle/swift-demangle.cpp
@@ -99,8 +99,15 @@
// mangling and demangling tests.
remangled = name;
} else {
+ // Also accept the future mangling prefix.
+ // TODO: remove the "_S" as soon as MANGLING_PREFIX_STR gets "_S".
remangled = swift::Demangle::mangleNode(pointer,
- /*NewMangling*/ name.startswith(MANGLING_PREFIX_STR));
+ /*NewMangling*/ name.startswith(MANGLING_PREFIX_STR)
+ || name.startswith("_S"));
+ if (name.startswith("_S")) {
+ assert(remangled.find(MANGLING_PREFIX_STR) == 0);
+ remangled = "_S" + remangled.substr(3);
+ }
if (name != remangled) {
llvm::errs() << "\nError: re-mangled name \n " << remangled
<< "\ndoes not match original name\n " << name << '\n';
@@ -130,8 +137,19 @@
std::string cName = name.str();
if (!swift::Demangle::isSwiftSymbol(cName.c_str()))
Classifications += 'N';
- if (DCtx.isThunkSymbol(name))
- Classifications += 'T';
+ if (DCtx.isThunkSymbol(name)) {
+ if (!Classifications.empty())
+ Classifications += ',';
+ Classifications += "T:";
+ Classifications += DCtx.getThunkTarget(name);
+ } else {
+ assert(DCtx.getThunkTarget(name).empty());
+ }
+ if (pointer && !DCtx.hasSwiftCallingConvention(name)) {
+ if (!Classifications.empty())
+ Classifications += ',';
+ Classifications += 'C';
+ }
if (!Classifications.empty())
llvm::outs() << '{' << Classifications << "} ";
}
@@ -142,7 +160,9 @@
static int demangleSTDIN(const swift::Demangle::DemangleOptions &options) {
// This doesn't handle Unicode symbols, but maybe that's okay.
- llvm::Regex maybeSymbol("(_T|" MANGLING_PREFIX_STR ")[_a-zA-Z0-9$]+");
+ // Also accept the future mangling prefix.
+ // TODO: remove the "_S" as soon as MANGLING_PREFIX_STR gets "_S".
+ llvm::Regex maybeSymbol("(_T|_S|" MANGLING_PREFIX_STR ")[_a-zA-Z0-9$]+");
swift::Demangle::Context DCtx;
for (std::string mangled; std::getline(std::cin, mangled);) {
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index 00f11f4..83425c7 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -2957,7 +2957,8 @@
if (auto swiftVersion =
version::Version::parseVersionString(options::SwiftVersion,
SourceLoc(), nullptr)) {
- InitInvok.getLangOptions().EffectiveLanguageVersion = *swiftVersion;
+ if (auto actual = swiftVersion.getValue().getEffectiveLanguageVersion())
+ InitInvok.getLangOptions().EffectiveLanguageVersion = actual.getValue();
}
}
InitInvok.getClangImporterOptions().ModuleCachePath =
diff --git a/unittests/Syntax/CMakeLists.txt b/unittests/Syntax/CMakeLists.txt
index d812d93..1b9f0cf 100644
--- a/unittests/Syntax/CMakeLists.txt
+++ b/unittests/Syntax/CMakeLists.txt
@@ -4,6 +4,7 @@
GenericSyntaxTests.cpp
RawSyntaxTests.cpp
StmtSyntaxTests.cpp
+ SyntaxCollectionTests.cpp
ThreadSafeCachingTests.cpp
TriviaTests.cpp
TypeSyntaxTests.cpp
diff --git a/unittests/Syntax/DeclSyntaxTests.cpp b/unittests/Syntax/DeclSyntaxTests.cpp
index ae6d857..7640dfe 100644
--- a/unittests/Syntax/DeclSyntaxTests.cpp
+++ b/unittests/Syntax/DeclSyntaxTests.cpp
@@ -1,5 +1,7 @@
#include "swift/Syntax/SyntaxFactory.h"
#include "swift/Syntax/DeclSyntax.h"
+#include "swift/Syntax/ExprSyntax.h"
+#include "swift/Syntax/StmtSyntax.h"
#include "llvm/ADT/SmallString.h"
#include "gtest/gtest.h"
@@ -9,6 +11,63 @@
using namespace swift;
using namespace swift::syntax;
+#pragma mark - declaration-modifier
+
+DeclModifierSyntax getCannedDeclModifier() {
+ auto Private = SyntaxFactory::makeIdentifier("private", {}, {});
+ auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto Set = SyntaxFactory::makeIdentifier("set", {}, {});
+ auto RParen = SyntaxFactory::makeRightParenToken({}, {});
+ return SyntaxFactory::makeDeclModifier(Private, LParen, Set, RParen);
+}
+
+TEST(DeclSyntaxTests, DeclModifierMakeAPIs) {
+ {
+ SmallString<1> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankDeclModifier().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+ {
+ SmallString<24> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ getCannedDeclModifier().print(OS);
+ ASSERT_EQ(OS.str().str(), "private(set)");
+ }
+}
+
+TEST(DeclSyntaxTests, DeclModifierGetAPIs) {
+ auto Private = SyntaxFactory::makeIdentifier("private", {}, {});
+ auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto Set = SyntaxFactory::makeIdentifier("set", {}, {});
+ auto RParen = SyntaxFactory::makeRightParenToken({}, {});
+ auto Mod = SyntaxFactory::makeDeclModifier(Private, LParen, Set, RParen);
+
+ ASSERT_EQ(Private, Mod.getName());
+ ASSERT_EQ(LParen, Mod.getLeftParenToken());
+ ASSERT_EQ(Set, Mod.getArgument());
+ ASSERT_EQ(RParen, Mod.getRightParenToken());
+}
+
+TEST(DeclSyntaxTests, DeclModifierWithAPIs) {
+ auto Private = SyntaxFactory::makeIdentifier("private", {}, {});
+ auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto Set = SyntaxFactory::makeIdentifier("set", {}, {});
+ auto RParen = SyntaxFactory::makeRightParenToken({}, {});
+
+ SmallString<24> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankDeclModifier()
+ .withName(Private)
+ .withLeftParenToken(LParen)
+ .withArgument(Set)
+ .withRightParenToken(RParen)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "private(set)");
+}
+
+#pragma mark - typealias-decl
+
TEST(DeclSyntaxTests, TypealiasMakeAPIs) {
{
SmallString<1> Scratch;
@@ -25,8 +84,7 @@
auto ElementParam =
SyntaxFactory::makeGenericParameter("Element", {}, {});
auto LeftAngle = SyntaxFactory::makeLeftAngleToken({}, {});
- auto RightAngle =
- SyntaxFactory::makeRightAngleToken({}, { Trivia::spaces(1) });
+ auto RightAngle = SyntaxFactory::makeRightAngleToken({}, Trivia::spaces(1));
auto GenericParams = GenericParameterClauseBuilder()
.useLeftAngleBracket(LeftAngle)
.useRightAngleBracket(RightAngle)
@@ -137,3 +195,402 @@
ASSERT_EQ(OS.str().str(),
"typealias MyCollection<Element> = Array<Element>");
}
+
+#pragma mark - parameter
+
+FunctionParameterSyntax getCannedFunctionParameter() {
+ auto ExternalName = SyntaxFactory::makeIdentifier("with", {},
+ Trivia::spaces(1));
+ auto LocalName = SyntaxFactory::makeIdentifier("radius", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto Int = SyntaxFactory::makeTypeIdentifier("Int", {},
+ Trivia::spaces(1));
+ auto NoEllipsis = TokenSyntax::missingToken(tok::identifier, "...");
+ auto Equal = SyntaxFactory::makeEqualToken({}, Trivia::spaces(1));
+
+ auto Sign = SyntaxFactory::makePrefixOpereator("-", {});
+ auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
+ auto One = SyntaxFactory::makeIntegerLiteralExpr(Sign, OneDigits);
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+
+ return SyntaxFactory::makeFunctionParameter(ExternalName, LocalName, Colon,
+ Int, NoEllipsis, Equal, One,
+ Comma);
+}
+
+TEST(DeclSyntaxTests, FunctionParameterMakeAPIs) {
+ {
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ getCannedFunctionParameter().print(OS);
+ ASSERT_EQ(OS.str().str(), "with radius: Int = -1, ");
+ }
+ {
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionParameter().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+}
+
+TEST(DeclSyntaxTests, FunctionParameterGetAPIs) {
+ auto ExternalName = SyntaxFactory::makeIdentifier("with", {},
+ Trivia::spaces(1));
+ auto LocalName = SyntaxFactory::makeIdentifier("radius", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto Int = SyntaxFactory::makeTypeIdentifier("Int", {},
+ Trivia::spaces(1));
+ auto NoEllipsis = TokenSyntax::missingToken(tok::identifier, "...");
+ auto Equal = SyntaxFactory::makeEqualToken({}, Trivia::spaces(1));
+
+ auto Sign = SyntaxFactory::makePrefixOpereator("-", {});
+ auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
+ auto One = SyntaxFactory::makeIntegerLiteralExpr(Sign, OneDigits);
+ auto Comma = SyntaxFactory::makeCommaToken({}, {});
+
+ auto Param = SyntaxFactory::makeFunctionParameter(ExternalName, LocalName,
+ Colon, Int, NoEllipsis,
+ Equal, One, Comma);
+
+ ASSERT_EQ(ExternalName, Param.getExternalName());
+ ASSERT_EQ(LocalName, Param.getLocalName());
+ ASSERT_EQ(Colon, Param.getColonToken());
+
+ auto GottenType = Param.getTypeSyntax().getValue();
+ auto GottenType2 = Param.getTypeSyntax().getValue();
+ ASSERT_TRUE(GottenType.hasSameIdentityAs(GottenType2));
+
+ ASSERT_EQ(Equal, Param.getEqualToken());
+
+ auto GottenDefaultValue = Param.getDefaultValue().getValue();
+ auto GottenDefaultValue2 = Param.getDefaultValue().getValue();
+ ASSERT_TRUE(GottenDefaultValue.hasSameIdentityAs(GottenDefaultValue2));
+
+ ASSERT_EQ(Comma, Param.getTrailingComma());
+
+ // Test that llvm::None is returned for non-token missing children:
+ auto Decimated = Param
+ .withTypeSyntax(llvm::None)
+ .withDefaultValue(llvm::None);
+
+ ASSERT_FALSE(Decimated.getTypeSyntax().hasValue());
+ ASSERT_FALSE(Decimated.getDefaultValue().hasValue());
+}
+
+TEST(DeclSyntaxTests, FunctionParameterWithAPIs) {
+ auto ExternalName = SyntaxFactory::makeIdentifier("for", {},
+ Trivia::spaces(1));
+ auto LocalName = SyntaxFactory::makeIdentifier("integer", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken(Trivia::spaces(1),
+ Trivia::spaces(1));
+ auto Int = SyntaxFactory::makeTypeIdentifier("Int", {},
+ Trivia::spaces(1));
+ auto Equal = SyntaxFactory::makeEqualToken({}, Trivia::spaces(1));
+
+ auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "");
+ auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
+ auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+ auto Comma = SyntaxFactory::makeCommaToken({}, {});
+
+ {
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ getCannedFunctionParameter()
+ .withExternalName(ExternalName)
+ .withLocalName(LocalName)
+ .withColonToken(Colon)
+ .withTypeSyntax(Int)
+ .withEqualToken(Equal)
+ .withDefaultValue(One)
+ .withTrailingComma(Comma)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "for integer : Int = 1,");
+ }
+ {
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ getCannedFunctionParameter()
+ .withTypeSyntax(llvm::None)
+ .withDefaultValue(llvm::None)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "with radius: = , ");
+ }
+}
+
+#pragma mark - parameter-list
+
+TEST(DeclSyntaxTests, FunctionParameterListMakeAPIs) {
+ {
+ SmallString<1> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionParameterList().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+ {
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto Param = getCannedFunctionParameter();
+ std::vector<FunctionParameterSyntax> Params { Param, Param, Param };
+ SyntaxFactory::makeFunctionParameterList(Params).print(OS);
+ ASSERT_EQ(OS.str().str(),
+ "with radius: Int = -1, with radius: Int = -1, with radius: Int = -1, ");
+ }
+}
+
+#pragma mark - function-signature
+
+FunctionSignatureSyntax getCannedFunctionSignature() {
+ auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto Param = getCannedFunctionParameter();
+ auto List = SyntaxFactory::makeBlankFunctionParameterList()
+ .appending(Param)
+ .appending(Param)
+ .appending(Param)
+ .castTo<FunctionParameterListSyntax>();
+ auto RParen = SyntaxFactory::makeRightParenToken({}, Trivia::spaces(1));
+ auto Throws = SyntaxFactory::makeThrowsKeyword({}, Trivia::spaces(1));
+ auto Arrow = SyntaxFactory::makeArrow({}, Trivia::spaces(1));
+ auto NoAttributes = SyntaxFactory::makeBlankTypeAttributes();
+ auto Int = SyntaxFactory::makeTypeIdentifier("Int", {}, Trivia::spaces(1));
+
+ return SyntaxFactory::makeFunctionSignature(LParen, List, RParen, Throws,
+ Arrow, NoAttributes, Int);
+}
+
+TEST(DeclSyntaxTests, FunctionSignatureMakeAPIs) {
+ {
+ SmallString<1> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionSignature().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+ {
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ getCannedFunctionSignature().print(OS);
+ ASSERT_EQ(OS.str().str(),
+ "(with radius: Int = -1, "
+ "with radius: Int = -1, "
+ "with radius: Int = -1, ) throws -> Int ");
+ }
+}
+
+TEST(DeclSyntaxTests, FunctionSignatureGetAPIs) {
+ auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto Param = getCannedFunctionParameter();
+ auto List = SyntaxFactory::makeBlankFunctionParameterList()
+ .appending(Param)
+ .appending(Param)
+ .appending(Param)
+ .castTo<FunctionParameterListSyntax>();
+ auto RParen = SyntaxFactory::makeRightParenToken({}, Trivia::spaces(1));
+ auto Throws = SyntaxFactory::makeThrowsKeyword({}, Trivia::spaces(1));
+ auto Arrow = SyntaxFactory::makeArrow({}, Trivia::spaces(1));
+ auto NoAttributes = SyntaxFactory::makeBlankTypeAttributes();
+ auto Int = SyntaxFactory::makeTypeIdentifier("Int", {}, {});
+
+ auto Sig = SyntaxFactory::makeFunctionSignature(LParen, List, RParen, Throws,
+ Arrow, NoAttributes, Int);
+
+ ASSERT_EQ(LParen, Sig.getLeftParenToken());
+
+ {
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto GottenList1 = Sig.getParameterList();
+ auto GottenList2 = Sig.getParameterList();
+ ASSERT_TRUE(GottenList1.hasSameIdentityAs(GottenList2));
+ GottenList1.print(OS);
+ ASSERT_EQ(OS.str().str(),
+ "with radius: Int = -1, "
+ "with radius: Int = -1, "
+ "with radius: Int = -1, ");
+ }
+
+ ASSERT_EQ(RParen, Sig.getRightParenToken());
+ ASSERT_EQ(Throws, Sig.getThrowsToken());
+ ASSERT_TRUE(Sig.getRethrowsToken()->isMissing());
+ ASSERT_EQ(Arrow, Sig.getArrowToken());
+
+ {
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto GottenAttrs1 = Sig.getReturnTypeAttributes();
+ auto GottenAttrs2 = Sig.getReturnTypeAttributes();
+ ASSERT_TRUE(GottenAttrs1.hasSameIdentityAs(GottenAttrs2));
+ ASSERT_EQ(OS.str().str(), "");
+ }
+
+ {
+ SmallString<3> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto GottenReturnType1 = Sig.getReturnTypeSyntax();
+ auto GottenReturnType2 = Sig.getReturnTypeSyntax();
+ ASSERT_TRUE(GottenReturnType1.hasSameIdentityAs(GottenReturnType2));
+ GottenReturnType1.print(OS);
+ ASSERT_EQ(OS.str().str(), "Int");
+ }
+}
+
+TEST(DeclSyntaxTests, FunctionSignatureWithAPIs) {
+ auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto Param = getCannedFunctionParameter();
+ auto List = SyntaxFactory::makeBlankFunctionParameterList()
+ .appending(Param)
+ .appending(Param)
+ .appending(Param)
+ .castTo<FunctionParameterListSyntax>();
+ auto RParen = SyntaxFactory::makeRightParenToken({}, Trivia::spaces(1));
+ auto Throws = SyntaxFactory::makeThrowsKeyword({}, Trivia::spaces(1));
+ auto Arrow = SyntaxFactory::makeArrow({}, Trivia::spaces(1));
+ auto NoAttributes = SyntaxFactory::makeBlankTypeAttributes();
+ auto Int = SyntaxFactory::makeTypeIdentifier("Int", {}, {});
+
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionSignature()
+ .withLeftParenToken(LParen)
+ .withParameterList(List)
+ .withRightParenToken(RParen)
+ .withThrowsToken(Throws)
+ .withReturnTypeAttributes(NoAttributes)
+ .withArrowToken(Arrow)
+ .withReturnTypeSyntax(Int)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(),
+ "(with radius: Int = -1, "
+ "with radius: Int = -1, "
+ "with radius: Int = -1, ) throws -> Int");
+}
+
+#pragma mark - function-declaration
+
+DeclModifierListSyntax getCannedModifiers() {
+ auto PublicID = SyntaxFactory::makePublicKeyword({}, Trivia::spaces(1));
+ auto NoLParen = TokenSyntax::missingToken(tok::l_paren, "(");
+ auto NoArgument = TokenSyntax::missingToken(tok::identifier, "");
+ auto NoRParen = TokenSyntax::missingToken(tok::r_paren, ")");
+ auto Public = SyntaxFactory::makeDeclModifier(PublicID, NoLParen, NoArgument,
+ NoRParen);
+
+ auto StaticKW = SyntaxFactory::makeStaticKeyword({}, Trivia::spaces(1));
+ auto Static = SyntaxFactory::makeDeclModifier(StaticKW, NoLParen, NoArgument,
+ NoRParen);
+
+ return SyntaxFactory::makeBlankDeclModifierList()
+ .appending(Public)
+ .appending(Static)
+ .castTo<DeclModifierListSyntax>();
+}
+
+GenericParameterClauseSyntax getCannedGenericParams() {
+ GenericParameterClauseBuilder GB;
+
+ auto LAngle = SyntaxFactory::makeLeftAngleToken({}, {});
+ auto RAngle = SyntaxFactory::makeRightAngleToken({}, {});
+
+ auto T = SyntaxFactory::makeGenericParameter("T", {}, {});
+ auto U = SyntaxFactory::makeGenericParameter("U", {}, {});
+
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+
+ GB.addParameter(llvm::None, T);
+ GB.addParameter(Comma, U);
+ GB.useLeftAngleBracket(LAngle);
+ GB.useRightAngleBracket(RAngle);
+
+ return GB.build();
+}
+
+CodeBlockStmtSyntax getCannedBody() {
+ auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "-");
+ auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
+ auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+ auto ReturnKW =
+ SyntaxFactory::makeReturnKeyword(Trivia::newlines(1) + Trivia::spaces(2),
+ {});
+ auto Return = SyntaxFactory::makeReturnStmt(ReturnKW, One);
+
+ auto Stmts = SyntaxFactory::makeBlankStmtList()
+ .appending(Return)
+ .castTo<StmtListSyntax>();
+
+ auto LBrace = SyntaxFactory::makeLeftBraceToken({}, {});
+ auto RBrace = SyntaxFactory::makeRightBraceToken(Trivia::newlines(1), {});
+
+ return SyntaxFactory::makeCodeBlock(LBrace, Stmts, RBrace);
+}
+
+GenericWhereClauseSyntax getCannedWhereClause() {
+ auto WhereKW = SyntaxFactory::makeWhereKeyword({}, Trivia::spaces(1));
+ auto T = SyntaxFactory::makeTypeIdentifier("T", {}, Trivia::spaces(1));
+ auto EqualEqual = SyntaxFactory::makeEqualityOperator({}, Trivia::spaces(1));
+ auto Int = SyntaxFactory::makeTypeIdentifier("Int", {}, Trivia::spaces(1));
+ auto SameType = SyntaxFactory::makeSameTypeRequirement(T, EqualEqual, Int);
+
+ auto Requirements = SyntaxFactory::makeBlankGenericRequirementList()
+ .appending(SameType.castTo<GenericRequirementSyntax>())
+ .castTo<GenericRequirementListSyntax>();
+
+ return SyntaxFactory::makeBlankGenericWhereClause()
+ .withWhereKeyword(WhereKW)
+ .withRequirementList(Requirements);
+}
+
+FunctionDeclSyntax getCannedFunctionDecl() {
+ auto NoAttributes = SyntaxFactory::makeBlankTypeAttributes();
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto FuncKW = SyntaxFactory::makeFuncKeyword({}, Trivia::spaces(1));
+ auto Modifiers = getCannedModifiers();
+ auto GenericParams = getCannedGenericParams();
+ auto GenericWhere = getCannedWhereClause();
+ auto Signature = getCannedFunctionSignature();
+ auto Body = getCannedBody();
+
+ return SyntaxFactory::makeFunctionDecl(NoAttributes, Modifiers, FuncKW, Foo,
+ GenericParams, Signature, GenericWhere,
+ Body);
+}
+
+TEST(DeclSyntaxTests, FunctionDeclMakeAPIs) {
+ {
+ SmallString<1> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionDecl().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+ {
+ SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ getCannedFunctionDecl().print(OS);
+ ASSERT_EQ(OS.str().str(),
+ "public static func foo<T, U>"
+ "(with radius: Int = -1, "
+ "with radius: Int = -1, "
+ "with radius: Int = -1, ) "
+ "throws -> Int "
+ "where T == Int {\n"
+ " return1\n"
+ "}");
+ }
+}
+
+TEST(DeclSyntaxTests, FunctionDeclGetAPIs) {
+ {
+ SmallString<1> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionDecl().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+ {
+
+ }
+}
+
+TEST(DeclSyntaxTests, FunctionDeclWithAPIs) {
+
+}
+
+TEST(DeclSyntaxTests, FunctionDeclBuilderAPIs) {
+
+}
diff --git a/unittests/Syntax/ExprSyntaxTests.cpp b/unittests/Syntax/ExprSyntaxTests.cpp
index ae95b65..52254fe 100644
--- a/unittests/Syntax/ExprSyntaxTests.cpp
+++ b/unittests/Syntax/ExprSyntaxTests.cpp
@@ -209,9 +209,10 @@
Comma);
return SyntaxFactory::makeBlankFunctionCallArgumentList()
- .withAdditionalArgument(Arg)
- .withAdditionalArgument(Arg.withLabel(Y))
- .withAdditionalArgument(Arg.withLabel(Z).withTrailingComma(NoComma));
+ .appending(Arg)
+ .appending(Arg.withLabel(Y))
+ .appending(Arg.withLabel(Z).withTrailingComma(NoComma))
+ .castTo<FunctionCallArgumentListSyntax>();
}
FunctionCallArgumentListSyntax getLabellessArgumentList() {
@@ -235,9 +236,10 @@
Three, NoComma);
return SyntaxFactory::makeBlankFunctionCallArgumentList()
- .withAdditionalArgument(OneArg)
- .withAdditionalArgument(TwoArg)
- .withAdditionalArgument(ThreeArg);
+ .appending(OneArg)
+ .appending(TwoArg)
+ .appending(ThreeArg)
+ .castTo<FunctionCallArgumentListSyntax>();
}
}
@@ -255,17 +257,18 @@
Comma);
auto ArgList = SyntaxFactory::makeBlankFunctionCallArgumentList()
- .withAdditionalArgument(Arg)
- .withAdditionalArgument(Arg.withLabel(Y))
- .withAdditionalArgument(Arg.withLabel(Z).withTrailingComma(NoComma));
+ .appending(Arg)
+ .appending(Arg.withLabel(Y))
+ .appending(Arg.withLabel(Z).withTrailingComma(NoComma))
+ .castTo<FunctionCallArgumentListSyntax>();
- ASSERT_EQ(ArgList.getNumArguments(), size_t(3));
+ ASSERT_EQ(ArgList.size(), size_t(3));
{
llvm::SmallString<16> Scratch;
llvm::raw_svector_ostream OS(Scratch);
- auto GottenArg1 = ArgList.getArgument(0);
- auto GottenArg1_2 = ArgList.getArgument(0);
+ auto GottenArg1 = ArgList[0];
+ auto GottenArg1_2 = ArgList[0];
ASSERT_TRUE(GottenArg1.hasSameIdentityAs(GottenArg1_2));
GottenArg1.print(OS);
ASSERT_EQ(OS.str().str(), "x: foo, ");
@@ -274,8 +277,8 @@
{
llvm::SmallString<16> Scratch;
llvm::raw_svector_ostream OS(Scratch);
- auto GottenArg2 = ArgList.getArgument(1);
- auto GottenArg2_2 = ArgList.getArgument(1);
+ auto GottenArg2 = ArgList[1];
+ auto GottenArg2_2 = ArgList[1];
ASSERT_TRUE(GottenArg2.hasSameIdentityAs(GottenArg2_2));
GottenArg2.print(OS);
ASSERT_EQ(OS.str().str(), "y: foo, ");
@@ -284,8 +287,8 @@
{
llvm::SmallString<16> Scratch;
llvm::raw_svector_ostream OS(Scratch);
- auto GottenArg3 = ArgList.getArgument(2);
- auto GottenArg3_2 = ArgList.getArgument(2);
+ auto GottenArg3 = ArgList[2];
+ auto GottenArg3_2 = ArgList[2];
ASSERT_TRUE(GottenArg3.hasSameIdentityAs(GottenArg3_2));
GottenArg3.print(OS);
ASSERT_EQ(OS.str().str(), "z: foo");
@@ -321,7 +324,7 @@
llvm::raw_svector_ostream OS(Scratch);
auto ArgList = SyntaxFactory::makeFunctionCallArgumentList(Args);
ArgList.print(OS);
- ASSERT_EQ(ArgList.getNumArguments(), size_t(3));
+ ASSERT_EQ(ArgList.size(), size_t(3));
ASSERT_EQ(OS.str().str(), "x: foo, y: foo, z: foo");
}
}
@@ -330,9 +333,9 @@
auto ArgList = getFullArgumentList();
llvm::SmallString<64> Scratch;
llvm::raw_svector_ostream OS(Scratch);
- ASSERT_EQ(ArgList.getNumArguments(), size_t(3));
+ ASSERT_EQ(ArgList.size(), size_t(3));
ArgList.print(OS);
- ASSERT_EQ(ArgList.getNumArguments(), size_t(3));
+ ASSERT_EQ(ArgList.size(), size_t(3));
ASSERT_EQ(OS.str().str(), "x: foo, y: foo, z: foo");
}
diff --git a/unittests/Syntax/SyntaxCollectionTests.cpp b/unittests/Syntax/SyntaxCollectionTests.cpp
new file mode 100644
index 0000000..656c44d
--- /dev/null
+++ b/unittests/Syntax/SyntaxCollectionTests.cpp
@@ -0,0 +1,260 @@
+#include "swift/Syntax/ExprSyntax.h"
+#include "swift/Syntax/SyntaxFactory.h"
+#include "llvm/ADT/SmallString.h"
+#include "gtest/gtest.h"
+
+using llvm::None;
+using llvm::SmallString;
+
+using namespace swift;
+using namespace swift::syntax;
+
+FunctionCallArgumentSyntax getCannedArgument() {
+ auto X = SyntaxFactory::makeIdentifier("x", {}, {});
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+
+ return SyntaxFactory::makeFunctionCallArgument(X, Colon, SymbolicRef, Comma);
+}
+
+TEST(SyntaxCollectionTests, empty) {
+ auto Empty = SyntaxFactory::makeBlankFunctionCallArgumentList();
+ ASSERT_TRUE(Empty.empty());
+ ASSERT_FALSE(Empty.appending(getCannedArgument()).empty());
+}
+
+TEST(SyntaxCollectionTests, size) {
+ auto Empty = SyntaxFactory::makeBlankFunctionCallArgumentList();
+ ASSERT_EQ(Empty.size(), size_t(0));
+ ASSERT_EQ(Empty.appending(getCannedArgument()).size(), size_t(1));
+}
+
+TEST(SyntaxCollectionTests, subscript) {
+ auto Empty = SyntaxFactory::makeBlankFunctionCallArgumentList();
+#ifndef NDEBUG
+ ASSERT_DEATH({ Empty[0]; }, "");
+#endif
+
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto Arg = getCannedArgument();
+ Arg.print(OS);
+
+ auto List = Empty.appending(Arg);
+
+ SmallString<48> GottenScratch;
+ llvm::raw_svector_ostream GottenOS(Scratch);
+ List[0].print(GottenOS);
+
+ ASSERT_EQ(OS.str().str(), GottenOS.str().str());
+
+ auto GottenArg1 = List[0];
+ auto GottenArg2 = List[0];
+ ASSERT_TRUE(GottenArg1.hasSameIdentityAs(GottenArg2));
+}
+
+TEST(SyntaxCollectionTests, appending) {
+ auto Arg = getCannedArgument();
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+ auto List = SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .appending(Arg)
+ .appending(Arg)
+ .appending(Arg.withTrailingComma(NoComma));
+
+ ASSERT_EQ(List.size(), size_t(3));
+
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ List.print(OS);
+
+ ASSERT_EQ(OS.str().str(), "x: foo, x: foo, x: foo");
+
+ auto GottenArg0_1 = List[0];
+ auto GottenArg0_2 = List[0];
+ ASSERT_TRUE(GottenArg0_1.hasSameIdentityAs(GottenArg0_2));
+
+ auto GottenArg1_1 = List[1];
+ auto GottenArg1_2 = List[1];
+ ASSERT_TRUE(GottenArg1_1.hasSameIdentityAs(GottenArg1_2));
+
+ auto GottenArg2_1 = List[2];
+ auto GottenArg2_2 = List[2];
+ ASSERT_TRUE(GottenArg2_1.hasSameIdentityAs(GottenArg2_2));
+}
+
+TEST(SyntaxCollectionTests, removingLast) {
+ ASSERT_DEATH({
+ SyntaxFactory::makeBlankFunctionCallArgumentList().removingLast();
+ }, "");
+ auto Arg = getCannedArgument();
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+ auto List = SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .appending(Arg)
+ .appending(Arg)
+ .appending(Arg.withTrailingComma(NoComma))
+ .removingLast();
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ List.print(OS);
+ ASSERT_EQ(OS.str().str(), "x: foo, x: foo, ");
+}
+
+TEST(SyntaxCollectionTests, prepending) {
+ auto Arg = getCannedArgument();
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+ auto List = SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .prepending(Arg.withTrailingComma(NoComma))
+ .prepending(Arg
+ .withLabel(SyntaxFactory::makeIdentifier("schwifty", {}, {})))
+ .prepending(Arg);
+
+ ASSERT_EQ(List.size(), size_t(3));
+
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ List.print(OS);
+
+ ASSERT_EQ(OS.str().str(), "x: foo, schwifty: foo, x: foo");
+
+ auto GottenArg0_1 = List[0];
+ auto GottenArg0_2 = List[0];
+ ASSERT_TRUE(GottenArg0_1.hasSameIdentityAs(GottenArg0_2));
+
+ auto GottenArg1_1 = List[1];
+ auto GottenArg1_2 = List[1];
+ ASSERT_TRUE(GottenArg1_1.hasSameIdentityAs(GottenArg1_2));
+
+ auto GottenArg2_1 = List[2];
+ auto GottenArg2_2 = List[2];
+ ASSERT_TRUE(GottenArg2_1.hasSameIdentityAs(GottenArg2_2));
+}
+
+TEST(SyntaxCollectionTests, removingFirst) {
+ ASSERT_DEATH({
+ SyntaxFactory::makeBlankFunctionCallArgumentList().removingFirst();
+ }, "");
+ auto Arg = getCannedArgument();
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+ auto List = SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .appending(Arg
+ .withLabel(SyntaxFactory::makeIdentifier("schwifty", {}, {})))
+ .appending(Arg)
+ .appending(Arg.withTrailingComma(NoComma))
+ .removingFirst();
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ List.print(OS);
+ ASSERT_EQ(OS.str().str(), "x: foo, x: foo");
+}
+
+TEST(SyntaxCollectionTests, inserting) {
+ auto Arg = getCannedArgument();
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+#ifndef NDEBUG
+ ASSERT_DEATH({
+ SyntaxFactory::makeBlankFunctionCallArgumentList().inserting(1, Arg);
+ }, "");
+#endif
+
+ {
+ SmallString<48> InsertedScratch;
+ llvm::raw_svector_ostream InsertedOS(InsertedScratch);
+ SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .inserting(0, Arg)
+ .inserting(0, Arg)
+ .inserting(0, Arg)
+ .print(InsertedOS);
+
+ SmallString<48> PrependedScratch;
+ llvm::raw_svector_ostream PrependedOS(PrependedScratch);
+ SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .prepending(Arg)
+ .prepending(Arg)
+ .prepending(Arg)
+ .print(PrependedOS);
+ ASSERT_EQ(InsertedOS.str().str(), PrependedOS.str().str());
+ }
+
+ {
+ SmallString<48> InsertedScratch;
+ llvm::raw_svector_ostream InsertedOS(InsertedScratch);
+ SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .inserting(0, Arg)
+ .inserting(1, Arg)
+ .inserting(2, Arg)
+ .print(InsertedOS);
+
+ SmallString<48> AppendedScratch;
+ llvm::raw_svector_ostream AppendedOS(AppendedScratch);
+ SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .appending(Arg)
+ .appending(Arg)
+ .appending(Arg)
+ .print(AppendedOS);
+ ASSERT_EQ(InsertedOS.str().str(), AppendedOS.str().str());
+ }
+
+ {
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .appending(Arg)
+ .appending(Arg)
+ .inserting(1,
+ Arg.withLabel(SyntaxFactory::makeIdentifier("schwifty",
+ {}, {})))
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "x: foo, schwifty: foo, x: foo, ");
+ }
+}
+
+TEST(SyntaxCollectionTests, cleared) {
+ auto Arg = getCannedArgument();
+ SmallString<1> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto List = SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .appending(Arg)
+ .appending(Arg)
+ .appending(Arg)
+ .cleared();
+
+ List.print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ ASSERT_TRUE(List.empty());
+ ASSERT_EQ(List.size(), size_t(0));
+}
+
+TEST(SyntaxCollectionTests, Iteration) {
+ auto Arg = getCannedArgument();
+ auto List = SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .appending(Arg)
+ .appending(Arg)
+ .appending(Arg);
+
+ auto Element0 = List[0];
+ auto Element1 = List[1];
+ auto Element2 = List[2];
+
+ SmallString<48> IteratedScratch;
+ llvm::raw_svector_ostream IteratedOS(IteratedScratch);
+ for (auto Element : List) {
+ Element.print(IteratedOS);
+ }
+ ASSERT_EQ(IteratedOS.str().str(), "x: foo, x: foo, x: foo, ");
+
+ auto IteratedElement0 = List[0];
+ auto IteratedElement1 = List[1];
+ auto IteratedElement2 = List[2];
+
+ ASSERT_TRUE(Element0.hasSameIdentityAs(IteratedElement0));
+ ASSERT_TRUE(Element1.hasSameIdentityAs(IteratedElement1));
+ ASSERT_TRUE(Element2.hasSameIdentityAs(IteratedElement2));
+
+ SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ List.print(OS);
+ ASSERT_EQ(OS.str().str(), IteratedOS.str().str());
+}
diff --git a/unittests/runtime/Refcounting.cpp b/unittests/runtime/Refcounting.cpp
index d01b279..2ac88d0 100644
--- a/unittests/runtime/Refcounting.cpp
+++ b/unittests/runtime/Refcounting.cpp
@@ -180,7 +180,7 @@
// RC big, unpinned
EXPECT_FALSE(swift_isUniquelyReferencedOrPinned_nonNull_native(object));
- auto pinResult = swift_tryPin(object);
+ swift_tryPin(object);
// RC big, pinned
EXPECT_TRUE(swift_isUniquelyReferencedOrPinned_nonNull_native(object));
diff --git a/unittests/runtime/weak.mm b/unittests/runtime/weak.mm
index 4d55479..80137fa 100644
--- a/unittests/runtime/weak.mm
+++ b/unittests/runtime/weak.mm
@@ -14,7 +14,6 @@
#include <objc/runtime.h>
#include "swift/Runtime/HeapObject.h"
#include "swift/Runtime/Metadata.h"
-#include "swift/Runtime/Metadata.h"
#include "gtest/gtest.h"
using namespace swift;
diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index 2d5b62e..980335c 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -1002,6 +1002,16 @@
assertions
+[preset: LLDB_Swift_DebugAssert_with_devices]
+mixin-preset=
+ LLDB_Swift_DebugAssert
+
+ios
+tvos
+watchos
+build-swift-static-stdlib
+build-swift-static-sdk-overlay
+
[preset: LLDB_Swift_ReleaseAssert]
mixin-preset=
LLDB_Nested
@@ -1009,6 +1019,16 @@
release-debuginfo
assertions
+[preset: LLDB_Swift_ReleaseAssert_with_devices]
+mixin-preset=
+ LLDB_Swift_ReleaseAssert
+
+ios
+tvos
+watchos
+build-swift-static-stdlib
+build-swift-static-sdk-overlay
+
#===------------------------------------------------------------------------===#
# Test all platforms on OS X builder
#===------------------------------------------------------------------------===#
@@ -1475,3 +1495,23 @@
swift-stdlib-build-type=RelWithDebInfo
swift-stdlib-enable-assertions=true
build-serialized-stdlib-unittest
+
+#===------------------------------------------------------------------------===#
+# Swift Coverage Preset
+#===------------------------------------------------------------------------===#
+
+[preset: buildbot_incremental,tools=RDA,stdlib=RDA,coverage]
+build-subdir=buildbot_incremental_coverage
+release-debuginfo
+assertions
+swift-analyze-code-coverage=not-merged
+test
+validation-test
+skip-test-ios
+skip-test-tvos
+skip-test-watchos
+skip-build-benchmark
+verbose-build
+lit-args=-v
+reconfigure
+build-ninja
diff --git a/utils/build-script-impl b/utils/build-script-impl
index c1e12b2..4779e4a 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -725,7 +725,6 @@
llvm_cmake_options+=(
-DLLVM_TOOL_COMPILER_RT_BUILD:BOOL="$(false_true ${SKIP_BUILD_COMPILER_RT})"
-DLLVM_BUILD_EXTERNAL_COMPILER_RT:BOOL="$(false_true ${SKIP_BUILD_COMPILER_RT})"
- -DLLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING:BOOL=TRUE
)
# If we are asked to not generate test targets for LLVM and or Swift,
diff --git a/utils/coverage/coverage-generate-data b/utils/coverage/coverage-generate-data
index ca1bf34..35943e8 100755
--- a/utils/coverage/coverage-generate-data
+++ b/utils/coverage/coverage-generate-data
@@ -194,8 +194,6 @@
parser = argparse.ArgumentParser(
description='Generate, parse test run profdata')
parser.add_argument('swift_dir', metavar='swift-dir')
- parser.add_argument('--build-dir')
- parser.add_argument('--build-subdir', default='coverage')
parser.add_argument('--log',
help='the level of information to log (default: info)',
metavar='LEVEL',
@@ -208,36 +206,17 @@
logging.debug(args)
swift_dir = os.path.realpath(os.path.abspath(args.swift_dir))
- if args.build_dir:
- build_dir = os.path.realpath(os.path.abspath(args.build_dir))
- else:
- build_dir = os.path.realpath(os.path.join(os.path.dirname(swift_dir),
- 'build'))
- build_subdir = os.path.join(build_dir, args.build_subdir)
+ build_dir = os.path.realpath(os.path.join(os.path.dirname(swift_dir),
+ 'build'))
+ build_subdir = os.path.join(build_dir, 'buildbot_incremental_coverage')
global_build_subdir = build_subdir
build_script_cmd = [
os.path.join(swift_dir, 'utils/build-script'),
- '--release',
- '--no-assertions',
- '--swift-analyze-code-coverage', 'not-merged',
- '--test',
- '--validation-test',
- '--skip-test-ios',
- '--skip-test-tvos',
- '--skip-test-watchos',
- '--skip-build-benchmark',
- '--verbose-build',
- '--lit-args=-v',
- '--reconfigure',
- '--build-ninja',
- '--build-subdir', build_subdir
+ '--preset=buildbot_incremental,tools=RDA,stdlib=RDA,coverage',
]
- if args.build_dir:
- build_script_cmd += ['--build-dir', build_dir]
-
call(build_script_cmd)
assert global_build_subdir
diff --git a/utils/sil-mode.el b/utils/sil-mode.el
index 6d390d0..b13b3e4 100644
--- a/utils/sil-mode.el
+++ b/utils/sil-mode.el
@@ -76,6 +76,9 @@
`(,(regexp-opt '("load_borrow" "begin_borrow" "store_borrow" "end_borrow_argument") 'words) . font-lock-keyword-face)
'("\\(end_borrow\\) %[[:alnum:]] \\(from\\)" (1 font-lock-keyword-face) (2 font-lock-keyword-face))
+ ;; SIL Instructions - ownership
+ `(,(regexp-opt '("unchecked_ownership_conversion") 'words) . font-lock-keyword-face)
+
;; SIL Instructions - Reference Counting.
`(,(regexp-opt '("strong_retain"
"strong_release" "strong_retain_unowned"
@@ -83,6 +86,7 @@
"load_weak" "store_weak"
"load_unowned" "store_unowned"
"fix_lifetime" "mark_dependence"
+ "end_lifetime"
"is_unique" "is_unique_or_pinned"
"copy_block"
"strong_unpin" "strong_pin" "is_unique" "is_unique_or_pinned")
diff --git a/utils/swift_build_support/swift_build_support/targets.py b/utils/swift_build_support/swift_build_support/targets.py
index 5cd6a67..ab3e6dc 100644
--- a/utils/swift_build_support/swift_build_support/targets.py
+++ b/utils/swift_build_support/swift_build_support/targets.py
@@ -126,6 +126,8 @@
Android = Platform("android", archs=["armv7"])
+ Windows = Platform("windows", archs=["x86_64"])
+
# The list of known platforms.
known_platforms = [
OSX,
@@ -135,7 +137,8 @@
Linux,
FreeBSD,
Cygwin,
- Android]
+ Android,
+ Windows]
# Cache of targets by name.
_targets_by_name = dict((target.name, target)
@@ -181,6 +184,10 @@
if machine == 'x86_64':
return StdlibDeploymentTarget.Cygwin.x86_64
+ elif system == 'Windows':
+ if machine == "AMD64":
+ return StdlibDeploymentTarget.Windows.x86_64
+
raise NotImplementedError('System "%s" with architecture "%s" is not '
'supported' % (system, machine))
diff --git a/utils/swift_build_support/swift_build_support/toolchain.py b/utils/swift_build_support/swift_build_support/toolchain.py
index 061d224..367384d 100644
--- a/utils/swift_build_support/swift_build_support/toolchain.py
+++ b/utils/swift_build_support/swift_build_support/toolchain.py
@@ -45,8 +45,13 @@
setattr(Toolchain, name, cache_util.reify(_getter))
-_register("cc", "clang")
-_register("cxx", "clang++")
+if platform.system() == 'Windows':
+ _register("cc", "clang-cl")
+ _register("cxx", "clang-cl")
+else:
+ _register("cc", "clang")
+ _register("cxx", "clang++")
+
_register("ninja", "ninja", "ninja-build")
_register("cmake", "cmake")
_register("distcc", "distcc")
@@ -173,6 +178,15 @@
pass
+class Windows(Toolchain):
+ def find_tool(self, *names):
+ for name in names:
+ found = which(name)
+ if found is not None:
+ return found
+ return None
+
+
def host_toolchain(**kwargs):
sys = platform.system()
if sys == 'Darwin':
@@ -183,6 +197,8 @@
return FreeBSD()
elif sys.startswith('CYGWIN'):
return Cygwin()
+ elif sys == 'Windows':
+ return Windows()
else:
raise NotImplementedError('The platform "%s" does not have a defined '
'toolchain.' % sys)
diff --git a/validation-test/compiler_crashers/28700-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift b/validation-test/compiler_crashers/28700-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
index 4cba9a3..3894ba7 100644
--- a/validation-test/compiler_crashers/28700-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
+++ b/validation-test/compiler_crashers/28700-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
@@ -6,5 +6,6 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// REQUIRES: asserts
+// REQUIRES: deterministic-behavior
// RUN: not --crash %target-swift-frontend %s -emit-ir
{ struct c{func ulntatin(UInt=1 + 1 as?Int){a{a
diff --git a/validation-test/compiler_crashers/28702-swift-typebase-getcanonicaltype.swift b/validation-test/compiler_crashers/28702-swift-typebase-getcanonicaltype.swift
index 479b7b8..e628c7d 100644
--- a/validation-test/compiler_crashers/28702-swift-typebase-getcanonicaltype.swift
+++ b/validation-test/compiler_crashers/28702-swift-typebase-getcanonicaltype.swift
@@ -5,5 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+// REQUIRES: deterministic-behavior
// RUN: not --crash %target-swift-frontend %s -emit-ir
{extension{func 丏(UInt=1 + 1 + 1 as?Int){a
diff --git a/validation-test/compiler_crashers/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift b/validation-test/compiler_crashers/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
new file mode 100644
index 0000000..8df4f0e
--- /dev/null
+++ b/validation-test/compiler_crashers/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
@@ -0,0 +1,10 @@
+// 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
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol P{let c{}typealias e:RangeReplaceableCollection}extension P{typealias e:a
diff --git a/validation-test/compiler_crashers/28707-false-encountered-error-in-diagnostic-text.swift b/validation-test/compiler_crashers/28707-false-encountered-error-in-diagnostic-text.swift
new file mode 100644
index 0000000..96aad26
--- /dev/null
+++ b/validation-test/compiler_crashers/28707-false-encountered-error-in-diagnostic-text.swift
@@ -0,0 +1,12 @@
+// 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
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+class a{@_versioned
+public
+protocol r
diff --git a/validation-test/compiler_crashers/28709-unreachable-executed-at-swift-lib-ast-type-cpp-1005.swift b/validation-test/compiler_crashers/28709-unreachable-executed-at-swift-lib-ast-type-cpp-1005.swift
new file mode 100644
index 0000000..4eb8150
--- /dev/null
+++ b/validation-test/compiler_crashers/28709-unreachable-executed-at-swift-lib-ast-type-cpp-1005.swift
@@ -0,0 +1,12 @@
+// 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
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+{
+class C{func o(UInt=1 + 1 + 1 + 1 + 1 as?Int){{
+{r
+p
diff --git a/validation-test/compiler_crashers_2_fixed/0079-rdar30702721.swift b/validation-test/compiler_crashers_2_fixed/0079-rdar30702721.swift
new file mode 100644
index 0000000..5965987
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0079-rdar30702721.swift
@@ -0,0 +1,9 @@
+// RUN: %target-swift-frontend %s -emit-ir
+
+extension Sequence {
+ typealias Element = Iterator.Element
+}
+
+func f<C: Sequence>(c: C) where C.Iterator == C {
+ c.makeIterator()
+}