diff --git a/docs/ABI.rst b/docs/ABI.rst index 61fb2932feb..0354ef86711 100644 --- a/docs/ABI.rst +++ b/docs/ABI.rst @@ -690,6 +690,8 @@ Globals entity-name ::= 's' decl-name type // setter entity-name ::= 'U' index type // explicit anonymous closure expression entity-name ::= 'u' index type // implicit anonymous closure + entity-name ::= 'w' decl-name type // willSet + entity-name ::= 'W' decl-name type // didSet decl-name ::= identifier decl-name ::= local-decl-name local-decl-name ::= 'L' index identifier // locally-discriminated declaration diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index cd713f7f4df..7b51c375b1e 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -3095,6 +3095,7 @@ public: /// isGetterOrSetter - Determine whether this is a getter or a setter vs. /// a normal function. bool isGetterOrSetter() const { return isGetter() || isSetter(); } + bool isAccessor() const { return getAccessorKind() != NotAccessor; } /// Creates the implicit 'DynamicSelf' generic parameter. /// diff --git a/include/swift/AST/Mangle.h b/include/swift/AST/Mangle.h index 2304009349f..4cb2ca10ca9 100644 --- a/include/swift/AST/Mangle.h +++ b/include/swift/AST/Mangle.h @@ -93,8 +93,8 @@ public: ResilienceExpansion kind, unsigned uncurryingLevel); void mangleDestructorEntity(DestructorDecl *decl, bool isDeallocating); void mangleIVarInitDestroyEntity(ClassDecl *decl, bool isDestroyer); - void mangleGetterEntity(ValueDecl *decl, ResilienceExpansion expansion); - void mangleSetterEntity(ValueDecl *decl, ResilienceExpansion expansion); + void mangleAccessorEntity(char Code, ValueDecl *decl, + ResilienceExpansion expansion); void mangleAddressorEntity(ValueDecl *decl); void mangleDefaultArgumentEntity(DeclContext *ctx, unsigned index); void mangleInitializerEntity(VarDecl *var); diff --git a/include/swift/Basic/DemangleNodes.def b/include/swift/Basic/DemangleNodes.def index d7d8e1bb7f6..458c6d9e5a4 100644 --- a/include/swift/Basic/DemangleNodes.def +++ b/include/swift/Basic/DemangleNodes.def @@ -39,6 +39,7 @@ NODE(DefaultArgumentInitializer) NODE(DependentProtocolWitnessTableGenerator) NODE(DependentProtocolWitnessTableTemplate) NODE(Destructor) +NODE(DidSet) NODE(Directness) NODE(Enum) NODE(ErrorType) @@ -104,6 +105,7 @@ NODE(ValueWitnessTable) NODE(Variable) NODE(VariadicTuple) NODE(Weak) +NODE(WillSet) NODE(WitnessTableOffset) #undef NODE diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp index 4a5dcded2f2..8542e647872 100644 --- a/lib/AST/Mangle.cpp +++ b/lib/AST/Mangle.cpp @@ -275,15 +275,23 @@ void Mangler::mangleContext(DeclContext *ctx, BindGenerics shouldBind) { return mangleConstructorEntity(ctor, /*allocating*/ false, ResilienceExpansion::Minimal, /*uncurry*/ 0); - } else if (auto dtor = dyn_cast(fn)) { + } + + if (auto dtor = dyn_cast(fn)) return mangleDestructorEntity(dtor, /*deallocating*/ false); - } else if (auto func = dyn_cast(fn)) { - if (func->isGetter()) - return mangleGetterEntity(func->getAccessorStorageDecl(), - ResilienceExpansion::Minimal); - if (func->isSetter()) - return mangleSetterEntity(func->getAccessorStorageDecl(), - ResilienceExpansion::Minimal); + + if (auto func = dyn_cast(fn)) { + char Code = '\0'; + switch (func->getAccessorKind()) { + case FuncDecl::IsGetter: Code = 'g'; break; + case FuncDecl::IsSetter: Code = 's'; break; + case FuncDecl::IsWillSet: Code = 'w'; break; + case FuncDecl::IsDidSet: Code = 'W'; break; + case FuncDecl::NotAccessor: break; + } + if (Code) + return mangleAccessorEntity(Code, func->getAccessorStorageDecl(), + ResilienceExpansion::Minimal); } return mangleEntity(fn, ResilienceExpansion::Minimal, /*uncurry*/ 0); } @@ -1108,21 +1116,14 @@ void Mangler::mangleDestructorEntity(DestructorDecl *dtor, void Mangler::mangleIVarInitDestroyEntity(ClassDecl *decl, bool isDestroyer) { Buffer << 'F'; mangleContext(decl, BindGenerics::Enclosing); - Buffer << (isDestroyer? 'E' : 'e'); + Buffer << (isDestroyer ? 'E' : 'e'); } -void Mangler::mangleGetterEntity(ValueDecl *decl, ResilienceExpansion explosion) { +void Mangler::mangleAccessorEntity(char Code, ValueDecl *decl, + ResilienceExpansion explosion) { Buffer << 'F'; mangleContextOf(decl, BindGenerics::All); - Buffer << 'g'; - mangleDeclName(decl); - mangleDeclType(decl, explosion, 0); -} - -void Mangler::mangleSetterEntity(ValueDecl *decl, ResilienceExpansion explosion) { - Buffer << 'F'; - mangleContextOf(decl, BindGenerics::All); - Buffer << 's'; + Buffer << Code; mangleDeclName(decl); mangleDeclType(decl, explosion, 0); } @@ -1152,7 +1153,7 @@ void Mangler::mangleEntity(ValueDecl *decl, ResilienceExpansion explosion, unsigned uncurryLevel) { assert(!isa(decl)); assert(!isa(decl)); - assert(!isa(decl) || !cast(decl)->isGetterOrSetter()); + assert(!isa(decl) || !cast(decl)->isAccessor()); BindGenerics shouldBindParent = BindGenerics::All; diff --git a/lib/Basic/Demangle.cpp b/lib/Basic/Demangle.cpp index 6ac11dfd977..f0cda15f992 100644 --- a/lib/Basic/Demangle.cpp +++ b/lib/Basic/Demangle.cpp @@ -918,6 +918,14 @@ private: entityKind = Node::Kind::Setter; name = demangleDeclName(); if (!name) return nullptr; + } else if (Mangled.nextIf('w')) { + entityKind = Node::Kind::WillSet; + name = demangleDeclName(); + if (!name) return nullptr; + } else if (Mangled.nextIf('W')) { + entityKind = Node::Kind::DidSet; + name = demangleDeclName(); + if (!name) return nullptr; } else if (Mangled.nextIf('U')) { entityKind = Node::Kind::ExplicitClosure; name = demangleIndexAsNode(); @@ -2123,6 +2131,12 @@ void NodePrinter::print(Node *pointer, bool asContext, bool suppressType) { case Node::Kind::Setter: printEntity(true, true, ".setter"); return; + case Node::Kind::WillSet: + printEntity(true, true, ".willset"); + return; + case Node::Kind::DidSet: + printEntity(true, true, ".didset"); + return; case Node::Kind::Allocator: printEntity(false, true, "__allocating_init"); return; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 1a0c2757fd9..cac9495304b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1055,7 +1055,15 @@ namespace { if (VD->hasAccessorFunctions()) { // Add getter & setter in source order. - FuncDecl* Accessors[2] = {VD->getGetter(), VD->getSetter()}; + FuncDecl *Accessors[2]; + + if (VD->getStorageKind() == VarDecl::WillSetDidSet) { + Accessors[0] = VD->getWillSetFunc(); + Accessors[1] = VD->getDidSetFunc(); + } else { + Accessors[0] = VD->getGetter(); + Accessors[1] = VD->getSetter(); + } if (Accessors[0] && Accessors[1] && !Context.SourceMgr.isBeforeInBuffer( Accessors[0]->getFuncLoc(), Accessors[1]->getFuncLoc())) { diff --git a/lib/SIL/SIL.cpp b/lib/SIL/SIL.cpp index 5384f5005aa..4c6b61fbfa2 100644 --- a/lib/SIL/SIL.cpp +++ b/lib/SIL/SIL.cpp @@ -360,6 +360,26 @@ static void mangleConstant(SILDeclRef c, llvm::raw_ostream &buffer, buffer << c.getDecl()->getAttrs().AsmName; return; } + + if (auto *FD = dyn_cast(c.getDecl())) { + switch (FD->getAccessorKind()) { + default: assert(0 && "Unhandled accessor"); + case FuncDecl::NotAccessor: break; + case FuncDecl::IsWillSet: + // entity ::= declaration 'w' // willSet + buffer << introducer; + mangler.mangleAccessorEntity('w', FD->getAccessorStorageDecl(), + expansion); + return; + + case FuncDecl::IsDidSet: + // entity ::= declaration 'W' // didSet + buffer << introducer; + mangler.mangleAccessorEntity('W', FD->getAccessorStorageDecl(), + expansion); + return; + } + } // Otherwise, fall through into the 'other decl' case. SWIFT_FALLTHROUGH; @@ -429,13 +449,13 @@ static void mangleConstant(SILDeclRef c, llvm::raw_ostream &buffer, // entity ::= declaration 'g' // getter case SILDeclRef::Kind::Getter: buffer << introducer; - mangler.mangleGetterEntity(c.getDecl(), expansion); + mangler.mangleAccessorEntity('g', c.getDecl(), expansion); return; // entity ::= declaration 's' // setter case SILDeclRef::Kind::Setter: buffer << introducer; - mangler.mangleSetterEntity(c.getDecl(), expansion); + mangler.mangleAccessorEntity('s', c.getDecl(), expansion); return; // entity ::= declaration 'a' // addressor