comparison dmd/FuncDeclaration.d @ 130:60bb0fe4563e

dmdfe 2.037 first main iteration
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Thu, 09 Sep 2010 22:51:44 +0100
parents 1765f3ef917d
children 206db751bd4c
comparison
equal deleted inserted replaced
129:010eb8f0e18d 130:60bb0fe4563e
52 import dmd.InvariantDeclaration; 52 import dmd.InvariantDeclaration;
53 import dmd.TY; 53 import dmd.TY;
54 import dmd.PtrExp; 54 import dmd.PtrExp;
55 import dmd.DeclarationExp; 55 import dmd.DeclarationExp;
56 import dmd.InlineDoState; 56 import dmd.InlineDoState;
57 import dmd.Argument; 57 import dmd.Parameter;
58 import dmd.StructDeclaration; 58 import dmd.StructDeclaration;
59 import dmd.ClassDeclaration; 59 import dmd.ClassDeclaration;
60 import dmd.InterfaceDeclaration; 60 import dmd.InterfaceDeclaration;
61 import dmd.Array; 61 import dmd.Array;
62 import dmd.Statement; 62 import dmd.Statement;
71 import dmd.Type; 71 import dmd.Type;
72 import dmd.BUILTIN; 72 import dmd.BUILTIN;
73 import dmd.TypeFunction; 73 import dmd.TypeFunction;
74 import dmd.Expression; 74 import dmd.Expression;
75 import dmd.STC; 75 import dmd.STC;
76 import dmd.TRUST;
76 import dmd.Dsymbol; 77 import dmd.Dsymbol;
77 import dmd.Scope; 78 import dmd.Scope;
78 import dmd.OutBuffer; 79 import dmd.OutBuffer;
79 import dmd.HdrGenState; 80 import dmd.HdrGenState;
80 import dmd.MATCH; 81 import dmd.MATCH;
306 307
307 if (!originalType) 308 if (!originalType)
308 originalType = type; 309 originalType = type;
309 if (!type.deco) 310 if (!type.deco)
310 { 311 {
311 /* Apply const and invariant storage class 312 /* Apply const, immutable and shared storage class
312 * to the function type 313 * to the function type
313 */ 314 */
314 type = type.semantic(loc, sc); 315 type = type.semantic(loc, sc);
315 STC stc = storage_class; 316 STC stc = storage_class;
316 if (type.isInvariant()) 317 if (type.isInvariant())
358 { 359 {
359 error("%s must be a function", toChars()); 360 error("%s must be a function", toChars());
360 return; 361 return;
361 } 362 }
362 f = cast(TypeFunction)type; 363 f = cast(TypeFunction)type;
363 size_t nparams = Argument.dim(f.parameters); 364 size_t nparams = Parameter.dim(f.parameters);
364 365
365 linkage = sc.linkage; 366 linkage = sc.linkage;
366 // if (!parent) 367 // if (!parent)
367 { 368 {
368 //parent = sc.scopesym; 369 //parent = sc.scopesym;
731 case 0: 732 case 0:
732 break; 733 break;
733 734
734 case 1: 735 case 1:
735 { 736 {
736 Argument arg0 = Argument.getNth(f.parameters, 0); 737 auto arg0 = Parameter.getNth(f.parameters, 0);
737 if (arg0.type.ty != TY.Tarray || 738 if (arg0.type.ty != TY.Tarray ||
738 arg0.type.nextOf().ty != TY.Tarray || 739 arg0.type.nextOf().ty != TY.Tarray ||
739 arg0.type.nextOf().nextOf().ty != TY.Tchar || 740 arg0.type.nextOf().nextOf().ty != TY.Tchar ||
740 arg0.storageClass & (STC.STCout | STC.STCref | STC.STClazy)) 741 arg0.storageClass & (STC.STCout | STC.STCref | STC.STClazy))
741 goto Lmainerr; 742 goto Lmainerr;
765 { if (f.varargs == 1) 766 { if (f.varargs == 1)
766 goto Lassignerr; 767 goto Lassignerr;
767 } 768 }
768 else 769 else
769 { 770 {
770 Argument arg0 = Argument.getNth(f.parameters, 0); 771 auto arg0 = Parameter.getNth(f.parameters, 0);
771 Type t0 = arg0.type.toBasetype(); 772 Type t0 = arg0.type.toBasetype();
772 Type tb = sd ? sd.type : cd.type; 773 Type tb = sd ? sd.type : cd.type;
773 if (arg0.type.implicitConvTo(tb) || 774 if (arg0.type.implicitConvTo(tb) ||
774 (sd && t0.ty == TY.Tpointer && t0.nextOf().implicitConvTo(tb)) 775 (sd && t0.ty == TY.Tpointer && t0.nextOf().implicitConvTo(tb))
775 ) 776 )
776 { 777 {
777 if (nparams == 1) 778 if (nparams == 1)
778 goto Lassignerr; 779 goto Lassignerr;
779 Argument arg1 = Argument.getNth(f.parameters, 1); 780 auto arg1 = Parameter.getNth(f.parameters, 1);
780 if (arg1.defaultArg) 781 if (arg1.defaultArg)
781 goto Lassignerr; 782 goto Lassignerr;
782 } 783 }
783 } 784 }
784 } 785 }
815 */ 816 */
816 if (!outId && f.nextOf().toBasetype().ty != Tvoid) 817 if (!outId && f.nextOf().toBasetype().ty != Tvoid)
817 outId = Id.result; // provide a default 818 outId = Id.result; // provide a default
818 819
819 Loc loc = fensure.loc; 820 Loc loc = fensure.loc;
820 Arguments arguments = new Arguments(); 821 auto arguments = new Parameters();
821 Argument a = null; 822 Parameter a = null;
822 if (outId) 823 if (outId)
823 { 824 {
824 a = new Argument(STCref, f.nextOf(), outId, null); 825 a = new Parameter(STCref, f.nextOf(), outId, null);
825 arguments.push(a); 826 arguments.push(a);
826 } 827 }
827 TypeFunction tf = new TypeFunction(arguments, Type.tvoid, 0, LINKd); 828 TypeFunction tf = new TypeFunction(arguments, Type.tvoid, 0, LINKd);
828 FuncDeclaration fd = new FuncDeclaration(loc, loc, Id.ensure, STCundefined, tf); 829 FuncDeclaration fd = new FuncDeclaration(loc, loc, Id.ensure, STCundefined, tf);
829 fd.fbody = fensure; 830 fd.fbody = fensure;
921 sc2.sbreak = null; 922 sc2.sbreak = null;
922 sc2.scontinue = null; 923 sc2.scontinue = null;
923 sc2.sw = null; 924 sc2.sw = null;
924 sc2.fes = fes; 925 sc2.fes = fes;
925 sc2.linkage = LINK.LINKd; 926 sc2.linkage = LINK.LINKd;
926 sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref); 927 sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated |
927 sc2.protection = PROT.PROTpublic; 928 STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref |
929 STCproperty | STCsafe | STCtrusted | STCsystem);
930 sc2.protection = PROT.PROTpublic;
928 sc2.explicitProtection = 0; 931 sc2.explicitProtection = 0;
929 sc2.structalign = 8; 932 sc2.structalign = 8;
930 sc2.incontract = 0; 933 sc2.incontract = 0;
931 sc2.tf = null; 934 sc2.tf = null;
932 sc2.noctor = 0; 935 sc2.noctor = 0;
1058 foreach (arg; f.parameters) 1061 foreach (arg; f.parameters)
1059 { 1062 {
1060 //printf("[%d] arg.type.ty = %d %s\n", i, arg.type.ty, arg.type.toChars()); 1063 //printf("[%d] arg.type.ty = %d %s\n", i, arg.type.ty, arg.type.toChars());
1061 if (arg.type.ty == TY.Ttuple) 1064 if (arg.type.ty == TY.Ttuple)
1062 { auto t = cast(TypeTuple)arg.type; 1065 { auto t = cast(TypeTuple)arg.type;
1063 size_t dim = Argument.dim(t.arguments); 1066 size_t dim = Parameter.dim(t.arguments);
1064 for (size_t j = 0; j < dim; j++) 1067 for (size_t j = 0; j < dim; j++)
1065 { Argument narg = Argument.getNth(t.arguments, j); 1068 {
1066 narg.storageClass = arg.storageClass; 1069 auto narg = Parameter.getNth(t.arguments, j);
1070 narg.storageClass = arg.storageClass;
1067 } 1071 }
1068 } 1072 }
1069 } 1073 }
1070 } 1074 }
1071 1075
1072 /* Declare all the function parameters as variables 1076 /* Declare all the function parameters as variables
1073 * and install them in parameters[] 1077 * and install them in parameters[]
1074 */ 1078 */
1075 size_t nparams = Argument.dim(f.parameters); 1079 size_t nparams = Parameter.dim(f.parameters);
1076 if (nparams) 1080 if (nparams)
1077 { /* parameters[] has all the tuples removed, as the back end 1081 { /* parameters[] has all the tuples removed, as the back end
1078 * doesn't know about tuples 1082 * doesn't know about tuples
1079 */ 1083 */
1080 parameters = new Dsymbols(); 1084 parameters = new Dsymbols();
1081 parameters.reserve(nparams); 1085 parameters.reserve(nparams);
1082 for (size_t i = 0; i < nparams; i++) 1086 for (size_t i = 0; i < nparams; i++)
1083 { 1087 {
1084 Argument arg = Argument.getNth(f.parameters, i); 1088 auto arg = Parameter.getNth(f.parameters, i);
1085 Identifier id = arg.ident; 1089 Identifier id = arg.ident;
1086 if (!id) 1090 if (!id)
1087 { 1091 {
1088 /* Generate identifier for un-named parameter, 1092 /* Generate identifier for un-named parameter,
1089 * because we need it later on. 1093 * because we need it later on.
1117 { 1121 {
1118 if (!arg.ident) 1122 if (!arg.ident)
1119 continue; // never used, so ignore 1123 continue; // never used, so ignore
1120 if (arg.type.ty == TY.Ttuple) 1124 if (arg.type.ty == TY.Ttuple)
1121 { auto t = cast(TypeTuple)arg.type; 1125 { auto t = cast(TypeTuple)arg.type;
1122 size_t dim = Argument.dim(t.arguments); 1126 size_t dim = Parameter.dim(t.arguments);
1123 Objects exps = new Objects(); 1127 Objects exps = new Objects();
1124 exps.setDim(dim); 1128 exps.setDim(dim);
1125 for (size_t j = 0; j < dim; j++) 1129 for (size_t j = 0; j < dim; j++)
1126 { Argument narg = Argument.getNth(t.arguments, j); 1130 { auto narg = Parameter.getNth(t.arguments, j);
1127 assert(narg.ident); 1131 assert(narg.ident);
1128 VarDeclaration v = sc2.search(Loc(0), narg.ident, null).isVarDeclaration(); 1132 VarDeclaration v = sc2.search(Loc(0), narg.ident, null).isVarDeclaration();
1129 assert(v); 1133 assert(v);
1130 Expression e = new VarExp(v.loc, v); 1134 Expression e = new VarExp(v.loc, v);
1131 exps[j] = e; 1135 exps[j] = e;
1188 outId = Id.result; // provide a default 1192 outId = Id.result; // provide a default
1189 } 1193 }
1190 1194
1191 if (outId) 1195 if (outId)
1192 { // Declare result variable 1196 { // Declare result variable
1193 VarDeclaration v;
1194 Loc loc = this.loc; 1197 Loc loc = this.loc;
1195 1198
1196 if (fensure) 1199 if (fensure)
1197 loc = fensure.loc; 1200 loc = fensure.loc;
1198 1201
1199 v = new VarDeclaration(loc, type.nextOf(), outId, null); 1202 auto v = new VarDeclaration(loc, type.nextOf(), outId, null);
1200 v.noauto = true; 1203 v.noauto = true;
1201 version (DMDV2) { 1204 version (DMDV2) {
1205 if (!isVirtual())
1206 v.storage_class |= STC.STCconst;
1202 if (f.isref) 1207 if (f.isref)
1203 { 1208 {
1204 v.storage_class |= STC.STCref | STC.STCforeach; 1209 v.storage_class |= STC.STCref | STC.STCforeach;
1205 } 1210 }
1206 } 1211 }
1895 scope OutBuffer buf2 = new OutBuffer(); 1900 scope OutBuffer buf2 = new OutBuffer();
1896 tf.modToBuffer(buf2); 1901 tf.modToBuffer(buf2);
1897 1902
1898 //printf("tf = %s, args = %s\n", tf.deco, ((Expression *)arguments.data[0]).type.deco); 1903 //printf("tf = %s, args = %s\n", tf.deco, ((Expression *)arguments.data[0]).type.deco);
1899 error(loc, "%s%s is not callable using argument types %s", 1904 error(loc, "%s%s is not callable using argument types %s",
1900 Argument.argsTypesToChars(tf.parameters, tf.varargs), 1905 Parameter.argsTypesToChars(tf.parameters, tf.varargs),
1901 buf2.toChars(), 1906 buf2.toChars(),
1902 buf.toChars()); 1907 buf.toChars());
1903 return m.anyf; // as long as it's not a FuncAliasDeclaration 1908 return m.anyf; // as long as it's not a FuncAliasDeclaration
1904 } 1909 }
1905 else 1910 else
1908 TypeFunction t1 = cast(TypeFunction)m.lastf.type; 1913 TypeFunction t1 = cast(TypeFunction)m.lastf.type;
1909 TypeFunction t2 = cast(TypeFunction)m.nextf.type; 1914 TypeFunction t2 = cast(TypeFunction)m.nextf.type;
1910 1915
1911 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s", 1916 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1912 buf.toChars(), 1917 buf.toChars(),
1913 m.lastf.toPrettyChars(), Argument.argsTypesToChars(t1.parameters, t1.varargs), 1918 m.lastf.toPrettyChars(), Parameter.argsTypesToChars(t1.parameters, t1.varargs),
1914 m.nextf.toPrettyChars(), Argument.argsTypesToChars(t2.parameters, t2.varargs)); 1919 m.nextf.toPrettyChars(), Parameter.argsTypesToChars(t2.parameters, t2.varargs));
1915 } else { 1920 } else {
1916 error(loc, "overloads %s and %s both match argument list for %s", 1921 error(loc, "overloads %s and %s both match argument list for %s",
1917 m.lastf.type.toChars(), 1922 m.lastf.type.toChars(),
1918 m.nextf.type.toChars(), 1923 m.nextf.type.toChars(),
1919 m.lastf.toChars()); 1924 m.lastf.toChars());
1941 * as g() is. 1946 * as g() is.
1942 */ 1947 */
1943 1948
1944 TypeFunction tf = cast(TypeFunction)type; 1949 TypeFunction tf = cast(TypeFunction)type;
1945 TypeFunction tg = cast(TypeFunction)g.type; 1950 TypeFunction tg = cast(TypeFunction)g.type;
1946 size_t nfparams = Argument.dim(tf.parameters); 1951 size_t nfparams = Parameter.dim(tf.parameters);
1947 size_t ngparams = Argument.dim(tg.parameters); 1952 size_t ngparams = Parameter.dim(tg.parameters);
1948 MATCH match = MATCHexact; 1953 MATCH match = MATCHexact;
1949 1954
1950 /* If both functions have a 'this' pointer, and the mods are not 1955 /* If both functions have a 'this' pointer, and the mods are not
1951 * the same and g's is not const, then this is less specialized. 1956 * the same and g's is not const, then this is less specialized.
1952 */ 1957 */
1965 */ 1970 */
1966 scope Expressions args = new Expressions(); 1971 scope Expressions args = new Expressions();
1967 args.setDim(nfparams); 1972 args.setDim(nfparams);
1968 for (int u = 0; u < nfparams; u++) 1973 for (int u = 0; u < nfparams; u++)
1969 { 1974 {
1970 Argument p = Argument.getNth(tf.parameters, u); 1975 auto p = Parameter.getNth(tf.parameters, u);
1971 Expression e; 1976 Expression e;
1972 if (p.storageClass & (STCref | STCout)) 1977 if (p.storageClass & (STCref | STCout))
1973 { 1978 {
1974 e = new IdentifierExp(Loc(0), p.ident); 1979 e = new IdentifierExp(Loc(0), p.ident);
1975 e.type = p.type; 1980 e.type = p.type;
2250 //printf("FuncDeclaration::isPure() '%s'\n", toChars()); 2255 //printf("FuncDeclaration::isPure() '%s'\n", toChars());
2251 assert(type.ty == TY.Tfunction); 2256 assert(type.ty == TY.Tfunction);
2252 return (cast(TypeFunction)this.type).ispure; 2257 return (cast(TypeFunction)this.type).ispure;
2253 } 2258 }
2254 2259
2260 int isSafe()
2261 {
2262 assert(type.ty == TY.Tfunction);
2263 return (cast(TypeFunction)this.type).trust == TRUST.TRUSTsafe;
2264 }
2265
2266 int isTrusted()
2267 {
2268 assert(type.ty == TY.Tfunction);
2269 return (cast(TypeFunction)this.type).trust == TRUST.TRUSTtrusted;
2270 }
2271
2255 bool isNested() 2272 bool isNested()
2256 { 2273 {
2257 //if (!toParent()) 2274 //if (!toParent())
2258 //printf("FuncDeclaration.isNested('%s') parent=%p\n", toChars(), parent); 2275 //printf("FuncDeclaration.isNested('%s') parent=%p\n", toChars(), parent);
2259 //printf("\ttoParent2() = '%s'\n", toParent2().toChars()); 2276 //printf("\ttoParent2() = '%s'\n", toParent2().toChars());
2390 } 2407 }
2391 2408
2392 // Ensure there are no lazy parameters 2409 // Ensure there are no lazy parameters
2393 if (tf.parameters) 2410 if (tf.parameters)
2394 { 2411 {
2395 size_t dim = Argument.dim(tf.parameters); 2412 size_t dim = Parameter.dim(tf.parameters);
2396 for (size_t i = 0; i < dim; i++) 2413 for (size_t i = 0; i < dim; i++)
2397 { 2414 {
2398 Argument arg = Argument.getNth(tf.parameters, i); 2415 auto arg = Parameter.getNth(tf.parameters, i);
2399 if (arg.storageClass & STClazy) 2416 if (arg.storageClass & STClazy)
2400 { 2417 {
2401 cantInterpret = 1; 2418 cantInterpret = 1;
2402 return null; 2419 return null;
2403 } 2420 }
2431 eargs.setDim(dim); 2448 eargs.setDim(dim);
2432 2449
2433 for (size_t i = 0; i < dim; i++) 2450 for (size_t i = 0; i < dim; i++)
2434 { 2451 {
2435 Expression earg = arguments[i]; 2452 Expression earg = arguments[i];
2436 Argument arg = Argument.getNth(tf.parameters, i); 2453 auto arg = Parameter.getNth(tf.parameters, i);
2437 2454
2438 if (arg.storageClass & (STCout | STCref)) 2455 if (arg.storageClass & (STCout | STCref))
2439 { 2456 {
2440 } 2457 }
2441 else 2458 else
2460 } 2477 }
2461 2478
2462 for (size_t i = 0; i < dim; i++) 2479 for (size_t i = 0; i < dim; i++)
2463 { 2480 {
2464 auto earg = eargs[i]; 2481 auto earg = eargs[i];
2465 Argument arg = Argument.getNth(tf.parameters, i); 2482 auto arg = Parameter.getNth(tf.parameters, i);
2466 auto v = cast(VarDeclaration)parameters[i]; 2483 auto v = cast(VarDeclaration)parameters[i];
2467 vsave[i] = v.value; 2484 vsave[i] = v.value;
2468 version (LOG) { 2485 version (LOG) {
2469 printf("arg[%d] = %s\n", i, earg.toChars()); 2486 printf("arg[%d] = %s\n", i, earg.toChars());
2470 } 2487 }