Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 6423 - Garbage is returned from void main() #3938

Merged
merged 1 commit into from Sep 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 21 additions & 21 deletions src/statement.c
Expand Up @@ -3538,7 +3538,6 @@ ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
: Statement(loc)
{
this->exp = exp;
this->implicit0 = 0;
}

Statement *ReturnStatement::syntaxCopy()
Expand Down Expand Up @@ -3570,13 +3569,6 @@ Statement *ReturnStatement::semantic(Scope *sc)
if (tret)
tbret = tret->toBasetype();

// main() returns 0, even if it returns void
if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain())
{
implicit0 = 1;
exp = new IntegerExp(0);
}

if (sc->flags & SCOPEcontract)
error("return statements cannot be in contracts");
if (sc->os && sc->os->tok != TOKon_scope_failure)
Expand Down Expand Up @@ -3760,7 +3752,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
{
Statement *s;

if (exp && !implicit0)
if (exp)
{
exp = exp->implicitCastTo(sc, tret);
}
Expand Down Expand Up @@ -3891,24 +3883,32 @@ Statement *ReturnStatement::semantic(Scope *sc)
return gs;
}

if (exp && tbret->ty == Tvoid && !implicit0)
if (tbret->ty == Tvoid)
{
if (exp->type->ty != Tvoid)
if (exp && exp->type->ty != Tvoid)
{
error("cannot return non-void from void function");
}

/* Replace:
* return exp;
* with:
* cast(void)exp; return;
*/
Expression *ce = new CastExp(loc, exp, Type::tvoid);
Statement *s = new ExpStatement(loc, ce);
s = s->semantic(sc);
Expression *eret = exp;
// main() returns 0, even if it returns void
if (fd->isMain())
exp = new IntegerExp(0);
else
exp = NULL;

exp = NULL;
return new CompoundStatement(loc, s, this);
if (eret)
{
/* Replace:
* return exp;
* with:
* cast(void)exp; return;
*/
Expression *ce = new CastExp(loc, eret, Type::tvoid);
Statement *s = new ExpStatement(loc, ce);
s = s->semantic(sc);
return new CompoundStatement(loc, s, this);
}
}

return this;
Expand Down
1 change: 0 additions & 1 deletion src/statement.h
Expand Up @@ -522,7 +522,6 @@ class ReturnStatement : public Statement
{
public:
Expression *exp;
bool implicit0; // this is an implicit "return 0;"

ReturnStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
Expand Down
6 changes: 6 additions & 0 deletions test/Makefile
Expand Up @@ -134,6 +134,12 @@ DISABLED_TESTS += testargtypes
DISABLED_TESTS += testxmm
endif

ifeq ($(OS),osx)
ifeq ($(MODEL),64)
DISABLED_TESTS += test6423
endif
endif

runnable_tests=$(wildcard runnable/*.d) $(wildcard runnable/*.sh)
runnable_test_results=$(addsuffix .out,$(addprefix $(RESULTS_DIR)/,$(runnable_tests)))

Expand Down
24 changes: 24 additions & 0 deletions test/runnable/test6423.d
@@ -0,0 +1,24 @@

bool flag;

void f()
{
}

void main()
{
if (!flag)
{
flag = true;
caller();
}
return f();
}

alias maintype = extern(C) int function();

void caller()
{
auto fp = cast(maintype)&main;
assert(fp() == 0);
}