diff options
Diffstat (limited to 'gcc/d/dmd/statement.c')
-rw-r--r-- | gcc/d/dmd/statement.c | 1793 |
1 files changed, 0 insertions, 1793 deletions
diff --git a/gcc/d/dmd/statement.c b/gcc/d/dmd/statement.c deleted file mode 100644 index 1f8e512..0000000 --- a/gcc/d/dmd/statement.c +++ /dev/null @@ -1,1793 +0,0 @@ - -/* Compiler implementation of the D programming language - * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved - * written by Walter Bright - * http://www.digitalmars.com - * Distributed under the Boost Software License, Version 1.0. - * http://www.boost.org/LICENSE_1_0.txt - * https://github.com/D-Programming-Language/dmd/blob/master/src/statement.c - */ - -#include "root/dsystem.h" - -#include "statement.h" -#include "errors.h" -#include "expression.h" -#include "cond.h" -#include "init.h" -#include "staticassert.h" -#include "scope.h" -#include "declaration.h" -#include "aggregate.h" -#include "id.h" -#include "hdrgen.h" -#include "parse.h" -#include "template.h" -#include "attrib.h" -#include "import.h" - -bool walkPostorder(Statement *s, StoppableVisitor *v); -StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f); -bool checkEscapeRef(Scope *sc, Expression *e, bool gag); -VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e); -Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion); -bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps); - -Identifier *fixupLabelName(Scope *sc, Identifier *ident) -{ - unsigned flags = (sc->flags & SCOPEcontract); - const char *id = ident->toChars(); - if (flags && flags != SCOPEinvariant && - !(id[0] == '_' && id[1] == '_')) - { - /* CTFE requires FuncDeclaration::labtab for the interpretation. - * So fixing the label name inside in/out contracts is necessary - * for the uniqueness in labtab. - */ - const char *prefix = flags == SCOPErequire ? "__in_" : "__out_"; - OutBuffer buf; - buf.printf("%s%s", prefix, ident->toChars()); - - const char *name = buf.extractChars(); - ident = Identifier::idPool(name); - } - return ident; -} - -LabelStatement *checkLabeledLoop(Scope *sc, Statement *statement) -{ - if (sc->slabel && sc->slabel->statement == statement) - { - return sc->slabel; - } - return NULL; -} - -/*********************************************************** - * Check an assignment is used as a condition. - * Intended to be use before the `semantic` call on `e`. - * Params: - * e = condition expression which is not yet run semantic analysis. - * Returns: - * `e` or ErrorExp. - */ -Expression *checkAssignmentAsCondition(Expression *e) -{ - Expression *ec = e; - while (ec->op == TOKcomma) - ec = ((CommaExp *)ec)->e2; - if (ec->op == TOKassign) - { - ec->error("assignment cannot be used as a condition, perhaps == was meant?"); - return new ErrorExp(); - } - return e; -} - -/// Return a type identifier reference to 'object.Throwable' -TypeIdentifier *getThrowable() -{ - TypeIdentifier *tid = new TypeIdentifier(Loc(), Id::empty); - tid->addIdent(Id::object); - tid->addIdent(Id::Throwable); - return tid; -} - -/******************************** Statement ***************************/ - -Statement::Statement(Loc loc) - : loc(loc) -{ - // If this is an in{} contract scope statement (skip for determining - // inlineStatus of a function body for header content) -} - -Statement *Statement::syntaxCopy() -{ - assert(0); - return NULL; -} - -/************************************* - * Do syntax copy of an array of Statement's. - */ -Statements *Statement::arraySyntaxCopy(Statements *a) -{ - Statements *b = NULL; - if (a) - { - b = a->copy(); - for (size_t i = 0; i < a->length; i++) - { - Statement *s = (*a)[i]; - (*b)[i] = s ? s->syntaxCopy() : NULL; - } - } - return b; -} - -void Statement::print() -{ - fprintf(stderr, "%s\n", toChars()); - fflush(stderr); -} - -const char *Statement::toChars() -{ - HdrGenState hgs; - - OutBuffer buf; - ::toCBuffer(this, &buf, &hgs); - return buf.extractChars(); -} - - -void Statement::error(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - ::verror(loc, format, ap); - va_end( ap ); -} - -void Statement::warning(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - ::vwarning(loc, format, ap); - va_end( ap ); -} - -void Statement::deprecation(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - ::vdeprecation(loc, format, ap); - va_end( ap ); -} - -bool Statement::hasBreak() -{ - //printf("Statement::hasBreak()\n"); - return false; -} - -bool Statement::hasContinue() -{ - return false; -} - -/* ============================================== */ -// true if statement uses exception handling - -bool Statement::usesEH() -{ - class UsesEH : public StoppableVisitor - { - public: - void visit(Statement *) {} - void visit(TryCatchStatement *) { stop = true; } - void visit(TryFinallyStatement *) { stop = true; } - void visit(ScopeGuardStatement *) { stop = true; } - void visit(SynchronizedStatement *) { stop = true; } - }; - - UsesEH ueh; - return walkPostorder(this, &ueh); -} - -/* ============================================== */ -// true if statement 'comes from' somewhere else, like a goto - -bool Statement::comeFrom() -{ - class ComeFrom : public StoppableVisitor - { - public: - void visit(Statement *) {} - void visit(CaseStatement *) { stop = true; } - void visit(DefaultStatement *) { stop = true; } - void visit(LabelStatement *) { stop = true; } - void visit(AsmStatement *) { stop = true; } - }; - - ComeFrom cf; - return walkPostorder(this, &cf); -} - -/* ============================================== */ -// Return true if statement has executable code. - -bool Statement::hasCode() -{ - class HasCode : public StoppableVisitor - { - public: - void visit(Statement *) - { - stop = true; - } - - void visit(ExpStatement *s) - { - if (s->exp != NULL) - { - stop = s->exp->hasCode(); - } - } - - void visit(CompoundStatement *) {} - void visit(ScopeStatement *) {} - void visit(ImportStatement *) {} - }; - - HasCode hc; - return walkPostorder(this, &hc); -} - -Statement *Statement::last() -{ - return this; -} - -/**************************************** - * If this statement has code that needs to run in a finally clause - * at the end of the current scope, return that code in the form of - * a Statement. - * Output: - * *sentry code executed upon entry to the scope - * *sexception code executed upon exit from the scope via exception - * *sfinally code executed in finally block - */ - -Statement *Statement::scopeCode(Scope *, Statement **sentry, Statement **sexception, Statement **sfinally) -{ - //printf("Statement::scopeCode()\n"); - //print(); - *sentry = NULL; - *sexception = NULL; - *sfinally = NULL; - return this; -} - -/********************************* - * Flatten out the scope by presenting the statement - * as an array of statements. - * Returns NULL if no flattening necessary. - */ - -Statements *Statement::flatten(Scope *) -{ - return NULL; -} - - -/******************************** ErrorStatement ***************************/ - -ErrorStatement::ErrorStatement() - : Statement(Loc()) -{ - assert(global.gaggedErrors || global.errors); -} - -Statement *ErrorStatement::syntaxCopy() -{ - return this; -} - -/******************************** PeelStatement ***************************/ - -PeelStatement::PeelStatement(Statement *s) - : Statement(s->loc) -{ - this->s = s; -} - -/******************************** ExpStatement ***************************/ - -ExpStatement::ExpStatement(Loc loc, Expression *exp) - : Statement(loc) -{ - this->exp = exp; -} - -ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration) - : Statement(loc) -{ - this->exp = new DeclarationExp(loc, declaration); -} - -ExpStatement *ExpStatement::create(Loc loc, Expression *exp) -{ - return new ExpStatement(loc, exp); -} - -Statement *ExpStatement::syntaxCopy() -{ - return new ExpStatement(loc, exp ? exp->syntaxCopy() : NULL); -} - -Statement *ExpStatement::scopeCode(Scope *, Statement **sentry, Statement **sexception, Statement **sfinally) -{ - //printf("ExpStatement::scopeCode()\n"); - //print(); - - *sentry = NULL; - *sexception = NULL; - *sfinally = NULL; - - if (exp) - { - if (exp->op == TOKdeclaration) - { - DeclarationExp *de = (DeclarationExp *)(exp); - VarDeclaration *v = de->declaration->isVarDeclaration(); - if (v && !v->isDataseg()) - { - if (v->needsScopeDtor()) - { - //printf("dtor is: "); v->edtor->print(); - *sfinally = new DtorExpStatement(loc, v->edtor, v); - v->storage_class |= STCnodtor; // don't add in dtor again - } - } - } - } - return this; -} - -/**************************************** - * Convert TemplateMixin members (== Dsymbols) to Statements. - */ -Statement *toStatement(Dsymbol *s) -{ - class ToStmt : public Visitor - { - public: - Statement *result; - - ToStmt() - { - this->result = NULL; - } - - Statement *visitMembers(Loc loc, Dsymbols *a) - { - if (!a) - return NULL; - - Statements *statements = new Statements(); - for (size_t i = 0; i < a->length; i++) - { - statements->push(toStatement((*a)[i])); - } - return new CompoundStatement(loc, statements); - } - - void visit(Dsymbol *s) - { - ::error(Loc(), "Internal Compiler Error: cannot mixin %s %s\n", s->kind(), s->toChars()); - result = new ErrorStatement(); - } - - void visit(TemplateMixin *tm) - { - Statements *a = new Statements(); - for (size_t i = 0; i < tm->members->length; i++) - { - Statement *s = toStatement((*tm->members)[i]); - if (s) - a->push(s); - } - result = new CompoundStatement(tm->loc, a); - } - - /* An actual declaration symbol will be converted to DeclarationExp - * with ExpStatement. - */ - Statement *declStmt(Dsymbol *s) - { - DeclarationExp *de = new DeclarationExp(s->loc, s); - de->type = Type::tvoid; // avoid repeated semantic - return new ExpStatement(s->loc, de); - } - void visit(VarDeclaration *d) { result = declStmt(d); } - void visit(AggregateDeclaration *d) { result = declStmt(d); } - void visit(FuncDeclaration *d) { result = declStmt(d); } - void visit(EnumDeclaration *d) { result = declStmt(d); } - void visit(AliasDeclaration *d) { result = declStmt(d); } - void visit(TemplateDeclaration *d) { result = declStmt(d); } - - /* All attributes have been already picked by the semantic analysis of - * 'bottom' declarations (function, struct, class, etc). - * So we don't have to copy them. - */ - void visit(StorageClassDeclaration *d) { result = visitMembers(d->loc, d->decl); } - void visit(DeprecatedDeclaration *d) { result = visitMembers(d->loc, d->decl); } - void visit(LinkDeclaration *d) { result = visitMembers(d->loc, d->decl); } - void visit(ProtDeclaration *d) { result = visitMembers(d->loc, d->decl); } - void visit(AlignDeclaration *d) { result = visitMembers(d->loc, d->decl); } - void visit(UserAttributeDeclaration *d) { result = visitMembers(d->loc, d->decl); } - void visit(ForwardingAttribDeclaration *d) { result = visitMembers(d->loc, d->decl); } - - void visit(StaticAssert *) {} - void visit(Import *) {} - void visit(PragmaDeclaration *) {} - - void visit(ConditionalDeclaration *d) - { - result = visitMembers(d->loc, d->include(NULL)); - } - - void visit(StaticForeachDeclaration *d) - { - assert(d->sfe && !!d->sfe->aggrfe ^ !!d->sfe->rangefe); - result = visitMembers(d->loc, d->include(NULL)); - } - - void visit(CompileDeclaration *d) - { - result = visitMembers(d->loc, d->include(NULL)); - } - }; - - if (!s) - return NULL; - - ToStmt v; - s->accept(&v); - return v.result; -} - -Statements *ExpStatement::flatten(Scope *sc) -{ - /* Bugzilla 14243: expand template mixin in statement scope - * to handle variable destructors. - */ - if (exp && exp->op == TOKdeclaration) - { - Dsymbol *d = ((DeclarationExp *)exp)->declaration; - if (TemplateMixin *tm = d->isTemplateMixin()) - { - Expression *e = expressionSemantic(exp, sc); - if (e->op == TOKerror || tm->errors) - { - Statements *a = new Statements(); - a->push(new ErrorStatement()); - return a; - } - assert(tm->members); - - Statement *s = toStatement(tm); - Statements *a = new Statements(); - a->push(s); - return a; - } - } - return NULL; -} - -/******************************** DtorExpStatement ***************************/ - -DtorExpStatement::DtorExpStatement(Loc loc, Expression *exp, VarDeclaration *v) - : ExpStatement(loc, exp) -{ - this->var = v; -} - -Statement *DtorExpStatement::syntaxCopy() -{ - return new DtorExpStatement(loc, exp ? exp->syntaxCopy() : NULL, var); -} - -/******************************** CompileStatement ***************************/ - -CompileStatement::CompileStatement(Loc loc, Expression *exp) - : Statement(loc) -{ - this->exps = new Expressions(); - this->exps->push(exp); -} - -CompileStatement::CompileStatement(Loc loc, Expressions *exps) - : Statement(loc) -{ - this->exps = exps; -} - -Statement *CompileStatement::syntaxCopy() -{ - return new CompileStatement(loc, Expression::arraySyntaxCopy(exps)); -} - -static Statements *errorStatements() -{ - Statements *a = new Statements(); - a->push(new ErrorStatement()); - return a; -} - -static Statements *compileIt(CompileStatement *cs, Scope *sc) -{ - //printf("CompileStatement::compileIt() %s\n", exp->toChars()); - OutBuffer buf; - if (expressionsToString(buf, sc, cs->exps)) - return errorStatements(); - - unsigned errors = global.errors; - const size_t len = buf.length(); - const char *str = buf.extractChars(); - Parser p(cs->loc, sc->_module, (const utf8_t *)str, len, false); - p.nextToken(); - - Statements *a = new Statements(); - while (p.token.value != TOKeof) - { - Statement *s = p.parseStatement(PSsemi | PScurlyscope); - if (!s || global.errors != errors) - return errorStatements(); - a->push(s); - } - return a; -} - -Statements *CompileStatement::flatten(Scope *sc) -{ - //printf("CompileStatement::flatten() %s\n", exp->toChars()); - return compileIt(this, sc); -} - -/******************************** CompoundStatement ***************************/ - -CompoundStatement::CompoundStatement(Loc loc, Statements *s) - : Statement(loc) -{ - statements = s; -} - -CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2) - : Statement(loc) -{ - statements = new Statements(); - statements->reserve(2); - statements->push(s1); - statements->push(s2); -} - -CompoundStatement::CompoundStatement(Loc loc, Statement *s1) - : Statement(loc) -{ - statements = new Statements(); - statements->push(s1); -} - -CompoundStatement *CompoundStatement::create(Loc loc, Statement *s1, Statement *s2) -{ - return new CompoundStatement(loc, s1, s2); -} - -Statement *CompoundStatement::syntaxCopy() -{ - return new CompoundStatement(loc, Statement::arraySyntaxCopy(statements)); -} - -Statements *CompoundStatement::flatten(Scope *) -{ - return statements; -} - -ReturnStatement *CompoundStatement::isReturnStatement() -{ - ReturnStatement *rs = NULL; - - for (size_t i = 0; i < statements->length; i++) - { - Statement *s = (*statements)[i]; - if (s) - { - rs = s->isReturnStatement(); - if (rs) - break; - } - } - return rs; -} - -Statement *CompoundStatement::last() -{ - Statement *s = NULL; - - for (size_t i = statements->length; i; --i) - { s = (*statements)[i - 1]; - if (s) - { - s = s->last(); - if (s) - break; - } - } - return s; -} - -/******************************** CompoundDeclarationStatement ***************************/ - -CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s) - : CompoundStatement(loc, s) -{ - statements = s; -} - -Statement *CompoundDeclarationStatement::syntaxCopy() -{ - Statements *a = new Statements(); - a->setDim(statements->length); - for (size_t i = 0; i < statements->length; i++) - { - Statement *s = (*statements)[i]; - (*a)[i] = s ? s->syntaxCopy() : NULL; - } - return new CompoundDeclarationStatement(loc, a); -} - -/**************************** UnrolledLoopStatement ***************************/ - -UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s) - : Statement(loc) -{ - statements = s; -} - -Statement *UnrolledLoopStatement::syntaxCopy() -{ - Statements *a = new Statements(); - a->setDim(statements->length); - for (size_t i = 0; i < statements->length; i++) - { - Statement *s = (*statements)[i]; - (*a)[i] = s ? s->syntaxCopy() : NULL; - } - return new UnrolledLoopStatement(loc, a); -} - -bool UnrolledLoopStatement::hasBreak() -{ - return true; -} - -bool UnrolledLoopStatement::hasContinue() -{ - return true; -} - -/******************************** ScopeStatement ***************************/ - -ScopeStatement::ScopeStatement(Loc loc, Statement *s, Loc endloc) - : Statement(loc) -{ - this->statement = s; - this->endloc = endloc; -} - -Statement *ScopeStatement::syntaxCopy() -{ - return new ScopeStatement(loc, statement ? statement->syntaxCopy() : NULL, endloc); -} - -ReturnStatement *ScopeStatement::isReturnStatement() -{ - if (statement) - return statement->isReturnStatement(); - return NULL; -} - -bool ScopeStatement::hasBreak() -{ - //printf("ScopeStatement::hasBreak() %s\n", toChars()); - return statement ? statement->hasBreak() : false; -} - -bool ScopeStatement::hasContinue() -{ - return statement ? statement->hasContinue() : false; -} - -/******************************** ForwardingStatement **********************/ - -/* Statement whose symbol table contains foreach index variables in a - * local scope and forwards other members to the parent scope. This - * wraps a statement. - * - * Also see: `ddmd.attrib.ForwardingAttribDeclaration` - */ - -ForwardingStatement::ForwardingStatement(Loc loc, ForwardingScopeDsymbol *sym, Statement *s) - : Statement(loc) -{ - this->sym = sym; - assert(s); - this->statement = s; -} - -ForwardingStatement::ForwardingStatement(Loc loc, Statement *s) - : Statement(loc) -{ - this->sym = new ForwardingScopeDsymbol(NULL); - this->sym->symtab = new DsymbolTable(); - assert(s); - this->statement = s; -} - -Statement *ForwardingStatement::syntaxCopy() -{ - return new ForwardingStatement(loc, statement->syntaxCopy()); -} - -/*********************** - * ForwardingStatements are distributed over the flattened - * sequence of statements. This prevents flattening to be - * "blocked" by a ForwardingStatement and is necessary, for - * example, to support generating scope guards with `static - * foreach`: - * - * static foreach(i; 0 .. 10) scope(exit) writeln(i); - * writeln("this is printed first"); - * // then, it prints 10, 9, 8, 7, ... - */ - -Statements *ForwardingStatement::flatten(Scope *sc) -{ - if (!statement) - { - return NULL; - } - sc = sc->push(sym); - Statements *a = statement->flatten(sc); - sc = sc->pop(); - if (!a) - { - return a; - } - Statements *b = new Statements(); - b->setDim(a->length); - for (size_t i = 0; i < a->length; i++) - { - Statement *s = (*a)[i]; - (*b)[i] = s ? new ForwardingStatement(s->loc, sym, s) : NULL; - } - return b; -} - -/******************************** WhileStatement ***************************/ - -WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b, Loc endloc) - : Statement(loc) -{ - condition = c; - _body = b; - this->endloc = endloc; -} - -Statement *WhileStatement::syntaxCopy() -{ - return new WhileStatement(loc, - condition->syntaxCopy(), - _body ? _body->syntaxCopy() : NULL, - endloc); -} - -bool WhileStatement::hasBreak() -{ - return true; -} - -bool WhileStatement::hasContinue() -{ - return true; -} - -/******************************** DoStatement ***************************/ - -DoStatement::DoStatement(Loc loc, Statement *b, Expression *c, Loc endloc) - : Statement(loc) -{ - _body = b; - condition = c; - this->endloc = endloc; -} - -Statement *DoStatement::syntaxCopy() -{ - return new DoStatement(loc, - _body ? _body->syntaxCopy() : NULL, - condition->syntaxCopy(), - endloc); -} - -bool DoStatement::hasBreak() -{ - return true; -} - -bool DoStatement::hasContinue() -{ - return true; -} - -/******************************** ForStatement ***************************/ - -ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body, Loc endloc) - : Statement(loc) -{ - this->_init = init; - this->condition = condition; - this->increment = increment; - this->_body = body; - this->endloc = endloc; - this->relatedLabeled = NULL; -} - -Statement *ForStatement::syntaxCopy() -{ - return new ForStatement(loc, - _init ? _init->syntaxCopy() : NULL, - condition ? condition->syntaxCopy() : NULL, - increment ? increment->syntaxCopy() : NULL, - _body->syntaxCopy(), - endloc); -} - -Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) -{ - //printf("ForStatement::scopeCode()\n"); - Statement::scopeCode(sc, sentry, sexception, sfinally); - return this; -} - -bool ForStatement::hasBreak() -{ - //printf("ForStatement::hasBreak()\n"); - return true; -} - -bool ForStatement::hasContinue() -{ - return true; -} - -/******************************** ForeachStatement ***************************/ - -ForeachStatement::ForeachStatement(Loc loc, TOK op, Parameters *parameters, - Expression *aggr, Statement *body, Loc endloc) - : Statement(loc) -{ - this->op = op; - this->parameters = parameters; - this->aggr = aggr; - this->_body = body; - this->endloc = endloc; - - this->key = NULL; - this->value = NULL; - - this->func = NULL; - - this->cases = NULL; - this->gotos = NULL; -} - -Statement *ForeachStatement::syntaxCopy() -{ - return new ForeachStatement(loc, op, - Parameter::arraySyntaxCopy(parameters), - aggr->syntaxCopy(), - _body ? _body->syntaxCopy() : NULL, - endloc); -} - -bool ForeachStatement::checkForArgTypes() -{ - bool result = false; - - for (size_t i = 0; i < parameters->length; i++) - { - Parameter *p = (*parameters)[i]; - if (!p->type) - { - error("cannot infer type for %s", p->ident->toChars()); - p->type = Type::terror; - result = true; - } - } - return result; -} - -bool ForeachStatement::hasBreak() -{ - return true; -} - -bool ForeachStatement::hasContinue() -{ - return true; -} - -/**************************** ForeachRangeStatement ***************************/ - - -ForeachRangeStatement::ForeachRangeStatement(Loc loc, TOK op, Parameter *prm, - Expression *lwr, Expression *upr, Statement *body, Loc endloc) - : Statement(loc) -{ - this->op = op; - this->prm = prm; - this->lwr = lwr; - this->upr = upr; - this->_body = body; - this->endloc = endloc; - - this->key = NULL; -} - -Statement *ForeachRangeStatement::syntaxCopy() -{ - return new ForeachRangeStatement(loc, op, - prm->syntaxCopy(), - lwr->syntaxCopy(), - upr->syntaxCopy(), - _body ? _body->syntaxCopy() : NULL, - endloc); -} - -bool ForeachRangeStatement::hasBreak() -{ - return true; -} - -bool ForeachRangeStatement::hasContinue() -{ - return true; -} - -/******************************** IfStatement ***************************/ - -IfStatement::IfStatement(Loc loc, Parameter *prm, Expression *condition, Statement *ifbody, Statement *elsebody, Loc endloc) - : Statement(loc) -{ - this->prm = prm; - this->condition = condition; - this->ifbody = ifbody; - this->elsebody = elsebody; - this->endloc = endloc; - this->match = NULL; -} - -Statement *IfStatement::syntaxCopy() -{ - return new IfStatement(loc, - prm ? prm->syntaxCopy() : NULL, - condition->syntaxCopy(), - ifbody ? ifbody->syntaxCopy() : NULL, - elsebody ? elsebody->syntaxCopy() : NULL, - endloc); -} - -/******************************** ConditionalStatement ***************************/ - -ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody) - : Statement(loc) -{ - this->condition = condition; - this->ifbody = ifbody; - this->elsebody = elsebody; -} - -Statement *ConditionalStatement::syntaxCopy() -{ - return new ConditionalStatement(loc, - condition->syntaxCopy(), - ifbody->syntaxCopy(), - elsebody ? elsebody->syntaxCopy() : NULL); -} - -Statements *ConditionalStatement::flatten(Scope *sc) -{ - Statement *s; - - //printf("ConditionalStatement::flatten()\n"); - if (condition->include(sc)) - { - DebugCondition *dc = condition->isDebugCondition(); - if (dc) - s = new DebugStatement(loc, ifbody); - else - s = ifbody; - } - else - s = elsebody; - - Statements *a = new Statements(); - a->push(s); - return a; -} - -/******************************** StaticForeachStatement ********************/ - -/* Static foreach statements, like: - * void main() - * { - * static foreach(i; 0 .. 10) - * { - * pragma(msg, i); - * } - * } - */ - -StaticForeachStatement::StaticForeachStatement(Loc loc, StaticForeach *sfe) - : Statement(loc) -{ - this->sfe = sfe; -} - -Statement *StaticForeachStatement::syntaxCopy() -{ - return new StaticForeachStatement(loc, sfe->syntaxCopy()); -} - -Statements *StaticForeachStatement::flatten(Scope *sc) -{ - staticForeachPrepare(sfe, sc); - if (staticForeachReady(sfe)) - { - Statement *s = makeTupleForeachStatic(sc, sfe->aggrfe, sfe->needExpansion); - Statements *result = s->flatten(sc); - if (result) - { - return result; - } - result = new Statements(); - result->push(s); - return result; - } - else - { - Statements *result = new Statements(); - result->push(new ErrorStatement()); - return result; - } -} - -/******************************** PragmaStatement ***************************/ - -PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body) - : Statement(loc) -{ - this->ident = ident; - this->args = args; - this->_body = body; -} - -Statement *PragmaStatement::syntaxCopy() -{ - return new PragmaStatement(loc, ident, - Expression::arraySyntaxCopy(args), - _body ? _body->syntaxCopy() : NULL); -} - -/******************************** StaticAssertStatement ***************************/ - -StaticAssertStatement::StaticAssertStatement(StaticAssert *sa) - : Statement(sa->loc) -{ - this->sa = sa; -} - -Statement *StaticAssertStatement::syntaxCopy() -{ - return new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL)); -} - -/******************************** SwitchStatement ***************************/ - -SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal) - : Statement(loc) -{ - this->condition = c; - this->_body = b; - this->isFinal = isFinal; - sdefault = NULL; - tf = NULL; - cases = NULL; - hasNoDefault = 0; - hasVars = 0; - lastVar = NULL; -} - -Statement *SwitchStatement::syntaxCopy() -{ - return new SwitchStatement(loc, - condition->syntaxCopy(), - _body->syntaxCopy(), - isFinal); -} - -bool SwitchStatement::hasBreak() -{ - return true; -} - -static bool checkVar(SwitchStatement *s, VarDeclaration *vd) -{ - if (!vd || vd->isDataseg() || (vd->storage_class & STCmanifest)) - return false; - - VarDeclaration *last = s->lastVar; - while (last && last != vd) - last = last->lastVar; - if (last == vd) - { - // All good, the label's scope has no variables - } - else if (vd->storage_class & STCexptemp) - { - // Lifetime ends at end of expression, so no issue with skipping the statement - } - else if (vd->ident == Id::withSym) - { - s->deprecation("`switch` skips declaration of `with` temporary at %s", vd->loc.toChars()); - return true; - } - else - { - s->deprecation("`switch` skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars()); - return true; - } - - return false; -} - -bool SwitchStatement::checkLabel() -{ - const bool error = true; - - if (sdefault && checkVar(this, sdefault->lastVar)) - return !error; // return error once fully deprecated - - for (size_t i = 0; i < cases->length; i++) - { - CaseStatement *scase = (*cases)[i]; - if (scase && checkVar(this, scase->lastVar)) - return !error; // return error once fully deprecated - } - return !error; -} - -/******************************** CaseStatement ***************************/ - -CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s) - : Statement(loc) -{ - this->exp = exp; - this->statement = s; - index = 0; - lastVar = NULL; -} - -Statement *CaseStatement::syntaxCopy() -{ - return new CaseStatement(loc, - exp->syntaxCopy(), - statement->syntaxCopy()); -} - -int CaseStatement::compare(RootObject *obj) -{ - // Sort cases so we can do an efficient lookup - CaseStatement *cs2 = (CaseStatement *)(obj); - - return exp->compare(cs2->exp); -} - -/******************************** CaseRangeStatement ***************************/ - - -CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first, - Expression *last, Statement *s) - : Statement(loc) -{ - this->first = first; - this->last = last; - this->statement = s; -} - -Statement *CaseRangeStatement::syntaxCopy() -{ - return new CaseRangeStatement(loc, - first->syntaxCopy(), - last->syntaxCopy(), - statement->syntaxCopy()); -} - -/******************************** DefaultStatement ***************************/ - -DefaultStatement::DefaultStatement(Loc loc, Statement *s) - : Statement(loc) -{ - this->statement = s; - this->lastVar = NULL; -} - -Statement *DefaultStatement::syntaxCopy() -{ - return new DefaultStatement(loc, statement->syntaxCopy()); -} - -/******************************** GotoDefaultStatement ***************************/ - -GotoDefaultStatement::GotoDefaultStatement(Loc loc) - : Statement(loc) -{ - sw = NULL; -} - -Statement *GotoDefaultStatement::syntaxCopy() -{ - return new GotoDefaultStatement(loc); -} - -/******************************** GotoCaseStatement ***************************/ - -GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp) - : Statement(loc) -{ - cs = NULL; - this->exp = exp; -} - -Statement *GotoCaseStatement::syntaxCopy() -{ - return new GotoCaseStatement(loc, exp ? exp->syntaxCopy() : NULL); -} - -/******************************** SwitchErrorStatement ***************************/ - -SwitchErrorStatement::SwitchErrorStatement(Loc loc) - : Statement(loc) -{ -} - -/******************************** ReturnStatement ***************************/ - -ReturnStatement::ReturnStatement(Loc loc, Expression *exp) - : Statement(loc) -{ - this->exp = exp; - this->caseDim = 0; -} - -Statement *ReturnStatement::syntaxCopy() -{ - return new ReturnStatement(loc, exp ? exp->syntaxCopy() : NULL); -} - -/******************************** BreakStatement ***************************/ - -BreakStatement::BreakStatement(Loc loc, Identifier *ident) - : Statement(loc) -{ - this->ident = ident; -} - -Statement *BreakStatement::syntaxCopy() -{ - return new BreakStatement(loc, ident); -} - -/******************************** ContinueStatement ***************************/ - -ContinueStatement::ContinueStatement(Loc loc, Identifier *ident) - : Statement(loc) -{ - this->ident = ident; -} - -Statement *ContinueStatement::syntaxCopy() -{ - return new ContinueStatement(loc, ident); -} - -/******************************** SynchronizedStatement ***************************/ - -SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body) - : Statement(loc) -{ - this->exp = exp; - this->_body = body; -} - -Statement *SynchronizedStatement::syntaxCopy() -{ - return new SynchronizedStatement(loc, - exp ? exp->syntaxCopy() : NULL, - _body ? _body->syntaxCopy() : NULL); -} - -bool SynchronizedStatement::hasBreak() -{ - return false; //true; -} - -bool SynchronizedStatement::hasContinue() -{ - return false; //true; -} - -/******************************** WithStatement ***************************/ - -WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body, Loc endloc) - : Statement(loc) -{ - this->exp = exp; - this->_body = body; - this->endloc = endloc; - wthis = NULL; -} - -Statement *WithStatement::syntaxCopy() -{ - return new WithStatement(loc, - exp->syntaxCopy(), - _body ? _body->syntaxCopy() : NULL, endloc); -} - -/******************************** TryCatchStatement ***************************/ - -TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches) - : Statement(loc) -{ - this->_body = body; - this->catches = catches; -} - -Statement *TryCatchStatement::syntaxCopy() -{ - Catches *a = new Catches(); - a->setDim(catches->length); - for (size_t i = 0; i < a->length; i++) - { - Catch *c = (*catches)[i]; - (*a)[i] = c->syntaxCopy(); - } - return new TryCatchStatement(loc, _body->syntaxCopy(), a); -} - -bool TryCatchStatement::hasBreak() -{ - return false; -} - -/******************************** Catch ***************************/ - -Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler) -{ - //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars()); - this->loc = loc; - this->type = t; - this->ident = id; - this->handler = handler; - var = NULL; - errors = false; - internalCatch = false; -} - -Catch *Catch::syntaxCopy() -{ - Catch *c = new Catch(loc, - type ? type->syntaxCopy() : getThrowable(), - ident, - (handler ? handler->syntaxCopy() : NULL)); - c->internalCatch = internalCatch; - return c; -} - -/****************************** TryFinallyStatement ***************************/ - -TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody) - : Statement(loc) -{ - this->_body = body; - this->finalbody = finalbody; -} - -TryFinallyStatement *TryFinallyStatement::create(Loc loc, Statement *body, Statement *finalbody) -{ - return new TryFinallyStatement(loc, body, finalbody); -} - -Statement *TryFinallyStatement::syntaxCopy() -{ - return new TryFinallyStatement(loc, - _body->syntaxCopy(), finalbody->syntaxCopy()); -} - -bool TryFinallyStatement::hasBreak() -{ - return false; //true; -} - -bool TryFinallyStatement::hasContinue() -{ - return false; //true; -} - -/****************************** ScopeGuardStatement ***************************/ - -ScopeGuardStatement::ScopeGuardStatement(Loc loc, TOK tok, Statement *statement) - : Statement(loc) -{ - this->tok = tok; - this->statement = statement; -} - -Statement *ScopeGuardStatement::syntaxCopy() -{ - return new ScopeGuardStatement(loc, tok, statement->syntaxCopy()); -} - -Statement *ScopeGuardStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) -{ - //printf("ScopeGuardStatement::scopeCode()\n"); - //print(); - *sentry = NULL; - *sexception = NULL; - *sfinally = NULL; - - Statement *s = new PeelStatement(statement); - - switch (tok) - { - case TOKon_scope_exit: - *sfinally = s; - break; - - case TOKon_scope_failure: - *sexception = s; - break; - - case TOKon_scope_success: - { - /* Create: - * sentry: bool x = false; - * sexception: x = true; - * sfinally: if (!x) statement; - */ - VarDeclaration *v = copyToTemp(0, "__os", new IntegerExp(Loc(), 0, Type::tbool)); - dsymbolSemantic(v, sc); - *sentry = new ExpStatement(loc, v); - - Expression *e = new IntegerExp(Loc(), 1, Type::tbool); - e = new AssignExp(Loc(), new VarExp(Loc(), v), e); - *sexception = new ExpStatement(Loc(), e); - - e = new VarExp(Loc(), v); - e = new NotExp(Loc(), e); - *sfinally = new IfStatement(Loc(), NULL, e, s, NULL, Loc()); - - break; - } - - default: - assert(0); - } - return NULL; -} - -/******************************** ThrowStatement ***************************/ - -ThrowStatement::ThrowStatement(Loc loc, Expression *exp) - : Statement(loc) -{ - this->exp = exp; - this->internalThrow = false; -} - -Statement *ThrowStatement::syntaxCopy() -{ - ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy()); - s->internalThrow = internalThrow; - return s; -} - -/******************************** DebugStatement **************************/ - -DebugStatement::DebugStatement(Loc loc, Statement *statement) - : Statement(loc) -{ - this->statement = statement; -} - -Statement *DebugStatement::syntaxCopy() -{ - return new DebugStatement(loc, - statement ? statement->syntaxCopy() : NULL); -} - -Statements *DebugStatement::flatten(Scope *sc) -{ - Statements *a = statement ? statement->flatten(sc) : NULL; - if (a) - { - for (size_t i = 0; i < a->length; i++) - { Statement *s = (*a)[i]; - - s = new DebugStatement(loc, s); - (*a)[i] = s; - } - } - - return a; -} - -/******************************** GotoStatement ***************************/ - -GotoStatement::GotoStatement(Loc loc, Identifier *ident) - : Statement(loc) -{ - this->ident = ident; - this->label = NULL; - this->tf = NULL; - this->os = NULL; - this->lastVar = NULL; -} - -Statement *GotoStatement::syntaxCopy() -{ - return new GotoStatement(loc, ident); -} - -bool GotoStatement::checkLabel() -{ - if (!label->statement) - { - error("label `%s` is undefined", label->toChars()); - return true; - } - - if (label->statement->os != os) - { - if (os && os->tok == TOKon_scope_failure && !label->statement->os) - { - // Jump out from scope(failure) block is allowed. - } - else - { - if (label->statement->os) - error("cannot goto in to %s block", Token::toChars(label->statement->os->tok)); - else - error("cannot goto out of %s block", Token::toChars(os->tok)); - return true; - } - } - - if (label->statement->tf != tf) - { - error("cannot goto in or out of finally block"); - return true; - } - - VarDeclaration *vd = label->statement->lastVar; - if (!vd || vd->isDataseg() || (vd->storage_class & STCmanifest)) - return false; - - VarDeclaration *last = lastVar; - while (last && last != vd) - last = last->lastVar; - if (last == vd) - { - // All good, the label's scope has no variables - } - else if (vd->ident == Id::withSym) - { - error("goto skips declaration of with temporary at %s", vd->loc.toChars()); - return true; - } - else - { - error("goto skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars()); - return true; - } - - return false; -} - -/******************************** LabelStatement ***************************/ - -LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) - : Statement(loc) -{ - this->ident = ident; - this->statement = statement; - this->tf = NULL; - this->os = NULL; - this->lastVar = NULL; - this->gotoTarget = NULL; - this->breaks = false; -} - -Statement *LabelStatement::syntaxCopy() -{ - return new LabelStatement(loc, ident, statement ? statement->syntaxCopy() : NULL); -} - -Statement *LabelStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally) -{ - //printf("LabelStatement::scopeCode()\n"); - if (statement) - statement = statement->scopeCode(sc, sentry, sexit, sfinally); - else - { - *sentry = NULL; - *sexit = NULL; - *sfinally = NULL; - } - return this; -} - -Statements *LabelStatement::flatten(Scope *sc) -{ - Statements *a = NULL; - - if (statement) - { - a = statement->flatten(sc); - if (a) - { - if (!a->length) - { - a->push(new ExpStatement(loc, (Expression *)NULL)); - } - - // reuse 'this' LabelStatement - this->statement = (*a)[0]; - (*a)[0] = this; - } - } - - return a; -} - -/******************************** LabelDsymbol ***************************/ - -LabelDsymbol::LabelDsymbol(Identifier *ident) - : Dsymbol(ident) -{ - statement = NULL; -} - -LabelDsymbol *LabelDsymbol::create(Identifier *ident) -{ - return new LabelDsymbol(ident); -} - -LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? -{ - return this; -} - - -/************************ AsmStatement ***************************************/ - -AsmStatement::AsmStatement(Loc loc, Token *tokens) - : Statement(loc) -{ - this->tokens = tokens; -} - -Statement *AsmStatement::syntaxCopy() -{ - return new AsmStatement(loc, tokens); -} - - -/************************ InlineAsmStatement **********************************/ - -InlineAsmStatement::InlineAsmStatement(Loc loc, Token *tokens) - : AsmStatement(loc, tokens) -{ - asmcode = NULL; - asmalign = 0; - refparam = false; - naked = false; - regs = 0; -} - -Statement *InlineAsmStatement::syntaxCopy() -{ - return new InlineAsmStatement(loc, tokens); -} - - -/************************ GccAsmStatement ***************************************/ - -GccAsmStatement::GccAsmStatement(Loc loc, Token *tokens) - : AsmStatement(loc, tokens) -{ - this->stc = STCundefined; - this->insn = NULL; - this->args = NULL; - this->outputargs = 0; - this->names = NULL; - this->constraints = NULL; - this->clobbers = NULL; - this->labels = NULL; - this->gotos = NULL; -} - -Statement *GccAsmStatement::syntaxCopy() -{ - return new GccAsmStatement(loc, tokens); -} - -/************************ CompoundAsmStatement ***************************************/ - -CompoundAsmStatement::CompoundAsmStatement(Loc loc, Statements *s, StorageClass stc) - : CompoundStatement(loc, s) -{ - this->stc = stc; -} - -CompoundAsmStatement *CompoundAsmStatement::syntaxCopy() -{ - Statements *a = new Statements(); - a->setDim(statements->length); - for (size_t i = 0; i < statements->length; i++) - { - Statement *s = (*statements)[i]; - (*a)[i] = s ? s->syntaxCopy() : NULL; - } - return new CompoundAsmStatement(loc, a, stc); -} - -Statements *CompoundAsmStatement::flatten(Scope *) -{ - return NULL; -} - -/************************ ImportStatement ***************************************/ - -ImportStatement::ImportStatement(Loc loc, Dsymbols *imports) - : Statement(loc) -{ - this->imports = imports; -} - -Statement *ImportStatement::syntaxCopy() -{ - Dsymbols *m = new Dsymbols(); - m->setDim(imports->length); - for (size_t i = 0; i < imports->length; i++) - { - Dsymbol *s = (*imports)[i]; - (*m)[i] = s->syntaxCopy(NULL); - } - return new ImportStatement(loc, m); -} |