mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
d: Merge dmd, druntime 11240a9663
D front-end changes: - Import latest fixes from dmd v2.107.0. D runtime changes: - Import latest fixes from druntime v2.107.0. Included in the merge are the fix for PR113772, and new testsuite directives to enable fixing PR104739. PR d/113772 gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 11240a9663. * d-builtins.cc (build_frontend_type): Update for new front-end interface. * types.cc (same_type_p): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 11240a9663.
This commit is contained in:
parent
3c57b1c12a
commit
2dde675ff4
@ -97,12 +97,15 @@ build_frontend_type (tree type)
|
||||
{
|
||||
/* Check for char * first. Needs to be done for chars/string. */
|
||||
if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == char_type_node)
|
||||
return Type::tchar->addMod (dtype->mod)->pointerTo ()->addMod (mod);
|
||||
{
|
||||
dtype = addMod (Type::tchar, dtype->mod);
|
||||
return addMod (dtype->pointerTo (), mod);
|
||||
}
|
||||
|
||||
if (dtype->ty == TY::Tfunction)
|
||||
return (TypePointer::create (dtype))->addMod (mod);
|
||||
return addMod (TypePointer::create (dtype), mod);
|
||||
|
||||
return dtype->pointerTo ()->addMod (mod);
|
||||
return addMod (dtype->pointerTo (), mod);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -113,7 +116,7 @@ build_frontend_type (tree type)
|
||||
/* Want to assign ctype directly so that the REFERENCE_TYPE code
|
||||
can be turned into as an `inout' argument. Can't use pointerTo(),
|
||||
because the returned Type is shared. */
|
||||
dtype = (TypePointer::create (dtype))->addMod (mod);
|
||||
dtype = addMod (TypePointer::create (dtype), mod);
|
||||
dtype->ctype = type;
|
||||
builtin_converted_decls.safe_push (builtin_data (dtype, type));
|
||||
return dtype;
|
||||
@ -122,7 +125,7 @@ build_frontend_type (tree type)
|
||||
|
||||
case BOOLEAN_TYPE:
|
||||
/* Should be no need for size checking. */
|
||||
return Type::tbool->addMod (mod);
|
||||
return addMod (Type::tbool, mod);
|
||||
|
||||
case INTEGER_TYPE:
|
||||
{
|
||||
@ -140,7 +143,7 @@ build_frontend_type (tree type)
|
||||
|| size != dtype->size ())
|
||||
continue;
|
||||
|
||||
return dtype->addMod (mod);
|
||||
return addMod (dtype, mod);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -157,7 +160,7 @@ build_frontend_type (tree type)
|
||||
if (dtype->size () != size)
|
||||
continue;
|
||||
|
||||
return dtype->addMod (mod);
|
||||
return addMod (dtype, mod);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -174,13 +177,13 @@ build_frontend_type (tree type)
|
||||
if (dtype->size () != size)
|
||||
continue;
|
||||
|
||||
return dtype->addMod (mod);
|
||||
return addMod (dtype, mod);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VOID_TYPE:
|
||||
return Type::tvoid->addMod (mod);
|
||||
return addMod (Type::tvoid, mod);
|
||||
|
||||
case ARRAY_TYPE:
|
||||
dtype = build_frontend_type (TREE_TYPE (type));
|
||||
@ -194,7 +197,7 @@ build_frontend_type (tree type)
|
||||
length = size_binop (PLUS_EXPR, size_one_node,
|
||||
convert (sizetype, length));
|
||||
|
||||
dtype = dtype->sarrayOf (TREE_INT_CST_LOW (length))->addMod (mod);
|
||||
dtype = addMod (dtype->sarrayOf (TREE_INT_CST_LOW (length)), mod);
|
||||
builtin_converted_decls.safe_push (builtin_data (dtype, type));
|
||||
return dtype;
|
||||
}
|
||||
@ -210,11 +213,11 @@ build_frontend_type (tree type)
|
||||
if (!dtype)
|
||||
break;
|
||||
|
||||
dtype = dtype->sarrayOf (nunits)->addMod (mod);
|
||||
dtype = addMod (dtype->sarrayOf (nunits), mod);
|
||||
if (target.isVectorTypeSupported (dtype->size (), dtype->nextOf ()))
|
||||
break;
|
||||
|
||||
dtype = (TypeVector::create (dtype))->addMod (mod);
|
||||
dtype = addMod (TypeVector::create (dtype), mod);
|
||||
builtin_converted_decls.safe_push (builtin_data (dtype, type));
|
||||
return dtype;
|
||||
}
|
||||
@ -238,7 +241,7 @@ build_frontend_type (tree type)
|
||||
sdecl->alignsize = TYPE_ALIGN_UNIT (type);
|
||||
sdecl->alignment.setDefault ();
|
||||
sdecl->sizeok = Sizeok::done;
|
||||
sdecl->type = (TypeStruct::create (sdecl))->addMod (mod);
|
||||
sdecl->type = addMod (TypeStruct::create (sdecl), mod);
|
||||
sdecl->type->ctype = type;
|
||||
merge2 (sdecl->type);
|
||||
|
||||
@ -331,7 +334,7 @@ build_frontend_type (tree type)
|
||||
if (args->length != 0 || varargs_p == VARARGnone)
|
||||
{
|
||||
dtype = TypeFunction::create (args, dtype, varargs_p, LINK::c);
|
||||
return dtype->addMod (mod);
|
||||
return addMod (dtype, mod);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
a6f10836997d0b5526c8c363d781b4029c77f09f
|
||||
11240a96635074b2f79d908b9348e9c0fbc3c7dc
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
@ -37,7 +37,7 @@ import dmd.identifier;
|
||||
import dmd.location;
|
||||
import dmd.mtype;
|
||||
import dmd.tokens;
|
||||
import dmd.typesem : defaultInit;
|
||||
import dmd.typesem : defaultInit, addMod;
|
||||
import dmd.visitor;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +42,7 @@ enum class Baseok : uint8_t
|
||||
};
|
||||
|
||||
FuncDeclaration *search_toString(StructDeclaration *sd);
|
||||
void semanticTypeInfoMembers(StructDeclaration *sd);
|
||||
|
||||
enum class ClassKind : uint8_t
|
||||
{
|
||||
|
@ -82,6 +82,7 @@ struct ASTCodegen
|
||||
alias Tcomplex64 = dmd.mtype.Tcomplex64;
|
||||
alias Tcomplex80 = dmd.mtype.Tcomplex80;
|
||||
|
||||
alias ModToStc = dmd.mtype.ModToStc;
|
||||
alias ParameterList = dmd.mtype.ParameterList;
|
||||
alias VarArg = dmd.mtype.VarArg;
|
||||
alias STC = dmd.declaration.STC;
|
||||
|
@ -152,7 +152,7 @@ bool isRefReturnScope(const ulong stc)
|
||||
|
||||
/* This is different from the one in declaration.d, make that fix a separate PR */
|
||||
static if (0)
|
||||
extern (C++) __gshared const(StorageClass) STCStorageClass =
|
||||
__gshared const(StorageClass) STCStorageClass =
|
||||
(STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.const_ | STC.final_ |
|
||||
STC.abstract_ | STC.synchronized_ | STC.deprecated_ | STC.override_ | STC.lazy_ |
|
||||
STC.alias_ | STC.out_ | STC.in_ | STC.manifest | STC.immutable_ | STC.shared_ |
|
||||
|
@ -327,10 +327,19 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
|
||||
auto e2 = new BlitExp(loc, new VarExp(loc, swap), new ThisExp(loc));
|
||||
auto e3 = new BlitExp(loc, new ThisExp(loc), new IdentifierExp(loc, Id.p));
|
||||
|
||||
/* Instead of running the destructor on s, run it
|
||||
* on swap. This avoids needing to copy swap back in to s.
|
||||
*/
|
||||
auto e4 = new CallExp(loc, new DotVarExp(loc, new VarExp(loc, swap), sd.dtor, false));
|
||||
Expression e4;
|
||||
if (target.isCalleeDestroyingArgs(tf))
|
||||
{ /* callee destroys s
|
||||
* Instead of running the destructor on s, run it
|
||||
* on swap.
|
||||
*/
|
||||
e4 = new CallExp(loc, new DotVarExp(loc, new VarExp(loc, swap), sd.dtor, false));
|
||||
}
|
||||
else
|
||||
{ /* caller destroys s, so copy contents of swap back into s
|
||||
*/
|
||||
e4 = new BlitExp(loc, new IdentifierExp(loc, Id.p), new VarExp(loc, swap));
|
||||
}
|
||||
|
||||
e = Expression.combine(e1, e2, e3, e4);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import dmd.root.utf;
|
||||
import dmd.sideeffect;
|
||||
import dmd.target;
|
||||
import dmd.tokens;
|
||||
import dmd.typesem : toDsymbol, equivalent;
|
||||
|
||||
private enum LOG = false;
|
||||
|
||||
@ -1038,7 +1039,6 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
|
||||
else if (tb.ty == Tstruct && e1.op == EXP.int64)
|
||||
{
|
||||
// Struct = 0;
|
||||
import dmd.typesem : toDsymbol;
|
||||
StructDeclaration sd = tb.toDsymbol(null).isStructDeclaration();
|
||||
assert(sd);
|
||||
auto elements = new Expressions();
|
||||
|
@ -235,7 +235,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
|
||||
* Returns:
|
||||
* The `MATCH` level between `e.type` and `t`.
|
||||
*/
|
||||
extern(C++) MATCH implicitConvTo(Expression e, Type t)
|
||||
MATCH implicitConvTo(Expression e, Type t)
|
||||
{
|
||||
MATCH visit(Expression e)
|
||||
{
|
||||
@ -2848,7 +2848,7 @@ private bool isVoidArrayLiteral(Expression e, Type other)
|
||||
*/
|
||||
Type typeMerge(Scope* sc, EXP op, ref Expression pe1, ref Expression pe2)
|
||||
{
|
||||
//printf("typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
|
||||
//printf("typeMerge() %s op %s\n", pe1.toChars(), pe2.toChars());
|
||||
|
||||
Expression e1 = pe1;
|
||||
Expression e2 = pe2;
|
||||
@ -3165,6 +3165,9 @@ Lagain:
|
||||
goto Lagain;
|
||||
}
|
||||
|
||||
LmergeClassTypes:
|
||||
/* Merge different type modifiers on classes
|
||||
*/
|
||||
if (t1.ty == Tclass && t2.ty == Tclass)
|
||||
{
|
||||
if (t1.mod != t2.mod)
|
||||
@ -3233,9 +3236,23 @@ Lagain:
|
||||
|
||||
if (t1.ty == Tclass && t2.ty == Tclass)
|
||||
{
|
||||
/* t1 cannot be converted to t2, and vice versa
|
||||
*/
|
||||
TypeClass tc1 = t1.isTypeClass();
|
||||
TypeClass tc2 = t2.isTypeClass();
|
||||
|
||||
//if (tc1.sym.interfaces.length || tc2.sym.interfaces.length)
|
||||
if (tc1.sym.isInterfaceDeclaration() ||
|
||||
tc2.sym.isInterfaceDeclaration())
|
||||
{
|
||||
ClassDeclaration cd = findClassCommonRoot(tc1.sym, tc2.sym);
|
||||
if (!cd)
|
||||
return null; // no common root
|
||||
t1 = cd.type.castMod(t1.mod);
|
||||
t2 = cd.type.castMod(t2.mod);
|
||||
goto LmergeClassTypes; // deal with mod differences
|
||||
}
|
||||
|
||||
/* Pick 'tightest' type
|
||||
*/
|
||||
ClassDeclaration cd1 = tc1.sym.baseClass;
|
||||
@ -3251,6 +3268,7 @@ Lagain:
|
||||
t2 = cd2.type;
|
||||
else
|
||||
return null;
|
||||
goto LmergeClassTypes;
|
||||
}
|
||||
else if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
|
||||
{
|
||||
@ -3582,6 +3600,71 @@ LmodCompare:
|
||||
return null;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Find common root that both cd1 and cd2 can be implicitly converted to.
|
||||
* Params:
|
||||
* cd1 = first class
|
||||
* cd2 = second class
|
||||
* Returns:
|
||||
* common base that both can implicitly convert to, null if none or
|
||||
* multiple matches
|
||||
*/
|
||||
private
|
||||
ClassDeclaration findClassCommonRoot(ClassDeclaration cd1, ClassDeclaration cd2)
|
||||
{
|
||||
enum log = false;
|
||||
if (log) printf("findClassCommonRoot(%s, %s)\n", cd1.toChars(), cd2.toChars());
|
||||
/* accumulate results in this */
|
||||
static struct Root
|
||||
{
|
||||
ClassDeclaration cd;
|
||||
bool error;
|
||||
|
||||
/* merge cd into results */
|
||||
void accumulate(ClassDeclaration cd)
|
||||
{
|
||||
if (log) printf(" accumulate(r.cd: %s r.error: %d cd: %s)\n", this.cd ? this.cd.toChars() : "null", error, cd ? cd.toChars() : null);
|
||||
if (this.cd is cd)
|
||||
{
|
||||
}
|
||||
else if (!this.cd)
|
||||
this.cd = cd;
|
||||
else
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find common root of cd1 and cd2. Accumulate results in r. depth is nesting level */
|
||||
void findCommonRoot(ClassDeclaration cd1, ClassDeclaration cd2, ref Root r)
|
||||
{
|
||||
if (log) printf("findCommonRoot(cd1: %s cd2: %s)\n", cd1.toChars(), cd2.toChars());
|
||||
/* Warning: quadratic time function
|
||||
*/
|
||||
if (cd1 is cd2)
|
||||
{
|
||||
r.accumulate(cd1);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (b1; (*cd1.baseclasses)[])
|
||||
{
|
||||
if (b1.sym != r.cd)
|
||||
findCommonRoot(cd2, b1.sym, r);
|
||||
}
|
||||
foreach (b2; (*cd2.baseclasses)[])
|
||||
{
|
||||
if (b2.sym != r.cd)
|
||||
findCommonRoot(cd1, b2.sym, r);
|
||||
}
|
||||
}
|
||||
|
||||
Root r;
|
||||
findCommonRoot(cd1, cd2, r);
|
||||
if (!r.cd || r.error)
|
||||
return null; // no common root
|
||||
return r.cd;
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Bring leaves to common type.
|
||||
* Returns:
|
||||
|
@ -213,7 +213,7 @@ bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
|
||||
|
||||
/******************************************
|
||||
*/
|
||||
extern (C++) void ObjectNotFound(Identifier id)
|
||||
void ObjectNotFound(Identifier id)
|
||||
{
|
||||
error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
|
||||
fatal();
|
||||
@ -1380,7 +1380,7 @@ extern (C++) class VarDeclaration : Declaration
|
||||
*/
|
||||
final bool needsScopeDtor()
|
||||
{
|
||||
//printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
|
||||
//printf("VarDeclaration::needsScopeDtor() %s %d\n", toChars(), edtor && !(storage_class & STC.nodtor));
|
||||
return edtor && !(storage_class & STC.nodtor);
|
||||
}
|
||||
|
||||
|
@ -107,8 +107,6 @@ bool functionSemantic3(FuncDeclaration* fd);
|
||||
#define STC_TYPECTOR (STCconst | STCimmutable | STCshared | STCwild)
|
||||
#define STC_FUNCATTR (STCref | STCnothrow | STCnogc | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem)
|
||||
|
||||
void ObjectNotFound(Identifier *id);
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
class Declaration : public Dsymbol
|
||||
|
@ -50,7 +50,7 @@ import dmd.rootobject;
|
||||
import dmd.root.utf;
|
||||
import dmd.statement;
|
||||
import dmd.tokens;
|
||||
import dmd.typesem : mutableOf;
|
||||
import dmd.typesem : mutableOf, equivalent;
|
||||
import dmd.utils : arrayCastBigEndian;
|
||||
import dmd.visitor;
|
||||
|
||||
|
@ -427,7 +427,5 @@ public:
|
||||
|
||||
void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds);
|
||||
Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, SearchOptFlags flags = (SearchOptFlags)SearchOpt::localsOnly);
|
||||
bool checkDeprecated(Dsymbol *d, const Loc &loc, Scope *sc);
|
||||
void setScope(Dsymbol *d, Scope *sc);
|
||||
void importAll(Dsymbol *d, Scope *sc);
|
||||
void setFieldOffset(Dsymbol *d, AggregateDeclaration *ad, FieldState& fieldState, bool isunion);
|
||||
|
@ -6907,7 +6907,7 @@ extern(C++) class ImportAllVisitor : Visitor
|
||||
override void visit(StaticForeachDeclaration _) {}
|
||||
}
|
||||
|
||||
extern(C++) void setFieldOffset(Dsymbol d, AggregateDeclaration ad, FieldState* fieldState, bool isunion)
|
||||
void setFieldOffset(Dsymbol d, AggregateDeclaration ad, FieldState* fieldState, bool isunion)
|
||||
{
|
||||
scope v = new SetFieldOffsetVisitor(ad, fieldState, isunion);
|
||||
d.accept(v);
|
||||
|
@ -24,8 +24,6 @@ enum class ErrorKind
|
||||
message = 4,
|
||||
};
|
||||
|
||||
bool isConsoleColorSupported();
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define D_ATTRIBUTE_FORMAT(m, n) __attribute__((format(printf, m, n))) __attribute__((nonnull (m)))
|
||||
#else
|
||||
|
@ -46,15 +46,15 @@ typedef union tree_node Symbol;
|
||||
struct Symbol; // back end symbol
|
||||
#endif
|
||||
|
||||
// in expressionsem.d
|
||||
Expression *expressionSemantic(Expression *e, Scope *sc);
|
||||
// in typesem.d
|
||||
Expression *defaultInit(Type *mt, const Loc &loc, const bool isCfile = false);
|
||||
|
||||
// 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);
|
||||
StringExp *toUTF8(StringExp *se, Scope *sc);
|
||||
Expression *resolveLoc(Expression *exp, const Loc &loc, Scope *sc);
|
||||
MATCH implicitConvTo(Expression *e, Type *t);
|
||||
Expression *toLvalue(Expression *_this, Scope *sc, const char* action);
|
||||
Expression *modifiableLvalue(Expression* exp, Scope *sc);
|
||||
Expression *optimize(Expression *exp, int result, bool keepLvalue = false);
|
||||
|
||||
typedef unsigned char OwnedBy;
|
||||
|
@ -2523,7 +2523,7 @@ private bool checkRightThis(Expression e, Scope* sc)
|
||||
return false;
|
||||
}
|
||||
|
||||
extern (C++) Expression resolveProperties(Scope* sc, Expression e)
|
||||
Expression resolveProperties(Scope* sc, Expression e)
|
||||
{
|
||||
//printf("resolveProperties(%s)\n", e.toChars());
|
||||
e = resolvePropertiesX(sc, e);
|
||||
@ -3464,12 +3464,12 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
||||
eprefix = ae.expressionSemantic(sc);
|
||||
}
|
||||
|
||||
for (ptrdiff_t i = 0; i != nargs; i++)
|
||||
foreach (ptrdiff_t i; 0 .. nargs)
|
||||
{
|
||||
Expression arg = (*arguments)[i];
|
||||
//printf("arg[%d]: %s\n", cast(int)i, arg.toChars());
|
||||
|
||||
Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
|
||||
Parameter parameter = i < nparams ? tf.parameterList[i] : null;
|
||||
const bool isRef = parameter && parameter.isReference();
|
||||
const bool isLazy = parameter && parameter.isLazy();
|
||||
|
||||
@ -3485,7 +3485,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
||||
* 'eprefix' will therefore finally contain all args up to and including 'lastPrefix',
|
||||
* excluding all lazy parameters.
|
||||
*/
|
||||
if (needsPrefix && (lastPrefix - i) >= 0)
|
||||
if (needsPrefix && i <= lastPrefix)
|
||||
{
|
||||
const bool needsDtor = !isRef && arg.type.needsDestruction() &&
|
||||
// Problem 3: last throwing arg doesn't require dtor patching
|
||||
@ -3494,9 +3494,9 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
||||
/* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
|
||||
*/
|
||||
auto tmp = copyToTemp(
|
||||
(parameter ? parameter.storageClass : tf.parameterList.stc) & (STC.scope_),
|
||||
(parameter ? parameter.storageClass : tf.parameterList.stc) & (STC.return_ | STC.scope_),
|
||||
needsDtor ? "__pfx" : "__pfy",
|
||||
!isRef ? arg : arg.addressOf());
|
||||
isRef ? arg.addressOf() : arg);
|
||||
tmp.dsymbolSemantic(sc);
|
||||
|
||||
if (callerDestroysArgs)
|
||||
@ -3511,15 +3511,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
||||
/* Problem 2: Modify the destructor so it only runs if gate==false,
|
||||
* i.e., only if there was a throw while constructing the args
|
||||
*/
|
||||
if (!needsDtor)
|
||||
{
|
||||
if (tmp.edtor)
|
||||
{
|
||||
assert(i == lastPrefix);
|
||||
tmp.edtor = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (needsDtor)
|
||||
{
|
||||
// edtor => (__gate || edtor)
|
||||
assert(tmp.edtor);
|
||||
@ -3528,6 +3520,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
||||
tmp.edtor = e.expressionSemantic(sc);
|
||||
//printf("edtor: %s\n", tmp.edtor.toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tmp.edtor)
|
||||
{
|
||||
assert(i == lastPrefix);
|
||||
tmp.edtor = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eprefix => (eprefix, auto __pfx/y = arg)
|
||||
@ -15534,7 +15534,7 @@ Expression addDtorHook(Expression e, Scope* sc)
|
||||
* action = for error messages, what the lvalue is needed for (e.g. take address of for `&x`, modify for `x++`)
|
||||
* Returns: converted expression, or `ErrorExp` on error
|
||||
*/
|
||||
extern(C++) Expression toLvalue(Expression _this, Scope* sc, const(char)* action)
|
||||
Expression toLvalue(Expression _this, Scope* sc, const(char)* action)
|
||||
{
|
||||
return toLvalueImpl(_this, sc, action, _this);
|
||||
}
|
||||
@ -15955,7 +15955,7 @@ Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag = ModifyF
|
||||
* sc = scope
|
||||
* Returns: `_this` converted to an lvalue, or an `ErrorExp`
|
||||
*/
|
||||
extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc)
|
||||
Expression modifiableLvalue(Expression _this, Scope* sc)
|
||||
{
|
||||
return modifiableLvalueImpl(_this, sc, _this);
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ import dmd.statement;
|
||||
import dmd.statementsem;
|
||||
import dmd.templatesem;
|
||||
import dmd.tokens;
|
||||
import dmd.typesem;
|
||||
import dmd.visitor;
|
||||
|
||||
version (IN_GCC) {}
|
||||
@ -518,7 +519,6 @@ extern (C++) class FuncDeclaration : Declaration
|
||||
int result = 0;
|
||||
if (fd.ident == ident)
|
||||
{
|
||||
import dmd.typesem : covariant;
|
||||
const cov = type.covariant(fd.type);
|
||||
if (cov != Covariant.distinct)
|
||||
{
|
||||
@ -625,7 +625,6 @@ extern (C++) class FuncDeclaration : Declaration
|
||||
*/
|
||||
if (t.ty == Tfunction)
|
||||
{
|
||||
import dmd.typesem : covariant;
|
||||
auto tf = cast(TypeFunction)f.type;
|
||||
if (tf.covariant(t) == Covariant.yes &&
|
||||
tf.nextOf().implicitConvTo(t.nextOf()) >= MATCH.constant)
|
||||
@ -840,7 +839,6 @@ extern (C++) class FuncDeclaration : Declaration
|
||||
args.push(e);
|
||||
}
|
||||
|
||||
import dmd.typesem : callMatch;
|
||||
MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1);
|
||||
if (m > MATCH.nomatch)
|
||||
{
|
||||
@ -1151,7 +1149,6 @@ extern (C++) class FuncDeclaration : Declaration
|
||||
{
|
||||
//printf("FuncDeclaration::isPure() '%s'\n", toChars());
|
||||
|
||||
import dmd.typesem : purityLevel;
|
||||
|
||||
TypeFunction tf = type.toTypeFunction();
|
||||
if (purityInprocess)
|
||||
@ -1464,7 +1461,6 @@ extern (C++) class FuncDeclaration : Declaration
|
||||
case Tstruct:
|
||||
/* Drill down and check the struct's fields
|
||||
*/
|
||||
import dmd.typesem : toDsymbol;
|
||||
auto sym = t.toDsymbol(null).isStructDeclaration();
|
||||
const tName = t.toChars.toDString;
|
||||
const entry = parentTypes.insert(tName, t);
|
||||
@ -1546,7 +1542,6 @@ extern (C++) class FuncDeclaration : Declaration
|
||||
case Tstruct:
|
||||
/* Drill down and check the struct's fields
|
||||
*/
|
||||
import dmd.typesem : toDsymbol;
|
||||
auto sym = tp.toDsymbol(null).isStructDeclaration();
|
||||
foreach (v; sym.fields)
|
||||
{
|
||||
@ -2411,7 +2406,6 @@ extern (C++) class FuncDeclaration : Declaration
|
||||
{
|
||||
Type t1 = fdv.type.nextOf().toBasetype();
|
||||
Type t2 = this.type.nextOf().toBasetype();
|
||||
import dmd.typesem : isBaseOf;
|
||||
if (t1.isBaseOf(t2, null))
|
||||
{
|
||||
/* Making temporary reference variable is necessary
|
||||
@ -3325,7 +3319,6 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
|
||||
*/
|
||||
Type getIndirection(Type t)
|
||||
{
|
||||
import dmd.typesem : hasPointers;
|
||||
t = t.baseElemOf();
|
||||
if (t.ty == Tarray || t.ty == Tpointer)
|
||||
return t.nextOf().toBasetype();
|
||||
@ -3372,7 +3365,6 @@ private bool traverseIndirections(Type ta, Type tb)
|
||||
|
||||
static bool traverse(Type ta, Type tb, ref scope AssocArray!(const(char)*, bool) table, bool reversePass)
|
||||
{
|
||||
import dmd.typesem : hasPointers;
|
||||
//printf("traverse(%s, %s)\n", ta.toChars(), tb.toChars());
|
||||
ta = ta.baseElemOf();
|
||||
tb = tb.baseElemOf();
|
||||
@ -3409,7 +3401,6 @@ private bool traverseIndirections(Type ta, Type tb)
|
||||
else
|
||||
*found = true;
|
||||
|
||||
import dmd.typesem : toDsymbol;
|
||||
AggregateDeclaration sym = tb.toDsymbol(null).isAggregateDeclaration();
|
||||
foreach (v; sym.fields)
|
||||
{
|
||||
|
@ -13,9 +13,17 @@
|
||||
#include "globals.h"
|
||||
#include "mtype.h"
|
||||
|
||||
class Expression;
|
||||
class Initializer;
|
||||
class Module;
|
||||
class Statement;
|
||||
|
||||
void genhdrfile(Module *m, bool doFuncBodies, OutBuffer &buf);
|
||||
void genCppHdrFiles(Modules &ms);
|
||||
void moduleToBuffer(OutBuffer& buf, bool vcg_ast, Module *m);
|
||||
const char *parametersTypeToChars(ParameterList pl);
|
||||
|
||||
const char* toChars(const Expression* const e);
|
||||
const char* toChars(const Initializer* const i);
|
||||
const char* toChars(const Statement* const s);
|
||||
const char* toChars(const Type* const t);
|
||||
|
@ -125,3 +125,4 @@ public:
|
||||
};
|
||||
|
||||
Expression *initializerToExpression(Initializer *init, Type *t = NULL, const bool isCfile = false);
|
||||
Initializer *initializerSemantic(Initializer *init, Scope *sc, Type *&tx, NeedInterpret needInterpret);
|
||||
|
@ -444,11 +444,6 @@ extern (C++) abstract class Type : ASTNode
|
||||
return false;
|
||||
}
|
||||
|
||||
final bool equivalent(Type t)
|
||||
{
|
||||
return immutableOf(this).equals(t.immutableOf());
|
||||
}
|
||||
|
||||
// kludge for template.isType()
|
||||
override final DYNCAST dyncast() const
|
||||
{
|
||||
@ -1191,111 +1186,6 @@ extern (C++) abstract class Type : ASTNode
|
||||
return t;
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Add MODxxxx bits to existing type.
|
||||
* We're adding, not replacing, so adding const to
|
||||
* a shared type => "shared const"
|
||||
*/
|
||||
final Type addMod(MOD mod)
|
||||
{
|
||||
/* Add anything to immutable, and it remains immutable
|
||||
*/
|
||||
Type t = this;
|
||||
if (!t.isImmutable())
|
||||
{
|
||||
//printf("addMod(%x) %s\n", mod, toChars());
|
||||
switch (mod)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case MODFlags.const_:
|
||||
if (isShared())
|
||||
{
|
||||
if (isWild())
|
||||
t = this.sharedWildConstOf();
|
||||
else
|
||||
t = this.sharedConstOf();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.isWild())
|
||||
t = this.wildConstOf();
|
||||
else
|
||||
t = t.constOf();
|
||||
}
|
||||
break;
|
||||
|
||||
case MODFlags.wild:
|
||||
if (isShared())
|
||||
{
|
||||
if (isConst())
|
||||
t = this.sharedWildConstOf();
|
||||
else
|
||||
t = this.sharedWildOf();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isConst())
|
||||
t = this.wildConstOf();
|
||||
else
|
||||
t = this.wildOf();
|
||||
}
|
||||
break;
|
||||
|
||||
case MODFlags.wildconst:
|
||||
if (isShared())
|
||||
t = this.sharedWildConstOf();
|
||||
else
|
||||
t = this.wildConstOf();
|
||||
break;
|
||||
|
||||
case MODFlags.shared_:
|
||||
if (isWild())
|
||||
{
|
||||
if (isConst())
|
||||
t = this.sharedWildConstOf();
|
||||
else
|
||||
t = this.sharedWildOf();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isConst())
|
||||
t = this.sharedConstOf();
|
||||
else
|
||||
t = this.sharedOf();
|
||||
}
|
||||
break;
|
||||
|
||||
case MODFlags.shared_ | MODFlags.const_:
|
||||
if (isWild())
|
||||
t = this.sharedWildConstOf();
|
||||
else
|
||||
t = this.sharedConstOf();
|
||||
break;
|
||||
|
||||
case MODFlags.shared_ | MODFlags.wild:
|
||||
if (isConst())
|
||||
t = this.sharedWildConstOf();
|
||||
else
|
||||
t = this.sharedWildOf();
|
||||
break;
|
||||
|
||||
case MODFlags.shared_ | MODFlags.wildconst:
|
||||
t = this.sharedWildConstOf();
|
||||
break;
|
||||
|
||||
case MODFlags.immutable_:
|
||||
t = this.immutableOf();
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Add storage class modifiers to type.
|
||||
*/
|
||||
@ -1315,7 +1205,7 @@ extern (C++) abstract class Type : ASTNode
|
||||
if (stc & STC.shared_)
|
||||
mod |= MODFlags.shared_;
|
||||
}
|
||||
return addMod(mod);
|
||||
return this.addMod(mod);
|
||||
}
|
||||
|
||||
final Type pointerTo()
|
||||
|
@ -39,7 +39,6 @@ typedef union tree_node type;
|
||||
typedef struct TYPE type;
|
||||
#endif
|
||||
|
||||
extern const char* toChars(const Type* const t);
|
||||
Type *typeSemantic(Type *t, const Loc &loc, Scope *sc);
|
||||
Type *merge(Type *type);
|
||||
|
||||
@ -218,7 +217,6 @@ public:
|
||||
Type *copy() const;
|
||||
virtual Type *syntaxCopy();
|
||||
bool equals(const RootObject * const o) const override;
|
||||
bool equivalent(Type *t);
|
||||
// kludge for template.isType()
|
||||
DYNCAST dyncast() const override final { return DYNCAST_TYPE; }
|
||||
size_t getUniqueID() const;
|
||||
@ -253,7 +251,6 @@ public:
|
||||
bool isSharedWild() const { return (mod & (MODshared | MODwild)) == (MODshared | MODwild); }
|
||||
bool isNaked() const { return mod == 0; }
|
||||
Type *nullAttributes() const;
|
||||
Type *addMod(MOD mod);
|
||||
virtual Type *addStorageClass(StorageClass stc);
|
||||
Type *pointerTo();
|
||||
Type *referenceTo();
|
||||
@ -889,10 +886,10 @@ AggregateDeclaration *isAggregate(Type *t);
|
||||
bool hasPointers(Type *t);
|
||||
// return the symbol to which type t resolves
|
||||
Dsymbol *toDsymbol(Type *t, Scope *sc);
|
||||
bool equivalent(Type *src, Type *t);
|
||||
Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false);
|
||||
bool isBaseOf(Type *tthis, Type *t, int *poffset);
|
||||
Type *trySemantic(Type *type, const Loc &loc, Scope *sc);
|
||||
void purityLevel(TypeFunction *type);
|
||||
Type *merge2(Type *type);
|
||||
Type *constOf(Type *type);
|
||||
Type *immutableOf(Type *type);
|
||||
@ -905,3 +902,4 @@ Type *wildConstOf(Type *type);
|
||||
Type *sharedWildOf(Type *type);
|
||||
Type *sharedWildConstOf(Type *type);
|
||||
Type *castMod(Type *type, MOD mod);
|
||||
Type *addMod(Type *type, MOD mod);
|
||||
|
@ -8730,7 +8730,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||
else
|
||||
{
|
||||
AST.Type t = parseType(); // cast( type )
|
||||
t = t.addMod(m); // cast( const type )
|
||||
t = t.addSTC(AST.ModToStc(m)); // cast( const type )
|
||||
check(TOK.rightParenthesis);
|
||||
e = parseUnaryExp();
|
||||
e = new AST.CastExp(loc, e, t);
|
||||
|
@ -701,7 +701,12 @@ public:
|
||||
void accept(Visitor *v) override { v->visit(this); }
|
||||
};
|
||||
|
||||
// in statementsem.d
|
||||
Statement* statementSemantic(Statement *s, Scope *sc);
|
||||
// in iasm.d
|
||||
Statement* asmSemantic(AsmStatement *s, Scope *sc);
|
||||
// in iasmgcc.d
|
||||
Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc);
|
||||
|
||||
class AsmStatement : public Statement
|
||||
{
|
||||
|
@ -317,6 +317,9 @@ public:
|
||||
void accept(Visitor *v) override { v->visit(this); }
|
||||
};
|
||||
|
||||
// in templateparamsem.d
|
||||
bool tpsemantic(TemplateParameter *tp, Scope *sc, TemplateParameters *parameters);
|
||||
|
||||
Expression *isExpression(RootObject *o);
|
||||
Dsymbol *isDsymbol(RootObject *o);
|
||||
Type *isType(RootObject *o);
|
||||
|
@ -520,7 +520,7 @@ int mutabilityOfType(bool isref, Type t)
|
||||
* Set 'purity' field of 'typeFunction'.
|
||||
* Do this lazily, as the parameter types might be forward referenced.
|
||||
*/
|
||||
extern(C++) void purityLevel(TypeFunction typeFunction)
|
||||
void purityLevel(TypeFunction typeFunction)
|
||||
{
|
||||
TypeFunction tf = typeFunction;
|
||||
if (tf.purity != PURE.fwdref)
|
||||
@ -6106,6 +6106,11 @@ extern(C++) bool isBaseOf(Type tthis, Type t, int* poffset)
|
||||
return false;
|
||||
}
|
||||
|
||||
extern(C++) bool equivalent(Type src, Type t)
|
||||
{
|
||||
return immutableOf(src).equals(t.immutableOf());
|
||||
}
|
||||
|
||||
/********************************
|
||||
* Convert to 'const'.
|
||||
*/
|
||||
@ -6405,6 +6410,111 @@ extern(C++) Type castMod(Type type, MOD mod)
|
||||
return t;
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Add MODxxxx bits to existing type.
|
||||
* We're adding, not replacing, so adding const to
|
||||
* a shared type => "shared const"
|
||||
*/
|
||||
extern(C++) Type addMod(Type type, MOD mod)
|
||||
{
|
||||
/* Add anything to immutable, and it remains immutable
|
||||
*/
|
||||
Type t = type;
|
||||
if (!t.isImmutable())
|
||||
{
|
||||
//printf("addMod(%x) %s\n", mod, toChars());
|
||||
switch (mod)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case MODFlags.const_:
|
||||
if (type.isShared())
|
||||
{
|
||||
if (type.isWild())
|
||||
t = type.sharedWildConstOf();
|
||||
else
|
||||
t = type.sharedConstOf();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type.isWild())
|
||||
t = type.wildConstOf();
|
||||
else
|
||||
t = t.constOf();
|
||||
}
|
||||
break;
|
||||
|
||||
case MODFlags.wild:
|
||||
if (type.isShared())
|
||||
{
|
||||
if (type.isConst())
|
||||
t = type.sharedWildConstOf();
|
||||
else
|
||||
t = type.sharedWildOf();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type.isConst())
|
||||
t = type.wildConstOf();
|
||||
else
|
||||
t = type.wildOf();
|
||||
}
|
||||
break;
|
||||
|
||||
case MODFlags.wildconst:
|
||||
if (type.isShared())
|
||||
t = type.sharedWildConstOf();
|
||||
else
|
||||
t = type.wildConstOf();
|
||||
break;
|
||||
|
||||
case MODFlags.shared_:
|
||||
if (type.isWild())
|
||||
{
|
||||
if (type.isConst())
|
||||
t = type.sharedWildConstOf();
|
||||
else
|
||||
t = type.sharedWildOf();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type.isConst())
|
||||
t = type.sharedConstOf();
|
||||
else
|
||||
t = type.sharedOf();
|
||||
}
|
||||
break;
|
||||
|
||||
case MODFlags.shared_ | MODFlags.const_:
|
||||
if (type.isWild())
|
||||
t = type.sharedWildConstOf();
|
||||
else
|
||||
t = type.sharedConstOf();
|
||||
break;
|
||||
|
||||
case MODFlags.shared_ | MODFlags.wild:
|
||||
if (type.isConst())
|
||||
t = type.sharedWildConstOf();
|
||||
else
|
||||
t = type.sharedWildOf();
|
||||
break;
|
||||
|
||||
case MODFlags.shared_ | MODFlags.wildconst:
|
||||
t = type.sharedWildConstOf();
|
||||
break;
|
||||
|
||||
case MODFlags.immutable_:
|
||||
t = type.immutableOf();
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/******************************* Private *****************************************/
|
||||
|
||||
private:
|
||||
|
@ -144,7 +144,7 @@ same_type_p (Type *t1, Type *t2)
|
||||
return true;
|
||||
|
||||
/* Types are mutably the same type. */
|
||||
if (tb1->ty == tb2->ty && tb1->equivalent (tb2))
|
||||
if (tb1->ty == tb2->ty && equivalent (tb1, tb2))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -413,12 +413,12 @@ static assert(is( X!( C, immutable(B) ) == const(B) ));
|
||||
static assert(is( X!( C, immutable(D) ) == const(B) ));
|
||||
static assert(is( X!( C, immutable(K) ) == const(Object) ));
|
||||
|
||||
static assert(Error!( C, immutable(SC) )); // should work
|
||||
static assert(Error!( C, immutable(SI) )); // should work
|
||||
static assert(Error!( immutable(SI), C )); // should work
|
||||
static assert(Error!( C, immutable(SB) )); // should work
|
||||
static assert(Error!( C, immutable(SD) )); // should work
|
||||
static assert(Error!( C, immutable(SK) )); // should work
|
||||
static assert(is( X!( C, immutable(SC)) == const(B) ));
|
||||
static assert(is( X!( C, immutable(SI) ) == const(I) ));
|
||||
static assert(is( X!( immutable(SI), C ) == const(I) ));
|
||||
static assert(is( X!( C, immutable(SB) ) == const(Object) ));
|
||||
static assert(is( X!( C, immutable(SD) ) == const(B) ));
|
||||
static assert(is( X!( C, immutable(SK) ) == const(Object) ));
|
||||
|
||||
static assert(is( X!( const(C), C ) == const(C) ));
|
||||
static assert(is( X!( const(C), I ) == const(I) ));
|
||||
@ -427,11 +427,11 @@ static assert(is( X!( const(C), D ) == const(B) ));
|
||||
static assert(is( X!( const(C), K ) == const(Object) ));
|
||||
|
||||
static assert(is( X!( const(C), SC ) == const(C)));
|
||||
static assert(Error!( const(C), SI )); // should work
|
||||
static assert(is( X!( const(SI), const(C) ) == const(I) )); // should work
|
||||
static assert(is( X!( const(C), SB ) == const(B)));
|
||||
static assert(is( X!( const(C), SI ) == const(I)));
|
||||
static assert(is( X!( const(SI), const(C) ) == const(I) ));
|
||||
static assert(is( X!( const(C), SB ) == const(Object)));
|
||||
static assert(is( X!( const(C), SD ) == const(B)));
|
||||
static assert(is( X!( const(C), SK ) == Object)); // `const`
|
||||
static assert(is( X!( const(C), SK ) == const(Object)));
|
||||
|
||||
static assert(is( X!( SiC, SC ) == const(C) ));
|
||||
|
||||
|
80
gcc/testsuite/gdc.test/compilable/test3543.d
Normal file
80
gcc/testsuite/gdc.test/compilable/test3543.d
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=3543
|
||||
|
||||
// merge with commontype.d?
|
||||
|
||||
void testi(bool bla)
|
||||
{
|
||||
interface Root { }
|
||||
interface A : Root { }
|
||||
interface B : Root { }
|
||||
A a;
|
||||
B b;
|
||||
Root r = bla ? a : b;
|
||||
static assert(is(typeof(r) == Root));
|
||||
Root[] t = [a, b];
|
||||
static assert(is(typeof(t[0]) == Root));
|
||||
}
|
||||
|
||||
void testc(bool bla)
|
||||
{
|
||||
class Root { }
|
||||
class A : Root { }
|
||||
class B : Root { }
|
||||
A a;
|
||||
B b;
|
||||
Root r = bla ? a : b;
|
||||
static assert(is(typeof(r) == Root));
|
||||
Root[] t = [a, b];
|
||||
static assert(is(typeof(t[0]) == Root));
|
||||
}
|
||||
|
||||
void teste(bool bla)
|
||||
{
|
||||
interface Root { }
|
||||
interface Othe { }
|
||||
interface A : Root, Othe { }
|
||||
interface B : Root, Othe { }
|
||||
A a;
|
||||
B b;
|
||||
static assert(!__traits(compiles, bla ? a : b));
|
||||
}
|
||||
|
||||
void testf(bool bla)
|
||||
{
|
||||
interface Othe { }
|
||||
interface Root : Othe { }
|
||||
interface A : Root { }
|
||||
interface B : Othe { }
|
||||
A a;
|
||||
B b;
|
||||
Othe r = bla ? a : b;
|
||||
}
|
||||
|
||||
void testg()
|
||||
{
|
||||
interface A{}
|
||||
interface B{}
|
||||
|
||||
interface C:A{}
|
||||
interface D:B,C{}
|
||||
|
||||
interface E:B{}
|
||||
interface F:A,E{}
|
||||
|
||||
D d;
|
||||
F f;
|
||||
static assert(!__traits(compiles, true ? d : f));
|
||||
static assert(!__traits(compiles, true ? f : d));
|
||||
}
|
||||
|
||||
void testh()
|
||||
{
|
||||
interface I {}
|
||||
class B {}
|
||||
class C : B, I {}
|
||||
class D : B {}
|
||||
C c;
|
||||
D d;
|
||||
auto b = true ? c : d;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// PERMUTE_ARGS:
|
||||
// EXTRA_SOURCES: imports/mangle10077.d
|
||||
// EXTRA_FILES: imports/testmangle.d
|
||||
// UNICODE_NAMES:
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
|
@ -1,4 +1,5 @@
|
||||
// PERMUTE_ARGS:
|
||||
// UNICODE_NAMES:
|
||||
|
||||
// $HeadURL$
|
||||
// $Date$
|
||||
@ -11,6 +12,7 @@
|
||||
|
||||
module run.unicode_06_哪里;
|
||||
|
||||
//UTF-8 chars
|
||||
int 哪里(int ö){
|
||||
return ö+2;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
// EXTRA_SOURCES: imports/ufcs5a.d imports/ufcs5b.d imports/ufcs5c.d imports/ufcs5d.d imports/ufcs5e.d
|
||||
// UNICODE_NAMES:
|
||||
|
||||
module ufcs;
|
||||
|
||||
@ -677,6 +678,7 @@ void test8453()
|
||||
/*******************************************/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=8503
|
||||
|
||||
//UTF-8 chars
|
||||
void α8503(int i) {}
|
||||
|
||||
void test8503()
|
||||
|
@ -1,4 +1,4 @@
|
||||
a6f10836997d0b5526c8c363d781b4029c77f09f
|
||||
11240a96635074b2f79d908b9348e9c0fbc3c7dc
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
@ -79,17 +79,6 @@ pure @safe:
|
||||
AddType addType = AddType.yes;
|
||||
bool mute = false;
|
||||
Hooks hooks;
|
||||
bool hasErrors = false;
|
||||
|
||||
/// Called when encountering an error / unrecognized mangle.
|
||||
///
|
||||
/// Currently, errors simply make `demangle` return
|
||||
/// the input string, but the `msg` string can be used for debugging.
|
||||
/// As a future enhancement, error handlers can be supplied through `Hooks`
|
||||
void error(string msg = "error")
|
||||
{
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type Testing and Conversion
|
||||
@ -733,7 +722,7 @@ pure @safe:
|
||||
TypeTuple:
|
||||
B Number Arguments
|
||||
*/
|
||||
BufSlice parseType() return scope nothrow
|
||||
BufSlice parseType(out bool errStatus) return scope nothrow
|
||||
{
|
||||
static immutable string[23] primitives = [
|
||||
"char", // a
|
||||
@ -763,8 +752,8 @@ pure @safe:
|
||||
|
||||
static if (__traits(hasMember, Hooks, "parseType"))
|
||||
{
|
||||
auto n = hooks.parseType(this, null);
|
||||
if (this.hasErrors)
|
||||
auto n = hooks.parseType(errStatus, this, null);
|
||||
if (errStatus)
|
||||
return dst.bslice_empty;
|
||||
else
|
||||
if (n !is null)
|
||||
@ -776,11 +765,11 @@ pure @safe:
|
||||
auto beg = dst.length;
|
||||
auto t = front;
|
||||
|
||||
BufSlice parseBackrefType(scope BufSlice delegate() pure @safe nothrow parseDg) pure @safe nothrow
|
||||
BufSlice parseBackrefType(out string errStatus, scope BufSlice delegate(bool err_flag) pure @safe nothrow parseDg) pure @safe nothrow
|
||||
{
|
||||
if (pos == brp)
|
||||
{
|
||||
this.error("recursive back reference");
|
||||
errStatus = "recursive back reference";
|
||||
return dst.bslice_empty;
|
||||
}
|
||||
|
||||
@ -789,7 +778,7 @@ pure @safe:
|
||||
auto n = decodeBackref();
|
||||
if (n == 0 || n > pos)
|
||||
{
|
||||
this.error("invalid back reference");
|
||||
errStatus = "invalid back reference";
|
||||
return dst.bslice_empty;
|
||||
}
|
||||
|
||||
@ -801,31 +790,44 @@ pure @safe:
|
||||
pos = refPos - n;
|
||||
brp = refPos;
|
||||
|
||||
auto ret = parseDg();
|
||||
bool err_flag;
|
||||
auto ret = parseDg(err_flag);
|
||||
if (err_flag)
|
||||
{
|
||||
errStatus = "parseDg error";
|
||||
return dst.bslice_empty;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// call parseType() and return error if occured
|
||||
enum parseTypeOrF = "parseType(errStatus); if (errStatus) return dst.bslice_empty;";
|
||||
|
||||
switch ( t )
|
||||
{
|
||||
case 'Q': // Type back reference
|
||||
auto r = parseBackrefType(() => parseType());
|
||||
string errMsg;
|
||||
auto r = parseBackrefType(errMsg, (e_flag) => parseType(e_flag));
|
||||
if (errMsg !is null)
|
||||
return dst.bslice_empty;
|
||||
return r;
|
||||
case 'O': // Shared (O Type)
|
||||
popFront();
|
||||
put( "shared(" );
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
put( ')' );
|
||||
return dst[beg .. $];
|
||||
case 'x': // Const (x Type)
|
||||
popFront();
|
||||
put( "const(" );
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
put( ')' );
|
||||
return dst[beg .. $];
|
||||
case 'y': // Immutable (y Type)
|
||||
popFront();
|
||||
put( "immutable(" );
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
put( ')' );
|
||||
return dst[beg .. $];
|
||||
case 'N':
|
||||
@ -840,28 +842,28 @@ pure @safe:
|
||||
popFront();
|
||||
// TODO: Anything needed here?
|
||||
put( "inout(" );
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
put( ')' );
|
||||
return dst[beg .. $];
|
||||
case 'h': // TypeVector (Nh Type)
|
||||
popFront();
|
||||
put( "__vector(" );
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
put( ')' );
|
||||
return dst[beg .. $];
|
||||
default:
|
||||
error();
|
||||
errStatus = true;
|
||||
return dst.bslice_empty;
|
||||
}
|
||||
case 'A': // TypeArray (A Type)
|
||||
popFront();
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
put( "[]" );
|
||||
return dst[beg .. $];
|
||||
case 'G': // TypeStaticArray (G Number Type)
|
||||
popFront();
|
||||
auto num = sliceNumber();
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
put( '[' );
|
||||
put( num );
|
||||
put( ']' );
|
||||
@ -869,34 +871,29 @@ pure @safe:
|
||||
case 'H': // TypeAssocArray (H Type Type)
|
||||
popFront();
|
||||
// skip t1
|
||||
auto tx = parseType();
|
||||
if (this.hasErrors)
|
||||
auto tx = parseType(errStatus);
|
||||
if (errStatus)
|
||||
return dst.bslice_empty;
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
put( '[' );
|
||||
shift(tx);
|
||||
put( ']' );
|
||||
return dst[beg .. $];
|
||||
case 'P': // TypePointer (P Type)
|
||||
popFront();
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
put( '*' );
|
||||
return dst[beg .. $];
|
||||
case 'F': case 'U': case 'W': case 'V': case 'R': // TypeFunction
|
||||
bool errStatus;
|
||||
auto r = parseTypeFunction(errStatus);
|
||||
if (errStatus)
|
||||
{
|
||||
error();
|
||||
return dst.bslice_empty;
|
||||
}
|
||||
return r;
|
||||
case 'C': // TypeClass (C LName)
|
||||
case 'S': // TypeStruct (S LName)
|
||||
case 'E': // TypeEnum (E LName)
|
||||
case 'T': // TypeTypedef (T LName)
|
||||
popFront();
|
||||
bool errStatus;
|
||||
parseQualifiedName(errStatus);
|
||||
if (errStatus)
|
||||
return dst.bslice_empty;
|
||||
@ -906,20 +903,16 @@ pure @safe:
|
||||
auto modifiers = parseModifier();
|
||||
if ( front == 'Q' )
|
||||
{
|
||||
bool errStatus;
|
||||
auto r = parseBackrefType(() => parseTypeFunction(errStatus, IsDelegate.yes));
|
||||
if (errStatus)
|
||||
{
|
||||
error();
|
||||
string errMsg;
|
||||
auto r = parseBackrefType(errMsg, (e_flag) => parseTypeFunction(e_flag, IsDelegate.yes));
|
||||
if (errMsg !is null)
|
||||
return dst.bslice_empty;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool errStatus;
|
||||
parseTypeFunction(errStatus, IsDelegate.yes);
|
||||
if (this.hasErrors || errStatus)
|
||||
if (errStatus)
|
||||
return dst.bslice_empty;
|
||||
}
|
||||
|
||||
@ -972,11 +965,11 @@ pure @safe:
|
||||
put( "ucent" );
|
||||
return dst[beg .. $];
|
||||
default:
|
||||
error("unknown type");
|
||||
errStatus = true;
|
||||
return dst.bslice_empty;
|
||||
}
|
||||
}
|
||||
error("unknown type");
|
||||
errStatus = true;
|
||||
return dst.bslice_empty;
|
||||
}
|
||||
}
|
||||
@ -1289,6 +1282,9 @@ pure @safe:
|
||||
pos--;
|
||||
}
|
||||
|
||||
// call parseType() and return error if occured
|
||||
enum parseTypeOrF = "parseType(errStatus); if (errStatus) return;";
|
||||
|
||||
switch ( front )
|
||||
{
|
||||
case 'I': // in (I Type)
|
||||
@ -1296,25 +1292,25 @@ pure @safe:
|
||||
put("in ");
|
||||
if (front == 'K')
|
||||
goto case;
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
continue;
|
||||
case 'K': // ref (K Type)
|
||||
popFront();
|
||||
put( "ref " );
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
continue;
|
||||
case 'J': // out (J Type)
|
||||
popFront();
|
||||
put( "out " );
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
continue;
|
||||
case 'L': // lazy (L Type)
|
||||
popFront();
|
||||
put( "lazy " );
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
continue;
|
||||
default:
|
||||
parseType();
|
||||
mixin(parseTypeOrF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1361,8 +1357,8 @@ pure @safe:
|
||||
// e.g. `delegate(int) @safedouble ' => 'double delegate(int) @safe'
|
||||
{
|
||||
auto retbeg = dst.length;
|
||||
parseType();
|
||||
if (this.hasErrors)
|
||||
parseType(errStatus);
|
||||
if (errStatus)
|
||||
return dst.bslice_empty;
|
||||
put(' ');
|
||||
shift(dst[argbeg .. retbeg]);
|
||||
@ -1576,9 +1572,7 @@ pure @safe:
|
||||
// f MangledName
|
||||
// A function literal symbol
|
||||
popFront();
|
||||
parseMangledName(false, 1);
|
||||
if (this.hasErrors)
|
||||
errStatus = true;
|
||||
parseMangledName(errStatus, false, 1);
|
||||
return;
|
||||
default:
|
||||
errStatus = true;
|
||||
@ -1716,12 +1710,9 @@ pure @safe:
|
||||
case 'T':
|
||||
popFront();
|
||||
putComma(n);
|
||||
parseType();
|
||||
if (this.hasErrors)
|
||||
{
|
||||
errStatus = true;
|
||||
parseType(errStatus);
|
||||
if (errStatus)
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
case 'V':
|
||||
popFront();
|
||||
@ -1742,7 +1733,7 @@ pure @safe:
|
||||
}
|
||||
}
|
||||
BufSlice name = dst.bslice_empty;
|
||||
silent( errStatus, delegate void(out bool e_flg) nothrow { name = parseType(); } );
|
||||
silent( errStatus, delegate void(out bool e_flg) nothrow { name = parseType(e_flg); } );
|
||||
if (errStatus)
|
||||
return;
|
||||
parseValue( errStatus, name, t );
|
||||
@ -1857,20 +1848,20 @@ pure @safe:
|
||||
debug(trace) printf( "parseMangledNameArg+\n" );
|
||||
debug(trace) scope(success) printf( "parseMangledNameArg-\n" );
|
||||
|
||||
bool errStatus;
|
||||
|
||||
size_t n = 0;
|
||||
if ( isDigit( front ) )
|
||||
{
|
||||
bool errStatus;
|
||||
n = decodeNumber(errStatus);
|
||||
|
||||
if (errStatus)
|
||||
{
|
||||
error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parseMangledName(false, n);
|
||||
return !this.hasErrors;
|
||||
parseMangledName(errStatus, false, n );
|
||||
|
||||
return !errStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2091,7 +2082,7 @@ pure @safe:
|
||||
_D QualifiedName Type
|
||||
_D QualifiedName M Type
|
||||
*/
|
||||
void parseMangledName(bool displayType, size_t n = 0 ) scope nothrow
|
||||
void parseMangledName( out bool errStatus, bool displayType, size_t n = 0 ) scope nothrow
|
||||
{
|
||||
debug(trace) printf( "parseMangledName+\n" );
|
||||
debug(trace) scope(success) printf( "parseMangledName-\n" );
|
||||
@ -2100,8 +2091,9 @@ pure @safe:
|
||||
auto end = pos + n;
|
||||
|
||||
eat( '_' );
|
||||
if (!match('D'))
|
||||
return error();
|
||||
errStatus = !match( 'D' );
|
||||
if (errStatus)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
@ -2117,17 +2109,16 @@ pure @safe:
|
||||
if (beg != dst.length)
|
||||
put( '.' );
|
||||
|
||||
bool errStatus;
|
||||
parseSymbolName(errStatus);
|
||||
if (errStatus)
|
||||
return error();
|
||||
return;
|
||||
|
||||
nameEnd = dst.length;
|
||||
attr = parseFunctionTypeNoReturn( displayType );
|
||||
|
||||
is_sym_name_front = isSymbolNameFront(errStatus);
|
||||
if (errStatus)
|
||||
return error();
|
||||
return;
|
||||
} while (is_sym_name_front);
|
||||
|
||||
if ( displayType )
|
||||
@ -2142,8 +2133,8 @@ pure @safe:
|
||||
popFront(); // has 'this' pointer
|
||||
|
||||
auto lastlen = dst.length;
|
||||
auto type = parseType();
|
||||
if (this.hasErrors)
|
||||
auto type = parseType(errStatus);
|
||||
if (errStatus)
|
||||
return;
|
||||
|
||||
if ( displayType )
|
||||
@ -2176,9 +2167,9 @@ pure @safe:
|
||||
} while ( true );
|
||||
}
|
||||
|
||||
void parseMangledName() nothrow
|
||||
void parseMangledName(out bool errStatus) nothrow
|
||||
{
|
||||
parseMangledName(AddType.yes == addType);
|
||||
parseMangledName(errStatus, AddType.yes == addType);
|
||||
}
|
||||
|
||||
char[] doDemangle(alias FUNC)() return scope nothrow
|
||||
@ -2187,8 +2178,9 @@ pure @safe:
|
||||
{
|
||||
debug(info) printf( "demangle(%.*s)\n", cast(int) buf.length, buf.ptr );
|
||||
|
||||
FUNC();
|
||||
if (!this.hasErrors)
|
||||
bool errStatus;
|
||||
FUNC(errStatus);
|
||||
if (!errStatus)
|
||||
{
|
||||
return dst[0 .. $].getSlice;
|
||||
}
|
||||
@ -2387,9 +2379,8 @@ char[] reencodeMangled(return scope const(char)[] mangled) nothrow pure @safe
|
||||
return true;
|
||||
}
|
||||
|
||||
char[] parseType(ref Remangle d, char[] name) return scope nothrow
|
||||
char[] parseType( out bool errStatus, ref Remangle d, char[] name ) return scope nothrow
|
||||
{
|
||||
bool errStatus;
|
||||
if (d.front != 'Q')
|
||||
return null;
|
||||
|
||||
@ -2400,7 +2391,8 @@ char[] reencodeMangled(return scope const(char)[] mangled) nothrow pure @safe
|
||||
auto n = d.decodeBackref();
|
||||
if (n == 0 || n > refPos)
|
||||
{
|
||||
d.error("invalid back reference");
|
||||
// invalid back reference
|
||||
errStatus = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -2436,7 +2428,7 @@ char[] reencodeMangled(return scope const(char)[] mangled) nothrow pure @safe
|
||||
|
||||
bool errStatus;
|
||||
d.parseMangledName(errStatus);
|
||||
if (d.hasErrors)
|
||||
if (errStatus)
|
||||
{
|
||||
// error cannot occur
|
||||
return mangled.dup;
|
||||
|
@ -609,7 +609,7 @@ else version (GNU)
|
||||
import gcc.builtins;
|
||||
import gcc.config;
|
||||
|
||||
enum IsAtomicLockFree(T) = __atomic_is_lock_free(T.sizeof, null);
|
||||
enum IsAtomicLockFree(T) = __traits(compiles, { enum E = __atomic_is_lock_free(T.sizeof, null); });
|
||||
|
||||
inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted
|
||||
if (CanCAS!T)
|
||||
|
@ -4941,6 +4941,7 @@ unittest
|
||||
// improve predictability of coverage of code that is eventually not hit by other tests
|
||||
debug (SENTINEL) {} else // cannot extend with SENTINEL
|
||||
debug (MARK_PRINTF) {} else // takes forever
|
||||
version (OnlyLowMemUnittests) {} else
|
||||
unittest
|
||||
{
|
||||
import core.memory;
|
||||
@ -4988,24 +4989,34 @@ version (D_LP64) unittest
|
||||
{
|
||||
// only run if the system has enough physical memory
|
||||
size_t sz = 2L^^32;
|
||||
//import core.stdc.stdio;
|
||||
//printf("availphys = %lld", os_physical_mem(true));
|
||||
if (os_physical_mem(true) > sz)
|
||||
size_t phys_mem = os_physical_mem(true);
|
||||
if (phys_mem > sz)
|
||||
{
|
||||
import core.memory;
|
||||
import core.exception;
|
||||
GC.collect();
|
||||
GC.minimize();
|
||||
auto stats = GC.stats();
|
||||
auto ptr = GC.malloc(sz, BlkAttr.NO_SCAN);
|
||||
auto info = GC.query(ptr);
|
||||
//printf("info.size = %lld", info.size);
|
||||
assert(info.size >= sz);
|
||||
GC.free(ptr);
|
||||
GC.minimize();
|
||||
auto nstats = GC.stats();
|
||||
assert(nstats.usedSize == stats.usedSize);
|
||||
assert(nstats.freeSize == stats.freeSize);
|
||||
assert(nstats.allocatedInCurrentThread - sz == stats.allocatedInCurrentThread);
|
||||
try
|
||||
{
|
||||
auto stats = GC.stats();
|
||||
auto ptr = GC.malloc(sz, BlkAttr.NO_SCAN);
|
||||
auto info = GC.query(ptr);
|
||||
//printf("info.size = %lld", info.size);
|
||||
assert(info.size >= sz);
|
||||
GC.free(ptr);
|
||||
GC.minimize();
|
||||
auto nstats = GC.stats();
|
||||
assert(nstats.usedSize == stats.usedSize);
|
||||
assert(nstats.freeSize == stats.freeSize);
|
||||
assert(nstats.allocatedInCurrentThread - sz == stats.allocatedInCurrentThread);
|
||||
}
|
||||
catch (OutOfMemoryError)
|
||||
{
|
||||
// ignore if the system still doesn't have enough virtual memory
|
||||
import core.stdc.stdio;
|
||||
printf("%s(%d): out-of-memory execption ignored, phys_mem = %zd",
|
||||
__FILE__.ptr, __LINE__, phys_mem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,6 +132,7 @@ else
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(qsort) import core.stdc.stdio;
|
||||
debug(qsort) printf("array.sort.unittest()\n");
|
||||
|
||||
int[] a = new int[10];
|
||||
@ -151,8 +152,8 @@ unittest
|
||||
|
||||
for (int i = 0; i < a.length - 1; i++)
|
||||
{
|
||||
//printf("i = %d", i);
|
||||
//printf(" %d %d\n", a[i], a[i + 1]);
|
||||
debug(qsort) printf("i = %d", i);
|
||||
debug(qsort) printf(" %d %d\n", a[i], a[i + 1]);
|
||||
assert(a[i] <= a[i + 1]);
|
||||
}
|
||||
}
|
||||
|
@ -575,6 +575,7 @@ extern(C):
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=13111
|
||||
///
|
||||
version (OnlyLowMemUnittests) {} else // Test needs a lot of RAM
|
||||
unittest
|
||||
{
|
||||
enum size1 = 1 << 11 + 1; // page in large object pool
|
||||
|
@ -2103,6 +2103,8 @@ private extern (D) void resume(ThreadBase _t) nothrow @nogc
|
||||
t.m_curr.tstack = t.m_curr.bstack;
|
||||
}
|
||||
}
|
||||
else
|
||||
static assert(false, "Platform not supported.");
|
||||
}
|
||||
|
||||
|
||||
|
@ -2584,6 +2584,8 @@ extern(C) void _d_initMonoTime() @nogc nothrow
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
static assert(0, "Unsupported platform");
|
||||
}
|
||||
|
||||
|
||||
@ -2883,6 +2885,8 @@ deprecated:
|
||||
else
|
||||
ticksPerSec = 1_000_000;
|
||||
}
|
||||
else
|
||||
static assert(0, "Unsupported platform");
|
||||
|
||||
if (ticksPerSec != 0)
|
||||
appOrigin = TickDuration.currSystemTick;
|
||||
|
@ -437,6 +437,7 @@ unittest
|
||||
string[412] names;
|
||||
ubyte[1024] moredata;
|
||||
}
|
||||
version (OnlyLowMemUnittests) {} else
|
||||
test!(Large, Large);
|
||||
}
|
||||
|
||||
|
@ -2247,6 +2247,7 @@ unittest
|
||||
assert(GC.getAttr(p) == BlkAttr.NO_SCAN);
|
||||
}
|
||||
test(16);
|
||||
version (OnlyLowMemUnittests) {} else
|
||||
test(1024 * 1024);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user