mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-04-20 02:39:02 +02:00
Merged DMD 1.038
This commit is contained in:
11
dmd/attrib.c
11
dmd/attrib.c
@@ -406,7 +406,7 @@ void LinkDeclaration::semantic3(Scope *sc)
|
||||
}
|
||||
|
||||
void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{ char *p;
|
||||
{ const char *p;
|
||||
|
||||
switch (linkage)
|
||||
{
|
||||
@@ -431,7 +431,7 @@ void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
|
||||
char *LinkDeclaration::toChars()
|
||||
{
|
||||
return "extern ()";
|
||||
return (char *)"extern ()";
|
||||
}
|
||||
|
||||
/********************************* ProtDeclaration ****************************/
|
||||
@@ -476,7 +476,7 @@ void ProtDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{ char *p;
|
||||
{ const char *p;
|
||||
|
||||
switch (protection)
|
||||
{
|
||||
@@ -721,7 +721,7 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
|
||||
const char *AnonDeclaration::kind()
|
||||
{
|
||||
return (char *)(isunion ? "anonymous union" : "anonymous struct");
|
||||
return (isunion ? "anonymous union" : "anonymous struct");
|
||||
}
|
||||
|
||||
/********************************* PragmaDeclaration ****************************/
|
||||
@@ -1363,6 +1363,7 @@ const char *StaticIfDeclaration::kind()
|
||||
CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
|
||||
: AttribDeclaration(NULL)
|
||||
{
|
||||
//printf("CompileDeclaration(loc = %d)\n", loc.linnum);
|
||||
this->loc = loc;
|
||||
this->exp = exp;
|
||||
this->sd = NULL;
|
||||
@@ -1392,7 +1393,7 @@ int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
|
||||
void CompileDeclaration::compileIt(Scope *sc)
|
||||
{
|
||||
//printf("CompileDeclaration::compileIt()\n");
|
||||
//printf("CompileDeclaration::compileIt(loc = %d)\n", loc.linnum);
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
exp = exp->optimize(WANTvalue | WANTinterpret);
|
||||
|
||||
@@ -539,7 +539,16 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
sc->inunion = 0;
|
||||
|
||||
if (isCOMclass())
|
||||
{
|
||||
#if _WIN32
|
||||
sc->linkage = LINKwindows;
|
||||
#else
|
||||
/* This enables us to use COM objects under Linux and
|
||||
* work with things like XPCOM
|
||||
*/
|
||||
sc->linkage = LINKc;
|
||||
#endif
|
||||
}
|
||||
sc->protection = PROTpublic;
|
||||
sc->explicitProtection = 0;
|
||||
sc->structalign = 8;
|
||||
|
||||
782
dmd/cond.c
782
dmd/cond.c
@@ -1,391 +1,391 @@
|
||||
|
||||
// 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 "id.h"
|
||||
#include "init.h"
|
||||
#include "declaration.h"
|
||||
#include "identifier.h"
|
||||
#include "expression.h"
|
||||
#include "cond.h"
|
||||
#include "module.h"
|
||||
#include "template.h"
|
||||
#include "lexer.h"
|
||||
#ifdef _DH
|
||||
#include "mtype.h"
|
||||
#include "scope.h"
|
||||
#endif
|
||||
|
||||
int findCondition(Array *ids, Identifier *ident)
|
||||
{
|
||||
if (ids)
|
||||
{
|
||||
for (int i = 0; i < ids->dim; i++)
|
||||
{
|
||||
char *id = (char *)ids->data[i];
|
||||
|
||||
if (strcmp(id, ident->toChars()) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
Condition::Condition(Loc loc)
|
||||
{
|
||||
this->loc = loc;
|
||||
inc = 0;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: Condition(0)
|
||||
{
|
||||
this->mod = mod;
|
||||
this->level = level;
|
||||
this->ident = ident;
|
||||
}
|
||||
|
||||
Condition *DVCondition::syntaxCopy()
|
||||
{
|
||||
return this; // don't need to copy
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void DebugCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.debuglevel = level;
|
||||
}
|
||||
|
||||
void DebugCondition::addGlobalIdent(char *ident)
|
||||
{
|
||||
if (!global.params.debugids)
|
||||
global.params.debugids = new Array();
|
||||
global.params.debugids->push(ident);
|
||||
}
|
||||
|
||||
|
||||
DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->debugids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.debugids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{ if (!mod->debugidsNot)
|
||||
mod->debugidsNot = new Array();
|
||||
mod->debugidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.debuglevel || level <= mod->debuglevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("debug (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("debug (%u)", level);
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void VersionCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.versionlevel = level;
|
||||
}
|
||||
|
||||
void VersionCondition::checkPredefined(Loc loc, char *ident)
|
||||
{
|
||||
static char* reserved[] =
|
||||
{
|
||||
"DigitalMars", "LLVM", "LDC", "LLVM64",
|
||||
"X86", "X86_64", "PPC", "PPC64",
|
||||
"Windows", "Win32", "Win64",
|
||||
"linux", "darwin", "Posix",
|
||||
"LittleEndian", "BigEndian",
|
||||
"all",
|
||||
"none",
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
|
||||
{
|
||||
if (strcmp(ident, reserved[i]) == 0)
|
||||
goto Lerror;
|
||||
}
|
||||
|
||||
if (ident[0] == 'D' && ident[1] == '_')
|
||||
goto Lerror;
|
||||
|
||||
return;
|
||||
|
||||
Lerror:
|
||||
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addGlobalIdent(char *ident)
|
||||
{
|
||||
checkPredefined(0, ident);
|
||||
addPredefinedGlobalIdent(ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addPredefinedGlobalIdent(char *ident)
|
||||
{
|
||||
if (!global.params.versionids)
|
||||
global.params.versionids = new Array();
|
||||
global.params.versionids->push(ident);
|
||||
}
|
||||
|
||||
|
||||
VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
|
||||
//if (ident) printf("\tident = '%s'\n", ident->toChars());
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->versionids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.versionids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{
|
||||
if (!mod->versionidsNot)
|
||||
mod->versionidsNot = new Array();
|
||||
mod->versionidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.versionlevel || level <= mod->versionlevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("version (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("version (%u)", level);
|
||||
}
|
||||
|
||||
|
||||
/**************************** StaticIfCondition *******************************/
|
||||
|
||||
StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
}
|
||||
|
||||
Condition *StaticIfCondition::syntaxCopy()
|
||||
{
|
||||
return new StaticIfCondition(loc, exp->syntaxCopy());
|
||||
}
|
||||
|
||||
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
#if 0
|
||||
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
|
||||
if (s)
|
||||
{
|
||||
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
||||
}
|
||||
#endif
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "static if conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sc = sc->push(sc->scopesym);
|
||||
sc->sd = s; // s gets any addMember()
|
||||
sc->flags |= SCOPEstaticif;
|
||||
Expression *e = exp->semantic(sc);
|
||||
sc->pop();
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->isBool(TRUE))
|
||||
inc = 1;
|
||||
else if (e->isBool(FALSE))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("static if(");
|
||||
exp->toCBuffer(buf, hgs);
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
/**************************** IftypeCondition *******************************/
|
||||
|
||||
IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->targ = targ;
|
||||
this->id = id;
|
||||
this->tok = tok;
|
||||
this->tspec = tspec;
|
||||
}
|
||||
|
||||
Condition *IftypeCondition::syntaxCopy()
|
||||
{
|
||||
return new IftypeCondition(loc,
|
||||
targ->syntaxCopy(),
|
||||
id,
|
||||
tok,
|
||||
tspec ? tspec->syntaxCopy() : NULL);
|
||||
}
|
||||
|
||||
int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
|
||||
{
|
||||
//printf("IftypeCondition::include()\n");
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "iftype conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
unsigned errors = global.errors;
|
||||
global.gag++; // suppress printing of error messages
|
||||
targ = targ->semantic(loc, sc);
|
||||
global.gag--;
|
||||
if (errors != global.errors) // if any errors happened
|
||||
{ inc = 2; // then condition is false
|
||||
global.errors = errors;
|
||||
}
|
||||
else if (id && tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec.
|
||||
* If TRUE, declare id as an alias for the specialized type.
|
||||
*/
|
||||
|
||||
MATCH m;
|
||||
TemplateTypeParameter tp(loc, id, NULL, NULL);
|
||||
|
||||
TemplateParameters parameters;
|
||||
parameters.setDim(1);
|
||||
parameters.data[0] = (void *)&tp;
|
||||
|
||||
Objects dedtypes;
|
||||
dedtypes.setDim(1);
|
||||
|
||||
m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes);
|
||||
if (m == MATCHnomatch ||
|
||||
(m != MATCHexact && tok == TOKequal))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
inc = 1;
|
||||
Type *tded = (Type *)dedtypes.data[0];
|
||||
if (!tded)
|
||||
tded = targ;
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, tded);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
}
|
||||
}
|
||||
else if (id)
|
||||
{
|
||||
/* Declare id as an alias for type targ. Evaluate to TRUE
|
||||
*/
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, targ);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
inc = 1;
|
||||
}
|
||||
else if (tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec
|
||||
*/
|
||||
tspec = tspec->semantic(loc, sc);
|
||||
//printf("targ = %s\n", targ->toChars());
|
||||
//printf("tspec = %s\n", tspec->toChars());
|
||||
if (tok == TOKcolon)
|
||||
{ if (targ->implicitConvTo(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
else /* == */
|
||||
{ if (targ->equals(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
inc = 1;
|
||||
//printf("inc = %d\n", inc);
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("iftype(");
|
||||
targ->toCBuffer(buf, id, hgs);
|
||||
if (tspec)
|
||||
{
|
||||
if (tok == TOKcolon)
|
||||
buf->writestring(" : ");
|
||||
else
|
||||
buf->writestring(" == ");
|
||||
tspec->toCBuffer(buf, NULL, hgs);
|
||||
}
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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 "id.h"
|
||||
#include "init.h"
|
||||
#include "declaration.h"
|
||||
#include "identifier.h"
|
||||
#include "expression.h"
|
||||
#include "cond.h"
|
||||
#include "module.h"
|
||||
#include "template.h"
|
||||
#include "lexer.h"
|
||||
#ifdef _DH
|
||||
#include "mtype.h"
|
||||
#include "scope.h"
|
||||
#endif
|
||||
|
||||
int findCondition(Array *ids, Identifier *ident)
|
||||
{
|
||||
if (ids)
|
||||
{
|
||||
for (int i = 0; i < ids->dim; i++)
|
||||
{
|
||||
char *id = (char *)ids->data[i];
|
||||
|
||||
if (strcmp(id, ident->toChars()) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
Condition::Condition(Loc loc)
|
||||
{
|
||||
this->loc = loc;
|
||||
inc = 0;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: Condition(0)
|
||||
{
|
||||
this->mod = mod;
|
||||
this->level = level;
|
||||
this->ident = ident;
|
||||
}
|
||||
|
||||
Condition *DVCondition::syntaxCopy()
|
||||
{
|
||||
return this; // don't need to copy
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void DebugCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.debuglevel = level;
|
||||
}
|
||||
|
||||
void DebugCondition::addGlobalIdent(char *ident)
|
||||
{
|
||||
if (!global.params.debugids)
|
||||
global.params.debugids = new Array();
|
||||
global.params.debugids->push(ident);
|
||||
}
|
||||
|
||||
|
||||
DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->debugids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.debugids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{ if (!mod->debugidsNot)
|
||||
mod->debugidsNot = new Array();
|
||||
mod->debugidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.debuglevel || level <= mod->debuglevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("debug (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("debug (%u)", level);
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void VersionCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.versionlevel = level;
|
||||
}
|
||||
|
||||
void VersionCondition::checkPredefined(Loc loc, char *ident)
|
||||
{
|
||||
static const char* reserved[] =
|
||||
{
|
||||
"DigitalMars", "LLVM", "LDC", "LLVM64",
|
||||
"X86", "X86_64", "PPC", "PPC64",
|
||||
"Windows", "Win32", "Win64",
|
||||
"linux", "darwin", "Posix",
|
||||
"LittleEndian", "BigEndian",
|
||||
"all",
|
||||
"none",
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
|
||||
{
|
||||
if (strcmp(ident, reserved[i]) == 0)
|
||||
goto Lerror;
|
||||
}
|
||||
|
||||
if (ident[0] == 'D' && ident[1] == '_')
|
||||
goto Lerror;
|
||||
|
||||
return;
|
||||
|
||||
Lerror:
|
||||
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addGlobalIdent(char *ident)
|
||||
{
|
||||
checkPredefined(0, ident);
|
||||
addPredefinedGlobalIdent(ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addPredefinedGlobalIdent(char *ident)
|
||||
{
|
||||
if (!global.params.versionids)
|
||||
global.params.versionids = new Array();
|
||||
global.params.versionids->push(ident);
|
||||
}
|
||||
|
||||
|
||||
VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
|
||||
//if (ident) printf("\tident = '%s'\n", ident->toChars());
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->versionids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.versionids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{
|
||||
if (!mod->versionidsNot)
|
||||
mod->versionidsNot = new Array();
|
||||
mod->versionidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.versionlevel || level <= mod->versionlevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("version (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("version (%u)", level);
|
||||
}
|
||||
|
||||
|
||||
/**************************** StaticIfCondition *******************************/
|
||||
|
||||
StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
}
|
||||
|
||||
Condition *StaticIfCondition::syntaxCopy()
|
||||
{
|
||||
return new StaticIfCondition(loc, exp->syntaxCopy());
|
||||
}
|
||||
|
||||
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
#if 0
|
||||
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
|
||||
if (s)
|
||||
{
|
||||
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
||||
}
|
||||
#endif
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "static if conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sc = sc->push(sc->scopesym);
|
||||
sc->sd = s; // s gets any addMember()
|
||||
sc->flags |= SCOPEstaticif;
|
||||
Expression *e = exp->semantic(sc);
|
||||
sc->pop();
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->isBool(TRUE))
|
||||
inc = 1;
|
||||
else if (e->isBool(FALSE))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("static if(");
|
||||
exp->toCBuffer(buf, hgs);
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
/**************************** IftypeCondition *******************************/
|
||||
|
||||
IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->targ = targ;
|
||||
this->id = id;
|
||||
this->tok = tok;
|
||||
this->tspec = tspec;
|
||||
}
|
||||
|
||||
Condition *IftypeCondition::syntaxCopy()
|
||||
{
|
||||
return new IftypeCondition(loc,
|
||||
targ->syntaxCopy(),
|
||||
id,
|
||||
tok,
|
||||
tspec ? tspec->syntaxCopy() : NULL);
|
||||
}
|
||||
|
||||
int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
|
||||
{
|
||||
//printf("IftypeCondition::include()\n");
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "iftype conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
unsigned errors = global.errors;
|
||||
global.gag++; // suppress printing of error messages
|
||||
targ = targ->semantic(loc, sc);
|
||||
global.gag--;
|
||||
if (errors != global.errors) // if any errors happened
|
||||
{ inc = 2; // then condition is false
|
||||
global.errors = errors;
|
||||
}
|
||||
else if (id && tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec.
|
||||
* If TRUE, declare id as an alias for the specialized type.
|
||||
*/
|
||||
|
||||
MATCH m;
|
||||
TemplateTypeParameter tp(loc, id, NULL, NULL);
|
||||
|
||||
TemplateParameters parameters;
|
||||
parameters.setDim(1);
|
||||
parameters.data[0] = (void *)&tp;
|
||||
|
||||
Objects dedtypes;
|
||||
dedtypes.setDim(1);
|
||||
|
||||
m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes);
|
||||
if (m == MATCHnomatch ||
|
||||
(m != MATCHexact && tok == TOKequal))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
inc = 1;
|
||||
Type *tded = (Type *)dedtypes.data[0];
|
||||
if (!tded)
|
||||
tded = targ;
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, tded);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
}
|
||||
}
|
||||
else if (id)
|
||||
{
|
||||
/* Declare id as an alias for type targ. Evaluate to TRUE
|
||||
*/
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, targ);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
inc = 1;
|
||||
}
|
||||
else if (tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec
|
||||
*/
|
||||
tspec = tspec->semantic(loc, sc);
|
||||
//printf("targ = %s\n", targ->toChars());
|
||||
//printf("tspec = %s\n", tspec->toChars());
|
||||
if (tok == TOKcolon)
|
||||
{ if (targ->implicitConvTo(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
else /* == */
|
||||
{ if (targ->equals(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
inc = 1;
|
||||
//printf("inc = %d\n", inc);
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("iftype(");
|
||||
targ->toCBuffer(buf, id, hgs);
|
||||
if (tspec)
|
||||
{
|
||||
if (tok == TOKcolon)
|
||||
buf->writestring(" : ");
|
||||
else
|
||||
buf->writestring(" == ");
|
||||
tspec->toCBuffer(buf, NULL, hgs);
|
||||
}
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
|
||||
36
dmd/doc.c
36
dmd/doc.c
@@ -47,9 +47,9 @@
|
||||
|
||||
struct Escape
|
||||
{
|
||||
char *strings[256];
|
||||
const char *strings[256];
|
||||
|
||||
static char *escapeChar(unsigned c);
|
||||
static const char *escapeChar(unsigned c);
|
||||
};
|
||||
|
||||
struct Section
|
||||
@@ -96,8 +96,8 @@ struct DocComment
|
||||
};
|
||||
|
||||
|
||||
int cmp(char *stringz, void *s, size_t slen);
|
||||
int icmp(char *stringz, void *s, size_t slen);
|
||||
int cmp(const char *stringz, void *s, size_t slen);
|
||||
int icmp(const char *stringz, void *s, size_t slen);
|
||||
int isDitto(unsigned char *comment);
|
||||
unsigned char *skipwhitespace(unsigned char *p);
|
||||
unsigned skiptoident(OutBuffer *buf, unsigned i);
|
||||
@@ -404,7 +404,7 @@ void ScopeDsymbol::emitMemberComments(Scope *sc)
|
||||
OutBuffer *buf = sc->docbuf;
|
||||
|
||||
if (members)
|
||||
{ char *m = "$(DDOC_MEMBERS \n";
|
||||
{ const char *m = "$(DDOC_MEMBERS \n";
|
||||
|
||||
if (isModule())
|
||||
m = "$(DDOC_MODULE_MEMBERS \n";
|
||||
@@ -441,7 +441,7 @@ void ScopeDsymbol::emitMemberComments(Scope *sc)
|
||||
|
||||
void emitProtection(OutBuffer *buf, PROT prot)
|
||||
{
|
||||
char *p;
|
||||
const char *p;
|
||||
|
||||
switch (prot)
|
||||
{
|
||||
@@ -918,6 +918,7 @@ DocComment::DocComment()
|
||||
DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment)
|
||||
{ unsigned idlen;
|
||||
|
||||
//printf("parse(%s): '%s'\n", s->toChars(), comment);
|
||||
if (sc->lastdc && isDitto(comment))
|
||||
return NULL;
|
||||
|
||||
@@ -963,6 +964,7 @@ void DocComment::parseSections(unsigned char *comment)
|
||||
unsigned char *name = NULL;
|
||||
unsigned namelen = 0;
|
||||
|
||||
//printf("parseSections('%s')\n", comment);
|
||||
p = comment;
|
||||
while (*p)
|
||||
{
|
||||
@@ -1088,7 +1090,7 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
{
|
||||
if (namelen)
|
||||
{
|
||||
static char *table[] =
|
||||
static const char *table[] =
|
||||
{ "AUTHORS", "BUGS", "COPYRIGHT", "DATE",
|
||||
"DEPRECATED", "EXAMPLES", "HISTORY", "LICENSE",
|
||||
"RETURNS", "SEE_ALSO", "STANDARDS", "THROWS",
|
||||
@@ -1432,7 +1434,7 @@ void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, u
|
||||
* Return < 0, ==0, > 0
|
||||
*/
|
||||
|
||||
int cmp(char *stringz, void *s, size_t slen)
|
||||
int cmp(const char *stringz, void *s, size_t slen)
|
||||
{
|
||||
size_t len1 = strlen(stringz);
|
||||
|
||||
@@ -1441,7 +1443,7 @@ int cmp(char *stringz, void *s, size_t slen)
|
||||
return memcmp(stringz, s, slen);
|
||||
}
|
||||
|
||||
int icmp(char *stringz, void *s, size_t slen)
|
||||
int icmp(const char *stringz, void *s, size_t slen)
|
||||
{
|
||||
size_t len1 = strlen(stringz);
|
||||
|
||||
@@ -1578,7 +1580,7 @@ Lno:
|
||||
|
||||
int isKeyword(unsigned char *p, unsigned len)
|
||||
{
|
||||
static char *table[] = { "true", "false", "null" };
|
||||
static const char *table[] = { "true", "false", "null" };
|
||||
|
||||
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
|
||||
{
|
||||
@@ -1629,10 +1631,10 @@ Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len)
|
||||
void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
|
||||
{
|
||||
//printf("highlightText()\n");
|
||||
char *sid = s->ident->toChars();
|
||||
const char *sid = s->ident->toChars();
|
||||
FuncDeclaration *f = s->isFuncDeclaration();
|
||||
unsigned char *p;
|
||||
char *se;
|
||||
const char *se;
|
||||
|
||||
int leadingBlank = 1;
|
||||
int inCode = 0;
|
||||
@@ -1878,7 +1880,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
|
||||
//printf("highlightCode(s = '%s', kind = %s)\n", sid, s->kind());
|
||||
for (unsigned i = offset; i < buf->offset; i++)
|
||||
{ unsigned char c = buf->data[i];
|
||||
char *se;
|
||||
const char *se;
|
||||
|
||||
se = Escape::escapeChar(c);
|
||||
if (se)
|
||||
@@ -1920,7 +1922,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
|
||||
void highlightCode3(OutBuffer *buf, unsigned char *p, unsigned char *pend)
|
||||
{
|
||||
for (; p < pend; p++)
|
||||
{ char *s = Escape::escapeChar(*p);
|
||||
{ const char *s = Escape::escapeChar(*p);
|
||||
if (s)
|
||||
buf->writestring(s);
|
||||
else
|
||||
@@ -1942,7 +1944,7 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
|
||||
Token tok;
|
||||
OutBuffer res;
|
||||
unsigned char *lastp = buf->data;
|
||||
char *highlight;
|
||||
const char *highlight;
|
||||
|
||||
//printf("highlightCode2('%.*s')\n", buf->offset - 1, buf->data);
|
||||
res.reserve(buf->offset);
|
||||
@@ -2003,8 +2005,8 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
|
||||
* Find character string to replace c with.
|
||||
*/
|
||||
|
||||
char *Escape::escapeChar(unsigned c)
|
||||
{ char *s;
|
||||
const char *Escape::escapeChar(unsigned c)
|
||||
{ const char *s;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
|
||||
523
dmd/expression.c
523
dmd/expression.c
@@ -12,7 +12,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#if _MSC_VER
|
||||
#include <complex>
|
||||
#else
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#if _WIN32 && __DMC__
|
||||
@@ -68,6 +71,7 @@ int isnan(double);
|
||||
#include "parse.h"
|
||||
|
||||
Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
|
||||
Expression *expandVar(int result, VarDeclaration *v);
|
||||
|
||||
#define LOGSEMANTIC 0
|
||||
|
||||
@@ -168,10 +172,20 @@ void initPrecedence()
|
||||
precedence[TOKue] = PREC_rel;
|
||||
precedence[TOKin] = PREC_rel;
|
||||
|
||||
#if 0
|
||||
precedence[TOKequal] = PREC_equal;
|
||||
precedence[TOKnotequal] = PREC_equal;
|
||||
precedence[TOKidentity] = PREC_equal;
|
||||
precedence[TOKnotidentity] = PREC_equal;
|
||||
#else
|
||||
/* Note that we changed precedence, so that < and != have the same
|
||||
* precedence. This change is in the parser, too.
|
||||
*/
|
||||
precedence[TOKequal] = PREC_rel;
|
||||
precedence[TOKnotequal] = PREC_rel;
|
||||
precedence[TOKidentity] = PREC_rel;
|
||||
precedence[TOKnotidentity] = PREC_rel;
|
||||
#endif
|
||||
|
||||
precedence[TOKand] = PREC_and;
|
||||
|
||||
@@ -352,7 +366,7 @@ Expression *resolveProperties(Scope *sc, Expression *e)
|
||||
{
|
||||
Type *t = e->type->toBasetype();
|
||||
|
||||
if (t->ty == Tfunction)
|
||||
if (t->ty == Tfunction /*|| e->op == TOKoverloadset*/)
|
||||
{
|
||||
e = new CallExp(e->loc, e);
|
||||
e = e->semantic(sc);
|
||||
@@ -539,8 +553,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
|
||||
void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments)
|
||||
{
|
||||
unsigned n;
|
||||
int done;
|
||||
Type *tb;
|
||||
|
||||
//printf("functionArguments()\n");
|
||||
assert(arguments);
|
||||
@@ -552,7 +564,7 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
|
||||
n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
|
||||
|
||||
done = 0;
|
||||
int done = 0;
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
Expression *arg;
|
||||
@@ -561,6 +573,7 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
arg = (Expression *)arguments->data[i];
|
||||
else
|
||||
arg = NULL;
|
||||
Type *tb;
|
||||
|
||||
if (i < nparams)
|
||||
{
|
||||
@@ -615,11 +628,8 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
static int idn;
|
||||
char name[10 + sizeof(idn)*3 + 1];
|
||||
sprintf(name, "__arrayArg%d", ++idn);
|
||||
Identifier *id = Lexer::idPool(name);
|
||||
Type *t = new TypeSArray(tb->next, new IntegerExp(nargs - i));
|
||||
Identifier *id = Lexer::uniqueId("__arrayArg");
|
||||
Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i));
|
||||
t = t->semantic(loc, sc);
|
||||
VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
|
||||
v->semantic(sc);
|
||||
@@ -631,16 +641,19 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
|
||||
for (size_t u = i; u < nargs; u++)
|
||||
{ Expression *a = (Expression *)arguments->data[u];
|
||||
if (tret && !tb->next->equals(a->type))
|
||||
if (tret && !((TypeArray *)tb)->next->equals(a->type))
|
||||
a = a->toDelegate(sc, tret);
|
||||
|
||||
Expression *e = new VarExp(loc, v);
|
||||
e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
|
||||
e = new AssignExp(loc, e, a);
|
||||
AssignExp *ae = new AssignExp(loc, e, a);
|
||||
#if DMDV2
|
||||
ae->op = TOKconstruct;
|
||||
#endif
|
||||
if (c)
|
||||
c = new CommaExp(loc, c, e);
|
||||
c = new CommaExp(loc, c, ae);
|
||||
else
|
||||
c = e;
|
||||
c = ae;
|
||||
}
|
||||
arg = new VarExp(loc, v);
|
||||
if (c)
|
||||
@@ -694,12 +707,50 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DMDV2
|
||||
if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
|
||||
{
|
||||
arg = callCpCtor(loc, sc, arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Convert lazy argument to a delegate
|
||||
if (p->storageClass & STClazy)
|
||||
{
|
||||
arg = arg->toDelegate(sc, p->type);
|
||||
}
|
||||
#if DMDV2
|
||||
/* Look for arguments that cannot 'escape' from the called
|
||||
* function.
|
||||
*/
|
||||
if (!tf->parameterEscapes(p))
|
||||
{
|
||||
/* Function literals can only appear once, so if this
|
||||
* appearance was scoped, there cannot be any others.
|
||||
*/
|
||||
if (arg->op == TOKfunction)
|
||||
{ FuncExp *fe = (FuncExp *)arg;
|
||||
fe->fd->tookAddressOf = 0;
|
||||
}
|
||||
|
||||
/* For passing a delegate to a scoped parameter,
|
||||
* this doesn't count as taking the address of it.
|
||||
* We only worry about 'escaping' references to the function.
|
||||
*/
|
||||
else if (arg->op == TOKdelegate)
|
||||
{ DelegateExp *de = (DelegateExp *)arg;
|
||||
if (de->e1->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)de->e1;
|
||||
FuncDeclaration *f = ve->var->isFuncDeclaration();
|
||||
if (f)
|
||||
{ f->tookAddressOf--;
|
||||
//printf("tookAddressOf = %d\n", f->tookAddressOf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -778,7 +829,11 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
|
||||
{
|
||||
//if (precedence[e->op] == 0) e->dump(0);
|
||||
if (precedence[e->op] < pr)
|
||||
if (precedence[e->op] < pr ||
|
||||
/* Despite precedence, we don't allow a<b<c expressions.
|
||||
* They must be parenthesized.
|
||||
*/
|
||||
(pr == PREC_rel && precedence[e->op] == pr))
|
||||
{
|
||||
buf->writeByte('(');
|
||||
e->toCBuffer(buf, hgs);
|
||||
@@ -982,6 +1037,16 @@ void Expression::toMangleBuffer(OutBuffer *buf)
|
||||
error("expression %s is not a valid template value argument", toChars());
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Return !=0 if expression is an lvalue.
|
||||
*/
|
||||
#if DMDV2
|
||||
int Expression::isLvalue()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************
|
||||
* Give error if we're not an lvalue.
|
||||
* If we can, convert expression to be an lvalue.
|
||||
@@ -1002,6 +1067,10 @@ Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
|
||||
//printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
|
||||
|
||||
// See if this expression is a modifiable lvalue (i.e. not const)
|
||||
#if DMDV2
|
||||
if (type && (!type->isMutable() || !type->isAssignable()))
|
||||
error("%s is not mutable", e->toChars());
|
||||
#endif
|
||||
return toLvalue(sc, e);
|
||||
}
|
||||
|
||||
@@ -1049,6 +1118,15 @@ void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
|
||||
s->checkDeprecated(loc, sc);
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
void Expression::checkPurity(Scope *sc, FuncDeclaration *f)
|
||||
{
|
||||
if (sc->func && sc->func->isPure() && !sc->intypeof && !f->isPure())
|
||||
error("pure function '%s' cannot call impure function '%s'\n",
|
||||
sc->func->toChars(), f->toChars());
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************
|
||||
* Check for expressions that have no use.
|
||||
* Input:
|
||||
@@ -1175,7 +1253,11 @@ int Expression::isBit()
|
||||
|
||||
int Expression::canThrow()
|
||||
{
|
||||
#if DMDV2
|
||||
return FALSE;
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1849,7 +1931,9 @@ Expression *IdentifierExp::semantic(Scope *sc)
|
||||
// ArrayScopeSymbol::search() doesn't have access to sc.
|
||||
s->semantic(sc);
|
||||
}
|
||||
// Look to see if f is really a function template
|
||||
/* If f is really a function template,
|
||||
* then replace f with the function template declaration.
|
||||
*/
|
||||
FuncDeclaration *f = s->isFuncDeclaration();
|
||||
if (f && f->parent)
|
||||
{ TemplateInstance *ti = f->parent->isTemplateInstance();
|
||||
@@ -1891,6 +1975,13 @@ void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writestring(ident->toChars());
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int IdentifierExp::isLvalue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
#if 0
|
||||
@@ -1954,7 +2045,11 @@ Lagain:
|
||||
// BUG: This should happen after overload resolution for functions, not before
|
||||
if (s->needThis())
|
||||
{
|
||||
if (hasThis(sc) /*&& !s->isFuncDeclaration()*/)
|
||||
if (hasThis(sc)
|
||||
#if DMDV2
|
||||
&& !s->isFuncDeclaration()
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Supply an implicit 'this', as in
|
||||
// this.ident
|
||||
@@ -2112,6 +2207,13 @@ void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writestring(s->toChars());
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int DsymbolExp::isLvalue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
#if 0
|
||||
@@ -2214,6 +2316,13 @@ void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writestring("this");
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int ThisExp::isLvalue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
return this;
|
||||
@@ -2431,7 +2540,7 @@ Expression *StringExp::semantic(Scope *sc)
|
||||
if (!type)
|
||||
{ OutBuffer buffer;
|
||||
size_t newlen = 0;
|
||||
char *p;
|
||||
const char *p;
|
||||
size_t u;
|
||||
unsigned c;
|
||||
|
||||
@@ -2629,7 +2738,7 @@ void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
void StringExp::toMangleBuffer(OutBuffer *buf)
|
||||
{ char m;
|
||||
OutBuffer tmp;
|
||||
char *p;
|
||||
const char *p;
|
||||
unsigned c;
|
||||
size_t u;
|
||||
unsigned char *q;
|
||||
@@ -2772,6 +2881,13 @@ int ArrayLiteralExp::isBool(int result)
|
||||
return result ? (dim != 0) : (dim == 0);
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int ArrayLiteralExp::canThrow()
|
||||
{
|
||||
return 1; // because it can fail allocating memory
|
||||
}
|
||||
#endif
|
||||
|
||||
void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writeByte('[');
|
||||
@@ -2890,6 +3006,13 @@ int AssocArrayLiteralExp::isBool(int result)
|
||||
return result ? (dim != 0) : (dim == 0);
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int AssocArrayLiteralExp::canThrow()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writeByte('[');
|
||||
@@ -3074,6 +3197,12 @@ int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int StructLiteralExp::isLvalue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
@@ -3096,6 +3225,13 @@ int StructLiteralExp::checkSideEffect(int flag)
|
||||
return f;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int StructLiteralExp::canThrow()
|
||||
{
|
||||
return arrayExpressionCanThrow(elements);
|
||||
}
|
||||
#endif
|
||||
|
||||
void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring(sd->toChars());
|
||||
@@ -3287,6 +3423,8 @@ void TemplateExp::rvalue()
|
||||
|
||||
/********************** NewExp **************************************/
|
||||
|
||||
/* thisexp.new(newargs) newtype(arguments) */
|
||||
|
||||
NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
|
||||
Type *newtype, Expressions *arguments)
|
||||
: Expression(loc, TOKnew, sizeof(NewExp))
|
||||
@@ -3472,17 +3610,14 @@ Lagain:
|
||||
}
|
||||
|
||||
if (cd->aggNew)
|
||||
{ Expression *e;
|
||||
|
||||
f = cd->aggNew;
|
||||
|
||||
{
|
||||
// Prepend the uint size argument to newargs[]
|
||||
e = new IntegerExp(loc, cd->size(loc), Type::tuns32);
|
||||
Expression *e = new IntegerExp(loc, cd->size(loc), Type::tuns32);
|
||||
if (!newargs)
|
||||
newargs = new Expressions();
|
||||
newargs->shift(e);
|
||||
|
||||
f = f->overloadResolve(loc, newargs);
|
||||
f = cd->aggNew->overloadResolve(loc, newargs);
|
||||
allocator = f->isNewDeclaration();
|
||||
assert(allocator);
|
||||
|
||||
@@ -3494,7 +3629,6 @@ Lagain:
|
||||
if (newargs && newargs->dim)
|
||||
error("no allocator for %s", cd->toChars());
|
||||
}
|
||||
|
||||
}
|
||||
else if (tb->ty == Tstruct)
|
||||
{
|
||||
@@ -3575,6 +3709,13 @@ int NewExp::checkSideEffect(int flag)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int NewExp::canThrow()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{ int i;
|
||||
|
||||
@@ -3642,6 +3783,13 @@ int NewAnonClassExp::checkSideEffect(int flag)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int NewAnonClassExp::canThrow()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{ int i;
|
||||
|
||||
@@ -3670,6 +3818,18 @@ void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
}
|
||||
}
|
||||
|
||||
/********************** SymbolExp **************************************/
|
||||
|
||||
#if DMDV2
|
||||
SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads)
|
||||
: Expression(loc, op, size)
|
||||
{
|
||||
assert(var);
|
||||
this->var = var;
|
||||
this->hasOverloads = hasOverloads;
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************** SymOffExp **************************************/
|
||||
|
||||
SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset)
|
||||
@@ -3760,6 +3920,11 @@ Expression *VarExp::semantic(Scope *sc)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Fix for 1161 doesn't work because it causes protection
|
||||
* problems when instantiating imported templates passing private
|
||||
* variables as alias template parameters.
|
||||
*/
|
||||
//accessCheck(loc, sc, NULL, var);
|
||||
|
||||
VarDeclaration *v = var->isVarDeclaration();
|
||||
if (v)
|
||||
@@ -3774,6 +3939,13 @@ Expression *VarExp::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
v->checkNestedReference(sc, loc);
|
||||
#if DMDV2
|
||||
if (sc->func && sc->func->isPure() && !sc->intypeof)
|
||||
{
|
||||
if (v->isDataseg() && !v->isInvariant())
|
||||
error("pure function '%s' cannot access mutable static data '%s'", sc->func->toChars(), v->toChars());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
|
||||
@@ -3812,6 +3984,15 @@ void VarExp::checkEscape()
|
||||
}
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int VarExp::isLvalue()
|
||||
{
|
||||
if (var->storage_class & STClazy)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *VarExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
#if 0
|
||||
@@ -4026,6 +4207,13 @@ int TupleExp::checkSideEffect(int flag)
|
||||
return f;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int TupleExp::canThrow()
|
||||
{
|
||||
return arrayExpressionCanThrow(exps);
|
||||
}
|
||||
#endif
|
||||
|
||||
void TupleExp::checkEscape()
|
||||
{
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
@@ -4195,6 +4383,18 @@ int DeclarationExp::checkSideEffect(int flag)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int DeclarationExp::canThrow()
|
||||
{
|
||||
VarDeclaration *v = declaration->isVarDeclaration();
|
||||
if (v && v->init)
|
||||
{ ExpInitializer *ie = v->init->isExpInitializer();
|
||||
return ie && ie->exp->canThrow();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
declaration->toCBuffer(buf, hgs);
|
||||
@@ -4398,6 +4598,7 @@ Expression *IsExp::semantic(Scope *sc)
|
||||
break;
|
||||
|
||||
case TOKinvariant:
|
||||
case TOKimmutable:
|
||||
if (!targ->isInvariant())
|
||||
goto Lno;
|
||||
tded = targ;
|
||||
@@ -4604,6 +4805,13 @@ Expression *UnaExp::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int UnaExp::canThrow()
|
||||
{
|
||||
return e1->canThrow();
|
||||
}
|
||||
#endif
|
||||
|
||||
void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring(Token::toChars(op));
|
||||
@@ -4773,6 +4981,13 @@ int BinExp::isunsigned()
|
||||
return e1->type->isunsigned() || e2->type->isunsigned();
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int BinExp::canThrow()
|
||||
{
|
||||
return e1->canThrow() || e2->canThrow();
|
||||
}
|
||||
#endif
|
||||
|
||||
void BinExp::incompatibleTypes()
|
||||
{
|
||||
error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
|
||||
@@ -4805,6 +5020,7 @@ Expression *CompileExp::semantic(Scope *sc)
|
||||
Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
|
||||
p.loc = loc;
|
||||
p.nextToken();
|
||||
//printf("p.loc.linnum = %d\n", p.loc.linnum);
|
||||
Expression *e = p.parseExpression();
|
||||
if (p.token.value != TOKeof)
|
||||
error("incomplete mixin expression (%s)", se->toChars());
|
||||
@@ -4877,7 +5093,7 @@ Expression *FileExp::semantic(Scope *sc)
|
||||
return se->semantic(sc);
|
||||
|
||||
Lerror:
|
||||
se = new StringExp(loc, "");
|
||||
se = new StringExp(loc, (char *)"");
|
||||
goto Lret;
|
||||
}
|
||||
|
||||
@@ -4940,6 +5156,13 @@ int AssertExp::checkSideEffect(int flag)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int AssertExp::canThrow()
|
||||
{
|
||||
return (global.params.useAssert != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("assert(");
|
||||
@@ -5162,6 +5385,13 @@ Expression *DotIdExp::semantic(Scope *sc)
|
||||
}
|
||||
return e;
|
||||
}
|
||||
#if DMDV2
|
||||
OverloadSet *o = s->isOverloadSet();
|
||||
if (o)
|
||||
{ //printf("'%s' is an overload set\n", o->toChars());
|
||||
return new OverExp(o);
|
||||
}
|
||||
#endif
|
||||
|
||||
Type *t = s->getType();
|
||||
if (t)
|
||||
@@ -5224,6 +5454,29 @@ Expression *DotIdExp::semantic(Scope *sc)
|
||||
e->type = ((TypePointer *)e1->type)->next;
|
||||
return e->type->dotExp(sc, e, ident);
|
||||
}
|
||||
#if DMDV2
|
||||
else if (t1b->ty == Tarray ||
|
||||
t1b->ty == Tsarray ||
|
||||
t1b->ty == Taarray)
|
||||
{ /* If ident is not a valid property, rewrite:
|
||||
* e1.ident
|
||||
* as:
|
||||
* .ident(e1)
|
||||
*/
|
||||
unsigned errors = global.errors;
|
||||
global.gag++;
|
||||
e = e1->type->dotExp(sc, e1, ident);
|
||||
global.gag--;
|
||||
if (errors != global.errors) // if failed to find the property
|
||||
{
|
||||
global.errors = errors;
|
||||
e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident);
|
||||
e = new CallExp(loc, e, e1);
|
||||
}
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
e = e1->type->dotExp(sc, e1, ident);
|
||||
@@ -5341,6 +5594,13 @@ Expression *DotVarExp::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int DotVarExp::isLvalue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
//printf("DotVarExp::toLvalue(%s)\n", toChars());
|
||||
@@ -5391,6 +5651,20 @@ Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if DMDV2
|
||||
else
|
||||
{
|
||||
Type *t1 = e1->type->toBasetype();
|
||||
|
||||
if (!t1->isMutable() ||
|
||||
(t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
|
||||
!var->type->isMutable() ||
|
||||
!var->type->isAssignable() ||
|
||||
var->storage_class & STCmanifest
|
||||
)
|
||||
error("cannot modify const/invariant %s", toChars());
|
||||
}
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -5713,12 +5987,16 @@ Expression *CallExp::semantic(Scope *sc)
|
||||
if (!arguments)
|
||||
arguments = new Expressions();
|
||||
arguments->shift(dotid->e1);
|
||||
#if DMDV2
|
||||
e1 = new DotIdExp(dotid->loc, new IdentifierExp(dotid->loc, Id::empty), dotid->ident);
|
||||
#else
|
||||
e1 = new IdentifierExp(dotid->loc, dotid->ident);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
#if 1
|
||||
/* This recognizes:
|
||||
* foo!(tiargs)(funcargs)
|
||||
*/
|
||||
@@ -5901,7 +6179,7 @@ Lagain:
|
||||
if (!arguments)
|
||||
// Should fix deduceFunctionTemplate() so it works on NULL argument
|
||||
arguments = new Expressions();
|
||||
f = td->deduceFunctionTemplate(sc, loc, NULL, arguments);
|
||||
f = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
|
||||
if (!f)
|
||||
{ type = Type::terror;
|
||||
return this;
|
||||
@@ -5925,6 +6203,9 @@ Lagain:
|
||||
}
|
||||
|
||||
checkDeprecated(sc, f);
|
||||
#if DMDV2
|
||||
checkPurity(sc, f);
|
||||
#endif
|
||||
accessCheck(loc, sc, ue->e1, f);
|
||||
if (!f->needThis())
|
||||
{
|
||||
@@ -5990,6 +6271,9 @@ Lagain:
|
||||
|
||||
f = f->overloadResolve(loc, arguments);
|
||||
checkDeprecated(sc, f);
|
||||
#if DMDV2
|
||||
checkPurity(sc, f);
|
||||
#endif
|
||||
e1 = new DotVarExp(e1->loc, e1, f);
|
||||
e1 = e1->semantic(sc);
|
||||
t1 = e1->type;
|
||||
@@ -6027,6 +6311,9 @@ Lagain:
|
||||
f = cd->ctor;
|
||||
f = f->overloadResolve(loc, arguments);
|
||||
checkDeprecated(sc, f);
|
||||
#if DMDV2
|
||||
checkPurity(sc, f);
|
||||
#endif
|
||||
e1 = new DotVarExp(e1->loc, e1, f);
|
||||
e1 = e1->semantic(sc);
|
||||
t1 = e1->type;
|
||||
@@ -6062,7 +6349,7 @@ Lagain:
|
||||
else if (e1->op == TOKtemplate)
|
||||
{
|
||||
TemplateExp *te = (TemplateExp *)e1;
|
||||
f = te->td->deduceFunctionTemplate(sc, loc, NULL, arguments);
|
||||
f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
|
||||
if (!f)
|
||||
{ type = Type::terror;
|
||||
return this;
|
||||
@@ -6118,6 +6405,9 @@ Lagain:
|
||||
|
||||
f = f->overloadResolve(loc, arguments);
|
||||
checkDeprecated(sc, f);
|
||||
#if DMDV2
|
||||
checkPurity(sc, f);
|
||||
#endif
|
||||
|
||||
if (f->needThis() && hasThis(sc))
|
||||
{
|
||||
@@ -6165,9 +6455,75 @@ Lcheckargs:
|
||||
|
||||
int CallExp::checkSideEffect(int flag)
|
||||
{
|
||||
#if DMDV2
|
||||
if (flag != 2)
|
||||
return 1;
|
||||
|
||||
if (e1->checkSideEffect(2))
|
||||
return 1;
|
||||
|
||||
/* If any of the arguments have side effects, this expression does
|
||||
*/
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = (Expression *)arguments->data[i];
|
||||
|
||||
if (e->checkSideEffect(2))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If calling a function or delegate that is typed as pure,
|
||||
* then this expression has no side effects.
|
||||
*/
|
||||
Type *t = e1->type->toBasetype();
|
||||
if (t->ty == Tfunction && ((TypeFunction *)t)->ispure)
|
||||
return 0;
|
||||
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->ispure)
|
||||
return 0;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int CallExp::canThrow()
|
||||
{
|
||||
if (e1->canThrow())
|
||||
return 1;
|
||||
|
||||
/* If any of the arguments can throw, then this expression can throw
|
||||
*/
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = (Expression *)arguments->data[i];
|
||||
|
||||
if (e->canThrow())
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If calling a function or delegate that is typed as nothrow,
|
||||
* then this expression cannot throw.
|
||||
* Note that pure functions can throw.
|
||||
*/
|
||||
Type *t = e1->type->toBasetype();
|
||||
if (t->ty == Tfunction && ((TypeFunction *)t)->isnothrow)
|
||||
return 0;
|
||||
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DMDV2
|
||||
int CallExp::isLvalue()
|
||||
{
|
||||
if (type->toBasetype()->ty == Tstruct)
|
||||
return 1;
|
||||
Type *tb = e1->type->toBasetype();
|
||||
if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
|
||||
return 1; // function returns a reference
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *CallExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
if (type->toBasetype()->ty == Tstruct)
|
||||
@@ -6309,6 +6665,13 @@ Expression *PtrExp::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int PtrExp::isLvalue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
#if 0
|
||||
@@ -6321,6 +6684,21 @@ Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
|
||||
return this;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
//printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
|
||||
|
||||
if (e1->op == TOKsymoff)
|
||||
{ SymOffExp *se = (SymOffExp *)e1;
|
||||
se->var->checkModify(loc, sc, type);
|
||||
//return toLvalue(sc, e);
|
||||
}
|
||||
|
||||
return Expression::modifiableLvalue(sc, e);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writeByte('*');
|
||||
@@ -6553,6 +6931,17 @@ CastExp::CastExp(Loc loc, Expression *e, Type *t)
|
||||
to = t;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
/* For cast(const) and cast(immutable)
|
||||
*/
|
||||
CastExp::CastExp(Loc loc, Expression *e, unsigned mod)
|
||||
: UnaExp(loc, TOKcast, sizeof(CastExp), e)
|
||||
{
|
||||
to = NULL;
|
||||
this->mod = mod;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *CastExp::syntaxCopy()
|
||||
{
|
||||
return new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy());
|
||||
@@ -6637,7 +7026,35 @@ void CastExp::checkEscape()
|
||||
void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("cast(");
|
||||
#if DMDV1
|
||||
to->toCBuffer(buf, NULL, hgs);
|
||||
#else
|
||||
if (to)
|
||||
to->toCBuffer(buf, NULL, hgs);
|
||||
else
|
||||
{
|
||||
switch (mod)
|
||||
{ case 0:
|
||||
break;
|
||||
case MODconst:
|
||||
buf->writestring(Token::tochars[TOKconst]);
|
||||
break;
|
||||
case MODinvariant:
|
||||
buf->writestring(Token::tochars[TOKimmutable]);
|
||||
break;
|
||||
case MODshared:
|
||||
buf->writestring(Token::tochars[TOKshared]);
|
||||
break;
|
||||
case MODshared | MODconst:
|
||||
buf->writestring(Token::tochars[TOKshared]);
|
||||
buf->writeByte(' ');
|
||||
buf->writestring(Token::tochars[TOKconst]);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
buf->writeByte(')');
|
||||
expToCBuffer(buf, hgs, e1, precedence[op]);
|
||||
}
|
||||
@@ -6831,6 +7248,13 @@ void SliceExp::checkEscape()
|
||||
e1->checkEscape();
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int SliceExp::isLvalue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
return this;
|
||||
@@ -6945,6 +7369,14 @@ Expression *ArrayExp::semantic(Scope *sc)
|
||||
return e;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int ArrayExp::isLvalue()
|
||||
{
|
||||
if (type && type->toBasetype()->ty == Tvoid)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
@@ -7015,6 +7447,13 @@ void CommaExp::checkEscape()
|
||||
e2->checkEscape();
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int CommaExp::isLvalue()
|
||||
{
|
||||
return e2->isLvalue();
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
e2 = e2->toLvalue(sc, NULL);
|
||||
@@ -7181,6 +7620,13 @@ Expression *IndexExp::semantic(Scope *sc)
|
||||
return e;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int IndexExp::isLvalue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
|
||||
{
|
||||
// if (type && type->toBasetype()->ty == Tvoid)
|
||||
@@ -9034,9 +9480,21 @@ Expression *CondExp::semantic(Scope *sc)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
printf("res: %s\n", type->toChars());
|
||||
printf("e1 : %s\n", e1->type->toChars());
|
||||
printf("e2 : %s\n", e2->type->toChars());
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int CondExp::isLvalue()
|
||||
{
|
||||
return e1->isLvalue() && e2->isLvalue();
|
||||
}
|
||||
#endif
|
||||
|
||||
Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
|
||||
{
|
||||
PtrExp *e;
|
||||
@@ -9092,6 +9550,13 @@ int CondExp::checkSideEffect(int flag)
|
||||
}
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int CondExp::canThrow()
|
||||
{
|
||||
return econd->canThrow() || e1->canThrow() || e2->canThrow();
|
||||
}
|
||||
#endif
|
||||
|
||||
void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
expToCBuffer(buf, hgs, econd, PREC_oror);
|
||||
|
||||
@@ -825,14 +825,11 @@ struct DotVarExp : UnaExp
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void dump(int indent);
|
||||
elem *toElem(IRState *irs);
|
||||
|
||||
//LDC: since we don't convert abc.def -> *(&abc + ABC.def.offsetof)
|
||||
// these are needed
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
};
|
||||
|
||||
struct DotTemplateInstanceExp : UnaExp
|
||||
|
||||
@@ -310,6 +310,8 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
|
||||
if (isFinal())
|
||||
{
|
||||
if (isOverride())
|
||||
error("does not override any function");
|
||||
cd->vtblFinal.push(this);
|
||||
}
|
||||
else
|
||||
@@ -999,7 +1001,6 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
}
|
||||
|
||||
int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE;
|
||||
//int offend = fbody ? fbody->fallOffEnd() : TRUE;
|
||||
|
||||
if (isStaticCtorDeclaration())
|
||||
{ /* It's a static constructor. Ensure that all
|
||||
|
||||
14
dmd/import.c
14
dmd/import.c
@@ -112,7 +112,6 @@ void Import::load(Scope *sc)
|
||||
}
|
||||
if (!pkg)
|
||||
pkg = mod;
|
||||
mod->semantic();
|
||||
|
||||
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
|
||||
}
|
||||
@@ -136,6 +135,12 @@ void Import::semantic(Scope *sc)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Modules need a list of each imported module
|
||||
//printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
|
||||
sc->module->aimports.push(mod);
|
||||
|
||||
mod->semantic();
|
||||
|
||||
/* Default to private importing
|
||||
*/
|
||||
protection = sc->protection;
|
||||
@@ -147,9 +152,6 @@ void Import::semantic(Scope *sc)
|
||||
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;
|
||||
|
||||
@@ -224,7 +226,9 @@ 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);
|
||||
{ load(NULL);
|
||||
mod->semantic();
|
||||
}
|
||||
|
||||
// Forward it to the package/module
|
||||
return pkg->search(loc, ident, flags);
|
||||
|
||||
4535
dmd/interpret.c
4535
dmd/interpret.c
File diff suppressed because it is too large
Load Diff
120
dmd/man.c
120
dmd/man.c
@@ -1,60 +1,60 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 2008-2008 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#pragma comment(lib,"shell32.lib")
|
||||
|
||||
void browse(const char *url)
|
||||
{
|
||||
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if linux || __APPLE__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void browse(const char *url)
|
||||
{
|
||||
pid_t childpid;
|
||||
const char *args[3];
|
||||
|
||||
char *browser = getenv("BROWSER");
|
||||
if (browser)
|
||||
browser = strdup(browser);
|
||||
else
|
||||
browser = "firefox";
|
||||
|
||||
args[0] = browser;
|
||||
args[1] = url;
|
||||
args[2] = NULL;
|
||||
|
||||
childpid = fork();
|
||||
if (childpid == 0)
|
||||
{
|
||||
execvp(args[0], (char**)args);
|
||||
perror(args[0]); // failed to execute
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 2008-2008 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#pragma comment(lib,"shell32.lib")
|
||||
|
||||
void browse(const char *url)
|
||||
{
|
||||
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if linux || __APPLE__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void browse(const char *url)
|
||||
{
|
||||
pid_t childpid;
|
||||
const char *args[3];
|
||||
|
||||
const char *browser = getenv("BROWSER");
|
||||
if (browser)
|
||||
browser = strdup(browser);
|
||||
else
|
||||
browser = "firefox";
|
||||
|
||||
args[0] = browser;
|
||||
args[1] = url;
|
||||
args[2] = NULL;
|
||||
|
||||
childpid = fork();
|
||||
if (childpid == 0)
|
||||
{
|
||||
execvp(args[0], (char**)args);
|
||||
perror(args[0]); // failed to execute
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -63,7 +63,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.037";
|
||||
version = "v1.038";
|
||||
ldc_version = LDC_REV;
|
||||
llvm_version = LLVM_REV;
|
||||
global.structalign = 8;
|
||||
|
||||
32
dmd/module.c
32
dmd/module.c
@@ -889,6 +889,38 @@ void Module::runDeferredSemantic()
|
||||
//printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Recursively look at every module this module imports,
|
||||
* return TRUE if it imports m.
|
||||
* Can be used to detect circular imports.
|
||||
*/
|
||||
|
||||
int Module::imports(Module *m)
|
||||
{
|
||||
//printf("%s Module::imports(%s)\n", toChars(), m->toChars());
|
||||
int aimports_dim = aimports.dim;
|
||||
#if 0
|
||||
for (int i = 0; i < aimports.dim; i++)
|
||||
{ Module *mi = (Module *)aimports.data[i];
|
||||
printf("\t[%d] %s\n", i, mi->toChars());
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < aimports.dim; i++)
|
||||
{ Module *mi = (Module *)aimports.data[i];
|
||||
if (mi == m)
|
||||
return TRUE;
|
||||
if (!mi->insearch)
|
||||
{
|
||||
mi->insearch = 1;
|
||||
int r = mi->imports(m);
|
||||
mi->insearch = 0;
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* =========================== ModuleDeclaration ===================== */
|
||||
|
||||
ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id)
|
||||
|
||||
@@ -141,6 +141,7 @@ struct Module : Package
|
||||
void deleteObjFile();
|
||||
void addDeferredSemantic(Dsymbol *s);
|
||||
void runDeferredSemantic();
|
||||
int imports(Module *m);
|
||||
|
||||
// Back end
|
||||
|
||||
|
||||
45
dmd/mtype.c
45
dmd/mtype.c
@@ -3721,6 +3721,34 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc)
|
||||
return t;
|
||||
}
|
||||
|
||||
Dsymbol *TypeInstance::toDsymbol(Scope *sc)
|
||||
{
|
||||
Type *t;
|
||||
Expression *e;
|
||||
Dsymbol *s;
|
||||
|
||||
//printf("TypeInstance::semantic(%s)\n", toChars());
|
||||
|
||||
if (sc->parameterSpecialization)
|
||||
{
|
||||
unsigned errors = global.errors;
|
||||
global.gag++;
|
||||
|
||||
resolve(loc, sc, &e, &t, &s);
|
||||
|
||||
global.gag--;
|
||||
if (errors != global.errors)
|
||||
{ if (global.gag == 0)
|
||||
global.errors = errors;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
resolve(loc, sc, &e, &t, &s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/***************************** TypeTypeof *****************************/
|
||||
|
||||
@@ -4380,9 +4408,12 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
||||
return new IntegerExp(e->loc, 0, Type::tint32);
|
||||
}
|
||||
|
||||
/* If e.tupleof
|
||||
*/
|
||||
if (ident == Id::tupleof)
|
||||
{
|
||||
/* Create a TupleExp
|
||||
/* Create a TupleExp out of the fields of the struct e:
|
||||
* (e.field0, e.field1, e.field2, ...)
|
||||
*/
|
||||
e = e->semantic(sc); // do this before turning on noaccesscheck
|
||||
Expressions *exps = new Expressions;
|
||||
@@ -4477,6 +4508,14 @@ L1:
|
||||
return de;
|
||||
}
|
||||
|
||||
Import *timp = s->isImport();
|
||||
if (timp)
|
||||
{
|
||||
e = new DsymbolExp(e->loc, s);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
d = s->isDeclaration();
|
||||
#ifdef DEBUG
|
||||
if (!d)
|
||||
@@ -4521,9 +4560,7 @@ L1:
|
||||
|
||||
// *(&e + offset)
|
||||
accessCheck(e->loc, sc, e, d);
|
||||
|
||||
// LDC we don't want dot exprs turned into pointer arithmetic. it complicates things for no apparent gain
|
||||
#ifndef IN_LLVM
|
||||
#if 0
|
||||
b = new AddrExp(e->loc, e);
|
||||
b->type = e->type->pointerTo();
|
||||
b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32));
|
||||
|
||||
@@ -507,6 +507,7 @@ struct TypeInstance : TypeQualified
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
};
|
||||
|
||||
|
||||
1496
dmd/opover.c
1496
dmd/opover.c
File diff suppressed because it is too large
Load Diff
@@ -278,19 +278,35 @@ Expression *PtrExp::optimize(int result)
|
||||
|
||||
Expression *DotVarExp::optimize(int result)
|
||||
{
|
||||
//printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars());
|
||||
e1 = e1->optimize(result);
|
||||
|
||||
// Constant fold structliteral.member
|
||||
#if DMDV2
|
||||
if (e1->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)e1;
|
||||
VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
Expression *e = expandVar(result, v);
|
||||
if (e && e->op == TOKstructliteral)
|
||||
{ StructLiteralExp *sle = (StructLiteralExp *)e;
|
||||
VarDeclaration *vf = var->isVarDeclaration();
|
||||
if (vf)
|
||||
{
|
||||
e = sle->getField(type, vf->offset);
|
||||
if (e != EXP_CANT_INTERPRET)
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (e1->op == TOKstructliteral)
|
||||
{ StructLiteralExp *se = (StructLiteralExp *)e1;
|
||||
|
||||
VarDeclaration* v;
|
||||
if (v = var->isVarDeclaration())
|
||||
{ StructLiteralExp *sle = (StructLiteralExp *)e1;
|
||||
VarDeclaration *vf = var->isVarDeclaration();
|
||||
if (vf)
|
||||
{
|
||||
Expression *e = se->getField(type, v->offset);
|
||||
if (!e)
|
||||
e = EXP_CANT_INTERPRET;
|
||||
return e;
|
||||
Expression *e = sle->getField(type, vf->offset);
|
||||
if (e != EXP_CANT_INTERPRET)
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +338,7 @@ Expression *CastExp::optimize(int result)
|
||||
//printf("CastExp::optimize(result = %d) %s\n", result, toChars());
|
||||
//printf("from %s to %s\n", type->toChars(), to->toChars());
|
||||
//printf("from %s\n", type->toChars());
|
||||
//printf("e1->type %s\n", e1->type->toChars());
|
||||
//printf("type = %p\n", type);
|
||||
assert(type);
|
||||
enum TOK op1 = e1->op;
|
||||
|
||||
208
dmd/statement.c
208
dmd/statement.c
@@ -124,13 +124,6 @@ int Statement::blockExit()
|
||||
return BEany;
|
||||
}
|
||||
|
||||
// TRUE if statement may fall off the end without a throw or return
|
||||
|
||||
int Statement::fallOffEnd()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// TRUE if statement 'comes from' somewhere else, like a goto
|
||||
|
||||
int Statement::comeFrom()
|
||||
@@ -227,21 +220,6 @@ int ExpStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int ExpStatement::fallOffEnd()
|
||||
{
|
||||
if (exp)
|
||||
{
|
||||
if (exp->op == TOKassert)
|
||||
{ AssertExp *a = (AssertExp *)exp;
|
||||
|
||||
if (a->e1->isBool(FALSE)) // if it's an assert(0)
|
||||
return FALSE;
|
||||
}
|
||||
else if (exp->op == TOKhalt)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************** CompileStatement ***************************/
|
||||
|
||||
@@ -574,25 +552,6 @@ int CompoundStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int CompoundStatement::fallOffEnd()
|
||||
{ int falloff = TRUE;
|
||||
|
||||
//printf("CompoundStatement::fallOffEnd() %s\n", toChars());
|
||||
for (int i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *)statements->data[i];
|
||||
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
if (!falloff && global.params.warnings && !s->comeFrom())
|
||||
{
|
||||
warning("%s: statement is not reachable", s->loc.toChars());
|
||||
}
|
||||
falloff = s->fallOffEnd();
|
||||
}
|
||||
return falloff;
|
||||
}
|
||||
|
||||
int CompoundStatement::comeFrom()
|
||||
{ int comefrom = FALSE;
|
||||
|
||||
@@ -710,18 +669,6 @@ int UnrolledLoopStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int UnrolledLoopStatement::fallOffEnd()
|
||||
{
|
||||
//printf("UnrolledLoopStatement::fallOffEnd()\n");
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *)statements->data[i];
|
||||
|
||||
if (s)
|
||||
s->fallOffEnd();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int UnrolledLoopStatement::comeFrom()
|
||||
{ int comefrom = FALSE;
|
||||
|
||||
@@ -815,11 +762,6 @@ int ScopeStatement::blockExit()
|
||||
return statement ? statement->blockExit() : BEfallthru;
|
||||
}
|
||||
|
||||
int ScopeStatement::fallOffEnd()
|
||||
{
|
||||
return statement ? statement->fallOffEnd() : TRUE;
|
||||
}
|
||||
|
||||
int ScopeStatement::comeFrom()
|
||||
{
|
||||
//printf("ScopeStatement::comeFrom()\n");
|
||||
@@ -945,13 +887,6 @@ int WhileStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int WhileStatement::fallOffEnd()
|
||||
{
|
||||
if (body)
|
||||
body->fallOffEnd();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int WhileStatement::comeFrom()
|
||||
{
|
||||
if (body)
|
||||
@@ -1040,13 +975,6 @@ int DoStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int DoStatement::fallOffEnd()
|
||||
{
|
||||
if (body)
|
||||
body->fallOffEnd();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int DoStatement::comeFrom()
|
||||
{
|
||||
if (body)
|
||||
@@ -1177,13 +1105,6 @@ int ForStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int ForStatement::fallOffEnd()
|
||||
{
|
||||
if (body)
|
||||
body->fallOffEnd();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int ForStatement::comeFrom()
|
||||
{
|
||||
//printf("ForStatement::comeFrom()\n");
|
||||
@@ -1878,13 +1799,6 @@ int ForeachStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int ForeachStatement::fallOffEnd()
|
||||
{
|
||||
if (body)
|
||||
body->fallOffEnd();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int ForeachStatement::comeFrom()
|
||||
{
|
||||
if (body)
|
||||
@@ -2042,15 +1956,6 @@ int IfStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int IfStatement::fallOffEnd()
|
||||
{
|
||||
if (!ifbody || ifbody->fallOffEnd() ||
|
||||
!elsebody || elsebody->fallOffEnd())
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("if (");
|
||||
@@ -2268,13 +2173,6 @@ int PragmaStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int PragmaStatement::fallOffEnd()
|
||||
{
|
||||
if (body)
|
||||
return body->fallOffEnd();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("pragma (");
|
||||
@@ -2475,13 +2373,6 @@ int SwitchStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int SwitchStatement::fallOffEnd()
|
||||
{
|
||||
if (body)
|
||||
body->fallOffEnd();
|
||||
return TRUE; // need to do this better
|
||||
}
|
||||
|
||||
void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("switch (");
|
||||
@@ -2586,11 +2477,6 @@ int CaseStatement::blockExit()
|
||||
return statement->blockExit();
|
||||
}
|
||||
|
||||
int CaseStatement::fallOffEnd()
|
||||
{
|
||||
return statement->fallOffEnd();
|
||||
}
|
||||
|
||||
int CaseStatement::comeFrom()
|
||||
{
|
||||
return TRUE;
|
||||
@@ -2650,11 +2536,6 @@ int DefaultStatement::blockExit()
|
||||
return statement->blockExit();
|
||||
}
|
||||
|
||||
int DefaultStatement::fallOffEnd()
|
||||
{
|
||||
return statement->fallOffEnd();
|
||||
}
|
||||
|
||||
int DefaultStatement::comeFrom()
|
||||
{
|
||||
return TRUE;
|
||||
@@ -2695,11 +2576,6 @@ int GotoDefaultStatement::blockExit()
|
||||
return BEgoto;
|
||||
}
|
||||
|
||||
int GotoDefaultStatement::fallOffEnd()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("goto default;\n");
|
||||
@@ -2749,11 +2625,6 @@ int GotoCaseStatement::blockExit()
|
||||
return BEgoto;
|
||||
}
|
||||
|
||||
int GotoCaseStatement::fallOffEnd()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("goto case");
|
||||
@@ -2777,11 +2648,6 @@ int SwitchErrorStatement::blockExit()
|
||||
return BEthrow;
|
||||
}
|
||||
|
||||
int SwitchErrorStatement::fallOffEnd()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("SwitchErrorStatement::toCBuffer()");
|
||||
@@ -3056,11 +2922,6 @@ int ReturnStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int ReturnStatement::fallOffEnd()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->printf("return ");
|
||||
@@ -3155,11 +3016,6 @@ int BreakStatement::blockExit()
|
||||
return ident ? BEgoto : BEbreak;
|
||||
}
|
||||
|
||||
int BreakStatement::fallOffEnd()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("break");
|
||||
@@ -3263,11 +3119,6 @@ int ContinueStatement::blockExit()
|
||||
return ident ? BEgoto : BEcontinue;
|
||||
}
|
||||
|
||||
int ContinueStatement::fallOffEnd()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("continue");
|
||||
@@ -3358,11 +3209,6 @@ int SynchronizedStatement::blockExit()
|
||||
return body ? body->blockExit() : BEfallthru;
|
||||
}
|
||||
|
||||
int SynchronizedStatement::fallOffEnd()
|
||||
{
|
||||
return body ? body->fallOffEnd() : TRUE;
|
||||
}
|
||||
|
||||
void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("synchronized");
|
||||
@@ -3480,11 +3326,6 @@ int WithStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int WithStatement::fallOffEnd()
|
||||
{
|
||||
return body ? body->fallOffEnd() : TRUE;
|
||||
}
|
||||
|
||||
/******************************** TryCatchStatement ***************************/
|
||||
|
||||
TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
|
||||
@@ -3556,22 +3397,6 @@ int TryCatchStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
int TryCatchStatement::fallOffEnd()
|
||||
{
|
||||
int result = FALSE;
|
||||
|
||||
if (body)
|
||||
result = body->fallOffEnd();
|
||||
for (int i = 0; i < catches->dim; i++)
|
||||
{ Catch *c;
|
||||
|
||||
c = (Catch *)catches->data[i];
|
||||
if (c->handler)
|
||||
result |= c->handler->fallOffEnd();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("try");
|
||||
@@ -3728,18 +3553,11 @@ int TryFinallyStatement::usesEH()
|
||||
|
||||
int TryFinallyStatement::blockExit()
|
||||
{
|
||||
int result = body->blockExit();
|
||||
return result;
|
||||
if (body)
|
||||
return body->blockExit();
|
||||
return BEfallthru;
|
||||
}
|
||||
|
||||
int TryFinallyStatement::fallOffEnd()
|
||||
{ int result;
|
||||
|
||||
result = body ? body->fallOffEnd() : TRUE;
|
||||
// if (finalbody)
|
||||
// result = finalbody->fallOffEnd();
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************** OnScopeStatement ***************************/
|
||||
|
||||
@@ -3861,11 +3679,6 @@ int ThrowStatement::blockExit()
|
||||
return BEthrow; // obviously
|
||||
}
|
||||
|
||||
int ThrowStatement::fallOffEnd()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->printf("throw ");
|
||||
@@ -3924,11 +3737,6 @@ int VolatileStatement::blockExit()
|
||||
return statement ? statement->blockExit() : BEfallthru;
|
||||
}
|
||||
|
||||
int VolatileStatement::fallOffEnd()
|
||||
{
|
||||
return statement ? statement->fallOffEnd() : TRUE;
|
||||
}
|
||||
|
||||
void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("volatile");
|
||||
@@ -3993,11 +3801,6 @@ int GotoStatement::blockExit()
|
||||
return BEgoto;
|
||||
}
|
||||
|
||||
int GotoStatement::fallOffEnd()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("goto ");
|
||||
@@ -4087,11 +3890,6 @@ int LabelStatement::blockExit()
|
||||
return statement ? statement->blockExit() : BEfallthru;
|
||||
}
|
||||
|
||||
int LabelStatement::fallOffEnd()
|
||||
{
|
||||
return statement ? statement->fallOffEnd() : TRUE;
|
||||
}
|
||||
|
||||
int LabelStatement::comeFrom()
|
||||
{
|
||||
//printf("LabelStatement::comeFrom()\n");
|
||||
|
||||
@@ -148,7 +148,6 @@ struct Statement : Object
|
||||
virtual int hasBreak();
|
||||
virtual int hasContinue();
|
||||
virtual int usesEH();
|
||||
virtual int fallOffEnd();
|
||||
virtual int blockExit();
|
||||
virtual int comeFrom();
|
||||
virtual void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
@@ -179,7 +178,6 @@ struct ExpStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int fallOffEnd();
|
||||
int blockExit();
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -225,7 +223,6 @@ struct CompoundStatement : Statement
|
||||
virtual Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
virtual Statements *flatten(Scope *sc);
|
||||
ReturnStatement *isReturnStatement();
|
||||
@@ -255,7 +252,6 @@ struct UnrolledLoopStatement : Statement
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -280,7 +276,6 @@ struct ScopeStatement : Statement
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
@@ -302,7 +297,6 @@ struct WhileStatement : Statement
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -325,7 +319,6 @@ struct DoStatement : Statement
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -351,7 +344,6 @@ struct ForStatement : Statement
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -384,7 +376,6 @@ struct ForeachStatement : Statement
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -413,7 +404,6 @@ struct ForeachRangeStatement : Statement
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -440,7 +430,6 @@ struct IfStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
IfStatement *isIfStatement() { return this; }
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -477,7 +466,6 @@ struct PragmaStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
@@ -511,7 +499,6 @@ struct SwitchStatement : Statement
|
||||
int hasBreak();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
@@ -533,7 +520,6 @@ struct CaseStatement : Statement
|
||||
int compare(Object *obj);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -561,7 +547,6 @@ struct DefaultStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -584,7 +569,6 @@ struct GotoDefaultStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -602,7 +586,6 @@ struct GotoCaseStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -612,7 +595,6 @@ struct SwitchErrorStatement : Statement
|
||||
{
|
||||
SwitchErrorStatement(Loc loc);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -628,7 +610,6 @@ struct ReturnStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -650,7 +631,6 @@ struct BreakStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -669,7 +649,6 @@ struct ContinueStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -691,7 +670,6 @@ struct SynchronizedStatement : Statement
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -715,7 +693,6 @@ struct WithStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -733,7 +710,6 @@ struct TryCatchStatement : Statement
|
||||
int hasBreak();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -771,7 +747,6 @@ struct TryFinallyStatement : Statement
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -803,7 +778,6 @@ struct ThrowStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -820,7 +794,6 @@ struct VolatileStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
Statements *flatten(Scope *sc);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -839,7 +812,6 @@ struct GotoStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -862,7 +834,6 @@ struct LabelStatement : Statement
|
||||
Statements *flatten(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
178
dmd/template.c
178
dmd/template.c
@@ -201,8 +201,10 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
|
||||
goto Lnomatch;
|
||||
}
|
||||
}
|
||||
//printf("match\n");
|
||||
return 1; // match
|
||||
Lnomatch:
|
||||
//printf("nomatch\n");
|
||||
return 0; // nomatch;
|
||||
}
|
||||
|
||||
@@ -320,7 +322,9 @@ void TemplateDeclaration::semantic(Scope *sc)
|
||||
|
||||
if (sc->func)
|
||||
{
|
||||
#if DMDV1
|
||||
error("cannot declare template at function scope %s", sc->func->toChars());
|
||||
#endif
|
||||
}
|
||||
|
||||
if (/*global.params.useArrayBounds &&*/ sc->module)
|
||||
@@ -551,7 +555,9 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
// Any parameter left without a type gets the type of its corresponding arg
|
||||
/* Any parameter left without a type gets the type of
|
||||
* its corresponding arg
|
||||
*/
|
||||
for (int i = 0; i < dedtypes_dim; i++)
|
||||
{
|
||||
if (!dedtypes->data[i])
|
||||
@@ -561,6 +567,25 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
|
||||
}
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
if (m && constraint && !(flag & 1))
|
||||
{ /* Check to see if constraint is satisfied.
|
||||
*/
|
||||
Expression *e = constraint->syntaxCopy();
|
||||
paramscope->flags |= SCOPEstaticif;
|
||||
e = e->semantic(paramscope);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->isBool(TRUE))
|
||||
;
|
||||
else if (e->isBool(FALSE))
|
||||
goto Lnomatch;
|
||||
else
|
||||
{
|
||||
e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LOGM
|
||||
// Print out the results
|
||||
printf("--------------------------\n");
|
||||
@@ -674,7 +699,9 @@ int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
|
||||
/*************************************************
|
||||
* Match function arguments against a specific template function.
|
||||
* Input:
|
||||
* loc instantiation location
|
||||
* targsi Expression/Type initial list of template arguments
|
||||
* ethis 'this' argument if !NULL
|
||||
* fargs arguments to function
|
||||
* Output:
|
||||
* dedargs Expression/Type deduced template arguments
|
||||
@@ -682,7 +709,8 @@ int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
|
||||
* match level
|
||||
*/
|
||||
|
||||
MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs,
|
||||
MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
|
||||
Expression *ethis, Expressions *fargs,
|
||||
Objects *dedargs)
|
||||
{
|
||||
size_t i;
|
||||
@@ -824,6 +852,27 @@ L1:
|
||||
}
|
||||
|
||||
L2:
|
||||
#if DMDV2
|
||||
// Match 'ethis' to any TemplateThisParameter's
|
||||
if (ethis)
|
||||
{
|
||||
for (size_t i = 0; i < parameters->dim; i++)
|
||||
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
||||
TemplateThisParameter *ttp = tp->isTemplateThisParameter();
|
||||
if (ttp)
|
||||
{ MATCH m;
|
||||
|
||||
Type *t = new TypeIdentifier(0, ttp->ident);
|
||||
m = ethis->type->deduceType(scope, t, parameters, &dedtypes);
|
||||
if (!m)
|
||||
goto Lnomatch;
|
||||
if (m < match)
|
||||
match = m; // pick worst match
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Loop through the function parameters
|
||||
for (i = 0; i < nfparams; i++)
|
||||
{
|
||||
@@ -982,7 +1031,7 @@ Lmatch:
|
||||
}
|
||||
}
|
||||
else
|
||||
{ oded = tp->defaultArg(paramscope);
|
||||
{ oded = tp->defaultArg(loc, paramscope);
|
||||
if (!oded)
|
||||
goto Lnomatch;
|
||||
}
|
||||
@@ -991,6 +1040,25 @@ Lmatch:
|
||||
}
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
if (constraint)
|
||||
{ /* Check to see if constraint is satisfied.
|
||||
*/
|
||||
Expression *e = constraint->syntaxCopy();
|
||||
paramscope->flags |= SCOPEstaticif;
|
||||
e = e->semantic(paramscope);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->isBool(TRUE))
|
||||
;
|
||||
else if (e->isBool(FALSE))
|
||||
goto Lnomatch;
|
||||
else
|
||||
{
|
||||
e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < dedargs->dim; i++)
|
||||
{ Type *t = (Type *)dedargs->data[i];
|
||||
@@ -1096,11 +1164,13 @@ int TemplateDeclaration::isOverloadable()
|
||||
* sc instantiation scope
|
||||
* loc instantiation location
|
||||
* targsi initial list of template arguments
|
||||
* ethis if !NULL, the 'this' pointer argument
|
||||
* fargs arguments to function
|
||||
* flags 1: do not issue error message on no match, just return NULL
|
||||
*/
|
||||
|
||||
FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
Objects *targsi, Expressions *fargs)
|
||||
Objects *targsi, Expression *ethis, Expressions *fargs, int flags)
|
||||
{
|
||||
MATCH m_best = MATCHnomatch;
|
||||
TemplateDeclaration *td_ambig = NULL;
|
||||
@@ -1142,7 +1212,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
MATCH m;
|
||||
Objects dedargs;
|
||||
|
||||
m = td->deduceFunctionTemplateMatch(targsi, fargs, &dedargs);
|
||||
m = td->deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, &dedargs);
|
||||
//printf("deduceFunctionTemplateMatch = %d\n", m);
|
||||
if (!m) // if no match
|
||||
continue;
|
||||
@@ -1207,14 +1277,26 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
|
||||
Lerror:
|
||||
{
|
||||
OutBuffer buf;
|
||||
HdrGenState hgs;
|
||||
|
||||
OutBuffer bufa;
|
||||
Objects *args = targsi;
|
||||
if (args)
|
||||
{ for (int i = 0; i < args->dim; i++)
|
||||
{
|
||||
if (i)
|
||||
bufa.writeByte(',');
|
||||
Object *oarg = (Object *)args->data[i];
|
||||
ObjectToCBuffer(&bufa, &hgs, oarg);
|
||||
}
|
||||
}
|
||||
|
||||
OutBuffer buf;
|
||||
argExpTypesToCBuffer(&buf, fargs, &hgs);
|
||||
error(loc, "cannot deduce template function from argument types (%s)",
|
||||
buf.toChars());
|
||||
return NULL;
|
||||
error(loc, "cannot deduce template function from argument types !(%s)(%s)",
|
||||
bufa.toChars(), buf.toChars());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
@@ -1237,6 +1319,13 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
tp->toCBuffer(buf, hgs);
|
||||
}
|
||||
buf->writeByte(')');
|
||||
#if DMDV2
|
||||
if (constraint)
|
||||
{ buf->writestring(" if (");
|
||||
constraint->toCBuffer(buf, hgs);
|
||||
buf->writeByte(')');
|
||||
}
|
||||
#endif
|
||||
|
||||
if (hgs->hdrgen)
|
||||
{
|
||||
@@ -1271,6 +1360,13 @@ char *TemplateDeclaration::toChars()
|
||||
tp->toCBuffer(&buf, &hgs);
|
||||
}
|
||||
buf.writeByte(')');
|
||||
#if DMDV2
|
||||
if (constraint)
|
||||
{ buf.writestring(" if (");
|
||||
constraint->toCBuffer(&buf, &hgs);
|
||||
buf.writeByte(')');
|
||||
}
|
||||
#endif
|
||||
buf.writeByte(0);
|
||||
return (char *)buf.extractData();
|
||||
}
|
||||
@@ -1323,9 +1419,11 @@ int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
|
||||
MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
||||
Objects *dedtypes)
|
||||
{
|
||||
//printf("Type::deduceType()\n");
|
||||
//printf("\tthis = %d, ", ty); print();
|
||||
//printf("\ttparam = %d, ", tparam->ty); tparam->print();
|
||||
#if 0
|
||||
printf("Type::deduceType()\n");
|
||||
printf("\tthis = %d, ", ty); print();
|
||||
printf("\ttparam = %d, ", tparam->ty); tparam->print();
|
||||
#endif
|
||||
if (!tparam)
|
||||
goto Lnomatch;
|
||||
|
||||
@@ -2027,7 +2125,7 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs,
|
||||
oarg = (Object *)tiargs->data[i];
|
||||
else
|
||||
{ // Get default argument instead
|
||||
oarg = defaultArg(sc);
|
||||
oarg = defaultArg(loc, sc);
|
||||
if (!oarg)
|
||||
{ assert(i < dedtypes->dim);
|
||||
// It might have already been deduced
|
||||
@@ -2141,7 +2239,7 @@ Object *TemplateTypeParameter::specialization()
|
||||
}
|
||||
|
||||
|
||||
Object *TemplateTypeParameter::defaultArg(Scope *sc)
|
||||
Object *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
@@ -2271,7 +2369,7 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc,
|
||||
oarg = (Object *)tiargs->data[i];
|
||||
else
|
||||
{ // Get default argument instead
|
||||
oarg = defaultArg(sc);
|
||||
oarg = defaultArg(loc, sc);
|
||||
if (!oarg)
|
||||
{ assert(i < dedtypes->dim);
|
||||
// It might have already been deduced
|
||||
@@ -2357,7 +2455,7 @@ Object *TemplateAliasParameter::specialization()
|
||||
}
|
||||
|
||||
|
||||
Object *TemplateAliasParameter::defaultArg(Scope *sc)
|
||||
Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
|
||||
{
|
||||
Dsymbol *s = NULL;
|
||||
|
||||
@@ -2485,7 +2583,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc,
|
||||
oarg = (Object *)tiargs->data[i];
|
||||
else
|
||||
{ // Get default argument instead
|
||||
oarg = defaultArg(sc);
|
||||
oarg = defaultArg(loc, sc);
|
||||
if (!oarg)
|
||||
{ assert(i < dedtypes->dim);
|
||||
// It might have already been deduced
|
||||
@@ -2602,7 +2700,7 @@ Object *TemplateValueParameter::specialization()
|
||||
}
|
||||
|
||||
|
||||
Object *TemplateValueParameter::defaultArg(Scope *sc)
|
||||
Object *TemplateValueParameter::defaultArg(Loc loc, Scope *sc)
|
||||
{
|
||||
Expression *e = defaultValue;
|
||||
if (e)
|
||||
@@ -2748,7 +2846,7 @@ Object *TemplateTupleParameter::specialization()
|
||||
}
|
||||
|
||||
|
||||
Object *TemplateTupleParameter::defaultArg(Scope *sc)
|
||||
Object *TemplateTupleParameter::defaultArg(Loc loc, Scope *sc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -2778,6 +2876,10 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
|
||||
this->tinst = NULL;
|
||||
}
|
||||
|
||||
/*****************
|
||||
* This constructor is only called when we figured out which function
|
||||
* template to instantiate.
|
||||
*/
|
||||
|
||||
TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *tiargs)
|
||||
: ScopeDsymbol(NULL)
|
||||
@@ -2830,7 +2932,6 @@ Objects *TemplateInstance::arraySyntaxCopy(Objects *objs)
|
||||
Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
TemplateInstance *ti;
|
||||
int i;
|
||||
|
||||
if (s)
|
||||
ti = (TemplateInstance *)s;
|
||||
@@ -2896,7 +2997,9 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Run semantic on each argument, place results in tiargs[]
|
||||
/* Run semantic on each argument, place results in tiargs[]
|
||||
* (if we havetempdecl, then tiargs is already evaluated)
|
||||
*/
|
||||
semanticTiargs(sc);
|
||||
|
||||
tempdecl = findTemplateDeclaration(sc);
|
||||
@@ -2974,12 +3077,26 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
#if 1
|
||||
int dosemantic3 = 0;
|
||||
{ Array *a;
|
||||
int i;
|
||||
|
||||
if (sc->scopesym && sc->scopesym->members && !sc->scopesym->isTemplateMixin())
|
||||
Scope *scx = sc;
|
||||
#if 0
|
||||
for (scx = sc; scx; scx = scx->enclosing)
|
||||
if (scx->scopesym)
|
||||
break;
|
||||
#endif
|
||||
|
||||
//if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
|
||||
if (scx && scx->scopesym &&
|
||||
scx->scopesym->members && !scx->scopesym->isTemplateMixin() &&
|
||||
/* The following test should really be if scx->module recursively
|
||||
* imports itself. Because if it does, see bugzilla 2500.
|
||||
*/
|
||||
//scx->module == tempdecl->getModule()
|
||||
!scx->module->imports(scx->module)
|
||||
)
|
||||
{
|
||||
//printf("\t1: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars());
|
||||
a = sc->scopesym->members;
|
||||
//printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
|
||||
a = scx->scopesym->members;
|
||||
}
|
||||
else
|
||||
{ Module *m = sc->module->importedFrom;
|
||||
@@ -3395,19 +3512,15 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
|
||||
return NULL;
|
||||
}
|
||||
m = td->matchWithInstance(this, &dedtypes, 0);
|
||||
//printf("m = %d\n", m);
|
||||
//printf("matchWithInstance = %d\n", m);
|
||||
if (!m) // no match at all
|
||||
continue;
|
||||
|
||||
#if 1
|
||||
if (m < m_best)
|
||||
goto Ltd_best;
|
||||
if (m > m_best)
|
||||
goto Ltd;
|
||||
#else
|
||||
if (!m_best)
|
||||
goto Ltd;
|
||||
#endif
|
||||
|
||||
{
|
||||
// Disambiguate by picking the most specialized TemplateDeclaration
|
||||
int c1 = td->leastAsSpecialized(td_best);
|
||||
@@ -3656,6 +3769,7 @@ Identifier *TemplateInstance::genIdent()
|
||||
buf.writeByte('Z');
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("\tgenIdent = %s\n", id);
|
||||
return new Identifier(id, TOKidentifier);
|
||||
}
|
||||
|
||||
@@ -3672,7 +3786,7 @@ void TemplateInstance::declareParameters(Scope *scope)
|
||||
{
|
||||
TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
|
||||
//Object *o = (Object *)tiargs->data[i];
|
||||
Object *o = (Object *)tdtypes.data[i];
|
||||
Object *o = (Object *)tdtypes.data[i]; // initializer for tp
|
||||
|
||||
//printf("\ttdtypes[%d] = %p\n", i, o);
|
||||
tempdecl->declareParameter(scope, tp, o);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -54,7 +54,9 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
TemplateParameters *parameters; // array of TemplateParameter's
|
||||
|
||||
TemplateParameters *origParameters; // originals for Ddoc
|
||||
|
||||
#if DMDV2
|
||||
Expression *constraint;
|
||||
#endif
|
||||
Array instances; // array of TemplateInstance's
|
||||
|
||||
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
||||
@@ -63,7 +65,11 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
Scope *scope;
|
||||
Dsymbol *onemember; // if !=NULL then one member of this template
|
||||
|
||||
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, Array *decldefs);
|
||||
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
|
||||
#if DMDV2
|
||||
Expression *constraint,
|
||||
#endif
|
||||
Array *decldefs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
@@ -77,8 +83,8 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
|
||||
int leastAsSpecialized(TemplateDeclaration *td2);
|
||||
|
||||
MATCH deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs, Objects *dedargs);
|
||||
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expressions *fargs);
|
||||
MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
|
||||
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
|
||||
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
|
||||
|
||||
TemplateDeclaration *isTemplateDeclaration() { return this; }
|
||||
@@ -112,6 +118,9 @@ struct TemplateParameter
|
||||
virtual TemplateTypeParameter *isTemplateTypeParameter();
|
||||
virtual TemplateValueParameter *isTemplateValueParameter();
|
||||
virtual TemplateAliasParameter *isTemplateAliasParameter();
|
||||
#if DMDV2
|
||||
virtual TemplateThisParameter *isTemplateThisParameter();
|
||||
#endif
|
||||
virtual TemplateTupleParameter *isTemplateTupleParameter();
|
||||
|
||||
virtual TemplateParameter *syntaxCopy() = 0;
|
||||
@@ -120,7 +129,7 @@ struct TemplateParameter
|
||||
virtual void print(Object *oarg, Object *oded) = 0;
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||
virtual Object *specialization() = 0;
|
||||
virtual Object *defaultArg(Scope *sc) = 0;
|
||||
virtual Object *defaultArg(Loc loc, Scope *sc) = 0;
|
||||
|
||||
/* If TemplateParameter's match as far as overloading goes.
|
||||
*/
|
||||
@@ -152,7 +161,7 @@ struct TemplateTypeParameter : TemplateParameter
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Scope *sc);
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
void *dummyArg();
|
||||
@@ -196,7 +205,7 @@ struct TemplateValueParameter : TemplateParameter
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Scope *sc);
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
void *dummyArg();
|
||||
@@ -224,7 +233,7 @@ struct TemplateAliasParameter : TemplateParameter
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Scope *sc);
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
void *dummyArg();
|
||||
@@ -245,7 +254,7 @@ struct TemplateTupleParameter : TemplateParameter
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Scope *sc);
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
void *dummyArg();
|
||||
|
||||
@@ -1375,7 +1375,7 @@ void VolatileStatement::toIR(IRState* p)
|
||||
statement->toIR(p);
|
||||
|
||||
// no point in a unreachable barrier, terminating statements must insert this themselves.
|
||||
if (statement->fallOffEnd())
|
||||
if (statement->blockExit() & BEfallthru)
|
||||
{
|
||||
// store-load
|
||||
DtoMemoryBarrier(false, false, true, false);
|
||||
|
||||
Reference in New Issue
Block a user