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 /******************************** GetLoggerExp **************************/
2113 GetLoggerExp::GetLoggerExp(Loc loc
)
2114 : Expression(loc
, TOKlogger
, sizeof(GetLoggerExp
))
2118 Expression
*GetLoggerExp::semantic(Scope
*sc
)
2120 Expression
*log
= new DotIdExp(loc
, new IdentifierExp(loc
, Id::empty
), Id::__log
);
2121 return log
->semantic(sc
);
2124 void GetLoggerExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2126 buf
->writestring("log");
2129 /******************************** ThisExp **************************/
2131 ThisExp::ThisExp(Loc loc
)
2132 : Expression(loc
, TOKthis
, sizeof(ThisExp
))
2137 Expression
*ThisExp::semantic(Scope
*sc
)
2138 { FuncDeclaration
*fd
;
2139 FuncDeclaration
*fdthis
;
2143 printf("ThisExp::semantic()\n");
2146 { //assert(global.errors || var);
2150 /* Special case for typeof(this) and typeof(super) since both
2151 * should work even if they are not inside a non-static member function
2155 // Find enclosing struct or class
2156 for (Dsymbol
*s
= sc
->parent
; 1; s
= s
->parent
)
2158 ClassDeclaration
*cd
;
2159 StructDeclaration
*sd
;
2163 error("%s is not in a struct or class scope", toChars());
2166 cd
= s
->isClassDeclaration();
2172 sd
= s
->isStructDeclaration();
2175 type
= sd
->type
->pointerTo();
2181 fdthis
= sc
->parent
->isFuncDeclaration();
2182 fd
= hasThis(sc
); // fd is the uplevel function with the 'this' variable
2188 assert(var
->parent
);
2190 var
->isVarDeclaration()->checkNestedReference(sc
, loc
);
2191 sc
->callSuper
|= CSXthis
;
2195 error("'this' is only defined in non-static member functions, not %s", sc
->parent
->toChars());
2196 type
= Type::terror
;
2200 int ThisExp::isBool(int result
)
2202 return result
? TRUE
: FALSE
;
2205 void ThisExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2207 buf
->writestring("this");
2210 Expression
*ThisExp::toLvalue(Scope
*sc
, Expression
*e
)
2215 /******************************** SuperExp **************************/
2217 SuperExp::SuperExp(Loc loc
)
2223 Expression
*SuperExp::semantic(Scope
*sc
)
2224 { FuncDeclaration
*fd
;
2225 FuncDeclaration
*fdthis
;
2226 ClassDeclaration
*cd
;
2230 printf("SuperExp::semantic('%s')\n", toChars());
2235 /* Special case for typeof(this) and typeof(super) since both
2236 * should work even if they are not inside a non-static member function
2240 // Find enclosing class
2241 for (Dsymbol
*s
= sc
->parent
; 1; s
= s
->parent
)
2243 ClassDeclaration
*cd
;
2247 error("%s is not in a class scope", toChars());
2250 cd
= s
->isClassDeclaration();
2255 { error("class %s has no 'super'", s
->toChars());
2264 fdthis
= sc
->parent
->isFuncDeclaration();
2270 assert(var
->parent
);
2273 while (s
&& s
->isTemplateInstance())
2276 cd
= s
->isClassDeclaration();
2277 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
2282 error("no base class for %s", cd
->toChars());
2283 type
= fd
->vthis
->type
;
2287 type
= cd
->baseClass
->type
;
2290 var
->isVarDeclaration()->checkNestedReference(sc
, loc
);
2292 sc
->callSuper
|= CSXsuper
;
2297 error("'super' is only allowed in non-static class member functions");
2298 type
= Type::tint32
;
2302 void SuperExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2304 buf
->writestring("super");
2308 /******************************** NullExp **************************/
2310 NullExp::NullExp(Loc loc
)
2311 : Expression(loc
, TOKnull
, sizeof(NullExp
))
2317 Expression
*NullExp::semantic(Scope
*sc
)
2320 printf("NullExp::semantic('%s')\n", toChars());
2322 // NULL is the same as (void *)0
2324 type
= Type::tvoid
->pointerTo();
2328 int NullExp::isBool(int result
)
2330 return result
? FALSE
: TRUE
;
2333 void NullExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2335 buf
->writestring("null");
2338 void NullExp::toMangleBuffer(OutBuffer
*buf
)
2340 buf
->writeByte('n');
2343 /******************************** StringExp **************************/
2345 StringExp::StringExp(Loc loc
, char *string
)
2346 : Expression(loc
, TOKstring
, sizeof(StringExp
))
2348 this->string
= string
;
2349 this->len
= strlen(string
);
2351 this->committed
= 0;
2355 StringExp::StringExp(Loc loc
, void *string
, size_t len
)
2356 : Expression(loc
, TOKstring
, sizeof(StringExp
))
2358 this->string
= string
;
2361 this->committed
= 0;
2365 StringExp::StringExp(Loc loc
, void *string
, size_t len
, unsigned char postfix
)
2366 : Expression(loc
, TOKstring
, sizeof(StringExp
))
2368 this->string
= string
;
2371 this->committed
= 0;
2372 this->postfix
= postfix
;
2376 Expression
*StringExp::syntaxCopy()
2378 printf("StringExp::syntaxCopy() %s\n", toChars());
2383 int StringExp::equals(Object
*o
)
2385 //printf("StringExp::equals('%s')\n", o->toChars());
2386 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
)
2387 { Expression
*e
= (Expression
*)o
;
2389 if (e
->op
== TOKstring
)
2391 return compare(o
) == 0;
2397 char *StringExp::toChars()
2403 memset(&hgs
, 0, sizeof(hgs
));
2404 toCBuffer(&buf
, &hgs
);
2406 p
= (char *)buf
.data
;
2411 Expression
*StringExp::semantic(Scope
*sc
)
2414 printf("StringExp::semantic() %s\n", toChars());
2426 for (u
= 0; u
< len
;)
2428 p
= utf_decodeChar((unsigned char *)string
, len
, &u
, &c
);
2439 string
= buffer
.extractData();
2442 type
= new TypeSArray(Type::tdchar
, new IntegerExp(loc
, len
, Type::tindex
));
2447 for (u
= 0; u
< len
;)
2449 p
= utf_decodeChar((unsigned char *)string
, len
, &u
, &c
);
2455 { buffer
.writeUTF16(c
);
2461 buffer
.writeUTF16(0);
2462 string
= buffer
.extractData();
2465 type
= new TypeSArray(Type::twchar
, new IntegerExp(loc
, len
, Type::tindex
));
2472 type
= new TypeSArray(Type::tchar
, new IntegerExp(loc
, len
, Type::tindex
));
2475 type
= type
->semantic(loc
, sc
);
2476 type
= type
->invariantOf();
2477 //printf("type = %s\n", type->toChars());
2482 /****************************************
2483 * Convert string to char[].
2486 StringExp
*StringExp::toUTF8(Scope
*sc
)
2489 { // Convert to UTF-8 string
2491 Expression
*e
= castTo(sc
, Type::tchar
->arrayOf());
2492 e
= e
->optimize(WANTvalue
);
2493 assert(e
->op
== TOKstring
);
2494 StringExp
*se
= (StringExp
*)e
;
2495 assert(se
->sz
== 1);
2501 int StringExp::compare(Object
*obj
)
2503 // Used to sort case statement expressions so we can do an efficient lookup
2504 StringExp
*se2
= (StringExp
*)(obj
);
2506 // This is a kludge so isExpression() in template.c will return 5
2511 assert(se2
->op
== TOKstring
);
2514 int len2
= se2
->len
;
2521 return strcmp((char *)string
, (char *)se2
->string
);
2525 d_wchar
*s1
= (d_wchar
*)string
;
2526 d_wchar
*s2
= (d_wchar
*)se2
->string
;
2528 for (u
= 0; u
< len
; u
++)
2531 return s1
[u
] - s2
[u
];
2537 d_dchar
*s1
= (d_dchar
*)string
;
2538 d_dchar
*s2
= (d_dchar
*)se2
->string
;
2540 for (u
= 0; u
< len
; u
++)
2543 return s1
[u
] - s2
[u
];
2555 int StringExp::isBool(int result
)
2557 return result
? TRUE
: FALSE
;
2560 unsigned StringExp::charAt(size_t i
)
2566 value
= ((unsigned char *)string
)[i
];
2570 value
= ((unsigned short *)string
)[i
];
2574 value
= ((unsigned int *)string
)[i
];
2584 void StringExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2586 buf
->writeByte('"');
2587 for (size_t i
= 0; i
< len
; i
++)
2588 { unsigned c
= charAt(i
);
2595 buf
->writeByte('\\');
2598 { if (c
<= 0x7F && (isprint(c
) || hgs
->console
))
2601 buf
->printf("\\x%02x", c
);
2603 else if (c
<= 0xFFFF)
2604 buf
->printf("\\x%02x\\x%02x", c
& 0xFF, c
>> 8);
2606 buf
->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2607 c
& 0xFF, (c
>> 8) & 0xFF, (c
>> 16) & 0xFF, c
>> 24);
2611 buf
->writeByte('"');
2613 buf
->writeByte(postfix
);
2616 void StringExp::toMangleBuffer(OutBuffer
*buf
)
2625 /* Write string in UTF-8 format
2630 q
= (unsigned char *)string
;
2635 for (u
= 0; u
< len
; )
2637 p
= utf_decodeWchar((unsigned short *)string
, len
, &u
, &c
);
2648 for (u
= 0; u
< len
; u
++)
2650 c
= ((unsigned *)string
)[u
];
2651 if (!utf_isValidDchar(c
))
2652 error("invalid UCS-32 char \\U%08x", c
);
2663 buf
->printf("%d_", qlen
);
2664 for (size_t i
= 0; i
< qlen
; i
++)
2665 buf
->printf("%02x", q
[i
]);
2668 /************************ ArrayLiteralExp ************************************/
2670 // [ e1, e2, e3, ... ]
2672 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expressions
*elements
)
2673 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
2675 this->elements
= elements
;
2678 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expression
*e
)
2679 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
2681 elements
= new Expressions
;
2685 Expression
*ArrayLiteralExp::syntaxCopy()
2687 return new ArrayLiteralExp(loc
, arraySyntaxCopy(elements
));
2690 Expression
*ArrayLiteralExp::semantic(Scope
*sc
)
2695 printf("ArrayLiteralExp::semantic('%s')\n", toChars());
2700 // Run semantic() on each element
2701 for (int i
= 0; i
< elements
->dim
; i
++)
2702 { e
= (Expression
*)elements
->data
[i
];
2703 e
= e
->semantic(sc
);
2704 elements
->data
[i
] = (void *)e
;
2706 expandTuples(elements
);
2707 for (int i
= 0; i
< elements
->dim
; i
++)
2708 { e
= (Expression
*)elements
->data
[i
];
2711 error("%s has no value", e
->toChars());
2712 e
= resolveProperties(sc
, e
);
2714 unsigned char committed
= 1;
2715 if (e
->op
== TOKstring
)
2716 committed
= ((StringExp
*)e
)->committed
;
2720 // Convert any static arrays to dynamic arrays
2721 if (t0
->ty
== Tsarray
)
2723 t0
= ((TypeSArray
*)t0
)->next
->arrayOf();
2724 e
= e
->implicitCastTo(sc
, t0
);
2728 e
= e
->implicitCastTo(sc
, t0
);
2729 if (!committed
&& e
->op
== TOKstring
)
2730 { StringExp
*se
= (StringExp
*)e
;
2733 elements
->data
[i
] = (void *)e
;
2738 type
= new TypeSArray(t0
, new IntegerExp(elements
->dim
));
2739 type
= type
->semantic(loc
, sc
);
2743 int ArrayLiteralExp::checkSideEffect(int flag
)
2746 for (size_t i
= 0; i
< elements
->dim
; i
++)
2747 { Expression
*e
= (Expression
*)elements
->data
[i
];
2749 f
|= e
->checkSideEffect(2);
2751 if (flag
== 0 && f
== 0)
2752 Expression::checkSideEffect(0);
2756 int ArrayLiteralExp::isBool(int result
)
2758 size_t dim
= elements
? elements
->dim
: 0;
2759 return result
? (dim
!= 0) : (dim
== 0);
2762 int ArrayLiteralExp::canThrow()
2764 return 1; // because it can fail allocating memory
2767 void ArrayLiteralExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2769 buf
->writeByte('[');
2770 argsToCBuffer(buf
, elements
, hgs
);
2771 buf
->writeByte(']');
2774 void ArrayLiteralExp::toMangleBuffer(OutBuffer
*buf
)
2776 size_t dim
= elements
? elements
->dim
: 0;
2777 buf
->printf("A%"PRIuSIZE
, dim
);
2778 for (size_t i
= 0; i
< dim
; i
++)
2779 { Expression
*e
= (Expression
*)elements
->data
[i
];
2780 e
->toMangleBuffer(buf
);
2784 /************************ AssocArrayLiteralExp ************************************/
2786 // [ key0 : value0, key1 : value1, ... ]
2788 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc
,
2789 Expressions
*keys
, Expressions
*values
)
2790 : Expression(loc
, TOKassocarrayliteral
, sizeof(AssocArrayLiteralExp
))
2792 assert(keys
->dim
== values
->dim
);
2794 this->values
= values
;
2797 Expression
*AssocArrayLiteralExp::syntaxCopy()
2799 return new AssocArrayLiteralExp(loc
,
2800 arraySyntaxCopy(keys
), arraySyntaxCopy(values
));
2803 Expression
*AssocArrayLiteralExp::semantic(Scope
*sc
)
2806 Type
*tvalue
= NULL
;
2809 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
2812 // Run semantic() on each element
2813 for (size_t i
= 0; i
< keys
->dim
; i
++)
2814 { Expression
*key
= (Expression
*)keys
->data
[i
];
2815 Expression
*value
= (Expression
*)values
->data
[i
];
2817 key
= key
->semantic(sc
);
2818 value
= value
->semantic(sc
);
2820 keys
->data
[i
] = (void *)key
;
2821 values
->data
[i
] = (void *)value
;
2824 expandTuples(values
);
2825 if (keys
->dim
!= values
->dim
)
2827 error("number of keys is %u, must match number of values %u", keys
->dim
, values
->dim
);
2831 for (size_t i
= 0; i
< keys
->dim
; i
++)
2832 { Expression
*key
= (Expression
*)keys
->data
[i
];
2833 Expression
*value
= (Expression
*)values
->data
[i
];
2836 error("%s has no value", key
->toChars());
2838 error("%s has no value", value
->toChars());
2839 key
= resolveProperties(sc
, key
);
2840 value
= resolveProperties(sc
, value
);
2845 key
= key
->implicitCastTo(sc
, tkey
);
2846 keys
->data
[i
] = (void *)key
;
2849 tvalue
= value
->type
;
2851 value
= value
->implicitCastTo(sc
, tvalue
);
2852 values
->data
[i
] = (void *)value
;
2858 tvalue
= Type::tvoid
;
2859 type
= new TypeAArray(tvalue
, tkey
);
2860 type
= type
->semantic(loc
, sc
);
2864 int AssocArrayLiteralExp::checkSideEffect(int flag
)
2867 for (size_t i
= 0; i
< keys
->dim
; i
++)
2868 { Expression
*key
= (Expression
*)keys
->data
[i
];
2869 Expression
*value
= (Expression
*)values
->data
[i
];
2871 f
|= key
->checkSideEffect(2);
2872 f
|= value
->checkSideEffect(2);
2874 if (flag
== 0 && f
== 0)
2875 Expression::checkSideEffect(0);
2879 int AssocArrayLiteralExp::isBool(int result
)
2881 size_t dim
= keys
->dim
;
2882 return result
? (dim
!= 0) : (dim
== 0);
2885 int AssocArrayLiteralExp::canThrow()
2890 void AssocArrayLiteralExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2892 buf
->writeByte('[');
2893 for (size_t i
= 0; i
< keys
->dim
; i
++)
2894 { Expression
*key
= (Expression
*)keys
->data
[i
];
2895 Expression
*value
= (Expression
*)values
->data
[i
];
2898 buf
->writeByte(',');
2899 expToCBuffer(buf
, hgs
, key
, PREC_assign
);
2900 buf
->writeByte(':');
2901 expToCBuffer(buf
, hgs
, value
, PREC_assign
);
2903 buf
->writeByte(']');
2906 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer
*buf
)
2908 size_t dim
= keys
->dim
;
2909 buf
->printf("A%u", dim
);
2910 for (size_t i
= 0; i
< dim
; i
++)
2911 { Expression
*key
= (Expression
*)keys
->data
[i
];
2912 Expression
*value
= (Expression
*)values
->data
[i
];
2914 key
->toMangleBuffer(buf
);
2915 value
->toMangleBuffer(buf
);
2919 /************************ StructLiteralExp ************************************/
2921 // sd( e1, e2, e3, ... )
2923 StructLiteralExp::StructLiteralExp(Loc loc
, StructDeclaration
*sd
, Expressions
*elements
)
2924 : Expression(loc
, TOKstructliteral
, sizeof(StructLiteralExp
))
2927 this->elements
= elements
;
2930 this->fillHoles
= 1;
2933 Expression
*StructLiteralExp::syntaxCopy()
2935 return new StructLiteralExp(loc
, sd
, arraySyntaxCopy(elements
));
2938 Expression
*StructLiteralExp::semantic(Scope
*sc
)
2942 printf("StructLiteralExp::semantic('%s')\n", toChars());
2947 // Run semantic() on each element
2948 for (size_t i
= 0; i
< elements
->dim
; i
++)
2949 { e
= (Expression
*)elements
->data
[i
];
2952 e
= e
->semantic(sc
);
2953 elements
->data
[i
] = (void *)e
;
2955 expandTuples(elements
);
2957 for (size_t i
= 0; i
< elements
->dim
; i
++)
2958 { e
= (Expression
*)elements
->data
[i
];
2963 error("%s has no value", e
->toChars());
2964 e
= resolveProperties(sc
, e
);
2965 if (i
>= sd
->fields
.dim
)
2966 { error("more initializers than fields of %s", sd
->toChars());
2969 Dsymbol
*s
= (Dsymbol
*)sd
->fields
.data
[i
];
2970 VarDeclaration
*v
= s
->isVarDeclaration();
2972 if (v
->offset
< offset
)
2973 error("overlapping initialization for %s", v
->toChars());
2974 offset
= v
->offset
+ v
->type
->size();
2976 Type
*telem
= v
->type
;
2977 while (!e
->implicitConvTo(telem
) && telem
->toBasetype()->ty
== Tsarray
)
2978 { /* Static array initialization, as in:
2981 telem
= telem
->toBasetype()->nextOf();
2984 e
= e
->implicitCastTo(sc
, telem
);
2986 elements
->data
[i
] = (void *)e
;
2989 /* Fill out remainder of elements[] with default initializers for fields[]
2991 for (size_t i
= elements
->dim
; i
< sd
->fields
.dim
; i
++)
2992 { Dsymbol
*s
= (Dsymbol
*)sd
->fields
.data
[i
];
2993 VarDeclaration
*v
= s
->isVarDeclaration();
2996 if (v
->offset
< offset
)
3003 { e
= v
->init
->toExpression();
3005 error("cannot make expression out of initializer for %s", v
->toChars());
3008 { e
= v
->type
->defaultInit();
3011 offset
= v
->offset
+ v
->type
->size();
3020 /**************************************
3021 * Gets expression at offset of type.
3022 * Returns NULL if not found.
3025 Expression
*StructLiteralExp::getField(Type
*type
, unsigned offset
)
3027 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
3028 // /*toChars()*/"", type->toChars(), offset);
3029 Expression
*e
= NULL
;
3030 int i
= getFieldIndex(type
, offset
);
3034 //printf("\ti = %d\n", i);
3035 assert(i
< elements
->dim
);
3036 e
= (Expression
*)elements
->data
[i
];
3046 /************************************
3047 * Get index of field.
3048 * Returns -1 if not found.
3051 int StructLiteralExp::getFieldIndex(Type
*type
, unsigned offset
)
3053 /* Find which field offset is by looking at the field offsets
3055 for (size_t i
= 0; i
< sd
->fields
.dim
; i
++)
3057 Dsymbol
*s
= (Dsymbol
*)sd
->fields
.data
[i
];
3058 VarDeclaration
*v
= s
->isVarDeclaration();
3061 if (offset
== v
->offset
&&
3062 type
->size() == v
->type
->size())
3063 { Expression
*e
= (Expression
*)elements
->data
[i
];
3075 Expression
*StructLiteralExp::toLvalue(Scope
*sc
, Expression
*e
)
3081 int StructLiteralExp::checkSideEffect(int flag
)
3084 for (size_t i
= 0; i
< elements
->dim
; i
++)
3085 { Expression
*e
= (Expression
*)elements
->data
[i
];
3089 f
|= e
->checkSideEffect(2);
3091 if (flag
== 0 && f
== 0)
3092 Expression::checkSideEffect(0);
3096 int StructLiteralExp::canThrow()
3098 return arrayExpressionCanThrow(elements
);
3101 void StructLiteralExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3103 buf
->writestring(sd
->toChars());
3104 buf
->writeByte('(');
3105 argsToCBuffer(buf
, elements
, hgs
);
3106 buf
->writeByte(')');
3109 void StructLiteralExp::toMangleBuffer(OutBuffer
*buf
)
3111 size_t dim
= elements
? elements
->dim
: 0;
3112 buf
->printf("S%u", dim
);
3113 for (size_t i
= 0; i
< dim
; i
++)
3114 { Expression
*e
= (Expression
*)elements
->data
[i
];
3116 e
->toMangleBuffer(buf
);
3118 buf
->writeByte('v'); // 'v' for void
3122 /************************ TypeDotIdExp ************************************/
3131 TypeDotIdExp::TypeDotIdExp(Loc loc
, Type
*type
, Identifier
*ident
)
3132 : Expression(loc
, TOKtypedot
, sizeof(TypeDotIdExp
))
3135 this->ident
= ident
;
3138 Expression
*TypeDotIdExp::syntaxCopy()
3140 TypeDotIdExp
*te
= new TypeDotIdExp(loc
, type
->syntaxCopy(), ident
);
3144 Expression
*TypeDotIdExp::semantic(Scope
*sc
)
3148 printf("TypeDotIdExp::semantic()\n");
3150 e
= new DotIdExp(loc
, new TypeExp(loc
, type
), ident
);
3151 e
= e
->semantic(sc
);
3155 void TypeDotIdExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3157 buf
->writeByte('(');
3158 type
->toCBuffer(buf
, NULL
, hgs
);
3159 buf
->writeByte(')');
3160 buf
->writeByte('.');
3161 buf
->writestring(ident
->toChars());
3164 /************************************************************/
3166 // Mainly just a placeholder
3168 TypeExp::TypeExp(Loc loc
, Type
*type
)
3169 : Expression(loc
, TOKtype
, sizeof(TypeExp
))
3171 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
3175 Expression
*TypeExp::semantic(Scope
*sc
)
3177 //printf("TypeExp::semantic(%s)\n", type->toChars());
3178 type
= type
->semantic(loc
, sc
);
3182 void TypeExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3184 type
->toCBuffer(buf
, NULL
, hgs
);
3187 /************************************************************/
3189 // Mainly just a placeholder
3191 ScopeExp::ScopeExp(Loc loc
, ScopeDsymbol
*pkg
)
3192 : Expression(loc
, TOKimport
, sizeof(ScopeExp
))
3194 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
3195 //static int count; if (++count == 38) *(char*)0=0;
3199 Expression
*ScopeExp::syntaxCopy()
3201 ScopeExp
*se
= new ScopeExp(loc
, (ScopeDsymbol
*)sds
->syntaxCopy(NULL
));
3205 Expression
*ScopeExp::semantic(Scope
*sc
)
3207 TemplateInstance
*ti
;
3211 printf("+ScopeExp::semantic('%s')\n", toChars());
3214 ti
= sds
->isTemplateInstance();
3215 if (ti
&& !global
.errors
)
3217 if (!ti
->semanticdone
)
3219 s
= ti
->inst
->toAlias();
3220 sds2
= s
->isScopeDsymbol();
3224 //printf("s = %s, '%s'\n", s->kind(), s->toChars());
3228 e
= new VarExp(loc
, ti
->withsym
->withstate
->wthis
);
3229 e
= new DotVarExp(loc
, e
, s
->isDeclaration());
3232 e
= new DsymbolExp(loc
, s
);
3233 e
= e
->semantic(sc
);
3234 //printf("-1ScopeExp::semantic()\n");
3242 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3246 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3247 //printf("\tparent = '%s'\n", sds->parent->toChars());
3251 //printf("-2ScopeExp::semantic() %s\n", toChars());
3255 void ScopeExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3257 if (sds
->isTemplateInstance())
3259 sds
->toCBuffer(buf
, hgs
);
3263 buf
->writestring(sds
->kind());
3264 buf
->writestring(" ");
3265 buf
->writestring(sds
->toChars());
3269 /********************** TemplateExp **************************************/
3271 // Mainly just a placeholder
3273 TemplateExp::TemplateExp(Loc loc
, TemplateDeclaration
*td
)
3274 : Expression(loc
, TOKtemplate
, sizeof(TemplateExp
))
3276 //printf("TemplateExp(): %s\n", td->toChars());
3280 void TemplateExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3282 buf
->writestring(td
->toChars());
3285 void TemplateExp::rvalue()
3287 error("template %s has no value", toChars());
3290 /********************** NewExp **************************************/
3292 NewExp::NewExp(Loc loc
, Expression
*thisexp
, Expressions
*newargs
,
3293 Type
*newtype
, Expressions
*arguments
)
3294 : Expression(loc
, TOKnew
, sizeof(NewExp
))
3296 this->thisexp
= thisexp
;
3297 this->newargs
= newargs
;
3298 this->newtype
= newtype
;
3299 this->arguments
= arguments
;
3305 Expression
*NewExp::syntaxCopy()
3307 return new NewExp(loc
,
3308 thisexp
? thisexp
->syntaxCopy() : NULL
,
3309 arraySyntaxCopy(newargs
),
3310 newtype
->syntaxCopy(), arraySyntaxCopy(arguments
));
3314 Expression
*NewExp::semantic(Scope
*sc
)
3317 ClassDeclaration
*cdthis
= NULL
;
3320 printf("NewExp::semantic() %s\n", toChars());
3322 printf("\tthisexp = %s\n", thisexp
->toChars());
3323 printf("\tnewtype: %s\n", newtype
->toChars());
3325 if (type
) // if semantic() already run
3330 { thisexp
= thisexp
->semantic(sc
);
3331 cdthis
= thisexp
->type
->isClassHandle();
3334 sc
= sc
->push(cdthis
);
3335 type
= newtype
->semantic(loc
, sc
);
3340 error("'this' for nested class must be a class type, not %s", thisexp
->type
->toChars());
3341 type
= newtype
->semantic(loc
, sc
);
3345 type
= newtype
->semantic(loc
, sc
);
3346 newtype
= type
; // in case type gets cast to something else
3347 tb
= type
->toBasetype();
3348 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
3350 arrayExpressionSemantic(newargs
, sc
);
3351 preFunctionArguments(loc
, sc
, newargs
);
3352 arrayExpressionSemantic(arguments
, sc
);
3353 preFunctionArguments(loc
, sc
, arguments
);
3355 if (thisexp
&& tb
->ty
!= Tclass
)
3356 error("e.new is only for allocating nested classes, not %s", tb
->toChars());
3358 if (tb
->ty
== Tclass
)
3361 TypeClass
*tc
= (TypeClass
*)(tb
);
3362 ClassDeclaration
*cd
= tc
->sym
->isClassDeclaration();
3363 if (cd
->isInterfaceDeclaration())
3364 error("cannot create instance of interface %s", cd
->toChars());
3365 else if (cd
->isAbstract())
3366 { error("cannot create instance of abstract class %s", cd
->toChars());
3367 for (int i
= 0; i
< cd
->vtbl
.dim
; i
++)
3368 { FuncDeclaration
*fd
= ((Dsymbol
*)cd
->vtbl
.data
[i
])->isFuncDeclaration();
3369 if (fd
&& fd
->isAbstract())
3370 error("function %s is abstract", fd
->toChars());
3373 checkDeprecated(sc
, cd
);
3375 { /* We need a 'this' pointer for the nested class.
3376 * Ensure we have the right one.
3378 Dsymbol
*s
= cd
->toParent2();
3379 ClassDeclaration
*cdn
= s
->isClassDeclaration();
3380 FuncDeclaration
*fdn
= s
->isFuncDeclaration();
3382 //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
3387 // Supply an implicit 'this' and try again
3388 thisexp
= new ThisExp(loc
);
3389 for (Dsymbol
*sp
= sc
->parent
; 1; sp
= sp
->parent
)
3392 error("outer class %s 'this' needed to 'new' nested class %s", cdn
->toChars(), cd
->toChars());
3395 ClassDeclaration
*cdp
= sp
->isClassDeclaration();
3398 if (cdp
== cdn
|| cdn
->isBaseOf(cdp
, NULL
))
3400 // Add a '.outer' and try again
3401 thisexp
= new DotIdExp(loc
, thisexp
, Id::outer
);
3408 //printf("cdthis = %s\n", cdthis->toChars());
3409 if (cdthis
!= cdn
&& !cdn
->isBaseOf(cdthis
, NULL
))
3410 error("'this' for nested class must be of type %s, not %s", cdn
->toChars(), thisexp
->type
->toChars());
3415 for (Dsymbol
*sf
= sc
->func
; 1; sf
= sf
->toParent2()->isFuncDeclaration())
3419 error("outer class %s 'this' needed to 'new' nested class %s", cdn
->toChars(), cd
->toChars());
3422 printf("sf = %s\n", sf
->toChars());
3423 AggregateDeclaration
*ad
= sf
->isThis();
3424 if (ad
&& (ad
== cdn
|| cdn
->isBaseOf(ad
->isClassDeclaration(), NULL
)))
3431 { /* The nested class cd is nested inside a function,
3432 * we'll let getEthis() look for errors.
3434 //printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars());
3436 // Because thisexp cannot be a function frame pointer
3437 error("e.new is only for allocating nested classes");
3443 error("e.new is only for allocating nested classes");
3445 FuncDeclaration
*f
= cd
->ctor
;
3449 f
= f
->overloadResolve(loc
, NULL
, arguments
);
3450 checkDeprecated(sc
, f
);
3451 member
= f
->isCtorDeclaration();
3454 cd
->accessCheck(loc
, sc
, member
);
3456 tf
= (TypeFunction
*)f
->type
;
3460 arguments
= new Expressions();
3461 functionArguments(loc
, sc
, tf
, arguments
);
3465 if (arguments
&& arguments
->dim
)
3466 error("no constructor for %s", cd
->toChars());
3474 // Prepend the uint size argument to newargs[]
3475 e
= new IntegerExp(loc
, cd
->size(loc
), Type::tsize_t
);
3477 newargs
= new Expressions();
3480 f
= f
->overloadResolve(loc
, NULL
, newargs
);
3481 allocator
= f
->isNewDeclaration();
3484 tf
= (TypeFunction
*)f
->type
;
3485 functionArguments(loc
, sc
, tf
, newargs
);
3489 if (newargs
&& newargs
->dim
)
3490 error("no allocator for %s", cd
->toChars());
3494 else if (tb
->ty
== Tstruct
)
3496 TypeStruct
*ts
= (TypeStruct
*)tb
;
3497 StructDeclaration
*sd
= ts
->sym
;
3498 FuncDeclaration
*f
= sd
->aggNew
;
3501 if (arguments
&& arguments
->dim
)
3502 error("no constructor for %s", type
->toChars());
3508 // Prepend the uint size argument to newargs[]
3509 e
= new IntegerExp(loc
, sd
->size(loc
), Type::tsize_t
);
3511 newargs
= new Expressions();
3514 f
= f
->overloadResolve(loc
, NULL
, newargs
);
3515 allocator
= f
->isNewDeclaration();
3518 tf
= (TypeFunction
*)f
->type
;
3519 functionArguments(loc
, sc
, tf
, newargs
);
3521 e
= new VarExp(loc
, f
);
3522 e
= new CallExp(loc
, e
, newargs
);
3523 e
= e
->semantic(sc
);
3524 e
->type
= type
->pointerTo();
3528 type
= type
->pointerTo();
3530 else if (tb
->ty
== Tarray
&& (arguments
&& arguments
->dim
))
3532 for (size_t i
= 0; i
< arguments
->dim
; i
++)
3534 if (tb
->ty
!= Tarray
)
3535 { error("too many arguments for array");
3540 Expression
*arg
= (Expression
*)arguments
->data
[i
];
3541 arg
= resolveProperties(sc
, arg
);
3542 arg
= arg
->implicitCastTo(sc
, Type::tsize_t
);
3543 arg
= arg
->optimize(WANTvalue
);
3544 if (arg
->op
== TOKint64
&& (long long)arg
->toInteger() < 0)
3545 error("negative array index %s", arg
->toChars());
3546 arguments
->data
[i
] = (void *) arg
;
3547 tb
= ((TypeDArray
*)tb
)->next
->toBasetype();
3550 else if (tb
->isscalar())
3552 if (arguments
&& arguments
->dim
)
3553 error("no constructor for %s", type
->toChars());
3555 type
= type
->pointerTo();
3559 error("new can only create structs, dynamic arrays or class objects, not %s's", type
->toChars());
3560 type
= type
->pointerTo();
3563 //printf("NewExp: '%s'\n", toChars());
3564 //printf("NewExp:type '%s'\n", type->toChars());
3569 int NewExp::checkSideEffect(int flag
)
3574 int NewExp::canThrow()
3579 void NewExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3583 { expToCBuffer(buf
, hgs
, thisexp
, PREC_primary
);
3584 buf
->writeByte('.');
3586 buf
->writestring("new ");
3587 if (newargs
&& newargs
->dim
)
3589 buf
->writeByte('(');
3590 argsToCBuffer(buf
, newargs
, hgs
);
3591 buf
->writeByte(')');
3593 newtype
->toCBuffer(buf
, NULL
, hgs
);
3594 if (arguments
&& arguments
->dim
)
3596 buf
->writeByte('(');
3597 argsToCBuffer(buf
, arguments
, hgs
);
3598 buf
->writeByte(')');
3602 /********************** NewAnonClassExp **************************************/
3604 NewAnonClassExp::NewAnonClassExp(Loc loc
, Expression
*thisexp
,
3605 Expressions
*newargs
, ClassDeclaration
*cd
, Expressions
*arguments
)
3606 : Expression(loc
, TOKnewanonclass
, sizeof(NewAnonClassExp
))
3608 this->thisexp
= thisexp
;
3609 this->newargs
= newargs
;
3611 this->arguments
= arguments
;
3614 Expression
*NewAnonClassExp::syntaxCopy()
3616 return new NewAnonClassExp(loc
,
3617 thisexp
? thisexp
->syntaxCopy() : NULL
,
3618 arraySyntaxCopy(newargs
),
3619 (ClassDeclaration
*)cd
->syntaxCopy(NULL
),
3620 arraySyntaxCopy(arguments
));
3624 Expression
*NewAnonClassExp::semantic(Scope
*sc
)
3627 printf("NewAnonClassExp::semantic() %s\n", toChars());
3628 //printf("type: %s\n", type->toChars());
3631 Expression
*d
= new DeclarationExp(loc
, cd
);
3632 d
= d
->semantic(sc
);
3634 Expression
*n
= new NewExp(loc
, thisexp
, newargs
, cd
->type
, arguments
);
3636 Expression
*c
= new CommaExp(loc
, d
, n
);
3637 return c
->semantic(sc
);
3640 int NewAnonClassExp::checkSideEffect(int flag
)
3645 int NewAnonClassExp::canThrow()
3650 void NewAnonClassExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3654 { expToCBuffer(buf
, hgs
, thisexp
, PREC_primary
);
3655 buf
->writeByte('.');
3657 buf
->writestring("new");
3658 if (newargs
&& newargs
->dim
)
3660 buf
->writeByte('(');
3661 argsToCBuffer(buf
, newargs
, hgs
);
3662 buf
->writeByte(')');
3664 buf
->writestring(" class ");
3665 if (arguments
&& arguments
->dim
)
3667 buf
->writeByte('(');
3668 argsToCBuffer(buf
, arguments
, hgs
);
3669 buf
->writeByte(')');
3671 //buf->writestring(" { }");
3674 cd
->toCBuffer(buf
, hgs
);
3678 /********************** SymOffExp **************************************/
3680 SymbolExp::SymbolExp(Loc loc
, enum TOK op
, int size
, Declaration
*var
, int hasOverloads
)
3681 : Expression(loc
, op
, size
)
3685 this->hasOverloads
= hasOverloads
;
3688 /********************** SymOffExp **************************************/
3690 SymOffExp::SymOffExp(Loc loc
, Declaration
*var
, target_size_t offset
, int hasOverloads
)
3691 : SymbolExp(loc
, TOKsymoff
, sizeof(SymOffExp
), var
, hasOverloads
)
3693 this->offset
= offset
;
3695 VarDeclaration
*v
= var
->isVarDeclaration();
3696 if (v
&& v
->needThis())
3697 error("need 'this' for address of %s", v
->toChars());
3700 Expression
*SymOffExp::semantic(Scope
*sc
)
3703 printf("SymOffExp::semantic('%s')\n", toChars());
3705 //var->semantic(sc);
3707 type
= var
->type
->pointerTo();
3708 VarDeclaration
*v
= var
->isVarDeclaration();
3710 v
->checkNestedReference(sc
, loc
);
3714 int SymOffExp::isBool(int result
)
3716 return result
? TRUE
: FALSE
;
3719 void SymOffExp::checkEscape()
3721 VarDeclaration
*v
= var
->isVarDeclaration();
3724 if (!v
->isDataseg())
3725 error("escaping reference to local variable %s", v
->toChars());
3729 void SymOffExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3732 buf
->printf("(& %s+%"PRIuTSIZE
")", var
->toChars(), offset
);
3734 buf
->printf("& %s", var
->toChars());
3737 /******************************** VarExp **************************/
3739 VarExp::VarExp(Loc loc
, Declaration
*var
, int hasOverloads
)
3740 : SymbolExp(loc
, TOKvar
, sizeof(VarExp
), var
, hasOverloads
)
3742 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
3743 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
3744 this->type
= var
->type
;
3747 int VarExp::equals(Object
*o
)
3751 (((Expression
*)o
)->op
== TOKvar
&&
3752 ((ne
= (VarExp
*)o
), type
->toHeadMutable()->equals(ne
->type
->toHeadMutable())) &&
3758 Expression
*VarExp::semantic(Scope
*sc
)
3759 { FuncLiteralDeclaration
*fd
;
3762 printf("VarExp::semantic(%s)\n", toChars());
3767 if (var
->storage_class
& STClazy
)
3769 TypeFunction
*tf
= new TypeFunction(NULL
, type
, 0, LINKd
);
3770 type
= new TypeDelegate(tf
);
3771 type
= type
->semantic(loc
, sc
);
3776 VarDeclaration
*v
= var
->isVarDeclaration();
3780 if ((v
->isConst() || v
->isInvariant()) &&
3781 type
->toBasetype()->ty
!= Tsarray
&& v
->init
)
3783 ExpInitializer
*ei
= v
->init
->isExpInitializer();
3786 //ei->exp->implicitCastTo(sc, type)->print();
3787 return ei
->exp
->implicitCastTo(sc
, type
);
3791 v
->checkNestedReference(sc
, loc
);
3794 else if ((fd
= var
->isFuncLiteralDeclaration()) != NULL
)
3796 e
= new FuncExp(loc
, fd
);
3804 char *VarExp::toChars()
3806 return var
->toChars();
3809 void VarExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3811 buf
->writestring(var
->toChars());
3814 void VarExp::checkEscape()
3816 VarDeclaration
*v
= var
->isVarDeclaration();
3818 { Type
*tb
= v
->type
->toBasetype();
3819 // if reference type
3820 if (tb
->ty
== Tarray
|| tb
->ty
== Tsarray
|| tb
->ty
== Tclass
)
3822 if ((v
->isAuto() || v
->isScope()) && !v
->noauto
)
3823 error("escaping reference to auto local %s", v
->toChars());
3824 else if (v
->storage_class
& STCvariadic
)
3825 error("escaping reference to variadic parameter %s", v
->toChars());
3830 Expression
*VarExp::toLvalue(Scope
*sc
, Expression
*e
)
3833 tym
= tybasic(e1
->ET
->Tty
);
3834 if (!(tyscalar(tym
) ||
3836 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
3837 synerr(EM_lvalue
); // lvalue expected
3839 if (var
->storage_class
& STClazy
)
3840 error("lazy variables cannot be lvalues");
3844 Expression
*VarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
3846 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
3847 if (type
&& type
->toBasetype()->ty
== Tsarray
)
3848 error("cannot change reference to static array '%s'", var
->toChars());
3850 var
->checkModify(loc
, sc
, type
);
3852 // See if this expression is a modifiable lvalue (i.e. not const)
3853 return toLvalue(sc
, e
);
3857 /******************************** OverExp **************************/
3859 OverExp::OverExp(OverloadSet
*s
)
3860 : Expression(loc
, TOKoverloadset
, sizeof(OverExp
))
3862 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
3867 Expression
*OverExp::toLvalue(Scope
*sc
, Expression
*e
)
3873 /******************************** TupleExp **************************/
3875 TupleExp::TupleExp(Loc loc
, Expressions
*exps
)
3876 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
3878 //printf("TupleExp(this = %p)\n", this);
3884 TupleExp::TupleExp(Loc loc
, TupleDeclaration
*tup
)
3885 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
3887 exps
= new Expressions();
3890 exps
->reserve(tup
->objects
->dim
);
3891 for (size_t i
= 0; i
< tup
->objects
->dim
; i
++)
3892 { Object
*o
= (Object
*)tup
->objects
->data
[i
];
3893 if (o
->dyncast() == DYNCAST_EXPRESSION
)
3895 Expression
*e
= (Expression
*)o
;
3896 e
= e
->syntaxCopy();
3899 else if (o
->dyncast() == DYNCAST_DSYMBOL
)
3901 Dsymbol
*s
= (Dsymbol
*)o
;
3902 Expression
*e
= new DsymbolExp(loc
, s
);
3905 else if (o
->dyncast() == DYNCAST_TYPE
)
3907 Type
*t
= (Type
*)o
;
3908 Expression
*e
= new TypeExp(loc
, t
);
3913 error("%s is not an expression", o
->toChars());
3918 int TupleExp::equals(Object
*o
)
3923 if (((Expression
*)o
)->op
== TOKtuple
)
3925 TupleExp
*te
= (TupleExp
*)o
;
3926 if (exps
->dim
!= te
->exps
->dim
)
3928 for (size_t i
= 0; i
< exps
->dim
; i
++)
3929 { Expression
*e1
= (Expression
*)exps
->data
[i
];
3930 Expression
*e2
= (Expression
*)te
->exps
->data
[i
];
3932 if (!e1
->equals(e2
))
3940 Expression
*TupleExp::syntaxCopy()
3942 return new TupleExp(loc
, arraySyntaxCopy(exps
));
3945 Expression
*TupleExp::semantic(Scope
*sc
)
3948 printf("+TupleExp::semantic(%s)\n", toChars());
3953 // Run semantic() on each argument
3954 for (size_t i
= 0; i
< exps
->dim
; i
++)
3955 { Expression
*e
= (Expression
*)exps
->data
[i
];
3957 e
= e
->semantic(sc
);
3959 { error("%s has no value", e
->toChars());
3960 e
->type
= Type::terror
;
3962 exps
->data
[i
] = (void *)e
;
3966 if (0 && exps
->dim
== 1)
3968 return (Expression
*)exps
->data
[0];
3970 type
= new TypeTuple(exps
);
3971 //printf("-TupleExp::semantic(%s)\n", toChars());
3975 void TupleExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3977 buf
->writestring("tuple(");
3978 argsToCBuffer(buf
, exps
, hgs
);
3979 buf
->writeByte(')');
3982 int TupleExp::checkSideEffect(int flag
)
3985 for (int i
= 0; i
< exps
->dim
; i
++)
3986 { Expression
*e
= (Expression
*)exps
->data
[i
];
3988 f
|= e
->checkSideEffect(2);
3990 if (flag
== 0 && f
== 0)
3991 Expression::checkSideEffect(0);
3995 int TupleExp::canThrow()
3997 return arrayExpressionCanThrow(exps
);
4000 void TupleExp::checkEscape()
4002 for (size_t i
= 0; i
< exps
->dim
; i
++)
4003 { Expression
*e
= (Expression
*)exps
->data
[i
];
4008 /******************************** FuncExp *********************************/
4010 FuncExp::FuncExp(Loc loc
, FuncLiteralDeclaration
*fd
)
4011 : Expression(loc
, TOKfunction
, sizeof(FuncExp
))
4016 Expression
*FuncExp::syntaxCopy()
4018 return new FuncExp(loc
, (FuncLiteralDeclaration
*)fd
->syntaxCopy(NULL
));
4021 Expression
*FuncExp::semantic(Scope
*sc
)
4024 printf("FuncExp::semantic(%s)\n", toChars());
4029 fd
->parent
= sc
->parent
;
4040 if (!global
.errors
&& global
.params
.useInline
)
4045 // Type is a "delegate to" or "pointer to" the function literal
4048 type
= new TypeDelegate(fd
->type
);
4049 type
= type
->semantic(loc
, sc
);
4053 type
= fd
->type
->pointerTo();
4055 fd
->tookAddressOf
++;
4060 char *FuncExp::toChars()
4062 return fd
->toChars();
4065 void FuncExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4067 buf
->writestring(fd
->toChars());
4071 /******************************** DeclarationExp **************************/
4073 DeclarationExp::DeclarationExp(Loc loc
, Dsymbol
*declaration
)
4074 : Expression(loc
, TOKdeclaration
, sizeof(DeclarationExp
))
4076 this->declaration
= declaration
;
4079 Expression
*DeclarationExp::syntaxCopy()
4081 return new DeclarationExp(loc
, declaration
->syntaxCopy(NULL
));
4084 Expression
*DeclarationExp::semantic(Scope
*sc
)
4090 printf("DeclarationExp::semantic() %s\n", toChars());
4093 /* This is here to support extern(linkage) declaration,
4094 * where the extern(linkage) winds up being an AttribDeclaration
4097 Dsymbol
*s
= declaration
;
4099 AttribDeclaration
*ad
= declaration
->isAttribDeclaration();
4102 if (ad
->decl
&& ad
->decl
->dim
== 1)
4103 s
= (Dsymbol
*)ad
->decl
->data
[0];
4106 if (s
->isVarDeclaration())
4107 { // Do semantic() on initializer first, so:
4110 declaration
->semantic(sc
);
4111 s
->parent
= sc
->parent
;
4114 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
4115 // Insert into both local scope and function scope.
4116 // Must be unique in both.
4120 error("declaration %s is already defined", s
->toPrettyChars());
4122 { VarDeclaration
*v
= s
->isVarDeclaration();
4123 if (s
->isFuncDeclaration() &&
4124 !sc
->func
->localsymtab
->insert(s
))
4125 error("declaration %s is already defined in another scope in %s", s
->toPrettyChars(), sc
->func
->toChars());
4126 else if (!global
.params
.useDeprecated
)
4127 { // Disallow shadowing
4129 for (Scope
*scx
= sc
->enclosing
; scx
&& scx
->func
== sc
->func
; scx
= scx
->enclosing
)
4132 if (scx
->scopesym
&& scx
->scopesym
->symtab
&&
4133 (s2
= scx
->scopesym
->symtab
->lookup(s
->ident
)) != NULL
&&
4136 error("shadowing declaration %s is deprecated", s
->toPrettyChars());
4142 if (!s
->isVarDeclaration())
4144 declaration
->semantic(sc
);
4145 s
->parent
= sc
->parent
;
4149 declaration
->semantic2(sc
);
4152 declaration
->semantic3(sc
);
4154 if (!global
.errors
&& global
.params
.useInline
)
4155 declaration
->inlineScan();
4163 int DeclarationExp::checkSideEffect(int flag
)
4168 int DeclarationExp::canThrow()
4170 VarDeclaration
*v
= declaration
->isVarDeclaration();
4172 { ExpInitializer
*ie
= v
->init
->isExpInitializer();
4173 return ie
&& ie
->exp
->canThrow();
4178 void DeclarationExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4180 declaration
->toCBuffer(buf
, hgs
);
4184 /************************ TypeidExp ************************************/
4190 TypeidExp::TypeidExp(Loc loc
, Type
*typeidType
)
4191 : Expression(loc
, TOKtypeid
, sizeof(TypeidExp
))
4193 this->typeidType
= typeidType
;
4197 Expression
*TypeidExp::syntaxCopy()
4199 return new TypeidExp(loc
, typeidType
->syntaxCopy());
4203 Expression
*TypeidExp::semantic(Scope
*sc
)
4207 printf("TypeidExp::semantic()\n");
4209 typeidType
= typeidType
->semantic(loc
, sc
);
4210 e
= typeidType
->getTypeInfo(sc
);
4214 void TypeidExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4216 buf
->writestring("typeid(");
4217 typeidType
->toCBuffer(buf
, NULL
, hgs
);
4218 buf
->writeByte(')');
4221 /************************ TraitsExp ************************************/
4224 * __traits(identifier, args...)
4227 TraitsExp::TraitsExp(Loc loc
, Identifier
*ident
, Objects
*args
)
4228 : Expression(loc
, TOKtraits
, sizeof(TraitsExp
))
4230 this->ident
= ident
;
4235 Expression
*TraitsExp::syntaxCopy()
4237 return new TraitsExp(loc
, ident
, TemplateInstance::arraySyntaxCopy(args
));
4241 void TraitsExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4243 buf
->writestring("__traits(");
4244 buf
->writestring(ident
->toChars());
4247 for (int i
= 0; i
< args
->dim
; i
++)
4249 buf
->writeByte(',');
4250 Object
*oarg
= (Object
*)args
->data
[i
];
4251 ObjectToCBuffer(buf
, hgs
, oarg
);
4254 buf
->writeByte(')');
4257 /************************************************************/
4259 HaltExp::HaltExp(Loc loc
)
4260 : Expression(loc
, TOKhalt
, sizeof(HaltExp
))
4264 Expression
*HaltExp::semantic(Scope
*sc
)
4267 printf("HaltExp::semantic()\n");
4273 int HaltExp::checkSideEffect(int flag
)
4278 void HaltExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4280 buf
->writestring("halt");
4283 /************************************************************/
4285 IsExp::IsExp(Loc loc
, Type
*targ
, Identifier
*id
, enum TOK tok
,
4286 Type
*tspec
, enum TOK tok2
, TemplateParameters
*parameters
)
4287 : Expression(loc
, TOKis
, sizeof(IsExp
))
4292 this->tspec
= tspec
;
4294 this->parameters
= parameters
;
4297 Expression
*IsExp::syntaxCopy()
4299 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4300 TemplateParameters
*p
= NULL
;
4303 p
= new TemplateParameters();
4304 p
->setDim(parameters
->dim
);
4305 for (int i
= 0; i
< p
->dim
; i
++)
4306 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
4307 p
->data
[i
] = (void *)tp
->syntaxCopy();
4311 return new IsExp(loc
,
4315 tspec
? tspec
->syntaxCopy() : NULL
,
4320 Expression
*IsExp::semantic(Scope
*sc
)
4323 /* is(targ id tok tspec)
4324 * is(targ id == tok2)
4327 //printf("IsExp::semantic(%s)\n", toChars());
4328 if (id
&& !(sc
->flags
& SCOPEstaticif
))
4329 error("can only declare type aliases within static if conditionals");
4331 unsigned errors_save
= global
.errors
;
4333 global
.gag
++; // suppress printing of error messages
4334 targ
= targ
->semantic(loc
, sc
);
4336 unsigned gerrors
= global
.errors
;
4337 global
.errors
= errors_save
;
4339 if (gerrors
) // if any errors happened
4340 { // then condition is false
4343 else if (tok2
!= TOKreserved
)
4348 if (targ
->ty
!= Ttypedef
)
4350 tded
= ((TypeTypedef
*)targ
)->sym
->basetype
;
4354 if (targ
->ty
!= Tstruct
)
4356 if (((TypeStruct
*)targ
)->sym
->isUnionDeclaration())
4362 if (targ
->ty
!= Tstruct
)
4364 if (!((TypeStruct
*)targ
)->sym
->isUnionDeclaration())
4370 if (targ
->ty
!= Tclass
)
4372 if (((TypeClass
*)targ
)->sym
->isInterfaceDeclaration())
4378 if (targ
->ty
!= Tclass
)
4380 if (!((TypeClass
*)targ
)->sym
->isInterfaceDeclaration())
4387 if (!targ
->isConst())
4393 if (!targ
->isInvariant())
4400 // If class or interface, get the base class and interfaces
4401 if (targ
->ty
!= Tclass
)
4404 { ClassDeclaration
*cd
= ((TypeClass
*)targ
)->sym
;
4405 Arguments
*args
= new Arguments
;
4406 args
->reserve(cd
->baseclasses
.dim
);
4407 for (size_t i
= 0; i
< cd
->baseclasses
.dim
; i
++)
4408 { BaseClass
*b
= (BaseClass
*)cd
->baseclasses
.data
[i
];
4409 args
->push(new Argument(STCin
, b
->type
, NULL
, NULL
));
4411 tded
= new TypeTuple(args
);
4416 if (targ
->ty
!= Tenum
)
4418 tded
= ((TypeEnum
*)targ
)->sym
->memtype
;
4422 if (targ
->ty
!= Tdelegate
)
4424 tded
= ((TypeDelegate
*)targ
)->next
; // the underlying function type
4429 if (targ
->ty
!= Tfunction
)
4433 /* Generate tuple from function parameter types.
4435 assert(tded
->ty
== Tfunction
);
4436 Arguments
*params
= ((TypeFunction
*)tded
)->parameters
;
4437 size_t dim
= Argument::dim(params
);
4438 Arguments
*args
= new Arguments
;
4440 for (size_t i
= 0; i
< dim
; i
++)
4441 { Argument
*arg
= Argument::getNth(params
, i
);
4442 assert(arg
&& arg
->type
);
4443 args
->push(new Argument(arg
->storageClass
, arg
->type
, NULL
, NULL
));
4445 tded
= new TypeTuple(args
);
4449 /* Get the 'return type' for the function,
4450 * delegate, or pointer to function.
4452 if (targ
->ty
== Tfunction
)
4453 tded
= ((TypeFunction
*)targ
)->next
;
4454 else if (targ
->ty
== Tdelegate
)
4455 { tded
= ((TypeDelegate
*)targ
)->next
;
4456 tded
= ((TypeFunction
*)tded
)->next
;
4458 else if (targ
->ty
== Tpointer
&&
4459 ((TypePointer
*)targ
)->next
->ty
== Tfunction
)
4460 { tded
= ((TypePointer
*)targ
)->next
;
4461 tded
= ((TypeFunction
*)tded
)->next
;
4472 else if (id
&& tspec
)
4474 /* Evaluate to TRUE if targ matches tspec.
4475 * If TRUE, declare id as an alias for the specialized type.
4479 assert(parameters
&& parameters
->dim
);
4482 dedtypes
.setDim(parameters
->dim
);
4485 m
= targ
->deduceType(NULL
, tspec
, parameters
, &dedtypes
);
4486 if (m
== MATCHnomatch
||
4487 (m
!= MATCHexact
&& tok
== TOKequal
))
4491 tded
= (Type
*)dedtypes
.data
[0];
4497 tiargs
.data
[0] = (void *)targ
;
4499 for (int i
= 1; i
< parameters
->dim
; i
++)
4500 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
4503 m
= tp
->matchArg(sc
, &tiargs
, i
, parameters
, &dedtypes
, &s
);
4504 if (m
== MATCHnomatch
)
4508 error("declaration %s is already defined", s
->toChars());
4510 Object
*o
= (Object
*)dedtypes
.data
[i
];
4511 Dsymbol
*s
= TemplateDeclaration::declareParameter(loc
, sc
, tp
, o
);
4514 s
->addMember(sc
, sc
->sd
, 1);
4522 /* Declare id as an alias for type targ. Evaluate to TRUE
4529 /* Evaluate to TRUE if targ matches tspec
4531 tspec
= tspec
->semantic(loc
, sc
);
4532 //printf("targ = %s\n", targ->toChars());
4533 //printf("tspec = %s\n", tspec->toChars());
4534 if (tok
== TOKcolon
)
4535 { if (targ
->implicitConvTo(tspec
))
4541 { if (targ
->equals(tspec
))
4551 Dsymbol
*s
= new AliasDeclaration(loc
, id
, tded
);
4554 error("declaration %s is already defined", s
->toChars());
4556 s
->addMember(sc
, sc
->sd
, 1);
4558 return new IntegerExp(loc
, 1, Type::tbool
);
4561 return new IntegerExp(loc
, 0, Type::tbool
);
4564 void IsExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4566 buf
->writestring("is(");
4567 targ
->toCBuffer(buf
, id
, hgs
);
4568 if (tok2
!= TOKreserved
)
4570 buf
->printf(" %s %s", Token::toChars(tok
), Token::toChars(tok2
));
4574 if (tok
== TOKcolon
)
4575 buf
->writestring(" : ");
4577 buf
->writestring(" == ");
4578 tspec
->toCBuffer(buf
, NULL
, hgs
);
4581 { // First parameter is already output, so start with second
4582 for (int i
= 1; i
< parameters
->dim
; i
++)
4584 buf
->writeByte(',');
4585 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
4586 tp
->toCBuffer(buf
, hgs
);
4589 buf
->writeByte(')');
4593 /************************************************************/
4595 UnaExp::UnaExp(Loc loc
, enum TOK op
, int size
, Expression
*e1
)
4596 : Expression(loc
, op
, size
)
4601 Expression
*UnaExp::syntaxCopy()
4604 e
= (UnaExp
*)copy();
4606 e
->e1
= e
->e1
->syntaxCopy();
4610 Expression
*UnaExp::semantic(Scope
*sc
)
4613 printf("UnaExp::semantic('%s')\n", toChars());
4615 e1
= e1
->semantic(sc
);
4617 // error("%s has no value", e1->toChars());
4621 int UnaExp::canThrow()
4623 return e1
->canThrow();
4626 void UnaExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4628 buf
->writestring(Token::toChars(op
));
4629 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
4632 /************************************************************/
4634 BinExp::BinExp(Loc loc
, enum TOK op
, int size
, Expression
*e1
, Expression
*e2
)
4635 : Expression(loc
, op
, size
)
4641 Expression
*BinExp::syntaxCopy()
4644 e
= (BinExp
*)copy();
4646 e
->e1
= e
->e1
->syntaxCopy();
4647 e
->e2
= e
->e2
->syntaxCopy();
4651 Expression
*BinExp::semantic(Scope
*sc
)
4654 printf("BinExp::semantic('%s')\n", toChars());
4656 e1
= e1
->semantic(sc
);
4659 error("%s has no value", e1
->toChars());
4660 e1
->type
= Type::terror
;
4662 e2
= e2
->semantic(sc
);
4665 error("%s has no value", e2
->toChars());
4666 e2
->type
= Type::terror
;
4672 Expression
*BinExp::semanticp(Scope
*sc
)
4674 BinExp::semantic(sc
);
4675 e1
= resolveProperties(sc
, e1
);
4676 e2
= resolveProperties(sc
, e2
);
4680 /***************************
4681 * Common semantic routine for some xxxAssignExp's.
4684 Expression
*BinExp::commonSemanticAssign(Scope
*sc
)
4689 BinExp::semantic(sc
);
4690 e2
= resolveProperties(sc
, e2
);
4692 e
= op_overload(sc
);
4696 e1
= e1
->modifiableLvalue(sc
, e1
);
4699 if (type
->toBasetype()->ty
== Tbool
)
4701 error("operator not allowed on bool expression %s", toChars());
4704 e1
->checkArithmetic();
4705 e2
->checkArithmetic();
4707 if (op
== TOKmodass
&& e2
->type
->iscomplex())
4708 { error("cannot perform modulo complex arithmetic");
4709 return new IntegerExp(0);
4715 Expression
*BinExp::commonSemanticAssignIntegral(Scope
*sc
)
4720 BinExp::semantic(sc
);
4721 e2
= resolveProperties(sc
, e2
);
4723 e
= op_overload(sc
);
4727 e1
= e1
->modifiableLvalue(sc
, e1
);
4730 if (type
->toBasetype()->ty
== Tbool
)
4732 e2
= e2
->implicitCastTo(sc
, type
);
4736 e1
->checkIntegral();
4737 e2
->checkIntegral();
4742 int BinExp::checkSideEffect(int flag
)
4744 if (op
== TOKplusplus
||
4745 op
== TOKminusminus
||
4747 op
== TOKconstruct
||
4764 return Expression::checkSideEffect(flag
);
4767 void BinExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4769 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
4770 buf
->writeByte(' ');
4771 buf
->writestring(Token::toChars(op
));
4772 buf
->writeByte(' ');
4773 expToCBuffer(buf
, hgs
, e2
, (enum PREC
)(precedence
[op
] + 1));
4776 int BinExp::isunsigned()
4778 return e1
->type
->isunsigned() || e2
->type
->isunsigned();
4781 int BinExp::canThrow()
4783 return e1
->canThrow() || e2
->canThrow();
4786 void BinExp::incompatibleTypes()
4788 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
4789 e1
->toChars(), Token::toChars(op
), e2
->toChars(),
4790 e1
->type
->toChars(), e2
->type
->toChars());
4793 /************************************************************/
4795 CompileExp::CompileExp(Loc loc
, Expression
*e
)
4796 : UnaExp(loc
, TOKmixin
, sizeof(CompileExp
), e
)
4800 Expression
*CompileExp::semantic(Scope
*sc
)
4803 printf("CompileExp::semantic('%s')\n", toChars());
4805 UnaExp::semantic(sc
);
4806 e1
= resolveProperties(sc
, e1
);
4807 e1
= e1
->optimize(WANTvalue
| WANTinterpret
);
4808 if (e1
->op
!= TOKstring
)
4809 { error("argument to mixin must be a string, not (%s)", e1
->toChars());
4810 type
= Type::terror
;
4813 StringExp
*se
= (StringExp
*)e1
;
4814 se
= se
->toUTF8(sc
);
4815 Parser
p(sc
->module
, (unsigned char *)se
->string
, se
->len
, 0);
4818 //printf("p.loc.linnum = %d\n", p.loc.linnum);
4819 Expression
*e
= p
.parseExpression();
4820 if (p
.token
.value
!= TOKeof
)
4821 error("incomplete mixin expression (%s)", se
->toChars());
4822 return e
->semantic(sc
);
4825 void CompileExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4827 buf
->writestring("mixin(");
4828 expToCBuffer(buf
, hgs
, e1
, PREC_assign
);
4829 buf
->writeByte(')');
4832 /************************************************************/
4834 FileExp::FileExp(Loc loc
, Expression
*e
)
4835 : UnaExp(loc
, TOKmixin
, sizeof(FileExp
), e
)
4839 Expression
*FileExp::semantic(Scope
*sc
)
4844 printf("FileExp::semantic('%s')\n", toChars());
4846 UnaExp::semantic(sc
);
4847 e1
= resolveProperties(sc
, e1
);
4848 e1
= e1
->optimize(WANTvalue
);
4849 if (e1
->op
!= TOKstring
)
4850 { error("file name argument must be a string, not (%s)", e1
->toChars());
4853 se
= (StringExp
*)e1
;
4854 se
= se
->toUTF8(sc
);
4855 name
= (char *)se
->string
;
4857 if (!global
.params
.fileImppath
)
4858 { error("need -Jpath switch to import text file %s", name
);
4862 if (name
!= FileName::name(name
))
4863 { error("use -Jpath switch to provide path for filename %s", name
);
4867 name
= FileName::searchPath(global
.filePath
, name
, 0);
4869 { error("file %s cannot be found, check -Jpath", se
->toChars());
4873 if (global
.params
.verbose
)
4874 printf("file %s\t(%s)\n", se
->string
, name
);
4878 { error("cannot read file %s", f
.toChars());
4884 se
= new StringExp(loc
, f
.buffer
, f
.len
);
4888 return se
->semantic(sc
);
4891 se
= new StringExp(loc
, "");
4895 void FileExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4897 buf
->writestring("import(");
4898 expToCBuffer(buf
, hgs
, e1
, PREC_assign
);
4899 buf
->writeByte(')');
4902 /************************************************************/
4904 AssertExp::AssertExp(Loc loc
, Expression
*e
, Expression
*msg
)
4905 : UnaExp(loc
, TOKassert
, sizeof(AssertExp
), e
)
4910 Expression
*AssertExp::syntaxCopy()
4912 AssertExp
*ae
= new AssertExp(loc
, e1
->syntaxCopy(),
4913 msg
? msg
->syntaxCopy() : NULL
);
4917 Expression
*AssertExp::semantic(Scope
*sc
)
4920 printf("AssertExp::semantic('%s')\n", toChars());
4922 UnaExp::semantic(sc
);
4923 e1
= resolveProperties(sc
, e1
);
4924 // BUG: see if we can do compile time elimination of the Assert
4925 e1
= e1
->optimize(WANTvalue
);
4926 e1
= e1
->checkToBoolean();
4929 msg
= msg
->semantic(sc
);
4930 msg
= resolveProperties(sc
, msg
);
4931 msg
= msg
->implicitCastTo(sc
, Type::tchar
->constOf()->arrayOf());
4932 msg
= msg
->optimize(WANTvalue
);
4934 if (e1
->isBool(FALSE
))
4936 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4937 fd
->hasReturnExp
|= 4;
4939 if (!global
.params
.useAssert
)
4940 { Expression
*e
= new HaltExp(loc
);
4941 e
= e
->semantic(sc
);
4949 int AssertExp::checkSideEffect(int flag
)
4954 int AssertExp::canThrow()
4956 return (global
.params
.useAssert
!= 0);
4959 void AssertExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4961 buf
->writestring("assert(");
4962 expToCBuffer(buf
, hgs
, e1
, PREC_assign
);
4965 buf
->writeByte(',');
4966 expToCBuffer(buf
, hgs
, msg
, PREC_assign
);
4968 buf
->writeByte(')');
4971 /************************************************************/
4973 DotIdExp::DotIdExp(Loc loc
, Expression
*e
, Identifier
*ident
)
4974 : UnaExp(loc
, TOKdot
, sizeof(DotIdExp
), e
)
4976 this->ident
= ident
;
4979 Expression
*DotIdExp::semantic(Scope
*sc
)
4985 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
4986 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
4989 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
4992 /* Don't do semantic analysis if we'll be converting
4995 if (ident
== Id::stringof
)
4996 { char *s
= e1
->toChars();
4997 e
= new StringExp(loc
, s
, strlen(s
), 'c');
4998 e
= e
->semantic(sc
);
5003 /* Special case: rewrite this.id and super.id
5004 * to be classtype.id and baseclasstype.id
5005 * if we have no this pointer.
5007 if ((e1
->op
== TOKthis
|| e1
->op
== TOKsuper
) && !hasThis(sc
))
5008 { ClassDeclaration
*cd
;
5009 StructDeclaration
*sd
;
5010 AggregateDeclaration
*ad
;
5012 ad
= sc
->getStructClassScope();
5015 cd
= ad
->isClassDeclaration();
5018 if (e1
->op
== TOKthis
)
5020 e
= new TypeDotIdExp(loc
, cd
->type
, ident
);
5021 return e
->semantic(sc
);
5023 else if (cd
->baseClass
&& e1
->op
== TOKsuper
)
5025 e
= new TypeDotIdExp(loc
, cd
->baseClass
->type
, ident
);
5026 return e
->semantic(sc
);
5031 sd
= ad
->isStructDeclaration();
5034 if (e1
->op
== TOKthis
)
5036 e
= new TypeDotIdExp(loc
, sd
->type
, ident
);
5037 return e
->semantic(sc
);
5044 UnaExp::semantic(sc
);
5046 if (e1
->op
== TOKdotexp
)
5048 DotExp
*de
= (DotExp
*)e1
;
5054 e1
= resolveProperties(sc
, e1
);
5059 if (e1
->op
== TOKtuple
&& ident
== Id::offsetof
)
5060 { /* 'distribute' the .offsetof to each of the tuple elements.
5062 TupleExp
*te
= (TupleExp
*)e1
;
5063 Expressions
*exps
= new Expressions();
5064 exps
->setDim(te
->exps
->dim
);
5065 for (int i
= 0; i
< exps
->dim
; i
++)
5066 { Expression
*e
= (Expression
*)te
->exps
->data
[i
];
5067 e
= e
->semantic(sc
);
5068 e
= new DotIdExp(e
->loc
, e
, Id::offsetof
);
5069 exps
->data
[i
] = (void *)e
;
5071 e
= new TupleExp(loc
, exps
);
5072 e
= e
->semantic(sc
);
5076 if (e1
->op
== TOKtuple
&& ident
== Id::length
)
5078 TupleExp
*te
= (TupleExp
*)e1
;
5079 e
= new IntegerExp(loc
, te
->exps
->dim
, Type::tsize_t
);
5083 if (eright
->op
== TOKimport
) // also used for template alias's
5086 ScopeExp
*ie
= (ScopeExp
*)eright
;
5088 s
= ie
->sds
->search(loc
, ident
, 0);
5092 checkDeprecated(sc
, s
);
5094 EnumMember
*em
= s
->isEnumMember();
5098 e
= e
->semantic(sc
);
5102 VarDeclaration
*v
= s
->isVarDeclaration();
5105 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
5108 error("circular reference to '%s'", v
->toChars());
5109 type
= Type::tint32
;
5114 if (v
->isConst() || v
->isInvariant())
5118 ExpInitializer
*ei
= v
->init
->isExpInitializer();
5121 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars());
5122 //ei->exp = ei->exp->semantic(sc);
5123 if (ei
->exp
->type
== type
)
5125 e
= ei
->exp
->copy(); // make copy so we can change loc
5131 else if (type
->isscalar())
5133 e
= type
->defaultInit();
5142 eleft
= new ThisExp(loc
);
5143 e
= new DotVarExp(loc
, eleft
, v
);
5144 e
= e
->semantic(sc
);
5148 e
= new VarExp(loc
, v
);
5150 { e
= new CommaExp(loc
, eleft
, e
);
5157 FuncDeclaration
*f
= s
->isFuncDeclaration();
5160 //printf("it's a function\n");
5164 eleft
= new ThisExp(loc
);
5165 e
= new DotVarExp(loc
, eleft
, f
);
5166 e
= e
->semantic(sc
);
5170 e
= new VarExp(loc
, f
, 1);
5172 { e
= new CommaExp(loc
, eleft
, e
);
5179 Type
*t
= s
->getType();
5182 return new TypeExp(loc
, t
);
5185 TupleDeclaration
*tup
= s
->isTupleDeclaration();
5189 error("cannot have e.tuple");
5190 e
= new TupleExp(loc
, tup
);
5191 e
= e
->semantic(sc
);
5195 ScopeDsymbol
*sds
= s
->isScopeDsymbol();
5198 //printf("it's a ScopeDsymbol\n");
5199 e
= new ScopeExp(loc
, sds
);
5200 e
= e
->semantic(sc
);
5202 e
= new DotExp(loc
, eleft
, e
);
5206 Import
*imp
= s
->isImport();
5211 ie
= new ScopeExp(loc
, imp
->pkg
);
5212 return ie
->semantic(sc
);
5215 // BUG: handle other cases like in IdentifierExp::semantic()
5217 printf("s = '%s', kind = '%s'\n", s
->toChars(), s
->kind());
5221 else if (ident
== Id::stringof
)
5222 { char *s
= ie
->toChars();
5223 e
= new StringExp(loc
, s
, strlen(s
), 'c');
5224 e
= e
->semantic(sc
);
5227 error("undefined identifier %s", toChars());
5231 else if (e1
->type
->ty
== Tpointer
&&
5232 ident
!= Id::init
&& ident
!= Id::__sizeof
&&
5233 ident
!= Id::alignof
&& ident
!= Id::offsetof
&&
5234 ident
!= Id::mangleof
&& ident
!= Id::stringof
)
5236 e
= new PtrExp(loc
, e1
);
5237 e
->type
= ((TypePointer
*)e1
->type
)->next
;
5238 return e
->type
->dotExp(sc
, e
, ident
);
5242 e
= e1
->type
->dotExp(sc
, e1
, ident
);
5243 e
= e
->semantic(sc
);
5248 void DotIdExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5250 //printf("DotIdExp::toCBuffer()\n");
5251 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5252 buf
->writeByte('.');
5253 buf
->writestring(ident
->toChars());
5256 /********************** DotTemplateExp ***********************************/
5258 // Mainly just a placeholder
5260 DotTemplateExp::DotTemplateExp(Loc loc
, Expression
*e
, TemplateDeclaration
*td
)
5261 : UnaExp(loc
, TOKdottd
, sizeof(DotTemplateExp
), e
)
5267 void DotTemplateExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5269 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5270 buf
->writeByte('.');
5271 buf
->writestring(td
->toChars());
5275 /************************************************************/
5277 DotVarExp::DotVarExp(Loc loc
, Expression
*e
, Declaration
*v
, int hasOverloads
)
5278 : UnaExp(loc
, TOKdotvar
, sizeof(DotVarExp
), e
)
5280 //printf("DotVarExp()\n");
5282 this->hasOverloads
= hasOverloads
;
5285 Expression
*DotVarExp::semantic(Scope
*sc
)
5288 printf("DotVarExp::semantic('%s')\n", toChars());
5292 var
= var
->toAlias()->isDeclaration();
5294 TupleDeclaration
*tup
= var
->isTupleDeclaration();
5299 * tuple(e1.a, e1.b, e1.c)
5301 Expressions
*exps
= new Expressions
;
5303 exps
->reserve(tup
->objects
->dim
);
5304 for (size_t i
= 0; i
< tup
->objects
->dim
; i
++)
5305 { Object
*o
= (Object
*)tup
->objects
->data
[i
];
5306 if (o
->dyncast() != DYNCAST_EXPRESSION
)
5308 error("%s is not an expression", o
->toChars());
5312 Expression
*e
= (Expression
*)o
;
5313 if (e
->op
!= TOKdsymbol
)
5314 error("%s is not a member", e
->toChars());
5316 { DsymbolExp
*ve
= (DsymbolExp
*)e
;
5318 e
= new DotVarExp(loc
, e1
, ve
->s
->isDeclaration());
5323 Expression
*e
= new TupleExp(loc
, exps
);
5324 e
= e
->semantic(sc
);
5328 e1
= e1
->semantic(sc
);
5331 if (!type
&& global
.errors
)
5332 { // var is goofed up, just return 0
5333 return new IntegerExp(0);
5337 if (!var
->isFuncDeclaration()) // for functions, do checks after overload resolution
5339 Type
*t1
= e1
->type
;
5340 if (t1
->ty
== Tpointer
)
5343 type
= type
->constOf();
5344 else if (t1
->isInvariant())
5345 type
= type
->invariantOf();
5347 AggregateDeclaration
*ad
= var
->toParent()->isAggregateDeclaration();
5348 e1
= getRightThis(loc
, sc
, ad
, e1
, var
);
5349 if (!sc
->noaccesscheck
)
5350 accessCheck(loc
, sc
, e1
, var
);
5353 //printf("-DotVarExp::semantic('%s')\n", toChars());
5357 Expression
*DotVarExp::toLvalue(Scope
*sc
, Expression
*e
)
5359 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5363 Expression
*DotVarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5366 printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
5367 printf("e1->type = %s\n", e1
->type
->toChars());
5368 printf("var->type = %s\n", var
->type
->toChars());
5371 // Also need this for non-null fields.
5372 VarDeclaration
*v
= var
->isVarDeclaration();
5373 if (v
) // When is it not a VarDeclaration?
5376 error("Just curious");
5378 if (var
->isCtorinit())
5379 { // It's only modifiable if inside the right constructor
5380 Dsymbol
*s
= sc
->func
;
5383 FuncDeclaration
*fd
= NULL
;
5385 fd
= s
->isFuncDeclaration();
5387 ((fd
->isCtorDeclaration() && var
->storage_class
& STCfield
) ||
5388 (fd
->isStaticCtorDeclaration() && !(var
->storage_class
& STCfield
))) &&
5389 fd
->toParent() == var
->toParent() &&
5393 VarDeclaration
*v
= var
->isVarDeclaration();
5396 //printf("setting ctorinit\n");
5401 { s
= s
->toParent2();
5406 const char *p
= var
->isStatic() ? "static " : "";
5407 error("can only initialize %sconst member %s inside %sconstructor",
5408 p
, var
->toChars(), p
);
5416 Type
*t1
= e1
->type
->toBasetype();
5418 if (!t1
->isMutable() ||
5419 (t1
->ty
== Tpointer
&& !t1
->nextOf()->isMutable()) ||
5420 !var
->type
->isMutable() ||
5421 !var
->type
->isAssignable() ||
5422 var
->storage_class
& STCmanifest
5424 error("cannot modify const/invariant %s", toChars());
5429 void DotVarExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5431 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5432 buf
->writeByte('.');
5433 buf
->writestring(var
->toChars());
5436 /************************************************************/
5442 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc
, Expression
*e
, TemplateInstance
*ti
)
5443 : UnaExp(loc
, TOKdotti
, sizeof(DotTemplateInstanceExp
), e
)
5445 //printf("DotTemplateInstanceExp()\n");
5449 Expression
*DotTemplateInstanceExp::syntaxCopy()
5451 DotTemplateInstanceExp
*de
= new DotTemplateInstanceExp(loc
,
5453 (TemplateInstance
*)ti
->syntaxCopy(NULL
));
5457 Expression
*DotTemplateInstanceExp::semantic(Scope
*sc
)
5460 TemplateDeclaration
*td
;
5464 Expression
*eleft
= NULL
;
5468 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
5472 e1
= e1
->semantic(sc
);
5475 t1
= t1
->toBasetype();
5478 /* Extract the following from e1:
5479 * s: the symbol which ti should be a member of
5480 * eleft: if not NULL, it is the 'this' pointer for ti
5483 if (e1
->op
== TOKdotexp
)
5484 { DotExp
*de
= (DotExp
*)e1
;
5492 if (eright
->op
== TOKimport
)
5494 s
= ((ScopeExp
*)eright
)->sds
;
5496 else if (e1
->op
== TOKtype
)
5498 s
= t1
->isClassHandle();
5500 { if (t1
->ty
== Tstruct
)
5501 s
= ((TypeStruct
*)t1
)->sym
;
5506 else if (t1
&& (t1
->ty
== Tstruct
|| t1
->ty
== Tclass
))
5508 s
= t1
->toDsymbol(sc
);
5511 else if (t1
&& t1
->ty
== Tpointer
)
5513 t1
= ((TypePointer
*)t1
)->next
->toBasetype();
5514 if (t1
->ty
!= Tstruct
)
5516 s
= t1
->toDsymbol(sc
);
5522 error("template %s is not a member of %s", ti
->toChars(), e1
->toChars());
5528 s2
= s
->search(loc
, id
, 0);
5530 { error("template identifier %s is not a member of %s %s", id
->toChars(), s
->kind(), s
->ident
->toChars());
5536 td
= s
->isTemplateDeclaration();
5539 error("%s is not a template", id
->toChars());
5551 s
= ti
->inst
->toAlias();
5552 v
= s
->isDeclaration();
5554 { e
= new DotVarExp(loc
, eleft
, v
);
5555 e
= e
->semantic(sc
);
5560 e
= new ScopeExp(loc
, ti
);
5563 e
= new DotExp(loc
, eleft
, e
);
5565 e
= e
->semantic(sc
);
5569 return new IntegerExp(0);
5572 void DotTemplateInstanceExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5574 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5575 buf
->writeByte('.');
5576 ti
->toCBuffer(buf
, hgs
);
5579 /************************************************************/
5581 DelegateExp::DelegateExp(Loc loc
, Expression
*e
, FuncDeclaration
*f
, int hasOverloads
)
5582 : UnaExp(loc
, TOKdelegate
, sizeof(DelegateExp
), e
)
5585 this->hasOverloads
= hasOverloads
;
5588 Expression
*DelegateExp::semantic(Scope
*sc
)
5591 printf("DelegateExp::semantic('%s')\n", toChars());
5595 e1
= e1
->semantic(sc
);
5596 type
= new TypeDelegate(func
->type
);
5597 type
= type
->semantic(loc
, sc
);
5598 AggregateDeclaration
*ad
= func
->toParent()->isAggregateDeclaration();
5599 if (func
->needThis())
5600 e1
= getRightThis(loc
, sc
, ad
, e1
, func
);
5605 void DelegateExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5607 buf
->writeByte('&');
5608 if (!func
->isNested())
5610 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5611 buf
->writeByte('.');
5613 buf
->writestring(func
->toChars());
5616 /************************************************************/
5618 DotTypeExp::DotTypeExp(Loc loc
, Expression
*e
, Dsymbol
*s
)
5619 : UnaExp(loc
, TOKdottype
, sizeof(DotTypeExp
), e
)
5622 this->type
= s
->getType();
5625 Expression
*DotTypeExp::semantic(Scope
*sc
)
5628 printf("DotTypeExp::semantic('%s')\n", toChars());
5630 UnaExp::semantic(sc
);
5634 void DotTypeExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5636 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5637 buf
->writeByte('.');
5638 buf
->writestring(sym
->toChars());
5641 /************************************************************/
5643 CallExp::CallExp(Loc loc
, Expression
*e
, Expressions
*exps
)
5644 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5646 this->arguments
= exps
;
5649 CallExp::CallExp(Loc loc
, Expression
*e
)
5650 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5652 this->arguments
= NULL
;
5655 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
)
5656 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5658 Expressions
*arguments
= new Expressions();
5659 arguments
->setDim(1);
5660 arguments
->data
[0] = (void *)earg1
;
5662 this->arguments
= arguments
;
5665 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
, Expression
*earg2
)
5666 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5668 Expressions
*arguments
= new Expressions();
5669 arguments
->setDim(2);
5670 arguments
->data
[0] = (void *)earg1
;
5671 arguments
->data
[1] = (void *)earg2
;
5673 this->arguments
= arguments
;
5676 Expression
*CallExp::syntaxCopy()
5678 return new CallExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
5682 Expression
*CallExp::semantic(Scope
*sc
)
5689 Objects
*targsi
= NULL
; // initial list of template arguments
5692 printf("CallExp::semantic() %s\n", toChars());
5696 return this; // semantic() already run
5698 if (arguments
&& arguments
->dim
)
5700 Expression
*earg
= (Expression
*)arguments
->data
[0];
5702 if (earg
->type
) earg
->type
->print();
5706 if (e1
->op
== TOKdelegate
)
5707 { DelegateExp
*de
= (DelegateExp
*)e1
;
5709 e1
= new DotVarExp(de
->loc
, de
->e1
, de
->func
);
5710 return semantic(sc
);
5714 * array.id(args) into id(array,args)
5715 * aa.remove(arg) into delete aa[arg]
5717 if (e1
->op
== TOKdot
)
5719 // BUG: we should handle array.a.b.c.e(args) too
5721 DotIdExp
*dotid
= (DotIdExp
*)(e1
);
5722 dotid
->e1
= dotid
->e1
->semantic(sc
);
5724 if (dotid
->e1
->type
)
5726 TY e1ty
= dotid
->e1
->type
->toBasetype()->ty
;
5727 if (e1ty
== Taarray
&& dotid
->ident
== Id::remove
)
5729 if (!arguments
|| arguments
->dim
!= 1)
5730 { error("expected key as argument to aa.remove()");
5733 Expression
*key
= (Expression
*)arguments
->data
[0];
5734 key
= key
->semantic(sc
);
5735 key
= resolveProperties(sc
, key
);
5738 TypeAArray
*taa
= (TypeAArray
*)dotid
->e1
->type
->toBasetype();
5739 key
= key
->implicitCastTo(sc
, taa
->index
);
5741 return new RemoveExp(loc
, dotid
->e1
, key
);
5743 else if (e1ty
== Tarray
|| e1ty
== Tsarray
|| e1ty
== Taarray
)
5746 arguments
= new Expressions();
5747 arguments
->shift(dotid
->e1
);
5748 e1
= new IdentifierExp(dotid
->loc
, dotid
->ident
);
5754 * foo!(tiargs)(funcargs)
5756 if (e1
->op
== TOKimport
&& !e1
->type
)
5757 { ScopeExp
*se
= (ScopeExp
*)e1
;
5758 TemplateInstance
*ti
= se
->sds
->isTemplateInstance();
5759 if (ti
&& !ti
->semanticdone
)
5761 /* Attempt to instantiate ti. If that works, go with it.
5762 * If not, go with partial explicit specialization.
5764 unsigned errors
= global
.errors
;
5768 if (errors
!= global
.errors
)
5770 global
.errors
= errors
;
5771 targsi
= ti
->tiargs
;
5772 e1
= new IdentifierExp(loc
, ti
->name
);
5778 * expr.foo!(tiargs)(funcargs)
5780 if (e1
->op
== TOKdotti
&& !e1
->type
)
5781 { DotTemplateInstanceExp
*se
= (DotTemplateInstanceExp
*)e1
;
5782 TemplateInstance
*ti
= se
->ti
;
5783 if (!ti
->semanticdone
)
5785 /* Attempt to instantiate ti. If that works, go with it.
5786 * If not, go with partial explicit specialization.
5789 unsigned errors
= global
.errors
;
5791 etmp
= e1
->semantic(sc
);
5793 if (errors
!= global
.errors
)
5795 global
.errors
= errors
;
5796 targsi
= ti
->tiargs
;
5797 e1
= new DotIdExp(loc
, se
->e1
, ti
->name
);
5806 //printf("Lagain: %s\n", toChars());
5808 if (e1
->op
== TOKthis
|| e1
->op
== TOKsuper
)
5810 // semantic() run later for these
5814 UnaExp::semantic(sc
);
5816 /* Look for e1 being a lazy parameter
5818 if (e1
->op
== TOKvar
)
5819 { VarExp
*ve
= (VarExp
*)e1
;
5821 if (ve
->var
->storage_class
& STClazy
)
5823 TypeFunction
*tf
= new TypeFunction(NULL
, ve
->var
->type
, 0, LINKd
);
5824 TypeDelegate
*t
= new TypeDelegate(tf
);
5825 ve
->type
= t
->semantic(loc
, sc
);
5829 if (e1
->op
== TOKimport
)
5830 { // Perhaps this should be moved to ScopeExp::semantic()
5831 ScopeExp
*se
= (ScopeExp
*)e1
;
5832 e1
= new DsymbolExp(loc
, se
->sds
);
5833 e1
= e1
->semantic(sc
);
5835 #if 1 // patch for #540 by Oskar Linde
5836 else if (e1
->op
== TOKdotexp
)
5838 DotExp
*de
= (DotExp
*) e1
;
5840 if (de
->e2
->op
== TOKimport
)
5841 { // This should *really* be moved to ScopeExp::semantic()
5842 ScopeExp
*se
= (ScopeExp
*)de
->e2
;
5843 de
->e2
= new DsymbolExp(loc
, se
->sds
);
5844 de
->e2
= de
->e2
->semantic(sc
);
5847 if (de
->e2
->op
== TOKtemplate
)
5848 { TemplateExp
*te
= (TemplateExp
*) de
->e2
;
5849 e1
= new DotTemplateExp(loc
,de
->e1
,te
->td
);
5855 if (e1
->op
== TOKcomma
)
5857 CommaExp
*ce
= (CommaExp
*)e1
;
5860 e1
->type
= ce
->type
;
5863 return ce
->semantic(sc
);
5868 t1
= e1
->type
->toBasetype();
5870 // Check for call operator overload
5872 { AggregateDeclaration
*ad
;
5874 if (t1
->ty
== Tstruct
)
5876 ad
= ((TypeStruct
*)t1
)->sym
;
5877 if (search_function(ad
, Id::call
))
5878 goto L1
; // overload of opCall, therefore it's a call
5880 if (e1
->op
!= TOKtype
)
5881 error("%s %s does not overload ()", ad
->kind(), ad
->toChars());
5882 /* It's a struct literal
5884 Expression
*e
= new StructLiteralExp(loc
, (StructDeclaration
*)ad
, arguments
);
5885 e
= e
->semantic(sc
);
5886 e
->type
= e1
->type
; // in case e1->type was a typedef
5889 else if (t1
->ty
== Tclass
)
5891 ad
= ((TypeClass
*)t1
)->sym
;
5894 // Rewrite as e1.call(arguments)
5895 Expression
*e
= new DotIdExp(loc
, e1
, Id::call
);
5896 e
= new CallExp(loc
, e
, arguments
);
5897 e
= e
->semantic(sc
);
5902 arrayExpressionSemantic(arguments
, sc
);
5903 preFunctionArguments(loc
, sc
, arguments
);
5905 if (e1
->op
== TOKdotvar
&& t1
->ty
== Tfunction
||
5909 DotTemplateExp
*dte
;
5910 AggregateDeclaration
*ad
;
5911 UnaExp
*ue
= (UnaExp
*)(e1
);
5913 if (e1
->op
== TOKdotvar
)
5914 { // Do overload resolution
5915 dve
= (DotVarExp
*)(e1
);
5917 f
= dve
->var
->isFuncDeclaration();
5919 f
= f
->overloadResolve(loc
, ue
->e1
, arguments
);
5921 ad
= f
->toParent()->isAggregateDeclaration();
5924 { dte
= (DotTemplateExp
*)(e1
);
5925 TemplateDeclaration
*td
= dte
->td
;
5928 // Should fix deduceFunctionTemplate() so it works on NULL argument
5929 arguments
= new Expressions();
5930 f
= td
->deduceFunctionTemplate(sc
, loc
, targsi
, ue
->e1
, arguments
);
5932 { type
= Type::terror
;
5935 ad
= td
->toParent()->isAggregateDeclaration();
5938 ue
->e1
= getRightThis(loc
, sc
, ad
, ue
->e1
, f
);
5940 checkDeprecated(sc
, f
);
5941 accessCheck(loc
, sc
, ue
->e1
, f
);
5944 VarExp
*ve
= new VarExp(loc
, f
);
5945 e1
= new CommaExp(loc
, ue
->e1
, ve
);
5950 if (e1
->op
== TOKdotvar
)
5953 e1
= new DotVarExp(loc
, dte
->e1
, f
);
5956 printf("ue->e1 = %s\n", ue
->e1
->toChars());
5957 printf("f = %s\n", f
->toChars());
5958 printf("t = %s\n", t
->toChars());
5959 printf("e1 = %s\n", e1
->toChars());
5960 printf("e1->type = %s\n", e1
->type
->toChars());
5962 // Const member function can take const/invariant/mutable this
5963 if (!(f
->type
->isConst()))
5965 // Check for const/invariant compatibility
5966 Type
*tthis
= ue
->e1
->type
->toBasetype();
5967 if (tthis
->ty
== Tpointer
)
5968 tthis
= tthis
->nextOf()->toBasetype();
5969 if (f
->type
->isInvariant())
5971 if (tthis
->mod
!= MODinvariant
)
5972 error("%s can only be called on an invariant object", e1
->toChars());
5976 if (tthis
->mod
!= 0)
5977 { //printf("mod = %x\n", tthis->mod);
5978 error("%s can only be called on a mutable object, not %s", e1
->toChars(), tthis
->toChars());
5982 /* Cannot call mutable method on a final struct
5984 if (tthis
->ty
== Tstruct
&&
5985 ue
->e1
->op
== TOKvar
)
5986 { VarExp
*v
= (VarExp
*)ue
->e1
;
5987 if (v
->var
->storage_class
& STCfinal
)
5988 error("cannot call mutable method on final struct");
5992 // See if we need to adjust the 'this' pointer
5993 AggregateDeclaration
*ad
= f
->isThis();
5994 ClassDeclaration
*cd
= ue
->e1
->type
->isClassHandle();
5995 if (ad
&& cd
&& ad
->isClassDeclaration() && ad
!= cd
&&
5996 ue
->e1
->op
!= TOKsuper
)
5998 ue
->e1
= ue
->e1
->castTo(sc
, ad
->type
); //new CastExp(loc, ue->e1, ad->type);
5999 ue
->e1
= ue
->e1
->semantic(sc
);
6004 else if (e1
->op
== TOKsuper
)
6006 // Base class constructor call
6007 ClassDeclaration
*cd
= NULL
;
6010 cd
= sc
->func
->toParent()->isClassDeclaration();
6011 if (!cd
|| !cd
->baseClass
|| !sc
->func
->isCtorDeclaration())
6013 error("super class constructor call must be in a constructor");
6014 type
= Type::terror
;
6019 f
= cd
->baseClass
->ctor
;
6021 { error("no super class constructor for %s", cd
->baseClass
->toChars());
6022 type
= Type::terror
;
6028 if (sc
->callSuper
& (CSXthis
| CSXsuper
))
6029 error("reference to this before super()");
6031 if (sc
->noctor
|| sc
->callSuper
& CSXlabel
)
6032 error("constructor calls not allowed in loops or after labels");
6033 if (sc
->callSuper
& (CSXsuper_ctor
| CSXthis_ctor
))
6034 error("multiple constructor calls");
6035 sc
->callSuper
|= CSXany_ctor
| CSXsuper_ctor
;
6037 f
= f
->overloadResolve(loc
, NULL
, arguments
);
6038 checkDeprecated(sc
, f
);
6039 e1
= new DotVarExp(e1
->loc
, e1
, f
);
6040 e1
= e1
->semantic(sc
);
6045 else if (e1
->op
== TOKthis
)
6047 // same class constructor call
6048 ClassDeclaration
*cd
= NULL
;
6051 cd
= sc
->func
->toParent()->isClassDeclaration();
6052 if (!cd
|| !sc
->func
->isCtorDeclaration())
6054 error("class constructor call must be in a constructor");
6055 type
= Type::terror
;
6061 if (sc
->callSuper
& (CSXthis
| CSXsuper
))
6062 error("reference to this before super()");
6064 if (sc
->noctor
|| sc
->callSuper
& CSXlabel
)
6065 error("constructor calls not allowed in loops or after labels");
6066 if (sc
->callSuper
& (CSXsuper_ctor
| CSXthis_ctor
))
6067 error("multiple constructor calls");
6068 sc
->callSuper
|= CSXany_ctor
| CSXthis_ctor
;
6071 f
= f
->overloadResolve(loc
, NULL
, arguments
);
6072 checkDeprecated(sc
, f
);
6073 e1
= new DotVarExp(e1
->loc
, e1
, f
);
6074 e1
= e1
->semantic(sc
);
6077 // BUG: this should really be done by checking the static
6080 error("cyclic constructor call");
6083 else if (e1
->op
== TOKoverloadset
)
6085 OverExp
*eo
= (OverExp
*)e1
;
6086 FuncDeclaration
*f
= NULL
;
6087 for (int i
= 0; i
< eo
->vars
->a
.dim
; i
++)
6088 { Dsymbol
*s
= (Dsymbol
*)eo
->vars
->a
.data
[i
];
6089 FuncDeclaration
*f2
= s
->isFuncDeclaration();
6092 f2
= f2
->overloadResolve(loc
, NULL
, arguments
, 1);
6095 { TemplateDeclaration
*td
= s
->isTemplateDeclaration();
6097 f2
= td
->deduceFunctionTemplate(sc
, loc
, targsi
, NULL
, arguments
, 1);
6101 /* Error if match in more than one overload set,
6102 * even if one is a 'better' match than the other.
6104 ScopeDsymbol::multiplyDefined(loc
, f
, f2
);
6110 { /* No overload matches, just set f and rely on error
6111 * message being generated later.
6113 f
= (FuncDeclaration
*)eo
->vars
->a
.data
[0];
6115 e1
= new VarExp(loc
, f
);
6120 error("function expected before (), not '%s'", e1
->toChars());
6121 type
= Type::terror
;
6124 else if (t1
->ty
!= Tfunction
)
6126 if (t1
->ty
== Tdelegate
)
6127 { TypeDelegate
*td
= (TypeDelegate
*)t1
;
6128 assert(td
->next
->ty
== Tfunction
);
6129 tf
= (TypeFunction
*)(td
->next
);
6132 else if (t1
->ty
== Tpointer
&& ((TypePointer
*)t1
)->next
->ty
== Tfunction
)
6135 e
= new PtrExp(loc
, e1
);
6136 t1
= ((TypePointer
*)t1
)->next
;
6140 else if (e1
->op
== TOKtemplate
)
6142 TemplateExp
*te
= (TemplateExp
*)e1
;
6143 f
= te
->td
->deduceFunctionTemplate(sc
, loc
, targsi
, NULL
, arguments
);
6145 { type
= Type::terror
;
6148 if (f
->needThis() && hasThis(sc
))
6150 // Supply an implicit 'this', as in
6153 e1
= new DotTemplateExp(loc
, (new ThisExp(loc
))->semantic(sc
), te
->td
);
6157 e1
= new VarExp(loc
, f
);
6161 { error("function expected before (), not %s of type %s", e1
->toChars(), e1
->type
->toChars());
6162 type
= Type::terror
;
6166 else if (e1
->op
== TOKvar
)
6168 // Do overload resolution
6169 VarExp
*ve
= (VarExp
*)e1
;
6171 f
= ve
->var
->isFuncDeclaration();
6174 if (ve
->hasOverloads
)
6175 f
= f
->overloadResolve(loc
, NULL
, arguments
);
6176 checkDeprecated(sc
, f
);
6178 if (f
->needThis() && hasThis(sc
))
6180 // Supply an implicit 'this', as in
6183 e1
= new DotVarExp(loc
, new ThisExp(loc
), f
);
6187 accessCheck(loc
, sc
, NULL
, f
);
6190 // ve->hasOverloads = 0;
6194 assert(t1
->ty
== Tfunction
);
6195 tf
= (TypeFunction
*)(t1
);
6198 assert(tf
->ty
== Tfunction
);
6202 arguments
= new Expressions();
6203 functionArguments(loc
, sc
, tf
, arguments
);
6210 target_ptrdiff_t offset
= 0;
6211 TypeFunction
*tf
= (TypeFunction
*)f
->tintro
;
6213 if (tf
->next
->isBaseOf(t
, &offset
) && offset
)
6216 return castTo(sc
, t
);
6223 int CallExp::checkSideEffect(int flag
)
6228 int CallExp::canThrow()
6233 Expression
*CallExp::toLvalue(Scope
*sc
, Expression
*e
)
6235 if (type
->toBasetype()->ty
== Tstruct
)
6238 return Expression::toLvalue(sc
, e
);
6241 void CallExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6244 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6245 buf
->writeByte('(');
6246 argsToCBuffer(buf
, arguments
, hgs
);
6247 buf
->writeByte(')');
6251 /************************************************************/
6253 AddrExp::AddrExp(Loc loc
, Expression
*e
)
6254 : UnaExp(loc
, TOKaddress
, sizeof(AddrExp
), e
)
6258 Expression
*AddrExp::semantic(Scope
*sc
)
6261 printf("AddrExp::semantic('%s')\n", toChars());
6265 UnaExp::semantic(sc
);
6266 e1
= e1
->toLvalue(sc
, NULL
);
6269 error("cannot take address of %s", e1
->toChars());
6270 type
= Type::tint32
;
6273 type
= e1
->type
->pointerTo();
6275 // See if this should really be a delegate
6276 if (e1
->op
== TOKdotvar
)
6278 DotVarExp
*dve
= (DotVarExp
*)e1
;
6280 FuncDeclaration
*f
= dve
->var
->isFuncDeclaration();
6284 if (!dve
->hasOverloads
)
6285 f
->tookAddressOf
= 1;
6286 Expression
*e
= new DelegateExp(loc
, dve
->e1
, f
, dve
->hasOverloads
);
6287 e
= e
->semantic(sc
);
6291 else if (e1
->op
== TOKvar
)
6293 VarExp
*ve
= (VarExp
*)e1
;
6295 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
6296 if (v
&& !v
->canTakeAddressOf())
6297 error("cannot take address of %s", e1
->toChars());
6299 FuncDeclaration
*f
= ve
->var
->isFuncDeclaration();
6303 if (!ve
->hasOverloads
)
6304 f
->tookAddressOf
= 1;
6307 Expression
*e
= new DelegateExp(loc
, e1
, f
, ve
->hasOverloads
);
6308 e
= e
->semantic(sc
);
6311 if (f
->needThis() && hasThis(sc
))
6313 /* Should probably supply 'this' after overload resolution,
6316 Expression
*ethis
= new ThisExp(loc
);
6317 Expression
*e
= new DelegateExp(loc
, ethis
, f
, ve
->hasOverloads
);
6318 e
= e
->semantic(sc
);
6323 return optimize(WANTvalue
);
6328 /************************************************************/
6330 PtrExp::PtrExp(Loc loc
, Expression
*e
)
6331 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
6334 type
= ((TypePointer
*)e
->type
)->next
;
6337 PtrExp::PtrExp(Loc loc
, Expression
*e
, Type
*t
)
6338 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
6343 Expression
*PtrExp::semantic(Scope
*sc
)
6347 printf("PtrExp::semantic('%s')\n", toChars());
6351 UnaExp::semantic(sc
);
6352 e1
= resolveProperties(sc
, e1
);
6354 printf("PtrExp::semantic('%s')\n", toChars());
6355 Expression
*e
= op_overload(sc
);
6358 tb
= e1
->type
->toBasetype();
6362 type
= ((TypePointer
*)tb
)->next
;
6367 type
= ((TypeArray
*)tb
)->next
;
6368 e1
= e1
->castTo(sc
, type
->pointerTo());
6372 error("can only * a pointer, not a '%s'", e1
->type
->toChars());
6373 type
= Type::tint32
;
6381 Expression
*PtrExp::toLvalue(Scope
*sc
, Expression
*e
)
6384 tym
= tybasic(e1
->ET
->Tty
);
6385 if (!(tyscalar(tym
) ||
6387 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
6388 synerr(EM_lvalue
); // lvalue expected
6393 Expression
*PtrExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6395 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
6397 if (e1
->op
== TOKsymoff
)
6398 { SymOffExp
*se
= (SymOffExp
*)e1
;
6399 se
->var
->checkModify(loc
, sc
, type
);
6400 //return toLvalue(sc, e);
6403 return Expression::modifiableLvalue(sc
, e
);
6407 void PtrExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6409 buf
->writeByte('*');
6410 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6413 /************************************************************/
6415 NegExp::NegExp(Loc loc
, Expression
*e
)
6416 : UnaExp(loc
, TOKneg
, sizeof(NegExp
), e
)
6420 Expression
*NegExp::semantic(Scope
*sc
)
6424 printf("NegExp::semantic('%s')\n", toChars());
6428 UnaExp::semantic(sc
);
6429 e1
= resolveProperties(sc
, e1
);
6430 e
= op_overload(sc
);
6435 e1
->checkArithmetic();
6441 /************************************************************/
6443 UAddExp::UAddExp(Loc loc
, Expression
*e
)
6444 : UnaExp(loc
, TOKuadd
, sizeof(UAddExp
), e
)
6448 Expression
*UAddExp::semantic(Scope
*sc
)
6452 printf("UAddExp::semantic('%s')\n", toChars());
6455 UnaExp::semantic(sc
);
6456 e1
= resolveProperties(sc
, e1
);
6457 e
= op_overload(sc
);
6461 e1
->checkArithmetic();
6465 /************************************************************/
6467 ComExp::ComExp(Loc loc
, Expression
*e
)
6468 : UnaExp(loc
, TOKtilde
, sizeof(ComExp
), e
)
6472 Expression
*ComExp::semantic(Scope
*sc
)
6477 UnaExp::semantic(sc
);
6478 e1
= resolveProperties(sc
, e1
);
6479 e
= op_overload(sc
);
6484 e1
= e1
->checkIntegral();
6490 /************************************************************/
6492 NotExp::NotExp(Loc loc
, Expression
*e
)
6493 : UnaExp(loc
, TOKnot
, sizeof(NotExp
), e
)
6497 Expression
*NotExp::semantic(Scope
*sc
)
6499 UnaExp::semantic(sc
);
6500 e1
= resolveProperties(sc
, e1
);
6501 e1
= e1
->checkToBoolean();
6502 type
= Type::tboolean
;
6513 /************************************************************/
6515 BoolExp::BoolExp(Loc loc
, Expression
*e
, Type
*t
)
6516 : UnaExp(loc
, TOKtobool
, sizeof(BoolExp
), e
)
6521 Expression
*BoolExp::semantic(Scope
*sc
)
6523 UnaExp::semantic(sc
);
6524 e1
= resolveProperties(sc
, e1
);
6525 e1
= e1
->checkToBoolean();
6526 type
= Type::tboolean
;
6530 int BoolExp::isBit()
6535 /************************************************************/
6537 DeleteExp::DeleteExp(Loc loc
, Expression
*e
)
6538 : UnaExp(loc
, TOKdelete
, sizeof(DeleteExp
), e
)
6542 Expression
*DeleteExp::semantic(Scope
*sc
)
6546 UnaExp::semantic(sc
);
6547 e1
= resolveProperties(sc
, e1
);
6548 e1
= e1
->toLvalue(sc
, NULL
);
6551 tb
= e1
->type
->toBasetype();
6554 { TypeClass
*tc
= (TypeClass
*)tb
;
6555 ClassDeclaration
*cd
= tc
->sym
;
6557 if (cd
->isCOMinterface())
6558 { /* Because COM classes are deleted by IUnknown.Release()
6560 error("cannot delete instance of COM interface %s", cd
->toChars());
6565 tb
= ((TypePointer
*)tb
)->next
->toBasetype();
6566 if (tb
->ty
== Tstruct
)
6568 TypeStruct
*ts
= (TypeStruct
*)tb
;
6569 StructDeclaration
*sd
= ts
->sym
;
6570 FuncDeclaration
*f
= sd
->aggDelete
;
6571 FuncDeclaration
*fd
= sd
->dtor
;
6577 * ea = copy e1 to a tmp to do side effects only once
6578 * eb = call destructor
6579 * ec = call deallocator
6581 Expression
*ea
= NULL
;
6582 Expression
*eb
= NULL
;
6583 Expression
*ec
= NULL
;
6587 { Identifier
*id
= Lexer::idPool("__tmp");
6588 v
= new VarDeclaration(loc
, e1
->type
, id
, new ExpInitializer(loc
, e1
));
6590 v
->parent
= sc
->parent
;
6591 ea
= new DeclarationExp(loc
, v
);
6596 { Expression
*e
= ea
? new VarExp(loc
, v
) : e1
;
6597 e
= new DotVarExp(0, e
, fd
, 0);
6598 eb
= new CallExp(loc
, e
);
6599 eb
= eb
->semantic(sc
);
6604 Type
*tpv
= Type::tvoid
->pointerTo();
6605 Expression
*e
= ea
? new VarExp(loc
, v
) : e1
->castTo(sc
, tpv
);
6606 e
= new CallExp(loc
, new VarExp(loc
, f
), e
);
6607 ec
= e
->semantic(sc
);
6609 ea
= combine(ea
, eb
);
6610 ea
= combine(ea
, ec
);
6617 /* BUG: look for deleting arrays of structs with dtors.
6622 if (e1
->op
== TOKindex
)
6624 IndexExp
*ae
= (IndexExp
*)(e1
);
6625 Type
*tb1
= ae
->e1
->type
->toBasetype();
6626 if (tb1
->ty
== Taarray
)
6629 error("cannot delete type %s", e1
->type
->toChars());
6633 if (e1
->op
== TOKindex
)
6635 IndexExp
*ae
= (IndexExp
*)(e1
);
6636 Type
*tb1
= ae
->e1
->type
->toBasetype();
6637 if (tb1
->ty
== Taarray
)
6638 { if (!global
.params
.useDeprecated
)
6639 error("delete aa[key] deprecated, use aa.remove(key)");
6646 int DeleteExp::checkSideEffect(int flag
)
6651 Expression
*DeleteExp::checkToBoolean()
6653 error("delete does not give a boolean result");
6657 void DeleteExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6659 buf
->writestring("delete ");
6660 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6663 /************************************************************/
6665 CastExp::CastExp(Loc loc
, Expression
*e
, Type
*t
)
6666 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
6669 this->tok
= TOKreserved
;
6672 /* For cast(const) and cast(invariant)
6674 CastExp::CastExp(Loc loc
, Expression
*e
, enum TOK tok
)
6675 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
6681 Expression
*CastExp::syntaxCopy()
6683 return to
? new CastExp(loc
, e1
->syntaxCopy(), to
->syntaxCopy())
6684 : new CastExp(loc
, e1
->syntaxCopy(), tok
);
6688 Expression
*CastExp::semantic(Scope
*sc
)
6694 printf("CastExp::semantic('%s')\n", toChars());
6697 //static int x; assert(++x < 10);
6701 UnaExp::semantic(sc
);
6702 if (e1
->type
) // if not a tuple
6704 e1
= resolveProperties(sc
, e1
);
6706 /* Handle cast(const) and cast(invariant)
6709 { if (tok
== TOKconst
)
6710 to
= e1
->type
->constOf();
6711 else if (tok
== TOKinvariant
)
6712 to
= e1
->type
->invariantOf();
6717 to
= to
->semantic(loc
, sc
);
6719 e
= op_overload(sc
);
6722 return e
->implicitCastTo(sc
, to
);
6725 Type
*tob
= to
->toBasetype();
6726 if (tob
->ty
== Tstruct
&&
6727 !tob
->equals(e1
->type
->toBasetype()) &&
6728 ((TypeStruct
*)to
)->sym
->search(0, Id::call
, 0)
6737 // Rewrite as to.call(e1)
6738 e
= new TypeExp(loc
, to
);
6739 e
= new DotIdExp(loc
, e
, Id::call
);
6740 e
= new CallExp(loc
, e
, e1
);
6741 e
= e
->semantic(sc
);
6746 { error("cannot cast tuple");
6750 e
= e1
->castTo(sc
, to
);
6752 e
= e1
->castTo(sc
, to
->maybe(true));
6756 int CastExp::checkSideEffect(int flag
)
6760 * cast(classtype)func()
6762 if (!to
->equals(Type::tvoid
) &&
6763 !(to
->ty
== Tclass
&& e1
->op
== TOKcall
&& e1
->type
->ty
== Tclass
))
6764 return Expression::checkSideEffect(flag
);
6768 void CastExp::checkEscape()
6769 { Type
*tb
= type
->toBasetype();
6770 if (tb
->ty
== Tarray
&& e1
->op
== TOKvar
&&
6771 e1
->type
->toBasetype()->ty
== Tsarray
)
6772 { VarExp
*ve
= (VarExp
*)e1
;
6773 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
6776 if (!v
->isDataseg() && !v
->isParameter())
6777 error("escaping reference to local %s", v
->toChars());
6782 void CastExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6784 buf
->writestring("cast(");
6786 to
->toCBuffer(buf
, NULL
, hgs
);
6788 buf
->writestring(Token::tochars
[tok
]);
6789 buf
->writeByte(')');
6790 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6794 /************************************************************/
6796 SliceExp::SliceExp(Loc loc
, Expression
*e1
, Expression
*lwr
, Expression
*upr
)
6797 : UnaExp(loc
, TOKslice
, sizeof(SliceExp
), e1
)
6804 Expression
*SliceExp::syntaxCopy()
6806 Expression
*lwr
= NULL
;
6808 lwr
= this->lwr
->syntaxCopy();
6810 Expression
*upr
= NULL
;
6812 upr
= this->upr
->syntaxCopy();
6814 return new SliceExp(loc
, e1
->syntaxCopy(), lwr
, upr
);
6817 Expression
*SliceExp::semantic(Scope
*sc
)
6819 AggregateDeclaration
*ad
;
6820 //FuncDeclaration *fd;
6824 printf("SliceExp::semantic('%s')\n", toChars());
6829 UnaExp::semantic(sc
);
6830 e1
= resolveProperties(sc
, e1
);
6834 Type
*t
= e1
->type
->toBasetype();
6835 if (t
->ty
== Tpointer
)
6838 error("need upper and lower bound to slice pointer");
6840 else if (t
->ty
== Tarray
)
6843 else if (t
->ty
== Tsarray
)
6846 else if (t
->ty
== Tclass
)
6848 ad
= ((TypeClass
*)t
)->sym
;
6851 else if (t
->ty
== Tstruct
)
6853 ad
= ((TypeStruct
*)t
)->sym
;
6856 if (search_function(ad
, Id::slice
))
6858 // Rewrite as e1.slice(lwr, upr)
6859 e
= new DotIdExp(loc
, e1
, Id::slice
);
6864 e
= new CallExp(loc
, e
, lwr
, upr
);
6868 e
= new CallExp(loc
, e
);
6870 e
= e
->semantic(sc
);
6875 else if (t
->ty
== Ttuple
)
6880 { error("need upper and lower bound to slice tuple");
6887 if (t
->ty
== Tsarray
|| t
->ty
== Tarray
|| t
->ty
== Ttuple
)
6889 sym
= new ArrayScopeSymbol(sc
, this);
6891 sym
->parent
= sc
->scopesym
;
6896 { lwr
= lwr
->semantic(sc
);
6897 lwr
= resolveProperties(sc
, lwr
);
6898 lwr
= lwr
->implicitCastTo(sc
, Type::tsize_t
);
6901 { upr
= upr
->semantic(sc
);
6902 upr
= resolveProperties(sc
, upr
);
6903 upr
= upr
->implicitCastTo(sc
, Type::tsize_t
);
6906 if (t
->ty
== Tsarray
|| t
->ty
== Tarray
|| t
->ty
== Ttuple
)
6909 if (t
->ty
== Ttuple
)
6911 lwr
= lwr
->optimize(WANTvalue
);
6912 upr
= upr
->optimize(WANTvalue
);
6913 uinteger_t i1
= lwr
->toUInteger();
6914 uinteger_t i2
= upr
->toUInteger();
6920 if (e1
->op
== TOKtuple
) // slicing an expression tuple
6921 { te
= (TupleExp
*)e1
;
6922 length
= te
->exps
->dim
;
6924 else if (e1
->op
== TOKtype
) // slicing a type tuple
6925 { tup
= (TypeTuple
*)t
;
6926 length
= Argument::dim(tup
->arguments
);
6931 if (i1
<= i2
&& i2
<= length
)
6932 { size_t j1
= (size_t) i1
;
6933 size_t j2
= (size_t) i2
;
6935 if (e1
->op
== TOKtuple
)
6936 { Expressions
*exps
= new Expressions
;
6937 exps
->setDim(j2
- j1
);
6938 for (size_t i
= 0; i
< j2
- j1
; i
++)
6939 { Expression
*e
= (Expression
*)te
->exps
->data
[j1
+ i
];
6940 exps
->data
[i
] = (void *)e
;
6942 e
= new TupleExp(loc
, exps
);
6945 { Arguments
*args
= new Arguments
;
6946 args
->reserve(j2
- j1
);
6947 for (size_t i
= j1
; i
< j2
; i
++)
6948 { Argument
*arg
= Argument::getNth(tup
->arguments
, i
);
6951 e
= new TypeExp(e1
->loc
, new TypeTuple(args
));
6953 e
= e
->semantic(sc
);
6957 error("string slice [%"PRIuMAX
" .. %"PRIuMAX
"] is out of bounds", i1
, i2
);
6963 type
= t
->nextOf()->arrayOf();
6972 error("%s cannot be sliced with []", s
);
6973 type
= Type::terror
;
6977 void SliceExp::checkEscape()
6982 Expression
*SliceExp::toLvalue(Scope
*sc
, Expression
*e
)
6987 Expression
*SliceExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6989 error("slice expression %s is not a modifiable lvalue", toChars());
6993 void SliceExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6995 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6996 buf
->writeByte('[');
7000 expToCBuffer(buf
, hgs
, lwr
, PREC_assign
);
7002 buf
->writeByte('0');
7003 buf
->writestring("..");
7005 expToCBuffer(buf
, hgs
, upr
, PREC_assign
);
7007 buf
->writestring("length"); // BUG: should be array.length
7009 buf
->writeByte(']');
7012 /********************** ArrayLength **************************************/
7014 ArrayLengthExp::ArrayLengthExp(Loc loc
, Expression
*e1
)
7015 : UnaExp(loc
, TOKarraylength
, sizeof(ArrayLengthExp
), e1
)
7019 Expression
*ArrayLengthExp::semantic(Scope
*sc
)
7023 printf("ArrayLengthExp::semantic('%s')\n", toChars());
7027 UnaExp::semantic(sc
);
7028 e1
= resolveProperties(sc
, e1
);
7030 type
= Type::tsize_t
;
7035 void ArrayLengthExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7037 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
7038 buf
->writestring(".length");
7041 /*********************** ArrayExp *************************************/
7043 // e1 [ i1, i2, i3, ... ]
7045 ArrayExp::ArrayExp(Loc loc
, Expression
*e1
, Expressions
*args
)
7046 : UnaExp(loc
, TOKarray
, sizeof(ArrayExp
), e1
)
7051 Expression
*ArrayExp::syntaxCopy()
7053 return new ArrayExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
7056 Expression
*ArrayExp::semantic(Scope
*sc
)
7061 printf("ArrayExp::semantic('%s')\n", toChars());
7063 UnaExp::semantic(sc
);
7064 e1
= resolveProperties(sc
, e1
);
7066 t1
= e1
->type
->toBasetype();
7067 if (t1
->ty
!= Tclass
&& t1
->ty
!= Tstruct
)
7068 { // Convert to IndexExp
7069 if (arguments
->dim
!= 1)
7070 error("only one index allowed to index %s", t1
->toChars());
7071 e
= new IndexExp(loc
, e1
, (Expression
*)arguments
->data
[0]);
7072 return e
->semantic(sc
);
7075 // Run semantic() on each argument
7076 for (size_t i
= 0; i
< arguments
->dim
; i
++)
7077 { e
= (Expression
*)arguments
->data
[i
];
7079 e
= e
->semantic(sc
);
7081 error("%s has no value", e
->toChars());
7082 arguments
->data
[i
] = (void *)e
;
7085 expandTuples(arguments
);
7086 assert(arguments
&& arguments
->dim
);
7088 e
= op_overload(sc
);
7090 { error("no [] operator overload for type %s", e1
->type
->toChars());
7097 Expression
*ArrayExp::toLvalue(Scope
*sc
, Expression
*e
)
7099 if (type
&& type
->toBasetype()->ty
== Tvoid
)
7100 error("voids have no value");
7105 void ArrayExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7108 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
7109 buf
->writeByte('[');
7110 argsToCBuffer(buf
, arguments
, hgs
);
7111 buf
->writeByte(']');
7114 /************************* DotExp ***********************************/
7116 DotExp::DotExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7117 : BinExp(loc
, TOKdotexp
, sizeof(DotExp
), e1
, e2
)
7121 Expression
*DotExp::semantic(Scope
*sc
)
7124 printf("DotExp::semantic('%s')\n", toChars());
7125 if (type
) printf("\ttype = %s\n", type
->toChars());
7127 e1
= e1
->semantic(sc
);
7128 e2
= e2
->semantic(sc
);
7129 if (e2
->op
== TOKimport
)
7131 ScopeExp
*se
= (ScopeExp
*)e2
;
7132 TemplateDeclaration
*td
= se
->sds
->isTemplateDeclaration();
7134 { Expression
*e
= new DotTemplateExp(loc
, e1
, td
);
7135 e
= e
->semantic(sc
);
7145 /************************* CommaExp ***********************************/
7147 CommaExp::CommaExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7148 : BinExp(loc
, TOKcomma
, sizeof(CommaExp
), e1
, e2
)
7152 Expression
*CommaExp::semantic(Scope
*sc
)
7155 { BinExp::semanticp(sc
);
7161 void CommaExp::checkEscape()
7166 Expression
*CommaExp::toLvalue(Scope
*sc
, Expression
*e
)
7168 e2
= e2
->toLvalue(sc
, NULL
);
7172 Expression
*CommaExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
7174 e2
= e2
->modifiableLvalue(sc
, e
);
7178 int CommaExp::isBool(int result
)
7180 return e2
->isBool(result
);
7183 int CommaExp::checkSideEffect(int flag
)
7186 return e1
->checkSideEffect(2) || e2
->checkSideEffect(2);
7189 // Don't check e1 until we cast(void) the a,b code generation
7190 return e2
->checkSideEffect(flag
);
7194 /************************** IndexExp **********************************/
7198 IndexExp::IndexExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7199 : BinExp(loc
, TOKindex
, sizeof(IndexExp
), e1
, e2
)
7201 //printf("IndexExp::IndexExp('%s')\n", toChars());
7203 modifiable
= 0; // assume it is an rvalue
7206 Expression
*IndexExp::semantic(Scope
*sc
)
7214 printf("IndexExp::semantic('%s')\n", toChars());
7219 e1
= e1
->semantic(sc
);
7220 assert(e1
->type
); // semantic() should already be run on it
7223 // Note that unlike C we do not implement the int[ptr]
7225 t1
= e1
->type
->toBasetype();
7227 if (t1
->ty
== Tsarray
|| t1
->ty
== Tarray
|| t1
->ty
== Ttuple
)
7228 { // Create scope for 'length' variable
7229 sym
= new ArrayScopeSymbol(sc
, this);
7231 sym
->parent
= sc
->scopesym
;
7235 e2
= e2
->semantic(sc
);
7238 error("%s has no value", e2
->toChars());
7239 e2
->type
= Type::terror
;
7241 e2
= resolveProperties(sc
, e2
);
7243 if (t1
->ty
== Tsarray
|| t1
->ty
== Tarray
|| t1
->ty
== Ttuple
)
7250 e2
= e2
->implicitCastTo(sc
, Type::tsize_t
);
7251 e
->type
= ((TypeNext
*)t1
)->next
;
7256 e2
= e2
->implicitCastTo(sc
, Type::tsize_t
);
7258 TypeSArray
*tsa
= (TypeSArray
*)t1
;
7260 #if 0 // Don't do now, because it might be short-circuit evaluated
7261 // Do compile time array bounds checking if possible
7262 e2
= e2
->optimize(WANTvalue
);
7263 if (e2
->op
== TOKint64
)
7265 integer_t index
= e2
->toInteger();
7266 integer_t length
= tsa
->dim
->toInteger();
7267 if (index
< 0 || index
>= length
)
7268 error("array index [%lld] is outside array bounds [0 .. %lld]",
7272 e
->type
= t1
->nextOf();
7277 { TypeAArray
*taa
= (TypeAArray
*)t1
;
7279 e2
= e2
->implicitCastTo(sc
, taa
->index
); // type checking
7286 e2
= e2
->implicitCastTo(sc
, Type::tsize_t
);
7287 e2
= e2
->optimize(WANTvalue
| WANTinterpret
);
7288 uinteger_t index
= e2
->toUInteger();
7293 if (e1
->op
== TOKtuple
)
7294 { te
= (TupleExp
*)e1
;
7295 length
= te
->exps
->dim
;
7297 else if (e1
->op
== TOKtype
)
7299 tup
= (TypeTuple
*)t1
;
7300 length
= Argument::dim(tup
->arguments
);
7308 if (e1
->op
== TOKtuple
)
7309 e
= (Expression
*)te
->exps
->data
[(size_t)index
];
7311 e
= new TypeExp(e1
->loc
, Argument::getNth(tup
->arguments
, (size_t)index
)->type
);
7315 error("array index [%"PRIuMAX
"] is outside array bounds [0 .. %"PRIuSIZE
"]",
7323 error("%s must be an array or pointer type, not %s",
7324 e1
->toChars(), e1
->type
->toChars());
7325 type
= Type::tint32
;
7331 Expression
*IndexExp::toLvalue(Scope
*sc
, Expression
*e
)
7333 // if (type && type->toBasetype()->ty == Tvoid)
7334 // error("voids have no value");
7338 Expression
*IndexExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
7340 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
7342 if (e1
->op
== TOKstring
)
7343 error("string literals are immutable");
7344 if (type
&& !type
->isMutable())
7345 error("%s isn't mutable", e
->toChars());
7346 if (e1
->type
->toBasetype()->ty
== Taarray
)
7347 e1
= e1
->modifiableLvalue(sc
, e1
);
7348 return toLvalue(sc
, e
);
7351 void IndexExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7353 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
7354 buf
->writeByte('[');
7355 expToCBuffer(buf
, hgs
, e2
, PREC_assign
);
7356 buf
->writeByte(']');
7360 /************************* PostExp ***********************************/
7362 PostExp::PostExp(enum TOK op
, Loc loc
, Expression
*e
)
7363 : BinExp(loc
, op
, sizeof(PostExp
), e
,
7364 new IntegerExp(loc
, 1, Type::tint32
))
7368 Expression
*PostExp::semantic(Scope
*sc
)
7369 { Expression
*e
= this;
7373 BinExp::semantic(sc
);
7374 e2
= resolveProperties(sc
, e2
);
7376 e
= op_overload(sc
);
7381 e1
= e1
->modifiableLvalue(sc
, e1
);
7384 if (e1
->type
->ty
== Tpointer
)
7385 e
= scaleFactor(sc
);
7387 e2
= e2
->castTo(sc
, e1
->type
);
7393 void PostExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7395 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
7396 buf
->writestring((op
== TOKplusplus
) ? (char *)"++" : (char *)"--");
7399 /************************************************************/
7401 /* op can be TOKassign, TOKconstruct, or TOKblit */
7403 AssignExp::AssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7404 : BinExp(loc
, TOKassign
, sizeof(AssignExp
), e1
, e2
)
7409 Expression
*AssignExp::semantic(Scope
*sc
)
7411 Expression
*e1old
= e1
;
7414 printf("AssignExp::semantic('%s')\n", toChars());
7416 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
7417 //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
7422 if (e2
->op
== TOKcomma
)
7423 { /* Rewrite to get rid of the comma from rvalue
7425 AssignExp
*ea
= new AssignExp(loc
, e1
, ((CommaExp
*)e2
)->e2
);
7427 Expression
*e
= new CommaExp(loc
, ((CommaExp
*)e2
)->e1
, ea
);
7428 return e
->semantic(sc
);
7431 /* Look for operator overloading of a[i]=value.
7432 * Do it before semantic() otherwise the a[i] will have been
7433 * converted to a.opIndex() already.
7435 if (e1
->op
== TOKarray
)
7437 ArrayExp
*ae
= (ArrayExp
*)e1
;
7438 AggregateDeclaration
*ad
;
7439 Identifier
*id
= Id::index
;
7441 ae
->e1
= ae
->e1
->semantic(sc
);
7442 Type
*t1
= ae
->e1
->type
->toBasetype();
7443 if (t1
->ty
== Tstruct
)
7445 ad
= ((TypeStruct
*)t1
)->sym
;
7448 else if (t1
->ty
== Tclass
)
7450 ad
= ((TypeClass
*)t1
)->sym
;
7452 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
7453 if (search_function(ad
, Id::indexass
))
7454 { Expression
*e
= new DotIdExp(loc
, ae
->e1
, Id::indexass
);
7455 Expressions
*a
= (Expressions
*)ae
->arguments
->copy();
7458 e
= new CallExp(loc
, e
, a
);
7459 e
= e
->semantic(sc
);
7464 // Rewrite (a[i] = value) to (a.opIndex(i, value))
7465 if (search_function(ad
, id
))
7466 { Expression
*e
= new DotIdExp(loc
, ae
->e1
, id
);
7468 if (1 || !global
.params
.useDeprecated
)
7469 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
7471 e
= new CallExp(loc
, e
, (Expression
*)ae
->arguments
->data
[0], e2
);
7472 e
= e
->semantic(sc
);
7478 /* Look for operator overloading of a[i..j]=value.
7479 * Do it before semantic() otherwise the a[i..j] will have been
7480 * converted to a.opSlice() already.
7482 if (e1
->op
== TOKslice
)
7484 SliceExp
*ae
= (SliceExp
*)e1
;
7485 AggregateDeclaration
*ad
;
7486 Identifier
*id
= Id::index
;
7488 ae
->e1
= ae
->e1
->semantic(sc
);
7489 ae
->e1
= resolveProperties(sc
, ae
->e1
);
7490 t1
= ae
->e1
->type
->toBasetype();
7491 if (t1
->ty
== Tstruct
)
7493 ad
= ((TypeStruct
*)t1
)->sym
;
7496 else if (t1
->ty
== Tclass
)
7498 ad
= ((TypeClass
*)t1
)->sym
;
7500 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
7501 if (search_function(ad
, Id::sliceass
))
7502 { Expression
*e
= new DotIdExp(loc
, ae
->e1
, Id::sliceass
);
7503 Expressions
*a
= new Expressions();
7513 e
= new CallExp(loc
, e
, a
);
7514 e
= e
->semantic(sc
);
7520 BinExp::semantic(sc
);
7521 e2
= resolveProperties(sc
, e2
);
7524 /* Rewrite tuple assignment as a tuple of assignments.
7526 if (e1
->op
== TOKtuple
&& e2
->op
== TOKtuple
)
7527 { TupleExp
*tup1
= (TupleExp
*)e1
;
7528 TupleExp
*tup2
= (TupleExp
*)e2
;
7529 size_t dim
= tup1
->exps
->dim
;
7530 if (dim
!= tup2
->exps
->dim
)
7532 error("mismatched tuple lengths, %d and %d", (int)dim
, (int)tup2
->exps
->dim
);
7535 { Expressions
*exps
= new Expressions
;
7538 for (int i
= 0; i
< dim
; i
++)
7539 { Expression
*ex1
= (Expression
*)tup1
->exps
->data
[i
];
7540 Expression
*ex2
= (Expression
*)tup2
->exps
->data
[i
];
7541 exps
->data
[i
] = (void *) new AssignExp(loc
, ex1
, ex2
);
7543 Expression
*e
= new TupleExp(loc
, exps
);
7544 e
= e
->semantic(sc
);
7549 Type
*t1
= e1
->type
->toBasetype();
7551 if (t1
->ty
== Tfunction
)
7552 { // Rewrite f=value to f(value)
7555 e
= new CallExp(loc
, e1
, e2
);
7556 e
= e
->semantic(sc
);
7560 /* If it is an assignment from a 'foreign' type,
7561 * check for operator overloading.
7563 if (t1
->ty
== Tstruct
)
7565 StructDeclaration
*sd
= ((TypeStruct
*)t1
)->sym
;
7566 if (op
== TOKassign
)
7568 Expression
*e
= op_overload(sc
);
7572 else if (op
== TOKconstruct
)
7573 { Type
*t2
= e2
->type
->toBasetype();
7574 if (t2
->ty
== Tstruct
&&
7575 sd
== ((TypeStruct
*)t2
)->sym
&&
7577 { /* We have a copy constructor for this
7579 if (e2
->op
== TOKvar
|| e2
->op
== TOKstar
)
7583 Expression
*e
= new DotVarExp(loc
, e1
, sd
->cpctor
, 0);
7584 e
= new CallExp(loc
, e
, e2
);
7585 return e
->semantic(sc
);
7587 else if (e2
->op
== TOKquestion
)
7589 * a ? e1 = b : e1 = c;
7591 CondExp
*ec
= (CondExp
*)e2
;
7592 AssignExp
*ea1
= new AssignExp(ec
->e1
->loc
, e1
, ec
->e1
);
7594 AssignExp
*ea2
= new AssignExp(ec
->e1
->loc
, e1
, ec
->e2
);
7596 Expression
*e
= new CondExp(loc
, ec
->econd
, ea1
, ea2
);
7597 return e
->semantic(sc
);
7602 else if (t1
->ty
== Tclass
)
7603 { // Disallow assignment operator overloads for same type
7604 if (!e2
->type
->implicitConvTo(e1
->type
))
7606 Expression
*e
= op_overload(sc
);
7612 if (t1
->ty
== Tsarray
)
7614 Expression
*e
= new SliceExp(e1
->loc
, e1
, NULL
, NULL
);
7615 e1
= e
->semantic(sc
);
7616 t1
= e1
->type
->toBasetype();
7621 if (e1
->op
== TOKarraylength
)
7623 // e1 is not an lvalue, but we let code generator handle it
7624 ArrayLengthExp
*ale
= (ArrayLengthExp
*)e1
;
7626 ale
->e1
= ale
->e1
->modifiableLvalue(sc
, e1
);
7628 else if (e1
->op
== TOKslice
)
7630 Type
*tn
= e1
->type
->nextOf();
7631 if (tn
&& !tn
->isMutable() && op
!= TOKconstruct
)
7632 error("slice %s is not mutable", e1
->toChars());
7635 { // Try to do a decent error message with the expression
7636 // before it got constant folded
7637 if (e1
->op
!= TOKvar
)
7638 e1
= e1
->optimize(WANTvalue
);
7639 if (op
!= TOKconstruct
)
7640 e1
= e1
->modifiableLvalue(sc
, e1old
);
7643 Type
*t2
= e2
->type
;
7644 if (e1
->op
== TOKslice
&&
7646 e2
->implicitConvTo(t1
->nextOf())
7649 ismemset
= 1; // make it easy for back end to tell what this is
7650 e2
= e2
->implicitCastTo(sc
, t1
->nextOf());
7652 else if (t1
->ty
== Tsarray
)
7654 /* Should have already converted e1 => e1[]
7657 //error("cannot assign to static array %s", e1->toChars());
7659 else if (e1
->op
== TOKslice
)
7661 e2
= e2
->implicitCastTo(sc
, e1
->type
->constOf());
7665 e2
= e2
->implicitCastTo(sc
, e1
->type
);
7672 Expression
*AssignExp::checkToBoolean()
7676 // are usually mistakes.
7678 error("'=' does not give a boolean result");
7682 /************************************************************/
7684 /* Allow pointer arithmetic on e1? */
7685 static bool allowPtrArith(Scope
*sc
, Expression
*e1
)
7687 if (e1
->type
->ty
== Tpointer
)
7689 else if (e1
->type
->ty
== Tmaybe
&& e1
->type
->nextOf()->ty
== Tpointer
)
7692 e1
->error("Can't do pointer arithmetic on pointer ('%s') that could be null",
7699 AddAssignExp::AddAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7700 : BinExp(loc
, TOKaddass
, sizeof(AddAssignExp
), e1
, e2
)
7704 Expression
*AddAssignExp::semantic(Scope
*sc
)
7710 BinExp::semantic(sc
);
7711 e2
= resolveProperties(sc
, e2
);
7713 e
= op_overload(sc
);
7717 e1
= e1
->modifiableLvalue(sc
, e1
);
7719 Type
*tb1
= e1
->type
->toBasetype();
7720 Type
*tb2
= e2
->type
->toBasetype();
7722 if ((tb1
->ty
== Tarray
|| tb1
->ty
== Tsarray
) &&
7723 (tb2
->ty
== Tarray
|| tb2
->ty
== Tsarray
) &&
7724 tb1
->nextOf()->equals(tb2
->nextOf())
7734 if (allowPtrArith(sc
, e1
) && tb2
->isintegral())
7735 e
= scaleFactor(sc
);
7736 else if (tb1
->ty
== Tbit
|| tb1
->ty
== Tbool
)
7739 // Need to rethink this
7740 if (e1
->op
!= TOKvar
)
7741 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
7746 Identifier
*id
= Lexer::uniqueId("__name");
7748 v
= new VarDeclaration(loc
, tb1
->pointerTo(), id
, NULL
);
7752 v
->parent
= sc
->func
;
7754 ea
= new AddrExp(loc
, e1
);
7755 ea
= new AssignExp(loc
, new VarExp(loc
, v
), ea
);
7757 ex
= new VarExp(loc
, v
);
7758 ex
= new PtrExp(loc
, ex
);
7759 e
= new AddExp(loc
, ex
, e2
);
7760 e
= new CastExp(loc
, e
, e1
->type
);
7761 e
= new AssignExp(loc
, ex
->syntaxCopy(), e
);
7763 e
= new CommaExp(loc
, ea
, e
);
7767 { // Rewrite e1+=e2 to e1=e1+e2
7768 // BUG: doesn't account for side effects in e1
7769 // BUG: other assignment operators for bits aren't handled at all
7770 e
= new AddExp(loc
, e1
, e2
);
7771 e
= new CastExp(loc
, e
, e1
->type
);
7772 e
= new AssignExp(loc
, e1
->syntaxCopy(), e
);
7774 e
= e
->semantic(sc
);
7780 e1
->checkArithmetic();
7781 e2
->checkArithmetic();
7782 if (type
->isreal() || type
->isimaginary())
7784 assert(global
.errors
|| e2
->type
->isfloating());
7785 e2
= e2
->castTo(sc
, e1
->type
);
7793 /************************************************************/
7795 MinAssignExp::MinAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7796 : BinExp(loc
, TOKminass
, sizeof(MinAssignExp
), e1
, e2
)
7800 Expression
*MinAssignExp::semantic(Scope
*sc
)
7806 BinExp::semantic(sc
);
7807 e2
= resolveProperties(sc
, e2
);
7809 e
= op_overload(sc
);
7813 e1
= e1
->modifiableLvalue(sc
, e1
);
7817 if (allowPtrArith(sc
, e1
) && e2
->type
->isintegral())
7818 e
= scaleFactor(sc
);
7821 e1
= e1
->checkArithmetic();
7822 e2
= e2
->checkArithmetic();
7825 if (type
->isreal() || type
->isimaginary())
7827 assert(e2
->type
->isfloating());
7828 e2
= e2
->castTo(sc
, e1
->type
);
7835 /************************************************************/
7837 CatAssignExp::CatAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7838 : BinExp(loc
, TOKcatass
, sizeof(CatAssignExp
), e1
, e2
)
7842 Expression
*CatAssignExp::semantic(Scope
*sc
)
7845 BinExp::semantic(sc
);
7846 e2
= resolveProperties(sc
, e2
);
7848 e
= op_overload(sc
);
7852 if (e1
->op
== TOKslice
)
7853 { SliceExp
*se
= (SliceExp
*)e1
;
7855 if (se
->e1
->type
->toBasetype()->ty
== Tsarray
)
7856 error("cannot append to static array %s", se
->e1
->type
->toChars());
7859 e1
= e1
->modifiableLvalue(sc
, e1
);
7861 Type
*tb1
= e1
->type
->toBasetype();
7862 Type
*tb2
= e2
->type
->toBasetype();
7866 if ((tb1
->ty
== Tarray
) &&
7867 (tb2
->ty
== Tarray
|| tb2
->ty
== Tsarray
) &&
7868 (e2
->implicitConvTo(e1
->type
) ||
7869 tb2
->nextOf()->implicitConvTo(tb1
->nextOf()))
7872 e2
= e2
->castTo(sc
, e1
->type
);
7876 else if ((tb1
->ty
== Tarray
) &&
7877 e2
->implicitConvTo(tb1
->nextOf())
7880 e2
= e2
->castTo(sc
, tb1
->nextOf());
7886 error("cannot append type %s to type %s", tb2
->toChars(), tb1
->toChars());
7887 type
= Type::tint32
;
7893 /************************************************************/
7895 MulAssignExp::MulAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7896 : BinExp(loc
, TOKmulass
, sizeof(MulAssignExp
), e1
, e2
)
7900 Expression
*MulAssignExp::semantic(Scope
*sc
)
7903 BinExp::semantic(sc
);
7904 e2
= resolveProperties(sc
, e2
);
7906 e
= op_overload(sc
);
7910 e1
= e1
->modifiableLvalue(sc
, e1
);
7915 e1
->checkArithmetic();
7916 e2
->checkArithmetic();
7917 if (e2
->type
->isfloating())
7925 if (t2
->isimaginary() || t2
->iscomplex())
7927 e2
= e2
->castTo(sc
, t1
);
7930 else if (t1
->isimaginary())
7932 if (t2
->isimaginary() || t2
->iscomplex())
7936 case Timaginary32
: t2
= Type::tfloat32
; break;
7937 case Timaginary64
: t2
= Type::tfloat64
; break;
7938 case Timaginary80
: t2
= Type::tfloat80
; break;
7942 e2
= e2
->castTo(sc
, t2
);
7949 /************************************************************/
7951 DivAssignExp::DivAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7952 : BinExp(loc
, TOKdivass
, sizeof(DivAssignExp
), e1
, e2
)
7956 Expression
*DivAssignExp::semantic(Scope
*sc
)
7959 BinExp::semantic(sc
);
7960 e2
= resolveProperties(sc
, e2
);
7962 e
= op_overload(sc
);
7966 e1
= e1
->modifiableLvalue(sc
, e1
);
7971 e1
->checkArithmetic();
7972 e2
->checkArithmetic();
7973 if (e2
->type
->isimaginary())
7980 // Therefore, the result is 0
7981 e2
= new CommaExp(loc
, e2
, new RealExp(loc
, 0, t1
));
7983 e
= new AssignExp(loc
, e1
, e2
);
7987 else if (t1
->isimaginary())
7992 case Timaginary32
: t2
= Type::tfloat32
; break;
7993 case Timaginary64
: t2
= Type::tfloat64
; break;
7994 case Timaginary80
: t2
= Type::tfloat80
; break;
7998 e2
= e2
->castTo(sc
, t2
);
7999 e
= new AssignExp(loc
, e1
, e2
);
8007 /************************************************************/
8009 ModAssignExp::ModAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8010 : BinExp(loc
, TOKmodass
, sizeof(ModAssignExp
), e1
, e2
)
8014 Expression
*ModAssignExp::semantic(Scope
*sc
)
8016 return commonSemanticAssign(sc
);
8019 /************************************************************/
8021 ShlAssignExp::ShlAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8022 : BinExp(loc
, TOKshlass
, sizeof(ShlAssignExp
), e1
, e2
)
8026 Expression
*ShlAssignExp::semantic(Scope
*sc
)
8029 //printf("ShlAssignExp::semantic()\n");
8030 BinExp::semantic(sc
);
8031 e2
= resolveProperties(sc
, e2
);
8033 e
= op_overload(sc
);
8037 e1
= e1
->modifiableLvalue(sc
, e1
);
8042 e1
->checkIntegral();
8043 e2
= e2
->checkIntegral();
8044 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8048 /************************************************************/
8050 ShrAssignExp::ShrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8051 : BinExp(loc
, TOKshrass
, sizeof(ShrAssignExp
), e1
, e2
)
8055 Expression
*ShrAssignExp::semantic(Scope
*sc
)
8058 BinExp::semantic(sc
);
8059 e2
= resolveProperties(sc
, e2
);
8061 e
= op_overload(sc
);
8065 e1
= e1
->modifiableLvalue(sc
, e1
);
8070 e1
->checkIntegral();
8071 e2
= e2
->checkIntegral();
8072 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8076 /************************************************************/
8078 UshrAssignExp::UshrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8079 : BinExp(loc
, TOKushrass
, sizeof(UshrAssignExp
), e1
, e2
)
8083 Expression
*UshrAssignExp::semantic(Scope
*sc
)
8086 BinExp::semantic(sc
);
8087 e2
= resolveProperties(sc
, e2
);
8089 e
= op_overload(sc
);
8093 e1
= e1
->modifiableLvalue(sc
, e1
);
8098 e1
->checkIntegral();
8099 e2
= e2
->checkIntegral();
8100 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8104 /************************************************************/
8106 AndAssignExp::AndAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8107 : BinExp(loc
, TOKandass
, sizeof(AndAssignExp
), e1
, e2
)
8111 Expression
*AndAssignExp::semantic(Scope
*sc
)
8113 return commonSemanticAssignIntegral(sc
);
8116 /************************************************************/
8118 OrAssignExp::OrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8119 : BinExp(loc
, TOKorass
, sizeof(OrAssignExp
), e1
, e2
)
8123 Expression
*OrAssignExp::semantic(Scope
*sc
)
8125 return commonSemanticAssignIntegral(sc
);
8128 /************************************************************/
8130 XorAssignExp::XorAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8131 : BinExp(loc
, TOKxorass
, sizeof(XorAssignExp
), e1
, e2
)
8135 Expression
*XorAssignExp::semantic(Scope
*sc
)
8137 return commonSemanticAssignIntegral(sc
);
8140 /************************* AddExp *****************************/
8142 AddExp::AddExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8143 : BinExp(loc
, TOKadd
, sizeof(AddExp
), e1
, e2
)
8147 Expression
*AddExp::semantic(Scope
*sc
)
8151 printf("AddExp::semantic('%s')\n", toChars());
8155 BinExp::semanticp(sc
);
8157 e
= op_overload(sc
);
8161 Type
*tb1
= e1
->type
->toBasetype();
8162 Type
*tb2
= e2
->type
->toBasetype();
8164 if ((tb1
->ty
== Tarray
|| tb1
->ty
== Tsarray
) &&
8165 (tb2
->ty
== Tarray
|| tb2
->ty
== Tsarray
) &&
8166 tb1
->nextOf()->equals(tb2
->nextOf())
8172 else if (tb1
->ty
== Tpointer
&& e2
->type
->isintegral() ||
8173 tb2
->ty
== Tpointer
&& e1
->type
->isintegral())
8174 e
= scaleFactor(sc
);
8175 else if (tb1
->ty
== Tpointer
&& tb2
->ty
== Tpointer
)
8177 incompatibleTypes();
8184 if ((e1
->type
->isreal() && e2
->type
->isimaginary()) ||
8185 (e1
->type
->isimaginary() && e2
->type
->isreal()))
8187 switch (type
->toBasetype()->ty
)
8191 type
= Type::tcomplex32
;
8196 type
= Type::tcomplex64
;
8201 type
= Type::tcomplex80
;
8215 /************************************************************/
8217 MinExp::MinExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8218 : BinExp(loc
, TOKmin
, sizeof(MinExp
), e1
, e2
)
8222 Expression
*MinExp::semantic(Scope
*sc
)
8228 printf("MinExp::semantic('%s')\n", toChars());
8233 BinExp::semanticp(sc
);
8235 e
= op_overload(sc
);
8240 t1
= e1
->type
->toBasetype();
8241 t2
= e2
->type
->toBasetype();
8242 if (t1
->ty
== Tpointer
)
8244 if (t2
->ty
== Tpointer
)
8245 { // Need to divide the result by the stride
8246 // Replace (ptr - ptr) with (ptr - ptr) / stride
8250 typeCombine(sc
); // make sure pointer types are compatible
8251 type
= Type::tptrdiff_t
;
8252 stride
= t2
->nextOf()->size();
8253 e
= new DivExp(loc
, this, new IntegerExp(0, stride
, Type::tptrdiff_t
));
8254 e
->type
= Type::tptrdiff_t
;
8257 else if (t2
->isintegral())
8258 e
= scaleFactor(sc
);
8260 { error("incompatible types for -");
8261 return new IntegerExp(0);
8264 else if (t2
->ty
== Tpointer
)
8267 error("can't subtract pointer from %s", e1
->type
->toChars());
8268 return new IntegerExp(0);
8273 t1
= e1
->type
->toBasetype();
8274 t2
= e2
->type
->toBasetype();
8275 if ((t1
->isreal() && t2
->isimaginary()) ||
8276 (t1
->isimaginary() && t2
->isreal()))
8282 type
= Type::tcomplex32
;
8287 type
= Type::tcomplex64
;
8292 type
= Type::tcomplex80
;
8303 /************************* CatExp *****************************/
8305 CatExp::CatExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8306 : BinExp(loc
, TOKcat
, sizeof(CatExp
), e1
, e2
)
8310 Expression
*CatExp::semantic(Scope
*sc
)
8313 //printf("CatExp::semantic() %s\n", toChars());
8316 BinExp::semanticp(sc
);
8317 e
= op_overload(sc
);
8321 Type
*tb1
= e1
->type
->toBasetype();
8322 Type
*tb2
= e2
->type
->toBasetype();
8325 /* BUG: Should handle things like:
8335 if ((tb1
->ty
== Tsarray
|| tb1
->ty
== Tarray
) &&
8336 e2
->type
->implicitConvTo(tb1
->nextOf()) >= MATCHconst
)
8338 type
= tb1
->nextOf()->arrayOf();
8339 if (tb2
->ty
== Tarray
)
8340 { // Make e2 into [e2]
8341 e2
= new ArrayLiteralExp(e2
->loc
, e2
);
8346 else if ((tb2
->ty
== Tsarray
|| tb2
->ty
== Tarray
) &&
8347 e1
->type
->implicitConvTo(tb2
->nextOf()) >= MATCHconst
)
8349 type
= tb2
->nextOf()->arrayOf();
8350 if (tb1
->ty
== Tarray
)
8351 { // Make e1 into [e1]
8352 e1
= new ArrayLiteralExp(e1
->loc
, e1
);
8359 if (type
->ty
== Tmaybe
)
8360 error("Cannot join arrays that may be null (%s)", toChars());
8362 type
= type
->toHeadMutable();
8364 Type
*tb
= type
->toBasetype();
8365 if (tb
->ty
== Tsarray
)
8366 type
= tb
->nextOf()->arrayOf();
8367 if (type
->ty
== Tarray
&& tb1
->nextOf() && tb2
->nextOf() &&
8368 tb1
->nextOf()->mod
!= tb2
->nextOf()->mod
)
8369 type
= type
->nextOf()->toHeadMutable()->arrayOf();
8376 Type
*t1
= e1
->type
->toBasetype();
8377 Type
*t2
= e2
->type
->toBasetype();
8378 if (e1
->op
== TOKstring
&& e2
->op
== TOKstring
)
8379 e
= optimize(WANTvalue
);
8380 else if ((t1
->ty
== Tarray
|| t1
->ty
== Tsarray
) &&
8381 (t2
->ty
== Tarray
|| t2
->ty
== Tsarray
))
8387 //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
8388 error("Can only concatenate arrays, not (%s ~ %s)",
8389 e1
->type
->toChars(), e2
->type
->toChars());
8390 type
= Type::tint32
;
8393 e
->type
= e
->type
->semantic(loc
, sc
);
8399 /************************************************************/
8401 MulExp::MulExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8402 : BinExp(loc
, TOKmul
, sizeof(MulExp
), e1
, e2
)
8406 Expression
*MulExp::semantic(Scope
*sc
)
8410 printf("MulExp::semantic() %s\n", toChars());
8417 BinExp::semanticp(sc
);
8418 e
= op_overload(sc
);
8423 e1
->checkArithmetic();
8424 e2
->checkArithmetic();
8425 if (type
->isfloating())
8426 { Type
*t1
= e1
->type
;
8427 Type
*t2
= e2
->type
;
8433 else if (t2
->isreal())
8437 else if (t1
->isimaginary())
8439 if (t2
->isimaginary())
8444 case Timaginary32
: type
= Type::tfloat32
; break;
8445 case Timaginary64
: type
= Type::tfloat64
; break;
8446 case Timaginary80
: type
= Type::tfloat80
; break;
8453 e
= new NegExp(loc
, this);
8454 e
= e
->semantic(sc
);
8458 type
= t2
; // t2 is complex
8460 else if (t2
->isimaginary())
8462 type
= t1
; // t1 is complex
8468 /************************************************************/
8470 DivExp::DivExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8471 : BinExp(loc
, TOKdiv
, sizeof(DivExp
), e1
, e2
)
8475 Expression
*DivExp::semantic(Scope
*sc
)
8481 BinExp::semanticp(sc
);
8482 e
= op_overload(sc
);
8487 e1
->checkArithmetic();
8488 e2
->checkArithmetic();
8489 if (type
->isfloating())
8490 { Type
*t1
= e1
->type
;
8491 Type
*t2
= e2
->type
;
8496 if (t2
->isimaginary())
8501 e
= new NegExp(loc
, this);
8502 e
= e
->semantic(sc
);
8506 else if (t2
->isreal())
8510 else if (t1
->isimaginary())
8512 if (t2
->isimaginary())
8516 case Timaginary32
: type
= Type::tfloat32
; break;
8517 case Timaginary64
: type
= Type::tfloat64
; break;
8518 case Timaginary80
: type
= Type::tfloat80
; break;
8523 type
= t2
; // t2 is complex
8525 else if (t2
->isimaginary())
8527 type
= t1
; // t1 is complex
8533 /************************************************************/
8535 ModExp::ModExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8536 : BinExp(loc
, TOKmod
, sizeof(ModExp
), e1
, e2
)
8540 Expression
*ModExp::semantic(Scope
*sc
)
8546 BinExp::semanticp(sc
);
8547 e
= op_overload(sc
);
8552 e1
->checkArithmetic();
8553 e2
->checkArithmetic();
8554 if (type
->isfloating())
8556 if (e2
->type
->iscomplex())
8557 { error("cannot perform modulo complex arithmetic");
8558 return new IntegerExp(0);
8564 /************************************************************/
8566 ShlExp::ShlExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8567 : BinExp(loc
, TOKshl
, sizeof(ShlExp
), e1
, e2
)
8571 Expression
*ShlExp::semantic(Scope
*sc
)
8574 //printf("ShlExp::semantic(), type = %p\n", type);
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 ShrExp::ShrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8592 : BinExp(loc
, TOKshr
, sizeof(ShrExp
), e1
, e2
)
8596 Expression
*ShrExp::semantic(Scope
*sc
)
8600 { BinExp::semanticp(sc
);
8601 e
= op_overload(sc
);
8604 e1
= e1
->checkIntegral();
8605 e2
= e2
->checkIntegral();
8606 e1
= e1
->integralPromotions(sc
);
8607 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8613 /************************************************************/
8615 UshrExp::UshrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8616 : BinExp(loc
, TOKushr
, sizeof(UshrExp
), e1
, e2
)
8620 Expression
*UshrExp::semantic(Scope
*sc
)
8624 { BinExp::semanticp(sc
);
8625 e
= op_overload(sc
);
8628 e1
= e1
->checkIntegral();
8629 e2
= e2
->checkIntegral();
8630 e1
= e1
->integralPromotions(sc
);
8631 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8637 /************************************************************/
8639 AndExp::AndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8640 : BinExp(loc
, TOKand
, sizeof(AndExp
), e1
, e2
)
8644 Expression
*AndExp::semantic(Scope
*sc
)
8648 { BinExp::semanticp(sc
);
8649 e
= op_overload(sc
);
8652 if (e1
->type
->toBasetype()->ty
== Tbool
&&
8653 e2
->type
->toBasetype()->ty
== Tbool
)
8661 e1
->checkIntegral();
8662 e2
->checkIntegral();
8668 /************************************************************/
8670 OrExp::OrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8671 : BinExp(loc
, TOKor
, sizeof(OrExp
), e1
, e2
)
8675 Expression
*OrExp::semantic(Scope
*sc
)
8679 { BinExp::semanticp(sc
);
8680 e
= op_overload(sc
);
8683 if (e1
->type
->toBasetype()->ty
== Tbool
&&
8684 e2
->type
->toBasetype()->ty
== Tbool
)
8692 e1
->checkIntegral();
8693 e2
->checkIntegral();
8699 /************************************************************/
8701 XorExp::XorExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8702 : BinExp(loc
, TOKxor
, sizeof(XorExp
), e1
, e2
)
8706 Expression
*XorExp::semantic(Scope
*sc
)
8710 { BinExp::semanticp(sc
);
8711 e
= op_overload(sc
);
8714 if (e1
->type
->toBasetype()->ty
== Tbool
&&
8715 e2
->type
->toBasetype()->ty
== Tbool
)
8723 e1
->checkIntegral();
8724 e2
->checkIntegral();
8731 /************************************************************/
8733 OrOrExp::OrOrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8734 : BinExp(loc
, TOKoror
, sizeof(OrOrExp
), e1
, e2
)
8738 Expression
*OrOrExp::semantic(Scope
*sc
)
8742 // same as for AndAnd
8743 e1
= e1
->semantic(sc
);
8744 e1
= resolveProperties(sc
, e1
);
8745 e1
= e1
->checkToPointer();
8746 e1
= e1
->checkToBoolean();
8747 cs1
= sc
->callSuper
;
8749 if (sc
->flags
& SCOPEstaticif
)
8751 /* If in static if, don't evaluate e2 if we don't have to.
8753 e1
= e1
->optimize(WANTflags
);
8754 if (e1
->isBool(TRUE
))
8756 return new IntegerExp(loc
, 1, Type::tboolean
);
8760 e2
= e2
->semantic(sc
);
8761 sc
->mergeCallSuper(loc
, cs1
);
8762 e2
= resolveProperties(sc
, e2
);
8763 e2
= e2
->checkToPointer();
8765 type
= Type::tboolean
;
8766 if (e1
->type
->ty
== Tvoid
)
8768 if (e2
->op
== TOKtype
|| e2
->op
== TOKimport
)
8769 error("%s is not an expression", e2
->toChars());
8773 Expression
*OrOrExp::checkToBoolean()
8775 e2
= e2
->checkToBoolean();
8779 int OrOrExp::isBit()
8784 int OrOrExp::checkSideEffect(int flag
)
8788 return e1
->checkSideEffect(2) || e2
->checkSideEffect(2);
8791 { e1
->checkSideEffect(1);
8792 return e2
->checkSideEffect(flag
);
8796 /************************************************************/
8798 AndAndExp::AndAndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8799 : BinExp(loc
, TOKandand
, sizeof(AndAndExp
), e1
, e2
)
8803 Expression
*AndAndExp::semantic(Scope
*sc
)
8808 e1
= e1
->semantic(sc
);
8809 e1
= resolveProperties(sc
, e1
);
8810 e1
= e1
->checkToPointer();
8811 e1
= e1
->checkToBoolean();
8812 cs1
= sc
->callSuper
;
8814 if (sc
->flags
& SCOPEstaticif
)
8816 /* If in static if, don't evaluate e2 if we don't have to.
8818 e1
= e1
->optimize(WANTflags
);
8819 if (e1
->isBool(FALSE
))
8821 return new IntegerExp(loc
, 0, Type::tboolean
);
8825 e2
= e2
->semantic(sc
);
8826 sc
->mergeCallSuper(loc
, cs1
);
8827 e2
= resolveProperties(sc
, e2
);
8828 e2
= e2
->checkToPointer();
8830 type
= Type::tboolean
;
8831 if (e1
->type
->ty
== Tvoid
)
8833 if (e2
->op
== TOKtype
|| e2
->op
== TOKimport
)
8834 error("%s is not an expression", e2
->toChars());
8838 Expression
*AndAndExp::checkToBoolean()
8840 e2
= e2
->checkToBoolean();
8844 int AndAndExp::isBit()
8849 int AndAndExp::checkSideEffect(int flag
)
8853 return e1
->checkSideEffect(2) || e2
->checkSideEffect(2);
8857 e1
->checkSideEffect(1);
8858 return e2
->checkSideEffect(flag
);
8862 /************************************************************/
8864 InExp::InExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8865 : BinExp(loc
, TOKin
, sizeof(InExp
), e1
, e2
)
8869 Expression
*InExp::semantic(Scope
*sc
)
8875 BinExp::semanticp(sc
);
8876 e
= op_overload(sc
);
8880 //type = Type::tboolean;
8881 Type
*t2b
= e2
->type
->toBasetype();
8882 if (t2b
->ty
!= Taarray
)
8884 error("rvalue of in expression must be an associative array, not %s", e2
->type
->toChars());
8885 type
= Type::terror
;
8889 TypeAArray
*ta
= (TypeAArray
*)t2b
;
8891 // Convert key to type of key
8892 e1
= e1
->implicitCastTo(sc
, ta
->index
);
8894 // Return type is pointer to value
8895 type
= ta
->nextOf()->pointerTo();
8897 type
= type
->maybe(true);
8908 /************************************************************/
8910 /* This deletes the key e1 from the associative array e2
8913 RemoveExp::RemoveExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8914 : BinExp(loc
, TOKremove
, sizeof(RemoveExp
), e1
, e2
)
8919 /************************************************************/
8921 CmpExp::CmpExp(enum TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
8922 : BinExp(loc
, op
, sizeof(CmpExp
), e1
, e2
)
8926 Expression
*CmpExp::semantic(Scope
*sc
)
8932 printf("CmpExp::semantic('%s')\n", toChars());
8937 BinExp::semanticp(sc
);
8939 if (e1
->type
->toBasetype()->ty
== Tclass
&& e2
->op
== TOKnull
||
8940 e2
->type
->toBasetype()->ty
== Tclass
&& e1
->op
== TOKnull
)
8942 error("do not use null when comparing class types");
8945 e
= op_overload(sc
);
8948 e
= new CmpExp(op
, loc
, e
, new IntegerExp(loc
, 0, Type::tint32
));
8949 e
= e
->semantic(sc
);
8954 type
= Type::tboolean
;
8956 // Special handling for array comparisons
8957 t1
= e1
->type
->toBasetype();
8958 t2
= e2
->type
->toBasetype();
8959 if ((t1
->ty
== Tarray
|| t1
->ty
== Tsarray
|| t1
->ty
== Tpointer
) &&
8960 (t2
->ty
== Tarray
|| t2
->ty
== Tsarray
|| t2
->ty
== Tpointer
))
8962 if (t1
->nextOf()->implicitConvTo(t2
->nextOf()) < MATCHconst
&&
8963 t2
->nextOf()->implicitConvTo(t1
->nextOf()) < MATCHconst
&&
8964 (t1
->nextOf()->ty
!= Tvoid
&& t2
->nextOf()->ty
!= Tvoid
))
8965 error("array comparison type mismatch, %s vs %s", t1
->nextOf()->toChars(), t2
->nextOf()->toChars());
8968 else if (t1
->ty
== Tstruct
|| t2
->ty
== Tstruct
||
8969 (t1
->ty
== Tclass
&& t2
->ty
== Tclass
))
8971 if (t2
->ty
== Tstruct
)
8972 error("need member function opCmp() for %s %s to compare", t2
->toDsymbol(sc
)->kind(), t2
->toChars());
8974 error("need member function opCmp() for %s %s to compare", t1
->toDsymbol(sc
)->kind(), t1
->toChars());
8978 else if (t1
->iscomplex() || t2
->iscomplex())
8980 error("compare not defined for complex operands");
8981 e
= new IntegerExp(0);
8986 //printf("CmpExp: %s\n", e->toChars());
8996 /************************************************************/
8998 EqualExp::EqualExp(enum TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
8999 : BinExp(loc
, op
, sizeof(EqualExp
), e1
, e2
)
9001 assert(op
== TOKequal
|| op
== TOKnotequal
);
9004 Expression
*EqualExp::semantic(Scope
*sc
)
9009 //printf("EqualExp::semantic('%s')\n", toChars());
9013 BinExp::semanticp(sc
);
9015 /* Before checking for operator overloading, check to see if we're
9016 * comparing the addresses of two statics. If so, we can just see
9017 * if they are the same symbol.
9019 if (e1
->op
== TOKaddress
&& e2
->op
== TOKaddress
)
9020 { AddrExp
*ae1
= (AddrExp
*)e1
;
9021 AddrExp
*ae2
= (AddrExp
*)e2
;
9023 if (ae1
->e1
->op
== TOKvar
&& ae2
->e1
->op
== TOKvar
)
9024 { VarExp
*ve1
= (VarExp
*)ae1
->e1
;
9025 VarExp
*ve2
= (VarExp
*)ae2
->e1
;
9027 if (ve1
->var
== ve2
->var
/*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
9029 // They are the same, result is 'true' for ==, 'false' for !=
9030 e
= new IntegerExp(loc
, (op
== TOKequal
), Type::tboolean
);
9036 if (e1
->type
->toBasetype()->ty
== Tclass
&& e2
->op
== TOKnull
||
9037 e2
->type
->toBasetype()->ty
== Tclass
&& e1
->op
== TOKnull
)
9039 error("use '%s' instead of '%s' when comparing with null",
9040 Token::toChars(op
== TOKequal
? TOKidentity
: TOKnotidentity
),
9041 Token::toChars(op
));
9044 //if (e2->op != TOKnull)
9046 e
= op_overload(sc
);
9049 if (op
== TOKnotequal
)
9051 e
= new NotExp(e
->loc
, e
);
9052 e
= e
->semantic(sc
);
9058 e
= typeCombine(sc
);
9059 type
= Type::tboolean
;
9061 // Special handling for array comparisons
9062 t1
= e1
->type
->toBasetype();
9063 t2
= e2
->type
->toBasetype();
9065 if ((t1
->ty
== Tarray
|| t1
->ty
== Tsarray
|| t1
->ty
== Tpointer
) &&
9066 (t2
->ty
== Tarray
|| t2
->ty
== Tsarray
|| t2
->ty
== Tpointer
))
9068 if (t1
->nextOf()->implicitConvTo(t2
->nextOf()) < MATCHconst
&&
9069 t2
->nextOf()->implicitConvTo(t1
->nextOf()) < MATCHconst
&&
9070 (t1
->nextOf()->ty
!= Tvoid
&& t2
->nextOf()->ty
!= Tvoid
))
9071 error("array equality comparison type mismatch, %s vs %s", t1
->toChars(), t2
->toChars());
9075 if (e1
->type
!= e2
->type
&& e1
->type
->isfloating() && e2
->type
->isfloating())
9077 // Cast both to complex
9078 e1
= e1
->castTo(sc
, Type::tcomplex80
);
9079 e2
= e2
->castTo(sc
, Type::tcomplex80
);
9085 int EqualExp::isBit()
9092 /************************************************************/
9094 IdentityExp::IdentityExp(enum TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
9095 : BinExp(loc
, op
, sizeof(IdentityExp
), e1
, e2
)
9099 Expression
*IdentityExp::semantic(Scope
*sc
)
9104 BinExp::semanticp(sc
);
9105 type
= Type::tboolean
;
9107 if (e1
->type
!= e2
->type
&& e1
->type
->isfloating() && e2
->type
->isfloating())
9109 // Cast both to complex
9110 e1
= e1
->castTo(sc
, Type::tcomplex80
);
9111 e2
= e2
->castTo(sc
, Type::tcomplex80
);
9116 int IdentityExp::isBit()
9122 /****************************************************************/
9124 CondExp::CondExp(Loc loc
, Expression
*econd
, Expression
*e1
, Expression
*e2
)
9125 : BinExp(loc
, TOKquestion
, sizeof(CondExp
), e1
, e2
)
9127 this->econd
= econd
;
9130 Expression
*CondExp::syntaxCopy()
9132 return new CondExp(loc
, econd
->syntaxCopy(), e1
->syntaxCopy(), e2
->syntaxCopy());
9136 Expression
*CondExp::semantic(Scope
*sc
)
9143 printf("CondExp::semantic('%s')\n", toChars());
9148 econd
= econd
->semantic(sc
);
9149 econd
= resolveProperties(sc
, econd
);
9150 econd
= econd
->checkToPointer();
9151 econd
= econd
->checkToBoolean();
9153 #if 0 /* this cannot work right because the types of e1 and e2
9154 * both contribute to the type of the result.
9156 if (sc
->flags
& SCOPEstaticif
)
9158 /* If in static if, don't evaluate what we don't have to.
9160 econd
= econd
->optimize(WANTflags
);
9161 if (econd
->isBool(TRUE
))
9163 e1
= e1
->semantic(sc
);
9164 e1
= resolveProperties(sc
, e1
);
9167 else if (econd
->isBool(FALSE
))
9169 e2
= e2
->semantic(sc
);
9170 e2
= resolveProperties(sc
, e2
);
9177 cs0
= sc
->callSuper
;
9178 e1
= e1
->semantic(sc
);
9179 e1
= resolveProperties(sc
, e1
);
9180 cs1
= sc
->callSuper
;
9181 sc
->callSuper
= cs0
;
9182 e2
= e2
->semantic(sc
);
9183 e2
= resolveProperties(sc
, e2
);
9184 sc
->mergeCallSuper(loc
, cs1
);
9187 // If either operand is void, the result is void
9190 if (t1
->ty
== Tvoid
|| t2
->ty
== Tvoid
)
9197 switch (e1
->type
->toBasetype()->ty
)
9202 e2
= e2
->castTo(sc
, e1
->type
);
9205 switch (e2
->type
->toBasetype()->ty
)
9210 e1
= e1
->castTo(sc
, e2
->type
);
9213 if (type
->toBasetype()->ty
== Tarray
)
9215 e1
= e1
->castTo(sc
, type
);
9216 e2
= e2
->castTo(sc
, type
);
9220 printf("res: %s\n", type
->toChars());
9221 printf("e1 : %s\n", e1
->type
->toChars());
9222 printf("e2 : %s\n", e2
->type
->toChars());
9227 Expression
*CondExp::toLvalue(Scope
*sc
, Expression
*ex
)
9231 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
9232 e
= new PtrExp(loc
, this, type
);
9234 e1
= e1
->addressOf(sc
);
9235 //e1 = e1->toLvalue(sc, NULL);
9237 e2
= e2
->addressOf(sc
);
9238 //e2 = e2->toLvalue(sc, NULL);
9246 Expression
*CondExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
9248 error("conditional expression %s is not a modifiable lvalue", toChars());
9252 void CondExp::checkEscape()
9259 Expression
*CondExp::checkToBoolean()
9261 e1
= e1
->checkToBoolean();
9262 e2
= e2
->checkToBoolean();
9266 int CondExp::checkSideEffect(int flag
)
9270 return econd
->checkSideEffect(2) ||
9271 e1
->checkSideEffect(2) ||
9272 e2
->checkSideEffect(2);
9276 econd
->checkSideEffect(1);
9277 e1
->checkSideEffect(flag
);
9278 return e2
->checkSideEffect(flag
);
9282 int CondExp::canThrow()
9284 return econd
->canThrow() || e1
->canThrow() || e2
->canThrow();
9288 void CondExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
9290 expToCBuffer(buf
, hgs
, econd
, PREC_oror
);
9291 buf
->writestring(" ? ");
9292 expToCBuffer(buf
, hgs
, e1
, PREC_expr
);
9293 buf
->writestring(" : ");
9294 expToCBuffer(buf
, hgs
, e2
, PREC_cond
);
9298 /****************************************************************/
9300 DefaultInitExp::DefaultInitExp(Loc loc
, enum TOK subop
, int size
)
9301 : Expression(loc
, TOKdefault
, size
)
9303 this->subop
= subop
;
9306 void DefaultInitExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
9308 buf
->writestring(Token::toChars(subop
));
9311 /****************************************************************/
9313 FileInitExp::FileInitExp(Loc loc
)
9314 : DefaultInitExp(loc
, TOKfile
, sizeof(FileInitExp
))
9318 Expression
*FileInitExp::semantic(Scope
*sc
)
9320 //printf("FileInitExp::semantic()\n");
9321 type
= Type::tchar
->invariantOf()->arrayOf();
9325 Expression
*FileInitExp::resolve(Loc loc
, Scope
*sc
)
9327 //printf("FileInitExp::resolve() %s\n", toChars());
9328 char *s
= loc
.filename
? loc
.filename
: sc
->module
->ident
->toChars();
9329 Expression
*e
= new StringExp(loc
, s
);
9330 e
= e
->semantic(sc
);
9331 e
= e
->castTo(sc
, type
);
9335 /****************************************************************/
9337 LineInitExp::LineInitExp(Loc loc
)
9338 : DefaultInitExp(loc
, TOKline
, sizeof(LineInitExp
))
9342 Expression
*LineInitExp::semantic(Scope
*sc
)
9344 type
= Type::tint32
;
9348 Expression
*LineInitExp::resolve(Loc loc
, Scope
*sc
)
9350 Expression
*e
= new IntegerExp(loc
, loc
.linnum
, Type::tint32
);
9351 e
= e
->castTo(sc
, type
);