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 ::= 's' decl-name type // setter
|
||||||
entity-name ::= 'U' index type // explicit anonymous closure expression
|
entity-name ::= 'U' index type // explicit anonymous closure expression
|
||||||
entity-name ::= 'u' index type // implicit anonymous closure
|
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 ::= identifier
|
||||||
decl-name ::= local-decl-name
|
decl-name ::= local-decl-name
|
||||||
local-decl-name ::= 'L' index identifier // locally-discriminated declaration
|
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.
|
/// isGetterOrSetter - Determine whether this is a getter or a setter vs.
|
||||||
/// a normal function.
|
/// a normal function.
|
||||||
bool isGetterOrSetter() const { return isGetter() || isSetter(); }
|
bool isGetterOrSetter() const { return isGetter() || isSetter(); }
|
||||||
|
bool isAccessor() const { return getAccessorKind() != NotAccessor; }
|
||||||
|
|
||||||
/// Creates the implicit 'DynamicSelf' generic parameter.
|
/// Creates the implicit 'DynamicSelf' generic parameter.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ public:
|
|||||||
ResilienceExpansion kind, unsigned uncurryingLevel);
|
ResilienceExpansion kind, unsigned uncurryingLevel);
|
||||||
void mangleDestructorEntity(DestructorDecl *decl, bool isDeallocating);
|
void mangleDestructorEntity(DestructorDecl *decl, bool isDeallocating);
|
||||||
void mangleIVarInitDestroyEntity(ClassDecl *decl, bool isDestroyer);
|
void mangleIVarInitDestroyEntity(ClassDecl *decl, bool isDestroyer);
|
||||||
void mangleGetterEntity(ValueDecl *decl, ResilienceExpansion expansion);
|
void mangleAccessorEntity(char Code, ValueDecl *decl,
|
||||||
void mangleSetterEntity(ValueDecl *decl, ResilienceExpansion expansion);
|
ResilienceExpansion expansion);
|
||||||
void mangleAddressorEntity(ValueDecl *decl);
|
void mangleAddressorEntity(ValueDecl *decl);
|
||||||
void mangleDefaultArgumentEntity(DeclContext *ctx, unsigned index);
|
void mangleDefaultArgumentEntity(DeclContext *ctx, unsigned index);
|
||||||
void mangleInitializerEntity(VarDecl *var);
|
void mangleInitializerEntity(VarDecl *var);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ NODE(DefaultArgumentInitializer)
|
|||||||
NODE(DependentProtocolWitnessTableGenerator)
|
NODE(DependentProtocolWitnessTableGenerator)
|
||||||
NODE(DependentProtocolWitnessTableTemplate)
|
NODE(DependentProtocolWitnessTableTemplate)
|
||||||
NODE(Destructor)
|
NODE(Destructor)
|
||||||
|
NODE(DidSet)
|
||||||
NODE(Directness)
|
NODE(Directness)
|
||||||
NODE(Enum)
|
NODE(Enum)
|
||||||
NODE(ErrorType)
|
NODE(ErrorType)
|
||||||
@@ -104,6 +105,7 @@ NODE(ValueWitnessTable)
|
|||||||
NODE(Variable)
|
NODE(Variable)
|
||||||
NODE(VariadicTuple)
|
NODE(VariadicTuple)
|
||||||
NODE(Weak)
|
NODE(Weak)
|
||||||
|
NODE(WillSet)
|
||||||
NODE(WitnessTableOffset)
|
NODE(WitnessTableOffset)
|
||||||
|
|
||||||
#undef NODE
|
#undef NODE
|
||||||
|
|||||||
@@ -275,15 +275,23 @@ void Mangler::mangleContext(DeclContext *ctx, BindGenerics shouldBind) {
|
|||||||
return mangleConstructorEntity(ctor, /*allocating*/ false,
|
return mangleConstructorEntity(ctor, /*allocating*/ false,
|
||||||
ResilienceExpansion::Minimal,
|
ResilienceExpansion::Minimal,
|
||||||
/*uncurry*/ 0);
|
/*uncurry*/ 0);
|
||||||
} else if (auto dtor = dyn_cast<DestructorDecl>(fn)) {
|
}
|
||||||
|
|
||||||
|
if (auto dtor = dyn_cast<DestructorDecl>(fn))
|
||||||
return mangleDestructorEntity(dtor, /*deallocating*/ false);
|
return mangleDestructorEntity(dtor, /*deallocating*/ false);
|
||||||
} else if (auto func = dyn_cast<FuncDecl>(fn)) {
|
|
||||||
if (func->isGetter())
|
if (auto func = dyn_cast<FuncDecl>(fn)) {
|
||||||
return mangleGetterEntity(func->getAccessorStorageDecl(),
|
char Code = '\0';
|
||||||
ResilienceExpansion::Minimal);
|
switch (func->getAccessorKind()) {
|
||||||
if (func->isSetter())
|
case FuncDecl::IsGetter: Code = 'g'; break;
|
||||||
return mangleSetterEntity(func->getAccessorStorageDecl(),
|
case FuncDecl::IsSetter: Code = 's'; break;
|
||||||
ResilienceExpansion::Minimal);
|
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);
|
return mangleEntity(fn, ResilienceExpansion::Minimal, /*uncurry*/ 0);
|
||||||
}
|
}
|
||||||
@@ -1108,21 +1116,14 @@ void Mangler::mangleDestructorEntity(DestructorDecl *dtor,
|
|||||||
void Mangler::mangleIVarInitDestroyEntity(ClassDecl *decl, bool isDestroyer) {
|
void Mangler::mangleIVarInitDestroyEntity(ClassDecl *decl, bool isDestroyer) {
|
||||||
Buffer << 'F';
|
Buffer << 'F';
|
||||||
mangleContext(decl, BindGenerics::Enclosing);
|
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';
|
Buffer << 'F';
|
||||||
mangleContextOf(decl, BindGenerics::All);
|
mangleContextOf(decl, BindGenerics::All);
|
||||||
Buffer << 'g';
|
Buffer << Code;
|
||||||
mangleDeclName(decl);
|
|
||||||
mangleDeclType(decl, explosion, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mangler::mangleSetterEntity(ValueDecl *decl, ResilienceExpansion explosion) {
|
|
||||||
Buffer << 'F';
|
|
||||||
mangleContextOf(decl, BindGenerics::All);
|
|
||||||
Buffer << 's';
|
|
||||||
mangleDeclName(decl);
|
mangleDeclName(decl);
|
||||||
mangleDeclType(decl, explosion, 0);
|
mangleDeclType(decl, explosion, 0);
|
||||||
}
|
}
|
||||||
@@ -1152,7 +1153,7 @@ void Mangler::mangleEntity(ValueDecl *decl, ResilienceExpansion explosion,
|
|||||||
unsigned uncurryLevel) {
|
unsigned uncurryLevel) {
|
||||||
assert(!isa<ConstructorDecl>(decl));
|
assert(!isa<ConstructorDecl>(decl));
|
||||||
assert(!isa<DestructorDecl>(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;
|
BindGenerics shouldBindParent = BindGenerics::All;
|
||||||
|
|
||||||
|
|||||||
@@ -918,6 +918,14 @@ private:
|
|||||||
entityKind = Node::Kind::Setter;
|
entityKind = Node::Kind::Setter;
|
||||||
name = demangleDeclName();
|
name = demangleDeclName();
|
||||||
if (!name) return nullptr;
|
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')) {
|
} else if (Mangled.nextIf('U')) {
|
||||||
entityKind = Node::Kind::ExplicitClosure;
|
entityKind = Node::Kind::ExplicitClosure;
|
||||||
name = demangleIndexAsNode();
|
name = demangleIndexAsNode();
|
||||||
@@ -2123,6 +2131,12 @@ void NodePrinter::print(Node *pointer, bool asContext, bool suppressType) {
|
|||||||
case Node::Kind::Setter:
|
case Node::Kind::Setter:
|
||||||
printEntity(true, true, ".setter");
|
printEntity(true, true, ".setter");
|
||||||
return;
|
return;
|
||||||
|
case Node::Kind::WillSet:
|
||||||
|
printEntity(true, true, ".willset");
|
||||||
|
return;
|
||||||
|
case Node::Kind::DidSet:
|
||||||
|
printEntity(true, true, ".didset");
|
||||||
|
return;
|
||||||
case Node::Kind::Allocator:
|
case Node::Kind::Allocator:
|
||||||
printEntity(false, true, "__allocating_init");
|
printEntity(false, true, "__allocating_init");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1055,7 +1055,15 @@ namespace {
|
|||||||
|
|
||||||
if (VD->hasAccessorFunctions()) {
|
if (VD->hasAccessorFunctions()) {
|
||||||
// Add getter & setter in source order.
|
// 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] &&
|
if (Accessors[0] && Accessors[1] &&
|
||||||
!Context.SourceMgr.isBeforeInBuffer(
|
!Context.SourceMgr.isBeforeInBuffer(
|
||||||
Accessors[0]->getFuncLoc(), Accessors[1]->getFuncLoc())) {
|
Accessors[0]->getFuncLoc(), Accessors[1]->getFuncLoc())) {
|
||||||
|
|||||||
@@ -360,6 +360,26 @@ static void mangleConstant(SILDeclRef c, llvm::raw_ostream &buffer,
|
|||||||
buffer << c.getDecl()->getAttrs().AsmName;
|
buffer << c.getDecl()->getAttrs().AsmName;
|
||||||
return;
|
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.
|
// Otherwise, fall through into the 'other decl' case.
|
||||||
SWIFT_FALLTHROUGH;
|
SWIFT_FALLTHROUGH;
|
||||||
@@ -429,13 +449,13 @@ static void mangleConstant(SILDeclRef c, llvm::raw_ostream &buffer,
|
|||||||
// entity ::= declaration 'g' // getter
|
// entity ::= declaration 'g' // getter
|
||||||
case SILDeclRef::Kind::Getter:
|
case SILDeclRef::Kind::Getter:
|
||||||
buffer << introducer;
|
buffer << introducer;
|
||||||
mangler.mangleGetterEntity(c.getDecl(), expansion);
|
mangler.mangleAccessorEntity('g', c.getDecl(), expansion);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// entity ::= declaration 's' // setter
|
// entity ::= declaration 's' // setter
|
||||||
case SILDeclRef::Kind::Setter:
|
case SILDeclRef::Kind::Setter:
|
||||||
buffer << introducer;
|
buffer << introducer;
|
||||||
mangler.mangleSetterEntity(c.getDecl(), expansion);
|
mangler.mangleAccessorEntity('s', c.getDecl(), expansion);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// entity ::= declaration 'a' // addressor
|
// entity ::= declaration 'a' // addressor
|
||||||
|
|||||||
Reference in New Issue
Block a user