comparison dmd/cast.c @ 19:788401029ecf trunk

[svn r23] * Updated to DMD 1.021
author lindquist
date Thu, 04 Oct 2007 03:42:56 +0200
parents c53b6e3fe49a
children 61615fa85940
comparison
equal deleted inserted replaced
18:c05ef76f1c20 19:788401029ecf
656 return e; 656 return e;
657 } 657 }
658 658
659 Expression *StringExp::castTo(Scope *sc, Type *t) 659 Expression *StringExp::castTo(Scope *sc, Type *t)
660 { 660 {
661 /* This follows copy-on-write; any changes to 'this'
662 * will result in a copy.
663 * The this->string member is considered immutable.
664 */
661 StringExp *se; 665 StringExp *se;
662 Type *tb; 666 Type *tb;
663 int unique; 667 int copied = 0;
664 668
665 //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed); 669 //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed);
666 670
667 if (!committed && t->ty == Tpointer && t->next->ty == Tvoid) 671 if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
668 { 672 {
669 error("cannot convert string literal to void*"); 673 error("cannot convert string literal to void*");
674 }
675
676 se = this;
677 if (!committed)
678 { se = (StringExp *)copy();
679 se->committed = 1;
680 copied = 1;
681 }
682
683 if (type == t)
684 {
685 return se;
670 } 686 }
671 687
672 tb = t->toBasetype(); 688 tb = t->toBasetype();
673 //printf("\ttype = %s\n", type->toChars()); 689 //printf("\ttype = %s\n", type->toChars());
674 if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate) 690 if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate)
675 return Expression::castTo(sc, t); 691 return Expression::castTo(sc, t);
676 692
677 se = this; 693 Type *typeb = type->toBasetype();
678 unique = 0; 694 if (typeb == tb)
679 if (!committed) 695 {
680 { 696 if (!copied)
681 // Copy when committing the type 697 { se = (StringExp *)copy();
682 void *s; 698 copied = 1;
683 699 }
684 s = (unsigned char *)mem.malloc((len + 1) * sz); 700 se->type = t;
685 memcpy(s, string, (len + 1) * sz);
686 se = new StringExp(loc, s, len);
687 se->type = type;
688 se->sz = sz;
689 se->committed = 0;
690 unique = 1; // this is the only instance
691 }
692 se->type = type->toBasetype();
693 if (tb == se->type)
694 { se->type = t;
695 se->committed = 1;
696 return se; 701 return se;
697 } 702 }
698 703
699 if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer) 704 if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer)
700 { se->committed = 1; 705 { if (!copied)
706 { se = (StringExp *)copy();
707 copied = 1;
708 }
701 goto Lcast; 709 goto Lcast;
702 } 710 }
703 if (se->type->ty != Tsarray && se->type->ty != Tarray && se->type->ty != Tpointer) 711 if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer)
704 { se->committed = 1; 712 { if (!copied)
713 { se = (StringExp *)copy();
714 copied = 1;
715 }
705 goto Lcast; 716 goto Lcast;
706 } 717 }
707 718
708 if (se->committed == 1) 719 if (typeb->nextOf()->size() == tb->nextOf()->size())
709 { 720 {
710 if (se->type->next->size() == tb->next->size()) 721 if (!copied)
711 { se->type = t; 722 { se = (StringExp *)copy();
712 return se; 723 copied = 1;
713 } 724 }
725 if (tb->ty == Tsarray)
726 goto L2; // handle possible change in static array dimension
727 se->type = t;
728 return se;
729 }
730
731 if (committed)
714 goto Lcast; 732 goto Lcast;
715 }
716
717 se->committed = 1;
718
719 int tfty;
720 int ttty;
721 char *p;
722 size_t u;
723 unsigned c;
724 size_t newlen;
725 733
726 #define X(tf,tt) ((tf) * 256 + (tt)) 734 #define X(tf,tt) ((tf) * 256 + (tt))
727 { 735 {
728 OutBuffer buffer; 736 OutBuffer buffer;
729 newlen = 0; 737 size_t newlen = 0;
730 tfty = se->type->next->toBasetype()->ty; 738 int tfty = typeb->nextOf()->toBasetype()->ty;
731 ttty = tb->next->toBasetype()->ty; 739 int ttty = tb->nextOf()->toBasetype()->ty;
732 switch (X(tfty, ttty)) 740 switch (X(tfty, ttty))
733 { 741 {
734 case X(Tchar, Tchar): 742 case X(Tchar, Tchar):
735 case X(Twchar,Twchar): 743 case X(Twchar,Twchar):
736 case X(Tdchar,Tdchar): 744 case X(Tdchar,Tdchar):
737 break; 745 break;
738 746
739 case X(Tchar, Twchar): 747 case X(Tchar, Twchar):
740 for (u = 0; u < len;) 748 for (size_t u = 0; u < len;)
741 { 749 { unsigned c;
742 p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); 750 char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
743 if (p) 751 if (p)
744 error("%s", p); 752 error("%s", p);
745 else 753 else
746 buffer.writeUTF16(c); 754 buffer.writeUTF16(c);
747 } 755 }
748 newlen = buffer.offset / 2; 756 newlen = buffer.offset / 2;
749 buffer.writeUTF16(0); 757 buffer.writeUTF16(0);
750 goto L1; 758 goto L1;
751 759
752 case X(Tchar, Tdchar): 760 case X(Tchar, Tdchar):
753 for (u = 0; u < len;) 761 for (size_t u = 0; u < len;)
754 { 762 { unsigned c;
755 p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); 763 char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
756 if (p) 764 if (p)
757 error("%s", p); 765 error("%s", p);
758 buffer.write4(c); 766 buffer.write4(c);
759 newlen++; 767 newlen++;
760 } 768 }
761 buffer.write4(0); 769 buffer.write4(0);
762 goto L1; 770 goto L1;
763 771
764 case X(Twchar,Tchar): 772 case X(Twchar,Tchar):
765 for (u = 0; u < len;) 773 for (size_t u = 0; u < len;)
766 { 774 { unsigned c;
767 p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); 775 char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
768 if (p) 776 if (p)
769 error("%s", p); 777 error("%s", p);
770 else 778 else
771 buffer.writeUTF8(c); 779 buffer.writeUTF8(c);
772 } 780 }
773 newlen = buffer.offset; 781 newlen = buffer.offset;
774 buffer.writeUTF8(0); 782 buffer.writeUTF8(0);
775 goto L1; 783 goto L1;
776 784
777 case X(Twchar,Tdchar): 785 case X(Twchar,Tdchar):
778 for (u = 0; u < len;) 786 for (size_t u = 0; u < len;)
779 { 787 { unsigned c;
780 p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); 788 char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
781 if (p) 789 if (p)
782 error("%s", p); 790 error("%s", p);
783 buffer.write4(c); 791 buffer.write4(c);
784 newlen++; 792 newlen++;
785 } 793 }
786 buffer.write4(0); 794 buffer.write4(0);
787 goto L1; 795 goto L1;
788 796
789 case X(Tdchar,Tchar): 797 case X(Tdchar,Tchar):
790 for (u = 0; u < len; u++) 798 for (size_t u = 0; u < len; u++)
791 { 799 {
792 c = ((unsigned *)se->string)[u]; 800 unsigned c = ((unsigned *)se->string)[u];
793 if (!utf_isValidDchar(c)) 801 if (!utf_isValidDchar(c))
794 error("invalid UCS-32 char \\U%08x", c); 802 error("invalid UCS-32 char \\U%08x", c);
795 else 803 else
796 buffer.writeUTF8(c); 804 buffer.writeUTF8(c);
797 newlen++; 805 newlen++;
799 newlen = buffer.offset; 807 newlen = buffer.offset;
800 buffer.writeUTF8(0); 808 buffer.writeUTF8(0);
801 goto L1; 809 goto L1;
802 810
803 case X(Tdchar,Twchar): 811 case X(Tdchar,Twchar):
804 for (u = 0; u < len; u++) 812 for (size_t u = 0; u < len; u++)
805 { 813 {
806 c = ((unsigned *)se->string)[u]; 814 unsigned c = ((unsigned *)se->string)[u];
807 if (!utf_isValidDchar(c)) 815 if (!utf_isValidDchar(c))
808 error("invalid UCS-32 char \\U%08x", c); 816 error("invalid UCS-32 char \\U%08x", c);
809 else 817 else
810 buffer.writeUTF16(c); 818 buffer.writeUTF16(c);
811 newlen++; 819 newlen++;
813 newlen = buffer.offset / 2; 821 newlen = buffer.offset / 2;
814 buffer.writeUTF16(0); 822 buffer.writeUTF16(0);
815 goto L1; 823 goto L1;
816 824
817 L1: 825 L1:
818 if (!unique) 826 if (!copied)
819 se = new StringExp(loc, NULL, 0); 827 { se = (StringExp *)copy();
828 copied = 1;
829 }
820 se->string = buffer.extractData(); 830 se->string = buffer.extractData();
821 se->len = newlen; 831 se->len = newlen;
822 se->sz = tb->next->size(); 832 se->sz = tb->nextOf()->size();
823 break; 833 break;
824 834
825 default: 835 default:
826 if (se->type->next->size() == tb->next->size()) 836 assert(typeb->nextOf()->size() != tb->nextOf()->size());
827 { se->type = t;
828 return se;
829 }
830 goto Lcast; 837 goto Lcast;
831 } 838 }
832 } 839 }
833 #undef X 840 #undef X
841 L2:
842 assert(copied);
834 843
835 // See if need to truncate or extend the literal 844 // See if need to truncate or extend the literal
836 if (tb->ty == Tsarray) 845 if (tb->ty == Tsarray)
837 { 846 {
838 int dim2 = ((TypeSArray *)tb)->dim->toInteger(); 847 int dim2 = ((TypeSArray *)tb)->dim->toInteger();
840 //printf("dim from = %d, to = %d\n", se->len, dim2); 849 //printf("dim from = %d, to = %d\n", se->len, dim2);
841 850
842 // Changing dimensions 851 // Changing dimensions
843 if (dim2 != se->len) 852 if (dim2 != se->len)
844 { 853 {
854 // Copy when changing the string literal
845 unsigned newsz = se->sz; 855 unsigned newsz = se->sz;
846 856 void *s;
847 if (unique && dim2 < se->len) 857 int d;
848 { se->len = dim2; 858
849 // Add terminating 0 859 d = (dim2 < se->len) ? dim2 : se->len;
850 memset((unsigned char *)se->string + dim2 * newsz, 0, newsz); 860 s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
851 } 861 memcpy(s, se->string, d * newsz);
852 else 862 // Extend with 0, add terminating 0
853 { 863 memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
854 // Copy when changing the string literal 864 se->string = s;
855 void *s; 865 se->len = dim2;
856 int d;
857
858 d = (dim2 < se->len) ? dim2 : se->len;
859 s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
860 memcpy(s, se->string, d * newsz);
861 // Extend with 0, add terminating 0
862 memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
863 se = new StringExp(loc, s, dim2);
864 se->committed = 1; // it now has a firm type
865 se->sz = newsz;
866 }
867 } 866 }
868 } 867 }
869 se->type = t; 868 se->type = t;
870 return se; 869 return se;
871 870
872 Lcast: 871 Lcast:
873 Expression *e = new CastExp(loc, se, t); 872 Expression *e = new CastExp(loc, se, t);
874 e->type = t; 873 e->type = t; // so semantic() won't be run on e
875 return e; 874 return e;
876 } 875 }
877 876
878 Expression *AddrExp::castTo(Scope *sc, Type *t) 877 Expression *AddrExp::castTo(Scope *sc, Type *t)
879 { 878 {