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:
Chris Lattner
2014-01-28 05:15:56 +00:00
parent ca439b1a48
commit d407bc8fc4
8 changed files with 73 additions and 25 deletions

View File

@@ -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

View File

@@ -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.
/// ///

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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())) {

View File

@@ -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