Skip to content

Commit

Permalink
fix Issue 22028 - importC: Parser accepts initializers for struct mem…
Browse files Browse the repository at this point in the history
…bers
  • Loading branch information
ibuclaw committed Jun 16, 2021
1 parent 8ce3da5 commit 4972f09
Showing 1 changed file with 162 additions and 1 deletion.
163 changes: 162 additions & 1 deletion src/dmd/cparse.d
Expand Up @@ -1671,6 +1671,167 @@ final class CParser(AST) : Parser!AST
}
}

/*************************************
* C11 6.7.2
* member-declaration:
* specifier-qualifier-list member-declarator-list (opt) ;
* static_assert-declaration
*
* member-declarator-list:
* member-declarator
* member-declarator-list , member-declarator
*
* member-declarator:
* declarator
* declarator (opt) : constant-expression
*/
void cparseMemberDeclaration()
{
//printf("cparseMemberDeclaration()\n");
if (token.value == TOK._Static_assert)
{
auto s = cparseStaticAssert();
symbols.push(s);
return;
}

auto symbolsSave = symbols;
Specifier specifier;
auto tspec = cparseSpecifierQualifierList(LVL.member, specifier);

/* If a declarator does not follow, it is unnamed
*/
if (token.value == TOK.semicolon &&
tspec && tspec.isTypeTag())
{
/* If anonymous struct declaration
* struct { ... members ... };
* C11 6.7.2.1-13
*/
nextToken();
auto tt = tspec.isTypeTag();
if (!tt.id && tt.members)
{
/* members of anonymous struct are considered members of
* the containing struct
*/
// TODO: merge in specifier
auto ad = new AST.AnonDeclaration(tt.loc, tt.tok == TOK.union_, tt.members);
if (!symbols)
symbols = new AST.Dsymbols();
symbols.push(ad);
return;
}
if (!tt.id && !tt.members)
return; // already gave error in cparseStruct()

/* `struct tag;` and `struct tag { ... };`
* always result in a declaration in the current scope
*/
// TODO: merge in specifier
auto stag = (tt.tok == TOK.struct_)
? new AST.StructDeclaration(tt.loc, tt.id, false)
: new AST.UnionDeclaration(tt.loc, tt.id);
stag.members = tt.members;
if (!symbols)
symbols = new AST.Dsymbols();
symbols.push(stag);
return;
}

while (1)
{
Identifier id;
AST.Type dt;
if (token.value == TOK.colon)
{
// C11 6.7.2.1-12 unnamed bit-field
nextToken();
cparseConstantExp();
error("unnamed bit fields are not supported"); // TODO
dt = AST.Type.tuns32;
}
else
dt = cparseDeclarator(tspec, id);
if (!dt)
{
panic();
nextToken();
break; // error recovery
}
if (id && token.value == TOK.colon)
{
// C11 6.7.2.1 bit-field
nextToken();
cparseConstantExp();
error("bit fields are not supported"); // TODO
}

if (specifier.mod & MOD.xconst)
dt = dt.addSTC(STC.const_);

if (!id) // no identifier
{
if (dt !is tspec)
{
error("identifier or `(` expected"); // )
panic();
break;
}
}

/* GNU Extensions
* member-declarator:
* declarator gnu-attributes (opt)
* declarator (opt) : constant-expression gnu-attributes (opt)
*/
if (token.value == TOK.__attribute__)
cparseGnuAttributes();

AST.Dsymbol s = null;
symbols = symbolsSave;
if (!symbols)
symbols = new AST.Dsymbols; // lazilly create it

if (!tspec && !specifier.scw && !specifier.mod)
error("specifier-qualifier-list required");
else if (id)
{
if (dt.ty == AST.Tvoid)
error("`void` has no value");

// declare the symbol
// Give member variables an implicit void initializer
auto initializer = new AST.VoidInitializer(token.loc);
s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(LVL.member, specifier));
}
if (s !is null)
symbols.push(s);

switch (token.value)
{
case TOK.identifier:
error("missing comma");
goto default;

case TOK.semicolon:
nextToken();
return;

case TOK.comma:
nextToken();
break;

default:
error("`;` or `,` expected");
while (token.value != TOK.semicolon && token.value != TOK.endOfFile)
nextToken();
nextToken();
return;
}
}
}

/***************************************
* C11 Function Definitions
* function-definition
Expand Down Expand Up @@ -2903,7 +3064,7 @@ final class CParser(AST) : Parser!AST
symbols = new AST.Dsymbols();
while (token.value != TOK.rightCurly)
{
cparseDeclaration(LVL.member);
cparseMemberDeclaration();

if (token.value == TOK.endOfFile)
break;
Expand Down

0 comments on commit 4972f09

Please sign in to comment.