Skip to content

Commit

Permalink
Merge pull request #535 from 9rnsr/fix5933
Browse files Browse the repository at this point in the history
Issue 5933 & 7159 - Resolve forward reference to auto-return member function
  • Loading branch information
WalterBright committed Nov 20, 2012
2 parents e3daa5e + a9bb247 commit 2ba68e1
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 47 deletions.
1 change: 1 addition & 0 deletions src/declaration.h
Expand Up @@ -632,6 +632,7 @@ struct FuncDeclaration : Declaration
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
bool functionSemantic(Scope *sc);
// called from semantic3
void varArgs(Scope *sc, TypeFunction*, VarDeclaration *&, VarDeclaration *&);
VarDeclaration *declareThis(Scope *sc, AggregateDeclaration *ad);
Expand Down
73 changes: 26 additions & 47 deletions src/expression.c
Expand Up @@ -3027,45 +3027,10 @@ Expression *DsymbolExp::semantic(Scope *sc)
}
f = s->isFuncDeclaration();
if (f)
{ f = f->toAliasFunc();

if (!f->originalType && f->scope) // semantic not yet run
{
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging() && !f->isSpeculative())
global.gag = 0;
f->semantic(f->scope);
global.gag = oldgag;
}

// if inferring return type, sematic3 needs to be run
if (f->scope && (f->inferRetType && f->type && !f->type->nextOf() ||
getFuncTemplateDecl(f)))
{
TemplateInstance *spec = f->isSpeculative();
int olderrs = global.errors;
// If it isn't speculative, we need to show errors
unsigned oldgag = global.gag;
if (global.gag && !spec)
global.gag = 0;
f->semantic3(f->scope);
global.gag = oldgag;
// Update the template instantiation with the number
// of errors which occured.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
}

if (f->isUnitTestDeclaration())
{
error("cannot call unittest function %s", toChars());
return new ErrorExp();
}
if (!f->type->deco)
{
error("forward reference to %s", toChars());
{
f = f->toAliasFunc();
if (!f->functionSemantic(sc))
return new ErrorExp();
}
FuncDeclaration *fd = s->isFuncDeclaration();
fd->type = f->type;
return new VarExp(loc, fd, hasOverloads);
Expand Down Expand Up @@ -5058,8 +5023,12 @@ Expression *VarExp::semantic(Scope *sc)
#if LOGSEMANTIC
printf("VarExp::semantic(%s)\n", toChars());
#endif
// if (var->sem == SemanticStart && var->scope) // if forward referenced
// var->semantic(sc);
if (FuncDeclaration *f = var->isFuncDeclaration())
{
if (!f->functionSemantic(sc))
return new ErrorExp();
}

if (!type)
{ type = var->type;
#if 0
Expand Down Expand Up @@ -7154,16 +7123,26 @@ Expression *DotVarExp::semantic(Scope *sc)

e1 = e1->semantic(sc);
e1 = e1->addDtorHook(sc);
type = var->type;
if (!type && global.errors)
{ // var is goofed up, just return 0
return new ErrorExp();
}
assert(type);

Type *t1 = e1->type;
if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution
FuncDeclaration *f = var->isFuncDeclaration();
if (f) // for functions, do checks after overload resolution
{
if (!f->functionSemantic(sc))
return new ErrorExp();

type = f->type;
assert(type);
}
else
{
type = var->type;
if (!type && global.errors)
{ // var is goofed up, just return 0
goto Lerr;
}
assert(type);

if (t1->ty == Tpointer)
t1 = t1->nextOf();

Expand Down
43 changes: 43 additions & 0 deletions src/func.c
Expand Up @@ -1681,6 +1681,49 @@ void FuncDeclaration::semantic3(Scope *sc)
//fflush(stdout);
}

bool FuncDeclaration::functionSemantic(Scope *sc)
{
if (!originalType && scope) // semantic not yet run
{
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging() && !isSpeculative())
global.gag = 0;
semantic(scope);
global.gag = oldgag;
}

// if inferring return type, sematic3 needs to be run
if (scope && (inferRetType && type && !type->nextOf() ||
getFuncTemplateDecl(this)))
{
TemplateInstance *spec = isSpeculative();
int olderrs = global.errors;
// If it isn't speculative, we need to show errors
unsigned oldgag = global.gag;
if (global.gag && !spec)
global.gag = 0;
semantic3(scope);
global.gag = oldgag;
// Update the template instantiation with the number
// of errors which occured.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
}

if (isUnitTestDeclaration())
{
error("cannot call unittest function %s", toChars());
return false;
}
if (!type->deco)
{
error("forward reference to %s", toChars());
return false;
}

return true;
}

void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
//printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
Expand Down
43 changes: 43 additions & 0 deletions test/runnable/xtest46.d
Expand Up @@ -4218,6 +4218,37 @@ void test5696()
}
}

/***************************************************/
// 5933

int dummyfunc();
alias typeof(dummyfunc) FuncType;

struct S5933a { auto x() { return 0; } }
static assert(is(typeof(&S5933a.init.x) == int delegate()));

struct S5933b { auto x() { return 0; } }
static assert(is(typeof(S5933b.init.x) == FuncType));

struct S5933c { auto x() { return 0; } }
static assert(is(typeof(&S5933c.x) == int function()));

struct S5933d { auto x() { return 0; } }
static assert(is(typeof(S5933d.x) == FuncType));


class C5933a { auto x() { return 0; } }
static assert(is(typeof(&(new C5933b()).x) == int delegate()));

class C5933b { auto x() { return 0; } }
static assert(is(typeof((new C5933b()).x) == FuncType));

class C5933c { auto x() { return 0; } }
static assert(is(typeof(&C5933c.x) == int function()));

class C5933d { auto x() { return 0; } }
static assert(is(typeof(C5933d.x) == FuncType));

/***************************************************/
// 6084

Expand Down Expand Up @@ -4830,6 +4861,18 @@ void test7150()
assert(A7150.cnt == 2);
}

/***************************************************/
// 7159

class HomeController7159 {
void* foo() {
return cast(void*)&HomeController7159.displayDefault;
}
auto displayDefault() {
return 1;
}
}

/***************************************************/
// 7160

Expand Down

0 comments on commit 2ba68e1

Please sign in to comment.