mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-01 15:40:55 +03:00
Nested static functions and function literals do not inherit the parent context
This commit is contained in:
parent
cda8a12112
commit
a2fe91d5e3
2 changed files with 64 additions and 51 deletions
|
@ -1789,12 +1789,7 @@ FuncDeclaration* getParentFunc(Dsymbol* sym, bool stopOnStatic)
|
|||
if (stopOnStatic)
|
||||
{
|
||||
// Fun fact: AggregateDeclarations are not Declarations.
|
||||
if (FuncDeclaration* decl = parent->isFuncDeclaration())
|
||||
{
|
||||
if (decl->isStatic())
|
||||
return NULL;
|
||||
}
|
||||
else if (AggregateDeclaration* decl = parent->isAggregateDeclaration())
|
||||
if (AggregateDeclaration* decl = parent->isAggregateDeclaration())
|
||||
{
|
||||
if (!decl->isNested())
|
||||
return NULL;
|
||||
|
@ -1803,7 +1798,11 @@ FuncDeclaration* getParentFunc(Dsymbol* sym, bool stopOnStatic)
|
|||
parent = parent->parent;
|
||||
}
|
||||
|
||||
return parent ? parent->isFuncDeclaration() : NULL;
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
FuncDeclaration* fd = parent->isFuncDeclaration();
|
||||
return fd;//(stopOnStatic && fd->isStatic()) ? NULL : fd;
|
||||
}
|
||||
|
||||
LLValue* DtoIndexAggregate(LLValue* src, AggregateDeclaration* ad, VarDeclaration* vd)
|
||||
|
|
102
gen/nested.cpp
102
gen/nested.cpp
|
@ -322,15 +322,28 @@ LLValue* DtoNestedContext(Loc& loc, Dsymbol* sym)
|
|||
return val;
|
||||
}
|
||||
|
||||
static void DtoCreateNestedContextType(FuncDeclaration* fd) {
|
||||
static void DtoCreateNestedContextType(FuncDeclaration* fd)
|
||||
{
|
||||
IF_LOG Logger::println("DtoCreateNestedContextType for %s", fd->toPrettyChars());
|
||||
LOG_SCOPE
|
||||
|
||||
DtoDeclareFunction(fd);
|
||||
|
||||
if (getIrFunc(fd)->nestedContextCreated)
|
||||
IrFunction& irFunc = *getIrFunc(fd);
|
||||
|
||||
if (irFunc.nestedContextCreated)
|
||||
return;
|
||||
getIrFunc(fd)->nestedContextCreated = true;
|
||||
irFunc.nestedContextCreated = true;
|
||||
|
||||
// Static functions and function (not delegate) literals don't allow
|
||||
// access to a parent context, even if they are nested.
|
||||
const bool certainlyNewRoot = fd->isStatic() ||
|
||||
(fd->isFuncLiteralDeclaration() &&
|
||||
static_cast<FuncLiteralDeclaration*>(fd)->tok == TOKfunction);
|
||||
FuncDeclaration* parentFunc = (certainlyNewRoot ? NULL : getParentFunc(fd, true));
|
||||
// Make sure the parent has already been analyzed.
|
||||
if (parentFunc)
|
||||
DtoCreateNestedContextType(parentFunc);
|
||||
|
||||
// construct nested variables array
|
||||
if (fd->closureVars.dim > 0)
|
||||
|
@ -339,42 +352,34 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
|
|||
// start with adding all enclosing parent frames until a static parent is reached
|
||||
|
||||
LLStructType* innerFrameType = NULL;
|
||||
unsigned depth = -1;
|
||||
int depth = 0;
|
||||
|
||||
// Static functions and function (not delegate) literals don't allow
|
||||
// access to a parent context, even if they are nested.
|
||||
const bool certainlyNewRoot = fd->isStatic() ||
|
||||
(fd->isFuncLiteralDeclaration() &&
|
||||
static_cast<FuncLiteralDeclaration*>(fd)->tok == TOKfunction);
|
||||
if (!certainlyNewRoot) {
|
||||
if (FuncDeclaration* parfd = getParentFunc(fd, true)) {
|
||||
// Make sure the parent has already been analyzed.
|
||||
DtoCreateNestedContextType(parfd);
|
||||
|
||||
innerFrameType = getIrFunc(parfd)->frameType;
|
||||
if (innerFrameType)
|
||||
depth = getIrFunc(parfd)->depth;
|
||||
}
|
||||
if (parentFunc)
|
||||
{
|
||||
IrFunction& parentIrFunc = *getIrFunc(parentFunc);
|
||||
innerFrameType = parentIrFunc.frameType;
|
||||
if (innerFrameType)
|
||||
depth = parentIrFunc.depth + 1;
|
||||
}
|
||||
getIrFunc(fd)->depth = ++depth;
|
||||
|
||||
irFunc.depth = depth;
|
||||
|
||||
IF_LOG Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n';
|
||||
|
||||
typedef std::vector<LLType*> TypeVec;
|
||||
TypeVec types;
|
||||
if (depth != 0) {
|
||||
if (depth != 0)
|
||||
{
|
||||
assert(innerFrameType);
|
||||
// Add frame pointer types for all but last frame
|
||||
if (depth > 1) {
|
||||
for (unsigned i = 0; i < (depth - 1); ++i) {
|
||||
types.push_back(innerFrameType->getElementType(i));
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < (depth - 1); ++i)
|
||||
types.push_back(innerFrameType->getElementType(i));
|
||||
// Add frame pointer type for last frame
|
||||
types.push_back(LLPointerType::getUnqual(innerFrameType));
|
||||
}
|
||||
|
||||
if (Logger::enabled() && depth != 0) {
|
||||
if (Logger::enabled() && depth != 0)
|
||||
{
|
||||
Logger::println("Frame types: ");
|
||||
LOG_SCOPE;
|
||||
for (TypeVec::iterator i = types.begin(); i != types.end(); ++i)
|
||||
|
@ -385,13 +390,15 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
|
|||
// TODO: optimize ordering for minimal space usage?
|
||||
for (VarDeclarations::iterator I = fd->closureVars.begin(),
|
||||
E = fd->closureVars.end();
|
||||
I != E; ++I) {
|
||||
I != E; ++I)
|
||||
{
|
||||
VarDeclaration* vd = *I;
|
||||
IrLocal *irLocal = getIrLocal(vd, true);
|
||||
irLocal->nestedIndex = types.size();
|
||||
irLocal->nestedDepth = depth;
|
||||
IrLocal& irLocal = *getIrLocal(vd, true);
|
||||
irLocal.nestedIndex = types.size();
|
||||
irLocal.nestedDepth = depth;
|
||||
|
||||
if (vd->isParameter() && getIrParameter(vd)->arg) {
|
||||
if (vd->isParameter() && getIrParameter(vd)->arg)
|
||||
{
|
||||
// Parameters that are part of the LLVM signature will have
|
||||
// storage associated with them (to handle byref etc.), so
|
||||
// handle those cases specially by storing a pointer instead
|
||||
|
@ -401,20 +408,22 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
|
|||
const bool lazy = vd->storage_class & STClazy;
|
||||
const bool byref = irparam->arg->byref;
|
||||
const bool isVthisPtr = irparam->isVthis && !byref;
|
||||
if (!(refout || (byref && !lazy)) || isVthisPtr) {
|
||||
if (!(refout || (byref && !lazy)) || isVthisPtr)
|
||||
{
|
||||
// This will be copied to the nesting frame.
|
||||
if (lazy)
|
||||
types.push_back(irparam->value->getType()->getContainedType(0));
|
||||
else
|
||||
types.push_back(DtoMemType(vd->type));
|
||||
} else {
|
||||
types.push_back(irparam->value->getType());
|
||||
}
|
||||
} else if (isSpecialRefVar(vd)) {
|
||||
types.push_back(DtoType(vd->type->pointerTo()));
|
||||
} else {
|
||||
types.push_back(DtoMemType(vd->type));
|
||||
else
|
||||
types.push_back(irparam->value->getType());
|
||||
}
|
||||
else if (isSpecialRefVar(vd))
|
||||
types.push_back(DtoType(vd->type->pointerTo()));
|
||||
else
|
||||
types.push_back(DtoMemType(vd->type));
|
||||
|
||||
IF_LOG Logger::cout() << "Nested var '" << vd->toChars()
|
||||
<< "' of type " << *types.back() << "\n";
|
||||
}
|
||||
|
@ -425,12 +434,17 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
|
|||
IF_LOG Logger::cout() << "frameType = " << *frameType << '\n';
|
||||
|
||||
// Store type in IrFunction
|
||||
getIrFunc(fd)->frameType = frameType;
|
||||
} else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) {
|
||||
// Propagate context arg properties if the context arg is passed on unmodified.
|
||||
DtoCreateNestedContextType(parFunc);
|
||||
getIrFunc(fd)->frameType = getIrFunc(parFunc)->frameType;
|
||||
getIrFunc(fd)->depth = getIrFunc(parFunc)->depth;
|
||||
irFunc.frameType = frameType;
|
||||
}
|
||||
else // no captured variables
|
||||
{
|
||||
if (parentFunc)
|
||||
{
|
||||
// Propagate context arg properties if the context arg is passed on unmodified.
|
||||
IrFunction& parentIrFunc = *getIrFunc(parentFunc);
|
||||
irFunc.frameType = parentIrFunc.frameType;
|
||||
irFunc.depth = parentIrFunc.depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue