Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream stable #3886

Merged
merged 6 commits into from
Dec 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/supported_llvm_versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ jobs:
host_dc: dmd-beta
llvm_version: "6.0.1"
cmake_opts: "-DLIB_SUFFIX=64 -DLDC_LINK_MANUALLY=ON"
- job_name: Latest macOS, LLVM 10, latest DMD beta
os: macos-latest
- job_name: macOS 10.15, LLVM 10, latest DMD beta
os: macos-10.15
host_dc: dmd-beta
llvm_version: "10.0.1"
cmake_opts: "-DBUILD_SHARED_LIBS=ON -DRT_SUPPORT_SANITIZERS=ON -DLDC_LINK_MANUALLY=ON"
- job_name: Latest macOS, LLVM 7, latest LDC beta
os: macos-latest
- job_name: macOS 10.15, LLVM 7, latest LDC beta
os: macos-10.15
host_dc: ldc-beta
llvm_version: "7.0.0"
cmake_opts: "-DBUILD_SHARED_LIBS=OFF"
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ include(GetLinuxDistribution)
#

# Version information
set(LDC_VERSION "1.28.0") # May be overridden by git hash tag
set(LDC_VERSION "1.28.1") # May be overridden by git hash tag
set(DMDFE_MAJOR_VERSION 2)
set(DMDFE_MINOR_VERSION 0)
set(DMDFE_PATCH_VERSION 98)
set(DMDFE_FIX_LEVEL 0)
set(DMDFE_FIX_LEVEL 1)

set(DMD_VERSION ${DMDFE_MAJOR_VERSION}.${DMDFE_MINOR_VERSION}${DMDFE_PATCH_VERSION})
if(DEFINED DMDFE_FIX_LEVEL)
Expand Down
2 changes: 1 addition & 1 deletion dmd/blockexit.d
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
else if (sd && (!sd.statement.hasCode() || sd.statement.isCaseStatement() || sd.statement.isErrorStatement()))
{
}
else
else if (!func.getModule().isCFile)
{
const(char)* gototype = s.isCaseStatement() ? "case" : "default";
s.deprecation("switch case fallthrough - use 'goto %s;' if intended", gototype);
Expand Down
19 changes: 18 additions & 1 deletion dmd/constfold.d
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,12 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
emplaceExp!(UnionExp)(&ue, ex);
return ue;
}
if (e1.type.toBasetype.equals(type) && type.equals(to))
{
emplaceExp!(UnionExp)(&ue, e1);
ue.exp().type = type;
return ue;
}
if (e1.type.implicitConvTo(to) >= MATCH.constant || to.implicitConvTo(e1.type) >= MATCH.constant)
{
goto L1;
Expand Down Expand Up @@ -1100,7 +1106,18 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
}
else if (tb.ty == Tbool)
{
emplaceExp!(IntegerExp)(&ue, loc, e1.toInteger() != 0, type);
bool val = void;
if (e1.isBool(true))
val = true;
else if (e1.isBool(false))
val = false;
else
{
cantExp(ue);
return ue;
}

emplaceExp!(IntegerExp)(&ue, loc, val, type);
}
else if (type.isintegral())
{
Expand Down
83 changes: 74 additions & 9 deletions dmd/cparse.d
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ final class CParser(AST) : Parser!AST
{
//printf("cparseTranslationUnit()\n");
symbols = new AST.Dsymbols();
addBuiltinDeclarations();
while (1)
{
if (token.value == TOK.endOfFile)
Expand Down Expand Up @@ -974,12 +975,17 @@ final class CParser(AST) : Parser!AST
token.value == TOK.leftParenthesis &&
!isCastExpression(pt))
{
/* this might actually be a function
* call that looks like `(a)(b)` or even `(a)(b,c)`
/* (t)(...)... might be a cast expression or a function call,
* with different grammars: a cast would be cparseCastExp(),
* a function call would be cparsePostfixExp(CallExp(cparseArguments())).
* We can't know until t is known. So, parse it as a function call
* and let semantic() rewrite the AST as a CastExp if it turns out
* to be a type.
*/
auto ie = new AST.IdentifierExp(loc, t.isTypeIdentifier().ident);
ie.parens = true; // disambiguate it from being a declaration
return new AST.CallExp(loc, ie, cparseArguments());
ie.parens = true; // let semantic know it might be a CastExp
AST.Expression e = new AST.CallExp(loc, ie, cparseArguments());
return cparsePostfixOperators(e);
}
else
{
Expand Down Expand Up @@ -1480,9 +1486,12 @@ final class CParser(AST) : Parser!AST

/* If a declarator does not follow, it is unnamed
*/
if (token.value == TOK.semicolon && tspec)
if (token.value == TOK.semicolon)
{
nextToken();
if (!tspec)
return; // accept empty declaration as an extension

auto tt = tspec.isTypeTag();
if (!tt ||
!tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_))
Expand Down Expand Up @@ -1659,7 +1668,8 @@ final class CParser(AST) : Parser!AST
{
// Give non-extern variables an implicit void initializer
// if one has not been explicitly set.
if (!hasInitializer && !(specifier.scw & SCW.xextern))
if (!hasInitializer &&
!(specifier.scw & (SCW.xextern | SCW.xstatic | SCW.x_Thread_local) || level == LVL.global))
initializer = new AST.VoidInitializer(token.loc);
s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(level, specifier));
}
Expand Down Expand Up @@ -1692,7 +1702,11 @@ final class CParser(AST) : Parser!AST
switch (token.value)
{
case TOK.identifier:
error("missing comma");
if (s)
{
error("missing comma or semicolon after declaration of `%s`, found `%s` instead", s.toChars(), token.toChars());
goto Lend;
}
goto default;

case TOK.semicolon:
Expand All @@ -1706,7 +1720,8 @@ final class CParser(AST) : Parser!AST
break;

default:
error("`=`, `;` or `,` expected");
error("`=`, `;` or `,` expected to end declaration instead of `%s`", token.toChars());
Lend:
while (token.value != TOK.semicolon && token.value != TOK.endOfFile)
nextToken();
nextToken();
Expand Down Expand Up @@ -2484,7 +2499,18 @@ final class CParser(AST) : Parser!AST
return t;
}

t = constApply(t);
if (declarator == DTR.xparameter &&
t.isTypePointer())
{
/* Because there are instances in .h files of "const pointer to mutable",
* skip applying transitive `const`
* https://issues.dlang.org/show_bug.cgi?id=22534
*/
auto tn = cast(AST.TypeNext)t;
tn.next = constApply(tn.next);
}
else
t = constApply(t);
}

//printf("result: %s\n", t.toChars());
Expand Down Expand Up @@ -2594,6 +2620,8 @@ final class CParser(AST) : Parser!AST

Identifier id;
auto t = cparseDeclarator(DTR.xparameter, tspec, id, specifier);
if (token.value == TOK.__attribute__)
cparseGnuAttributes(specifier);
if (specifier.mod & MOD.xconst)
t = toConst(t);
auto param = new AST.Parameter(STC.parameter, t, id, null, null);
Expand Down Expand Up @@ -4341,5 +4369,42 @@ final class CParser(AST) : Parser!AST
return s;
}

/***********************************
* Add global target-dependent builtin declarations.
*/
private void addBuiltinDeclarations()
{
void genBuiltinFunc(Identifier id, AST.VarArg va)
{
auto tva_list = new AST.TypeIdentifier(Loc.initial, Id.builtin_va_list);
auto parameters = new AST.Parameters();
parameters.push(new AST.Parameter(STC.parameter | STC.ref_, tva_list, null, null, null));
auto pl = AST.ParameterList(parameters, va, 0);
auto tf = new AST.TypeFunction(pl, AST.Type.tvoid, LINK.c, 0);
auto s = new AST.FuncDeclaration(Loc.initial, Loc.initial, id, AST.STC.static_, tf, false);
symbols.push(s);
}

/* void __builtin_va_start(__builtin_va_list, ...);
* The second argument is supposed to be of any type, so fake it with the ...
*/
genBuiltinFunc(Id.builtin_va_start, AST.VarArg.variadic);

/* void __builtin_va_end(__builtin_va_list);
*/
genBuiltinFunc(Id.builtin_va_end, AST.VarArg.none);

version (IN_LLVM) { /* not needed */ } else
{
/* struct __va_list_tag
* {
* uint, uint, void*, void*
* }
*/
auto s = new AST.StructDeclaration(Loc.initial, Id.va_list_tag, false);
symbols.push(s);
} // !IN_LLVM
}

//}
}
16 changes: 12 additions & 4 deletions dmd/ctfeexpr.d
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,11 @@ bool isSafePointerCast(Type srcPointee, Type destPointee)
// It's OK if both are the same (modulo const)
if (srcPointee.constConv(destPointee))
return true;

// It's ok to cast from/to shared because CTFE is single threaded anyways
if (srcPointee.unSharedOf() == destPointee.unSharedOf())
return true;

// It's OK if function pointers differ only in safe/pure/nothrow
if (srcPointee.ty == Tfunction && destPointee.ty == Tfunction)
return srcPointee.covariant(destPointee) == 1 || destPointee.covariant(srcPointee) == 1;
Expand Down Expand Up @@ -1568,7 +1573,7 @@ Expression ctfeIndex(UnionExp* pue, const ref Loc loc, Type type, Expression e1,
assert(0);
}

Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expression e)
Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expression e, bool explicitCast = false)
{
Expression paint()
{
Expand All @@ -1581,9 +1586,12 @@ Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expres
if (e.op == TOK.classReference)
{
// Disallow reinterpreting class casts. Do this by ensuring that
// the original class can implicitly convert to the target class
ClassDeclaration originalClass = (cast(ClassReferenceExp)e).originalClass();
if (originalClass.type.implicitConvTo(to.mutableOf()))
// the original class can implicitly convert to the target class.
// Also do not check 'alias this' for explicit cast expressions.
auto tclass = (cast(ClassReferenceExp)e).originalClass().type.isTypeClass();
auto match = explicitCast ? tclass.implicitConvToWithoutAliasThis(to.mutableOf())
: tclass.implicitConvTo(to.mutableOf());
if (match)
return paint();
else
{
Expand Down
38 changes: 29 additions & 9 deletions dmd/dcast.d
Original file line number Diff line number Diff line change
Expand Up @@ -1500,12 +1500,8 @@ MATCH cimplicitConvTo(Expression e, Type t)
return MATCH.convert;
if (tb.isintegral() && typeb.ty == Tpointer) // C11 6.3.2.3-6
return MATCH.convert;
if (tb.ty == Tpointer && typeb.ty == Tpointer)
{
if (tb.isTypePointer().next.ty == Tvoid ||
typeb.isTypePointer().next.ty == Tvoid)
return MATCH.convert; // convert to/from void* C11 6.3.2.3-1
}
if (tb.ty == Tpointer && typeb.ty == Tpointer) // C11 6.3.2.3-7
return MATCH.convert;

return implicitConvTo(e, t);
}
Expand Down Expand Up @@ -1856,7 +1852,8 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)

//printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t.toChars(), e.toChars(), e.committed);

if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid &&
(!sc || !(sc.flags & SCOPE.Cfile)))
{
e.error("cannot convert string literal to `void*`");
result = ErrorExp.get();
Expand Down Expand Up @@ -3178,6 +3175,14 @@ Lagain:
Lcc:
while (1)
{
MATCH i1woat = MATCH.exact;
MATCH i2woat = MATCH.exact;

if (auto t2c = t2.isTypeClass())
i1woat = t2c.implicitConvToWithoutAliasThis(t1);
if (auto t1c = t1.isTypeClass())
i2woat = t1c.implicitConvToWithoutAliasThis(t2);

MATCH i1 = e2.implicitConvTo(t1);
MATCH i2 = e1.implicitConvTo(t2);

Expand All @@ -3190,11 +3195,26 @@ Lagain:
i2 = MATCH.nomatch;
}

if (i2)
// Match but without 'alias this' on classes
if (i2 && i2woat)
return coerce(t2);
if (i1)
if (i1 && i1woat)
return coerce(t1);

// Here use implicitCastTo() instead of castTo() to try 'alias this' on classes
Type coerceImplicit(Type towards)
{
e1 = e1.implicitCastTo(sc, towards);
e2 = e2.implicitCastTo(sc, towards);
return Lret(towards);
}

// Implicit conversion with 'alias this'
if (i2)
return coerceImplicit(t2);
if (i1)
return coerceImplicit(t1);

if (t1.ty == Tclass && t2.ty == Tclass)
{
TypeClass tc1 = t1.isTypeClass();
Expand Down
5 changes: 3 additions & 2 deletions dmd/dinterpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public Expression ctfeInterpret(Expression e)
case TOK.template_: // non-eponymous template/instance
case TOK.scope_: // ditto
case TOK.dotTemplateDeclaration: // ditto, e.e1 doesn't matter here
case TOK.dotTemplateInstance: // ditto
case TOK.dot: // ditto
if (e.type.ty == Terror)
return ErrorExp.get();
Expand Down Expand Up @@ -2202,7 +2203,7 @@ version (IN_LLVM)
Expression ev = getValue(v);
if (ev.op == TOK.variable ||
ev.op == TOK.index ||
ev.op == TOK.slice ||
(ev.op == TOK.slice && ev.type.toBasetype().ty == Tsarray) ||
ev.op == TOK.dotVariable)
{
result = interpret(pue, ev, istate, goal);
Expand Down Expand Up @@ -6041,7 +6042,7 @@ version (IN_LLVM)
result = pue.exp();
return;
}
result = ctfeCast(pue, e.loc, e.type, e.to, e1);
result = ctfeCast(pue, e.loc, e.type, e.to, e1, true);
}

override void visit(AssertExp e)
Expand Down
3 changes: 2 additions & 1 deletion dmd/dmangle.d
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,8 @@ public:
extern (D) static const(char)[] externallyMangledIdentifier(Declaration d)
{
const par = d.toParent(); //toParent() skips over mixin templates
if (!par || par.isModule() || d.linkage == LINK.cpp)
if (!par || par.isModule() || d.linkage == LINK.cpp ||
(d.linkage == LINK.c && d.isCsymbol() && d.isFuncDeclaration()))
{
if (d.linkage != LINK.d && d.localNum)
d.error("the same declaration cannot be in multiple scopes with non-D linkage");
Expand Down
Loading