aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2025-01-05 14:24:49 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2025-01-05 14:24:49 +0100
commita676a516701789730aa482bcef4adcb683ba0140 (patch)
tree6c5b56d13162e537bae0ed373a9addf9be73af56 /gcc/d/dmd
parent3dfad340cb140d64b8c0ecab05fa329238ebd06b (diff)
downloadgcc-a676a516701789730aa482bcef4adcb683ba0140.zip
gcc-a676a516701789730aa482bcef4adcb683ba0140.tar.gz
gcc-a676a516701789730aa482bcef4adcb683ba0140.tar.bz2
d: Merge upstream dmd, druntime 07bc5b9b3c, phobos de1dea109
Synchronizing with the upstream release of v2.109.0. D front-end changes: - Import dmd v2.109.0. D runtime changes: - Import druntime v2.109.0. Phobos changes: - Import phobos v2.109.0. gcc/d/ChangeLog: * decl.cc (DeclVisitor::finish_vtable): Update for new front-end interface. * dmd/MERGE: Merge upstream dmd 07bc5b9b3c. * dmd/VERSION: Bump version to v2.109.0. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 07bc5b9b3c. * src/MERGE: Merge upstream phobos de1dea109.
Diffstat (limited to 'gcc/d/dmd')
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/README.md2
-rw-r--r--gcc/d/dmd/VERSION2
-rw-r--r--gcc/d/dmd/cxxfrontend.d6
-rw-r--r--gcc/d/dmd/declaration.h2
-rw-r--r--gcc/d/dmd/dmodule.d2
-rw-r--r--gcc/d/dmd/dstruct.d5
-rw-r--r--gcc/d/dmd/dsymbolsem.d22
-rw-r--r--gcc/d/dmd/dtemplate.d11
-rw-r--r--gcc/d/dmd/enumsem.d5
-rw-r--r--gcc/d/dmd/expression.h1
-rw-r--r--gcc/d/dmd/expressionsem.d23
-rw-r--r--gcc/d/dmd/func.d317
-rw-r--r--gcc/d/dmd/funcsem.d377
-rw-r--r--gcc/d/dmd/gluelayer.d6
-rw-r--r--gcc/d/dmd/hdrgen.d3
-rw-r--r--gcc/d/dmd/id.d3
-rw-r--r--gcc/d/dmd/mtype.d13
-rw-r--r--gcc/d/dmd/semantic3.d2
-rw-r--r--gcc/d/dmd/statementsem.d5
-rw-r--r--gcc/d/dmd/target.d5
-rw-r--r--gcc/d/dmd/target.h5
-rw-r--r--gcc/d/dmd/templatesem.d10
-rw-r--r--gcc/d/dmd/traits.d11
-rw-r--r--gcc/d/dmd/typesem.d40
25 files changed, 482 insertions, 398 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 46d435e..77e8562 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-c11e1d1708646c9ac81ac2aafb57fa1ef5d289ad
+07bc5b9b3c81cc0d4314e0040de981124b363ea5
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md
index d784d07..baac0d7 100644
--- a/gcc/d/dmd/README.md
+++ b/gcc/d/dmd/README.md
@@ -201,11 +201,9 @@ Note that these groups have no strict meaning, the category assignments are a bi
| [libelf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libelf.d) | Library in ELF format (Unix) |
| [libmach.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libmach.d) | Library in Mach-O format (macOS) |
| [libmscoff.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libmscoff.d) | Library in COFF format (32/64-bit Windows) |
-| [libomf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libomf.d) | Library in OMF format (legacy 32-bit Windows) |
| [scanelf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanelf.d) | Extract symbol names from a library in ELF format |
| [scanmach.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanmach.d) | Extract symbol names from a library in Mach-O format |
| [scanmscoff.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanmscoff.d) | Extract symbol names from a library in COFF format |
-| [scanomf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanomf.d) | Extract symbol names from a library in OMF format |
### Code generation / back-end interfacing
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 99582f5..3d80c3d 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.108.1
+v2.109.0
diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d
index c0805b8..403588b 100644
--- a/gcc/d/dmd/cxxfrontend.d
+++ b/gcc/d/dmd/cxxfrontend.d
@@ -265,6 +265,12 @@ bool functionSemantic3(FuncDeclaration fd)
return dmd.funcsem.functionSemantic3(fd);
}
+MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names)
+{
+ import dmd.funcsem;
+ return dmd.funcsem.leastAsSpecialized(f, g, names);
+}
+
/***********************************************************
* hdrgen.d
*/
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 998beba9..fdfe8a8 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -34,6 +34,7 @@ namespace dmd
{
bool functionSemantic(FuncDeclaration* fd);
bool functionSemantic3(FuncDeclaration* fd);
+ MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names);
}
//enum STC : ulong from astenums.d:
@@ -706,7 +707,6 @@ public:
bool overloadInsert(Dsymbol *s) override;
bool inUnittest();
- static MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names);
LabelDsymbol *searchLabel(Identifier *ident, const Loc &loc);
const char *toPrettyChars(bool QualifyTypes = false) override;
const char *toFullSignature(); // for diagnostics, e.g. 'int foo(int x, int y) pure'
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index a1a337b..005f1c9 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -766,7 +766,7 @@ extern (C++) final class Module : Package
{
filetype = FileType.c;
- global.compileEnv.masm = target.os == Target.OS.Windows && !target.omfobj; // Microsoft inline assembler format
+ global.compileEnv.masm = target.os == Target.OS.Windows; // Microsoft inline assembler format
scope p = new CParser!AST(this, buf, cast(bool) docfile, global.errorSink, target.c, &defines, &global.compileEnv);
global.compileEnv.masm = false;
p.nextToken();
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index 339b223..416bd57 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -320,11 +320,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration
*/
structsize = 4;
}
- else if (target.c.bitFieldStyle == TargetC.BitFieldStyle.DM)
- {
- structsize = 0;
- alignsize = 0;
- }
else
structsize = 0;
break;
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 65a1b04..4a21b14 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -7259,25 +7259,6 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
return;
}
}
- else if (style == TargetC.BitFieldStyle.DM)
- {
- if (anon && bfd.fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
- return; // this probably should be a bug in DMC
- if (ad.alignsize == 0)
- ad.alignsize = 1;
- if (bfd.fieldWidth == 0)
- {
- if (fieldState.inFlight && !isunion)
- {
- const alsz = memsize;
- fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
- ad.structsize = fieldState.offset;
- }
-
- fieldState.inFlight = false;
- return;
- }
- }
if (!fieldState.inFlight)
{
@@ -7307,8 +7288,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
}
}
}
- else if (style == TargetC.BitFieldStyle.DM ||
- style == TargetC.BitFieldStyle.MS)
+ else if (style == TargetC.BitFieldStyle.MS)
{
if (memsize != fieldState.fieldSize ||
fieldState.bitOffset + bfd.fieldWidth > fieldState.fieldSize * 8)
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index fb11821..33ec6b1 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -751,6 +751,17 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
return buf.extractChars();
}
+ /****************************
+ * Similar to `toChars`, but does not print the template constraints
+ */
+ const(char)* toCharsNoConstraints() const
+ {
+ HdrGenState hgs = { skipConstraints: true };
+ OutBuffer buf;
+ toCharsMaybeConstraints(this, buf, hgs);
+ return buf.extractChars();
+ }
+
override Visibility visible() pure nothrow @nogc @safe
{
return visibility;
diff --git a/gcc/d/dmd/enumsem.d b/gcc/d/dmd/enumsem.d
index 3886ca2..c67ac61 100644
--- a/gcc/d/dmd/enumsem.d
+++ b/gcc/d/dmd/enumsem.d
@@ -325,7 +325,10 @@ void enumSemantic(Scope* sc, EnumDeclaration ed)
if (EnumMember em = s.isEnumMember())
{
em.type = commonType;
- em.value = em.value.castTo(sc, commonType);
+ // optimize out the cast so that other parts of the compiler can
+ // assume that an integral enum's members are `IntegerExp`s.
+ // https://issues.dlang.org/show_bug.cgi?id=24504
+ em.value = em.value.castTo(sc, commonType).optimize(WANTvalue);
}
});
}
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 1ff6c4c..ad79281 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -889,6 +889,7 @@ public:
// Possible to cast to one type while painting to another type
Type *to; // type to cast to
unsigned char mod; // MODxxxxx
+ d_bool trusted; // assume cast is safe
CastExp *syntaxCopy() override;
bool isLvalue() override;
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 3502a1c..481806d 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -14306,14 +14306,16 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
if (auto te = exp.e1.isTupleExp())
{
- if (exp.ident == Id.offsetof)
+ if (exp.ident == Id.offsetof ||
+ exp.ident == Id.bitoffsetof ||
+ exp.ident == Id.bitwidth)
{
/* 'distribute' the .offsetof to each of the tuple elements.
*/
auto exps = new Expressions(te.exps.length);
foreach (i, e; (*te.exps)[])
{
- (*exps)[i] = new DotIdExp(e.loc, e, Id.offsetof);
+ (*exps)[i] = new DotIdExp(e.loc, e, exp.ident);
}
// Don't evaluate te.e0 in runtime
Expression e = new TupleExp(exp.loc, null, exps);
@@ -14636,6 +14638,8 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag)
!cfile &&
(exp.ident == Id._mangleof ||
exp.ident == Id.offsetof ||
+ exp.ident == Id.bitoffsetof ||
+ exp.ident == Id.bitwidth ||
exp.ident == Id._init ||
exp.ident == Id.stringof)
))
@@ -15282,6 +15286,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
Expression visitStructLiteral(StructLiteralExp exp)
{
+ if (!exp.elements)
+ return exp;
+
foreach (ref element; *exp.elements)
{
if (element)
@@ -15300,6 +15307,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
if (exp.lowering)
exp.lowering = exp.lowering.resolveLoc(loc, sc);
+ if (!exp.arguments)
+ return exp;
+
foreach (ref element; *exp.arguments)
{
if (element)
@@ -15311,6 +15321,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
Expression visitCall(CallExp exp)
{
+ if (!exp.arguments)
+ return exp;
+
foreach (ref element; *exp.arguments)
{
if (element)
@@ -15324,6 +15337,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
{
exp.e1 = exp.e1.resolveLoc(loc, sc);
+ if (!exp.arguments)
+ return exp;
+
foreach (ref element; *exp.arguments)
{
if (element)
@@ -15357,6 +15373,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
if (exp.basis)
exp.basis = exp.basis.resolveLoc(loc, sc);
+ if (!exp.elements)
+ return exp;
+
foreach (ref element; *exp.elements)
{
if (element)
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index f3d7aba..cb19b14 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -424,27 +424,6 @@ extern (C++) class FuncDeclaration : Declaration
}
/****************************************************
- * Determine if 'this' overrides fd.
- * Return !=0 if it does.
- */
- extern (D) final int overrides(FuncDeclaration fd)
- {
- int result = 0;
- if (fd.ident == ident)
- {
- const cov = type.covariant(fd.type);
- if (cov != Covariant.distinct)
- {
- ClassDeclaration cd1 = toParent().isClassDeclaration();
- ClassDeclaration cd2 = fd.toParent().isClassDeclaration();
- if (cd1 && cd2 && cd2.isBaseOf(cd1, null))
- result = 1;
- }
- }
- return result;
- }
-
- /****************************************************
* Overload this FuncDeclaration with the new one f.
* Return true if successful; i.e. no conflict.
*/
@@ -547,91 +526,6 @@ extern (C++) class FuncDeclaration : Declaration
return false;
}
- /*************************************
- * Determine partial specialization order of functions `f` vs `g`.
- * This is very similar to TemplateDeclaration::leastAsSpecialized().
- * Params:
- * f = first function
- * g = second function
- * names = names of parameters
- * Returns:
- * match 'this' is at least as specialized as g
- * 0 g is more specialized than 'this'
- */
- static MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names)
- {
- enum LOG_LEASTAS = 0;
- static if (LOG_LEASTAS)
- {
- import core.stdc.stdio : printf;
- printf("leastAsSpecialized(%s, %s, %s)\n", f.toChars(), g.toChars(), names ? names.toChars() : "null");
- printf("%s, %s\n", f.type.toChars(), g.type.toChars());
- }
-
- /* This works by calling g() with f()'s parameters, and
- * if that is possible, then f() is at least as specialized
- * as g() is.
- */
-
- TypeFunction tf = f.type.toTypeFunction();
- TypeFunction tg = g.type.toTypeFunction();
-
- /* If both functions have a 'this' pointer, and the mods are not
- * the same and g's is not const, then this is less specialized.
- */
- if (f.needThis() && g.needThis() && tf.mod != tg.mod)
- {
- if (f.isCtorDeclaration())
- {
- if (!MODimplicitConv(tg.mod, tf.mod))
- return MATCH.nomatch;
- }
- else
- {
- if (!MODimplicitConv(tf.mod, tg.mod))
- return MATCH.nomatch;
- }
- }
-
- /* Create a dummy array of arguments out of the parameters to f()
- */
- Expressions args;
- foreach (u, p; tf.parameterList)
- {
- Expression e;
- if (p.isReference())
- {
- e = new IdentifierExp(Loc.initial, p.ident);
- e.type = p.type;
- }
- else
- e = p.type.defaultInitLiteral(Loc.initial);
- args.push(e);
- }
-
- MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1);
- if (m > MATCH.nomatch)
- {
- /* A variadic parameter list is less specialized than a
- * non-variadic one.
- */
- if (tf.parameterList.varargs && !tg.parameterList.varargs)
- goto L1; // less specialized
-
- static if (LOG_LEASTAS)
- {
- printf(" matches %d, so is least as specialized\n", m);
- }
- return m;
- }
- L1:
- static if (LOG_LEASTAS)
- {
- printf(" doesn't match, so is not as specialized\n");
- }
- return MATCH.nomatch;
- }
-
/********************************
* Searches for a label with the given identifier. This function will insert a new
* `LabelDsymbol` into `labtab` if it does not contain a mapping for `ident`.
@@ -1607,27 +1501,6 @@ extern (C++) class FuncDeclaration : Declaration
return false;
}
- /****************************************************
- * Determine whether an 'out' contract is declared inside
- * the given function or any of its overrides.
- * Params:
- * fd = the function to search
- * Returns:
- * true found an 'out' contract
- */
- static bool needsFensure(FuncDeclaration fd) @safe
- {
- if (fd.fensures)
- return true;
-
- foreach (fdv; fd.foverrides)
- {
- if (needsFensure(fdv))
- return true;
- }
- return false;
- }
-
/*********************************************
* Returns: the function's parameter list, and whether
* it is variadic or not.
@@ -1684,179 +1557,6 @@ extern (C++) class FuncDeclaration : Declaration
return fd;
}
- /+
- + Checks the parameter and return types iff this is a `main` function.
- +
- + The following signatures are allowed for a `D main`:
- + - Either no or a single parameter of type `string[]`
- + - Return type is either `void`, `int` or `noreturn`
- +
- + The following signatures are standard C:
- + - `int main()`
- + - `int main(int, char**)`
- +
- + This function accepts the following non-standard extensions:
- + - `char** envp` as a third parameter
- + - `void` / `noreturn` as return type
- +
- + This function will issue errors for unexpected arguments / return types.
- +/
- extern (D) final void checkMain()
- {
- if (ident != Id.main || isMember() || isNested())
- return; // Not a main function
-
- TypeFunction tf = type.toTypeFunction();
-
- Type retType = tf.nextOf();
- if (!retType)
- {
- // auto main(), check after semantic
- assert(this.inferRetType);
- return;
- }
-
- /// Checks whether `t` is equivalent to `char**`
- /// Ignores qualifiers and treats enums according to their base type
- static bool isCharPtrPtr(Type t)
- {
- auto tp = t.toBasetype().isTypePointer();
- if (!tp)
- return false;
-
- tp = tp.next.toBasetype().isTypePointer();
- if (!tp)
- return false;
-
- return tp.next.toBasetype().ty == Tchar;
- }
-
- // Neither of these qualifiers is allowed because they affect the ABI
- enum invalidSTC = STC.out_ | STC.ref_ | STC.lazy_;
-
- const nparams = tf.parameterList.length;
- bool argerr;
-
- const linkage = resolvedLinkage();
- if (linkage == LINK.d)
- {
- if (nparams == 1)
- {
- auto fparam0 = tf.parameterList[0];
- auto t = fparam0.type.toBasetype();
- if (t.ty != Tarray ||
- t.nextOf().ty != Tarray ||
- t.nextOf().nextOf().ty != Tchar ||
- fparam0.storageClass & invalidSTC)
- {
- argerr = true;
- }
- }
-
- if (tf.parameterList.varargs || nparams >= 2 || argerr)
- .error(loc, "%s `%s` parameter list must be empty or accept one parameter of type `string[]`", kind, toPrettyChars);
- }
-
- else if (linkage == LINK.c)
- {
- if (nparams == 2 || nparams == 3)
- {
- // Argument count must be int
- auto argCount = tf.parameterList[0];
- argerr |= !!(argCount.storageClass & invalidSTC);
- argerr |= argCount.type.toBasetype().ty != Tint32;
-
- // Argument pointer must be char**
- auto argPtr = tf.parameterList[1];
- argerr |= !!(argPtr.storageClass & invalidSTC);
- argerr |= !isCharPtrPtr(argPtr.type);
-
- // `char** environ` is a common extension, see J.5.1 of the C standard
- if (nparams == 3)
- {
- auto envPtr = tf.parameterList[2];
- argerr |= !!(envPtr.storageClass & invalidSTC);
- argerr |= !isCharPtrPtr(envPtr.type);
- }
- }
- else
- argerr = nparams != 0;
-
- // Disallow variadic main() - except for K&R declarations in C files.
- // E.g. int main(), int main(argc, argv) int argc, char** argc { ... }
- if (tf.parameterList.varargs && (!this.isCsymbol() || (!tf.parameterList.hasIdentifierList && nparams)))
- argerr |= true;
-
- if (argerr)
- {
- .error(loc, "%s `%s` parameters must match one of the following signatures", kind, toPrettyChars);
- loc.errorSupplemental("`main()`");
- loc.errorSupplemental("`main(int argc, char** argv)`");
- loc.errorSupplemental("`main(int argc, char** argv, char** environ)` [POSIX extension]");
- }
- }
- else
- return; // Neither C nor D main, ignore (should probably be an error)
-
- // Allow enums with appropriate base types (same ABI)
- retType = retType.toBasetype();
-
- if (retType.ty != Tint32 && retType.ty != Tvoid && retType.ty != Tnoreturn)
- .error(loc, "%s `%s` must return `int`, `void` or `noreturn`, not `%s`", kind, toPrettyChars, tf.nextOf().toChars());
- }
-
- /***********************************************
- * Check all return statements for a function to verify that returning
- * using NRVO is possible.
- *
- * Returns:
- * `false` if the result cannot be returned by hidden reference.
- */
- extern (D) final bool checkNRVO()
- {
- if (!isNRVO() || returns is null)
- return false;
-
- auto tf = type.toTypeFunction();
- if (tf.isref)
- return false;
-
- foreach (rs; *returns)
- {
- if (auto ve = rs.exp.isVarExp())
- {
- auto v = ve.var.isVarDeclaration();
- if (!v || v.isReference())
- return false;
- else if (nrvo_var is null)
- {
- // Variables in the data segment (e.g. globals, TLS or not),
- // parameters and closure variables cannot be NRVOed.
- if (v.isDataseg() || v.isParameter() || v.toParent2() != this)
- return false;
- if (v.nestedrefs.length && needsClosure())
- return false;
- // don't know if the return storage is aligned
- version (MARS)
- {
- if (alignSectionVars && (*alignSectionVars).contains(v))
- return false;
- }
- // The variable type needs to be equivalent to the return type.
- if (!v.type.equivalent(tf.next))
- return false;
- //printf("Setting nrvo to %s\n", v.toChars());
- nrvo_var = v;
- }
- else if (nrvo_var != v)
- return false;
- }
- else //if (!exp.isLvalue()) // keep NRVO-ability
- return false;
- }
- return true;
- }
-
override final inout(FuncDeclaration) isFuncDeclaration() inout
{
return this;
@@ -2067,23 +1767,6 @@ unittest
}
/**************************************
- * Returns an indirect type one step from t.
- */
-Type getIndirection(Type t)
-{
- t = t.baseElemOf();
- if (t.ty == Tarray || t.ty == Tpointer)
- return t.nextOf().toBasetype();
- if (t.ty == Taarray || t.ty == Tclass)
- return t;
- if (t.ty == Tstruct)
- return t.hasPointers() ? t : null; // TODO
-
- // should consider TypeDelegate?
- return null;
-}
-
-/**************************************
* Performs type-based alias analysis between a newly created value and a pre-
* existing memory reference:
*
diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d
index e058deb..ee36a16 100644
--- a/gcc/d/dmd/funcsem.d
+++ b/gcc/d/dmd/funcsem.d
@@ -65,6 +65,10 @@ import dmd.tokens;
import dmd.typesem;
import dmd.visitor;
+version (IN_GCC) {}
+else version (IN_LLVM) {}
+else version = MARS;
+
/* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
*/
extern (C++) final class NrvoWalker : StatementRewriteWalker
@@ -742,7 +746,10 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
{
if (fdv.isFuture())
{
- deprecation(funcdecl.loc, "`@__future` base class method `%s` is being overridden by `%s`; rename the latter", fdv.toPrettyChars(), funcdecl.toPrettyChars());
+ deprecation(funcdecl.loc, "method `%s` implicitly overrides `@__future` base class method; rename the former",
+ funcdecl.toPrettyChars());
+ deprecationSupplemental(fdv.loc, "base method `%s` defined here",
+ fdv.toPrettyChars());
// Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
goto Lintro;
}
@@ -1743,10 +1750,24 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
// max num of overloads to print (-v or -verror-supplements overrides this).
const uint DisplayLimit = global.params.v.errorSupplementCount();
const(char)* constraintsTip;
- // determine if the first candidate was printed
- int printed;
- bool matchSymbol(Dsymbol s, bool print, bool single_candidate = false)
+ int printed = 0; // number of candidates printed
+ int count = 0; // total candidates
+ bool child; // true if inside an eponymous template
+ const(char)* errorPrefix() @safe
+ {
+ if (child)
+ return " - Containing: ";
+
+ // align with blank spaces after first message
+ enum plural = "Candidates are: ";
+ enum spaces = " ";
+ if (printed)
+ return spaces;
+
+ return (count == 1) ? "Candidate is: " : plural;
+ }
+ bool matchSymbol(Dsymbol s, bool print)
{
if (auto fd = s.isFuncDeclaration())
{
@@ -1762,16 +1783,14 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
return true;
auto tf = cast(TypeFunction) fd.type;
OutBuffer buf;
- buf.writestring(fd.toPrettyChars());
+ buf.writestring(child ? fd.toChars() : fd.toPrettyChars());
buf.writestring(parametersTypeToChars(tf.parameterList));
if (tf.mod)
{
buf.writeByte(' ');
buf.MODtoBuffer(tf.mod);
}
- .errorSupplemental(fd.loc,
- printed ? " `%s`" :
- single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`", buf.peekChars());
+ .errorSupplemental(fd.loc, "%s`%s`", errorPrefix(), buf.peekChars());
}
else if (auto td = s.isTemplateDeclaration())
{
@@ -1779,35 +1798,43 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
if (!print)
return true;
+
+ // td.onemember may not have overloads set
+ // (see fail_compilation/onemember_overloads.d)
+ // assume if more than one member it is overloaded internally
+ bool recurse = td.onemember && td.members.length > 1;
OutBuffer buf;
HdrGenState hgs;
hgs.skipConstraints = true;
+ hgs.showOneMember = !recurse;
toCharsMaybeConstraints(td, buf, hgs);
const tmsg = buf.peekChars();
- const cmsg = td.getConstraintEvalError(constraintsTip);
-
- // add blank space if there are multiple candidates
- // the length of the blank space is `strlen("Candidates are: ")`
+ const cmsg = child ? null : td.getConstraintEvalError(constraintsTip);
if (cmsg)
- {
- .errorSupplemental(td.loc,
- printed ? " `%s`\n%s" :
- single_candidate ? "Candidate is: `%s`\n%s" : "Candidates are: `%s`\n%s",
- tmsg, cmsg);
- }
+ .errorSupplemental(td.loc, "%s`%s`\n%s", errorPrefix(), tmsg, cmsg);
else
+ .errorSupplemental(td.loc, "%s`%s`", errorPrefix(), tmsg);
+
+ if (recurse)
{
- .errorSupplemental(td.loc,
- printed ? " `%s`" :
- single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`",
- tmsg);
+ child = true;
+ foreach (d; *td.members)
+ {
+ if (d.ident != td.ident)
+ continue;
+
+ if (auto fd2 = d.isFuncDeclaration())
+ matchSymbol(fd2, print);
+ else if (auto td2 = d.isTemplateDeclaration())
+ matchSymbol(td2, print);
+ }
+ child = false;
}
}
return true;
}
// determine if there's > 1 candidate
- int count = 0;
overloadApply(declaration, (s) {
if (matchSymbol(s, false))
count++;
@@ -1817,7 +1844,7 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
overloadApply(declaration, (s) {
if (global.params.v.verbose || printed < DisplayLimit)
{
- if (matchSymbol(s, true, count == 1))
+ if (matchSymbol(s, true))
printed++;
}
else
@@ -1928,6 +1955,112 @@ FuncDeclaration overloadExactMatch(FuncDeclaration thisfd, Type t)
return fd;
}
+/****************************************************
+ * Determine if fd1 overrides fd2.
+ * Return !=0 if it does.
+ */
+int overrides(FuncDeclaration fd1, FuncDeclaration fd2)
+{
+ int result = 0;
+ if (fd1.ident == fd2.ident)
+ {
+ const cov = fd1.type.covariant(fd2.type);
+ if (cov != Covariant.distinct)
+ {
+ ClassDeclaration cd1 = fd1.toParent().isClassDeclaration();
+ ClassDeclaration cd2 = fd2.toParent().isClassDeclaration();
+ if (cd1 && cd2 && cd2.isBaseOf(cd1, null))
+ result = 1;
+ }
+ }
+ return result;
+}
+
+/*************************************
+ * Determine partial specialization order of functions `f` vs `g`.
+ * This is very similar to TemplateDeclaration::leastAsSpecialized().
+ * Params:
+ * f = first function
+ * g = second function
+ * names = names of parameters
+ * Returns:
+ * match 'this' is at least as specialized as g
+ * 0 g is more specialized than 'this'
+ */
+MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names)
+{
+ enum LOG_LEASTAS = 0;
+ static if (LOG_LEASTAS)
+ {
+ import core.stdc.stdio : printf;
+ printf("leastAsSpecialized(%s, %s, %s)\n", f.toChars(), g.toChars(), names ? names.toChars() : "null");
+ printf("%s, %s\n", f.type.toChars(), g.type.toChars());
+ }
+
+ /* This works by calling g() with f()'s parameters, and
+ * if that is possible, then f() is at least as specialized
+ * as g() is.
+ */
+
+ TypeFunction tf = f.type.toTypeFunction();
+ TypeFunction tg = g.type.toTypeFunction();
+
+ /* If both functions have a 'this' pointer, and the mods are not
+ * the same and g's is not const, then this is less specialized.
+ */
+ if (f.needThis() && g.needThis() && tf.mod != tg.mod)
+ {
+ if (f.isCtorDeclaration())
+ {
+ if (!MODimplicitConv(tg.mod, tf.mod))
+ return MATCH.nomatch;
+ }
+ else
+ {
+ if (!MODimplicitConv(tf.mod, tg.mod))
+ return MATCH.nomatch;
+ }
+ }
+
+ /* Create a dummy array of arguments out of the parameters to f()
+ */
+ Expressions args;
+ foreach (u, p; tf.parameterList)
+ {
+ Expression e;
+ if (p.isReference())
+ {
+ e = new IdentifierExp(Loc.initial, p.ident);
+ e.type = p.type;
+ }
+ else
+ e = p.type.defaultInitLiteral(Loc.initial);
+ args.push(e);
+ }
+
+ MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1);
+ if (m > MATCH.nomatch)
+ {
+ /* A variadic parameter list is less specialized than a
+ * non-variadic one.
+ */
+ if (tf.parameterList.varargs && !tg.parameterList.varargs)
+ goto L1; // less specialized
+
+ static if (LOG_LEASTAS)
+ {
+ printf(" matches %d, so is least as specialized\n", m);
+ }
+ return m;
+ }
+L1:
+ static if (LOG_LEASTAS)
+ {
+ printf(" doesn't match, so is not as specialized\n");
+ }
+ return MATCH.nomatch;
+}
+
/********************************************
* Find function in overload list that matches to the 'this' modifier.
* There's four result types.
@@ -2494,6 +2627,27 @@ void buildEnsureRequire(FuncDeclaration thisfd)
}
/****************************************************
+ * Determine whether an 'out' contract is declared inside
+ * the given function or any of its overrides.
+ * Params:
+ * fd = the function to search
+ * Returns:
+ * true found an 'out' contract
+ */
+bool needsFensure(FuncDeclaration fd) @safe
+{
+ if (fd.fensures)
+ return true;
+
+ foreach (fdv; fd.foverrides)
+ {
+ if (needsFensure(fdv))
+ return true;
+ }
+ return false;
+}
+
+/****************************************************
* Merge into this function the 'out' contracts of all it overrides.
* 'out's are AND'd together, i.e. all of them need to pass.
*/
@@ -2515,7 +2669,7 @@ Statement mergeFensure(FuncDeclaration fd, Statement sf, Identifier oid, Express
* https://issues.dlang.org/show_bug.cgi?id=3602 and
* https://issues.dlang.org/show_bug.cgi?id=5230
*/
- if (fd.needsFensure(fdv) && fdv.semanticRun != PASS.semantic3done)
+ if (needsFensure(fdv) && fdv.semanticRun != PASS.semantic3done)
{
assert(fdv._scope);
Scope* sc = fdv._scope.push();
@@ -2735,3 +2889,176 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)
return false;
}
}
+
+/+
+ + Checks the parameter and return types iff this is a `main` function.
+ +
+ + The following signatures are allowed for a `D main`:
+ + - Either no or a single parameter of type `string[]`
+ + - Return type is either `void`, `int` or `noreturn`
+ +
+ + The following signatures are standard C:
+ + - `int main()`
+ + - `int main(int, char**)`
+ +
+ + This function accepts the following non-standard extensions:
+ + - `char** envp` as a third parameter
+ + - `void` / `noreturn` as return type
+ +
+ + This function will issue errors for unexpected arguments / return types.
+ +/
+extern (D) void checkMain(FuncDeclaration fd)
+{
+ if (fd.ident != Id.main || fd.isMember() || fd.isNested())
+ return; // Not a main function
+
+ TypeFunction tf = fd.type.toTypeFunction();
+
+ Type retType = tf.nextOf();
+ if (!retType)
+ {
+ // auto main(), check after semantic
+ assert(fd.inferRetType);
+ return;
+ }
+
+ /// Checks whether `t` is equivalent to `char**`
+ /// Ignores qualifiers and treats enums according to their base type
+ static bool isCharPtrPtr(Type t)
+ {
+ auto tp = t.toBasetype().isTypePointer();
+ if (!tp)
+ return false;
+
+ tp = tp.next.toBasetype().isTypePointer();
+ if (!tp)
+ return false;
+
+ return tp.next.toBasetype().ty == Tchar;
+ }
+
+ // Neither of these qualifiers is allowed because they affect the ABI
+ enum invalidSTC = STC.out_ | STC.ref_ | STC.lazy_;
+
+ const nparams = tf.parameterList.length;
+ bool argerr;
+
+ const linkage = fd.resolvedLinkage();
+ if (linkage == LINK.d)
+ {
+ if (nparams == 1)
+ {
+ auto fparam0 = tf.parameterList[0];
+ auto t = fparam0.type.toBasetype();
+ if (t.ty != Tarray ||
+ t.nextOf().ty != Tarray ||
+ t.nextOf().nextOf().ty != Tchar ||
+ fparam0.storageClass & invalidSTC)
+ {
+ argerr = true;
+ }
+ }
+
+ if (tf.parameterList.varargs || nparams >= 2 || argerr)
+ .error(fd.loc, "%s `%s` parameter list must be empty or accept one parameter of type `string[]`", fd.kind, fd.toPrettyChars);
+ }
+
+ else if (linkage == LINK.c)
+ {
+ if (nparams == 2 || nparams == 3)
+ {
+ // Argument count must be int
+ auto argCount = tf.parameterList[0];
+ argerr |= !!(argCount.storageClass & invalidSTC);
+ argerr |= argCount.type.toBasetype().ty != Tint32;
+
+ // Argument pointer must be char**
+ auto argPtr = tf.parameterList[1];
+ argerr |= !!(argPtr.storageClass & invalidSTC);
+ argerr |= !isCharPtrPtr(argPtr.type);
+
+ // `char** environ` is a common extension, see J.5.1 of the C standard
+ if (nparams == 3)
+ {
+ auto envPtr = tf.parameterList[2];
+ argerr |= !!(envPtr.storageClass & invalidSTC);
+ argerr |= !isCharPtrPtr(envPtr.type);
+ }
+ }
+ else
+ argerr = nparams != 0;
+
+ // Disallow variadic main() - except for K&R declarations in C files.
+ // E.g. int main(), int main(argc, argv) int argc, char** argc { ... }
+ if (tf.parameterList.varargs && (!fd.isCsymbol() || (!tf.parameterList.hasIdentifierList && nparams)))
+ argerr |= true;
+
+ if (argerr)
+ {
+ .error(fd.loc, "%s `%s` parameters must match one of the following signatures", fd.kind, fd.toPrettyChars);
+ fd.loc.errorSupplemental("`main()`");
+ fd.loc.errorSupplemental("`main(int argc, char** argv)`");
+ fd.loc.errorSupplemental("`main(int argc, char** argv, char** environ)` [POSIX extension]");
+ }
+ }
+ else
+ return; // Neither C nor D main, ignore (should probably be an error)
+
+ // Allow enums with appropriate base types (same ABI)
+ retType = retType.toBasetype();
+
+ if (retType.ty != Tint32 && retType.ty != Tvoid && retType.ty != Tnoreturn)
+ .error(fd.loc, "%s `%s` must return `int`, `void` or `noreturn`, not `%s`", fd.kind, fd.toPrettyChars, tf.nextOf().toChars());
+}
+
+/***********************************************
+ * Check all return statements for a function to verify that returning
+ * using NRVO is possible.
+ *
+ * Returns:
+ * `false` if the result cannot be returned by hidden reference.
+ */
+extern (D) bool checkNRVO(FuncDeclaration fd)
+{
+ if (!fd.isNRVO() || fd.returns is null)
+ return false;
+
+ auto tf = fd.type.toTypeFunction();
+ if (tf.isref)
+ return false;
+
+ foreach (rs; *fd.returns)
+ {
+ if (auto ve = rs.exp.isVarExp())
+ {
+ auto v = ve.var.isVarDeclaration();
+ if (!v || v.isReference())
+ return false;
+ else if (fd.nrvo_var is null)
+ {
+ // Variables in the data segment (e.g. globals, TLS or not),
+ // parameters and closure variables cannot be NRVOed.
+ if (v.isDataseg() || v.isParameter() || v.toParent2() != fd)
+ return false;
+ if (v.nestedrefs.length && fd.needsClosure())
+ return false;
+ // don't know if the return storage is aligned
+ version (MARS)
+ {
+ if (fd.alignSectionVars && (*fd.alignSectionVars).contains(v))
+ return false;
+ }
+ // The variable type needs to be equivalent to the return type.
+ if (!v.type.equivalent(tf.next))
+ return false;
+ //printf("Setting nrvo to %s\n", v.toChars());
+ fd.nrvo_var = v;
+ }
+ else if (fd.nrvo_var != v)
+ return false;
+ }
+ else //if (!exp.isLvalue()) // keep NRVO-ability
+ return false;
+ }
+ return true;
+}
diff --git a/gcc/d/dmd/gluelayer.d b/gcc/d/dmd/gluelayer.d
index a3a3bd0..72e6c52 100644
--- a/gcc/d/dmd/gluelayer.d
+++ b/gcc/d/dmd/gluelayer.d
@@ -25,7 +25,7 @@ version (NoBackend)
struct Symbol;
struct code;
struct block;
- struct Blockx;
+ struct BlockState;
struct elem;
struct TYPE;
alias type = TYPE;
@@ -51,9 +51,9 @@ else version (IN_GCC)
}
else
{
- public import dmd.backend.cc : block, Blockx, Symbol;
+ public import dmd.backend.cc : block, BlockState, Symbol;
public import dmd.backend.type : type;
public import dmd.backend.el : elem;
- public import dmd.backend.code_x86 : code;
+ public import dmd.backend.x86.code_x86 : code;
public import dmd.objc_glue : ObjcGlue;
}
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 41da11d..1e72cf7 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -62,6 +62,7 @@ struct HdrGenState
bool doFuncBodies; /// include function bodies in output
bool vcg_ast; /// write out codegen-ast
bool skipConstraints; // skip constraints when doing templates
+ bool showOneMember = true;
bool fullQual; /// fully qualify types when printing
int tpltMember;
@@ -1974,7 +1975,7 @@ void toCharsMaybeConstraints(const TemplateDeclaration td, ref OutBuffer buf, re
}
buf.writeByte(')');
- if (td.onemember)
+ if (hgs.showOneMember && td.onemember)
{
if (const fd = td.onemember.isFuncDeclaration())
{
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 6dbc60b..dfaf8f5 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -102,6 +102,8 @@ immutable Msgtable[] msgtable =
{ "ctfe", "__ctfe" },
{ "offset" },
{ "offsetof" },
+ { "bitoffsetof" },
+ { "bitwidth" },
{ "ModuleInfo" },
{ "ClassInfo" },
{ "classinfo" },
@@ -455,6 +457,7 @@ immutable Msgtable[] msgtable =
{ "isAbstractClass" },
{ "isArithmetic" },
{ "isAssociativeArray" },
+ { "isBitfield" },
{ "isFinalClass" },
{ "isTemplate" },
{ "isPOD" },
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index dcfe183..a91a0a4 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -597,6 +597,14 @@ extern (C++) abstract class Type : ASTNode
tsize_t = basic[isLP64 ? Tuns64 : Tuns32];
tptrdiff_t = basic[isLP64 ? Tint64 : Tint32];
thash_t = tsize_t;
+
+ static if (__VERSION__ == 2081)
+ {
+ // Related issue: https://issues.dlang.org/show_bug.cgi?id=19134
+ // D 2.081.x regressed initializing class objects at compile time.
+ // As a workaround initialize this global at run-time instead.
+ TypeTuple.empty = new TypeTuple();
+ }
}
/**
@@ -4405,7 +4413,10 @@ extern (C++) final class TypeClass : Type
extern (C++) final class TypeTuple : Type
{
// 'logically immutable' cached global - don't modify!
- __gshared TypeTuple empty = new TypeTuple();
+ static if (__VERSION__ == 2081)
+ __gshared TypeTuple empty; // See comment in Type._init
+ else
+ __gshared TypeTuple empty = new TypeTuple();
Parameters* arguments; // types making up the tuple
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index d88face..963fa92 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -314,7 +314,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
fds.checkInContractOverrides();
// Remember whether we need to generate an 'out' contract.
- immutable bool needEnsure = FuncDeclaration.needsFensure(funcdecl);
+ immutable bool needEnsure = funcdecl.needsFensure();
if (funcdecl.fbody || funcdecl.frequires || needEnsure)
{
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index ae68d6a..d0e1b9a 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -3542,6 +3542,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
ls2.statement = ls;
sc = sc.push();
+ sc.lastVar = sc.enclosing.lastVar;
sc.scopesym = sc.enclosing.scopesym;
sc.ctorflow.orCSX(CSX.label);
@@ -3549,6 +3550,10 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
sc.slabel = ls;
if (ls.statement)
ls.statement = ls.statement.statementSemantic(sc);
+
+ //issue 24534: lastVar may have been updated in the nested scope
+ sc.enclosing.lastVar = sc.lastVar;
+
sc.pop();
result = ls;
diff --git a/gcc/d/dmd/target.d b/gcc/d/dmd/target.d
index 87826b5..dadf519 100644
--- a/gcc/d/dmd/target.d
+++ b/gcc/d/dmd/target.d
@@ -113,6 +113,7 @@ extern (C++) struct Target
const(char)[] architectureName;
CPU cpu; // CPU instruction set to target
bool isX86_64; // generate 64 bit code for x86_64; true by default for 64 bit dmd
+ bool isX86; // generate 32 bit Intel x86 code
bool isLP64; // pointers are 64 bits
// Environmental
@@ -120,7 +121,6 @@ extern (C++) struct Target
const(char)[] lib_ext; /// extension for static library files
const(char)[] dll_ext; /// extension for dynamic library files
bool run_noext; /// allow -run sources without extensions
- bool omfobj; // for Win32: write OMF object files instead of MsCoff
/**
* Values representing all properties for floating point types
*/
@@ -302,7 +302,6 @@ struct TargetC
{
Unspecified,
Bionic,
- DigitalMars,
Glibc,
Microsoft,
Musl,
@@ -314,7 +313,6 @@ struct TargetC
enum BitFieldStyle : ubyte
{
Unspecified,
- DM, /// Digital Mars 32 bit C compiler
MS, /// Microsoft 32 and 64 bit C compilers
/// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160
/// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
@@ -347,7 +345,6 @@ struct TargetCPP
{
Unspecified,
Clang,
- DigitalMars,
Gcc,
Microsoft,
Sun
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index 6237cf14..a5caa74 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -50,7 +50,6 @@ struct TargetC
{
Unspecified,
Bionic,
- DigitalMars,
Glibc,
Microsoft,
Musl,
@@ -62,7 +61,6 @@ struct TargetC
enum class BitFieldStyle : unsigned char
{
Unspecified,
- DM, // Digital Mars 32 bit C compiler
MS, // Microsoft 32 and 64 bit C compilers
// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160
// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
@@ -87,7 +85,6 @@ struct TargetCPP
{
Unspecified,
Clang,
- DigitalMars,
Gcc,
Microsoft,
Sun
@@ -157,6 +154,7 @@ struct Target
DString architectureName; // name of the platform architecture (e.g. X86_64)
CPU cpu; // CPU instruction set to target
d_bool isX86_64; // generate 64 bit code for x86_64; true by default for 64 bit dmd
+ d_bool isX86; // generate 32 bit Intel x86 code
d_bool isLP64; // pointers are 64 bits
// Environmental
@@ -164,7 +162,6 @@ struct Target
DString lib_ext; /// extension for static library files
DString dll_ext; /// extension for dynamic library files
d_bool run_noext; /// allow -run sources without extensions
- d_bool omfobj; /// for Win32: write OMF object files instead of COFF
template <typename T>
struct FPTypeProperties
diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d
index bd3cd89..d26e35d 100644
--- a/gcc/d/dmd/templatesem.d
+++ b/gcc/d/dmd/templatesem.d
@@ -56,6 +56,8 @@ import dmd.tokens;
import dmd.typesem;
import dmd.visitor;
+alias funcLeastAsSpecialized = dmd.funcsem.leastAsSpecialized;
+
/************************************
* Perform semantic analysis on template.
* Params:
@@ -2021,8 +2023,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
* This is because f() is "more specialized."
*/
{
- MATCH c1 = FuncDeclaration.leastAsSpecialized(fd, m.lastf, argumentList.names);
- MATCH c2 = FuncDeclaration.leastAsSpecialized(m.lastf, fd, argumentList.names);
+ MATCH c1 = funcLeastAsSpecialized(fd, m.lastf, argumentList.names);
+ MATCH c2 = funcLeastAsSpecialized(m.lastf, fd, argumentList.names);
//printf("c1 = %d, c2 = %d\n", c1, c2);
if (c1 > c2) return firstIsBetter();
if (c1 < c2) return 0;
@@ -2301,8 +2303,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
}
{
// Disambiguate by picking the most specialized FunctionDeclaration
- MATCH c1 = FuncDeclaration.leastAsSpecialized(fd, m.lastf, argumentList.names);
- MATCH c2 = FuncDeclaration.leastAsSpecialized(m.lastf, fd, argumentList.names);
+ MATCH c1 = funcLeastAsSpecialized(fd, m.lastf, argumentList.names);
+ MATCH c2 = funcLeastAsSpecialized(m.lastf, fd, argumentList.names);
//printf("3: c1 = %d, c2 = %d\n", c1, c2);
if (c1 > c2) goto Ltd;
if (c1 < c2) goto Ltd_best;
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 81d42e6..5ec3844 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -503,6 +503,17 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
sm => sm.isTemplateDeclaration() !is null) != 0;
});
}
+ if (e.ident == Id.isBitfield)
+ {
+ if (dim != 1)
+ return dimError(1);
+
+ return isDsymX((s)
+ {
+ s = s.toAlias();
+ return s.isBitFieldDeclaration() !is null;
+ });
+ }
if (e.ident == Id.isPOD)
{
if (dim != 1)
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 195fdc7..31ebc4c 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1282,6 +1282,23 @@ bool hasPointers(Type t)
}
}
+/**************************************
+ * Returns an indirect type one step from t.
+ */
+Type getIndirection(Type t)
+{
+ t = t.baseElemOf();
+ if (t.ty == Tarray || t.ty == Tpointer)
+ return t.nextOf().toBasetype();
+ if (t.ty == Taarray || t.ty == Tclass)
+ return t;
+ if (t.ty == Tstruct)
+ return t.hasPointers() ? t : null; // TODO
+
+ // should consider TypeDelegate?
+ return null;
+}
+
/******************************************
* Perform semantic analysis on a type.
* Params:
@@ -4083,7 +4100,9 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
}
if (v)
{
- if (ident == Id.offsetof)
+ if (ident == Id.offsetof ||
+ ident == Id.bitoffsetof ||
+ ident == Id.bitwidth)
{
v.dsymbolSemantic(null);
if (v.isField())
@@ -4093,7 +4112,20 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
ad.size(e.loc);
if (ad.sizeok != Sizeok.done)
return ErrorExp.get();
- return new IntegerExp(e.loc, v.offset, Type.tsize_t);
+ uint value;
+ if (ident == Id.offsetof)
+ value = v.offset;
+ else // Id.bitoffsetof || Id.bitwidth
+ {
+ auto bf = v.isBitFieldDeclaration();
+ if (bf)
+ {
+ value = ident == Id.bitoffsetof ? bf.bitOffset : bf.fieldWidth;
+ }
+ else
+ error(v.loc, "`%s` is not a bitfield, cannot apply `%s`", v.toChars(), ident.toChars());
+ }
+ return new IntegerExp(e.loc, value, Type.tsize_t);
}
}
else if (ident == Id._init)
@@ -4512,6 +4544,8 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
ident != Id._mangleof &&
ident != Id.stringof &&
ident != Id.offsetof &&
+ ident != Id.bitoffsetof &&
+ ident != Id.bitwidth &&
// https://issues.dlang.org/show_bug.cgi?id=15045
// Don't forward special built-in member functions.
ident != Id.ctor &&
@@ -6687,7 +6721,7 @@ Type substWildTo(Type type, uint mod)
t = new TypeSArray(t, (cast(TypeSArray)type).dim.syntaxCopy());
else if (type.ty == Taarray)
{
- t = new TypeAArray(t, (cast(TypeAArray)type).index.syntaxCopy());
+ t = new TypeAArray(t, (cast(TypeAArray)type).index.substWildTo(mod));
}
else if (type.ty == Tdelegate)
{