diff --git a/compiler/src/dmd/astbase.d b/compiler/src/dmd/astbase.d index bdc489871c36..379a22ccc7a7 100644 --- a/compiler/src/dmd/astbase.d +++ b/compiler/src/dmd/astbase.d @@ -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; diff --git a/compiler/src/dmd/clone.d b/compiler/src/dmd/clone.d index bbfb1ee9f87d..6e104be10281 100644 --- a/compiler/src/dmd/clone.d +++ b/compiler/src/dmd/clone.d @@ -1617,6 +1617,7 @@ private Statement generateCopyCtorBody(StructDeclaration sd) */ bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor) { + //printf("needCopyCtor() %s\n", sd.toChars()); if (global.errors) return false; @@ -1655,7 +1656,7 @@ bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor) if (cpCtor) { - if (rvalueCtor) + if (0 && rvalueCtor) { .error(sd.loc, "`struct %s` may not define both a rvalue constructor and a copy constructor", sd.toChars()); errorSupplemental(rvalueCtor.loc,"rvalue constructor defined here"); diff --git a/compiler/src/dmd/declaration.h b/compiler/src/dmd/declaration.h index bdefd2d9f864..a98213d9198c 100644 --- a/compiler/src/dmd/declaration.h +++ b/compiler/src/dmd/declaration.h @@ -782,6 +782,7 @@ class CtorDeclaration final : public FuncDeclaration { public: d_bool isCpCtor; + d_bool isMoveCtor; CtorDeclaration *syntaxCopy(Dsymbol *) override; const char *kind() const override; const char *toChars() const override; diff --git a/compiler/src/dmd/dscope.d b/compiler/src/dmd/dscope.d index aa48d57ba999..76627bec3343 100644 --- a/compiler/src/dmd/dscope.d +++ b/compiler/src/dmd/dscope.d @@ -24,6 +24,7 @@ import dmd.dclass; import dmd.declaration; import dmd.dmodule; import dmd.doc; +import dmd.dstruct; import dmd.dsymbol; import dmd.dsymbolsem; import dmd.dtemplate; @@ -146,6 +147,7 @@ extern (C++) struct Scope AliasDeclaration aliasAsg; /// if set, then aliasAsg is being assigned a new value, /// do not set wasRead for it + StructDeclaration argStruct; /// elimiate recursion when looking for rvalue construction extern (D) __gshared Scope* freelist; diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d index 173532af397c..87738591a3ab 100644 --- a/compiler/src/dmd/dsymbolsem.d +++ b/compiler/src/dmd/dsymbolsem.d @@ -2484,10 +2484,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { //printf("tf: %s\n", tf.toChars()); auto param = tf.parameterList[0]; - if (param.storageClass & STC.ref_ && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf()) + if (param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf()) { //printf("copy constructor\n"); - ctd.isCpCtor = true; + if (param.storageClass & STC.ref_) + ctd.isCpCtor = true; // copy constructor + else + ctd.isMoveCtor = true; // move constructor } } } diff --git a/compiler/src/dmd/e2ir.d b/compiler/src/dmd/e2ir.d index 1d1efd1f966f..5ea7faa3232b 100644 --- a/compiler/src/dmd/e2ir.d +++ b/compiler/src/dmd/e2ir.d @@ -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; diff --git a/compiler/src/dmd/expression.d b/compiler/src/dmd/expression.d index dc72b3a8df1b..3d0ae2528460 100644 --- a/compiler/src/dmd/expression.d +++ b/compiler/src/dmd/expression.d @@ -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 { @@ -1307,7 +1308,7 @@ extern (C++) class IdentifierExp : Expression override final bool isLvalue() { - return true; + return !this.rvalue; } override void accept(Visitor v) @@ -1351,7 +1352,7 @@ extern (C++) final class DsymbolExp : Expression override bool isLvalue() { - return true; + return !rvalue; } override void accept(Visitor v) @@ -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) @@ -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); } /******************************** @@ -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; } @@ -3098,7 +3099,7 @@ extern (C++) class BinAssignExp : BinExp override final bool isLvalue() { - return true; + return !rvalue; } override void accept(Visitor v) @@ -3303,6 +3304,8 @@ extern (C++) final class DotVarExp : UnaExp override bool isLvalue() { + if (rvalue) + return false; if (e1.op != EXP.structLiteral) return true; auto vd = var.isVarDeclaration(); @@ -3530,6 +3533,8 @@ extern (C++) final class CallExp : UnaExp override bool isLvalue() { + if (rvalue) + return false; Type tb = e1.type.toBasetype(); if (tb.ty == Tdelegate || tb.ty == Tpointer) tb = tb.nextOf(); @@ -3648,7 +3653,7 @@ extern (C++) final class PtrExp : UnaExp override bool isLvalue() { - return true; + return !rvalue; } override void accept(Visitor v) @@ -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()); @@ -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) @@ -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() @@ -3956,6 +3961,8 @@ extern (C++) final class ArrayExp : UnaExp override bool isLvalue() { + if (rvalue) + return false; if (type && type.toBasetype().ty == Tvoid) return false; return true; @@ -4005,7 +4012,7 @@ extern (C++) final class CommaExp : BinExp override bool isLvalue() { - return e2.isLvalue(); + return !rvalue && e2.isLvalue(); } override Optional!bool toBool() @@ -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) @@ -4103,7 +4110,7 @@ extern (C++) final class DelegateFuncptrExp : UnaExp override bool isLvalue() { - return e1.isLvalue(); + return !rvalue && e1.isLvalue(); } override void accept(Visitor v) @@ -4143,6 +4150,8 @@ extern (C++) final class IndexExp : BinExp override bool isLvalue() { + if (rvalue) + return false; auto t1b = e1.type.toBasetype(); if (t1b.isTypeAArray() || t1b.isTypeSArray() || (e1.isIndexExp() && t1b != t1b.isTypeDArray())) @@ -4251,7 +4260,7 @@ extern (C++) class AssignExp : BinExp { return false; } - return true; + return !rvalue; } override void accept(Visitor v) @@ -4982,7 +4991,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) diff --git a/compiler/src/dmd/expression.h b/compiler/src/dmd/expression.h index c353a191a662..73bb950d32ff 100644 --- a/compiler/src/dmd/expression.h +++ b/compiler/src/dmd/expression.h @@ -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(); diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index 49a8f189a0dc..ab0dc9ad71d5 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -846,6 +846,7 @@ extern (D) Expression doCopyOrMove(Scope *sc, Expression e, Type t = null) */ private Expression callCpCtor(Scope* sc, Expression e, Type destinationType) { + //printf("callCpCtor(e: %s et: %s destinationType: %s\n", toChars(e), toChars(e.type), toChars(destinationType)); auto ts = e.type.baseElemOf().isTypeStruct(); if (!ts) @@ -2952,7 +2953,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, Type* prettype, Expression* peprefix) { Expressions* arguments = argumentList.arguments; - //printf("functionParameters() %s\n", fd ? fd.toChars() : ""); + //printf("functionParameters() fd: %s tf: %s\n", fd ? fd.ident.toChars() : "", toChars(tf)); assert(arguments); assert(fd || tf.next); const size_t nparams = tf.parameterList.length; @@ -3892,6 +3893,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } + scope (success) result.rvalue = exp.rvalue; + Dsymbol scopesym; Dsymbol s = sc.search(exp.loc, exp.ident, scopesym); if (s) @@ -6718,7 +6721,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor errorSupplemental(exp.loc, "%s", failMessage); } - if (tf.callMatch(null, exp.argumentList, 0, &errorHelper, sc) == MATCH.nomatch) + if (callMatch(tf, null, exp.argumentList, 0, &errorHelper, sc) == MATCH.nomatch) return setError(); // Purity and safety check should run after testing arguments matching @@ -6801,7 +6804,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.f = null; } - if (tf.callMatch(null, exp.argumentList, 0, &errorHelper2, sc) == MATCH.nomatch) + if (callMatch(tf, null, exp.argumentList, 0, &errorHelper2, sc) == MATCH.nomatch) exp.f = null; } if (!exp.f || exp.f.errors) diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index fcd1888a19ed..6b39d784d734 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -2068,6 +2068,7 @@ enum class EXP : uint8_t _Generic_ = 125u, interval = 126u, loweredAssignExp = 127u, + rvalue = 128u, }; typedef uint64_t dinteger_t; @@ -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(); @@ -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 @@ -3792,6 +3795,7 @@ class CtorDeclaration final : public FuncDeclaration { public: bool isCpCtor; + bool isMoveCtor; CtorDeclaration* syntaxCopy(Dsymbol* s) override; const char* kind() const override; const char* toChars() const override; @@ -5260,18 +5264,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]; @@ -7130,6 +7134,7 @@ struct Scope final void* anchorCounts; Identifier* prevAnchor; AliasDeclaration* aliasAsg; + StructDeclaration* argStruct; Dsymbol* search(const Loc& loc, Identifier* ident, Dsymbol*& pscopesym, uint32_t flags = 0u); Scope() : enclosing(), @@ -7170,10 +7175,11 @@ struct Scope final userAttribDecl(), lastdc(), prevAnchor(), - aliasAsg() + aliasAsg(), + argStruct() { } - Scope(Scope* enclosing, Module* _module = nullptr, ScopeDsymbol* scopesym = nullptr, FuncDeclaration* func = nullptr, VarDeclaration* varDecl = nullptr, Dsymbol* parent = nullptr, LabelStatement* slabel = nullptr, SwitchStatement* sw = nullptr, Statement* tryBody = nullptr, TryFinallyStatement* tf = nullptr, ScopeGuardStatement* os = nullptr, Statement* sbreak = nullptr, Statement* scontinue = nullptr, ForeachStatement* fes = nullptr, Scope* callsc = nullptr, Dsymbol* inunion = nullptr, bool nofree = false, bool inLoop = false, bool inDefaultArg = false, int32_t intypeof = 0, VarDeclaration* lastVar = nullptr, ErrorSink* eSink = nullptr, Module* minst = nullptr, TemplateInstance* tinst = nullptr, CtorFlow ctorflow = CtorFlow(), AlignDeclaration* aligndecl = nullptr, CPPNamespaceDeclaration* namespace_ = nullptr, LINK linkage = (LINK)1u, CPPMANGLE cppmangle = (CPPMANGLE)0u, PragmaDeclaration* inlining = nullptr, Visibility visibility = Visibility((Visibility::Kind)5u, nullptr), int32_t explicitVisibility = 0, uint64_t stc = 0LLU, DeprecatedDeclaration* depdecl = nullptr, uint32_t bitFields = 0u, UserAttributeDeclaration* userAttribDecl = nullptr, DocComment* lastdc = nullptr, void* anchorCounts = nullptr, Identifier* prevAnchor = nullptr, AliasDeclaration* aliasAsg = nullptr) : + Scope(Scope* enclosing, Module* _module = nullptr, ScopeDsymbol* scopesym = nullptr, FuncDeclaration* func = nullptr, VarDeclaration* varDecl = nullptr, Dsymbol* parent = nullptr, LabelStatement* slabel = nullptr, SwitchStatement* sw = nullptr, Statement* tryBody = nullptr, TryFinallyStatement* tf = nullptr, ScopeGuardStatement* os = nullptr, Statement* sbreak = nullptr, Statement* scontinue = nullptr, ForeachStatement* fes = nullptr, Scope* callsc = nullptr, Dsymbol* inunion = nullptr, bool nofree = false, bool inLoop = false, bool inDefaultArg = false, int32_t intypeof = 0, VarDeclaration* lastVar = nullptr, ErrorSink* eSink = nullptr, Module* minst = nullptr, TemplateInstance* tinst = nullptr, CtorFlow ctorflow = CtorFlow(), AlignDeclaration* aligndecl = nullptr, CPPNamespaceDeclaration* namespace_ = nullptr, LINK linkage = (LINK)1u, CPPMANGLE cppmangle = (CPPMANGLE)0u, PragmaDeclaration* inlining = nullptr, Visibility visibility = Visibility((Visibility::Kind)5u, nullptr), int32_t explicitVisibility = 0, uint64_t stc = 0LLU, DeprecatedDeclaration* depdecl = nullptr, uint32_t bitFields = 0u, UserAttributeDeclaration* userAttribDecl = nullptr, DocComment* lastdc = nullptr, void* anchorCounts = nullptr, Identifier* prevAnchor = nullptr, AliasDeclaration* aliasAsg = nullptr, StructDeclaration* argStruct = nullptr) : enclosing(enclosing), _module(_module), scopesym(scopesym), @@ -7213,7 +7219,8 @@ struct Scope final lastdc(lastdc), anchorCounts(anchorCounts), prevAnchor(prevAnchor), - aliasAsg(aliasAsg) + aliasAsg(aliasAsg), + argStruct(argStruct) {} }; diff --git a/compiler/src/dmd/func.d b/compiler/src/dmd/func.d index 2db1b12893ff..9c5a3d0bbb96 100644 --- a/compiler/src/dmd/func.d +++ b/compiler/src/dmd/func.d @@ -1370,11 +1370,13 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration */ extern (C++) final class CtorDeclaration : FuncDeclaration { - bool isCpCtor; - extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, Type type, bool isCpCtor = false) + bool isCpCtor; // copy constructor + bool isMoveCtor; // move constructor (aka rvalue constructor) + extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, Type type, bool isCpCtor = false, bool isMoveCtor = false) { super(loc, endloc, Id.ctor, stc, type); this.isCpCtor = isCpCtor; + this.isMoveCtor = isMoveCtor; //printf("CtorDeclaration(loc = %s) %s %p\n", loc.toChars(), toChars(), this); } diff --git a/compiler/src/dmd/funcsem.d b/compiler/src/dmd/funcsem.d index 689aa57dab3a..fce2a1acc40c 100644 --- a/compiler/src/dmd/funcsem.d +++ b/compiler/src/dmd/funcsem.d @@ -2088,7 +2088,7 @@ MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* name args.push(e); } - MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1); + MATCH m = callMatch(tg, null, ArgumentList(&args, names), 1); if (m > MATCH.nomatch) { /* A variadic parameter list is less specialized than a diff --git a/compiler/src/dmd/hdrgen.d b/compiler/src/dmd/hdrgen.d index 4da5b162850a..ff9eb41b3f83 100644 --- a/compiler/src/dmd/hdrgen.d +++ b/compiler/src/dmd/hdrgen.d @@ -2869,6 +2869,12 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt buf.writestring(e.value.toChars()); } + if (e.rvalue) + buf.writestring("__rvalue("); + scope (success) + if (e.rvalue) + buf.writeByte(')'); + switch (e.op) { default: diff --git a/compiler/src/dmd/parse.d b/compiler/src/dmd/parse.d index 43fcaf933545..e85d35cf8106 100644 --- a/compiler/src/dmd/parse.d +++ b/compiler/src/dmd/parse.d @@ -5880,6 +5880,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(); @@ -8426,6 +8427,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...) diff --git a/compiler/src/dmd/scope.h b/compiler/src/dmd/scope.h index 7983a7ac93f2..5289955a7df7 100644 --- a/compiler/src/dmd/scope.h +++ b/compiler/src/dmd/scope.h @@ -143,6 +143,7 @@ struct Scope final AliasDeclaration *aliasAsg; // if set, then aliasAsg is being assigned a new value, // do not set wasRead for it + StructDeclaration *argStruct; // eliminate recursion when looking for rvalue construction Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol *&pscopesym, SearchOptFlags flags = (SearchOptFlags)SearchOpt::all); }; diff --git a/compiler/src/dmd/templatesem.d b/compiler/src/dmd/templatesem.d index 0e9c4338a052..f0adc7b91bb1 100644 --- a/compiler/src/dmd/templatesem.d +++ b/compiler/src/dmd/templatesem.d @@ -1993,7 +1993,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, tf.mod = tthis_fd.mod; } const(char)* failMessage; - MATCH mfa = tf.callMatch(tthis_fd, argumentList, 0, errorHelper, sc); + MATCH mfa = callMatch(tf, tthis_fd, argumentList, 0, errorHelper, sc); //printf("test1: mfa = %d\n", mfa); if (failMessage) errorHelper(failMessage); @@ -2198,7 +2198,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Type tthis_fd = fd.needThis() && !fd.isCtorDeclaration() ? tthis : null; auto tf = fd.type.isTypeFunction(); - MATCH mfa = tf.callMatch(tthis_fd, argumentList, 0, null, sc); + MATCH mfa = callMatch(tf, tthis_fd, argumentList, 0, null, sc); if (mfa < m.last) return 0; @@ -2300,8 +2300,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, // Disambiguate by tf.callMatch auto tf1 = fd.type.isTypeFunction(); auto tf2 = m.lastf.type.isTypeFunction(); - MATCH c1 = tf1.callMatch(tthis_fd, argumentList, 0, null, sc); - MATCH c2 = tf2.callMatch(tthis_best, argumentList, 0, null, sc); + MATCH c1 = callMatch(tf1, tthis_fd, argumentList, 0, null, sc); + MATCH c2 = callMatch(tf2, tthis_best, argumentList, 0, null, sc); //printf("2: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; @@ -2404,7 +2404,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, if (m.lastf.type.ty == Terror) goto Lerror; auto tf = m.lastf.type.isTypeFunction(); - if (!tf.callMatch(tthis_best, argumentList, 0, null, sc)) + if (callMatch(tf, tthis_best, argumentList, 0, null, sc) == MATCH.nomatch) goto Lnomatch; /* As https://issues.dlang.org/show_bug.cgi?id=3682 shows, diff --git a/compiler/src/dmd/tokens.d b/compiler/src/dmd/tokens.d index da4a3ee209ef..b499c008eab3 100644 --- a/compiler/src/dmd/tokens.d +++ b/compiler/src/dmd/tokens.d @@ -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, @@ -249,6 +252,7 @@ enum TOK : ubyte wchar_tLiteral, endOfLine, // \n, \r, \u2028, \u2029 whitespace, + rvalue, // C only keywords inline, @@ -425,6 +429,7 @@ enum EXP : ubyte interval, loweredAssignExp, + rvalue, } enum FirstCKeyword = TOK.inline; @@ -556,6 +561,7 @@ private immutable TOK[] keywords = TOK.prettyFunction, TOK.shared_, TOK.immutable_, + TOK.rvalue, // C only keywords TOK.inline, @@ -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", diff --git a/compiler/src/dmd/tokens.h b/compiler/src/dmd/tokens.h index 929897a3fa6f..2a984b4b7b62 100644 --- a/compiler/src/dmd/tokens.h +++ b/compiler/src/dmd/tokens.h @@ -258,6 +258,7 @@ enum class TOK : unsigned char wchar_tLiteral, endOfLine, // \n, \r, \u2028, \u2029 whitespace, + rvalue, // C only keywords inline_, diff --git a/compiler/test/fail_compilation/fail19871.d b/compiler/test/fail_compilation/fail19871.d deleted file mode 100644 index ad458df20019..000000000000 --- a/compiler/test/fail_compilation/fail19871.d +++ /dev/null @@ -1,20 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/fail19871.d(10): Error: `struct Struct` may not define both a rvalue constructor and a copy constructor -fail_compilation/fail19871.d(19): rvalue constructor defined here -fail_compilation/fail19871.d(13): copy constructor defined here ---- -*/ - -struct Struct -{ - @disable this(); - this(ref Struct other) - { - const Struct s = void; - this(s); - } - - this(Struct) {} -} diff --git a/compiler/test/fail_compilation/fail19931.d b/compiler/test/fail_compilation/fail19931.d deleted file mode 100644 index 940a1faee028..000000000000 --- a/compiler/test/fail_compilation/fail19931.d +++ /dev/null @@ -1,15 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/fail19931.d(10): Error: `struct S` may not define both a rvalue constructor and a copy constructor -fail_compilation/fail19931.d(12): rvalue constructor defined here -fail_compilation/fail19931.d(13): copy constructor defined here ---- -*/ - -struct S -{ - this(S s) {} - this(ref S s) {} - this(this) {} -} diff --git a/compiler/test/fail_compilation/fail23036.d b/compiler/test/fail_compilation/fail23036.d deleted file mode 100644 index 8920586c67a8..000000000000 --- a/compiler/test/fail_compilation/fail23036.d +++ /dev/null @@ -1,22 +0,0 @@ -// https://issues.dlang.org/show_bug.cgi?id=23036 - -/* -TEST_OUTPUT: ---- -fail_compilation/fail23036.d(12): Error: `struct S` may not define both a rvalue constructor and a copy constructor -fail_compilation/fail23036.d(15): rvalue constructor defined here -fail_compilation/fail23036.d(14): copy constructor defined here ---- -*/ - -struct S -{ - this(ref S) {} - this(S, int a = 2) {} -} - -void main() -{ - S a; - S b = a; -} diff --git a/compiler/test/unit/lexer/location_offset.d b/compiler/test/unit/lexer/location_offset.d index 21266276d2c3..fb7edfd5eb21 100644 --- a/compiler/test/unit/lexer/location_offset.d +++ b/compiler/test/unit/lexer/location_offset.d @@ -399,6 +399,7 @@ enum Test[string] tests = [ "auto_" : Test("auto"), "package_" : Test("package"), "immutable_" : Test("immutable"), + "rvalue" : Test("__rvalue"), "if_" : Test("if"), "else_" : Test("else"),