Merged DMD 1.037 frontend

This commit is contained in:
Tomas Lindquist Olsen
2008-12-13 13:15:31 +01:00
parent cabc236a79
commit 6716aecc52
12 changed files with 507 additions and 349 deletions

View File

@@ -615,6 +615,7 @@ void AnonDeclaration::semantic(Scope *sc)
sc->flags = 0;
aad.structalign = sc->structalign;
aad.parent = ad;
for (unsigned i = 0; i < decl->dim; i++)
{
Dsymbol *s = (Dsymbol *)decl->data[i];

View File

@@ -33,9 +33,10 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
{
//printf("implicitCastTo(%s) => %s\n", type->toChars(), t->toChars());
if (implicitConvTo(t))
{
{ TY tyfrom = type->toBasetype()->ty;
TY tyto = t->toBasetype()->ty;
if (global.params.warnings &&
Type::impcnvWarn[type->toBasetype()->ty][t->toBasetype()->ty] &&
Type::impcnvWarn[tyfrom][tyto] &&
op != TOKint64)
{
Expression *e = optimize(WANTflags | WANTvalue);
@@ -43,8 +44,24 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
if (e->op == TOKint64)
return e->implicitCastTo(sc, t);
warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data",
loc.toChars(), toChars(), type->toChars(), t->toChars());
if (tyfrom == Tint32 &&
(op == TOKadd || op == TOKmin ||
op == TOKand || op == TOKor || op == TOKxor)
)
{
/* This is really only a semi-kludge fix,
* we really should look at the operands of op
* and see if they are narrower types.
* For example, b=b|b and b=b|7 and s=b+b should be allowed,
* but b=b|i should be an error.
*/
;
}
else
{
warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data",
loc.toChars(), toChars(), type->toChars(), t->toChars());
}
}
#if DMDV2
if (match == MATCHconst && t == type->constOf())

View File

@@ -623,6 +623,7 @@ struct FuncDeclaration : Declaration
virtual int isNested();
int needThis();
virtual int isVirtual();
virtual int isFinal();
virtual int addPreInvariant();
virtual int addPostInvariant();
Expression *interpret(InterState *istate, Expressions *arguments);

View File

@@ -5067,10 +5067,14 @@ Expression *DotIdExp::semantic(Scope *sc)
if (eright->op == TOKimport) // also used for template alias's
{
Dsymbol *s;
ScopeExp *ie = (ScopeExp *)eright;
s = ie->sds->search(loc, ident, 0);
/* Disable access to another module's private imports.
* The check for 'is sds our current module' is because
* the current module should have access to its own imports.
*/
Dsymbol *s = ie->sds->search(loc, ident,
(ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0);
if (s)
{
s = s->toAlias();

View File

@@ -1965,6 +1965,23 @@ int FuncDeclaration::isVirtual()
toParent()->isClassDeclaration();
}
int FuncDeclaration::isFinal()
{
ClassDeclaration *cd;
#if 0
printf("FuncDeclaration::isFinal(%s)\n", toChars());
printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
printf("result is %d\n",
isMember() &&
!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
(cd = toParent()->isClassDeclaration()) != NULL &&
cd->storage_class & STCfinal);
#endif
return isMember() &&
(Declaration::isFinal() ||
((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
}
int FuncDeclaration::isAbstract()
{
return storage_class & STCabstract;
@@ -2708,10 +2725,11 @@ void UnitTestDeclaration::semantic(Scope *sc)
{
if (global.params.useUnitTests)
{
Type *tret;
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
FuncDeclaration::semantic(sc);
Scope *sc2 = sc->push();
sc2->linkage = LINKd;
FuncDeclaration::semantic(sc2);
sc2->pop();
}
// We're going to need ModuleInfo even if the unit tests are not

View File

@@ -1,275 +1,262 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "dsymbol.h"
#include "import.h"
#include "identifier.h"
#include "module.h"
#include "scope.h"
#include "hdrgen.h"
#include "mtype.h"
#include "declaration.h"
#include "id.h"
/********************************* Import ****************************/
Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
int isstatic)
: Dsymbol(id)
{
this->loc = loc;
this->packages = packages;
this->id = id;
this->aliasId = aliasId;
this->isstatic = isstatic;
protection = PROTundefined;
pkg = NULL;
mod = NULL;
if (aliasId)
this->ident = aliasId;
// Kludge to change Import identifier to first package
else if (packages && packages->dim)
this->ident = (Identifier *)packages->data[0];
}
void Import::addAlias(Identifier *name, Identifier *alias)
{
if (isstatic)
error("cannot have an import bind list");
if (!aliasId)
this->ident = NULL; // make it an anonymous import
names.push(name);
aliases.push(alias);
}
const char *Import::kind()
{
return isstatic ? (char *)"static import" : (char *)"import";
}
enum PROT Import::prot()
{
return protection;
}
Dsymbol *Import::syntaxCopy(Dsymbol *s)
{
assert(!s);
Import *si;
si = new Import(loc, packages, id, aliasId, isstatic);
for (size_t i = 0; i < names.dim; i++)
{
si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
}
return si;
}
void Import::load(Scope *sc)
{
DsymbolTable *dst;
Dsymbol *s;
//printf("Import::load('%s')\n", toChars());
// See if existing module
dst = Package::resolve(packages, NULL, &pkg);
s = dst->lookup(id);
if (s)
{
if (s->isModule())
mod = (Module *)s;
else
error("package and module have the same name");
}
if (!mod)
{
// Load module
mod = Module::load(loc, packages, id);
dst->insert(id, mod); // id may be different from mod->ident,
// if so then insert alias
if (!mod->importedFrom)
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
}
if (!pkg)
pkg = mod;
mod->semantic();
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s')\n", toChars());
load(sc);
if (mod)
{
#if 0
if (mod->loc.linnum != 0)
{ /* If the line number is not 0, then this is not
* a 'root' module, i.e. it was not specified on the command line.
*/
mod->importedFrom = sc->module->importedFrom;
assert(mod->importedFrom);
}
#endif
/* Default to private importing
*/
protection = sc->protection;
if (!sc->explicitProtection)
protection = PROTprivate;
if (!isstatic && !aliasId && !names.dim)
{
sc->scopesym->importScope(mod, protection);
}
// Modules need a list of each imported module
sc->module->aimports.push(mod);
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
sc = sc->push(mod);
for (size_t i = 0; i < aliasdecls.dim; i++)
{ AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (!mod->search(loc, (Identifier *)names.data[i], 0))
error("%s not found", ((Identifier *)names.data[i])->toChars());
ad->semantic(sc);
ad->protection = protection;
}
sc = sc->pop();
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic2(Scope *sc)
{
//printf("Import::semantic2('%s')\n", toChars());
mod->semantic2();
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
}
Dsymbol *Import::toAlias()
{
if (aliasId)
return mod;
return this;
}
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
int result = 0;
if (names.dim == 0)
return Dsymbol::addMember(sc, sd, memnum);
if (aliasId)
result = Dsymbol::addMember(sc, sd, memnum);
for (size_t i = 0; i < names.dim; i++)
{
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias)
alias = name;
#if 1
TypeIdentifier *tname = new TypeIdentifier(loc, name);
#else
TypeIdentifier *tname = new TypeIdentifier(loc, NULL);
if (packages)
{
for (size_t j = 0; j < packages->dim; j++)
{ Identifier *pid = (Identifier *)packages->data[j];
if (!tname->ident)
tname->ident = pid;
else
tname->addIdent(pid);
}
}
if (!tname->ident)
tname->ident = id;
else
tname->addIdent(id);
tname->addIdent(name);
#endif
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
result |= ad->addMember(sc, sd, memnum);
aliasdecls.push(ad);
}
return result;
}
Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
{
//printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
if (!pkg)
load(NULL);
// Forward it to the package/module
return pkg->search(loc, ident, flags);
}
int Import::overloadInsert(Dsymbol *s)
{
// Allow multiple imports of the same name
return s->isImport() != NULL;
}
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (hgs->hdrgen && id == Id::object)
return; // object is imported by default
if (isstatic)
buf->writestring("static ");
buf->writestring("import ");
if (aliasId)
{
buf->printf("%s = ", aliasId->toChars());
}
if (packages && packages->dim)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = (Identifier *)packages->data[i];
buf->printf("%s.", pid->toChars());
}
}
buf->printf("%s;", id->toChars());
buf->writenl();
}
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "dsymbol.h"
#include "import.h"
#include "identifier.h"
#include "module.h"
#include "scope.h"
#include "hdrgen.h"
#include "mtype.h"
#include "declaration.h"
#include "id.h"
/********************************* Import ****************************/
Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
int isstatic)
: Dsymbol(id)
{
this->loc = loc;
this->packages = packages;
this->id = id;
this->aliasId = aliasId;
this->isstatic = isstatic;
protection = PROTundefined;
pkg = NULL;
mod = NULL;
if (aliasId)
this->ident = aliasId;
// Kludge to change Import identifier to first package
else if (packages && packages->dim)
this->ident = (Identifier *)packages->data[0];
}
void Import::addAlias(Identifier *name, Identifier *alias)
{
if (isstatic)
error("cannot have an import bind list");
if (!aliasId)
this->ident = NULL; // make it an anonymous import
names.push(name);
aliases.push(alias);
}
const char *Import::kind()
{
return isstatic ? (char *)"static import" : (char *)"import";
}
enum PROT Import::prot()
{
return protection;
}
Dsymbol *Import::syntaxCopy(Dsymbol *s)
{
assert(!s);
Import *si;
si = new Import(loc, packages, id, aliasId, isstatic);
for (size_t i = 0; i < names.dim; i++)
{
si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
}
return si;
}
void Import::load(Scope *sc)
{
DsymbolTable *dst;
Dsymbol *s;
//printf("Import::load('%s')\n", toChars());
// See if existing module
dst = Package::resolve(packages, NULL, &pkg);
s = dst->lookup(id);
if (s)
{
if (s->isModule())
mod = (Module *)s;
else
error("package and module have the same name");
}
if (!mod)
{
// Load module
mod = Module::load(loc, packages, id);
dst->insert(id, mod); // id may be different from mod->ident,
// if so then insert alias
if (!mod->importedFrom)
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
}
if (!pkg)
pkg = mod;
mod->semantic();
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s')\n", toChars());
load(sc);
if (mod)
{
#if 0
if (mod->loc.linnum != 0)
{ /* If the line number is not 0, then this is not
* a 'root' module, i.e. it was not specified on the command line.
*/
mod->importedFrom = sc->module->importedFrom;
assert(mod->importedFrom);
}
#endif
/* Default to private importing
*/
protection = sc->protection;
if (!sc->explicitProtection)
protection = PROTprivate;
if (!isstatic && !aliasId && !names.dim)
{
sc->scopesym->importScope(mod, protection);
}
// Modules need a list of each imported module
sc->module->aimports.push(mod);
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
sc = sc->push(mod);
for (size_t i = 0; i < aliasdecls.dim; i++)
{ AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (!mod->search(loc, (Identifier *)names.data[i], 0))
error("%s not found", ((Identifier *)names.data[i])->toChars());
ad->semantic(sc);
ad->protection = protection;
}
sc = sc->pop();
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic2(Scope *sc)
{
//printf("Import::semantic2('%s')\n", toChars());
mod->semantic2();
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
}
Dsymbol *Import::toAlias()
{
if (aliasId)
return mod;
return this;
}
/*****************************
* Add import to sd's symbol table.
*/
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
int result = 0;
if (names.dim == 0)
return Dsymbol::addMember(sc, sd, memnum);
if (aliasId)
result = Dsymbol::addMember(sc, sd, memnum);
/* Instead of adding the import to sd's symbol table,
* add each of the alias=name pairs
*/
for (size_t i = 0; i < names.dim; i++)
{
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias)
alias = name;
TypeIdentifier *tname = new TypeIdentifier(loc, name);
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
result |= ad->addMember(sc, sd, memnum);
aliasdecls.push(ad);
}
return result;
}
Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
{
//printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
if (!pkg)
load(NULL);
// Forward it to the package/module
return pkg->search(loc, ident, flags);
}
int Import::overloadInsert(Dsymbol *s)
{
// Allow multiple imports of the same name
return s->isImport() != NULL;
}
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (hgs->hdrgen && id == Id::object)
return; // object is imported by default
if (isstatic)
buf->writestring("static ");
buf->writestring("import ");
if (aliasId)
{
buf->printf("%s = ", aliasId->toChars());
}
if (packages && packages->dim)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = (Identifier *)packages->data[i];
buf->printf("%s.", pid->toChars());
}
}
buf->printf("%s;", id->toChars());
buf->writenl();
}

View File

@@ -2656,10 +2656,13 @@ unsigned Lexer::decodeUTF()
void Lexer::getDocComment(Token *t, unsigned lineComment)
{
OutBuffer buf;
/* ct tells us which kind of comment it is: '/', '*', or '+'
*/
unsigned char ct = t->ptr[2];
/* Start of comment text skips over / * *, / + +, or / / /
*/
unsigned char *q = t->ptr + 3; // start of comment text
int linestart = 0;
unsigned char *qend = p;
if (ct == '*' || ct == '+')
@@ -2684,6 +2687,12 @@ void Lexer::getDocComment(Token *t, unsigned lineComment)
}
}
/* Comment is now [q .. qend].
* Canonicalize it into buf[].
*/
OutBuffer buf;
int linestart = 0;
for (; q < qend; q++)
{
unsigned char c = *q;
@@ -2760,11 +2769,14 @@ void Lexer::getDocComment(Token *t, unsigned lineComment)
}
/********************************************
* Combine two document comments into one.
* Combine two document comments into one,
* separated by a newline.
*/
unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
{
//printf("Lexer::combineComments('%s', '%s')\n", c1, c2);
unsigned char *c = c2;
if (c1)
@@ -2775,9 +2787,12 @@ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
c = (unsigned char *)mem.malloc(len1 + 1 + len2 + 1);
memcpy(c, c1, len1);
c[len1] = '\n';
memcpy(c + len1 + 1, c2, len2);
c[len1 + 1 + len2] = 0;
if (len1 && c1[len1 - 1] != '\n')
{ c[len1] = '\n';
len1++;
}
memcpy(c + len1, c2, len2);
c[len1 + len2] = 0;
}
}
return c;
@@ -2951,6 +2966,7 @@ static Keyword keywords[] =
{ "__FILE__", TOKfile },
{ "__LINE__", TOKline },
{ "shared", TOKshared },
{ "immutable", TOKimmutable },
#endif
};

View File

@@ -64,7 +64,7 @@ Global::Global()
copyright = "Copyright (c) 1999-2008 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen";
version = "v1.036";
version = "v1.037";
ldc_version = "0.1";
global.structalign = 8;

View File

@@ -2485,7 +2485,7 @@ Expression *TypeAArray::defaultInit(Loc loc)
int TypeAArray::isZeroInit()
{
return 1;
return TRUE;
}
int TypeAArray::checkBoolean()
@@ -3994,6 +3994,12 @@ Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
goto Lfwd;
e = defaultInit(loc);
}
else if (ident == Id::stringof)
{ char *s = toChars();
e = new StringExp(loc, s, strlen(s), 'c');
Scope sc;
e = e->semantic(&sc);
}
else
{
if (!sym->memtype)

View File

@@ -386,7 +386,7 @@ Array *Parser::parseDeclDefs(int once)
}
ident = token.ident;
nextToken();
if (token.value == TOKcomma)
if (token.value == TOKcomma && peekNext() != TOKrparen)
args = parseArguments(); // pragma(identifier, args...)
else
check(TOKrparen); // pragma(identifier)
@@ -3068,7 +3068,7 @@ Statement *Parser::parseStatement(int flags)
}
ident = token.ident;
nextToken();
if (token.value == TOKcomma)
if (token.value == TOKcomma && peekNext() != TOKrparen)
args = parseArguments(); // pragma(identifier, args...);
else
check(TOKrparen); // pragma(identifier);

View File

@@ -16,6 +16,7 @@
#if _MSC_VER ||__MINGW32__
#include <malloc.h>
#include <string>
#endif
#if _WIN32
@@ -47,6 +48,7 @@ extern "C" void __cdecl _assert(void *e, void *f, unsigned line)
}
#endif
/*************************************
* Convert wchar string to ascii string.
*/
@@ -1606,6 +1608,36 @@ void OutBuffer::align(unsigned size)
fill0(nbytes);
}
////////////////////////////////////////////////////////////////
// The compiler shipped with Visual Studio 2005 (and possible
// other versions) does not support C99 printf format specfiers
// such as %z and %j
#if _MSC_VER
using std::string;
using std::wstring;
template<typename S>
inline void
search_and_replace(S& str, const S& what, const S& replacement)
{
assert(!what.empty());
size_t pos = str.find(what);
while (pos != S::npos)
{
str.replace(pos, what.size(), replacement);
pos = str.find(what, pos + replacement.size());
}
}
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
S tmp = f; \
search_and_replace(fmt, S("%z"), S("%l")); \
search_and_replace(fmt, S("%j"), S("%i")); \
f = tmp.c_str();
#else
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
#endif
void OutBuffer::vprintf(const char *format, va_list args)
{
char buffer[128];
@@ -1613,10 +1645,7 @@ void OutBuffer::vprintf(const char *format, va_list args)
unsigned psize;
int count;
// On some platforms (i.e. x86_64) va_list is an array and thus passed by
// reference. Copy the input list so we can copy it back before retrying.
va_list orig_args;
va_copy(orig_args, args);
WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format);
p = buffer;
psize = sizeof(buffer);
@@ -1628,7 +1657,19 @@ void OutBuffer::vprintf(const char *format, va_list args)
break;
psize *= 2;
#elif POSIX
count = vsnprintf(p,psize,format,args);
va_list va;
va_copy(va, args);
/*
The functions vprintf(), vfprintf(), vsprintf(), vsnprintf()
are equivalent to the functions printf(), fprintf(), sprintf(),
snprintf(), respectively, except that they are called with a
va_list instead of a variable number of arguments. These
functions do not call the va_end macro. Consequently, the value
of ap is undefined after the call. The application should call
va_end(ap) itself afterwards.
*/
count = vsnprintf(p,psize,format,va);
va_end(va);
if (count == -1)
psize *= 2;
else if (count >= psize)
@@ -1636,7 +1677,6 @@ void OutBuffer::vprintf(const char *format, va_list args)
else
break;
#endif
va_copy(args, orig_args);
p = (char *) alloca(psize); // buffer too small, try again with larger size
}
write(p,count);
@@ -1650,6 +1690,8 @@ void OutBuffer::vprintf(const wchar_t *format, va_list args)
unsigned psize;
int count;
WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format);
p = buffer;
psize = sizeof(buffer) / sizeof(buffer[0]);
for (;;)
@@ -1661,7 +1703,11 @@ void OutBuffer::vprintf(const wchar_t *format, va_list args)
psize *= 2;
#endif
#if POSIX
count = vsnwprintf(p,psize,format,args);
va_list va;
va_copy(va, args);
count = vsnwprintf(p,psize,format,va);
va_end(va);
if (count == -1)
psize *= 2;
else if (count >= psize)

View File

@@ -26,6 +26,7 @@
#include "id.h"
#include "hdrgen.h"
#include "parse.h"
#include "template.h"
/******************************** Statement ***************************/
@@ -451,10 +452,7 @@ Statement *CompoundStatement::semantic(Scope *sc)
body = new CompoundStatement(0, a);
body = new ScopeStatement(0, body);
static int num;
char name[3 + sizeof(num) * 3 + 1];
sprintf(name, "__o%d", ++num);
Identifier *id = Lexer::idPool(name);
Identifier *id = Lexer::uniqueId("__o");
Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
handler = new CompoundStatement(0, sexception, handler);
@@ -1107,12 +1105,17 @@ Statement *ForStatement::semantic(Scope *sc)
// Use a default value
condition = new IntegerExp(loc, 1, Type::tboolean);
sc->noctor++;
condition = condition->semantic(sc);
condition = resolveProperties(sc, condition);
condition = condition->optimize(WANTvalue);
condition = condition->checkToBoolean();
if (condition)
{
condition = condition->semantic(sc);
condition = resolveProperties(sc, condition);
condition = condition->optimize(WANTvalue);
condition = condition->checkToBoolean();
}
if (increment)
increment = increment->semantic(sc);
{ increment = increment->semantic(sc);
increment = resolveProperties(sc, increment);
}
sc->sbreak = this;
sc->scontinue = this;
@@ -1257,8 +1260,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
//printf("ForeachStatement::semantic() %p\n", this);
ScopeDsymbol *sym;
Statement *s = this;
int dim = arguments->dim;
int i;
size_t dim = arguments->dim;
TypeAArray *taa = NULL;
Type *tn = NULL;
@@ -1272,6 +1274,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
aggr = aggr->semantic(sc);
aggr = resolveProperties(sc, aggr);
aggr = aggr->optimize(WANTvalue);
if (!aggr->type)
{
error("invalid foreach aggregate %s", aggr->toChars());
@@ -1387,7 +1390,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
return s;
}
for (i = 0; i < dim; i++)
for (size_t i = 0; i < dim; i++)
{ Argument *arg = (Argument *)arguments->data[i];
if (!arg->type)
{
@@ -1419,7 +1422,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
{ Argument *arg;
i = (dim == 1) ? 0 : 1; // index of value
int i = (dim == 1) ? 0 : 1; // index of value
arg = (Argument *)arguments->data[i];
arg->type = arg->type->semantic(loc, sc);
tnv = arg->type->toBasetype();
@@ -1437,7 +1440,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
}
}
for (i = 0; i < dim; i++)
for (size_t i = 0; i < dim; i++)
{ // Declare args
Argument *arg = (Argument *)arguments->data[i];
VarDeclaration *var;
@@ -1468,7 +1471,8 @@ Statement *ForeachStatement::semantic(Scope *sc)
if (aggr->op == TOKstring)
aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
else
error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars());
error("foreach: %s is not an array of %s",
tab->toChars(), value->type->toChars());
}
if (key)
@@ -1505,6 +1509,72 @@ Statement *ForeachStatement::semantic(Scope *sc)
case Tclass:
case Tstruct:
#if DMDV2
{ /* Look for range iteration, i.e. the properties
* .empty, .next, .retreat, .head and .rear
* foreach (e; range) { ... }
* translates to:
* for (auto __r = range; !__r.empty; __r.next)
* { auto e = __r.head;
* ...
* }
*/
if (dim != 1) // only one argument allowed with ranges
goto Lapply;
AggregateDeclaration *ad = (tab->ty == Tclass)
? (AggregateDeclaration *)((TypeClass *)tab)->sym
: (AggregateDeclaration *)((TypeStruct *)tab)->sym;
Identifier *idhead;
Identifier *idnext;
if (op == TOKforeach)
{ idhead = Id::Fhead;
idnext = Id::Fnext;
}
else
{ idhead = Id::Frear;
idnext = Id::Fretreat;
}
Dsymbol *shead = search_function(ad, idhead);
if (!shead)
goto Lapply;
/* Generate a temporary __r and initialize it with the aggregate.
*/
Identifier *id = Identifier::generateId("__r");
VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr));
r->semantic(sc);
Statement *init = new DeclarationStatement(loc, r);
// !__r.empty
Expression *e = new VarExp(loc, r);
e = new DotIdExp(loc, e, Id::Fempty);
Expression *condition = new NotExp(loc, e);
// __r.next
e = new VarExp(loc, r);
Expression *increment = new DotIdExp(loc, e, idnext);
/* Declaration statement for e:
* auto e = __r.idhead;
*/
e = new VarExp(loc, r);
Expression *einit = new DotIdExp(loc, e, idhead);
einit = einit->semantic(sc);
Argument *arg = (Argument *)arguments->data[0];
VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
ve->storage_class |= STCforeach;
ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
DeclarationExp *de = new DeclarationExp(loc, ve);
Statement *body = new CompoundStatement(loc,
new DeclarationStatement(loc, de), this->body);
s = new ForStatement(loc, init, condition, increment, body);
s = s->semantic(sc);
break;
}
#endif
case Tdelegate:
Lapply:
{ FuncDeclaration *fdapply;
@@ -1540,7 +1610,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
* int delegate(ref T arg) { body }
*/
args = new Arguments();
for (i = 0; i < dim; i++)
for (size_t i = 0; i < dim; i++)
{ Argument *arg = (Argument *)arguments->data[i];
arg->type = arg->type->semantic(loc, sc);
@@ -1551,10 +1621,8 @@ Statement *ForeachStatement::semantic(Scope *sc)
// a reference.
VarDeclaration *v;
Initializer *ie;
char applyArg[10 + sizeof(i)*3 + 1];
sprintf(applyArg, "__applyArg%d", i);
id = Lexer::idPool(applyArg);
id = Lexer::uniqueId("__applyArg", i);
ie = new ExpInitializer(0, new IdentifierExp(0, id));
v = new VarDeclaration(0, arg->type, arg->ident, ie);
@@ -2145,6 +2213,11 @@ Statement *PragmaStatement::semantic(Scope *sc)
}
else if (ident == Id::lib)
{
#if 1
/* Should this be allowed?
*/
error("pragma(lib) not allowed as statement");
#else
if (!args || args->dim != 1)
error("string expected for library name");
else
@@ -2166,6 +2239,7 @@ Statement *PragmaStatement::semantic(Scope *sc)
mem.free(name);
}
}
#endif
}
else
error("unrecognized pragma(%s)", ident->toChars());
@@ -2454,8 +2528,7 @@ Statement *CaseStatement::semantic(Scope *sc)
//printf("CaseStatement::semantic() %s\n", toChars());
exp = exp->semantic(sc);
if (sw)
{ int i;
{
exp = exp->implicitCastTo(sc, sw->condition->type);
exp = exp->optimize(WANTvalue | WANTinterpret);
if (exp->op != TOKstring && exp->op != TOKint64)
@@ -2464,7 +2537,7 @@ Statement *CaseStatement::semantic(Scope *sc)
exp = new IntegerExp(0);
}
for (i = 0; i < sw->cases->dim; i++)
for (int i = 0; i < sw->cases->dim; i++)
{
CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
@@ -2478,7 +2551,7 @@ Statement *CaseStatement::semantic(Scope *sc)
sw->cases->push(this);
// Resolve any goto case's with no exp to this case statement
for (i = 0; i < sw->gotoCases.dim; i++)
for (size_t i = 0; i < sw->gotoCases.dim; i++)
{
GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
@@ -2875,32 +2948,25 @@ Statement *ReturnStatement::semantic(Scope *sc)
exp->op == TOKstring)
{
sc->fes->cases.push(this);
// Construct: return cases.dim+1;
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
}
else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
{
Statement *s1;
Statement *s2;
s = new ReturnStatement(0, NULL);
sc->fes->cases.push(s);
// Construct: { exp; return cases.dim + 1; }
s1 = new ExpStatement(loc, exp);
s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
Statement *s1 = new ExpStatement(loc, exp);
Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
s = new CompoundStatement(loc, s1, s2);
}
else
{
VarExp *v;
Statement *s1;
Statement *s2;
// Construct: return vresult;
if (!fd->vresult)
{ VarDeclaration *v;
v = new VarDeclaration(loc, tret, Id::result, NULL);
{ // Declare vresult
VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
v->noauto = 1;
v->semantic(scx);
if (!scx->insert(v))
@@ -2909,16 +2975,14 @@ Statement *ReturnStatement::semantic(Scope *sc)
fd->vresult = v;
}
v = new VarExp(0, fd->vresult);
s = new ReturnStatement(0, v);
s = new ReturnStatement(0, new VarExp(0, fd->vresult));
sc->fes->cases.push(s);
// Construct: { vresult = exp; return cases.dim + 1; }
v = new VarExp(0, fd->vresult);
exp = new AssignExp(loc, v, exp);
exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp);
exp = exp->semantic(sc);
s1 = new ExpStatement(loc, exp);
s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
Statement *s1 = new ExpStatement(loc, exp);
Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
s = new CompoundStatement(loc, s1, s2);
}
return s;
@@ -2959,9 +3023,10 @@ Statement *ReturnStatement::semantic(Scope *sc)
gs->label = fd->returnLabel;
if (exp)
{ Statement *s;
s = new ExpStatement(0, exp);
{ /* Replace: return exp;
* with: exp; goto returnLabel;
*/
Statement *s = new ExpStatement(0, exp);
return new CompoundStatement(loc, s, gs);
}
return gs;
@@ -3739,10 +3804,7 @@ void OnScopeStatement::scopeCode(Statement **sentry, Statement **sexception, Sta
* sexception: x = 1;
* sfinally: if (!x) statement;
*/
static int num;
char name[5 + sizeof(num) * 3 + 1];
sprintf(name, "__osf%d", ++num);
Identifier *id = Lexer::idPool(name);
Identifier *id = Lexer::uniqueId("__os");
ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0));
VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);