Mercurial > projects > ldc
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 { |