Skip to content

Commit

Permalink
Merge pull request #3455 from WalterBright/atnogc
Browse files Browse the repository at this point in the history
start on @nogc
  • Loading branch information
andralex committed Apr 21, 2014
2 parents 8903f3f + 2688f71 commit cdeb19e
Show file tree
Hide file tree
Showing 15 changed files with 69 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/arrayop.c
Expand Up @@ -61,8 +61,8 @@ FuncDeclaration *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc
//printf("s2: %s\n", s2->toChars());
Statement *fbody = new CompoundStatement(Loc(), s1, s2);

// Built-in array ops should be @trusted, pure and nothrow
StorageClass stc = STCtrusted | STCpure | STCnothrow;
// Built-in array ops should be @trusted, pure, nothrow and nogc
StorageClass stc = STCtrusted | STCpure | STCnothrow | STCnogc;

/* Construct the function
*/
Expand Down
1 change: 1 addition & 0 deletions src/attrib.c
Expand Up @@ -463,6 +463,7 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
{ STCref, TOKref },
{ STCtls },
{ STCgshared, TOKgshared },
{ STCnogc, TOKat, "nogc" },
{ STCproperty, TOKat, "property" },
{ STCsafe, TOKat, "safe" },
{ STCtrusted, TOKat, "trusted" },
Expand Down
1 change: 1 addition & 0 deletions src/cast.c
Expand Up @@ -2558,6 +2558,7 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
assert(d->purity != PUREfwdref);

d->isnothrow = (tf1->isnothrow && tf2->isnothrow);
d->isnogc = (tf1->isnogc && tf2->isnogc);

if (tf1->trust == tf2->trust)
d->trust = tf1->trust;
Expand Down
1 change: 1 addition & 0 deletions src/class.c
Expand Up @@ -720,6 +720,7 @@ void ClassDeclaration::semantic(Scope *sc)
TypeFunction *tf = new TypeFunction(NULL, NULL, 0, LINKd, fd->storage_class);
tf->purity = btf->purity;
tf->isnothrow = btf->isnothrow;
tf->isnogc = btf->isnogc;
tf->trust = btf->trust;
CtorDeclaration *ctor = new CtorDeclaration(loc, Loc(), 0, tf);
ctor->fbody = new CompoundStatement(Loc(), new Statements());
Expand Down
5 changes: 5 additions & 0 deletions src/clone.c
Expand Up @@ -41,6 +41,8 @@ StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f)
s2 |= STCpure;
if (tf->isnothrow)
s2 |= STCnothrow;
if (tf->isnogc)
s2 |= STCnogc;

StorageClass stc = 0;
StorageClass sa = s1 & s2;
Expand All @@ -61,6 +63,9 @@ StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f)
if (sa & STCnothrow)
stc |= STCnothrow;

if (sa & STCnogc)
stc |= STCnogc;

if (so & STCdisable)
stc |= STCdisable;

Expand Down
6 changes: 3 additions & 3 deletions src/declaration.c
Expand Up @@ -521,11 +521,11 @@ void AliasDeclaration::semantic(Scope *sc)
goto L2; // it's a symbolic alias

type = type->addStorageClass(storage_class);
if (storage_class & (STCref | STCnothrow | STCpure | STCdisable))
if (storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCdisable))
{ // For 'ref' to be attached to function types, and picked
// up by Type::resolve(), it has to go into sc.
sc = sc->push();
sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared | STCdisable);
sc->stc |= storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCshared | STCdisable);
type->resolve(loc, sc, &e, &t, &s);
sc = sc->pop();
}
Expand Down Expand Up @@ -1362,7 +1362,7 @@ void VarDeclaration::semantic(Scope *sc)
if (init)
{
sc = sc->push();
sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref | STCdisable);
sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCnogc | STCref | STCdisable);

ExpInitializer *ei = init->isExpInitializer();
if (ei && isScope())
Expand Down
5 changes: 3 additions & 2 deletions src/declaration.h
Expand Up @@ -73,7 +73,7 @@ enum PURE;
// but not typed as "shared"
#define STCwild 0x80000000LL // for "wild" type constructor
#define STC_TYPECTOR (STCconst | STCimmutable | STCshared | STCwild)
#define STC_FUNCATTR (STCref | STCnothrow | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem)
#define STC_FUNCATTR (STCref | STCnothrow | STCnogc | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem)

#define STCproperty 0x100000000LL
#define STCsafe 0x200000000LL
Expand All @@ -86,11 +86,12 @@ enum PURE;
#define STCtemp 0x10000000000LL // temporary variable
#define STCrvalue 0x20000000000LL // force rvalue for variables
#define STCvirtual 0x40000000000LL
#define STCnogc 0x80000000000LL // @nogc

const StorageClass STCStorageClass = (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal |
STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias |
STCout | STCin | STCvirtual |
STCmanifest | STCimmutable | STCshared | STCwild | STCnothrow | STCpure | STCref | STCtls |
STCmanifest | STCimmutable | STCshared | STCwild | STCnothrow | STCnogc | STCpure | STCref | STCtls |
STCgshared | STCproperty | STCsafe | STCtrusted | STCsystem | STCdisable);

struct Match
Expand Down
4 changes: 2 additions & 2 deletions src/expression.c
Expand Up @@ -5875,9 +5875,9 @@ Expression *DeclarationExp::semantic(Scope *sc)
if (!s->isVarDeclaration())
{
Scope *sc2 = sc;
if (sc2->stc & (STCpure | STCnothrow))
if (sc2->stc & (STCpure | STCnothrow | STCnogc))
sc2 = sc->push();
sc2->stc &= ~(STCpure | STCnothrow);
sc2->stc &= ~(STCpure | STCnothrow | STCnogc);
declaration->semantic(sc2);
if (sc2 != sc)
sc2->pop();
Expand Down
4 changes: 4 additions & 0 deletions src/func.c
Expand Up @@ -468,6 +468,7 @@ void FuncDeclaration::semantic(Scope *sc)
#endif
if (tf->isref) sc->stc |= STCref;
if (tf->isnothrow) sc->stc |= STCnothrow;
if (tf->isnogc) sc->stc |= STCnogc;
if (tf->isproperty) sc->stc |= STCproperty;
if (tf->purity == PUREfwdref) sc->stc |= STCpure;
if (tf->trust == TRUSTsafe) sc->stc |= STCsafe;
Expand Down Expand Up @@ -590,6 +591,7 @@ void FuncDeclaration::semantic(Scope *sc)
tfo->mod = tfx->mod;
tfo->isref = tfx->isref;
tfo->isnothrow = tfx->isnothrow;
tfo->isnogc = tfx->isnogc;
tfo->isproperty = tfx->isproperty;
tfo->purity = tfx->purity;
tfo->trust = tfx->trust;
Expand Down Expand Up @@ -1085,6 +1087,7 @@ void FuncDeclaration::semantic(Scope *sc)
Loc loc = frequire->loc;
TypeFunction *tf = new TypeFunction(NULL, Type::tvoid, 0, LINKd);
tf->isnothrow = f->isnothrow;
tf->isnogc = f->isnogc;
tf->purity = f->purity;
tf->trust = f->trust;
FuncDeclaration *fd = new FuncDeclaration(loc, loc,
Expand Down Expand Up @@ -1116,6 +1119,7 @@ void FuncDeclaration::semantic(Scope *sc)
}
TypeFunction *tf = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
tf->isnothrow = f->isnothrow;
tf->isnogc = f->isnogc;
tf->purity = f->purity;
tf->trust = f->trust;
FuncDeclaration *fd = new FuncDeclaration(loc, loc,
Expand Down
4 changes: 4 additions & 0 deletions src/hdrgen.c
Expand Up @@ -862,6 +862,8 @@ class PrettyPrintVisitor : public Visitor
buf->writestring(" pure");
if (t->isnothrow)
buf->writestring(" nothrow");
if (t->isnogc)
buf->writestring(" @nogc");
if (t->isproperty)
buf->writestring(" @property");
if (t->isref)
Expand Down Expand Up @@ -1790,6 +1792,8 @@ void functionToBufferFull(TypeFunction *tf, OutBuffer *buf, Identifier *ident,
buf->writestring("pure ");
if (tf->isnothrow)
buf->writestring("nothrow ");
if (tf->isnogc)
buf->writestring("@nogc ");
if (tf->isproperty)
buf->writestring("@property ");
if (tf->isref && ident != Id::ctor)
Expand Down
1 change: 1 addition & 0 deletions src/idgen.c
Expand Up @@ -146,6 +146,7 @@ Msgtable msgtable[] =
{ "reverse" },

{ "property" },
{ "nogc" },
{ "safe" },
{ "trusted" },
{ "system" },
Expand Down
21 changes: 19 additions & 2 deletions src/mtype.c
Expand Up @@ -2098,6 +2098,7 @@ Type *TypeFunction::substWildTo(unsigned)
TypeFunction *t = new TypeFunction(params, tret, varargs, linkage);
t->mod = ((mod & MODwild) ? (mod & ~MODwild) | MODconst : mod);
t->isnothrow = isnothrow;
t->isnogc = isnogc;
t->purity = purity;
t->isproperty = isproperty;
t->isref = isref;
Expand Down Expand Up @@ -4769,6 +4770,7 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int
TypeFunction *tf = (TypeFunction *)fd_aaLen->type;
tf->purity = PUREconst;
tf->isnothrow = true;
tf->isnogc = false;
}
Expression *ev = new VarExp(e->loc, fd_aaLen);
e = new CallExp(e->loc, ev, e);
Expand Down Expand Up @@ -5106,6 +5108,7 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, L
this->linkage = linkage;
this->inuse = 0;
this->isnothrow = false;
this->isnogc = false;
this->purity = PUREimpure;
this->isproperty = false;
this->isref = false;
Expand All @@ -5116,6 +5119,8 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, L
this->purity = PUREfwdref;
if (stc & STCnothrow)
this->isnothrow = true;
if (stc & STCnogc)
this->isnogc = true;
if (stc & STCproperty)
this->isproperty = true;

Expand Down Expand Up @@ -5148,6 +5153,7 @@ Type *TypeFunction::syntaxCopy()
TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
t->mod = mod;
t->isnothrow = isnothrow;
t->isnogc = isnogc;
t->purity = purity;
t->isproperty = isproperty;
t->isref = isref;
Expand Down Expand Up @@ -5297,14 +5303,17 @@ int Type::covariant(Type *t, StorageClass *pstc)
#endif
}

/* Can convert pure to impure, and nothrow to throw
/* Can convert pure to impure, nothrow to throw, and nogc to gc
*/
if (!t1->purity && t2->purity)
stc |= STCpure;

if (!t1->isnothrow && t2->isnothrow)
stc |= STCnothrow;

if (!t1->isnogc && t2->isnogc)
stc |= STCnogc;

/* Can convert safe/trusted to system
*/
if (t1->trust <= TRUSTsystem && t2->trust >= TRUSTtrusted)
Expand Down Expand Up @@ -5355,7 +5364,7 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag)
}
buf->writeByte(mc);

if (purity || isnothrow || isproperty || isref || trust)
if (purity || isnothrow || isnogc || isproperty || isref || trust)
{
if (purity)
buf->writestring("Na");
Expand All @@ -5365,6 +5374,8 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag)
buf->writestring("Nc");
if (isproperty)
buf->writestring("Nd");
if (isnogc)
buf->writestring("Ni");
switch (trust)
{
case TRUSTtrusted:
Expand Down Expand Up @@ -5419,6 +5430,8 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
tf->purity = PUREfwdref;
if (sc->stc & STCnothrow)
tf->isnothrow = true;
if (sc->stc & STCnogc)
tf->isnogc = true;
if (sc->stc & STCref)
tf->isref = true;

Expand Down Expand Up @@ -6123,6 +6136,7 @@ Type *TypeFunction::addStorageClass(StorageClass stc)
TypeFunction *t = (TypeFunction *)Type::addStorageClass(stc);
if ((stc & STCpure && !t->purity) ||
(stc & STCnothrow && !t->isnothrow) ||
(stc & STCnogc && !t->isnogc) ||
(stc & STCsafe && t->trust < TRUSTtrusted))
{
// Klunky to change these
Expand All @@ -6131,6 +6145,7 @@ Type *TypeFunction::addStorageClass(StorageClass stc)
tf->fargs = fargs;
tf->purity = t->purity;
tf->isnothrow = t->isnothrow;
tf->isnogc = t->isnogc;
tf->isproperty = t->isproperty;
tf->isref = t->isref;
tf->trust = t->trust;
Expand All @@ -6140,6 +6155,8 @@ Type *TypeFunction::addStorageClass(StorageClass stc)
tf->purity = PUREfwdref;
if (stc & STCnothrow)
tf->isnothrow = true;
if (stc & STCnogc)
tf->isnogc = true;
if (stc & STCsafe)
tf->trust = TRUSTsafe;

Expand Down
1 change: 1 addition & 0 deletions src/mtype.h
Expand Up @@ -614,6 +614,7 @@ class TypeFunction : public TypeNext
int varargs; // 1: T t, ...) style for variable number of arguments
// 2: T t ...) style for variable number of arguments
bool isnothrow; // true: nothrow
bool isnogc; // true: is @nogc
bool isproperty; // can be called without parentheses
bool isref; // true: returns a reference
LINK linkage; // calling convention
Expand Down
3 changes: 3 additions & 0 deletions src/parse.c
Expand Up @@ -813,6 +813,8 @@ StorageClass Parser::parseAttribute(Expressions **pudas)
{
if (token.ident == Id::property)
stc = STCproperty;
else if (token.ident == Id::nogc)
stc = STCnogc;
else if (token.ident == Id::safe)
stc = STCsafe;
else if (token.ident == Id::trusted)
Expand Down Expand Up @@ -5823,6 +5825,7 @@ int Parser::skipAttributes(Token *t, Token **pt)
* @predefined_attribute
*/
if (t->ident == Id::property ||
t->ident == Id::nogc ||
t->ident == Id::safe ||
t->ident == Id::trusted ||
t->ident == Id::system ||
Expand Down
19 changes: 19 additions & 0 deletions test/runnable/nogc.d
@@ -0,0 +1,19 @@

import std.stdio;

/***********************/

@nogc int test1()
{
return 3;
}

/***********************/

int main()
{
test1();

writeln("Success");
return 0;
}

0 comments on commit cdeb19e

Please sign in to comment.