PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/d/dmd/statement.c

https://bitbucket.org/goshawk/gdc/
C | 4560 lines | 3578 code | 633 blank | 349 comment | 668 complexity | 8cffde6f3962fa6c60ceb278ef036e82 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. // Compiler implementation of the D programming language
  2. // Copyright (c) 1999-2011 by Digital Mars
  3. // All Rights Reserved
  4. // written by Walter Bright
  5. // http://www.digitalmars.com
  6. // License for redistribution is by either the Artistic License
  7. // in artistic.txt, or the GNU General Public License in gnu.txt.
  8. // See the included readme.txt for details.
  9. /* NOTE: This file has been patched from the original DMD distribution to
  10. work with the GDC compiler.
  11. Modified by Michael Parrott, September 2009
  12. Using David Friedman's code
  13. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <assert.h>
  17. #include "rmem.h"
  18. #include "statement.h"
  19. #include "expression.h"
  20. #include "cond.h"
  21. #include "init.h"
  22. #include "staticassert.h"
  23. #include "mtype.h"
  24. #include "scope.h"
  25. #include "declaration.h"
  26. #include "aggregate.h"
  27. #include "id.h"
  28. #include "hdrgen.h"
  29. #include "parse.h"
  30. #include "template.h"
  31. #include "attrib.h"
  32. #if _WIN32
  33. #include <windows.h>
  34. #define CRITSECSIZE sizeof(CRITICAL_SECTION)
  35. #elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
  36. #include <pthread.h>
  37. #define CRITSECSIZE sizeof(pthread_mutex_t)
  38. #else
  39. #define CRITSECSIZE 64
  40. #endif
  41. /******************************** Statement ***************************/
  42. Statement::Statement(Loc loc)
  43. : loc(loc)
  44. {
  45. // If this is an in{} contract scope statement (skip for determining
  46. // inlineStatus of a function body for header content)
  47. incontract = 0;
  48. }
  49. Statement *Statement::syntaxCopy()
  50. {
  51. assert(0);
  52. return NULL;
  53. }
  54. void Statement::print()
  55. {
  56. fprintf(stdmsg, "%s\n", toChars());
  57. fflush(stdmsg);
  58. }
  59. char *Statement::toChars()
  60. { OutBuffer *buf;
  61. HdrGenState hgs;
  62. buf = new OutBuffer();
  63. toCBuffer(buf, &hgs);
  64. return buf->toChars();
  65. }
  66. void Statement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  67. {
  68. buf->printf("Statement::toCBuffer()");
  69. buf->writenl();
  70. }
  71. Statement *Statement::semantic(Scope *sc)
  72. {
  73. return this;
  74. }
  75. Statement *Statement::semanticNoScope(Scope *sc)
  76. {
  77. //printf("Statement::semanticNoScope() %s\n", toChars());
  78. Statement *s = this;
  79. if (!s->isCompoundStatement() && !s->isScopeStatement())
  80. {
  81. s = new CompoundStatement(loc, this); // so scopeCode() gets called
  82. }
  83. s = s->semantic(sc);
  84. return s;
  85. }
  86. // Same as semanticNoScope(), but do create a new scope
  87. Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue)
  88. {
  89. Scope *scd = sc->push();
  90. if (sbreak)
  91. scd->sbreak = sbreak;
  92. if (scontinue)
  93. scd->scontinue = scontinue;
  94. Statement *s = semanticNoScope(scd);
  95. scd->pop();
  96. return s;
  97. }
  98. void Statement::error(const char *format, ...)
  99. {
  100. va_list ap;
  101. va_start(ap, format);
  102. ::verror(loc, format, ap);
  103. va_end( ap );
  104. }
  105. void Statement::warning(const char *format, ...)
  106. {
  107. va_list ap;
  108. va_start(ap, format);
  109. ::vwarning(loc, format, ap);
  110. va_end( ap );
  111. }
  112. int Statement::hasBreak()
  113. {
  114. //printf("Statement::hasBreak()\n");
  115. return FALSE;
  116. }
  117. int Statement::hasContinue()
  118. {
  119. return FALSE;
  120. }
  121. // TRUE if statement uses exception handling
  122. int Statement::usesEH()
  123. {
  124. return FALSE;
  125. }
  126. /* Only valid after semantic analysis
  127. */
  128. int Statement::blockExit(bool mustNotThrow)
  129. {
  130. printf("Statement::blockExit(%p)\n", this);
  131. printf("%s\n", toChars());
  132. assert(0);
  133. return BEany;
  134. }
  135. // TRUE if statement 'comes from' somewhere else, like a goto
  136. int Statement::comeFrom()
  137. {
  138. //printf("Statement::comeFrom()\n");
  139. return FALSE;
  140. }
  141. // Return TRUE if statement has no code in it
  142. int Statement::isEmpty()
  143. {
  144. //printf("Statement::isEmpty()\n");
  145. return FALSE;
  146. }
  147. /****************************************
  148. * If this statement has code that needs to run in a finally clause
  149. * at the end of the current scope, return that code in the form of
  150. * a Statement.
  151. * Output:
  152. * *sentry code executed upon entry to the scope
  153. * *sexception code executed upon exit from the scope via exception
  154. * *sfinally code executed in finally block
  155. */
  156. void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
  157. {
  158. //printf("Statement::scopeCode()\n");
  159. //print();
  160. *sentry = NULL;
  161. *sexception = NULL;
  162. *sfinally = NULL;
  163. }
  164. /*********************************
  165. * Flatten out the scope by presenting the statement
  166. * as an array of statements.
  167. * Returns NULL if no flattening necessary.
  168. */
  169. Statements *Statement::flatten(Scope *sc)
  170. {
  171. return NULL;
  172. }
  173. /******************************** PeelStatement ***************************/
  174. PeelStatement::PeelStatement(Statement *s)
  175. : Statement(s->loc)
  176. {
  177. this->s = s;
  178. }
  179. Statement *PeelStatement::semantic(Scope *sc)
  180. {
  181. /* "peel" off this wrapper, and don't run semantic()
  182. * on the result.
  183. */
  184. return s;
  185. }
  186. /******************************** ExpStatement ***************************/
  187. ExpStatement::ExpStatement(Loc loc, Expression *exp)
  188. : Statement(loc)
  189. {
  190. this->exp = exp;
  191. }
  192. ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration)
  193. : Statement(loc)
  194. {
  195. this->exp = new DeclarationExp(loc, declaration);
  196. }
  197. Statement *ExpStatement::syntaxCopy()
  198. {
  199. Expression *e = exp ? exp->syntaxCopy() : NULL;
  200. ExpStatement *es = new ExpStatement(loc, e);
  201. return es;
  202. }
  203. void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  204. {
  205. if (exp)
  206. { exp->toCBuffer(buf, hgs);
  207. if (exp->op != TOKdeclaration)
  208. { buf->writeByte(';');
  209. if (!hgs->FLinit.init)
  210. buf->writenl();
  211. }
  212. }
  213. else
  214. {
  215. buf->writeByte(';');
  216. if (!hgs->FLinit.init)
  217. buf->writenl();
  218. }
  219. }
  220. Statement *ExpStatement::semantic(Scope *sc)
  221. {
  222. if (exp)
  223. {
  224. //printf("ExpStatement::semantic() %s\n", exp->toChars());
  225. exp = exp->semantic(sc);
  226. exp = resolveProperties(sc, exp);
  227. exp->checkSideEffect(0);
  228. exp = exp->optimize(0);
  229. }
  230. return this;
  231. }
  232. int ExpStatement::blockExit(bool mustNotThrow)
  233. { int result = BEfallthru;
  234. if (exp)
  235. {
  236. if (exp->op == TOKhalt)
  237. return BEhalt;
  238. if (exp->op == TOKassert)
  239. { AssertExp *a = (AssertExp *)exp;
  240. if (a->e1->isBool(FALSE)) // if it's an assert(0)
  241. return BEhalt;
  242. }
  243. if (exp->canThrow())
  244. result |= BEthrow;
  245. }
  246. return result;
  247. }
  248. int ExpStatement::isEmpty()
  249. {
  250. return exp == NULL;
  251. }
  252. void ExpStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
  253. {
  254. //printf("ExpStatement::scopeCode()\n");
  255. //print();
  256. *sentry = NULL;
  257. *sexception = NULL;
  258. *sfinally = NULL;
  259. if (exp)
  260. {
  261. if (exp->op == TOKdeclaration)
  262. {
  263. DeclarationExp *de = (DeclarationExp *)(exp);
  264. VarDeclaration *v = de->declaration->isVarDeclaration();
  265. if (v)
  266. { Expression *e;
  267. e = v->callScopeDtor(sc);
  268. if (e)
  269. {
  270. //printf("dtor is: "); e->print();
  271. #if 0
  272. if (v->type->toBasetype()->ty == Tstruct)
  273. { /* Need a 'gate' to turn on/off destruction,
  274. * in case v gets moved elsewhere.
  275. */
  276. Identifier *id = Lexer::uniqueId("__runDtor");
  277. ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1));
  278. VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie);
  279. *sentry = new ExpStatement(loc, rd);
  280. v->rundtor = rd;
  281. /* Rewrite e as:
  282. * rundtor && e
  283. */
  284. Expression *ve = new VarExp(loc, v->rundtor);
  285. e = new AndAndExp(loc, ve, e);
  286. e->type = Type::tbool;
  287. }
  288. #endif
  289. *sfinally = new ExpStatement(loc, e);
  290. }
  291. }
  292. }
  293. }
  294. }
  295. /******************************** CompileStatement ***************************/
  296. CompileStatement::CompileStatement(Loc loc, Expression *exp)
  297. : Statement(loc)
  298. {
  299. this->exp = exp;
  300. }
  301. Statement *CompileStatement::syntaxCopy()
  302. {
  303. Expression *e = exp->syntaxCopy();
  304. CompileStatement *es = new CompileStatement(loc, e);
  305. return es;
  306. }
  307. void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  308. {
  309. buf->writestring("mixin(");
  310. exp->toCBuffer(buf, hgs);
  311. buf->writestring(");");
  312. if (!hgs->FLinit.init)
  313. buf->writenl();
  314. }
  315. Statements *CompileStatement::flatten(Scope *sc)
  316. {
  317. //printf("CompileStatement::flatten() %s\n", exp->toChars());
  318. exp = exp->semantic(sc);
  319. exp = resolveProperties(sc, exp);
  320. exp = exp->optimize(WANTvalue | WANTinterpret);
  321. if (exp->op == TOKerror)
  322. return NULL;
  323. StringExp *se = exp->toString();
  324. if (!se)
  325. { error("argument to mixin must be a string, not (%s)", exp->toChars());
  326. return NULL;
  327. }
  328. se = se->toUTF8(sc);
  329. Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
  330. p.loc = loc;
  331. p.nextToken();
  332. Statements *a = new Statements();
  333. while (p.token.value != TOKeof)
  334. {
  335. Statement *s = p.parseStatement(PSsemi | PScurlyscope);
  336. if (s) // if no parsing errors
  337. a->push(s);
  338. }
  339. return a;
  340. }
  341. Statement *CompileStatement::semantic(Scope *sc)
  342. {
  343. //printf("CompileStatement::semantic() %s\n", exp->toChars());
  344. Statements *a = flatten(sc);
  345. if (!a)
  346. return NULL;
  347. Statement *s = new CompoundStatement(loc, a);
  348. return s->semantic(sc);
  349. }
  350. /******************************** CompoundStatement ***************************/
  351. CompoundStatement::CompoundStatement(Loc loc, Statements *s)
  352. : Statement(loc)
  353. {
  354. statements = s;
  355. }
  356. CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
  357. : Statement(loc)
  358. {
  359. statements = new Statements();
  360. statements->reserve(2);
  361. statements->push(s1);
  362. statements->push(s2);
  363. }
  364. CompoundStatement::CompoundStatement(Loc loc, Statement *s1)
  365. : Statement(loc)
  366. {
  367. statements = new Statements();
  368. statements->push(s1);
  369. }
  370. Statement *CompoundStatement::syntaxCopy()
  371. {
  372. Statements *a = new Statements();
  373. a->setDim(statements->dim);
  374. for (size_t i = 0; i < statements->dim; i++)
  375. { Statement *s = (Statement *)statements->data[i];
  376. if (s)
  377. s = s->syntaxCopy();
  378. a->data[i] = s;
  379. }
  380. CompoundStatement *cs = new CompoundStatement(loc, a);
  381. return cs;
  382. }
  383. Statement *CompoundStatement::semantic(Scope *sc)
  384. { Statement *s;
  385. //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
  386. for (size_t i = 0; i < statements->dim; )
  387. {
  388. s = (Statement *) statements->data[i];
  389. if (s)
  390. { Statements *a = s->flatten(sc);
  391. if (a)
  392. {
  393. statements->remove(i);
  394. statements->insert(i, a);
  395. continue;
  396. }
  397. s = s->semantic(sc);
  398. statements->data[i] = s;
  399. if (s)
  400. {
  401. Statement *sentry;
  402. Statement *sexception;
  403. Statement *sfinally;
  404. s->scopeCode(sc, &sentry, &sexception, &sfinally);
  405. if (sentry)
  406. {
  407. sentry = sentry->semantic(sc);
  408. statements->data[i] = sentry;
  409. }
  410. if (sexception)
  411. {
  412. if (i + 1 == statements->dim && !sfinally)
  413. {
  414. #if 1
  415. sexception = sexception->semantic(sc);
  416. #else
  417. statements->push(sexception);
  418. if (sfinally)
  419. // Assume sexception does not throw
  420. statements->push(sfinally);
  421. #endif
  422. }
  423. else
  424. {
  425. /* Rewrite:
  426. * s; s1; s2;
  427. * As:
  428. * s;
  429. * try { s1; s2; }
  430. * catch (Object __o)
  431. * { sexception; throw __o; }
  432. */
  433. Statement *body;
  434. Statements *a = new Statements();
  435. for (size_t j = i + 1; j < statements->dim; j++)
  436. {
  437. a->push((*statements)[j]);
  438. }
  439. body = new CompoundStatement(0, a);
  440. body = new ScopeStatement(0, body);
  441. Identifier *id = Lexer::uniqueId("__o");
  442. Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
  443. handler = new CompoundStatement(0, sexception, handler);
  444. Array *catches = new Array();
  445. Catch *ctch = new Catch(0, NULL, id, handler);
  446. catches->push(ctch);
  447. s = new TryCatchStatement(0, body, catches);
  448. if (sfinally)
  449. s = new TryFinallyStatement(0, s, sfinally);
  450. s = s->semantic(sc);
  451. statements->setDim(i + 1);
  452. statements->push(s);
  453. break;
  454. }
  455. }
  456. else if (sfinally)
  457. {
  458. if (0 && i + 1 == statements->dim)
  459. {
  460. statements->push(sfinally);
  461. }
  462. else
  463. {
  464. /* Rewrite:
  465. * s; s1; s2;
  466. * As:
  467. * s; try { s1; s2; } finally { sfinally; }
  468. */
  469. Statement *body;
  470. Statements *a = new Statements();
  471. for (size_t j = i + 1; j < statements->dim; j++)
  472. {
  473. a->push((*statements)[j]);
  474. }
  475. body = new CompoundStatement(0, a);
  476. s = new TryFinallyStatement(0, body, sfinally);
  477. s = s->semantic(sc);
  478. statements->setDim(i + 1);
  479. statements->push(s);
  480. break;
  481. }
  482. }
  483. }
  484. }
  485. i++;
  486. }
  487. if (statements->dim == 1)
  488. {
  489. return (*statements)[0];
  490. }
  491. return this;
  492. }
  493. Statements *CompoundStatement::flatten(Scope *sc)
  494. {
  495. return statements;
  496. }
  497. ReturnStatement *CompoundStatement::isReturnStatement()
  498. {
  499. ReturnStatement *rs = NULL;
  500. for (size_t i = 0; i < statements->dim; i++)
  501. { Statement *s = (*statements)[i];
  502. if (s)
  503. {
  504. rs = s->isReturnStatement();
  505. if (rs)
  506. break;
  507. }
  508. }
  509. return rs;
  510. }
  511. void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  512. {
  513. for (size_t i = 0; i < statements->dim; i++)
  514. { Statement *s = (Statement *) statements->data[i];
  515. if (s)
  516. s->toCBuffer(buf, hgs);
  517. }
  518. }
  519. int CompoundStatement::usesEH()
  520. {
  521. for (size_t i = 0; i < statements->dim; i++)
  522. { Statement *s = (Statement *) statements->data[i];
  523. if (s && s->usesEH())
  524. return TRUE;
  525. }
  526. return FALSE;
  527. }
  528. int CompoundStatement::blockExit(bool mustNotThrow)
  529. {
  530. //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
  531. int result = BEfallthru;
  532. for (size_t i = 0; i < statements->dim; i++)
  533. { Statement *s = (Statement *) statements->data[i];
  534. if (s)
  535. {
  536. //printf("result = x%x\n", result);
  537. //printf("%s\n", s->toChars());
  538. if (!(result & BEfallthru) && !s->comeFrom())
  539. {
  540. if (s->blockExit(mustNotThrow) != BEhalt && !s->isEmpty())
  541. s->warning("statement is not reachable");
  542. }
  543. else
  544. {
  545. result &= ~BEfallthru;
  546. result |= s->blockExit(mustNotThrow);
  547. }
  548. }
  549. }
  550. return result;
  551. }
  552. int CompoundStatement::comeFrom()
  553. { int comefrom = FALSE;
  554. //printf("CompoundStatement::comeFrom()\n");
  555. for (size_t i = 0; i < statements->dim; i++)
  556. { Statement *s = (Statement *)statements->data[i];
  557. if (!s)
  558. continue;
  559. comefrom |= s->comeFrom();
  560. }
  561. return comefrom;
  562. }
  563. int CompoundStatement::isEmpty()
  564. {
  565. for (size_t i = 0; i < statements->dim; i++)
  566. { Statement *s = (Statement *) statements->data[i];
  567. if (s && !s->isEmpty())
  568. return FALSE;
  569. }
  570. return TRUE;
  571. }
  572. /******************************** CompoundDeclarationStatement ***************************/
  573. CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s)
  574. : CompoundStatement(loc, s)
  575. {
  576. statements = s;
  577. }
  578. Statement *CompoundDeclarationStatement::syntaxCopy()
  579. {
  580. Statements *a = new Statements();
  581. a->setDim(statements->dim);
  582. for (size_t i = 0; i < statements->dim; i++)
  583. { Statement *s = (Statement *)statements->data[i];
  584. if (s)
  585. s = s->syntaxCopy();
  586. a->data[i] = s;
  587. }
  588. CompoundDeclarationStatement *cs = new CompoundDeclarationStatement(loc, a);
  589. return cs;
  590. }
  591. void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  592. {
  593. int nwritten = 0;
  594. for (size_t i = 0; i < statements->dim; i++)
  595. { Statement *s = (Statement *) statements->data[i];
  596. ExpStatement *ds;
  597. if (s &&
  598. (ds = s->isExpStatement()) != NULL &&
  599. ds->exp->op == TOKdeclaration)
  600. {
  601. DeclarationExp *de = (DeclarationExp *)ds->exp;
  602. assert(de->op == TOKdeclaration);
  603. Declaration *d = de->declaration->isDeclaration();
  604. assert(d);
  605. VarDeclaration *v = d->isVarDeclaration();
  606. if (v)
  607. {
  608. /* This essentially copies the part of VarDeclaration::toCBuffer()
  609. * that does not print the type.
  610. * Should refactor this.
  611. */
  612. if (nwritten)
  613. {
  614. buf->writeByte(',');
  615. buf->writestring(v->ident->toChars());
  616. }
  617. else
  618. {
  619. StorageClassDeclaration::stcToCBuffer(buf, v->storage_class);
  620. if (v->type)
  621. v->type->toCBuffer(buf, v->ident, hgs);
  622. else
  623. buf->writestring(v->ident->toChars());
  624. }
  625. if (v->init)
  626. { buf->writestring(" = ");
  627. #if DMDV2
  628. ExpInitializer *ie = v->init->isExpInitializer();
  629. if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
  630. ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
  631. else
  632. #endif
  633. v->init->toCBuffer(buf, hgs);
  634. }
  635. }
  636. else
  637. d->toCBuffer(buf, hgs);
  638. nwritten++;
  639. }
  640. }
  641. buf->writeByte(';');
  642. if (!hgs->FLinit.init)
  643. buf->writenl();
  644. }
  645. /**************************** UnrolledLoopStatement ***************************/
  646. UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
  647. : Statement(loc)
  648. {
  649. statements = s;
  650. }
  651. Statement *UnrolledLoopStatement::syntaxCopy()
  652. {
  653. Statements *a = new Statements();
  654. a->setDim(statements->dim);
  655. for (size_t i = 0; i < statements->dim; i++)
  656. { Statement *s = (Statement *)statements->data[i];
  657. if (s)
  658. s = s->syntaxCopy();
  659. a->data[i] = s;
  660. }
  661. UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a);
  662. return cs;
  663. }
  664. Statement *UnrolledLoopStatement::semantic(Scope *sc)
  665. {
  666. //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
  667. sc->noctor++;
  668. Scope *scd = sc->push();
  669. scd->sbreak = this;
  670. scd->scontinue = this;
  671. for (size_t i = 0; i < statements->dim; i++)
  672. {
  673. Statement *s = (Statement *) statements->data[i];
  674. if (s)
  675. {
  676. //printf("[%d]: %s\n", i, s->toChars());
  677. s = s->semantic(scd);
  678. statements->data[i] = s;
  679. }
  680. }
  681. scd->pop();
  682. sc->noctor--;
  683. return this;
  684. }
  685. void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  686. {
  687. buf->writestring("unrolled {");
  688. buf->writenl();
  689. for (size_t i = 0; i < statements->dim; i++)
  690. { Statement *s;
  691. s = (Statement *) statements->data[i];
  692. if (s)
  693. s->toCBuffer(buf, hgs);
  694. }
  695. buf->writeByte('}');
  696. buf->writenl();
  697. }
  698. int UnrolledLoopStatement::hasBreak()
  699. {
  700. return TRUE;
  701. }
  702. int UnrolledLoopStatement::hasContinue()
  703. {
  704. return TRUE;
  705. }
  706. int UnrolledLoopStatement::usesEH()
  707. {
  708. for (size_t i = 0; i < statements->dim; i++)
  709. { Statement *s = (Statement *) statements->data[i];
  710. if (s && s->usesEH())
  711. return TRUE;
  712. }
  713. return FALSE;
  714. }
  715. int UnrolledLoopStatement::blockExit(bool mustNotThrow)
  716. {
  717. int result = BEfallthru;
  718. for (size_t i = 0; i < statements->dim; i++)
  719. { Statement *s = (Statement *) statements->data[i];
  720. if (s)
  721. {
  722. int r = s->blockExit(mustNotThrow);
  723. result |= r & ~(BEbreak | BEcontinue);
  724. }
  725. }
  726. return result;
  727. }
  728. int UnrolledLoopStatement::comeFrom()
  729. { int comefrom = FALSE;
  730. //printf("UnrolledLoopStatement::comeFrom()\n");
  731. for (size_t i = 0; i < statements->dim; i++)
  732. { Statement *s = (Statement *)statements->data[i];
  733. if (!s)
  734. continue;
  735. comefrom |= s->comeFrom();
  736. }
  737. return comefrom;
  738. }
  739. /******************************** ScopeStatement ***************************/
  740. ScopeStatement::ScopeStatement(Loc loc, Statement *s)
  741. : Statement(loc)
  742. {
  743. this->statement = s;
  744. }
  745. Statement *ScopeStatement::syntaxCopy()
  746. {
  747. Statement *s;
  748. s = statement ? statement->syntaxCopy() : NULL;
  749. s = new ScopeStatement(loc, s);
  750. return s;
  751. }
  752. Statement *ScopeStatement::semantic(Scope *sc)
  753. { ScopeDsymbol *sym;
  754. //printf("ScopeStatement::semantic(sc = %p)\n", sc);
  755. if (statement)
  756. { Statements *a;
  757. sym = new ScopeDsymbol();
  758. sym->parent = sc->scopesym;
  759. sc = sc->push(sym);
  760. a = statement->flatten(sc);
  761. if (a)
  762. {
  763. statement = new CompoundStatement(loc, a);
  764. }
  765. statement = statement->semantic(sc);
  766. if (statement)
  767. {
  768. Statement *sentry;
  769. Statement *sexception;
  770. Statement *sfinally;
  771. statement->scopeCode(sc, &sentry, &sexception, &sfinally);
  772. if (sfinally)
  773. {
  774. //printf("adding sfinally\n");
  775. sfinally = sfinally->semantic(sc);
  776. statement = new CompoundStatement(loc, statement, sfinally);
  777. }
  778. }
  779. sc->pop();
  780. }
  781. return this;
  782. }
  783. int ScopeStatement::hasBreak()
  784. {
  785. //printf("ScopeStatement::hasBreak() %s\n", toChars());
  786. return statement ? statement->hasBreak() : FALSE;
  787. }
  788. int ScopeStatement::hasContinue()
  789. {
  790. return statement ? statement->hasContinue() : FALSE;
  791. }
  792. int ScopeStatement::usesEH()
  793. {
  794. return statement ? statement->usesEH() : FALSE;
  795. }
  796. int ScopeStatement::blockExit(bool mustNotThrow)
  797. {
  798. //printf("ScopeStatement::blockExit(%p)\n", statement);
  799. return statement ? statement->blockExit(mustNotThrow) : BEfallthru;
  800. }
  801. int ScopeStatement::comeFrom()
  802. {
  803. //printf("ScopeStatement::comeFrom()\n");
  804. return statement ? statement->comeFrom() : FALSE;
  805. }
  806. int ScopeStatement::isEmpty()
  807. {
  808. //printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE);
  809. return statement ? statement->isEmpty() : TRUE;
  810. }
  811. void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  812. {
  813. buf->writeByte('{');
  814. buf->writenl();
  815. if (statement)
  816. statement->toCBuffer(buf, hgs);
  817. buf->writeByte('}');
  818. buf->writenl();
  819. }
  820. /******************************** WhileStatement ***************************/
  821. WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
  822. : Statement(loc)
  823. {
  824. condition = c;
  825. body = b;
  826. }
  827. Statement *WhileStatement::syntaxCopy()
  828. {
  829. WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL);
  830. return s;
  831. }
  832. Statement *WhileStatement::semantic(Scope *sc)
  833. {
  834. /* Rewrite as a for(;condition;) loop
  835. */
  836. Statement *s = new ForStatement(loc, NULL, condition, NULL, body);
  837. s = s->semantic(sc);
  838. return s;
  839. }
  840. int WhileStatement::hasBreak()
  841. {
  842. return TRUE;
  843. }
  844. int WhileStatement::hasContinue()
  845. {
  846. return TRUE;
  847. }
  848. int WhileStatement::usesEH()
  849. {
  850. assert(0);
  851. return body ? body->usesEH() : 0;
  852. }
  853. int WhileStatement::blockExit(bool mustNotThrow)
  854. {
  855. assert(0);
  856. //printf("WhileStatement::blockExit(%p)\n", this);
  857. int result = BEnone;
  858. if (condition->canThrow())
  859. result |= BEthrow;
  860. if (condition->isBool(TRUE))
  861. {
  862. if (body)
  863. { result |= body->blockExit(mustNotThrow);
  864. if (result & BEbreak)
  865. result |= BEfallthru;
  866. }
  867. }
  868. else if (condition->isBool(FALSE))
  869. {
  870. result |= BEfallthru;
  871. }
  872. else
  873. {
  874. if (body)
  875. result |= body->blockExit(mustNotThrow);
  876. result |= BEfallthru;
  877. }
  878. result &= ~(BEbreak | BEcontinue);
  879. return result;
  880. }
  881. int WhileStatement::comeFrom()
  882. {
  883. assert(0);
  884. if (body)
  885. return body->comeFrom();
  886. return FALSE;
  887. }
  888. void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  889. {
  890. buf->writestring("while (");
  891. condition->toCBuffer(buf, hgs);
  892. buf->writebyte(')');
  893. buf->writenl();
  894. if (body)
  895. body->toCBuffer(buf, hgs);
  896. }
  897. /******************************** DoStatement ***************************/
  898. DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
  899. : Statement(loc)
  900. {
  901. body = b;
  902. condition = c;
  903. }
  904. Statement *DoStatement::syntaxCopy()
  905. {
  906. DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy());
  907. return s;
  908. }
  909. Statement *DoStatement::semantic(Scope *sc)
  910. {
  911. sc->noctor++;
  912. if (body)
  913. body = body->semanticScope(sc, this, this);
  914. sc->noctor--;
  915. condition = condition->semantic(sc);
  916. condition = resolveProperties(sc, condition);
  917. condition = condition->optimize(WANTvalue);
  918. condition = condition->checkToBoolean();
  919. return this;
  920. }
  921. int DoStatement::hasBreak()
  922. {
  923. return TRUE;
  924. }
  925. int DoStatement::hasContinue()
  926. {
  927. return TRUE;
  928. }
  929. int DoStatement::usesEH()
  930. {
  931. return body ? body->usesEH() : 0;
  932. }
  933. int DoStatement::blockExit(bool mustNotThrow)
  934. { int result;
  935. if (body)
  936. { result = body->blockExit(mustNotThrow);
  937. if (result == BEbreak)
  938. return BEfallthru;
  939. if (result & BEcontinue)
  940. result |= BEfallthru;
  941. }
  942. else
  943. result = BEfallthru;
  944. if (result & BEfallthru)
  945. {
  946. if (condition->canThrow())
  947. result |= BEthrow;
  948. if (!(result & BEbreak) && condition->isBool(TRUE))
  949. result &= ~BEfallthru;
  950. }
  951. result &= ~(BEbreak | BEcontinue);
  952. return result;
  953. }
  954. int DoStatement::comeFrom()
  955. {
  956. if (body)
  957. return body->comeFrom();
  958. return FALSE;
  959. }
  960. void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  961. {
  962. buf->writestring("do");
  963. buf->writenl();
  964. if (body)
  965. body->toCBuffer(buf, hgs);
  966. buf->writestring("while (");
  967. condition->toCBuffer(buf, hgs);
  968. buf->writebyte(')');
  969. }
  970. /******************************** ForStatement ***************************/
  971. ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body)
  972. : Statement(loc)
  973. {
  974. this->init = init;
  975. this->condition = condition;
  976. this->increment = increment;
  977. this->body = body;
  978. }
  979. Statement *ForStatement::syntaxCopy()
  980. {
  981. Statement *i = NULL;
  982. if (init)
  983. i = init->syntaxCopy();
  984. Expression *c = NULL;
  985. if (condition)
  986. c = condition->syntaxCopy();
  987. Expression *inc = NULL;
  988. if (increment)
  989. inc = increment->syntaxCopy();
  990. ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy());
  991. return s;
  992. }
  993. Statement *ForStatement::semantic(Scope *sc)
  994. {
  995. ScopeDsymbol *sym = new ScopeDsymbol();
  996. sym->parent = sc->scopesym;
  997. sc = sc->push(sym);
  998. if (init)
  999. init = init->semantic(sc);
  1000. #if 0
  1001. if (!condition)
  1002. // Use a default value
  1003. condition = new IntegerExp(loc, 1, Type::tboolean);
  1004. #endif
  1005. sc->noctor++;
  1006. if (condition)
  1007. {
  1008. condition = condition->semantic(sc);
  1009. condition = resolveProperties(sc, condition);
  1010. condition = condition->optimize(WANTvalue);
  1011. condition = condition->checkToBoolean();
  1012. }
  1013. if (increment)
  1014. { increment = increment->semantic(sc);
  1015. increment = resolveProperties(sc, increment);
  1016. increment = increment->optimize(0);
  1017. }
  1018. sc->sbreak = this;
  1019. sc->scontinue = this;
  1020. if (body)
  1021. body = body->semanticNoScope(sc);
  1022. sc->noctor--;
  1023. sc->pop();
  1024. return this;
  1025. }
  1026. void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
  1027. {
  1028. //printf("ForStatement::scopeCode()\n");
  1029. //print();
  1030. if (init)
  1031. init->scopeCode(sc, sentry, sexception, sfinally);
  1032. else
  1033. Statement::scopeCode(sc, sentry, sexception, sfinally);
  1034. }
  1035. int ForStatement::hasBreak()
  1036. {
  1037. //printf("ForStatement::hasBreak()\n");
  1038. return TRUE;
  1039. }
  1040. int ForStatement::hasContinue()
  1041. {
  1042. return TRUE;
  1043. }
  1044. int ForStatement::usesEH()
  1045. {
  1046. return (init && init->usesEH()) || body->usesEH();
  1047. }
  1048. int ForStatement::blockExit(bool mustNotThrow)
  1049. { int result = BEfallthru;
  1050. if (init)
  1051. { result = init->blockExit(mustNotThrow);
  1052. if (!(result & BEfallthru))
  1053. return result;
  1054. }
  1055. if (condition)
  1056. { if (condition->canThrow())
  1057. result |= BEthrow;
  1058. if (condition->isBool(TRUE))
  1059. result &= ~BEfallthru;
  1060. else if (condition->isBool(FALSE))
  1061. return result;
  1062. }
  1063. else
  1064. result &= ~BEfallthru; // the body must do the exiting
  1065. if (body)
  1066. { int r = body->blockExit(mustNotThrow);
  1067. if (r & (BEbreak | BEgoto))
  1068. result |= BEfallthru;
  1069. result |= r & ~(BEfallthru | BEbreak | BEcontinue);
  1070. }
  1071. if (increment && increment->canThrow())
  1072. result |= BEthrow;
  1073. return result;
  1074. }
  1075. int ForStatement::comeFrom()
  1076. {
  1077. //printf("ForStatement::comeFrom()\n");
  1078. if (body)
  1079. { int result = body->comeFrom();
  1080. //printf("result = %d\n", result);
  1081. return result;
  1082. }
  1083. return FALSE;
  1084. }
  1085. void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  1086. {
  1087. buf->writestring("for (");
  1088. if (init)
  1089. {
  1090. hgs->FLinit.init++;
  1091. init->toCBuffer(buf, hgs);
  1092. hgs->FLinit.init--;
  1093. }
  1094. else
  1095. buf->writebyte(';');
  1096. if (condition)
  1097. { buf->writebyte(' ');
  1098. condition->toCBuffer(buf, hgs);
  1099. }
  1100. buf->writebyte(';');
  1101. if (increment)
  1102. { buf->writebyte(' ');
  1103. increment->toCBuffer(buf, hgs);
  1104. }
  1105. buf->writebyte(')');
  1106. buf->writenl();
  1107. buf->writebyte('{');
  1108. buf->writenl();
  1109. body->toCBuffer(buf, hgs);
  1110. buf->writebyte('}');
  1111. buf->writenl();
  1112. }
  1113. /******************************** ForeachStatement ***************************/
  1114. ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Parameters *arguments,
  1115. Expression *aggr, Statement *body)
  1116. : Statement(loc)
  1117. {
  1118. this->op = op;
  1119. this->arguments = arguments;
  1120. this->aggr = aggr;
  1121. this->body = body;
  1122. this->key = NULL;
  1123. this->value = NULL;
  1124. this->func = NULL;
  1125. this->cases = NULL;
  1126. this->gotos = NULL;
  1127. }
  1128. Statement *ForeachStatement::syntaxCopy()
  1129. {
  1130. //printf("ForeachStatement::syntaxCopy()\n");
  1131. Parameters *args = Parameter::arraySyntaxCopy(arguments);
  1132. Expression *exp = aggr->syntaxCopy();
  1133. ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
  1134. body ? body->syntaxCopy() : NULL);
  1135. return s;
  1136. }
  1137. Statement *ForeachStatement::semantic(Scope *sc)
  1138. {
  1139. //printf("ForeachStatement::semantic() %p\n", this);
  1140. ScopeDsymbol *sym;
  1141. Statement *s = this;
  1142. size_t dim = arguments->dim;
  1143. TypeAArray *taa = NULL;
  1144. Type *tn = NULL;
  1145. Type *tnv = NULL;
  1146. func = sc->func;
  1147. if (func->fes)
  1148. func = func->fes->func;
  1149. aggr = aggr->semantic(sc);
  1150. aggr = resolveProperties(sc, aggr);
  1151. aggr = aggr->optimize(WANTvalue);
  1152. if (!aggr->type)
  1153. {
  1154. error("invalid foreach aggregate %s", aggr->toChars());
  1155. return this;
  1156. }
  1157. inferApplyArgTypes(op, arguments, aggr);
  1158. /* Check for inference errors
  1159. */
  1160. if (dim != arguments->dim)
  1161. {
  1162. //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
  1163. error("cannot uniquely infer foreach argument types");
  1164. return this;
  1165. }
  1166. Type *tab = aggr->type->toBasetype();
  1167. if (tab->ty == Ttuple) // don't generate new scope for tuple loops
  1168. {
  1169. if (dim < 1 || dim > 2)
  1170. {
  1171. error("only one (value) or two (key,value) arguments for tuple foreach");
  1172. return s;
  1173. }
  1174. TypeTuple *tuple = (TypeTuple *)tab;
  1175. Statements *statements = new Statements();
  1176. //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
  1177. size_t n;
  1178. TupleExp *te = NULL;
  1179. if (aggr->op == TOKtuple) // expression tuple
  1180. { te = (TupleExp *)aggr;
  1181. n = te->exps->dim;
  1182. }
  1183. else if (aggr->op == TOKtype) // type tuple
  1184. {
  1185. n = Parameter::dim(tuple->arguments);
  1186. }
  1187. else
  1188. assert(0);
  1189. for (size_t j = 0; j < n; j++)
  1190. { size_t k = (op == TOKforeach) ? j : n - 1 - j;
  1191. Expression *e;
  1192. Type *t;
  1193. if (te)
  1194. e = te->exps->tdata()[k];
  1195. else
  1196. t = Parameter::getNth(tuple->arguments, k)->type;
  1197. Parameter *arg = arguments->tdata()[0];
  1198. Statements *st = new Statements();
  1199. if (dim == 2)
  1200. { // Declare key
  1201. if (arg->storageClass & (STCout | STCref | STClazy))
  1202. error("no storage class for key %s", arg->ident->toChars());
  1203. arg->type = arg->type->semantic(loc, sc);
  1204. TY keyty = arg->type->ty;
  1205. if (keyty != Tint32 && keyty != Tuns32)
  1206. {
  1207. if (global.params.is64bit)
  1208. {
  1209. if (keyty != Tint64 && keyty != Tuns64)
  1210. error("foreach: key type must be int or uint, long or ulong, not %s", arg->type->toChars());
  1211. }
  1212. else
  1213. error("foreach: key type must be int or uint, not %s", arg->type->toChars());
  1214. }
  1215. Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
  1216. VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
  1217. var->storage_class |= STCconst;
  1218. DeclarationExp *de = new DeclarationExp(loc, var);
  1219. st->push(new ExpStatement(loc, de));
  1220. arg = (*arguments)[1]; // value
  1221. }
  1222. // Declare value
  1223. if (arg->storageClass & (STCout | STCref | STClazy))
  1224. error("no storage class for value %s", arg->ident->toChars());
  1225. Dsymbol *var;
  1226. if (te)
  1227. { Type *tb = e->type->toBasetype();
  1228. Dsymbol *s = NULL;
  1229. if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
  1230. s = ((VarExp *)e)->var;
  1231. else if (e->op == TOKtemplate)
  1232. s =((TemplateExp *)e)->td;
  1233. else if (e->op == TOKimport)
  1234. s =((ScopeExp *)e)->sds;
  1235. if (s)
  1236. var = new AliasDeclaration(loc, arg->ident, s);
  1237. else
  1238. {
  1239. arg->type = e->type;
  1240. Initializer *ie = new ExpInitializer(0, e);
  1241. VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
  1242. if (e->isConst() || e->op == TOKstring)
  1243. v->storage_class |= STCconst;
  1244. var = v;
  1245. }
  1246. }
  1247. else
  1248. {
  1249. var = new AliasDeclaration(loc, arg->ident, t);
  1250. }
  1251. DeclarationExp *de = new DeclarationExp(loc, var);
  1252. st->push(new ExpStatement(loc, de));
  1253. st->push(body->syntaxCopy());
  1254. s = new CompoundStatement(loc, st);
  1255. s = new ScopeStatement(loc, s);
  1256. statements->push(s);
  1257. }
  1258. s = new UnrolledLoopStatement(loc, statements);
  1259. s = s->semantic(sc);
  1260. return s;
  1261. }
  1262. for (size_t i = 0; i < dim; i++)
  1263. { Parameter *arg = (Parameter *)arguments->data[i];
  1264. if (!arg->type)
  1265. {
  1266. error("cannot infer type for %s", arg->ident->toChars());
  1267. return this;
  1268. }
  1269. }
  1270. sym = new ScopeDsymbol();
  1271. sym->parent = sc->scopesym;
  1272. sc = sc->push(sym);
  1273. sc->noctor++;
  1274. switch (tab->ty)
  1275. {
  1276. case Tarray:
  1277. case Tsarray:
  1278. if (dim < 1 || dim > 2)
  1279. {
  1280. error("only one or two arguments for array foreach");
  1281. break;
  1282. }
  1283. /* Look for special case of parsing char types out of char type
  1284. * array.
  1285. */
  1286. tn = tab->nextOf()->toBasetype();
  1287. if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
  1288. { Parameter *arg;
  1289. int i = (dim == 1) ? 0 : 1; // index of value
  1290. arg = (Parameter *)arguments->data[i];
  1291. arg->type = arg->type->semantic(loc, sc);
  1292. tnv = arg->type->toBasetype();
  1293. if (tnv->ty != tn->ty &&
  1294. (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
  1295. {
  1296. if (arg->storageClass & STCref)
  1297. error("foreach: value of UTF conversion cannot be ref");
  1298. if (dim == 2)
  1299. { arg = (Parameter *)arguments->data[0];
  1300. if (arg->storageClass & STCref)
  1301. error("foreach: key cannot be ref");
  1302. }
  1303. goto Lapply;
  1304. }
  1305. }
  1306. for (size_t i = 0; i < dim; i++)
  1307. { // Declare args
  1308. Parameter *arg = (Parameter *)arguments->data[i];
  1309. Type *argtype = arg->type->semantic(loc, sc);
  1310. VarDeclaration *var;
  1311. var = new VarDeclaration(loc, argtype, arg->ident, NULL);
  1312. var->storage_class |= STCforeach;
  1313. var->storage_class |= arg->storageClass & (STCin | STCout | STCref);
  1314. if (dim == 2 && i == 0)
  1315. key = var;
  1316. else
  1317. value = var;
  1318. #if 0
  1319. DeclarationExp *de = new DeclarationExp(loc, var);
  1320. de->semantic(sc);
  1321. #endif
  1322. }
  1323. #if 1
  1324. {
  1325. /* Convert to a ForStatement
  1326. * foreach (key, value; a) body =>
  1327. * for (T[] tmp = a[], size_t key; key < tmp.length; ++key)
  1328. * { T value = tmp[k]; body }
  1329. *
  1330. * foreach_reverse (key, value; a) body =>
  1331. * for (T[] tmp = a[], size_t key = tmp.length; key--; )
  1332. * { T value = tmp[k]; body }
  1333. */
  1334. Identifier *id = Lexer::uniqueId("__aggr");
  1335. ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL));
  1336. VarDeclaration *tmp = new VarDeclaration(loc, tab->nextOf()->arrayOf(), id, ie);
  1337. Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length);
  1338. if (!key)
  1339. {
  1340. Identifier *idkey = Lexer::uniqueId("__key");
  1341. key = new VarDeclaration(loc, Type::tsize_t, idkey, NULL);
  1342. }
  1343. if (op == TOKforeach_reverse)
  1344. key->init = new ExpInitializer(loc, tmp_length);
  1345. else
  1346. key->init = new ExpInitializer(loc, new IntegerExp(0));
  1347. Statements *cs = new Statements();
  1348. cs->push(new ExpStatement(loc, tmp));
  1349. cs->push(new ExpStatement(loc, key));
  1350. Statement *forinit = new CompoundDeclarationStatement(loc, cs);
  1351. Expression *cond;
  1352. if (op == TOKforeach_reverse)
  1353. // key--
  1354. cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
  1355. else
  1356. // key < tmp.length
  1357. cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length);
  1358. Expression *increment = NULL;
  1359. if (op == TOKforeach)
  1360. // key += 1
  1361. increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
  1362. // T value = tmp[key];
  1363. value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key)));
  1364. Statement *ds = new ExpStatement(loc, value);
  1365. body = new CompoundStatement(loc, ds, body);
  1366. ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
  1367. s = fs->semantic(sc);
  1368. break;
  1369. }
  1370. #else
  1371. if (!value->type->equals(tab->next))
  1372. {
  1373. if (aggr->op == TOKstring)
  1374. aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
  1375. else
  1376. error("foreach: %s is not an array of %s",
  1377. tab->toChars(), value->type->toChars());
  1378. }
  1379. if (key)
  1380. {
  1381. if (key->type->ty != Tint32 && key->type->ty != Tuns32)
  1382. {
  1383. if (global.params.is64bit)
  1384. {
  1385. if (key->type->ty != Tint64 && key->type->ty != Tuns64)
  1386. error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars());
  1387. }
  1388. else
  1389. error("foreach: key type must be int or uint, not %s", key->type->toChars());
  1390. }
  1391. if (key->storage_class & (STCout | STCref))
  1392. error("foreach: key cannot be out or ref");
  1393. }
  1394. sc->sbreak = this;
  1395. sc->scontinue = this;
  1396. body = body->semantic(sc);
  1397. break;
  1398. #endif
  1399. case Taarray:
  1400. taa = (TypeAArray *)tab;
  1401. if (dim < 1 || dim > 2)
  1402. {
  1403. error("only one or two arguments for associative array foreach");
  1404. break;
  1405. }
  1406. if (op == TOKforeach_reverse)
  1407. {
  1408. error("no reverse iteration on associative arrays");
  1409. }
  1410. goto Lapply;
  1411. case Tclass:
  1412. case Tstruct:
  1413. #if DMDV2
  1414. { /* Look for range iteration, i.e. the properties
  1415. * .empty, .next, .retreat, .head and .rear
  1416. * foreach (e; aggr) { ... }
  1417. * translates to:
  1418. * for (auto __r = aggr[]; !__r.empty; __r.next)
  1419. * { auto e = __r.head;
  1420. * ...
  1421. * }
  1422. */
  1423. if (dim != 1) // only one argument allowed with ranges
  1424. goto Lapply;
  1425. AggregateDeclaration *ad = (tab->ty == Tclass)
  1426. ? (AggregateDeclaration *)((TypeClass *)tab)->sym
  1427. : (AggregateDeclaration *)((TypeStruct *)tab)->sym;
  1428. Identifier *idhead;
  1429. Identifier *idnext;
  1430. if (op == TOKforeach)
  1431. { idhead = Id::Fhead;
  1432. idnext = Id::Fnext;
  1433. }
  1434. else
  1435. { idhead = Id::Ftoe;
  1436. idnext = Id::Fretreat;
  1437. }
  1438. Dsymbol *shead = search_function(ad, idhead);
  1439. if (!shead)
  1440. goto Lapply;
  1441. /* Generate a temporary __r and initialize it with the aggregate.
  1442. */
  1443. Identifier *id = Identifier::generateId("__r");
  1444. Expression *rinit = new SliceExp(loc, aggr, NULL, NULL);
  1445. rinit = rinit->trySemantic(sc);
  1446. if (!rinit) // if application of [] failed
  1447. rinit = aggr;
  1448. VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit));
  1449. // r->semantic(sc);
  1450. //printf("r: %s, init: %s\n", r->toChars(), r->init->toChars());
  1451. Statement *init = new ExpStatement(loc, r);
  1452. //printf("init: %s\n", init->toChars());
  1453. // !__r.empty
  1454. Expression *e = new VarExp(loc, r);
  1455. e = new DotIdExp(loc, e, Id::Fempty);
  1456. Expression *condition = new NotExp(loc, e);
  1457. // __r.next
  1458. e = new VarExp(loc, r);
  1459. Expression *increment = new DotIdExp(loc, e, idnext);
  1460. /* Declaration statement for e:
  1461. * auto e = __r.idhead;
  1462. */
  1463. e = new VarExp(loc, r);
  1464. Expression *einit = new DotIdExp(loc, e, idhead);
  1465. // einit = einit->semantic(sc);
  1466. Parameter *arg = (Parameter *)arguments->data[0];
  1467. VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
  1468. ve->storage_class |= STCforeach;
  1469. ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
  1470. DeclarationExp *de = new DeclarationExp(loc, ve);
  1471. Statement *body = new CompoundStatement(loc,
  1472. new ExpStatement(loc, de), this->body);
  1473. s = new ForStatement(loc, init, condition, increment, body);
  1474. #if 0
  1475. printf("init: %s\n", init->toChars());
  1476. printf("condition: %s\n", condition->toChars());
  1477. printf("increment: %s\n", increment->toChars());
  1478. printf("body: %s\n", body->toChars());
  1479. #endif
  1480. s = s->semantic(sc);
  1481. break;
  1482. }
  1483. #endif
  1484. case Tdelegate:
  1485. Lapply:
  1486. {
  1487. Expression *ec;
  1488. Expression *e;
  1489. Parameter *a;
  1490. Type *tret = func->type->nextOf();
  1491. // Need a variable to hold value from any return statements in body.
  1492. if (!sc->func->vresult && tret && tret != Type::tvoid)
  1493. {
  1494. VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
  1495. v->noscope = 1;
  1496. v->semantic(sc);
  1497. if (!sc->insert(v))
  1498. assert(0);
  1499. v->parent = sc->func;
  1500. sc->func->vresult = v;
  1501. }
  1502. /* Turn body into the function literal:
  1503. * int delegate(ref T arg) { body }
  1504. */
  1505. Parameters *args = new Parameters();
  1506. for (size_t i = 0; i < dim; i++)
  1507. { Parameter *arg = (Parameter *)arguments->data[i];
  1508. Identifier *id;
  1509. arg->type = arg->type->semantic(loc, sc);
  1510. if (arg->storageClass & STCref)
  1511. id = arg->ident;
  1512. else
  1513. { // Make a copy of the ref argument so it isn't
  1514. // a reference.
  1515. id = Lexer::uniqueId("__applyArg", i);
  1516. Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id));
  1517. VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie);
  1518. s = new ExpStatement(0, v);
  1519. body = new CompoundStatement(loc, s, body);
  1520. }
  1521. a = new Parameter(STCref, arg->type, id, NULL);
  1522. args->push(a);
  1523. }
  1524. Type *t = new TypeFunction(args, Type::tint32, 0, LINKd);
  1525. cases = new Statements();
  1526. gotos = new Array();
  1527. FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
  1528. fld->fbody = body;
  1529. Expression *flde = new FuncExp(loc, fld);
  1530. flde = flde->semantic(sc);
  1531. // Resolve any forward referenced goto's
  1532. for (size_t i = 0; i < gotos->dim; i++)
  1533. { CompoundStatement *cs = (CompoundStatement *)gotos->data[i];
  1534. GotoStatement *gs = (GotoStatement *)cs->statements->data[0];
  1535. if (!gs->label->statement)
  1536. { // 'Promote' it to this scope, and replace with a return
  1537. cases->push(gs);
  1538. s = new ReturnStatement(0, new IntegerExp(cases->dim + 1));
  1539. cs->statements->data[0] = (void *)s;
  1540. }
  1541. }
  1542. if (taa)
  1543. {
  1544. // Check types
  1545. Parameter *arg = (Parameter *)arguments->data[0];
  1546. if (dim == 2)
  1547. {
  1548. if (arg->storageClass & STCref)
  1549. error("foreach: index cannot be ref");
  1550. if (!arg->type->equals(taa->index))
  1551. error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
  1552. arg = (Parameter *)arguments->data[1];
  1553. }
  1554. if (!arg->type->equals(taa->nextOf()))
  1555. error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
  1556. /* Call:
  1557. * _aaApply(aggr, keysize, flde)
  1558. */
  1559. FuncDeclaration *fdapply;
  1560. if (dim == 2)
  1561. fdapply = FuncDeclaration::genCfunc(Type::tint32, "_aaApply2",
  1562. aggr->type, Type::tsize_t, flde->type);
  1563. else
  1564. fdapply = FuncDeclaration::genCfunc(Type::tint32, "_aaApply",
  1565. aggr->type, Type::tsize_t, flde->type);
  1566. ec = new VarExp(0, fdapply);
  1567. Expressions *exps = new Expressions();
  1568. exps->push(aggr);
  1569. size_t keysize = taa->key->size();
  1570. if (global.params.is64bit)
  1571. keysize = (keysize + 15) & ~15;
  1572. else
  1573. keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1);
  1574. exps->push(new IntegerExp(0, keysize, Type::tsize_t));
  1575. exps->push(flde);
  1576. e = new CallExp(loc, ec, exps);
  1577. e->type = Type::tindex; // don't run semantic() on e
  1578. }
  1579. else if (tab->ty == Tarray || tab->ty == Tsarray)
  1580. {
  1581. /* Call:
  1582. * _aApply(aggr, flde)
  1583. */
  1584. static char fntab[9][3] =
  1585. { "cc","cw","cd",
  1586. "wc","cc","wd",
  1587. "dc","dw","dd"
  1588. };
  1589. char fdname[7+1+2+ sizeof(dim)*3 + 1];
  1590. int flag;
  1591. switch (tn->ty)
  1592. {
  1593. case Tchar: flag = 0; break;
  1594. case Twchar: flag = 3; break;
  1595. case Tdchar: flag = 6; break;
  1596. default: assert(0);
  1597. }
  1598. switch (tnv->ty)
  1599. {
  1600. case Tchar: flag += 0; break;
  1601. case Twchar: flag += 1; break;
  1602. case Tdchar: flag += 2; break;
  1603. default: assert(0);
  1604. }
  1605. const char *r = (op == TOKforeach_reverse) ? "R" : "";
  1606. int j = sprintf(fdname, "_aApply%s%.*s%zd", r, 2, fntab[flag], dim);
  1607. assert(j < sizeof(fdname));
  1608. FuncDeclaration *fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname,
  1609. tn->arrayOf(), flde->type);
  1610. ec = new VarExp(0, fdapply);
  1611. Expressions *exps = new Expressions();
  1612. if (tab->ty == Tsarray)
  1613. aggr = aggr->castTo(sc, tn->arrayOf());
  1614. exps->push(aggr);
  1615. exps->push(flde);
  1616. e = new CallExp(loc, ec, exps);
  1617. e->type = Type::tindex; // don't run semantic() on e
  1618. }
  1619. else if (tab->ty == Tdelegate)
  1620. {
  1621. /* Call:
  1622. * aggr(flde)
  1623. */
  1624. Expressions *exps = new Expressions();
  1625. exps->push(flde);
  1626. if (aggr->op == TOKdelegate &&
  1627. ((DelegateExp *)aggr)->func->isNested())
  1628. // See Bugzilla 3560
  1629. e = new CallExp(loc, ((DelegateExp *)aggr)->e1, exps);
  1630. else
  1631. e = new CallExp(loc, aggr, exps);
  1632. e = e->semantic(sc);
  1633. if (e->type != Type::tint32)
  1634. error("opApply() function for %s must return an int", tab->toChars());
  1635. }
  1636. else
  1637. {
  1638. /* Call:
  1639. * aggr.apply(flde)
  1640. */
  1641. ec = new DotIdExp(loc, aggr,
  1642. (op == TOKforeach_reverse) ? Id::applyReverse
  1643. : Id::apply);
  1644. Expressions *exps = new Expressions();
  1645. exps->push(flde);
  1646. e = new CallExp(loc, ec, exps);
  1647. e = e->semantic(sc);
  1648. if (e->type != Type::tint32)
  1649. error("opApply() function for %s must return an int", tab->toChars());
  1650. }
  1651. if (!cases->dim)
  1652. // Easy case, a clean exit from the loop
  1653. s = new ExpStatement(loc, e);
  1654. else
  1655. { // Construct a switch statement around the return value
  1656. // of the apply function.
  1657. Statements *a = new Statements();
  1658. // default: break; takes care of cases 0 and 1
  1659. s = new BreakStatement(0, NULL);
  1660. s = new DefaultStatement(0, s);
  1661. a->push(s);
  1662. // cases 2...
  1663. for (size_t i = 0; i < cases->dim; i++)
  1664. {
  1665. s = (Statement *)cases->data[i];
  1666. s = new CaseStatement(0, new IntegerExp(i + 2), s);
  1667. a->push(s);
  1668. }
  1669. s = new CompoundStatement(loc, a);
  1670. s = new SwitchStatement(loc, e, s);
  1671. s = s->semantic(sc);
  1672. }
  1673. break;
  1674. }
  1675. case Terror:
  1676. s = NULL;
  1677. break;
  1678. default:
  1679. error("foreach: %s is not an aggregate type", aggr->type->toChars());
  1680. s = NULL; // error recovery
  1681. break;
  1682. }
  1683. sc->noctor--;
  1684. sc->pop();
  1685. return s;
  1686. }
  1687. int ForeachStatement::hasBreak()
  1688. {
  1689. return TRUE;
  1690. }
  1691. int ForeachStatement::hasContinue()
  1692. {
  1693. return TRUE;
  1694. }
  1695. int ForeachStatement::usesEH()
  1696. {
  1697. return body->usesEH();
  1698. }
  1699. int ForeachStatement::blockExit(bool mustNotThrow)
  1700. { int result = BEfallthru;
  1701. if (aggr->canThrow())
  1702. result |= BEthrow;
  1703. if (body)
  1704. {
  1705. result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue);
  1706. }
  1707. return result;
  1708. }
  1709. int ForeachStatement::comeFrom()
  1710. {
  1711. if (body)
  1712. return body->comeFrom();
  1713. return FALSE;
  1714. }
  1715. void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  1716. {
  1717. buf->writestring(Token::toChars(op));
  1718. buf->writestring(" (");
  1719. for (size_t i = 0; i < arguments->dim; i++)
  1720. {
  1721. Parameter *a = (Parameter *)arguments->data[i];
  1722. if (i)
  1723. buf->writestring(", ");
  1724. if (a->storageClass & STCref)
  1725. buf->writestring((global.params.Dversion == 1)
  1726. ? (char*)"inout " : (char*)"ref ");
  1727. if (a->type)
  1728. a->type->toCBuffer(buf, a->ident, hgs);
  1729. else
  1730. buf->writestring(a->ident->toChars());
  1731. }
  1732. buf->writestring("; ");
  1733. aggr->toCBuffer(buf, hgs);
  1734. buf->writebyte(')');
  1735. buf->writenl();
  1736. buf->writebyte('{');
  1737. buf->writenl();
  1738. if (body)
  1739. body->toCBuffer(buf, hgs);
  1740. buf->writebyte('}');
  1741. buf->writenl();
  1742. }
  1743. /**************************** ForeachRangeStatement ***************************/
  1744. #if DMDV2
  1745. ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Parameter *arg,
  1746. Expression *lwr, Expression *upr, Statement *body)
  1747. : Statement(loc)
  1748. {
  1749. this->op = op;
  1750. this->arg = arg;
  1751. this->lwr = lwr;
  1752. this->upr = upr;
  1753. this->body = body;
  1754. this->key = NULL;
  1755. }
  1756. Statement *ForeachRangeStatement::syntaxCopy()
  1757. {
  1758. ForeachRangeStatement *s = new ForeachRangeStatement(loc, op,
  1759. arg->syntaxCopy(),
  1760. lwr->syntaxCopy(),
  1761. upr->syntaxCopy(),
  1762. body ? body->syntaxCopy() : NULL);
  1763. return s;
  1764. }
  1765. Statement *ForeachRangeStatement::semantic(Scope *sc)
  1766. {
  1767. //printf("ForeachRangeStatement::semantic() %p\n", this);
  1768. Statement *s = this;
  1769. lwr = lwr->semantic(sc);
  1770. lwr = resolveProperties(sc, lwr);
  1771. lwr = lwr->optimize(WANTvalue);
  1772. if (!lwr->type)
  1773. {
  1774. error("invalid range lower bound %s", lwr->toChars());
  1775. return this;
  1776. }
  1777. upr = upr->semantic(sc);
  1778. upr = resolveProperties(sc, upr);
  1779. upr = upr->optimize(WANTvalue);
  1780. if (!upr->type)
  1781. {
  1782. error("invalid range upper bound %s", upr->toChars());
  1783. return this;
  1784. }
  1785. if (arg->type)
  1786. {
  1787. arg->type = arg->type->semantic(loc, sc);
  1788. lwr = lwr->implicitCastTo(sc, arg->type);
  1789. upr = upr->implicitCastTo(sc, arg->type);
  1790. }
  1791. else
  1792. {
  1793. /* Must infer types from lwr and upr
  1794. */
  1795. AddExp ea(loc, lwr, upr);
  1796. Expression *e = ea.typeCombine(sc);
  1797. if (e->op == TOKerror)
  1798. return this;
  1799. arg->type = ea.type->mutableOf();
  1800. lwr = ea.e1;
  1801. upr = ea.e2;
  1802. }
  1803. #if 1
  1804. /* Convert to a for loop:
  1805. * foreach (key; lwr .. upr) =>
  1806. * for (auto key = lwr, auto tmp = upr; key < tmp; ++key)
  1807. *
  1808. * foreach_reverse (key; lwr .. upr) =>
  1809. * for (auto tmp = lwr, auto key = upr; key-- > tmp;)
  1810. */
  1811. ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr);
  1812. key = new VarDeclaration(loc, arg->type, arg->ident, ie);
  1813. Identifier *id = Lexer::uniqueId("__limit");
  1814. ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr);
  1815. VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie);
  1816. Statements *cs = new Statements();
  1817. // Keep order of evaluation as lwr, then upr
  1818. if (op == TOKforeach)
  1819. {
  1820. cs->push(new ExpStatement(loc, key));
  1821. cs->push(new ExpStatement(loc, tmp));
  1822. }
  1823. else
  1824. {
  1825. cs->push(new ExpStatement(loc, tmp));
  1826. cs->push(new ExpStatement(loc, key));
  1827. }
  1828. Statement *forinit = new CompoundDeclarationStatement(loc, cs);
  1829. Expression *cond;
  1830. if (op == TOKforeach_reverse)
  1831. { // key-- > tmp
  1832. cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
  1833. cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp));
  1834. }
  1835. else
  1836. // key < tmp
  1837. cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp));
  1838. Expression *increment = NULL;
  1839. if (op == TOKforeach)
  1840. // key += 1
  1841. increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
  1842. ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
  1843. s = fs->semantic(sc);
  1844. return s;
  1845. #else
  1846. if (!arg->type->isscalar())
  1847. error("%s is not a scalar type", arg->type->toChars());
  1848. sym = new ScopeDsymbol();
  1849. sym->parent = sc->scopesym;
  1850. sc = sc->push(sym);
  1851. sc->noctor++;
  1852. key = new VarDeclaration(loc, arg->type, arg->ident, NULL);
  1853. DeclarationExp *de = new DeclarationExp(loc, key);
  1854. de->semantic(sc);
  1855. if (key->storage_class)
  1856. error("foreach range: key cannot have storage class");
  1857. sc->sbreak = this;
  1858. sc->scontinue = this;
  1859. body = body->semantic(sc);
  1860. sc->noctor--;
  1861. sc->pop();
  1862. return s;
  1863. #endif
  1864. }
  1865. int ForeachRangeStatement::hasBreak()
  1866. {
  1867. return TRUE;
  1868. }
  1869. int ForeachRangeStatement::hasContinue()
  1870. {
  1871. return TRUE;
  1872. }
  1873. int ForeachRangeStatement::usesEH()
  1874. {
  1875. assert(0);
  1876. return body->usesEH();
  1877. }
  1878. int ForeachRangeStatement::blockExit(bool mustNotThrow)
  1879. {
  1880. assert(0);
  1881. int result = BEfallthru;
  1882. if (lwr && lwr->canThrow())
  1883. result |= BEthrow;
  1884. else if (upr && upr->canThrow())
  1885. result |= BEthrow;
  1886. if (body)
  1887. {
  1888. result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue);
  1889. }
  1890. return result;
  1891. }
  1892. int ForeachRangeStatement::comeFrom()
  1893. {
  1894. assert(0);
  1895. if (body)
  1896. return body->comeFrom();
  1897. return FALSE;
  1898. }
  1899. void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  1900. {
  1901. buf->writestring(Token::toChars(op));
  1902. buf->writestring(" (");
  1903. if (arg->type)
  1904. arg->type->toCBuffer(buf, arg->ident, hgs);
  1905. else
  1906. buf->writestring(arg->ident->toChars());
  1907. buf->writestring("; ");
  1908. lwr->toCBuffer(buf, hgs);
  1909. buf->writestring(" .. ");
  1910. upr->toCBuffer(buf, hgs);
  1911. buf->writebyte(')');
  1912. buf->writenl();
  1913. buf->writebyte('{');
  1914. buf->writenl();
  1915. if (body)
  1916. body->toCBuffer(buf, hgs);
  1917. buf->writebyte('}');
  1918. buf->writenl();
  1919. }
  1920. #endif
  1921. /******************************** IfStatement ***************************/
  1922. IfStatement::IfStatement(Loc loc, Parameter *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
  1923. : Statement(loc)
  1924. {
  1925. this->arg = arg;
  1926. this->condition = condition;
  1927. this->ifbody = ifbody;
  1928. this->elsebody = elsebody;
  1929. this->match = NULL;
  1930. }
  1931. Statement *IfStatement::syntaxCopy()
  1932. {
  1933. Statement *i = NULL;
  1934. if (ifbody)
  1935. i = ifbody->syntaxCopy();
  1936. Statement *e = NULL;
  1937. if (elsebody)
  1938. e = elsebody->syntaxCopy();
  1939. Parameter *a = arg ? arg->syntaxCopy() : NULL;
  1940. IfStatement *s = new IfStatement(loc, a, condition->syntaxCopy(), i, e);
  1941. return s;
  1942. }
  1943. Statement *IfStatement::semantic(Scope *sc)
  1944. {
  1945. condition = condition->semantic(sc);
  1946. condition = resolveProperties(sc, condition);
  1947. condition = condition->checkToBoolean();
  1948. // If we can short-circuit evaluate the if statement, don't do the
  1949. // semantic analysis of the skipped code.
  1950. // This feature allows a limited form of conditional compilation.
  1951. condition = condition->optimize(WANTflags);
  1952. // Evaluate at runtime
  1953. unsigned cs0 = sc->callSuper;
  1954. unsigned cs1;
  1955. Scope *scd;
  1956. if (arg)
  1957. { /* Declare arg, which we will set to be the
  1958. * result of condition.
  1959. */
  1960. ScopeDsymbol *sym = new ScopeDsymbol();
  1961. sym->parent = sc->scopesym;
  1962. scd = sc->push(sym);
  1963. Type *t = arg->type ? arg->type : condition->type;
  1964. match = new VarDeclaration(loc, t, arg->ident, NULL);
  1965. match->noscope = 1;
  1966. match->semantic(scd);
  1967. if (!scd->insert(match))
  1968. assert(0);
  1969. match->parent = sc->func;
  1970. /* Generate:
  1971. * (arg = condition)
  1972. */
  1973. VarExp *v = new VarExp(0, match);
  1974. condition = new AssignExp(loc, v, condition);
  1975. condition = condition->semantic(scd);
  1976. }
  1977. else
  1978. scd = sc->push();
  1979. ifbody = ifbody->semanticNoScope(scd);
  1980. scd->pop();
  1981. cs1 = sc->callSuper;
  1982. sc->callSuper = cs0;
  1983. if (elsebody)
  1984. elsebody = elsebody->semanticScope(sc, NULL, NULL);
  1985. sc->mergeCallSuper(loc, cs1);
  1986. return this;
  1987. }
  1988. int IfStatement::usesEH()
  1989. {
  1990. return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
  1991. }
  1992. int IfStatement::blockExit(bool mustNotThrow)
  1993. {
  1994. //printf("IfStatement::blockExit(%p)\n", this);
  1995. int result = BEnone;
  1996. if (condition->canThrow())
  1997. result |= BEthrow;
  1998. if (condition->isBool(TRUE))
  1999. {
  2000. if (ifbody)
  2001. result |= ifbody->blockExit(mustNotThrow);
  2002. else
  2003. result |= BEfallthru;
  2004. }
  2005. else if (condition->isBool(FALSE))
  2006. {
  2007. if (elsebody)
  2008. result |= elsebody->blockExit(mustNotThrow);
  2009. else
  2010. result |= BEfallthru;
  2011. }
  2012. else
  2013. {
  2014. if (ifbody)
  2015. result |= ifbody->blockExit(mustNotThrow);
  2016. else
  2017. result |= BEfallthru;
  2018. if (elsebody)
  2019. result |= elsebody->blockExit(mustNotThrow);
  2020. else
  2021. result |= BEfallthru;
  2022. }
  2023. //printf("IfStatement::blockExit(%p) = x%x\n", this, result);
  2024. return result;
  2025. }
  2026. void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2027. {
  2028. buf->writestring("if (");
  2029. if (arg)
  2030. {
  2031. if (arg->type)
  2032. arg->type->toCBuffer(buf, arg->ident, hgs);
  2033. else
  2034. { buf->writestring("auto ");
  2035. buf->writestring(arg->ident->toChars());
  2036. }
  2037. buf->writestring(" = ");
  2038. }
  2039. condition->toCBuffer(buf, hgs);
  2040. buf->writebyte(')');
  2041. buf->writenl();
  2042. ifbody->toCBuffer(buf, hgs);
  2043. if (elsebody)
  2044. { buf->writestring("else");
  2045. buf->writenl();
  2046. elsebody->toCBuffer(buf, hgs);
  2047. }
  2048. }
  2049. /******************************** ConditionalStatement ***************************/
  2050. ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody)
  2051. : Statement(loc)
  2052. {
  2053. this->condition = condition;
  2054. this->ifbody = ifbody;
  2055. this->elsebody = elsebody;
  2056. }
  2057. Statement *ConditionalStatement::syntaxCopy()
  2058. {
  2059. Statement *e = NULL;
  2060. if (elsebody)
  2061. e = elsebody->syntaxCopy();
  2062. ConditionalStatement *s = new ConditionalStatement(loc,
  2063. condition->syntaxCopy(), ifbody->syntaxCopy(), e);
  2064. return s;
  2065. }
  2066. Statement *ConditionalStatement::semantic(Scope *sc)
  2067. {
  2068. //printf("ConditionalStatement::semantic()\n");
  2069. // If we can short-circuit evaluate the if statement, don't do the
  2070. // semantic analysis of the skipped code.
  2071. // This feature allows a limited form of conditional compilation.
  2072. if (condition->include(sc, NULL))
  2073. {
  2074. ifbody = ifbody->semantic(sc);
  2075. return ifbody;
  2076. }
  2077. else
  2078. {
  2079. if (elsebody)
  2080. elsebody = elsebody->semantic(sc);
  2081. return elsebody;
  2082. }
  2083. }
  2084. Statements *ConditionalStatement::flatten(Scope *sc)
  2085. {
  2086. Statement *s;
  2087. if (condition->include(sc, NULL))
  2088. s = ifbody;
  2089. else
  2090. s = elsebody;
  2091. Statements *a = new Statements();
  2092. a->push(s);
  2093. return a;
  2094. }
  2095. int ConditionalStatement::usesEH()
  2096. {
  2097. return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
  2098. }
  2099. int ConditionalStatement::blockExit(bool mustNotThrow)
  2100. {
  2101. int result = ifbody->blockExit(mustNotThrow);
  2102. if (elsebody)
  2103. result |= elsebody->blockExit(mustNotThrow);
  2104. return result;
  2105. }
  2106. void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2107. {
  2108. condition->toCBuffer(buf, hgs);
  2109. buf->writenl();
  2110. buf->writeByte('{');
  2111. buf->writenl();
  2112. if (ifbody)
  2113. ifbody->toCBuffer(buf, hgs);
  2114. buf->writeByte('}');
  2115. buf->writenl();
  2116. if (elsebody)
  2117. {
  2118. buf->writestring("else");
  2119. buf->writenl();
  2120. buf->writeByte('{');
  2121. buf->writenl();
  2122. elsebody->toCBuffer(buf, hgs);
  2123. buf->writeByte('}');
  2124. buf->writenl();
  2125. }
  2126. buf->writenl();
  2127. }
  2128. /******************************** PragmaStatement ***************************/
  2129. PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body)
  2130. : Statement(loc)
  2131. {
  2132. this->ident = ident;
  2133. this->args = args;
  2134. this->body = body;
  2135. }
  2136. Statement *PragmaStatement::syntaxCopy()
  2137. {
  2138. Statement *b = NULL;
  2139. if (body)
  2140. b = body->syntaxCopy();
  2141. PragmaStatement *s = new PragmaStatement(loc,
  2142. ident, Expression::arraySyntaxCopy(args), b);
  2143. return s;
  2144. }
  2145. Statement *PragmaStatement::semantic(Scope *sc)
  2146. { // Should be merged with PragmaDeclaration
  2147. //printf("PragmaStatement::semantic() %s\n", toChars());
  2148. //printf("body = %p\n", body);
  2149. if (ident == Id::msg)
  2150. {
  2151. if (args)
  2152. {
  2153. for (size_t i = 0; i < args->dim; i++)
  2154. {
  2155. Expression *e = args->tdata()[i];
  2156. e = e->semantic(sc);
  2157. e = e->optimize(WANTvalue | WANTinterpret);
  2158. StringExp *se = e->toString();
  2159. if (se)
  2160. {
  2161. fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
  2162. }
  2163. else
  2164. fprintf(stdmsg, "%s", e->toChars());
  2165. }
  2166. fprintf(stdmsg, "\n");
  2167. }
  2168. }
  2169. else if (ident == Id::lib)
  2170. {
  2171. #if 1
  2172. /* Should this be allowed?
  2173. */
  2174. error("pragma(lib) not allowed as statement");
  2175. #else
  2176. if (!args || args->dim != 1)
  2177. error("string expected for library name");
  2178. else
  2179. {
  2180. Expression *e = args->tdata()[0];
  2181. e = e->semantic(sc);
  2182. e = e->optimize(WANTvalue | WANTinterpret);
  2183. args->tdata()[0] = e;
  2184. StringExp *se = e->toString();
  2185. if (!se)
  2186. error("string expected for library name, not '%s'", e->toChars());
  2187. else if (global.params.verbose)
  2188. {
  2189. char *name = (char *)mem.malloc(se->len + 1);
  2190. memcpy(name, se->string, se->len);
  2191. name[se->len] = 0;
  2192. printf("library %s\n", name);
  2193. mem.free(name);
  2194. }
  2195. }
  2196. #endif
  2197. }
  2198. #if DMDV2
  2199. else if (ident == Id::startaddress)
  2200. {
  2201. if (!args || args->dim != 1)
  2202. error("function name expected for start address");
  2203. else
  2204. {
  2205. Expression *e = (Expression *)args->data[0];
  2206. e = e->semantic(sc);
  2207. e = e->optimize(WANTvalue | WANTinterpret);
  2208. args->data[0] = (void *)e;
  2209. Dsymbol *sa = getDsymbol(e);
  2210. if (!sa || !sa->isFuncDeclaration())
  2211. error("function name expected for start address, not '%s'", e->toChars());
  2212. if (body)
  2213. {
  2214. body = body->semantic(sc);
  2215. }
  2216. return this;
  2217. }
  2218. }
  2219. #endif
  2220. else
  2221. error("unrecognized pragma(%s)", ident->toChars());
  2222. if (body)
  2223. {
  2224. body = body->semantic(sc);
  2225. }
  2226. return body;
  2227. }
  2228. int PragmaStatement::usesEH()
  2229. {
  2230. return body && body->usesEH();
  2231. }
  2232. int PragmaStatement::blockExit(bool mustNotThrow)
  2233. {
  2234. int result = BEfallthru;
  2235. #if 0 // currently, no code is generated for Pragma's, so it's just fallthru
  2236. if (arrayExpressionCanThrow(args))
  2237. result |= BEthrow;
  2238. if (body)
  2239. result |= body->blockExit(mustNotThrow);
  2240. #endif
  2241. return result;
  2242. }
  2243. void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2244. {
  2245. buf->writestring("pragma (");
  2246. buf->writestring(ident->toChars());
  2247. if (args && args->dim)
  2248. {
  2249. buf->writestring(", ");
  2250. argsToCBuffer(buf, args, hgs);
  2251. }
  2252. buf->writeByte(')');
  2253. if (body)
  2254. {
  2255. buf->writenl();
  2256. buf->writeByte('{');
  2257. buf->writenl();
  2258. body->toCBuffer(buf, hgs);
  2259. buf->writeByte('}');
  2260. buf->writenl();
  2261. }
  2262. else
  2263. {
  2264. buf->writeByte(';');
  2265. buf->writenl();
  2266. }
  2267. }
  2268. /******************************** StaticAssertStatement ***************************/
  2269. StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
  2270. : Statement(sa->loc)
  2271. {
  2272. this->sa = sa;
  2273. }
  2274. Statement *StaticAssertStatement::syntaxCopy()
  2275. {
  2276. StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
  2277. return s;
  2278. }
  2279. Statement *StaticAssertStatement::semantic(Scope *sc)
  2280. {
  2281. sa->semantic2(sc);
  2282. return NULL;
  2283. }
  2284. int StaticAssertStatement::blockExit(bool mustNotThrow)
  2285. {
  2286. return BEfallthru;
  2287. }
  2288. void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2289. {
  2290. sa->toCBuffer(buf, hgs);
  2291. }
  2292. /******************************** SwitchStatement ***************************/
  2293. SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
  2294. : Statement(loc)
  2295. {
  2296. condition = c;
  2297. body = b;
  2298. sdefault = NULL;
  2299. cases = NULL;
  2300. hasNoDefault = 0;
  2301. }
  2302. Statement *SwitchStatement::syntaxCopy()
  2303. {
  2304. SwitchStatement *s = new SwitchStatement(loc,
  2305. condition->syntaxCopy(), body->syntaxCopy());
  2306. return s;
  2307. }
  2308. Statement *SwitchStatement::semantic(Scope *sc)
  2309. {
  2310. //printf("SwitchStatement::semantic(%p)\n", this);
  2311. assert(!cases); // ensure semantic() is only run once
  2312. condition = condition->semantic(sc);
  2313. condition = resolveProperties(sc, condition);
  2314. if (condition->type->isString())
  2315. {
  2316. // If it's not an array, cast it to one
  2317. if (condition->type->ty != Tarray)
  2318. {
  2319. condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf());
  2320. }
  2321. }
  2322. else
  2323. { condition = condition->integralPromotions(sc);
  2324. condition->checkIntegral();
  2325. }
  2326. condition = condition->optimize(WANTvalue);
  2327. sc = sc->push();
  2328. sc->sbreak = this;
  2329. sc->sw = this;
  2330. cases = new CaseStatements();
  2331. sc->noctor++; // BUG: should use Scope::mergeCallSuper() for each case instead
  2332. body = body->semantic(sc);
  2333. sc->noctor--;
  2334. // Resolve any goto case's with exp
  2335. for (size_t i = 0; i < gotoCases.dim; i++)
  2336. {
  2337. GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i];
  2338. if (!gcs->exp)
  2339. {
  2340. gcs->error("no case statement following goto case;");
  2341. break;
  2342. }
  2343. for (Scope *scx = sc; scx; scx = scx->enclosing)
  2344. {
  2345. if (!scx->sw)
  2346. continue;
  2347. for (size_t j = 0; j < scx->sw->cases->dim; j++)
  2348. {
  2349. CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j];
  2350. if (cs->exp->equals(gcs->exp))
  2351. {
  2352. gcs->cs = cs;
  2353. goto Lfoundcase;
  2354. }
  2355. }
  2356. }
  2357. gcs->error("case %s not found", gcs->exp->toChars());
  2358. Lfoundcase:
  2359. ;
  2360. }
  2361. if (!sc->sw->sdefault)
  2362. { hasNoDefault = 1;
  2363. warning("switch statement has no default");
  2364. // Generate runtime error if the default is hit
  2365. Statements *a = new Statements();
  2366. CompoundStatement *cs;
  2367. Statement *s;
  2368. if (global.params.useSwitchError)
  2369. s = new SwitchErrorStatement(loc);
  2370. else
  2371. { Expression *e = new HaltExp(loc);
  2372. s = new ExpStatement(loc, e);
  2373. }
  2374. a->reserve(4);
  2375. a->push(body);
  2376. a->push(new BreakStatement(loc, NULL));
  2377. sc->sw->sdefault = new DefaultStatement(loc, s);
  2378. a->push(sc->sw->sdefault);
  2379. cs = new CompoundStatement(loc, a);
  2380. body = cs;
  2381. }
  2382. #if DMDV2
  2383. if (isFinal)
  2384. { Type *t = condition->type;
  2385. while (t->ty == Ttypedef)
  2386. { // Don't use toBasetype() because that will skip past enums
  2387. t = ((TypeTypedef *)t)->sym->basetype;
  2388. }
  2389. if (condition->type->ty == Tenum)
  2390. { TypeEnum *te = (TypeEnum *)condition->type;
  2391. EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration();
  2392. assert(ed);
  2393. size_t dim = ed->members->dim;
  2394. for (size_t i = 0; i < dim; i++)
  2395. {
  2396. EnumMember *em = ((Dsymbol *)ed->members->data[i])->isEnumMember();
  2397. if (em)
  2398. {
  2399. for (size_t j = 0; j < cases->dim; j++)
  2400. { CaseStatement *cs = (CaseStatement *)cases->data[j];
  2401. if (cs->exp->equals(em->value))
  2402. goto L1;
  2403. }
  2404. error("enum member %s not represented in final switch", em->toChars());
  2405. }
  2406. L1:
  2407. ;
  2408. }
  2409. }
  2410. }
  2411. #endif
  2412. sc->pop();
  2413. return this;
  2414. }
  2415. int SwitchStatement::hasBreak()
  2416. {
  2417. return TRUE;
  2418. }
  2419. int SwitchStatement::usesEH()
  2420. {
  2421. return body ? body->usesEH() : 0;
  2422. }
  2423. int SwitchStatement::blockExit(bool mustNotThrow)
  2424. { int result = BEnone;
  2425. if (condition->canThrow())
  2426. result |= BEthrow;
  2427. if (body)
  2428. { result |= body->blockExit(mustNotThrow);
  2429. if (result & BEbreak)
  2430. { result |= BEfallthru;
  2431. result &= ~BEbreak;
  2432. }
  2433. }
  2434. else
  2435. result |= BEfallthru;
  2436. return result;
  2437. }
  2438. void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2439. {
  2440. buf->writestring("switch (");
  2441. condition->toCBuffer(buf, hgs);
  2442. buf->writebyte(')');
  2443. buf->writenl();
  2444. if (body)
  2445. {
  2446. if (!body->isScopeStatement())
  2447. { buf->writebyte('{');
  2448. buf->writenl();
  2449. body->toCBuffer(buf, hgs);
  2450. buf->writebyte('}');
  2451. buf->writenl();
  2452. }
  2453. else
  2454. {
  2455. body->toCBuffer(buf, hgs);
  2456. }
  2457. }
  2458. }
  2459. /******************************** CaseStatement ***************************/
  2460. CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s)
  2461. : Statement(loc)
  2462. {
  2463. this->exp = exp;
  2464. this->statement = s;
  2465. cblock = NULL;
  2466. }
  2467. Statement *CaseStatement::syntaxCopy()
  2468. {
  2469. CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy());
  2470. return s;
  2471. }
  2472. Statement *CaseStatement::semantic(Scope *sc)
  2473. { SwitchStatement *sw = sc->sw;
  2474. //printf("CaseStatement::semantic() %s\n", toChars());
  2475. exp = exp->semantic(sc);
  2476. if (sw)
  2477. {
  2478. exp = exp->implicitCastTo(sc, sw->condition->type);
  2479. exp = exp->optimize(WANTvalue | WANTinterpret);
  2480. if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror)
  2481. {
  2482. error("case must be a string or an integral constant, not %s", exp->toChars());
  2483. exp = new IntegerExp(0);
  2484. }
  2485. for (size_t i = 0; i < sw->cases->dim; i++)
  2486. {
  2487. CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
  2488. //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
  2489. if (cs->exp->equals(exp))
  2490. { error("duplicate case %s in switch statement", exp->toChars());
  2491. break;
  2492. }
  2493. }
  2494. sw->cases->push(this);
  2495. // Resolve any goto case's with no exp to this case statement
  2496. for (size_t i = 0; i < sw->gotoCases.dim; i++)
  2497. {
  2498. GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
  2499. if (!gcs->exp)
  2500. {
  2501. gcs->cs = this;
  2502. sw->gotoCases.remove(i); // remove from array
  2503. }
  2504. }
  2505. }
  2506. else
  2507. error("case not in switch statement");
  2508. statement = statement->semantic(sc);
  2509. return this;
  2510. }
  2511. int CaseStatement::compare(Object *obj)
  2512. {
  2513. // Sort cases so we can do an efficient lookup
  2514. CaseStatement *cs2 = (CaseStatement *)(obj);
  2515. return exp->compare(cs2->exp);
  2516. }
  2517. int CaseStatement::usesEH()
  2518. {
  2519. return statement->usesEH();
  2520. }
  2521. int CaseStatement::blockExit(bool mustNotThrow)
  2522. {
  2523. return statement->blockExit(mustNotThrow);
  2524. }
  2525. int CaseStatement::comeFrom()
  2526. {
  2527. return TRUE;
  2528. }
  2529. void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2530. {
  2531. buf->writestring("case ");
  2532. exp->toCBuffer(buf, hgs);
  2533. buf->writebyte(':');
  2534. buf->writenl();
  2535. statement->toCBuffer(buf, hgs);
  2536. }
  2537. /******************************** CaseRangeStatement ***************************/
  2538. #if DMDV2
  2539. CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first,
  2540. Expression *last, Statement *s)
  2541. : Statement(loc)
  2542. {
  2543. this->first = first;
  2544. this->last = last;
  2545. this->statement = s;
  2546. }
  2547. Statement *CaseRangeStatement::syntaxCopy()
  2548. {
  2549. CaseRangeStatement *s = new CaseRangeStatement(loc,
  2550. first->syntaxCopy(), last->syntaxCopy(), statement->syntaxCopy());
  2551. return s;
  2552. }
  2553. Statement *CaseRangeStatement::semantic(Scope *sc)
  2554. { SwitchStatement *sw = sc->sw;
  2555. //printf("CaseRangeStatement::semantic() %s\n", toChars());
  2556. if (sw->isFinal)
  2557. error("case ranges not allowed in final switch");
  2558. first = first->semantic(sc);
  2559. first = first->implicitCastTo(sc, sw->condition->type);
  2560. first = first->optimize(WANTvalue | WANTinterpret);
  2561. last = last->semantic(sc);
  2562. last = last->implicitCastTo(sc, sw->condition->type);
  2563. last = last->optimize(WANTvalue | WANTinterpret);
  2564. if (first->op == TOKerror || last->op == TOKerror)
  2565. return statement ? statement->semantic(sc) : NULL;
  2566. dinteger_t fval = first->toInteger();
  2567. dinteger_t lval = last->toInteger();
  2568. if (lval - fval > 256)
  2569. { error("more than 256 cases in case range");
  2570. lval = fval + 256;
  2571. }
  2572. /* This works by replacing the CaseRange with an array of Case's.
  2573. *
  2574. * case a: .. case b: s;
  2575. * =>
  2576. * case a:
  2577. * [...]
  2578. * case b:
  2579. * s;
  2580. */
  2581. Statements *statements = new Statements();
  2582. for (dinteger_t i = fval; i <= lval; i++)
  2583. {
  2584. Statement *s = statement;
  2585. if (i != lval)
  2586. s = new ExpStatement(loc, NULL);
  2587. Expression *e = new IntegerExp(loc, i, first->type);
  2588. Statement *cs = new CaseStatement(loc, e, s);
  2589. statements->push(cs);
  2590. }
  2591. Statement *s = new CompoundStatement(loc, statements);
  2592. s = s->semantic(sc);
  2593. return s;
  2594. }
  2595. void CaseRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2596. {
  2597. buf->writestring("case ");
  2598. first->toCBuffer(buf, hgs);
  2599. buf->writestring(": .. case ");
  2600. last->toCBuffer(buf, hgs);
  2601. buf->writenl();
  2602. statement->toCBuffer(buf, hgs);
  2603. }
  2604. #endif
  2605. /******************************** DefaultStatement ***************************/
  2606. DefaultStatement::DefaultStatement(Loc loc, Statement *s)
  2607. : Statement(loc)
  2608. {
  2609. this->statement = s;
  2610. #if IN_GCC
  2611. cblock = NULL;
  2612. #endif
  2613. }
  2614. Statement *DefaultStatement::syntaxCopy()
  2615. {
  2616. DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy());
  2617. return s;
  2618. }
  2619. Statement *DefaultStatement::semantic(Scope *sc)
  2620. {
  2621. //printf("DefaultStatement::semantic()\n");
  2622. if (sc->sw)
  2623. {
  2624. if (sc->sw->sdefault)
  2625. {
  2626. error("switch statement already has a default");
  2627. }
  2628. sc->sw->sdefault = this;
  2629. }
  2630. else
  2631. error("default not in switch statement");
  2632. statement = statement->semantic(sc);
  2633. return this;
  2634. }
  2635. int DefaultStatement::usesEH()
  2636. {
  2637. return statement->usesEH();
  2638. }
  2639. int DefaultStatement::blockExit(bool mustNotThrow)
  2640. {
  2641. return statement->blockExit(mustNotThrow);
  2642. }
  2643. int DefaultStatement::comeFrom()
  2644. {
  2645. return TRUE;
  2646. }
  2647. void DefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2648. {
  2649. buf->writestring("default:\n");
  2650. statement->toCBuffer(buf, hgs);
  2651. }
  2652. /******************************** GotoDefaultStatement ***************************/
  2653. GotoDefaultStatement::GotoDefaultStatement(Loc loc)
  2654. : Statement(loc)
  2655. {
  2656. sw = NULL;
  2657. }
  2658. Statement *GotoDefaultStatement::syntaxCopy()
  2659. {
  2660. GotoDefaultStatement *s = new GotoDefaultStatement(loc);
  2661. return s;
  2662. }
  2663. Statement *GotoDefaultStatement::semantic(Scope *sc)
  2664. {
  2665. sw = sc->sw;
  2666. if (!sw)
  2667. error("goto default not in switch statement");
  2668. return this;
  2669. }
  2670. int GotoDefaultStatement::blockExit(bool mustNotThrow)
  2671. {
  2672. return BEgoto;
  2673. }
  2674. void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2675. {
  2676. buf->writestring("goto default;\n");
  2677. }
  2678. /******************************** GotoCaseStatement ***************************/
  2679. GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
  2680. : Statement(loc)
  2681. {
  2682. cs = NULL;
  2683. this->exp = exp;
  2684. }
  2685. Statement *GotoCaseStatement::syntaxCopy()
  2686. {
  2687. Expression *e = exp ? exp->syntaxCopy() : NULL;
  2688. GotoCaseStatement *s = new GotoCaseStatement(loc, e);
  2689. return s;
  2690. }
  2691. Statement *GotoCaseStatement::semantic(Scope *sc)
  2692. {
  2693. if (exp)
  2694. exp = exp->semantic(sc);
  2695. if (!sc->sw)
  2696. error("goto case not in switch statement");
  2697. else
  2698. {
  2699. sc->sw->gotoCases.push(this);
  2700. if (exp)
  2701. {
  2702. exp = exp->implicitCastTo(sc, sc->sw->condition->type);
  2703. exp = exp->optimize(WANTvalue);
  2704. }
  2705. }
  2706. return this;
  2707. }
  2708. int GotoCaseStatement::blockExit(bool mustNotThrow)
  2709. {
  2710. return BEgoto;
  2711. }
  2712. void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2713. {
  2714. buf->writestring("goto case");
  2715. if (exp)
  2716. { buf->writebyte(' ');
  2717. exp->toCBuffer(buf, hgs);
  2718. }
  2719. buf->writebyte(';');
  2720. buf->writenl();
  2721. }
  2722. /******************************** SwitchErrorStatement ***************************/
  2723. SwitchErrorStatement::SwitchErrorStatement(Loc loc)
  2724. : Statement(loc)
  2725. {
  2726. }
  2727. int SwitchErrorStatement::blockExit(bool mustNotThrow)
  2728. {
  2729. return BEthrow;
  2730. }
  2731. void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2732. {
  2733. buf->writestring("SwitchErrorStatement::toCBuffer()");
  2734. buf->writenl();
  2735. }
  2736. /******************************** ReturnStatement ***************************/
  2737. ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
  2738. : Statement(loc)
  2739. {
  2740. this->exp = exp;
  2741. }
  2742. Statement *ReturnStatement::syntaxCopy()
  2743. {
  2744. Expression *e = NULL;
  2745. if (exp)
  2746. e = exp->syntaxCopy();
  2747. ReturnStatement *s = new ReturnStatement(loc, e);
  2748. return s;
  2749. }
  2750. Statement *ReturnStatement::semantic(Scope *sc)
  2751. {
  2752. //printf("ReturnStatement::semantic() %s\n", toChars());
  2753. FuncDeclaration *fd = sc->parent->isFuncDeclaration();
  2754. Scope *scx = sc;
  2755. int implicit0 = 0;
  2756. if (sc->fes)
  2757. {
  2758. // Find scope of function foreach is in
  2759. for (; 1; scx = scx->enclosing)
  2760. {
  2761. assert(scx);
  2762. if (scx->func != fd)
  2763. { fd = scx->func; // fd is now function enclosing foreach
  2764. break;
  2765. }
  2766. }
  2767. }
  2768. Type *tret = fd->type->nextOf();
  2769. if (fd->tintro)
  2770. /* We'll be implicitly casting the return expression to tintro
  2771. */
  2772. tret = fd->tintro->nextOf();
  2773. Type *tbret = NULL;
  2774. if (tret)
  2775. tbret = tret->toBasetype();
  2776. // main() returns 0, even if it returns void
  2777. if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain())
  2778. { implicit0 = 1;
  2779. exp = new IntegerExp(0);
  2780. }
  2781. if (sc->incontract || scx->incontract)
  2782. error("return statements cannot be in contracts");
  2783. if (sc->tf || scx->tf)
  2784. error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
  2785. if (fd->isCtorDeclaration())
  2786. {
  2787. // Constructors implicitly do:
  2788. // return this;
  2789. if (exp && exp->op != TOKthis)
  2790. error("cannot return expression from constructor");
  2791. exp = new ThisExp(0);
  2792. }
  2793. if (!exp)
  2794. fd->nrvo_can = 0;
  2795. if (exp)
  2796. {
  2797. fd->hasReturnExp |= 1;
  2798. exp = exp->semantic(sc);
  2799. exp = resolveProperties(sc, exp);
  2800. exp = exp->optimize(WANTvalue);
  2801. if (fd->nrvo_can && exp->op == TOKvar)
  2802. { VarExp *ve = (VarExp *)exp;
  2803. VarDeclaration *v = ve->var->isVarDeclaration();
  2804. if (!v || v->isOut() || v->isRef())
  2805. fd->nrvo_can = 0;
  2806. else if (fd->nrvo_var == NULL)
  2807. { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
  2808. { //printf("Setting nrvo to %s\n", v->toChars());
  2809. fd->nrvo_var = v;
  2810. }
  2811. else
  2812. fd->nrvo_can = 0;
  2813. }
  2814. else if (fd->nrvo_var != v)
  2815. fd->nrvo_can = 0;
  2816. }
  2817. else
  2818. fd->nrvo_can = 0;
  2819. if (fd->returnLabel && tbret->ty != Tvoid)
  2820. {
  2821. }
  2822. else if (fd->inferRetType)
  2823. {
  2824. Type *tfret = fd->type->nextOf();
  2825. if (tfret)
  2826. {
  2827. if (tfret != Type::terror && !exp->type->equals(tfret))
  2828. error("mismatched function return type inference of %s and %s",
  2829. exp->type->toChars(), tfret->toChars());
  2830. }
  2831. else
  2832. {
  2833. fd->type->next = exp->type;
  2834. fd->type = fd->type->semantic(loc, sc);
  2835. if (!fd->tintro)
  2836. { tret = fd->type->nextOf();
  2837. tbret = tret->toBasetype();
  2838. }
  2839. }
  2840. }
  2841. else if (tbret->ty != Tvoid)
  2842. {
  2843. if (fd->tintro)
  2844. exp = exp->implicitCastTo(sc, fd->type->nextOf());
  2845. exp = exp->implicitCastTo(sc, tret);
  2846. }
  2847. }
  2848. else if (fd->inferRetType)
  2849. {
  2850. if (fd->type->nextOf())
  2851. {
  2852. if (fd->type->nextOf()->ty != Tvoid)
  2853. error("mismatched function return type inference of void and %s",
  2854. fd->type->nextOf()->toChars());
  2855. }
  2856. else
  2857. {
  2858. fd->type->next = Type::tvoid;
  2859. fd->type = fd->type->semantic(loc, sc);
  2860. if (!fd->tintro)
  2861. { tret = Type::tvoid;
  2862. tbret = tret;
  2863. }
  2864. }
  2865. }
  2866. else if (tbret->ty != Tvoid) // if non-void return
  2867. error("return expression expected");
  2868. if (sc->fes)
  2869. {
  2870. Statement *s;
  2871. if (exp && !implicit0)
  2872. {
  2873. exp = exp->implicitCastTo(sc, tret);
  2874. }
  2875. if (!exp || exp->op == TOKint64 || exp->op == TOKfloat64 ||
  2876. exp->op == TOKimaginary80 || exp->op == TOKcomplex80 ||
  2877. exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull ||
  2878. exp->op == TOKstring)
  2879. {
  2880. sc->fes->cases->push(this);
  2881. // Construct: return cases->dim+1;
  2882. s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
  2883. }
  2884. else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
  2885. {
  2886. s = new ReturnStatement(0, NULL);
  2887. sc->fes->cases->push(s);
  2888. // Construct: { exp; return cases->dim + 1; }
  2889. Statement *s1 = new ExpStatement(loc, exp);
  2890. Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
  2891. s = new CompoundStatement(loc, s1, s2);
  2892. }
  2893. else
  2894. {
  2895. // Construct: return vresult;
  2896. if (!fd->vresult)
  2897. { // Declare vresult
  2898. VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
  2899. v->noscope = 1;
  2900. v->semantic(scx);
  2901. if (!scx->insert(v))
  2902. assert(0);
  2903. v->parent = fd;
  2904. fd->vresult = v;
  2905. }
  2906. s = new ReturnStatement(0, new VarExp(0, fd->vresult));
  2907. sc->fes->cases->push(s);
  2908. // Construct: { vresult = exp; return cases->dim + 1; }
  2909. exp = new ConstructExp(loc, new VarExp(0, fd->vresult), exp);
  2910. exp = exp->semantic(sc);
  2911. Statement *s1 = new ExpStatement(loc, exp);
  2912. Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
  2913. s = new CompoundStatement(loc, s1, s2);
  2914. }
  2915. return s;
  2916. }
  2917. if (exp)
  2918. {
  2919. if (fd->returnLabel && tbret->ty != Tvoid)
  2920. {
  2921. assert(fd->vresult);
  2922. VarExp *v = new VarExp(0, fd->vresult);
  2923. exp = new AssignExp(loc, v, exp);
  2924. exp->op = TOKconstruct;
  2925. exp = exp->semantic(sc);
  2926. }
  2927. //exp->dump(0);
  2928. //exp->print();
  2929. exp->checkEscape();
  2930. }
  2931. /* BUG: need to issue an error on:
  2932. * this
  2933. * { if (x) return;
  2934. * super();
  2935. * }
  2936. */
  2937. if (sc->callSuper & CSXany_ctor &&
  2938. !(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor)))
  2939. error("return without calling constructor");
  2940. sc->callSuper |= CSXreturn;
  2941. // See if all returns are instead to be replaced with a goto returnLabel;
  2942. if (fd->returnLabel)
  2943. {
  2944. GotoStatement *gs = new GotoStatement(loc, Id::returnLabel);
  2945. gs->label = fd->returnLabel;
  2946. if (exp)
  2947. { /* Replace: return exp;
  2948. * with: exp; goto returnLabel;
  2949. */
  2950. Statement *s = new ExpStatement(0, exp);
  2951. return new CompoundStatement(loc, s, gs);
  2952. }
  2953. return gs;
  2954. }
  2955. if (exp && tbret->ty == Tvoid && !implicit0)
  2956. {
  2957. /* Replace:
  2958. * return exp;
  2959. * with:
  2960. * exp; return;
  2961. */
  2962. Statement *s = new ExpStatement(loc, exp);
  2963. exp = NULL;
  2964. s = s->semantic(sc);
  2965. return new CompoundStatement(loc, s, this);
  2966. }
  2967. return this;
  2968. }
  2969. int ReturnStatement::blockExit(bool mustNotThrow)
  2970. { int result = BEreturn;
  2971. if (exp && exp->canThrow())
  2972. result |= BEthrow;
  2973. return result;
  2974. }
  2975. void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  2976. {
  2977. buf->printf("return ");
  2978. if (exp)
  2979. exp->toCBuffer(buf, hgs);
  2980. buf->writeByte(';');
  2981. buf->writenl();
  2982. }
  2983. /******************************** BreakStatement ***************************/
  2984. BreakStatement::BreakStatement(Loc loc, Identifier *ident)
  2985. : Statement(loc)
  2986. {
  2987. this->ident = ident;
  2988. }
  2989. Statement *BreakStatement::syntaxCopy()
  2990. {
  2991. BreakStatement *s = new BreakStatement(loc, ident);
  2992. return s;
  2993. }
  2994. Statement *BreakStatement::semantic(Scope *sc)
  2995. {
  2996. //printf("BreakStatement::semantic()\n");
  2997. // If:
  2998. // break Identifier;
  2999. if (ident)
  3000. {
  3001. Scope *scx;
  3002. FuncDeclaration *thisfunc = sc->func;
  3003. for (scx = sc; scx; scx = scx->enclosing)
  3004. {
  3005. LabelStatement *ls;
  3006. if (scx->func != thisfunc) // if in enclosing function
  3007. {
  3008. if (sc->fes) // if this is the body of a foreach
  3009. {
  3010. /* Post this statement to the fes, and replace
  3011. * it with a return value that caller will put into
  3012. * a switch. Caller will figure out where the break
  3013. * label actually is.
  3014. * Case numbers start with 2, not 0, as 0 is continue
  3015. * and 1 is break.
  3016. */
  3017. Statement *s;
  3018. sc->fes->cases->push(this);
  3019. s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
  3020. return s;
  3021. }
  3022. break; // can't break to it
  3023. }
  3024. ls = scx->slabel;
  3025. if (ls && ls->ident == ident)
  3026. {
  3027. Statement *s = ls->statement;
  3028. if (!s->hasBreak())
  3029. error("label '%s' has no break", ident->toChars());
  3030. if (ls->tf != sc->tf)
  3031. error("cannot break out of finally block");
  3032. return this;
  3033. }
  3034. }
  3035. error("enclosing label '%s' for break not found", ident->toChars());
  3036. }
  3037. else if (!sc->sbreak)
  3038. {
  3039. if (sc->fes)
  3040. { Statement *s;
  3041. // Replace break; with return 1;
  3042. s = new ReturnStatement(0, new IntegerExp(1));
  3043. return s;
  3044. }
  3045. error("break is not inside a loop or switch");
  3046. }
  3047. return this;
  3048. }
  3049. int BreakStatement::blockExit(bool mustNotThrow)
  3050. {
  3051. //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
  3052. return ident ? BEgoto : BEbreak;
  3053. }
  3054. void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3055. {
  3056. buf->writestring("break");
  3057. if (ident)
  3058. { buf->writebyte(' ');
  3059. buf->writestring(ident->toChars());
  3060. }
  3061. buf->writebyte(';');
  3062. buf->writenl();
  3063. }
  3064. /******************************** ContinueStatement ***************************/
  3065. ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
  3066. : Statement(loc)
  3067. {
  3068. this->ident = ident;
  3069. }
  3070. Statement *ContinueStatement::syntaxCopy()
  3071. {
  3072. ContinueStatement *s = new ContinueStatement(loc, ident);
  3073. return s;
  3074. }
  3075. Statement *ContinueStatement::semantic(Scope *sc)
  3076. {
  3077. //printf("ContinueStatement::semantic() %p\n", this);
  3078. if (ident)
  3079. {
  3080. Scope *scx;
  3081. FuncDeclaration *thisfunc = sc->func;
  3082. for (scx = sc; scx; scx = scx->enclosing)
  3083. {
  3084. LabelStatement *ls;
  3085. if (scx->func != thisfunc) // if in enclosing function
  3086. {
  3087. if (sc->fes) // if this is the body of a foreach
  3088. {
  3089. for (; scx; scx = scx->enclosing)
  3090. {
  3091. ls = scx->slabel;
  3092. if (ls && ls->ident == ident && ls->statement == sc->fes)
  3093. {
  3094. // Replace continue ident; with return 0;
  3095. return new ReturnStatement(0, new IntegerExp(0));
  3096. }
  3097. }
  3098. /* Post this statement to the fes, and replace
  3099. * it with a return value that caller will put into
  3100. * a switch. Caller will figure out where the break
  3101. * label actually is.
  3102. * Case numbers start with 2, not 0, as 0 is continue
  3103. * and 1 is break.
  3104. */
  3105. Statement *s;
  3106. sc->fes->cases->push(this);
  3107. s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
  3108. return s;
  3109. }
  3110. break; // can't continue to it
  3111. }
  3112. ls = scx->slabel;
  3113. if (ls && ls->ident == ident)
  3114. {
  3115. Statement *s = ls->statement;
  3116. if (!s->hasContinue())
  3117. error("label '%s' has no continue", ident->toChars());
  3118. if (ls->tf != sc->tf)
  3119. error("cannot continue out of finally block");
  3120. return this;
  3121. }
  3122. }
  3123. error("enclosing label '%s' for continue not found", ident->toChars());
  3124. }
  3125. else if (!sc->scontinue)
  3126. {
  3127. if (sc->fes)
  3128. { Statement *s;
  3129. // Replace continue; with return 0;
  3130. s = new ReturnStatement(0, new IntegerExp(0));
  3131. return s;
  3132. }
  3133. error("continue is not inside a loop");
  3134. }
  3135. return this;
  3136. }
  3137. int ContinueStatement::blockExit(bool mustNotThrow)
  3138. {
  3139. return ident ? BEgoto : BEcontinue;
  3140. }
  3141. void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3142. {
  3143. buf->writestring("continue");
  3144. if (ident)
  3145. { buf->writebyte(' ');
  3146. buf->writestring(ident->toChars());
  3147. }
  3148. buf->writebyte(';');
  3149. buf->writenl();
  3150. }
  3151. /******************************** SynchronizedStatement ***************************/
  3152. SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body)
  3153. : Statement(loc)
  3154. {
  3155. this->exp = exp;
  3156. this->body = body;
  3157. this->esync = NULL;
  3158. }
  3159. SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body)
  3160. : Statement(loc)
  3161. {
  3162. this->exp = NULL;
  3163. this->body = body;
  3164. this->esync = esync;
  3165. }
  3166. Statement *SynchronizedStatement::syntaxCopy()
  3167. {
  3168. Expression *e = exp ? exp->syntaxCopy() : NULL;
  3169. SynchronizedStatement *s = new SynchronizedStatement(loc, e, body ? body->syntaxCopy() : NULL);
  3170. return s;
  3171. }
  3172. Statement *SynchronizedStatement::semantic(Scope *sc)
  3173. {
  3174. if (exp)
  3175. {
  3176. exp = exp->semantic(sc);
  3177. exp = resolveProperties(sc, exp);
  3178. ClassDeclaration *cd = exp->type->isClassHandle();
  3179. if (!cd)
  3180. error("can only synchronize on class objects, not '%s'", exp->type->toChars());
  3181. else if (cd->isInterfaceDeclaration())
  3182. { /* Cast the interface to an object, as the object has the monitor,
  3183. * not the interface.
  3184. */
  3185. Type *t = new TypeIdentifier(0, Id::Object);
  3186. t = t->semantic(0, sc);
  3187. exp = new CastExp(loc, exp, t);
  3188. exp = exp->semantic(sc);
  3189. }
  3190. #if 1
  3191. /* Rewrite as:
  3192. * auto tmp = exp;
  3193. * _d_monitorenter(tmp);
  3194. * try { body } finally { _d_monitorexit(tmp); }
  3195. */
  3196. Identifier *id = Lexer::uniqueId("__sync");
  3197. ExpInitializer *ie = new ExpInitializer(loc, exp);
  3198. VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie);
  3199. Statements *cs = new Statements();
  3200. cs->push(new ExpStatement(loc, tmp));
  3201. FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter, exp->type);
  3202. Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp));
  3203. e->type = Type::tvoid; // do not run semantic on e
  3204. cs->push(new ExpStatement(loc, e));
  3205. FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorexit, exp->type);
  3206. e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp));
  3207. e->type = Type::tvoid; // do not run semantic on e
  3208. Statement *s = new ExpStatement(loc, e);
  3209. s = new TryFinallyStatement(loc, body, s);
  3210. cs->push(s);
  3211. s = new CompoundStatement(loc, cs);
  3212. return s->semantic(sc);
  3213. #endif
  3214. }
  3215. #if 1
  3216. else
  3217. { /* Generate our own critical section, then rewrite as:
  3218. * __gshared byte[CriticalSection.sizeof] critsec;
  3219. * _d_criticalenter(critsec.ptr);
  3220. * try { body } finally { _d_criticalexit(critsec.ptr); }
  3221. */
  3222. Identifier *id = Lexer::uniqueId("__critsec");
  3223. Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + CRITSECSIZE));
  3224. VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL);
  3225. tmp->storage_class |= STCgshared | STCstatic;
  3226. Statements *cs = new Statements();
  3227. cs->push(new ExpStatement(loc, tmp));
  3228. FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter, Type::tvoidptr);
  3229. Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
  3230. e = e->semantic(sc);
  3231. e = new CallExp(loc, new VarExp(loc, fdenter), e);
  3232. e->type = Type::tvoid; // do not run semantic on e
  3233. cs->push(new ExpStatement(loc, e));
  3234. FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit, Type::tvoidptr);
  3235. e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
  3236. e = e->semantic(sc);
  3237. e = new CallExp(loc, new VarExp(loc, fdexit), e);
  3238. e->type = Type::tvoid; // do not run semantic on e
  3239. Statement *s = new ExpStatement(loc, e);
  3240. s = new TryFinallyStatement(loc, body, s);
  3241. cs->push(s);
  3242. s = new CompoundStatement(loc, cs);
  3243. return s->semantic(sc);
  3244. }
  3245. #endif
  3246. if (body)
  3247. body = body->semantic(sc);
  3248. return this;
  3249. }
  3250. int SynchronizedStatement::hasBreak()
  3251. {
  3252. return FALSE; //TRUE;
  3253. }
  3254. int SynchronizedStatement::hasContinue()
  3255. {
  3256. return FALSE; //TRUE;
  3257. }
  3258. int SynchronizedStatement::usesEH()
  3259. {
  3260. return TRUE;
  3261. }
  3262. int SynchronizedStatement::blockExit(bool mustNotThrow)
  3263. {
  3264. return body ? body->blockExit(mustNotThrow) : BEfallthru;
  3265. }
  3266. void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3267. {
  3268. buf->writestring("synchronized");
  3269. if (exp)
  3270. { buf->writebyte('(');
  3271. exp->toCBuffer(buf, hgs);
  3272. buf->writebyte(')');
  3273. }
  3274. if (body)
  3275. {
  3276. buf->writebyte(' ');
  3277. body->toCBuffer(buf, hgs);
  3278. }
  3279. }
  3280. /******************************** WithStatement ***************************/
  3281. WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body)
  3282. : Statement(loc)
  3283. {
  3284. this->exp = exp;
  3285. this->body = body;
  3286. wthis = NULL;
  3287. }
  3288. Statement *WithStatement::syntaxCopy()
  3289. {
  3290. WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body ? body->syntaxCopy() : NULL);
  3291. return s;
  3292. }
  3293. Statement *WithStatement::semantic(Scope *sc)
  3294. { ScopeDsymbol *sym;
  3295. Initializer *init;
  3296. //printf("WithStatement::semantic()\n");
  3297. exp = exp->semantic(sc);
  3298. exp = resolveProperties(sc, exp);
  3299. if (exp->op == TOKerror)
  3300. return NULL;
  3301. if (exp->op == TOKimport)
  3302. { ScopeExp *es = (ScopeExp *)exp;
  3303. sym = es->sds;
  3304. }
  3305. else if (exp->op == TOKtype)
  3306. { TypeExp *es = (TypeExp *)exp;
  3307. Dsymbol *s = es->type->toDsymbol(sc);
  3308. sym = s ? s->isScopeDsymbol() : NULL;
  3309. if (!sym)
  3310. { error("with type %s has no members", es->toChars());
  3311. if (body)
  3312. body = body->semantic(sc);
  3313. return this;
  3314. }
  3315. }
  3316. else
  3317. { Type *t = exp->type;
  3318. assert(t);
  3319. t = t->toBasetype();
  3320. if (t->isClassHandle())
  3321. {
  3322. init = new ExpInitializer(loc, exp);
  3323. wthis = new VarDeclaration(loc, exp->type, Id::withSym, init);
  3324. wthis->semantic(sc);
  3325. sym = new WithScopeSymbol(this);
  3326. sym->parent = sc->scopesym;
  3327. }
  3328. else if (t->ty == Tstruct)
  3329. {
  3330. Expression *e = exp->addressOf(sc);
  3331. init = new ExpInitializer(loc, e);
  3332. wthis = new VarDeclaration(loc, e->type, Id::withSym, init);
  3333. wthis->semantic(sc);
  3334. sym = new WithScopeSymbol(this);
  3335. sym->parent = sc->scopesym;
  3336. }
  3337. else
  3338. { error("with expressions must be class objects, not '%s'", exp->type->toChars());
  3339. return NULL;
  3340. }
  3341. }
  3342. sc = sc->push(sym);
  3343. if (body)
  3344. body = body->semantic(sc);
  3345. sc->pop();
  3346. return this;
  3347. }
  3348. void WithStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3349. {
  3350. buf->writestring("with (");
  3351. exp->toCBuffer(buf, hgs);
  3352. buf->writestring(")\n");
  3353. if (body)
  3354. body->toCBuffer(buf, hgs);
  3355. }
  3356. int WithStatement::usesEH()
  3357. {
  3358. return body ? body->usesEH() : 0;
  3359. }
  3360. int WithStatement::blockExit(bool mustNotThrow)
  3361. {
  3362. int result = BEnone;
  3363. if (exp->canThrow())
  3364. result = BEthrow;
  3365. if (body)
  3366. result |= body->blockExit(mustNotThrow);
  3367. else
  3368. result |= BEfallthru;
  3369. return result;
  3370. }
  3371. /******************************** TryCatchStatement ***************************/
  3372. TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
  3373. : Statement(loc)
  3374. {
  3375. this->body = body;
  3376. this->catches = catches;
  3377. }
  3378. Statement *TryCatchStatement::syntaxCopy()
  3379. {
  3380. Array *a = new Array();
  3381. a->setDim(catches->dim);
  3382. for (size_t i = 0; i < a->dim; i++)
  3383. { Catch *c;
  3384. c = (Catch *)catches->data[i];
  3385. c = c->syntaxCopy();
  3386. a->data[i] = c;
  3387. }
  3388. TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a);
  3389. return s;
  3390. }
  3391. Statement *TryCatchStatement::semantic(Scope *sc)
  3392. {
  3393. body = body->semanticScope(sc, NULL /*this*/, NULL);
  3394. /* Even if body is NULL, still do semantic analysis on catches
  3395. */
  3396. for (size_t i = 0; i < catches->dim; i++)
  3397. { Catch *c = (Catch *)catches->data[i];
  3398. c->semantic(sc);
  3399. // Determine if current catch 'hides' any previous catches
  3400. for (size_t j = 0; j < i; j++)
  3401. { Catch *cj = (Catch *)catches->data[j];
  3402. char *si = c->loc.toChars();
  3403. char *sj = cj->loc.toChars();
  3404. if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype()))
  3405. error("catch at %s hides catch at %s", sj, si);
  3406. }
  3407. }
  3408. if (!body || body->isEmpty())
  3409. {
  3410. return NULL;
  3411. }
  3412. return this;
  3413. }
  3414. int TryCatchStatement::hasBreak()
  3415. {
  3416. return FALSE; //TRUE;
  3417. }
  3418. int TryCatchStatement::usesEH()
  3419. {
  3420. return TRUE;
  3421. }
  3422. int TryCatchStatement::blockExit(bool mustNotThrow)
  3423. {
  3424. assert(body);
  3425. int result = body->blockExit(false);
  3426. int catchresult = 0;
  3427. for (size_t i = 0; i < catches->dim; i++)
  3428. {
  3429. Catch *c = (Catch *)catches->data[i];
  3430. if (c->type == Type::terror)
  3431. continue;
  3432. catchresult |= c->blockExit(mustNotThrow);
  3433. /* If we're catching Object, then there is no throwing
  3434. */
  3435. Identifier *id = c->type->toBasetype()->isClassHandle()->ident;
  3436. if (id == Id::Object)
  3437. {
  3438. result &= ~BEthrow;
  3439. }
  3440. }
  3441. if (mustNotThrow && (result & BEthrow))
  3442. {
  3443. body->blockExit(mustNotThrow); // now explain why this is nothrow
  3444. }
  3445. return result | catchresult;
  3446. }
  3447. void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3448. {
  3449. buf->writestring("try");
  3450. buf->writenl();
  3451. if (body)
  3452. body->toCBuffer(buf, hgs);
  3453. for (size_t i = 0; i < catches->dim; i++)
  3454. {
  3455. Catch *c = (Catch *)catches->data[i];
  3456. c->toCBuffer(buf, hgs);
  3457. }
  3458. }
  3459. /******************************** Catch ***************************/
  3460. Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler)
  3461. {
  3462. //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
  3463. this->loc = loc;
  3464. this->type = t;
  3465. this->ident = id;
  3466. this->handler = handler;
  3467. var = NULL;
  3468. }
  3469. Catch *Catch::syntaxCopy()
  3470. {
  3471. Catch *c = new Catch(loc,
  3472. (type ? type->syntaxCopy() : NULL),
  3473. ident,
  3474. (handler ? handler->syntaxCopy() : NULL));
  3475. return c;
  3476. }
  3477. void Catch::semantic(Scope *sc)
  3478. { ScopeDsymbol *sym;
  3479. //printf("Catch::semantic(%s)\n", ident->toChars());
  3480. #ifndef IN_GCC
  3481. if (sc->tf)
  3482. {
  3483. /* This is because the _d_local_unwind() gets the stack munged
  3484. * up on this. The workaround is to place any try-catches into
  3485. * a separate function, and call that.
  3486. * To fix, have the compiler automatically convert the finally
  3487. * body into a nested function.
  3488. */
  3489. error(loc, "cannot put catch statement inside finally block");
  3490. }
  3491. #endif
  3492. sym = new ScopeDsymbol();
  3493. sym->parent = sc->scopesym;
  3494. sc = sc->push(sym);
  3495. if (!type)
  3496. type = new TypeIdentifier(0, Id::Object);
  3497. type = type->semantic(loc, sc);
  3498. if (!type->toBasetype()->isClassHandle())
  3499. {
  3500. if (type != Type::terror)
  3501. { error(loc, "can only catch class objects, not '%s'", type->toChars());
  3502. type = Type::terror;
  3503. }
  3504. }
  3505. else if (ident)
  3506. {
  3507. var = new VarDeclaration(loc, type, ident, NULL);
  3508. var->parent = sc->parent;
  3509. sc->insert(var);
  3510. }
  3511. handler = handler->semantic(sc);
  3512. sc->pop();
  3513. }
  3514. int Catch::blockExit(bool mustNotThrow)
  3515. {
  3516. return handler ? handler->blockExit(mustNotThrow) : BEfallthru;
  3517. }
  3518. void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3519. {
  3520. buf->writestring("catch");
  3521. if (type)
  3522. { buf->writebyte('(');
  3523. type->toCBuffer(buf, ident, hgs);
  3524. buf->writebyte(')');
  3525. }
  3526. buf->writenl();
  3527. buf->writebyte('{');
  3528. buf->writenl();
  3529. if (handler)
  3530. handler->toCBuffer(buf, hgs);
  3531. buf->writebyte('}');
  3532. buf->writenl();
  3533. }
  3534. /****************************** TryFinallyStatement ***************************/
  3535. TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody)
  3536. : Statement(loc)
  3537. {
  3538. this->body = body;
  3539. this->finalbody = finalbody;
  3540. }
  3541. Statement *TryFinallyStatement::syntaxCopy()
  3542. {
  3543. TryFinallyStatement *s = new TryFinallyStatement(loc,
  3544. body->syntaxCopy(), finalbody->syntaxCopy());
  3545. return s;
  3546. }
  3547. Statement *TryFinallyStatement::semantic(Scope *sc)
  3548. {
  3549. //printf("TryFinallyStatement::semantic()\n");
  3550. body = body->semantic(sc);
  3551. sc = sc->push();
  3552. sc->tf = this;
  3553. sc->sbreak = NULL;
  3554. sc->scontinue = NULL; // no break or continue out of finally block
  3555. finalbody = finalbody->semanticNoScope(sc);
  3556. sc->pop();
  3557. return this;
  3558. }
  3559. void TryFinallyStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3560. {
  3561. buf->printf("try\n{\n");
  3562. body->toCBuffer(buf, hgs);
  3563. buf->printf("}\nfinally\n{\n");
  3564. finalbody->toCBuffer(buf, hgs);
  3565. buf->writeByte('}');
  3566. buf->writenl();
  3567. }
  3568. int TryFinallyStatement::hasBreak()
  3569. {
  3570. return FALSE; //TRUE;
  3571. }
  3572. int TryFinallyStatement::hasContinue()
  3573. {
  3574. return FALSE; //TRUE;
  3575. }
  3576. int TryFinallyStatement::usesEH()
  3577. {
  3578. return TRUE;
  3579. }
  3580. int TryFinallyStatement::blockExit(bool mustNotThrow)
  3581. {
  3582. if (body)
  3583. return body->blockExit(mustNotThrow);
  3584. return BEfallthru;
  3585. }
  3586. /****************************** OnScopeStatement ***************************/
  3587. OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement)
  3588. : Statement(loc)
  3589. {
  3590. this->tok = tok;
  3591. this->statement = statement;
  3592. }
  3593. Statement *OnScopeStatement::syntaxCopy()
  3594. {
  3595. OnScopeStatement *s = new OnScopeStatement(loc,
  3596. tok, statement->syntaxCopy());
  3597. return s;
  3598. }
  3599. Statement *OnScopeStatement::semantic(Scope *sc)
  3600. {
  3601. /* semantic is called on results of scopeCode() */
  3602. return this;
  3603. }
  3604. int OnScopeStatement::blockExit(bool mustNotThrow)
  3605. { // At this point, this statement is just an empty placeholder
  3606. return BEfallthru;
  3607. }
  3608. void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3609. {
  3610. buf->writestring(Token::toChars(tok));
  3611. buf->writebyte(' ');
  3612. statement->toCBuffer(buf, hgs);
  3613. }
  3614. int OnScopeStatement::usesEH()
  3615. {
  3616. return (tok != TOKon_scope_success);
  3617. }
  3618. void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
  3619. {
  3620. //printf("OnScopeStatement::scopeCode()\n");
  3621. //print();
  3622. *sentry = NULL;
  3623. *sexception = NULL;
  3624. *sfinally = NULL;
  3625. switch (tok)
  3626. {
  3627. case TOKon_scope_exit:
  3628. *sfinally = statement;
  3629. break;
  3630. case TOKon_scope_failure:
  3631. *sexception = statement;
  3632. break;
  3633. case TOKon_scope_success:
  3634. {
  3635. /* Create:
  3636. * sentry: int x = 0;
  3637. * sexception: x = 1;
  3638. * sfinally: if (!x) statement;
  3639. */
  3640. Identifier *id = Lexer::uniqueId("__os");
  3641. ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0));
  3642. VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);
  3643. *sentry = new ExpStatement(loc, v);
  3644. Expression *e = new IntegerExp(1);
  3645. e = new AssignExp(0, new VarExp(0, v), e);
  3646. *sexception = new ExpStatement(0, e);
  3647. e = new VarExp(0, v);
  3648. e = new NotExp(0, e);
  3649. *sfinally = new IfStatement(0, NULL, e, statement, NULL);
  3650. break;
  3651. }
  3652. default:
  3653. assert(0);
  3654. }
  3655. }
  3656. /******************************** ThrowStatement ***************************/
  3657. ThrowStatement::ThrowStatement(Loc loc, Expression *exp)
  3658. : Statement(loc)
  3659. {
  3660. this->exp = exp;
  3661. }
  3662. Statement *ThrowStatement::syntaxCopy()
  3663. {
  3664. ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy());
  3665. return s;
  3666. }
  3667. Statement *ThrowStatement::semantic(Scope *sc)
  3668. {
  3669. //printf("ThrowStatement::semantic()\n");
  3670. FuncDeclaration *fd = sc->parent->isFuncDeclaration();
  3671. fd->hasReturnExp |= 2;
  3672. if (sc->incontract)
  3673. error("Throw statements cannot be in contracts");
  3674. exp = exp->semantic(sc);
  3675. exp = resolveProperties(sc, exp);
  3676. if (exp->op == TOKerror)
  3677. return this;
  3678. if (!exp->type->toBasetype()->isClassHandle())
  3679. error("can only throw class objects, not type %s", exp->type->toChars());
  3680. return this;
  3681. }
  3682. int ThrowStatement::blockExit(bool mustNotThrow)
  3683. {
  3684. return BEthrow; // obviously
  3685. }
  3686. void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3687. {
  3688. buf->printf("throw ");
  3689. exp->toCBuffer(buf, hgs);
  3690. buf->writeByte(';');
  3691. buf->writenl();
  3692. }
  3693. /******************************** VolatileStatement **************************/
  3694. VolatileStatement::VolatileStatement(Loc loc, Statement *statement)
  3695. : Statement(loc)
  3696. {
  3697. this->statement = statement;
  3698. }
  3699. Statement *VolatileStatement::syntaxCopy()
  3700. {
  3701. VolatileStatement *s = new VolatileStatement(loc,
  3702. statement ? statement->syntaxCopy() : NULL);
  3703. return s;
  3704. }
  3705. Statement *VolatileStatement::semantic(Scope *sc)
  3706. {
  3707. if (statement)
  3708. statement = statement->semantic(sc);
  3709. return this;
  3710. }
  3711. Statements *VolatileStatement::flatten(Scope *sc)
  3712. {
  3713. Statements *a;
  3714. a = statement ? statement->flatten(sc) : NULL;
  3715. if (a)
  3716. { for (size_t i = 0; i < a->dim; i++)
  3717. { Statement *s = (Statement *)a->data[i];
  3718. s = new VolatileStatement(loc, s);
  3719. a->data[i] = s;
  3720. }
  3721. }
  3722. return a;
  3723. }
  3724. int VolatileStatement::blockExit(bool mustNotThrow)
  3725. {
  3726. return statement ? statement->blockExit(mustNotThrow) : BEfallthru;
  3727. }
  3728. void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3729. {
  3730. buf->writestring("volatile");
  3731. if (statement)
  3732. { if (statement->isScopeStatement())
  3733. buf->writenl();
  3734. else
  3735. buf->writebyte(' ');
  3736. statement->toCBuffer(buf, hgs);
  3737. }
  3738. }
  3739. /******************************** GotoStatement ***************************/
  3740. GotoStatement::GotoStatement(Loc loc, Identifier *ident)
  3741. : Statement(loc)
  3742. {
  3743. this->ident = ident;
  3744. this->label = NULL;
  3745. this->tf = NULL;
  3746. }
  3747. Statement *GotoStatement::syntaxCopy()
  3748. {
  3749. GotoStatement *s = new GotoStatement(loc, ident);
  3750. return s;
  3751. }
  3752. Statement *GotoStatement::semantic(Scope *sc)
  3753. { FuncDeclaration *fd = sc->parent->isFuncDeclaration();
  3754. //printf("GotoStatement::semantic()\n");
  3755. tf = sc->tf;
  3756. label = fd->searchLabel(ident);
  3757. if (!label->statement && sc->fes)
  3758. {
  3759. /* Either the goto label is forward referenced or it
  3760. * is in the function that the enclosing foreach is in.
  3761. * Can't know yet, so wrap the goto in a compound statement
  3762. * so we can patch it later, and add it to a 'look at this later'
  3763. * list.
  3764. */
  3765. Statements *a = new Statements();
  3766. Statement *s;
  3767. a->push(this);
  3768. s = new CompoundStatement(loc, a);
  3769. sc->fes->gotos->push(s); // 'look at this later' list
  3770. return s;
  3771. }
  3772. if (label->statement && label->statement->tf != sc->tf)
  3773. error("cannot goto in or out of finally block");
  3774. return this;
  3775. }
  3776. int GotoStatement::blockExit(bool mustNotThrow)
  3777. {
  3778. //printf("GotoStatement::blockExit(%p)\n", this);
  3779. return BEgoto;
  3780. }
  3781. void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3782. {
  3783. buf->writestring("goto ");
  3784. buf->writestring(ident->toChars());
  3785. buf->writebyte(';');
  3786. buf->writenl();
  3787. }
  3788. /******************************** LabelStatement ***************************/
  3789. LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
  3790. : Statement(loc)
  3791. {
  3792. this->ident = ident;
  3793. this->statement = statement;
  3794. this->tf = NULL;
  3795. this->lblock = NULL;
  3796. this->fwdrefs = NULL;
  3797. }
  3798. Statement *LabelStatement::syntaxCopy()
  3799. {
  3800. LabelStatement *s = new LabelStatement(loc, ident, statement->syntaxCopy());
  3801. return s;
  3802. }
  3803. Statement *LabelStatement::semantic(Scope *sc)
  3804. { LabelDsymbol *ls;
  3805. FuncDeclaration *fd = sc->parent->isFuncDeclaration();
  3806. //printf("LabelStatement::semantic()\n");
  3807. ls = fd->searchLabel(ident);
  3808. if (ls->statement)
  3809. error("Label '%s' already defined", ls->toChars());
  3810. else
  3811. ls->statement = this;
  3812. tf = sc->tf;
  3813. sc = sc->push();
  3814. sc->scopesym = sc->enclosing->scopesym;
  3815. sc->callSuper |= CSXlabel;
  3816. sc->slabel = this;
  3817. if (statement)
  3818. statement = statement->semanticNoScope(sc);
  3819. sc->pop();
  3820. return this;
  3821. }
  3822. Statements *LabelStatement::flatten(Scope *sc)
  3823. {
  3824. Statements *a = NULL;
  3825. if (statement)
  3826. {
  3827. a = statement->flatten(sc);
  3828. if (a)
  3829. {
  3830. if (!a->dim)
  3831. {
  3832. a->push(new ExpStatement(loc, (Expression *)NULL));
  3833. }
  3834. Statement *s = (Statement *)a->data[0];
  3835. s = new LabelStatement(loc, ident, s);
  3836. a->data[0] = s;
  3837. }
  3838. }
  3839. return a;
  3840. }
  3841. int LabelStatement::usesEH()
  3842. {
  3843. return statement ? statement->usesEH() : FALSE;
  3844. }
  3845. int LabelStatement::blockExit(bool mustNotThrow)
  3846. {
  3847. //printf("LabelStatement::blockExit(%p)\n", this);
  3848. return statement ? statement->blockExit(mustNotThrow) : BEfallthru;
  3849. }
  3850. int LabelStatement::comeFrom()
  3851. {
  3852. //printf("LabelStatement::comeFrom()\n");
  3853. return TRUE;
  3854. }
  3855. void LabelStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3856. {
  3857. buf->writestring(ident->toChars());
  3858. buf->writebyte(':');
  3859. buf->writenl();
  3860. if (statement)
  3861. statement->toCBuffer(buf, hgs);
  3862. }
  3863. /******************************** LabelDsymbol ***************************/
  3864. LabelDsymbol::LabelDsymbol(Identifier *ident)
  3865. : Dsymbol(ident)
  3866. {
  3867. statement = NULL;
  3868. #if IN_GCC
  3869. asmLabelNum = 0;
  3870. #endif
  3871. }
  3872. LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
  3873. {
  3874. return this;
  3875. }
  3876. /************************ AsmStatement ***************************************/
  3877. AsmStatement::AsmStatement(Loc loc, Token *tokens)
  3878. : Statement(loc)
  3879. {
  3880. this->tokens = tokens;
  3881. asmcode = NULL;
  3882. asmalign = 0;
  3883. refparam = FALSE;
  3884. naked = FALSE;
  3885. regs = 0;
  3886. }
  3887. Statement *AsmStatement::syntaxCopy()
  3888. {
  3889. return new AsmStatement(loc, tokens);
  3890. }
  3891. int AsmStatement::comeFrom()
  3892. {
  3893. return TRUE;
  3894. }
  3895. int AsmStatement::blockExit(bool mustNotThrow)
  3896. {
  3897. // Assume the worst
  3898. return BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt;
  3899. }
  3900. void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  3901. {
  3902. buf->writestring("asm { ");
  3903. Token *t = tokens;
  3904. while (t)
  3905. {
  3906. buf->writestring(t->toChars());
  3907. if (t->next &&
  3908. t->value != TOKmin &&
  3909. t->value != TOKcomma &&
  3910. t->next->value != TOKcomma &&
  3911. t->value != TOKlbracket &&
  3912. t->next->value != TOKlbracket &&
  3913. t->next->value != TOKrbracket &&
  3914. t->value != TOKlparen &&
  3915. t->next->value != TOKlparen &&
  3916. t->next->value != TOKrparen &&
  3917. t->value != TOKdot &&
  3918. t->next->value != TOKdot)
  3919. {
  3920. buf->writebyte(' ');
  3921. }
  3922. t = t->next;
  3923. }
  3924. buf->writestring("; }");
  3925. buf->writenl();
  3926. }