diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2019-04-23 20:08:46 +0000 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gcc.gnu.org> | 2019-04-23 20:08:46 +0000 |
commit | c0aebc60b2ac19816f0431241d8f7203e60afb01 (patch) | |
tree | 4eec38d1f02e2a59de0dc908c56593c54d0d3960 /gcc/d/dmd | |
parent | 32efff9f947137bb6f6bf47a846e3bf8a162170a (diff) | |
download | gcc-c0aebc60b2ac19816f0431241d8f7203e60afb01.zip gcc-c0aebc60b2ac19816f0431241d8f7203e60afb01.tar.gz gcc-c0aebc60b2ac19816f0431241d8f7203e60afb01.tar.bz2 |
d: Add support for compiling without libphobos library.
Merges upstream dmd 3b3dca8be
Reviewed-on: https://github.com/dlang/dmd/pull/9678
gcc/d/ChangeLog:
2019-04-23 Iain Buclaw <ibuclaw@gdcproject.org>
* d-builtins.cc (d_init_versions): Add D_BetterC, D_ModuleInfo,
D_Exceptions, D_TypeInfo as predefined version conditions.
* d-codegen.cc (build_bounds_condition): Generate trap if D asserts
are turned off.
* d-frontend.cc (getTypeInfoType): Add error when -fno-rtti is set.
* d-lang.cc (d_init_options): Initialize new front-end options.
(d_handle_option): Handle -fdruntime, -fexceptions, and -frtti.
(d_post_options): Turn off D runtime features if -fno-druntime is set.
* d-spec.cc (lang_specific_driver): Handle -fdruntime.
* d-tree.h (have_typeinfo_p): Add prototype.
(build_typeinfo): Update prototype.
* decl.cc (DeclVisitor::visit(StructDeclaration)): Create typeinfo
only if TypeInfo exists.
(DeclVisitor::visit(ClassDeclaration)): Likewise.
(DeclVisitor::visit(InterfaceDeclaration)): Likewise.
(DeclVisitor::visit(EnumDeclaration)): Likewise.
* expr.cc: Update all calls to build_typeinfo.
* gdc.texi (Runtime Options): Document -fdruntime and -frtti.
* lang.opt: Add -fdruntime and -frtti.
* modules.cc (build_module_tree): Create module info only if
ModuleInfo exists.
* toir.cc (IRVisitor::visit(ThrowStatement)): Update test for
-fno-exceptions.
* typeinfo.cc (create_tinfo_types): Build internal typeinfo classes
only if Object exists.
(have_typeinfo_p): New function.
(class TypeInfoVisitor): Update all calls to build_typeinfo.
(build_typeinfo): Add error when -fno-rtti is set.
gcc/testsuite/ChangeLog:
2019-04-23 Iain Buclaw <ibuclaw@gdcproject.org>
* gdc.test/fail_compilation/fail2456.d: New test.
* gdc.test/fail_compilation/test18312.d: New test.
* gdc.test/gdc-test.exp (gdc-convert-args): Handle -betterC.
From-SVN: r270518
Diffstat (limited to 'gcc/d/dmd')
-rw-r--r-- | gcc/d/dmd/MERGE | 2 | ||||
-rw-r--r-- | gcc/d/dmd/clone.c | 12 | ||||
-rw-r--r-- | gcc/d/dmd/dcast.c | 2 | ||||
-rw-r--r-- | gcc/d/dmd/declaration.c | 4 | ||||
-rw-r--r-- | gcc/d/dmd/dinterpret.c | 6 | ||||
-rw-r--r-- | gcc/d/dmd/dmodule.c | 63 | ||||
-rw-r--r-- | gcc/d/dmd/dstruct.c | 15 | ||||
-rw-r--r-- | gcc/d/dmd/expressionsem.c | 7 | ||||
-rw-r--r-- | gcc/d/dmd/func.c | 28 | ||||
-rw-r--r-- | gcc/d/dmd/globals.h | 15 | ||||
-rw-r--r-- | gcc/d/dmd/idgen.c | 6 | ||||
-rw-r--r-- | gcc/d/dmd/opover.c | 8 | ||||
-rw-r--r-- | gcc/d/dmd/parse.c | 2 | ||||
-rw-r--r-- | gcc/d/dmd/statementsem.c | 52 |
14 files changed, 118 insertions, 104 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index c360fe5..7424576 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -065fbd452f2aa498fc3a554be48a5495bd98aa14 +3b3dca8be201b443f17621cd29cf614007b5c75e The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/clone.c b/gcc/d/dmd/clone.c index 888cba5..d9a9055 100644 --- a/gcc/d/dmd/clone.c +++ b/gcc/d/dmd/clone.c @@ -839,7 +839,7 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc) } else { - // _ArrayPostblit((cast(S*)this.v.ptr)[0 .. n]) + // __ArrayPostblit((cast(S*)this.v.ptr)[0 .. n]) uinteger_t n = 1; while (tv->ty == Tsarray) @@ -865,7 +865,7 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc) ((SliceExp *)ex)->upperIsInBounds = true; ((SliceExp *)ex)->lowerIsLessThanUpper = true; - ex = new CallExp(loc, new IdentifierExp(loc, Id::_ArrayPostblit), ex); + ex = new CallExp(loc, new IdentifierExp(loc, Id::__ArrayPostblit), ex); } a->push(new ExpStatement(loc, ex)); // combine in forward order @@ -896,7 +896,7 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc) } else { - // _ArrayDtor((cast(S*)this.v.ptr)[0 .. n]) + // __ArrayDtor((cast(S*)this.v.ptr)[0 .. n]) uinteger_t n = 1; while (tv->ty == Tsarray) @@ -922,7 +922,7 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc) ((SliceExp *)ex)->upperIsInBounds = true; ((SliceExp *)ex)->lowerIsLessThanUpper = true; - ex = new CallExp(loc, new IdentifierExp(loc, Id::_ArrayDtor), ex); + ex = new CallExp(loc, new IdentifierExp(loc, Id::__ArrayDtor), ex); } a->push(new OnScopeStatement(loc, TOKon_scope_failure, new ExpStatement(loc, ex))); } @@ -1047,7 +1047,7 @@ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc) } else { - // _ArrayDtor((cast(S*)this.v.ptr)[0 .. n]) + // __ArrayDtor((cast(S*)this.v.ptr)[0 .. n]) uinteger_t n = 1; while (tv->ty == Tsarray) @@ -1073,7 +1073,7 @@ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc) ((SliceExp *)ex)->upperIsInBounds = true; ((SliceExp *)ex)->lowerIsLessThanUpper = true; - ex = new CallExp(loc, new IdentifierExp(loc, Id::_ArrayDtor), ex); + ex = new CallExp(loc, new IdentifierExp(loc, Id::__ArrayDtor), ex); } e = Expression::combine(ex, e); // combine in reverse order } diff --git a/gcc/d/dmd/dcast.c b/gcc/d/dmd/dcast.c index 2fa762c..a3df701 100644 --- a/gcc/d/dmd/dcast.c +++ b/gcc/d/dmd/dcast.c @@ -131,7 +131,7 @@ Expression *implicitCastTo(Expression *e, Scope *sc, Type *t) visit((Expression *)e); Type *tb = result->type->toBasetype(); - if (tb->ty == Tarray) + if (tb->ty == Tarray && global.params.useTypeInfo && Type::dtypeinfo) semanticTypeInfo(sc, ((TypeDArray *)tb)->next); } diff --git a/gcc/d/dmd/declaration.c b/gcc/d/dmd/declaration.c index 835c6ae..d0911e2 100644 --- a/gcc/d/dmd/declaration.c +++ b/gcc/d/dmd/declaration.c @@ -2118,7 +2118,7 @@ Expression *VarDeclaration::callScopeDtor(Scope *) } else { - // _ArrayDtor(v[0 .. n]) + // __ArrayDtor(v[0 .. n]) e = new VarExp(loc, this); const d_uns64 sdsz = sd->type->size(); @@ -2133,7 +2133,7 @@ Expression *VarDeclaration::callScopeDtor(Scope *) // This is a hack so we can call destructors on const/immutable objects. e->type = sd->type->arrayOf(); - e = new CallExp(loc, new IdentifierExp(loc, Id::_ArrayDtor), e); + e = new CallExp(loc, new IdentifierExp(loc, Id::__ArrayDtor), e); } return e; } diff --git a/gcc/d/dmd/dinterpret.c b/gcc/d/dmd/dinterpret.c index 40f3e77..acca4e8 100644 --- a/gcc/d/dmd/dinterpret.c +++ b/gcc/d/dmd/dinterpret.c @@ -4633,8 +4633,8 @@ public: fd = ((VarExp *)ecall)->var->isFuncDeclaration(); assert(fd); - if (fd->ident == Id::_ArrayPostblit || - fd->ident == Id::_ArrayDtor) + if (fd->ident == Id::__ArrayPostblit || + fd->ident == Id::__ArrayDtor) { assert(e->arguments->dim == 1); Expression *ea = (*e->arguments)[0]; @@ -4654,7 +4654,7 @@ public: if (CTFEExp::isCantExp(result)) return; - if (fd->ident == Id::_ArrayPostblit) + if (fd->ident == Id::__ArrayPostblit) result = evaluatePostblit(istate, result); else result = evaluateDtor(istate, result); diff --git a/gcc/d/dmd/dmodule.c b/gcc/d/dmd/dmodule.c index 07e4712..1f6fd9f 100644 --- a/gcc/d/dmd/dmodule.c +++ b/gcc/d/dmd/dmodule.c @@ -575,69 +575,6 @@ Module *Module::parse() error("has non-identifier characters in filename, use module declaration instead"); } - // Add internal used functions in 'object' module members. - if (!parent && ident == Id::object) - { - static const utf8_t code_ArrayEq[] = - "bool _ArrayEq(T1, T2)(T1[] a, T2[] b) {\n" - " if (a.length != b.length) return false;\n" - " foreach (size_t i; 0 .. a.length) { if (a[i] != b[i]) return false; }\n" - " return true; }\n"; - - static const utf8_t code_ArrayPostblit[] = - "void _ArrayPostblit(T)(T[] a) { foreach (ref T e; a) e.__xpostblit(); }\n"; - - static const utf8_t code_ArrayDtor[] = - "void _ArrayDtor(T)(T[] a) { foreach_reverse (ref T e; a) e.__xdtor(); }\n"; - - static const utf8_t code_xopEquals[] = - "bool _xopEquals(in void*, in void*) { throw new Error(\"TypeInfo.equals is not implemented\"); }\n"; - - static const utf8_t code_xopCmp[] = - "bool _xopCmp(in void*, in void*) { throw new Error(\"TypeInfo.compare is not implemented\"); }\n"; - - Identifier *arreq = Id::_ArrayEq; - Identifier *xopeq = Identifier::idPool("_xopEquals"); - Identifier *xopcmp = Identifier::idPool("_xopCmp"); - for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *sx = (*members)[i]; - if (!sx) continue; - if (arreq && sx->ident == arreq) arreq = NULL; - if (xopeq && sx->ident == xopeq) xopeq = NULL; - if (xopcmp && sx->ident == xopcmp) xopcmp = NULL; - } - - if (arreq) - { - Parser p(loc, this, code_ArrayEq, strlen((const char *)code_ArrayEq), 0); - p.nextToken(); - members->append(p.parseDeclDefs(0)); - } - { - Parser p(loc, this, code_ArrayPostblit, strlen((const char *)code_ArrayPostblit), 0); - p.nextToken(); - members->append(p.parseDeclDefs(0)); - } - { - Parser p(loc, this, code_ArrayDtor, strlen((const char *)code_ArrayDtor), 0); - p.nextToken(); - members->append(p.parseDeclDefs(0)); - } - if (xopeq) - { - Parser p(loc, this, code_xopEquals, strlen((const char *)code_xopEquals), 0); - p.nextToken(); - members->append(p.parseDeclDefs(0)); - } - if (xopcmp) - { - Parser p(loc, this, code_xopCmp, strlen((const char *)code_xopCmp), 0); - p.nextToken(); - members->append(p.parseDeclDefs(0)); - } - } - // Insert module into the symbol table Dsymbol *s = this; if (isPackageFile) diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c index d35b005..1338e1f 100644 --- a/gcc/d/dmd/dstruct.c +++ b/gcc/d/dmd/dstruct.c @@ -23,7 +23,7 @@ #include "template.h" #include "tokens.h" -Type *getTypeInfoType(Type *t, Scope *sc); +Type *getTypeInfoType(Loc loc, Type *t, Scope *sc); TypeTuple *toArgTypes(Type *t); void unSpeculative(Scope *sc, RootObject *o); bool MODimplicitConv(MOD modfrom, MOD modto); @@ -101,7 +101,7 @@ void semanticTypeInfo(Scope *sc, Type *t) { Scope scx; scx._module = sd->getModule(); - getTypeInfoType(t, &scx); + getTypeInfoType(sd->loc, t, &scx); sd->requestTypeInfo = true; } else if (!sc->minst) @@ -111,7 +111,7 @@ void semanticTypeInfo(Scope *sc, Type *t) } else { - getTypeInfoType(t, sc); + getTypeInfoType(sd->loc, t, sc); sd->requestTypeInfo = true; // Bugzilla 15149, if the typeid operand type comes from a @@ -1165,9 +1165,12 @@ void StructDeclaration::semantic(Scope *sc) buildOpAssign(this, sc2); buildOpEquals(this, sc2); - xeq = buildXopEquals(this, sc2); - xcmp = buildXopCmp(this, sc2); - xhash = buildXtoHash(this, sc2); + if (global.params.useTypeInfo && Type::dtypeinfo) // these functions are used for TypeInfo + { + xeq = buildXopEquals(this, sc2); + xcmp = buildXopCmp(this, sc2); + xhash = buildXtoHash(this, sc2); + } inv = buildInv(this, sc2); diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c index a88ff88..19b7ccb 100644 --- a/gcc/d/dmd/expressionsem.c +++ b/gcc/d/dmd/expressionsem.c @@ -46,7 +46,7 @@ bool checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad, size_t istar bool symbolIsVisible(Module *mod, Dsymbol *s); VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e); Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expression *e, bool alwaysCopy = false); -Type *getTypeInfoType(Type *t, Scope *sc); +Type *getTypeInfoType(Loc loc, Type *t, Scope *sc); bool MODimplicitConv(MOD modfrom, MOD modto); MATCH MODmethodConv(MOD modfrom, MOD modto); void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod); @@ -713,7 +713,8 @@ public: return setError(); } - semanticTypeInfo(sc, e->type); + if (global.params.useTypeInfo && Type::dtypeinfo) + semanticTypeInfo(sc, e->type); result = e; } @@ -1819,7 +1820,7 @@ public: { // Handle this in the glue layer e = new TypeidExp(exp->loc, ta); - e->type = getTypeInfoType(ta, sc); + e->type = getTypeInfoType(exp->loc, ta, sc); semanticTypeInfo(sc, ta); diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c index afba82a..568decc 100644 --- a/gcc/d/dmd/func.c +++ b/gcc/d/dmd/func.c @@ -246,6 +246,15 @@ public: s->finalbody && (des = s->finalbody->isDtorExpStatement()) != NULL && fd->nrvo_var == des->var) { + if (!(global.params.useExceptions && ClassDeclaration::throwable)) + { + /* Don't need to call destructor at all, since it is nrvo + */ + replaceCurrent(s->_body); + s->_body->accept(this); + return; + } + /* Normally local variable dtors are called regardless exceptions. * But for nrvo_var, its dtor should be called only when exception is thrown. * @@ -1325,6 +1334,16 @@ static void buildEnsureRequire(FuncDeclaration *fdx) } } +/* Determine if function should add `return 0;` + */ +static bool addReturn0(FuncDeclaration *funcdecl) +{ + TypeFunction *f = (TypeFunction *)funcdecl->type; + + return f->next->ty == Tvoid && + (funcdecl->isMain() || (global.params.betterC && funcdecl->isCMain())); +} + // Do the semantic analysis on the internals of the function. void FuncDeclaration::semantic3(Scope *sc) @@ -1708,7 +1727,10 @@ void FuncDeclaration::semantic3(Scope *sc) Expression *exp = (*returns)[i]->exp; if (exp->op == TOKvar && ((VarExp *)exp)->var == vresult) { - exp->type = f->next; + if (addReturn0(this)) + exp->type = Type::tint32; + else + exp->type = f->next; // Remove `return vresult;` from returns returns->remove(i); continue; @@ -1901,7 +1923,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (returns) { - bool implicit0 = (f->next->ty == Tvoid && isMain()); + bool implicit0 = addReturn0(this); Type *tret = implicit0 ? Type::tint32 : f->next; assert(tret->ty != Tvoid); if (vresult || returnLabel) @@ -2123,7 +2145,7 @@ void FuncDeclaration::semantic3(Scope *sc) a->push(s); } } - if (isMain() && f->next->ty == Tvoid) + if (addReturn0(this)) { // Add a return 0; statement Statement *s = new ReturnStatement(Loc(), new IntegerExp(0)); diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h index e2d42c7..1094679 100644 --- a/gcc/d/dmd/globals.h +++ b/gcc/d/dmd/globals.h @@ -36,6 +36,14 @@ enum BOUNDSCHECK BOUNDSCHECKsafeonly // do bounds checking only in @safe functions }; +typedef unsigned char CHECKACTION; +enum +{ + CHECKACTION_D, // call D assert on failure + CHECKACTION_C, // call C assert on failure + CHECKACTION_halt // cause program halt on failure +}; + enum CPU { x87, @@ -116,6 +124,9 @@ struct Param bool nofloat; // code should not pull in floating point support bool ignoreUnsupportedPragmas; // rather than error on them bool enforcePropertySyntax; + bool useModuleInfo; // generate runtime module information + bool useTypeInfo; // generate runtime type information + bool useExceptions; // support exception handling bool betterC; // be a "better C" compiler; no dependency on D runtime bool addMain; // add a default main() function bool allInst; // generate code for all template instantiations @@ -126,7 +137,9 @@ struct Param bool showGaggedErrors; // print gagged errors anyway CPU cpu; // CPU instruction set to target - BOUNDSCHECK useArrayBounds; + + BOUNDSCHECK useArrayBounds; // when to generate code for array bounds checks + CHECKACTION checkAction; // action to take when bounds, asserts or switch defaults are violated const char *argv0; // program name Array<const char *> *modFileAliasStrings; // array of char*'s of -I module filename alias strings diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c index e750048..dc0ecd1 100644 --- a/gcc/d/dmd/idgen.c +++ b/gcc/d/dmd/idgen.c @@ -264,9 +264,9 @@ Msgtable msgtable[] = { "monitorexit", "_d_monitorexit" }, { "criticalenter", "_d_criticalenter" }, { "criticalexit", "_d_criticalexit" }, - { "_ArrayEq", NULL }, - { "_ArrayPostblit", NULL }, - { "_ArrayDtor", NULL }, + { "__ArrayEq", NULL }, + { "__ArrayPostblit", NULL }, + { "__ArrayDtor", NULL }, { "dup", NULL }, { "_aaApply", NULL }, { "_aaApply2", NULL }, diff --git a/gcc/d/dmd/opover.c b/gcc/d/dmd/opover.c index 453ba65..b3ea6cf 100644 --- a/gcc/d/dmd/opover.c +++ b/gcc/d/dmd/opover.c @@ -900,7 +900,9 @@ Expression *op_overload(Expression *e, Scope *sc) if (t->ty != Tstruct) return false; - semanticTypeInfo(sc, t); + if (global.params.useTypeInfo && Type::dtypeinfo) + semanticTypeInfo(sc, t); + return ((TypeStruct *)t)->sym->hasIdentityEquals; } @@ -919,9 +921,9 @@ Expression *op_overload(Expression *e, Scope *sc) if (needsDirectEq(t1, t2, sc)) { /* Rewrite as: - * _ArrayEq(e1, e2) + * __ArrayEq(e1, e2) */ - Expression *eeq = new IdentifierExp(e->loc, Id::_ArrayEq); + Expression *eeq = new IdentifierExp(e->loc, Id::__ArrayEq); result = new CallExp(e->loc, eeq, e->e1, e->e2); if (e->op == TOKnotequal) result = new NotExp(e->loc, result); diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c index 3afdbc2..9da58af 100644 --- a/gcc/d/dmd/parse.c +++ b/gcc/d/dmd/parse.c @@ -70,7 +70,6 @@ Parser::Parser(Loc loc, Module *module, const utf8_t *base, size_t length, bool //printf("Parser::Parser()\n"); scanloc = loc; -#ifndef IN_GCC if (loc.filename) { /* Create a pseudo-filename for the mixin string, as it may not even exist @@ -80,7 +79,6 @@ Parser::Parser(Loc loc, Module *module, const utf8_t *base, size_t length, bool sprintf(filename, "%s-mixin-%d", loc.filename, (int)loc.linnum); scanloc.filename = filename; } -#endif mod = module; md = NULL; diff --git a/gcc/d/dmd/statementsem.c b/gcc/d/dmd/statementsem.c index f694fb1..64cc42d 100644 --- a/gcc/d/dmd/statementsem.c +++ b/gcc/d/dmd/statementsem.c @@ -2073,8 +2073,19 @@ public: CompoundStatement *cs; Statement *s; - if (global.params.useSwitchError) - s = new SwitchErrorStatement(ss->loc); + if (global.params.useSwitchError && + global.params.checkAction != CHECKACTION_halt) + { + if (global.params.checkAction == CHECKACTION_C) + { + /* Rewrite as an assert(0) and let e2ir generate + * the call to the C assert failure function + */ + s = new ExpStatement(ss->loc, new AssertExp(ss->loc, new IntegerExp(ss->loc, 0, Type::tint32))); + } + else + s = new SwitchErrorStatement(ss->loc); + } else s = new ExpStatement(ss->loc, new HaltExp(ss->loc)); @@ -3118,6 +3129,18 @@ public: void visit(TryCatchStatement *tcs) { + if (!global.params.useExceptions) + { + tcs->error("Cannot use try-catch statements with -betterC"); + return setError(); + } + + if (!ClassDeclaration::throwable) + { + tcs->error("Cannot use try-catch statements because `object.Throwable` was not declared"); + return setError(); + } + unsigned flags = 0; const unsigned FLAGcpp = 1; const unsigned FLAGd = 2; @@ -3227,7 +3250,14 @@ public: return; } - if (blockExit(tfs->_body, sc->func, false) == BEfallthru) + int blockexit = blockExit(tfs->_body, sc->func, false); + + // if not worrying about exceptions + if (!(global.params.useExceptions && ClassDeclaration::throwable)) + blockexit &= ~BEthrow; // don't worry about paths that otherwise may throw + + // Don't care about paths that halt, either + if ((blockexit & ~BEhalt) == BEfallthru) { result = new CompoundStatement(tfs->loc, tfs->_body, tfs->finalbody); return; @@ -3237,7 +3267,6 @@ public: void visit(OnScopeStatement *oss) { -#ifndef IN_GCC if (oss->tok != TOKon_scope_exit) { // scope(success) and scope(failure) are rewritten to try-catch(-finally) statement, @@ -3255,7 +3284,6 @@ public: return setError(); } } -#endif sc = sc->push(); sc->tf = NULL; @@ -3281,6 +3309,18 @@ public: { //printf("ThrowStatement::semantic()\n"); + if (!global.params.useExceptions) + { + ts->error("Cannot use `throw` statements with -betterC"); + return setError(); + } + + if (!ClassDeclaration::throwable) + { + ts->error("Cannot use `throw` statements because `object.Throwable` was not declared"); + return setError(); + } + FuncDeclaration *fd = sc->parent->isFuncDeclaration(); fd->hasReturnExp |= 2; @@ -3463,7 +3503,6 @@ void semantic(Catch *c, Scope *sc) { //printf("Catch::semantic(%s)\n", ident->toChars()); -#ifndef IN_GCC if (sc->os && sc->os->tok != TOKon_scope_failure) { // If enclosing is scope(success) or scope(exit), this will be placed in finally block. @@ -3481,7 +3520,6 @@ void semantic(Catch *c, Scope *sc) error(c->loc, "cannot put catch statement inside finally block"); c->errors = true; } -#endif ScopeDsymbol *sym = new ScopeDsymbol(); sym->parent = sc->scopesym; |