mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Teach the parser to add the didSet/willSet functions to the enclosing
type, so we emit them. Add mangler (and demangler) support for these. Enhance our testcase to check to make sure that stores within these specifiers are direct, they don't cause recursive infinite loops. John, I picked w/W for the mangling letters, let me know if this is ok. Swift SVN r13050
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
///
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<DestructorDecl>(fn)) {
|
||||
}
|
||||
|
||||
if (auto dtor = dyn_cast<DestructorDecl>(fn))
|
||||
return mangleDestructorEntity(dtor, /*deallocating*/ false);
|
||||
} else if (auto func = dyn_cast<FuncDecl>(fn)) {
|
||||
if (func->isGetter())
|
||||
return mangleGetterEntity(func->getAccessorStorageDecl(),
|
||||
ResilienceExpansion::Minimal);
|
||||
if (func->isSetter())
|
||||
return mangleSetterEntity(func->getAccessorStorageDecl(),
|
||||
ResilienceExpansion::Minimal);
|
||||
|
||||
if (auto func = dyn_cast<FuncDecl>(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<ConstructorDecl>(decl));
|
||||
assert(!isa<DestructorDecl>(decl));
|
||||
assert(!isa<FuncDecl>(decl) || !cast<FuncDecl>(decl)->isGetterOrSetter());
|
||||
assert(!isa<FuncDecl>(decl) || !cast<FuncDecl>(decl)->isAccessor());
|
||||
|
||||
BindGenerics shouldBindParent = BindGenerics::All;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())) {
|
||||
|
||||
@@ -360,6 +360,26 @@ static void mangleConstant(SILDeclRef c, llvm::raw_ostream &buffer,
|
||||
buffer << c.getDecl()->getAttrs().AsmName;
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto *FD = dyn_cast<FuncDecl>(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
|
||||
|
||||
Reference in New Issue
Block a user