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
);
586 ((NullExp
*) arg
)->dUnchecked
= true;
590 Identifier
*id
= Lexer::uniqueId("__arrayArg");
591 Type
*t
= new TypeSArray(((TypeArray
*)tb
)->next
, new IntegerExp(nargs
- i
));
592 t
= t
->semantic(loc
, sc
);
593 VarDeclaration
*v
= new VarDeclaration(loc
, t
, id
, new VoidInitializer(loc
));
595 v
->parent
= sc
->parent
;
598 Expression
*c
= new DeclarationExp(0, v
);
601 for (size_t u
= i
; u
< nargs
; u
++)
602 { Expression
*a
= (Expression
*)arguments
->data
[u
];
603 if (tret
&& !((TypeArray
*)tb
)->next
->equals(a
->type
))
604 a
= a
->toDelegate(sc
, tret
);
606 Expression
*e
= new VarExp(loc
, v
);
607 e
= new IndexExp(loc
, e
, new IntegerExp(u
+ 1 - nparams
));
608 AssignExp
*ae
= new AssignExp(loc
, e
, a
);
609 ae
->op
= TOKconstruct
;
611 c
= new CommaExp(loc
, c
, ae
);
615 arg
= new VarExp(loc
, v
);
617 arg
= new CommaExp(loc
, c
, arg
);
622 * new Tclass(arg0, arg1, ..., argn)
624 Expressions
*args
= new Expressions();
625 args
->setDim(nargs
- i
);
626 for (size_t u
= i
; u
< nargs
; u
++)
627 args
->data
[u
- i
] = arguments
->data
[u
];
628 arg
= new NewExp(loc
, NULL
, NULL
, p
->type
, args
);
633 { error(loc
, "not enough arguments");
638 arg
= arg
->semantic(sc
);
639 //printf("\targ = '%s'\n", arg->toChars());
640 arguments
->setDim(i
+ 1);
645 if (!(p
->storageClass
& STClazy
&& p
->type
->ty
== Tvoid
))
647 if (p
->type
!= arg
->type
)
649 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
650 arg
= arg
->implicitCastTo(sc
, p
->type
);
651 arg
= arg
->optimize(WANTvalue
);
654 if (p
->storageClass
& STCref
)
656 arg
= arg
->toLvalue(sc
, arg
);
658 else if (p
->storageClass
& STCout
)
660 arg
= arg
->modifiableLvalue(sc
, arg
);
663 // Convert static arrays to pointers
664 tb
= arg
->type
->toBasetype();
665 if (tb
->ty
== Tsarray
)
667 arg
= arg
->checkToPointer();
670 if (tb
->ty
== Tstruct
&& !(p
->storageClass
& (STCref
| STCout
)))
672 arg
= callCpCtor(loc
, sc
, arg
);
675 // Convert lazy argument to a delegate
676 if (p
->storageClass
& STClazy
)
678 arg
= arg
->toDelegate(sc
, p
->type
);
684 // If not D linkage, do promotions
685 if (tf
->linkage
!= LINKd
)
687 // Promote bytes, words, etc., to ints
688 arg
= arg
->integralPromotions(sc
);
690 // Promote floats to doubles
691 switch (arg
->type
->ty
)
694 arg
= arg
->castTo(sc
, Type::tfloat64
);
698 arg
= arg
->castTo(sc
, Type::timaginary64
);
703 // Convert static arrays to dynamic arrays
704 tb
= arg
->type
->toBasetype();
705 if (tb
->ty
== Tsarray
)
706 { TypeSArray
*ts
= (TypeSArray
*)tb
;
707 Type
*ta
= ts
->next
->arrayOf();
708 if (ts
->size(arg
->loc
) == 0)
709 { arg
= new NullExp(arg
->loc
);
713 arg
= arg
->castTo(sc
, ta
);
716 if (tb
->ty
== Tstruct
)
718 arg
= callCpCtor(loc
, sc
, arg
);
721 // Give error for overloaded function addresses
722 if (arg
->op
== TOKsymoff
)
723 { SymOffExp
*se
= (SymOffExp
*)arg
;
724 if (se
->hasOverloads
&& !se
->var
->isFuncDeclaration()->isUnique())
725 arg
->error("function %s is overloaded", arg
->toChars());
730 arg
= arg
->optimize(WANTvalue
);
731 arguments
->data
[i
] = (void *) arg
;
736 // If D linkage and variadic, add _arguments[] as first argument
737 if (tf
->linkage
== LINKd
&& tf
->varargs
== 1)
741 e
= createTypeInfoArray(sc
, (Expression
**)&arguments
->data
[nparams
],
742 arguments
->dim
- nparams
);
743 arguments
->insert(0, e
);
747 /**************************************************
748 * Write expression out to buf, but wrap it
749 * in ( ) if its precedence is less than pr.
752 void expToCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
, Expression
*e
, enum PREC pr
)
754 //if (precedence[e->op] == 0) e->dump(0);
755 if (precedence
[e
->op
] < pr
)
758 e
->toCBuffer(buf
, hgs
);
762 e
->toCBuffer(buf
, hgs
);
765 /**************************************************
766 * Write out argument list to buf.
769 void argsToCBuffer(OutBuffer
*buf
, Expressions
*arguments
, HdrGenState
*hgs
)
773 for (size_t i
= 0; i
< arguments
->dim
; i
++)
774 { Expression
*arg
= (Expression
*)arguments
->data
[i
];
779 expToCBuffer(buf
, hgs
, arg
, PREC_assign
);
785 /**************************************************
786 * Write out argument types to buf.
789 void argExpTypesToCBuffer(OutBuffer
*buf
, Expressions
*arguments
, HdrGenState
*hgs
)
794 for (size_t i
= 0; i
< arguments
->dim
; i
++)
795 { Expression
*arg
= (Expression
*)arguments
->data
[i
];
800 arg
->type
->toCBuffer2(&argbuf
, hgs
, 0);
806 /******************************** Expression **************************/
808 Expression::Expression(Loc loc
, enum TOK op
, int size
)
817 Expression
*Expression::syntaxCopy()
819 //printf("Expression::syntaxCopy()\n");
824 /*********************************
825 * Does *not* do a deep copy.
828 Expression
*Expression::copy()
834 fprintf(stdmsg
, "No expression copy for: %s\n", toChars());
835 printf("op = %d\n", op
);
840 e
= (Expression
*)mem
.malloc(size
);
841 return (Expression
*)memcpy(e
, this, size
);
844 /**************************
845 * Semantically analyze Expression.
846 * Determine types, fold constants, etc.
849 Expression
*Expression::semantic(Scope
*sc
)
852 printf("Expression::semantic() %s\n", toChars());
855 type
= type
->semantic(loc
, sc
);
861 void Expression::print()
863 fprintf(stdmsg
, "%s\n", toChars());
867 char *Expression::toChars()
871 memset(&hgs
, 0, sizeof(hgs
));
872 buf
= new OutBuffer();
873 toCBuffer(buf
, &hgs
);
874 return buf
->toChars();
877 void Expression::error(const char *format
, ...)
880 va_start(ap
, format
);
881 ::verror(loc
, format
, ap
);
885 void Expression::rvalue()
887 if (type
&& type
->toBasetype()->ty
== Tvoid
)
888 { error("expression %s is void and has no value", toChars());
897 Expression
*Expression::combine(Expression
*e1
, Expression
*e2
)
903 e1
= new CommaExp(e1
->loc
, e1
, e2
);
912 integer_t
Expression::toInteger()
914 //printf("Expression %s\n", Token::toChars(op));
915 error("Integer constant expression expected instead of %s", toChars());
919 uinteger_t
Expression::toUInteger()
921 //printf("Expression %s\n", Token::toChars(op));
922 return (uinteger_t
)toInteger();
925 real_t
Expression::toReal()
927 error("Floating point constant expression expected instead of %s", toChars());
931 real_t
Expression::toImaginary()
933 error("Floating point constant expression expected instead of %s", toChars());
937 complex_t
Expression::toComplex()
939 error("Floating point constant expression expected instead of %s", toChars());
941 return complex_t(real_t(0)); // %% nicer
947 void Expression::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
949 buf
->writestring(Token::toChars(op
));
952 void Expression::toMangleBuffer(OutBuffer
*buf
)
954 error("expression %s is not a valid template value argument", toChars());
957 /*******************************
958 * Give error if we're not an lvalue.
959 * If we can, convert expression to be an lvalue.
962 Expression
*Expression::toLvalue(Scope
*sc
, Expression
*e
)
966 else if (!loc
.filename
)
968 error("%s is not an lvalue", e
->toChars());
972 Expression
*Expression::modifiableLvalue(Scope
*sc
, Expression
*e
)
974 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
976 // See if this expression is a modifiable lvalue (i.e. not const)
977 if (type
&& (!type
->isMutable() || !type
->isAssignable()))
978 error("%s is not mutable", e
->toChars());
980 return toLvalue(sc
, e
);
983 /************************************
984 * Detect cases where pointers to the stack can 'escape' the
985 * lifetime of the stack frame.
988 void Expression::checkEscape()
992 void Expression::checkScalar()
994 if (!type
->isscalar())
995 error("'%s' is not a scalar, it is a %s", toChars(), type
->toChars());
998 void Expression::checkNoBool()
1000 if (type
->toBasetype()->ty
== Tbool
)
1001 error("operation not allowed on bool '%s'", toChars());
1004 Expression
*Expression::checkIntegral()
1006 if (!type
->isintegral())
1007 { error("'%s' is not of integral type, it is a %s", toChars(), type
->toChars());
1008 return new IntegerExp(0);
1013 Expression
*Expression::checkArithmetic()
1015 if (!type
->isintegral() && !type
->isfloating())
1016 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type
->toChars());
1017 return new IntegerExp(0);
1022 void Expression::checkDeprecated(Scope
*sc
, Dsymbol
*s
)
1024 s
->checkDeprecated(loc
, sc
);
1027 /********************************
1028 * Check for expressions that have no use.
1030 * flag 0 not going to use the result, so issue error message if no
1032 * 1 the result of the expression is used, but still check
1033 * for useless subexpressions
1034 * 2 do not issue error messages, just return !=0 if expression
1038 int Expression::checkSideEffect(int flag
)
1041 { if (op
== TOKimport
)
1043 error("%s has no effect", toChars());
1046 error("%s has no effect in expression (%s)",
1047 Token::toChars(op
), toChars());
1052 /*****************************
1053 * Check that expression can be tested for true or false.
1056 Expression
*Expression::checkToBoolean()
1058 // Default is 'yes' - do nothing
1065 if (!type
->checkBoolean())
1067 error("expression %s of type %s does not have a boolean value", toChars(), type
->toChars());
1072 /****************************
1075 Expression
*Expression::checkToPointer()
1080 //printf("Expression::checkToPointer()\n");
1083 // If C static array, convert to pointer
1084 tb
= type
->toBasetype();
1085 if (tb
->ty
== Tsarray
)
1086 { TypeSArray
*ts
= (TypeSArray
*)tb
;
1087 if (ts
->size(loc
) == 0)
1088 e
= new NullExp(loc
);
1090 e
= new AddrExp(loc
, this);
1091 e
->type
= ts
->next
->pointerTo();
1096 /******************************
1097 * Take address of expression.
1100 Expression
*Expression::addressOf(Scope
*sc
)
1104 //printf("Expression::addressOf()\n");
1105 e
= toLvalue(sc
, NULL
);
1106 e
= new AddrExp(loc
, e
);
1107 e
->type
= type
->pointerTo();
1111 /******************************
1112 * If this is a reference, dereference it.
1115 Expression
*Expression::deref()
1117 //printf("Expression::deref()\n");
1118 if (type
->ty
== Treference
)
1121 e
= new PtrExp(loc
, this);
1122 e
->type
= ((TypeReference
*)type
)->next
;
1128 /********************************
1129 * Does this expression statically evaluate to a boolean TRUE or FALSE?
1132 int Expression::isBool(int result
)
1137 /********************************
1138 * Does this expression result in either a 1 or a 0?
1141 int Expression::isBit()
1146 /********************************
1147 * Can this expression throw an exception?
1148 * Valid only after semantic() pass.
1151 int Expression::canThrow()
1158 Expressions
*Expression::arraySyntaxCopy(Expressions
*exps
)
1159 { Expressions
*a
= NULL
;
1163 a
= new Expressions();
1164 a
->setDim(exps
->dim
);
1165 for (int i
= 0; i
< a
->dim
; i
++)
1166 { Expression
*e
= (Expression
*)exps
->data
[i
];
1168 e
= e
->syntaxCopy();
1175 /******************************** IntegerExp **************************/
1177 IntegerExp::IntegerExp(Loc loc
, integer_t value
, Type
*type
)
1178 : Expression(loc
, TOKint64
, sizeof(IntegerExp
))
1180 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
1181 if (type
&& !type
->isscalar())
1183 //printf("%s, loc = %d\n", toChars(), loc.linnum);
1184 error("integral constant must be scalar type, not %s", type
->toChars());
1185 type
= Type::terror
;
1188 this->value
= value
;
1191 IntegerExp::IntegerExp(integer_t value
)
1192 : Expression(0, TOKint64
, sizeof(IntegerExp
))
1194 this->type
= Type::tint32
;
1195 this->value
= value
;
1198 int IntegerExp::equals(Object
*o
)
1202 (((Expression
*)o
)->op
== TOKint64
&&
1203 ((ne
= (IntegerExp
*)o
), type
->toHeadMutable()->equals(ne
->type
->toHeadMutable())) &&
1204 value
== ne
->value
))
1209 char *IntegerExp::toChars()
1212 return Expression::toChars();
1214 static char buffer
[sizeof(value
) * 3 + 1];
1216 sprintf(buffer
, "%"PRIdMAX
, value
);
1221 integer_t
IntegerExp::toInteger()
1230 case Tbool
: value
= (value
!= 0); break;
1231 case Tint8
: value
= (d_int8
) value
; break;
1233 case Tuns8
: value
= (d_uns8
) value
; break;
1234 case Tint16
: value
= (d_int16
) value
; break;
1236 case Tuns16
: value
= (d_uns16
) value
; break;
1237 case Tint32
: value
= (d_int32
) value
; break;
1239 case Tuns32
: value
= (d_uns32
) value
; break;
1240 case Tint64
: value
= (d_int64
) value
; break;
1241 case Tuns64
: value
= (d_uns64
) value
; break;
1246 case 4: value
= (d_uns32
) value
; break;
1247 case 8: value
= (d_uns64
) value
; break;
1249 assert(PTRSIZE
== 4 || PTRSIZE
== 8);
1255 TypeEnum
*te
= (TypeEnum
*)t
;
1256 t
= te
->sym
->memtype
;
1262 TypeTypedef
*tt
= (TypeTypedef
*)t
;
1263 t
= tt
->sym
->basetype
;
1277 real_t
IntegerExp::toReal()
1282 t
= type
->toBasetype();
1283 if (t
->ty
== Tuns64
)
1284 return (real_t
)(d_uns64
)value
;
1286 return (real_t
)(d_int64
)value
;
1289 real_t
IntegerExp::toImaginary()
1294 complex_t
IntegerExp::toComplex()
1299 int IntegerExp::isBool(int result
)
1301 return result
? value
!= 0 : value
== 0;
1304 Expression
*IntegerExp::semantic(Scope
*sc
)
1308 // Determine what the type of this number is
1309 integer_t number
= value
;
1311 if (number
& 0x8000000000000000LL
)
1312 type
= Type::tuns64
;
1313 else if (number
& 0xFFFFFFFF80000000LL
)
1314 type
= Type::tint64
;
1316 type
= Type::tint32
;
1320 type
= type
->semantic(loc
, sc
);
1325 Expression
*IntegerExp::toLvalue(Scope
*sc
, Expression
*e
)
1329 else if (!loc
.filename
)
1331 e
->error("constant %s is not an lvalue", e
->toChars());
1335 void IntegerExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1337 integer_t v
= toInteger();
1346 { TypeEnum
*te
= (TypeEnum
*)t
;
1347 buf
->printf("cast(%s)", te
->sym
->toChars());
1348 t
= te
->sym
->memtype
;
1353 { TypeTypedef
*tt
= (TypeTypedef
*)t
;
1354 buf
->printf("cast(%s)", tt
->sym
->toChars());
1355 t
= tt
->sym
->basetype
;
1359 case Twchar
: // BUG: need to cast(wchar)
1360 case Tdchar
: // BUG: need to cast(dchar)
1361 if ((uinteger_t
)v
> 0xFF)
1363 buf
->printf("'\\U%08x'", v
);
1368 buf
->writestring("'\\''");
1369 else if (isprint(v
) && v
!= '\\')
1370 buf
->printf("'%c'", (int)v
);
1372 buf
->printf("'\\x%02x'", (int)v
);
1376 buf
->writestring("cast(byte)");
1380 buf
->writestring("cast(short)");
1385 buf
->printf("%d", (int)v
);
1389 buf
->writestring("cast(ubyte)");
1393 buf
->writestring("cast(ushort)");
1398 buf
->printf("%du", (unsigned)v
);
1402 buf
->printf("%"PRIdMAX
"L", v
);
1406 buf
->printf("%"PRIuMAX
"LU", v
);
1411 buf
->writestring((char *)(v
? "true" : "false"));
1415 buf
->writestring("cast(");
1416 buf
->writestring(t
->toChars());
1417 buf
->writeByte(')');
1427 else if (v
& 0x8000000000000000LL
)
1428 buf
->printf("0x%"PRIxMAX
, v
);
1430 buf
->printf("%"PRIdMAX
, v
);
1433 void IntegerExp::toMangleBuffer(OutBuffer
*buf
)
1435 if ((sinteger_t
)value
< 0)
1436 buf
->printf("N%"PRIdMAX
, -value
);
1438 buf
->printf("%"PRIdMAX
, value
);
1441 /******************************** RealExp **************************/
1443 RealExp::RealExp(Loc loc
, real_t value
, Type
*type
)
1444 : Expression(loc
, TOKfloat64
, sizeof(RealExp
))
1446 //printf("RealExp::RealExp(%Lg)\n", value);
1447 this->value
= value
;
1451 char *RealExp::toChars()
1453 char buffer
[sizeof(value
) * 3 + 8 + 1 + 1];
1456 value
.format(buffer
, sizeof(buffer
));
1457 if (type
->isimaginary())
1458 strcat(buffer
, "i");
1460 sprintf(buffer
, type
->isimaginary() ? "%Lgi" : "%Lg", value
);
1462 assert(strlen(buffer
) < sizeof(buffer
));
1463 return mem
.strdup(buffer
);
1466 integer_t
RealExp::toInteger()
1469 return (d_int64
) toReal().toInt();
1471 return (sinteger_t
) toReal();
1475 uinteger_t
RealExp::toUInteger()
1478 return (uinteger_t
) toReal().toInt();
1480 return (uinteger_t
) toReal();
1484 real_t
RealExp::toReal()
1486 return type
->isreal() ? value
: 0;
1489 real_t
RealExp::toImaginary()
1491 return type
->isreal() ? 0 : value
;
1494 complex_t
RealExp::toComplex()
1497 return toReal() + toImaginary() * I
;
1499 return complex_t(toReal(), toImaginary());
1503 /********************************
1504 * Test to see if two reals are the same.
1505 * Regard NaN's as equivalent.
1506 * Regard +0 and -0 as different.
1509 int RealEquals(real_t x1
, real_t x2
)
1512 return (isnan(x1
) && isnan(x2
)) ||
1513 /* In some cases, the REALPAD bytes get garbage in them,
1514 * so be sure and ignore them.
1516 memcmp(&x1
, &x2
, REALSIZE
- REALPAD
) == 0;
1518 return (x1
.isNan() && x2
.isNan()) || x1
.isIdenticalTo(x2
);
1522 int RealExp::equals(Object
*o
)
1526 (((Expression
*)o
)->op
== TOKfloat64
&&
1527 ((ne
= (RealExp
*)o
), type
->toHeadMutable()->equals(ne
->type
->toHeadMutable())) &&
1528 RealEquals(value
, ne
->value
)
1535 Expression
*RealExp::semantic(Scope
*sc
)
1538 type
= Type::tfloat64
;
1540 type
= type
->semantic(loc
, sc
);
1544 int RealExp::isBool(int result
)
1547 return result
? (! value
.isZero()) : (value
.isZero());
1549 return result
? (value
!= 0)
1554 void floatToBuffer(OutBuffer
*buf
, Type
*type
, const real_t
& value
)
1556 /* In order to get an exact representation, try converting it
1557 * to decimal then back again. If it matches, use it.
1558 * If it doesn't, fall back to hex, which is
1563 real_t parsed_value
;
1565 value
.format(buffer
, sizeof(buffer
));
1566 parsed_value
= real_t::parse(buffer
, real_t::LongDouble
);
1567 if (parsed_value
.isIdenticalTo( value
))
1568 buf
->writestring(buffer
);
1571 value
.formatHex(buffer
, sizeof(buffer
));
1572 buf
->writestring(buffer
);
1575 sprintf(buffer
, "%Lg", value
);
1576 assert(strlen(buffer
) < sizeof(buffer
));
1577 #if _WIN32 && __DMC__
1578 char *save
= __locale_decpoint
;
1579 __locale_decpoint
= ".";
1580 real_t r
= strtold(buffer
, NULL
);
1581 __locale_decpoint
= save
;
1583 real_t r
= strtold(buffer
, NULL
);
1585 if (r
== value
) // if exact duplication
1586 buf
->writestring(buffer
);
1588 buf
->printf("%La", value
); // ensure exact duplication
1593 Type
*t
= type
->toBasetype();
1599 buf
->writeByte('F');
1605 buf
->writeByte('L');
1611 if (t
->isimaginary())
1612 buf
->writeByte('i');
1616 void RealExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1618 floatToBuffer(buf
, type
, value
);
1621 void realToMangleBuffer(OutBuffer
*buf
, real_t value
)
1623 /* Rely on %A to get portable mangling.
1624 * Must munge result to get only identifier characters.
1626 * Possible values from %A => mangled result
1630 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79
1636 buf
->writestring("NAN"); // no -NAN bugs
1637 else if (value
.isInf())
1638 buf
->writestring(value
.isNegative()?"NINF":"INF");
1641 buf
->writestring("NAN"); // no -NAN bugs
1647 value
.formatHex(buffer
, sizeof(buffer
));
1648 int n
= strlen(buffer
);
1650 int n
= sprintf(buffer
, "%LA", value
);
1651 assert(n
> 0 && n
< sizeof(buffer
));
1653 for (int i
= 0; i
< n
; i
++)
1654 { char c
= buffer
[i
];
1659 buf
->writeByte('N');
1670 break; // skip leading 0X
1679 void RealExp::toMangleBuffer(OutBuffer
*buf
)
1681 buf
->writeByte('e');
1682 realToMangleBuffer(buf
, value
);
1686 /******************************** ComplexExp **************************/
1688 ComplexExp::ComplexExp(Loc loc
, complex_t value
, Type
*type
)
1689 : Expression(loc
, TOKcomplex80
, sizeof(ComplexExp
))
1691 this->value
= value
;
1693 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
1696 char *ComplexExp::toChars()
1698 char buffer
[sizeof(value
) * 3 + 8 + 1];
1701 char buf1
[sizeof(value
) * 3 + 8 + 1];
1702 char buf2
[sizeof(value
) * 3 + 8 + 1];
1703 creall(value
).format(buf1
, sizeof(buf1
));
1704 cimagl(value
).format(buf2
, sizeof(buf2
));
1705 sprintf(buffer
, "(%s+%si)", buf1
, buf2
);
1707 sprintf(buffer
, "(%Lg+%Lgi)", creall(value
), cimagl(value
));
1708 assert(strlen(buffer
) < sizeof(buffer
));
1710 return mem
.strdup(buffer
);
1713 integer_t
ComplexExp::toInteger()
1716 return (d_int64
) toReal().toInt();
1718 return (sinteger_t
) toReal();
1722 uinteger_t
ComplexExp::toUInteger()
1725 return (uinteger_t
) toReal().toInt();
1727 return (uinteger_t
) toReal();
1731 real_t
ComplexExp::toReal()
1733 return creall(value
);
1736 real_t
ComplexExp::toImaginary()
1738 return cimagl(value
);
1741 complex_t
ComplexExp::toComplex()
1746 int ComplexExp::equals(Object
*o
)
1750 (((Expression
*)o
)->op
== TOKcomplex80
&&
1751 ((ne
= (ComplexExp
*)o
), type
->toHeadMutable()->equals(ne
->type
->toHeadMutable())) &&
1753 RealEquals(creall(value
), creall(ne
->value
)) &&
1754 RealEquals(cimagl(value
), cimagl(ne
->value
))
1756 RealEquals(value
.re
, ne
->value
.re
) &&
1757 RealEquals(value
.im
, ne
->value
.im
)
1765 Expression
*ComplexExp::semantic(Scope
*sc
)
1768 type
= Type::tcomplex80
;
1770 type
= type
->semantic(loc
, sc
);
1774 int ComplexExp::isBool(int result
)
1777 return (bool)(value
);
1782 void ComplexExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1788 char buf1
[sizeof(value
) * 3 + 8 + 1];
1789 char buf2
[sizeof(value
) * 3 + 8 + 1];
1790 creall(value
).format(buf1
, sizeof(buf1
));
1791 cimagl(value
).format(buf2
, sizeof(buf2
));
1792 buf
->printf("(%s+%si)", buf1
, buf2
);
1794 buf
->writeByte('(');
1795 floatToBuffer(buf
, type
, creall(value
));
1796 buf
->writeByte('+');
1797 floatToBuffer(buf
, type
, cimagl(value
));
1798 buf
->writestring("i)");
1802 void ComplexExp::toMangleBuffer(OutBuffer
*buf
)
1804 buf
->writeByte('c');
1805 real_t r
= toReal();
1806 realToMangleBuffer(buf
, r
);
1807 buf
->writeByte('c'); // separate the two
1809 realToMangleBuffer(buf
, r
);
1812 /******************************** IdentifierExp **************************/
1814 IdentifierExp::IdentifierExp(Loc loc
, Identifier
*ident
)
1815 : Expression(loc
, TOKidentifier
, sizeof(IdentifierExp
))
1817 this->ident
= ident
;
1820 Expression
*IdentifierExp::semantic(Scope
*sc
)
1826 printf("IdentifierExp::semantic('%s')\n", ident
->toChars());
1828 s
= sc
->search(loc
, ident
, &scopesym
);
1831 WithScopeSymbol
*withsym
;
1833 /* See if the symbol was a member of an enclosing 'with'
1835 withsym
= scopesym
->isWithScopeSymbol();
1840 // Same as wthis.ident
1841 if (s
->needThis() || s
->isTemplateDeclaration())
1843 e
= new VarExp(loc
, withsym
->withstate
->wthis
);
1844 e
= new DotIdExp(loc
, e
, ident
);
1847 { Type
*t
= withsym
->withstate
->wthis
->type
;
1848 if (t
->ty
== Tpointer
)
1849 t
= ((TypePointer
*)t
)->next
;
1850 e
= new TypeDotIdExp(loc
, t
, ident
);
1855 /* If f is really a function template,
1856 * then replace f with the function template declaration.
1858 FuncDeclaration
*f
= s
->isFuncDeclaration();
1860 { TemplateInstance
*ti
= f
->parent
->isTemplateInstance();
1863 !ti
->isTemplateMixin() &&
1864 (ti
->name
== f
->ident
||
1865 ti
->toAlias()->ident
== f
->ident
)
1867 ti
->tempdecl
&& ti
->tempdecl
->onemember
)
1869 TemplateDeclaration
*tempdecl
= ti
->tempdecl
;
1870 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
1871 tempdecl
= tempdecl
->overroot
; // then get the start
1872 e
= new TemplateExp(loc
, tempdecl
);
1873 e
= e
->semantic(sc
);
1877 // Haven't done overload resolution yet, so pass 1
1878 e
= new DsymbolExp(loc
, s
, 1);
1880 return e
->semantic(sc
);
1882 error("undefined identifier %s", ident
->toChars());
1883 type
= Type::terror
;
1887 char *IdentifierExp::toChars()
1889 return ident
->toChars();
1892 void IdentifierExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1895 buf
->writestring(ident
->toHChars2());
1897 buf
->writestring(ident
->toChars());
1900 Expression
*IdentifierExp::toLvalue(Scope
*sc
, Expression
*e
)
1903 tym
= tybasic(e1
->ET
->Tty
);
1904 if (!(tyscalar(tym
) ||
1906 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
1907 synerr(EM_lvalue
); // lvalue expected
1912 /******************************** DollarExp **************************/
1914 DollarExp::DollarExp(Loc loc
)
1915 : IdentifierExp(loc
, Id::dollar
)
1919 /******************************** DsymbolExp **************************/
1921 DsymbolExp::DsymbolExp(Loc loc
, Dsymbol
*s
, int hasOverloads
)
1922 : Expression(loc
, TOKdsymbol
, sizeof(DsymbolExp
))
1925 this->hasOverloads
= hasOverloads
;
1928 Expression
*DsymbolExp::semantic(Scope
*sc
)
1931 printf("DsymbolExp::semantic('%s')\n", s
->toChars());
1939 FuncLiteralDeclaration
*fld
;
1942 ClassDeclaration
*cd
;
1943 ClassDeclaration
*thiscd
= NULL
;
1948 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
1949 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
1952 if (!s
->isFuncDeclaration()) // functions are checked after overloading
1953 checkDeprecated(sc
, s
);
1955 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
1956 if (!s
->isFuncDeclaration())
1957 checkDeprecated(sc
, s
);
1960 thiscd
= sc
->func
->parent
->isClassDeclaration();
1962 // BUG: This should happen after overload resolution for functions, not before
1965 if (hasThis(sc
) && !s
->isFuncDeclaration())
1967 // Supply an implicit 'this', as in
1972 de
= new DotVarExp(loc
, new ThisExp(loc
), s
->isDeclaration());
1973 return de
->semantic(sc
);
1977 em
= s
->isEnumMember();
1981 e
= e
->semantic(sc
);
1984 v
= s
->isVarDeclaration();
1987 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
1991 { error("forward reference of %s", v
->toChars());
1992 type
= Type::terror
;
1995 e
= new VarExp(loc
, v
);
1997 e
= e
->semantic(sc
);
2000 fld
= s
->isFuncLiteralDeclaration();
2002 { //printf("'%s' is a function literal\n", fld->toChars());
2003 e
= new FuncExp(loc
, fld
);
2004 return e
->semantic(sc
);
2006 f
= s
->isFuncDeclaration();
2008 { //printf("'%s' is a function\n", f->toChars());
2009 return new VarExp(loc
, f
, hasOverloads
);
2011 o
= s
->isOverloadSet();
2013 { //printf("'%s' is an overload set\n", o->toChars());
2014 return new OverExp(o
);
2016 cd
= s
->isClassDeclaration();
2017 if (cd
&& thiscd
&& cd
->isBaseOf(thiscd
, NULL
) && sc
->func
->needThis())
2019 // We need to add an implicit 'this' if cd is this class or a base class.
2022 dte
= new DotTypeExp(loc
, new ThisExp(loc
), s
);
2023 return dte
->semantic(sc
);
2025 imp
= s
->isImport();
2030 ie
= new ScopeExp(loc
, imp
->pkg
);
2031 return ie
->semantic(sc
);
2033 pkg
= s
->isPackage();
2038 ie
= new ScopeExp(loc
, pkg
);
2039 return ie
->semantic(sc
);
2041 Module
*mod
= s
->isModule();
2046 ie
= new ScopeExp(loc
, mod
);
2047 return ie
->semantic(sc
);
2053 return new TypeExp(loc
, t
);
2056 TupleDeclaration
*tup
= s
->isTupleDeclaration();
2059 e
= new TupleExp(loc
, tup
);
2060 e
= e
->semantic(sc
);
2064 TemplateInstance
*ti
= s
->isTemplateInstance();
2065 if (ti
&& !global
.errors
)
2066 { if (!ti
->semanticdone
)
2068 s
= ti
->inst
->toAlias();
2069 if (!s
->isTemplateInstance())
2071 e
= new ScopeExp(loc
, ti
);
2072 e
= e
->semantic(sc
);
2076 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
2079 e
= new TemplateExp(loc
, td
);
2080 e
= e
->semantic(sc
);
2085 error("%s '%s' is not a variable", s
->kind(), s
->toChars());
2086 type
= Type::terror
;
2090 char *DsymbolExp::toChars()
2092 return s
->toChars();
2095 void DsymbolExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2097 buf
->writestring(s
->toChars());
2100 Expression
*DsymbolExp::toLvalue(Scope
*sc
, Expression
*e
)
2103 tym
= tybasic(e1
->ET
->Tty
);
2104 if (!(tyscalar(tym
) ||
2106 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
2107 synerr(EM_lvalue
); // lvalue expected
2112 /******************************** GetLoggerExp **************************/
2114 GetLoggerExp::GetLoggerExp(Loc loc
)
2115 : Expression(loc
, TOKlogger
, sizeof(GetLoggerExp
))
2119 Expression
*GetLoggerExp::semantic(Scope
*sc
)
2121 Expression
*log
= new DotIdExp(loc
, new IdentifierExp(loc
, Id::empty
), Id::__log
);
2122 return log
->semantic(sc
);
2125 void GetLoggerExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2127 buf
->writestring("log");
2130 /******************************** ThisExp **************************/
2132 ThisExp::ThisExp(Loc loc
)
2133 : Expression(loc
, TOKthis
, sizeof(ThisExp
))
2138 Expression
*ThisExp::semantic(Scope
*sc
)
2139 { FuncDeclaration
*fd
;
2140 FuncDeclaration
*fdthis
;
2144 printf("ThisExp::semantic()\n");
2147 { //assert(global.errors || var);
2151 /* Special case for typeof(this) and typeof(super) since both
2152 * should work even if they are not inside a non-static member function
2156 // Find enclosing struct or class
2157 for (Dsymbol
*s
= sc
->parent
; 1; s
= s
->parent
)
2159 ClassDeclaration
*cd
;
2160 StructDeclaration
*sd
;
2164 error("%s is not in a struct or class scope", toChars());
2167 cd
= s
->isClassDeclaration();
2173 sd
= s
->isStructDeclaration();
2176 type
= sd
->type
->pointerTo();
2182 fdthis
= sc
->parent
->isFuncDeclaration();
2183 fd
= hasThis(sc
); // fd is the uplevel function with the 'this' variable
2189 assert(var
->parent
);
2191 var
->isVarDeclaration()->checkNestedReference(sc
, loc
);
2192 sc
->callSuper
|= CSXthis
;
2196 error("'this' is only defined in non-static member functions, not %s", sc
->parent
->toChars());
2197 type
= Type::terror
;
2201 int ThisExp::isBool(int result
)
2203 return result
? TRUE
: FALSE
;
2206 void ThisExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2208 buf
->writestring("this");
2211 Expression
*ThisExp::toLvalue(Scope
*sc
, Expression
*e
)
2216 /******************************** SuperExp **************************/
2218 SuperExp::SuperExp(Loc loc
)
2224 Expression
*SuperExp::semantic(Scope
*sc
)
2225 { FuncDeclaration
*fd
;
2226 FuncDeclaration
*fdthis
;
2227 ClassDeclaration
*cd
;
2231 printf("SuperExp::semantic('%s')\n", toChars());
2236 /* Special case for typeof(this) and typeof(super) since both
2237 * should work even if they are not inside a non-static member function
2241 // Find enclosing class
2242 for (Dsymbol
*s
= sc
->parent
; 1; s
= s
->parent
)
2244 ClassDeclaration
*cd
;
2248 error("%s is not in a class scope", toChars());
2251 cd
= s
->isClassDeclaration();
2256 { error("class %s has no 'super'", s
->toChars());
2265 fdthis
= sc
->parent
->isFuncDeclaration();
2271 assert(var
->parent
);
2274 while (s
&& s
->isTemplateInstance())
2277 cd
= s
->isClassDeclaration();
2278 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
2283 error("no base class for %s", cd
->toChars());
2284 type
= fd
->vthis
->type
;
2288 type
= cd
->baseClass
->type
;
2291 var
->isVarDeclaration()->checkNestedReference(sc
, loc
);
2293 sc
->callSuper
|= CSXsuper
;
2298 error("'super' is only allowed in non-static class member functions");
2299 type
= Type::tint32
;
2303 void SuperExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2305 buf
->writestring("super");
2309 /******************************** NullExp **************************/
2311 NullExp::NullExp(Loc loc
)
2312 : Expression(loc
, TOKnull
, sizeof(NullExp
))
2318 Expression
*NullExp::semantic(Scope
*sc
)
2321 printf("NullExp::semantic('%s')\n", toChars());
2323 // NULL is the same as (void *)0
2325 type
= Type::tvoid
->pointerTo();
2329 int NullExp::isBool(int result
)
2331 return result
? FALSE
: TRUE
;
2334 void NullExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2336 buf
->writestring("null");
2339 void NullExp::toMangleBuffer(OutBuffer
*buf
)
2341 buf
->writeByte('n');
2344 /******************************** StringExp **************************/
2346 StringExp::StringExp(Loc loc
, char *string
)
2347 : Expression(loc
, TOKstring
, sizeof(StringExp
))
2349 this->string
= string
;
2350 this->len
= strlen(string
);
2352 this->committed
= 0;
2356 StringExp::StringExp(Loc loc
, void *string
, size_t len
)
2357 : Expression(loc
, TOKstring
, sizeof(StringExp
))
2359 this->string
= string
;
2362 this->committed
= 0;
2366 StringExp::StringExp(Loc loc
, void *string
, size_t len
, unsigned char postfix
)
2367 : Expression(loc
, TOKstring
, sizeof(StringExp
))
2369 this->string
= string
;
2372 this->committed
= 0;
2373 this->postfix
= postfix
;
2377 Expression
*StringExp::syntaxCopy()
2379 printf("StringExp::syntaxCopy() %s\n", toChars());
2384 int StringExp::equals(Object
*o
)
2386 //printf("StringExp::equals('%s')\n", o->toChars());
2387 if (o
&& o
->dyncast() == DYNCAST_EXPRESSION
)
2388 { Expression
*e
= (Expression
*)o
;
2390 if (e
->op
== TOKstring
)
2392 return compare(o
) == 0;
2398 char *StringExp::toChars()
2404 memset(&hgs
, 0, sizeof(hgs
));
2405 toCBuffer(&buf
, &hgs
);
2407 p
= (char *)buf
.data
;
2412 Expression
*StringExp::semantic(Scope
*sc
)
2415 printf("StringExp::semantic() %s\n", toChars());
2427 for (u
= 0; u
< len
;)
2429 p
= utf_decodeChar((unsigned char *)string
, len
, &u
, &c
);
2440 string
= buffer
.extractData();
2443 type
= new TypeSArray(Type::tdchar
, new IntegerExp(loc
, len
, Type::tindex
));
2448 for (u
= 0; u
< len
;)
2450 p
= utf_decodeChar((unsigned char *)string
, len
, &u
, &c
);
2456 { buffer
.writeUTF16(c
);
2462 buffer
.writeUTF16(0);
2463 string
= buffer
.extractData();
2466 type
= new TypeSArray(Type::twchar
, new IntegerExp(loc
, len
, Type::tindex
));
2473 type
= new TypeSArray(Type::tchar
, new IntegerExp(loc
, len
, Type::tindex
));
2476 type
= type
->semantic(loc
, sc
);
2477 type
= type
->invariantOf();
2478 //printf("type = %s\n", type->toChars());
2483 /****************************************
2484 * Convert string to char[].
2487 StringExp
*StringExp::toUTF8(Scope
*sc
)
2490 { // Convert to UTF-8 string
2492 Expression
*e
= castTo(sc
, Type::tchar
->arrayOf());
2493 e
= e
->optimize(WANTvalue
);
2494 assert(e
->op
== TOKstring
);
2495 StringExp
*se
= (StringExp
*)e
;
2496 assert(se
->sz
== 1);
2502 int StringExp::compare(Object
*obj
)
2504 // Used to sort case statement expressions so we can do an efficient lookup
2505 StringExp
*se2
= (StringExp
*)(obj
);
2507 // This is a kludge so isExpression() in template.c will return 5
2512 assert(se2
->op
== TOKstring
);
2515 int len2
= se2
->len
;
2522 return strcmp((char *)string
, (char *)se2
->string
);
2526 d_wchar
*s1
= (d_wchar
*)string
;
2527 d_wchar
*s2
= (d_wchar
*)se2
->string
;
2529 for (u
= 0; u
< len
; u
++)
2532 return s1
[u
] - s2
[u
];
2538 d_dchar
*s1
= (d_dchar
*)string
;
2539 d_dchar
*s2
= (d_dchar
*)se2
->string
;
2541 for (u
= 0; u
< len
; u
++)
2544 return s1
[u
] - s2
[u
];
2556 int StringExp::isBool(int result
)
2558 return result
? TRUE
: FALSE
;
2561 unsigned StringExp::charAt(size_t i
)
2567 value
= ((unsigned char *)string
)[i
];
2571 value
= ((unsigned short *)string
)[i
];
2575 value
= ((unsigned int *)string
)[i
];
2585 void StringExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2587 buf
->writeByte('"');
2588 for (size_t i
= 0; i
< len
; i
++)
2589 { unsigned c
= charAt(i
);
2596 buf
->writeByte('\\');
2599 { if (c
<= 0x7F && (isprint(c
) || hgs
->console
))
2602 buf
->printf("\\x%02x", c
);
2604 else if (c
<= 0xFFFF)
2605 buf
->printf("\\x%02x\\x%02x", c
& 0xFF, c
>> 8);
2607 buf
->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2608 c
& 0xFF, (c
>> 8) & 0xFF, (c
>> 16) & 0xFF, c
>> 24);
2612 buf
->writeByte('"');
2614 buf
->writeByte(postfix
);
2617 void StringExp::toMangleBuffer(OutBuffer
*buf
)
2626 /* Write string in UTF-8 format
2631 q
= (unsigned char *)string
;
2636 for (u
= 0; u
< len
; )
2638 p
= utf_decodeWchar((unsigned short *)string
, len
, &u
, &c
);
2649 for (u
= 0; u
< len
; u
++)
2651 c
= ((unsigned *)string
)[u
];
2652 if (!utf_isValidDchar(c
))
2653 error("invalid UCS-32 char \\U%08x", c
);
2664 buf
->printf("%d_", qlen
);
2665 for (size_t i
= 0; i
< qlen
; i
++)
2666 buf
->printf("%02x", q
[i
]);
2669 /************************ ArrayLiteralExp ************************************/
2671 // [ e1, e2, e3, ... ]
2673 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expressions
*elements
)
2674 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
2676 this->elements
= elements
;
2679 ArrayLiteralExp::ArrayLiteralExp(Loc loc
, Expression
*e
)
2680 : Expression(loc
, TOKarrayliteral
, sizeof(ArrayLiteralExp
))
2682 elements
= new Expressions
;
2686 Expression
*ArrayLiteralExp::syntaxCopy()
2688 return new ArrayLiteralExp(loc
, arraySyntaxCopy(elements
));
2691 Expression
*ArrayLiteralExp::semantic(Scope
*sc
)
2696 printf("ArrayLiteralExp::semantic('%s')\n", toChars());
2701 // Run semantic() on each element
2702 for (int i
= 0; i
< elements
->dim
; i
++)
2703 { e
= (Expression
*)elements
->data
[i
];
2704 e
= e
->semantic(sc
);
2705 elements
->data
[i
] = (void *)e
;
2707 expandTuples(elements
);
2708 for (int i
= 0; i
< elements
->dim
; i
++)
2709 { e
= (Expression
*)elements
->data
[i
];
2712 error("%s has no value", e
->toChars());
2713 e
= resolveProperties(sc
, e
);
2715 unsigned char committed
= 1;
2716 if (e
->op
== TOKstring
)
2717 committed
= ((StringExp
*)e
)->committed
;
2721 // Convert any static arrays to dynamic arrays
2722 if (t0
->ty
== Tsarray
)
2724 t0
= ((TypeSArray
*)t0
)->next
->arrayOf();
2725 e
= e
->implicitCastTo(sc
, t0
);
2729 e
= e
->implicitCastTo(sc
, t0
);
2730 if (!committed
&& e
->op
== TOKstring
)
2731 { StringExp
*se
= (StringExp
*)e
;
2734 elements
->data
[i
] = (void *)e
;
2739 type
= new TypeSArray(t0
, new IntegerExp(elements
->dim
));
2740 type
= type
->semantic(loc
, sc
);
2744 int ArrayLiteralExp::checkSideEffect(int flag
)
2747 for (size_t i
= 0; i
< elements
->dim
; i
++)
2748 { Expression
*e
= (Expression
*)elements
->data
[i
];
2750 f
|= e
->checkSideEffect(2);
2752 if (flag
== 0 && f
== 0)
2753 Expression::checkSideEffect(0);
2757 int ArrayLiteralExp::isBool(int result
)
2759 size_t dim
= elements
? elements
->dim
: 0;
2760 return result
? (dim
!= 0) : (dim
== 0);
2763 int ArrayLiteralExp::canThrow()
2765 return 1; // because it can fail allocating memory
2768 void ArrayLiteralExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2770 buf
->writeByte('[');
2771 argsToCBuffer(buf
, elements
, hgs
);
2772 buf
->writeByte(']');
2775 void ArrayLiteralExp::toMangleBuffer(OutBuffer
*buf
)
2777 size_t dim
= elements
? elements
->dim
: 0;
2778 buf
->printf("A%"PRIuSIZE
, dim
);
2779 for (size_t i
= 0; i
< dim
; i
++)
2780 { Expression
*e
= (Expression
*)elements
->data
[i
];
2781 e
->toMangleBuffer(buf
);
2785 /************************ AssocArrayLiteralExp ************************************/
2787 // [ key0 : value0, key1 : value1, ... ]
2789 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc
,
2790 Expressions
*keys
, Expressions
*values
)
2791 : Expression(loc
, TOKassocarrayliteral
, sizeof(AssocArrayLiteralExp
))
2793 assert(keys
->dim
== values
->dim
);
2795 this->values
= values
;
2798 Expression
*AssocArrayLiteralExp::syntaxCopy()
2800 return new AssocArrayLiteralExp(loc
,
2801 arraySyntaxCopy(keys
), arraySyntaxCopy(values
));
2804 Expression
*AssocArrayLiteralExp::semantic(Scope
*sc
)
2807 Type
*tvalue
= NULL
;
2810 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
2813 // Run semantic() on each element
2814 for (size_t i
= 0; i
< keys
->dim
; i
++)
2815 { Expression
*key
= (Expression
*)keys
->data
[i
];
2816 Expression
*value
= (Expression
*)values
->data
[i
];
2818 key
= key
->semantic(sc
);
2819 value
= value
->semantic(sc
);
2821 keys
->data
[i
] = (void *)key
;
2822 values
->data
[i
] = (void *)value
;
2825 expandTuples(values
);
2826 if (keys
->dim
!= values
->dim
)
2828 error("number of keys is %u, must match number of values %u", keys
->dim
, values
->dim
);
2832 for (size_t i
= 0; i
< keys
->dim
; i
++)
2833 { Expression
*key
= (Expression
*)keys
->data
[i
];
2834 Expression
*value
= (Expression
*)values
->data
[i
];
2837 error("%s has no value", key
->toChars());
2839 error("%s has no value", value
->toChars());
2840 key
= resolveProperties(sc
, key
);
2841 value
= resolveProperties(sc
, value
);
2846 key
= key
->implicitCastTo(sc
, tkey
);
2847 keys
->data
[i
] = (void *)key
;
2850 tvalue
= value
->type
;
2852 value
= value
->implicitCastTo(sc
, tvalue
);
2853 values
->data
[i
] = (void *)value
;
2859 tvalue
= Type::tvoid
;
2860 type
= new TypeAArray(tvalue
, tkey
);
2861 type
= type
->semantic(loc
, sc
);
2865 int AssocArrayLiteralExp::checkSideEffect(int flag
)
2868 for (size_t i
= 0; i
< keys
->dim
; i
++)
2869 { Expression
*key
= (Expression
*)keys
->data
[i
];
2870 Expression
*value
= (Expression
*)values
->data
[i
];
2872 f
|= key
->checkSideEffect(2);
2873 f
|= value
->checkSideEffect(2);
2875 if (flag
== 0 && f
== 0)
2876 Expression::checkSideEffect(0);
2880 int AssocArrayLiteralExp::isBool(int result
)
2882 size_t dim
= keys
->dim
;
2883 return result
? (dim
!= 0) : (dim
== 0);
2886 int AssocArrayLiteralExp::canThrow()
2891 void AssocArrayLiteralExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2893 buf
->writeByte('[');
2894 for (size_t i
= 0; i
< keys
->dim
; i
++)
2895 { Expression
*key
= (Expression
*)keys
->data
[i
];
2896 Expression
*value
= (Expression
*)values
->data
[i
];
2899 buf
->writeByte(',');
2900 expToCBuffer(buf
, hgs
, key
, PREC_assign
);
2901 buf
->writeByte(':');
2902 expToCBuffer(buf
, hgs
, value
, PREC_assign
);
2904 buf
->writeByte(']');
2907 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer
*buf
)
2909 size_t dim
= keys
->dim
;
2910 buf
->printf("A%u", dim
);
2911 for (size_t i
= 0; i
< dim
; i
++)
2912 { Expression
*key
= (Expression
*)keys
->data
[i
];
2913 Expression
*value
= (Expression
*)values
->data
[i
];
2915 key
->toMangleBuffer(buf
);
2916 value
->toMangleBuffer(buf
);
2920 /************************ StructLiteralExp ************************************/
2922 // sd( e1, e2, e3, ... )
2924 StructLiteralExp::StructLiteralExp(Loc loc
, StructDeclaration
*sd
, Expressions
*elements
)
2925 : Expression(loc
, TOKstructliteral
, sizeof(StructLiteralExp
))
2928 this->elements
= elements
;
2931 this->fillHoles
= 1;
2934 Expression
*StructLiteralExp::syntaxCopy()
2936 return new StructLiteralExp(loc
, sd
, arraySyntaxCopy(elements
));
2939 Expression
*StructLiteralExp::semantic(Scope
*sc
)
2943 printf("StructLiteralExp::semantic('%s')\n", toChars());
2948 // Run semantic() on each element
2949 for (size_t i
= 0; i
< elements
->dim
; i
++)
2950 { e
= (Expression
*)elements
->data
[i
];
2953 e
= e
->semantic(sc
);
2954 elements
->data
[i
] = (void *)e
;
2956 expandTuples(elements
);
2958 for (size_t i
= 0; i
< elements
->dim
; i
++)
2959 { e
= (Expression
*)elements
->data
[i
];
2964 error("%s has no value", e
->toChars());
2965 e
= resolveProperties(sc
, e
);
2966 if (i
>= sd
->fields
.dim
)
2967 { error("more initializers than fields of %s", sd
->toChars());
2970 Dsymbol
*s
= (Dsymbol
*)sd
->fields
.data
[i
];
2971 VarDeclaration
*v
= s
->isVarDeclaration();
2973 if (v
->offset
< offset
)
2974 error("overlapping initialization for %s", v
->toChars());
2975 offset
= v
->offset
+ v
->type
->size();
2977 Type
*telem
= v
->type
;
2978 while (!e
->implicitConvTo(telem
) && telem
->toBasetype()->ty
== Tsarray
)
2979 { /* Static array initialization, as in:
2982 telem
= telem
->toBasetype()->nextOf();
2985 e
= e
->implicitCastTo(sc
, telem
);
2987 elements
->data
[i
] = (void *)e
;
2990 /* Fill out remainder of elements[] with default initializers for fields[]
2992 for (size_t i
= elements
->dim
; i
< sd
->fields
.dim
; i
++)
2993 { Dsymbol
*s
= (Dsymbol
*)sd
->fields
.data
[i
];
2994 VarDeclaration
*v
= s
->isVarDeclaration();
2997 if (v
->offset
< offset
)
3004 { e
= v
->init
->toExpression();
3006 error("cannot make expression out of initializer for %s", v
->toChars());
3009 { e
= v
->type
->defaultInit();
3012 offset
= v
->offset
+ v
->type
->size();
3021 /**************************************
3022 * Gets expression at offset of type.
3023 * Returns NULL if not found.
3026 Expression
*StructLiteralExp::getField(Type
*type
, unsigned offset
)
3028 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
3029 // /*toChars()*/"", type->toChars(), offset);
3030 Expression
*e
= NULL
;
3031 int i
= getFieldIndex(type
, offset
);
3035 //printf("\ti = %d\n", i);
3036 assert(i
< elements
->dim
);
3037 e
= (Expression
*)elements
->data
[i
];
3047 /************************************
3048 * Get index of field.
3049 * Returns -1 if not found.
3052 int StructLiteralExp::getFieldIndex(Type
*type
, unsigned offset
)
3054 /* Find which field offset is by looking at the field offsets
3056 for (size_t i
= 0; i
< sd
->fields
.dim
; i
++)
3058 Dsymbol
*s
= (Dsymbol
*)sd
->fields
.data
[i
];
3059 VarDeclaration
*v
= s
->isVarDeclaration();
3062 if (offset
== v
->offset
&&
3063 type
->size() == v
->type
->size())
3064 { Expression
*e
= (Expression
*)elements
->data
[i
];
3076 Expression
*StructLiteralExp::toLvalue(Scope
*sc
, Expression
*e
)
3082 int StructLiteralExp::checkSideEffect(int flag
)
3085 for (size_t i
= 0; i
< elements
->dim
; i
++)
3086 { Expression
*e
= (Expression
*)elements
->data
[i
];
3090 f
|= e
->checkSideEffect(2);
3092 if (flag
== 0 && f
== 0)
3093 Expression::checkSideEffect(0);
3097 int StructLiteralExp::canThrow()
3099 return arrayExpressionCanThrow(elements
);
3102 void StructLiteralExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3104 buf
->writestring(sd
->toChars());
3105 buf
->writeByte('(');
3106 argsToCBuffer(buf
, elements
, hgs
);
3107 buf
->writeByte(')');
3110 void StructLiteralExp::toMangleBuffer(OutBuffer
*buf
)
3112 size_t dim
= elements
? elements
->dim
: 0;
3113 buf
->printf("S%u", dim
);
3114 for (size_t i
= 0; i
< dim
; i
++)
3115 { Expression
*e
= (Expression
*)elements
->data
[i
];
3117 e
->toMangleBuffer(buf
);
3119 buf
->writeByte('v'); // 'v' for void
3123 /************************ TypeDotIdExp ************************************/
3132 TypeDotIdExp::TypeDotIdExp(Loc loc
, Type
*type
, Identifier
*ident
)
3133 : Expression(loc
, TOKtypedot
, sizeof(TypeDotIdExp
))
3136 this->ident
= ident
;
3139 Expression
*TypeDotIdExp::syntaxCopy()
3141 TypeDotIdExp
*te
= new TypeDotIdExp(loc
, type
->syntaxCopy(), ident
);
3145 Expression
*TypeDotIdExp::semantic(Scope
*sc
)
3149 printf("TypeDotIdExp::semantic()\n");
3151 e
= new DotIdExp(loc
, new TypeExp(loc
, type
), ident
);
3152 e
= e
->semantic(sc
);
3156 void TypeDotIdExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3158 buf
->writeByte('(');
3159 type
->toCBuffer(buf
, NULL
, hgs
);
3160 buf
->writeByte(')');
3161 buf
->writeByte('.');
3162 buf
->writestring(ident
->toChars());
3165 /************************************************************/
3167 // Mainly just a placeholder
3169 TypeExp::TypeExp(Loc loc
, Type
*type
)
3170 : Expression(loc
, TOKtype
, sizeof(TypeExp
))
3172 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
3176 Expression
*TypeExp::semantic(Scope
*sc
)
3178 //printf("TypeExp::semantic(%s)\n", type->toChars());
3179 type
= type
->semantic(loc
, sc
);
3183 void TypeExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3185 type
->toCBuffer(buf
, NULL
, hgs
);
3188 /************************************************************/
3190 // Mainly just a placeholder
3192 ScopeExp::ScopeExp(Loc loc
, ScopeDsymbol
*pkg
)
3193 : Expression(loc
, TOKimport
, sizeof(ScopeExp
))
3195 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
3196 //static int count; if (++count == 38) *(char*)0=0;
3200 Expression
*ScopeExp::syntaxCopy()
3202 ScopeExp
*se
= new ScopeExp(loc
, (ScopeDsymbol
*)sds
->syntaxCopy(NULL
));
3206 Expression
*ScopeExp::semantic(Scope
*sc
)
3208 TemplateInstance
*ti
;
3212 printf("+ScopeExp::semantic('%s')\n", toChars());
3215 ti
= sds
->isTemplateInstance();
3216 if (ti
&& !global
.errors
)
3218 if (!ti
->semanticdone
)
3220 s
= ti
->inst
->toAlias();
3221 sds2
= s
->isScopeDsymbol();
3225 //printf("s = %s, '%s'\n", s->kind(), s->toChars());
3229 e
= new VarExp(loc
, ti
->withsym
->withstate
->wthis
);
3230 e
= new DotVarExp(loc
, e
, s
->isDeclaration());
3233 e
= new DsymbolExp(loc
, s
);
3234 e
= e
->semantic(sc
);
3235 //printf("-1ScopeExp::semantic()\n");
3243 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3247 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3248 //printf("\tparent = '%s'\n", sds->parent->toChars());
3252 //printf("-2ScopeExp::semantic() %s\n", toChars());
3256 void ScopeExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3258 if (sds
->isTemplateInstance())
3260 sds
->toCBuffer(buf
, hgs
);
3264 buf
->writestring(sds
->kind());
3265 buf
->writestring(" ");
3266 buf
->writestring(sds
->toChars());
3270 /********************** TemplateExp **************************************/
3272 // Mainly just a placeholder
3274 TemplateExp::TemplateExp(Loc loc
, TemplateDeclaration
*td
)
3275 : Expression(loc
, TOKtemplate
, sizeof(TemplateExp
))
3277 //printf("TemplateExp(): %s\n", td->toChars());
3281 void TemplateExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3283 buf
->writestring(td
->toChars());
3286 void TemplateExp::rvalue()
3288 error("template %s has no value", toChars());
3291 /********************** NewExp **************************************/
3293 NewExp::NewExp(Loc loc
, Expression
*thisexp
, Expressions
*newargs
,
3294 Type
*newtype
, Expressions
*arguments
)
3295 : Expression(loc
, TOKnew
, sizeof(NewExp
))
3297 this->thisexp
= thisexp
;
3298 this->newargs
= newargs
;
3299 this->newtype
= newtype
;
3300 this->arguments
= arguments
;
3306 Expression
*NewExp::syntaxCopy()
3308 return new NewExp(loc
,
3309 thisexp
? thisexp
->syntaxCopy() : NULL
,
3310 arraySyntaxCopy(newargs
),
3311 newtype
->syntaxCopy(), arraySyntaxCopy(arguments
));
3315 Expression
*NewExp::semantic(Scope
*sc
)
3318 ClassDeclaration
*cdthis
= NULL
;
3321 printf("NewExp::semantic() %s\n", toChars());
3323 printf("\tthisexp = %s\n", thisexp
->toChars());
3324 printf("\tnewtype: %s\n", newtype
->toChars());
3326 if (type
) // if semantic() already run
3331 { thisexp
= thisexp
->semantic(sc
);
3332 cdthis
= thisexp
->type
->isClassHandle();
3335 sc
= sc
->push(cdthis
);
3336 type
= newtype
->semantic(loc
, sc
);
3341 error("'this' for nested class must be a class type, not %s", thisexp
->type
->toChars());
3342 type
= newtype
->semantic(loc
, sc
);
3346 type
= newtype
->semantic(loc
, sc
);
3347 newtype
= type
; // in case type gets cast to something else
3348 tb
= type
->toBasetype();
3349 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
3351 arrayExpressionSemantic(newargs
, sc
);
3352 preFunctionArguments(loc
, sc
, newargs
);
3353 arrayExpressionSemantic(arguments
, sc
);
3354 preFunctionArguments(loc
, sc
, arguments
);
3356 if (thisexp
&& tb
->ty
!= Tclass
)
3357 error("e.new is only for allocating nested classes, not %s", tb
->toChars());
3359 if (tb
->ty
== Tclass
)
3362 TypeClass
*tc
= (TypeClass
*)(tb
);
3363 ClassDeclaration
*cd
= tc
->sym
->isClassDeclaration();
3364 if (cd
->isInterfaceDeclaration())
3365 error("cannot create instance of interface %s", cd
->toChars());
3366 else if (cd
->isAbstract())
3367 { error("cannot create instance of abstract class %s", cd
->toChars());
3368 for (int i
= 0; i
< cd
->vtbl
.dim
; i
++)
3369 { FuncDeclaration
*fd
= ((Dsymbol
*)cd
->vtbl
.data
[i
])->isFuncDeclaration();
3370 if (fd
&& fd
->isAbstract())
3371 error("function %s is abstract", fd
->toChars());
3374 checkDeprecated(sc
, cd
);
3376 { /* We need a 'this' pointer for the nested class.
3377 * Ensure we have the right one.
3379 Dsymbol
*s
= cd
->toParent2();
3380 ClassDeclaration
*cdn
= s
->isClassDeclaration();
3381 FuncDeclaration
*fdn
= s
->isFuncDeclaration();
3383 //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
3388 // Supply an implicit 'this' and try again
3389 thisexp
= new ThisExp(loc
);
3390 for (Dsymbol
*sp
= sc
->parent
; 1; sp
= sp
->parent
)
3393 error("outer class %s 'this' needed to 'new' nested class %s", cdn
->toChars(), cd
->toChars());
3396 ClassDeclaration
*cdp
= sp
->isClassDeclaration();
3399 if (cdp
== cdn
|| cdn
->isBaseOf(cdp
, NULL
))
3401 // Add a '.outer' and try again
3402 thisexp
= new DotIdExp(loc
, thisexp
, Id::outer
);
3409 //printf("cdthis = %s\n", cdthis->toChars());
3410 if (cdthis
!= cdn
&& !cdn
->isBaseOf(cdthis
, NULL
))
3411 error("'this' for nested class must be of type %s, not %s", cdn
->toChars(), thisexp
->type
->toChars());
3416 for (Dsymbol
*sf
= sc
->func
; 1; sf
= sf
->toParent2()->isFuncDeclaration())
3420 error("outer class %s 'this' needed to 'new' nested class %s", cdn
->toChars(), cd
->toChars());
3423 printf("sf = %s\n", sf
->toChars());
3424 AggregateDeclaration
*ad
= sf
->isThis();
3425 if (ad
&& (ad
== cdn
|| cdn
->isBaseOf(ad
->isClassDeclaration(), NULL
)))
3432 { /* The nested class cd is nested inside a function,
3433 * we'll let getEthis() look for errors.
3435 //printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars());
3437 // Because thisexp cannot be a function frame pointer
3438 error("e.new is only for allocating nested classes");
3444 error("e.new is only for allocating nested classes");
3446 FuncDeclaration
*f
= cd
->ctor
;
3450 f
= f
->overloadResolve(loc
, NULL
, arguments
);
3451 checkDeprecated(sc
, f
);
3452 member
= f
->isCtorDeclaration();
3455 cd
->accessCheck(loc
, sc
, member
);
3457 tf
= (TypeFunction
*)f
->type
;
3461 arguments
= new Expressions();
3462 functionArguments(loc
, sc
, tf
, arguments
);
3466 if (arguments
&& arguments
->dim
)
3467 error("no constructor for %s", cd
->toChars());
3475 // Prepend the uint size argument to newargs[]
3476 e
= new IntegerExp(loc
, cd
->size(loc
), Type::tsize_t
);
3478 newargs
= new Expressions();
3481 f
= f
->overloadResolve(loc
, NULL
, newargs
);
3482 allocator
= f
->isNewDeclaration();
3485 tf
= (TypeFunction
*)f
->type
;
3486 functionArguments(loc
, sc
, tf
, newargs
);
3490 if (newargs
&& newargs
->dim
)
3491 error("no allocator for %s", cd
->toChars());
3495 else if (tb
->ty
== Tstruct
)
3497 TypeStruct
*ts
= (TypeStruct
*)tb
;
3498 StructDeclaration
*sd
= ts
->sym
;
3499 FuncDeclaration
*f
= sd
->aggNew
;
3502 if (arguments
&& arguments
->dim
)
3503 error("no constructor for %s", type
->toChars());
3509 // Prepend the uint size argument to newargs[]
3510 e
= new IntegerExp(loc
, sd
->size(loc
), Type::tsize_t
);
3512 newargs
= new Expressions();
3515 f
= f
->overloadResolve(loc
, NULL
, newargs
);
3516 allocator
= f
->isNewDeclaration();
3519 tf
= (TypeFunction
*)f
->type
;
3520 functionArguments(loc
, sc
, tf
, newargs
);
3522 e
= new VarExp(loc
, f
);
3523 e
= new CallExp(loc
, e
, newargs
);
3524 e
= e
->semantic(sc
);
3525 e
->type
= type
->pointerTo();
3529 type
= type
->pointerTo();
3531 else if (tb
->ty
== Tarray
&& (arguments
&& arguments
->dim
))
3533 for (size_t i
= 0; i
< arguments
->dim
; i
++)
3535 if (tb
->ty
!= Tarray
)
3536 { error("too many arguments for array");
3541 Expression
*arg
= (Expression
*)arguments
->data
[i
];
3542 arg
= resolveProperties(sc
, arg
);
3543 arg
= arg
->implicitCastTo(sc
, Type::tsize_t
);
3544 arg
= arg
->optimize(WANTvalue
);
3545 if (arg
->op
== TOKint64
&& (long long)arg
->toInteger() < 0)
3546 error("negative array index %s", arg
->toChars());
3547 arguments
->data
[i
] = (void *) arg
;
3548 tb
= ((TypeDArray
*)tb
)->next
->toBasetype();
3551 else if (tb
->isscalar())
3553 if (arguments
&& arguments
->dim
)
3554 error("no constructor for %s", type
->toChars());
3556 type
= type
->pointerTo();
3560 error("new can only create structs, dynamic arrays or class objects, not %s's", type
->toChars());
3561 type
= type
->pointerTo();
3564 //printf("NewExp: '%s'\n", toChars());
3565 //printf("NewExp:type '%s'\n", type->toChars());
3570 int NewExp::checkSideEffect(int flag
)
3575 int NewExp::canThrow()
3580 void NewExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3584 { expToCBuffer(buf
, hgs
, thisexp
, PREC_primary
);
3585 buf
->writeByte('.');
3587 buf
->writestring("new ");
3588 if (newargs
&& newargs
->dim
)
3590 buf
->writeByte('(');
3591 argsToCBuffer(buf
, newargs
, hgs
);
3592 buf
->writeByte(')');
3594 newtype
->toCBuffer(buf
, NULL
, hgs
);
3595 if (arguments
&& arguments
->dim
)
3597 buf
->writeByte('(');
3598 argsToCBuffer(buf
, arguments
, hgs
);
3599 buf
->writeByte(')');
3603 /********************** NewAnonClassExp **************************************/
3605 NewAnonClassExp::NewAnonClassExp(Loc loc
, Expression
*thisexp
,
3606 Expressions
*newargs
, ClassDeclaration
*cd
, Expressions
*arguments
)
3607 : Expression(loc
, TOKnewanonclass
, sizeof(NewAnonClassExp
))
3609 this->thisexp
= thisexp
;
3610 this->newargs
= newargs
;
3612 this->arguments
= arguments
;
3615 Expression
*NewAnonClassExp::syntaxCopy()
3617 return new NewAnonClassExp(loc
,
3618 thisexp
? thisexp
->syntaxCopy() : NULL
,
3619 arraySyntaxCopy(newargs
),
3620 (ClassDeclaration
*)cd
->syntaxCopy(NULL
),
3621 arraySyntaxCopy(arguments
));
3625 Expression
*NewAnonClassExp::semantic(Scope
*sc
)
3628 printf("NewAnonClassExp::semantic() %s\n", toChars());
3629 //printf("type: %s\n", type->toChars());
3632 Expression
*d
= new DeclarationExp(loc
, cd
);
3633 d
= d
->semantic(sc
);
3635 Expression
*n
= new NewExp(loc
, thisexp
, newargs
, cd
->type
, arguments
);
3637 Expression
*c
= new CommaExp(loc
, d
, n
);
3638 return c
->semantic(sc
);
3641 int NewAnonClassExp::checkSideEffect(int flag
)
3646 int NewAnonClassExp::canThrow()
3651 void NewAnonClassExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3655 { expToCBuffer(buf
, hgs
, thisexp
, PREC_primary
);
3656 buf
->writeByte('.');
3658 buf
->writestring("new");
3659 if (newargs
&& newargs
->dim
)
3661 buf
->writeByte('(');
3662 argsToCBuffer(buf
, newargs
, hgs
);
3663 buf
->writeByte(')');
3665 buf
->writestring(" class ");
3666 if (arguments
&& arguments
->dim
)
3668 buf
->writeByte('(');
3669 argsToCBuffer(buf
, arguments
, hgs
);
3670 buf
->writeByte(')');
3672 //buf->writestring(" { }");
3675 cd
->toCBuffer(buf
, hgs
);
3679 /********************** SymOffExp **************************************/
3681 SymbolExp::SymbolExp(Loc loc
, enum TOK op
, int size
, Declaration
*var
, int hasOverloads
)
3682 : Expression(loc
, op
, size
)
3686 this->hasOverloads
= hasOverloads
;
3689 /********************** SymOffExp **************************************/
3691 SymOffExp::SymOffExp(Loc loc
, Declaration
*var
, target_size_t offset
, int hasOverloads
)
3692 : SymbolExp(loc
, TOKsymoff
, sizeof(SymOffExp
), var
, hasOverloads
)
3694 this->offset
= offset
;
3696 VarDeclaration
*v
= var
->isVarDeclaration();
3697 if (v
&& v
->needThis())
3698 error("need 'this' for address of %s", v
->toChars());
3701 Expression
*SymOffExp::semantic(Scope
*sc
)
3704 printf("SymOffExp::semantic('%s')\n", toChars());
3706 //var->semantic(sc);
3708 type
= var
->type
->pointerTo();
3709 VarDeclaration
*v
= var
->isVarDeclaration();
3711 v
->checkNestedReference(sc
, loc
);
3715 int SymOffExp::isBool(int result
)
3717 return result
? TRUE
: FALSE
;
3720 void SymOffExp::checkEscape()
3722 VarDeclaration
*v
= var
->isVarDeclaration();
3725 if (!v
->isDataseg())
3726 error("escaping reference to local variable %s", v
->toChars());
3730 void SymOffExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3733 buf
->printf("(& %s+%"PRIuTSIZE
")", var
->toChars(), offset
);
3735 buf
->printf("& %s", var
->toChars());
3738 /******************************** VarExp **************************/
3740 VarExp::VarExp(Loc loc
, Declaration
*var
, int hasOverloads
)
3741 : SymbolExp(loc
, TOKvar
, sizeof(VarExp
), var
, hasOverloads
)
3743 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
3744 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
3745 this->type
= var
->type
;
3748 int VarExp::equals(Object
*o
)
3752 (((Expression
*)o
)->op
== TOKvar
&&
3753 ((ne
= (VarExp
*)o
), type
->toHeadMutable()->equals(ne
->type
->toHeadMutable())) &&
3759 Expression
*VarExp::semantic(Scope
*sc
)
3760 { FuncLiteralDeclaration
*fd
;
3763 printf("VarExp::semantic(%s)\n", toChars());
3768 if (var
->storage_class
& STClazy
)
3770 TypeFunction
*tf
= new TypeFunction(NULL
, type
, 0, LINKd
);
3771 type
= new TypeDelegate(tf
);
3772 type
= type
->semantic(loc
, sc
);
3777 VarDeclaration
*v
= var
->isVarDeclaration();
3781 if ((v
->isConst() || v
->isInvariant()) &&
3782 type
->toBasetype()->ty
!= Tsarray
&& v
->init
)
3784 ExpInitializer
*ei
= v
->init
->isExpInitializer();
3787 //ei->exp->implicitCastTo(sc, type)->print();
3788 return ei
->exp
->implicitCastTo(sc
, type
);
3792 v
->checkNestedReference(sc
, loc
);
3795 else if ((fd
= var
->isFuncLiteralDeclaration()) != NULL
)
3797 e
= new FuncExp(loc
, fd
);
3805 char *VarExp::toChars()
3807 return var
->toChars();
3810 void VarExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3812 buf
->writestring(var
->toChars());
3815 void VarExp::checkEscape()
3817 VarDeclaration
*v
= var
->isVarDeclaration();
3819 { Type
*tb
= v
->type
->toBasetype();
3820 // if reference type
3821 if (tb
->ty
== Tarray
|| tb
->ty
== Tsarray
|| tb
->ty
== Tclass
)
3823 if ((v
->isAuto() || v
->isScope()) && !v
->noauto
)
3824 error("escaping reference to auto local %s", v
->toChars());
3825 else if (v
->storage_class
& STCvariadic
)
3826 error("escaping reference to variadic parameter %s", v
->toChars());
3831 Expression
*VarExp::toLvalue(Scope
*sc
, Expression
*e
)
3834 tym
= tybasic(e1
->ET
->Tty
);
3835 if (!(tyscalar(tym
) ||
3837 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
3838 synerr(EM_lvalue
); // lvalue expected
3840 if (var
->storage_class
& STClazy
)
3841 error("lazy variables cannot be lvalues");
3845 Expression
*VarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
3847 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
3848 if (type
&& type
->toBasetype()->ty
== Tsarray
)
3849 error("cannot change reference to static array '%s'", var
->toChars());
3851 var
->checkModify(loc
, sc
, type
);
3853 // See if this expression is a modifiable lvalue (i.e. not const)
3854 return toLvalue(sc
, e
);
3858 /******************************** OverExp **************************/
3860 OverExp::OverExp(OverloadSet
*s
)
3861 : Expression(loc
, TOKoverloadset
, sizeof(OverExp
))
3863 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
3868 Expression
*OverExp::toLvalue(Scope
*sc
, Expression
*e
)
3874 /******************************** TupleExp **************************/
3876 TupleExp::TupleExp(Loc loc
, Expressions
*exps
)
3877 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
3879 //printf("TupleExp(this = %p)\n", this);
3885 TupleExp::TupleExp(Loc loc
, TupleDeclaration
*tup
)
3886 : Expression(loc
, TOKtuple
, sizeof(TupleExp
))
3888 exps
= new Expressions();
3891 exps
->reserve(tup
->objects
->dim
);
3892 for (size_t i
= 0; i
< tup
->objects
->dim
; i
++)
3893 { Object
*o
= (Object
*)tup
->objects
->data
[i
];
3894 if (o
->dyncast() == DYNCAST_EXPRESSION
)
3896 Expression
*e
= (Expression
*)o
;
3897 e
= e
->syntaxCopy();
3900 else if (o
->dyncast() == DYNCAST_DSYMBOL
)
3902 Dsymbol
*s
= (Dsymbol
*)o
;
3903 Expression
*e
= new DsymbolExp(loc
, s
);
3906 else if (o
->dyncast() == DYNCAST_TYPE
)
3908 Type
*t
= (Type
*)o
;
3909 Expression
*e
= new TypeExp(loc
, t
);
3914 error("%s is not an expression", o
->toChars());
3919 int TupleExp::equals(Object
*o
)
3924 if (((Expression
*)o
)->op
== TOKtuple
)
3926 TupleExp
*te
= (TupleExp
*)o
;
3927 if (exps
->dim
!= te
->exps
->dim
)
3929 for (size_t i
= 0; i
< exps
->dim
; i
++)
3930 { Expression
*e1
= (Expression
*)exps
->data
[i
];
3931 Expression
*e2
= (Expression
*)te
->exps
->data
[i
];
3933 if (!e1
->equals(e2
))
3941 Expression
*TupleExp::syntaxCopy()
3943 return new TupleExp(loc
, arraySyntaxCopy(exps
));
3946 Expression
*TupleExp::semantic(Scope
*sc
)
3949 printf("+TupleExp::semantic(%s)\n", toChars());
3954 // Run semantic() on each argument
3955 for (size_t i
= 0; i
< exps
->dim
; i
++)
3956 { Expression
*e
= (Expression
*)exps
->data
[i
];
3958 e
= e
->semantic(sc
);
3960 { error("%s has no value", e
->toChars());
3961 e
->type
= Type::terror
;
3963 exps
->data
[i
] = (void *)e
;
3967 if (0 && exps
->dim
== 1)
3969 return (Expression
*)exps
->data
[0];
3971 type
= new TypeTuple(exps
);
3972 //printf("-TupleExp::semantic(%s)\n", toChars());
3976 void TupleExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3978 buf
->writestring("tuple(");
3979 argsToCBuffer(buf
, exps
, hgs
);
3980 buf
->writeByte(')');
3983 int TupleExp::checkSideEffect(int flag
)
3986 for (int i
= 0; i
< exps
->dim
; i
++)
3987 { Expression
*e
= (Expression
*)exps
->data
[i
];
3989 f
|= e
->checkSideEffect(2);
3991 if (flag
== 0 && f
== 0)
3992 Expression::checkSideEffect(0);
3996 int TupleExp::canThrow()
3998 return arrayExpressionCanThrow(exps
);
4001 void TupleExp::checkEscape()
4003 for (size_t i
= 0; i
< exps
->dim
; i
++)
4004 { Expression
*e
= (Expression
*)exps
->data
[i
];
4009 /******************************** FuncExp *********************************/
4011 FuncExp::FuncExp(Loc loc
, FuncLiteralDeclaration
*fd
)
4012 : Expression(loc
, TOKfunction
, sizeof(FuncExp
))
4017 Expression
*FuncExp::syntaxCopy()
4019 return new FuncExp(loc
, (FuncLiteralDeclaration
*)fd
->syntaxCopy(NULL
));
4022 Expression
*FuncExp::semantic(Scope
*sc
)
4025 printf("FuncExp::semantic(%s)\n", toChars());
4030 fd
->parent
= sc
->parent
;
4033 fd
->type
= fd
->type
->semantic(loc
, sc
);
4042 if (!global
.errors
&& global
.params
.useInline
)
4047 // Type is a "delegate to" or "pointer to" the function literal
4050 type
= new TypeDelegate(fd
->type
);
4051 type
= type
->semantic(loc
, sc
);
4055 type
= fd
->type
->pointerTo();
4057 fd
->tookAddressOf
++;
4062 char *FuncExp::toChars()
4064 return fd
->toChars();
4067 void FuncExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4069 buf
->writestring(fd
->toChars());
4073 /******************************** DeclarationExp **************************/
4075 DeclarationExp::DeclarationExp(Loc loc
, Dsymbol
*declaration
)
4076 : Expression(loc
, TOKdeclaration
, sizeof(DeclarationExp
))
4078 this->declaration
= declaration
;
4081 Expression
*DeclarationExp::syntaxCopy()
4083 return new DeclarationExp(loc
, declaration
->syntaxCopy(NULL
));
4086 Expression
*DeclarationExp::semantic(Scope
*sc
)
4092 printf("DeclarationExp::semantic() %s\n", toChars());
4095 /* This is here to support extern(linkage) declaration,
4096 * where the extern(linkage) winds up being an AttribDeclaration
4099 Dsymbol
*s
= declaration
;
4101 AttribDeclaration
*ad
= declaration
->isAttribDeclaration();
4104 if (ad
->decl
&& ad
->decl
->dim
== 1)
4105 s
= (Dsymbol
*)ad
->decl
->data
[0];
4108 if (s
->isVarDeclaration())
4109 { // Do semantic() on initializer first, so:
4112 declaration
->semantic(sc
);
4113 s
->parent
= sc
->parent
;
4116 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
4117 // Insert into both local scope and function scope.
4118 // Must be unique in both.
4122 error("declaration %s is already defined", s
->toPrettyChars());
4124 { VarDeclaration
*v
= s
->isVarDeclaration();
4125 if (s
->isFuncDeclaration() &&
4126 !sc
->func
->localsymtab
->insert(s
))
4127 error("declaration %s is already defined in another scope in %s", s
->toPrettyChars(), sc
->func
->toChars());
4128 else if (!global
.params
.useDeprecated
)
4129 { // Disallow shadowing
4131 for (Scope
*scx
= sc
->enclosing
; scx
&& scx
->func
== sc
->func
; scx
= scx
->enclosing
)
4134 if (scx
->scopesym
&& scx
->scopesym
->symtab
&&
4135 (s2
= scx
->scopesym
->symtab
->lookup(s
->ident
)) != NULL
&&
4138 error("shadowing declaration %s is deprecated", s
->toPrettyChars());
4144 if (!s
->isVarDeclaration())
4146 declaration
->semantic(sc
);
4147 s
->parent
= sc
->parent
;
4151 declaration
->semantic2(sc
);
4154 declaration
->semantic3(sc
);
4156 if (!global
.errors
&& global
.params
.useInline
)
4157 declaration
->inlineScan();
4165 int DeclarationExp::checkSideEffect(int flag
)
4170 int DeclarationExp::canThrow()
4172 VarDeclaration
*v
= declaration
->isVarDeclaration();
4174 { ExpInitializer
*ie
= v
->init
->isExpInitializer();
4175 return ie
&& ie
->exp
->canThrow();
4180 void DeclarationExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4182 declaration
->toCBuffer(buf
, hgs
);
4186 /************************ TypeidExp ************************************/
4192 TypeidExp::TypeidExp(Loc loc
, Type
*typeidType
)
4193 : Expression(loc
, TOKtypeid
, sizeof(TypeidExp
))
4195 this->typeidType
= typeidType
;
4199 Expression
*TypeidExp::syntaxCopy()
4201 return new TypeidExp(loc
, typeidType
->syntaxCopy());
4205 Expression
*TypeidExp::semantic(Scope
*sc
)
4209 printf("TypeidExp::semantic()\n");
4211 typeidType
= typeidType
->semantic(loc
, sc
);
4212 e
= typeidType
->getTypeInfo(sc
);
4216 void TypeidExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4218 buf
->writestring("typeid(");
4219 typeidType
->toCBuffer(buf
, NULL
, hgs
);
4220 buf
->writeByte(')');
4223 /************************ TraitsExp ************************************/
4226 * __traits(identifier, args...)
4229 TraitsExp::TraitsExp(Loc loc
, Identifier
*ident
, Objects
*args
)
4230 : Expression(loc
, TOKtraits
, sizeof(TraitsExp
))
4232 this->ident
= ident
;
4237 Expression
*TraitsExp::syntaxCopy()
4239 return new TraitsExp(loc
, ident
, TemplateInstance::arraySyntaxCopy(args
));
4243 void TraitsExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4245 buf
->writestring("__traits(");
4246 buf
->writestring(ident
->toChars());
4249 for (int i
= 0; i
< args
->dim
; i
++)
4251 buf
->writeByte(',');
4252 Object
*oarg
= (Object
*)args
->data
[i
];
4253 ObjectToCBuffer(buf
, hgs
, oarg
);
4256 buf
->writeByte(')');
4259 /************************************************************/
4261 HaltExp::HaltExp(Loc loc
)
4262 : Expression(loc
, TOKhalt
, sizeof(HaltExp
))
4266 Expression
*HaltExp::semantic(Scope
*sc
)
4269 printf("HaltExp::semantic()\n");
4275 int HaltExp::checkSideEffect(int flag
)
4280 void HaltExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4282 buf
->writestring("halt");
4285 /************************************************************/
4287 IsExp::IsExp(Loc loc
, Type
*targ
, Identifier
*id
, enum TOK tok
,
4288 Type
*tspec
, enum TOK tok2
, TemplateParameters
*parameters
)
4289 : Expression(loc
, TOKis
, sizeof(IsExp
))
4294 this->tspec
= tspec
;
4296 this->parameters
= parameters
;
4299 Expression
*IsExp::syntaxCopy()
4301 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4302 TemplateParameters
*p
= NULL
;
4305 p
= new TemplateParameters();
4306 p
->setDim(parameters
->dim
);
4307 for (int i
= 0; i
< p
->dim
; i
++)
4308 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
4309 p
->data
[i
] = (void *)tp
->syntaxCopy();
4313 return new IsExp(loc
,
4317 tspec
? tspec
->syntaxCopy() : NULL
,
4322 Expression
*IsExp::semantic(Scope
*sc
)
4325 /* is(targ id tok tspec)
4326 * is(targ id == tok2)
4329 //printf("IsExp::semantic(%s)\n", toChars());
4330 if (id
&& !(sc
->flags
& SCOPEstaticif
))
4331 error("can only declare type aliases within static if conditionals");
4333 unsigned errors_save
= global
.errors
;
4335 global
.gag
++; // suppress printing of error messages
4336 targ
= targ
->semantic(loc
, sc
);
4338 unsigned gerrors
= global
.errors
;
4339 global
.errors
= errors_save
;
4341 if (gerrors
) // if any errors happened
4342 { // then condition is false
4345 else if (tok2
!= TOKreserved
)
4350 if (targ
->ty
!= Ttypedef
)
4352 tded
= ((TypeTypedef
*)targ
)->sym
->basetype
;
4356 if (targ
->ty
!= Tstruct
)
4358 if (((TypeStruct
*)targ
)->sym
->isUnionDeclaration())
4364 if (targ
->ty
!= Tstruct
)
4366 if (!((TypeStruct
*)targ
)->sym
->isUnionDeclaration())
4372 if (targ
->ty
!= Tclass
)
4374 if (((TypeClass
*)targ
)->sym
->isInterfaceDeclaration())
4380 if (targ
->ty
!= Tclass
)
4382 if (!((TypeClass
*)targ
)->sym
->isInterfaceDeclaration())
4389 if (!targ
->isConst())
4395 if (!targ
->isInvariant())
4402 // If class or interface, get the base class and interfaces
4403 if (targ
->ty
!= Tclass
)
4406 { ClassDeclaration
*cd
= ((TypeClass
*)targ
)->sym
;
4407 Arguments
*args
= new Arguments
;
4408 args
->reserve(cd
->baseclasses
.dim
);
4409 for (size_t i
= 0; i
< cd
->baseclasses
.dim
; i
++)
4410 { BaseClass
*b
= (BaseClass
*)cd
->baseclasses
.data
[i
];
4411 args
->push(new Argument(STCin
, b
->type
, NULL
, NULL
));
4413 tded
= new TypeTuple(args
);
4418 if (targ
->ty
!= Tenum
)
4420 tded
= ((TypeEnum
*)targ
)->sym
->memtype
;
4424 if (targ
->ty
!= Tdelegate
)
4426 tded
= ((TypeDelegate
*)targ
)->next
; // the underlying function type
4431 if (targ
->ty
!= Tfunction
)
4435 /* Generate tuple from function parameter types.
4437 assert(tded
->ty
== Tfunction
);
4438 Arguments
*params
= ((TypeFunction
*)tded
)->parameters
;
4439 size_t dim
= Argument::dim(params
);
4440 Arguments
*args
= new Arguments
;
4442 for (size_t i
= 0; i
< dim
; i
++)
4443 { Argument
*arg
= Argument::getNth(params
, i
);
4444 assert(arg
&& arg
->type
);
4445 args
->push(new Argument(arg
->storageClass
, arg
->type
, NULL
, NULL
));
4447 tded
= new TypeTuple(args
);
4451 /* Get the 'return type' for the function,
4452 * delegate, or pointer to function.
4454 if (targ
->ty
== Tfunction
)
4455 tded
= ((TypeFunction
*)targ
)->next
;
4456 else if (targ
->ty
== Tdelegate
)
4457 { tded
= ((TypeDelegate
*)targ
)->next
;
4458 tded
= ((TypeFunction
*)tded
)->next
;
4460 else if (targ
->ty
== Tpointer
&&
4461 ((TypePointer
*)targ
)->next
->ty
== Tfunction
)
4462 { tded
= ((TypePointer
*)targ
)->next
;
4463 tded
= ((TypeFunction
*)tded
)->next
;
4474 else if (id
&& tspec
)
4476 /* Evaluate to TRUE if targ matches tspec.
4477 * If TRUE, declare id as an alias for the specialized type.
4481 assert(parameters
&& parameters
->dim
);
4484 dedtypes
.setDim(parameters
->dim
);
4487 m
= targ
->deduceType(NULL
, tspec
, parameters
, &dedtypes
);
4488 if (m
== MATCHnomatch
||
4489 (m
!= MATCHexact
&& tok
== TOKequal
))
4493 tded
= (Type
*)dedtypes
.data
[0];
4499 tiargs
.data
[0] = (void *)targ
;
4501 for (int i
= 1; i
< parameters
->dim
; i
++)
4502 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
4505 m
= tp
->matchArg(sc
, &tiargs
, i
, parameters
, &dedtypes
, &s
);
4506 if (m
== MATCHnomatch
)
4510 error("declaration %s is already defined", s
->toChars());
4512 Object
*o
= (Object
*)dedtypes
.data
[i
];
4513 Dsymbol
*s
= TemplateDeclaration::declareParameter(loc
, sc
, tp
, o
);
4516 s
->addMember(sc
, sc
->sd
, 1);
4524 /* Declare id as an alias for type targ. Evaluate to TRUE
4531 /* Evaluate to TRUE if targ matches tspec
4533 tspec
= tspec
->semantic(loc
, sc
);
4534 //printf("targ = %s\n", targ->toChars());
4535 //printf("tspec = %s\n", tspec->toChars());
4536 if (tok
== TOKcolon
)
4537 { if (targ
->implicitConvTo(tspec
))
4543 { if (targ
->equals(tspec
))
4553 Dsymbol
*s
= new AliasDeclaration(loc
, id
, tded
);
4556 error("declaration %s is already defined", s
->toChars());
4558 s
->addMember(sc
, sc
->sd
, 1);
4560 return new IntegerExp(loc
, 1, Type::tbool
);
4563 return new IntegerExp(loc
, 0, Type::tbool
);
4566 void IsExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4568 buf
->writestring("is(");
4569 targ
->toCBuffer(buf
, id
, hgs
);
4570 if (tok2
!= TOKreserved
)
4572 buf
->printf(" %s %s", Token::toChars(tok
), Token::toChars(tok2
));
4576 if (tok
== TOKcolon
)
4577 buf
->writestring(" : ");
4579 buf
->writestring(" == ");
4580 tspec
->toCBuffer(buf
, NULL
, hgs
);
4583 { // First parameter is already output, so start with second
4584 for (int i
= 1; i
< parameters
->dim
; i
++)
4586 buf
->writeByte(',');
4587 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
4588 tp
->toCBuffer(buf
, hgs
);
4591 buf
->writeByte(')');
4595 /************************************************************/
4597 UnaExp::UnaExp(Loc loc
, enum TOK op
, int size
, Expression
*e1
)
4598 : Expression(loc
, op
, size
)
4603 Expression
*UnaExp::syntaxCopy()
4606 e
= (UnaExp
*)copy();
4608 e
->e1
= e
->e1
->syntaxCopy();
4612 Expression
*UnaExp::semantic(Scope
*sc
)
4615 printf("UnaExp::semantic('%s')\n", toChars());
4617 e1
= e1
->semantic(sc
);
4619 // error("%s has no value", e1->toChars());
4623 int UnaExp::canThrow()
4625 return e1
->canThrow();
4628 void UnaExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4630 buf
->writestring(Token::toChars(op
));
4631 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
4634 /************************************************************/
4636 BinExp::BinExp(Loc loc
, enum TOK op
, int size
, Expression
*e1
, Expression
*e2
)
4637 : Expression(loc
, op
, size
)
4643 Expression
*BinExp::syntaxCopy()
4646 e
= (BinExp
*)copy();
4648 e
->e1
= e
->e1
->syntaxCopy();
4649 e
->e2
= e
->e2
->syntaxCopy();
4653 Expression
*BinExp::semantic(Scope
*sc
)
4656 printf("BinExp::semantic('%s')\n", toChars());
4658 e1
= e1
->semantic(sc
);
4661 error("%s has no value", e1
->toChars());
4662 e1
->type
= Type::terror
;
4664 e2
= e2
->semantic(sc
);
4667 error("%s has no value", e2
->toChars());
4668 e2
->type
= Type::terror
;
4674 Expression
*BinExp::semanticp(Scope
*sc
)
4676 BinExp::semantic(sc
);
4677 e1
= resolveProperties(sc
, e1
);
4678 e2
= resolveProperties(sc
, e2
);
4682 /***************************
4683 * Common semantic routine for some xxxAssignExp's.
4686 Expression
*BinExp::commonSemanticAssign(Scope
*sc
)
4691 BinExp::semantic(sc
);
4692 e2
= resolveProperties(sc
, e2
);
4694 e
= op_overload(sc
);
4698 e1
= e1
->modifiableLvalue(sc
, e1
);
4701 if (type
->toBasetype()->ty
== Tbool
)
4703 error("operator not allowed on bool expression %s", toChars());
4706 e1
->checkArithmetic();
4707 e2
->checkArithmetic();
4709 if (op
== TOKmodass
&& e2
->type
->iscomplex())
4710 { error("cannot perform modulo complex arithmetic");
4711 return new IntegerExp(0);
4717 Expression
*BinExp::commonSemanticAssignIntegral(Scope
*sc
)
4722 BinExp::semantic(sc
);
4723 e2
= resolveProperties(sc
, e2
);
4725 e
= op_overload(sc
);
4729 e1
= e1
->modifiableLvalue(sc
, e1
);
4732 if (type
->toBasetype()->ty
== Tbool
)
4734 e2
= e2
->implicitCastTo(sc
, type
);
4738 e1
->checkIntegral();
4739 e2
->checkIntegral();
4744 int BinExp::checkSideEffect(int flag
)
4746 if (op
== TOKplusplus
||
4747 op
== TOKminusminus
||
4749 op
== TOKconstruct
||
4766 return Expression::checkSideEffect(flag
);
4769 void BinExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4771 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
4772 buf
->writeByte(' ');
4773 buf
->writestring(Token::toChars(op
));
4774 buf
->writeByte(' ');
4775 expToCBuffer(buf
, hgs
, e2
, (enum PREC
)(precedence
[op
] + 1));
4778 int BinExp::isunsigned()
4780 return e1
->type
->isunsigned() || e2
->type
->isunsigned();
4783 int BinExp::canThrow()
4785 return e1
->canThrow() || e2
->canThrow();
4788 void BinExp::incompatibleTypes()
4790 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
4791 e1
->toChars(), Token::toChars(op
), e2
->toChars(),
4792 e1
->type
->toChars(), e2
->type
->toChars());
4795 /************************************************************/
4797 CompileExp::CompileExp(Loc loc
, Expression
*e
)
4798 : UnaExp(loc
, TOKmixin
, sizeof(CompileExp
), e
)
4802 Expression
*CompileExp::semantic(Scope
*sc
)
4805 printf("CompileExp::semantic('%s')\n", toChars());
4807 UnaExp::semantic(sc
);
4808 e1
= resolveProperties(sc
, e1
);
4809 e1
= e1
->optimize(WANTvalue
| WANTinterpret
);
4810 if (e1
->op
!= TOKstring
)
4811 { error("argument to mixin must be a string, not (%s)", e1
->toChars());
4812 type
= Type::terror
;
4815 StringExp
*se
= (StringExp
*)e1
;
4816 se
= se
->toUTF8(sc
);
4817 Parser
p(sc
->module
, (unsigned char *)se
->string
, se
->len
, 0);
4820 //printf("p.loc.linnum = %d\n", p.loc.linnum);
4821 Expression
*e
= p
.parseExpression();
4822 if (p
.token
.value
!= TOKeof
)
4823 error("incomplete mixin expression (%s)", se
->toChars());
4824 return e
->semantic(sc
);
4827 void CompileExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4829 buf
->writestring("mixin(");
4830 expToCBuffer(buf
, hgs
, e1
, PREC_assign
);
4831 buf
->writeByte(')');
4834 /************************************************************/
4836 FileExp::FileExp(Loc loc
, Expression
*e
)
4837 : UnaExp(loc
, TOKmixin
, sizeof(FileExp
), e
)
4841 Expression
*FileExp::semantic(Scope
*sc
)
4846 printf("FileExp::semantic('%s')\n", toChars());
4848 UnaExp::semantic(sc
);
4849 e1
= resolveProperties(sc
, e1
);
4850 e1
= e1
->optimize(WANTvalue
);
4851 if (e1
->op
!= TOKstring
)
4852 { error("file name argument must be a string, not (%s)", e1
->toChars());
4855 se
= (StringExp
*)e1
;
4856 se
= se
->toUTF8(sc
);
4857 name
= (char *)se
->string
;
4859 if (!global
.params
.fileImppath
)
4860 { error("need -Jpath switch to import text file %s", name
);
4864 if (name
!= FileName::name(name
))
4865 { error("use -Jpath switch to provide path for filename %s", name
);
4869 name
= FileName::searchPath(global
.filePath
, name
, 0);
4871 { error("file %s cannot be found, check -Jpath", se
->toChars());
4875 if (global
.params
.verbose
)
4876 printf("file %s\t(%s)\n", se
->string
, name
);
4880 { error("cannot read file %s", f
.toChars());
4886 se
= new StringExp(loc
, f
.buffer
, f
.len
);
4890 return se
->semantic(sc
);
4893 se
= new StringExp(loc
, "");
4897 void FileExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4899 buf
->writestring("import(");
4900 expToCBuffer(buf
, hgs
, e1
, PREC_assign
);
4901 buf
->writeByte(')');
4904 /************************************************************/
4906 AssertExp::AssertExp(Loc loc
, Expression
*e
, Expression
*msg
)
4907 : UnaExp(loc
, TOKassert
, sizeof(AssertExp
), e
)
4912 Expression
*AssertExp::syntaxCopy()
4914 AssertExp
*ae
= new AssertExp(loc
, e1
->syntaxCopy(),
4915 msg
? msg
->syntaxCopy() : NULL
);
4919 Expression
*AssertExp::semantic(Scope
*sc
)
4922 printf("AssertExp::semantic('%s')\n", toChars());
4924 UnaExp::semantic(sc
);
4925 e1
= resolveProperties(sc
, e1
);
4926 // BUG: see if we can do compile time elimination of the Assert
4927 e1
= e1
->optimize(WANTvalue
);
4928 e1
= e1
->checkToBoolean();
4931 msg
= msg
->semantic(sc
);
4932 msg
= resolveProperties(sc
, msg
);
4933 msg
= msg
->implicitCastTo(sc
, Type::tchar
->constOf()->arrayOf());
4934 msg
= msg
->optimize(WANTvalue
);
4936 if (e1
->isBool(FALSE
))
4938 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4939 fd
->hasReturnExp
|= 4;
4941 if (!global
.params
.useAssert
)
4942 { Expression
*e
= new HaltExp(loc
);
4943 e
= e
->semantic(sc
);
4951 int AssertExp::checkSideEffect(int flag
)
4956 int AssertExp::canThrow()
4958 return (global
.params
.useAssert
!= 0);
4961 void AssertExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4963 buf
->writestring("assert(");
4964 expToCBuffer(buf
, hgs
, e1
, PREC_assign
);
4967 buf
->writeByte(',');
4968 expToCBuffer(buf
, hgs
, msg
, PREC_assign
);
4970 buf
->writeByte(')');
4973 /************************************************************/
4975 DotIdExp::DotIdExp(Loc loc
, Expression
*e
, Identifier
*ident
)
4976 : UnaExp(loc
, TOKdot
, sizeof(DotIdExp
), e
)
4978 this->ident
= ident
;
4981 Expression
*DotIdExp::semantic(Scope
*sc
)
4987 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
4988 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
4991 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
4994 /* Don't do semantic analysis if we'll be converting
4997 if (ident
== Id::stringof
)
4998 { char *s
= e1
->toChars();
4999 e
= new StringExp(loc
, s
, strlen(s
), 'c');
5000 e
= e
->semantic(sc
);
5005 /* Special case: rewrite this.id and super.id
5006 * to be classtype.id and baseclasstype.id
5007 * if we have no this pointer.
5009 if ((e1
->op
== TOKthis
|| e1
->op
== TOKsuper
) && !hasThis(sc
))
5010 { ClassDeclaration
*cd
;
5011 StructDeclaration
*sd
;
5012 AggregateDeclaration
*ad
;
5014 ad
= sc
->getStructClassScope();
5017 cd
= ad
->isClassDeclaration();
5020 if (e1
->op
== TOKthis
)
5022 e
= new TypeDotIdExp(loc
, cd
->type
, ident
);
5023 return e
->semantic(sc
);
5025 else if (cd
->baseClass
&& e1
->op
== TOKsuper
)
5027 e
= new TypeDotIdExp(loc
, cd
->baseClass
->type
, ident
);
5028 return e
->semantic(sc
);
5033 sd
= ad
->isStructDeclaration();
5036 if (e1
->op
== TOKthis
)
5038 e
= new TypeDotIdExp(loc
, sd
->type
, ident
);
5039 return e
->semantic(sc
);
5046 UnaExp::semantic(sc
);
5048 if (e1
->op
== TOKdotexp
)
5050 DotExp
*de
= (DotExp
*)e1
;
5056 e1
= resolveProperties(sc
, e1
);
5061 if (e1
->op
== TOKtuple
&& ident
== Id::offsetof
)
5062 { /* 'distribute' the .offsetof to each of the tuple elements.
5064 TupleExp
*te
= (TupleExp
*)e1
;
5065 Expressions
*exps
= new Expressions();
5066 exps
->setDim(te
->exps
->dim
);
5067 for (int i
= 0; i
< exps
->dim
; i
++)
5068 { Expression
*e
= (Expression
*)te
->exps
->data
[i
];
5069 e
= e
->semantic(sc
);
5070 e
= new DotIdExp(e
->loc
, e
, Id::offsetof
);
5071 exps
->data
[i
] = (void *)e
;
5073 e
= new TupleExp(loc
, exps
);
5074 e
= e
->semantic(sc
);
5078 if (e1
->op
== TOKtuple
&& ident
== Id::length
)
5080 TupleExp
*te
= (TupleExp
*)e1
;
5081 e
= new IntegerExp(loc
, te
->exps
->dim
, Type::tsize_t
);
5085 if (eright
->op
== TOKimport
) // also used for template alias's
5088 ScopeExp
*ie
= (ScopeExp
*)eright
;
5090 s
= ie
->sds
->search(loc
, ident
, 0);
5094 checkDeprecated(sc
, s
);
5096 EnumMember
*em
= s
->isEnumMember();
5100 e
= e
->semantic(sc
);
5104 VarDeclaration
*v
= s
->isVarDeclaration();
5107 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
5110 error("circular reference to '%s'", v
->toChars());
5111 type
= Type::tint32
;
5116 if (v
->isConst() || v
->isInvariant())
5120 ExpInitializer
*ei
= v
->init
->isExpInitializer();
5123 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars());
5124 //ei->exp = ei->exp->semantic(sc);
5125 if (ei
->exp
->type
== type
)
5127 e
= ei
->exp
->copy(); // make copy so we can change loc
5133 else if (type
->isscalar())
5135 e
= type
->defaultInit();
5144 eleft
= new ThisExp(loc
);
5145 e
= new DotVarExp(loc
, eleft
, v
);
5146 e
= e
->semantic(sc
);
5150 e
= new VarExp(loc
, v
);
5152 { e
= new CommaExp(loc
, eleft
, e
);
5159 FuncDeclaration
*f
= s
->isFuncDeclaration();
5162 //printf("it's a function\n");
5166 eleft
= new ThisExp(loc
);
5167 e
= new DotVarExp(loc
, eleft
, f
);
5168 e
= e
->semantic(sc
);
5172 e
= new VarExp(loc
, f
, 1);
5174 { e
= new CommaExp(loc
, eleft
, e
);
5181 Type
*t
= s
->getType();
5184 return new TypeExp(loc
, t
);
5187 TupleDeclaration
*tup
= s
->isTupleDeclaration();
5191 error("cannot have e.tuple");
5192 e
= new TupleExp(loc
, tup
);
5193 e
= e
->semantic(sc
);
5197 ScopeDsymbol
*sds
= s
->isScopeDsymbol();
5200 //printf("it's a ScopeDsymbol\n");
5201 e
= new ScopeExp(loc
, sds
);
5202 e
= e
->semantic(sc
);
5204 e
= new DotExp(loc
, eleft
, e
);
5208 Import
*imp
= s
->isImport();
5213 ie
= new ScopeExp(loc
, imp
->pkg
);
5214 return ie
->semantic(sc
);
5217 // BUG: handle other cases like in IdentifierExp::semantic()
5219 printf("s = '%s', kind = '%s'\n", s
->toChars(), s
->kind());
5223 else if (ident
== Id::stringof
)
5224 { char *s
= ie
->toChars();
5225 e
= new StringExp(loc
, s
, strlen(s
), 'c');
5226 e
= e
->semantic(sc
);
5229 error("undefined identifier %s", toChars());
5233 else if (e1
->type
->ty
== Tpointer
&&
5234 ident
!= Id::init
&& ident
!= Id::__sizeof
&&
5235 ident
!= Id::alignof
&& ident
!= Id::offsetof
&&
5236 ident
!= Id::mangleof
&& ident
!= Id::stringof
)
5238 e
= new PtrExp(loc
, e1
);
5239 e
->type
= ((TypePointer
*)e1
->type
)->next
;
5240 return e
->type
->dotExp(sc
, e
, ident
);
5244 e
= e1
->type
->dotExp(sc
, e1
, ident
);
5245 e
= e
->semantic(sc
);
5250 void DotIdExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5252 //printf("DotIdExp::toCBuffer()\n");
5253 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5254 buf
->writeByte('.');
5255 buf
->writestring(ident
->toChars());
5258 /********************** DotTemplateExp ***********************************/
5260 // Mainly just a placeholder
5262 DotTemplateExp::DotTemplateExp(Loc loc
, Expression
*e
, TemplateDeclaration
*td
)
5263 : UnaExp(loc
, TOKdottd
, sizeof(DotTemplateExp
), e
)
5269 void DotTemplateExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5271 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5272 buf
->writeByte('.');
5273 buf
->writestring(td
->toChars());
5277 /************************************************************/
5279 DotVarExp::DotVarExp(Loc loc
, Expression
*e
, Declaration
*v
, int hasOverloads
)
5280 : UnaExp(loc
, TOKdotvar
, sizeof(DotVarExp
), e
)
5282 //printf("DotVarExp()\n");
5284 this->hasOverloads
= hasOverloads
;
5287 Expression
*DotVarExp::semantic(Scope
*sc
)
5290 printf("DotVarExp::semantic('%s')\n", toChars());
5294 var
= var
->toAlias()->isDeclaration();
5296 TupleDeclaration
*tup
= var
->isTupleDeclaration();
5301 * tuple(e1.a, e1.b, e1.c)
5303 Expressions
*exps
= new Expressions
;
5305 exps
->reserve(tup
->objects
->dim
);
5306 for (size_t i
= 0; i
< tup
->objects
->dim
; i
++)
5307 { Object
*o
= (Object
*)tup
->objects
->data
[i
];
5308 if (o
->dyncast() != DYNCAST_EXPRESSION
)
5310 error("%s is not an expression", o
->toChars());
5314 Expression
*e
= (Expression
*)o
;
5315 if (e
->op
!= TOKdsymbol
)
5316 error("%s is not a member", e
->toChars());
5318 { DsymbolExp
*ve
= (DsymbolExp
*)e
;
5320 e
= new DotVarExp(loc
, e1
, ve
->s
->isDeclaration());
5325 Expression
*e
= new TupleExp(loc
, exps
);
5326 e
= e
->semantic(sc
);
5330 e1
= e1
->semantic(sc
);
5333 if (!type
&& global
.errors
)
5334 { // var is goofed up, just return 0
5335 return new IntegerExp(0);
5339 if (!var
->isFuncDeclaration()) // for functions, do checks after overload resolution
5341 Type
*t1
= e1
->type
;
5342 if (t1
->ty
== Tpointer
)
5345 type
= type
->constOf();
5346 else if (t1
->isInvariant())
5347 type
= type
->invariantOf();
5349 AggregateDeclaration
*ad
= var
->toParent()->isAggregateDeclaration();
5350 e1
= getRightThis(loc
, sc
, ad
, e1
, var
);
5351 if (!sc
->noaccesscheck
)
5352 accessCheck(loc
, sc
, e1
, var
);
5355 //printf("-DotVarExp::semantic('%s')\n", toChars());
5359 Expression
*DotVarExp::toLvalue(Scope
*sc
, Expression
*e
)
5361 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5365 Expression
*DotVarExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
5368 printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
5369 printf("e1->type = %s\n", e1
->type
->toChars());
5370 printf("var->type = %s\n", var
->type
->toChars());
5373 // Also need this for non-null fields.
5374 VarDeclaration
*v
= var
->isVarDeclaration();
5375 if (v
) // When is it not a VarDeclaration?
5378 error("Just curious");
5380 if (var
->isCtorinit())
5381 { // It's only modifiable if inside the right constructor
5382 Dsymbol
*s
= sc
->func
;
5385 FuncDeclaration
*fd
= NULL
;
5387 fd
= s
->isFuncDeclaration();
5389 ((fd
->isCtorDeclaration() && var
->storage_class
& STCfield
) ||
5390 (fd
->isStaticCtorDeclaration() && !(var
->storage_class
& STCfield
))) &&
5391 fd
->toParent() == var
->toParent() &&
5395 VarDeclaration
*v
= var
->isVarDeclaration();
5398 //printf("setting ctorinit\n");
5403 { s
= s
->toParent2();
5408 const char *p
= var
->isStatic() ? "static " : "";
5409 error("can only initialize %sconst member %s inside %sconstructor",
5410 p
, var
->toChars(), p
);
5418 Type
*t1
= e1
->type
->toBasetype();
5420 if (!t1
->isMutable() ||
5421 (t1
->ty
== Tpointer
&& !t1
->nextOf()->isMutable()) ||
5422 !var
->type
->isMutable() ||
5423 !var
->type
->isAssignable() ||
5424 var
->storage_class
& STCmanifest
5426 error("cannot modify const/invariant %s", toChars());
5431 void DotVarExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5433 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5434 buf
->writeByte('.');
5435 buf
->writestring(var
->toChars());
5438 /************************************************************/
5444 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc
, Expression
*e
, TemplateInstance
*ti
)
5445 : UnaExp(loc
, TOKdotti
, sizeof(DotTemplateInstanceExp
), e
)
5447 //printf("DotTemplateInstanceExp()\n");
5451 Expression
*DotTemplateInstanceExp::syntaxCopy()
5453 DotTemplateInstanceExp
*de
= new DotTemplateInstanceExp(loc
,
5455 (TemplateInstance
*)ti
->syntaxCopy(NULL
));
5459 Expression
*DotTemplateInstanceExp::semantic(Scope
*sc
)
5462 TemplateDeclaration
*td
;
5466 Expression
*eleft
= NULL
;
5470 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
5474 e1
= e1
->semantic(sc
);
5477 t1
= t1
->toBasetype();
5480 /* Extract the following from e1:
5481 * s: the symbol which ti should be a member of
5482 * eleft: if not NULL, it is the 'this' pointer for ti
5485 if (e1
->op
== TOKdotexp
)
5486 { DotExp
*de
= (DotExp
*)e1
;
5494 if (eright
->op
== TOKimport
)
5496 s
= ((ScopeExp
*)eright
)->sds
;
5498 else if (e1
->op
== TOKtype
)
5500 s
= t1
->isClassHandle();
5502 { if (t1
->ty
== Tstruct
)
5503 s
= ((TypeStruct
*)t1
)->sym
;
5508 else if (t1
&& (t1
->ty
== Tstruct
|| t1
->ty
== Tclass
))
5510 s
= t1
->toDsymbol(sc
);
5513 else if (t1
&& t1
->ty
== Tpointer
)
5515 t1
= ((TypePointer
*)t1
)->next
->toBasetype();
5516 if (t1
->ty
!= Tstruct
)
5518 s
= t1
->toDsymbol(sc
);
5524 error("template %s is not a member of %s", ti
->toChars(), e1
->toChars());
5530 s2
= s
->search(loc
, id
, 0);
5532 { error("template identifier %s is not a member of %s %s", id
->toChars(), s
->kind(), s
->ident
->toChars());
5538 td
= s
->isTemplateDeclaration();
5541 error("%s is not a template", id
->toChars());
5553 s
= ti
->inst
->toAlias();
5554 v
= s
->isDeclaration();
5556 { e
= new DotVarExp(loc
, eleft
, v
);
5557 e
= e
->semantic(sc
);
5562 e
= new ScopeExp(loc
, ti
);
5565 e
= new DotExp(loc
, eleft
, e
);
5567 e
= e
->semantic(sc
);
5571 return new IntegerExp(0);
5574 void DotTemplateInstanceExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5576 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5577 buf
->writeByte('.');
5578 ti
->toCBuffer(buf
, hgs
);
5581 /************************************************************/
5583 DelegateExp::DelegateExp(Loc loc
, Expression
*e
, FuncDeclaration
*f
, int hasOverloads
)
5584 : UnaExp(loc
, TOKdelegate
, sizeof(DelegateExp
), e
)
5587 this->hasOverloads
= hasOverloads
;
5590 Expression
*DelegateExp::semantic(Scope
*sc
)
5593 printf("DelegateExp::semantic('%s')\n", toChars());
5597 e1
= e1
->semantic(sc
);
5598 type
= new TypeDelegate(func
->type
);
5599 type
= type
->semantic(loc
, sc
);
5600 AggregateDeclaration
*ad
= func
->toParent()->isAggregateDeclaration();
5601 if (func
->needThis())
5602 e1
= getRightThis(loc
, sc
, ad
, e1
, func
);
5607 void DelegateExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5609 buf
->writeByte('&');
5610 if (!func
->isNested())
5612 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5613 buf
->writeByte('.');
5615 buf
->writestring(func
->toChars());
5618 /************************************************************/
5620 DotTypeExp::DotTypeExp(Loc loc
, Expression
*e
, Dsymbol
*s
)
5621 : UnaExp(loc
, TOKdottype
, sizeof(DotTypeExp
), e
)
5624 this->type
= s
->getType();
5627 Expression
*DotTypeExp::semantic(Scope
*sc
)
5630 printf("DotTypeExp::semantic('%s')\n", toChars());
5632 UnaExp::semantic(sc
);
5636 void DotTypeExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
5638 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
5639 buf
->writeByte('.');
5640 buf
->writestring(sym
->toChars());
5643 /************************************************************/
5645 CallExp::CallExp(Loc loc
, Expression
*e
, Expressions
*exps
)
5646 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5648 this->arguments
= exps
;
5651 CallExp::CallExp(Loc loc
, Expression
*e
)
5652 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5654 this->arguments
= NULL
;
5657 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
)
5658 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5660 Expressions
*arguments
= new Expressions();
5661 arguments
->setDim(1);
5662 arguments
->data
[0] = (void *)earg1
;
5664 this->arguments
= arguments
;
5667 CallExp::CallExp(Loc loc
, Expression
*e
, Expression
*earg1
, Expression
*earg2
)
5668 : UnaExp(loc
, TOKcall
, sizeof(CallExp
), e
)
5670 Expressions
*arguments
= new Expressions();
5671 arguments
->setDim(2);
5672 arguments
->data
[0] = (void *)earg1
;
5673 arguments
->data
[1] = (void *)earg2
;
5675 this->arguments
= arguments
;
5678 Expression
*CallExp::syntaxCopy()
5680 return new CallExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
5684 Expression
*CallExp::semantic(Scope
*sc
)
5691 Objects
*targsi
= NULL
; // initial list of template arguments
5694 printf("CallExp::semantic() %s\n", toChars());
5698 return this; // semantic() already run
5700 if (arguments
&& arguments
->dim
)
5702 Expression
*earg
= (Expression
*)arguments
->data
[0];
5704 if (earg
->type
) earg
->type
->print();
5708 if (e1
->op
== TOKdelegate
)
5709 { DelegateExp
*de
= (DelegateExp
*)e1
;
5711 e1
= new DotVarExp(de
->loc
, de
->e1
, de
->func
);
5712 return semantic(sc
);
5716 * array.id(args) into id(array,args)
5717 * aa.remove(arg) into delete aa[arg]
5719 if (e1
->op
== TOKdot
)
5721 // BUG: we should handle array.a.b.c.e(args) too
5723 DotIdExp
*dotid
= (DotIdExp
*)(e1
);
5724 dotid
->e1
= dotid
->e1
->semantic(sc
);
5726 if (dotid
->e1
->type
)
5728 TY e1ty
= dotid
->e1
->type
->toBasetype()->ty
;
5729 if (e1ty
== Taarray
&& dotid
->ident
== Id::remove
)
5731 if (!arguments
|| arguments
->dim
!= 1)
5732 { error("expected key as argument to aa.remove()");
5735 Expression
*key
= (Expression
*)arguments
->data
[0];
5736 key
= key
->semantic(sc
);
5737 key
= resolveProperties(sc
, key
);
5740 TypeAArray
*taa
= (TypeAArray
*)dotid
->e1
->type
->toBasetype();
5741 key
= key
->implicitCastTo(sc
, taa
->index
);
5743 return new RemoveExp(loc
, dotid
->e1
, key
);
5745 else if (e1ty
== Tarray
|| e1ty
== Tsarray
|| e1ty
== Taarray
)
5748 arguments
= new Expressions();
5749 arguments
->shift(dotid
->e1
);
5750 e1
= new IdentifierExp(dotid
->loc
, dotid
->ident
);
5756 * foo!(tiargs)(funcargs)
5758 if (e1
->op
== TOKimport
&& !e1
->type
)
5759 { ScopeExp
*se
= (ScopeExp
*)e1
;
5760 TemplateInstance
*ti
= se
->sds
->isTemplateInstance();
5761 if (ti
&& !ti
->semanticdone
)
5763 /* Attempt to instantiate ti. If that works, go with it.
5764 * If not, go with partial explicit specialization.
5766 unsigned errors
= global
.errors
;
5770 if (errors
!= global
.errors
)
5772 global
.errors
= errors
;
5773 targsi
= ti
->tiargs
;
5774 e1
= new IdentifierExp(loc
, ti
->name
);
5780 * expr.foo!(tiargs)(funcargs)
5782 if (e1
->op
== TOKdotti
&& !e1
->type
)
5783 { DotTemplateInstanceExp
*se
= (DotTemplateInstanceExp
*)e1
;
5784 TemplateInstance
*ti
= se
->ti
;
5785 if (!ti
->semanticdone
)
5787 /* Attempt to instantiate ti. If that works, go with it.
5788 * If not, go with partial explicit specialization.
5791 unsigned errors
= global
.errors
;
5793 etmp
= e1
->semantic(sc
);
5795 if (errors
!= global
.errors
)
5797 global
.errors
= errors
;
5798 targsi
= ti
->tiargs
;
5799 e1
= new DotIdExp(loc
, se
->e1
, ti
->name
);
5808 //printf("Lagain: %s\n", toChars());
5810 if (e1
->op
== TOKthis
|| e1
->op
== TOKsuper
)
5812 // semantic() run later for these
5816 UnaExp::semantic(sc
);
5818 /* Look for e1 being a lazy parameter
5820 if (e1
->op
== TOKvar
)
5821 { VarExp
*ve
= (VarExp
*)e1
;
5823 if (ve
->var
->storage_class
& STClazy
)
5825 TypeFunction
*tf
= new TypeFunction(NULL
, ve
->var
->type
, 0, LINKd
);
5826 TypeDelegate
*t
= new TypeDelegate(tf
);
5827 ve
->type
= t
->semantic(loc
, sc
);
5831 if (e1
->op
== TOKimport
)
5832 { // Perhaps this should be moved to ScopeExp::semantic()
5833 ScopeExp
*se
= (ScopeExp
*)e1
;
5834 e1
= new DsymbolExp(loc
, se
->sds
);
5835 e1
= e1
->semantic(sc
);
5837 #if 1 // patch for #540 by Oskar Linde
5838 else if (e1
->op
== TOKdotexp
)
5840 DotExp
*de
= (DotExp
*) e1
;
5842 if (de
->e2
->op
== TOKimport
)
5843 { // This should *really* be moved to ScopeExp::semantic()
5844 ScopeExp
*se
= (ScopeExp
*)de
->e2
;
5845 de
->e2
= new DsymbolExp(loc
, se
->sds
);
5846 de
->e2
= de
->e2
->semantic(sc
);
5849 if (de
->e2
->op
== TOKtemplate
)
5850 { TemplateExp
*te
= (TemplateExp
*) de
->e2
;
5851 e1
= new DotTemplateExp(loc
,de
->e1
,te
->td
);
5857 if (e1
->op
== TOKcomma
)
5859 CommaExp
*ce
= (CommaExp
*)e1
;
5862 e1
->type
= ce
->type
;
5865 return ce
->semantic(sc
);
5870 t1
= e1
->type
->toBasetype();
5872 // Check for call operator overload
5874 { AggregateDeclaration
*ad
;
5876 if (t1
->ty
== Tstruct
)
5878 ad
= ((TypeStruct
*)t1
)->sym
;
5879 if (search_function(ad
, Id::call
))
5880 goto L1
; // overload of opCall, therefore it's a call
5882 if (e1
->op
!= TOKtype
)
5883 error("%s %s does not overload ()", ad
->kind(), ad
->toChars());
5884 /* It's a struct literal
5886 Expression
*e
= new StructLiteralExp(loc
, (StructDeclaration
*)ad
, arguments
);
5887 e
= e
->semantic(sc
);
5888 e
->type
= e1
->type
; // in case e1->type was a typedef
5891 else if (t1
->ty
== Tclass
)
5893 ad
= ((TypeClass
*)t1
)->sym
;
5896 // Rewrite as e1.call(arguments)
5897 Expression
*e
= new DotIdExp(loc
, e1
, Id::call
);
5898 e
= new CallExp(loc
, e
, arguments
);
5899 e
= e
->semantic(sc
);
5904 arrayExpressionSemantic(arguments
, sc
);
5905 preFunctionArguments(loc
, sc
, arguments
);
5907 if (e1
->op
== TOKdotvar
&& t1
->ty
== Tfunction
||
5911 DotTemplateExp
*dte
;
5912 AggregateDeclaration
*ad
;
5913 UnaExp
*ue
= (UnaExp
*)(e1
);
5915 if (e1
->op
== TOKdotvar
)
5916 { // Do overload resolution
5917 dve
= (DotVarExp
*)(e1
);
5919 f
= dve
->var
->isFuncDeclaration();
5921 f
= f
->overloadResolve(loc
, ue
->e1
, arguments
);
5923 ad
= f
->toParent()->isAggregateDeclaration();
5926 { dte
= (DotTemplateExp
*)(e1
);
5927 TemplateDeclaration
*td
= dte
->td
;
5930 // Should fix deduceFunctionTemplate() so it works on NULL argument
5931 arguments
= new Expressions();
5932 f
= td
->deduceFunctionTemplate(sc
, loc
, targsi
, ue
->e1
, arguments
);
5934 { type
= Type::terror
;
5937 ad
= td
->toParent()->isAggregateDeclaration();
5940 ue
->e1
= getRightThis(loc
, sc
, ad
, ue
->e1
, f
);
5942 checkDeprecated(sc
, f
);
5943 accessCheck(loc
, sc
, ue
->e1
, f
);
5946 VarExp
*ve
= new VarExp(loc
, f
);
5947 e1
= new CommaExp(loc
, ue
->e1
, ve
);
5952 if (e1
->op
== TOKdotvar
)
5955 e1
= new DotVarExp(loc
, dte
->e1
, f
);
5958 printf("ue->e1 = %s\n", ue
->e1
->toChars());
5959 printf("f = %s\n", f
->toChars());
5960 printf("t = %s\n", t
->toChars());
5961 printf("e1 = %s\n", e1
->toChars());
5962 printf("e1->type = %s\n", e1
->type
->toChars());
5964 // Const member function can take const/invariant/mutable this
5965 if (!(f
->type
->isConst()))
5967 // Check for const/invariant compatibility
5968 Type
*tthis
= ue
->e1
->type
->toBasetype();
5969 if (tthis
->ty
== Tpointer
)
5970 tthis
= tthis
->nextOf()->toBasetype();
5971 if (f
->type
->isInvariant())
5973 if (tthis
->mod
!= MODinvariant
)
5974 error("%s can only be called on an invariant object", e1
->toChars());
5978 if (tthis
->mod
!= 0)
5979 { //printf("mod = %x\n", tthis->mod);
5980 error("%s can only be called on a mutable object, not %s", e1
->toChars(), tthis
->toChars());
5984 /* Cannot call mutable method on a final struct
5986 if (tthis
->ty
== Tstruct
&&
5987 ue
->e1
->op
== TOKvar
)
5988 { VarExp
*v
= (VarExp
*)ue
->e1
;
5989 if (v
->var
->storage_class
& STCfinal
)
5990 error("cannot call mutable method on final struct");
5994 // See if we need to adjust the 'this' pointer
5995 AggregateDeclaration
*ad
= f
->isThis();
5996 ClassDeclaration
*cd
= ue
->e1
->type
->isClassHandle();
5997 if (ad
&& cd
&& ad
->isClassDeclaration() && ad
!= cd
&&
5998 ue
->e1
->op
!= TOKsuper
)
6000 ue
->e1
= ue
->e1
->castTo(sc
, ad
->type
); //new CastExp(loc, ue->e1, ad->type);
6001 ue
->e1
= ue
->e1
->semantic(sc
);
6006 else if (e1
->op
== TOKsuper
)
6008 // Base class constructor call
6009 ClassDeclaration
*cd
= NULL
;
6012 cd
= sc
->func
->toParent()->isClassDeclaration();
6013 if (!cd
|| !cd
->baseClass
|| !sc
->func
->isCtorDeclaration())
6015 error("super class constructor call must be in a constructor");
6016 type
= Type::terror
;
6021 f
= cd
->baseClass
->ctor
;
6023 { error("no super class constructor for %s", cd
->baseClass
->toChars());
6024 type
= Type::terror
;
6030 if (sc
->callSuper
& (CSXthis
| CSXsuper
))
6031 error("reference to this before super()");
6033 if (sc
->noctor
|| sc
->callSuper
& CSXlabel
)
6034 error("constructor calls not allowed in loops or after labels");
6035 if (sc
->callSuper
& (CSXsuper_ctor
| CSXthis_ctor
))
6036 error("multiple constructor calls");
6037 sc
->callSuper
|= CSXany_ctor
| CSXsuper_ctor
;
6039 f
= f
->overloadResolve(loc
, NULL
, arguments
);
6040 checkDeprecated(sc
, f
);
6041 e1
= new DotVarExp(e1
->loc
, e1
, f
);
6042 e1
= e1
->semantic(sc
);
6047 else if (e1
->op
== TOKthis
)
6049 // same class constructor call
6050 ClassDeclaration
*cd
= NULL
;
6053 cd
= sc
->func
->toParent()->isClassDeclaration();
6054 if (!cd
|| !sc
->func
->isCtorDeclaration())
6056 error("class constructor call must be in a constructor");
6057 type
= Type::terror
;
6063 if (sc
->callSuper
& (CSXthis
| CSXsuper
))
6064 error("reference to this before super()");
6066 if (sc
->noctor
|| sc
->callSuper
& CSXlabel
)
6067 error("constructor calls not allowed in loops or after labels");
6068 if (sc
->callSuper
& (CSXsuper_ctor
| CSXthis_ctor
))
6069 error("multiple constructor calls");
6070 sc
->callSuper
|= CSXany_ctor
| CSXthis_ctor
;
6073 f
= f
->overloadResolve(loc
, NULL
, arguments
);
6074 checkDeprecated(sc
, f
);
6075 e1
= new DotVarExp(e1
->loc
, e1
, f
);
6076 e1
= e1
->semantic(sc
);
6079 // BUG: this should really be done by checking the static
6082 error("cyclic constructor call");
6085 else if (e1
->op
== TOKoverloadset
)
6087 OverExp
*eo
= (OverExp
*)e1
;
6088 FuncDeclaration
*f
= NULL
;
6089 for (int i
= 0; i
< eo
->vars
->a
.dim
; i
++)
6090 { Dsymbol
*s
= (Dsymbol
*)eo
->vars
->a
.data
[i
];
6091 FuncDeclaration
*f2
= s
->isFuncDeclaration();
6094 f2
= f2
->overloadResolve(loc
, NULL
, arguments
, 1);
6097 { TemplateDeclaration
*td
= s
->isTemplateDeclaration();
6099 f2
= td
->deduceFunctionTemplate(sc
, loc
, targsi
, NULL
, arguments
, 1);
6103 /* Error if match in more than one overload set,
6104 * even if one is a 'better' match than the other.
6106 ScopeDsymbol::multiplyDefined(loc
, f
, f2
);
6112 { /* No overload matches, just set f and rely on error
6113 * message being generated later.
6115 f
= (FuncDeclaration
*)eo
->vars
->a
.data
[0];
6117 e1
= new VarExp(loc
, f
);
6122 error("function expected before (), not '%s'", e1
->toChars());
6123 type
= Type::terror
;
6126 else if (t1
->ty
!= Tfunction
)
6128 if (t1
->ty
== Tdelegate
)
6129 { TypeDelegate
*td
= (TypeDelegate
*)t1
;
6130 assert(td
->next
->ty
== Tfunction
);
6131 tf
= (TypeFunction
*)(td
->next
);
6134 else if (t1
->ty
== Tpointer
&& ((TypePointer
*)t1
)->next
->ty
== Tfunction
)
6137 e
= new PtrExp(loc
, e1
);
6138 t1
= ((TypePointer
*)t1
)->next
;
6142 else if (e1
->op
== TOKtemplate
)
6144 TemplateExp
*te
= (TemplateExp
*)e1
;
6145 f
= te
->td
->deduceFunctionTemplate(sc
, loc
, targsi
, NULL
, arguments
);
6147 { type
= Type::terror
;
6150 if (f
->needThis() && hasThis(sc
))
6152 // Supply an implicit 'this', as in
6155 e1
= new DotTemplateExp(loc
, (new ThisExp(loc
))->semantic(sc
), te
->td
);
6159 e1
= new VarExp(loc
, f
);
6163 { error("function expected before (), not %s of type %s", e1
->toChars(), e1
->type
->toChars());
6164 type
= Type::terror
;
6168 else if (e1
->op
== TOKvar
)
6170 // Do overload resolution
6171 VarExp
*ve
= (VarExp
*)e1
;
6173 f
= ve
->var
->isFuncDeclaration();
6176 if (ve
->hasOverloads
)
6177 f
= f
->overloadResolve(loc
, NULL
, arguments
);
6178 checkDeprecated(sc
, f
);
6180 if (f
->needThis() && hasThis(sc
))
6182 // Supply an implicit 'this', as in
6185 e1
= new DotVarExp(loc
, new ThisExp(loc
), f
);
6189 accessCheck(loc
, sc
, NULL
, f
);
6192 // ve->hasOverloads = 0;
6196 assert(t1
->ty
== Tfunction
);
6197 tf
= (TypeFunction
*)(t1
);
6200 assert(tf
->ty
== Tfunction
);
6204 arguments
= new Expressions();
6205 functionArguments(loc
, sc
, tf
, arguments
);
6212 target_ptrdiff_t offset
= 0;
6213 TypeFunction
*tf
= (TypeFunction
*)f
->tintro
;
6215 if (tf
->next
->isBaseOf(t
, &offset
) && offset
)
6218 return castTo(sc
, t
);
6225 int CallExp::checkSideEffect(int flag
)
6230 int CallExp::canThrow()
6235 Expression
*CallExp::toLvalue(Scope
*sc
, Expression
*e
)
6237 if (type
->toBasetype()->ty
== Tstruct
)
6240 return Expression::toLvalue(sc
, e
);
6243 void CallExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6246 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6247 buf
->writeByte('(');
6248 argsToCBuffer(buf
, arguments
, hgs
);
6249 buf
->writeByte(')');
6253 /************************************************************/
6255 AddrExp::AddrExp(Loc loc
, Expression
*e
)
6256 : UnaExp(loc
, TOKaddress
, sizeof(AddrExp
), e
)
6260 Expression
*AddrExp::semantic(Scope
*sc
)
6263 printf("AddrExp::semantic('%s')\n", toChars());
6267 UnaExp::semantic(sc
);
6268 e1
= e1
->toLvalue(sc
, NULL
);
6271 error("cannot take address of %s", e1
->toChars());
6272 type
= Type::tint32
;
6275 type
= e1
->type
->pointerTo();
6277 // See if this should really be a delegate
6278 if (e1
->op
== TOKdotvar
)
6280 DotVarExp
*dve
= (DotVarExp
*)e1
;
6282 FuncDeclaration
*f
= dve
->var
->isFuncDeclaration();
6286 if (!dve
->hasOverloads
)
6287 f
->tookAddressOf
= 1;
6288 Expression
*e
= new DelegateExp(loc
, dve
->e1
, f
, dve
->hasOverloads
);
6289 e
= e
->semantic(sc
);
6293 else if (e1
->op
== TOKvar
)
6295 VarExp
*ve
= (VarExp
*)e1
;
6297 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
6298 if (v
&& !v
->canTakeAddressOf())
6299 error("cannot take address of %s", e1
->toChars());
6301 FuncDeclaration
*f
= ve
->var
->isFuncDeclaration();
6305 if (!ve
->hasOverloads
)
6306 f
->tookAddressOf
= 1;
6309 Expression
*e
= new DelegateExp(loc
, e1
, f
, ve
->hasOverloads
);
6310 e
= e
->semantic(sc
);
6313 if (f
->needThis() && hasThis(sc
))
6315 /* Should probably supply 'this' after overload resolution,
6318 Expression
*ethis
= new ThisExp(loc
);
6319 Expression
*e
= new DelegateExp(loc
, ethis
, f
, ve
->hasOverloads
);
6320 e
= e
->semantic(sc
);
6325 return optimize(WANTvalue
);
6330 /************************************************************/
6332 PtrExp::PtrExp(Loc loc
, Expression
*e
)
6333 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
6336 type
= ((TypePointer
*)e
->type
)->next
;
6339 PtrExp::PtrExp(Loc loc
, Expression
*e
, Type
*t
)
6340 : UnaExp(loc
, TOKstar
, sizeof(PtrExp
), e
)
6345 Expression
*PtrExp::semantic(Scope
*sc
)
6349 printf("PtrExp::semantic('%s')\n", toChars());
6353 UnaExp::semantic(sc
);
6354 e1
= resolveProperties(sc
, e1
);
6356 printf("PtrExp::semantic('%s')\n", toChars());
6357 Expression
*e
= op_overload(sc
);
6360 tb
= e1
->type
->toBasetype();
6364 type
= ((TypePointer
*)tb
)->next
;
6369 type
= ((TypeArray
*)tb
)->next
;
6370 e1
= e1
->castTo(sc
, type
->pointerTo());
6374 error("can only * a pointer, not a '%s'", e1
->type
->toChars());
6375 type
= Type::tint32
;
6383 Expression
*PtrExp::toLvalue(Scope
*sc
, Expression
*e
)
6386 tym
= tybasic(e1
->ET
->Tty
);
6387 if (!(tyscalar(tym
) ||
6389 tym
== TYarray
&& e
->Eoper
== TOKaddr
))
6390 synerr(EM_lvalue
); // lvalue expected
6395 Expression
*PtrExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6397 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
6399 if (e1
->op
== TOKsymoff
)
6400 { SymOffExp
*se
= (SymOffExp
*)e1
;
6401 se
->var
->checkModify(loc
, sc
, type
);
6402 //return toLvalue(sc, e);
6405 return Expression::modifiableLvalue(sc
, e
);
6409 void PtrExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6411 buf
->writeByte('*');
6412 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6415 /************************************************************/
6417 NegExp::NegExp(Loc loc
, Expression
*e
)
6418 : UnaExp(loc
, TOKneg
, sizeof(NegExp
), e
)
6422 Expression
*NegExp::semantic(Scope
*sc
)
6426 printf("NegExp::semantic('%s')\n", toChars());
6430 UnaExp::semantic(sc
);
6431 e1
= resolveProperties(sc
, e1
);
6432 e
= op_overload(sc
);
6437 e1
->checkArithmetic();
6443 /************************************************************/
6445 UAddExp::UAddExp(Loc loc
, Expression
*e
)
6446 : UnaExp(loc
, TOKuadd
, sizeof(UAddExp
), e
)
6450 Expression
*UAddExp::semantic(Scope
*sc
)
6454 printf("UAddExp::semantic('%s')\n", toChars());
6457 UnaExp::semantic(sc
);
6458 e1
= resolveProperties(sc
, e1
);
6459 e
= op_overload(sc
);
6463 e1
->checkArithmetic();
6467 /************************************************************/
6469 ComExp::ComExp(Loc loc
, Expression
*e
)
6470 : UnaExp(loc
, TOKtilde
, sizeof(ComExp
), e
)
6474 Expression
*ComExp::semantic(Scope
*sc
)
6479 UnaExp::semantic(sc
);
6480 e1
= resolveProperties(sc
, e1
);
6481 e
= op_overload(sc
);
6486 e1
= e1
->checkIntegral();
6492 /************************************************************/
6494 NotExp::NotExp(Loc loc
, Expression
*e
)
6495 : UnaExp(loc
, TOKnot
, sizeof(NotExp
), e
)
6499 Expression
*NotExp::semantic(Scope
*sc
)
6501 UnaExp::semantic(sc
);
6502 e1
= resolveProperties(sc
, e1
);
6503 e1
= e1
->checkToBoolean();
6504 type
= Type::tboolean
;
6515 /************************************************************/
6517 BoolExp::BoolExp(Loc loc
, Expression
*e
, Type
*t
)
6518 : UnaExp(loc
, TOKtobool
, sizeof(BoolExp
), e
)
6523 Expression
*BoolExp::semantic(Scope
*sc
)
6525 UnaExp::semantic(sc
);
6526 e1
= resolveProperties(sc
, e1
);
6527 e1
= e1
->checkToBoolean();
6528 type
= Type::tboolean
;
6532 int BoolExp::isBit()
6537 /************************************************************/
6539 DeleteExp::DeleteExp(Loc loc
, Expression
*e
)
6540 : UnaExp(loc
, TOKdelete
, sizeof(DeleteExp
), e
)
6544 Expression
*DeleteExp::semantic(Scope
*sc
)
6548 UnaExp::semantic(sc
);
6549 e1
= resolveProperties(sc
, e1
);
6550 e1
= e1
->toLvalue(sc
, NULL
);
6553 tb
= e1
->type
->toBasetype();
6556 { TypeClass
*tc
= (TypeClass
*)tb
;
6557 ClassDeclaration
*cd
= tc
->sym
;
6559 if (cd
->isCOMinterface())
6560 { /* Because COM classes are deleted by IUnknown.Release()
6562 error("cannot delete instance of COM interface %s", cd
->toChars());
6567 tb
= ((TypePointer
*)tb
)->next
->toBasetype();
6568 if (tb
->ty
== Tstruct
)
6570 TypeStruct
*ts
= (TypeStruct
*)tb
;
6571 StructDeclaration
*sd
= ts
->sym
;
6572 FuncDeclaration
*f
= sd
->aggDelete
;
6573 FuncDeclaration
*fd
= sd
->dtor
;
6579 * ea = copy e1 to a tmp to do side effects only once
6580 * eb = call destructor
6581 * ec = call deallocator
6583 Expression
*ea
= NULL
;
6584 Expression
*eb
= NULL
;
6585 Expression
*ec
= NULL
;
6589 { Identifier
*id
= Lexer::idPool("__tmp");
6590 v
= new VarDeclaration(loc
, e1
->type
, id
, new ExpInitializer(loc
, e1
));
6592 v
->parent
= sc
->parent
;
6593 ea
= new DeclarationExp(loc
, v
);
6598 { Expression
*e
= ea
? new VarExp(loc
, v
) : e1
;
6599 e
= new DotVarExp(0, e
, fd
, 0);
6600 eb
= new CallExp(loc
, e
);
6601 eb
= eb
->semantic(sc
);
6606 Type
*tpv
= Type::tvoid
->pointerTo();
6607 Expression
*e
= ea
? new VarExp(loc
, v
) : e1
->castTo(sc
, tpv
);
6608 e
= new CallExp(loc
, new VarExp(loc
, f
), e
);
6609 ec
= e
->semantic(sc
);
6611 ea
= combine(ea
, eb
);
6612 ea
= combine(ea
, ec
);
6619 /* BUG: look for deleting arrays of structs with dtors.
6624 if (e1
->op
== TOKindex
)
6626 IndexExp
*ae
= (IndexExp
*)(e1
);
6627 Type
*tb1
= ae
->e1
->type
->toBasetype();
6628 if (tb1
->ty
== Taarray
)
6631 error("cannot delete type %s", e1
->type
->toChars());
6635 if (e1
->op
== TOKindex
)
6637 IndexExp
*ae
= (IndexExp
*)(e1
);
6638 Type
*tb1
= ae
->e1
->type
->toBasetype();
6639 if (tb1
->ty
== Taarray
)
6640 { if (!global
.params
.useDeprecated
)
6641 error("delete aa[key] deprecated, use aa.remove(key)");
6648 int DeleteExp::checkSideEffect(int flag
)
6653 Expression
*DeleteExp::checkToBoolean()
6655 error("delete does not give a boolean result");
6659 void DeleteExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6661 buf
->writestring("delete ");
6662 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6665 /************************************************************/
6667 CastExp::CastExp(Loc loc
, Expression
*e
, Type
*t
)
6668 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
6671 this->tok
= TOKreserved
;
6674 /* For cast(const) and cast(invariant)
6676 CastExp::CastExp(Loc loc
, Expression
*e
, enum TOK tok
)
6677 : UnaExp(loc
, TOKcast
, sizeof(CastExp
), e
)
6683 Expression
*CastExp::syntaxCopy()
6685 return to
? new CastExp(loc
, e1
->syntaxCopy(), to
->syntaxCopy())
6686 : new CastExp(loc
, e1
->syntaxCopy(), tok
);
6690 Expression
*CastExp::semantic(Scope
*sc
)
6696 printf("CastExp::semantic('%s')\n", toChars());
6699 //static int x; assert(++x < 10);
6703 UnaExp::semantic(sc
);
6704 if (e1
->type
) // if not a tuple
6706 e1
= resolveProperties(sc
, e1
);
6708 /* Handle cast(const) and cast(invariant)
6711 { if (tok
== TOKconst
)
6712 to
= e1
->type
->constOf();
6713 else if (tok
== TOKinvariant
)
6714 to
= e1
->type
->invariantOf();
6719 to
= to
->semantic(loc
, sc
);
6721 e
= op_overload(sc
);
6724 return e
->implicitCastTo(sc
, to
);
6727 Type
*tob
= to
->toBasetype();
6728 if (tob
->ty
== Tstruct
&&
6729 !tob
->equals(e1
->type
->toBasetype()) &&
6730 ((TypeStruct
*)to
)->sym
->search(0, Id::call
, 0)
6739 // Rewrite as to.call(e1)
6740 e
= new TypeExp(loc
, to
);
6741 e
= new DotIdExp(loc
, e
, Id::call
);
6742 e
= new CallExp(loc
, e
, e1
);
6743 e
= e
->semantic(sc
);
6748 { error("cannot cast tuple");
6751 if (sc
->fromDcode
|| to
->ty
!= Tclass
)
6752 e
= e1
->castTo(sc
, to
);
6755 // Result is null if "e1" is not an instance of "to"
6756 e
= e1
->castTo(sc
, to
->maybe(true));
6761 int CastExp::checkSideEffect(int flag
)
6765 * cast(classtype)func()
6767 if (!to
->equals(Type::tvoid
) &&
6768 !(to
->ty
== Tclass
&& e1
->op
== TOKcall
&& e1
->type
->ty
== Tclass
))
6769 return Expression::checkSideEffect(flag
);
6773 void CastExp::checkEscape()
6774 { Type
*tb
= type
->toBasetype();
6775 if (tb
->ty
== Tarray
&& e1
->op
== TOKvar
&&
6776 e1
->type
->toBasetype()->ty
== Tsarray
)
6777 { VarExp
*ve
= (VarExp
*)e1
;
6778 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
6781 if (!v
->isDataseg() && !v
->isParameter())
6782 error("escaping reference to local %s", v
->toChars());
6787 void CastExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
6789 buf
->writestring("cast(");
6791 to
->toCBuffer(buf
, NULL
, hgs
);
6793 buf
->writestring(Token::tochars
[tok
]);
6794 buf
->writeByte(')');
6795 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
6799 /************************************************************/
6801 SliceExp::SliceExp(Loc loc
, Expression
*e1
, Expression
*lwr
, Expression
*upr
)
6802 : UnaExp(loc
, TOKslice
, sizeof(SliceExp
), e1
)
6809 Expression
*SliceExp::syntaxCopy()
6811 Expression
*lwr
= NULL
;
6813 lwr
= this->lwr
->syntaxCopy();
6815 Expression
*upr
= NULL
;
6817 upr
= this->upr
->syntaxCopy();
6819 return new SliceExp(loc
, e1
->syntaxCopy(), lwr
, upr
);
6822 Expression
*SliceExp::semantic(Scope
*sc
)
6824 AggregateDeclaration
*ad
;
6825 //FuncDeclaration *fd;
6829 printf("SliceExp::semantic('%s')\n", toChars());
6834 UnaExp::semantic(sc
);
6835 e1
= resolveProperties(sc
, e1
);
6839 Type
*t
= e1
->type
->toBasetype();
6840 if (t
->ty
== Tpointer
)
6843 error("need upper and lower bound to slice pointer");
6845 else if (t
->ty
== Tarray
)
6848 else if (t
->ty
== Tsarray
)
6851 else if (t
->ty
== Tclass
)
6853 ad
= ((TypeClass
*)t
)->sym
;
6856 else if (t
->ty
== Tstruct
)
6858 ad
= ((TypeStruct
*)t
)->sym
;
6861 if (search_function(ad
, Id::slice
))
6863 // Rewrite as e1.slice(lwr, upr)
6864 e
= new DotIdExp(loc
, e1
, Id::slice
);
6869 e
= new CallExp(loc
, e
, lwr
, upr
);
6873 e
= new CallExp(loc
, e
);
6875 e
= e
->semantic(sc
);
6880 else if (t
->ty
== Ttuple
)
6885 { error("need upper and lower bound to slice tuple");
6892 if (t
->ty
== Tsarray
|| t
->ty
== Tarray
|| t
->ty
== Ttuple
)
6894 sym
= new ArrayScopeSymbol(sc
, this);
6896 sym
->parent
= sc
->scopesym
;
6901 { lwr
= lwr
->semantic(sc
);
6902 lwr
= resolveProperties(sc
, lwr
);
6903 lwr
= lwr
->implicitCastTo(sc
, Type::tsize_t
);
6906 { upr
= upr
->semantic(sc
);
6907 upr
= resolveProperties(sc
, upr
);
6908 upr
= upr
->implicitCastTo(sc
, Type::tsize_t
);
6911 if (t
->ty
== Tsarray
|| t
->ty
== Tarray
|| t
->ty
== Ttuple
)
6914 if (t
->ty
== Ttuple
)
6916 lwr
= lwr
->optimize(WANTvalue
);
6917 upr
= upr
->optimize(WANTvalue
);
6918 uinteger_t i1
= lwr
->toUInteger();
6919 uinteger_t i2
= upr
->toUInteger();
6925 if (e1
->op
== TOKtuple
) // slicing an expression tuple
6926 { te
= (TupleExp
*)e1
;
6927 length
= te
->exps
->dim
;
6929 else if (e1
->op
== TOKtype
) // slicing a type tuple
6930 { tup
= (TypeTuple
*)t
;
6931 length
= Argument::dim(tup
->arguments
);
6936 if (i1
<= i2
&& i2
<= length
)
6937 { size_t j1
= (size_t) i1
;
6938 size_t j2
= (size_t) i2
;
6940 if (e1
->op
== TOKtuple
)
6941 { Expressions
*exps
= new Expressions
;
6942 exps
->setDim(j2
- j1
);
6943 for (size_t i
= 0; i
< j2
- j1
; i
++)
6944 { Expression
*e
= (Expression
*)te
->exps
->data
[j1
+ i
];
6945 exps
->data
[i
] = (void *)e
;
6947 e
= new TupleExp(loc
, exps
);
6950 { Arguments
*args
= new Arguments
;
6951 args
->reserve(j2
- j1
);
6952 for (size_t i
= j1
; i
< j2
; i
++)
6953 { Argument
*arg
= Argument::getNth(tup
->arguments
, i
);
6956 e
= new TypeExp(e1
->loc
, new TypeTuple(args
));
6958 e
= e
->semantic(sc
);
6962 error("string slice [%"PRIuMAX
" .. %"PRIuMAX
"] is out of bounds", i1
, i2
);
6968 type
= t
->nextOf()->arrayOf();
6977 error("%s cannot be sliced with []", s
);
6978 type
= Type::terror
;
6982 void SliceExp::checkEscape()
6987 Expression
*SliceExp::toLvalue(Scope
*sc
, Expression
*e
)
6992 Expression
*SliceExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
6994 error("slice expression %s is not a modifiable lvalue", toChars());
6998 void SliceExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7000 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
7001 buf
->writeByte('[');
7005 expToCBuffer(buf
, hgs
, lwr
, PREC_assign
);
7007 buf
->writeByte('0');
7008 buf
->writestring("..");
7010 expToCBuffer(buf
, hgs
, upr
, PREC_assign
);
7012 buf
->writestring("length"); // BUG: should be array.length
7014 buf
->writeByte(']');
7017 /********************** ArrayLength **************************************/
7019 ArrayLengthExp::ArrayLengthExp(Loc loc
, Expression
*e1
)
7020 : UnaExp(loc
, TOKarraylength
, sizeof(ArrayLengthExp
), e1
)
7024 Expression
*ArrayLengthExp::semantic(Scope
*sc
)
7028 printf("ArrayLengthExp::semantic('%s')\n", toChars());
7032 UnaExp::semantic(sc
);
7033 e1
= resolveProperties(sc
, e1
);
7035 type
= Type::tsize_t
;
7040 void ArrayLengthExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7042 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
7043 buf
->writestring(".length");
7046 /*********************** ArrayExp *************************************/
7048 // e1 [ i1, i2, i3, ... ]
7050 ArrayExp::ArrayExp(Loc loc
, Expression
*e1
, Expressions
*args
)
7051 : UnaExp(loc
, TOKarray
, sizeof(ArrayExp
), e1
)
7056 Expression
*ArrayExp::syntaxCopy()
7058 return new ArrayExp(loc
, e1
->syntaxCopy(), arraySyntaxCopy(arguments
));
7061 Expression
*ArrayExp::semantic(Scope
*sc
)
7066 printf("ArrayExp::semantic('%s')\n", toChars());
7068 UnaExp::semantic(sc
);
7069 e1
= resolveProperties(sc
, e1
);
7071 t1
= e1
->type
->toBasetype();
7072 if (t1
->ty
!= Tclass
&& t1
->ty
!= Tstruct
)
7073 { // Convert to IndexExp
7074 if (arguments
->dim
!= 1)
7075 error("only one index allowed to index %s", t1
->toChars());
7076 e
= new IndexExp(loc
, e1
, (Expression
*)arguments
->data
[0]);
7077 return e
->semantic(sc
);
7080 // Run semantic() on each argument
7081 for (size_t i
= 0; i
< arguments
->dim
; i
++)
7082 { e
= (Expression
*)arguments
->data
[i
];
7084 e
= e
->semantic(sc
);
7086 error("%s has no value", e
->toChars());
7087 arguments
->data
[i
] = (void *)e
;
7090 expandTuples(arguments
);
7091 assert(arguments
&& arguments
->dim
);
7093 e
= op_overload(sc
);
7095 { error("no [] operator overload for type %s", e1
->type
->toChars());
7102 Expression
*ArrayExp::toLvalue(Scope
*sc
, Expression
*e
)
7104 if (type
&& type
->toBasetype()->ty
== Tvoid
)
7105 error("voids have no value");
7110 void ArrayExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7113 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
7114 buf
->writeByte('[');
7115 argsToCBuffer(buf
, arguments
, hgs
);
7116 buf
->writeByte(']');
7119 /************************* DotExp ***********************************/
7121 DotExp::DotExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7122 : BinExp(loc
, TOKdotexp
, sizeof(DotExp
), e1
, e2
)
7126 Expression
*DotExp::semantic(Scope
*sc
)
7129 printf("DotExp::semantic('%s')\n", toChars());
7130 if (type
) printf("\ttype = %s\n", type
->toChars());
7132 e1
= e1
->semantic(sc
);
7133 e2
= e2
->semantic(sc
);
7134 if (e2
->op
== TOKimport
)
7136 ScopeExp
*se
= (ScopeExp
*)e2
;
7137 TemplateDeclaration
*td
= se
->sds
->isTemplateDeclaration();
7139 { Expression
*e
= new DotTemplateExp(loc
, e1
, td
);
7140 e
= e
->semantic(sc
);
7150 /************************* CommaExp ***********************************/
7152 CommaExp::CommaExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7153 : BinExp(loc
, TOKcomma
, sizeof(CommaExp
), e1
, e2
)
7157 Expression
*CommaExp::semantic(Scope
*sc
)
7160 { BinExp::semanticp(sc
);
7166 void CommaExp::checkEscape()
7171 Expression
*CommaExp::toLvalue(Scope
*sc
, Expression
*e
)
7173 e2
= e2
->toLvalue(sc
, NULL
);
7177 Expression
*CommaExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
7179 e2
= e2
->modifiableLvalue(sc
, e
);
7183 int CommaExp::isBool(int result
)
7185 return e2
->isBool(result
);
7188 int CommaExp::checkSideEffect(int flag
)
7191 return e1
->checkSideEffect(2) || e2
->checkSideEffect(2);
7194 // Don't check e1 until we cast(void) the a,b code generation
7195 return e2
->checkSideEffect(flag
);
7199 /************************** IndexExp **********************************/
7203 IndexExp::IndexExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7204 : BinExp(loc
, TOKindex
, sizeof(IndexExp
), e1
, e2
)
7206 //printf("IndexExp::IndexExp('%s')\n", toChars());
7208 modifiable
= 0; // assume it is an rvalue
7211 Expression
*IndexExp::semantic(Scope
*sc
)
7219 printf("IndexExp::semantic('%s')\n", toChars());
7224 e1
= e1
->semantic(sc
);
7225 assert(e1
->type
); // semantic() should already be run on it
7228 if (e1
->type
->ty
== Tmaybe
)
7229 error("Attempt to index %s of type %s, which may be null", e1
->toChars(), e1
->type
->toChars());
7231 // Note that unlike C we do not implement the int[ptr]
7233 t1
= e1
->type
->toBasetype();
7235 if (t1
->ty
== Tsarray
|| t1
->ty
== Tarray
|| t1
->ty
== Ttuple
)
7236 { // Create scope for 'length' variable
7237 sym
= new ArrayScopeSymbol(sc
, this);
7239 sym
->parent
= sc
->scopesym
;
7243 e2
= e2
->semantic(sc
);
7246 error("%s has no value", e2
->toChars());
7247 e2
->type
= Type::terror
;
7249 e2
= resolveProperties(sc
, e2
);
7251 if (t1
->ty
== Tsarray
|| t1
->ty
== Tarray
|| t1
->ty
== Ttuple
)
7258 e2
= e2
->implicitCastTo(sc
, Type::tsize_t
);
7259 e
->type
= ((TypeNext
*)t1
)->next
;
7264 e2
= e2
->implicitCastTo(sc
, Type::tsize_t
);
7266 TypeSArray
*tsa
= (TypeSArray
*)t1
;
7268 #if 0 // Don't do now, because it might be short-circuit evaluated
7269 // Do compile time array bounds checking if possible
7270 e2
= e2
->optimize(WANTvalue
);
7271 if (e2
->op
== TOKint64
)
7273 integer_t index
= e2
->toInteger();
7274 integer_t length
= tsa
->dim
->toInteger();
7275 if (index
< 0 || index
>= length
)
7276 error("array index [%lld] is outside array bounds [0 .. %lld]",
7280 e
->type
= t1
->nextOf();
7285 { TypeAArray
*taa
= (TypeAArray
*)t1
;
7287 e2
= e2
->implicitCastTo(sc
, taa
->index
); // type checking
7294 e2
= e2
->implicitCastTo(sc
, Type::tsize_t
);
7295 e2
= e2
->optimize(WANTvalue
| WANTinterpret
);
7296 uinteger_t index
= e2
->toUInteger();
7301 if (e1
->op
== TOKtuple
)
7302 { te
= (TupleExp
*)e1
;
7303 length
= te
->exps
->dim
;
7305 else if (e1
->op
== TOKtype
)
7307 tup
= (TypeTuple
*)t1
;
7308 length
= Argument::dim(tup
->arguments
);
7316 if (e1
->op
== TOKtuple
)
7317 e
= (Expression
*)te
->exps
->data
[(size_t)index
];
7319 e
= new TypeExp(e1
->loc
, Argument::getNth(tup
->arguments
, (size_t)index
)->type
);
7323 error("array index [%"PRIuMAX
"] is outside array bounds [0 .. %"PRIuSIZE
"]",
7331 error("%s must be an array or pointer type, not %s",
7332 e1
->toChars(), e1
->type
->toChars());
7333 type
= Type::tint32
;
7339 Expression
*IndexExp::toLvalue(Scope
*sc
, Expression
*e
)
7341 // if (type && type->toBasetype()->ty == Tvoid)
7342 // error("voids have no value");
7346 Expression
*IndexExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
7348 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
7350 if (e1
->op
== TOKstring
)
7351 error("string literals are immutable");
7352 if (type
&& !type
->isMutable())
7353 error("%s isn't mutable", e
->toChars());
7354 if (e1
->type
->toBasetype()->ty
== Taarray
)
7355 e1
= e1
->modifiableLvalue(sc
, e1
);
7356 return toLvalue(sc
, e
);
7359 void IndexExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7361 expToCBuffer(buf
, hgs
, e1
, PREC_primary
);
7362 buf
->writeByte('[');
7363 expToCBuffer(buf
, hgs
, e2
, PREC_assign
);
7364 buf
->writeByte(']');
7368 /************************* PostExp ***********************************/
7370 PostExp::PostExp(enum TOK op
, Loc loc
, Expression
*e
)
7371 : BinExp(loc
, op
, sizeof(PostExp
), e
,
7372 new IntegerExp(loc
, 1, Type::tint32
))
7376 Expression
*PostExp::semantic(Scope
*sc
)
7377 { Expression
*e
= this;
7381 BinExp::semantic(sc
);
7382 e2
= resolveProperties(sc
, e2
);
7384 e
= op_overload(sc
);
7389 e1
= e1
->modifiableLvalue(sc
, e1
);
7392 if (e1
->type
->ty
== Tpointer
)
7393 e
= scaleFactor(sc
);
7395 e2
= e2
->castTo(sc
, e1
->type
);
7401 void PostExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
7403 expToCBuffer(buf
, hgs
, e1
, precedence
[op
]);
7404 buf
->writestring((op
== TOKplusplus
) ? (char *)"++" : (char *)"--");
7407 /************************************************************/
7409 /* op can be TOKassign, TOKconstruct, or TOKblit */
7411 AssignExp::AssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7412 : BinExp(loc
, TOKassign
, sizeof(AssignExp
), e1
, e2
)
7417 Expression
*AssignExp::semantic(Scope
*sc
)
7419 Expression
*e1old
= e1
;
7422 printf("AssignExp::semantic('%s')\n", toChars());
7424 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
7425 //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
7430 if (e2
->op
== TOKcomma
)
7431 { /* Rewrite to get rid of the comma from rvalue
7433 AssignExp
*ea
= new AssignExp(loc
, e1
, ((CommaExp
*)e2
)->e2
);
7435 Expression
*e
= new CommaExp(loc
, ((CommaExp
*)e2
)->e1
, ea
);
7436 return e
->semantic(sc
);
7439 /* Look for operator overloading of a[i]=value.
7440 * Do it before semantic() otherwise the a[i] will have been
7441 * converted to a.opIndex() already.
7443 if (e1
->op
== TOKarray
)
7445 ArrayExp
*ae
= (ArrayExp
*)e1
;
7446 AggregateDeclaration
*ad
;
7447 Identifier
*id
= Id::index
;
7449 ae
->e1
= ae
->e1
->semantic(sc
);
7450 Type
*t1
= ae
->e1
->type
->toBasetype();
7451 if (t1
->ty
== Tstruct
)
7453 ad
= ((TypeStruct
*)t1
)->sym
;
7456 else if (t1
->ty
== Tclass
)
7458 ad
= ((TypeClass
*)t1
)->sym
;
7460 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
7461 if (search_function(ad
, Id::indexass
))
7462 { Expression
*e
= new DotIdExp(loc
, ae
->e1
, Id::indexass
);
7463 Expressions
*a
= (Expressions
*)ae
->arguments
->copy();
7466 e
= new CallExp(loc
, e
, a
);
7467 e
= e
->semantic(sc
);
7472 // Rewrite (a[i] = value) to (a.opIndex(i, value))
7473 if (search_function(ad
, id
))
7474 { Expression
*e
= new DotIdExp(loc
, ae
->e1
, id
);
7476 if (1 || !global
.params
.useDeprecated
)
7477 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
7479 e
= new CallExp(loc
, e
, (Expression
*)ae
->arguments
->data
[0], e2
);
7480 e
= e
->semantic(sc
);
7486 /* Look for operator overloading of a[i..j]=value.
7487 * Do it before semantic() otherwise the a[i..j] will have been
7488 * converted to a.opSlice() already.
7490 if (e1
->op
== TOKslice
)
7492 SliceExp
*ae
= (SliceExp
*)e1
;
7493 AggregateDeclaration
*ad
;
7494 Identifier
*id
= Id::index
;
7496 ae
->e1
= ae
->e1
->semantic(sc
);
7497 ae
->e1
= resolveProperties(sc
, ae
->e1
);
7498 t1
= ae
->e1
->type
->toBasetype();
7499 if (t1
->ty
== Tstruct
)
7501 ad
= ((TypeStruct
*)t1
)->sym
;
7504 else if (t1
->ty
== Tclass
)
7506 ad
= ((TypeClass
*)t1
)->sym
;
7508 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
7509 if (search_function(ad
, Id::sliceass
))
7510 { Expression
*e
= new DotIdExp(loc
, ae
->e1
, Id::sliceass
);
7511 Expressions
*a
= new Expressions();
7521 e
= new CallExp(loc
, e
, a
);
7522 e
= e
->semantic(sc
);
7528 BinExp::semantic(sc
);
7529 e2
= resolveProperties(sc
, e2
);
7532 /* Rewrite tuple assignment as a tuple of assignments.
7534 if (e1
->op
== TOKtuple
&& e2
->op
== TOKtuple
)
7535 { TupleExp
*tup1
= (TupleExp
*)e1
;
7536 TupleExp
*tup2
= (TupleExp
*)e2
;
7537 size_t dim
= tup1
->exps
->dim
;
7538 if (dim
!= tup2
->exps
->dim
)
7540 error("mismatched tuple lengths, %d and %d", (int)dim
, (int)tup2
->exps
->dim
);
7543 { Expressions
*exps
= new Expressions
;
7546 for (int i
= 0; i
< dim
; i
++)
7547 { Expression
*ex1
= (Expression
*)tup1
->exps
->data
[i
];
7548 Expression
*ex2
= (Expression
*)tup2
->exps
->data
[i
];
7549 exps
->data
[i
] = (void *) new AssignExp(loc
, ex1
, ex2
);
7551 Expression
*e
= new TupleExp(loc
, exps
);
7552 e
= e
->semantic(sc
);
7557 Type
*t1
= e1
->type
->toBasetype();
7559 if (t1
->ty
== Tfunction
)
7560 { // Rewrite f=value to f(value)
7563 e
= new CallExp(loc
, e1
, e2
);
7564 e
= e
->semantic(sc
);
7568 /* If it is an assignment from a 'foreign' type,
7569 * check for operator overloading.
7571 if (t1
->ty
== Tstruct
)
7573 StructDeclaration
*sd
= ((TypeStruct
*)t1
)->sym
;
7574 if (op
== TOKassign
)
7576 Expression
*e
= op_overload(sc
);
7580 else if (op
== TOKconstruct
)
7581 { Type
*t2
= e2
->type
->toBasetype();
7582 if (t2
->ty
== Tstruct
&&
7583 sd
== ((TypeStruct
*)t2
)->sym
&&
7585 { /* We have a copy constructor for this
7587 if (e2
->op
== TOKvar
|| e2
->op
== TOKstar
)
7591 Expression
*e
= new DotVarExp(loc
, e1
, sd
->cpctor
, 0);
7592 e
= new CallExp(loc
, e
, e2
);
7593 return e
->semantic(sc
);
7595 else if (e2
->op
== TOKquestion
)
7597 * a ? e1 = b : e1 = c;
7599 CondExp
*ec
= (CondExp
*)e2
;
7600 AssignExp
*ea1
= new AssignExp(ec
->e1
->loc
, e1
, ec
->e1
);
7602 AssignExp
*ea2
= new AssignExp(ec
->e1
->loc
, e1
, ec
->e2
);
7604 Expression
*e
= new CondExp(loc
, ec
->econd
, ea1
, ea2
);
7605 return e
->semantic(sc
);
7610 else if (t1
->ty
== Tclass
)
7611 { // Disallow assignment operator overloads for same type
7612 if (!e2
->type
->implicitConvTo(e1
->type
))
7614 Expression
*e
= op_overload(sc
);
7620 if (t1
->ty
== Tsarray
)
7622 Expression
*e
= new SliceExp(e1
->loc
, e1
, NULL
, NULL
);
7623 e1
= e
->semantic(sc
);
7624 t1
= e1
->type
->toBasetype();
7629 if (e1
->op
== TOKarraylength
)
7631 // e1 is not an lvalue, but we let code generator handle it
7632 ArrayLengthExp
*ale
= (ArrayLengthExp
*)e1
;
7634 ale
->e1
= ale
->e1
->modifiableLvalue(sc
, e1
);
7636 else if (e1
->op
== TOKslice
)
7638 Type
*tn
= e1
->type
->nextOf();
7639 if (tn
&& !tn
->isMutable() && op
!= TOKconstruct
)
7640 error("slice %s is not mutable", e1
->toChars());
7643 { // Try to do a decent error message with the expression
7644 // before it got constant folded
7645 if (e1
->op
!= TOKvar
)
7646 e1
= e1
->optimize(WANTvalue
);
7647 if (op
!= TOKconstruct
)
7648 e1
= e1
->modifiableLvalue(sc
, e1old
);
7651 Type
*t2
= e2
->type
;
7652 if (e1
->op
== TOKslice
&&
7654 e2
->implicitConvTo(t1
->nextOf())
7657 ismemset
= 1; // make it easy for back end to tell what this is
7658 e2
= e2
->implicitCastTo(sc
, t1
->nextOf());
7660 else if (t1
->ty
== Tsarray
)
7662 /* Should have already converted e1 => e1[]
7665 //error("cannot assign to static array %s", e1->toChars());
7667 else if (e1
->op
== TOKslice
)
7669 e2
= e2
->implicitCastTo(sc
, e1
->type
->constOf());
7673 e2
= e2
->implicitCastTo(sc
, e1
->type
);
7680 Expression
*AssignExp::checkToBoolean()
7684 // are usually mistakes.
7686 error("'=' does not give a boolean result");
7690 /************************************************************/
7692 /* Allow pointer arithmetic on e1? */
7693 static bool allowPtrArith(Scope
*sc
, Expression
*e1
)
7695 if (e1
->type
->ty
== Tpointer
)
7697 else if (e1
->type
->ty
== Tmaybe
&& e1
->type
->nextOf()->ty
== Tpointer
)
7700 e1
->error("Can't do pointer arithmetic on pointer ('%s') that could be null",
7707 AddAssignExp::AddAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7708 : BinExp(loc
, TOKaddass
, sizeof(AddAssignExp
), e1
, e2
)
7712 Expression
*AddAssignExp::semantic(Scope
*sc
)
7718 BinExp::semantic(sc
);
7719 e2
= resolveProperties(sc
, e2
);
7721 e
= op_overload(sc
);
7725 e1
= e1
->modifiableLvalue(sc
, e1
);
7727 Type
*tb1
= e1
->type
->toBasetype();
7728 Type
*tb2
= e2
->type
->toBasetype();
7730 if ((tb1
->ty
== Tarray
|| tb1
->ty
== Tsarray
) &&
7731 (tb2
->ty
== Tarray
|| tb2
->ty
== Tsarray
) &&
7732 tb1
->nextOf()->equals(tb2
->nextOf())
7742 if (allowPtrArith(sc
, e1
) && tb2
->isintegral())
7743 e
= scaleFactor(sc
);
7744 else if (tb1
->ty
== Tbit
|| tb1
->ty
== Tbool
)
7747 // Need to rethink this
7748 if (e1
->op
!= TOKvar
)
7749 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
7754 Identifier
*id
= Lexer::uniqueId("__name");
7756 v
= new VarDeclaration(loc
, tb1
->pointerTo(), id
, NULL
);
7760 v
->parent
= sc
->func
;
7762 ea
= new AddrExp(loc
, e1
);
7763 ea
= new AssignExp(loc
, new VarExp(loc
, v
), ea
);
7765 ex
= new VarExp(loc
, v
);
7766 ex
= new PtrExp(loc
, ex
);
7767 e
= new AddExp(loc
, ex
, e2
);
7768 e
= new CastExp(loc
, e
, e1
->type
);
7769 e
= new AssignExp(loc
, ex
->syntaxCopy(), e
);
7771 e
= new CommaExp(loc
, ea
, e
);
7775 { // Rewrite e1+=e2 to e1=e1+e2
7776 // BUG: doesn't account for side effects in e1
7777 // BUG: other assignment operators for bits aren't handled at all
7778 e
= new AddExp(loc
, e1
, e2
);
7779 e
= new CastExp(loc
, e
, e1
->type
);
7780 e
= new AssignExp(loc
, e1
->syntaxCopy(), e
);
7782 e
= e
->semantic(sc
);
7788 e1
->checkArithmetic();
7789 e2
->checkArithmetic();
7790 if (type
->isreal() || type
->isimaginary())
7792 assert(global
.errors
|| e2
->type
->isfloating());
7793 e2
= e2
->castTo(sc
, e1
->type
);
7801 /************************************************************/
7803 MinAssignExp::MinAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7804 : BinExp(loc
, TOKminass
, sizeof(MinAssignExp
), e1
, e2
)
7808 Expression
*MinAssignExp::semantic(Scope
*sc
)
7814 BinExp::semantic(sc
);
7815 e2
= resolveProperties(sc
, e2
);
7817 e
= op_overload(sc
);
7821 e1
= e1
->modifiableLvalue(sc
, e1
);
7825 if (allowPtrArith(sc
, e1
) && e2
->type
->isintegral())
7826 e
= scaleFactor(sc
);
7829 e1
= e1
->checkArithmetic();
7830 e2
= e2
->checkArithmetic();
7833 if (type
->isreal() || type
->isimaginary())
7835 assert(e2
->type
->isfloating());
7836 e2
= e2
->castTo(sc
, e1
->type
);
7843 /************************************************************/
7845 CatAssignExp::CatAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7846 : BinExp(loc
, TOKcatass
, sizeof(CatAssignExp
), e1
, e2
)
7850 Expression
*CatAssignExp::semantic(Scope
*sc
)
7853 BinExp::semantic(sc
);
7854 e2
= resolveProperties(sc
, e2
);
7856 e
= op_overload(sc
);
7860 if (e1
->op
== TOKslice
)
7861 { SliceExp
*se
= (SliceExp
*)e1
;
7863 if (se
->e1
->type
->toBasetype()->ty
== Tsarray
)
7864 error("cannot append to static array %s", se
->e1
->type
->toChars());
7867 e1
= e1
->modifiableLvalue(sc
, e1
);
7869 Type
*tb1
= e1
->type
->toBasetype();
7870 Type
*tb2
= e2
->type
->toBasetype();
7874 if ((tb1
->ty
== Tarray
) &&
7875 (tb2
->ty
== Tarray
|| tb2
->ty
== Tsarray
) &&
7876 (e2
->implicitConvTo(e1
->type
) ||
7877 tb2
->nextOf()->implicitConvTo(tb1
->nextOf()))
7880 e2
= e2
->castTo(sc
, e1
->type
);
7884 else if ((tb1
->ty
== Tarray
) &&
7885 e2
->implicitConvTo(tb1
->nextOf())
7888 e2
= e2
->castTo(sc
, tb1
->nextOf());
7894 error("cannot append type %s to type %s", tb2
->toChars(), tb1
->toChars());
7895 type
= Type::tint32
;
7901 /************************************************************/
7903 MulAssignExp::MulAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7904 : BinExp(loc
, TOKmulass
, sizeof(MulAssignExp
), e1
, e2
)
7908 Expression
*MulAssignExp::semantic(Scope
*sc
)
7911 BinExp::semantic(sc
);
7912 e2
= resolveProperties(sc
, e2
);
7914 e
= op_overload(sc
);
7918 e1
= e1
->modifiableLvalue(sc
, e1
);
7923 e1
->checkArithmetic();
7924 e2
->checkArithmetic();
7925 if (e2
->type
->isfloating())
7933 if (t2
->isimaginary() || t2
->iscomplex())
7935 e2
= e2
->castTo(sc
, t1
);
7938 else if (t1
->isimaginary())
7940 if (t2
->isimaginary() || t2
->iscomplex())
7944 case Timaginary32
: t2
= Type::tfloat32
; break;
7945 case Timaginary64
: t2
= Type::tfloat64
; break;
7946 case Timaginary80
: t2
= Type::tfloat80
; break;
7950 e2
= e2
->castTo(sc
, t2
);
7957 /************************************************************/
7959 DivAssignExp::DivAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
7960 : BinExp(loc
, TOKdivass
, sizeof(DivAssignExp
), e1
, e2
)
7964 Expression
*DivAssignExp::semantic(Scope
*sc
)
7967 BinExp::semantic(sc
);
7968 e2
= resolveProperties(sc
, e2
);
7970 e
= op_overload(sc
);
7974 e1
= e1
->modifiableLvalue(sc
, e1
);
7979 e1
->checkArithmetic();
7980 e2
->checkArithmetic();
7981 if (e2
->type
->isimaginary())
7988 // Therefore, the result is 0
7989 e2
= new CommaExp(loc
, e2
, new RealExp(loc
, 0, t1
));
7991 e
= new AssignExp(loc
, e1
, e2
);
7995 else if (t1
->isimaginary())
8000 case Timaginary32
: t2
= Type::tfloat32
; break;
8001 case Timaginary64
: t2
= Type::tfloat64
; break;
8002 case Timaginary80
: t2
= Type::tfloat80
; break;
8006 e2
= e2
->castTo(sc
, t2
);
8007 e
= new AssignExp(loc
, e1
, e2
);
8015 /************************************************************/
8017 ModAssignExp::ModAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8018 : BinExp(loc
, TOKmodass
, sizeof(ModAssignExp
), e1
, e2
)
8022 Expression
*ModAssignExp::semantic(Scope
*sc
)
8024 return commonSemanticAssign(sc
);
8027 /************************************************************/
8029 ShlAssignExp::ShlAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8030 : BinExp(loc
, TOKshlass
, sizeof(ShlAssignExp
), e1
, e2
)
8034 Expression
*ShlAssignExp::semantic(Scope
*sc
)
8037 //printf("ShlAssignExp::semantic()\n");
8038 BinExp::semantic(sc
);
8039 e2
= resolveProperties(sc
, e2
);
8041 e
= op_overload(sc
);
8045 e1
= e1
->modifiableLvalue(sc
, e1
);
8050 e1
->checkIntegral();
8051 e2
= e2
->checkIntegral();
8052 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8056 /************************************************************/
8058 ShrAssignExp::ShrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8059 : BinExp(loc
, TOKshrass
, sizeof(ShrAssignExp
), e1
, e2
)
8063 Expression
*ShrAssignExp::semantic(Scope
*sc
)
8066 BinExp::semantic(sc
);
8067 e2
= resolveProperties(sc
, e2
);
8069 e
= op_overload(sc
);
8073 e1
= e1
->modifiableLvalue(sc
, e1
);
8078 e1
->checkIntegral();
8079 e2
= e2
->checkIntegral();
8080 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8084 /************************************************************/
8086 UshrAssignExp::UshrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8087 : BinExp(loc
, TOKushrass
, sizeof(UshrAssignExp
), e1
, e2
)
8091 Expression
*UshrAssignExp::semantic(Scope
*sc
)
8094 BinExp::semantic(sc
);
8095 e2
= resolveProperties(sc
, e2
);
8097 e
= op_overload(sc
);
8101 e1
= e1
->modifiableLvalue(sc
, e1
);
8106 e1
->checkIntegral();
8107 e2
= e2
->checkIntegral();
8108 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8112 /************************************************************/
8114 AndAssignExp::AndAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8115 : BinExp(loc
, TOKandass
, sizeof(AndAssignExp
), e1
, e2
)
8119 Expression
*AndAssignExp::semantic(Scope
*sc
)
8121 return commonSemanticAssignIntegral(sc
);
8124 /************************************************************/
8126 OrAssignExp::OrAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8127 : BinExp(loc
, TOKorass
, sizeof(OrAssignExp
), e1
, e2
)
8131 Expression
*OrAssignExp::semantic(Scope
*sc
)
8133 return commonSemanticAssignIntegral(sc
);
8136 /************************************************************/
8138 XorAssignExp::XorAssignExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8139 : BinExp(loc
, TOKxorass
, sizeof(XorAssignExp
), e1
, e2
)
8143 Expression
*XorAssignExp::semantic(Scope
*sc
)
8145 return commonSemanticAssignIntegral(sc
);
8148 /************************* AddExp *****************************/
8150 AddExp::AddExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8151 : BinExp(loc
, TOKadd
, sizeof(AddExp
), e1
, e2
)
8155 Expression
*AddExp::semantic(Scope
*sc
)
8159 printf("AddExp::semantic('%s')\n", toChars());
8163 BinExp::semanticp(sc
);
8165 e
= op_overload(sc
);
8169 Type
*tb1
= e1
->type
->toBasetype();
8170 Type
*tb2
= e2
->type
->toBasetype();
8172 if ((tb1
->ty
== Tarray
|| tb1
->ty
== Tsarray
) &&
8173 (tb2
->ty
== Tarray
|| tb2
->ty
== Tsarray
) &&
8174 tb1
->nextOf()->equals(tb2
->nextOf())
8180 else if (tb1
->ty
== Tpointer
&& e2
->type
->isintegral() ||
8181 tb2
->ty
== Tpointer
&& e1
->type
->isintegral())
8182 e
= scaleFactor(sc
);
8183 else if (tb1
->ty
== Tpointer
&& tb2
->ty
== Tpointer
)
8185 incompatibleTypes();
8192 if ((e1
->type
->isreal() && e2
->type
->isimaginary()) ||
8193 (e1
->type
->isimaginary() && e2
->type
->isreal()))
8195 switch (type
->toBasetype()->ty
)
8199 type
= Type::tcomplex32
;
8204 type
= Type::tcomplex64
;
8209 type
= Type::tcomplex80
;
8223 /************************************************************/
8225 MinExp::MinExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8226 : BinExp(loc
, TOKmin
, sizeof(MinExp
), e1
, e2
)
8230 Expression
*MinExp::semantic(Scope
*sc
)
8236 printf("MinExp::semantic('%s')\n", toChars());
8241 BinExp::semanticp(sc
);
8243 e
= op_overload(sc
);
8248 t1
= e1
->type
->toBasetype();
8249 t2
= e2
->type
->toBasetype();
8250 if (t1
->ty
== Tpointer
)
8252 if (t2
->ty
== Tpointer
)
8253 { // Need to divide the result by the stride
8254 // Replace (ptr - ptr) with (ptr - ptr) / stride
8258 typeCombine(sc
); // make sure pointer types are compatible
8259 type
= Type::tptrdiff_t
;
8260 stride
= t2
->nextOf()->size();
8261 e
= new DivExp(loc
, this, new IntegerExp(0, stride
, Type::tptrdiff_t
));
8262 e
->type
= Type::tptrdiff_t
;
8265 else if (t2
->isintegral())
8266 e
= scaleFactor(sc
);
8268 { error("incompatible types for -");
8269 return new IntegerExp(0);
8272 else if (t2
->ty
== Tpointer
)
8275 error("can't subtract pointer from %s", e1
->type
->toChars());
8276 return new IntegerExp(0);
8281 t1
= e1
->type
->toBasetype();
8282 t2
= e2
->type
->toBasetype();
8283 if ((t1
->isreal() && t2
->isimaginary()) ||
8284 (t1
->isimaginary() && t2
->isreal()))
8290 type
= Type::tcomplex32
;
8295 type
= Type::tcomplex64
;
8300 type
= Type::tcomplex80
;
8311 /************************* CatExp *****************************/
8313 CatExp::CatExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8314 : BinExp(loc
, TOKcat
, sizeof(CatExp
), e1
, e2
)
8318 Expression
*CatExp::semantic(Scope
*sc
)
8321 //printf("CatExp::semantic() %s\n", toChars());
8324 BinExp::semanticp(sc
);
8325 e
= op_overload(sc
);
8329 Type
*tb1
= e1
->type
->toBasetype();
8330 Type
*tb2
= e2
->type
->toBasetype();
8333 /* BUG: Should handle things like:
8343 if ((tb1
->ty
== Tsarray
|| tb1
->ty
== Tarray
) &&
8344 e2
->type
->implicitConvTo(tb1
->nextOf()) >= MATCHconst
)
8346 type
= tb1
->nextOf()->arrayOf();
8347 if (tb2
->ty
== Tarray
)
8348 { // Make e2 into [e2]
8349 e2
= new ArrayLiteralExp(e2
->loc
, e2
);
8354 else if ((tb2
->ty
== Tsarray
|| tb2
->ty
== Tarray
) &&
8355 e1
->type
->implicitConvTo(tb2
->nextOf()) >= MATCHconst
)
8357 type
= tb2
->nextOf()->arrayOf();
8358 if (tb1
->ty
== Tarray
)
8359 { // Make e1 into [e1]
8360 e1
= new ArrayLiteralExp(e1
->loc
, e1
);
8367 if (type
->ty
== Tmaybe
)
8368 error("Cannot join arrays that may be null (%s)", toChars());
8370 type
= type
->toHeadMutable();
8372 Type
*tb
= type
->toBasetype();
8373 if (tb
->ty
== Tsarray
)
8374 type
= tb
->nextOf()->arrayOf();
8375 if (type
->ty
== Tarray
&& tb1
->nextOf() && tb2
->nextOf() &&
8376 tb1
->nextOf()->mod
!= tb2
->nextOf()->mod
)
8377 type
= type
->nextOf()->toHeadMutable()->arrayOf();
8384 Type
*t1
= e1
->type
->toBasetype();
8385 Type
*t2
= e2
->type
->toBasetype();
8386 if (e1
->op
== TOKstring
&& e2
->op
== TOKstring
)
8387 e
= optimize(WANTvalue
);
8388 else if ((t1
->ty
== Tarray
|| t1
->ty
== Tsarray
) &&
8389 (t2
->ty
== Tarray
|| t2
->ty
== Tsarray
))
8395 //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
8396 error("Can only concatenate arrays, not (%s ~ %s)",
8397 e1
->type
->toChars(), e2
->type
->toChars());
8398 type
= Type::tint32
;
8401 e
->type
= e
->type
->semantic(loc
, sc
);
8407 /************************************************************/
8409 MulExp::MulExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8410 : BinExp(loc
, TOKmul
, sizeof(MulExp
), e1
, e2
)
8414 Expression
*MulExp::semantic(Scope
*sc
)
8418 printf("MulExp::semantic() %s\n", toChars());
8425 BinExp::semanticp(sc
);
8426 e
= op_overload(sc
);
8431 e1
->checkArithmetic();
8432 e2
->checkArithmetic();
8433 if (type
->isfloating())
8434 { Type
*t1
= e1
->type
;
8435 Type
*t2
= e2
->type
;
8441 else if (t2
->isreal())
8445 else if (t1
->isimaginary())
8447 if (t2
->isimaginary())
8452 case Timaginary32
: type
= Type::tfloat32
; break;
8453 case Timaginary64
: type
= Type::tfloat64
; break;
8454 case Timaginary80
: type
= Type::tfloat80
; break;
8461 e
= new NegExp(loc
, this);
8462 e
= e
->semantic(sc
);
8466 type
= t2
; // t2 is complex
8468 else if (t2
->isimaginary())
8470 type
= t1
; // t1 is complex
8476 /************************************************************/
8478 DivExp::DivExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8479 : BinExp(loc
, TOKdiv
, sizeof(DivExp
), e1
, e2
)
8483 Expression
*DivExp::semantic(Scope
*sc
)
8489 BinExp::semanticp(sc
);
8490 e
= op_overload(sc
);
8495 e1
->checkArithmetic();
8496 e2
->checkArithmetic();
8497 if (type
->isfloating())
8498 { Type
*t1
= e1
->type
;
8499 Type
*t2
= e2
->type
;
8504 if (t2
->isimaginary())
8509 e
= new NegExp(loc
, this);
8510 e
= e
->semantic(sc
);
8514 else if (t2
->isreal())
8518 else if (t1
->isimaginary())
8520 if (t2
->isimaginary())
8524 case Timaginary32
: type
= Type::tfloat32
; break;
8525 case Timaginary64
: type
= Type::tfloat64
; break;
8526 case Timaginary80
: type
= Type::tfloat80
; break;
8531 type
= t2
; // t2 is complex
8533 else if (t2
->isimaginary())
8535 type
= t1
; // t1 is complex
8541 /************************************************************/
8543 ModExp::ModExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8544 : BinExp(loc
, TOKmod
, sizeof(ModExp
), e1
, e2
)
8548 Expression
*ModExp::semantic(Scope
*sc
)
8554 BinExp::semanticp(sc
);
8555 e
= op_overload(sc
);
8560 e1
->checkArithmetic();
8561 e2
->checkArithmetic();
8562 if (type
->isfloating())
8564 if (e2
->type
->iscomplex())
8565 { error("cannot perform modulo complex arithmetic");
8566 return new IntegerExp(0);
8572 /************************************************************/
8574 ShlExp::ShlExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8575 : BinExp(loc
, TOKshl
, sizeof(ShlExp
), e1
, e2
)
8579 Expression
*ShlExp::semantic(Scope
*sc
)
8582 //printf("ShlExp::semantic(), type = %p\n", type);
8584 { BinExp::semanticp(sc
);
8585 e
= op_overload(sc
);
8588 e1
= e1
->checkIntegral();
8589 e2
= e2
->checkIntegral();
8590 e1
= e1
->integralPromotions(sc
);
8591 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8597 /************************************************************/
8599 ShrExp::ShrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8600 : BinExp(loc
, TOKshr
, sizeof(ShrExp
), e1
, e2
)
8604 Expression
*ShrExp::semantic(Scope
*sc
)
8608 { BinExp::semanticp(sc
);
8609 e
= op_overload(sc
);
8612 e1
= e1
->checkIntegral();
8613 e2
= e2
->checkIntegral();
8614 e1
= e1
->integralPromotions(sc
);
8615 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8621 /************************************************************/
8623 UshrExp::UshrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8624 : BinExp(loc
, TOKushr
, sizeof(UshrExp
), e1
, e2
)
8628 Expression
*UshrExp::semantic(Scope
*sc
)
8632 { BinExp::semanticp(sc
);
8633 e
= op_overload(sc
);
8636 e1
= e1
->checkIntegral();
8637 e2
= e2
->checkIntegral();
8638 e1
= e1
->integralPromotions(sc
);
8639 e2
= e2
->castTo(sc
, Type::tshiftcnt
);
8645 /************************************************************/
8647 AndExp::AndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8648 : BinExp(loc
, TOKand
, sizeof(AndExp
), e1
, e2
)
8652 Expression
*AndExp::semantic(Scope
*sc
)
8656 { BinExp::semanticp(sc
);
8657 e
= op_overload(sc
);
8660 if (e1
->type
->toBasetype()->ty
== Tbool
&&
8661 e2
->type
->toBasetype()->ty
== Tbool
)
8669 e1
->checkIntegral();
8670 e2
->checkIntegral();
8676 /************************************************************/
8678 OrExp::OrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8679 : BinExp(loc
, TOKor
, sizeof(OrExp
), e1
, e2
)
8683 Expression
*OrExp::semantic(Scope
*sc
)
8687 { BinExp::semanticp(sc
);
8688 e
= op_overload(sc
);
8691 if (e1
->type
->toBasetype()->ty
== Tbool
&&
8692 e2
->type
->toBasetype()->ty
== Tbool
)
8700 e1
->checkIntegral();
8701 e2
->checkIntegral();
8707 /************************************************************/
8709 XorExp::XorExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8710 : BinExp(loc
, TOKxor
, sizeof(XorExp
), e1
, e2
)
8714 Expression
*XorExp::semantic(Scope
*sc
)
8718 { BinExp::semanticp(sc
);
8719 e
= op_overload(sc
);
8722 if (e1
->type
->toBasetype()->ty
== Tbool
&&
8723 e2
->type
->toBasetype()->ty
== Tbool
)
8731 e1
->checkIntegral();
8732 e2
->checkIntegral();
8739 /************************************************************/
8741 OrOrExp::OrOrExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8742 : BinExp(loc
, TOKoror
, sizeof(OrOrExp
), e1
, e2
)
8746 Expression
*OrOrExp::semantic(Scope
*sc
)
8750 // same as for AndAnd
8751 e1
= e1
->semantic(sc
);
8752 e1
= resolveProperties(sc
, e1
);
8753 e1
= e1
->checkToPointer();
8754 e1
= e1
->checkToBoolean();
8755 cs1
= sc
->callSuper
;
8757 if (sc
->flags
& SCOPEstaticif
)
8759 /* If in static if, don't evaluate e2 if we don't have to.
8761 e1
= e1
->optimize(WANTflags
);
8762 if (e1
->isBool(TRUE
))
8764 return new IntegerExp(loc
, 1, Type::tboolean
);
8768 e2
= e2
->semantic(sc
);
8769 sc
->mergeCallSuper(loc
, cs1
);
8770 e2
= resolveProperties(sc
, e2
);
8771 e2
= e2
->checkToPointer();
8773 type
= Type::tboolean
;
8774 if (e1
->type
->ty
== Tvoid
)
8776 if (e2
->op
== TOKtype
|| e2
->op
== TOKimport
)
8777 error("%s is not an expression", e2
->toChars());
8781 Expression
*OrOrExp::checkToBoolean()
8783 e2
= e2
->checkToBoolean();
8787 int OrOrExp::isBit()
8792 int OrOrExp::checkSideEffect(int flag
)
8796 return e1
->checkSideEffect(2) || e2
->checkSideEffect(2);
8799 { e1
->checkSideEffect(1);
8800 return e2
->checkSideEffect(flag
);
8804 /************************************************************/
8806 AndAndExp::AndAndExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8807 : BinExp(loc
, TOKandand
, sizeof(AndAndExp
), e1
, e2
)
8811 Expression
*AndAndExp::semantic(Scope
*sc
)
8816 e1
= e1
->semantic(sc
);
8817 e1
= resolveProperties(sc
, e1
);
8818 e1
= e1
->checkToPointer();
8819 e1
= e1
->checkToBoolean();
8820 cs1
= sc
->callSuper
;
8822 if (sc
->flags
& SCOPEstaticif
)
8824 /* If in static if, don't evaluate e2 if we don't have to.
8826 e1
= e1
->optimize(WANTflags
);
8827 if (e1
->isBool(FALSE
))
8829 return new IntegerExp(loc
, 0, Type::tboolean
);
8833 e2
= e2
->semantic(sc
);
8834 sc
->mergeCallSuper(loc
, cs1
);
8835 e2
= resolveProperties(sc
, e2
);
8836 e2
= e2
->checkToPointer();
8838 type
= Type::tboolean
;
8839 if (e1
->type
->ty
== Tvoid
)
8841 if (e2
->op
== TOKtype
|| e2
->op
== TOKimport
)
8842 error("%s is not an expression", e2
->toChars());
8846 Expression
*AndAndExp::checkToBoolean()
8848 e2
= e2
->checkToBoolean();
8852 int AndAndExp::isBit()
8857 int AndAndExp::checkSideEffect(int flag
)
8861 return e1
->checkSideEffect(2) || e2
->checkSideEffect(2);
8865 e1
->checkSideEffect(1);
8866 return e2
->checkSideEffect(flag
);
8870 /************************************************************/
8872 InExp::InExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8873 : BinExp(loc
, TOKin
, sizeof(InExp
), e1
, e2
)
8877 Expression
*InExp::semantic(Scope
*sc
)
8883 BinExp::semanticp(sc
);
8884 e
= op_overload(sc
);
8888 //type = Type::tboolean;
8889 Type
*t2b
= e2
->type
->toBasetype();
8890 if (t2b
->ty
!= Taarray
)
8892 error("rvalue of in expression must be an associative array, not %s", e2
->type
->toChars());
8893 type
= Type::terror
;
8897 TypeAArray
*ta
= (TypeAArray
*)t2b
;
8899 // Convert key to type of key
8900 e1
= e1
->implicitCastTo(sc
, ta
->index
);
8902 // Return type is pointer to value
8903 type
= ta
->nextOf()->pointerTo();
8905 type
= type
->maybe(true);
8916 /************************************************************/
8918 /* This deletes the key e1 from the associative array e2
8921 RemoveExp::RemoveExp(Loc loc
, Expression
*e1
, Expression
*e2
)
8922 : BinExp(loc
, TOKremove
, sizeof(RemoveExp
), e1
, e2
)
8927 /************************************************************/
8929 CmpExp::CmpExp(enum TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
8930 : BinExp(loc
, op
, sizeof(CmpExp
), e1
, e2
)
8934 Expression
*CmpExp::semantic(Scope
*sc
)
8940 printf("CmpExp::semantic('%s')\n", toChars());
8945 BinExp::semanticp(sc
);
8947 if (e1
->type
->toBasetype()->ty
== Tclass
&& e2
->op
== TOKnull
||
8948 e2
->type
->toBasetype()->ty
== Tclass
&& e1
->op
== TOKnull
)
8950 error("do not use null when comparing class types");
8953 e
= op_overload(sc
);
8956 e
= new CmpExp(op
, loc
, e
, new IntegerExp(loc
, 0, Type::tint32
));
8957 e
= e
->semantic(sc
);
8962 type
= Type::tboolean
;
8964 // Special handling for array comparisons
8965 t1
= e1
->type
->toBasetype();
8966 t2
= e2
->type
->toBasetype();
8967 if ((t1
->ty
== Tarray
|| t1
->ty
== Tsarray
|| t1
->ty
== Tpointer
) &&
8968 (t2
->ty
== Tarray
|| t2
->ty
== Tsarray
|| t2
->ty
== Tpointer
))
8970 if (t1
->nextOf()->implicitConvTo(t2
->nextOf()) < MATCHconst
&&
8971 t2
->nextOf()->implicitConvTo(t1
->nextOf()) < MATCHconst
&&
8972 (t1
->nextOf()->ty
!= Tvoid
&& t2
->nextOf()->ty
!= Tvoid
))
8973 error("array comparison type mismatch, %s vs %s", t1
->nextOf()->toChars(), t2
->nextOf()->toChars());
8976 else if (t1
->ty
== Tstruct
|| t2
->ty
== Tstruct
||
8977 (t1
->ty
== Tclass
&& t2
->ty
== Tclass
))
8979 if (t2
->ty
== Tstruct
)
8980 error("need member function opCmp() for %s %s to compare", t2
->toDsymbol(sc
)->kind(), t2
->toChars());
8982 error("need member function opCmp() for %s %s to compare", t1
->toDsymbol(sc
)->kind(), t1
->toChars());
8986 else if (t1
->iscomplex() || t2
->iscomplex())
8988 error("compare not defined for complex operands");
8989 e
= new IntegerExp(0);
8994 //printf("CmpExp: %s\n", e->toChars());
9004 /************************************************************/
9006 EqualExp::EqualExp(enum TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
9007 : BinExp(loc
, op
, sizeof(EqualExp
), e1
, e2
)
9009 assert(op
== TOKequal
|| op
== TOKnotequal
);
9012 Expression
*EqualExp::semantic(Scope
*sc
)
9017 //printf("EqualExp::semantic('%s')\n", toChars());
9021 BinExp::semanticp(sc
);
9023 /* Before checking for operator overloading, check to see if we're
9024 * comparing the addresses of two statics. If so, we can just see
9025 * if they are the same symbol.
9027 if (e1
->op
== TOKaddress
&& e2
->op
== TOKaddress
)
9028 { AddrExp
*ae1
= (AddrExp
*)e1
;
9029 AddrExp
*ae2
= (AddrExp
*)e2
;
9031 if (ae1
->e1
->op
== TOKvar
&& ae2
->e1
->op
== TOKvar
)
9032 { VarExp
*ve1
= (VarExp
*)ae1
->e1
;
9033 VarExp
*ve2
= (VarExp
*)ae2
->e1
;
9035 if (ve1
->var
== ve2
->var
/*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
9037 // They are the same, result is 'true' for ==, 'false' for !=
9038 e
= new IntegerExp(loc
, (op
== TOKequal
), Type::tboolean
);
9044 if (e1
->type
->toBasetype()->ty
== Tclass
&& e2
->op
== TOKnull
||
9045 e2
->type
->toBasetype()->ty
== Tclass
&& e1
->op
== TOKnull
)
9047 error("use '%s' instead of '%s' when comparing with null",
9048 Token::toChars(op
== TOKequal
? TOKidentity
: TOKnotidentity
),
9049 Token::toChars(op
));
9052 //if (e2->op != TOKnull)
9054 e
= op_overload(sc
);
9057 if (op
== TOKnotequal
)
9059 e
= new NotExp(e
->loc
, e
);
9060 e
= e
->semantic(sc
);
9066 e
= typeCombine(sc
);
9067 type
= Type::tboolean
;
9069 // Special handling for array comparisons
9070 t1
= e1
->type
->toBasetype();
9071 t2
= e2
->type
->toBasetype();
9073 if ((t1
->ty
== Tarray
|| t1
->ty
== Tsarray
|| t1
->ty
== Tpointer
) &&
9074 (t2
->ty
== Tarray
|| t2
->ty
== Tsarray
|| t2
->ty
== Tpointer
))
9076 if (t1
->nextOf()->implicitConvTo(t2
->nextOf()) < MATCHconst
&&
9077 t2
->nextOf()->implicitConvTo(t1
->nextOf()) < MATCHconst
&&
9078 (t1
->nextOf()->ty
!= Tvoid
&& t2
->nextOf()->ty
!= Tvoid
))
9079 error("array equality comparison type mismatch, %s vs %s", t1
->toChars(), t2
->toChars());
9083 if (e1
->type
!= e2
->type
&& e1
->type
->isfloating() && e2
->type
->isfloating())
9085 // Cast both to complex
9086 e1
= e1
->castTo(sc
, Type::tcomplex80
);
9087 e2
= e2
->castTo(sc
, Type::tcomplex80
);
9093 int EqualExp::isBit()
9100 /************************************************************/
9102 IdentityExp::IdentityExp(enum TOK op
, Loc loc
, Expression
*e1
, Expression
*e2
)
9103 : BinExp(loc
, op
, sizeof(IdentityExp
), e1
, e2
)
9107 Expression
*IdentityExp::semantic(Scope
*sc
)
9112 BinExp::semanticp(sc
);
9113 type
= Type::tboolean
;
9115 if (e1
->type
!= e2
->type
&& e1
->type
->isfloating() && e2
->type
->isfloating())
9117 // Cast both to complex
9118 e1
= e1
->castTo(sc
, Type::tcomplex80
);
9119 e2
= e2
->castTo(sc
, Type::tcomplex80
);
9124 int IdentityExp::isBit()
9130 /****************************************************************/
9132 CondExp::CondExp(Loc loc
, Expression
*econd
, Expression
*e1
, Expression
*e2
)
9133 : BinExp(loc
, TOKquestion
, sizeof(CondExp
), e1
, e2
)
9135 this->econd
= econd
;
9138 Expression
*CondExp::syntaxCopy()
9140 return new CondExp(loc
, econd
->syntaxCopy(), e1
->syntaxCopy(), e2
->syntaxCopy());
9144 Expression
*CondExp::semantic(Scope
*sc
)
9151 printf("CondExp::semantic('%s')\n", toChars());
9156 econd
= econd
->semantic(sc
);
9157 econd
= resolveProperties(sc
, econd
);
9158 econd
= econd
->checkToPointer();
9159 econd
= econd
->checkToBoolean();
9161 #if 0 /* this cannot work right because the types of e1 and e2
9162 * both contribute to the type of the result.
9164 if (sc
->flags
& SCOPEstaticif
)
9166 /* If in static if, don't evaluate what we don't have to.
9168 econd
= econd
->optimize(WANTflags
);
9169 if (econd
->isBool(TRUE
))
9171 e1
= e1
->semantic(sc
);
9172 e1
= resolveProperties(sc
, e1
);
9175 else if (econd
->isBool(FALSE
))
9177 e2
= e2
->semantic(sc
);
9178 e2
= resolveProperties(sc
, e2
);
9185 cs0
= sc
->callSuper
;
9186 e1
= e1
->semantic(sc
);
9187 e1
= resolveProperties(sc
, e1
);
9188 cs1
= sc
->callSuper
;
9189 sc
->callSuper
= cs0
;
9190 e2
= e2
->semantic(sc
);
9191 e2
= resolveProperties(sc
, e2
);
9192 sc
->mergeCallSuper(loc
, cs1
);
9195 // If either operand is void, the result is void
9198 if (t1
->ty
== Tvoid
|| t2
->ty
== Tvoid
)
9205 switch (e1
->type
->toBasetype()->ty
)
9210 e2
= e2
->castTo(sc
, e1
->type
);
9213 switch (e2
->type
->toBasetype()->ty
)
9218 e1
= e1
->castTo(sc
, e2
->type
);
9221 if (type
->toBasetype()->ty
== Tarray
)
9223 e1
= e1
->castTo(sc
, type
);
9224 e2
= e2
->castTo(sc
, type
);
9228 printf("res: %s\n", type
->toChars());
9229 printf("e1 : %s\n", e1
->type
->toChars());
9230 printf("e2 : %s\n", e2
->type
->toChars());
9235 Expression
*CondExp::toLvalue(Scope
*sc
, Expression
*ex
)
9239 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
9240 e
= new PtrExp(loc
, this, type
);
9242 e1
= e1
->addressOf(sc
);
9243 //e1 = e1->toLvalue(sc, NULL);
9245 e2
= e2
->addressOf(sc
);
9246 //e2 = e2->toLvalue(sc, NULL);
9254 Expression
*CondExp::modifiableLvalue(Scope
*sc
, Expression
*e
)
9256 error("conditional expression %s is not a modifiable lvalue", toChars());
9260 void CondExp::checkEscape()
9267 Expression
*CondExp::checkToBoolean()
9269 e1
= e1
->checkToBoolean();
9270 e2
= e2
->checkToBoolean();
9274 int CondExp::checkSideEffect(int flag
)
9278 return econd
->checkSideEffect(2) ||
9279 e1
->checkSideEffect(2) ||
9280 e2
->checkSideEffect(2);
9284 econd
->checkSideEffect(1);
9285 e1
->checkSideEffect(flag
);
9286 return e2
->checkSideEffect(flag
);
9290 int CondExp::canThrow()
9292 return econd
->canThrow() || e1
->canThrow() || e2
->canThrow();
9296 void CondExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
9298 expToCBuffer(buf
, hgs
, econd
, PREC_oror
);
9299 buf
->writestring(" ? ");
9300 expToCBuffer(buf
, hgs
, e1
, PREC_expr
);
9301 buf
->writestring(" : ");
9302 expToCBuffer(buf
, hgs
, e2
, PREC_cond
);
9306 /****************************************************************/
9308 DefaultInitExp::DefaultInitExp(Loc loc
, enum TOK subop
, int size
)
9309 : Expression(loc
, TOKdefault
, size
)
9311 this->subop
= subop
;
9314 void DefaultInitExp::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
9316 buf
->writestring(Token::toChars(subop
));
9319 /****************************************************************/
9321 FileInitExp::FileInitExp(Loc loc
)
9322 : DefaultInitExp(loc
, TOKfile
, sizeof(FileInitExp
))
9326 Expression
*FileInitExp::semantic(Scope
*sc
)
9328 //printf("FileInitExp::semantic()\n");
9329 type
= Type::tchar
->invariantOf()->arrayOf();
9333 Expression
*FileInitExp::resolve(Loc loc
, Scope
*sc
)
9335 //printf("FileInitExp::resolve() %s\n", toChars());
9336 char *s
= loc
.filename
? loc
.filename
: sc
->module
->ident
->toChars();
9337 Expression
*e
= new StringExp(loc
, s
);
9338 e
= e
->semantic(sc
);
9339 e
= e
->castTo(sc
, type
);
9343 /****************************************************************/
9345 LineInitExp::LineInitExp(Loc loc
)
9346 : DefaultInitExp(loc
, TOKline
, sizeof(LineInitExp
))
9350 Expression
*LineInitExp::semantic(Scope
*sc
)
9352 type
= Type::tint32
;
9356 Expression
*LineInitExp::resolve(Loc loc
, Scope
*sc
)
9358 Expression
*e
= new IntegerExp(loc
, loc
.linnum
, Type::tint32
);
9359 e
= e
->castTo(sc
, type
);