Improve support for C++11 alignof(T)
Support alignof(T) for arbitrary type T, and deduce the type of
alignof(T) as size_t.
diff --git a/CHANGES.current b/CHANGES.current
index a932dd9..13b6874 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -8,6 +8,10 @@
===========================
2024-06-06: olly
+ Support alignof(T) for arbitrary type T, and deduce the type of
+ alignof(T) as size_t.
+
+2024-06-06: olly
#2919 Support parsing `sizeof(X)` for any expression or type X by
skipping balanced parentheses. We don't need to actually parse X
since the type of sizeof is always size_t.
diff --git a/Examples/test-suite/constant_expr.i b/Examples/test-suite/constant_expr.i
index ed27da9..8aeb8bd 100644
--- a/Examples/test-suite/constant_expr.i
+++ b/Examples/test-suite/constant_expr.i
@@ -56,4 +56,11 @@
sizeof(char) ||
std::is_trivially_destructible<T>::value>
is_destructor_skippable;
+
+ // This is nonsensical, but provides a regression test for this not working with alignof() either.
+ typedef std::integral_constant<
+ bool, alignof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
+ alignof(char) ||
+ std::is_trivially_destructible<T>::value>
+ test_alignof_too;
};
diff --git a/Examples/test-suite/cpp11_decltype.i b/Examples/test-suite/cpp11_decltype.i
index 9e7e5e7..06995f5 100644
--- a/Examples/test-suite/cpp11_decltype.i
+++ b/Examples/test-suite/cpp11_decltype.i
@@ -70,6 +70,7 @@
decltype(sizeof(i+j)) should_be_ulong;
decltype(sizeof(-i)) should_be_ulong2;
+ decltype(alignof(int)) should_be_ulong3;
static constexpr decltype(*"abc") should_be_char = 0;
diff --git a/Examples/test-suite/php/cpp11_decltype_runme.php b/Examples/test-suite/php/cpp11_decltype_runme.php
index 4c96bb7..d5d42ad 100644
--- a/Examples/test-suite/php/cpp11_decltype_runme.php
+++ b/Examples/test-suite/php/cpp11_decltype_runme.php
@@ -53,6 +53,7 @@
check::equal(gettype($b->should_be_ulong), "integer");
check::equal(gettype($b->should_be_ulong2), "integer");
+check::equal(gettype($b->should_be_ulong3), "integer");
check::equal(gettype($b->should_be_bool), "boolean");
check::equal(gettype($b->should_be_bool2), "boolean");
diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c
index 4348f1f..0535613 100644
--- a/Source/CParse/cscanner.c
+++ b/Source/CParse/cscanner.c
@@ -905,6 +905,8 @@
return (USING);
if (strcmp(yytext, "namespace") == 0)
return (NAMESPACE);
+ if (strcmp(yytext, "alignof") == 0)
+ return (ALIGNOF);
if (strcmp(yytext, "override") == 0) {
last_id = 1;
return (OVERRIDE);
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index 3825764..1593df2 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -1670,7 +1670,7 @@
%token <intvalue> TYPEDEF
%token <type> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64
%token LPAREN RPAREN COMMA SEMI EXTERN LBRACE RBRACE PERIOD ELLIPSIS
-%token CONST_QUAL VOLATILE REGISTER STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET
+%token CONST_QUAL VOLATILE REGISTER STRUCT UNION EQUAL SIZEOF ALIGNOF MODULE LBRACKET RBRACKET
%token BEGINFILE ENDOFFILE
%token ILLEGAL CONSTANT
%token RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS
@@ -6618,6 +6618,14 @@
$$.type = T_ULONG;
$$.unary_arg_type = 0;
}
+ /* alignof(T) always has type size_t. */
+ | ALIGNOF LPAREN {
+ if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
+ $$.val = NewStringf("alignof%s", scanner_ccode);
+ Clear(scanner_ccode);
+ $$.type = T_ULONG;
+ $$.unary_arg_type = 0;
+ }
| SIZEOF ELLIPSIS LPAREN identifier RPAREN {
$$.val = NewStringf("sizeof...(%s)", $identifier);
$$.type = T_ULONG;