ImportC: allow _Alignof expression (#21181)

Resolves https://github.com/dlang/dmd/issues/20434

Allowing this gnu/clang extension actually removes lines of code as
we can unify the parsing and semantics of `_Alignof` and `sizeof`
and have the normal D machinery handle the difference later.
This commit is contained in:
drpriver 2025-04-09 16:20:50 -07:00 committed by GitHub
parent 93b0317cc3
commit a0bf0f368a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 9 additions and 71 deletions

View file

@ -982,6 +982,7 @@ final class CParser(AST) : Parser!AST
* sizeof unary-expression
* sizeof ( type-name )
* _Alignof ( type-name )
* _Alignof unary-expression // gcc extension
*
* unary-operator:
* & * + - ~ !
@ -1044,8 +1045,10 @@ final class CParser(AST) : Parser!AST
e = new AST.ComExp(loc, e);
break;
case TOK._Alignof:
case TOK.sizeof_:
{
Identifier id = token.value == TOK.sizeof_? Id.__sizeof : Id.__xalignof;
nextToken();
if (token.value == TOK.leftParenthesis)
{
@ -1084,7 +1087,7 @@ final class CParser(AST) : Parser!AST
e = cparseUnaryExp();
}
e = new AST.DotIdExp(loc, e, Id.__sizeof);
e = new AST.DotIdExp(loc, e, id);
break;
}
@ -1096,17 +1099,6 @@ final class CParser(AST) : Parser!AST
e = cparseCastExp();
break;
case TOK._Alignof:
{
nextToken();
check(TOK.leftParenthesis);
auto t = cparseTypeName();
check(TOK.rightParenthesis);
e = new AST.TypeExp(loc, t);
e = new AST.DotIdExp(loc, e, Id.__xalignof);
break;
}
default:
e = cparsePostfixExp(e);
break;
@ -5025,6 +5017,7 @@ final class CParser(AST) : Parser!AST
return false;
break;
case TOK._Alignof:
case TOK.sizeof_:
t = peek(t);
if (t.value == TOK.leftParenthesis)
@ -5042,15 +5035,6 @@ final class CParser(AST) : Parser!AST
return false;
break;
case TOK._Alignof:
t = peek(t);
if (t.value != TOK.leftParenthesis)
return false;
t = peek(t);
if (!isTypeName(t) || t.value != TOK.rightParenthesis)
return false;
break;
default:
// Compound literals are handled by cast and sizeof expressions,
// so be content with just seeing a primary expression.

View file

@ -8191,37 +8191,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (exp.arrow) // ImportC only
exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
if (exp.ident == Id.__xalignof && exp.e1.isTypeExp())
{
// C11 6.5.3 says _Alignof only applies to types
Expression e;
Type t;
Dsymbol s;
dmd.typesem.resolve(exp.e1.type, exp.e1.loc, sc, e, t, s, true);
if (e)
{
error(exp.e1.loc, "argument to `_Alignof` must be a type");
return setError();
}
else if (t)
{
// Note similarity to getProperty() implementation of __xalignof
const explicitAlignment = t.alignment();
const naturalAlignment = t.alignsize();
const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get());
result = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
}
else if (s)
{
error(exp.e1.loc, "argument to `_Alignof` must be a type");
return setError();
}
else
assert(0);
return;
}
if (exp.ident != Id.__sizeof)
if (exp.ident != Id.__sizeof && exp.ident != Id.__xalignof)
{
result = fieldLookup(exp.e1, sc, exp.ident, exp.arrow);
return;

View file

@ -3,10 +3,10 @@
int printf(const char *, ...);
_Alignas(4) _Alignas(8) _Alignas(0) int x = 5;
//_Static_assert(_Alignof(x) == 8, "in");
_Static_assert(_Alignof(x) == 8, "in");
_Alignas(int) short y = 6;
//_Static_assert(_Alignof(y) == 4, "in");
_Static_assert(_Alignof(y) == 4, "in");
struct S
{

View file

@ -329,6 +329,7 @@ void test4(int i)
_Static_assert(sizeof 3 == 4, "ok");
_Static_assert(sizeof(3) == 4, "ok");
_Static_assert(_Alignof(int) == 4, "ok");
_Static_assert(_Alignof 3 == 4, "ok");
_Static_assert((int)3 == 3, "ok");
_Static_assert(sizeof p[0] == 4, "ok");
_Static_assert(1 && 2, "ok");

View file

@ -1,17 +0,0 @@
/* TEST_OUTPUT:
---
fail_compilation/test22246.c(106): Error: argument to `_Alignof` must be a type
---
*/
// https://issues.dlang.org/show_bug.cgi?id=22246
#line 100
struct S { int m; };
int test()
{
struct S s;
return _Alignof(s);
}