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 ::= '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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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