comparison dmd/VarDeclaration.d @ 179:cd48cb899aee

Updated to dmd2.040
author korDen
date Sun, 17 Oct 2010 20:56:07 +0400
parents e3afd1303184
children b0d41ff5e0df
comparison
equal deleted inserted replaced
178:e3afd1303184 179:cd48cb899aee
462 TOK op = TOK.TOKconstruct; 462 TOK op = TOK.TOKconstruct;
463 if (!init && !sc.inunion && !isStatic() && fd && 463 if (!init && !sc.inunion && !isStatic() && fd &&
464 (!(storage_class & (STC.STCfield | STC.STCin | STC.STCforeach | STC.STCparameter)) || (storage_class & STC.STCout)) && 464 (!(storage_class & (STC.STCfield | STC.STCin | STC.STCforeach | STC.STCparameter)) || (storage_class & STC.STCout)) &&
465 type.size() != 0) 465 type.size() != 0)
466 { 466 {
467 // Provide a default initializer 467 // Provide a default initializer
468 //printf("Providing default initializer for '%s'\n", toChars()); 468 //printf("Providing default initializer for '%s'\n", toChars());
469 if (type.ty == TY.Tstruct && 469 if (type.ty == TY.Tstruct &&
470 (cast(TypeStruct)type).sym.zeroInit) 470 (cast(TypeStruct)type).sym.zeroInit)
471 { /* If a struct is all zeros, as a special case 471 { /* If a struct is all zeros, as a special case
472 * set it's initializer to the integer 0. 472 * set it's initializer to the integer 0.
473 * In AssignExp.toElem(), we check for this and issue 473 * In AssignExp.toElem(), we check for this and issue
474 * a memset() to initialize the struct. 474 * a memset() to initialize the struct.
475 * Must do same check in interpreter. 475 * Must do same check in interpreter.
476 */ 476 */
477 Expression e = new IntegerExp(loc, 0, Type.tint32); 477 Expression e = new IntegerExp(loc, 0, Type.tint32);
478 Expression e1; 478 Expression e1;
479 e1 = new VarExp(loc, this); 479 e1 = new VarExp(loc, this);
480 e = new AssignExp(loc, e1, e); 480 e = new AssignExp(loc, e1, e);
481 e.op = TOK.TOKconstruct; 481 e.op = TOK.TOKconstruct;
482 e.type = e1.type; // don't type check this, it would fail 482 e.type = e1.type; // don't type check this, it would fail
483 init = new ExpInitializer(loc, e); 483 init = new ExpInitializer(loc, e);
484 return; 484 return;
485 } 485 }
486 else if (type.ty == TY.Ttypedef) 486 else if (type.ty == TY.Ttypedef)
487 { TypeTypedef td = cast(TypeTypedef)type; 487 {
488 if (td.sym.init) 488 TypeTypedef td = cast(TypeTypedef)type;
489 { init = td.sym.init; 489 if (td.sym.init)
490 ExpInitializer ie = init.isExpInitializer(); 490 {
491 if (ie) 491 init = td.sym.init;
492 // Make copy so we can modify it 492 ExpInitializer ie = init.isExpInitializer();
493 init = new ExpInitializer(ie.loc, ie.exp); 493 if (ie)
494 // Make copy so we can modify it
495 init = new ExpInitializer(ie.loc, ie.exp);
496 }
497 else
498 init = getExpInitializer();
494 } 499 }
495 else 500 else
496 init = getExpInitializer(); 501 {
497 } 502 init = getExpInitializer();
498 else 503 }
499 { 504 // Default initializer is always a blit
500 init = getExpInitializer(); 505 op = TOK.TOKblit;
501 }
502 // Default initializer is always a blit
503 op = TOK.TOKblit;
504 } 506 }
505 507
506 if (init) 508 if (init)
507 { 509 {
508 sc = sc.push(); 510 sc = sc.push();
509 sc.stc &= ~(STC.STC_TYPECTOR | STC.STCpure | STC.STCnothrow | STC.STCref); 511 sc.stc &= ~(STC.STC_TYPECTOR | STC.STCpure | STC.STCnothrow | STC.STCref | STCdisable);
510 512
511 ArrayInitializer ai = init.isArrayInitializer(); 513 ArrayInitializer ai = init.isArrayInitializer();
512 if (ai && tb.ty == TY.Taarray) 514 if (ai && tb.ty == TY.Taarray)
513 { 515 {
514 Expression e = ai.toAssocArrayLiteral(); 516 Expression e = ai.toAssocArrayLiteral();
515 init = new ExpInitializer(e.loc, e); 517 init = new ExpInitializer(e.loc, e);
516 } 518 }
517 519
518 StructInitializer si = init.isStructInitializer(); 520 StructInitializer si = init.isStructInitializer();
519 ExpInitializer ei = init.isExpInitializer(); 521 ExpInitializer ei = init.isExpInitializer();
520 522
521 // See if initializer is a NewExp that can be allocated on the stack 523 // See if initializer is a NewExp that can be allocated on the stack
522 if (ei && isScope() && ei.exp.op == TOK.TOKnew) 524 if (ei && isScope() && ei.exp.op == TOK.TOKnew)
523 { NewExp ne = cast(NewExp)ei.exp; 525 { NewExp ne = cast(NewExp)ei.exp;
524 if (!(ne.newargs && ne.newargs.dim)) 526 if (!(ne.newargs && ne.newargs.dim))
525 { ne.onstack = 1; 527 { ne.onstack = 1;
526 onstack = 1; 528 onstack = 1;
527 if (type.isBaseOf(ne.newtype.semantic(loc, sc), null)) 529 if (type.isBaseOf(ne.newtype.semantic(loc, sc), null))
528 onstack = 2; 530 onstack = 2;
529 } 531 }
530 } 532 }
531 533
532 // If inside function, there is no semantic3() call 534 // If inside function, there is no semantic3() call
533 if (sc.func) 535 if (sc.func)
534 { 536 {
535 // If local variable, use AssignExp to handle all the various 537 // If local variable, use AssignExp to handle all the various
536 // possibilities. 538 // possibilities.
537 if (fd && 539 if (fd &&
538 !(storage_class & (STC.STCmanifest | STC.STCstatic | STC.STCtls | STC.STCgshared | STC.STCextern)) && 540 !(storage_class & (STC.STCmanifest | STC.STCstatic | STC.STCtls | STC.STCgshared | STC.STCextern)) &&
539 !init.isVoidInitializer()) 541 !init.isVoidInitializer())
540 { 542 {
541 //printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars()); 543 //printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
542 if (!ei) 544 if (!ei)
543 { 545 {
544 Expression e = init.toExpression(); 546 Expression e = init.toExpression();
545 if (!e) 547 if (!e)
548 {
549 init = init.semantic(sc, type);
550 e = init.toExpression();
551 if (!e)
552 { error("is not a static and cannot have static initializer");
553 return;
554 }
555 }
556 ei = new ExpInitializer(init.loc, e);
557 init = ei;
558 }
559
560 Expression e1 = new VarExp(loc, this);
561
562 Type t = type.toBasetype();
563 if (t.ty == TY.Tsarray && !(storage_class & (STC.STCref | STC.STCout)))
564 {
565 ei.exp = ei.exp.semantic(sc);
566 if (!ei.exp.implicitConvTo(type))
567 {
568 int dim = cast(int)(cast(TypeSArray)t).dim.toInteger(); ///
569 // If multidimensional static array, treat as one large array
570 while (1)
571 {
572 t = t.nextOf().toBasetype();
573 if (t.ty != TY.Tsarray)
574 break;
575 dim *= (cast(TypeSArray)t).dim.toInteger();
576 e1.type = new TypeSArray(t.nextOf(), new IntegerExp(Loc(0), dim, Type.tindex));
577 }
578 }
579 e1 = new SliceExp(loc, e1, null, null);
580 }
581 else if (t.ty == TY.Tstruct)
582 {
583 ei.exp = ei.exp.semantic(sc);
584 ei.exp = resolveProperties(sc, ei.exp);
585 StructDeclaration sd = (cast(TypeStruct)t).sym;
586 version (DMDV2)
587 {
588 /* Look to see if initializer is a call to the constructor
589 */
590 if (sd.ctor && // there are constructors
591 ei.exp.type.ty == TY.Tstruct && // rvalue is the same struct
592 (cast(TypeStruct)ei.exp.type).sym == sd &&
593 ei.exp.op == TOK.TOKstar)
594 {
595 /* Look for form of constructor call which is:
596 * *__ctmp.ctor(arguments...)
597 */
598 PtrExp pe = cast(PtrExp)ei.exp;
599 if (pe.e1.op == TOK.TOKcall)
600 { CallExp ce = cast(CallExp)pe.e1;
601 if (ce.e1.op == TOK.TOKdotvar)
602 { DotVarExp dve = cast(DotVarExp)ce.e1;
603 if (dve.var.isCtorDeclaration())
604 { /* It's a constructor call, currently constructing
605 * a temporary __ctmp.
606 */
607 /* Before calling the constructor, initialize
608 * variable with a bit copy of the default
609 * initializer
610 */
611 Expression e = new AssignExp(loc, new VarExp(loc, this), t.defaultInit(loc));
612 e.op = TOK.TOKblit;
613 e.type = t;
614 ei.exp = new CommaExp(loc, e, ei.exp);
615
616 /* Replace __ctmp being constructed with e1
617 */
618 dve.e1 = e1;
619 return;
620 }
621 }
622 }
623 }
624 }
625 if (!ei.exp.implicitConvTo(type))
626 {
627 Type ti = ei.exp.type.toBasetype();
628 // Look for constructor first
629 if (sd.ctor &&
630 /* Initializing with the same type is done differently
631 */
632 !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
633 {
634 // Rewrite as e1.ctor(arguments)
635 Expression ector = new DotIdExp(loc, e1, Id.ctor);
636 ei.exp = new CallExp(loc, ector, ei.exp);
637 }
638 else
639 /* Look for opCall
640 * See bugzilla 2702 for more discussion
641 */
642
643 // Don't cast away invariant or mutability in initializer
644 if (search_function(sd, Id.call) &&
645 /* Initializing with the same type is done differently
646 */
647 !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
648 { // Rewrite as e1.call(arguments)
649 Expression eCall = new DotIdExp(loc, e1, Id.call);
650 ei.exp = new CallExp(loc, eCall, ei.exp);
651 }
652 }
653 }
654 ei.exp = new AssignExp(loc, e1, ei.exp);
655 ei.exp.op = op;
656 canassign++;
657 ei.exp = ei.exp.semantic(sc);
658 canassign--;
659 ei.exp.optimize(WANT.WANTvalue);
660 }
661 else
546 { 662 {
547 init = init.semantic(sc, type); 663 init = init.semantic(sc, type);
548 e = init.toExpression(); 664 }
549 if (!e) 665 }
550 { error("is not a static and cannot have static initializer"); 666 else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) ||
551 return; 667 type.isConst() || type.isImmutable() ||
552 } 668 parent.isAggregateDeclaration())
553 } 669 {
554 ei = new ExpInitializer(init.loc, e); 670 /* Because we may need the results of a const declaration in a
555 init = ei; 671 * subsequent type, such as an array dimension, before semantic2()
556 } 672 * gets ordinarily run, try to run semantic2() now.
557 673 * Ignore failure.
558 Expression e1 = new VarExp(loc, this); 674 */
559 675
560 Type t = type.toBasetype(); 676 if (!global.errors && !inferred)
561 if (t.ty == TY.Tsarray && !(storage_class & (STC.STCref | STC.STCout)))
562 {
563 ei.exp = ei.exp.semantic(sc);
564 if (!ei.exp.implicitConvTo(type))
565 { 677 {
566 int dim = cast(int)(cast(TypeSArray)t).dim.toInteger(); /// 678 uint errors = global.errors;
567 // If multidimensional static array, treat as one large array 679 global.gag++;
568 while (1) 680 //printf("+gag\n");
569 { 681 Expression e;
570 t = t.nextOf().toBasetype(); 682 Initializer i2 = init;
571 if (t.ty != TY.Tsarray) 683 inuse++;
572 break; 684 if (ei)
573 dim *= (cast(TypeSArray)t).dim.toInteger(); 685 {
574 e1.type = new TypeSArray(t.nextOf(), new IntegerExp(Loc(0), dim, Type.tindex)); 686 e = ei.exp.syntaxCopy();
575 } 687 e = e.semantic(sc);
576 } 688 e = resolveProperties(sc, e);
577 e1 = new SliceExp(loc, e1, null, null); 689 version (DMDV2) {
578 } 690 /* The problem is the following code:
579 else if (t.ty == TY.Tstruct) 691 * struct CopyTest {
580 { 692 * double x;
581 ei.exp = ei.exp.semantic(sc); 693 * this(double a) { x = a * 10.0;}
582 ei.exp = resolveProperties(sc, ei.exp); 694 * this(this) { x += 2.0; }
583 StructDeclaration sd = (cast(TypeStruct)t).sym; 695 * }
584 version (DMDV2) 696 * const CopyTest z = CopyTest(5.3); // ok
585 { 697 * const CopyTest w = z; // not ok, postblit not run
586 /* Look to see if initializer is a call to the constructor 698 * static assert(w.x == 55.0);
587 */ 699 * because the postblit doesn't get run on the initialization of w.
588 if (sd.ctor && // there are constructors 700 */
589 ei.exp.type.ty == TY.Tstruct && // rvalue is the same struct 701
590 (cast(TypeStruct)ei.exp.type).sym == sd && 702 Type tb_ = e.type.toBasetype();
591 ei.exp.op == TOK.TOKstar) 703 if (tb_.ty == Tstruct)
592 { 704 {
593 /* Look for form of constructor call which is: 705 StructDeclaration sd = (cast(TypeStruct)tb_).sym;
594 * *__ctmp.ctor(arguments...) 706 Type typeb = type.toBasetype();
595 */ 707 /* Look to see if initializer involves a copy constructor
596 PtrExp pe = cast(PtrExp)ei.exp; 708 * (which implies a postblit)
597 if (pe.e1.op == TOK.TOKcall)
598 { CallExp ce = cast(CallExp)pe.e1;
599 if (ce.e1.op == TOK.TOKdotvar)
600 { DotVarExp dve = cast(DotVarExp)ce.e1;
601 if (dve.var.isCtorDeclaration())
602 { /* It's a constructor call, currently constructing
603 * a temporary __ctmp.
604 */ 709 */
605 /* Before calling the constructor, initialize 710 if (sd.cpctor && // there is a copy constructor
606 * variable with a bit copy of the default 711 typeb.equals(tb_)) // rvalue is the same struct
607 * initializer 712 {
713 // The only allowable initializer is a (non-copy) constructor
714 if (e.op == TOKcall)
715 {
716 CallExp ce = cast(CallExp)e;
717 if (ce.e1.op == TOKdotvar)
718 {
719 DotVarExp dve = cast(DotVarExp)ce.e1;
720 if (dve.var.isCtorDeclaration())
721 goto LNoCopyConstruction;
722 }
723 }
724 global.gag--;
725 error("of type struct %s uses this(this), which is not allowed in static initialization", typeb.toChars());
726 global.gag++;
727
728 LNoCopyConstruction:
729 ;
730 }
731 }
732 }
733 e = e.implicitCastTo(sc, type);
734 }
735 else if (si || ai)
736 {
737 i2 = init.syntaxCopy();
738 i2 = i2.semantic(sc, type);
739 }
740 inuse--;
741 global.gag--;
742 //printf("-gag\n");
743 if (errors != global.errors) // if errors happened
744 {
745 if (global.gag == 0)
746 global.errors = errors; // act as if nothing happened
747 version (DMDV2) {
748 /* Save scope for later use, to try again
608 */ 749 */
609 Expression e = new AssignExp(loc, new VarExp(loc, this), t.defaultInit(loc)); 750 scope_ = sc.clone();
610 e.op = TOK.TOKblit; 751 scope_.setNoFree();
611 e.type = t; 752 }
612 ei.exp = new CommaExp(loc, e, ei.exp); 753 }
613 754 else if (ei)
614 /* Replace __ctmp being constructed with e1
615 */
616 dve.e1 = e1;
617 return;
618 }
619 }
620 }
621 }
622 }
623 if (!ei.exp.implicitConvTo(type))
624 {
625 Type ti = ei.exp.type.toBasetype();
626 // Look for constructor first
627 if (sd.ctor &&
628 /* Initializing with the same type is done differently
629 */
630 !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
631 { 755 {
632 // Rewrite as e1.ctor(arguments) 756 if (isDataseg())
633 Expression ector = new DotIdExp(loc, e1, Id.ctor); 757 /* static const/invariant does CTFE
634 ei.exp = new CallExp(loc, ector, ei.exp); 758 */
635 } 759 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
760 else
761 e = e.optimize(WANT.WANTvalue);
762 if (e.op == TOK.TOKint64 || e.op == TOK.TOKstring || e.op == TOK.TOKfloat64)
763 {
764 ei.exp = e; // no errors, keep result
765 }
766 ///version (DMDV2) {
767 else
768 {
769 /* Save scope for later use, to try again
770 */
771 scope_ = sc.clone();
772 scope_.setNoFree();
773 }
774 ///}
775 }
636 else 776 else
637 /* Look for opCall 777 init = i2; // no errors, keep result
638 * See bugzilla 2702 for more discussion 778 }
639 */ 779 }
640 780 sc = sc.pop();
641 // Don't cast away invariant or mutability in initializer
642 if (search_function(sd, Id.call) &&
643 /* Initializing with the same type is done differently
644 */
645 !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
646 { // Rewrite as e1.call(arguments)
647 Expression eCall = new DotIdExp(loc, e1, Id.call);
648 ei.exp = new CallExp(loc, eCall, ei.exp);
649 }
650 }
651 }
652 ei.exp = new AssignExp(loc, e1, ei.exp);
653 ei.exp.op = op;
654 canassign++;
655 ei.exp = ei.exp.semantic(sc);
656 canassign--;
657 ei.exp.optimize(WANT.WANTvalue);
658 }
659 else
660 {
661 init = init.semantic(sc, type);
662 }
663 }
664 else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) ||
665 type.isConst() || type.isImmutable() ||
666 parent.isAggregateDeclaration())
667 {
668 /* Because we may need the results of a const declaration in a
669 * subsequent type, such as an array dimension, before semantic2()
670 * gets ordinarily run, try to run semantic2() now.
671 * Ignore failure.
672 */
673
674 if (!global.errors && !inferred)
675 {
676 uint errors = global.errors;
677 global.gag++;
678 //printf("+gag\n");
679 Expression e;
680 Initializer i2 = init;
681 inuse++;
682 if (ei)
683 {
684 e = ei.exp.syntaxCopy();
685 e = e.semantic(sc);
686 e = e.implicitCastTo(sc, type);
687 }
688 else if (si || ai)
689 { i2 = init.syntaxCopy();
690 i2 = i2.semantic(sc, type);
691 }
692 inuse--;
693 global.gag--;
694 //printf("-gag\n");
695 if (errors != global.errors) // if errors happened
696 {
697 if (global.gag == 0)
698 global.errors = errors; // act as if nothing happened
699 version (DMDV2) {
700 /* Save scope for later use, to try again
701 */
702 scope_ = sc.clone();
703 scope_.setNoFree();
704 }
705 }
706 else if (ei)
707 {
708 if (isDataseg())
709 /* static const/invariant does CTFE
710 */
711 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
712 else
713 e = e.optimize(WANT.WANTvalue);
714 if (e.op == TOK.TOKint64 || e.op == TOK.TOKstring || e.op == TOK.TOKfloat64)
715 {
716 ei.exp = e; // no errors, keep result
717 }
718 ///version (DMDV2) {
719 else
720 {
721 /* Save scope for later use, to try again
722 */
723 scope_ = sc.clone();
724 scope_.setNoFree();
725 }
726 ///}
727 }
728 else
729 init = i2; // no errors, keep result
730 }
731 }
732 sc = sc.pop();
733 } 781 }
734 } 782 }
735 783
736 override void semantic2(Scope sc) 784 override void semantic2(Scope sc)
737 { 785 {