aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2019-04-23 20:08:46 +0000
committerIain Buclaw <ibuclaw@gcc.gnu.org>2019-04-23 20:08:46 +0000
commitc0aebc60b2ac19816f0431241d8f7203e60afb01 (patch)
tree4eec38d1f02e2a59de0dc908c56593c54d0d3960 /gcc/d/dmd
parent32efff9f947137bb6f6bf47a846e3bf8a162170a (diff)
downloadgcc-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/MERGE2
-rw-r--r--gcc/d/dmd/clone.c12
-rw-r--r--gcc/d/dmd/dcast.c2
-rw-r--r--gcc/d/dmd/declaration.c4
-rw-r--r--gcc/d/dmd/dinterpret.c6
-rw-r--r--gcc/d/dmd/dmodule.c63
-rw-r--r--gcc/d/dmd/dstruct.c15
-rw-r--r--gcc/d/dmd/expressionsem.c7
-rw-r--r--gcc/d/dmd/func.c28
-rw-r--r--gcc/d/dmd/globals.h15
-rw-r--r--gcc/d/dmd/idgen.c6
-rw-r--r--gcc/d/dmd/opover.c8
-rw-r--r--gcc/d/dmd/parse.c2
-rw-r--r--gcc/d/dmd/statementsem.c52
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;