/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
* written by Walter Bright
* https://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
class ClassDeclaration;
class OverloadSet;
class StringExp;
-struct UnionExp;
+class InterpExp;
+class LoweredAssignExp;
#ifdef IN_GCC
typedef union tree_node Symbol;
#else
struct Symbol; // back end symbol
#endif
-void expandTuples(Expressions *exps);
-bool isTrivialExp(Expression *e);
-bool hasSideEffect(Expression *e, bool assumeImpureCalls = false);
+namespace dmd
+{
+ // in expressionsem.d
+ Expression *expressionSemantic(Expression *e, Scope *sc);
+ // in typesem.d
+ Expression *defaultInit(Type *mt, const Loc &loc, const bool isCfile = false);
-enum BE : int32_t;
-BE canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow);
+ // Entry point for CTFE.
+ // A compile-time result is required. Give an error if not possible
+ Expression *ctfeInterpret(Expression *e);
+ void expandTuples(Expressions *exps, Identifiers *names = nullptr);
+ Expression *optimize(Expression *exp, int result, bool keepLvalue = false);
+}
typedef unsigned char OwnedBy;
enum
class Expression : public ASTNode
{
public:
- EXP op; // to minimize use of dynamic_cast
- unsigned char size; // # of bytes in Expression so we can copy() it
- unsigned char parens; // if this is a parenthesized expression
Type *type; // !=NULL means that semantic() has been run
Loc loc; // file location
+ EXP op; // to minimize use of dynamic_cast
+ d_bool parens; // if this is a parenthesized expression
+ size_t size() const;
static void _init();
- Expression *copy();
virtual Expression *syntaxCopy();
// kludge for template.isExpression()
DYNCAST dyncast() const override final { return DYNCAST_EXPRESSION; }
const char *toChars() const override;
- void error(const char *format, ...) const;
- void warning(const char *format, ...) const;
- void deprecation(const char *format, ...) const;
virtual dinteger_t toInteger();
virtual uinteger_t toUInteger();
virtual complex_t toComplex();
virtual StringExp *toStringExp();
virtual bool isLvalue();
- virtual Expression *toLvalue(Scope *sc, Expression *e);
- virtual Expression *modifiableLvalue(Scope *sc, Expression *e);
- Expression *implicitCastTo(Scope *sc, Type *t);
- MATCH implicitConvTo(Type *t);
- Expression *castTo(Scope *sc, Type *t);
- virtual Expression *resolveLoc(const Loc &loc, Scope *sc);
virtual bool checkType();
virtual bool checkValue();
- bool checkDeprecated(Scope *sc, Dsymbol *s);
- virtual Expression *addDtorHook(Scope *sc);
Expression *addressOf();
Expression *deref();
- 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();
int isConst();
+ virtual bool isIdentical(const Expression *e) const;
virtual Optional<bool> toBool();
virtual bool hasCode()
{
SuperExp* isSuperExp();
NullExp* isNullExp();
StringExp* isStringExp();
+ InterpExp* isInterpExp();
TupleExp* isTupleExp();
ArrayLiteralExp* isArrayLiteralExp();
AssocArrayLiteralExp* isAssocArrayLiteralExp();
UnaExp* isUnaExp();
BinExp* isBinExp();
BinAssignExp* isBinAssignExp();
+ LoweredAssignExp* isLoweredAssignExp();
void accept(Visitor *v) override { v->visit(this); }
};
dinteger_t value;
static IntegerExp *create(const Loc &loc, dinteger_t value, Type *type);
- static void emplace(UnionExp *pue, const Loc &loc, dinteger_t value, Type *type);
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
dinteger_t toInteger() override;
real_t toReal() override;
real_t toImaginary() override;
complex_t toComplex() override;
Optional<bool> toBool() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
dinteger_t getInteger() { return value; }
- void setInteger(dinteger_t value);
template<int v>
static IntegerExp literal();
};
class ErrorExp final : public Expression
{
public:
- Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
static ErrorExp *errorexp; // handy shared value
real_t value;
static RealExp *create(const Loc &loc, real_t value, Type *type);
- static void emplace(UnionExp *pue, const Loc &loc, real_t value, Type *type);
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
+ bool isIdentical(const Expression *e) const override;
dinteger_t toInteger() override;
uinteger_t toUInteger() override;
real_t toReal() override;
complex_t value;
static ComplexExp *create(const Loc &loc, complex_t value, Type *type);
- static void emplace(UnionExp *pue, const Loc &loc, complex_t value, Type *type);
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
+ bool isIdentical(const Expression *e) const override;
dinteger_t toInteger() override;
uinteger_t toUInteger() override;
real_t toReal() override;
static IdentifierExp *create(const Loc &loc, Identifier *ident);
bool isLvalue() override final;
- Expression *toLvalue(Scope *sc, Expression *e) override final;
void accept(Visitor *v) override { v->visit(this); }
};
{
public:
Dsymbol *s;
- bool hasOverloads;
+ d_bool hasOverloads;
DsymbolExp *syntaxCopy() override;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
ThisExp *syntaxCopy() override;
Optional<bool> toBool() override;
- bool isLvalue() override final;
- Expression *toLvalue(Scope *sc, Expression *e) override final;
+ bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class NullExp final : public Expression
{
public:
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
Optional<bool> toBool() override;
StringExp *toStringExp() override;
void accept(Visitor *v) override { v->visit(this); }
class StringExp final : 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'
OwnedBy ownedByCtfe;
+ void *string; // char, wchar, dchar, or long data
+ size_t len; // number of chars, wchars, or dchars
+ unsigned char sz; // 1: char, 2: wchar, 4: dchar
+ d_bool committed; // if type is committed
+ d_bool hexString; // if string is parsed from a hex string literal
static StringExp *create(const Loc &loc, const char *s);
static StringExp *create(const Loc &loc, const void *s, d_size_t len);
- static void emplace(UnionExp *pue, const Loc &loc, const char *s);
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
char32_t getCodeUnit(d_size_t i) const;
- void setCodeUnit(d_size_t i, char32_t c);
+ dinteger_t getIndex(d_size_t i) const;
StringExp *toStringExp() override;
- StringExp *toUTF8(Scope *sc);
Optional<bool> toBool() override;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
size_t numberOfCodeUnits(int tynto = 0) const;
void writeTo(void* dest, bool zero, int tyto = 0) const;
};
+class InterpExp final : public Expression
+{
+public:
+ utf8_t postfix; // 'c', 'w', 'd'
+ OwnedBy ownedByCtfe;
+ void* interpolatedSet;
+
+ void accept(Visitor* v) override { v->visit(this); }
+};
+
// Tuple
class TupleExp final : public Expression
static TupleExp *create(const Loc &loc, Expressions *exps);
TupleExp *syntaxCopy() override;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
void accept(Visitor *v) override { v->visit(this); }
};
class ArrayLiteralExp final : public Expression
{
public:
+ OwnedBy ownedByCtfe;
+ d_bool onstack;
Expression *basis;
Expressions *elements;
- OwnedBy ownedByCtfe;
static ArrayLiteralExp *create(const Loc &loc, Expressions *elements);
- static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements);
ArrayLiteralExp *syntaxCopy() override;
- bool equals(const RootObject *o) const override;
- Expression *getElement(d_size_t i); // use opIndex instead
- Expression *opIndex(d_size_t i);
+ bool equals(const RootObject * const o) const override;
+ Expression *getElement(d_size_t i);
Optional<bool> toBool() override;
StringExp *toStringExp() override;
class AssocArrayLiteralExp final : public Expression
{
public:
+ OwnedBy ownedByCtfe;
Expressions *keys;
Expressions *values;
- OwnedBy ownedByCtfe;
+ Expression* lowering;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
AssocArrayLiteralExp *syntaxCopy() override;
Optional<bool> toBool() override;
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)
- Symbol *sym; // back end symbol to initialize with literal
+ union
+ {
+ Symbol *sym; // back end symbol to initialize with literal (used as a Symbol*)
+
+ // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer.
+ StructLiteralExp *inlinecopy;
+ };
/** pointer to the origin instance of the expression.
* once a new expression is created, origin is set to 'this'.
*/
StructLiteralExp *origin;
- // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer.
- StructLiteralExp *inlinecopy;
/** 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.
*/
- int stageflags;
+ uint8_t stageflags;
- bool useStaticInit; // if this is true, use the StructDeclaration's init symbol
- bool isOriginal; // used when moving instances to indicate `this is this.origin`
+ d_bool useStaticInit; // if this is true, use the StructDeclaration's init symbol
+ d_bool isOriginal; // used when moving instances to indicate `this is this.origin`
OwnedBy ownedByCtfe;
static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
StructLiteralExp *syntaxCopy() override;
- Expression *getField(Type *type, unsigned offset);
- int getFieldIndex(Type *type, unsigned offset);
- Expression *addDtorHook(Scope *sc) override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
FuncDeclaration *fd;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
bool checkType() override;
bool checkValue() override;
void accept(Visitor *v) override { v->visit(this); }
Expression *thisexp; // if !NULL, 'this' for class being allocated
Type *newtype;
Expressions *arguments; // Array of Expression's
+ Identifiers *names; // Array of names corresponding to expressions
Expression *argprefix; // expression to be evaluated just before arguments[]
CtorDeclaration *member; // constructor function
- bool onstack; // allocate on stack
- bool thrownew; // this NewExp is the expression of a ThrowStatement
+ d_bool onstack; // allocate on stack
+ d_bool thrownew; // this NewExp is the expression of a ThrowStatement
+
+ Expression *lowering; // lowered druntime hook: `_d_newclass`
static NewExp *create(const Loc &loc, Expression *thisexp, Type *newtype, Expressions *arguments);
NewExp *syntaxCopy() override;
public:
Declaration *var;
Dsymbol *originalScope;
- bool hasOverloads;
+ d_bool hasOverloads;
void accept(Visitor *v) override { v->visit(this); }
};
class VarExp final : public SymbolExp
{
public:
- bool delegateWasExtracted;
+ d_bool delegateWasExtracted;
static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true);
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
OverloadSet *vars;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
TemplateDeclaration *td;
TOK tok;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
FuncExp *syntaxCopy() override;
const char *toChars() const override;
bool checkType() override;
{
public:
Expression *e1;
- Type *att1; // Save alias this type to detect recursion
UnaExp *syntaxCopy() override;
- Expression *incompatibleTypes();
- Expression *resolveLoc(const Loc &loc, Scope *sc) override final;
void accept(Visitor *v) override { v->visit(this); }
};
Type *att2; // Save alias this type to detect recursion
BinExp *syntaxCopy() override;
- Expression *incompatibleTypes();
-
- Expression *reorderSettingAAElem(Scope *sc);
void accept(Visitor *v) override { v->visit(this); }
};
{
public:
bool isLvalue() override final;
- Expression *toLvalue(Scope *sc, Expression *ex) override final;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override final;
void accept(Visitor *v) override { v->visit(this); }
};
{
public:
Identifier *ident;
- bool noderef; // true if the result of the expression will never be dereferenced
- bool wantsym; // do not replace Symbol with its initializer during semantic()
- bool arrow; // ImportC: if -> instead of .
+ d_bool noderef; // true if the result of the expression will never be dereferenced
+ d_bool wantsym; // do not replace Symbol with its initializer during semantic()
+ d_bool arrow; // ImportC: if -> instead of .
static DotIdExp *create(const Loc &loc, Expression *e, Identifier *ident);
void accept(Visitor *v) override { v->visit(this); }
{
public:
Declaration *var;
- bool hasOverloads;
+ d_bool hasOverloads;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
TemplateInstance *ti;
DotTemplateInstanceExp *syntaxCopy() override;
- bool findTempDecl(Scope *sc);
bool checkType() override;
bool checkValue() override;
void accept(Visitor *v) override { v->visit(this); }
{
public:
FuncDeclaration *func;
- bool hasOverloads;
+ d_bool hasOverloads;
VarDeclaration *vthis2; // container for multi-context
{
public:
Expressions *arguments; // function arguments
+ Identifiers *names;
FuncDeclaration *f; // symbol to call
- bool directcall; // true if a virtual call is devirtualized
- bool inDebugStatement; // true if this was in a debug statement
- bool ignoreAttributes; // don't enforce attributes (e.g. call @gc function in @nogc code)
+ d_bool directcall; // true if a virtual call is devirtualized
+ d_bool inDebugStatement; // true if this was in a debug statement
+ d_bool ignoreAttributes; // don't enforce attributes (e.g. call @gc function in @nogc code)
+ d_bool isUfcsRewrite; // the first argument was pushed in here by a UFCS rewrite
VarDeclaration *vthis2; // container for multi-context
static CallExp *create(const Loc &loc, Expression *e, Expressions *exps);
CallExp *syntaxCopy() override;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *addDtorHook(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
{
public:
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
class DeleteExp final : public UnaExp
{
public:
- bool isRAII;
+ d_bool isRAII;
void accept(Visitor *v) override { v->visit(this); }
};
CastExp *syntaxCopy() override;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
OwnedBy ownedByCtfe;
static VectorExp *create(const Loc &loc, Expression *e, Type *t);
- static void emplace(UnionExp *pue, const Loc &loc, Expression *e, Type *t);
VectorExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
{
public:
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
Expression *upr; // NULL if implicit 0
Expression *lwr; // NULL if implicit [length - 1]
VarDeclaration *lengthVar;
- bool upperIsInBounds; // true if upr <= e1.length
- bool lowerIsLessThanUpper; // true if lwr <= upr
- bool arrayop; // an array operation, rather than a slice
+ bool upperIsInBounds() const; // true if upr <= e1.length
+ bool upperIsInBounds(bool v);
+ bool lowerIsLessThanUpper() const; // true if lwr <= upr
+ bool lowerIsLessThanUpper(bool v);
+ bool arrayop() const; // an array operation, rather than a slice
+ bool arrayop(bool v);
+private:
+ uint8_t bitFields;
+
+public:
SliceExp *syntaxCopy() override;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
{
public:
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
{
public:
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
ArrayExp *syntaxCopy() override;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
class CommaExp final : public BinExp
{
public:
- bool isGenerated;
- bool allowCommaExp;
+ d_bool isGenerated;
+ d_bool allowCommaExp;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
Optional<bool> toBool() override;
- Expression *addDtorHook(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
{
public:
VarDeclaration *lengthVar;
- bool modifiable;
- bool indexIsInBounds; // true if 0 <= e2 && e2 <= e1.length - 1
+ d_bool modifiable;
+ d_bool indexIsInBounds; // true if 0 <= e2 && e2 <= e1.length - 1
IndexExp *syntaxCopy() override;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
MemorySet memset;
bool isLvalue() override final;
- Expression *toLvalue(Scope *sc, Expression *ex) override final;
void accept(Visitor *v) override { v->visit(this); }
};
void accept(Visitor *v) override { v->visit(this); }
};
+class LoweredAssignExp final : public AssignExp
+{
+public:
+ Expression *lowering;
+
+ const char *toChars() const override;
+ void accept(Visitor *v) override { v->visit(this); }
+};
+
class BlitExp final : public AssignExp
{
public:
class CatAssignExp : public BinAssignExp
{
public:
+ Expression *lowering; // lowered druntime hook `_d_arrayappend{cTX,T}`
+
void accept(Visitor *v) override { v->visit(this); }
};
class CatExp final : public BinExp
{
public:
+ Expression *lowering; // call to druntime hook `_d_arraycatnTX`
+
void accept(Visitor *v) override { v->visit(this); }
};
CondExp *syntaxCopy() override;
bool isLvalue() override;
- Expression *toLvalue(Scope *sc, Expression *e) override;
- Expression *modifiableLvalue(Scope *sc, Expression *e) override;
- void hookDtors(Scope *sc);
void accept(Visitor *v) override { v->visit(this); }
};
class FileInitExp final : public DefaultInitExp
{
public:
- Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
class LineInitExp final : public DefaultInitExp
{
public:
- Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
class ModuleInitExp final : public DefaultInitExp
{
public:
- Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
class FuncInitExp final : public DefaultInitExp
{
public:
- Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
class PrettyFuncInitExp final : public DefaultInitExp
{
public:
- Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
/****************************************************************/
-/* 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.
- */
-struct UnionExp
-{
- UnionExp() { } // yes, default constructor does nothing
-
- UnionExp(Expression *e)
- {
- memcpy(this, (void *)e, e->size);
- }
-
- /* Extract pointer to Expression
- */
- Expression *exp() { return (Expression *)&u; }
-
- /* Convert to an allocated Expression
- */
- Expression *copy();
-
-private:
- // Ensure that the union is suitably aligned.
-#if defined(__GNUC__) || defined(__clang__)
- __attribute__((aligned(8)))
-#elif defined(_MSC_VER)
- __declspec(align(8))
-#elif defined(__DMC__)
- #pragma pack(8)
-#endif
- union
- {
- char exp [sizeof(Expression)];
- char integerexp[sizeof(IntegerExp)];
- char errorexp [sizeof(ErrorExp)];
- char realexp [sizeof(RealExp)];
- char complexexp[sizeof(ComplexExp)];
- char symoffexp [sizeof(SymOffExp)];
- char stringexp [sizeof(StringExp)];
- char arrayliteralexp [sizeof(ArrayLiteralExp)];
- char assocarrayliteralexp [sizeof(AssocArrayLiteralExp)];
- char structliteralexp [sizeof(StructLiteralExp)];
- char nullexp [sizeof(NullExp)];
- char dotvarexp [sizeof(DotVarExp)];
- char addrexp [sizeof(AddrExp)];
- char indexexp [sizeof(IndexExp)];
- char sliceexp [sizeof(SliceExp)];
- char vectorexp [sizeof(VectorExp)];
- } u;
-#if defined(__DMC__)
- #pragma pack()
-#endif
-};
-
-/****************************************************************/
-
class ObjcClassReferenceExp final : public Expression
{
public: