fix Issue 24155 - ImportC: accept C23 default initializers (#15801)

This commit is contained in:
Walter Bright 2023-11-15 13:04:42 -08:00 committed by GitHub
parent 00a2a7f180
commit 8c84af86bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 136 additions and 5 deletions

View file

@ -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 struct Designator
{ {
Expression exp; /// [ constant-expression ] Expression exp; /// [ constant-expression ]

View file

@ -383,6 +383,7 @@ enum STMT : ubyte
enum InitKind : ubyte enum InitKind : ubyte
{ {
void_, void_,
default_,
error, error,
struct_, struct_,
array, array,

View file

@ -2168,6 +2168,7 @@ final class CParser(AST) : Parser!AST
* C11 Initialization * C11 Initialization
* initializer: * initializer:
* assignment-expression * assignment-expression
* { } // C23 6.7.10 addition
* { initializer-list } * { initializer-list }
* { initializer-list , } * { initializer-list , }
* *
@ -2198,6 +2199,12 @@ final class CParser(AST) : Parser!AST
nextToken(); nextToken();
const loc = token.loc; const loc = token.loc;
if (token.value == TOK.rightCurly) // { }
{
nextToken();
return new AST.DefaultInitializer(loc);
}
/* Collect one or more `designation (opt) initializer` /* Collect one or more `designation (opt) initializer`
* into ci.initializerList, but lazily create ci * into ci.initializerList, but lazily create ci
*/ */

View file

@ -305,6 +305,7 @@ class TryCatchStatement;
class DebugStatement; class DebugStatement;
class ErrorInitializer; class ErrorInitializer;
class VoidInitializer; class VoidInitializer;
class DefaultInitializer;
class StructInitializer; class StructInitializer;
class ArrayInitializer; class ArrayInitializer;
class ExpInitializer; class ExpInitializer;
@ -1880,6 +1881,7 @@ public:
virtual void visit(typename AST::StructInitializer i); virtual void visit(typename AST::StructInitializer i);
virtual void visit(typename AST::ArrayInitializer i); virtual void visit(typename AST::ArrayInitializer i);
virtual void visit(typename AST::VoidInitializer i); virtual void visit(typename AST::VoidInitializer i);
virtual void visit(typename AST::DefaultInitializer i);
virtual void visit(typename AST::CInitializer 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 enum class InitKind : uint8_t
{ {
void_ = 0u, void_ = 0u,
error = 1u, default_ = 1u,
struct_ = 2u, error = 2u,
array = 3u, struct_ = 3u,
exp = 4u, array = 4u,
C_ = 5u, exp = 5u,
C_ = 6u,
}; };
class Initializer : public ASTNode class Initializer : public ASTNode
@ -2723,6 +2726,7 @@ public:
DYNCAST dyncast() const override; DYNCAST dyncast() const override;
ErrorInitializer* isErrorInitializer(); ErrorInitializer* isErrorInitializer();
VoidInitializer* isVoidInitializer(); VoidInitializer* isVoidInitializer();
DefaultInitializer* isDefaultInitializer();
StructInitializer* isStructInitializer(); StructInitializer* isStructInitializer();
ArrayInitializer* isArrayInitializer(); ArrayInitializer* isArrayInitializer();
ExpInitializer* isExpInitializer(); ExpInitializer* isExpInitializer();
@ -2752,6 +2756,13 @@ public:
void accept(Visitor* v) override; void accept(Visitor* v) override;
}; };
class DefaultInitializer final : public Initializer
{
public:
Type* type;
void accept(Visitor* v) override;
};
class ErrorInitializer final : public Initializer class ErrorInitializer final : public Initializer
{ {
public: public:
@ -4946,6 +4957,7 @@ struct ASTCodegen final
using HdrGenState = ::HdrGenState; using HdrGenState = ::HdrGenState;
using ArrayInitializer = ::ArrayInitializer; using ArrayInitializer = ::ArrayInitializer;
using CInitializer = ::CInitializer; using CInitializer = ::CInitializer;
using DefaultInitializer = ::DefaultInitializer;
using DesigInit = ::DesigInit; using DesigInit = ::DesigInit;
using Designator = ::Designator; using Designator = ::Designator;
using ErrorInitializer = ::ErrorInitializer; using ErrorInitializer = ::ErrorInitializer;

View file

@ -3856,6 +3856,11 @@ private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState
buf.writestring("void"); buf.writestring("void");
} }
void visitDefault(DefaultInitializer iz)
{
buf.writestring("{ }");
}
void visitStruct(StructInitializer si) void visitStruct(StructInitializer si)
{ {
//printf("StructInitializer::toCBuffer()\n"); //printf("StructInitializer::toCBuffer()\n");

View file

@ -68,6 +68,11 @@ extern (C++) class Initializer : ASTNode
return kind == InitKind.void_ ? cast(inout VoidInitializer)cast(void*)this : null; 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 final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure
{ {
return kind == InitKind.struct_ ? cast(inout StructInitializer)cast(void*)this : null; 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 extern (C++) final class ErrorInitializer : Initializer
@ -266,6 +289,11 @@ Initializer syntaxCopy(Initializer inx)
return new VoidInitializer(vi.loc); return new VoidInitializer(vi.loc);
} }
static Initializer visitDefault(DefaultInitializer vi)
{
return new DefaultInitializer(vi.loc);
}
static Initializer visitError(ErrorInitializer vi) static Initializer visitError(ErrorInitializer vi)
{ {
return vi; return vi;
@ -352,6 +380,7 @@ mixin template VisitInitializer(Result)
final switch (init.kind) final switch (init.kind)
{ {
case InitKind.void_: mixin(visitCase("Void")); break; case InitKind.void_: mixin(visitCase("Void")); break;
case InitKind.default_: mixin(visitCase("Default")); break;
case InitKind.error: mixin(visitCase("Error")); break; case InitKind.error: mixin(visitCase("Error")); break;
case InitKind.struct_: mixin(visitCase("Struct")); break; case InitKind.struct_: mixin(visitCase("Struct")); break;
case InitKind.array: mixin(visitCase("Array")); break; case InitKind.array: mixin(visitCase("Array")); break;

View file

@ -20,6 +20,7 @@ class Expression;
class Type; class Type;
class ErrorInitializer; class ErrorInitializer;
class VoidInitializer; class VoidInitializer;
class DefaultInitializer;
class StructInitializer; class StructInitializer;
class ArrayInitializer; class ArrayInitializer;
class ExpInitializer; class ExpInitializer;
@ -37,6 +38,7 @@ public:
ErrorInitializer *isErrorInitializer(); ErrorInitializer *isErrorInitializer();
VoidInitializer *isVoidInitializer(); VoidInitializer *isVoidInitializer();
DefaultInitializer *isDefaultInitializer();
StructInitializer *isStructInitializer(); StructInitializer *isStructInitializer();
ArrayInitializer *isArrayInitializer(); ArrayInitializer *isArrayInitializer();
ExpInitializer *isExpInitializer(); ExpInitializer *isExpInitializer();
@ -53,6 +55,14 @@ public:
void accept(Visitor *v) override { v->visit(this); } 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 class ErrorInitializer final : public Initializer
{ {
public: public:

View file

@ -106,6 +106,7 @@ Expression toAssocArrayLiteral(ArrayInitializer ai)
*/ */
extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret) 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; Type t = tx;
static Initializer err() static Initializer err()
@ -119,6 +120,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
return i; return i;
} }
Initializer visitDefault(DefaultInitializer i)
{
i.type = t;
return i;
}
Initializer visitError(ErrorInitializer i) Initializer visitError(ErrorInitializer i)
{ {
return i; return i;
@ -1017,6 +1024,12 @@ Initializer inferType(Initializer init, Scope* sc)
return new ErrorInitializer(); return new ErrorInitializer();
} }
Initializer visitDefault(DefaultInitializer i)
{
error(i.loc, "cannot infer type from default initializer");
return new ErrorInitializer();
}
Initializer visitError(ErrorInitializer i) Initializer visitError(ErrorInitializer i)
{ {
return i; return i;
@ -1175,6 +1188,11 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n
return null; return null;
} }
Expression visitDefault(DefaultInitializer di)
{
return di.type ? di.type.defaultInit(Loc.initial, isCfile) : null;
}
Expression visitError(ErrorInitializer) Expression visitError(ErrorInitializer)
{ {
return ErrorExp.get(); return ErrorExp.get();

View file

@ -298,5 +298,6 @@ public:
void visit(AST.StructInitializer i) { visit(cast(AST.Initializer)i); } void visit(AST.StructInitializer i) { visit(cast(AST.Initializer)i); }
void visit(AST.ArrayInitializer 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.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); } void visit(AST.CInitializer i) { visit(cast(AST.CInitializer)i); }
} }

View file

@ -234,5 +234,6 @@ extern(C++) class StrictVisitor(AST) : ParseTimeVisitor!AST
override void visit(AST.StructInitializer) { assert(0); } override void visit(AST.StructInitializer) { assert(0); }
override void visit(AST.ArrayInitializer) { assert(0); } override void visit(AST.ArrayInitializer) { assert(0); }
override void visit(AST.VoidInitializer) { assert(0); } override void visit(AST.VoidInitializer) { assert(0); }
override void visit(AST.DefaultInitializer) { assert(0); }
override void visit(AST.CInitializer) { assert(0); } override void visit(AST.CInitializer) { assert(0); }
} }

View file

@ -205,6 +205,13 @@ extern (C++) void Initializer_toDt(Initializer init, ref DtBuilder dtb, bool isC
assert(0); 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; mixin VisitInitializer!void visit;
visit.VisitInitializer(init); visit.VisitInitializer(init);
} }

View file

@ -176,6 +176,7 @@ class NewDeclaration;
class Initializer; class Initializer;
class VoidInitializer; class VoidInitializer;
class DefaultInitializer;
class ErrorInitializer; class ErrorInitializer;
class StructInitializer; class StructInitializer;
class ArrayInitializer; class ArrayInitializer;
@ -591,6 +592,7 @@ public:
virtual void visit(StructInitializer *i) { visit((Initializer *)i); } virtual void visit(StructInitializer *i) { visit((Initializer *)i); }
virtual void visit(ArrayInitializer *i) { visit((Initializer *)i); } virtual void visit(ArrayInitializer *i) { visit((Initializer *)i); }
virtual void visit(VoidInitializer *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); } virtual void visit(CInitializer *i) { visit((Initializer *)i); }
}; };

View file

@ -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() int main()
{ {
test1(); test1();
@ -893,6 +917,7 @@ int main()
test22925(); test22925();
test47(); test47();
test24154(); test24154();
test24155();
return 0; return 0;
} }