2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
17 // Issues with using -include total.h (defines integer_t) and then complex.h fails...
28 #define integer_t dmd_integer_t
32 extern "C" char * __cdecl __locale_decpoint
;
38 #include "..\root\mem.h"
40 #include "../root/mem.h"
45 #include "expression.h"
50 #include "statement.h"
51 #include "declaration.h"
52 #include "aggregate.h"
61 Expression
*createTypeInfoArray(Scope
*sc
, Expression
*args
[], int dim
);
65 /**********************************
66 * Set operator precedence for each operator.
69 // Operator precedence - greater values are higher precedence
91 enum PREC precedence
[TOKMAX
];
95 precedence
[TOKdotvar
] = PREC_primary
;
96 precedence
[TOKimport
] = PREC_primary
;
97 precedence
[TOKidentifier
] = PREC_primary
;
98 precedence
[TOKthis
] = PREC_primary
;
99 precedence
[TOKsuper
] = PREC_primary
;
100 precedence
[TOKint64
] = PREC_primary
;
101 precedence
[TOKfloat64
] = PREC_primary
;
102 precedence
[TOKnull
] = PREC_primary
;
103 precedence
[TOKstring
] = PREC_primary
;
104 precedence
[TOKarrayliteral
] = PREC_primary
;
105 precedence
[TOKtypedot
] = PREC_primary
;
106 precedence
[TOKtypeid
] = PREC_primary
;
107 precedence
[TOKis
] = PREC_primary
;
108 precedence
[TOKassert
] = PREC_primary
;
109 precedence
[TOKfunction
] = PREC_primary
;
110 precedence
[TOKvar
] = PREC_primary
;
111 precedence
[TOKdefault
] = PREC_primary
;
114 precedence
[TOKdotti
] = PREC_primary
;
115 precedence
[TOKdot
] = PREC_primary
;
116 // precedence[TOKarrow] = PREC_primary;
117 precedence
[TOKplusplus
] = PREC_primary
;
118 precedence
[TOKminusminus
] = PREC_primary
;
119 precedence
[TOKcall
] = PREC_primary
;
120 precedence
[TOKslice
] = PREC_primary
;
121 precedence
[TOKarray
] = PREC_primary
;
123 precedence
[TOKaddress
] = PREC_unary
;
124 precedence
[TOKstar
] = PREC_unary
;
125 precedence
[TOKneg
] = PREC_unary
;
126 precedence
[TOKuadd
] = PREC_unary
;
127 precedence
[TOKnot
] = PREC_unary
;
128 precedence
[TOKtobool
] = PREC_add
;
129 precedence
[TOKtilde
] = PREC_unary
;
130 precedence
[TOKdelete
] = PREC_unary
;
131 precedence
[TOKnew
] = PREC_unary
;
132 precedence
[TOKcast
] = PREC_unary
;
134 precedence
[TOKmul
] = PREC_mul
;
135 precedence
[TOKdiv
] = PREC_mul
;
136 precedence
[TOKmod
] = PREC_mul
;
138 precedence
[TOKadd
] = PREC_add
;
139 precedence
[TOKmin
] = PREC_add
;
140 precedence
[TOKcat
] = PREC_add
;
142 precedence
[TOKshl
] = PREC_shift
;
143 precedence
[TOKshr
] = PREC_shift
;
144 precedence
[TOKushr
] = PREC_shift
;
146 precedence
[TOKlt
] = PREC_rel
;
147 precedence
[TOKle
] = PREC_rel
;
148 precedence
[TOKgt
] = PREC_rel
;
149 precedence
[TOKge
] = PREC_rel
;
150 precedence
[TOKunord
] = PREC_rel
;
151 precedence
[TOKlg
] = PREC_rel
;
152 precedence
[TOKleg
] = PREC_rel
;
153 precedence
[TOKule
] = PREC_rel
;
154 precedence
[TOKul
] = PREC_rel
;
155 precedence
[TOKuge
] = PREC_rel
;
156 precedence
[TOKug
] = PREC_rel
;
157 precedence
[TOKue
] = PREC_rel
;
158 precedence
[TOKin
] = PREC_rel
;
160 precedence
[TOKequal
] = PREC_equal
;
161 precedence
[TOKnotequal
] = PREC_equal
;
162 precedence
[TOKidentity
] = PREC_equal
;
163 precedence
[TOKnotidentity
] = PREC_equal
;
165 precedence
[TOKand
] = PREC_and
;
167 precedence
[TOKxor
] = PREC_xor
;
169 precedence
[TOKor
] = PREC_or
;
171 precedence
[TOKandand
] = PREC_andand
;
173 precedence
[TOKoror
] = PREC_oror
;
175 precedence
[TOKquestion
] = PREC_cond
;
177 precedence
[TOKassign
] = PREC_assign
;
178 precedence
[TOKconstruct
] = PREC_assign
;
179 precedence
[TOKblit
] = PREC_assign
;
180 precedence
[TOKaddass
] = PREC_assign
;
181 precedence
[TOKminass
] = PREC_assign
;
182 precedence
[TOKcatass
] = PREC_assign
;
183 precedence
[TOKmulass
] = PREC_assign
;
184 precedence
[TOKdivass
] = PREC_assign
;
185 precedence
[TOKmodass
] = PREC_assign
;
186 precedence
[TOKshlass
] = PREC_assign
;
187 precedence
[TOKshrass
] = PREC_assign
;
188 precedence
[TOKushrass
] = PREC_assign
;
189 precedence
[TOKandass
] = PREC_assign
;
190 precedence
[TOKorass
] = PREC_assign
;
191 precedence
[TOKxorass
] = PREC_assign
;
193 precedence
[TOKcomma
] = PREC_expr
;
196 /*************************************************************
197 * Given var, we need to get the
198 * right 'this' pointer if var is in an outer class, but our
199 * existing 'this' pointer is in an inner class.
202 * ad struct or class we need the correct 'this' for
203 * var the specific member of ad we're accessing
206 Expression
*getRightThis(Loc loc
, Scope
*sc
, AggregateDeclaration
*ad
,
207 Expression
*e1
, Declaration
*var
)
210 Type
*t
= e1
->type
->toBasetype();
212 /* If e1 is not the 'this' pointer for ad
215 !(t
->ty
== Tpointer
&& t
->nextOf()->ty
== Tstruct
&&
216 ((TypeStruct
*)t
->nextOf())->sym
== ad
)
218 !(t
->ty
== Tstruct
&&
219 ((TypeStruct
*)t
)->sym
== ad
)
222 ClassDeclaration
*cd
= ad
->isClassDeclaration();
223 ClassDeclaration
*tcd
= t
->isClassHandle();
225 /* e1 is the right this if ad is a base class of e1
228 !(tcd
== cd
|| cd
->isBaseOf(tcd
, NULL
))
231 /* Only classes can be inner classes with an 'outer'
232 * member pointing to the enclosing class instance
234 if (tcd
&& tcd
->isNested())
235 { /* e1 is the 'this' pointer for an inner class.
236 * Rewrite it as the 'this' pointer for the outer class.
239 e1
= new DotVarExp(loc
, e1
, tcd
->vthis
);
240 e1
= e1
->semantic(sc
);
242 // Skip up over nested functions, and get the enclosing
245 for (s
= tcd
->toParent();
246 s
&& s
->isFuncDeclaration();
248 { FuncDeclaration
*f
= s
->isFuncDeclaration();
251 e1
= new VarExp(loc
, f
->vthis
);
254 if (s
&& s
->isClassDeclaration())
255 e1
->type
= s
->isClassDeclaration()->type
;
256 e1
= e1
->semantic(sc
);
260 /* Can't find a path from e1 to ad
262 error("this for %s needs to be type %s not type %s",
263 var
->toChars(), ad
->toChars(), t
->toChars());
269 /*****************************************
270 * Determine if 'this' is available.
271 * If it is, return the FuncDeclaration that has it.
274 FuncDeclaration
*hasThis(Scope
*sc
)
275 { FuncDeclaration
*fd
;
276 FuncDeclaration
*fdthis
;
278 //printf("hasThis()\n");
279 fdthis
= sc
->parent
->isFuncDeclaration();
280 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
282 // Go upwards until we find the enclosing member function
293 Dsymbol
*parent
= fd
->parent
;
296 TemplateInstance
*ti
= parent
->isTemplateInstance();
303 fd
= fd
->parent
->isFuncDeclaration();
307 { //printf("test '%s'\n", fd->toChars());
315 return NULL
; // don't have 'this' available
319 /***************************************
320 * Pull out any properties.
323 Expression
*resolveProperties(Scope
*sc
, Expression
*e
)
325 //printf("resolveProperties(%s)\n", e->toChars());
328 Type
*t
= e
->type
->toBasetype();
330 if (t
->ty
== Tfunction
|| e
->op
== TOKoverloadset
)
332 e
= new CallExp(e
->loc
, e
);
336 /* Look for e being a lazy parameter; rewrite as delegate call
338 else if (e
->op
== TOKvar
)
339 { VarExp
*ve
= (VarExp
*)e
;
341 if (ve
->var
->storage_class
& STClazy
)
343 e
= new CallExp(e
->loc
, e
);
348 else if (e
->op
== TOKdotexp
)
350 e
->error("expression has no value");
357 /******************************
358 * Perform semantic() on an array of Expressions.
361 void arrayExpressionSemantic(Expressions
*exps
, Scope
*sc
)
365 for (size_t i
= 0; i
< exps
->dim
; i
++)
366 { Expression
*e
= (Expression
*)exps
->data
[i
];
369 exps
->data
[i
] = (void *)e
;
375 /******************************
376 * Perform canThrow() on an array of Expressions.
379 int arrayExpressionCanThrow(Expressions
*exps
)
383 for (size_t i
= 0; i
< exps
->dim
; i
++)
384 { Expression
*e
= (Expression
*)exps
->data
[i
];
385 if (e
&& e
->canThrow())
393 /****************************************
397 void expandTuples(Expressions
*exps
)
399 //printf("expandTuples()\n");
402 for (size_t i
= 0; i
< exps
->dim
; i
++)
403 { Expression
*arg
= (Expression
*)exps
->data
[i
];
407 // Look for tuple with 0 members
408 if (arg
->op
== TOKtype
)
409 { TypeExp
*e
= (TypeExp
*)arg
;
410 if (e
->type
->toBasetype()->ty
== Ttuple
)
411 { TypeTuple
*tt
= (TypeTuple
*)e
->type
->toBasetype();
413 if (!tt
->arguments
|| tt
->arguments
->dim
== 0)
424 // Inline expand all the tuples
425 while (arg
->op
== TOKtuple
)
426 { TupleExp
*te
= (TupleExp
*)arg
;
428 exps
->remove(i
); // remove arg
429 exps
->insert(i
, te
->exps
); // replace with tuple contents
431 return; // empty tuple, no more arguments
432 arg
= (Expression
*)exps
->data
[i
];
438 /****************************************
439 * Preprocess arguments to function.
442 void preFunctionArguments(Loc loc
, Scope
*sc
, Expressions
*exps
)
448 for (size_t i
= 0; i
< exps
->dim
; i
++)
449 { Expression
*arg
= (Expression
*)exps
->data
[i
];
457 arg
->error("%s is not an expression", arg
->toChars());
458 arg
= new IntegerExp(arg
->loc
, 0, Type::tint32
);
461 arg
= resolveProperties(sc
, arg
);
462 exps
->data
[i
] = (void *) arg
;
466 if (arg
->type
->ty
== Tfunction
)
468 arg
= new AddrExp(arg
->loc
, arg
);
469 arg
= arg
->semantic(sc
);
470 exps
->data
[i
] = (void *) arg
;
477 /*********************************************
478 * Call copy constructor for struct value argument.
481 Expression
*callCpCtor(Loc loc
, Scope
*sc
, Expression
*e
)
483 Type
*tb
= e
->type
->toBasetype();
484 assert(tb
->ty
== Tstruct
);
485 StructDeclaration
*sd
= ((TypeStruct
*)tb
)->sym
;
488 /* Create a variable tmp, and replace the argument e with:
490 * and let AssignExp() handle the construction.
491 * This is not the most efficent, ideally tmp would be constructed
492 * directly onto the stack.
494 Identifier
*idtmp
= Lexer::uniqueId("__tmp");
495 VarDeclaration
*tmp
= new VarDeclaration(loc
, tb
, idtmp
, new ExpInitializer(0, e
));
496 Expression
*ae
= new DeclarationExp(loc
, tmp
);
497 e
= new CommaExp(loc
, ae
, new VarExp(loc
, tmp
));
503 /****************************************
504 * Now that we know the exact type of the function we're calling,
505 * the arguments[] need to be adjusted:
506 * 1. implicitly convert argument to the corresponding parameter type
507 * 2. add default arguments for any missing arguments
508 * 3. do default promotions on arguments corresponding to ...
509 * 4. add hidden _arguments[] argument
510 * 5. call copy constructor for struct value arguments
513 void functionArguments(Loc loc
, Scope
*sc
, TypeFunction
*tf
, Expressions
*arguments
)
517 //printf("functionArguments()\n");
519 size_t nargs
= arguments
? arguments
->dim
: 0;
520 size_t nparams
= Argument::dim(tf
->parameters
);
522 if (nargs
> nparams
&& tf
->varargs
== 0)
523 error(loc
, "expected %"PRIuSIZE
" arguments, not %"PRIuSIZE
, nparams
, nargs
);
525 n
= (nargs
> nparams
) ? nargs
: nparams
; // n = max(nargs, nparams)
528 for (size_t i
= 0; i
< n
; i
++)
533 arg
= (Expression
*)arguments
->data
[i
];
540 Argument
*p
= Argument::getNth(tf
->parameters
, i
);
546 if (tf
->varargs
== 2 && i
+ 1 == nparams
)
548 error(loc
, "expected %"PRIuSIZE
" arguments, not %"PRIuSIZE
, nparams
, nargs
);
552 if (arg
->op
== TOKdefault
)
553 { DefaultInitExp
*de
= (DefaultInitExp
*)arg
;
554 arg
= de
->resolve(loc
, sc
);
558 arguments
->push(arg
);
562 if (tf
->varargs
== 2 && i
+ 1 == nparams
)
564 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
565 if (arg
->implicitConvTo(p
->type
))
567 if (nargs
!= nparams
)
568 error(loc
, "expected %"PRIuSIZE
" arguments, not %"PRIuSIZE
, nparams
, nargs
);
572 Type
*tb
= p
->type
->toBasetype();
573 Type
*tret
= p
->isLazyArray();
578 { // Create a static array variable v of type arg->type
580 /* GCC 4.0 does not like zero length arrays used like
581 this; pass a null array value instead. Could also
582 just make a one-element array. */
585 arg
= new NullExp(loc
);
589 Identifier
*id
= Lexer::uniqueId("__arrayArg");
590 Type
*t
= new TypeSArray(((TypeArray
*)tb
)->next
, new IntegerExp(nargs
- i
));
591 t
= t
->semantic(loc
, sc
);
592 VarDeclaration
*v
= new VarDeclaration(loc
, t
, id
, new VoidInitializer(loc
));
594 v
->parent
= sc
->parent
;
597 Expression
*c
= new DeclarationExp(0, v
);
600 for (size_t u
= i
; u
< nargs
; u
++)
601 { Expression
*a
= (Expression
*)arguments
->data
[u
];
602 if (tret
&& !((TypeArray
*)tb
)->next
->equals(a
->type
))
603 a
= a
->toDelegate(sc
, tret
);
605 Expression
*e
= new VarExp(loc
, v
);
606 e
= new IndexExp(loc
, e
, new IntegerExp(u
+ 1 - nparams
));
607 AssignExp
*ae
= new AssignExp(loc
, e
, a
);
608 ae
->op
= TOKconstruct
;
610 c
= new CommaExp(loc
, c
, ae
);
614 arg
= new VarExp(loc
, v
);
616 arg
= new CommaExp(loc
, c
, arg
);
621 * new Tclass(arg0, arg1, ..., argn)
623 Expressions
*args
= new Expressions();
624 args
->setDim(nargs
- i
);
625 for (size_t u
= i
; u
< nargs
; u
++)
626 args
->data
[u
- i
] = arguments
->data
[u
];
627 arg
= new NewExp(loc
, NULL
, NULL
, p
->type
, args
);
632 { error(loc
, "not enough arguments");
637 arg
= arg
->semantic(sc
);
638 //printf("\targ = '%s'\n", arg->toChars());
639 arguments
->setDim(i
+ 1);
644 if (!(p
->storageClass
& STClazy
&& p
->type
->ty
== Tvoid
))
646 if (p
->type
!= arg
->type
)
648 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
649 arg
= arg
->implicitCastTo(sc
, p
->type
);
650 arg
= arg
->optimize(WANTvalue
);
653 if (p
->storageClass
& STCref
)
655 arg
= arg
->toLvalue(sc
, arg
);
657 else if (p
->storageClass
& STCout
)
659 arg
= arg
->modifiableLvalue(sc
, arg
);
662 // Convert static arrays to pointers
663 tb
= arg
->type
->toBasetype();
664 if (tb
->ty
== Tsarray
)
666 arg
= arg
->checkToPointer();
669 if (tb
->ty
== Tstruct
&& !(p
->storageClass
& (STCref
| STCout
)))
671 arg
= callCpCtor(loc
, sc
, arg
);
674 // Convert lazy argument to a delegate
675 if (p
->storageClass
& STClazy
)
677 arg
= arg
->toDelegate(sc
, p
->type
);
683 // If not D linkage, do promotions
684 if (tf
->linkage
!= LINKd
)
686 // Promote bytes, words, etc., to ints
687 arg
= arg
->integralPromotions(sc
);
689 // Promote floats to doubles
690 switch (arg
->type
->ty
)
693 arg
= arg
->castTo(sc
, Type::tfloat64
);
697 arg
= arg
->castTo(sc
, Type::timaginary64
);
702 // Convert static arrays to dynamic arrays
703 tb
= arg
->type
->toBasetype();
704 if (tb
->ty
== Tsarray
)
705 { TypeSArray
*ts
= (TypeSArray
*)tb
;
706 Type
*ta
= ts
->next
->arrayOf();
707 if (ts
->size(arg
->loc
) == 0)
708 { arg
= new NullExp(arg
->loc
);
712 arg
= arg
->castTo(sc
, ta
);
715 if (tb
->ty
== Tstruct
)
717 arg
= callCpCtor(loc
, sc
, arg
);
720 // Give error for overloaded function addresses
721 if (arg
->op
== TOKsymoff
)
722 { SymOffExp
*se
= (SymOffExp
*)arg
;
723 if (se
->hasOverloads
&& !se
->var
->isFuncDeclaration()->isUnique())
724 arg
->error("function %s is overloaded", arg
->toChars());
729 arg
= arg
->optimize(WANTvalue
);
730 arguments
->data
[i
] = (void *) arg
;
735 // If D linkage and variadic, add _arguments[] as first argument
736 if (tf
->linkage
== LINKd
&& tf
->varargs
== 1)
740 e
= createTypeInfoArray(sc
, (Expression
**)&arguments
->data
[nparams
],
741 arguments
->dim
- nparams
);
742 arguments
->insert(0, e
);
746 /**************************************************
747 * Write expression out to buf, but wrap it
748 * in ( ) if its precedence is less than pr.
751 void expToCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
, Expression
*e
, enum PREC pr
)
753 //if (precedence[e->op] == 0) e->dump(0);
754 if (precedence
[e
->op
] < pr
)
757 e
->toCBuffer(buf
, hgs
);
761 e
->toCBuffer(buf
, hgs
);
764 /**************************************************
765 * Write out argument list to buf.
768 void argsToCBuffer(OutBuffer
*buf
, Expressions
*arguments
, HdrGenState
*hgs
)
772 for (size_t i
= 0; i
< arguments
->dim
; i
++)
773 { Expression
*arg
= (Expression
*)arguments
->data
[i
];
778 expToCBuffer(buf
, hgs
, arg
, PREC_assign
);
784 /**************************************************
785 * Write out argument types to buf.
788 void argExpTypesToCBuffer(OutBuffer
*buf
, Expressions
*arguments
, HdrGenState
*hgs
)
793 for (size_t i
= 0; i
< arguments
->dim
; i
++)
794 { Expression
*arg
= (Expression
*)arguments
->data
[i
];
799 arg
->type
->toCBuffer2(&argbuf
, hgs
, 0);
805 /******************************** Expression **************************/
807 Expression::Expression(Loc loc
, enum TOK op
, int size
)
816 Expression
*Expression::syntaxCopy()
818 //printf("Expression::syntaxCopy()\n");
823 /*********************************
824 * Does *not* do a deep copy.
827 Expression
*Expression::copy()
833 fprintf(stdmsg
, "No expression copy for: %s\n", toChars());
834 printf("op = %d\n", op
);
839 e
= (Expression
*)mem
.malloc(size
);
840 return (Expression
*)memcpy(e
, this, size
);
843 /**************************
844 * Semantically analyze Expression.
845 * Determine types, fold constants, etc.
848 Expression
*Expression::semantic(Scope
*sc
)
851 printf("Expression::semantic() %s\n", toChars());
854 type
= type
->semantic(loc
, sc
);
860 void Expression::print()
862 fprintf(stdmsg
, "%s\n", toChars());
866 char *Expression::toChars()
870 memset(&hgs
, 0, sizeof(hgs
));
871 buf
= new OutBuffer();
872 toCBuffer(buf
, &hgs
);
873 return buf
->toChars();
876 void Expression::error(const char *format
, ...)
879 va_start(ap
, format
);
880 ::verror(loc
, format
, ap
);
884 void Expression::rvalue()
886 if (type
&& type
->toBasetype()->ty
== Tvoid
)
887 { error("expression %s is void and has no value", toChars());
896 Expression
*Expression::combine(Expression
*e1
, Expression
*e2
)
902 e1
= new CommaExp(e1
->loc
, e1
, e2
);
911 integer_t
Expression::toInteger()
913 //printf("Expression %s\n", Token::toChars(op));
914 error("Integer constant expression expected instead of %s", toChars());
918 uinteger_t
Expression::toUInteger()
920 //printf("Expression %s\n", Token::toChars(op));
921 return (uinteger_t
)toInteger();
924 real_t
Expression::toReal()
926 error("Floating point constant expression expected instead of %s", toChars());
930 real_t
Expression::toImaginary()
932 error("Floating point constant expression expected instead of %s", toChars());
936 complex_t
Expression::toComplex()
938 error("Floating point constant expression expected instead of %s", toChars());
940 return complex_t(real_t(0)); // %% nicer
946 void Expression::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
948 buf
->writestring(Token::toChars(op
));
951 void Expression::toMangleBuffer(OutBuffer
*buf
)
953 error("expression %s is not a valid template value argument", toChars());
956 /*******************************
957 * Give error if we're not an lvalue.
958 * If we can, convert expression to be an lvalue.
961 Expression
*Expression::toLvalue(Scope
*sc
, Expression
*e
)
965 else if (!loc
.filename
)
967 error("%s is not an lvalue", e
->toChars());
971 Expression
*Expression::modifiableLvalue(Scope
*sc
, Expression
*e
)
973 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
975 // See if this expression is a modifiable lvalue (i.e. not const)
976 if (type
&& (!type
->isMutable() || !type
->isAssignable()))
977 error("%s is not mutable", e
->toChars());
979 return toLvalue(sc
, e
);
982 /************************************
983 * Detect cases where pointers to the stack can 'escape' the
984 * lifetime of the stack frame.
987 void Expression::checkEscape()
991 void Expression::checkScalar()
993 if (!type
->isscalar())
994 error("'%s' is not a scalar, it is a %s", toChars(), type
->toChars());
997 void Expression::checkNoBool()
999 if (type
->toBasetype()->ty
== Tbool
)
1000 error("operation not allowed on bool '%s'", toChars());
1003 Expression
*Expression::checkIntegral()
1005 if (!type
->isintegral())
1006 { error("'%s' is not of integral type, it is a %s", toChars(), type
->toChars());
1007 return new IntegerExp(0);
1012 Expression
*Expression::checkArithmetic()
1014 if (!type
->isintegral() && !type
->isfloating())
1015 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type
->toChars());
1016 return new IntegerExp(0);
1021 void Expression::checkDeprecated(Scope
*sc
, Dsymbol
*s
)
1023 s
->checkDeprecated(loc
, sc
);
1026 /********************************
1027 * Check for expressions that have no use.
1029 * flag 0 not going to use the result, so issue error message if no
1031 * 1 the result of the expression is used, but still check
1032 * for useless subexpressions
1033 * 2 do not issue error messages, just return !=0 if expression
1037 int Expression::checkSideEffect(int flag
)
1040 { if (op
== TOKimport
)
1042 error("%s has no effect", toChars());
1045 error("%s has no effect in expression (%s)",
1046 Token::toChars(op
), toChars());
1051 /*****************************
1052 * Check that expression can be tested for true or false.
1055 Expression
*Expression::checkToBoolean()
1057 // Default is 'yes' - do nothing
1064 if (!type
->checkBoolean())
1066 error("expression %s of type %s does not have a boolean value", toChars(), type
->toChars());
1071 /****************************
1074 Expression
*Expression::checkToPointer()
1079 //printf("Expression::checkToPointer()\n");
1082 // If C static array, convert to pointer
1083 tb
= type
->toBasetype();
1084 if (tb
->ty
== Tsarray
)
1085 { TypeSArray
*ts
= (TypeSArray
*)tb
;
1086 if (ts
->size(loc
) == 0)
1087 e
= new NullExp(loc
);
1089 e
= new AddrExp(loc
, this);
1090 e
->type
= ts
->next
->pointerTo();
1095 /******************************
1096 * Take address of expression.
1099 Expression
*Expression::addressOf(Scope
*sc
)
1103 //printf("Expression::addressOf()\n");
1104 e
= toLvalue(sc
, NULL
);
1105 e
= new AddrExp(loc
, e
);
1106 e
->type
= type
->pointerTo();
1110 /******************************
1111 * If this is a reference, dereference it.
1114 Expression
*Expression::deref()
1116 //printf("Expression::deref()\n");
1117 if (type
->ty
== Treference
)
1120 e
= new PtrExp(loc
, this);
1121 e
->type
= ((TypeReference
*)type
)->next
;
1127 /********************************
1128 * Does this expression statically evaluate to a boolean TRUE or FALSE?
1131 int Expression::isBool(int result
)
1136 /********************************
1137 * Does this expression result in either a 1 or a 0?
1140 int Expression::isBit()
1145 /********************************
1146 * Can this expression throw an exception?
1147 * Valid only after semantic() pass.
1150 int Expression::canThrow()
1157 Expressions
*Expression::arraySyntaxCopy(Expressions
*exps
)
1158 { Expressions
*a
= NULL
;
1162 a
= new Expressions();
1163 a
->setDim(exps
->dim
);
1164 for (int i
= 0; i
< a
->dim
; i
++)
1165 { Expression
*e
= (Expression
*)exps
->data
[i
];
1167 e
= e
->syntaxCopy();
1174 /******************************** IntegerExp **************************/
1176 IntegerExp::IntegerExp(Loc loc
, integer_t value
, Type
*type
)
1177 : Expression(loc
, TOKint64
, sizeof(IntegerExp
))
1179 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
1180 if (type
&& !type
->isscalar())
1182 //printf("%s, loc = %d\n", toChars(), loc.linnum);
1183 error("integral constant must be scalar type, not %s", type
->toChars());
1184 type
= Type::terror
;
1187 this->value
= value
;
1190 IntegerExp::IntegerExp(integer_t value
)
1191 : Expression(0, TOKint64
, sizeof(IntegerExp
))
1193 this->type
= Type::tint32
;
1194 this->value
= value
;
1197 int IntegerExp::equals(Object
*o
)
1201 (((Expression
*)o
)->op
== TOKint64
&&
1202 ((ne
= (IntegerExp
*)o
), type
->toHeadMutable()->equals(ne
->type
->toHeadMutable())) &&
1203 value
== ne
->value
))
1208 char *IntegerExp::toChars()
1211 return Expression::toChars();
1213 static char buffer
[sizeof(value
) * 3 + 1];
1215 sprintf(buffer
, "%"PRIdMAX
, value
);
1220 integer_t
IntegerExp::toInteger()
1229 case Tbool
: value
= (value
!= 0); break;
1230 case Tint8
: value
= (d_int8
) value
; break;
1232 case Tuns8
: value
= (d_uns8
) value
; break;
1233 case Tint16
: value
= (d_int16
) value
; break;
1235 case Tuns16
: value
= (d_uns16
) value
; break;
1236 case Tint32
: value
= (d_int32
) value
; break;
1238 case Tuns32
: value
= (d_uns32
) value
; break;
1239 case Tint64
: value
= (d_int64
) value
; break;
1240 case Tuns64
: value
= (d_uns64
) value
; break;
1245 case 4: value
= (d_uns32
) value
; break;
1246 case 8: value
= (d_uns64
) value
; break;
1248 assert(PTRSIZE
== 4 || PTRSIZE
== 8);
1254 TypeEnum
*te
= (TypeEnum
*)t
;
1255 t
= te
->sym
->memtype
;
1261 TypeTypedef
*tt
= (TypeTypedef
*)t
;
1262 t
= tt
->sym
->basetype
;
1276 real_t
IntegerExp::toReal()
1281 t
= type
->toBasetype();
1282 if (t
->ty
== Tuns64
)
1283 return (real_t
)(d_uns64
)value
;
1285 return (real_t
)(d_int64
)value
;
1288 real_t
IntegerExp::toImaginary()
1293 complex_t
IntegerExp::toComplex()
1298 int IntegerExp::isBool(int result
)
1300 return result
? value
!= 0 : value
== 0;
1303 Expression
*IntegerExp::semantic(Scope
*sc
)
1307 // Determine what the type of this number is
1308 integer_t number
= value
;
1310 if (number
& 0x8000000000000000LL
)
1311 type
= Type::tuns64
;
1312 else if (number
& 0xFFFFFFFF80000000LL
)
1313 type
= Type::tint64
;
1315 type
= Type::tint32
;
1319 type
= type
->semantic(loc
, sc
);
1324 Expression
*IntegerExp::toLvalue(Scope
*sc
, Expression
*e
)
1328 else if (!loc
.filename
)
1330 e
->error("constant %s is not an lvalue", e
->toChars());
1334 void IntegerExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1336 integer_t v
= toInteger();
1345 { TypeEnum
*te
= (TypeEnum
*)t
;
1346 buf
->printf("cast(%s)", te
->sym
->toChars());
1347 t
= te
->sym
->memtype
;
1352 { TypeTypedef
*tt
= (TypeTypedef
*)t
;
1353 buf
->printf("cast(%s)", tt
->sym
->toChars());
1354 t
= tt
->sym
->basetype
;
1358 case Twchar
: // BUG: need to cast(wchar)
1359 case Tdchar
: // BUG: need to cast(dchar)
1360 if ((uinteger_t
)v
> 0xFF)
1362 buf
->printf("'\\U%08x'", v
);
1367 buf
->writestring("'\\''");
1368 else if (isprint(v
) && v
!= '\\')
1369 buf
->printf("'%c'", (int)v
);
1371 buf
->printf("'\\x%02x'", (int)v
);
1375 buf
->writestring("cast(byte)");
1379 buf
->writestring("cast(short)");
1384 buf
->printf("%d", (int)v
);
1388 buf
->writestring("cast(ubyte)");
1392 buf
->writestring("cast(ushort)");
1397 buf
->printf("%du", (unsigned)v
);
1401 buf
->printf("%"PRIdMAX
"L", v
);
1405 buf
->printf("%"PRIuMAX
"LU", v
);
1410 buf
->writestring((char *)(v
? "true" : "false"));
1414 buf
->writestring("cast(");
1415 buf
->writestring(t
->toChars());
1416 buf
->writeByte(')');
1426 else if (v
& 0x8000000000000000LL
)
1427 buf
->printf("0x%"PRIxMAX
, v
);
1429 buf
->printf("%"PRIdMAX
, v
);
1432 void IntegerExp::toMangleBuffer(OutBuffer
*buf
)
1434 if ((sinteger_t
)value
< 0)
1435 buf
->printf("N%"PRIdMAX
, -value
);
1437 buf
->printf("%"PRIdMAX
, value
);
1440 /******************************** RealExp **************************/
1442 RealExp::RealExp(Loc loc
, real_t value
, Type
*type
)
1443 : Expression(loc
, TOKfloat64
, sizeof(RealExp
))
1445 //printf("RealExp::RealExp(%Lg)\n", value);
1446 this->value
= value
;
1450 char *RealExp::toChars()
1452 char buffer
[sizeof(value
) * 3 + 8 + 1 + 1];
1455 value
.format(buffer
, sizeof(buffer
));
1456 if (type
->isimaginary())
1457 strcat(buffer
, "i");
1459 sprintf(buffer
, type
->isimaginary() ? "%Lgi" : "%Lg", value
);
1461 assert(strlen(buffer
) < sizeof(buffer
));
1462 return mem
.strdup(buffer
);
1465 integer_t
RealExp::toInteger()
1468 return (d_int64
) toReal().toInt();
1470 return (sinteger_t
) toReal();
1474 uinteger_t
RealExp::toUInteger()
1477 return (uinteger_t
) toReal().toInt();
1479 return (uinteger_t
) toReal();
1483 real_t
RealExp::toReal()
1485 return type
->isreal() ? value
: 0;
1488 real_t
RealExp::toImaginary()
1490 return type
->isreal() ? 0 : value
;
1493 complex_t
RealExp::toComplex()
1496 return toReal() + toImaginary() * I
;
1498 return complex_t(toReal(), toImaginary());
1502 /********************************
1503 * Test to see if two reals are the same.
1504 * Regard NaN's as equivalent.
1505 * Regard +0 and -0 as different.
1508 int RealEquals(real_t x1
, real_t x2
)
1511 return (isnan(x1
) && isnan(x2
)) ||
1512 /* In some cases, the REALPAD bytes get garbage in them,
1513 * so be sure and ignore them.
1515 memcmp(&x1
, &x2
, REALSIZE
- REALPAD
) == 0;
1517 return (x1
.isNan() && x2
.isNan()) || x1
.isIdenticalTo(x2
);
1521 int RealExp::equals(Object
*o
)
1525 (((Expression
*)o
)->op
== TOKfloat64
&&
1526 ((ne
= (RealExp
*)o
), type
->toHeadMutable()->equals(ne
->type
->toHeadMutable())) &&
1527 RealEquals(value
, ne
->value
)
1534 Expression
*RealExp::semantic(Scope
*sc
)
1537 type
= Type::tfloat64
;
1539 type
= type
->semantic(loc
, sc
);
1543 int RealExp::isBool(int result
)
1546 return result
? (! value
.isZero()) : (value
.isZero());
1548 return result
? (value
!= 0)
1553 void floatToBuffer(OutBuffer
*buf
, Type
*type
, const real_t
& value
)
1555 /* In order to get an exact representation, try converting it
1556 * to decimal then back again. If it matches, use it.
1557 * If it doesn't, fall back to hex, which is
1562 real_t parsed_value
;
1564 value
.format(buffer
, sizeof(buffer
));
1565 parsed_value
= real_t::parse(buffer
, real_t::LongDouble
);
1566 if (parsed_value
.isIdenticalTo( value
))
1567 buf
->writestring(buffer
);
1570 value
.formatHex(buffer
, sizeof(buffer
));
1571 buf
->writestring(buffer
);
1574 sprintf(buffer
, "%Lg", value
);
1575 assert(strlen(buffer
) < sizeof(buffer
));
1576 #if _WIN32 && __DMC__
1577 char *save
= __locale_decpoint
;
1578 __locale_decpoint
= ".";
1579 real_t r
= strtold(buffer
, NULL
);
1580 __locale_decpoint
= save
;
1582 real_t r
= strtold(buffer
, NULL
);
1584 if (r
== value
) // if exact duplication
1585 buf
->writestring(buffer
);
1587 buf
->printf("%La", value
); // ensure exact duplication
1592 Type
*t
= type
->toBasetype();
1598 buf
->writeByte('F');
1604 buf
->writeByte('L');
1610 if (t
->isimaginary())
1611 buf
->writeByte('i');
1615 void RealExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1617 floatToBuffer(buf
, type
, value
);
1620 void realToMangleBuffer(OutBuffer
*buf
, real_t value
)
1622 /* Rely on %A to get portable mangling.
1623 * Must munge result to get only identifier characters.
1625 * Possible values from %A => mangled result
1629 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79
1635 buf
->writestring("NAN"); // no -NAN bugs
1636 else if (value
.isInf())
1637 buf
->writestring(value
.isNegative()?"NINF":"INF");
1640 buf
->writestring("NAN"); // no -NAN bugs
1646 value
.formatHex(buffer
, sizeof(buffer
));
1647 int n
= strlen(buffer
);
1649 int n
= sprintf(buffer
, "%LA", value
);
1650 assert(n
> 0 && n
< sizeof(buffer
));
1652 for (int i
= 0; i
< n
; i
++)
1653 { char c
= buffer
[i
];
1658 buf
->writeByte('N');
1669 break; // skip leading 0X
1678 void RealExp::toMangleBuffer(OutBuffer
*buf
)
1680 buf
->writeByte('e');
1681 realToMangleBuffer(buf
, value
);
1685 /******************************** ComplexExp **************************/
1687 ComplexExp::ComplexExp(Loc loc
, complex_t value
, Type
*type
)
1688 : Expression(loc
, TOKcomplex80
, sizeof(ComplexExp
))
1690 this->value
= value
;
1692 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
1695 char *ComplexExp::toChars()
1697 char buffer
[sizeof(value
) * 3 + 8 + 1];
1700 char buf1
[sizeof(value
) * 3 + 8 + 1];
1701 char buf2
[sizeof(value
) * 3 + 8 + 1];
1702 creall(value
).format(buf1
, sizeof(buf1
));
1703 cimagl(value
).format(buf2
, sizeof(buf2
));
1704 sprintf(buffer
, "(%s+%si)", buf1
, buf2
);
1706 sprintf(buffer
, "(%Lg+%Lgi)", creall(value
), cimagl(value
));
1707 assert(strlen(buffer
) < sizeof(buffer
));
1709 return mem
.strdup(buffer
);
1712 integer_t
ComplexExp::toInteger()
1715 return (d_int64
) toReal().toInt();
1717 return (sinteger_t
) toReal();
1721 uinteger_t
ComplexExp::toUInteger()
1724 return (uinteger_t
) toReal().toInt();
1726 return (uinteger_t
) toReal();
1730 real_t
ComplexExp::toReal()
1732 return creall(value
);
1735 real_t
ComplexExp::toImaginary()
1737 return cimagl(value
);
1740 complex_t
ComplexExp::toComplex()
1745 int ComplexExp::equals(Object
*o
)
1749 (((Expression
*)o
)->op
== TOKcomplex80
&&
1750 ((ne
= (ComplexExp
*)o
), type
->toHeadMutable()->equals(ne
->type
->toHeadMutable())) &&
1752 RealEquals(creall(value
), creall(ne
->value
)) &&
1753 RealEquals(cimagl(value
), cimagl(ne
->value
))
1755 RealEquals(value
.re
, ne
->value
.re
) &&
1756 RealEquals(value
.im
, ne
->value
.im
)
1764 Expression
*ComplexExp::semantic(Scope
*sc
)
1767 type
= Type::tcomplex80
;
1769 type
= type
->semantic(loc
, sc
);
1773 int ComplexExp::isBool(int result
)
1776 return (bool)(value
);
1781 void ComplexExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1787 char buf1
[sizeof(value
) * 3 + 8 + 1];
1788 char buf2
[sizeof(value
) * 3 + 8 + 1];
1789 creall(value
).format(buf1
, sizeof(buf1
));
1790 cimagl(value
).format(buf2
, sizeof(buf2
));
1791 buf
->printf("(%s+%si)", buf1
, buf2
);
1793 buf
->writeByte('(');
1794 floatToBuffer(buf
, type
, creall(value
));
1795 buf
->writeByte('+');
1796 floatToBuffer(buf
, type
, cimagl(value
));
1797 buf
->writestring("i)");
1801 void ComplexExp::toMangleBuffer(OutBuffer
*buf
)
1803 buf
->writeByte('c');
1804 real_t r
= toReal();
1805 realToMangleBuffer(buf
, r
);
1806 buf
->writeByte('c'); // separate the two
1808 realToMangleBuffer(buf
, r
);
1811 /******************************** IdentifierExp **************************/
1813 IdentifierExp::IdentifierExp(Loc loc
, Identifier
*ident
)
1814 : Expression(loc
, TOKidentifier
, sizeof(IdentifierExp
))
1816 this->ident
= ident
;
1819 Expression
*IdentifierExp::semantic(Scope
*sc
)
1825 printf("IdentifierExp::semantic('%s')\n", ident
->toChars());
1827 s
= sc
->search(loc
, ident
, &scopesym
);
1830 WithScopeSymbol
*withsym
;
1832 /* See if the symbol was a member of an enclosing 'with'
1834 withsym
= scopesym
->isWithScopeSymbol();
1839 // Same as wthis.ident
1840 if (s
->needThis() || s
->isTemplateDeclaration())
1842 e
= new VarExp(loc
, withsym
->withstate
->wthis
);
1843 e
= new DotIdExp(loc
, e
, ident
);
1846 { Type
*t
= withsym
->withstate
->wthis
->type
;
1847 if (t
->ty
== Tpointer
)
1848 t
= ((TypePointer
*)t
)->next
;
1849 e
= new TypeDotIdExp(loc
, t
, ident
);
1854 /* If f is really a function template,
1855 * then replace f with the function template declaration.
1857 FuncDeclaration
*f
= s
->isFuncDeclaration();
1859 { TemplateInstance
*ti
= f
->parent
->isTemplateInstance();
1862 !ti
->isTemplateMixin() &&
1863 (ti
->name
== f
->ident
||
1864 ti
->toAlias()->ident
== f
->ident
)
1866 ti
->tempdecl
&& ti
->tempdecl
->onemember
)
1868 TemplateDeclaration
*tempdecl
= ti
->tempdecl
;
1869 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
1870 tempdecl
= tempdecl
->overroot
; // then get the start
1871 e
= new TemplateExp(loc
, tempdecl
);
1872 e
= e
->semantic(sc
);
1876 // Haven't done overload resolution yet, so pass 1
1877 e
= new DsymbolExp(loc
, s
, 1);
1879 return e
->semantic(sc
);
1881 error("undefined identifier %s", ident
->toChars());
1882 type
= Type::terror
;
1886 char *IdentifierExp::toChars()
1888 return ident
->toChars();
1891 void IdentifierExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1894 buf
->writestring(ident
->toHChars2());
1896 buf
->writestring(ident
->toChars());
1899 Expression
*IdentifierExp::toLvalue(Scope
*sc
, Expression
*e
)
1902 tym
= tybasic(e1
->ET
->Tty
);
1903 if (!(tyscalar(tym
) ||
1905 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
1906 synerr(EM_lvalue
); // lvalue expected
1911 /******************************** DollarExp **************************/
1913 DollarExp::DollarExp(Loc loc
)
1914 : IdentifierExp(loc
, Id::dollar
)
1918 /******************************** DsymbolExp **************************/
1920 DsymbolExp::DsymbolExp(Loc loc
, Dsymbol
*s
, int hasOverloads
)
1921 : Expression(loc
, TOKdsymbol
, sizeof(DsymbolExp
))
1924 this->hasOverloads
= hasOverloads
;
1927 Expression
*DsymbolExp::semantic(Scope
*sc
)
1930 printf("DsymbolExp::semantic('%s')\n", s
->toChars());
1938 FuncLiteralDeclaration
*fld
;
1941 ClassDeclaration
*cd
;
1942 ClassDeclaration
*thiscd
= NULL
;
1947 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
1948 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
1951 if (!s
->isFuncDeclaration()) // functions are checked after overloading
1952 checkDeprecated(sc
, s
);
1954 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
1955 if (!s
->isFuncDeclaration())
1956 checkDeprecated(sc
, s
);
1959 thiscd
= sc
->func
->parent
->isClassDeclaration();
1961 // BUG: This should happen after overload resolution for functions, not before
1964 if (hasThis(sc
) && !s
->isFuncDeclaration())
1966 // Supply an implicit 'this', as in
1971 de
= new DotVarExp(loc
, new ThisExp(loc
), s
->isDeclaration());
1972 return de
->semantic(sc
);
1976 em
= s
->isEnumMember();
1980 e
= e
->semantic(sc
);
1983 v
= s
->isVarDeclaration();
1986 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
1990 { error("forward reference of %s", v
->toChars());
1991 type
= Type::terror
;
1994 e
= new VarExp(loc
, v
);
1996 e
= e
->semantic(sc
);
1999 fld
= s
->isFuncLiteralDeclaration();
2001 { //printf("'%s' is a function literal\n", fld->toChars());
2002 e
= new FuncExp(loc
, fld
);
2003 return e
->semantic(sc
);
2005 f
= s
->isFuncDeclaration();
2007 { //printf("'%s' is a function\n", f->toChars());
2008 return new VarExp(loc
, f
, hasOverloads
);
2010 o
= s
->isOverloadSet();
2012 { //printf("'%s' is an overload set\n", o->toChars());
2013 return new OverExp(o
);
2015 cd
= s
->isClassDeclaration();
2016 if (cd
&& thiscd
&& cd
->isBaseOf(thiscd
, NULL
) && sc
->func
->needThis())
2018 // We need to add an implicit 'this' if cd is this class or a base class.
2021 dte
= new DotTypeExp(loc
, new ThisExp(loc
), s
);
2022 return dte
->semantic(sc
);
2024 imp
= s
->isImport();
2029 ie
= new ScopeExp(loc
, imp
->pkg
);
2030 return ie
->semantic(sc
);
2032 pkg
= s
->isPackage();
2037 ie
= new ScopeExp(loc
, pkg
);
2038 return ie
->semantic(sc
);
2040 Module
*mod
= s
->isModule();
2045 ie
= new ScopeExp(loc
, mod
);
2046 return ie
->semantic(sc
);
2052 return new TypeExp(loc
, t
);
2055 TupleDeclaration
*tup
= s
->isTupleDeclaration();
2058 e
= new TupleExp(loc
, tup
);
2059 e
= e
->semantic(sc
);
2063 TemplateInstance
*ti
= s
->isTemplateInstance();
2064 if (ti
&& !global
.errors
)
2065 { if (!ti
->semanticdone
)
2067 s
= ti
->inst
->toAlias();
2068 if (!s
->isTemplateInstance())
2070 e
= new ScopeExp(loc
, ti
);
2071 e
= e
->semantic(sc
);
2075 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
2078 e
= new TemplateExp(loc
, td
);
2079 e
= e
->semantic(sc
);
2084 error("%s '%s' is not a variable", s
->kind(), s
->toChars());
2085 type
= Type::terror
;
2089 char *DsymbolExp::toChars()
2091 return s
->toChars();
2094 void DsymbolExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2096 buf
->writestring(s
->toChars());
2099 Expression
*DsymbolExp::toLvalue(Scope
*sc
, Expression
*e
)
2102 tym
= tybasic(e1
->ET
->Tty
);
2103 if (!(tyscalar(tym
) ||
2105 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
2106 synerr(EM_lvalue
); // lvalue expected
2111 /******************************** ThisExp **************************/
2113 ThisExp::ThisExp(Loc loc
)
2114 : Expression(loc
, TOKthis
, sizeof(ThisExp
))
2119 Expression
*ThisExp::semantic(Scope
*sc
)
2120 { FuncDeclaration
*fd
;
2121 FuncDeclaration
*fdthis
;
2125 printf("ThisExp::semantic()\n");
2128 { //assert(global.errors || var);
2132 /* Special case for typeof(this) and typeof(super) since both
2133 * should work even if they are not inside a non-static member function
2137 // Find enclosing struct or class
2138 for (Dsymbol
*s
= sc
->parent
; 1; s
= s
->parent
)
2140 ClassDeclaration
*cd
;
2141 StructDeclaration
*sd
;
2145 error("%s is not in a struct or class scope", toChars());
2148 cd
= s
->isClassDeclaration();
2154 sd
= s
->isStructDeclaration();
2157 type
= sd
->type
->pointerTo();
2163 fdthis
= sc
->parent
->isFuncDeclaration();
2164 fd
= hasThis(sc
); // fd is the uplevel function with the 'this' variable
2170 assert(var
->parent
);
2172 var
->isVarDeclaration()->checkNestedReference(sc
, loc
);
2173 sc
->callSuper
|= CSXthis
;
2177 error("'this' is only defined in non-static member functions, not %s", sc
->parent
->toChars());
2178 type
= Type::terror
;
2182 int ThisExp::isBool(int result
)
2184 return result
? TRUE
: FALSE
;
2187 void ThisExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2189 buf
->writestring("this");
2192 Expression
*ThisExp::toLvalue(Scope
*sc
, Expression
*e
)
2197 /******************************** SuperExp **************************/
2199 SuperExp::SuperExp(Loc loc
)
2205 Expression
*SuperExp::semantic(Scope
*sc
)
2206 { FuncDeclaration
*fd
;
2207 FuncDeclaration
*fdthis
;
2208 ClassDeclaration
*cd
;
2212 printf("SuperExp::semantic('%s')\n", toChars());
2217 /* Special case for typeof(this) and typeof(super) since both
2218 * should work even if they are not inside a non-static member function
2222 // Find enclosing class
2223 for (Dsymbol
*s
= sc
->parent
; 1; s
= s
->parent
)
2225 ClassDeclaration
*cd
;
2229 error("%s is not in a class scope", toChars());
2232 cd
= s
->isClassDeclaration();
2237 { error("class %s has no 'super'", s
->toChars());
2246 fdthis
= sc
->parent
->isFuncDeclaration();
2252 assert(var
->parent
);
2255 while (s
&& s
->isTemplateInstance())
2258 cd
= s
->isClassDeclaration();
2259 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
2264 error("no base class for %s", cd
->toChars());
2265 type
= fd
->vthis
->type
;
2269 type
= cd
->baseClass
->type
;
2272 var
->isVarDeclaration()->checkNestedReference(sc
, loc
);
2274 sc
->callSuper
|= CSXsuper
;
2279 error("'super' is only allowed in non-static class member functions");
2280 type
= Type::tint32
;
2284 void SuperExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2286 buf
->writestring("super");
2290 /******************************** NullExp **************************/
2292 NullExp::NullExp(Loc loc
)
2293 : Expression(loc
, TOKnull
, sizeof(NullExp
))
2298 Expression
*NullExp::semantic(Scope
*sc
)
2301 printf("NullExp::semantic('%s')\n", toChars());
2303 // NULL is the same as (void *)0
2305 type
= Type::tvoid
->pointerTo();
2309 int NullExp::isBool(int result
)
2311 return result
? FALSE
: TRUE
;
2314 void NullExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2316 buf
->writestring("null");
2319 void NullExp::toMangleBuffer(OutBuffer
*buf
)
2321 buf
->writeByte('n');
2324 /******************************** StringExp **************************/
2326 StringExp::StringExp(Loc loc
, char *string
)
2327 : Expression(loc
, TOKstring
, sizeof(StringExp
))
2329 this->string
= string
;
2330 this->len
= strlen(string
);
2332 this->committed
= 0;
2336 StringExp::StringExp(Loc loc
, void *string
, size_t len
)
2337 : Expression(loc
, TOKstring
, sizeof(StringExp
))
2339 this->string
= string
;
2342 this->committed
= 0;
2346 StringExp::StringExp(Loc loc
, void *string
, size_t len
, unsigned char postfix
)
2347 : Expression(loc
, TOKstring
, sizeof(StringExp
))
2349 this->string
= string
;
2352 this->committed
= 0;
2353 this->postfix
= postfix
;
2357 Expression
*StringExp::syntaxCopy()
2359 printf("StringExp::syntaxCopy() %s\n", toChars());
2364 int StringExp::equals(Object
*o
)
2366 //printf("StringExp::equals('%s')\n", o->toChars());
2367 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
)
2368 { Expression
*e
= (Expression
*)o
;
2370 if (e
->op
== TOKstring
)
2372 return compare(o
) == 0;
2378 char *StringExp::toChars()
2384 memset(&hgs
, 0, sizeof(hgs
));
2385 toCBuffer(&buf
, &hgs
);
2387 p
= (char *)buf
.data
;
2392 Expression
*StringExp::semantic(Scope
*sc
)
2395 printf("StringExp::semantic() %s\n", toChars());
2407 for (u
= 0; u
< len
;)
2409 p
= utf_decodeChar((unsigned char *)string
, len
, &u
, &c
);
2420 string
= buffer
.extractData();
2423 type
= new TypeSArray(Type::tdchar
, new IntegerExp(loc
, len
, Type::tindex
));
2428 for (u
= 0; u
< len
;)
2430 p
= utf_decodeChar((unsigned char *)string
, len
, &u
, &c
);
2436 { buffer
.writeUTF16(c
);
2442 buffer
.writeUTF16(0);
2443 string
= buffer
.extractData();
2446 type
= new TypeSArray(Type::twchar
, new IntegerExp(loc
, len
, Type::tindex
));
2453 type
= new TypeSArray(Type::tchar
, new IntegerExp(loc
, len
, Type::tindex
));
2456 type
= type
->semantic(loc
, sc
);
2457 type
= type
->invariantOf();
2458 //printf("type = %s\n", type->toChars());
2463 /****************************************
2464 * Convert string to char[].
2467 StringExp
*StringExp::toUTF8(Scope
*sc
)
2470 { // Convert to UTF-8 string
2472 Expression
*e
= castTo(sc
, Type::tchar
->arrayOf());
2473 e
= e
->optimize(WANTvalue
);
2474 assert(e
->op
== TOKstring
);
2475 StringExp
*se
= (StringExp
*)e
;
2476 assert(se
->sz
== 1);
2482 int StringExp::compare(Object
*obj
)
2484 // Used to sort case statement expressions so we can do an efficient lookup
2485 StringExp
*se2
= (StringExp
*)(obj
);
2487 // This is a kludge so isExpression() in template.c will return 5
2492 assert(se2
->op
== TOKstring
);
2495 int len2
= se2
->len
;
2502 return strcmp((char *)string
, (char *)se2
->string
);
2506 d_wchar
*s1
= (d_wchar
*)string
;
2507 d_wchar
*s2
= (d_wchar
*)se2
->string
;
2509 for (u
= 0; u
< len
; u
++)
2512 return s1
[u
] - s2
[u
];
2518 d_dchar
*s1
= (d_dchar
*)string
;
2519 d_dchar
*s2
= (d_dchar
*)se2
->string
;
2521 for (u
= 0; u
< len
; u
++)
2524 return s1
[u
] - s2
[u
];
2536 int StringExp::isBool(int result
)
2538 return result
? TRUE
: FALSE
;
2541 unsigned StringExp::charAt(size_t i
)
2547 value
= ((unsigned char *)string
)[i
];
2551 value
= ((unsigned short *)string
)[i
];
2555 value
= ((unsigned int *)string
)[i
];
2565 void StringExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2567 buf
->writeByte('"');
2568 for (size_t i
= 0; i
< len
; i
++)
2569 { unsigned c
= charAt(i
);
2576 buf
->writeByte('\\');
2579 { if (c
<= 0x7F && (isprint(c
) || hgs
->console
))
2582 buf
->printf("\\x%02x", c
);
2584 else if (c
<= 0xFFFF)
2585 buf
->printf("\\x%02x\\x%02x", c
& 0xFF, c
>> 8);
2587 buf
->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2588 c
& 0xFF, (c
>> 8) & 0xFF, (c
>> 16) & 0xFF, c
>> 24);
2592 buf
->writeByte('"');
2594 buf
->writeByte(postfix
);
2597 void StringExp::toMangleBuffer(OutBuffer
*buf
)
2606 /* Write string in UTF-8 format
2611 q
= (unsigned char *)string
;
2616 for (u
= 0; u
< len
; )
2618 p
= utf_decodeWchar((unsigned short *)string
, len
, &u
, &c
);
2629 for (u
= 0; u
< len
; u
++)
2631 c
= ((unsigned *)string
)[u
];
2632 if (!utf_isValidDchar(c
))
2633 error("invalid UCS-32 char \\U%08x", c
);
2644 buf
->printf("%d_", qlen
);
2645 for (size_t i
= 0; i
< qlen
; i
++)
2646 buf
->printf("%02x", q
[i
]);
2649 /************************ ArrayLiteralExp ************************************/
2651 // [ e1, e2, e3, ... ]
2653 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expressions
*elements
)
2654 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
2656 this->elements
= elements
;
2659 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expression
*e
)
2660 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
2662 elements
= new Expressions
;
2666 Expression
*ArrayLiteralExp::syntaxCopy()
2668 return new ArrayLiteralExp(loc
, arraySyntaxCopy(elements
));
2671 Expression
*ArrayLiteralExp::semantic(Scope
*sc
)
2676 printf("ArrayLiteralExp::semantic('%s')\n", toChars());
2681 // Run semantic() on each element
2682 for (int i
= 0; i
< elements
->dim
; i
++)
2683 { e
= (Expression
*)elements
->data
[i
];
2684 e
= e
->semantic(sc
);
2685 elements
->data
[i
] = (void *)e
;
2687 expandTuples(elements
);
2688 for (int i
= 0; i
< elements
->dim
; i
++)
2689 { e
= (Expression
*)elements
->data
[i
];
2692 error("%s has no value", e
->toChars());
2693 e
= resolveProperties(sc
, e
);
2695 unsigned char committed
= 1;
2696 if (e
->op
== TOKstring
)
2697 committed
= ((StringExp
*)e
)->committed
;
2701 // Convert any static arrays to dynamic arrays
2702 if (t0
->ty
== Tsarray
)
2704 t0
= ((TypeSArray
*)t0
)->next
->arrayOf();
2705 e
= e
->implicitCastTo(sc
, t0
);
2709 e
= e
->implicitCastTo(sc
, t0
);
2710 if (!committed
&& e
->op
== TOKstring
)
2711 { StringExp
*se
= (StringExp
*)e
;
2714 elements
->data
[i
] = (void *)e
;
2719 type
= new TypeSArray(t0
, new IntegerExp(elements
->dim
));
2720 type
= type
->semantic(loc
, sc
);
2724 int ArrayLiteralExp::checkSideEffect(int flag
)
2727 for (size_t i
= 0; i
< elements
->dim
; i
++)
2728 { Expression
*e
= (Expression
*)elements
->data
[i
];
2730 f
|= e
->checkSideEffect(2);
2732 if (flag
== 0 && f
== 0)
2733 Expression::checkSideEffect(0);
2737 int ArrayLiteralExp::isBool(int result
)
2739 size_t dim
= elements
? elements
->dim
: 0;
2740 return result
? (dim
!= 0) : (dim
== 0);
2743 int ArrayLiteralExp::canThrow()
2745 return 1; // because it can fail allocating memory
2748 void ArrayLiteralExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2750 buf
->writeByte('[');
2751 argsToCBuffer(buf
, elements
, hgs
);
2752 buf
->writeByte(']');
2755 void ArrayLiteralExp::toMangleBuffer(OutBuffer
*buf
)
2757 size_t dim
= elements
? elements
->dim
: 0;
2758 buf
->printf("A%"PRIuSIZE
, dim
);
2759 for (size_t i
= 0; i
< dim
; i
++)
2760 { Expression
*e
= (Expression
*)elements
->data
[i
];
2761 e
->toMangleBuffer(buf
);
2765 /************************ AssocArrayLiteralExp ************************************/
2767 // [ key0 : value0, key1 : value1, ... ]
2769 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc
,
2770 Expressions
*keys
, Expressions
*values
)
2771 : Expression(loc
, TOKassocarrayliteral
, sizeof(AssocArrayLiteralExp
))
2773 assert(keys
->dim
== values
->dim
);
2775 this->values
= values
;
2778 Expression
*AssocArrayLiteralExp::syntaxCopy()
2780 return new AssocArrayLiteralExp(loc
,
2781 arraySyntaxCopy(keys
), arraySyntaxCopy(values
));
2784 Expression
*AssocArrayLiteralExp::semantic(Scope
*sc
)
2787 Type
*tvalue
= NULL
;
2790 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
2793 // Run semantic() on each element
2794 for (size_t i
= 0; i
< keys
->dim
; i
++)
2795 { Expression
*key
= (Expression
*)keys
->data
[i
];
2796 Expression
*value
= (Expression
*)values
->data
[i
];
2798 key
= key
->semantic(sc
);
2799 value
= value
->semantic(sc
);
2801 keys
->data
[i
] = (void *)key
;
2802 values
->data
[i
] = (void *)value
;
2805 expandTuples(values
);
2806 if (keys
->dim
!= values
->dim
)
2808 error("number of keys is %u, must match number of values %u", keys
->dim
, values
->dim
);
2812 for (size_t i
= 0; i
< keys
->dim
; i
++)
2813 { Expression
*key
= (Expression
*)keys
->data
[i
];
2814 Expression
*value
= (Expression
*)values
->data
[i
];
2817 error("%s has no value", key
->toChars());
2819 error("%s has no value", value
->toChars());
2820 key
= resolveProperties(sc
, key
);
2821 value
= resolveProperties(sc
, value
);
2826 key
= key
->implicitCastTo(sc
, tkey
);
2827 keys
->data
[i
] = (void *)key
;
2830 tvalue
= value
->type
;
2832 value
= value
->implicitCastTo(sc
, tvalue
);
2833 values
->data
[i
] = (void *)value
;
2839 tvalue
= Type::tvoid
;
2840 type
= new TypeAArray(tvalue
, tkey
);
2841 type
= type
->semantic(loc
, sc
);
2845 int AssocArrayLiteralExp::checkSideEffect(int flag
)
2848 for (size_t i
= 0; i
< keys
->dim
; i
++)
2849 { Expression
*key
= (Expression
*)keys
->data
[i
];
2850 Expression
*value
= (Expression
*)values
->data
[i
];
2852 f
|= key
->checkSideEffect(2);
2853 f
|= value
->checkSideEffect(2);
2855 if (flag
== 0 && f
== 0)
2856 Expression::checkSideEffect(0);
2860 int AssocArrayLiteralExp::isBool(int result
)
2862 size_t dim
= keys
->dim
;
2863 return result
? (dim
!= 0) : (dim
== 0);
2866 int AssocArrayLiteralExp::canThrow()
2871 void AssocArrayLiteralExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2873 buf
->writeByte('[');
2874 for (size_t i
= 0; i
< keys
->dim
; i
++)
2875 { Expression
*key
= (Expression
*)keys
->data
[i
];
2876 Expression
*value
= (Expression
*)values
->data
[i
];
2879 buf
->writeByte(',');
2880 expToCBuffer(buf
, hgs
, key
, PREC_assign
);
2881 buf
->writeByte(':');
2882 expToCBuffer(buf
, hgs
, value
, PREC_assign
);
2884 buf
->writeByte(']');
2887 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer
*buf
)
2889 size_t dim
= keys
->dim
;
2890 buf
->printf("A%u", dim
);
2891 for (size_t i
= 0; i
< dim
; i
++)
2892 { Expression
*key
= (Expression
*)keys
->data
[i
];
2893 Expression
*value
= (Expression
*)values
->data
[i
];
2895 key
->toMangleBuffer(buf
);
2896 value
->toMangleBuffer(buf
);
2900 /************************ StructLiteralExp ************************************/
2902 // sd( e1, e2, e3, ... )
2904 StructLiteralExp::StructLiteralExp(Loc loc
, StructDeclaration
*sd
, Expressions
*elements
)
2905 : Expression(loc
, TOKstructliteral
, sizeof(StructLiteralExp
))
2908 this->elements
= elements
;
2911 this->fillHoles
= 1;
2914 Expression
*StructLiteralExp::syntaxCopy()
2916 return new StructLiteralExp(loc
, sd
, arraySyntaxCopy(elements
));
2919 Expression
*StructLiteralExp::semantic(Scope
*sc
)
2923 printf("StructLiteralExp::semantic('%s')\n", toChars());
2928 // Run semantic() on each element
2929 for (size_t i
= 0; i
< elements
->dim
; i
++)
2930 { e
= (Expression
*)elements
->data
[i
];
2933 e
= e
->semantic(sc
);
2934 elements
->data
[i
] = (void *)e
;
2936 expandTuples(elements
);
2938 for (size_t i
= 0; i
< elements
->dim
; i
++)
2939 { e
= (Expression
*)elements
->data
[i
];
2944 error("%s has no value", e
->toChars());
2945 e
= resolveProperties(sc
, e
);
2946 if (i
>= sd
->fields
.dim
)
2947 { error("more initializers than fields of %s", sd
->toChars());
2950 Dsymbol
*s
= (Dsymbol
*)sd
->fields
.data
[i
];
2951 VarDeclaration
*v
= s
->isVarDeclaration();
2953 if (v
->offset
< offset
)
2954 error("overlapping initialization for %s", v
->toChars());
2955 offset
= v
->offset
+ v
->type
->size();
2957 Type
*telem
= v
->type
;
2958 while (!e
->implicitConvTo(telem
) && telem
->toBasetype()->ty
== Tsarray
)
2959 { /* Static array initialization, as in:
2962 telem
= telem
->toBasetype()->nextOf();
2965 e
= e
->implicitCastTo(sc
, telem
);
2967 elements
->data
[i
] = (void *)e
;
2970 /* Fill out remainder of elements[] with default initializers for fields[]
2972 for (size_t i
= elements
->dim
; i
< sd
->fields
.dim
; i
++)
2973 { Dsymbol
*s
= (Dsymbol
*)sd
->fields
.data
[i
];
2974 VarDeclaration
*v
= s
->isVarDeclaration();
2977 if (v
->offset
< offset
)
2984 { e
= v
->init
->toExpression();
2986 error("cannot make expression out of initializer for %s", v
->toChars());
2989 { e
= v
->type
->defaultInit();
2992 offset
= v
->offset
+ v
->type
->size();
3001 /**************************************
3002 * Gets expression at offset of type.
3003 * Returns NULL if not found.
3006 Expression
*StructLiteralExp::getField(Type
*type
, unsigned offset
)
3008 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
3009 // /*toChars()*/"", type->toChars(), offset);
3010 Expression
*e
= NULL
;
3011 int i
= getFieldIndex(type
, offset
);
3015 //printf("\ti = %d\n", i);
3016 assert(i
< elements
->dim
);
3017 e
= (Expression
*)elements
->data
[i
];
3027 /************************************
3028 * Get index of field.
3029 * Returns -1 if not found.
3032 int StructLiteralExp::getFieldIndex(Type
*type
, unsigned offset
)
3034 /* Find which field offset is by looking at the field offsets
3036 for (size_t i
= 0; i
< sd
->fields
.dim
; i
++)
3038 Dsymbol
*s
= (Dsymbol
*)sd
->fields
.data
[i
];
3039 VarDeclaration
*v
= s
->isVarDeclaration();
3042 if (offset
== v
->offset
&&
3043 type
->size() == v
->type
->size())
3044 { Expression
*e
= (Expression
*)elements
->data
[i
];
3056 Expression
*StructLiteralExp::toLvalue(Scope
*sc
, Expression
*e
)
3062 int StructLiteralExp::checkSideEffect(int flag
)
3065 for (size_t i
= 0; i
< elements
->dim
; i
++)
3066 { Expression
*e
= (Expression
*)elements
->data
[i
];
3070 f
|= e
->checkSideEffect(2);
3072 if (flag
== 0 && f
== 0)
3073 Expression::checkSideEffect(0);
3077 int StructLiteralExp::canThrow()
3079 return arrayExpressionCanThrow(elements
);
3082 void StructLiteralExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3084 buf
->writestring(sd
->toChars());
3085 buf
->writeByte('(');
3086 argsToCBuffer(buf
, elements
, hgs
);
3087 buf
->writeByte(')');
3090 void StructLiteralExp::toMangleBuffer(OutBuffer
*buf
)
3092 size_t dim
= elements
? elements
->dim
: 0;
3093 buf
->printf("S%u", dim
);
3094 for (size_t i
= 0; i
< dim
; i
++)
3095 { Expression
*e
= (Expression
*)elements
->data
[i
];
3097 e
->toMangleBuffer(buf
);
3099 buf
->writeByte('v'); // 'v' for void
3103 /************************ TypeDotIdExp ************************************/
3112 TypeDotIdExp::TypeDotIdExp(Loc loc
, Type
*type
, Identifier
*ident
)
3113 : Expression(loc
, TOKtypedot
, sizeof(TypeDotIdExp
))
3116 this->ident
= ident
;
3119 Expression
*TypeDotIdExp::syntaxCopy()
3121 TypeDotIdExp
*te
= new TypeDotIdExp(loc
, type
->syntaxCopy(), ident
);
3125 Expression
*TypeDotIdExp::semantic(Scope
*sc
)
3129 printf("TypeDotIdExp::semantic()\n");
3131 e
= new DotIdExp(loc
, new TypeExp(loc
, type
), ident
);
3132 e
= e
->semantic(sc
);
3136 void TypeDotIdExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3138 buf
->writeByte('(');
3139 type
->toCBuffer(buf
, NULL
, hgs
);
3140 buf
->writeByte(')');
3141 buf
->writeByte('.');
3142 buf
->writestring(ident
->toChars());
3145 /************************************************************/
3147 // Mainly just a placeholder
3149 TypeExp::TypeExp(Loc loc
, Type
*type
)
3150 : Expression(loc
, TOKtype
, sizeof(TypeExp
))
3152 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
3156 Expression
*TypeExp::semantic(Scope
*sc
)
3158 //printf("TypeExp::semantic(%s)\n", type->toChars());
3159 type
= type
->semantic(loc
, sc
);
3163 void TypeExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3165 type
->toCBuffer(buf
, NULL
, hgs
);
3168 /************************************************************/
3170 // Mainly just a placeholder
3172 ScopeExp::ScopeExp(Loc loc
, ScopeDsymbol
*pkg
)
3173 : Expression(loc
, TOKimport
, sizeof(ScopeExp
))
3175 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
3176 //static int count; if (++count == 38) *(char*)0=0;
3180 Expression
*ScopeExp::syntaxCopy()
3182 ScopeExp
*se
= new ScopeExp(loc
, (ScopeDsymbol
*)sds
->syntaxCopy(NULL
));
3186 Expression
*ScopeExp::semantic(Scope
*sc
)
3188 TemplateInstance
*ti
;
3192 printf("+ScopeExp::semantic('%s')\n", toChars());
3195 ti
= sds
->isTemplateInstance();
3196 if (ti
&& !global
.errors
)
3198 if (!ti
->semanticdone
)
3200 s
= ti
->inst
->toAlias();
3201 sds2
= s
->isScopeDsymbol();
3205 //printf("s = %s, '%s'\n", s->kind(), s->toChars());
3209 e
= new VarExp(loc
, ti
->withsym
->withstate
->wthis
);
3210 e
= new DotVarExp(loc
, e
, s
->isDeclaration());
3213 e
= new DsymbolExp(loc
, s
);
3214 e
= e
->semantic(sc
);
3215 //printf("-1ScopeExp::semantic()\n");
3223 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3227 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3228 //printf("\tparent = '%s'\n", sds->parent->toChars());
3232 //printf("-2ScopeExp::semantic() %s\n", toChars());
3236 void ScopeExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3238 if (sds
->isTemplateInstance())
3240 sds
->toCBuffer(buf
, hgs
);
3244 buf
->writestring(sds
->kind());
3245 buf
->writestring(" ");
3246 buf
->writestring(sds
->toChars());
3250 /********************** TemplateExp **************************************/
3252 // Mainly just a placeholder
3254 TemplateExp::TemplateExp(Loc loc
, TemplateDeclaration
*td
)
3255 : Expression(loc
, TOKtemplate
, sizeof(TemplateExp
))
3257 //printf("TemplateExp(): %s\n", td->toChars());
3261 void TemplateExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3263 buf
->writestring(td
->toChars());
3266 void TemplateExp::rvalue()
3268 error("template %s has no value", toChars());
3271 /********************** NewExp **************************************/
3273 NewExp::NewExp(Loc loc
, Expression
*thisexp
, Expressions
*newargs
,
3274 Type
*newtype
, Expressions
*arguments
)
3275 : Expression(loc
, TOKnew
, sizeof(NewExp
))
3277 this->thisexp
= thisexp
;
3278 this->newargs
= newargs
;
3279 this->newtype
= newtype
;
3280 this->arguments
= arguments
;
3286 Expression
*NewExp::syntaxCopy()
3288 return new NewExp(loc
,
3289 thisexp
? thisexp
->syntaxCopy() : NULL
,
3290 arraySyntaxCopy(newargs
),
3291 newtype
->syntaxCopy(), arraySyntaxCopy(arguments
));
3295 Expression
*NewExp::semantic(Scope
*sc
)
3298 ClassDeclaration
*cdthis
= NULL
;
3301 printf("NewExp::semantic() %s\n", toChars());
3303 printf("\tthisexp = %s\n", thisexp
->toChars());
3304 printf("\tnewtype: %s\n", newtype
->toChars());
3306 if (type
) // if semantic() already run
3311 { thisexp
= thisexp
->semantic(sc
);
3312 cdthis
= thisexp
->type
->isClassHandle();
3315 sc
= sc
->push(cdthis
);
3316 type
= newtype
->semantic(loc
, sc
);
3321 error("'this' for nested class must be a class type, not %s", thisexp
->type
->toChars());
3322 type
= newtype
->semantic(loc
, sc
);
3326 type
= newtype
->semantic(loc
, sc
);
3327 newtype
= type
; // in case type gets cast to something else
3328 tb
= type
->toBasetype();
3329 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
3331 arrayExpressionSemantic(newargs
, sc
);
3332 preFunctionArguments(loc
, sc
, newargs
);
3333 arrayExpressionSemantic(arguments
, sc
);
3334 preFunctionArguments(loc
, sc
, arguments
);
3336 if (thisexp
&& tb
->ty
!= Tclass
)
3337 error("e.new is only for allocating nested classes, not %s", tb
->toChars());
3339 if (tb
->ty
== Tclass
)
3342 TypeClass
*tc
= (TypeClass
*)(tb
);
3343 ClassDeclaration
*cd
= tc
->sym
->isClassDeclaration();
3344 if (cd
->isInterfaceDeclaration())
3345 error("cannot create instance of interface %s", cd
->toChars());
3346 else if (cd
->isAbstract())
3347 { error("cannot create instance of abstract class %s", cd
->toChars());
3348 for (int i
= 0; i
< cd
->vtbl
.dim
; i
++)
3349 { FuncDeclaration
*fd
= ((Dsymbol
*)cd
->vtbl
.data
[i
])->isFuncDeclaration();
3350 if (fd
&& fd
->isAbstract())
3351 error("function %s is abstract", fd
->toChars());
3354 checkDeprecated(sc
, cd
);
3356 { /* We need a 'this' pointer for the nested class.
3357 * Ensure we have the right one.
3359 Dsymbol
*s
= cd
->toParent2();
3360 ClassDeclaration
*cdn
= s
->isClassDeclaration();
3361 FuncDeclaration
*fdn
= s
->isFuncDeclaration();
3363 //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
3368 // Supply an implicit 'this' and try again
3369 thisexp
= new ThisExp(loc
);
3370 for (Dsymbol
*sp
= sc
->parent
; 1; sp
= sp
->parent
)
3373 error("outer class %s 'this' needed to 'new' nested class %s", cdn
->toChars(), cd
->toChars());
3376 ClassDeclaration
*cdp
= sp
->isClassDeclaration();
3379 if (cdp
== cdn
|| cdn
->isBaseOf(cdp
, NULL
))
3381 // Add a '.outer' and try again
3382 thisexp
= new DotIdExp(loc
, thisexp
, Id::outer
);
3389 //printf("cdthis = %s\n", cdthis->toChars());
3390 if (cdthis
!= cdn
&& !cdn
->isBaseOf(cdthis
, NULL
))
3391 error("'this' for nested class must be of type %s, not %s", cdn
->toChars(), thisexp
->type
->toChars());
3396 for (Dsymbol
*sf
= sc
->func
; 1; sf
= sf
->toParent2()->isFuncDeclaration())
3400 error("outer class %s 'this' needed to 'new' nested class %s", cdn
->toChars(), cd
->toChars());
3403 printf("sf = %s\n", sf
->toChars());
3404 AggregateDeclaration
*ad
= sf
->isThis();
3405 if (ad
&& (ad
== cdn
|| cdn
->isBaseOf(ad
->isClassDeclaration(), NULL
)))
3412 { /* The nested class cd is nested inside a function,
3413 * we'll let getEthis() look for errors.
3415 //printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars());
3417 // Because thisexp cannot be a function frame pointer
3418 error("e.new is only for allocating nested classes");
3424 error("e.new is only for allocating nested classes");
3426 FuncDeclaration
*f
= cd
->ctor
;
3430 f
= f
->overloadResolve(loc
, NULL
, arguments
);
3431 checkDeprecated(sc
, f
);
3432 member
= f
->isCtorDeclaration();
3435 cd
->accessCheck(loc
, sc
, member
);
3437 tf
= (TypeFunction
*)f
->type
;
3441 arguments
= new Expressions();
3442 functionArguments(loc
, sc
, tf
, arguments
);
3446 if (arguments
&& arguments
->dim
)
3447 error("no constructor for %s", cd
->toChars());
3455 // Prepend the uint size argument to newargs[]
3456 e
= new IntegerExp(loc
, cd
->size(loc
), Type::tsize_t
);
3458 newargs
= new Expressions();
3461 f
= f
->overloadResolve(loc
, NULL
, newargs
);
3462 allocator
= f
->isNewDeclaration();
3465 tf
= (TypeFunction
*)f
->type
;
3466 functionArguments(loc
, sc
, tf
, newargs
);
3470 if (newargs
&& newargs
->dim
)
3471 error("no allocator for %s", cd
->toChars());
3475 else if (tb
->ty
== Tstruct
)
3477 TypeStruct
*ts
= (TypeStruct
*)tb
;
3478 StructDeclaration
*sd
= ts
->sym
;
3479 FuncDeclaration
*f
= sd
->aggNew
;
3482 if (arguments
&& arguments
->dim
)
3483 error("no constructor for %s", type
->toChars());
3489 // Prepend the uint size argument to newargs[]
3490 e
= new IntegerExp(loc
, sd
->size(loc
), Type::tsize_t
);
3492 newargs
= new Expressions();
3495 f
= f
->overloadResolve(loc
, NULL
, newargs
);
3496 allocator
= f
->isNewDeclaration();
3499 tf
= (TypeFunction
*)f
->type
;
3500 functionArguments(loc
, sc
, tf
, newargs
);
3502 e
= new VarExp(loc
, f
);
3503 e
= new CallExp(loc
, e
, newargs
);
3504 e
= e
->semantic(sc
);
3505 e
->type
= type
->pointerTo();
3509 type
= type
->pointerTo();
3511 else if (tb
->ty
== Tarray
&& (arguments
&& arguments
->dim
))
3513 for (size_t i
= 0; i
< arguments
->dim
; i
++)
3515 if (tb
->ty
!= Tarray
)
3516 { error("too many arguments for array");
3521 Expression
*arg
= (Expression
*)arguments
->data
[i
];
3522 arg
= resolveProperties(sc
, arg
);
3523 arg
= arg
->implicitCastTo(sc
, Type::tsize_t
);
3524 arg
= arg
->optimize(WANTvalue
);
3525 if (arg
->op
== TOKint64
&& (long long)arg
->toInteger() < 0)
3526 error("negative array index %s", arg
->toChars());
3527 arguments
->data
[i
] = (void *) arg
;
3528 tb
= ((TypeDArray
*)tb
)->next
->toBasetype();
3531 else if (tb
->isscalar())
3533 if (arguments
&& arguments
->dim
)
3534 error("no constructor for %s", type
->toChars());
3536 type
= type
->pointerTo();
3540 error("new can only create structs, dynamic arrays or class objects, not %s's", type
->toChars());
3541 type
= type
->pointerTo();
3544 //printf("NewExp: '%s'\n", toChars());
3545 //printf("NewExp:type '%s'\n", type->toChars());
3550 int NewExp::checkSideEffect(int flag
)
3555 int NewExp::canThrow()
3560 void NewExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3564 { expToCBuffer(buf
, hgs
, thisexp
, PREC_primary
);
3565 buf
->writeByte('.');
3567 buf
->writestring("new ");
3568 if (newargs
&& newargs
->dim
)
3570 buf
->writeByte('(');
3571 argsToCBuffer(buf
, newargs
, hgs
);
3572 buf
->writeByte(')');
3574 newtype
->toCBuffer(buf
, NULL
, hgs
);
3575 if (arguments
&& arguments
->dim
)
3577 buf
->writeByte('(');
3578 argsToCBuffer(buf
, arguments
, hgs
);
3579 buf
->writeByte(')');
3583 /********************** NewAnonClassExp **************************************/
3585 NewAnonClassExp::NewAnonClassExp(Loc loc
, Expression
*thisexp
,
3586 Expressions
*newargs
, ClassDeclaration
*cd
, Expressions
*arguments
)
3587 : Expression(loc
, TOKnewanonclass
, sizeof(NewAnonClassExp
))
3589 this->thisexp
= thisexp
;
3590 this->newargs
= newargs
;
3592 this->arguments
= arguments
;
3595 Expression
*NewAnonClassExp::syntaxCopy()
3597 return new NewAnonClassExp(loc
,
3598 thisexp
? thisexp
->syntaxCopy() : NULL
,
3599 arraySyntaxCopy(newargs
),
3600 (ClassDeclaration
*)cd
->syntaxCopy(NULL
),
3601 arraySyntaxCopy(arguments
));
3605 Expression
*NewAnonClassExp::semantic(Scope
*sc
)
3608 printf("NewAnonClassExp::semantic() %s\n", toChars());
3609 //printf("type: %s\n", type->toChars());
3612 Expression
*d
= new DeclarationExp(loc
, cd
);
3613 d
= d
->semantic(sc
);
3615 Expression
*n
= new NewExp(loc
, thisexp
, newargs
, cd
->type
, arguments
);
3617 Expression
*c
= new CommaExp(loc
, d
, n
);
3618 return c
->semantic(sc
);
3621 int NewAnonClassExp::checkSideEffect(int flag
)
3626 int NewAnonClassExp::canThrow()
3631 void NewAnonClassExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3635 { expToCBuffer(buf
, hgs
, thisexp
, PREC_primary
);
3636 buf
->writeByte('.');
3638 buf
->writestring("new");
3639 if (newargs
&& newargs
->dim
)
3641 buf
->writeByte('(');
3642 argsToCBuffer(buf
, newargs
, hgs
);
3643 buf
->writeByte(')');
3645 buf
->writestring(" class ");
3646 if (arguments
&& arguments
->dim
)
3648 buf
->writeByte('(');
3649 argsToCBuffer(buf
, arguments
, hgs
);
3650 buf
->writeByte(')');
3652 //buf->writestring(" { }");
3655 cd
->toCBuffer(buf
, hgs
);
3659 /********************** SymOffExp **************************************/
3661 SymbolExp::SymbolExp(Loc loc
, enum TOK op
, int size
, Declaration
*var
, int hasOverloads
)
3662 : Expression(loc
, op
, size
)
3666 this->hasOverloads
= hasOverloads
;
3669 /********************** SymOffExp **************************************/
3671 SymOffExp::SymOffExp(Loc loc
, Declaration
*var
, target_size_t offset
, int hasOverloads
)
3672 : SymbolExp(loc
, TOKsymoff
, sizeof(SymOffExp
), var
, hasOverloads
)
3674 this->offset
= offset
;
3676 VarDeclaration
*v
= var
->isVarDeclaration();
3677 if (v
&& v
->needThis())
3678 error("need 'this' for address of %s", v
->toChars());
3681 Expression
*SymOffExp::semantic(Scope
*sc
)
3684 printf("SymOffExp::semantic('%s')\n", toChars());
3686 //var->semantic(sc);
3688 type
= var
->type
->pointerTo();
3689 VarDeclaration
*v
= var
->isVarDeclaration();
3691 v
->checkNestedReference(sc
, loc
);
3695 int SymOffExp::isBool(int result
)
3697 return result
? TRUE
: FALSE
;
3700 void SymOffExp::checkEscape()
3702 VarDeclaration
*v
= var
->isVarDeclaration();
3705 if (!v
->isDataseg())
3706 error("escaping reference to local variable %s", v
->toChars());
3710 void SymOffExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3713 buf
->printf("(& %s+%"PRIuTSIZE
")", var
->toChars(), offset
);
3715 buf
->printf("& %s", var
->toChars());
3718 /******************************** VarExp **************************/
3720 VarExp::VarExp(Loc loc
, Declaration
*var
, int hasOverloads
)
3721 : SymbolExp(loc
, TOKvar
, sizeof(VarExp
), var
, hasOverloads
)
3723 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
3724 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
3725 this->type
= var
->type
;
3728 int VarExp::equals(Object
*o
)
3732 (((Expression
*)o
)->op
== TOKvar
&&
3733 ((ne
= (VarExp
*)o
), type
->toHeadMutable()->equals(ne
->type
->toHeadMutable())) &&
3739 Expression
*VarExp::semantic(Scope
*sc
)
3740 { FuncLiteralDeclaration
*fd
;
3743 printf("VarExp::semantic(%s)\n", toChars());
3748 if (var
->storage_class
& STClazy
)
3750 TypeFunction
*tf
= new TypeFunction(NULL
, type
, 0, LINKd
);
3751 type
= new TypeDelegate(tf
);
3752 type
= type
->semantic(loc
, sc
);
3757 VarDeclaration
*v
= var
->isVarDeclaration();
3761 if ((v
->isConst() || v
->isInvariant()) &&
3762 type
->toBasetype()->ty
!= Tsarray
&& v
->init
)
3764 ExpInitializer
*ei
= v
->init
->isExpInitializer();
3767 //ei->exp->implicitCastTo(sc, type)->print();
3768 return ei
->exp
->implicitCastTo(sc
, type
);
3772 v
->checkNestedReference(sc
, loc
);
3775 else if ((fd
= var
->isFuncLiteralDeclaration()) != NULL
)
3777 e
= new FuncExp(loc
, fd
);
3785 char *VarExp::toChars()
3787 return var
->toChars();
3790 void VarExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3792 buf
->writestring(var
->toChars());
3795 void VarExp::checkEscape()
3797 VarDeclaration
*v
= var
->isVarDeclaration();
3799 { Type
*tb
= v
->type
->toBasetype();
3800 // if reference type
3801 if (tb
->ty
== Tarray
|| tb
->ty
== Tsarray
|| tb
->ty
== Tclass
)
3803 if ((v
->isAuto() || v
->isScope()) && !v
->noauto
)
3804 error("escaping reference to auto local %s", v
->toChars());
3805 else if (v
->storage_class
& STCvariadic
)
3806 error("escaping reference to variadic parameter %s", v
->toChars());
3811 Expression
*VarExp::toLvalue(Scope
*sc
, Expression
*e
)
3814 tym
= tybasic(e1
->ET
->Tty
);
3815 if (!(tyscalar(tym
) ||
3817 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
3818 synerr(EM_lvalue
); // lvalue expected
3820 if (var
->storage_class
& STClazy
)
3821 error("lazy variables cannot be lvalues");
3825 Expression
*VarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
3827 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
3828 if (type
&& type
->toBasetype()->ty
== Tsarray
)
3829 error("cannot change reference to static array '%s'", var
->toChars());
3831 var
->checkModify(loc
, sc
, type
);
3833 // See if this expression is a modifiable lvalue (i.e. not const)
3834 return toLvalue(sc
, e
);
3838 /******************************** OverExp **************************/
3840 OverExp::OverExp(OverloadSet
*s
)
3841 : Expression(loc
, TOKoverloadset
, sizeof(OverExp
))
3843 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
3848 Expression
*OverExp::toLvalue(Scope
*sc
, Expression
*e
)
3854 /******************************** TupleExp **************************/
3856 TupleExp::TupleExp(Loc loc
, Expressions
*exps
)
3857 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
3859 //printf("TupleExp(this = %p)\n", this);
3865 TupleExp::TupleExp(Loc loc
, TupleDeclaration
*tup
)
3866 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
3868 exps
= new Expressions();
3871 exps
->reserve(tup
->objects
->dim
);
3872 for (size_t i
= 0; i
< tup
->objects
->dim
; i
++)
3873 { Object
*o
= (Object
*)tup
->objects
->data
[i
];
3874 if (o
->dyncast() == DYNCAST_EXPRESSION
)
3876 Expression
*e
= (Expression
*)o
;
3877 e
= e
->syntaxCopy();
3880 else if (o
->dyncast() == DYNCAST_DSYMBOL
)
3882 Dsymbol
*s
= (Dsymbol
*)o
;
3883 Expression
*e
= new DsymbolExp(loc
, s
);
3886 else if (o
->dyncast() == DYNCAST_TYPE
)
3888 Type
*t
= (Type
*)o
;
3889 Expression
*e
= new TypeExp(loc
, t
);
3894 error("%s is not an expression", o
->toChars());
3899 int TupleExp::equals(Object
*o
)
3904 if (((Expression
*)o
)->op
== TOKtuple
)
3906 TupleExp
*te
= (TupleExp
*)o
;
3907 if (exps
->dim
!= te
->exps
->dim
)
3909 for (size_t i
= 0; i
< exps
->dim
; i
++)
3910 { Expression
*e1
= (Expression
*)exps
->data
[i
];
3911 Expression
*e2
= (Expression
*)te
->exps
->data
[i
];
3913 if (!e1
->equals(e2
))
3921 Expression
*TupleExp::syntaxCopy()
3923 return new TupleExp(loc
, arraySyntaxCopy(exps
));
3926 Expression
*TupleExp::semantic(Scope
*sc
)
3929 printf("+TupleExp::semantic(%s)\n", toChars());
3934 // Run semantic() on each argument
3935 for (size_t i
= 0; i
< exps
->dim
; i
++)
3936 { Expression
*e
= (Expression
*)exps
->data
[i
];
3938 e
= e
->semantic(sc
);
3940 { error("%s has no value", e
->toChars());
3941 e
->type
= Type::terror
;
3943 exps
->data
[i
] = (void *)e
;
3947 if (0 && exps
->dim
== 1)
3949 return (Expression
*)exps
->data
[0];
3951 type
= new TypeTuple(exps
);
3952 //printf("-TupleExp::semantic(%s)\n", toChars());
3956 void TupleExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3958 buf
->writestring("tuple(");
3959 argsToCBuffer(buf
, exps
, hgs
);
3960 buf
->writeByte(')');
3963 int TupleExp::checkSideEffect(int flag
)
3966 for (int i
= 0; i
< exps
->dim
; i
++)
3967 { Expression
*e
= (Expression
*)exps
->data
[i
];
3969 f
|= e
->checkSideEffect(2);
3971 if (flag
== 0 && f
== 0)
3972 Expression::checkSideEffect(0);
3976 int TupleExp::canThrow()
3978 return arrayExpressionCanThrow(exps
);
3981 void TupleExp::checkEscape()
3983 for (size_t i
= 0; i
< exps
->dim
; i
++)
3984 { Expression
*e
= (Expression
*)exps
->data
[i
];
3989 /******************************** FuncExp *********************************/
3991 FuncExp::FuncExp(Loc loc
, FuncLiteralDeclaration
*fd
)
3992 : Expression(loc
, TOKfunction
, sizeof(FuncExp
))
3997 Expression
*FuncExp::syntaxCopy()
3999 return new FuncExp(loc
, (FuncLiteralDeclaration
*)fd
->syntaxCopy(NULL
));
4002 Expression
*FuncExp::semantic(Scope
*sc
)
4005 printf("FuncExp::semantic(%s)\n", toChars());
4010 fd
->parent
= sc
->parent
;
4021 if (!global
.errors
&& global
.params
.useInline
)
4026 // Type is a "delegate to" or "pointer to" the function literal
4029 type
= new TypeDelegate(fd
->type
);
4030 type
= type
->semantic(loc
, sc
);
4034 type
= fd
->type
->pointerTo();
4036 fd
->tookAddressOf
++;
4041 char *FuncExp::toChars()
4043 return fd
->toChars();
4046 void FuncExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4048 buf
->writestring(fd
->toChars());
4052 /******************************** DeclarationExp **************************/
4054 DeclarationExp::DeclarationExp(Loc loc
, Dsymbol
*declaration
)
4055 : Expression(loc
, TOKdeclaration
, sizeof(DeclarationExp
))
4057 this->declaration
= declaration
;
4060 Expression
*DeclarationExp::syntaxCopy()
4062 return new DeclarationExp(loc
, declaration
->syntaxCopy(NULL
));
4065 Expression
*DeclarationExp::semantic(Scope
*sc
)
4071 printf("DeclarationExp::semantic() %s\n", toChars());
4074 /* This is here to support extern(linkage) declaration,
4075 * where the extern(linkage) winds up being an AttribDeclaration
4078 Dsymbol
*s
= declaration
;
4080 AttribDeclaration
*ad
= declaration
->isAttribDeclaration();
4083 if (ad
->decl
&& ad
->decl
->dim
== 1)
4084 s
= (Dsymbol
*)ad
->decl
->data
[0];
4087 if (s
->isVarDeclaration())
4088 { // Do semantic() on initializer first, so:
4091 declaration
->semantic(sc
);
4092 s
->parent
= sc
->parent
;
4095 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
4096 // Insert into both local scope and function scope.
4097 // Must be unique in both.
4101 error("declaration %s is already defined", s
->toPrettyChars());
4103 { VarDeclaration
*v
= s
->isVarDeclaration();
4104 if (s
->isFuncDeclaration() &&
4105 !sc
->func
->localsymtab
->insert(s
))
4106 error("declaration %s is already defined in another scope in %s", s
->toPrettyChars(), sc
->func
->toChars());
4107 else if (!global
.params
.useDeprecated
)
4108 { // Disallow shadowing
4110 for (Scope
*scx
= sc
->enclosing
; scx
&& scx
->func
== sc
->func
; scx
= scx
->enclosing
)
4113 if (scx
->scopesym
&& scx
->scopesym
->symtab
&&
4114 (s2
= scx
->scopesym
->symtab
->lookup(s
->ident
)) != NULL
&&
4117 error("shadowing declaration %s is deprecated", s
->toPrettyChars());
4123 if (!s
->isVarDeclaration())
4125 declaration
->semantic(sc
);
4126 s
->parent
= sc
->parent
;
4130 declaration
->semantic2(sc
);
4133 declaration
->semantic3(sc
);
4135 if (!global
.errors
&& global
.params
.useInline
)
4136 declaration
->inlineScan();
4144 int DeclarationExp::checkSideEffect(int flag
)
4149 int DeclarationExp::canThrow()
4151 VarDeclaration
*v
= declaration
->isVarDeclaration();
4153 { ExpInitializer
*ie
= v
->init
->isExpInitializer();
4154 return ie
&& ie
->exp
->canThrow();
4159 void DeclarationExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4161 declaration
->toCBuffer(buf
, hgs
);
4165 /************************ TypeidExp ************************************/
4171 TypeidExp::TypeidExp(Loc loc
, Type
*typeidType
)
4172 : Expression(loc
, TOKtypeid
, sizeof(TypeidExp
))
4174 this->typeidType
= typeidType
;
4178 Expression
*TypeidExp::syntaxCopy()
4180 return new TypeidExp(loc
, typeidType
->syntaxCopy());
4184 Expression
*TypeidExp::semantic(Scope
*sc
)
4188 printf("TypeidExp::semantic()\n");
4190 typeidType
= typeidType
->semantic(loc
, sc
);
4191 e
= typeidType
->getTypeInfo(sc
);
4195 void TypeidExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4197 buf
->writestring("typeid(");
4198 typeidType
->toCBuffer(buf
, NULL
, hgs
);
4199 buf
->writeByte(')');
4202 /************************ TraitsExp ************************************/
4205 * __traits(identifier, args...)
4208 TraitsExp::TraitsExp(Loc loc
, Identifier
*ident
, Objects
*args
)
4209 : Expression(loc
, TOKtraits
, sizeof(TraitsExp
))
4211 this->ident
= ident
;
4216 Expression
*TraitsExp::syntaxCopy()
4218 return new TraitsExp(loc
, ident
, TemplateInstance::arraySyntaxCopy(args
));
4222 void TraitsExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4224 buf
->writestring("__traits(");
4225 buf
->writestring(ident
->toChars());
4228 for (int i
= 0; i
< args
->dim
; i
++)
4230 buf
->writeByte(',');
4231 Object
*oarg
= (Object
*)args
->data
[i
];
4232 ObjectToCBuffer(buf
, hgs
, oarg
);
4235 buf
->writeByte(')');
4238 /************************************************************/
4240 HaltExp::HaltExp(Loc loc
)
4241 : Expression(loc
, TOKhalt
, sizeof(HaltExp
))
4245 Expression
*HaltExp::semantic(Scope
*sc
)
4248 printf("HaltExp::semantic()\n");
4254 int HaltExp::checkSideEffect(int flag
)
4259 void HaltExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4261 buf
->writestring("halt");
4264 /************************************************************/
4266 IsExp::IsExp(Loc loc
, Type
*targ
, Identifier
*id
, enum TOK tok
,
4267 Type
*tspec
, enum TOK tok2
, TemplateParameters
*parameters
)
4268 : Expression(loc
, TOKis
, sizeof(IsExp
))
4273 this->tspec
= tspec
;
4275 this->parameters
= parameters
;
4278 Expression
*IsExp::syntaxCopy()
4280 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4281 TemplateParameters
*p
= NULL
;
4284 p
= new TemplateParameters();
4285 p
->setDim(parameters
->dim
);
4286 for (int i
= 0; i
< p
->dim
; i
++)
4287 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
4288 p
->data
[i
] = (void *)tp
->syntaxCopy();
4292 return new IsExp(loc
,
4296 tspec
? tspec
->syntaxCopy() : NULL
,
4301 Expression
*IsExp::semantic(Scope
*sc
)
4304 /* is(targ id tok tspec)
4305 * is(targ id == tok2)
4308 //printf("IsExp::semantic(%s)\n", toChars());
4309 if (id
&& !(sc
->flags
& SCOPEstaticif
))
4310 error("can only declare type aliases within static if conditionals");
4312 unsigned errors_save
= global
.errors
;
4314 global
.gag
++; // suppress printing of error messages
4315 targ
= targ
->semantic(loc
, sc
);
4317 unsigned gerrors
= global
.errors
;
4318 global
.errors
= errors_save
;
4320 if (gerrors
) // if any errors happened
4321 { // then condition is false
4324 else if (tok2
!= TOKreserved
)
4329 if (targ
->ty
!= Ttypedef
)
4331 tded
= ((TypeTypedef
*)targ
)->sym
->basetype
;
4335 if (targ
->ty
!= Tstruct
)
4337 if (((TypeStruct
*)targ
)->sym
->isUnionDeclaration())
4343 if (targ
->ty
!= Tstruct
)
4345 if (!((TypeStruct
*)targ
)->sym
->isUnionDeclaration())
4351 if (targ
->ty
!= Tclass
)
4353 if (((TypeClass
*)targ
)->sym
->isInterfaceDeclaration())
4359 if (targ
->ty
!= Tclass
)
4361 if (!((TypeClass
*)targ
)->sym
->isInterfaceDeclaration())
4368 if (!targ
->isConst())
4374 if (!targ
->isInvariant())
4381 // If class or interface, get the base class and interfaces
4382 if (targ
->ty
!= Tclass
)
4385 { ClassDeclaration
*cd
= ((TypeClass
*)targ
)->sym
;
4386 Arguments
*args
= new Arguments
;
4387 args
->reserve(cd
->baseclasses
.dim
);
4388 for (size_t i
= 0; i
< cd
->baseclasses
.dim
; i
++)
4389 { BaseClass
*b
= (BaseClass
*)cd
->baseclasses
.data
[i
];
4390 args
->push(new Argument(STCin
, b
->type
, NULL
, NULL
));
4392 tded
= new TypeTuple(args
);
4397 if (targ
->ty
!= Tenum
)
4399 tded
= ((TypeEnum
*)targ
)->sym
->memtype
;
4403 if (targ
->ty
!= Tdelegate
)
4405 tded
= ((TypeDelegate
*)targ
)->next
; // the underlying function type
4410 if (targ
->ty
!= Tfunction
)
4414 /* Generate tuple from function parameter types.
4416 assert(tded
->ty
== Tfunction
);
4417 Arguments
*params
= ((TypeFunction
*)tded
)->parameters
;
4418 size_t dim
= Argument::dim(params
);
4419 Arguments
*args
= new Arguments
;
4421 for (size_t i
= 0; i
< dim
; i
++)
4422 { Argument
*arg
= Argument::getNth(params
, i
);
4423 assert(arg
&& arg
->type
);
4424 args
->push(new Argument(arg
->storageClass
, arg
->type
, NULL
, NULL
));
4426 tded
= new TypeTuple(args
);
4430 /* Get the 'return type' for the function,
4431 * delegate, or pointer to function.
4433 if (targ
->ty
== Tfunction
)
4434 tded
= ((TypeFunction
*)targ
)->next
;
4435 else if (targ
->ty
== Tdelegate
)
4436 { tded
= ((TypeDelegate
*)targ
)->next
;
4437 tded
= ((TypeFunction
*)tded
)->next
;
4439 else if (targ
->ty
== Tpointer
&&
4440 ((TypePointer
*)targ
)->next
->ty
== Tfunction
)
4441 { tded
= ((TypePointer
*)targ
)->next
;
4442 tded
= ((TypeFunction
*)tded
)->next
;
4453 else if (id
&& tspec
)
4455 /* Evaluate to TRUE if targ matches tspec.
4456 * If TRUE, declare id as an alias for the specialized type.
4460 assert(parameters
&& parameters
->dim
);
4463 dedtypes
.setDim(parameters
->dim
);
4466 m
= targ
->deduceType(NULL
, tspec
, parameters
, &dedtypes
);
4467 if (m
== MATCHnomatch
||
4468 (m
!= MATCHexact
&& tok
== TOKequal
))
4472 tded
= (Type
*)dedtypes
.data
[0];
4478 tiargs
.data
[0] = (void *)targ
;
4480 for (int i
= 1; i
< parameters
->dim
; i
++)
4481 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
4484 m
= tp
->matchArg(sc
, &tiargs
, i
, parameters
, &dedtypes
, &s
);
4485 if (m
== MATCHnomatch
)
4489 error("declaration %s is already defined", s
->toChars());
4491 Object
*o
= (Object
*)dedtypes
.data
[i
];
4492 Dsymbol
*s
= TemplateDeclaration::declareParameter(loc
, sc
, tp
, o
);
4495 s
->addMember(sc
, sc
->sd
, 1);
4503 /* Declare id as an alias for type targ. Evaluate to TRUE
4510 /* Evaluate to TRUE if targ matches tspec
4512 tspec
= tspec
->semantic(loc
, sc
);
4513 //printf("targ = %s\n", targ->toChars());
4514 //printf("tspec = %s\n", tspec->toChars());
4515 if (tok
== TOKcolon
)
4516 { if (targ
->implicitConvTo(tspec
))
4522 { if (targ
->equals(tspec
))
4532 Dsymbol
*s
= new AliasDeclaration(loc
, id
, tded
);
4535 error("declaration %s is already defined", s
->toChars());
4537 s
->addMember(sc
, sc
->sd
, 1);
4539 return new IntegerExp(loc
, 1, Type::tbool
);
4542 return new IntegerExp(loc
, 0, Type::tbool
);
4545 void IsExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4547 buf
->writestring("is(");
4548 targ
->toCBuffer(buf
, id
, hgs
);
4549 if (tok2
!= TOKreserved
)
4551 buf
->printf(" %s %s", Token::toChars(tok
), Token::toChars(tok2
));
4555 if (tok
== TOKcolon
)
4556 buf
->writestring(" : ");
4558 buf
->writestring(" == ");
4559 tspec
->toCBuffer(buf
, NULL
, hgs
);
4562 { // First parameter is already output, so start with second
4563 for (int i
= 1; i
< parameters
->dim
; i
++)
4565 buf
->writeByte(',');
4566 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
4567 tp
->toCBuffer(buf
, hgs
);
4570 buf
->writeByte(')');
4574 /************************************************************/
4576 UnaExp::UnaExp(Loc loc
, enum TOK op
, int size
, Expression
*e1
)
4577 : Expression(loc
, op
, size
)
4582 Expression
*UnaExp::syntaxCopy()
4585 e
= (UnaExp
*)copy();
4587 e
->e1
= e
->e1
->syntaxCopy();
4591 Expression
*UnaExp::semantic(Scope
*sc
)
4594 printf("UnaExp::semantic('%s')\n", toChars());
4596 e1
= e1
->semantic(sc
);
4598 // error("%s has no value", e1->toChars());
4602 int UnaExp::canThrow()
4604 return e1
->canThrow();
4607 void UnaExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4609 buf
->writestring(Token::toChars(op
));
4610 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
4613 /************************************************************/
4615 BinExp::BinExp(Loc loc
, enum TOK op
, int size
, Expression
*e1
, Expression
*e2
)
4616 : Expression(loc
, op
, size
)
4622 Expression
*BinExp::syntaxCopy()
4625 e
= (BinExp
*)copy();
4627 e
->e1
= e
->e1
->syntaxCopy();
4628 e
->e2
= e
->e2
->syntaxCopy();
4632 Expression
*BinExp::semantic(Scope
*sc
)
4635 printf("BinExp::semantic('%s')\n", toChars());
4637 e1
= e1
->semantic(sc
);
4640 error("%s has no value", e1
->toChars());
4641 e1
->type
= Type::terror
;
4643 e2
= e2
->semantic(sc
);
4646 error("%s has no value", e2
->toChars());
4647 e2
->type
= Type::terror
;
4653 Expression
*BinExp::semanticp(Scope
*sc
)
4655 BinExp::semantic(sc
);
4656 e1
= resolveProperties(sc
, e1
);
4657 e2
= resolveProperties(sc
, e2
);
4661 /***************************
4662 * Common semantic routine for some xxxAssignExp's.
4665 Expression
*BinExp::commonSemanticAssign(Scope
*sc
)
4670 BinExp::semantic(sc
);
4671 e2
= resolveProperties(sc
, e2
);
4673 e
= op_overload(sc
);
4677 e1
= e1
->modifiableLvalue(sc
, e1
);
4680 if (type
->toBasetype()->ty
== Tbool
)
4682 error("operator not allowed on bool expression %s", toChars());
4685 e1
->checkArithmetic();
4686 e2
->checkArithmetic();
4688 if (op
== TOKmodass
&& e2
->type
->iscomplex())
4689 { error("cannot perform modulo complex arithmetic");
4690 return new IntegerExp(0);
4696 Expression
*BinExp::commonSemanticAssignIntegral(Scope
*sc
)
4701 BinExp::semantic(sc
);
4702 e2
= resolveProperties(sc
, e2
);
4704 e
= op_overload(sc
);
4708 e1
= e1
->modifiableLvalue(sc
, e1
);
4711 if (type
->toBasetype()->ty
== Tbool
)
4713 e2
= e2
->implicitCastTo(sc
, type
);
4717 e1
->checkIntegral();
4718 e2
->checkIntegral();
4723 int BinExp::checkSideEffect(int flag
)
4725 if (op
== TOKplusplus
||
4726 op
== TOKminusminus
||
4728 op
== TOKconstruct
||
4745 return Expression::checkSideEffect(flag
);
4748 void BinExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4750 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
4751 buf
->writeByte(' ');
4752 buf
->writestring(Token::toChars(op
));
4753 buf
->writeByte(' ');
4754 expToCBuffer(buf
, hgs
, e2
, (enum PREC
)(precedence
[op
] + 1));
4757 int BinExp::isunsigned()
4759 return e1
->type
->isunsigned() || e2
->type
->isunsigned();
4762 int BinExp::canThrow()
4764 return e1
->canThrow() || e2
->canThrow();
4767 void BinExp::incompatibleTypes()
4769 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
4770 e1
->toChars(), Token::toChars(op
), e2
->toChars(),
4771 e1
->type
->toChars(), e2
->type
->toChars());
4774 /************************************************************/
4776 CompileExp::CompileExp(Loc loc
, Expression
*e
)
4777 : UnaExp(loc
, TOKmixin
, sizeof(CompileExp
), e
)
4781 Expression
*CompileExp::semantic(Scope
*sc
)
4784 printf("CompileExp::semantic('%s')\n", toChars());
4786 UnaExp::semantic(sc
);
4787 e1
= resolveProperties(sc
, e1
);
4788 e1
= e1
->optimize(WANTvalue
| WANTinterpret
);
4789 if (e1
->op
!= TOKstring
)
4790 { error("argument to mixin must be a string, not (%s)", e1
->toChars());
4791 type
= Type::terror
;
4794 StringExp
*se
= (StringExp
*)e1
;
4795 se
= se
->toUTF8(sc
);
4796 Parser
p(sc
->module
, (unsigned char *)se
->string
, se
->len
, 0);
4799 //printf("p.loc.linnum = %d\n", p.loc.linnum);
4800 Expression
*e
= p
.parseExpression();
4801 if (p
.token
.value
!= TOKeof
)
4802 error("incomplete mixin expression (%s)", se
->toChars());
4803 return e
->semantic(sc
);
4806 void CompileExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4808 buf
->writestring("mixin(");
4809 expToCBuffer(buf
, hgs
, e1
, PREC_assign
);
4810 buf
->writeByte(')');
4813 /************************************************************/
4815 FileExp::FileExp(Loc loc
, Expression
*e
)
4816 : UnaExp(loc
, TOKmixin
, sizeof(FileExp
), e
)
4820 Expression
*FileExp::semantic(Scope
*sc
)
4825 printf("FileExp::semantic('%s')\n", toChars());
4827 UnaExp::semantic(sc
);
4828 e1
= resolveProperties(sc
, e1
);
4829 e1
= e1
->optimize(WANTvalue
);
4830 if (e1
->op
!= TOKstring
)
4831 { error("file name argument must be a string, not (%s)", e1
->toChars());
4834 se
= (StringExp
*)e1
;
4835 se
= se
->toUTF8(sc
);
4836 name
= (char *)se
->string
;
4838 if (!global
.params
.fileImppath
)
4839 { error("need -Jpath switch to import text file %s", name
);
4843 if (name
!= FileName::name(name
))
4844 { error("use -Jpath switch to provide path for filename %s", name
);
4848 name
= FileName::searchPath(global
.filePath
, name
, 0);
4850 { error("file %s cannot be found, check -Jpath", se
->toChars());
4854 if (global
.params
.verbose
)
4855 printf("file %s\t(%s)\n", se
->string
, name
);
4859 { error("cannot read file %s", f
.toChars());
4865 se
= new StringExp(loc
, f
.buffer
, f
.len
);
4869 return se
->semantic(sc
);
4872 se
= new StringExp(loc
, "");
4876 void FileExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4878 buf
->writestring("import(");
4879 expToCBuffer(buf
, hgs
, e1
, PREC_assign
);
4880 buf
->writeByte(')');
4883 /************************************************************/
4885 AssertExp::AssertExp(Loc loc
, Expression
*e
, Expression
*msg
)
4886 : UnaExp(loc
, TOKassert
, sizeof(AssertExp
), e
)
4891 Expression
*AssertExp::syntaxCopy()
4893 AssertExp
*ae
= new AssertExp(loc
, e1
->syntaxCopy(),
4894 msg
? msg
->syntaxCopy() : NULL
);
4898 Expression
*AssertExp::semantic(Scope
*sc
)
4901 printf("AssertExp::semantic('%s')\n", toChars());
4903 UnaExp::semantic(sc
);
4904 e1
= resolveProperties(sc
, e1
);
4905 // BUG: see if we can do compile time elimination of the Assert
4906 e1
= e1
->optimize(WANTvalue
);
4907 e1
= e1
->checkToBoolean();
4910 msg
= msg
->semantic(sc
);
4911 msg
= resolveProperties(sc
, msg
);
4912 msg
= msg
->implicitCastTo(sc
, Type::tchar
->constOf()->arrayOf());
4913 msg
= msg
->optimize(WANTvalue
);
4915 if (e1
->isBool(FALSE
))
4917 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4918 fd
->hasReturnExp
|= 4;
4920 if (!global
.params
.useAssert
)
4921 { Expression
*e
= new HaltExp(loc
);
4922 e
= e
->semantic(sc
);
4930 int AssertExp::checkSideEffect(int flag
)
4935 int AssertExp::canThrow()
4937 return (global
.params
.useAssert
!= 0);
4940 void AssertExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4942 buf
->writestring("assert(");
4943 expToCBuffer(buf
, hgs
, e1
, PREC_assign
);
4946 buf
->writeByte(',');
4947 expToCBuffer(buf
, hgs
, msg
, PREC_assign
);
4949 buf
->writeByte(')');
4952 /************************************************************/
4954 DotIdExp::DotIdExp(Loc loc
, Expression
*e
, Identifier
*ident
)
4955 : UnaExp(loc
, TOKdot
, sizeof(DotIdExp
), e
)
4957 this->ident
= ident
;
4960 Expression
*DotIdExp::semantic(Scope
*sc
)
4966 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
4967 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
4970 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
4973 /* Don't do semantic analysis if we'll be converting
4976 if (ident
== Id::stringof
)
4977 { char *s
= e1
->toChars();
4978 e
= new StringExp(loc
, s
, strlen(s
), 'c');
4979 e
= e
->semantic(sc
);
4984 /* Special case: rewrite this.id and super.id
4985 * to be classtype.id and baseclasstype.id
4986 * if we have no this pointer.
4988 if ((e1
->op
== TOKthis
|| e1
->op
== TOKsuper
) && !hasThis(sc
))
4989 { ClassDeclaration
*cd
;
4990 StructDeclaration
*sd
;
4991 AggregateDeclaration
*ad
;
4993 ad
= sc
->getStructClassScope();
4996 cd
= ad
->isClassDeclaration();
4999 if (e1
->op
== TOKthis
)
5001 e
= new TypeDotIdExp(loc
, cd
->type
, ident
);
5002 return e
->semantic(sc
);
5004 else if (cd
->baseClass
&& e1
->op
== TOKsuper
)
5006 e
= new TypeDotIdExp(loc
, cd
->baseClass
->type
, ident
);
5007 return e
->semantic(sc
);
5012 sd
= ad
->isStructDeclaration();
5015 if (e1
->op
== TOKthis
)
5017 e
= new TypeDotIdExp(loc
, sd
->type
, ident
);
5018 return e
->semantic(sc
);
5025 UnaExp::semantic(sc
);
5027 if (e1
->op
== TOKdotexp
)
5029 DotExp
*de
= (DotExp
*)e1
;
5035 e1
= resolveProperties(sc
, e1
);
5040 if (e1
->op
== TOKtuple
&& ident
== Id::offsetof
)
5041 { /* 'distribute' the .offsetof to each of the tuple elements.
5043 TupleExp
*te
= (TupleExp
*)e1
;
5044 Expressions
*exps
= new Expressions();
5045 exps
->setDim(te
->exps
->dim
);
5046 for (int i
= 0; i
< exps
->dim
; i
++)
5047 { Expression
*e
= (Expression
*)te
->exps
->data
[i
];
5048 e
= e
->semantic(sc
);
5049 e
= new DotIdExp(e
->loc
, e
, Id::offsetof
);
5050 exps
->data
[i
] = (void *)e
;
5052 e
= new TupleExp(loc
, exps
);
5053 e
= e
->semantic(sc
);
5057 if (e1
->op
== TOKtuple
&& ident
== Id::length
)
5059 TupleExp
*te
= (TupleExp
*)e1
;
5060 e
= new IntegerExp(loc
, te
->exps
->dim
, Type::tsize_t
);
5064 if (eright
->op
== TOKimport
) // also used for template alias's
5067 ScopeExp
*ie
= (ScopeExp
*)eright
;
5069 s
= ie
->sds
->search(loc
, ident
, 0);
5073 checkDeprecated(sc
, s
);
5075 EnumMember
*em
= s
->isEnumMember();
5079 e
= e
->semantic(sc
);
5083 VarDeclaration
*v
= s
->isVarDeclaration();
5086 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
5089 error("circular reference to '%s'", v
->toChars());
5090 type
= Type::tint32
;
5095 if (v
->isConst() || v
->isInvariant())
5099 ExpInitializer
*ei
= v
->init
->isExpInitializer();
5102 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars());
5103 //ei->exp = ei->exp->semantic(sc);
5104 if (ei
->exp
->type
== type
)
5106 e
= ei
->exp
->copy(); // make copy so we can change loc
5112 else if (type
->isscalar())
5114 e
= type
->defaultInit();
5123 eleft
= new ThisExp(loc
);
5124 e
= new DotVarExp(loc
, eleft
, v
);
5125 e
= e
->semantic(sc
);
5129 e
= new VarExp(loc
, v
);
5131 { e
= new CommaExp(loc
, eleft
, e
);
5138 FuncDeclaration
*f
= s
->isFuncDeclaration();
5141 //printf("it's a function\n");
5145 eleft
= new ThisExp(loc
);
5146 e
= new DotVarExp(loc
, eleft
, f
);
5147 e
= e
->semantic(sc
);
5151 e
= new VarExp(loc
, f
, 1);
5153 { e
= new CommaExp(loc
, eleft
, e
);
5160 Type
*t
= s
->getType();
5163 return new TypeExp(loc
, t
);
5166 TupleDeclaration
*tup
= s
->isTupleDeclaration();
5170 error("cannot have e.tuple");
5171 e
= new TupleExp(loc
, tup
);
5172 e
= e
->semantic(sc
);
5176 ScopeDsymbol
*sds
= s
->isScopeDsymbol();
5179 //printf("it's a ScopeDsymbol\n");
5180 e
= new ScopeExp(loc
, sds
);
5181 e
= e
->semantic(sc
);
5183 e
= new DotExp(loc
, eleft
, e
);
5187 Import
*imp
= s
->isImport();
5192 ie
= new ScopeExp(loc
, imp
->pkg
);
5193 return ie
->semantic(sc
);
5196 // BUG: handle other cases like in IdentifierExp::semantic()
5198 printf("s = '%s', kind = '%s'\n", s
->toChars(), s
->kind());
5202 else if (ident
== Id::stringof
)
5203 { char *s
= ie
->toChars();
5204 e
= new StringExp(loc
, s
, strlen(s
), 'c');
5205 e
= e
->semantic(sc
);
5208 error("undefined identifier %s", toChars());
5212 else if (e1
->type
->ty
== Tpointer
&&
5213 ident
!= Id::init
&& ident
!= Id::__sizeof
&&
5214 ident
!= Id::alignof
&& ident
!= Id::offsetof
&&
5215 ident
!= Id::mangleof
&& ident
!= Id::stringof
)
5217 e
= new PtrExp(loc
, e1
);
5218 e
->type
= ((TypePointer
*)e1
->type
)->next
;
5219 return e
->type
->dotExp(sc
, e
, ident
);
5223 e
= e1
->type
->dotExp(sc
, e1
, ident
);
5224 e
= e
->semantic(sc
);
5229 void DotIdExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5231 //printf("DotIdExp::toCBuffer()\n");
5232 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5233 buf
->writeByte('.');
5234 buf
->writestring(ident
->toChars());
5237 /********************** DotTemplateExp ***********************************/
5239 // Mainly just a placeholder
5241 DotTemplateExp::DotTemplateExp(Loc loc
, Expression
*e
, TemplateDeclaration
*td
)
5242 : UnaExp(loc
, TOKdottd
, sizeof(DotTemplateExp
), e
)
5248 void DotTemplateExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5250 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5251 buf
->writeByte('.');
5252 buf
->writestring(td
->toChars());
5256 /************************************************************/
5258 DotVarExp::DotVarExp(Loc loc
, Expression
*e
, Declaration
*v
, int hasOverloads
)
5259 : UnaExp(loc
, TOKdotvar
, sizeof(DotVarExp
), e
)
5261 //printf("DotVarExp()\n");
5263 this->hasOverloads
= hasOverloads
;
5266 Expression
*DotVarExp::semantic(Scope
*sc
)
5269 printf("DotVarExp::semantic('%s')\n", toChars());
5273 var
= var
->toAlias()->isDeclaration();
5275 TupleDeclaration
*tup
= var
->isTupleDeclaration();
5280 * tuple(e1.a, e1.b, e1.c)
5282 Expressions
*exps
= new Expressions
;
5284 exps
->reserve(tup
->objects
->dim
);
5285 for (size_t i
= 0; i
< tup
->objects
->dim
; i
++)
5286 { Object
*o
= (Object
*)tup
->objects
->data
[i
];
5287 if (o
->dyncast() != DYNCAST_EXPRESSION
)
5289 error("%s is not an expression", o
->toChars());
5293 Expression
*e
= (Expression
*)o
;
5294 if (e
->op
!= TOKdsymbol
)
5295 error("%s is not a member", e
->toChars());
5297 { DsymbolExp
*ve
= (DsymbolExp
*)e
;
5299 e
= new DotVarExp(loc
, e1
, ve
->s
->isDeclaration());
5304 Expression
*e
= new TupleExp(loc
, exps
);
5305 e
= e
->semantic(sc
);
5309 e1
= e1
->semantic(sc
);
5312 if (!type
&& global
.errors
)
5313 { // var is goofed up, just return 0
5314 return new IntegerExp(0);
5318 if (!var
->isFuncDeclaration()) // for functions, do checks after overload resolution
5320 Type
*t1
= e1
->type
;
5321 if (t1
->ty
== Tpointer
)
5324 type
= type
->constOf();
5325 else if (t1
->isInvariant())
5326 type
= type
->invariantOf();
5328 AggregateDeclaration
*ad
= var
->toParent()->isAggregateDeclaration();
5329 e1
= getRightThis(loc
, sc
, ad
, e1
, var
);
5330 if (!sc
->noaccesscheck
)
5331 accessCheck(loc
, sc
, e1
, var
);
5334 //printf("-DotVarExp::semantic('%s')\n", toChars());
5338 Expression
*DotVarExp::toLvalue(Scope
*sc
, Expression
*e
)
5340 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5344 Expression
*DotVarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5347 printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
5348 printf("e1->type = %s\n", e1
->type
->toChars());
5349 printf("var->type = %s\n", var
->type
->toChars());
5352 if (var
->isCtorinit())
5353 { // It's only modifiable if inside the right constructor
5354 Dsymbol
*s
= sc
->func
;
5357 FuncDeclaration
*fd
= NULL
;
5359 fd
= s
->isFuncDeclaration();
5361 ((fd
->isCtorDeclaration() && var
->storage_class
& STCfield
) ||
5362 (fd
->isStaticCtorDeclaration() && !(var
->storage_class
& STCfield
))) &&
5363 fd
->toParent() == var
->toParent() &&
5367 VarDeclaration
*v
= var
->isVarDeclaration();
5370 //printf("setting ctorinit\n");
5375 { s
= s
->toParent2();
5380 const char *p
= var
->isStatic() ? "static " : "";
5381 error("can only initialize %sconst member %s inside %sconstructor",
5382 p
, var
->toChars(), p
);
5390 Type
*t1
= e1
->type
->toBasetype();
5392 if (!t1
->isMutable() ||
5393 (t1
->ty
== Tpointer
&& !t1
->nextOf()->isMutable()) ||
5394 !var
->type
->isMutable() ||
5395 !var
->type
->isAssignable() ||
5396 var
->storage_class
& STCmanifest
5398 error("cannot modify const/invariant %s", toChars());
5403 void DotVarExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5405 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5406 buf
->writeByte('.');
5407 buf
->writestring(var
->toChars());
5410 /************************************************************/
5416 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc
, Expression
*e
, TemplateInstance
*ti
)
5417 : UnaExp(loc
, TOKdotti
, sizeof(DotTemplateInstanceExp
), e
)
5419 //printf("DotTemplateInstanceExp()\n");
5423 Expression
*DotTemplateInstanceExp::syntaxCopy()
5425 DotTemplateInstanceExp
*de
= new DotTemplateInstanceExp(loc
,
5427 (TemplateInstance
*)ti
->syntaxCopy(NULL
));
5431 Expression
*DotTemplateInstanceExp::semantic(Scope
*sc
)
5434 TemplateDeclaration
*td
;
5438 Expression
*eleft
= NULL
;
5442 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
5446 e1
= e1
->semantic(sc
);
5449 t1
= t1
->toBasetype();
5452 /* Extract the following from e1:
5453 * s: the symbol which ti should be a member of
5454 * eleft: if not NULL, it is the 'this' pointer for ti
5457 if (e1
->op
== TOKdotexp
)
5458 { DotExp
*de
= (DotExp
*)e1
;
5466 if (eright
->op
== TOKimport
)
5468 s
= ((ScopeExp
*)eright
)->sds
;
5470 else if (e1
->op
== TOKtype
)
5472 s
= t1
->isClassHandle();
5474 { if (t1
->ty
== Tstruct
)
5475 s
= ((TypeStruct
*)t1
)->sym
;
5480 else if (t1
&& (t1
->ty
== Tstruct
|| t1
->ty
== Tclass
))
5482 s
= t1
->toDsymbol(sc
);
5485 else if (t1
&& t1
->ty
== Tpointer
)
5487 t1
= ((TypePointer
*)t1
)->next
->toBasetype();
5488 if (t1
->ty
!= Tstruct
)
5490 s
= t1
->toDsymbol(sc
);
5496 error("template %s is not a member of %s", ti
->toChars(), e1
->toChars());
5502 s2
= s
->search(loc
, id
, 0);
5504 { error("template identifier %s is not a member of %s %s", id
->toChars(), s
->kind(), s
->ident
->toChars());
5510 td
= s
->isTemplateDeclaration();
5513 error("%s is not a template", id
->toChars());
5525 s
= ti
->inst
->toAlias();
5526 v
= s
->isDeclaration();
5528 { e
= new DotVarExp(loc
, eleft
, v
);
5529 e
= e
->semantic(sc
);
5534 e
= new ScopeExp(loc
, ti
);
5537 e
= new DotExp(loc
, eleft
, e
);
5539 e
= e
->semantic(sc
);
5543 return new IntegerExp(0);
5546 void DotTemplateInstanceExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5548 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5549 buf
->writeByte('.');
5550 ti
->toCBuffer(buf
, hgs
);
5553 /************************************************************/
5555 DelegateExp::DelegateExp(Loc loc
, Expression
*e
, FuncDeclaration
*f
, int hasOverloads
)
5556 : UnaExp(loc
, TOKdelegate
, sizeof(DelegateExp
), e
)
5559 this->hasOverloads
= hasOverloads
;
5562 Expression
*DelegateExp::semantic(Scope
*sc
)
5565 printf("DelegateExp::semantic('%s')\n", toChars());
5569 e1
= e1
->semantic(sc
);
5570 type
= new TypeDelegate(func
->type
);
5571 type
= type
->semantic(loc
, sc
);
5572 AggregateDeclaration
*ad
= func
->toParent()->isAggregateDeclaration();
5573 if (func
->needThis())
5574 e1
= getRightThis(loc
, sc
, ad
, e1
, func
);
5579 void DelegateExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5581 buf
->writeByte('&');
5582 if (!func
->isNested())
5584 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5585 buf
->writeByte('.');
5587 buf
->writestring(func
->toChars());
5590 /************************************************************/
5592 DotTypeExp::DotTypeExp(Loc loc
, Expression
*e
, Dsymbol
*s
)
5593 : UnaExp(loc
, TOKdottype
, sizeof(DotTypeExp
), e
)
5596 this->type
= s
->getType();
5599 Expression
*DotTypeExp::semantic(Scope
*sc
)
5602 printf("DotTypeExp::semantic('%s')\n", toChars());
5604 UnaExp::semantic(sc
);
5608 void DotTypeExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5610 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5611 buf
->writeByte('.');
5612 buf
->writestring(sym
->toChars());
5615 /************************************************************/
5617 CallExp::CallExp(Loc loc
, Expression
*e
, Expressions
*exps
)
5618 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5620 this->arguments
= exps
;
5623 CallExp::CallExp(Loc loc
, Expression
*e
)
5624 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5626 this->arguments
= NULL
;
5629 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
)
5630 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5632 Expressions
*arguments
= new Expressions();
5633 arguments
->setDim(1);
5634 arguments
->data
[0] = (void *)earg1
;
5636 this->arguments
= arguments
;
5639 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
, Expression
*earg2
)
5640 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5642 Expressions
*arguments
= new Expressions();
5643 arguments
->setDim(2);
5644 arguments
->data
[0] = (void *)earg1
;
5645 arguments
->data
[1] = (void *)earg2
;
5647 this->arguments
= arguments
;
5650 Expression
*CallExp::syntaxCopy()
5652 return new CallExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
5656 Expression
*CallExp::semantic(Scope
*sc
)
5663 Objects
*targsi
= NULL
; // initial list of template arguments
5666 printf("CallExp::semantic() %s\n", toChars());
5670 return this; // semantic() already run
5672 if (arguments
&& arguments
->dim
)
5674 Expression
*earg
= (Expression
*)arguments
->data
[0];
5676 if (earg
->type
) earg
->type
->print();
5680 if (e1
->op
== TOKdelegate
)
5681 { DelegateExp
*de
= (DelegateExp
*)e1
;
5683 e1
= new DotVarExp(de
->loc
, de
->e1
, de
->func
);
5684 return semantic(sc
);
5688 * array.id(args) into id(array,args)
5689 * aa.remove(arg) into delete aa[arg]
5691 if (e1
->op
== TOKdot
)
5693 // BUG: we should handle array.a.b.c.e(args) too
5695 DotIdExp
*dotid
= (DotIdExp
*)(e1
);
5696 dotid
->e1
= dotid
->e1
->semantic(sc
);
5698 if (dotid
->e1
->type
)
5700 TY e1ty
= dotid
->e1
->type
->toBasetype()->ty
;
5701 if (e1ty
== Taarray
&& dotid
->ident
== Id::remove
)
5703 if (!arguments
|| arguments
->dim
!= 1)
5704 { error("expected key as argument to aa.remove()");
5707 Expression
*key
= (Expression
*)arguments
->data
[0];
5708 key
= key
->semantic(sc
);
5709 key
= resolveProperties(sc
, key
);
5712 TypeAArray
*taa
= (TypeAArray
*)dotid
->e1
->type
->toBasetype();
5713 key
= key
->implicitCastTo(sc
, taa
->index
);
5715 return new RemoveExp(loc
, dotid
->e1
, key
);
5717 else if (e1ty
== Tarray
|| e1ty
== Tsarray
|| e1ty
== Taarray
)
5720 arguments
= new Expressions();
5721 arguments
->shift(dotid
->e1
);
5722 e1
= new IdentifierExp(dotid
->loc
, dotid
->ident
);
5728 * foo!(tiargs)(funcargs)
5730 if (e1
->op
== TOKimport
&& !e1
->type
)
5731 { ScopeExp
*se
= (ScopeExp
*)e1
;
5732 TemplateInstance
*ti
= se
->sds
->isTemplateInstance();
5733 if (ti
&& !ti
->semanticdone
)
5735 /* Attempt to instantiate ti. If that works, go with it.
5736 * If not, go with partial explicit specialization.
5738 unsigned errors
= global
.errors
;
5742 if (errors
!= global
.errors
)
5744 global
.errors
= errors
;
5745 targsi
= ti
->tiargs
;
5746 e1
= new IdentifierExp(loc
, ti
->name
);
5752 * expr.foo!(tiargs)(funcargs)
5754 if (e1
->op
== TOKdotti
&& !e1
->type
)
5755 { DotTemplateInstanceExp
*se
= (DotTemplateInstanceExp
*)e1
;
5756 TemplateInstance
*ti
= se
->ti
;
5757 if (!ti
->semanticdone
)
5759 /* Attempt to instantiate ti. If that works, go with it.
5760 * If not, go with partial explicit specialization.
5763 unsigned errors
= global
.errors
;
5765 etmp
= e1
->semantic(sc
);
5767 if (errors
!= global
.errors
)
5769 global
.errors
= errors
;
5770 targsi
= ti
->tiargs
;
5771 e1
= new DotIdExp(loc
, se
->e1
, ti
->name
);
5780 //printf("Lagain: %s\n", toChars());
5782 if (e1
->op
== TOKthis
|| e1
->op
== TOKsuper
)
5784 // semantic() run later for these
5788 UnaExp::semantic(sc
);
5790 /* Look for e1 being a lazy parameter
5792 if (e1
->op
== TOKvar
)
5793 { VarExp
*ve
= (VarExp
*)e1
;
5795 if (ve
->var
->storage_class
& STClazy
)
5797 TypeFunction
*tf
= new TypeFunction(NULL
, ve
->var
->type
, 0, LINKd
);
5798 TypeDelegate
*t
= new TypeDelegate(tf
);
5799 ve
->type
= t
->semantic(loc
, sc
);
5803 if (e1
->op
== TOKimport
)
5804 { // Perhaps this should be moved to ScopeExp::semantic()
5805 ScopeExp
*se
= (ScopeExp
*)e1
;
5806 e1
= new DsymbolExp(loc
, se
->sds
);
5807 e1
= e1
->semantic(sc
);
5809 #if 1 // patch for #540 by Oskar Linde
5810 else if (e1
->op
== TOKdotexp
)
5812 DotExp
*de
= (DotExp
*) e1
;
5814 if (de
->e2
->op
== TOKimport
)
5815 { // This should *really* be moved to ScopeExp::semantic()
5816 ScopeExp
*se
= (ScopeExp
*)de
->e2
;
5817 de
->e2
= new DsymbolExp(loc
, se
->sds
);
5818 de
->e2
= de
->e2
->semantic(sc
);
5821 if (de
->e2
->op
== TOKtemplate
)
5822 { TemplateExp
*te
= (TemplateExp
*) de
->e2
;
5823 e1
= new DotTemplateExp(loc
,de
->e1
,te
->td
);
5829 if (e1
->op
== TOKcomma
)
5831 CommaExp
*ce
= (CommaExp
*)e1
;
5834 e1
->type
= ce
->type
;
5837 return ce
->semantic(sc
);
5842 t1
= e1
->type
->toBasetype();
5844 // Check for call operator overload
5846 { AggregateDeclaration
*ad
;
5848 if (t1
->ty
== Tstruct
)
5850 ad
= ((TypeStruct
*)t1
)->sym
;
5851 if (search_function(ad
, Id::call
))
5852 goto L1
; // overload of opCall, therefore it's a call
5854 if (e1
->op
!= TOKtype
)
5855 error("%s %s does not overload ()", ad
->kind(), ad
->toChars());
5856 /* It's a struct literal
5858 Expression
*e
= new StructLiteralExp(loc
, (StructDeclaration
*)ad
, arguments
);
5859 e
= e
->semantic(sc
);
5860 e
->type
= e1
->type
; // in case e1->type was a typedef
5863 else if (t1
->ty
== Tclass
)
5865 ad
= ((TypeClass
*)t1
)->sym
;
5868 // Rewrite as e1.call(arguments)
5869 Expression
*e
= new DotIdExp(loc
, e1
, Id::call
);
5870 e
= new CallExp(loc
, e
, arguments
);
5871 e
= e
->semantic(sc
);
5876 arrayExpressionSemantic(arguments
, sc
);
5877 preFunctionArguments(loc
, sc
, arguments
);
5879 if (e1
->op
== TOKdotvar
&& t1
->ty
== Tfunction
||
5883 DotTemplateExp
*dte
;
5884 AggregateDeclaration
*ad
;
5885 UnaExp
*ue
= (UnaExp
*)(e1
);
5887 if (e1
->op
== TOKdotvar
)
5888 { // Do overload resolution
5889 dve
= (DotVarExp
*)(e1
);
5891 f
= dve
->var
->isFuncDeclaration();
5893 f
= f
->overloadResolve(loc
, ue
->e1
, arguments
);
5895 ad
= f
->toParent()->isAggregateDeclaration();
5898 { dte
= (DotTemplateExp
*)(e1
);
5899 TemplateDeclaration
*td
= dte
->td
;
5902 // Should fix deduceFunctionTemplate() so it works on NULL argument
5903 arguments
= new Expressions();
5904 f
= td
->deduceFunctionTemplate(sc
, loc
, targsi
, ue
->e1
, arguments
);
5906 { type
= Type::terror
;
5909 ad
= td
->toParent()->isAggregateDeclaration();
5912 ue
->e1
= getRightThis(loc
, sc
, ad
, ue
->e1
, f
);
5914 checkDeprecated(sc
, f
);
5915 accessCheck(loc
, sc
, ue
->e1
, f
);
5918 VarExp
*ve
= new VarExp(loc
, f
);
5919 e1
= new CommaExp(loc
, ue
->e1
, ve
);
5924 if (e1
->op
== TOKdotvar
)
5927 e1
= new DotVarExp(loc
, dte
->e1
, f
);
5930 printf("ue->e1 = %s\n", ue
->e1
->toChars());
5931 printf("f = %s\n", f
->toChars());
5932 printf("t = %s\n", t
->toChars());
5933 printf("e1 = %s\n", e1
->toChars());
5934 printf("e1->type = %s\n", e1
->type
->toChars());
5936 // Const member function can take const/invariant/mutable this
5937 if (!(f
->type
->isConst()))
5939 // Check for const/invariant compatibility
5940 Type
*tthis
= ue
->e1
->type
->toBasetype();
5941 if (tthis
->ty
== Tpointer
)
5942 tthis
= tthis
->nextOf()->toBasetype();
5943 if (f
->type
->isInvariant())
5945 if (tthis
->mod
!= MODinvariant
)
5946 error("%s can only be called on an invariant object", e1
->toChars());
5950 if (tthis
->mod
!= 0)
5951 { //printf("mod = %x\n", tthis->mod);
5952 error("%s can only be called on a mutable object, not %s", e1
->toChars(), tthis
->toChars());
5956 /* Cannot call mutable method on a final struct
5958 if (tthis
->ty
== Tstruct
&&
5959 ue
->e1
->op
== TOKvar
)
5960 { VarExp
*v
= (VarExp
*)ue
->e1
;
5961 if (v
->var
->storage_class
& STCfinal
)
5962 error("cannot call mutable method on final struct");
5966 // See if we need to adjust the 'this' pointer
5967 AggregateDeclaration
*ad
= f
->isThis();
5968 ClassDeclaration
*cd
= ue
->e1
->type
->isClassHandle();
5969 if (ad
&& cd
&& ad
->isClassDeclaration() && ad
!= cd
&&
5970 ue
->e1
->op
!= TOKsuper
)
5972 ue
->e1
= ue
->e1
->castTo(sc
, ad
->type
); //new CastExp(loc, ue->e1, ad->type);
5973 ue
->e1
= ue
->e1
->semantic(sc
);
5978 else if (e1
->op
== TOKsuper
)
5980 // Base class constructor call
5981 ClassDeclaration
*cd
= NULL
;
5984 cd
= sc
->func
->toParent()->isClassDeclaration();
5985 if (!cd
|| !cd
->baseClass
|| !sc
->func
->isCtorDeclaration())
5987 error("super class constructor call must be in a constructor");
5988 type
= Type::terror
;
5993 f
= cd
->baseClass
->ctor
;
5995 { error("no super class constructor for %s", cd
->baseClass
->toChars());
5996 type
= Type::terror
;
6002 if (sc
->callSuper
& (CSXthis
| CSXsuper
))
6003 error("reference to this before super()");
6005 if (sc
->noctor
|| sc
->callSuper
& CSXlabel
)
6006 error("constructor calls not allowed in loops or after labels");
6007 if (sc
->callSuper
& (CSXsuper_ctor
| CSXthis_ctor
))
6008 error("multiple constructor calls");
6009 sc
->callSuper
|= CSXany_ctor
| CSXsuper_ctor
;
6011 f
= f
->overloadResolve(loc
, NULL
, arguments
);
6012 checkDeprecated(sc
, f
);
6013 e1
= new DotVarExp(e1
->loc
, e1
, f
);
6014 e1
= e1
->semantic(sc
);
6019 else if (e1
->op
== TOKthis
)
6021 // same class constructor call
6022 ClassDeclaration
*cd
= NULL
;
6025 cd
= sc
->func
->toParent()->isClassDeclaration();
6026 if (!cd
|| !sc
->func
->isCtorDeclaration())
6028 error("class constructor call must be in a constructor");
6029 type
= Type::terror
;
6035 if (sc
->callSuper
& (CSXthis
| CSXsuper
))
6036 error("reference to this before super()");
6038 if (sc
->noctor
|| sc
->callSuper
& CSXlabel
)
6039 error("constructor calls not allowed in loops or after labels");
6040 if (sc
->callSuper
& (CSXsuper_ctor
| CSXthis_ctor
))
6041 error("multiple constructor calls");
6042 sc
->callSuper
|= CSXany_ctor
| CSXthis_ctor
;
6045 f
= f
->overloadResolve(loc
, NULL
, arguments
);
6046 checkDeprecated(sc
, f
);
6047 e1
= new DotVarExp(e1
->loc
, e1
, f
);
6048 e1
= e1
->semantic(sc
);
6051 // BUG: this should really be done by checking the static
6054 error("cyclic constructor call");
6057 else if (e1
->op
== TOKoverloadset
)
6059 OverExp
*eo
= (OverExp
*)e1
;
6060 FuncDeclaration
*f
= NULL
;
6061 for (int i
= 0; i
< eo
->vars
->a
.dim
; i
++)
6062 { Dsymbol
*s
= (Dsymbol
*)eo
->vars
->a
.data
[i
];
6063 FuncDeclaration
*f2
= s
->isFuncDeclaration();
6066 f2
= f2
->overloadResolve(loc
, NULL
, arguments
, 1);
6069 { TemplateDeclaration
*td
= s
->isTemplateDeclaration();
6071 f2
= td
->deduceFunctionTemplate(sc
, loc
, targsi
, NULL
, arguments
, 1);
6075 /* Error if match in more than one overload set,
6076 * even if one is a 'better' match than the other.
6078 ScopeDsymbol::multiplyDefined(loc
, f
, f2
);
6084 { /* No overload matches, just set f and rely on error
6085 * message being generated later.
6087 f
= (FuncDeclaration
*)eo
->vars
->a
.data
[0];
6089 e1
= new VarExp(loc
, f
);
6094 error("function expected before (), not '%s'", e1
->toChars());
6095 type
= Type::terror
;
6098 else if (t1
->ty
!= Tfunction
)
6100 if (t1
->ty
== Tdelegate
)
6101 { TypeDelegate
*td
= (TypeDelegate
*)t1
;
6102 assert(td
->next
->ty
== Tfunction
);
6103 tf
= (TypeFunction
*)(td
->next
);
6106 else if (t1
->ty
== Tpointer
&& ((TypePointer
*)t1
)->next
->ty
== Tfunction
)
6109 e
= new PtrExp(loc
, e1
);
6110 t1
= ((TypePointer
*)t1
)->next
;
6114 else if (e1
->op
== TOKtemplate
)
6116 TemplateExp
*te
= (TemplateExp
*)e1
;
6117 f
= te
->td
->deduceFunctionTemplate(sc
, loc
, targsi
, NULL
, arguments
);
6119 { type
= Type::terror
;
6122 if (f
->needThis() && hasThis(sc
))
6124 // Supply an implicit 'this', as in
6127 e1
= new DotTemplateExp(loc
, (new ThisExp(loc
))->semantic(sc
), te
->td
);
6131 e1
= new VarExp(loc
, f
);
6135 { error("function expected before (), not %s of type %s", e1
->toChars(), e1
->type
->toChars());
6136 type
= Type::terror
;
6140 else if (e1
->op
== TOKvar
)
6142 // Do overload resolution
6143 VarExp
*ve
= (VarExp
*)e1
;
6145 f
= ve
->var
->isFuncDeclaration();
6148 if (ve
->hasOverloads
)
6149 f
= f
->overloadResolve(loc
, NULL
, arguments
);
6150 checkDeprecated(sc
, f
);
6152 if (f
->needThis() && hasThis(sc
))
6154 // Supply an implicit 'this', as in
6157 e1
= new DotVarExp(loc
, new ThisExp(loc
), f
);
6161 accessCheck(loc
, sc
, NULL
, f
);
6164 // ve->hasOverloads = 0;
6168 assert(t1
->ty
== Tfunction
);
6169 tf
= (TypeFunction
*)(t1
);
6172 assert(tf
->ty
== Tfunction
);
6176 arguments
= new Expressions();
6177 functionArguments(loc
, sc
, tf
, arguments
);
6184 target_ptrdiff_t offset
= 0;
6185 TypeFunction
*tf
= (TypeFunction
*)f
->tintro
;
6187 if (tf
->next
->isBaseOf(t
, &offset
) && offset
)
6190 return castTo(sc
, t
);
6197 int CallExp::checkSideEffect(int flag
)
6202 int CallExp::canThrow()
6207 Expression
*CallExp::toLvalue(Scope
*sc
, Expression
*e
)
6209 if (type
->toBasetype()->ty
== Tstruct
)
6212 return Expression::toLvalue(sc
, e
);
6215 void CallExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6218 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6219 buf
->writeByte('(');
6220 argsToCBuffer(buf
, arguments
, hgs
);
6221 buf
->writeByte(')');
6225 /************************************************************/
6227 AddrExp::AddrExp(Loc loc
, Expression
*e
)
6228 : UnaExp(loc
, TOKaddress
, sizeof(AddrExp
), e
)
6232 Expression
*AddrExp::semantic(Scope
*sc
)
6235 printf("AddrExp::semantic('%s')\n", toChars());
6239 UnaExp::semantic(sc
);
6240 e1
= e1
->toLvalue(sc
, NULL
);
6243 error("cannot take address of %s", e1
->toChars());
6244 type
= Type::tint32
;
6247 type
= e1
->type
->pointerTo();
6249 // See if this should really be a delegate
6250 if (e1
->op
== TOKdotvar
)
6252 DotVarExp
*dve
= (DotVarExp
*)e1
;
6254 FuncDeclaration
*f
= dve
->var
->isFuncDeclaration();
6258 if (!dve
->hasOverloads
)
6259 f
->tookAddressOf
= 1;
6260 Expression
*e
= new DelegateExp(loc
, dve
->e1
, f
, dve
->hasOverloads
);
6261 e
= e
->semantic(sc
);
6265 else if (e1
->op
== TOKvar
)
6267 VarExp
*ve
= (VarExp
*)e1
;
6269 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
6270 if (v
&& !v
->canTakeAddressOf())
6271 error("cannot take address of %s", e1
->toChars());
6273 FuncDeclaration
*f
= ve
->var
->isFuncDeclaration();
6277 if (!ve
->hasOverloads
)
6278 f
->tookAddressOf
= 1;
6281 Expression
*e
= new DelegateExp(loc
, e1
, f
, ve
->hasOverloads
);
6282 e
= e
->semantic(sc
);
6285 if (f
->needThis() && hasThis(sc
))
6287 /* Should probably supply 'this' after overload resolution,
6290 Expression
*ethis
= new ThisExp(loc
);
6291 Expression
*e
= new DelegateExp(loc
, ethis
, f
, ve
->hasOverloads
);
6292 e
= e
->semantic(sc
);
6297 return optimize(WANTvalue
);
6302 /************************************************************/
6304 PtrExp::PtrExp(Loc loc
, Expression
*e
)
6305 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
6308 type
= ((TypePointer
*)e
->type
)->next
;
6311 PtrExp::PtrExp(Loc loc
, Expression
*e
, Type
*t
)
6312 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
6317 Expression
*PtrExp::semantic(Scope
*sc
)
6321 printf("PtrExp::semantic('%s')\n", toChars());
6325 UnaExp::semantic(sc
);
6326 e1
= resolveProperties(sc
, e1
);
6328 printf("PtrExp::semantic('%s')\n", toChars());
6329 Expression
*e
= op_overload(sc
);
6332 tb
= e1
->type
->toBasetype();
6336 type
= ((TypePointer
*)tb
)->next
;
6341 type
= ((TypeArray
*)tb
)->next
;
6342 e1
= e1
->castTo(sc
, type
->pointerTo());
6346 error("can only * a pointer, not a '%s'", e1
->type
->toChars());
6347 type
= Type::tint32
;
6355 Expression
*PtrExp::toLvalue(Scope
*sc
, Expression
*e
)
6358 tym
= tybasic(e1
->ET
->Tty
);
6359 if (!(tyscalar(tym
) ||
6361 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
6362 synerr(EM_lvalue
); // lvalue expected
6367 Expression
*PtrExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6369 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
6371 if (e1
->op
== TOKsymoff
)
6372 { SymOffExp
*se
= (SymOffExp
*)e1
;
6373 se
->var
->checkModify(loc
, sc
, type
);
6374 //return toLvalue(sc, e);
6377 return Expression::modifiableLvalue(sc
, e
);
6381 void PtrExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6383 buf
->writeByte('*');
6384 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6387 /************************************************************/
6389 NegExp::NegExp(Loc loc
, Expression
*e
)
6390 : UnaExp(loc
, TOKneg
, sizeof(NegExp
), e
)
6394 Expression
*NegExp::semantic(Scope
*sc
)
6398 printf("NegExp::semantic('%s')\n", toChars());
6402 UnaExp::semantic(sc
);
6403 e1
= resolveProperties(sc
, e1
);
6404 e
= op_overload(sc
);
6409 e1
->checkArithmetic();
6415 /************************************************************/
6417 UAddExp::UAddExp(Loc loc
, Expression
*e
)
6418 : UnaExp(loc
, TOKuadd
, sizeof(UAddExp
), e
)
6422 Expression
*UAddExp::semantic(Scope
*sc
)
6426 printf("UAddExp::semantic('%s')\n", toChars());
6429 UnaExp::semantic(sc
);
6430 e1
= resolveProperties(sc
, e1
);
6431 e
= op_overload(sc
);
6435 e1
->checkArithmetic();
6439 /************************************************************/
6441 ComExp::ComExp(Loc loc
, Expression
*e
)
6442 : UnaExp(loc
, TOKtilde
, sizeof(ComExp
), e
)
6446 Expression
*ComExp::semantic(Scope
*sc
)
6451 UnaExp::semantic(sc
);
6452 e1
= resolveProperties(sc
, e1
);
6453 e
= op_overload(sc
);
6458 e1
= e1
->checkIntegral();
6464 /************************************************************/
6466 NotExp::NotExp(Loc loc
, Expression
*e
)
6467 : UnaExp(loc
, TOKnot
, sizeof(NotExp
), e
)
6471 Expression
*NotExp::semantic(Scope
*sc
)
6473 UnaExp::semantic(sc
);
6474 e1
= resolveProperties(sc
, e1
);
6475 e1
= e1
->checkToBoolean();
6476 type
= Type::tboolean
;
6487 /************************************************************/
6489 BoolExp::BoolExp(Loc loc
, Expression
*e
, Type
*t
)
6490 : UnaExp(loc
, TOKtobool
, sizeof(BoolExp
), e
)
6495 Expression
*BoolExp::semantic(Scope
*sc
)
6497 UnaExp::semantic(sc
);
6498 e1
= resolveProperties(sc
, e1
);
6499 e1
= e1
->checkToBoolean();
6500 type
= Type::tboolean
;
6504 int BoolExp::isBit()
6509 /************************************************************/
6511 DeleteExp::DeleteExp(Loc loc
, Expression
*e
)
6512 : UnaExp(loc
, TOKdelete
, sizeof(DeleteExp
), e
)
6516 Expression
*DeleteExp::semantic(Scope
*sc
)
6520 UnaExp::semantic(sc
);
6521 e1
= resolveProperties(sc
, e1
);
6522 e1
= e1
->toLvalue(sc
, NULL
);
6525 tb
= e1
->type
->toBasetype();
6528 { TypeClass
*tc
= (TypeClass
*)tb
;
6529 ClassDeclaration
*cd
= tc
->sym
;
6531 if (cd
->isCOMinterface())
6532 { /* Because COM classes are deleted by IUnknown.Release()
6534 error("cannot delete instance of COM interface %s", cd
->toChars());
6539 tb
= ((TypePointer
*)tb
)->next
->toBasetype();
6540 if (tb
->ty
== Tstruct
)
6542 TypeStruct
*ts
= (TypeStruct
*)tb
;
6543 StructDeclaration
*sd
= ts
->sym
;
6544 FuncDeclaration
*f
= sd
->aggDelete
;
6545 FuncDeclaration
*fd
= sd
->dtor
;
6551 * ea = copy e1 to a tmp to do side effects only once
6552 * eb = call destructor
6553 * ec = call deallocator
6555 Expression
*ea
= NULL
;
6556 Expression
*eb
= NULL
;
6557 Expression
*ec
= NULL
;
6561 { Identifier
*id
= Lexer::idPool("__tmp");
6562 v
= new VarDeclaration(loc
, e1
->type
, id
, new ExpInitializer(loc
, e1
));
6564 v
->parent
= sc
->parent
;
6565 ea
= new DeclarationExp(loc
, v
);
6570 { Expression
*e
= ea
? new VarExp(loc
, v
) : e1
;
6571 e
= new DotVarExp(0, e
, fd
, 0);
6572 eb
= new CallExp(loc
, e
);
6573 eb
= eb
->semantic(sc
);
6578 Type
*tpv
= Type::tvoid
->pointerTo();
6579 Expression
*e
= ea
? new VarExp(loc
, v
) : e1
->castTo(sc
, tpv
);
6580 e
= new CallExp(loc
, new VarExp(loc
, f
), e
);
6581 ec
= e
->semantic(sc
);
6583 ea
= combine(ea
, eb
);
6584 ea
= combine(ea
, ec
);
6591 /* BUG: look for deleting arrays of structs with dtors.
6596 if (e1
->op
== TOKindex
)
6598 IndexExp
*ae
= (IndexExp
*)(e1
);
6599 Type
*tb1
= ae
->e1
->type
->toBasetype();
6600 if (tb1
->ty
== Taarray
)
6603 error("cannot delete type %s", e1
->type
->toChars());
6607 if (e1
->op
== TOKindex
)
6609 IndexExp
*ae
= (IndexExp
*)(e1
);
6610 Type
*tb1
= ae
->e1
->type
->toBasetype();
6611 if (tb1
->ty
== Taarray
)
6612 { if (!global
.params
.useDeprecated
)
6613 error("delete aa[key] deprecated, use aa.remove(key)");
6620 int DeleteExp::checkSideEffect(int flag
)
6625 Expression
*DeleteExp::checkToBoolean()
6627 error("delete does not give a boolean result");
6631 void DeleteExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6633 buf
->writestring("delete ");
6634 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6637 /************************************************************/
6639 CastExp::CastExp(Loc loc
, Expression
*e
, Type
*t
)
6640 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
6643 this->tok
= TOKreserved
;
6646 /* For cast(const) and cast(invariant)
6648 CastExp::CastExp(Loc loc
, Expression
*e
, enum TOK tok
)
6649 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
6655 Expression
*CastExp::syntaxCopy()
6657 return to
? new CastExp(loc
, e1
->syntaxCopy(), to
->syntaxCopy())
6658 : new CastExp(loc
, e1
->syntaxCopy(), tok
);
6662 Expression
*CastExp::semantic(Scope
*sc
)
6668 printf("CastExp::semantic('%s')\n", toChars());
6671 //static int x; assert(++x < 10);
6675 UnaExp::semantic(sc
);
6676 if (e1
->type
) // if not a tuple
6678 e1
= resolveProperties(sc
, e1
);
6680 /* Handle cast(const) and cast(invariant)
6683 { if (tok
== TOKconst
)
6684 to
= e1
->type
->constOf();
6685 else if (tok
== TOKinvariant
)
6686 to
= e1
->type
->invariantOf();
6691 to
= to
->semantic(loc
, sc
);
6693 e
= op_overload(sc
);
6696 return e
->implicitCastTo(sc
, to
);
6699 Type
*tob
= to
->toBasetype();
6700 if (tob
->ty
== Tstruct
&&
6701 !tob
->equals(e1
->type
->toBasetype()) &&
6702 ((TypeStruct
*)to
)->sym
->search(0, Id::call
, 0)
6711 // Rewrite as to.call(e1)
6712 e
= new TypeExp(loc
, to
);
6713 e
= new DotIdExp(loc
, e
, Id::call
);
6714 e
= new CallExp(loc
, e
, e1
);
6715 e
= e
->semantic(sc
);
6720 { error("cannot cast tuple");
6723 e
= e1
->castTo(sc
, to
);
6727 int CastExp::checkSideEffect(int flag
)
6731 * cast(classtype)func()
6733 if (!to
->equals(Type::tvoid
) &&
6734 !(to
->ty
== Tclass
&& e1
->op
== TOKcall
&& e1
->type
->ty
== Tclass
))
6735 return Expression::checkSideEffect(flag
);
6739 void CastExp::checkEscape()
6740 { Type
*tb
= type
->toBasetype();
6741 if (tb
->ty
== Tarray
&& e1
->op
== TOKvar
&&
6742 e1
->type
->toBasetype()->ty
== Tsarray
)
6743 { VarExp
*ve
= (VarExp
*)e1
;
6744 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
6747 if (!v
->isDataseg() && !v
->isParameter())
6748 error("escaping reference to local %s", v
->toChars());
6753 void CastExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6755 buf
->writestring("cast(");
6757 to
->toCBuffer(buf
, NULL
, hgs
);
6759 buf
->writestring(Token::tochars
[tok
]);
6760 buf
->writeByte(')');
6761 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6765 /************************************************************/
6767 SliceExp::SliceExp(Loc loc
, Expression
*e1
, Expression
*lwr
, Expression
*upr
)
6768 : UnaExp(loc
, TOKslice
, sizeof(SliceExp
), e1
)
6775 Expression
*SliceExp::syntaxCopy()
6777 Expression
*lwr
= NULL
;
6779 lwr
= this->lwr
->syntaxCopy();
6781 Expression
*upr
= NULL
;
6783 upr
= this->upr
->syntaxCopy();
6785 return new SliceExp(loc
, e1
->syntaxCopy(), lwr
, upr
);
6788 Expression
*SliceExp::semantic(Scope
*sc
)
6790 AggregateDeclaration
*ad
;
6791 //FuncDeclaration *fd;
6795 printf("SliceExp::semantic('%s')\n", toChars());
6800 UnaExp::semantic(sc
);
6801 e1
= resolveProperties(sc
, e1
);
6805 Type
*t
= e1
->type
->toBasetype();
6806 if (t
->ty
== Tpointer
)
6809 error("need upper and lower bound to slice pointer");
6811 else if (t
->ty
== Tarray
)
6814 else if (t
->ty
== Tsarray
)
6817 else if (t
->ty
== Tclass
)
6819 ad
= ((TypeClass
*)t
)->sym
;
6822 else if (t
->ty
== Tstruct
)
6824 ad
= ((TypeStruct
*)t
)->sym
;
6827 if (search_function(ad
, Id::slice
))
6829 // Rewrite as e1.slice(lwr, upr)
6830 e
= new DotIdExp(loc
, e1
, Id::slice
);
6835 e
= new CallExp(loc
, e
, lwr
, upr
);
6839 e
= new CallExp(loc
, e
);
6841 e
= e
->semantic(sc
);
6846 else if (t
->ty
== Ttuple
)
6851 { error("need upper and lower bound to slice tuple");
6858 if (t
->ty
== Tsarray
|| t
->ty
== Tarray
|| t
->ty
== Ttuple
)
6860 sym
= new ArrayScopeSymbol(sc
, this);
6862 sym
->parent
= sc
->scopesym
;
6867 { lwr
= lwr
->semantic(sc
);
6868 lwr
= resolveProperties(sc
, lwr
);
6869 lwr
= lwr
->implicitCastTo(sc
, Type::tsize_t
);
6872 { upr
= upr
->semantic(sc
);
6873 upr
= resolveProperties(sc
, upr
);
6874 upr
= upr
->implicitCastTo(sc
, Type::tsize_t
);
6877 if (t
->ty
== Tsarray
|| t
->ty
== Tarray
|| t
->ty
== Ttuple
)
6880 if (t
->ty
== Ttuple
)
6882 lwr
= lwr
->optimize(WANTvalue
);
6883 upr
= upr
->optimize(WANTvalue
);
6884 uinteger_t i1
= lwr
->toUInteger();
6885 uinteger_t i2
= upr
->toUInteger();
6891 if (e1
->op
== TOKtuple
) // slicing an expression tuple
6892 { te
= (TupleExp
*)e1
;
6893 length
= te
->exps
->dim
;
6895 else if (e1
->op
== TOKtype
) // slicing a type tuple
6896 { tup
= (TypeTuple
*)t
;
6897 length
= Argument::dim(tup
->arguments
);
6902 if (i1
<= i2
&& i2
<= length
)
6903 { size_t j1
= (size_t) i1
;
6904 size_t j2
= (size_t) i2
;
6906 if (e1
->op
== TOKtuple
)
6907 { Expressions
*exps
= new Expressions
;
6908 exps
->setDim(j2
- j1
);
6909 for (size_t i
= 0; i
< j2
- j1
; i
++)
6910 { Expression
*e
= (Expression
*)te
->exps
->data
[j1
+ i
];
6911 exps
->data
[i
] = (void *)e
;
6913 e
= new TupleExp(loc
, exps
);
6916 { Arguments
*args
= new Arguments
;
6917 args
->reserve(j2
- j1
);
6918 for (size_t i
= j1
; i
< j2
; i
++)
6919 { Argument
*arg
= Argument::getNth(tup
->arguments
, i
);
6922 e
= new TypeExp(e1
->loc
, new TypeTuple(args
));
6924 e
= e
->semantic(sc
);
6928 error("string slice [%"PRIuMAX
" .. %"PRIuMAX
"] is out of bounds", i1
, i2
);
6934 type
= t
->nextOf()->arrayOf();
6943 error("%s cannot be sliced with []", s
);
6944 type
= Type::terror
;
6948 void SliceExp::checkEscape()
6953 Expression
*SliceExp::toLvalue(Scope
*sc
, Expression
*e
)
6958 Expression
*SliceExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6960 error("slice expression %s is not a modifiable lvalue", toChars());
6964 void SliceExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6966 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6967 buf
->writeByte('[');
6971 expToCBuffer(buf
, hgs
, lwr
, PREC_assign
);
6973 buf
->writeByte('0');
6974 buf
->writestring("..");
6976 expToCBuffer(buf
, hgs
, upr
, PREC_assign
);
6978 buf
->writestring("length"); // BUG: should be array.length
6980 buf
->writeByte(']');
6983 /********************** ArrayLength **************************************/
6985 ArrayLengthExp::ArrayLengthExp(Loc loc
, Expression
*e1
)
6986 : UnaExp(loc
, TOKarraylength
, sizeof(ArrayLengthExp
), e1
)
6990 Expression
*ArrayLengthExp::semantic(Scope
*sc
)
6994 printf("ArrayLengthExp::semantic('%s')\n", toChars());
6998 UnaExp::semantic(sc
);
6999 e1
= resolveProperties(sc
, e1
);
7001 type
= Type::tsize_t
;
7006 void ArrayLengthExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7008 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
7009 buf
->writestring(".length");
7012 /*********************** ArrayExp *************************************/
7014 // e1 [ i1, i2, i3, ... ]
7016 ArrayExp::ArrayExp(Loc loc
, Expression
*e1
, Expressions
*args
)
7017 : UnaExp(loc
, TOKarray
, sizeof(ArrayExp
), e1
)
7022 Expression
*ArrayExp::syntaxCopy()
7024 return new ArrayExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
7027 Expression
*ArrayExp::semantic(Scope
*sc
)
7032 printf("ArrayExp::semantic('%s')\n", toChars());
7034 UnaExp::semantic(sc
);
7035 e1
= resolveProperties(sc
, e1
);
7037 t1
= e1
->type
->toBasetype();
7038 if (t1
->ty
!= Tclass
&& t1
->ty
!= Tstruct
)
7039 { // Convert to IndexExp
7040 if (arguments
->dim
!= 1)
7041 error("only one index allowed to index %s", t1
->toChars());
7042 e
= new IndexExp(loc
, e1
, (Expression
*)arguments
->data
[0]);
7043 return e
->semantic(sc
);
7046 // Run semantic() on each argument
7047 for (size_t i
= 0; i
< arguments
->dim
; i
++)
7048 { e
= (Expression
*)arguments
->data
[i
];
7050 e
= e
->semantic(sc
);
7052 error("%s has no value", e
->toChars());
7053 arguments
->data
[i
] = (void *)e
;
7056 expandTuples(arguments
);
7057 assert(arguments
&& arguments
->dim
);
7059 e
= op_overload(sc
);
7061 { error("no [] operator overload for type %s", e1
->type
->toChars());
7068 Expression
*ArrayExp::toLvalue(Scope
*sc
, Expression
*e
)
7070 if (type
&& type
->toBasetype()->ty
== Tvoid
)
7071 error("voids have no value");
7076 void ArrayExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7079 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
7080 buf
->writeByte('[');
7081 argsToCBuffer(buf
, arguments
, hgs
);
7082 buf
->writeByte(']');
7085 /************************* DotExp ***********************************/
7087 DotExp::DotExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7088 : BinExp(loc
, TOKdotexp
, sizeof(DotExp
), e1
, e2
)
7092 Expression
*DotExp::semantic(Scope
*sc
)
7095 printf("DotExp::semantic('%s')\n", toChars());
7096 if (type
) printf("\ttype = %s\n", type
->toChars());
7098 e1
= e1
->semantic(sc
);
7099 e2
= e2
->semantic(sc
);
7100 if (e2
->op
== TOKimport
)
7102 ScopeExp
*se
= (ScopeExp
*)e2
;
7103 TemplateDeclaration
*td
= se
->sds
->isTemplateDeclaration();
7105 { Expression
*e
= new DotTemplateExp(loc
, e1
, td
);
7106 e
= e
->semantic(sc
);
7116 /************************* CommaExp ***********************************/
7118 CommaExp::CommaExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7119 : BinExp(loc
, TOKcomma
, sizeof(CommaExp
), e1
, e2
)
7123 Expression
*CommaExp::semantic(Scope
*sc
)
7126 { BinExp::semanticp(sc
);
7132 void CommaExp::checkEscape()
7137 Expression
*CommaExp::toLvalue(Scope
*sc
, Expression
*e
)
7139 e2
= e2
->toLvalue(sc
, NULL
);
7143 Expression
*CommaExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
7145 e2
= e2
->modifiableLvalue(sc
, e
);
7149 int CommaExp::isBool(int result
)
7151 return e2
->isBool(result
);
7154 int CommaExp::checkSideEffect(int flag
)
7157 return e1
->checkSideEffect(2) || e2
->checkSideEffect(2);
7160 // Don't check e1 until we cast(void) the a,b code generation
7161 return e2
->checkSideEffect(flag
);
7165 /************************** IndexExp **********************************/
7169 IndexExp::IndexExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7170 : BinExp(loc
, TOKindex
, sizeof(IndexExp
), e1
, e2
)
7172 //printf("IndexExp::IndexExp('%s')\n", toChars());
7174 modifiable
= 0; // assume it is an rvalue
7177 Expression
*IndexExp::semantic(Scope
*sc
)
7185 printf("IndexExp::semantic('%s')\n", toChars());
7190 e1
= e1
->semantic(sc
);
7191 assert(e1
->type
); // semantic() should already be run on it
7194 // Note that unlike C we do not implement the int[ptr]
7196 t1
= e1
->type
->toBasetype();
7198 if (t1
->ty
== Tsarray
|| t1
->ty
== Tarray
|| t1
->ty
== Ttuple
)
7199 { // Create scope for 'length' variable
7200 sym
= new ArrayScopeSymbol(sc
, this);
7202 sym
->parent
= sc
->scopesym
;
7206 e2
= e2
->semantic(sc
);
7209 error("%s has no value", e2
->toChars());
7210 e2
->type
= Type::terror
;
7212 e2
= resolveProperties(sc
, e2
);
7214 if (t1
->ty
== Tsarray
|| t1
->ty
== Tarray
|| t1
->ty
== Ttuple
)
7221 e2
= e2
->implicitCastTo(sc
, Type::tsize_t
);
7222 e
->type
= ((TypeNext
*)t1
)->next
;
7227 e2
= e2
->implicitCastTo(sc
, Type::tsize_t
);
7229 TypeSArray
*tsa
= (TypeSArray
*)t1
;
7231 #if 0 // Don't do now, because it might be short-circuit evaluated
7232 // Do compile time array bounds checking if possible
7233 e2
= e2
->optimize(WANTvalue
);
7234 if (e2
->op
== TOKint64
)
7236 integer_t index
= e2
->toInteger();
7237 integer_t length
= tsa
->dim
->toInteger();
7238 if (index
< 0 || index
>= length
)
7239 error("array index [%lld] is outside array bounds [0 .. %lld]",
7243 e
->type
= t1
->nextOf();
7248 { TypeAArray
*taa
= (TypeAArray
*)t1
;
7250 e2
= e2
->implicitCastTo(sc
, taa
->index
); // type checking
7257 e2
= e2
->implicitCastTo(sc
, Type::tsize_t
);
7258 e2
= e2
->optimize(WANTvalue
| WANTinterpret
);
7259 uinteger_t index
= e2
->toUInteger();
7264 if (e1
->op
== TOKtuple
)
7265 { te
= (TupleExp
*)e1
;
7266 length
= te
->exps
->dim
;
7268 else if (e1
->op
== TOKtype
)
7270 tup
= (TypeTuple
*)t1
;
7271 length
= Argument::dim(tup
->arguments
);
7279 if (e1
->op
== TOKtuple
)
7280 e
= (Expression
*)te
->exps
->data
[(size_t)index
];
7282 e
= new TypeExp(e1
->loc
, Argument::getNth(tup
->arguments
, (size_t)index
)->type
);
7286 error("array index [%"PRIuMAX
"] is outside array bounds [0 .. %"PRIuSIZE
"]",
7294 error("%s must be an array or pointer type, not %s",
7295 e1
->toChars(), e1
->type
->toChars());
7296 type
= Type::tint32
;
7302 Expression
*IndexExp::toLvalue(Scope
*sc
, Expression
*e
)
7304 // if (type && type->toBasetype()->ty == Tvoid)
7305 // error("voids have no value");
7309 Expression
*IndexExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
7311 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
7313 if (e1
->op
== TOKstring
)
7314 error("string literals are immutable");
7315 if (type
&& !type
->isMutable())
7316 error("%s isn't mutable", e
->toChars());
7317 if (e1
->type
->toBasetype()->ty
== Taarray
)
7318 e1
= e1
->modifiableLvalue(sc
, e1
);
7319 return toLvalue(sc
, e
);
7322 void IndexExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7324 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
7325 buf
->writeByte('[');
7326 expToCBuffer(buf
, hgs
, e2
, PREC_assign
);
7327 buf
->writeByte(']');
7331 /************************* PostExp ***********************************/
7333 PostExp::PostExp(enum TOK op
, Loc loc
, Expression
*e
)
7334 : BinExp(loc
, op
, sizeof(PostExp
), e
,
7335 new IntegerExp(loc
, 1, Type::tint32
))
7339 Expression
*PostExp::semantic(Scope
*sc
)
7340 { Expression
*e
= this;
7344 BinExp::semantic(sc
);
7345 e2
= resolveProperties(sc
, e2
);
7347 e
= op_overload(sc
);
7352 e1
= e1
->modifiableLvalue(sc
, e1
);
7355 if (e1
->type
->ty
== Tpointer
)
7356 e
= scaleFactor(sc
);
7358 e2
= e2
->castTo(sc
, e1
->type
);
7364 void PostExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7366 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
7367 buf
->writestring((op
== TOKplusplus
) ? (char *)"++" : (char *)"--");
7370 /************************************************************/
7372 /* op can be TOKassign, TOKconstruct, or TOKblit */
7374 AssignExp::AssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7375 : BinExp(loc
, TOKassign
, sizeof(AssignExp
), e1
, e2
)
7380 Expression
*AssignExp::semantic(Scope
*sc
)
7382 Expression
*e1old
= e1
;
7385 printf("AssignExp::semantic('%s')\n", toChars());
7387 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
7388 //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
7393 if (e2
->op
== TOKcomma
)
7394 { /* Rewrite to get rid of the comma from rvalue
7396 AssignExp
*ea
= new AssignExp(loc
, e1
, ((CommaExp
*)e2
)->e2
);
7398 Expression
*e
= new CommaExp(loc
, ((CommaExp
*)e2
)->e1
, ea
);
7399 return e
->semantic(sc
);
7402 /* Look for operator overloading of a[i]=value.
7403 * Do it before semantic() otherwise the a[i] will have been
7404 * converted to a.opIndex() already.
7406 if (e1
->op
== TOKarray
)
7408 ArrayExp
*ae
= (ArrayExp
*)e1
;
7409 AggregateDeclaration
*ad
;
7410 Identifier
*id
= Id::index
;
7412 ae
->e1
= ae
->e1
->semantic(sc
);
7413 Type
*t1
= ae
->e1
->type
->toBasetype();
7414 if (t1
->ty
== Tstruct
)
7416 ad
= ((TypeStruct
*)t1
)->sym
;
7419 else if (t1
->ty
== Tclass
)
7421 ad
= ((TypeClass
*)t1
)->sym
;
7423 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
7424 if (search_function(ad
, Id::indexass
))
7425 { Expression
*e
= new DotIdExp(loc
, ae
->e1
, Id::indexass
);
7426 Expressions
*a
= (Expressions
*)ae
->arguments
->copy();
7429 e
= new CallExp(loc
, e
, a
);
7430 e
= e
->semantic(sc
);
7435 // Rewrite (a[i] = value) to (a.opIndex(i, value))
7436 if (search_function(ad
, id
))
7437 { Expression
*e
= new DotIdExp(loc
, ae
->e1
, id
);
7439 if (1 || !global
.params
.useDeprecated
)
7440 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
7442 e
= new CallExp(loc
, e
, (Expression
*)ae
->arguments
->data
[0], e2
);
7443 e
= e
->semantic(sc
);
7449 /* Look for operator overloading of a[i..j]=value.
7450 * Do it before semantic() otherwise the a[i..j] will have been
7451 * converted to a.opSlice() already.
7453 if (e1
->op
== TOKslice
)
7455 SliceExp
*ae
= (SliceExp
*)e1
;
7456 AggregateDeclaration
*ad
;
7457 Identifier
*id
= Id::index
;
7459 ae
->e1
= ae
->e1
->semantic(sc
);
7460 ae
->e1
= resolveProperties(sc
, ae
->e1
);
7461 t1
= ae
->e1
->type
->toBasetype();
7462 if (t1
->ty
== Tstruct
)
7464 ad
= ((TypeStruct
*)t1
)->sym
;
7467 else if (t1
->ty
== Tclass
)
7469 ad
= ((TypeClass
*)t1
)->sym
;
7471 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
7472 if (search_function(ad
, Id::sliceass
))
7473 { Expression
*e
= new DotIdExp(loc
, ae
->e1
, Id::sliceass
);
7474 Expressions
*a
= new Expressions();
7484 e
= new CallExp(loc
, e
, a
);
7485 e
= e
->semantic(sc
);
7491 BinExp::semantic(sc
);
7492 e2
= resolveProperties(sc
, e2
);
7495 /* Rewrite tuple assignment as a tuple of assignments.
7497 if (e1
->op
== TOKtuple
&& e2
->op
== TOKtuple
)
7498 { TupleExp
*tup1
= (TupleExp
*)e1
;
7499 TupleExp
*tup2
= (TupleExp
*)e2
;
7500 size_t dim
= tup1
->exps
->dim
;
7501 if (dim
!= tup2
->exps
->dim
)
7503 error("mismatched tuple lengths, %d and %d", (int)dim
, (int)tup2
->exps
->dim
);
7506 { Expressions
*exps
= new Expressions
;
7509 for (int i
= 0; i
< dim
; i
++)
7510 { Expression
*ex1
= (Expression
*)tup1
->exps
->data
[i
];
7511 Expression
*ex2
= (Expression
*)tup2
->exps
->data
[i
];
7512 exps
->data
[i
] = (void *) new AssignExp(loc
, ex1
, ex2
);
7514 Expression
*e
= new TupleExp(loc
, exps
);
7515 e
= e
->semantic(sc
);
7520 Type
*t1
= e1
->type
->toBasetype();
7522 if (t1
->ty
== Tfunction
)
7523 { // Rewrite f=value to f(value)
7526 e
= new CallExp(loc
, e1
, e2
);
7527 e
= e
->semantic(sc
);
7531 /* If it is an assignment from a 'foreign' type,
7532 * check for operator overloading.
7534 if (t1
->ty
== Tstruct
)
7536 StructDeclaration
*sd
= ((TypeStruct
*)t1
)->sym
;
7537 if (op
== TOKassign
)
7539 Expression
*e
= op_overload(sc
);
7543 else if (op
== TOKconstruct
)
7544 { Type
*t2
= e2
->type
->toBasetype();
7545 if (t2
->ty
== Tstruct
&&
7546 sd
== ((TypeStruct
*)t2
)->sym
&&
7548 { /* We have a copy constructor for this
7550 if (e2
->op
== TOKvar
|| e2
->op
== TOKstar
)
7554 Expression
*e
= new DotVarExp(loc
, e1
, sd
->cpctor
, 0);
7555 e
= new CallExp(loc
, e
, e2
);
7556 return e
->semantic(sc
);
7558 else if (e2
->op
== TOKquestion
)
7560 * a ? e1 = b : e1 = c;
7562 CondExp
*ec
= (CondExp
*)e2
;
7563 AssignExp
*ea1
= new AssignExp(ec
->e1
->loc
, e1
, ec
->e1
);
7565 AssignExp
*ea2
= new AssignExp(ec
->e1
->loc
, e1
, ec
->e2
);
7567 Expression
*e
= new CondExp(loc
, ec
->econd
, ea1
, ea2
);
7568 return e
->semantic(sc
);
7573 else if (t1
->ty
== Tclass
)
7574 { // Disallow assignment operator overloads for same type
7575 if (!e2
->type
->implicitConvTo(e1
->type
))
7577 Expression
*e
= op_overload(sc
);
7583 if (t1
->ty
== Tsarray
)
7585 Expression
*e
= new SliceExp(e1
->loc
, e1
, NULL
, NULL
);
7586 e1
= e
->semantic(sc
);
7587 t1
= e1
->type
->toBasetype();
7592 if (e1
->op
== TOKarraylength
)
7594 // e1 is not an lvalue, but we let code generator handle it
7595 ArrayLengthExp
*ale
= (ArrayLengthExp
*)e1
;
7597 ale
->e1
= ale
->e1
->modifiableLvalue(sc
, e1
);
7599 else if (e1
->op
== TOKslice
)
7601 Type
*tn
= e1
->type
->nextOf();
7602 if (tn
&& !tn
->isMutable() && op
!= TOKconstruct
)
7603 error("slice %s is not mutable", e1
->toChars());
7606 { // Try to do a decent error message with the expression
7607 // before it got constant folded
7608 if (e1
->op
!= TOKvar
)
7609 e1
= e1
->optimize(WANTvalue
);
7610 if (op
!= TOKconstruct
)
7611 e1
= e1
->modifiableLvalue(sc
, e1old
);
7614 Type
*t2
= e2
->type
;
7615 if (e1
->op
== TOKslice
&&
7617 e2
->implicitConvTo(t1
->nextOf())
7620 ismemset
= 1; // make it easy for back end to tell what this is
7621 e2
= e2
->implicitCastTo(sc
, t1
->nextOf());
7623 else if (t1
->ty
== Tsarray
)
7625 /* Should have already converted e1 => e1[]
7628 //error("cannot assign to static array %s", e1->toChars());
7630 else if (e1
->op
== TOKslice
)
7632 e2
= e2
->implicitCastTo(sc
, e1
->type
->constOf());
7636 e2
= e2
->implicitCastTo(sc
, e1
->type
);
7643 Expression
*AssignExp::checkToBoolean()
7647 // are usually mistakes.
7649 error("'=' does not give a boolean result");
7653 /************************************************************/
7655 AddAssignExp::AddAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7656 : BinExp(loc
, TOKaddass
, sizeof(AddAssignExp
), e1
, e2
)
7660 Expression
*AddAssignExp::semantic(Scope
*sc
)
7666 BinExp::semantic(sc
);
7667 e2
= resolveProperties(sc
, e2
);
7669 e
= op_overload(sc
);
7673 e1
= e1
->modifiableLvalue(sc
, e1
);
7675 Type
*tb1
= e1
->type
->toBasetype();
7676 Type
*tb2
= e2
->type
->toBasetype();
7678 if ((tb1
->ty
== Tarray
|| tb1
->ty
== Tsarray
) &&
7679 (tb2
->ty
== Tarray
|| tb2
->ty
== Tsarray
) &&
7680 tb1
->nextOf()->equals(tb2
->nextOf())
7690 if (tb1
->ty
== Tpointer
&& tb2
->isintegral())
7691 e
= scaleFactor(sc
);
7692 else if (tb1
->ty
== Tbit
|| tb1
->ty
== Tbool
)
7695 // Need to rethink this
7696 if (e1
->op
!= TOKvar
)
7697 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
7702 Identifier
*id
= Lexer::uniqueId("__name");
7704 v
= new VarDeclaration(loc
, tb1
->pointerTo(), id
, NULL
);
7708 v
->parent
= sc
->func
;
7710 ea
= new AddrExp(loc
, e1
);
7711 ea
= new AssignExp(loc
, new VarExp(loc
, v
), ea
);
7713 ex
= new VarExp(loc
, v
);
7714 ex
= new PtrExp(loc
, ex
);
7715 e
= new AddExp(loc
, ex
, e2
);
7716 e
= new CastExp(loc
, e
, e1
->type
);
7717 e
= new AssignExp(loc
, ex
->syntaxCopy(), e
);
7719 e
= new CommaExp(loc
, ea
, e
);
7723 { // Rewrite e1+=e2 to e1=e1+e2
7724 // BUG: doesn't account for side effects in e1
7725 // BUG: other assignment operators for bits aren't handled at all
7726 e
= new AddExp(loc
, e1
, e2
);
7727 e
= new CastExp(loc
, e
, e1
->type
);
7728 e
= new AssignExp(loc
, e1
->syntaxCopy(), e
);
7730 e
= e
->semantic(sc
);
7736 e1
->checkArithmetic();
7737 e2
->checkArithmetic();
7738 if (type
->isreal() || type
->isimaginary())
7740 assert(global
.errors
|| e2
->type
->isfloating());
7741 e2
= e2
->castTo(sc
, e1
->type
);
7749 /************************************************************/
7751 MinAssignExp::MinAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7752 : BinExp(loc
, TOKminass
, sizeof(MinAssignExp
), e1
, e2
)
7756 Expression
*MinAssignExp::semantic(Scope
*sc
)
7762 BinExp::semantic(sc
);
7763 e2
= resolveProperties(sc
, e2
);
7765 e
= op_overload(sc
);
7769 e1
= e1
->modifiableLvalue(sc
, e1
);
7772 if (e1
->type
->ty
== Tpointer
&& e2
->type
->isintegral())
7773 e
= scaleFactor(sc
);
7776 e1
= e1
->checkArithmetic();
7777 e2
= e2
->checkArithmetic();
7780 if (type
->isreal() || type
->isimaginary())
7782 assert(e2
->type
->isfloating());
7783 e2
= e2
->castTo(sc
, e1
->type
);
7790 /************************************************************/
7792 CatAssignExp::CatAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7793 : BinExp(loc
, TOKcatass
, sizeof(CatAssignExp
), e1
, e2
)
7797 Expression
*CatAssignExp::semantic(Scope
*sc
)
7800 BinExp::semantic(sc
);
7801 e2
= resolveProperties(sc
, e2
);
7803 e
= op_overload(sc
);
7807 if (e1
->op
== TOKslice
)
7808 { SliceExp
*se
= (SliceExp
*)e1
;
7810 if (se
->e1
->type
->toBasetype()->ty
== Tsarray
)
7811 error("cannot append to static array %s", se
->e1
->type
->toChars());
7814 e1
= e1
->modifiableLvalue(sc
, e1
);
7816 Type
*tb1
= e1
->type
->toBasetype();
7817 Type
*tb2
= e2
->type
->toBasetype();
7821 if ((tb1
->ty
== Tarray
) &&
7822 (tb2
->ty
== Tarray
|| tb2
->ty
== Tsarray
) &&
7823 (e2
->implicitConvTo(e1
->type
) ||
7824 tb2
->nextOf()->implicitConvTo(tb1
->nextOf()))
7827 e2
= e2
->castTo(sc
, e1
->type
);
7831 else if ((tb1
->ty
== Tarray
) &&
7832 e2
->implicitConvTo(tb1
->nextOf())
7835 e2
= e2
->castTo(sc
, tb1
->nextOf());
7841 error("cannot append type %s to type %s", tb2
->toChars(), tb1
->toChars());
7842 type
= Type::tint32
;
7848 /************************************************************/
7850 MulAssignExp::MulAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7851 : BinExp(loc
, TOKmulass
, sizeof(MulAssignExp
), e1
, e2
)
7855 Expression
*MulAssignExp::semantic(Scope
*sc
)
7858 BinExp::semantic(sc
);
7859 e2
= resolveProperties(sc
, e2
);
7861 e
= op_overload(sc
);
7865 e1
= e1
->modifiableLvalue(sc
, e1
);
7870 e1
->checkArithmetic();
7871 e2
->checkArithmetic();
7872 if (e2
->type
->isfloating())
7880 if (t2
->isimaginary() || t2
->iscomplex())
7882 e2
= e2
->castTo(sc
, t1
);
7885 else if (t1
->isimaginary())
7887 if (t2
->isimaginary() || t2
->iscomplex())
7891 case Timaginary32
: t2
= Type::tfloat32
; break;
7892 case Timaginary64
: t2
= Type::tfloat64
; break;
7893 case Timaginary80
: t2
= Type::tfloat80
; break;
7897 e2
= e2
->castTo(sc
, t2
);
7904 /************************************************************/
7906 DivAssignExp::DivAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7907 : BinExp(loc
, TOKdivass
, sizeof(DivAssignExp
), e1
, e2
)
7911 Expression
*DivAssignExp::semantic(Scope
*sc
)
7914 BinExp::semantic(sc
);
7915 e2
= resolveProperties(sc
, e2
);
7917 e
= op_overload(sc
);
7921 e1
= e1
->modifiableLvalue(sc
, e1
);
7926 e1
->checkArithmetic();
7927 e2
->checkArithmetic();
7928 if (e2
->type
->isimaginary())
7935 // Therefore, the result is 0
7936 e2
= new CommaExp(loc
, e2
, new RealExp(loc
, 0, t1
));
7938 e
= new AssignExp(loc
, e1
, e2
);
7942 else if (t1
->isimaginary())
7947 case Timaginary32
: t2
= Type::tfloat32
; break;
7948 case Timaginary64
: t2
= Type::tfloat64
; break;
7949 case Timaginary80
: t2
= Type::tfloat80
; break;
7953 e2
= e2
->castTo(sc
, t2
);
7954 e
= new AssignExp(loc
, e1
, e2
);
7962 /************************************************************/
7964 ModAssignExp::ModAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7965 : BinExp(loc
, TOKmodass
, sizeof(ModAssignExp
), e1
, e2
)
7969 Expression
*ModAssignExp::semantic(Scope
*sc
)
7971 return commonSemanticAssign(sc
);
7974 /************************************************************/
7976 ShlAssignExp::ShlAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7977 : BinExp(loc
, TOKshlass
, sizeof(ShlAssignExp
), e1
, e2
)
7981 Expression
*ShlAssignExp::semantic(Scope
*sc
)
7984 //printf("ShlAssignExp::semantic()\n");
7985 BinExp::semantic(sc
);
7986 e2
= resolveProperties(sc
, e2
);
7988 e
= op_overload(sc
);
7992 e1
= e1
->modifiableLvalue(sc
, e1
);
7997 e1
->checkIntegral();
7998 e2
= e2
->checkIntegral();
7999 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8003 /************************************************************/
8005 ShrAssignExp::ShrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8006 : BinExp(loc
, TOKshrass
, sizeof(ShrAssignExp
), e1
, e2
)
8010 Expression
*ShrAssignExp::semantic(Scope
*sc
)
8013 BinExp::semantic(sc
);
8014 e2
= resolveProperties(sc
, e2
);
8016 e
= op_overload(sc
);
8020 e1
= e1
->modifiableLvalue(sc
, e1
);
8025 e1
->checkIntegral();
8026 e2
= e2
->checkIntegral();
8027 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8031 /************************************************************/
8033 UshrAssignExp::UshrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8034 : BinExp(loc
, TOKushrass
, sizeof(UshrAssignExp
), e1
, e2
)
8038 Expression
*UshrAssignExp::semantic(Scope
*sc
)
8041 BinExp::semantic(sc
);
8042 e2
= resolveProperties(sc
, e2
);
8044 e
= op_overload(sc
);
8048 e1
= e1
->modifiableLvalue(sc
, e1
);
8053 e1
->checkIntegral();
8054 e2
= e2
->checkIntegral();
8055 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8059 /************************************************************/
8061 AndAssignExp::AndAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8062 : BinExp(loc
, TOKandass
, sizeof(AndAssignExp
), e1
, e2
)
8066 Expression
*AndAssignExp::semantic(Scope
*sc
)
8068 return commonSemanticAssignIntegral(sc
);
8071 /************************************************************/
8073 OrAssignExp::OrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8074 : BinExp(loc
, TOKorass
, sizeof(OrAssignExp
), e1
, e2
)
8078 Expression
*OrAssignExp::semantic(Scope
*sc
)
8080 return commonSemanticAssignIntegral(sc
);
8083 /************************************************************/
8085 XorAssignExp::XorAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8086 : BinExp(loc
, TOKxorass
, sizeof(XorAssignExp
), e1
, e2
)
8090 Expression
*XorAssignExp::semantic(Scope
*sc
)
8092 return commonSemanticAssignIntegral(sc
);
8095 /************************* AddExp *****************************/
8097 AddExp::AddExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8098 : BinExp(loc
, TOKadd
, sizeof(AddExp
), e1
, e2
)
8102 Expression
*AddExp::semantic(Scope
*sc
)
8106 printf("AddExp::semantic('%s')\n", toChars());
8110 BinExp::semanticp(sc
);
8112 e
= op_overload(sc
);
8116 Type
*tb1
= e1
->type
->toBasetype();
8117 Type
*tb2
= e2
->type
->toBasetype();
8119 if ((tb1
->ty
== Tarray
|| tb1
->ty
== Tsarray
) &&
8120 (tb2
->ty
== Tarray
|| tb2
->ty
== Tsarray
) &&
8121 tb1
->nextOf()->equals(tb2
->nextOf())
8127 else if (tb1
->ty
== Tpointer
&& e2
->type
->isintegral() ||
8128 tb2
->ty
== Tpointer
&& e1
->type
->isintegral())
8129 e
= scaleFactor(sc
);
8130 else if (tb1
->ty
== Tpointer
&& tb2
->ty
== Tpointer
)
8132 incompatibleTypes();
8139 if ((e1
->type
->isreal() && e2
->type
->isimaginary()) ||
8140 (e1
->type
->isimaginary() && e2
->type
->isreal()))
8142 switch (type
->toBasetype()->ty
)
8146 type
= Type::tcomplex32
;
8151 type
= Type::tcomplex64
;
8156 type
= Type::tcomplex80
;
8170 /************************************************************/
8172 MinExp::MinExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8173 : BinExp(loc
, TOKmin
, sizeof(MinExp
), e1
, e2
)
8177 Expression
*MinExp::semantic(Scope
*sc
)
8183 printf("MinExp::semantic('%s')\n", toChars());
8188 BinExp::semanticp(sc
);
8190 e
= op_overload(sc
);
8195 t1
= e1
->type
->toBasetype();
8196 t2
= e2
->type
->toBasetype();
8197 if (t1
->ty
== Tpointer
)
8199 if (t2
->ty
== Tpointer
)
8200 { // Need to divide the result by the stride
8201 // Replace (ptr - ptr) with (ptr - ptr) / stride
8205 typeCombine(sc
); // make sure pointer types are compatible
8206 type
= Type::tptrdiff_t
;
8207 stride
= t2
->nextOf()->size();
8208 e
= new DivExp(loc
, this, new IntegerExp(0, stride
, Type::tptrdiff_t
));
8209 e
->type
= Type::tptrdiff_t
;
8212 else if (t2
->isintegral())
8213 e
= scaleFactor(sc
);
8215 { error("incompatible types for -");
8216 return new IntegerExp(0);
8219 else if (t2
->ty
== Tpointer
)
8222 error("can't subtract pointer from %s", e1
->type
->toChars());
8223 return new IntegerExp(0);
8228 t1
= e1
->type
->toBasetype();
8229 t2
= e2
->type
->toBasetype();
8230 if ((t1
->isreal() && t2
->isimaginary()) ||
8231 (t1
->isimaginary() && t2
->isreal()))
8237 type
= Type::tcomplex32
;
8242 type
= Type::tcomplex64
;
8247 type
= Type::tcomplex80
;
8258 /************************* CatExp *****************************/
8260 CatExp::CatExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8261 : BinExp(loc
, TOKcat
, sizeof(CatExp
), e1
, e2
)
8265 Expression
*CatExp::semantic(Scope
*sc
)
8268 //printf("CatExp::semantic() %s\n", toChars());
8271 BinExp::semanticp(sc
);
8272 e
= op_overload(sc
);
8276 Type
*tb1
= e1
->type
->toBasetype();
8277 Type
*tb2
= e2
->type
->toBasetype();
8280 /* BUG: Should handle things like:
8290 if ((tb1
->ty
== Tsarray
|| tb1
->ty
== Tarray
) &&
8291 e2
->type
->implicitConvTo(tb1
->nextOf()) >= MATCHconst
)
8293 type
= tb1
->nextOf()->arrayOf();
8294 if (tb2
->ty
== Tarray
)
8295 { // Make e2 into [e2]
8296 e2
= new ArrayLiteralExp(e2
->loc
, e2
);
8301 else if ((tb2
->ty
== Tsarray
|| tb2
->ty
== Tarray
) &&
8302 e1
->type
->implicitConvTo(tb2
->nextOf()) >= MATCHconst
)
8304 type
= tb2
->nextOf()->arrayOf();
8305 if (tb1
->ty
== Tarray
)
8306 { // Make e1 into [e1]
8307 e1
= new ArrayLiteralExp(e1
->loc
, e1
);
8314 type
= type
->toHeadMutable();
8316 Type
*tb
= type
->toBasetype();
8317 if (tb
->ty
== Tsarray
)
8318 type
= tb
->nextOf()->arrayOf();
8319 if (type
->ty
== Tarray
&& tb1
->nextOf() && tb2
->nextOf() &&
8320 tb1
->nextOf()->mod
!= tb2
->nextOf()->mod
)
8321 type
= type
->nextOf()->toHeadMutable()->arrayOf();
8328 Type
*t1
= e1
->type
->toBasetype();
8329 Type
*t2
= e2
->type
->toBasetype();
8330 if (e1
->op
== TOKstring
&& e2
->op
== TOKstring
)
8331 e
= optimize(WANTvalue
);
8332 else if ((t1
->ty
== Tarray
|| t1
->ty
== Tsarray
) &&
8333 (t2
->ty
== Tarray
|| t2
->ty
== Tsarray
))
8339 //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
8340 error("Can only concatenate arrays, not (%s ~ %s)",
8341 e1
->type
->toChars(), e2
->type
->toChars());
8342 type
= Type::tint32
;
8345 e
->type
= e
->type
->semantic(loc
, sc
);
8351 /************************************************************/
8353 MulExp::MulExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8354 : BinExp(loc
, TOKmul
, sizeof(MulExp
), e1
, e2
)
8358 Expression
*MulExp::semantic(Scope
*sc
)
8362 printf("MulExp::semantic() %s\n", toChars());
8369 BinExp::semanticp(sc
);
8370 e
= op_overload(sc
);
8375 e1
->checkArithmetic();
8376 e2
->checkArithmetic();
8377 if (type
->isfloating())
8378 { Type
*t1
= e1
->type
;
8379 Type
*t2
= e2
->type
;
8385 else if (t2
->isreal())
8389 else if (t1
->isimaginary())
8391 if (t2
->isimaginary())
8396 case Timaginary32
: type
= Type::tfloat32
; break;
8397 case Timaginary64
: type
= Type::tfloat64
; break;
8398 case Timaginary80
: type
= Type::tfloat80
; break;
8405 e
= new NegExp(loc
, this);
8406 e
= e
->semantic(sc
);
8410 type
= t2
; // t2 is complex
8412 else if (t2
->isimaginary())
8414 type
= t1
; // t1 is complex
8420 /************************************************************/
8422 DivExp::DivExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8423 : BinExp(loc
, TOKdiv
, sizeof(DivExp
), e1
, e2
)
8427 Expression
*DivExp::semantic(Scope
*sc
)
8433 BinExp::semanticp(sc
);
8434 e
= op_overload(sc
);
8439 e1
->checkArithmetic();
8440 e2
->checkArithmetic();
8441 if (type
->isfloating())
8442 { Type
*t1
= e1
->type
;
8443 Type
*t2
= e2
->type
;
8448 if (t2
->isimaginary())
8453 e
= new NegExp(loc
, this);
8454 e
= e
->semantic(sc
);
8458 else if (t2
->isreal())
8462 else if (t1
->isimaginary())
8464 if (t2
->isimaginary())
8468 case Timaginary32
: type
= Type::tfloat32
; break;
8469 case Timaginary64
: type
= Type::tfloat64
; break;
8470 case Timaginary80
: type
= Type::tfloat80
; break;
8475 type
= t2
; // t2 is complex
8477 else if (t2
->isimaginary())
8479 type
= t1
; // t1 is complex
8485 /************************************************************/
8487 ModExp::ModExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8488 : BinExp(loc
, TOKmod
, sizeof(ModExp
), e1
, e2
)
8492 Expression
*ModExp::semantic(Scope
*sc
)
8498 BinExp::semanticp(sc
);
8499 e
= op_overload(sc
);
8504 e1
->checkArithmetic();
8505 e2
->checkArithmetic();
8506 if (type
->isfloating())
8508 if (e2
->type
->iscomplex())
8509 { error("cannot perform modulo complex arithmetic");
8510 return new IntegerExp(0);
8516 /************************************************************/
8518 ShlExp::ShlExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8519 : BinExp(loc
, TOKshl
, sizeof(ShlExp
), e1
, e2
)
8523 Expression
*ShlExp::semantic(Scope
*sc
)
8526 //printf("ShlExp::semantic(), type = %p\n", type);
8528 { BinExp::semanticp(sc
);
8529 e
= op_overload(sc
);
8532 e1
= e1
->checkIntegral();
8533 e2
= e2
->checkIntegral();
8534 e1
= e1
->integralPromotions(sc
);
8535 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8541 /************************************************************/
8543 ShrExp::ShrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8544 : BinExp(loc
, TOKshr
, sizeof(ShrExp
), e1
, e2
)
8548 Expression
*ShrExp::semantic(Scope
*sc
)
8552 { BinExp::semanticp(sc
);
8553 e
= op_overload(sc
);
8556 e1
= e1
->checkIntegral();
8557 e2
= e2
->checkIntegral();
8558 e1
= e1
->integralPromotions(sc
);
8559 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8565 /************************************************************/
8567 UshrExp::UshrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8568 : BinExp(loc
, TOKushr
, sizeof(UshrExp
), e1
, e2
)
8572 Expression
*UshrExp::semantic(Scope
*sc
)
8576 { BinExp::semanticp(sc
);
8577 e
= op_overload(sc
);
8580 e1
= e1
->checkIntegral();
8581 e2
= e2
->checkIntegral();
8582 e1
= e1
->integralPromotions(sc
);
8583 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8589 /************************************************************/
8591 AndExp::AndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8592 : BinExp(loc
, TOKand
, sizeof(AndExp
), e1
, e2
)
8596 Expression
*AndExp::semantic(Scope
*sc
)
8600 { BinExp::semanticp(sc
);
8601 e
= op_overload(sc
);
8604 if (e1
->type
->toBasetype()->ty
== Tbool
&&
8605 e2
->type
->toBasetype()->ty
== Tbool
)
8613 e1
->checkIntegral();
8614 e2
->checkIntegral();
8620 /************************************************************/
8622 OrExp::OrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8623 : BinExp(loc
, TOKor
, sizeof(OrExp
), e1
, e2
)
8627 Expression
*OrExp::semantic(Scope
*sc
)
8631 { BinExp::semanticp(sc
);
8632 e
= op_overload(sc
);
8635 if (e1
->type
->toBasetype()->ty
== Tbool
&&
8636 e2
->type
->toBasetype()->ty
== Tbool
)
8644 e1
->checkIntegral();
8645 e2
->checkIntegral();
8651 /************************************************************/
8653 XorExp::XorExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8654 : BinExp(loc
, TOKxor
, sizeof(XorExp
), e1
, e2
)
8658 Expression
*XorExp::semantic(Scope
*sc
)
8662 { BinExp::semanticp(sc
);
8663 e
= op_overload(sc
);
8666 if (e1
->type
->toBasetype()->ty
== Tbool
&&
8667 e2
->type
->toBasetype()->ty
== Tbool
)
8675 e1
->checkIntegral();
8676 e2
->checkIntegral();
8683 /************************************************************/
8685 OrOrExp::OrOrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8686 : BinExp(loc
, TOKoror
, sizeof(OrOrExp
), e1
, e2
)
8690 Expression
*OrOrExp::semantic(Scope
*sc
)
8694 // same as for AndAnd
8695 e1
= e1
->semantic(sc
);
8696 e1
= resolveProperties(sc
, e1
);
8697 e1
= e1
->checkToPointer();
8698 e1
= e1
->checkToBoolean();
8699 cs1
= sc
->callSuper
;
8701 if (sc
->flags
& SCOPEstaticif
)
8703 /* If in static if, don't evaluate e2 if we don't have to.
8705 e1
= e1
->optimize(WANTflags
);
8706 if (e1
->isBool(TRUE
))
8708 return new IntegerExp(loc
, 1, Type::tboolean
);
8712 e2
= e2
->semantic(sc
);
8713 sc
->mergeCallSuper(loc
, cs1
);
8714 e2
= resolveProperties(sc
, e2
);
8715 e2
= e2
->checkToPointer();
8717 type
= Type::tboolean
;
8718 if (e1
->type
->ty
== Tvoid
)
8720 if (e2
->op
== TOKtype
|| e2
->op
== TOKimport
)
8721 error("%s is not an expression", e2
->toChars());
8725 Expression
*OrOrExp::checkToBoolean()
8727 e2
= e2
->checkToBoolean();
8731 int OrOrExp::isBit()
8736 int OrOrExp::checkSideEffect(int flag
)
8740 return e1
->checkSideEffect(2) || e2
->checkSideEffect(2);
8743 { e1
->checkSideEffect(1);
8744 return e2
->checkSideEffect(flag
);
8748 /************************************************************/
8750 AndAndExp::AndAndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8751 : BinExp(loc
, TOKandand
, sizeof(AndAndExp
), e1
, e2
)
8755 Expression
*AndAndExp::semantic(Scope
*sc
)
8760 e1
= e1
->semantic(sc
);
8761 e1
= resolveProperties(sc
, e1
);
8762 e1
= e1
->checkToPointer();
8763 e1
= e1
->checkToBoolean();
8764 cs1
= sc
->callSuper
;
8766 if (sc
->flags
& SCOPEstaticif
)
8768 /* If in static if, don't evaluate e2 if we don't have to.
8770 e1
= e1
->optimize(WANTflags
);
8771 if (e1
->isBool(FALSE
))
8773 return new IntegerExp(loc
, 0, Type::tboolean
);
8777 e2
= e2
->semantic(sc
);
8778 sc
->mergeCallSuper(loc
, cs1
);
8779 e2
= resolveProperties(sc
, e2
);
8780 e2
= e2
->checkToPointer();
8782 type
= Type::tboolean
;
8783 if (e1
->type
->ty
== Tvoid
)
8785 if (e2
->op
== TOKtype
|| e2
->op
== TOKimport
)
8786 error("%s is not an expression", e2
->toChars());
8790 Expression
*AndAndExp::checkToBoolean()
8792 e2
= e2
->checkToBoolean();
8796 int AndAndExp::isBit()
8801 int AndAndExp::checkSideEffect(int flag
)
8805 return e1
->checkSideEffect(2) || e2
->checkSideEffect(2);
8809 e1
->checkSideEffect(1);
8810 return e2
->checkSideEffect(flag
);
8814 /************************************************************/
8816 InExp::InExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8817 : BinExp(loc
, TOKin
, sizeof(InExp
), e1
, e2
)
8821 Expression
*InExp::semantic(Scope
*sc
)
8827 BinExp::semanticp(sc
);
8828 e
= op_overload(sc
);
8832 //type = Type::tboolean;
8833 Type
*t2b
= e2
->type
->toBasetype();
8834 if (t2b
->ty
!= Taarray
)
8836 error("rvalue of in expression must be an associative array, not %s", e2
->type
->toChars());
8837 type
= Type::terror
;
8841 TypeAArray
*ta
= (TypeAArray
*)t2b
;
8843 // Convert key to type of key
8844 e1
= e1
->implicitCastTo(sc
, ta
->index
);
8846 // Return type is pointer to value
8847 type
= ta
->nextOf()->pointerTo();
8858 /************************************************************/
8860 /* This deletes the key e1 from the associative array e2
8863 RemoveExp::RemoveExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8864 : BinExp(loc
, TOKremove
, sizeof(RemoveExp
), e1
, e2
)
8869 /************************************************************/
8871 CmpExp::CmpExp(enum TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
8872 : BinExp(loc
, op
, sizeof(CmpExp
), e1
, e2
)
8876 Expression
*CmpExp::semantic(Scope
*sc
)
8882 printf("CmpExp::semantic('%s')\n", toChars());
8887 BinExp::semanticp(sc
);
8889 if (e1
->type
->toBasetype()->ty
== Tclass
&& e2
->op
== TOKnull
||
8890 e2
->type
->toBasetype()->ty
== Tclass
&& e1
->op
== TOKnull
)
8892 error("do not use null when comparing class types");
8895 e
= op_overload(sc
);
8898 e
= new CmpExp(op
, loc
, e
, new IntegerExp(loc
, 0, Type::tint32
));
8899 e
= e
->semantic(sc
);
8904 type
= Type::tboolean
;
8906 // Special handling for array comparisons
8907 t1
= e1
->type
->toBasetype();
8908 t2
= e2
->type
->toBasetype();
8909 if ((t1
->ty
== Tarray
|| t1
->ty
== Tsarray
|| t1
->ty
== Tpointer
) &&
8910 (t2
->ty
== Tarray
|| t2
->ty
== Tsarray
|| t2
->ty
== Tpointer
))
8912 if (t1
->nextOf()->implicitConvTo(t2
->nextOf()) < MATCHconst
&&
8913 t2
->nextOf()->implicitConvTo(t1
->nextOf()) < MATCHconst
&&
8914 (t1
->nextOf()->ty
!= Tvoid
&& t2
->nextOf()->ty
!= Tvoid
))
8915 error("array comparison type mismatch, %s vs %s", t1
->nextOf()->toChars(), t2
->nextOf()->toChars());
8918 else if (t1
->ty
== Tstruct
|| t2
->ty
== Tstruct
||
8919 (t1
->ty
== Tclass
&& t2
->ty
== Tclass
))
8921 if (t2
->ty
== Tstruct
)
8922 error("need member function opCmp() for %s %s to compare", t2
->toDsymbol(sc
)->kind(), t2
->toChars());
8924 error("need member function opCmp() for %s %s to compare", t1
->toDsymbol(sc
)->kind(), t1
->toChars());
8928 else if (t1
->iscomplex() || t2
->iscomplex())
8930 error("compare not defined for complex operands");
8931 e
= new IntegerExp(0);
8936 //printf("CmpExp: %s\n", e->toChars());
8946 /************************************************************/
8948 EqualExp::EqualExp(enum TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
8949 : BinExp(loc
, op
, sizeof(EqualExp
), e1
, e2
)
8951 assert(op
== TOKequal
|| op
== TOKnotequal
);
8954 Expression
*EqualExp::semantic(Scope
*sc
)
8959 //printf("EqualExp::semantic('%s')\n", toChars());
8963 BinExp::semanticp(sc
);
8965 /* Before checking for operator overloading, check to see if we're
8966 * comparing the addresses of two statics. If so, we can just see
8967 * if they are the same symbol.
8969 if (e1
->op
== TOKaddress
&& e2
->op
== TOKaddress
)
8970 { AddrExp
*ae1
= (AddrExp
*)e1
;
8971 AddrExp
*ae2
= (AddrExp
*)e2
;
8973 if (ae1
->e1
->op
== TOKvar
&& ae2
->e1
->op
== TOKvar
)
8974 { VarExp
*ve1
= (VarExp
*)ae1
->e1
;
8975 VarExp
*ve2
= (VarExp
*)ae2
->e1
;
8977 if (ve1
->var
== ve2
->var
/*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
8979 // They are the same, result is 'true' for ==, 'false' for !=
8980 e
= new IntegerExp(loc
, (op
== TOKequal
), Type::tboolean
);
8986 if (e1
->type
->toBasetype()->ty
== Tclass
&& e2
->op
== TOKnull
||
8987 e2
->type
->toBasetype()->ty
== Tclass
&& e1
->op
== TOKnull
)
8989 error("use '%s' instead of '%s' when comparing with null",
8990 Token::toChars(op
== TOKequal
? TOKidentity
: TOKnotidentity
),
8991 Token::toChars(op
));
8994 //if (e2->op != TOKnull)
8996 e
= op_overload(sc
);
8999 if (op
== TOKnotequal
)
9001 e
= new NotExp(e
->loc
, e
);
9002 e
= e
->semantic(sc
);
9008 e
= typeCombine(sc
);
9009 type
= Type::tboolean
;
9011 // Special handling for array comparisons
9012 t1
= e1
->type
->toBasetype();
9013 t2
= e2
->type
->toBasetype();
9015 if ((t1
->ty
== Tarray
|| t1
->ty
== Tsarray
|| t1
->ty
== Tpointer
) &&
9016 (t2
->ty
== Tarray
|| t2
->ty
== Tsarray
|| t2
->ty
== Tpointer
))
9018 if (t1
->nextOf()->implicitConvTo(t2
->nextOf()) < MATCHconst
&&
9019 t2
->nextOf()->implicitConvTo(t1
->nextOf()) < MATCHconst
&&
9020 (t1
->nextOf()->ty
!= Tvoid
&& t2
->nextOf()->ty
!= Tvoid
))
9021 error("array equality comparison type mismatch, %s vs %s", t1
->toChars(), t2
->toChars());
9025 if (e1
->type
!= e2
->type
&& e1
->type
->isfloating() && e2
->type
->isfloating())
9027 // Cast both to complex
9028 e1
= e1
->castTo(sc
, Type::tcomplex80
);
9029 e2
= e2
->castTo(sc
, Type::tcomplex80
);
9035 int EqualExp::isBit()
9042 /************************************************************/
9044 IdentityExp::IdentityExp(enum TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
9045 : BinExp(loc
, op
, sizeof(IdentityExp
), e1
, e2
)
9049 Expression
*IdentityExp::semantic(Scope
*sc
)
9054 BinExp::semanticp(sc
);
9055 type
= Type::tboolean
;
9057 if (e1
->type
!= e2
->type
&& e1
->type
->isfloating() && e2
->type
->isfloating())
9059 // Cast both to complex
9060 e1
= e1
->castTo(sc
, Type::tcomplex80
);
9061 e2
= e2
->castTo(sc
, Type::tcomplex80
);
9066 int IdentityExp::isBit()
9072 /****************************************************************/
9074 CondExp::CondExp(Loc loc
, Expression
*econd
, Expression
*e1
, Expression
*e2
)
9075 : BinExp(loc
, TOKquestion
, sizeof(CondExp
), e1
, e2
)
9077 this->econd
= econd
;
9080 Expression
*CondExp::syntaxCopy()
9082 return new CondExp(loc
, econd
->syntaxCopy(), e1
->syntaxCopy(), e2
->syntaxCopy());
9086 Expression
*CondExp::semantic(Scope
*sc
)
9093 printf("CondExp::semantic('%s')\n", toChars());
9098 econd
= econd
->semantic(sc
);
9099 econd
= resolveProperties(sc
, econd
);
9100 econd
= econd
->checkToPointer();
9101 econd
= econd
->checkToBoolean();
9103 #if 0 /* this cannot work right because the types of e1 and e2
9104 * both contribute to the type of the result.
9106 if (sc
->flags
& SCOPEstaticif
)
9108 /* If in static if, don't evaluate what we don't have to.
9110 econd
= econd
->optimize(WANTflags
);
9111 if (econd
->isBool(TRUE
))
9113 e1
= e1
->semantic(sc
);
9114 e1
= resolveProperties(sc
, e1
);
9117 else if (econd
->isBool(FALSE
))
9119 e2
= e2
->semantic(sc
);
9120 e2
= resolveProperties(sc
, e2
);
9127 cs0
= sc
->callSuper
;
9128 e1
= e1
->semantic(sc
);
9129 e1
= resolveProperties(sc
, e1
);
9130 cs1
= sc
->callSuper
;
9131 sc
->callSuper
= cs0
;
9132 e2
= e2
->semantic(sc
);
9133 e2
= resolveProperties(sc
, e2
);
9134 sc
->mergeCallSuper(loc
, cs1
);
9137 // If either operand is void, the result is void
9140 if (t1
->ty
== Tvoid
|| t2
->ty
== Tvoid
)
9147 switch (e1
->type
->toBasetype()->ty
)
9152 e2
= e2
->castTo(sc
, e1
->type
);
9155 switch (e2
->type
->toBasetype()->ty
)
9160 e1
= e1
->castTo(sc
, e2
->type
);
9163 if (type
->toBasetype()->ty
== Tarray
)
9165 e1
= e1
->castTo(sc
, type
);
9166 e2
= e2
->castTo(sc
, type
);
9170 printf("res: %s\n", type
->toChars());
9171 printf("e1 : %s\n", e1
->type
->toChars());
9172 printf("e2 : %s\n", e2
->type
->toChars());
9177 Expression
*CondExp::toLvalue(Scope
*sc
, Expression
*ex
)
9181 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
9182 e
= new PtrExp(loc
, this, type
);
9184 e1
= e1
->addressOf(sc
);
9185 //e1 = e1->toLvalue(sc, NULL);
9187 e2
= e2
->addressOf(sc
);
9188 //e2 = e2->toLvalue(sc, NULL);
9196 Expression
*CondExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
9198 error("conditional expression %s is not a modifiable lvalue", toChars());
9202 void CondExp::checkEscape()
9209 Expression
*CondExp::checkToBoolean()
9211 e1
= e1
->checkToBoolean();
9212 e2
= e2
->checkToBoolean();
9216 int CondExp::checkSideEffect(int flag
)
9220 return econd
->checkSideEffect(2) ||
9221 e1
->checkSideEffect(2) ||
9222 e2
->checkSideEffect(2);
9226 econd
->checkSideEffect(1);
9227 e1
->checkSideEffect(flag
);
9228 return e2
->checkSideEffect(flag
);
9232 int CondExp::canThrow()
9234 return econd
->canThrow() || e1
->canThrow() || e2
->canThrow();
9238 void CondExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
9240 expToCBuffer(buf
, hgs
, econd
, PREC_oror
);
9241 buf
->writestring(" ? ");
9242 expToCBuffer(buf
, hgs
, e1
, PREC_expr
);
9243 buf
->writestring(" : ");
9244 expToCBuffer(buf
, hgs
, e2
, PREC_cond
);
9248 /****************************************************************/
9250 DefaultInitExp::DefaultInitExp(Loc loc
, enum TOK subop
, int size
)
9251 : Expression(loc
, TOKdefault
, size
)
9253 this->subop
= subop
;
9256 void DefaultInitExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
9258 buf
->writestring(Token::toChars(subop
));
9261 /****************************************************************/
9263 FileInitExp::FileInitExp(Loc loc
)
9264 : DefaultInitExp(loc
, TOKfile
, sizeof(FileInitExp
))
9268 Expression
*FileInitExp::semantic(Scope
*sc
)
9270 //printf("FileInitExp::semantic()\n");
9271 type
= Type::tchar
->invariantOf()->arrayOf();
9275 Expression
*FileInitExp::resolve(Loc loc
, Scope
*sc
)
9277 //printf("FileInitExp::resolve() %s\n", toChars());
9278 char *s
= loc
.filename
? loc
.filename
: sc
->module
->ident
->toChars();
9279 Expression
*e
= new StringExp(loc
, s
);
9280 e
= e
->semantic(sc
);
9281 e
= e
->castTo(sc
, type
);
9285 /****************************************************************/
9287 LineInitExp::LineInitExp(Loc loc
)
9288 : DefaultInitExp(loc
, TOKline
, sizeof(LineInitExp
))
9292 Expression
*LineInitExp::semantic(Scope
*sc
)
9294 type
= Type::tint32
;
9298 Expression
*LineInitExp::resolve(Loc loc
, Scope
*sc
)
9300 Expression
*e
= new IntegerExp(loc
, loc
.linnum
, Type::tint32
);
9301 e
= e
->castTo(sc
, type
);