mirror of
https://github.com/dlang/dmd.git
synced 2025-04-27 21:51:03 +03:00
fix Issue 24155 - ImportC: accept C23 default initializers (#15801)
This commit is contained in:
parent
00a2a7f180
commit
8c84af86bc
13 changed files with 136 additions and 5 deletions
|
@ -6655,6 +6655,19 @@ struct ASTBase
|
|||
}
|
||||
}
|
||||
|
||||
extern (C++) final class DefaultInitializer : Initializer
|
||||
{
|
||||
extern (D) this(const ref Loc loc)
|
||||
{
|
||||
super(loc, InitKind.default_);
|
||||
}
|
||||
|
||||
override void accept(Visitor v)
|
||||
{
|
||||
v.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
struct Designator
|
||||
{
|
||||
Expression exp; /// [ constant-expression ]
|
||||
|
|
|
@ -383,6 +383,7 @@ enum STMT : ubyte
|
|||
enum InitKind : ubyte
|
||||
{
|
||||
void_,
|
||||
default_,
|
||||
error,
|
||||
struct_,
|
||||
array,
|
||||
|
|
|
@ -2168,6 +2168,7 @@ final class CParser(AST) : Parser!AST
|
|||
* C11 Initialization
|
||||
* initializer:
|
||||
* assignment-expression
|
||||
* { } // C23 6.7.10 addition
|
||||
* { initializer-list }
|
||||
* { initializer-list , }
|
||||
*
|
||||
|
@ -2198,6 +2199,12 @@ final class CParser(AST) : Parser!AST
|
|||
nextToken();
|
||||
const loc = token.loc;
|
||||
|
||||
if (token.value == TOK.rightCurly) // { }
|
||||
{
|
||||
nextToken();
|
||||
return new AST.DefaultInitializer(loc);
|
||||
}
|
||||
|
||||
/* Collect one or more `designation (opt) initializer`
|
||||
* into ci.initializerList, but lazily create ci
|
||||
*/
|
||||
|
|
|
@ -305,6 +305,7 @@ class TryCatchStatement;
|
|||
class DebugStatement;
|
||||
class ErrorInitializer;
|
||||
class VoidInitializer;
|
||||
class DefaultInitializer;
|
||||
class StructInitializer;
|
||||
class ArrayInitializer;
|
||||
class ExpInitializer;
|
||||
|
@ -1880,6 +1881,7 @@ public:
|
|||
virtual void visit(typename AST::StructInitializer i);
|
||||
virtual void visit(typename AST::ArrayInitializer i);
|
||||
virtual void visit(typename AST::VoidInitializer i);
|
||||
virtual void visit(typename AST::DefaultInitializer i);
|
||||
virtual void visit(typename AST::CInitializer i);
|
||||
};
|
||||
|
||||
|
@ -2708,11 +2710,12 @@ extern const char* toChars(const Statement* const s);
|
|||
enum class InitKind : uint8_t
|
||||
{
|
||||
void_ = 0u,
|
||||
error = 1u,
|
||||
struct_ = 2u,
|
||||
array = 3u,
|
||||
exp = 4u,
|
||||
C_ = 5u,
|
||||
default_ = 1u,
|
||||
error = 2u,
|
||||
struct_ = 3u,
|
||||
array = 4u,
|
||||
exp = 5u,
|
||||
C_ = 6u,
|
||||
};
|
||||
|
||||
class Initializer : public ASTNode
|
||||
|
@ -2723,6 +2726,7 @@ public:
|
|||
DYNCAST dyncast() const override;
|
||||
ErrorInitializer* isErrorInitializer();
|
||||
VoidInitializer* isVoidInitializer();
|
||||
DefaultInitializer* isDefaultInitializer();
|
||||
StructInitializer* isStructInitializer();
|
||||
ArrayInitializer* isArrayInitializer();
|
||||
ExpInitializer* isExpInitializer();
|
||||
|
@ -2752,6 +2756,13 @@ public:
|
|||
void accept(Visitor* v) override;
|
||||
};
|
||||
|
||||
class DefaultInitializer final : public Initializer
|
||||
{
|
||||
public:
|
||||
Type* type;
|
||||
void accept(Visitor* v) override;
|
||||
};
|
||||
|
||||
class ErrorInitializer final : public Initializer
|
||||
{
|
||||
public:
|
||||
|
@ -4946,6 +4957,7 @@ struct ASTCodegen final
|
|||
using HdrGenState = ::HdrGenState;
|
||||
using ArrayInitializer = ::ArrayInitializer;
|
||||
using CInitializer = ::CInitializer;
|
||||
using DefaultInitializer = ::DefaultInitializer;
|
||||
using DesigInit = ::DesigInit;
|
||||
using Designator = ::Designator;
|
||||
using ErrorInitializer = ::ErrorInitializer;
|
||||
|
|
|
@ -3856,6 +3856,11 @@ private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState
|
|||
buf.writestring("void");
|
||||
}
|
||||
|
||||
void visitDefault(DefaultInitializer iz)
|
||||
{
|
||||
buf.writestring("{ }");
|
||||
}
|
||||
|
||||
void visitStruct(StructInitializer si)
|
||||
{
|
||||
//printf("StructInitializer::toCBuffer()\n");
|
||||
|
|
|
@ -68,6 +68,11 @@ extern (C++) class Initializer : ASTNode
|
|||
return kind == InitKind.void_ ? cast(inout VoidInitializer)cast(void*)this : null;
|
||||
}
|
||||
|
||||
final inout(DefaultInitializer) isDefaultInitializer() inout @nogc nothrow pure
|
||||
{
|
||||
return kind == InitKind.default_ ? cast(inout DefaultInitializer)cast(void*)this : null;
|
||||
}
|
||||
|
||||
final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure
|
||||
{
|
||||
return kind == InitKind.struct_ ? cast(inout StructInitializer)cast(void*)this : null;
|
||||
|
@ -111,6 +116,24 @@ extern (C++) final class VoidInitializer : Initializer
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* The C23 default initializer `{ }`
|
||||
*/
|
||||
extern (C++) final class DefaultInitializer : Initializer
|
||||
{
|
||||
Type type; // type that this will initialize to
|
||||
|
||||
extern (D) this(const ref Loc loc) @safe
|
||||
{
|
||||
super(loc, InitKind.default_);
|
||||
}
|
||||
|
||||
override void accept(Visitor v)
|
||||
{
|
||||
v.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
*/
|
||||
extern (C++) final class ErrorInitializer : Initializer
|
||||
|
@ -266,6 +289,11 @@ Initializer syntaxCopy(Initializer inx)
|
|||
return new VoidInitializer(vi.loc);
|
||||
}
|
||||
|
||||
static Initializer visitDefault(DefaultInitializer vi)
|
||||
{
|
||||
return new DefaultInitializer(vi.loc);
|
||||
}
|
||||
|
||||
static Initializer visitError(ErrorInitializer vi)
|
||||
{
|
||||
return vi;
|
||||
|
@ -352,6 +380,7 @@ mixin template VisitInitializer(Result)
|
|||
final switch (init.kind)
|
||||
{
|
||||
case InitKind.void_: mixin(visitCase("Void")); break;
|
||||
case InitKind.default_: mixin(visitCase("Default")); break;
|
||||
case InitKind.error: mixin(visitCase("Error")); break;
|
||||
case InitKind.struct_: mixin(visitCase("Struct")); break;
|
||||
case InitKind.array: mixin(visitCase("Array")); break;
|
||||
|
|
|
@ -20,6 +20,7 @@ class Expression;
|
|||
class Type;
|
||||
class ErrorInitializer;
|
||||
class VoidInitializer;
|
||||
class DefaultInitializer;
|
||||
class StructInitializer;
|
||||
class ArrayInitializer;
|
||||
class ExpInitializer;
|
||||
|
@ -37,6 +38,7 @@ public:
|
|||
|
||||
ErrorInitializer *isErrorInitializer();
|
||||
VoidInitializer *isVoidInitializer();
|
||||
DefaultInitializer *isDefaultInitializer();
|
||||
StructInitializer *isStructInitializer();
|
||||
ArrayInitializer *isArrayInitializer();
|
||||
ExpInitializer *isExpInitializer();
|
||||
|
@ -53,6 +55,14 @@ public:
|
|||
void accept(Visitor *v) override { v->visit(this); }
|
||||
};
|
||||
|
||||
class DefaultInitializer final : public Initializer
|
||||
{
|
||||
public:
|
||||
Type *type; // type that this will initialize to
|
||||
|
||||
void accept(Visitor *v) override { v->visit(this); }
|
||||
};
|
||||
|
||||
class ErrorInitializer final : public Initializer
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -106,6 +106,7 @@ Expression toAssocArrayLiteral(ArrayInitializer ai)
|
|||
*/
|
||||
extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
|
||||
{
|
||||
//printf("initializerSemantic() tx: %p %s\n", tx, tx.toChars());
|
||||
Type t = tx;
|
||||
|
||||
static Initializer err()
|
||||
|
@ -119,6 +120,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
|
|||
return i;
|
||||
}
|
||||
|
||||
Initializer visitDefault(DefaultInitializer i)
|
||||
{
|
||||
i.type = t;
|
||||
return i;
|
||||
}
|
||||
|
||||
Initializer visitError(ErrorInitializer i)
|
||||
{
|
||||
return i;
|
||||
|
@ -1017,6 +1024,12 @@ Initializer inferType(Initializer init, Scope* sc)
|
|||
return new ErrorInitializer();
|
||||
}
|
||||
|
||||
Initializer visitDefault(DefaultInitializer i)
|
||||
{
|
||||
error(i.loc, "cannot infer type from default initializer");
|
||||
return new ErrorInitializer();
|
||||
}
|
||||
|
||||
Initializer visitError(ErrorInitializer i)
|
||||
{
|
||||
return i;
|
||||
|
@ -1175,6 +1188,11 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n
|
|||
return null;
|
||||
}
|
||||
|
||||
Expression visitDefault(DefaultInitializer di)
|
||||
{
|
||||
return di.type ? di.type.defaultInit(Loc.initial, isCfile) : null;
|
||||
}
|
||||
|
||||
Expression visitError(ErrorInitializer)
|
||||
{
|
||||
return ErrorExp.get();
|
||||
|
|
|
@ -298,5 +298,6 @@ public:
|
|||
void visit(AST.StructInitializer i) { visit(cast(AST.Initializer)i); }
|
||||
void visit(AST.ArrayInitializer i) { visit(cast(AST.Initializer)i); }
|
||||
void visit(AST.VoidInitializer i) { visit(cast(AST.Initializer)i); }
|
||||
void visit(AST.DefaultInitializer i) { visit(cast(AST.Initializer)i); }
|
||||
void visit(AST.CInitializer i) { visit(cast(AST.CInitializer)i); }
|
||||
}
|
||||
|
|
|
@ -234,5 +234,6 @@ extern(C++) class StrictVisitor(AST) : ParseTimeVisitor!AST
|
|||
override void visit(AST.StructInitializer) { assert(0); }
|
||||
override void visit(AST.ArrayInitializer) { assert(0); }
|
||||
override void visit(AST.VoidInitializer) { assert(0); }
|
||||
override void visit(AST.DefaultInitializer) { assert(0); }
|
||||
override void visit(AST.CInitializer) { assert(0); }
|
||||
}
|
||||
|
|
|
@ -205,6 +205,13 @@ extern (C++) void Initializer_toDt(Initializer init, ref DtBuilder dtb, bool isC
|
|||
assert(0);
|
||||
}
|
||||
|
||||
void visitDefault(DefaultInitializer di)
|
||||
{
|
||||
/* Default initializers are set to 0, because C23 says so
|
||||
*/
|
||||
dtb.nzeros(cast(uint)di.type.size());
|
||||
}
|
||||
|
||||
mixin VisitInitializer!void visit;
|
||||
visit.VisitInitializer(init);
|
||||
}
|
||||
|
|
|
@ -176,6 +176,7 @@ class NewDeclaration;
|
|||
|
||||
class Initializer;
|
||||
class VoidInitializer;
|
||||
class DefaultInitializer;
|
||||
class ErrorInitializer;
|
||||
class StructInitializer;
|
||||
class ArrayInitializer;
|
||||
|
@ -591,6 +592,7 @@ public:
|
|||
virtual void visit(StructInitializer *i) { visit((Initializer *)i); }
|
||||
virtual void visit(ArrayInitializer *i) { visit((Initializer *)i); }
|
||||
virtual void visit(VoidInitializer *i) { visit((Initializer *)i); }
|
||||
virtual void visit(DefaultInitializer *i) { visit((Initializer *)i); }
|
||||
virtual void visit(CInitializer *i) { visit((Initializer *)i); }
|
||||
};
|
||||
|
||||
|
|
|
@ -844,6 +844,30 @@ void test24154()
|
|||
|
||||
/*******************************************/
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24155
|
||||
|
||||
struct S24155 { int x, y; };
|
||||
|
||||
struct S24155 s = { };
|
||||
|
||||
void abc(int i)
|
||||
{
|
||||
assert(s.x == 0 && s.y == 0, __LINE__);
|
||||
struct S24155 s1 = { };
|
||||
assert(s1.x == 0 && s1.y == 0, __LINE__);
|
||||
struct S24155 s2 = { { i }, { } };
|
||||
assert(s2.x == i && s2.y == 0, __LINE__);
|
||||
struct S24155 s3 = { { }, { i } };
|
||||
assert(s3.x == 0 && s3.y == i, __LINE__);
|
||||
}
|
||||
|
||||
void test24155()
|
||||
{
|
||||
abc(1);
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
|
||||
int main()
|
||||
{
|
||||
test1();
|
||||
|
@ -893,6 +917,7 @@ int main()
|
|||
test22925();
|
||||
test47();
|
||||
test24154();
|
||||
test24155();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue