Files
ldc/dmd2/expression.h
David Nadlinger 3ec084da59 Return undef instead of null on toConstElem failure.
This fixes a segfault with associative array literals of
arrays of associative array literals, which occured because
of arrayLiteralToConst not handling null values properly.
Ensuring that null pointers are handled correctly in all
toConstElem callers is much more error-prone than just
returning an LLVM undef, an error is emitted anyway.

The root of the problem is actually in the kludgly
implementation of AssocArrayLiteral::toElem, we should
revisit this at some point.
2013-12-27 18:35:50 +01:00

2049 lines
59 KiB
C++

// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_EXPRESSION_H
#define DMD_EXPRESSION_H
#include "mars.h"
#include "identifier.h"
#include "lexer.h"
#include "arraytypes.h"
#include "intrange.h"
class Type;
class TypeVector;
struct Scope;
class TupleDeclaration;
class VarDeclaration;
class FuncDeclaration;
class FuncLiteralDeclaration;
class Declaration;
class CtorDeclaration;
class NewDeclaration;
class Dsymbol;
class Import;
class Module;
class ScopeDsymbol;
struct InlineCostState;
struct InlineDoState;
struct InlineScanState;
class Expression;
class Declaration;
class AggregateDeclaration;
class StructDeclaration;
class TemplateInstance;
class TemplateDeclaration;
class ClassDeclaration;
struct HdrGenState;
class BinExp;
struct InterState;
#if IN_DMD
struct Symbol; // back end symbol
#endif
class OverloadSet;
class Initializer;
class StringExp;
class ArrayExp;
class SliceExp;
#if IN_LLVM
class AssignExp;
class SymbolDeclaration;
#endif
enum TOK;
#if IN_DMD
// Back end
struct IRState;
struct dt_t;
#endif
#ifdef IN_GCC
typedef union tree_node elem;
#elif IN_LLVM
class DValue; typedef class DValue elem;
#else
struct elem;
#endif
#if IN_LLVM
struct IRState;
namespace llvm {
class Constant;
class ConstantInt;
class GlobalVariable;
class StructType;
class Value;
}
#endif
void initPrecedence();
typedef int (*apply_fp_t)(Expression *, void *);
Expression *resolveProperties(Scope *sc, Expression *e);
Expression *resolvePropertiesOnly(Scope *sc, Expression *e1);
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d);
Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Dsymbol *d);
Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid);
void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
void expandTuples(Expressions *exps);
TupleDeclaration *isAliasThisTuple(Expression *e);
int expandAliasThisTuples(Expressions *exps, size_t starti = 0);
FuncDeclaration *hasThis(Scope *sc);
Expression *fromConstInitializer(int result, Expression *e);
int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow);
TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s);
Expression *valueNoDtor(Expression *e);
int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1);
#if DMDV2
Expression *resolveAliasThis(Scope *sc, Expression *e);
Expression *callCpCtor(Scope *sc, Expression *e);
#endif
Expression *resolveOpDollar(Scope *sc, ArrayExp *ae);
Expression *resolveOpDollar(Scope *sc, SliceExp *se);
Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc);
/* Run CTFE on the expression, but allow the expression to be a TypeExp
* or a tuple containing a TypeExp. (This is required by pragma(msg)).
*/
Expression *ctfeInterpretForPragmaMsg(Expression *e);
/* Interpreter: what form of return value expression is required?
*/
enum CtfeGoal
{ ctfeNeedRvalue, // Must return an Rvalue
ctfeNeedLvalue, // Must return an Lvalue
ctfeNeedAnyValue, // Can return either an Rvalue or an Lvalue
ctfeNeedLvalueRef,// Must return a reference to an Lvalue (for ref types)
ctfeNeedNothing // The return value is not required
};
#define WANTflags 1
#define WANTvalue 2
// Same as WANTvalue, but also expand variables as far as possible
#define WANTexpand 8
class Expression : public RootObject
{
public:
Loc loc; // file location
TOK op; // handy to minimize use of dynamic_cast
Type *type; // !=NULL means that semantic() has been run
unsigned char size; // # of bytes in Expression so we can copy() it
unsigned char parens; // if this is a parenthesized expression
Expression(Loc loc, TOK op, int size);
static void init();
Expression *copy();
virtual Expression *syntaxCopy();
virtual int apply(apply_fp_t fp, void *param);
virtual Expression *semantic(Scope *sc);
Expression *trySemantic(Scope *sc);
int dyncast() { return DYNCAST_EXPRESSION; } // kludge for template.isExpression()
void print();
char *toChars();
virtual void dump(int indent);
void error(const char *format, ...);
void warning(const char *format, ...);
void deprecation(const char *format, ...);
virtual int rvalue();
static Expression *combine(Expression *e1, Expression *e2);
static Expressions *arraySyntaxCopy(Expressions *exps);
virtual dinteger_t toInteger();
virtual uinteger_t toUInteger();
virtual real_t toReal();
virtual real_t toImaginary();
virtual complex_t toComplex();
virtual StringExp *toString();
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toMangleBuffer(OutBuffer *buf);
virtual int isLvalue();
virtual Expression *toLvalue(Scope *sc, Expression *e);
virtual Expression *modifiableLvalue(Scope *sc, Expression *e);
virtual Expression *implicitCastTo(Scope *sc, Type *t);
virtual MATCH implicitConvTo(Type *t);
virtual IntRange getIntRange();
virtual Expression *castTo(Scope *sc, Type *t);
virtual Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
virtual void checkEscape();
virtual void checkEscapeRef();
virtual Expression *resolveLoc(Loc loc, Scope *sc);
void checkScalar();
void checkNoBool();
Expression *checkIntegral();
Expression *checkArithmetic();
void checkDeprecated(Scope *sc, Dsymbol *s);
void checkPurity(Scope *sc, FuncDeclaration *f);
void checkPurity(Scope *sc, VarDeclaration *v);
void checkSafety(Scope *sc, FuncDeclaration *f);
bool checkPostblit(Scope *sc, Type *t);
virtual int checkModifiable(Scope *sc, int flag = 0);
virtual Expression *checkToBoolean(Scope *sc);
virtual Expression *addDtorHook(Scope *sc);
Expression *checkToPointer();
Expression *addressOf(Scope *sc);
Expression *deref();
Expression *integralPromotions(Scope *sc);
Expression *isTemp();
Expression *toDelegate(Scope *sc, Type *t);
virtual Expression *optimize(int result, bool keepLvalue = false);
// Entry point for CTFE.
// A compile-time result is required. Give an error if not possible
Expression *ctfeInterpret();
// Implementation of CTFE for this expression
virtual Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
virtual int isConst();
virtual int isBool(int result);
virtual int isBit();
bool hasSideEffect();
void discardValue();
void useValue();
int canThrow(bool mustNotThrow);
virtual int inlineCost3(InlineCostState *ics);
virtual Expression *doInline(InlineDoState *ids);
virtual Expression *inlineScan(InlineScanState *iss);
Expression *inlineCopy(Scope *sc);
// For operator overloading
virtual int isCommutative();
virtual Identifier *opId();
virtual Identifier *opId_r();
// For array ops
virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
virtual Expression *buildArrayLoop(Parameters *fparams);
int isArrayOperand();
// Back end
virtual elem *toElem(IRState *irs);
elem *toElemDtor(IRState *irs);
#if IN_LLVM
/// Emits an LLVM constant corresponding to the expression.
///
/// Due to the current implementation of AssocArrayLiteralExp::toElem,the
/// implementations have to be able to handle being called on expressions
/// that are not actually constant. In such a case, an LLVM undef of the
/// expected type should be returned (_not_ null).
virtual llvm::Constant *toConstElem(IRState *irs);
virtual void cacheLvalue(IRState* irs);
llvm::Value* cachedLvalue;
virtual AssignExp* isAssignExp() { return NULL; }
#else
virtual dt_t **toDt(dt_t **pdt);
#endif
};
class IntegerExp : public Expression
{
public:
dinteger_t value;
IntegerExp(Loc loc, dinteger_t value, Type *type);
IntegerExp(dinteger_t value);
bool equals(RootObject *o);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
char *toChars();
void dump(int indent);
IntRange getIntRange();
dinteger_t toInteger();
real_t toReal();
real_t toImaginary();
complex_t toComplex();
int isConst();
int isBool(int result);
MATCH implicitConvTo(Type *t);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
Expression *toLvalue(Scope *sc, Expression *e);
elem *toElem(IRState *irs);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
class ErrorExp : public IntegerExp
{
public:
ErrorExp();
Expression *implicitCastTo(Scope *sc, Type *t);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *toLvalue(Scope *sc, Expression *e);
};
class RealExp : public Expression
{
public:
real_t value;
RealExp(Loc loc, real_t value, Type *type);
bool equals(RootObject *o);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
char *toChars();
dinteger_t toInteger();
uinteger_t toUInteger();
real_t toReal();
real_t toImaginary();
complex_t toComplex();
Expression *castTo(Scope *sc, Type *t);
int isConst();
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
elem *toElem(IRState *irs);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
class ComplexExp : public Expression
{
public:
complex_t value;
ComplexExp(Loc loc, complex_t value, Type *type);
bool equals(RootObject *o);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
char *toChars();
dinteger_t toInteger();
uinteger_t toUInteger();
real_t toReal();
real_t toImaginary();
complex_t toComplex();
Expression *castTo(Scope *sc, Type *t);
int isConst();
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
elem *toElem(IRState *irs);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
class IdentifierExp : public Expression
{
public:
Identifier *ident;
Declaration *var;
IdentifierExp(Loc loc, Identifier *ident);
Expression *semantic(Scope *sc);
char *toChars();
void dump(int indent);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
};
class DollarExp : public IdentifierExp
{
public:
DollarExp(Loc loc);
};
class DsymbolExp : public Expression
{
public:
Dsymbol *s;
bool hasOverloads;
DsymbolExp(Loc loc, Dsymbol *s, bool hasOverloads = false);
Expression *semantic(Scope *sc);
char *toChars();
void dump(int indent);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
};
class ThisExp : public Expression
{
public:
Declaration *var;
ThisExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
elem *toElem(IRState *irs);
};
class SuperExp : public ThisExp
{
public:
SuperExp(Loc loc);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
};
class NullExp : public Expression
{
public:
unsigned char committed; // !=0 if type is committed
NullExp(Loc loc, Type *t = NULL);
bool equals(RootObject *o);
Expression *semantic(Scope *sc);
int isBool(int result);
int isConst();
StringExp *toString();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
elem *toElem(IRState *irs);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
class StringExp : public Expression
{
public:
void *string; // char, wchar, or dchar data
size_t len; // number of chars, wchars, or dchars
unsigned char sz; // 1: char, 2: wchar, 4: dchar
unsigned char committed; // !=0 if type is committed
utf8_t postfix; // 'c', 'w', 'd'
bool ownedByCtfe; // true = created in CTFE
StringExp(Loc loc, char *s);
StringExp(Loc loc, void *s, size_t len);
StringExp(Loc loc, void *s, size_t len, utf8_t postfix);
//Expression *syntaxCopy();
bool equals(RootObject *o);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
size_t length();
StringExp *toString();
StringExp *toUTF8(Scope *sc);
Expression *implicitCastTo(Scope *sc, Type *t);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
int compare(RootObject *obj);
int isBool(int result);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
unsigned charAt(size_t i);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
elem *toElem(IRState *irs);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
// Tuple
class TupleExp : public Expression
{
public:
Expression *e0; // side-effect part
/* Tuple-field access may need to take out its side effect part.
* For example:
* foo().tupleof
* is rewritten as:
* (ref __tup = foo(); tuple(__tup.field0, __tup.field1, ...))
* The declaration of temporary variable __tup will be stored in TupleExp::e0.
*/
Expressions *exps;
TupleExp(Loc loc, Expression *e0, Expressions *exps);
TupleExp(Loc loc, Expressions *exps);
TupleExp(Loc loc, TupleDeclaration *tup);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
bool equals(RootObject *o);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void checkEscape();
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *castTo(Scope *sc, Type *t);
elem *toElem(IRState *irs);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
class ArrayLiteralExp : public Expression
{
public:
Expressions *elements;
bool ownedByCtfe; // true = created in CTFE
ArrayLiteralExp(Loc loc, Expressions *elements);
ArrayLiteralExp(Loc loc, Expression *e);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
bool equals(RootObject *o);
Expression *semantic(Scope *sc);
int isBool(int result);
elem *toElem(IRState *irs);
StringExp *toString();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
class AssocArrayLiteralExp : public Expression
{
public:
Expressions *keys;
Expressions *values;
bool ownedByCtfe; // true = created in CTFE
AssocArrayLiteralExp(Loc loc, Expressions *keys, Expressions *values);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
int isBool(int result);
elem *toElem(IRState *irs);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
// scrubReturnValue is running
#define stageScrub 0x1
// hasNonConstPointers is running
#define stageSearchPointers 0x2
// optimize is running
#define stageOptimize 0x4
// apply is running
#define stageApply 0x8
//inlineScan is running
#define stageInlineScan 0x10
// toCBuffer is running
#define stageToCBuffer 0x20
class StructLiteralExp : public Expression
{
public:
StructDeclaration *sd; // which aggregate this is for
Expressions *elements; // parallels sd->fields[] with
// NULL entries for fields to skip
Type *stype; // final type of result (can be different from sd's type)
#if IN_DMD
Symbol *sinit; // if this is a defaultInitLiteral, this symbol contains the default initializer
Symbol *sym; // back end symbol to initialize with literal
#endif
size_t soffset; // offset from start of s
int fillHoles; // fill alignment 'holes' with zero
bool ownedByCtfe; // true = created in CTFE
StructLiteralExp *origin; // pointer to the origin instance of the expression.
// once a new expression is created, origin is set to 'this'.
// anytime when an expression copy is created, 'origin' pointer is set to
// 'origin' pointer value of the original expression.
StructLiteralExp *inlinecopy; // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer.
int stageflags; // anytime when recursive function is calling, 'stageflags' marks with bit flag of
// current stage and unmarks before return from this function.
// 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline'
// (with infinite recursion) of this expression.
StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL);
bool equals(RootObject *o);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *fill(bool ctorinit);
Expression *getField(Type *type, unsigned offset);
int getFieldIndex(Type *type, unsigned offset);
elem *toElem(IRState *irs);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
#if IN_LLVM
// With the introduction of pointers returned from CTFE, struct literals can
// now contain pointers to themselves. While in toElem, contains a pointer
// to the memory used to build the literal for resolving such references.
llvm::Value* inProgressMemory;
llvm::Constant *toConstElem(IRState *irs);
// A global variable for taking the address of this struct literal constant,
// if it already exists. Used to resolve self-references.
llvm::GlobalVariable *globalVar;
/// Set if this is really the result of a struct .init access and should be
/// resolved codegen'd as an access to the given SymbolDeclaration.
// LDC_FIXME: Figure out whether this, i.e. imitating the DMD behavior, is
// really the best way to fix the nested struct constant folding issue.
SymbolDeclaration *sinit;
#else
dt_t **toDt(dt_t **pdt);
Symbol *toSymbol();
#endif
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
class DotIdExp;
DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident);
class TypeExp : public Expression
{
public:
TypeExp(Loc loc, Type *type);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
int rvalue();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result, bool keepLvalue = false);
elem *toElem(IRState *irs);
};
class ScopeExp : public Expression
{
public:
ScopeDsymbol *sds;
ScopeExp(Loc loc, ScopeDsymbol *sds);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
elem *toElem(IRState *irs);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
class TemplateExp : public Expression
{
public:
TemplateDeclaration *td;
FuncDeclaration *fd;
TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd = NULL);
int rvalue();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
};
class NewExp : public Expression
{
public:
/* thisexp.new(newargs) newtype(arguments)
*/
Expression *thisexp; // if !NULL, 'this' for class being allocated
Expressions *newargs; // Array of Expression's to call new operator
Type *newtype;
Expressions *arguments; // Array of Expression's
CtorDeclaration *member; // constructor function
NewDeclaration *allocator; // allocator function
int onstack; // allocate on stack
NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
Type *newtype, Expressions *arguments);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *optimize(int result, bool keepLvalue = false);
MATCH implicitConvTo(Type *t);
elem *toElem(IRState *irs);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
//int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
};
class NewAnonClassExp : public Expression
{
public:
/* thisexp.new(newargs) class baseclasses { } (arguments)
*/
Expression *thisexp; // if !NULL, 'this' for class being allocated
Expressions *newargs; // Array of Expression's to call new operator
ClassDeclaration *cd; // class being instantiated
Expressions *arguments; // Array of Expression's to call class constructor
NewAnonClassExp(Loc loc, Expression *thisexp, Expressions *newargs,
ClassDeclaration *cd, Expressions *arguments);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#if DMDV2
class SymbolExp : public Expression
{
public:
Declaration *var;
bool hasOverloads;
SymbolExp(Loc loc, TOK op, int size, Declaration *var, bool hasOverloads);
elem *toElem(IRState *irs);
};
#endif
// Offset from symbol
class SymOffExp : public SymbolExp
{
public:
unsigned offset;
SymOffExp(Loc loc, Declaration *var, unsigned offset, bool hasOverloads = false);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void checkEscape();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isConst();
int isBool(int result);
Expression *doInline(InlineDoState *ids);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
#if IN_LLVM
DValue* toElem(IRState* irs);
llvm::Constant* toConstElem(IRState* irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
// Variable
class VarExp : public SymbolExp
{
public:
VarExp(Loc loc, Declaration *var, bool hasOverloads = false);
bool equals(RootObject *o);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void dump(int indent);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void checkEscape();
void checkEscapeRef();
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
#if IN_LLVM
DValue* toElem(IRState* irs);
llvm::Constant *toConstElem(IRState *irs);
void cacheLvalue(IRState* irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
};
#if DMDV2
// Overload Set
class OverExp : public Expression
{
public:
OverloadSet *vars;
OverExp(Loc loc, OverloadSet *s);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
// Function/Delegate literal
class FuncExp : public Expression
{
public:
FuncLiteralDeclaration *fd;
TemplateDeclaration *td;
TOK tok;
FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL);
void genIdent(Scope *sc);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *semantic(Scope *sc, Expressions *arguments);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *implicitCastTo(Scope *sc, Type *t);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
int inlineCost3(InlineCostState *ics);
//Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
};
// Declaration of a symbol
class DeclarationExp : public Expression
{
public:
Dsymbol *declaration;
DeclarationExp(Loc loc, Dsymbol *declaration);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
class TypeidExp : public Expression
{
public:
RootObject *obj;
TypeidExp(Loc loc, RootObject *obj);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#if DMDV2
class TraitsExp : public Expression
{
public:
Identifier *ident;
Objects *args;
TraitsExp(Loc loc, Identifier *ident, Objects *args);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
class HaltExp : public Expression
{
public:
HaltExp(Loc loc);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
};
class IsExp : public Expression
{
public:
/* is(targ id tok tspec)
* is(targ id == tok2)
*/
Type *targ;
Identifier *id; // can be NULL
TOK tok; // ':' or '=='
Type *tspec; // can be NULL
TOK tok2; // 'struct', 'union', 'typedef', etc.
TemplateParameters *parameters;
IsExp(Loc loc, Type *targ, Identifier *id, TOK tok, Type *tspec,
TOK tok2, TemplateParameters *parameters);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
/****************************************************************/
class UnaExp : public Expression
{
public:
Expression *e1;
Type *att1; // Save alias this type to detect recursion
UnaExp(Loc loc, TOK op, int size, Expression *e1);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result, bool keepLvalue = false);
void dump(int indent);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *resolveLoc(Loc loc, Scope *sc);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
virtual Expression *op_overload(Scope *sc);
};
typedef Expression *(*fp_t)(Type *, Expression *, Expression *);
typedef int (*fp2_t)(Loc loc, TOK, Expression *, Expression *);
class BinExp : public Expression
{
public:
Expression *e1;
Expression *e2;
Type *att1; // Save alias this type to detect recursion
Type *att2; // Save alias this type to detect recursion
BinExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *semanticp(Scope *sc);
Expression *checkComplexOpAssign(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *scaleFactor(Scope *sc);
Expression *typeCombine(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
int isunsigned();
Expression *incompatibleTypes();
void dump(int indent);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp);
Expression *interpretCompareCommon(InterState *istate, CtfeGoal goal, fp2_t fp);
Expression *interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_t fp, int post = 0);
Expression *interpretFourPointerRelation(InterState *istate, CtfeGoal goal);
virtual Expression *arrayOp(Scope *sc);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
Expression *op_overload(Scope *sc);
Expression *compare_overload(Scope *sc, Identifier *id);
Expression *reorderSettingAAElem(Scope *sc);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
#if IN_DMD
elem *toElemBin(IRState *irs, int op);
#endif
};
class BinAssignExp : public BinExp
{
public:
BinAssignExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2)
: BinExp(loc, op, size, e1, e2)
{
}
Expression *semantic(Scope *sc);
Expression *arrayOp(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *op_overload(Scope *sc);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *ex);
Expression *modifiableLvalue(Scope *sc, Expression *e);
};
/****************************************************************/
class CompileExp : public UnaExp
{
public:
CompileExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
class FileExp : public UnaExp
{
public:
FileExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
class AssertExp : public UnaExp
{
public:
Expression *msg;
AssertExp(Loc loc, Expression *e, Expression *msg = NULL);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
elem *toElem(IRState *irs);
};
class DotIdExp : public UnaExp
{
public:
Identifier *ident;
DotIdExp(Loc loc, Expression *e, Identifier *ident);
Expression *semantic(Scope *sc);
Expression *semanticX(Scope *sc);
Expression *semanticY(Scope *sc, int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int i);
};
class DotTemplateExp : public UnaExp
{
public:
TemplateDeclaration *td;
DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
class DotVarExp : public UnaExp
{
public:
Declaration *var;
bool hasOverloads;
DotVarExp(Loc loc, Expression *e, Declaration *var, bool hasOverloads = false);
Expression *semantic(Scope *sc);
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
elem *toElem(IRState *irs);
#if IN_LLVM
void cacheLvalue(IRState* irs);
#endif
};
class DotTemplateInstanceExp : public UnaExp
{
public:
TemplateInstance *ti;
DotTemplateInstanceExp(Loc loc, Expression *e, Identifier *name, Objects *tiargs);
Expression *syntaxCopy();
bool findTempDecl(Scope *sc);
Expression *semantic(Scope *sc);
Expression *semanticY(Scope *sc, int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
};
class DelegateExp : public UnaExp
{
public:
FuncDeclaration *func;
bool hasOverloads;
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func, bool hasOverloads = false);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
int inlineCost3(InlineCostState *ics);
elem *toElem(IRState *irs);
};
class DotTypeExp : public UnaExp
{
public:
Dsymbol *sym; // symbol that represents a type
DotTypeExp(Loc loc, Expression *e, Dsymbol *sym);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
};
class CallExp : public UnaExp
{
public:
Expressions *arguments; // function arguments
FuncDeclaration *f; // symbol to call
CallExp(Loc loc, Expression *e, Expressions *exps);
CallExp(Loc loc, Expression *e);
CallExp(Loc loc, Expression *e, Expression *earg1);
CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
elem *toElem(IRState *irs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *addDtorHook(Scope *sc);
MATCH implicitConvTo(Type *t);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
#if IN_LLVM
void cacheLvalue(IRState* p);
#endif
};
class AddrExp : public UnaExp
{
public:
AddrExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
void checkEscape();
elem *toElem(IRState *irs);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
class PtrExp : public UnaExp
{
public:
PtrExp(Loc loc, Expression *e);
PtrExp(Loc loc, Expression *e, Type *t);
Expression *semantic(Scope *sc);
void checkEscapeRef();
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
// For operator overloading
Identifier *opId();
#if IN_LLVM
void cacheLvalue(IRState* irs);
#endif
};
class NegExp : public UnaExp
{
public:
NegExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
elem *toElem(IRState *irs);
};
class UAddExp : public UnaExp
{
public:
UAddExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
// For operator overloading
Identifier *opId();
};
class ComExp : public UnaExp
{
public:
ComExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
elem *toElem(IRState *irs);
};
class NotExp : public UnaExp
{
public:
NotExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
int isBit();
elem *toElem(IRState *irs);
};
class BoolExp : public UnaExp
{
public:
BoolExp(Loc loc, Expression *e, Type *type);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
int isBit();
elem *toElem(IRState *irs);
};
class DeleteExp : public UnaExp
{
public:
DeleteExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *checkToBoolean(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
};
class CastExp : public UnaExp
{
public:
// Possible to cast to one type while painting to another type
Type *to; // type to cast to
unsigned mod; // MODxxxxx
CastExp(Loc loc, Expression *e, Type *t);
CastExp(Loc loc, Expression *e, unsigned mod);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
MATCH implicitConvTo(Type *t);
IntRange getIntRange();
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void checkEscape();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
elem *toElem(IRState *irs);
// For operator overloading
Identifier *opId();
Expression *op_overload(Scope *sc);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
class VectorExp : public UnaExp
{
public:
TypeVector *to; // the target vector type before semantic()
unsigned dim; // number of elements in the vector
VectorExp(Loc loc, Expression *e, Type *t);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
#if IN_DMD
dt_t **toDt(dt_t **pdt);
#endif
};
class SliceExp : public UnaExp
{
public:
Expression *upr; // NULL if implicit 0
Expression *lwr; // NULL if implicit [length - 1]
VarDeclaration *lengthVar;
SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
void checkEscape();
void checkEscapeRef();
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Type *toStaticArrayType();
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void dump(int indent);
elem *toElem(IRState *irs);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
class ArrayLengthExp : public UnaExp
{
public:
ArrayLengthExp(Loc loc, Expression *e1);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
static Expression *rewriteOpAssign(BinExp *exp);
};
// e1[a0,a1,a2,a3,...]
class ArrayExp : public UnaExp
{
public:
Expressions *arguments; // Array of Expression's
size_t currentDimension; // for opDollar
VarDeclaration *lengthVar;
ArrayExp(Loc loc, Expression *e1, Expressions *arguments);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
// For operator overloading
Identifier *opId();
Expression *op_overload(Scope *sc);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
/****************************************************************/
class DotExp : public BinExp
{
public:
DotExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
class CommaExp : public BinExp
{
public:
CommaExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
void checkEscape();
void checkEscapeRef();
int checkModifiable(Scope *sc, int flag);
IntRange getIntRange();
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int isBool(int result);
MATCH implicitConvTo(Type *t);
Expression *addDtorHook(Scope *sc);
Expression *castTo(Scope *sc, Type *t);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
elem *toElem(IRState *irs);
#if IN_LLVM
void cacheLvalue(IRState* irs);
#endif
};
class IndexExp : public BinExp
{
public:
VarDeclaration *lengthVar;
int modifiable;
bool skipboundscheck;
IndexExp(Loc loc, Expression *e1, Expression *e2);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *doInline(InlineDoState *ids);
elem *toElem(IRState *irs);
#if IN_LLVM
void cacheLvalue(IRState* irs);
#endif
};
/* For both i++ and i--
*/
class PostExp : public BinExp
{
public:
PostExp(TOK op, Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Identifier *opId(); // For operator overloading
elem *toElem(IRState *irs);
};
/* For both ++i and --i
*/
class PreExp : public UnaExp
{
public:
PreExp(TOK op, Loc loc, Expression *e);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
class AssignExp : public BinExp
{
public:
int ismemset; // !=0 if setting the contents of an array
AssignExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *checkToBoolean(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Identifier *opId(); // For operator overloading
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
elem *toElem(IRState *irs);
#if IN_LLVM
virtual AssignExp* isAssignExp() { return this; }
#endif
};
class ConstructExp : public AssignExp
{
public:
ConstructExp(Loc loc, Expression *e1, Expression *e2);
};
#define ASSIGNEXP(op) \
class op##AssignExp : public BinAssignExp \
{ \
public: \
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
S(Expression *semantic(Scope *sc);) \
\
Identifier *opId(); /* For operator overloading */ \
\
elem *toElem(IRState *irs); \
};
#define X(a) a
#define S(a)
ASSIGNEXP(Add)
ASSIGNEXP(Min)
ASSIGNEXP(Mul)
ASSIGNEXP(Div)
ASSIGNEXP(Mod)
ASSIGNEXP(And)
ASSIGNEXP(Or)
ASSIGNEXP(Xor)
#undef S
#if DMDV2
#define S(a) a
ASSIGNEXP(Pow)
#undef S
#endif
#undef S
#undef X
#define X(a)
#define S(a)
ASSIGNEXP(Shl)
ASSIGNEXP(Shr)
ASSIGNEXP(Ushr)
#undef S
#define S(a) a
ASSIGNEXP(Cat)
#undef S
#undef X
#undef ASSIGNEXP
class AddExp : public BinExp
{
public:
AddExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
IntRange getIntRange();
// For operator overloading
int isCommutative();
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
#if IN_LLVM
llvm::Constant *toConstElem(IRState* p);
#endif
};
class MinExp : public BinExp
{
public:
MinExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
#if IN_LLVM
llvm::Constant *toConstElem(IRState* p);
#endif
};
class CatExp : public BinExp
{
public:
CatExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
// For operator overloading
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class MulExp : public BinExp
{
public:
MulExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
IntRange getIntRange();
// For operator overloading
int isCommutative();
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class DivExp : public BinExp
{
public:
DivExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class ModExp : public BinExp
{
public:
ModExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
#if DMDV2
class PowExp : public BinExp
{
public:
PowExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
// For operator overloading
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
#endif
class ShlExp : public BinExp
{
public:
ShlExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class ShrExp : public BinExp
{
public:
ShrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class UshrExp : public BinExp
{
public:
UshrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class AndExp : public BinExp
{
public:
AndExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
IntRange getIntRange();
// For operator overloading
int isCommutative();
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class OrExp : public BinExp
{
public:
OrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
MATCH implicitConvTo(Type *t);
IntRange getIntRange();
// For operator overloading
int isCommutative();
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class XorExp : public BinExp
{
public:
XorExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
MATCH implicitConvTo(Type *t);
IntRange getIntRange();
// For operator overloading
int isCommutative();
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class OrOrExp : public BinExp
{
public:
OrOrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *checkToBoolean(Scope *sc);
int isBit();
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
elem *toElem(IRState *irs);
};
class AndAndExp : public BinExp
{
public:
AndAndExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *checkToBoolean(Scope *sc);
int isBit();
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
elem *toElem(IRState *irs);
};
class CmpExp : public BinExp
{
public:
CmpExp(TOK op, Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
int isBit();
// For operator overloading
int isCommutative();
Identifier *opId();
Expression *op_overload(Scope *sc);
elem *toElem(IRState *irs);
};
class InExp : public BinExp
{
public:
InExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
// For operator overloading
Identifier *opId();
Identifier *opId_r();
elem *toElem(IRState *irs);
};
class RemoveExp : public BinExp
{
public:
RemoveExp(Loc loc, Expression *e1, Expression *e2);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
};
// == and !=
class EqualExp : public BinExp
{
public:
EqualExp(TOK op, Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
int isBit();
// For operator overloading
int isCommutative();
Identifier *opId();
Expression *op_overload(Scope *sc);
elem *toElem(IRState *irs);
};
// is and !is
class IdentityExp : public BinExp
{
public:
IdentityExp(TOK op, Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
int isBit();
Expression *optimize(int result, bool keepLvalue = false);
elem *toElem(IRState *irs);
};
/****************************************************************/
class CondExp : public BinExp
{
public:
Expression *econd;
CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void checkEscape();
void checkEscapeRef();
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
Expression *checkToBoolean(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
elem *toElem(IRState *irs);
};
#if DMDV2
/****************************************************************/
class DefaultInitExp : public Expression
{
public:
TOK subop; // which of the derived classes this is
DefaultInitExp(Loc loc, TOK subop, int size);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
class FileInitExp : public DefaultInitExp
{
public:
FileInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolveLoc(Loc loc, Scope *sc);
};
class LineInitExp : public DefaultInitExp
{
public:
LineInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolveLoc(Loc loc, Scope *sc);
};
class ModuleInitExp : public DefaultInitExp
{
public:
ModuleInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolveLoc(Loc loc, Scope *sc);
};
class FuncInitExp : public DefaultInitExp
{
public:
FuncInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolveLoc(Loc loc, Scope *sc);
};
class PrettyFuncInitExp : public DefaultInitExp
{
public:
PrettyFuncInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolveLoc(Loc loc, Scope *sc);
};
#endif
/****************************************************************/
#if IN_LLVM
// this stuff is strictly LDC
struct GEPExp : UnaExp
{
unsigned index;
Identifier* ident;
GEPExp(Loc loc, Expression* e, Identifier* id, unsigned idx);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *toLvalue(Scope *sc, Expression *e);
DValue* toElem(IRState* irs);
};
#endif
/****************************************************************/
/* Special values used by the interpreter
*/
extern Expression *EXP_CANT_INTERPRET;
extern Expression *EXP_CONTINUE_INTERPRET;
extern Expression *EXP_BREAK_INTERPRET;
extern Expression *EXP_GOTO_INTERPRET;
extern Expression *EXP_VOID_INTERPRET;
Expression *expType(Type *type, Expression *e);
Expression *Neg(Type *type, Expression *e1);
Expression *Com(Type *type, Expression *e1);
Expression *Not(Type *type, Expression *e1);
Expression *Bool(Type *type, Expression *e1);
Expression *Cast(Type *type, Type *to, Expression *e1);
Expression *ArrayLength(Type *type, Expression *e1);
Expression *Ptr(Type *type, Expression *e1);
Expression *Add(Type *type, Expression *e1, Expression *e2);
Expression *Min(Type *type, Expression *e1, Expression *e2);
Expression *Mul(Type *type, Expression *e1, Expression *e2);
Expression *Div(Type *type, Expression *e1, Expression *e2);
Expression *Mod(Type *type, Expression *e1, Expression *e2);
Expression *Pow(Type *type, Expression *e1, Expression *e2);
Expression *Shl(Type *type, Expression *e1, Expression *e2);
Expression *Shr(Type *type, Expression *e1, Expression *e2);
Expression *Ushr(Type *type, Expression *e1, Expression *e2);
Expression *And(Type *type, Expression *e1, Expression *e2);
Expression *Or(Type *type, Expression *e1, Expression *e2);
Expression *Xor(Type *type, Expression *e1, Expression *e2);
Expression *Index(Type *type, Expression *e1, Expression *e2);
Expression *Cat(Type *type, Expression *e1, Expression *e2);
Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2);
Expression *Cmp(TOK op, Type *type, Expression *e1, Expression *e2);
Expression *Identity(TOK op, Type *type, Expression *e1, Expression *e2);
Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr);
// Const-folding functions used by CTFE
void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, size_t firstIndex);
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, size_t firstIndex);
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_t firstIndex);
int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len);
int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len);
#endif /* DMD_EXPRESSION_H */