Break dependency of expression.d on ctfeexp.d

This commit is contained in:
RazvanN7 2023-11-07 11:50:56 +02:00 committed by The Dlang Bot
parent 14b5325a64
commit 38173e34b4
5 changed files with 646 additions and 653 deletions

View file

@ -15,6 +15,7 @@ import core.stdc.string;
import dmd.astenums;
import dmd.arraytypes;
import dmd.ctfeexpr;
import dmd.dmodule;
import dmd.errors;
import dmd.expression;

View file

@ -35,75 +35,98 @@ import dmd.root.rmem;
import dmd.tokens;
import dmd.visitor;
/***********************************************************
* A reference to a class, or an interface. We need this when we
* point to a base class (we must record what the type is).
/****************************************************************/
/* A type meant as a union of all the Expression types,
* to serve essentially as a Variant that will sit on the stack
* during CTFE to reduce memory consumption.
*/
extern (C++) final class ClassReferenceExp : Expression
extern (D) struct UnionExp
{
StructLiteralExp value;
extern (D) this(const ref Loc loc, StructLiteralExp lit, Type type) @safe
// yes, default constructor does nothing
extern (D) this(Expression e)
{
super(loc, EXP.classReference);
assert(lit && lit.sd && lit.sd.isClassDeclaration());
this.value = lit;
this.type = type;
memcpy(&this, cast(void*)e, e.size);
}
ClassDeclaration originalClass()
/* Extract pointer to Expression
*/
extern (D) Expression exp() return
{
return value.sd.isClassDeclaration();
return cast(Expression)&u;
}
// Return index of the field, or -1 if not found
private int getFieldIndex(Type fieldtype, uint fieldoffset)
/* Convert to an allocated Expression
*/
extern (D) Expression copy()
{
ClassDeclaration cd = originalClass();
uint fieldsSoFar = 0;
for (size_t j = 0; j < value.elements.length; j++)
Expression e = exp();
//if (e.size > sizeof(u)) printf("%s\n", EXPtoString(e.op).ptr);
assert(e.size <= u.sizeof);
switch (e.op)
{
while (j - fieldsSoFar >= cd.fields.length)
{
fieldsSoFar += cd.fields.length;
cd = cd.baseClass;
}
VarDeclaration v2 = cd.fields[j - fieldsSoFar];
if (fieldoffset == v2.offset && fieldtype.size() == v2.type.size())
{
return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar));
}
case EXP.cantExpression: return CTFEExp.cantexp;
case EXP.voidExpression: return CTFEExp.voidexp;
case EXP.break_: return CTFEExp.breakexp;
case EXP.continue_: return CTFEExp.continueexp;
case EXP.goto_: return CTFEExp.gotoexp;
default: return e.copy();
}
return -1;
}
// Return index of the field, or -1 if not found
// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
int findFieldIndexByName(VarDeclaration v)
private:
// Ensure that the union is suitably aligned.
align(8) union _AnonStruct_u
{
ClassDeclaration cd = originalClass();
size_t fieldsSoFar = 0;
for (size_t j = 0; j < value.elements.length; j++)
{
while (j - fieldsSoFar >= cd.fields.length)
{
fieldsSoFar += cd.fields.length;
cd = cd.baseClass;
}
VarDeclaration v2 = cd.fields[j - fieldsSoFar];
if (v == v2)
{
return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar));
}
}
return -1;
char[__traits(classInstanceSize, Expression)] exp;
char[__traits(classInstanceSize, IntegerExp)] integerexp;
char[__traits(classInstanceSize, ErrorExp)] errorexp;
char[__traits(classInstanceSize, RealExp)] realexp;
char[__traits(classInstanceSize, ComplexExp)] complexexp;
char[__traits(classInstanceSize, SymOffExp)] symoffexp;
char[__traits(classInstanceSize, StringExp)] stringexp;
char[__traits(classInstanceSize, ArrayLiteralExp)] arrayliteralexp;
char[__traits(classInstanceSize, AssocArrayLiteralExp)] assocarrayliteralexp;
char[__traits(classInstanceSize, StructLiteralExp)] structliteralexp;
char[__traits(classInstanceSize, CompoundLiteralExp)] compoundliteralexp;
char[__traits(classInstanceSize, NullExp)] nullexp;
char[__traits(classInstanceSize, DotVarExp)] dotvarexp;
char[__traits(classInstanceSize, AddrExp)] addrexp;
char[__traits(classInstanceSize, IndexExp)] indexexp;
char[__traits(classInstanceSize, SliceExp)] sliceexp;
char[__traits(classInstanceSize, VectorExp)] vectorexp;
}
override void accept(Visitor v)
{
v.visit(this);
}
_AnonStruct_u u;
}
void emplaceExp(T : Expression, Args...)(void* p, Args args)
{
static if (__VERSION__ < 2099)
const init = typeid(T).initializer;
else
const init = __traits(initSymbol, T);
p[0 .. __traits(classInstanceSize, T)] = init[];
(cast(T)p).__ctor(args);
}
void emplaceExp(T : UnionExp)(T* p, Expression e)
{
memcpy(p, cast(void*)e, e.size);
}
// Generate an error message when this exception is not caught
void generateUncaughtError(ThrownExceptionExp tee)
{
UnionExp ue = void;
Expression e = resolveSlice((*tee.thrown.value.elements)[0], &ue);
StringExp se = e.toStringExp();
error(tee.thrown.loc, "uncaught CTFE exception `%s(%s)`", tee.thrown.type.toChars(), se ? se.toChars() : e.toChars());
/* Also give the line where the throw statement was. We won't have it
* in the case where the ThrowStatement is generated internally
* (eg, in ScopeStatement)
*/
if (tee.loc.isValid() && !tee.loc.equals(tee.thrown.loc))
.errorSupplemental(tee.loc, "thrown from here");
}
/*************************
@ -121,100 +144,6 @@ int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pur
return -1;
}
/***********************************************************
* Fake class which holds the thrown exception.
* Used for implementing exception handling.
*/
extern (C++) final class ThrownExceptionExp : Expression
{
ClassReferenceExp thrown; // the thing being tossed
extern (D) this(const ref Loc loc, ClassReferenceExp victim) @safe
{
super(loc, EXP.thrownException);
this.thrown = victim;
this.type = victim.type;
}
override const(char)* toChars() const
{
return "CTFE ThrownException";
}
// Generate an error message when this exception is not caught
extern (D) void generateUncaughtError()
{
UnionExp ue = void;
Expression e = resolveSlice((*thrown.value.elements)[0], &ue);
StringExp se = e.toStringExp();
error(thrown.loc, "uncaught CTFE exception `%s(%s)`", thrown.type.toChars(), se ? se.toChars() : e.toChars());
/* Also give the line where the throw statement was. We won't have it
* in the case where the ThrowStatement is generated internally
* (eg, in ScopeStatement)
*/
if (loc.isValid() && !loc.equals(thrown.loc))
.errorSupplemental(loc, "thrown from here");
}
override void accept(Visitor v)
{
v.visit(this);
}
}
/***********************************************************
* This type is only used by the interpreter.
*/
extern (C++) final class CTFEExp : Expression
{
extern (D) this(EXP tok)
{
super(Loc.initial, tok);
type = Type.tvoid;
}
override const(char)* toChars() const
{
switch (op)
{
case EXP.cantExpression:
return "<cant>";
case EXP.voidExpression:
return "cast(void)0";
case EXP.showCtfeContext:
return "<error>";
case EXP.break_:
return "<break>";
case EXP.continue_:
return "<continue>";
case EXP.goto_:
return "<goto>";
default:
assert(0);
}
}
extern (D) __gshared CTFEExp cantexp;
extern (D) __gshared CTFEExp voidexp;
extern (D) __gshared CTFEExp breakexp;
extern (D) __gshared CTFEExp continueexp;
extern (D) __gshared CTFEExp gotoexp;
/* Used when additional information is needed regarding
* a ctfe error.
*/
extern (D) __gshared CTFEExp showcontext;
extern (D) static bool isCantExp(const Expression e) @safe
{
return e && e.op == EXP.cantExpression;
}
extern (D) static bool isGotoExp(const Expression e) @safe
{
return e && e.op == EXP.goto_;
}
}
// True if 'e' is CTFEExp::cantexp, or an exception
bool exceptionOrCantInterpret(const Expression e) @safe
{

View file

@ -18,14 +18,10 @@ import core.stdc.stdio;
import core.stdc.string;
import dmd.aggregate;
import dmd.aliasthis;
import dmd.arrayop;
import dmd.arraytypes;
import dmd.astenums;
import dmd.ast_node;
import dmd.gluelayer;
import dmd.ctfeexpr;
import dmd.ctorflow;
import dmd.dclass;
import dmd.declaration;
import dmd.dimport;
@ -43,39 +39,21 @@ import dmd.identifier;
import dmd.init;
import dmd.location;
import dmd.mtype;
import dmd.opover;
import dmd.optimize;
import dmd.root.complex;
import dmd.root.ctfloat;
import dmd.root.filename;
import dmd.common.outbuffer;
import dmd.root.optional;
import dmd.root.rmem;
import dmd.rootobject;
import dmd.root.string;
import dmd.root.utf;
import dmd.safe;
import dmd.target;
import dmd.tokens;
import dmd.visitor;
enum LOGSEMANTIC = false;
void emplaceExp(T : Expression, Args...)(void* p, Args args)
{
static if (__VERSION__ < 2099)
const init = typeid(T).initializer;
else
const init = __traits(initSymbol, T);
p[0 .. __traits(classInstanceSize, T)] = init[];
(cast(T)p).__ctor(args);
}
void emplaceExp(T : UnionExp)(T* p, Expression e)
{
memcpy(p, cast(void*)e, e.size);
}
/// Return value for `checkModifiable`
enum Modifiable
{
@ -274,70 +252,6 @@ TemplateDeclaration getFuncTemplateDecl(Dsymbol s) @safe
return null;
}
/****************************************************************/
/* A type meant as a union of all the Expression types,
* to serve essentially as a Variant that will sit on the stack
* during CTFE to reduce memory consumption.
*/
extern (D) struct UnionExp
{
// yes, default constructor does nothing
extern (D) this(Expression e)
{
memcpy(&this, cast(void*)e, e.size);
}
/* Extract pointer to Expression
*/
extern (D) Expression exp() return
{
return cast(Expression)&u;
}
/* Convert to an allocated Expression
*/
extern (D) Expression copy()
{
Expression e = exp();
//if (e.size > sizeof(u)) printf("%s\n", EXPtoString(e.op).ptr);
assert(e.size <= u.sizeof);
switch (e.op)
{
case EXP.cantExpression: return CTFEExp.cantexp;
case EXP.voidExpression: return CTFEExp.voidexp;
case EXP.break_: return CTFEExp.breakexp;
case EXP.continue_: return CTFEExp.continueexp;
case EXP.goto_: return CTFEExp.gotoexp;
default: return e.copy();
}
}
private:
// Ensure that the union is suitably aligned.
align(8) union _AnonStruct_u
{
char[__traits(classInstanceSize, Expression)] exp;
char[__traits(classInstanceSize, IntegerExp)] integerexp;
char[__traits(classInstanceSize, ErrorExp)] errorexp;
char[__traits(classInstanceSize, RealExp)] realexp;
char[__traits(classInstanceSize, ComplexExp)] complexexp;
char[__traits(classInstanceSize, SymOffExp)] symoffexp;
char[__traits(classInstanceSize, StringExp)] stringexp;
char[__traits(classInstanceSize, ArrayLiteralExp)] arrayliteralexp;
char[__traits(classInstanceSize, AssocArrayLiteralExp)] assocarrayliteralexp;
char[__traits(classInstanceSize, StructLiteralExp)] structliteralexp;
char[__traits(classInstanceSize, CompoundLiteralExp)] compoundliteralexp;
char[__traits(classInstanceSize, NullExp)] nullexp;
char[__traits(classInstanceSize, DotVarExp)] dotvarexp;
char[__traits(classInstanceSize, AddrExp)] addrexp;
char[__traits(classInstanceSize, IndexExp)] indexexp;
char[__traits(classInstanceSize, SliceExp)] sliceexp;
char[__traits(classInstanceSize, VectorExp)] vectorexp;
}
_AnonStruct_u u;
}
/************************ TypeDotIdExp ************************************/
/* Things like:
* int.size
@ -1195,7 +1109,7 @@ extern (C++) final class IntegerExp : Expression
*/
extern (C++) final class ErrorExp : Expression
{
private extern (D) this()
extern (D) this()
{
super(Loc.initial, EXP.error);
type = Type.terror;
@ -5262,6 +5176,155 @@ extern (C++) final class PrettyFuncInitExp : DefaultInitExp
}
}
/***********************************************************
* A reference to a class, or an interface. We need this when we
* point to a base class (we must record what the type is).
*/
extern (C++) final class ClassReferenceExp : Expression
{
StructLiteralExp value;
extern (D) this(const ref Loc loc, StructLiteralExp lit, Type type) @safe
{
super(loc, EXP.classReference);
assert(lit && lit.sd && lit.sd.isClassDeclaration());
this.value = lit;
this.type = type;
}
ClassDeclaration originalClass()
{
return value.sd.isClassDeclaration();
}
// Return index of the field, or -1 if not found
int getFieldIndex(Type fieldtype, uint fieldoffset)
{
ClassDeclaration cd = originalClass();
uint fieldsSoFar = 0;
for (size_t j = 0; j < value.elements.length; j++)
{
while (j - fieldsSoFar >= cd.fields.length)
{
fieldsSoFar += cd.fields.length;
cd = cd.baseClass;
}
VarDeclaration v2 = cd.fields[j - fieldsSoFar];
if (fieldoffset == v2.offset && fieldtype.size() == v2.type.size())
{
return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar));
}
}
return -1;
}
// Return index of the field, or -1 if not found
// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
int findFieldIndexByName(VarDeclaration v)
{
ClassDeclaration cd = originalClass();
size_t fieldsSoFar = 0;
for (size_t j = 0; j < value.elements.length; j++)
{
while (j - fieldsSoFar >= cd.fields.length)
{
fieldsSoFar += cd.fields.length;
cd = cd.baseClass;
}
VarDeclaration v2 = cd.fields[j - fieldsSoFar];
if (v == v2)
{
return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar));
}
}
return -1;
}
override void accept(Visitor v)
{
v.visit(this);
}
}
/***********************************************************
* This type is only used by the interpreter.
*/
extern (C++) final class CTFEExp : Expression
{
extern (D) this(EXP tok)
{
super(Loc.initial, tok);
type = Type.tvoid;
}
override const(char)* toChars() const
{
switch (op)
{
case EXP.cantExpression:
return "<cant>";
case EXP.voidExpression:
return "cast(void)0";
case EXP.showCtfeContext:
return "<error>";
case EXP.break_:
return "<break>";
case EXP.continue_:
return "<continue>";
case EXP.goto_:
return "<goto>";
default:
assert(0);
}
}
extern (D) __gshared CTFEExp cantexp;
extern (D) __gshared CTFEExp voidexp;
extern (D) __gshared CTFEExp breakexp;
extern (D) __gshared CTFEExp continueexp;
extern (D) __gshared CTFEExp gotoexp;
/* Used when additional information is needed regarding
* a ctfe error.
*/
extern (D) __gshared CTFEExp showcontext;
extern (D) static bool isCantExp(const Expression e) @safe
{
return e && e.op == EXP.cantExpression;
}
extern (D) static bool isGotoExp(const Expression e) @safe
{
return e && e.op == EXP.goto_;
}
}
/***********************************************************
* Fake class which holds the thrown exception.
* Used for implementing exception handling.
*/
extern (C++) final class ThrownExceptionExp : Expression
{
ClassReferenceExp thrown; // the thing being tossed
extern (D) this(const ref Loc loc, ClassReferenceExp victim) @safe
{
super(loc, EXP.thrownException);
this.thrown = victim;
this.type = victim.type;
}
override const(char)* toChars() const
{
return "CTFE ThrownException";
}
override void accept(Visitor v)
{
v.visit(this);
}
}
/**
* Objective-C class reference expression.
*

View file

@ -117,6 +117,56 @@ class StaticIfCondition;
class ForeachStatement;
class ForeachRangeStatement;
struct OutBuffer;
class TypeInfoClassDeclaration;
class Initializer;
struct IntRange;
struct ModuleDeclaration;
template <typename Datum>
struct FileMapping;
struct Escape;
class ErrorSink;
class LabelStatement;
class SwitchStatement;
class Statement;
class TryFinallyStatement;
class ScopeGuardStatement;
struct DocComment;
class WithStatement;
struct AA;
class Tuple;
class Parameter;
class TemplateParameter;
struct TemplatePrevious;
struct TYPE;
class TypeBasic;
class TypeFunction;
class TypeError;
class TypeVector;
class TypeSArray;
class TypeDArray;
class TypeAArray;
class TypePointer;
class TypeReference;
class TypeDelegate;
class TypeIdentifier;
class TypeInstance;
class TypeTypeof;
class TypeReturn;
class TypeStruct;
class TypeEnum;
class TypeClass;
class TypeSlice;
class TypeNull;
class TypeMixin;
class TypeTraits;
class TypeNoreturn;
class TypeTag;
class TemplateTypeParameter;
class TemplateValueParameter;
class TemplateAliasParameter;
class TemplateThisParameter;
class TemplateTupleParameter;
class TypeQualified;
class StringExp;
class IntegerExp;
class ErrorExp;
@ -231,56 +281,6 @@ class ThrownExceptionExp;
class UnaExp;
class BinExp;
class BinAssignExp;
class TypeInfoClassDeclaration;
class Initializer;
struct IntRange;
struct ModuleDeclaration;
template <typename Datum>
struct FileMapping;
struct Escape;
class ErrorSink;
class LabelStatement;
class SwitchStatement;
class Statement;
class TryFinallyStatement;
class ScopeGuardStatement;
struct DocComment;
class WithStatement;
struct AA;
class Tuple;
class Parameter;
class TemplateParameter;
struct TemplatePrevious;
struct TYPE;
class TypeBasic;
class TypeFunction;
class TypeError;
class TypeVector;
class TypeSArray;
class TypeDArray;
class TypeAArray;
class TypePointer;
class TypeReference;
class TypeDelegate;
class TypeIdentifier;
class TypeInstance;
class TypeTypeof;
class TypeReturn;
class TypeStruct;
class TypeEnum;
class TypeClass;
class TypeSlice;
class TypeNull;
class TypeMixin;
class TypeTraits;
class TypeNoreturn;
class TypeTag;
class TemplateTypeParameter;
class TemplateValueParameter;
class TemplateAliasParameter;
class TemplateThisParameter;
class TemplateTupleParameter;
class TypeQualified;
class CaseStatement;
class Catch;
struct Designator;
@ -789,310 +789,6 @@ public:
}
};
enum class EXP : uint8_t
{
reserved = 0u,
negate = 1u,
cast_ = 2u,
null_ = 3u,
assert_ = 4u,
array = 5u,
call = 6u,
address = 7u,
type = 8u,
throw_ = 9u,
new_ = 10u,
delete_ = 11u,
star = 12u,
symbolOffset = 13u,
variable = 14u,
dotVariable = 15u,
dotIdentifier = 16u,
dotTemplateInstance = 17u,
dotType = 18u,
slice = 19u,
arrayLength = 20u,
dollar = 21u,
template_ = 22u,
dotTemplateDeclaration = 23u,
declaration = 24u,
dSymbol = 25u,
typeid_ = 26u,
uadd = 27u,
remove = 28u,
newAnonymousClass = 29u,
arrayLiteral = 30u,
assocArrayLiteral = 31u,
structLiteral = 32u,
classReference = 33u,
thrownException = 34u,
delegatePointer = 35u,
delegateFunctionPointer = 36u,
lessThan = 37u,
greaterThan = 38u,
lessOrEqual = 39u,
greaterOrEqual = 40u,
equal = 41u,
notEqual = 42u,
identity = 43u,
notIdentity = 44u,
index = 45u,
is_ = 46u,
leftShift = 47u,
rightShift = 48u,
leftShiftAssign = 49u,
rightShiftAssign = 50u,
unsignedRightShift = 51u,
unsignedRightShiftAssign = 52u,
concatenate = 53u,
concatenateAssign = 54u,
concatenateElemAssign = 55u,
concatenateDcharAssign = 56u,
add = 57u,
min = 58u,
addAssign = 59u,
minAssign = 60u,
mul = 61u,
div = 62u,
mod = 63u,
mulAssign = 64u,
divAssign = 65u,
modAssign = 66u,
and_ = 67u,
or_ = 68u,
xor_ = 69u,
andAssign = 70u,
orAssign = 71u,
xorAssign = 72u,
assign = 73u,
not_ = 74u,
tilde = 75u,
plusPlus = 76u,
minusMinus = 77u,
construct = 78u,
blit = 79u,
dot = 80u,
comma = 81u,
question = 82u,
andAnd = 83u,
orOr = 84u,
prePlusPlus = 85u,
preMinusMinus = 86u,
identifier = 87u,
string_ = 88u,
this_ = 89u,
super_ = 90u,
halt = 91u,
tuple = 92u,
error = 93u,
void_ = 94u,
int64 = 95u,
float64 = 96u,
complex80 = 97u,
import_ = 98u,
delegate_ = 99u,
function_ = 100u,
mixin_ = 101u,
in_ = 102u,
break_ = 103u,
continue_ = 104u,
goto_ = 105u,
scope_ = 106u,
traits = 107u,
overloadSet = 108u,
line = 109u,
file = 110u,
fileFullPath = 111u,
moduleString = 112u,
functionString = 113u,
prettyFunction = 114u,
pow = 115u,
powAssign = 116u,
vector = 117u,
voidExpression = 118u,
cantExpression = 119u,
showCtfeContext = 120u,
objcClassReference = 121u,
vectorArray = 122u,
compoundLiteral = 123u,
_Generic_ = 124u,
interval = 125u,
loweredAssignExp = 126u,
};
typedef uint64_t dinteger_t;
struct complex_t final
{
_d_real re;
_d_real im;
complex_t() = delete;
complex_t(_d_real re);
complex_t(_d_real re, _d_real im);
int32_t opEquals(complex_t y) const;
};
template <typename T>
struct Optional final
{
T value;
bool present;
Optional(T value);
static Optional<T > create(T val);
bool isPresent() const;
bool isEmpty() const;
T get();
bool hasValue(T exp) const;
Optional()
{
}
};
class Expression : public ASTNode
{
public:
Type* type;
Loc loc;
const EXP op;
size_t size() const;
static void _init();
static void deinitialize();
virtual Expression* syntaxCopy();
DYNCAST dyncast() const final override;
const char* toChars() const override;
virtual dinteger_t toInteger();
virtual uinteger_t toUInteger();
virtual _d_real toReal();
virtual _d_real toImaginary();
virtual complex_t toComplex();
virtual StringExp* toStringExp();
virtual bool isLvalue();
virtual bool checkType();
virtual bool checkValue();
Expression* addressOf();
Expression* deref();
Expression* optimize(int32_t result, bool keepLvalue = false);
int32_t isConst();
virtual bool isIdentical(const Expression* const e) const;
virtual Optional<bool > toBool();
virtual bool hasCode();
IntegerExp* isIntegerExp();
ErrorExp* isErrorExp();
VoidInitExp* isVoidInitExp();
RealExp* isRealExp();
ComplexExp* isComplexExp();
IdentifierExp* isIdentifierExp();
DollarExp* isDollarExp();
DsymbolExp* isDsymbolExp();
ThisExp* isThisExp();
SuperExp* isSuperExp();
NullExp* isNullExp();
StringExp* isStringExp();
TupleExp* isTupleExp();
ArrayLiteralExp* isArrayLiteralExp();
AssocArrayLiteralExp* isAssocArrayLiteralExp();
StructLiteralExp* isStructLiteralExp();
CompoundLiteralExp* isCompoundLiteralExp();
TypeExp* isTypeExp();
ScopeExp* isScopeExp();
TemplateExp* isTemplateExp();
NewExp* isNewExp();
NewAnonClassExp* isNewAnonClassExp();
SymOffExp* isSymOffExp();
VarExp* isVarExp();
OverExp* isOverExp();
FuncExp* isFuncExp();
DeclarationExp* isDeclarationExp();
TypeidExp* isTypeidExp();
TraitsExp* isTraitsExp();
HaltExp* isHaltExp();
IsExp* isExp();
MixinExp* isMixinExp();
ImportExp* isImportExp();
AssertExp* isAssertExp();
ThrowExp* isThrowExp();
DotIdExp* isDotIdExp();
DotTemplateExp* isDotTemplateExp();
DotVarExp* isDotVarExp();
DotTemplateInstanceExp* isDotTemplateInstanceExp();
DelegateExp* isDelegateExp();
DotTypeExp* isDotTypeExp();
CallExp* isCallExp();
AddrExp* isAddrExp();
PtrExp* isPtrExp();
NegExp* isNegExp();
UAddExp* isUAddExp();
ComExp* isComExp();
NotExp* isNotExp();
DeleteExp* isDeleteExp();
CastExp* isCastExp();
VectorExp* isVectorExp();
VectorArrayExp* isVectorArrayExp();
SliceExp* isSliceExp();
ArrayLengthExp* isArrayLengthExp();
ArrayExp* isArrayExp();
DotExp* isDotExp();
CommaExp* isCommaExp();
IntervalExp* isIntervalExp();
DelegatePtrExp* isDelegatePtrExp();
DelegateFuncptrExp* isDelegateFuncptrExp();
IndexExp* isIndexExp();
PostExp* isPostExp();
PreExp* isPreExp();
AssignExp* isAssignExp();
LoweredAssignExp* isLoweredAssignExp();
ConstructExp* isConstructExp();
BlitExp* isBlitExp();
AddAssignExp* isAddAssignExp();
MinAssignExp* isMinAssignExp();
MulAssignExp* isMulAssignExp();
DivAssignExp* isDivAssignExp();
ModAssignExp* isModAssignExp();
AndAssignExp* isAndAssignExp();
OrAssignExp* isOrAssignExp();
XorAssignExp* isXorAssignExp();
PowAssignExp* isPowAssignExp();
ShlAssignExp* isShlAssignExp();
ShrAssignExp* isShrAssignExp();
UshrAssignExp* isUshrAssignExp();
CatAssignExp* isCatAssignExp();
CatElemAssignExp* isCatElemAssignExp();
CatDcharAssignExp* isCatDcharAssignExp();
AddExp* isAddExp();
MinExp* isMinExp();
CatExp* isCatExp();
MulExp* isMulExp();
DivExp* isDivExp();
ModExp* isModExp();
PowExp* isPowExp();
ShlExp* isShlExp();
ShrExp* isShrExp();
UshrExp* isUshrExp();
AndExp* isAndExp();
OrExp* isOrExp();
XorExp* isXorExp();
LogicalExp* isLogicalExp();
InExp* isInExp();
RemoveExp* isRemoveExp();
EqualExp* isEqualExp();
IdentityExp* isIdentityExp();
CondExp* isCondExp();
GenericExp* isGenericExp();
DefaultInitExp* isDefaultInitExp();
FileInitExp* isFileInitExp();
LineInitExp* isLineInitExp();
ModuleInitExp* isModuleInitExp();
FuncInitExp* isFuncInitExp();
PrettyFuncInitExp* isPrettyFuncInitExp();
ObjcClassReferenceExp* isObjcClassReferenceExp();
ClassReferenceExp* isClassReferenceExp();
ThrownExceptionExp* isThrownExceptionExp();
UnaExp* isUnaExp();
BinExp* isBinExp();
BinAssignExp* isBinAssignExp();
void accept(Visitor* v) override;
};
enum class MATCH
{
nomatch = 0,
@ -1328,6 +1024,8 @@ enum class Covariant
fwdref = 3,
};
typedef uint64_t dinteger_t;
class Type : public ASTNode
{
public:
@ -1553,6 +1251,163 @@ public:
TypeFunction* toTypeFunction();
};
enum class EXP : uint8_t
{
reserved = 0u,
negate = 1u,
cast_ = 2u,
null_ = 3u,
assert_ = 4u,
array = 5u,
call = 6u,
address = 7u,
type = 8u,
throw_ = 9u,
new_ = 10u,
delete_ = 11u,
star = 12u,
symbolOffset = 13u,
variable = 14u,
dotVariable = 15u,
dotIdentifier = 16u,
dotTemplateInstance = 17u,
dotType = 18u,
slice = 19u,
arrayLength = 20u,
dollar = 21u,
template_ = 22u,
dotTemplateDeclaration = 23u,
declaration = 24u,
dSymbol = 25u,
typeid_ = 26u,
uadd = 27u,
remove = 28u,
newAnonymousClass = 29u,
arrayLiteral = 30u,
assocArrayLiteral = 31u,
structLiteral = 32u,
classReference = 33u,
thrownException = 34u,
delegatePointer = 35u,
delegateFunctionPointer = 36u,
lessThan = 37u,
greaterThan = 38u,
lessOrEqual = 39u,
greaterOrEqual = 40u,
equal = 41u,
notEqual = 42u,
identity = 43u,
notIdentity = 44u,
index = 45u,
is_ = 46u,
leftShift = 47u,
rightShift = 48u,
leftShiftAssign = 49u,
rightShiftAssign = 50u,
unsignedRightShift = 51u,
unsignedRightShiftAssign = 52u,
concatenate = 53u,
concatenateAssign = 54u,
concatenateElemAssign = 55u,
concatenateDcharAssign = 56u,
add = 57u,
min = 58u,
addAssign = 59u,
minAssign = 60u,
mul = 61u,
div = 62u,
mod = 63u,
mulAssign = 64u,
divAssign = 65u,
modAssign = 66u,
and_ = 67u,
or_ = 68u,
xor_ = 69u,
andAssign = 70u,
orAssign = 71u,
xorAssign = 72u,
assign = 73u,
not_ = 74u,
tilde = 75u,
plusPlus = 76u,
minusMinus = 77u,
construct = 78u,
blit = 79u,
dot = 80u,
comma = 81u,
question = 82u,
andAnd = 83u,
orOr = 84u,
prePlusPlus = 85u,
preMinusMinus = 86u,
identifier = 87u,
string_ = 88u,
this_ = 89u,
super_ = 90u,
halt = 91u,
tuple = 92u,
error = 93u,
void_ = 94u,
int64 = 95u,
float64 = 96u,
complex80 = 97u,
import_ = 98u,
delegate_ = 99u,
function_ = 100u,
mixin_ = 101u,
in_ = 102u,
break_ = 103u,
continue_ = 104u,
goto_ = 105u,
scope_ = 106u,
traits = 107u,
overloadSet = 108u,
line = 109u,
file = 110u,
fileFullPath = 111u,
moduleString = 112u,
functionString = 113u,
prettyFunction = 114u,
pow = 115u,
powAssign = 116u,
vector = 117u,
voidExpression = 118u,
cantExpression = 119u,
showCtfeContext = 120u,
objcClassReference = 121u,
vectorArray = 122u,
compoundLiteral = 123u,
_Generic_ = 124u,
interval = 125u,
loweredAssignExp = 126u,
};
struct complex_t final
{
_d_real re;
_d_real im;
complex_t() = delete;
complex_t(_d_real re);
complex_t(_d_real re, _d_real im);
int32_t opEquals(complex_t y) const;
};
template <typename T>
struct Optional final
{
T value;
bool present;
Optional(T value);
static Optional<T > create(T val);
bool isPresent() const;
bool isEmpty() const;
T get();
bool hasValue(T exp) const;
Optional()
{
}
};
enum class OwnedBy : uint8_t
{
code = 0u,
@ -2304,41 +2159,6 @@ enum class ModifyFlags
fieldAssign = 2,
};
struct UnionExp final
{
#pragma pack(push, 8)
private:
union _AnonStruct_u
{
char exp[29LLU];
char integerexp[40LLU];
char errorexp[29LLU];
char realexp[48LLU];
char complexexp[64LLU];
char symoffexp[64LLU];
char stringexp[51LLU];
char arrayliteralexp[48LLU];
char assocarrayliteralexp[56LLU];
char structliteralexp[76LLU];
char compoundliteralexp[40LLU];
char nullexp[29LLU];
char dotvarexp[49LLU];
char addrexp[40LLU];
char indexexp[74LLU];
char sliceexp[65LLU];
char vectorexp[53LLU];
};
#pragma pack(pop)
// Ignoring var u alignment 8
_AnonStruct_u u;
public:
UnionExp() :
u()
{
}
};
enum : int32_t { WANTexpand = 1 };
enum : int32_t { WANTvalue = 0 };
@ -4745,6 +4565,41 @@ extern Type* merge(Type* type);
extern Type* typeSemantic(Type* type, const Loc& loc, Scope* sc);
struct UnionExp final
{
#pragma pack(push, 8)
private:
union _AnonStruct_u
{
char exp[29LLU];
char integerexp[40LLU];
char errorexp[29LLU];
char realexp[48LLU];
char complexexp[64LLU];
char symoffexp[64LLU];
char stringexp[51LLU];
char arrayliteralexp[48LLU];
char assocarrayliteralexp[56LLU];
char structliteralexp[76LLU];
char compoundliteralexp[40LLU];
char nullexp[29LLU];
char dotvarexp[49LLU];
char addrexp[40LLU];
char indexexp[74LLU];
char sliceexp[65LLU];
char vectorexp[53LLU];
};
#pragma pack(pop)
// Ignoring var u alignment 8
_AnonStruct_u u;
public:
UnionExp() :
u()
{
}
};
enum class MODFlags
{
none = 0,
@ -4961,12 +4816,14 @@ struct ASTCodegen final
using BinAssignExp = ::BinAssignExp;
using BinExp = ::BinExp;
using BlitExp = ::BlitExp;
using CTFEExp = ::CTFEExp;
using CallExp = ::CallExp;
using CastExp = ::CastExp;
using CatAssignExp = ::CatAssignExp;
using CatDcharAssignExp = ::CatDcharAssignExp;
using CatElemAssignExp = ::CatElemAssignExp;
using CatExp = ::CatExp;
using ClassReferenceExp = ::ClassReferenceExp;
using CmpExp = ::CmpExp;
using ComExp = ::ComExp;
using CommaExp = ::CommaExp;
@ -5052,13 +4909,13 @@ struct ASTCodegen final
using TemplateExp = ::TemplateExp;
using ThisExp = ::ThisExp;
using ThrowExp = ::ThrowExp;
using ThrownExceptionExp = ::ThrownExceptionExp;
using TraitsExp = ::TraitsExp;
using TupleExp = ::TupleExp;
using TypeExp = ::TypeExp;
using TypeidExp = ::TypeidExp;
using UAddExp = ::UAddExp;
using UnaExp = ::UnaExp;
using UnionExp = ::UnionExp;
using UshrAssignExp = ::UshrAssignExp;
using UshrExp = ::UshrExp;
using VarExp = ::VarExp;
@ -5067,7 +4924,6 @@ struct ASTCodegen final
using VoidInitExp = ::VoidInitExp;
using XorAssignExp = ::XorAssignExp;
using XorExp = ::XorExp;
using emplaceExp = ::emplaceExp;
using AttributeViolation = ::AttributeViolation;
using BUILTIN = ::BUILTIN;
using CtorDeclaration = ::CtorDeclaration;
@ -5185,9 +5041,8 @@ struct ASTCodegen final
using WhileStatement = ::WhileStatement;
using WithStatement = ::WithStatement;
using StaticAssert = ::StaticAssert;
using CTFEExp = ::CTFEExp;
using ClassReferenceExp = ::ClassReferenceExp;
using ThrownExceptionExp = ::ThrownExceptionExp;
using UnionExp = ::UnionExp;
using emplaceExp = ::emplaceExp;
typedef UserAttributeDeclaration* UserAttributeDeclaration;
typedef Ensure Ensure;
typedef ErrorExp* ErrorExp;
@ -5833,29 +5688,6 @@ extern const char* cppTypeInfoMangleDMC(Dsymbol* s);
extern FileName preprocess(FileName csrcfile, const Loc& loc, bool& ifile, OutBuffer* defines);
class ClassReferenceExp final : public Expression
{
public:
StructLiteralExp* value;
ClassDeclaration* originalClass();
int32_t findFieldIndexByName(VarDeclaration* v);
void accept(Visitor* v) override;
};
class ThrownExceptionExp final : public Expression
{
public:
ClassReferenceExp* thrown;
const char* toChars() const override;
void accept(Visitor* v) override;
};
class CTFEExp final : public Expression
{
public:
const char* toChars() const override;
};
extern MATCH implicitConvTo(Expression* e, Type* t);
struct BaseClass final
@ -7017,6 +6849,151 @@ public:
extern void expandTuples(Array<Expression* >* exps, Array<Identifier* >* names = nullptr);
class Expression : public ASTNode
{
public:
Type* type;
Loc loc;
const EXP op;
size_t size() const;
static void _init();
static void deinitialize();
virtual Expression* syntaxCopy();
DYNCAST dyncast() const final override;
const char* toChars() const override;
virtual dinteger_t toInteger();
virtual uinteger_t toUInteger();
virtual _d_real toReal();
virtual _d_real toImaginary();
virtual complex_t toComplex();
virtual StringExp* toStringExp();
virtual bool isLvalue();
virtual bool checkType();
virtual bool checkValue();
Expression* addressOf();
Expression* deref();
Expression* optimize(int32_t result, bool keepLvalue = false);
int32_t isConst();
virtual bool isIdentical(const Expression* const e) const;
virtual Optional<bool > toBool();
virtual bool hasCode();
IntegerExp* isIntegerExp();
ErrorExp* isErrorExp();
VoidInitExp* isVoidInitExp();
RealExp* isRealExp();
ComplexExp* isComplexExp();
IdentifierExp* isIdentifierExp();
DollarExp* isDollarExp();
DsymbolExp* isDsymbolExp();
ThisExp* isThisExp();
SuperExp* isSuperExp();
NullExp* isNullExp();
StringExp* isStringExp();
TupleExp* isTupleExp();
ArrayLiteralExp* isArrayLiteralExp();
AssocArrayLiteralExp* isAssocArrayLiteralExp();
StructLiteralExp* isStructLiteralExp();
CompoundLiteralExp* isCompoundLiteralExp();
TypeExp* isTypeExp();
ScopeExp* isScopeExp();
TemplateExp* isTemplateExp();
NewExp* isNewExp();
NewAnonClassExp* isNewAnonClassExp();
SymOffExp* isSymOffExp();
VarExp* isVarExp();
OverExp* isOverExp();
FuncExp* isFuncExp();
DeclarationExp* isDeclarationExp();
TypeidExp* isTypeidExp();
TraitsExp* isTraitsExp();
HaltExp* isHaltExp();
IsExp* isExp();
MixinExp* isMixinExp();
ImportExp* isImportExp();
AssertExp* isAssertExp();
ThrowExp* isThrowExp();
DotIdExp* isDotIdExp();
DotTemplateExp* isDotTemplateExp();
DotVarExp* isDotVarExp();
DotTemplateInstanceExp* isDotTemplateInstanceExp();
DelegateExp* isDelegateExp();
DotTypeExp* isDotTypeExp();
CallExp* isCallExp();
AddrExp* isAddrExp();
PtrExp* isPtrExp();
NegExp* isNegExp();
UAddExp* isUAddExp();
ComExp* isComExp();
NotExp* isNotExp();
DeleteExp* isDeleteExp();
CastExp* isCastExp();
VectorExp* isVectorExp();
VectorArrayExp* isVectorArrayExp();
SliceExp* isSliceExp();
ArrayLengthExp* isArrayLengthExp();
ArrayExp* isArrayExp();
DotExp* isDotExp();
CommaExp* isCommaExp();
IntervalExp* isIntervalExp();
DelegatePtrExp* isDelegatePtrExp();
DelegateFuncptrExp* isDelegateFuncptrExp();
IndexExp* isIndexExp();
PostExp* isPostExp();
PreExp* isPreExp();
AssignExp* isAssignExp();
LoweredAssignExp* isLoweredAssignExp();
ConstructExp* isConstructExp();
BlitExp* isBlitExp();
AddAssignExp* isAddAssignExp();
MinAssignExp* isMinAssignExp();
MulAssignExp* isMulAssignExp();
DivAssignExp* isDivAssignExp();
ModAssignExp* isModAssignExp();
AndAssignExp* isAndAssignExp();
OrAssignExp* isOrAssignExp();
XorAssignExp* isXorAssignExp();
PowAssignExp* isPowAssignExp();
ShlAssignExp* isShlAssignExp();
ShrAssignExp* isShrAssignExp();
UshrAssignExp* isUshrAssignExp();
CatAssignExp* isCatAssignExp();
CatElemAssignExp* isCatElemAssignExp();
CatDcharAssignExp* isCatDcharAssignExp();
AddExp* isAddExp();
MinExp* isMinExp();
CatExp* isCatExp();
MulExp* isMulExp();
DivExp* isDivExp();
ModExp* isModExp();
PowExp* isPowExp();
ShlExp* isShlExp();
ShrExp* isShrExp();
UshrExp* isUshrExp();
AndExp* isAndExp();
OrExp* isOrExp();
XorExp* isXorExp();
LogicalExp* isLogicalExp();
InExp* isInExp();
RemoveExp* isRemoveExp();
EqualExp* isEqualExp();
IdentityExp* isIdentityExp();
CondExp* isCondExp();
GenericExp* isGenericExp();
DefaultInitExp* isDefaultInitExp();
FileInitExp* isFileInitExp();
LineInitExp* isLineInitExp();
ModuleInitExp* isModuleInitExp();
FuncInitExp* isFuncInitExp();
PrettyFuncInitExp* isPrettyFuncInitExp();
ObjcClassReferenceExp* isObjcClassReferenceExp();
ClassReferenceExp* isClassReferenceExp();
ThrownExceptionExp* isThrownExceptionExp();
UnaExp* isUnaExp();
BinExp* isBinExp();
BinAssignExp* isBinAssignExp();
void accept(Visitor* v) override;
};
class IntegerExp final : public Expression
{
dinteger_t value;
@ -7968,6 +7945,30 @@ public:
void accept(Visitor* v) override;
};
class ClassReferenceExp final : public Expression
{
public:
StructLiteralExp* value;
ClassDeclaration* originalClass();
int32_t getFieldIndex(Type* fieldtype, uint32_t fieldoffset);
int32_t findFieldIndexByName(VarDeclaration* v);
void accept(Visitor* v) override;
};
class CTFEExp final : public Expression
{
public:
const char* toChars() const override;
};
class ThrownExceptionExp final : public Expression
{
public:
ClassReferenceExp* thrown;
const char* toChars() const override;
void accept(Visitor* v) override;
};
class ObjcClassReferenceExp final : public Expression
{
public:

View file

@ -123,8 +123,7 @@ unittest
@("Expression.deinitialize")
unittest
{
import dmd.ctfeexpr : CTFEExp;
import dmd.expression : Expression;
import dmd.expression : Expression, CTFEExp;
static void assertInitialState()
{