72
|
1 module dmd.CallExp;
|
|
2
|
79
|
3 import dmd.ErrorExp;
|
72
|
4 import dmd.Expression;
|
|
5 import dmd.Cast;
|
|
6 import dmd.WANT;
|
|
7 import dmd.BUILTIN;
|
|
8 import dmd.TypeFunction;
|
|
9 import dmd.ScopeDsymbol;
|
|
10 import dmd.CastExp;
|
|
11 import dmd.GlobalExpressions;
|
|
12 import dmd.TypePointer;
|
|
13 import dmd.ThisExp;
|
|
14 import dmd.OverExp;
|
|
15 import dmd.Dsymbol;
|
|
16 import dmd.CSX;
|
|
17 import dmd.AggregateDeclaration;
|
|
18 import dmd.TypeDelegate;
|
|
19 import dmd.ClassDeclaration;
|
|
20 import dmd.DsymbolExp;
|
|
21 import dmd.DotExp;
|
|
22 import dmd.TemplateExp;
|
|
23 import dmd.TypeStruct;
|
|
24 import dmd.TypeClass;
|
|
25 import dmd.Identifier;
|
|
26 import dmd.Lexer;
|
|
27 import dmd.VarDeclaration;
|
|
28 import dmd.DeclarationExp;
|
|
29 import dmd.CtorDeclaration;
|
|
30 import dmd.PtrExp;
|
|
31 import dmd.TemplateDeclaration;
|
|
32 import dmd.StructLiteralExp;
|
|
33 import dmd.StructDeclaration;
|
|
34 import dmd.DotTemplateExp;
|
|
35 import dmd.CommaExp;
|
|
36 import dmd.AggregateDeclaration;
|
|
37 import dmd.FuncDeclaration;
|
|
38 import dmd.Type;
|
|
39 import dmd.ScopeExp;
|
|
40 import dmd.VarExp;
|
|
41 import dmd.STC;
|
|
42 import dmd.LINK;
|
|
43 import dmd.Global;
|
|
44 import dmd.DotTemplateInstanceExp;
|
|
45 import dmd.TemplateInstance;
|
|
46 import dmd.DelegateExp;
|
|
47 import dmd.IdentifierExp;
|
|
48 import dmd.DotVarExp;
|
|
49 import dmd.DotIdExp;
|
|
50 import dmd.TY;
|
|
51 import dmd.Id;
|
|
52 import dmd.TypeAArray;
|
|
53 import dmd.RemoveExp;
|
|
54 import dmd.backend.elem;
|
|
55 import dmd.UnaExp;
|
|
56 import dmd.InterState;
|
|
57 import dmd.OutBuffer;
|
|
58 import dmd.Loc;
|
|
59 import dmd.Scope;
|
|
60 import dmd.InlineCostState;
|
|
61 import dmd.IRState;
|
|
62 import dmd.InlineDoState;
|
|
63 import dmd.HdrGenState;
|
|
64 import dmd.InlineScanState;
|
|
65 import dmd.ArrayTypes;
|
|
66 import dmd.TOK;
|
|
67 import dmd.PREC;
|
|
68 import dmd.expression.Util;
|
|
69 import dmd.backend.Symbol;
|
|
70 import dmd.backend.TYPE;
|
|
71 import dmd.backend.Util;
|
|
72 import dmd.backend.TYM;
|
|
73 import dmd.codegen.Util;
|
|
74
|
|
75 import std.stdio;
|
|
76
|
0
|
77 class CallExp : UnaExp
|
|
78 {
|
|
79 Expressions arguments;
|
|
80
|
|
81 this(Loc loc, Expression e, Expressions exps)
|
|
82 {
|
72
|
83 super(loc, TOK.TOKcall, CallExp.sizeof, e);
|
0
|
84 this.arguments = exps;
|
|
85 }
|
|
86
|
|
87 this(Loc loc, Expression e)
|
|
88 {
|
|
89 super(loc, TOK.TOKcall, CallExp.sizeof, e);
|
|
90 }
|
|
91
|
|
92 this(Loc loc, Expression e, Expression earg1)
|
|
93 {
|
72
|
94 super(loc, TOK.TOKcall, CallExp.sizeof, e);
|
|
95
|
|
96 Expressions arguments = new Expressions();
|
73
|
97 if (earg1)
|
|
98 {
|
|
99 arguments.setDim(1);
|
|
100 arguments.data[0] = cast(void*)earg1;
|
|
101 }
|
0
|
102 this.arguments = arguments;
|
|
103 }
|
|
104
|
|
105 this(Loc loc, Expression e, Expression earg1, Expression earg2)
|
72
|
106 {
|
|
107 super(loc, TOK.TOKcall, CallExp.sizeof, e);
|
66
|
108
|
72
|
109 Expressions arguments = new Expressions();
|
|
110 arguments.setDim(2);
|
|
111 arguments.data[0] = cast(void*)earg1;
|
|
112 arguments.data[1] = cast(void*)earg2;
|
|
113
|
66
|
114 this.arguments = arguments;
|
0
|
115 }
|
|
116
|
72
|
117 override Expression syntaxCopy()
|
0
|
118 {
|
|
119 return new CallExp(loc, e1.syntaxCopy(), arraySyntaxCopy(arguments));
|
|
120 }
|
|
121
|
72
|
122 override Expression semantic(Scope sc)
|
|
123 {
|
|
124 TypeFunction tf;
|
|
125 FuncDeclaration f;
|
|
126 Type t1;
|
|
127 int istemp;
|
|
128 Objects targsi; // initial list of template arguments
|
|
129 TemplateInstance tierror;
|
|
130
|
79
|
131 version (LOGSEMANTIC)
|
|
132 {
|
72
|
133 printf("CallExp.semantic() %s\n", toChars());
|
|
134 }
|
|
135 if (type)
|
|
136 return this; // semantic() already run
|
|
137
|
79
|
138 static if (false)
|
|
139 {
|
72
|
140 if (arguments && arguments.dim)
|
|
141 {
|
|
142 Expression earg = cast(Expression)arguments.data[0];
|
|
143 earg.print();
|
|
144 if (earg.type) earg.type.print();
|
|
145 }
|
|
146 }
|
|
147
|
|
148 if (e1.op == TOK.TOKdelegate)
|
|
149 {
|
|
150 DelegateExp de = cast(DelegateExp)e1;
|
|
151
|
|
152 e1 = new DotVarExp(de.loc, de.e1, de.func);
|
|
153 return semantic(sc);
|
|
154 }
|
|
155
|
|
156 /* Transform:
|
|
157 * array.id(args) into .id(array,args)
|
|
158 * aa.remove(arg) into delete aa[arg]
|
|
159 */
|
|
160 if (e1.op == TOK.TOKdot)
|
|
161 {
|
|
162 // BUG: we should handle array.a.b.c.e(args) too
|
|
163
|
|
164 DotIdExp dotid = cast(DotIdExp)(e1);
|
|
165 dotid.e1 = dotid.e1.semantic(sc);
|
|
166 assert(dotid.e1);
|
|
167 if (dotid.e1.type)
|
|
168 {
|
|
169 TY e1ty = dotid.e1.type.toBasetype().ty;
|
|
170 if (e1ty == TY.Taarray && dotid.ident == Id.remove)
|
|
171 {
|
|
172 if (!arguments || arguments.dim != 1)
|
|
173 {
|
|
174 error("expected key as argument to aa.remove()");
|
|
175 goto Lagain;
|
|
176 }
|
|
177 Expression key = cast(Expression)arguments.data[0];
|
|
178 key = key.semantic(sc);
|
|
179 key = resolveProperties(sc, key);
|
|
180 key.rvalue();
|
|
181
|
|
182 TypeAArray taa = cast(TypeAArray)dotid.e1.type.toBasetype();
|
|
183 key = key.implicitCastTo(sc, taa.index);
|
|
184
|
|
185 return new RemoveExp(loc, dotid.e1, key);
|
|
186 }
|
|
187 else if (e1ty == TY.Tarray || e1ty == TY.Tsarray || e1ty == TY.Taarray)
|
|
188 {
|
|
189 if (!arguments)
|
|
190 arguments = new Expressions();
|
|
191 arguments.shift(cast(void*)dotid.e1);
|
|
192 version (DMDV2) {
|
|
193 e1 = new DotIdExp(dotid.loc, new IdentifierExp(dotid.loc, Id.empty), dotid.ident);
|
|
194 } else {
|
|
195 e1 = new IdentifierExp(dotid.loc, dotid.ident);
|
|
196 }
|
|
197 }
|
|
198 }
|
|
199 }
|
|
200
|
|
201 static if (true) {
|
|
202 /* This recognizes:
|
|
203 * foo!(tiargs)(funcargs)
|
|
204 */
|
|
205 if (e1.op == TOK.TOKimport && !e1.type)
|
|
206 {
|
|
207 ScopeExp se = cast(ScopeExp)e1;
|
|
208 TemplateInstance ti = se.sds.isTemplateInstance();
|
|
209 if (ti && !ti.semanticRun)
|
|
210 {
|
|
211 /* Attempt to instantiate ti. If that works, go with it.
|
|
212 * If not, go with partial explicit specialization.
|
|
213 */
|
|
214 ti.semanticTiargs(sc);
|
|
215 uint errors = global.errors;
|
|
216 global.gag++;
|
|
217 ti.semantic(sc);
|
|
218 global.gag--;
|
|
219 if (errors != global.errors)
|
|
220 {
|
|
221 /* Didn't work, go with partial explicit specialization
|
|
222 */
|
|
223 global.errors = errors;
|
|
224 targsi = ti.tiargs;
|
|
225 tierror = ti; // for error reporting
|
|
226 e1 = new IdentifierExp(loc, ti.name);
|
|
227 }
|
|
228 }
|
|
229 }
|
|
230
|
|
231 /* This recognizes:
|
|
232 * expr.foo!(tiargs)(funcargs)
|
|
233 */
|
|
234 if (e1.op == TOK.TOKdotti && !e1.type)
|
|
235 {
|
|
236 DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)e1;
|
|
237 TemplateInstance ti = se.ti;
|
|
238 if (!ti.semanticRun)
|
|
239 {
|
|
240 /* Attempt to instantiate ti. If that works, go with it.
|
|
241 * If not, go with partial explicit specialization.
|
|
242 */
|
|
243 ti.semanticTiargs(sc);
|
|
244 Expression etmp = e1.trySemantic(sc);
|
|
245 if (etmp)
|
|
246 e1 = etmp; // it worked
|
|
247 else // didn't work
|
|
248 {
|
|
249 targsi = ti.tiargs;
|
|
250 tierror = ti; // for error reporting
|
|
251 e1 = new DotIdExp(loc, se.e1, ti.name);
|
|
252 }
|
|
253 }
|
|
254 }
|
|
255 }
|
|
256
|
|
257 istemp = 0;
|
|
258 Lagain:
|
|
259 //printf("Lagain: %s\n", toChars());
|
|
260 f = null;
|
|
261 if (e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper)
|
|
262 {
|
|
263 // semantic() run later for these
|
|
264 }
|
|
265 else
|
|
266 {
|
|
267 UnaExp.semantic(sc);
|
|
268
|
|
269 /* Look for e1 being a lazy parameter
|
|
270 */
|
|
271 if (e1.op == TOK.TOKvar)
|
|
272 {
|
|
273 VarExp ve = cast(VarExp)e1;
|
|
274
|
|
275 if (ve.var.storage_class & STC.STClazy)
|
|
276 {
|
|
277 TypeFunction tff = new TypeFunction(null, ve.var.type, 0, LINK.LINKd);
|
|
278 TypeDelegate t = new TypeDelegate(tff);
|
|
279 ve.type = t.semantic(loc, sc);
|
|
280 }
|
|
281 }
|
|
282
|
|
283 if (e1.op == TOK.TOKimport)
|
|
284 {
|
|
285 // Perhaps this should be moved to ScopeExp.semantic()
|
|
286 ScopeExp se = cast(ScopeExp)e1;
|
|
287 e1 = new DsymbolExp(loc, se.sds);
|
|
288 e1 = e1.semantic(sc);
|
|
289 }
|
|
290 ///static if (true) { // patch for #540 by Oskar Linde
|
|
291 else if (e1.op == TOK.TOKdotexp)
|
|
292 {
|
|
293 DotExp de = cast(DotExp)e1;
|
|
294
|
|
295 if (de.e2.op == TOK.TOKimport)
|
|
296 {
|
|
297 // This should *really* be moved to ScopeExp.semantic()
|
|
298 ScopeExp se = cast(ScopeExp)de.e2;
|
|
299 de.e2 = new DsymbolExp(loc, se.sds);
|
|
300 de.e2 = de.e2.semantic(sc);
|
|
301 }
|
|
302
|
|
303 if (de.e2.op == TOK.TOKtemplate)
|
|
304 {
|
|
305 TemplateExp te = cast(TemplateExp)de.e2;
|
|
306 e1 = new DotTemplateExp(loc,de.e1,te.td);
|
|
307 }
|
|
308 }
|
|
309 ///}
|
|
310 }
|
|
311
|
|
312 if (e1.op == TOK.TOKcomma)
|
|
313 {
|
|
314 CommaExp ce = cast(CommaExp)e1;
|
|
315
|
|
316 e1 = ce.e2;
|
|
317 e1.type = ce.type;
|
|
318 ce.e2 = this;
|
|
319 ce.type = null;
|
|
320 return ce.semantic(sc);
|
|
321 }
|
|
322
|
|
323 t1 = null;
|
|
324 if (e1.type)
|
|
325 t1 = e1.type.toBasetype();
|
|
326
|
|
327 // Check for call operator overload
|
|
328 if (t1)
|
|
329 {
|
|
330 AggregateDeclaration ad;
|
|
331
|
|
332 if (t1.ty == TY.Tstruct)
|
|
333 {
|
|
334 ad = (cast(TypeStruct)t1).sym;
|
|
335 version (DMDV2) {
|
|
336 // First look for constructor
|
|
337 if (ad.ctor && arguments && arguments.dim)
|
|
338 {
|
|
339 // Create variable that will get constructed
|
|
340 Identifier idtmp = Lexer.uniqueId("__ctmp");
|
|
341 VarDeclaration tmp = new VarDeclaration(loc, t1, idtmp, null);
|
|
342 Expression av = new DeclarationExp(loc, tmp);
|
|
343 av = new CommaExp(loc, av, new VarExp(loc, tmp));
|
|
344
|
|
345 Expression e;
|
|
346 CtorDeclaration cf = ad.ctor.isCtorDeclaration();
|
|
347 if (cf)
|
|
348 e = new DotVarExp(loc, av, cf, 1);
|
|
349 else
|
|
350 {
|
|
351 TemplateDeclaration td = ad.ctor.isTemplateDeclaration();
|
|
352 assert(td);
|
|
353 e = new DotTemplateExp(loc, av, td);
|
|
354 }
|
|
355 e = new CallExp(loc, e, arguments);
|
|
356 version (STRUCTTHISREF) {
|
|
357 } else {
|
|
358 /* Constructors return a pointer to the instance
|
|
359 */
|
|
360 e = new PtrExp(loc, e);
|
|
361 }
|
|
362 e = e.semantic(sc);
|
|
363 return e;
|
|
364 }
|
|
365 }
|
|
366 // No constructor, look for overload of opCall
|
|
367 if (search_function(ad, Id.call))
|
|
368 goto L1; // overload of opCall, therefore it's a call
|
|
369
|
|
370 if (e1.op != TOK.TOKtype)
|
|
371 error("%s %s does not overload ()", ad.kind(), ad.toChars());
|
|
372
|
|
373 /* It's a struct literal
|
|
374 */
|
|
375 Expression e = new StructLiteralExp(loc, cast(StructDeclaration)ad, arguments);
|
|
376 e = e.semantic(sc);
|
|
377 e.type = e1.type; // in case e1.type was a typedef
|
|
378 return e;
|
|
379 }
|
|
380 else if (t1.ty == TY.Tclass)
|
|
381 {
|
|
382 ad = (cast(TypeClass)t1).sym;
|
|
383 goto L1;
|
|
384 L1:
|
|
385 // Rewrite as e1.call(arguments)
|
|
386 Expression e = new DotIdExp(loc, e1, Id.call);
|
|
387 e = new CallExp(loc, e, arguments);
|
|
388 e = e.semantic(sc);
|
|
389 return e;
|
|
390 }
|
|
391 }
|
|
392
|
|
393 arrayExpressionSemantic(arguments, sc);
|
|
394 preFunctionArguments(loc, sc, arguments);
|
|
395
|
|
396 if (e1.op == TOK.TOKdotvar && t1.ty == TY.Tfunction ||
|
|
397 e1.op == TOK.TOKdottd)
|
|
398 {
|
|
399 DotVarExp dve;
|
|
400 DotTemplateExp dte;
|
|
401 AggregateDeclaration ad;
|
|
402 UnaExp ue = cast(UnaExp)e1;
|
|
403
|
|
404 if (e1.op == TOK.TOKdotvar)
|
|
405 {
|
|
406 // Do overload resolution
|
|
407 dve = cast(DotVarExp)e1;
|
|
408
|
|
409 f = dve.var.isFuncDeclaration();
|
|
410 assert(f);
|
|
411 f = f.overloadResolve(loc, ue.e1, arguments);
|
|
412
|
|
413 ad = f.toParent().isAggregateDeclaration();
|
|
414 }
|
|
415 else
|
|
416 {
|
|
417 dte = cast(DotTemplateExp)e1;
|
|
418 TemplateDeclaration td = dte.td;
|
|
419 assert(td);
|
|
420
|
|
421 if (!arguments)
|
|
422 // Should fix deduceFunctionTemplate() so it works on null argument
|
|
423 arguments = new Expressions();
|
|
424
|
|
425 f = td.deduceFunctionTemplate(sc, loc, targsi, ue.e1, arguments);
|
|
426 if (!f)
|
|
427 {
|
|
428 type = Type.terror;
|
|
429 return this;
|
|
430 }
|
|
431 ad = td.toParent().isAggregateDeclaration();
|
|
432 }
|
|
433
|
|
434 if (f.needThis())
|
|
435 {
|
|
436 ue.e1 = getRightThis(loc, sc, ad, ue.e1, f);
|
|
437 }
|
|
438
|
|
439 /* Cannot call public functions from inside invariant
|
|
440 * (because then the invariant would have infinite recursion)
|
|
441 */
|
|
442 if (sc.func && sc.func.isInvariantDeclaration() &&
|
|
443 ue.e1.op == TOK.TOKthis && f.addPostInvariant())
|
|
444 {
|
|
445 error("cannot call public/export function %s from invariant", f.toChars());
|
|
446 }
|
|
447
|
|
448 checkDeprecated(sc, f);
|
|
449 version (DMDV2) {
|
|
450 checkPurity(sc, f);
|
|
451 }
|
|
452 accessCheck(loc, sc, ue.e1, f);
|
|
453 if (!f.needThis())
|
|
454 {
|
|
455 VarExp ve = new VarExp(loc, f);
|
|
456 e1 = new CommaExp(loc, ue.e1, ve);
|
|
457 e1.type = f.type;
|
|
458 }
|
|
459 else
|
|
460 {
|
|
461 if (e1.op == TOK.TOKdotvar)
|
|
462 dve.var = f;
|
|
463 else
|
|
464 e1 = new DotVarExp(loc, dte.e1, f);
|
|
465
|
|
466 e1.type = f.type;
|
|
467 static if (false) {
|
|
468 printf("ue.e1 = %s\n", ue.e1.toChars());
|
|
469 printf("f = %s\n", f.toChars());
|
|
470 printf("t = %s\n", t.toChars());
|
|
471 printf("e1 = %s\n", e1.toChars());
|
|
472 printf("e1.type = %s\n", e1.type.toChars());
|
|
473 }
|
|
474 // Const member function can take const/immutable/mutable this
|
|
475 if (!(f.type.isConst()))
|
|
476 {
|
|
477 // Check for const/immutable compatibility
|
|
478 Type tthis = ue.e1.type.toBasetype();
|
|
479 if (tthis.ty == TY.Tpointer)
|
|
480 tthis = tthis.nextOf().toBasetype();
|
|
481
|
|
482 static if (false) { // this checking should have been already done
|
|
483 if (f.type.isInvariant())
|
|
484 {
|
|
485 if (tthis.mod != MOD.MODinvariant)
|
|
486 error("%s can only be called with an immutable object", e1.toChars());
|
|
487 }
|
|
488 else if (f.type.isShared())
|
|
489 {
|
|
490 if (tthis.mod != MOD.MODinvariant && tthis.mod != MOD.MODshared && tthis.mod != (MOD.MODshared | MOD.MODconst))
|
|
491 error("shared %s can only be called with a shared or immutable object", e1.toChars());
|
|
492 }
|
|
493 else
|
|
494 {
|
|
495 if (tthis.mod != MOD.MODundefined)
|
|
496 {
|
|
497 //printf("mod = %x\n", tthis.mod);
|
|
498 error("%s can only be called with a mutable object, not %s", e1.toChars(), tthis.toChars());
|
|
499 }
|
|
500 }
|
|
501 }
|
|
502 /* Cannot call mutable method on a final struct
|
|
503 */
|
|
504 if (tthis.ty == TY.Tstruct &&
|
|
505 ue.e1.op == TOK.TOKvar)
|
|
506 {
|
|
507 VarExp v = cast(VarExp)ue.e1;
|
|
508 if (v.var.storage_class & STC.STCfinal)
|
|
509 error("cannot call mutable method on final struct");
|
|
510 }
|
|
511 }
|
|
512
|
|
513 // See if we need to adjust the 'this' pointer
|
|
514 AggregateDeclaration add = f.isThis();
|
|
515 ClassDeclaration cd = ue.e1.type.isClassHandle();
|
|
516 if (add && cd && add.isClassDeclaration() && add != cd && ue.e1.op != TOK.TOKsuper)
|
|
517 {
|
|
518 ue.e1 = ue.e1.castTo(sc, add.type); //new CastExp(loc, ue.e1, add.type);
|
|
519 ue.e1 = ue.e1.semantic(sc);
|
|
520 }
|
|
521 }
|
|
522 t1 = e1.type;
|
|
523 }
|
|
524 else if (e1.op == TOK.TOKsuper)
|
|
525 {
|
|
526 // Base class constructor call
|
|
527 ClassDeclaration cd = null;
|
|
528
|
|
529 if (sc.func)
|
|
530 cd = sc.func.toParent().isClassDeclaration();
|
|
531 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
|
|
532 {
|
|
533 error("super class constructor call must be in a constructor");
|
|
534 type = Type.terror;
|
|
535 return this;
|
|
536 }
|
|
537 else
|
|
538 {
|
|
539 if (!cd.baseClass.ctor)
|
|
540 {
|
|
541 error("no super class constructor for %s", cd.baseClass.toChars());
|
|
542 type = Type.terror;
|
|
543 return this;
|
|
544 }
|
|
545 else
|
|
546 {
|
|
547 if (!sc.intypeof)
|
|
548 {
|
|
549 static if (false) {
|
|
550 if (sc.callSuper & (CSX.CSXthis | CSX.CSXsuper))
|
|
551 error("reference to this before super()");
|
|
552 }
|
|
553 if (sc.noctor || sc.callSuper & CSX.CSXlabel)
|
|
554 error("constructor calls not allowed in loops or after labels");
|
|
555 if (sc.callSuper & (CSX.CSXsuper_ctor | CSX.CSXthis_ctor))
|
|
556 error("multiple constructor calls");
|
|
557 sc.callSuper |= CSX.CSXany_ctor | CSX.CSXsuper_ctor;
|
|
558 }
|
|
559
|
|
560 f = resolveFuncCall(sc, loc, cd.baseClass.ctor, null, null, arguments, 0);
|
|
561 checkDeprecated(sc, f);
|
|
562 version (DMDV2) {
|
|
563 checkPurity(sc, f);
|
|
564 }
|
|
565 e1 = new DotVarExp(e1.loc, e1, f);
|
|
566 e1 = e1.semantic(sc);
|
|
567 t1 = e1.type;
|
|
568 }
|
|
569 }
|
|
570 }
|
|
571 else if (e1.op == TOK.TOKthis)
|
|
572 {
|
|
573 // same class constructor call
|
|
574 AggregateDeclaration cd = null;
|
|
575
|
|
576 if (sc.func)
|
|
577 cd = sc.func.toParent().isAggregateDeclaration();
|
|
578 if (!cd || !sc.func.isCtorDeclaration())
|
|
579 {
|
|
580 error("constructor call must be in a constructor");
|
|
581 type = Type.terror;
|
|
582 return this;
|
|
583 }
|
|
584 else
|
|
585 {
|
|
586 if (!sc.intypeof)
|
|
587 {
|
|
588 static if (false) {
|
|
589 if (sc.callSuper & (CSXthis | CSXsuper))
|
|
590 error("reference to this before super()");
|
|
591 }
|
|
592 if (sc.noctor || sc.callSuper & CSX.CSXlabel)
|
|
593 error("constructor calls not allowed in loops or after labels");
|
|
594 if (sc.callSuper & (CSX.CSXsuper_ctor | CSX.CSXthis_ctor))
|
|
595 error("multiple constructor calls");
|
|
596 sc.callSuper |= CSX.CSXany_ctor | CSX.CSXthis_ctor;
|
|
597 }
|
|
598
|
|
599 f = resolveFuncCall(sc, loc, cd.ctor, null, null, arguments, 0);
|
|
600 checkDeprecated(sc, f);
|
|
601 version (DMDV2) {
|
|
602 checkPurity(sc, f);
|
|
603 }
|
|
604 e1 = new DotVarExp(e1.loc, e1, f);
|
|
605 e1 = e1.semantic(sc);
|
|
606 t1 = e1.type;
|
|
607
|
|
608 // BUG: this should really be done by checking the static
|
|
609 // call graph
|
|
610 if (f == sc.func)
|
|
611 error("cyclic constructor call");
|
|
612 }
|
|
613 }
|
|
614 else if (e1.op == TOK.TOKoverloadset)
|
|
615 {
|
|
616 OverExp eo = cast(OverExp)e1;
|
|
617 FuncDeclaration ff = null;
|
79
|
618 Dsymbol s = null;
|
|
619 for(size_t i = 0; i<eo.vars.a.dim; i++)
|
|
620 {
|
|
621 s = eo.vars.a[i];
|
72
|
622 FuncDeclaration f2 = s.isFuncDeclaration();
|
|
623 if (f2)
|
|
624 {
|
|
625 f2 = f2.overloadResolve(loc, null, arguments, 1);
|
|
626 }
|
|
627 else
|
|
628 {
|
|
629 TemplateDeclaration td = s.isTemplateDeclaration();
|
|
630 assert(td);
|
|
631 f2 = td.deduceFunctionTemplate(sc, loc, targsi, null, arguments, 1);
|
|
632 }
|
|
633 if (f2)
|
|
634 {
|
|
635 if (ff)
|
|
636 /* Error if match in more than one overload set,
|
|
637 * even if one is a 'better' match than the other.
|
|
638 */
|
|
639 ScopeDsymbol.multiplyDefined(loc, ff, f2);
|
|
640 else
|
|
641 ff = f2;
|
|
642 }
|
|
643 }
|
|
644 if (!ff)
|
79
|
645 {
|
|
646 // No overload matches
|
|
647 error("no overload matches for %s", s.toChars());
|
|
648 return new ErrorExp();
|
72
|
649 }
|
|
650 e1 = new VarExp(loc, ff);
|
|
651 goto Lagain;
|
|
652 }
|
|
653 else if (!t1)
|
|
654 {
|
|
655 error("function expected before (), not '%s'", e1.toChars());
|
|
656 type = Type.terror;
|
|
657 return this;
|
|
658 }
|
|
659 else if (t1.ty != TY.Tfunction)
|
|
660 {
|
|
661 if (t1.ty == TY.Tdelegate)
|
|
662 {
|
|
663 TypeDelegate td = cast(TypeDelegate)t1;
|
|
664 assert(td.next.ty == TY.Tfunction);
|
|
665 tf = cast(TypeFunction)(td.next);
|
|
666 if (sc.func && sc.func.isPure() && !tf.ispure)
|
|
667 {
|
|
668 error("pure function '%s' cannot call impure delegate '%s'", sc.func.toChars(), e1.toChars());
|
|
669 }
|
|
670 goto Lcheckargs;
|
|
671 }
|
|
672 else if (t1.ty == TY.Tpointer && (cast(TypePointer)t1).next.ty == TY.Tfunction)
|
|
673 {
|
|
674 Expression e = new PtrExp(loc, e1);
|
|
675 t1 = (cast(TypePointer)t1).next;
|
|
676 if (sc.func && sc.func.isPure() && !(cast(TypeFunction)t1).ispure)
|
|
677 {
|
|
678 error("pure function '%s' cannot call impure function pointer '%s'", sc.func.toChars(), e1.toChars());
|
|
679 }
|
|
680 e.type = t1;
|
|
681 e1 = e;
|
|
682 }
|
|
683 else if (e1.op == TOK.TOKtemplate)
|
|
684 {
|
|
685 TemplateExp te = cast(TemplateExp)e1;
|
|
686 f = te.td.deduceFunctionTemplate(sc, loc, targsi, null, arguments);
|
|
687 if (!f)
|
|
688 {
|
|
689 if (tierror)
|
|
690 tierror.error("errors instantiating template"); // give better error message
|
|
691 type = Type.terror;
|
|
692 return this;
|
|
693 }
|
|
694 if (f.needThis() && hasThis(sc))
|
|
695 {
|
|
696 // Supply an implicit 'this', as in
|
|
697 // this.ident
|
|
698
|
|
699 e1 = new DotTemplateExp(loc, (new ThisExp(loc)).semantic(sc), te.td);
|
|
700 goto Lagain;
|
|
701 }
|
|
702
|
|
703 e1 = new VarExp(loc, f);
|
|
704 goto Lagain;
|
|
705 }
|
|
706 else
|
|
707 {
|
|
708 error("function expected before (), not %s of type %s", e1.toChars(), e1.type.toChars());
|
|
709 type = Type.terror;
|
|
710 return this;
|
|
711 }
|
|
712 }
|
|
713 else if (e1.op == TOK.TOKvar)
|
|
714 {
|
|
715 // Do overload resolution
|
|
716 VarExp ve = cast(VarExp)e1;
|
|
717
|
|
718 f = ve.var.isFuncDeclaration();
|
|
719 assert(f);
|
|
720
|
|
721 if (ve.hasOverloads)
|
|
722 f = f.overloadResolve(loc, null, arguments);
|
|
723
|
|
724 checkDeprecated(sc, f);
|
|
725 version (DMDV2) {
|
|
726 checkPurity(sc, f);
|
|
727 }
|
|
728
|
|
729 if (f.needThis() && hasThis(sc))
|
|
730 {
|
|
731 // Supply an implicit 'this', as in
|
|
732 // this.ident
|
|
733
|
|
734 e1 = new DotVarExp(loc, new ThisExp(loc), f);
|
|
735 goto Lagain;
|
|
736 }
|
|
737
|
|
738 accessCheck(loc, sc, null, f);
|
|
739
|
|
740 ve.var = f;
|
73
|
741 // ve.hasOverloads = false;
|
72
|
742 ve.type = f.type;
|
|
743 t1 = f.type;
|
|
744 }
|
|
745 assert(t1.ty == TY.Tfunction);
|
|
746 tf = cast(TypeFunction)t1;
|
|
747
|
|
748 Lcheckargs:
|
|
749 assert(tf.ty == TY.Tfunction);
|
|
750 type = tf.next;
|
|
751
|
|
752 if (!arguments)
|
|
753 arguments = new Expressions();
|
|
754
|
|
755 functionArguments(loc, sc, tf, arguments);
|
|
756
|
|
757 if (!type)
|
|
758 {
|
|
759 error("forward reference to inferred return type of function call %s", toChars());
|
|
760 type = Type.terror;
|
|
761 }
|
|
762
|
|
763 if (f && f.tintro)
|
|
764 {
|
|
765 Type t = type;
|
|
766 int offset = 0;
|
|
767 TypeFunction tff = cast(TypeFunction)f.tintro;
|
|
768
|
|
769 if (tff.next.isBaseOf(t, &offset) && offset)
|
|
770 {
|
|
771 type = tff.next;
|
|
772 return castTo(sc, t);
|
|
773 }
|
|
774 }
|
|
775
|
|
776 return this;
|
0
|
777 }
|
|
778
|
72
|
779 override Expression optimize(int result)
|
0
|
780 {
|
72
|
781 //printf("CallExp::optimize(result = %d) %s\n", result, toChars());
|
|
782 Expression e = this;
|
|
783
|
|
784 // Optimize parameters
|
|
785 if (arguments)
|
|
786 {
|
|
787 for (size_t i = 0; i < arguments.dim; i++)
|
|
788 {
|
|
789 Expression ee = cast(Expression)arguments.data[i];
|
|
790
|
|
791 ee = ee.optimize(WANT.WANTvalue);
|
|
792 arguments.data[i] = cast(void*)ee;
|
|
793 }
|
|
794 }
|
|
795
|
|
796 e1 = e1.optimize(result);
|
|
797 if (e1.op == TOK.TOKvar)
|
|
798 {
|
|
799 FuncDeclaration fd = (cast(VarExp)e1).var.isFuncDeclaration();
|
|
800 if (fd)
|
|
801 {
|
|
802 BUILTIN b = fd.isBuiltin();
|
|
803 if (b)
|
|
804 {
|
|
805 e = eval_builtin(b, arguments);
|
|
806 if (!e) // failed
|
|
807 e = this; // evaluate at runtime
|
|
808 }
|
|
809 else if (result & WANT.WANTinterpret)
|
|
810 {
|
|
811 Expression eresult = fd.interpret(null, arguments);
|
|
812 if (eresult && eresult !is EXP_VOID_INTERPRET)
|
|
813 e = eresult;
|
|
814 else
|
|
815 error("cannot evaluate %s at compile time", toChars());
|
|
816 }
|
|
817 }
|
|
818 }
|
|
819
|
0
|
820 return e;
|
|
821 }
|
|
822
|
72
|
823 override Expression interpret(InterState istate)
|
0
|
824 {
|
72
|
825 Expression e = EXP_CANT_INTERPRET;
|
|
826
|
|
827 version (LOG) {
|
|
828 printf("CallExp.interpret() %.*s\n", toChars());
|
|
829 }
|
|
830 if (e1.op == TOKdotvar)
|
|
831 {
|
|
832 Expression pthis = (cast(DotVarExp)e1).e1;
|
|
833 FuncDeclaration fd = (cast(DotVarExp)e1).var.isFuncDeclaration();
|
|
834 TypeFunction tf = fd ? cast(TypeFunction)fd.type : null;
|
|
835 if (tf)
|
|
836 {
|
|
837 // Member function call
|
|
838 if(pthis.op == TOKthis)
|
|
839 pthis = istate.localThis;
|
|
840 Expression eresult = fd.interpret(istate, arguments, pthis);
|
|
841 if (eresult)
|
|
842 e = eresult;
|
|
843 else if (fd.type.toBasetype().nextOf().ty == Tvoid && !global.errors)
|
|
844 e = EXP_VOID_INTERPRET;
|
|
845 else
|
|
846 error("cannot evaluate %s at compile time", toChars());
|
|
847 return e;
|
|
848 }
|
|
849 error("cannot evaluate %s at compile time", toChars());
|
|
850 return EXP_CANT_INTERPRET;
|
|
851 }
|
|
852 if (e1.op == TOKvar)
|
|
853 {
|
|
854 FuncDeclaration fd = (cast(VarExp)e1).var.isFuncDeclaration();
|
|
855 if (fd)
|
|
856 {
|
|
857 ///version (DMDV2) {
|
|
858 BUILTIN b = fd.isBuiltin();
|
|
859 if (b)
|
|
860 {
|
|
861 scope Expressions args = new Expressions();
|
|
862 args.setDim(arguments.dim);
|
|
863 for (size_t i = 0; i < args.dim; i++)
|
|
864 {
|
|
865 Expression earg = cast(Expression)arguments.data[i];
|
|
866 earg = earg.interpret(istate);
|
|
867 if (earg == EXP_CANT_INTERPRET)
|
|
868 return earg;
|
|
869 args.data[i] = cast(void*)earg;
|
|
870 }
|
|
871 e = eval_builtin(b, args);
|
|
872 if (!e)
|
|
873 e = EXP_CANT_INTERPRET;
|
|
874 }
|
|
875 else
|
|
876 ///}
|
|
877 // Inline .dup
|
|
878 if (fd.ident == Id.adDup && arguments && arguments.dim == 2)
|
|
879 {
|
|
880 e = cast(Expression)arguments.data[1];
|
|
881 e = e.interpret(istate);
|
|
882 if (e !is EXP_CANT_INTERPRET)
|
|
883 {
|
|
884 e = expType(type, e);
|
|
885 }
|
|
886 }
|
|
887 else
|
|
888 {
|
|
889 Expression eresult = fd.interpret(istate, arguments);
|
|
890 if (eresult)
|
|
891 e = eresult;
|
|
892 else if (fd.type.toBasetype().nextOf().ty == Tvoid && !global.errors)
|
|
893 e = EXP_VOID_INTERPRET;
|
|
894 else
|
|
895 error("cannot evaluate %s at compile time", toChars());
|
|
896 }
|
|
897 }
|
|
898 }
|
63
|
899 return e;
|
0
|
900 }
|
|
901
|
72
|
902 override bool checkSideEffect(int flag)
|
0
|
903 {
|
72
|
904 version (DMDV2) {
|
|
905 if (flag != 2)
|
|
906 return true;
|
|
907
|
|
908 if (e1.checkSideEffect(2))
|
|
909 return true;
|
|
910
|
|
911 /* If any of the arguments have side effects, this expression does
|
|
912 */
|
|
913 for (size_t i = 0; i < arguments.dim; i++)
|
|
914 {
|
|
915 Expression e = cast(Expression)arguments.data[i];
|
|
916
|
|
917 if (e.checkSideEffect(2))
|
|
918 return true;
|
|
919 }
|
|
920
|
|
921 /* If calling a function or delegate that is typed as pure,
|
|
922 * then this expression has no side effects.
|
|
923 */
|
|
924 Type t = e1.type.toBasetype();
|
|
925 if (t.ty == TY.Tfunction && (cast(TypeFunction)t).ispure)
|
|
926 return false;
|
|
927 if (t.ty == TY.Tdelegate && (cast(TypeFunction)(cast(TypeDelegate)t).next).ispure)
|
|
928 return false;
|
|
929 }
|
0
|
930 return true;
|
|
931 }
|
|
932
|
72
|
933 override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
|
0
|
934 {
|
72
|
935 int i;
|
|
936 expToCBuffer(buf, hgs, e1, precedence[op]);
|
|
937 buf.writeByte('(');
|
|
938 argsToCBuffer(buf, arguments, hgs);
|
0
|
939 buf.writeByte(')');
|
|
940 }
|
|
941
|
72
|
942 override void dump(int indent)
|
0
|
943 {
|
|
944 assert(false);
|
|
945 }
|
|
946
|
72
|
947 override elem* toElem(IRState* irs)
|
0
|
948 {
|
72
|
949 //printf("CallExp::toElem('%s')\n", toChars());
|
|
950 assert(e1.type);
|
|
951 elem* ec;
|
|
952 int directcall;
|
|
953 FuncDeclaration fd;
|
|
954 Type t1 = e1.type.toBasetype();
|
|
955 Type ectype = t1;
|
|
956
|
|
957 elem* ehidden = irs.ehidden;
|
|
958 irs.ehidden = null;
|
|
959
|
|
960 directcall = 0;
|
|
961 fd = null;
|
|
962 if (e1.op == TOK.TOKdotvar && t1.ty != TY.Tdelegate)
|
|
963 {
|
|
964 DotVarExp dve = cast(DotVarExp)e1;
|
|
965
|
|
966 fd = dve.var.isFuncDeclaration();
|
|
967 Expression ex = dve.e1;
|
|
968 while (1)
|
|
969 {
|
|
970 switch (ex.op)
|
|
971 {
|
|
972 case TOK.TOKsuper: // super.member() calls directly
|
|
973 case TOK.TOKdottype: // type.member() calls directly
|
|
974 directcall = 1;
|
|
975 break;
|
|
976
|
|
977 case TOK.TOKcast:
|
|
978 ex = (cast(CastExp)ex).e1;
|
|
979 continue;
|
|
980
|
|
981 default:
|
|
982 //ex.dump(0);
|
|
983 break;
|
|
984 }
|
|
985 break;
|
|
986 }
|
|
987 ec = dve.e1.toElem(irs);
|
|
988 ectype = dve.e1.type.toBasetype();
|
|
989 }
|
|
990 else if (e1.op == TOK.TOKvar)
|
|
991 {
|
|
992 fd = (cast(VarExp)e1).var.isFuncDeclaration();
|
|
993
|
|
994 if (fd && fd.ident == Id.alloca && !fd.fbody && fd.linkage == LINK.LINKc && arguments && arguments.dim == 1)
|
|
995 {
|
|
996 Expression arg = cast(Expression)arguments.data[0];
|
|
997 arg = arg.optimize(WANT.WANTvalue);
|
|
998 if (arg.isConst() && arg.type.isintegral())
|
|
999 {
|
|
1000 long sz = arg.toInteger();
|
|
1001 if (sz > 0 && sz < 0x40000)
|
|
1002 {
|
|
1003 // It's an alloca(sz) of a fixed amount.
|
|
1004 // Replace with an array allocated on the stack
|
|
1005 // of the same size: char[sz] tmp;
|
|
1006
|
|
1007 Symbol* stmp;
|
|
1008 .type* t;
|
|
1009
|
|
1010 assert(!ehidden);
|
|
1011 t = type_allocn(TYM.TYarray, tschar);
|
|
1012 t.Tdim = cast(uint)sz;
|
|
1013 stmp = symbol_genauto(t);
|
|
1014 ec = el_ptr(stmp);
|
|
1015 el_setLoc(ec,loc);
|
|
1016 return ec;
|
|
1017 }
|
|
1018 }
|
|
1019 }
|
|
1020
|
|
1021 ec = e1.toElem(irs);
|
|
1022 }
|
|
1023 else
|
|
1024 {
|
|
1025 ec = e1.toElem(irs);
|
|
1026 }
|
|
1027 ec = callfunc(loc, irs, directcall, type, ec, ectype, fd, t1, ehidden, arguments);
|
|
1028 el_setLoc(ec,loc);
|
0
|
1029 return ec;
|
|
1030 }
|
|
1031
|
72
|
1032 override void scanForNestedRef(Scope sc)
|
0
|
1033 {
|
72
|
1034 //printf("CallExp.scanForNestedRef(Scope *sc): %s\n", toChars());
|
|
1035 e1.scanForNestedRef(sc);
|
64
|
1036 arrayExpressionScanForNestedRef(sc, arguments);
|
72
|
1037 }
|
0
|
1038
|
|
1039 version (DMDV2) {
|
72
|
1040 override int isLvalue()
|
0
|
1041 {
|
72
|
1042 // if (type.toBasetype().ty == Tstruct)
|
|
1043 // return 1;
|
|
1044 Type tb = e1.type.toBasetype();
|
|
1045 if (tb.ty == Tfunction && (cast(TypeFunction)tb).isref)
|
|
1046 return 1; // function returns a reference
|
0
|
1047 return 0;
|
|
1048 }
|
|
1049 }
|
72
|
1050 override Expression toLvalue(Scope sc, Expression e)
|
0
|
1051 {
|
72
|
1052 if (isLvalue())
|
|
1053 return this;
|
0
|
1054 return Expression.toLvalue(sc, e);
|
72
|
1055 }
|
0
|
1056
|
|
1057 version (DMDV2) {
|
72
|
1058 override bool canThrow()
|
0
|
1059 {
|
72
|
1060 //printf("CallExp::canThrow() %s\n", toChars());
|
|
1061 if (e1.canThrow())
|
|
1062 return true;
|
|
1063
|
|
1064 /* If any of the arguments can throw, then this expression can throw
|
|
1065 */
|
|
1066 for (size_t i = 0; i < arguments.dim; i++)
|
|
1067 {
|
|
1068 Expression e = cast(Expression)arguments.data[i];
|
|
1069
|
|
1070 if (e && e.canThrow())
|
|
1071 return true;
|
|
1072 }
|
|
1073
|
|
1074 if (global.errors && !e1.type)
|
|
1075 return false; // error recovery
|
|
1076
|
|
1077 /* If calling a function or delegate that is typed as nothrow,
|
|
1078 * then this expression cannot throw.
|
|
1079 * Note that pure functions can throw.
|
|
1080 */
|
|
1081 Type t = e1.type.toBasetype();
|
|
1082 if (t.ty == TY.Tfunction && (cast(TypeFunction)t).isnothrow)
|
|
1083 return false;
|
|
1084 if (t.ty == TY.Tdelegate && (cast(TypeFunction)(cast(TypeDelegate)t).next).isnothrow)
|
|
1085 return false;
|
|
1086
|
0
|
1087 return true;
|
|
1088 }
|
|
1089 }
|
72
|
1090 override int inlineCost(InlineCostState* ics)
|
0
|
1091 {
|
|
1092 return 1 + e1.inlineCost(ics) + arrayInlineCost(ics, arguments);
|
|
1093 }
|
|
1094
|
72
|
1095 override Expression doInline(InlineDoState ids)
|
0
|
1096 {
|
72
|
1097 CallExp ce = cast(CallExp)copy();
|
|
1098 ce.e1 = e1.doInline(ids);
|
|
1099 ce.arguments = arrayExpressiondoInline(arguments, ids);
|
0
|
1100 return ce;
|
|
1101 }
|
|
1102
|
72
|
1103 override Expression inlineScan(InlineScanState* iss)
|
0
|
1104 {
|
72
|
1105 Expression e = this;
|
|
1106
|
|
1107 //printf("CallExp.inlineScan()\n");
|
|
1108 e1 = e1.inlineScan(iss);
|
|
1109 arrayInlineScan(iss, arguments);
|
|
1110
|
|
1111 if (e1.op == TOKvar)
|
|
1112 {
|
|
1113 VarExp ve = cast(VarExp)e1;
|
|
1114 FuncDeclaration fd = ve.var.isFuncDeclaration();
|
|
1115
|
|
1116 if (fd && fd != iss.fd && fd.canInline(0))
|
|
1117 {
|
|
1118 e = fd.doInline(iss, null, arguments);
|
|
1119 }
|
|
1120 }
|
|
1121 else if (e1.op == TOKdotvar)
|
|
1122 {
|
|
1123 DotVarExp dve = cast(DotVarExp)e1;
|
|
1124 FuncDeclaration fd = dve.var.isFuncDeclaration();
|
|
1125
|
|
1126 if (fd && fd != iss.fd && fd.canInline(1))
|
|
1127 {
|
|
1128 if (dve.e1.op == TOKcall &&
|
|
1129 dve.e1.type.toBasetype().ty == Tstruct)
|
|
1130 {
|
|
1131 /* To create ethis, we'll need to take the address
|
|
1132 * of dve.e1, but this won't work if dve.e1 is
|
|
1133 * a function call.
|
|
1134 */
|
|
1135 ;
|
|
1136 }
|
|
1137 else
|
|
1138 e = fd.doInline(iss, dve.e1, arguments);
|
|
1139 }
|
|
1140 }
|
|
1141
|
0
|
1142 return e;
|
|
1143 }
|
|
1144 }
|
|
1145
|