Skip to content

Commit 259747a

Browse files
Translate sizeof / _Alignof to size_t literals
Adds a UnaryExprOrTypeTraitExpr arm to trRValue in cpp/impl.cpp that asks clang to constant-fold sizeof/_Alignof/_PreferredAlignOf via EvaluateAsInt and emits the result as a size_t integer literal. VLA sizeof falls through to the existing unsupported-rvalue error. Also fills in the previously-TODO (SizeT, Int) cast arm in emit.rs as the dual of the existing (Int, SizeT) arm, so that (uintN_t)sizeof(T) emits as UIntN.uint_to_t (SizeT.v Nsz). This is needed in practice because once sizeof emits a real size_t literal, narrowing casts of it appear immediately. The test file exercises sizeof on builtin types, expressions, struct types, array types, an arithmetic combination with another size_t literal, the new SizeT -> uint32_t cast, and _Alignof. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3f11c61 commit 259747a

3 files changed

Lines changed: 80 additions & 1 deletion

File tree

cpp/impl.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,24 @@ class PALConsumer : public ASTConsumer {
797797
}
798798
// Other DeclRefExpr in rvalue context: treat as lvalue read
799799
return mk_rvalue_lvalue(std::move(loc), trLValue(e));
800+
} else if (auto *u = dyn_cast<UnaryExprOrTypeTraitExpr>(e)) {
801+
// sizeof / _Alignof: clang has already constant-folded these for any
802+
// non-VLA type or expression. Emit as a size_t literal. The value
803+
// depends on the target triple PAL invokes clang with; for a 64-bit
804+
// target this matches the runtime layout assumed by msquic.
805+
if (u->getKind() == UETT_SizeOf || u->getKind() == UETT_AlignOf ||
806+
u->getKind() == UETT_PreferredAlignOf) {
807+
Expr::EvalResult er;
808+
if (u->EvaluateAsInt(er, *astCtx)) {
809+
SmallString<32> valStr;
810+
er.Val.getInt().toString(valStr);
811+
return mk_int_lit(loc.clone(),
812+
mk_bigint(toStr(StringRef(valStr))),
813+
mk_sizet(std::move(loc)));
814+
}
815+
// VLA sizeof or other non-constant case: fall through to the
816+
// generic unsupported-rvalue error below.
817+
}
800818
}
801819

802820
reportUnsupported(e->getSourceRange(), loc,

src/pass/emit.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1544,7 +1544,17 @@ impl<'a> Emitter<'a> {
15441544
// (TypeT::Int { signed, width }, TypeT::SizeT) => todo!(),
15451545
// (TypeT::Int { signed, width }, TypeT::SLProp) => todo!(),
15461546
// (TypeT::SizeT, TypeT::Bool) => todo!(),
1547-
// (TypeT::SizeT, TypeT::Int { signed, width }) => todo!(),
1547+
(TypeT::SizeT, TypeT::Int { signed, width }) => {
1548+
if let Some(m) = get_int_mod(signed, width) {
1549+
unaryfn(
1550+
Doc::text(format!("{}.uint_to_t (SizeT.v", m)),
1551+
val_doc.append(Doc::text(")")),
1552+
)
1553+
} else {
1554+
self.report(default_msg.clone(), &v.loc);
1555+
Doc::text("(admit())")
1556+
}
1557+
}
15481558
// (TypeT::SizeT, TypeT::SLProp) => todo!(),
15491559
// (TypeT::Pointer { to, kind }, TypeT::Bool) => todo!(),
15501560
(TypeT::Pointer(_, kind), TypeT::Bool) => {

test/sizeof.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include "pal.h"
2+
#include <stdint.h>
3+
#include <stddef.h>
4+
5+
// sizeof of a builtin type in a size_t-position
6+
size_t size_of_int(void)
7+
{
8+
return sizeof(int);
9+
}
10+
11+
// sizeof of an expression (clang folds based on the expression's type)
12+
size_t size_of_expr(int x)
13+
{
14+
return sizeof(x);
15+
}
16+
17+
// sizeof participating in arithmetic against another size_t literal
18+
size_t bytes_for_10_ints(void)
19+
{
20+
return (size_t) 10 * sizeof(int);
21+
}
22+
23+
// sizeof of a struct type
24+
typedef struct {
25+
int x;
26+
int y;
27+
} two_ints;
28+
29+
size_t size_of_two_ints(void)
30+
{
31+
return sizeof(two_ints);
32+
}
33+
34+
// sizeof of an array type
35+
size_t size_of_int_array(void)
36+
{
37+
return sizeof(int[8]);
38+
}
39+
40+
// Cast sizeof to a narrower integer type (exercises the new SizeT -> Int cast).
41+
uint32_t size_of_int_u32(void)
42+
{
43+
return (uint32_t) sizeof(int);
44+
}
45+
46+
// _Alignof of a builtin type
47+
size_t align_of_int(void)
48+
{
49+
return _Alignof(int);
50+
}
51+

0 commit comments

Comments
 (0)