Skip to content

Commit

Permalink
add __rvalue(expression) builtin
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Nov 5, 2024
1 parent f713bd3 commit 8ccedfb
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 47 deletions.
1 change: 1 addition & 0 deletions compiler/src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -4548,6 +4548,7 @@ struct ASTBase
EXP op;
ubyte size;
ubyte parens;
ubyte rvalue; // consider this an rvalue, even if it is an lvalue
Type type;
Loc loc;

Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/e2ir.d
Original file line number Diff line number Diff line change
Expand Up @@ -5532,6 +5532,8 @@ elem *callfunc(const ref Loc loc,
v = ve.var.isVarDeclaration();
bool copy = !(v && (v.isArgDtorVar || v.storage_class & STC.rvalue)); // copy unless the destructor is going to be run on it
// then assume the frontend took care of the copying and pass it by ref
if (arg.rvalue) // marked with __rvalue
copy = false;

elems[i] = addressElem(ea, arg.type, copy);
continue;
Expand Down
39 changes: 24 additions & 15 deletions compiler/src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ extern (C++) abstract class Expression : ASTNode
Loc loc; // file location
const EXP op; // to minimize use of dynamic_cast
bool parens; // if this is a parenthesized expression
bool rvalue; // true if this is considered to be an rvalue, even if it is an lvalue

extern (D) this(const ref Loc loc, EXP op) scope @safe
{
Expand Down Expand Up @@ -1307,7 +1308,7 @@ extern (C++) class IdentifierExp : Expression

override final bool isLvalue()
{
return true;
return !this.rvalue;
}

override void accept(Visitor v)
Expand Down Expand Up @@ -1351,7 +1352,7 @@ extern (C++) final class DsymbolExp : Expression

override bool isLvalue()
{
return true;
return !rvalue;

Check warning on line 1355 in compiler/src/dmd/expression.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expression.d#L1355

Added line #L1355 was not covered by tests
}

override void accept(Visitor v)
Expand Down Expand Up @@ -1397,7 +1398,7 @@ extern (C++) class ThisExp : Expression
override final bool isLvalue()
{
// Class `this` should be an rvalue; struct `this` should be an lvalue.
return type.toBasetype().ty != Tclass;
return !rvalue && type.toBasetype().ty != Tclass;
}

override void accept(Visitor v)
Expand Down Expand Up @@ -1782,7 +1783,7 @@ extern (C++) final class StringExp : Expression
/* string literal is rvalue in default, but
* conversion to reference of static array is only allowed.
*/
return (type && type.toBasetype().ty == Tsarray);
return !rvalue && (type && type.toBasetype().ty == Tsarray);
}

/********************************
Expand Down Expand Up @@ -2719,7 +2720,7 @@ extern (C++) final class VarExp : SymbolExp

override bool isLvalue()
{
if (var.storage_class & (STC.lazy_ | STC.rvalue | STC.manifest))
if (rvalue || var.storage_class & (STC.lazy_ | STC.rvalue | STC.manifest))
return false;
return true;
}
Expand Down Expand Up @@ -3098,7 +3099,7 @@ extern (C++) class BinAssignExp : BinExp

override final bool isLvalue()
{
return true;
return !rvalue;
}

override void accept(Visitor v)
Expand Down Expand Up @@ -3303,6 +3304,8 @@ extern (C++) final class DotVarExp : UnaExp

override bool isLvalue()
{
if (rvalue)
return false;

Check warning on line 3308 in compiler/src/dmd/expression.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expression.d#L3308

Added line #L3308 was not covered by tests
if (e1.op != EXP.structLiteral)
return true;
auto vd = var.isVarDeclaration();
Expand Down Expand Up @@ -3530,6 +3533,8 @@ extern (C++) final class CallExp : UnaExp

override bool isLvalue()
{
if (rvalue)
return false;

Check warning on line 3537 in compiler/src/dmd/expression.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expression.d#L3537

Added line #L3537 was not covered by tests
Type tb = e1.type.toBasetype();
if (tb.ty == Tdelegate || tb.ty == Tpointer)
tb = tb.nextOf();
Expand Down Expand Up @@ -3648,7 +3653,7 @@ extern (C++) final class PtrExp : UnaExp

override bool isLvalue()
{
return true;
return !rvalue;
}

override void accept(Visitor v)
Expand Down Expand Up @@ -3777,7 +3782,7 @@ extern (C++) final class CastExp : UnaExp
override bool isLvalue()
{
//printf("e1.type = %s, to.type = %s\n", e1.type.toChars(), to.toChars());
if (!e1.isLvalue())
if (rvalue || !e1.isLvalue())
return false;
return (to.ty == Tsarray && (e1.type.ty == Tvector || e1.type.ty == Tsarray)) ||
e1.type.mutableOf.unSharedOf().equals(to.mutableOf().unSharedOf());
Expand Down Expand Up @@ -3834,7 +3839,7 @@ extern (C++) final class VectorArrayExp : UnaExp

override bool isLvalue()
{
return e1.isLvalue();
return !rvalue && e1.isLvalue();
}

override void accept(Visitor v)
Expand Down Expand Up @@ -3891,7 +3896,7 @@ extern (C++) final class SliceExp : UnaExp
/* slice expression is rvalue in default, but
* conversion to reference of static array is only allowed.
*/
return (type && type.toBasetype().ty == Tsarray);
return !rvalue && (type && type.toBasetype().ty == Tsarray);
}

override Optional!bool toBool()
Expand Down Expand Up @@ -3956,6 +3961,8 @@ extern (C++) final class ArrayExp : UnaExp

override bool isLvalue()
{
if (rvalue)
return false;

Check warning on line 3965 in compiler/src/dmd/expression.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expression.d#L3964-L3965

Added lines #L3964 - L3965 were not covered by tests
if (type && type.toBasetype().ty == Tvoid)
return false;
return true;
Expand Down Expand Up @@ -4005,7 +4012,7 @@ extern (C++) final class CommaExp : BinExp

override bool isLvalue()
{
return e2.isLvalue();
return !rvalue && e2.isLvalue();
}

override Optional!bool toBool()
Expand Down Expand Up @@ -4080,7 +4087,7 @@ extern (C++) final class DelegatePtrExp : UnaExp

override bool isLvalue()
{
return e1.isLvalue();
return !rvalue && e1.isLvalue();
}

override void accept(Visitor v)
Expand All @@ -4103,7 +4110,7 @@ extern (C++) final class DelegateFuncptrExp : UnaExp

override bool isLvalue()
{
return e1.isLvalue();
return !rvalue && e1.isLvalue();

Check warning on line 4113 in compiler/src/dmd/expression.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expression.d#L4113

Added line #L4113 was not covered by tests
}

override void accept(Visitor v)
Expand Down Expand Up @@ -4143,6 +4150,8 @@ extern (C++) final class IndexExp : BinExp

override bool isLvalue()
{
if (rvalue)
return false;

Check warning on line 4154 in compiler/src/dmd/expression.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expression.d#L4154

Added line #L4154 was not covered by tests
if (e1.op == EXP.assocArrayLiteral)
return false;
if (e1.type.ty == Tsarray ||
Expand Down Expand Up @@ -4252,7 +4261,7 @@ extern (C++) class AssignExp : BinExp
{
return false;
}
return true;
return !rvalue;
}

override void accept(Visitor v)
Expand Down Expand Up @@ -4983,7 +4992,7 @@ extern (C++) final class CondExp : BinExp

override bool isLvalue()
{
return e1.isLvalue() && e2.isLvalue();
return !rvalue && e1.isLvalue() && e2.isLvalue();
}

override void accept(Visitor v)
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class Expression : public ASTNode
Loc loc; // file location
EXP op; // to minimize use of dynamic_cast
d_bool parens; // if this is a parenthesized expression
d_bool rvalue; // consider this an rvalue, even if it is an lvalue

size_t size() const;
static void _init();
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -3890,6 +3890,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}

scope (success) result.rvalue = exp.rvalue;

Check warning on line 3893 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L3893

Added line #L3893 was not covered by tests

Dsymbol scopesym;
Dsymbol s = sc.search(exp.loc, exp.ident, scopesym);
if (s)
Expand Down
67 changes: 35 additions & 32 deletions compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,7 @@ enum class EXP : uint8_t
_Generic_ = 125u,
interval = 126u,
loweredAssignExp = 127u,
rvalue = 128u,
};

typedef uint64_t dinteger_t;
Expand Down Expand Up @@ -2105,6 +2106,7 @@ class Expression : public ASTNode
Loc loc;
const EXP op;
bool parens;
bool rvalue;
size_t size() const;
static void _init();
static void deinitialize();
Expand Down Expand Up @@ -2888,33 +2890,34 @@ enum class TOK : uint8_t
wchar_tLiteral = 196u,
endOfLine = 197u,
whitespace = 198u,
inline_ = 199u,
register_ = 200u,
restrict_ = 201u,
signed_ = 202u,
sizeof_ = 203u,
typedef_ = 204u,
unsigned_ = 205u,
volatile_ = 206u,
_Alignas_ = 207u,
_Alignof_ = 208u,
_Atomic_ = 209u,
_Bool_ = 210u,
_Complex_ = 211u,
_Generic_ = 212u,
_Imaginary_ = 213u,
_Noreturn_ = 214u,
_Static_assert_ = 215u,
_Thread_local_ = 216u,
_assert_ = 217u,
_import_ = 218u,
__cdecl_ = 219u,
__declspec_ = 220u,
__stdcall_ = 221u,
__thread_ = 222u,
__pragma_ = 223u,
__int128_ = 224u,
__attribute___ = 225u,
rvalue = 199u,
inline_ = 200u,
register_ = 201u,
restrict_ = 202u,
signed_ = 203u,
sizeof_ = 204u,
typedef_ = 205u,
unsigned_ = 206u,
volatile_ = 207u,
_Alignas_ = 208u,
_Alignof_ = 209u,
_Atomic_ = 210u,
_Bool_ = 211u,
_Complex_ = 212u,
_Generic_ = 213u,
_Imaginary_ = 214u,
_Noreturn_ = 215u,
_Static_assert_ = 216u,
_Thread_local_ = 217u,
_assert_ = 218u,
_import_ = 219u,
__cdecl_ = 220u,
__declspec_ = 221u,
__stdcall_ = 222u,
__thread_ = 223u,
__pragma_ = 224u,
__int128_ = 225u,
__attribute___ = 226u,
};

class FuncExp final : public Expression
Expand Down Expand Up @@ -5264,18 +5267,18 @@ struct UnionExp final
private:
union _AnonStruct_u
{
char exp[30LLU];
char exp[31LLU];
char integerexp[40LLU];
char errorexp[30LLU];
char errorexp[31LLU];
char realexp[48LLU];
char complexexp[64LLU];
char symoffexp[64LLU];
char stringexp[51LLU];
char arrayliteralexp[48LLU];
char stringexp[59LLU];
char arrayliteralexp[56LLU];
char assocarrayliteralexp[56LLU];
char structliteralexp[76LLU];
char compoundliteralexp[40LLU];
char nullexp[30LLU];
char nullexp[31LLU];
char dotvarexp[49LLU];
char addrexp[40LLU];
char indexexp[74LLU];
Expand Down
6 changes: 6 additions & 0 deletions compiler/src/dmd/hdrgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -2888,6 +2888,12 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
buf.writestring(e.value.toChars());
}

if (e.rvalue)
buf.writestring("__rvalue(");

Check warning on line 2892 in compiler/src/dmd/hdrgen.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/hdrgen.d#L2892

Added line #L2892 was not covered by tests
scope (success)
if (e.rvalue)
buf.writeByte(')');

Check warning on line 2895 in compiler/src/dmd/hdrgen.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/hdrgen.d#L2895

Added line #L2895 was not covered by tests

switch (e.op)
{
default:
Expand Down
10 changes: 10 additions & 0 deletions compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -5877,6 +5877,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.moduleString:
case TOK.functionString:
case TOK.prettyFunction:
case TOK.rvalue:
Lexp:
{
AST.Expression exp = parseExpression();
Expand Down Expand Up @@ -8410,6 +8411,15 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
e = new AST.TypeidExp(loc, o);
break;
}
case TOK.rvalue:
{
nextToken();
check(TOK.leftParenthesis, "`__rvalue`");
e = parseAssignExp();
e.rvalue = true;
check(TOK.rightParenthesis);
break;
}
case TOK.traits:
{
/* __traits(identifier, args...)
Expand Down
7 changes: 7 additions & 0 deletions compiler/src/dmd/tokens.d
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ enum TOK : ubyte
{
reserved,

// if this list changes, update
// tokens.h, ../tests/cxxfrontend.cc and ../../test/unit/lexer/location_offset.d to match

// Other
leftParenthesis,
rightParenthesis,
Expand Down Expand Up @@ -249,6 +252,7 @@ enum TOK : ubyte
wchar_tLiteral,
endOfLine, // \n, \r, \u2028, \u2029
whitespace,
rvalue,

// C only keywords
inline,
Expand Down Expand Up @@ -425,6 +429,7 @@ enum EXP : ubyte
interval,

loweredAssignExp,
rvalue,
}

enum FirstCKeyword = TOK.inline;
Expand Down Expand Up @@ -556,6 +561,7 @@ private immutable TOK[] keywords =
TOK.prettyFunction,
TOK.shared_,
TOK.immutable_,
TOK.rvalue,

// C only keywords
TOK.inline,
Expand Down Expand Up @@ -680,6 +686,7 @@ extern (C++) struct Token
TOK.pragma_: "pragma",
TOK.typeof_: "typeof",
TOK.typeid_: "typeid",
TOK.rvalue: "__rvalue",
TOK.template_: "template",
TOK.void_: "void",
TOK.int8: "byte",
Expand Down
Loading

0 comments on commit 8ccedfb

Please sign in to comment.