Merge pull request #13821 from slavapestov/kill-unused-link-entities
Kill unused link entities
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index fefc6bb..a727c13 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -117,7 +117,7 @@
global ::= global 'TD' // dynamic dispatch thunk
global ::= global 'Td' // direct method reference thunk
global ::= entity entity 'TV' // vtable override thunk, derived followed by base
- global ::= type 'D' // type mangling for the debugger. TODO: check if we really need this
+ global ::= type label-list? 'D' // type mangling for the debugger with label list for function types.
global ::= protocol-conformance entity 'TW' // protocol witness thunk
global ::= context identifier identifier 'TB' // property behavior initializer thunk (not used currently)
global ::= context identifier identifier 'Tb' // property behavior setter thunk (not used currently)
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 0330f5f..148911e 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -621,18 +621,11 @@
Bits.Decl.EscapedFromIfConfig = false;
}
- ClangNode getClangNodeImpl() const {
- assert(Bits.Decl.FromClang);
- return ClangNode::getFromOpaqueValue(
- *(reinterpret_cast<void * const*>(this) - 1));
- }
+ /// \brief Get the Clang node associated with this declaration.
+ ClangNode getClangNodeImpl() const;
/// \brief Set the Clang node associated with this declaration.
- void setClangNode(ClangNode Node) {
- Bits.Decl.FromClang = true;
- // Extra memory is allocated for this.
- *(reinterpret_cast<void **>(this) - 1) = Node.getOpaqueValue();
- }
+ void setClangNode(ClangNode Node);
void updateClangNode(ClangNode node) {
assert(hasClangNode());
@@ -1355,8 +1348,10 @@
}
};
-class GenericContext : public DeclContext {
-private:
+// A private class for forcing exact field layout.
+class _GenericContext {
+// Not really public. See GenericContext.
+public:
GenericParamList *GenericParams = nullptr;
/// The trailing where clause.
@@ -1371,13 +1366,15 @@
/// environment will be lazily loaded.
mutable llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
GenericSigOrEnv;
+};
+class GenericContext : private _GenericContext, public DeclContext {
/// Lazily populate the generic environment.
GenericEnvironment *getLazyGenericEnvironmentSlow() const;
protected:
GenericContext(DeclContextKind Kind, DeclContext *Parent)
- : DeclContext(Kind, Parent) { }
+ : _GenericContext(), DeclContext(Kind, Parent) { }
public:
/// \brief Retrieve the set of parameters to a generic context, or null if
@@ -1424,6 +1421,8 @@
/// Set the generic context of this context.
void setGenericEnvironment(GenericEnvironment *genericEnv);
};
+static_assert(sizeof(_GenericContext) + sizeof(DeclContext) ==
+ sizeof(GenericContext), "Please add fields to _GenericContext");
/// Describes what kind of name is being imported.
///
@@ -1532,7 +1531,7 @@
/// ExtensionDecl - This represents a type extension containing methods
/// associated with the type. This is not a ValueDecl and has no Type because
/// there are no runtime values of the Extension's type.
-class ExtensionDecl final : public Decl, public GenericContext,
+class ExtensionDecl final : public GenericContext, public Decl,
public IterableDeclContext {
SourceLoc ExtensionLoc; // Location of 'extension' keyword.
SourceRange Braces;
@@ -1948,13 +1947,13 @@
/// This, among other things, makes it easier to distinguish between local
/// top-level variables (which are not live past the end of the statement) and
/// global variables.
-class TopLevelCodeDecl : public Decl, public DeclContext {
+class TopLevelCodeDecl : public DeclContext, public Decl {
BraceStmt *Body;
public:
TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr)
- : Decl(DeclKind::TopLevelCode, Parent),
- DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
+ : DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
+ Decl(DeclKind::TopLevelCode, Parent),
Body(Body) {}
BraceStmt *getBody() const { return Body; }
@@ -2373,7 +2372,7 @@
/// A type declaration that can have generic parameters attached to it. Because
/// it has these generic parameters, it is always a DeclContext.
-class GenericTypeDecl : public TypeDecl, public GenericContext {
+class GenericTypeDecl : public GenericContext, public TypeDecl {
public:
GenericTypeDecl(DeclKind K, DeclContext *DC,
Identifier name, SourceLoc nameLoc,
@@ -4702,7 +4701,7 @@
/// A given type can have multiple subscript declarations, so long as the
/// signatures (indices and element type) are distinct.
///
-class SubscriptDecl : public AbstractStorageDecl, public GenericContext {
+class SubscriptDecl : public GenericContext, public AbstractStorageDecl {
SourceLoc ArrowLoc;
ParameterList *Indices;
TypeLoc ElementTy;
@@ -4711,8 +4710,8 @@
SubscriptDecl(DeclName Name, SourceLoc SubscriptLoc, ParameterList *Indices,
SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
GenericParamList *GenericParams)
- : AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
- GenericContext(DeclContextKind::SubscriptDecl, Parent),
+ : GenericContext(DeclContextKind::SubscriptDecl, Parent),
+ AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) {
setIndices(Indices);
setGenericParams(GenericParams);
@@ -4794,7 +4793,7 @@
};
/// \brief Base class for function-like declarations.
-class AbstractFunctionDecl : public ValueDecl, public GenericContext {
+class AbstractFunctionDecl : public GenericContext, public ValueDecl {
public:
enum class BodyKind {
/// The function did not have a body in the source code file.
@@ -4854,8 +4853,8 @@
SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
unsigned NumParameterLists,
GenericParamList *GenericParams)
- : ValueDecl(Kind, Parent, Name, NameLoc),
- GenericContext(DeclContextKind::AbstractFunctionDecl, Parent),
+ : GenericContext(DeclContextKind::AbstractFunctionDecl, Parent),
+ ValueDecl(Kind, Parent, Name, NameLoc),
Body(nullptr), ThrowsLoc(ThrowsLoc) {
setBodyKind(BodyKind::None);
setGenericParams(GenericParams);
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index bec8aae..688bf93 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -72,7 +72,7 @@
using DeclID = llvm::PointerEmbeddedInt<unsigned, 31>;
}
-enum class DeclContextKind : uint8_t {
+enum class DeclContextKind : unsigned {
AbstractClosureExpr,
Initializer,
TopLevelCodeDecl,
@@ -179,19 +179,24 @@
/// DeclContext, but a new brace statement is not. There's no
/// particular mandate for this, though.
///
-/// Note that DeclContexts have stricter alignment requirements than AST nodes
-/// in general, so if an AST node class multiply inherits from DeclContext
-/// and another base class, it must 'using DeclContext::operator new;' in order
-/// to use an allocator with the correct alignment.
+/// Please note that DeclContext assumes that it prefaces AST type hierarchies
+/// and therefore can safely access trailing memory. If you need to create a
+/// macro context, please see GenericContext for how to minimize new entries in
+/// the ASTHierarchy enum below.
class alignas(1 << DeclContextAlignInBits) DeclContext {
-
- enum {
- KindBits = DeclContextAlignInBits
+ enum class ASTHierarchy : unsigned {
+ Decl,
+ Expr,
+ FileUnit,
+ Initializer,
+ SerializedLocal,
+ // If you add a new AST hierarchies, then update the static_assert() below.
};
- static_assert(unsigned(DeclContextKind::Last_DeclContextKind) < 1U<<KindBits,
- "Not enough KindBits for DeclContextKind");
-
- llvm::PointerIntPair<DeclContext*, KindBits, DeclContextKind> ParentAndKind;
+ static_assert(unsigned(ASTHierarchy::SerializedLocal) <
+ (1 << DeclContextAlignInBits),
+ "ASTHierarchy exceeds bits available");
+
+ llvm::PointerIntPair<DeclContext*, 3, ASTHierarchy> ParentAndKind;
/// Change the parent of this context. This should only be used
/// very carefully.
@@ -209,17 +214,44 @@
/// extension thereof, return the GenericTypeDecl.
GenericTypeDecl *getAsTypeOrTypeExtensionContext() const;
+ static ASTHierarchy getASTHierarchyFromKind(DeclContextKind Kind) {
+ switch (Kind) {
+ case DeclContextKind::AbstractClosureExpr:
+ return ASTHierarchy::Expr;
+ case DeclContextKind::Initializer:
+ return ASTHierarchy::Initializer;
+ case DeclContextKind::SerializedLocal:
+ return ASTHierarchy::SerializedLocal;
+ case DeclContextKind::FileUnit:
+ return ASTHierarchy::FileUnit;
+ case DeclContextKind::Module:
+ case DeclContextKind::TopLevelCodeDecl:
+ case DeclContextKind::AbstractFunctionDecl:
+ case DeclContextKind::SubscriptDecl:
+ case DeclContextKind::GenericTypeDecl:
+ case DeclContextKind::ExtensionDecl:
+ return ASTHierarchy::Decl;
+ }
+ llvm_unreachable("Unhandled DeclContextKind");
+ }
+
+ Decl *getAsDeclOrDeclExtensionContext() {
+ return ParentAndKind.getInt() == ASTHierarchy::Decl ?
+ reinterpret_cast<Decl*>(this + 1) : nullptr;
+ }
+ const Decl *getAsDeclOrDeclExtensionContext() const {
+ return const_cast<DeclContext*>(this)->getAsDeclOrDeclExtensionContext();
+ }
+
public:
DeclContext(DeclContextKind Kind, DeclContext *Parent)
- : ParentAndKind(Parent, Kind) {
- assert((Parent != 0 || isModuleContext()) &&
- "DeclContext must have a parent unless it is a module!");
+ : ParentAndKind(Parent, getASTHierarchyFromKind(Kind)) {
+ if (Kind != DeclContextKind::Module)
+ assert(Parent != nullptr && "DeclContext must have a parent context");
}
/// Returns the kind of context this is.
- DeclContextKind getContextKind() const {
- return ParentAndKind.getInt();
- }
+ DeclContextKind getContextKind() const;
/// Determines whether this context is itself a local scope in a
/// code block. A context that appears in such a scope, like a
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index 62e845a..d122585 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -3389,7 +3389,7 @@
/// \brief A base class for closure expressions.
-class AbstractClosureExpr : public Expr, public DeclContext {
+class AbstractClosureExpr : public DeclContext, public Expr {
CaptureInfo Captures;
/// \brief The set of parameters.
@@ -3398,8 +3398,8 @@
public:
AbstractClosureExpr(ExprKind Kind, Type FnType, bool Implicit,
unsigned Discriminator, DeclContext *Parent)
- : Expr(Kind, Implicit, FnType),
- DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
+ : DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
+ Expr(Kind, Implicit, FnType),
parameterList(nullptr) {
Bits.AbstractClosureExpr.Discriminator = Discriminator;
}
diff --git a/include/swift/AST/ExprNodes.def b/include/swift/AST/ExprNodes.def
index d57d7c9..3aa95b6 100644
--- a/include/swift/AST/ExprNodes.def
+++ b/include/swift/AST/ExprNodes.def
@@ -48,6 +48,13 @@
#define LITERAL_EXPR(Id, Parent) EXPR(Id, Parent)
#endif
+/// A expression node with a DeclContext. For example: closures.
+///
+/// By default, these are treated like any other expression.
+#ifndef CONTEXT_EXPR
+#define CONTEXT_EXPR(Id, Parent) EXPR(Id, Parent)
+#endif
+
/// A convenience for determining the range of expressions. These will always
/// appear immediately after the last member.
#ifndef EXPR_RANGE
@@ -109,8 +116,8 @@
EXPR(TupleElement, Expr)
EXPR(CaptureList, Expr)
ABSTRACT_EXPR(AbstractClosure, Expr)
- EXPR(Closure, AbstractClosureExpr)
- EXPR(AutoClosure, AbstractClosureExpr)
+ CONTEXT_EXPR(Closure, AbstractClosureExpr)
+ CONTEXT_EXPR(AutoClosure, AbstractClosureExpr)
EXPR_RANGE(AbstractClosure, Closure, AutoClosure)
EXPR(InOut, Expr)
EXPR(DynamicType, Expr)
@@ -183,5 +190,6 @@
#undef LITERAL_EXPR
#undef UNCHECKED_EXPR
#undef ABSTRACT_EXPR
+#undef CONTEXT_EXPR
#undef EXPR
#undef LAST_EXPR
diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h
index 4186e69..41b9f9d 100644
--- a/include/swift/AST/Module.h
+++ b/include/swift/AST/Module.h
@@ -127,7 +127,7 @@
/// output binary and logical module (such as a single library or executable).
///
/// \sa FileUnit
-class ModuleDecl : public TypeDecl, public DeclContext {
+class ModuleDecl : public DeclContext, public TypeDecl {
public:
typedef ArrayRef<std::pair<Identifier, SourceLoc>> AccessPathTy;
typedef std::pair<ModuleDecl::AccessPathTy, ModuleDecl*> ImportedModule;
diff --git a/include/swift/AST/TypeAlignments.h b/include/swift/AST/TypeAlignments.h
index e021da0..67fc513 100644
--- a/include/swift/AST/TypeAlignments.h
+++ b/include/swift/AST/TypeAlignments.h
@@ -52,7 +52,7 @@
/// We frequently use three tag bits on all of these types.
constexpr size_t DeclAlignInBits = 3;
- constexpr size_t DeclContextAlignInBits = 4;
+ constexpr size_t DeclContextAlignInBits = 3;
constexpr size_t ExprAlignInBits = 3;
constexpr size_t StmtAlignInBits = 3;
constexpr size_t TypeAlignInBits = 3;
diff --git a/include/swift/Basic/Compiler.h b/include/swift/Basic/Compiler.h
index 04f231a..eea6c93 100644
--- a/include/swift/Basic/Compiler.h
+++ b/include/swift/Basic/Compiler.h
@@ -23,6 +23,9 @@
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
#if SWIFT_COMPILER_IS_MSVC && _MSC_VER < 1910
// Work around MSVC bug: attempting to reference a deleted function
@@ -40,4 +43,10 @@
#define SWIFT_ASSUME(x)
#endif
+#if __has_attribute(constructor)
+#define SWIFT_CONSTRUCTOR __attribute__((constructor))
+#else
+#define SWIFT_CONSTRUCTOR
+#endif
+
#endif // SWIFT_BASIC_COMPILER_H
diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h
index 152f49d..0b5beec 100644
--- a/include/swift/Demangling/Demangle.h
+++ b/include/swift/Demangling/Demangle.h
@@ -206,6 +206,8 @@
// Only to be used by the demangler parsers.
void addChild(NodePointer Child, NodeFactory &Factory);
+ // Only to be used by the demangler parsers.
+ void removeChildAt(unsigned Pos, NodeFactory &factory);
// Reverses the order of children.
void reverseChildren(size_t StartingAt = 0);
@@ -234,6 +236,12 @@
/// \param mangledName A null-terminated string containing a mangled name.
bool isSwiftSymbol(const char *mangledName);
+/// Returns true if the mangled name has the old scheme of function type
+/// mangling where labels are part of the type.
+///
+/// \param mangledName A null-terminated string containing a mangled name.
+bool isOldFunctionTypeMangling(const char *mangledName);
+
class Demangler;
/// The demangler context.
diff --git a/include/swift/Demangling/Demangler.h b/include/swift/Demangling/Demangler.h
index b34b3d6..ec0e4d1 100644
--- a/include/swift/Demangling/Demangler.h
+++ b/include/swift/Demangling/Demangler.h
@@ -290,6 +290,11 @@
StringRef Text;
size_t Pos = 0;
+ /// Mangling style where function type would have
+ /// labels attached to it, instead of having them
+ /// as part of the name.
+ bool IsOldFunctionTypeMangling = false;
+
Vector<NodePointer> NodeStack;
Vector<NodePointer> Substitutions;
Vector<unsigned> PendingSubstitutions;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 3340433..21aa961 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -861,8 +861,8 @@
MutableArrayRef<TypeLoc> inherited,
DeclContext *parent,
TrailingWhereClause *trailingWhereClause)
- : Decl(DeclKind::Extension, parent),
- GenericContext(DeclContextKind::ExtensionDecl, parent),
+ : GenericContext(DeclContextKind::ExtensionDecl, parent),
+ Decl(DeclKind::Extension, parent),
IterableDeclContext(IterableDeclContextKind::ExtensionDecl),
ExtensionLoc(extensionLoc),
ExtendedType(extendedType),
@@ -2490,8 +2490,8 @@
Identifier name, SourceLoc nameLoc,
MutableArrayRef<TypeLoc> inherited,
GenericParamList *GenericParams) :
- TypeDecl(K, DC, name, nameLoc, inherited),
- GenericContext(DeclContextKind::GenericTypeDecl, DC) {
+ GenericContext(DeclContextKind::GenericTypeDecl, DC),
+ TypeDecl(K, DC, name, nameLoc, inherited) {
setGenericParams(GenericParams);
}
@@ -5548,3 +5548,30 @@
&& "superclass must be interface type");
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
}
+
+ClangNode Decl::getClangNodeImpl() const {
+ assert(Bits.Decl.FromClang);
+ void * const *ptr = nullptr;
+ switch (getKind()) {
+#define DECL(Id, Parent) \
+ case DeclKind::Id: \
+ ptr = reinterpret_cast<void * const*>(static_cast<const Id##Decl*>(this)); \
+ break;
+#include "swift/AST/DeclNodes.def"
+ }
+ return ClangNode::getFromOpaqueValue(*(ptr - 1));
+}
+
+void Decl::setClangNode(ClangNode Node) {
+ Bits.Decl.FromClang = true;
+ // The extra/preface memory is allocated by the importer.
+ void **ptr = nullptr;
+ switch (getKind()) {
+#define DECL(Id, Parent) \
+ case DeclKind::Id: \
+ ptr = reinterpret_cast<void **>(static_cast<Id##Decl*>(this)); \
+ break;
+#include "swift/AST/DeclNodes.def"
+ }
+ *(ptr - 1) = Node.getOpaqueValue();
+}
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index b3bfe08..4eb4c1c 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -47,32 +47,15 @@
GenericTypeDecl *
DeclContext::getAsTypeOrTypeExtensionContext() const {
- switch (getContextKind()) {
- case DeclContextKind::Module:
- case DeclContextKind::FileUnit:
- case DeclContextKind::AbstractClosureExpr:
- case DeclContextKind::TopLevelCodeDecl:
- case DeclContextKind::AbstractFunctionDecl:
- case DeclContextKind::SubscriptDecl:
- case DeclContextKind::Initializer:
- case DeclContextKind::SerializedLocal:
- return nullptr;
-
- case DeclContextKind::ExtensionDecl: {
- auto ED = cast<ExtensionDecl>(this);
- auto type = ED->getExtendedType();
-
- if (!type)
+ if (auto decl = const_cast<Decl*>(getAsDeclOrDeclExtensionContext())) {
+ if (auto ED = dyn_cast<ExtensionDecl>(decl)) {
+ if (auto type = ED->getExtendedType())
+ return type->getAnyNominal();
return nullptr;
-
- return type->getAnyNominal();
+ }
+ return dyn_cast<GenericTypeDecl>(decl);
}
-
- case DeclContextKind::GenericTypeDecl:
- return const_cast<GenericTypeDecl*>(cast<GenericTypeDecl>(this));
- }
-
- llvm_unreachable("Unhandled DeclContextKind in switch.");
+ return nullptr;
}
/// If this DeclContext is a NominalType declaration or an
@@ -101,10 +84,11 @@
}
ProtocolDecl *DeclContext::getAsProtocolExtensionContext() const {
- if (getContextKind() != DeclContextKind::ExtensionDecl)
- return nullptr;
-
- return dyn_cast_or_null<ProtocolDecl>(getAsTypeOrTypeExtensionContext());
+ if (auto decl = const_cast<Decl*>(getAsDeclOrDeclExtensionContext()))
+ if (auto ED = dyn_cast<ExtensionDecl>(decl))
+ if (auto type = ED->getExtendedType())
+ return dyn_cast_or_null<ProtocolDecl>(type->getAnyNominal());
+ return nullptr;
}
GenericTypeParamType *DeclContext::getProtocolSelfType() const {
@@ -384,33 +368,10 @@
Decl *DeclContext::getInnermostDeclarationDeclContext() {
DeclContext *DC = this;
- while (DC) {
- switch (DC->getContextKind()) {
- case DeclContextKind::AbstractClosureExpr:
- case DeclContextKind::Initializer:
- case DeclContextKind::SerializedLocal:
- case DeclContextKind::Module:
- case DeclContextKind::FileUnit:
- break;
-
- case DeclContextKind::TopLevelCodeDecl:
- return cast<TopLevelCodeDecl>(DC);
-
- case DeclContextKind::AbstractFunctionDecl:
- return cast<AbstractFunctionDecl>(DC);
-
- case DeclContextKind::SubscriptDecl:
- return cast<SubscriptDecl>(DC);
-
- case DeclContextKind::GenericTypeDecl:
- return cast<GenericTypeDecl>(DC);
-
- case DeclContextKind::ExtensionDecl:
- return cast<ExtensionDecl>(DC);
- }
-
- DC = DC->getParent();
- }
+ do {
+ if (auto decl = DC->getAsDeclOrDeclExtensionContext())
+ return isa<ModuleDecl>(decl) ? nullptr : decl;
+ } while ((DC = DC->getParent()));
return nullptr;
}
@@ -1100,3 +1061,83 @@
return false;
}
+
+DeclContextKind DeclContext::getContextKind() const {
+ switch (ParentAndKind.getInt()) {
+ case ASTHierarchy::Expr:
+ return DeclContextKind::AbstractClosureExpr;
+ case ASTHierarchy::Initializer:
+ return DeclContextKind::Initializer;
+ case ASTHierarchy::SerializedLocal:
+ return DeclContextKind::SerializedLocal;
+ case ASTHierarchy::FileUnit:
+ return DeclContextKind::FileUnit;
+ case ASTHierarchy::Decl: {
+ auto decl = reinterpret_cast<const Decl*>(this + 1);
+ if (isa<AbstractFunctionDecl>(decl))
+ return DeclContextKind::AbstractFunctionDecl;
+ if (isa<GenericTypeDecl>(decl))
+ return DeclContextKind::GenericTypeDecl;
+ switch (decl->getKind()) {
+ case DeclKind::Module:
+ return DeclContextKind::Module;
+ case DeclKind::TopLevelCode:
+ return DeclContextKind::TopLevelCodeDecl;
+ case DeclKind::Subscript:
+ return DeclContextKind::SubscriptDecl;
+ case DeclKind::Extension:
+ return DeclContextKind::ExtensionDecl;
+ default:
+ llvm_unreachable("Unhandled Decl kind");
+ }
+ }
+ }
+ llvm_unreachable("Unhandled DeclContext ASTHierarchy");
+}
+
+#define DECL(Id, Parent) \
+ static_assert(!std::is_base_of<DeclContext, Id##Decl>::value, \
+ "Non-context Decl node has context?");
+#define CONTEXT_DECL(Id, Parent) \
+ static_assert(alignof(DeclContext) == alignof(Id##Decl), "Alignment error"); \
+ static_assert(std::is_base_of<DeclContext, Id##Decl>::value, \
+ "CONTEXT_DECL nodes must inherit from DeclContext");
+#define CONTEXT_VALUE_DECL(Id, Parent) \
+ static_assert(alignof(DeclContext) == alignof(Id##Decl), "Alignment error"); \
+ static_assert(std::is_base_of<DeclContext, Id##Decl>::value, \
+ "CONTEXT_VALUE_DECL nodes must inherit from DeclContext");
+#include "swift/AST/DeclNodes.def"
+
+#define EXPR(Id, Parent) \
+ static_assert(!std::is_base_of<DeclContext, Id##Expr>::value, \
+ "Non-context Expr node has context?");
+#define CONTEXT_EXPR(Id, Parent) \
+ static_assert(alignof(DeclContext) == alignof(Id##Expr), "Alignment error"); \
+ static_assert(std::is_base_of<DeclContext, Id##Expr>::value, \
+ "CONTEXT_EXPR nodes must inherit from DeclContext");
+#include "swift/AST/ExprNodes.def"
+
+#ifndef NDEBUG
+// XXX -- static_cast is not static enough for use with static_assert().
+// DO verify this by temporarily breaking a Decl or Expr.
+// DO NOT assume that the compiler will emit this code blindly.
+SWIFT_CONSTRUCTOR
+static void verify_DeclContext_is_start_of_node() {
+ auto decl = reinterpret_cast<Decl*>(0x1000 + sizeof(DeclContext));
+#define DECL(Id, Parent)
+#define CONTEXT_DECL(Id, Parent) \
+ assert(reinterpret_cast<DeclContext*>(0x1000) == \
+ static_cast<Id##Decl*>(decl));
+#define CONTEXT_VALUE_DECL(Id, Parent) \
+ assert(reinterpret_cast<DeclContext*>(0x1000) == \
+ static_cast<Id##Decl*>(decl));
+#include "swift/AST/DeclNodes.def"
+
+ auto expr = reinterpret_cast<Expr*>(0x1000 + sizeof(DeclContext));
+#define EXPR(Id, Parent)
+#define CONTEXT_EXPR(Id, Parent) \
+ assert(reinterpret_cast<DeclContext*>(0x1000) == \
+ static_cast<Id##Expr*>(expr));
+#include "swift/AST/ExprNodes.def"
+}
+#endif
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index fa2b376..bd943a8 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -347,8 +347,8 @@
//===----------------------------------------------------------------------===//
ModuleDecl::ModuleDecl(Identifier name, ASTContext &ctx)
- : TypeDecl(DeclKind::Module, &ctx, name, SourceLoc(), { }),
- DeclContext(DeclContextKind::Module, nullptr),
+ : DeclContext(DeclContextKind::Module, nullptr),
+ TypeDecl(DeclKind::Module, &ctx, name, SourceLoc(), { }),
Flags({0, 0, 0}) {
ctx.addDestructorCleanup(*this);
setImplicit();
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index df57f86..c0b0eff 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -136,6 +136,10 @@
return getManglingPrefixLength(mangledName) != 0;
}
+bool swift::Demangle::isOldFunctionTypeMangling(const char *mangledName) {
+ return mangledName[0] == '_' && mangledName[1] == 'T';
+}
+
namespace swift {
namespace Demangle {
@@ -151,6 +155,23 @@
Children[NumChildren++] = Child;
}
+void Node::removeChildAt(unsigned Pos, swift::Demangle::NodeFactory &factory) {
+ assert(Pos < NumChildren && "invalid child position!");
+
+ size_t Index = 0;
+ auto *NewChildren = factory.Allocate<NodePointer>(NumChildren - 1);
+ for (unsigned i = 0, n = NumChildren; i != n; ++i) {
+ auto Child = Children[i];
+ if (i != Pos) {
+ NewChildren[Index] = Child;
+ ++Index;
+ } else {
+ --NumChildren;
+ }
+ }
+ Children = NewChildren;
+}
+
void Node::reverseChildren(size_t StartingAt) {
assert(StartingAt <= NumChildren);
std::reverse(Children + StartingAt, Children + NumChildren);
@@ -257,6 +278,7 @@
if (PrefixLength == 0)
return nullptr;
+ IsOldFunctionTypeMangling = isOldFunctionTypeMangling(MangledName.data());
Pos += PrefixLength;
// If any other prefixes are accepted, please update Mangler::verify.
@@ -392,7 +414,7 @@
auto TypeMangling = createNode(Node::Kind::TypeMangling);
addChild(TypeMangling, LabelList);
- addChild(TypeMangling, Type);
+ TypeMangling = addChild(TypeMangling, Type);
return TypeMangling;
}
@@ -884,7 +906,7 @@
}
NodePointer Demangler::popFunctionParamLabels(NodePointer Type) {
- if (popNode(Node::Kind::EmptyList))
+ if (!IsOldFunctionTypeMangling && popNode(Node::Kind::EmptyList))
return createNode(Node::Kind::LabelList);
if (!Type || Type->getKind() != Node::Kind::Type)
@@ -905,15 +927,65 @@
if (ParameterType->getIndex() == 0)
return nullptr;
+ auto getChildIf =
+ [](NodePointer Node,
+ Node::Kind filterBy) -> std::pair<NodePointer, unsigned> {
+ for (unsigned i = 0, n = Node->getNumChildren(); i != n; ++i) {
+ auto Child = Node->getChild(i);
+ if (Child->getKind() == filterBy)
+ return {Child, i};
+ }
+ return {nullptr, 0};
+ };
+
+ auto getLabel = [&](NodePointer Params, unsigned Idx) -> NodePointer {
+ // Old-style function type mangling has labels as part of the argument.
+ if (IsOldFunctionTypeMangling) {
+ auto Param = Params->getChild(Idx);
+ auto Label = getChildIf(Param, Node::Kind::TupleElementName);
+
+ if (Label.first) {
+ Param->removeChildAt(Label.second, *this);
+ return createNodeWithAllocatedText(Node::Kind::Identifier,
+ Label.first->getText());
+ }
+
+ return createNode(Node::Kind::FirstElementMarker);
+ }
+
+ return popNode();
+ };
+
auto LabelList = createNode(Node::Kind::LabelList);
+ auto Tuple = ParameterType->getFirstChild()->getFirstChild();
+
+ if (IsOldFunctionTypeMangling &&
+ (!Tuple || Tuple->getKind() != Node::Kind::Tuple))
+ return LabelList;
+
+ bool hasLabels = false;
for (unsigned i = 0, n = ParameterType->getIndex(); i != n; ++i) {
- auto Label = popNode();
- assert(Label && (Label->getKind() == Node::Kind::Identifier ||
- Label->getKind() == Node::Kind::FirstElementMarker));
+ auto Label = getLabel(Tuple, i);
+
+ if (!Label)
+ return nullptr;
+
+ if (Label->getKind() != Node::Kind::Identifier &&
+ Label->getKind() != Node::Kind::FirstElementMarker)
+ return nullptr;
+
LabelList->addChild(Label, *this);
+ hasLabels |= Label->getKind() != Node::Kind::FirstElementMarker;
}
- LabelList->reverseChildren();
+ // Old style label mangling can produce label list without
+ // actual labels, we need to support that case specifically.
+ if (!hasLabels)
+ return createNode(Node::Kind::LabelList);
+
+ if (!IsOldFunctionTypeMangling)
+ LabelList->reverseChildren();
+
return LabelList;
}
@@ -1999,16 +2071,16 @@
case None:
break;
case Index:
- addChild(Entity, NameOrIndex);
+ Entity = addChild(Entity, NameOrIndex);
break;
case TypeAndMaybePrivateName:
addChild(Entity, LabelList);
- addChild(Entity, ParamType);
+ Entity = addChild(Entity, ParamType);
addChild(Entity, NameOrIndex);
break;
case TypeAndIndex:
- addChild(Entity, NameOrIndex);
- addChild(Entity, ParamType);
+ Entity = addChild(Entity, NameOrIndex);
+ Entity = addChild(Entity, ParamType);
break;
}
return Entity;
@@ -2035,9 +2107,9 @@
NodePointer Context = popContext();
NodePointer Subscript = createNode(Node::Kind::Subscript);
- addChild(Subscript, Context);
+ Subscript = addChild(Subscript, Context);
addChild(Subscript, LabelList);
- addChild(Subscript, Type);
+ Subscript = addChild(Subscript, Type);
addChild(Subscript, PrivateName);
return demangleAccessor(Subscript);
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index 63338be..fbc1ff1 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -163,16 +163,27 @@
DemanglerPrinter Printer;
DemangleOptions Options;
bool SpecializationPrefixPrinted = false;
+ bool isValid = true;
public:
NodePrinter(DemangleOptions options) : Options(options) {}
std::string printRoot(NodePointer root) {
+ isValid = true;
print(root);
- return std::move(Printer).str();
+ if (isValid)
+ return std::move(Printer).str();
+ return "";
}
-private:
+private:
+ /// Called when the node tree in valid.
+ ///
+ /// The demangler already catches most error cases and mostly produces valid
+ /// node trees. But some cases are difficult to catch in the demangler and
+ /// instead the NodePrinter bails.
+ void setInvalid() { isValid = false; }
+
void printChildren(Node::iterator begin,
Node::iterator end,
const char *sep = nullptr) {
@@ -553,7 +564,10 @@
void printFunctionParameters(NodePointer LabelList, NodePointer ParameterType,
bool showTypes) {
- assert(ParameterType->getKind() == Node::Kind::ArgumentTuple);
+ if (ParameterType->getKind() != Node::Kind::ArgumentTuple) {
+ setInvalid();
+ return;
+ }
NodePointer Parameters = ParameterType->getFirstChild();
assert(Parameters->getKind() == Node::Kind::Type);
@@ -609,7 +623,10 @@
}
void printFunctionType(NodePointer LabelList, NodePointer node) {
- assert(node->getNumChildren() == 2 || node->getNumChildren() == 3);
+ if (node->getNumChildren() != 2 && node->getNumChildren() != 3) {
+ setInvalid();
+ return;
+ }
unsigned startIndex = 0;
if (node->getChild(0)->getKind() == Node::Kind::ThrowsAnnotation)
startIndex = 1;
@@ -1925,6 +1942,10 @@
if (TypePr != TypePrinting::NoType) {
NodePointer type = getChildIf(Entity, Node::Kind::Type);
assert(type && "malformed entity");
+ if (!type) {
+ setInvalid();
+ return nullptr;
+ }
type = type->getChild(0);
if (TypePr == TypePrinting::FunctionStyle) {
// We expect to see a function type here, but if we don't, use the colon.
diff --git a/lib/IRGen/ProtocolInfo.h b/lib/IRGen/ProtocolInfo.h
index cb37b83..f69374b 100644
--- a/lib/IRGen/ProtocolInfo.h
+++ b/lib/IRGen/ProtocolInfo.h
@@ -29,9 +29,7 @@
namespace swift {
class CanType;
- class Decl;
class ProtocolConformance;
- class ProtocolDecl;
namespace irgen {
class ConformanceInfo; // private to GenProto.cpp
@@ -43,10 +41,11 @@
/// introduced by the protocol.
class WitnessTableEntry {
public:
- void *MemberOrAssociatedType;
+ llvm::PointerUnion<Decl *, TypeBase *> MemberOrAssociatedType;
ProtocolDecl *Protocol;
- WitnessTableEntry(void *member, ProtocolDecl *protocol)
+ WitnessTableEntry(llvm::PointerUnion<Decl *, TypeBase *> member,
+ ProtocolDecl *protocol)
: MemberOrAssociatedType(member), Protocol(protocol) {}
public:
@@ -54,15 +53,15 @@
static WitnessTableEntry forOutOfLineBase(ProtocolDecl *proto) {
assert(proto != nullptr);
- return WitnessTableEntry(nullptr, proto);
+ return WitnessTableEntry({}, proto);
}
/// Is this a base-protocol entry?
- bool isBase() const { return MemberOrAssociatedType == nullptr; }
+ bool isBase() const { return MemberOrAssociatedType.isNull(); }
bool matchesBase(ProtocolDecl *proto) const {
assert(proto != nullptr);
- return MemberOrAssociatedType == nullptr && Protocol == proto;
+ return MemberOrAssociatedType.isNull() && Protocol == proto;
}
/// Given that this is a base-protocol entry, is the table
@@ -83,19 +82,21 @@
}
bool isFunction() const {
- return Protocol == nullptr &&
- isa<AbstractFunctionDecl>(
- static_cast<Decl*>(MemberOrAssociatedType));
+ auto decl = MemberOrAssociatedType.get<Decl*>();
+ return Protocol == nullptr && isa<AbstractFunctionDecl>(decl);
}
bool matchesFunction(AbstractFunctionDecl *func) const {
assert(func != nullptr);
- return MemberOrAssociatedType == func && Protocol == nullptr;
+ if (auto decl = MemberOrAssociatedType.dyn_cast<Decl*>())
+ return decl == func && Protocol == nullptr;
+ return false;
}
AbstractFunctionDecl *getFunction() const {
assert(isFunction());
- return static_cast<AbstractFunctionDecl*>(MemberOrAssociatedType);
+ auto decl = MemberOrAssociatedType.get<Decl*>();
+ return static_cast<AbstractFunctionDecl*>(decl);
}
static WitnessTableEntry forAssociatedType(AssociatedType ty) {
@@ -103,19 +104,21 @@
}
bool isAssociatedType() const {
- return Protocol == nullptr &&
- isa<AssociatedTypeDecl>(
- static_cast<Decl*>(MemberOrAssociatedType));
+ if (auto decl = MemberOrAssociatedType.dyn_cast<Decl*>())
+ return Protocol == nullptr && isa<AssociatedTypeDecl>(decl);
+ return false;
}
bool matchesAssociatedType(AssociatedType assocType) const {
- return MemberOrAssociatedType == assocType.getAssociation() &&
- Protocol == nullptr;
+ if (auto decl = MemberOrAssociatedType.dyn_cast<Decl*>())
+ return decl == assocType.getAssociation() && Protocol == nullptr;
+ return false;
}
AssociatedTypeDecl *getAssociatedType() const {
assert(isAssociatedType());
- return static_cast<AssociatedTypeDecl*>(MemberOrAssociatedType);
+ auto decl = MemberOrAssociatedType.get<Decl*>();
+ return static_cast<AssociatedTypeDecl*>(decl);
}
static WitnessTableEntry forAssociatedConformance(AssociatedConformance conf){
@@ -124,17 +127,20 @@
}
bool isAssociatedConformance() const {
- return Protocol != nullptr && MemberOrAssociatedType != nullptr;
+ return Protocol != nullptr && !MemberOrAssociatedType.isNull();
}
bool matchesAssociatedConformance(const AssociatedConformance &conf) const {
- return MemberOrAssociatedType == conf.getAssociation().getPointer() &&
- Protocol == conf.getAssociatedRequirement();
+ if (auto type = MemberOrAssociatedType.dyn_cast<TypeBase*>())
+ return type == conf.getAssociation().getPointer() &&
+ Protocol == conf.getAssociatedRequirement();
+ return false;
}
CanType getAssociatedConformancePath() const {
assert(isAssociatedConformance());
- return CanType(static_cast<TypeBase *>(MemberOrAssociatedType));
+ auto type = MemberOrAssociatedType.get<TypeBase*>();
+ return CanType(type);
}
ProtocolDecl *getAssociatedConformanceRequirement() const {
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index b76b538..c62282b 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -475,6 +475,7 @@
return parseExprPostfix(Message, isExprBasic);
case tok::amp_prefix: {
+ SyntaxParsingContext AmpCtx(SyntaxContext, SyntaxKind::InOutExpr);
SourceLoc Loc = consumeToken(tok::amp_prefix);
ParserResult<Expr> SubExpr = parseExprUnary(Message, isExprBasic);
@@ -558,9 +559,11 @@
/// !
/// [ expression ]
ParserResult<Expr> Parser::parseExprKeyPath() {
+ SyntaxParsingContext KeyPathCtx(SyntaxContext, SyntaxKind::KeyPathExpr);
// Consume '\'.
SourceLoc backslashLoc = consumeToken(tok::backslash);
llvm::SaveAndRestore<SourceLoc> slashLoc(SwiftKeyPathSlashLoc, backslashLoc);
+ SyntaxParsingContext ExprCtx(SyntaxContext, SyntaxContextKind::Expr);
// FIXME: diagnostics
ParserResult<Expr> rootResult, pathResult;
@@ -606,6 +609,7 @@
/// '#keyPath' '(' unqualified-name ('.' unqualified-name) * ')'
///
ParserResult<Expr> Parser::parseExprKeyPathObjC() {
+ SyntaxParsingContext ObjcKPCtx(SyntaxContext, SyntaxKind::ObjcKeyPathExpr);
// Consume '#keyPath'.
SourceLoc keywordLoc = consumeToken(tok::pound_keyPath);
@@ -636,6 +640,7 @@
// Parse the sequence of unqualified-names.
ParserStatus status;
while (true) {
+ SyntaxParsingContext NamePieceCtx(SyntaxContext, SyntaxKind::ObjcNamePiece);
// Handle code completion.
if (Tok.is(tok::code_complete))
return handleCodeCompletion(!components.empty());
@@ -667,6 +672,9 @@
break;
}
+ // Collect all name pieces to an objc name.
+ SyntaxContext->collectNodesInPlace(SyntaxKind::ObjcName);
+
// Parse the closing ')'.
SourceLoc rParenLoc;
if (status.isError()) {
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 3376344..dabe4b9 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -3607,12 +3607,34 @@
}
void checkInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *IBSHI) {
- require(IBSHI->getBlockStorage()->getType().isAddress(),
+ auto storage = IBSHI->getBlockStorage();
+ require(storage->getType().isAddress(),
"block storage operand must be an address");
- auto storageTy
- = IBSHI->getBlockStorage()->getType().getAs<SILBlockStorageType>();
+
+ auto storageTy = storage->getType().getAs<SILBlockStorageType>();
require(storageTy, "block storage operand must be a @block_storage type");
-
+
+ auto captureTy = storageTy->getCaptureType();
+ if (auto capturedFnTy = captureTy->getAs<SILFunctionType>()) {
+ if (capturedFnTy->isNoEscape()) {
+ // If the capture is a noescape function then it must be possible to
+ // locally determine the value stored to initialize the storage for the
+ // capture. This is required to diagnose static exclusivity violations
+ // when a noescape closure is converted to a noescape block that
+ // is then passed to a function.
+ auto *storageProjection =
+ storage->getSingleUserOfType<ProjectBlockStorageInst>();
+ require(storageProjection,
+ "block storage operand with noescape capture must have "
+ "projection from block");
+
+ auto *storeInst = storageProjection->getSingleUserOfType<StoreInst>();
+ require(storeInst,
+ "block storage operand with noescape capture must have "
+ "store to projection");
+ }
+ }
+
require(IBSHI->getInvokeFunction()->getType().isObject(),
"invoke function operand must be a value");
auto invokeTy
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 75e8369..89fc3c4 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -524,7 +524,7 @@
Expr *buildDeclRef(ValueDecl *decl, DeclNameLoc loc, Type openedType,
ConstraintLocatorBuilder locator, bool implicit,
FunctionRefKind functionRefKind,
- AccessSemantics semantics) {
+ AccessSemantics semantics, bool forceUnwrap) {
// Determine the declaration selected for this overloaded reference.
auto &ctx = cs.getASTContext();
@@ -554,7 +554,7 @@
ConformanceCheckFlags::Used));
if (conformance && conformance->isConcrete()) {
if (auto witness =
- conformance->getConcrete()->getWitnessDecl(decl, &tc)) {
+ conformance->getConcrete()->getWitnessDecl(decl, &tc)) {
// Hack up an AST that we can type-check (independently) to get
// it into the right form.
// FIXME: the hop through 'getDecl()' is because
@@ -583,11 +583,14 @@
cs.cacheExprTypes(refExpr);
- // Remove an outer function-conversion expression. This
- // happens when we end up referring to a witness for a
- // superclass conformance, and 'Self' differs.
- if (auto fnConv = dyn_cast<FunctionConversionExpr>(refExpr))
- refExpr = fnConv->getSubExpr();
+ // Remove an outer function-conversion expression. This
+ // happens when we end up referring to a witness for a
+ // superclass conformance, and 'Self' differs.
+ if (auto fnConv = dyn_cast<FunctionConversionExpr>(refExpr))
+ refExpr = fnConv->getSubExpr();
+
+ if (forceUnwrap)
+ return forceUnwrapResult(refExpr);
return refExpr;
}
@@ -600,10 +603,10 @@
TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy, ctx);
cs.cacheExprTypes(base);
- return buildMemberRef(base, openedType, SourceLoc(), decl,
- loc, openedFnType->getResult(),
- locator, locator, implicit, functionRefKind,
- semantics, /*isDynamic=*/false);
+ return buildMemberRef(base, openedType, SourceLoc(), decl, loc,
+ openedFnType->getResult(), locator, locator,
+ implicit, functionRefKind, semantics,
+ /*isDynamic=*/false, forceUnwrap);
}
auto type = solution.simplifyType(openedType);
@@ -636,6 +639,9 @@
loc, implicit, semantics, type);
cs.cacheType(declRefExpr);
declRefExpr->setFunctionRefKind(functionRefKind);
+ if (forceUnwrap)
+ return forceUnwrapResult(declRefExpr);
+
return declRefExpr;
}
@@ -878,9 +884,10 @@
Expr *buildMemberRef(Expr *base, Type openedFullType, SourceLoc dotLoc,
ValueDecl *member, DeclNameLoc memberLoc,
Type openedType, ConstraintLocatorBuilder locator,
- ConstraintLocatorBuilder memberLocator,
- bool Implicit, FunctionRefKind functionRefKind,
- AccessSemantics semantics, bool isDynamic) {
+ ConstraintLocatorBuilder memberLocator, bool Implicit,
+ FunctionRefKind functionRefKind,
+ AccessSemantics semantics, bool isDynamic,
+ bool forceUnwrap) {
auto &tc = cs.getTypeChecker();
auto &context = tc.Context;
@@ -933,9 +940,11 @@
auto ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit);
cs.setType(ref, refTy);
ref->setFunctionRefKind(functionRefKind);
- return cs.cacheType(new (context)
- DotSyntaxBaseIgnoredExpr(base, dotLoc, ref,
- cs.getType(ref)));
+ auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
+ base, dotLoc, ref, cs.getType(ref)));
+ if (forceUnwrap)
+ return forceUnwrapResult(DSBI);
+ return DSBI;
}
// The formal type of the 'self' value for the member's declaration.
@@ -1056,6 +1065,8 @@
}
}
+ if (forceUnwrap)
+ return forceUnwrapResult(ref);
return ref;
}
@@ -1082,6 +1093,8 @@
cs.setType(memberRefExpr, simplifyType(openedType));
Expr *result = memberRefExpr;
closeExistential(result, locator);
+ if (forceUnwrap)
+ return forceUnwrapResult(result);
return result;
}
@@ -1102,6 +1115,8 @@
ApplyExpr *apply;
if (isa<ConstructorDecl>(member)) {
// FIXME: Provide type annotation.
+ if (forceUnwrap)
+ ref = forceUnwrapResult(ref);
apply = new (context) ConstructorRefCallExpr(ref, base);
} else if (!baseIsInstance && member->isInstanceMember()) {
// Reference to an unbound instance method.
@@ -1110,10 +1125,15 @@
cs.getType(ref));
cs.cacheType(result);
closeExistential(result, locator, /*force=*/openedExistential);
+ if (forceUnwrap)
+ return forceUnwrapResult(result);
return result;
} else {
assert((!baseIsInstance || member->isInstanceMember()) &&
"can't call a static method on an instance");
+ if (forceUnwrap)
+ ref = forceUnwrapResult(ref);
+
apply = new (context) DotSyntaxCallExpr(ref, dotLoc, base);
if (Implicit) {
apply->setImplicit();
@@ -1358,8 +1378,9 @@
Expr *buildSubscript(Expr *base, Expr *index,
ArrayRef<Identifier> argLabels,
bool hasTrailingClosure,
- ConstraintLocatorBuilder locator,
- bool isImplicit, AccessSemantics semantics) {
+ ConstraintLocatorBuilder locator, bool isImplicit,
+ AccessSemantics semantics) {
+
// Determine the declaration selected for this subscript operation.
auto selected = getOverloadChoiceIfAvailable(
cs.getConstraintLocator(
@@ -1386,13 +1407,31 @@
return nullptr;
}
- auto choice = selected->choice;
-
+ // Build the new subscript.
+ auto newSubscript = buildSubscriptHelper(base, index, argLabels,
+ *selected, hasTrailingClosure,
+ locator, isImplicit, semantics);
+
+ if (shouldForceUnwrapResult(cs.getConstraintLocator(locator)->getAnchor(),
+ selected->choice))
+ return forceUnwrapResult(newSubscript);
+
+ return newSubscript;
+ }
+
+ Expr *buildSubscriptHelper(Expr *base, Expr *index,
+ ArrayRef<Identifier> argLabels,
+ SelectedOverload &selected,
+ bool hasTrailingClosure,
+ ConstraintLocatorBuilder locator,
+ bool isImplicit, AccessSemantics semantics) {
+ auto choice = selected.choice;
+
// Apply a key path if we have one.
if (choice.getKind() == OverloadChoiceKind::KeyPathApplication) {
- auto applicationTy = simplifyType(selected->openedType)
- ->castTo<FunctionType>();
-
+ auto applicationTy =
+ simplifyType(selected.openedType)->castTo<FunctionType>();
+
index = cs.coerceToRValue(index);
// The index argument should be (keyPath: KeyPath<Root, Value>).
// Dig the key path expression out of the argument tuple.
@@ -1495,7 +1534,7 @@
}
// Figure out the index and result types.
- auto subscriptTy = simplifyType(selected->openedType);
+ auto subscriptTy = simplifyType(selected.openedType);
auto subscriptFnTy = subscriptTy->castTo<AnyFunctionType>();
auto resultTy = subscriptFnTy->getResult();
@@ -1551,7 +1590,7 @@
}
// Convert the base.
- auto openedFullFnType = selected->openedFullType->castTo<FunctionType>();
+ auto openedFullFnType = selected.openedFullType->castTo<FunctionType>();
auto openedBaseType = openedFullFnType->getInput();
auto containerTy = solution.simplifyType(openedBaseType);
base = coerceObjectArgumentToType(
@@ -2362,6 +2401,31 @@
return expr;
}
+ bool shouldForceUnwrapResult(Expr *expr, OverloadChoice &choice) {
+ if (!choice.isImplicitlyUnwrappedValueOrReturnValue())
+ return false;
+
+ auto choiceLocator = cs.getConstraintLocator(
+ expr, ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice);
+
+ return solution.getDisjunctionChoice(choiceLocator);
+ }
+
+ Expr *forceUnwrapResult(Expr *newExpr) {
+ auto ty = simplifyType(cs.getType(newExpr));
+
+ if (auto *fnTy = ty->getAs<AnyFunctionType>()) {
+ auto underlyingType = cs.replaceFinalResultTypeWithUnderlying(fnTy);
+
+ auto &ctx = cs.getTypeChecker().Context;
+ return cs.cacheType(new (ctx) ImplicitlyUnwrappedFunctionConversionExpr(
+ newExpr, underlyingType));
+ } else {
+ return coerceImplicitlyUnwrappedOptionalToValue(
+ newExpr, ty->getWithoutSpecifierType()->getAnyOptionalObjectType());
+ }
+ }
+
Expr *visitDeclRefExpr(DeclRefExpr *expr) {
auto locator = cs.getConstraintLocator(expr);
@@ -2378,13 +2442,11 @@
auto choice = selected->choice;
auto decl = choice.getDecl();
- // FIXME: Cannibalize the existing DeclRefExpr rather than allocating a
- // new one?
+ auto forceUnwrap = shouldForceUnwrapResult(expr, choice);
return buildDeclRef(decl, expr->getNameLoc(), selected->openedFullType,
- locator,
- expr->isImplicit(),
+ locator, expr->isImplicit(),
expr->getFunctionRefKind(),
- expr->getAccessSemantics());
+ expr->getAccessSemantics(), forceUnwrap);
}
Expr *visitSuperRefExpr(SuperRefExpr *expr) {
@@ -2416,10 +2478,11 @@
auto choice = selected.choice;
auto decl = choice.getDecl();
+ auto forceUnwrap = shouldForceUnwrapResult(expr, choice);
return buildDeclRef(decl, expr->getNameLoc(), selected.openedFullType,
locator, expr->isImplicit(),
choice.getFunctionRefKind(),
- AccessSemantics::Ordinary);
+ AccessSemantics::Ordinary, forceUnwrap);
}
Expr *visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *expr) {
@@ -2439,17 +2502,13 @@
auto selected = getOverloadChoice(memberLocator);
bool isDynamic
= selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
- return buildMemberRef(expr->getBase(),
- selected.openedFullType,
- expr->getDotLoc(),
- selected.choice.getDecl(), expr->getNameLoc(),
- selected.openedType,
- cs.getConstraintLocator(expr),
- memberLocator,
- expr->isImplicit(),
- selected.choice.getFunctionRefKind(),
- expr->getAccessSemantics(),
- isDynamic);
+ auto forceUnwrap = shouldForceUnwrapResult(expr, selected.choice);
+ return buildMemberRef(
+ expr->getBase(), selected.openedFullType, expr->getDotLoc(),
+ selected.choice.getDecl(), expr->getNameLoc(), selected.openedType,
+ cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
+ selected.choice.getFunctionRefKind(), expr->getAccessSemantics(),
+ isDynamic, forceUnwrap);
}
Expr *visitDynamicMemberRefExpr(DynamicMemberRefExpr *expr) {
@@ -2493,17 +2552,13 @@
// Build the member reference.
bool isDynamic
= selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
- auto result = buildMemberRef(base,
- selected.openedFullType,
- expr->getDotLoc(), member,
- expr->getNameLoc(),
- selected.openedType,
- cs.getConstraintLocator(expr),
- memberLocator,
- expr->isImplicit(),
- selected.choice.getFunctionRefKind(),
- AccessSemantics::Ordinary,
- isDynamic);
+ auto forceUnwrap = shouldForceUnwrapResult(expr, selected.choice);
+ auto result = buildMemberRef(
+ base, selected.openedFullType, expr->getDotLoc(), member,
+ expr->getNameLoc(), selected.openedType,
+ cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
+ selected.choice.getFunctionRefKind(), AccessSemantics::Ordinary,
+ isDynamic, forceUnwrap);
if (!result)
return nullptr;
@@ -2520,8 +2575,7 @@
result = finishApply(apply, Type(), cs.getConstraintLocator(expr));
}
- result = coerceToType(result, resultTy, cs.getConstraintLocator(expr));
- return result;
+ return coerceToType(result, resultTy, cs.getConstraintLocator(expr));
}
private:
@@ -2550,15 +2604,12 @@
// If the subexpression is a metatype, build a direct reference to the
// constructor.
if (cs.getType(base)->is<AnyMetatypeType>()) {
- return buildMemberRef(base, openedType, dotLoc, ctor, nameLoc,
- cs.getType(expr),
- ConstraintLocatorBuilder(
- cs.getConstraintLocator(expr)),
- ctorLocator,
- implicit,
- functionRefKind,
- AccessSemantics::Ordinary,
- /*isDynamic=*/false);
+ return buildMemberRef(
+ base, openedType, dotLoc, ctor, nameLoc, cs.getType(expr),
+ ConstraintLocatorBuilder(cs.getConstraintLocator(expr)),
+ ctorLocator, implicit, functionRefKind, AccessSemantics::Ordinary,
+ /*isDynamic=*/false,
+ /*forceUnwrap=*/false);
}
// The subexpression must be either 'self' or 'super'.
@@ -2675,24 +2726,15 @@
case OverloadChoiceKind::Decl:
case OverloadChoiceKind::DeclViaUnwrappedOptional:
- case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
case OverloadChoiceKind::DeclViaDynamic: {
bool isDynamic
= selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
- auto member = buildMemberRef(base,
- selected.openedFullType,
- dotLoc,
- selected.choice.getDecl(),
- nameLoc,
- selected.openedType,
- cs.getConstraintLocator(expr),
- memberLocator,
- implicit,
- selected.choice.getFunctionRefKind(),
- AccessSemantics::Ordinary,
- isDynamic);
-
- return member;
+ auto forceUnwrap = shouldForceUnwrapResult(expr, selected.choice);
+ return buildMemberRef(
+ base, selected.openedFullType, dotLoc, selected.choice.getDecl(),
+ nameLoc, selected.openedType, cs.getConstraintLocator(expr),
+ memberLocator, implicit, selected.choice.getFunctionRefKind(),
+ AccessSemantics::Ordinary, isDynamic, forceUnwrap);
}
case OverloadChoiceKind::TupleIndex: {
@@ -3433,7 +3475,7 @@
return nullptr;
return coerceImplicitlyUnwrappedOptionalToValue(
- coerced, cs.getType(coerced)->getOptionalObjectType());
+ coerced, cs.getType(coerced)->getAnyOptionalObjectType());
}
return visitCoerceExpr(expr, None);
@@ -3518,7 +3560,7 @@
return nullptr;
return coerceImplicitlyUnwrappedOptionalToValue(
- coerced, cs.getType(coerced)->getOptionalObjectType());
+ coerced, cs.getType(coerced)->getAnyOptionalObjectType());
}
return handleForcedCheckedCastExpr(expr);
@@ -3598,7 +3640,7 @@
return nullptr;
return coerceImplicitlyUnwrappedOptionalToValue(
- coerced, cs.getType(coerced)->getOptionalObjectType());
+ coerced, cs.getType(coerced)->getAnyOptionalObjectType());
}
return handleConditionalCheckedCastExpr(expr);
@@ -7145,6 +7187,12 @@
if (auto fnTy = cs.lookThroughImplicitlyUnwrappedOptionalType(cs.getType(fn)))
fn = coerceImplicitlyUnwrappedOptionalToValue(fn, fnTy);
+ bool unwrapResult = false;
+ if (auto *IUOFnTy = dyn_cast<ImplicitlyUnwrappedFunctionConversionExpr>(fn)) {
+ unwrapResult = true;
+ fn = IUOFnTy->getSubExpr();
+ }
+
// If we're applying a function that resulted from a covariant
// function conversion, strip off that conversion.
// FIXME: It would be nicer if we could build the ASTs properly in the
@@ -7249,9 +7297,16 @@
}
}
}
+
+ if (unwrapResult)
+ return forceUnwrapResult(result);
+
return result;
}
+ // FIXME: handle unwrapping everywhere else
+ assert(!unwrapResult);
+
// If this is an UnresolvedType in the system, preserve it.
if (cs.getType(fn)->is<UnresolvedType>()) {
cs.setType(apply, cs.getType(fn));
@@ -7308,17 +7363,13 @@
// Consider the constructor decl reference expr 'implicit', but the
// constructor call expr itself has the apply's 'implicitness'.
bool isDynamic = choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
- Expr *declRef = buildMemberRef(fn,
- selected->openedFullType,
- /*dotLoc=*/SourceLoc(),
- decl, DeclNameLoc(fn->getEndLoc()),
- selected->openedType,
- locator,
- ctorLocator,
- /*Implicit=*/true,
- choice.getFunctionRefKind(),
- AccessSemantics::Ordinary,
- isDynamic);
+ auto forceUnwrap = shouldForceUnwrapResult(apply, choice);
+ Expr *declRef =
+ buildMemberRef(fn, selected->openedFullType,
+ /*dotLoc=*/SourceLoc(), decl, DeclNameLoc(fn->getEndLoc()),
+ selected->openedType, locator, ctorLocator,
+ /*Implicit=*/true, choice.getFunctionRefKind(),
+ AccessSemantics::Ordinary, isDynamic, forceUnwrap);
if (!declRef)
return nullptr;
declRef->setImplicit(apply->isImplicit());
@@ -8008,15 +8059,13 @@
ExprRewriter rewriter(cs, solution,
/*suppressDiagnostics=*/false);
- auto memberRef = rewriter.buildMemberRef(base, openedFullType,
- base->getStartLoc(),
- witness,
- DeclNameLoc(base->getEndLoc()),
- openedType, dotLocator, dotLocator,
- /*Implicit=*/true,
- FunctionRefKind::SingleApply,
- AccessSemantics::Ordinary,
- /*isDynamic=*/false);
+ auto memberRef = rewriter.buildMemberRef(
+ base, openedFullType, base->getStartLoc(), witness,
+ DeclNameLoc(base->getEndLoc()), openedType, dotLocator, dotLocator,
+ /*Implicit=*/true, FunctionRefKind::SingleApply,
+ AccessSemantics::Ordinary,
+ /*isDynamic=*/false,
+ /*forceUnwrap=*/false);
call->setFn(memberRef);
// Call the witness.
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index bea8ac3..00cc13e 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -522,7 +522,6 @@
case OverloadChoiceKind::DeclViaDynamic:
case OverloadChoiceKind::DeclViaBridge:
case OverloadChoiceKind::DeclViaUnwrappedOptional:
- case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
// FIXME: show deduced types, etc, etc.
if (EmittedDecls.insert(choice.getDecl()).second)
tc.diagnose(choice.getDecl(), diag::found_candidate);
@@ -8404,8 +8403,7 @@
if (resolved->Locator != locator) continue;
// We only handle the simplest decl binding.
- if (resolved->Choice.getKind() != OverloadChoiceKind::Decl
- && resolved->Choice.getKind() != OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional)
+ if (resolved->Choice.getKind() != OverloadChoiceKind::Decl)
return nullptr;
return resolved->Choice.getDecl();
}
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 5d08812..bfd98e3 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -997,13 +997,8 @@
TVO_CanBindToLValue |
TVO_CanBindToInOut);
- OverloadChoice choice;
- if (decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
- choice = OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
- CS.getType(base), decl, functionRefKind);
- } else {
- choice = OverloadChoice(CS.getType(base), decl, functionRefKind);
- }
+ OverloadChoice choice =
+ OverloadChoice(CS.getType(base), decl, functionRefKind);
auto locator = CS.getConstraintLocator(expr, ConstraintLocator::Member);
CS.addBindOverloadConstraint(tv, choice, locator, CurDC);
@@ -1106,13 +1101,8 @@
// a known subscript here. This might be cleaner if we split off a new
// UnresolvedSubscriptExpr from SubscriptExpr.
if (auto decl = declOrNull) {
- OverloadChoice choice;
- if (decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
- choice = OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
- baseTy, decl, FunctionRefKind::DoubleApply);
- } else {
- choice = OverloadChoice(baseTy, decl, FunctionRefKind::DoubleApply);
- }
+ OverloadChoice choice =
+ OverloadChoice(baseTy, decl, FunctionRefKind::DoubleApply);
CS.addBindOverloadConstraint(fnTy, choice, memberLocator,
CurDC);
} else {
@@ -1309,15 +1299,8 @@
auto tv = CS.createTypeVariable(locator,
TVO_CanBindToLValue);
- OverloadChoice choice;
- if (E->getDecl()
- ->getAttrs()
- .hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
- choice = OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
- Type(), E->getDecl(), E->getFunctionRefKind());
- } else {
- choice = OverloadChoice(Type(), E->getDecl(), E->getFunctionRefKind());
- }
+ OverloadChoice choice =
+ OverloadChoice(Type(), E->getDecl(), E->getFunctionRefKind());
CS.resolveOverload(locator, tv, choice, CurDC);
if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
@@ -1394,15 +1377,8 @@
if (decls[i]->isInvalid())
continue;
- OverloadChoice choice;
- if (decls[i]
- ->getAttrs()
- .hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
- choice = OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
- Type(), decls[i], expr->getFunctionRefKind());
- } else {
- choice = OverloadChoice(Type(), decls[i], expr->getFunctionRefKind());
- }
+ OverloadChoice choice =
+ OverloadChoice(Type(), decls[i], expr->getFunctionRefKind());
choices.push_back(choice);
}
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index e5b6a37..4f38811 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -131,26 +131,10 @@
return false;
}
-static bool sameChoiceKind(const OverloadChoice &lhs,
- const OverloadChoice &rhs) {
- if (lhs.getKind() == rhs.getKind())
- return true;
-
- if (lhs.getKind() == OverloadChoiceKind::Decl
- && rhs.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional)
- return true;
-
- if (lhs.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional
- && rhs.getKind() == OverloadChoiceKind::Decl)
- return true;
-
- return false;
-}
-
/// \brief Compare two overload choices for equality.
static bool sameOverloadChoice(const OverloadChoice &x,
const OverloadChoice &y) {
- if (!sameChoiceKind(x, y))
+ if (x.getKind() != y.getKind())
return false;
switch (x.getKind()) {
@@ -163,7 +147,6 @@
case OverloadChoiceKind::DeclViaDynamic:
case OverloadChoiceKind::DeclViaBridge:
case OverloadChoiceKind::DeclViaUnwrappedOptional:
- case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
return sameDecl(x.getDecl(), y.getDecl());
case OverloadChoiceKind::TupleIndex:
@@ -834,14 +817,13 @@
}
// If the kinds of overload choice don't match...
- if (!sameChoiceKind(choice1, choice2)) {
+ if (choice1.getKind() != choice2.getKind()) {
identical = false;
// A declaration found directly beats any declaration found via dynamic
// lookup, bridging, or optional unwrapping.
- if ((choice1.getKind() == OverloadChoiceKind::Decl
- || choice1.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional) &&
- (choice2.getKind() == OverloadChoiceKind::DeclViaDynamic ||
+ if ((choice1.getKind() == OverloadChoiceKind::Decl) &&
+ (choice2.getKind() == OverloadChoiceKind::DeclViaDynamic ||
choice2.getKind() == OverloadChoiceKind::DeclViaBridge ||
choice2.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional)) {
score1 += weight;
@@ -851,8 +833,7 @@
if ((choice1.getKind() == OverloadChoiceKind::DeclViaDynamic ||
choice1.getKind() == OverloadChoiceKind::DeclViaBridge ||
choice1.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional) &&
- (choice2.getKind() == OverloadChoiceKind::Decl
- || choice2.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional)) {
+ choice2.getKind() == OverloadChoiceKind::Decl) {
score2 += weight;
continue;
}
@@ -874,7 +855,6 @@
case OverloadChoiceKind::Decl:
case OverloadChoiceKind::DeclViaBridge:
case OverloadChoiceKind::DeclViaUnwrappedOptional:
- case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
break;
}
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 5cd68af..8653398 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1521,6 +1521,49 @@
return SolutionKind::Solved;
}
+ // If we're binding an optional type, or function type that has an
+ // optional result type, this may be the result of an IUO
+ // declaration. These are candidates for creating a disjunction.
+ bool isOptional = false;
+ if (type->getRValueType()->getAnyOptionalObjectType()) {
+ isOptional = true;
+ } else if (auto *fnTy = type->getAs<AnyFunctionType>()) {
+ auto resultTy = fnTy->getResult();
+ while (resultTy->is<AnyFunctionType>())
+ resultTy = resultTy->castTo<AnyFunctionType>()->getResult();
+
+ // FIXME: work-around the fact that doesStorageProduceLValue returns true
+ // for
+ // #selector(getter: NSMenuItem.action)
+ resultTy = resultTy->getRValueType();
+
+ if (resultTy->getAnyOptionalObjectType()) {
+ isOptional = true;
+ }
+ }
+
+ if (isOptional) {
+ SmallVector<LocatorPathElt, 4> path;
+ locator.getLocatorParts(path);
+
+ // Find the last element that is either an indication we need to
+ // create a disjunction, or an indication that we already have.
+ auto last = std::find_if(
+ path.rbegin(), path.rend(), [](LocatorPathElt &elt) -> bool {
+ return elt.getKind() == ConstraintLocator::ImplicitlyUnwrappedValue ||
+ elt.getKind() ==
+ ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice;
+ });
+
+ // If we need to create a disjunction for this value, do so.
+ if (last != path.rend() &&
+ last->getKind() == ConstraintLocator::ImplicitlyUnwrappedValue) {
+ buildDisjunctionForImplicitlyUnwrappedOptional(
+ typeVar, type, getConstraintLocator(locator));
+ return SolutionKind::Solved;
+ }
+ }
+
assignFixedType(typeVar, type);
return SolutionKind::Solved;
@@ -3207,11 +3250,6 @@
functionRefKind);
}
- if (cand->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
- return OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
- baseTy, cand, functionRefKind);
- }
-
return OverloadChoice(baseTy, cand, functionRefKind);
};
diff --git a/lib/Sema/CalleeCandidateInfo.cpp b/lib/Sema/CalleeCandidateInfo.cpp
index f70ad84..75e642e 100644
--- a/lib/Sema/CalleeCandidateInfo.cpp
+++ b/lib/Sema/CalleeCandidateInfo.cpp
@@ -830,8 +830,7 @@
// Look through optional or IUO to get the underlying type the decl was
// found in.
substType = substType->getAnyOptionalObjectType();
- } else if (cand.getKind() != OverloadChoiceKind::Decl
- && cand.getKind() != OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional) {
+ } else if (cand.getKind() != OverloadChoiceKind::Decl) {
// Otherwise, if it is a remapping we can't handle, don't try to compute
// a substitution.
substType = Type();
diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp
index 49f4d08..8d68fa9 100644
--- a/lib/Sema/Constraint.cpp
+++ b/lib/Sema/Constraint.cpp
@@ -358,10 +358,6 @@
Out << "decl-via-unwrapped-optional ";
printDecl();
break;
- case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
- Out << "decl-for-implicitly-unwrapped-optional ";
- printDecl();
- break;
case OverloadChoiceKind::BaseType:
Out << "base type";
break;
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index a5795b5..5717faf 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1403,9 +1403,8 @@
OverloadChoice choice,
Type &refType,
Type &openedFullType) {
- assert(choice.getKind() == OverloadChoiceKind::Decl
- || choice.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional);
-
+ assert(choice.getKind() == OverloadChoiceKind::Decl);
+
switch (CS.TC.getDeclTypeCheckingSemantics(choice.getDecl())) {
case DeclTypeCheckingSemantics::Normal:
return false;
@@ -1515,7 +1514,6 @@
Type openedFullType;
switch (auto kind = choice.getKind()) {
case OverloadChoiceKind::Decl:
- case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
// If we refer to a top-level decl with special type-checking semantics,
// handle it now.
if (resolveOverloadForDeclWithSpecialTypeCheckingSemantics(
@@ -1675,8 +1673,7 @@
// value. Processing the bind constraint will generate a new
// disjunction constraint that attempts the Optional and if that
// doesn't succeed, the underlying type.
- if (choice.getKind() ==
- OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional) {
+ if (choice.isImplicitlyUnwrappedValueOrReturnValue()) {
locator = getConstraintLocator(locator,
ConstraintLocator::ImplicitlyUnwrappedValue);
}
@@ -1838,7 +1835,6 @@
case OverloadChoiceKind::DeclViaDynamic:
case OverloadChoiceKind::DeclViaBridge:
case OverloadChoiceKind::DeclViaUnwrappedOptional:
- case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
return getDecl()->getFullName();
case OverloadChoiceKind::KeyPathApplication: {
@@ -1855,3 +1851,10 @@
llvm_unreachable("Unhandled OverloadChoiceKind in switch.");
}
+
+bool OverloadChoice::isImplicitlyUnwrappedValueOrReturnValue() const {
+ // FIXME: Disable new IUO implementation for now.
+ return false;
+ return isDecl() &&
+ getDecl()->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
+}
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 6947b61..7b829f8 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -2331,6 +2331,36 @@
ConstraintLocatorBuilder locator);
public:
+ /// Given a function type where the eventual result type is an optional,
+ /// where "eventual result type" is defined as:
+ /// 1. The result type is an optional
+ /// 2. The result type is a function type with an eventual result
+ /// type that is an optional.
+ ///
+ /// return the same function type but with the eventual result type
+ /// replaced by its underlying type.
+ ///
+ /// i.e. return (S) -> T for (S) -> T?
+ // return (X) -> () -> Y for (X) -> () -> Y?
+ Type replaceFinalResultTypeWithUnderlying(AnyFunctionType *fnTy) {
+ auto resultTy = fnTy->getResult();
+ if (auto *resultFnTy = resultTy->getAs<AnyFunctionType>())
+ resultTy = replaceFinalResultTypeWithUnderlying(resultFnTy);
+ else
+ resultTy =
+ resultTy->getWithoutSpecifierType()->getAnyOptionalObjectType();
+
+ assert(resultTy);
+
+ if (auto *genericFn = fnTy->getAs<GenericFunctionType>()) {
+ return GenericFunctionType::get(genericFn->getGenericSignature(),
+ genericFn->getParams(), resultTy,
+ genericFn->getExtInfo());
+ }
+
+ return FunctionType::get(fnTy->getParams(), resultTy, fnTy->getExtInfo());
+ }
+
// Build a disjunction for the choices between an Optional type and
// it's underlying type. We'll make the choice of the Optional
// preferred, and select that if the expression type-checks
@@ -2351,31 +2381,17 @@
bindToOptional->setFavored();
Type underlyingType;
- if (auto *fnTy = type->getAs<AnyFunctionType>()) {
- auto resultTy = fnTy->getResult();
- while (resultTy->is<AnyFunctionType>())
- resultTy = resultTy->castTo<AnyFunctionType>()->getResult();
-
- assert(resultTy->getAnyOptionalObjectType());
-
- if (auto genericFn = type->getAs<GenericFunctionType>()) {
- underlyingType = GenericFunctionType::get(
- genericFn->getGenericSignature(), genericFn->getParams(),
- resultTy->getAnyOptionalObjectType(), genericFn->getExtInfo());
- } else {
- underlyingType = FunctionType::get(fnTy->getParams(),
- resultTy->getAnyOptionalObjectType(),
- fnTy->getExtInfo());
- }
- } else {
+ if (auto *fnTy = type->getAs<AnyFunctionType>())
+ underlyingType = replaceFinalResultTypeWithUnderlying(fnTy);
+ else
underlyingType =
type->getWithoutSpecifierType()->getAnyOptionalObjectType();
- assert(underlyingType);
- if (type->is<LValueType>())
- underlyingType = LValueType::get(underlyingType);
- assert(!type->is<InOutType>());
- }
+ assert(underlyingType);
+
+ if (type->is<LValueType>())
+ underlyingType = LValueType::get(underlyingType);
+ assert(!type->is<InOutType>());
auto *bindToUnderlying = Constraint::create(
*this, ConstraintKind::Bind, tv, underlyingType, disjunctionLocator);
diff --git a/lib/Sema/OverloadChoice.h b/lib/Sema/OverloadChoice.h
index 32d3fff..524e75f 100644
--- a/lib/Sema/OverloadChoice.h
+++ b/lib/Sema/OverloadChoice.h
@@ -53,10 +53,6 @@
/// \brief The overload choice selects a particular declaration that
/// was found by unwrapping an optional context type.
DeclViaUnwrappedOptional,
- /// \brief The overload choice selects a declaration that is
- /// implicitly unwrapped only when needed in order to successfully
- /// type check an expression.
- DeclForImplicitlyUnwrappedOptional,
/// \brief The overload choice indexes into a tuple. Index zero will
/// have the value of this enumerator, index one will have the value of this
/// enumerator + 1, and so on. Thus, this enumerator must always be last.
@@ -79,9 +75,6 @@
/// Indicates that this declaration was dynamic, turning a
/// "Decl" kind into "DeclViaDynamic" kind.
IsDeclViaDynamic = 0x03,
- /// Indicates that this declaration is of an Optional that is
- /// implicitly unwrapped.
- IsDeclForImplicitlyUnwrappedOptional = 0x04,
};
/// \brief The base type to be used when referencing the declaration
@@ -127,7 +120,6 @@
kind != OverloadChoiceKind::DeclViaDynamic &&
kind != OverloadChoiceKind::DeclViaBridge &&
kind != OverloadChoiceKind::DeclViaUnwrappedOptional &&
- kind != OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional &&
"wrong constructor for decl");
}
@@ -182,20 +174,6 @@
return result;
}
- /// Retrieve an overload choice for a declaration that can be
- /// implicitly unwrapped if needed in order to type check an
- /// expression.
- static OverloadChoice
- getDeclForImplicitlyUnwrappedOptional(Type base, ValueDecl *value,
- FunctionRefKind functionRefKind) {
- OverloadChoice result;
- result.BaseAndDeclKind.setPointer(base);
- result.BaseAndDeclKind.setInt(IsDeclForImplicitlyUnwrappedOptional);
- result.DeclOrKind = value;
- result.TheFunctionRefKind = functionRefKind;
- return result;
- }
-
/// \brief Retrieve the base type used to refer to the declaration.
Type getBaseType() const {
return BaseAndDeclKind.getPointer();
@@ -209,8 +187,6 @@
case IsDeclViaDynamic: return OverloadChoiceKind::DeclViaDynamic;
case IsDeclViaUnwrappedOptional:
return OverloadChoiceKind::DeclViaUnwrappedOptional;
- case IsDeclForImplicitlyUnwrappedOptional:
- return OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional;
default: return OverloadChoiceKind::Decl;
}
}
@@ -231,7 +207,13 @@
ValueDecl *getDecl() const {
return DeclOrKind.get<ValueDecl*>();
}
-
+
+ /// Returns true if this is either a decl for an optional that was
+ /// declared as one that can be implicitly unwrapped, or is a
+ /// function-typed decl that has a return value that is implicitly
+ /// unwrapped.
+ bool isImplicitlyUnwrappedValueOrReturnValue() const;
+
/// Get the name of the overload choice.
DeclName getName() const;
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 4910df3..2148e8b 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -3019,7 +3019,6 @@
case OverloadChoiceKind::DeclViaDynamic:
case OverloadChoiceKind::DeclViaBridge:
case OverloadChoiceKind::DeclViaUnwrappedOptional:
- case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
choice.getDecl()->dumpRef(out);
out << " as ";
if (choice.getBaseType())
@@ -3196,7 +3195,6 @@
case OverloadChoiceKind::DeclViaDynamic:
case OverloadChoiceKind::DeclViaBridge:
case OverloadChoiceKind::DeclViaUnwrappedOptional:
- case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
if (choice.getBaseType())
out << choice.getBaseType()->getString() << ".";
out << choice.getDecl()->getBaseName() << ": "
diff --git a/lib/Syntax/Status.md b/lib/Syntax/Status.md
index 52bc7b3..1ff9806 100644
--- a/lib/Syntax/Status.md
+++ b/lib/Syntax/Status.md
@@ -31,13 +31,13 @@
* SuperRefExpr
* ImplicitMemberExpr
* InterpolatedStringLiteralExpr
+ * KeyPathExpr
+ * KeyPathDotExpr
+ * InOutExpr
### In-progress (UnknownExpr):
* ObjectLiteralExpr
* MagicIdentifierLiteralExpr
- * InOutExpr
- * KeyPathExpr
- * KeyPathDotExpr
* EditorPlaceholderExpr
### Not-started (UnknownExpr):
diff --git a/lib/Syntax/SyntaxParsingContext.cpp b/lib/Syntax/SyntaxParsingContext.cpp
index 10bf371..537a4e3 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -285,7 +285,7 @@
// Never.
case AccumulationMode::NotSet:
- assert(!Enabled && "Cleanup mode must be spefcified before destruction");
+ assert(!Enabled && "Cleanup mode must be specified before destruction");
break;
}
}
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index 22607e4..644fe2f 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -80,8 +80,8 @@
_TFC3foo3bar3basfT3zimCS_3zim_T_ ---> foo.bar.bas(zim: foo.zim) -> ()
_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
-_T03foo3barC3bas3zimyAaEC_tFTo ---> {T:_T03foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
-_T0SC3fooyS2d_SdtFTO ---> {T:_T0SC3fooyS2d_SdtF} @nonobjc __C.foo(Swift.Double, Swift.Double) -> Swift.Double
+_T03foo3barC3basyAA3zimCAE_tFTo ---> {T:_T03foo3barC3basyAA3zimCAE_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
+_T0SC3fooS2d_SdtFTO ---> {T:_T0SC3fooS2d_SdtF} @nonobjc __C.foo(Swift.Double, Swift.Double) -> Swift.Double
__$S3foo3barC3bas3zimyAaEC_tFTo ---> {T:_$S3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
__$SSC3fooyS2d_SdtFTO ---> {T:_$SSC3fooyS2d_SdtF} @nonobjc __C.foo(Swift.Double, Swift.Double) -> Swift.Double
_$S3foo3barC3bas3zimyAaEC_tFTo ---> {T:_$S3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
@@ -246,36 +246,60 @@
_TFVFE15nested_genericsSS3fooFT_T_L_6CheeseCfT8materialx_GS0_x_ ---> init(material: A) -> Cheese #1 in (extension in nested_generics):Swift.String.foo() -> ()<A> in Cheese #1 in (extension in nested_generics):Swift.String.foo() -> ()
_TTWOE5imojiCSo5Imoji14ImojiMatchRankS_9RankValueS_FS2_g9rankValueqq_Ss16RawRepresentable8RawValue ---> _TTWOE5imojiCSo5Imoji14ImojiMatchRankS_9RankValueS_FS2_g9rankValueqq_Ss16RawRepresentable8RawValue
_TtFzas4VoidGC16FusionXBaseUtils6FutureQq_ZFVS_7Futures6futureurFFzT_GS0_x_GS0_x__ ---> _TtFzas4VoidGC16FusionXBaseUtils6FutureQq_ZFVS_7Futures6futureurFFzT_GS0_x_GS0_x__
-_T0s17MutableCollectionP1asAARzs012RandomAccessB0RzsAA11SubSequences013BidirectionalB0PRpzsAdHRQlE06rotatecD015shiftingToStart5Indexs01_A9IndexablePQzAN_tFAKs01_M4BasePQzAQcfU_ ---> closure #1 (A.Index) -> A.Index in (extension in a):Swift.MutableCollection<A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection, A.SubSequence: Swift.MutableCollection, A.SubSequence: Swift.RandomAccessCollection>.rotateRandomAccess(shiftingToStart: A.Index) -> A.Index
+_T0s17MutableCollectionP1asAARzs012RandomAccessB0RzsAA11SubSequences013BidirectionalB0PRpzsAdHRQlE06rotatecD05Indexs01_A9IndexablePQzAM15shiftingToStart_tFAJs01_J4BasePQzAQcfU_ ---> closure #1 (A.Index) -> A.Index in (extension in a):Swift.MutableCollection<A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection, A.SubSequence: Swift.MutableCollection, A.SubSequence: Swift.RandomAccessCollection>.rotateRandomAccess(shiftingToStart: A.Index) -> A.Index
+_$Ss17MutableCollectionP1asAARzs012RandomAccessB0RzsAA11SubSequences013BidirectionalB0PRpzsAdHRQlE06rotatecD015shiftingToStart5Indexs01_A9IndexablePQzAN_tFAKs01_M4BasePQzAQcfU_ ---> closure #1 (A.Index) -> A.Index in (extension in a):Swift.MutableCollection<A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection, A.SubSequence: Swift.MutableCollection, A.SubSequence: Swift.RandomAccessCollection>.rotateRandomAccess(shiftingToStart: A.Index) -> A.Index
_T03foo4_123ABTf3psbpsb_n ---> function signature specialization <Arg[0] = [Constant Propagated String : u8'123'], Arg[1] = [Constant Propagated String : u8'123']> of foo
-_T04main5inneryys5Int32Vz_yADctF25closure_with_box_argumentxz_Bi32__lXXTf1nc_n ---> function signature specialization <Arg[1] = [Closure Propagated : closure_with_box_argument, Argument Types : [<A> { var A } <Builtin.Int32>]> of main.inner(inout Swift.Int32, (Swift.Int32) -> ()) -> ()
-_T03foo6testityyyyc_yyctF1a1bTf3pfpf_n ---> function signature specialization <Arg[0] = [Constant Propagated Function : a], Arg[1] = [Constant Propagated Function : b]> of foo.testit(() -> (), () -> ()) -> ()
+_T04main5innerys5Int32Vz_yADctF25closure_with_box_argumentxz_Bi32__lXXTf1nc_n ---> function signature specialization <Arg[1] = [Closure Propagated : closure_with_box_argument, Argument Types : [<A> { var A } <Builtin.Int32>]> of main.inner(inout Swift.Int32, (Swift.Int32) -> ()) -> ()
+_$S4main5inneryys5Int32Vz_yADctF25closure_with_box_argumentxz_Bi32__lXXTf1nc_n ---> function signature specialization <Arg[1] = [Closure Propagated : closure_with_box_argument, Argument Types : [<A> { var A } <Builtin.Int32>]> of main.inner(inout Swift.Int32, (Swift.Int32) -> ()) -> ()
+_T03foo6testityyyc_yyctF1a1bTf3pfpf_n ---> function signature specialization <Arg[0] = [Constant Propagated Function : a], Arg[1] = [Constant Propagated Function : b]> of foo.testit(() -> (), () -> ()) -> ()
+_$S3foo6testityyyyc_yyctF1a1bTf3pfpf_n ---> function signature specialization <Arg[0] = [Constant Propagated Function : a], Arg[1] = [Constant Propagated Function : b]> of foo.testit(() -> (), () -> ()) -> ()
_SocketJoinOrLeaveMulticast ---> _SocketJoinOrLeaveMulticast
-_T0s10DictionaryV3t17E6Index2V1loiySbAEyxq__G_AGtFZ ---> static (extension in t17):Swift.Dictionary.Index2.< infix((extension in t17):[A : B].Index2, (extension in t17):[A : B].Index2) -> Swift.Bool
-_T08mangling14varargsVsArray3arr1nySid_SStF ---> mangling.varargsVsArray(arr: Swift.Int..., n: Swift.String) -> ()
-_T08mangling14varargsVsArray3arr1nySaySiG_SStF ---> mangling.varargsVsArray(arr: [Swift.Int], n: Swift.String) -> ()
-_T08mangling14varargsVsArray3arr1nySaySiGd_SStF ---> mangling.varargsVsArray(arr: [Swift.Int]..., n: Swift.String) -> ()
-_T08mangling14varargsVsArray3arrySid_tF ---> mangling.varargsVsArray(arr: Swift.Int...) -> ()
-_T08mangling14varargsVsArray3arrySaySiGd_tF ---> mangling.varargsVsArray(arr: [Swift.Int]...) -> ()
+_T0s10DictionaryV3t17E6Index2V1loiSbAEyxq__G_AGtFZ ---> static (extension in t17):Swift.Dictionary.Index2.< infix((extension in t17):[A : B].Index2, (extension in t17):[A : B].Index2) -> Swift.Bool
+_T08mangling14varargsVsArrayySi3arrd_SS1ntF ---> mangling.varargsVsArray(arr: Swift.Int..., n: Swift.String) -> ()
+_T08mangling14varargsVsArrayySaySiG3arr_SS1ntF ---> mangling.varargsVsArray(arr: [Swift.Int], n: Swift.String) -> ()
+_T08mangling14varargsVsArrayySaySiG3arrd_SS1ntF ---> mangling.varargsVsArray(arr: [Swift.Int]..., n: Swift.String) -> ()
+_T08mangling14varargsVsArrayySi3arrd_tF ---> mangling.varargsVsArray(arr: Swift.Int...) -> ()
+_T08mangling14varargsVsArrayySaySiG3arrd_tF ---> mangling.varargsVsArray(arr: [Swift.Int]...) -> ()
+_$Ss10DictionaryV3t17E6Index2V1loiySbAEyxq__G_AGtFZ ---> static (extension in t17):Swift.Dictionary.Index2.< infix((extension in t17):[A : B].Index2, (extension in t17):[A : B].Index2) -> Swift.Bool
+_$S8mangling14varargsVsArray3arr1nySid_SStF ---> mangling.varargsVsArray(arr: Swift.Int..., n: Swift.String) -> ()
+_$S8mangling14varargsVsArray3arr1nySaySiG_SStF ---> mangling.varargsVsArray(arr: [Swift.Int], n: Swift.String) -> ()
+_$S8mangling14varargsVsArray3arr1nySaySiGd_SStF ---> mangling.varargsVsArray(arr: [Swift.Int]..., n: Swift.String) -> ()
+_$S8mangling14varargsVsArray3arrySid_tF ---> mangling.varargsVsArray(arr: Swift.Int...) -> ()
+_$S8mangling14varargsVsArray3arrySaySiGd_tF ---> mangling.varargsVsArray(arr: [Swift.Int]...) -> ()
_T0s13_UnicodeViewsVss22RandomAccessCollectionRzs0A8EncodingR_11SubSequence_5IndexQZAFRtzsAcERpzAE_AEQZAIRSs15UnsignedInteger8Iterator_7ElementRPzAE_AlMQZANRS13EncodedScalar_AlMQY_AORSr0_lE13CharacterViewVyxq__G ---> (extension in Swift):Swift._UnicodeViews<A, B><A, B where A: Swift.RandomAccessCollection, B: Swift.UnicodeEncoding, A.Index == A.SubSequence.Index, A.SubSequence: Swift.RandomAccessCollection, A.SubSequence == A.SubSequence.SubSequence, A.Iterator.Element: Swift.UnsignedInteger, A.Iterator.Element == A.SubSequence.Iterator.Element, A.SubSequence.Iterator.Element == B.EncodedScalar.Iterator.Element>.CharacterView
-_T010Foundation11MeasurementV12SimulatorKitSo9UnitAngleCRszlE11OrientationO2eeoiySbAcDEAGOyAF_G_AKtFZ ---> static (extension in SimulatorKit):Foundation.Measurement<A where A == __ObjC.UnitAngle>.Orientation.== infix((extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation, (extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation) -> Swift.Bool
+_T010Foundation11MeasurementV12SimulatorKitSo9UnitAngleCRszlE11OrientationO2eeoiSbAcDEAGOyAF_G_AKtFZ ---> static (extension in SimulatorKit):Foundation.Measurement<A where A == __ObjC.UnitAngle>.Orientation.== infix((extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation, (extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation) -> Swift.Bool
+_$S10Foundation11MeasurementV12SimulatorKitSo9UnitAngleCRszlE11OrientationO2eeoiySbAcDEAGOyAF_G_AKtFZ ---> static (extension in SimulatorKit):Foundation.Measurement<A where A == __ObjC.UnitAngle>.Orientation.== infix((extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation, (extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation) -> Swift.Bool
_T04main1_yyF ---> main._() -> ()
-_T04test6testitySiyt_tF ---> test.testit(()) -> Swift.Int
+_T04test6testitSiyt_tF ---> test.testit(()) -> Swift.Int
+_$S4test6testitySiyt_tF ---> test.testit(()) -> Swift.Int
_T08_ElementQzSbs5Error_pIxxdzo_ABSbsAC_pIxidzo_s26RangeReplaceableCollectionRzABRLClTR ---> {T:} reabstraction thunk helper <A where A: Swift.RangeReplaceableCollection, A._Element: AnyObject> from @callee_owned (@owned A._Element) -> (@unowned Swift.Bool, @error @owned Swift.Error) to @callee_owned (@in A._Element) -> (@unowned Swift.Bool, @error @owned Swift.Error)
_T0Ix_IyB_Tr ---> {T:} reabstraction thunk from @callee_owned () -> () to @callee_unowned @convention(block) () -> ()
_T0Rml ---> _T0Rml
_T0Tk ---> _T0Tk
_T0A8 ---> _T0A8
_T0s30ReversedRandomAccessCollectionVyxGTfq3nnpf_nTfq1cn_nTfq4x_n ---> _T0s30ReversedRandomAccessCollectionVyxGTfq3nnpf_nTfq1cn_nTfq4x_n
-_T03abc6testityySiFTm ---> merged abc.testit(Swift.Int) -> ()
-_T04main4TestC1xACSi_tc6_PRIV_Llfc ---> main.Test.(in _PRIV_).init(x: Swift.Int) -> main.Test
+_T03abc6testitySiFTm ---> merged abc.testit(Swift.Int) -> ()
+_T04main4TestCACSi1x_tc6_PRIV_Llfc ---> main.Test.(in _PRIV_).init(x: Swift.Int) -> main.Test
+_$S3abc6testityySiFTm ---> merged abc.testit(Swift.Int) -> ()
+_$S4main4TestC1xACSi_tc6_PRIV_Llfc ---> main.Test.(in _PRIV_).init(x: Swift.Int) -> main.Test
_T0SqWy.17 ---> outlined copy of Swift.Optional with unmangled suffix ".17"
_T03nix6testitSaySiGyFTv_ ---> outlined variable #0 of nix.testit() -> [Swift.Int]
_T03nix6testitSaySiGyFTv0_ ---> outlined variable #1 of nix.testit() -> [Swift.Int]
_T0So11UITextFieldC4textSSSgvgToTepb_ ---> outlined bridged method (pb) of @objc __ObjC.UITextField.text.getter : Swift.String?
_T0So11UITextFieldC4textSSSgvgToTeab_ ---> outlined bridged method (ab) of @objc __ObjC.UITextField.text.getter : Swift.String?
-_T0So5GizmoC11doSomethingySQyypGSQySaySSGGFToTembnn_ ---> outlined bridged method (mbnn) of @objc __ObjC.Gizmo.doSomething([Swift.String]!) -> Any!
-_T0So5GizmoC12modifyString_10withNumber0D6FoobarSQySSGAF_SiSQyypGtFToTembnnnb_ ---> outlined bridged method (mbnnnb) of @objc __ObjC.Gizmo.modifyString(_: Swift.String!, withNumber: Swift.Int, withFoobar: Any!) -> Swift.String!
+_T0So5GizmoC11doSomethingSQyypGSQySaySSGGFToTembnn_ ---> outlined bridged method (mbnn) of @objc __ObjC.Gizmo.doSomething([Swift.String]!) -> Any!
+_T0So5GizmoC12modifyStringSQySSGAD_Si10withNumberSQyypG0D6FoobartFToTembnnnb_ ---> outlined bridged method (mbnnnb) of @objc __ObjC.Gizmo.modifyString(_: Swift.String!, withNumber: Swift.Int, withFoobar: Any!) -> Swift.String!
+_$SSo5GizmoC11doSomethingySQyypGSQySaySSGGFToTembnn_ ---> outlined bridged method (mbnn) of @objc __ObjC.Gizmo.doSomething([Swift.String]!) -> Any!
+_$SSo5GizmoC12modifyString_10withNumber0D6FoobarSQySSGAF_SiSQyypGtFToTembnnnb_ ---> outlined bridged method (mbnnnb) of @objc __ObjC.Gizmo.modifyString(_: Swift.String!, withNumber: Swift.Int, withFoobar: Any!) -> Swift.String!
_T04test1SVyxGAA1RA2A1ZRzAA1Y2ZZRpzl1A_AhaGPWT ---> {C} associated type witness table accessor for A.ZZ : test.Y in <A where A: test.Z, A.ZZ: test.Y> test.S<A> : test.R in test
_T0s24_UnicodeScalarExceptions33_0E4228093681F6920F0AB2E48B4F1C69LLVACycfC ---> Swift.(_UnicodeScalarExceptions in _0E4228093681F6920F0AB2E48B4F1C69).init() -> Swift.(_UnicodeScalarExceptions in _0E4228093681F6920F0AB2E48B4F1C69)
-
+_T0D ---> _T0D
+_T0s18EnumeratedIteratorVyxGs8Sequencess0B8ProtocolRzlsADP5splitSay03SubC0QzGSi9maxSplits_Sb25omittingEmptySubsequencesSb7ElementQzKc14whereSeparatortKFTW ---> {T:} protocol witness for Swift.Sequence.split(maxSplits: Swift.Int, omittingEmptySubsequences: Swift.Bool, whereSeparator: (A.Element) throws -> Swift.Bool) throws -> [A.SubSequence] in conformance <A where A: Swift.IteratorProtocol> Swift.EnumeratedIterator<A> : Swift.Sequence in Swift
+_T0s3SetVyxGs10CollectiotySivm ---> _T0s3SetVyxGs10CollectiotySivm
+_S$s3SetVyxGs10CollectiotySivm ---> _S$s3SetVyxGs10CollectiotySivm
+_T0s18ReversedCollectionVyxGs04LazyB8ProtocolfC ---> _T0s18ReversedCollectionVyxGs04LazyB8ProtocolfC
+_S$s18ReversedCollectionVyxGs04LazyB8ProtocolfC ---> _S$s18ReversedCollectionVyxGs04LazyB8ProtocolfC
+_T0iW ---> _T0iW
+_S$iW ---> _S$iW
+_T0s5print_9separator10terminatoryypfC ---> _T0s5print_9separator10terminatoryypfC
+_S$s5print_9separator10terminatoryypfC ---> _S$s5print_9separator10terminatoryypfC
diff --git a/test/Demangle/Inputs/simplified-manglings.txt b/test/Demangle/Inputs/simplified-manglings.txt
index 38d11e3..f92e4d8 100644
--- a/test/Demangle/Inputs/simplified-manglings.txt
+++ b/test/Demangle/Inputs/simplified-manglings.txt
@@ -203,5 +203,7 @@
_TTRXFo_oCSo13SKPhysicsBodydVSC7CGPointdVSC8CGVectordGSpV10ObjectiveC8ObjCBool___XFdCb_dS_dS0_dS1_dGSpS3____ ---> thunk for @callee_owned (@owned SKPhysicsBody, @unowned CGPoint, @unowned CGVector, @unowned UnsafeMutablePointer<ObjCBool>) -> ()
_T0So13SKPhysicsBodyCSC7CGPointVSC8CGVectorVSpy10ObjectiveC8ObjCBoolVGIxxyyy_AbdFSpyAIGIyByyyy_TR ---> thunk for @callee_owned (@owned SKPhysicsBody, @unowned CGPoint, @unowned CGVector, @unowned UnsafeMutablePointer<ObjCBool>) -> ()
_T04main1_yyF ---> _()
-_T03abc6testityySiFTm ---> testit(_:)
-_T04main4TestC1xACSi_tc6_PRIV_Llfc ---> Test.init(x:)
+_T03abc6testitySiFTm ---> testit(_:)
+_T04main4TestCACSi1x_tc6_PRIV_Llfc ---> Test.init(x:)
+_$S3abc6testityySiFTm ---> testit(_:)
+_$S4main4TestC1xACSi_tc6_PRIV_Llfc ---> Test.init(x:)
diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index eefd51c..ecb48cb 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -222,7 +222,8 @@
foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></IdentifierExpr>()</FunctionCallExpr><SequenceExpr><DiscardAssignmentExpr>
_ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ImplicitMemberExpr>.foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></ImplicitMemberExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><IdentifierExpr>x</IdentifierExpr>.foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></MemberAccessExpr></SequenceExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><IdentifierExpr>x</IdentifierExpr>.foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></MemberAccessExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><FunctionCallExpr><IdentifierExpr>foo</IdentifierExpr>(<FunctionCallArgument><InOutExpr>&<IdentifierExpr>d</IdentifierExpr></InOutExpr></FunctionCallArgument>)</FunctionCallExpr></SequenceExpr>
}</CodeBlock></FunctionDecl><IfConfigDecl>
#if <IdentifierExpr>blah</IdentifierExpr><ElseDirectiveClause>
@@ -341,4 +342,12 @@
de </StringSegment><ExpressionSegment>\(<SequenceExpr><IntegerLiteralExpr>3 </IntegerLiteralExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><IntegerLiteralExpr>3 </IntegerLiteralExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><StringInterpolationExpr>"<StringSegment>abc </StringSegment><ExpressionSegment>\(<FunctionCallExpr><IdentifierExpr>foo</IdentifierExpr>()</FunctionCallExpr>)</ExpressionSegment><StringSegment> def</StringSegment>"</StringInterpolationExpr></SequenceExpr>)</ExpressionSegment><StringSegment>
fg
</StringSegment>"""</StringInterpolationExpr></InitializerClause></PatternBinding></VariableDecl>
+}</CodeBlock></FunctionDecl><FunctionDecl>
+
+func keypath<FunctionSignature><ParameterClause>() </ParameterClause></FunctionSignature><CodeBlock>{<SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><KeyPathExpr>\<IdentifierExpr>a</IdentifierExpr>.?.b</KeyPathExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><KeyPathExpr>\<MemberAccessExpr><MemberAccessExpr><IdentifierExpr>a</IdentifierExpr>.b</MemberAccessExpr>.c</MemberAccessExpr></KeyPathExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><KeyPathExpr>\<SubscriptExpr><MemberAccessExpr><IdentifierExpr>a</IdentifierExpr>.b</MemberAccessExpr>[<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>]</SubscriptExpr></KeyPathExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><KeyPathExpr>\<MemberAccessExpr>.a.b</MemberAccessExpr></KeyPathExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ObjcKeyPathExpr>#keyPath(<ObjcNamePiece>a.</ObjcNamePiece><ObjcNamePiece>b.</ObjcNamePiece><ObjcNamePiece>c</ObjcNamePiece>)</ObjcKeyPathExpr></SequenceExpr>
}</CodeBlock></FunctionDecl>
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index 15e908d..c36a25f 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -223,6 +223,7 @@
foo(x:y:)()
_ = .foo(x:y:)
_ = x.foo(x:y:)
+ _ = foo(&d)
}
#if blah
@@ -342,3 +343,11 @@
fg
"""
}
+
+func keypath() {
+ _ = \a.?.b
+ _ = \a.b.c
+ _ = \a.b[1]
+ _ = \.a.b
+ _ = #keyPath(a.b.c)
+}
diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py
index d5d4c5e..b8df2b5 100644
--- a/utils/gyb_syntax_support/ExprNodes.py
+++ b/utils/gyb_syntax_support/ExprNodes.py
@@ -7,7 +7,7 @@
Node('InOutExpr', kind='Expr',
children=[
Child('Ampersand', kind='PrefixAmpersandToken'),
- Child('Identifier', kind='IdentifierToken'),
+ Child('Expression', kind='Expr'),
]),
# A #column expression.
@@ -440,4 +440,30 @@
'MultilineStringQuoteToken',
]),
]),
+
+ # e.g. "\a.b[2].a"
+ Node('KeyPathExpr', kind='Expr',
+ children=[
+ Child('Backslash', kind='BackslashToken'),
+ Child('Expression', kind='Expr'),
+ ]),
+
+ # e.g. "a." or "a"
+ Node('ObjcNamePiece', kind='Syntax',
+ children=[
+ Child('Name', kind='IdentifierToken'),
+ Child('Dot', kind='PeriodToken', is_optional=True),
+ ]),
+
+ # e.g. "a.b.c"
+ Node('ObjcName', kind='SyntaxCollection', element='ObjcNamePiece'),
+
+ # e.g. "#keyPath(a.b.c)"
+ Node('ObjcKeyPathExpr', kind='Expr',
+ children=[
+ Child('KeyPath', kind='PoundKeyPathToken'),
+ Child('LeftParen', kind='LeftParenToken'),
+ Child('Name', kind='ObjcName'),
+ Child('RightParen', kind='RightParenToken'),
+ ]),
]