2525#include < cxx/const_expression_evaluator.h>
2626#include < cxx/control.h>
2727#include < cxx/literals.h>
28+ #include < cxx/memory_layout.h>
2829#include < cxx/name_lookup.h>
2930#include < cxx/name_printer.h>
3031#include < cxx/names.h>
3435#include < cxx/token.h>
3536#include < cxx/type_printer.h>
3637#include < cxx/types.h>
38+ #include < cxx/util.h>
3739#include < cxx/views/symbol_chain.h>
3840
3941#include < algorithm>
4244#include < ranges>
4345#include < unordered_set>
4446
45- #include " cxx/cxx_fwd.h"
46- #include " cxx/parser_fwd.h"
47- #include " cxx/source_location.h"
48- #include " cxx/symbols_fwd.h"
49- #include " cxx/token_fwd.h"
50-
5147namespace cxx {
5248
5349namespace {
@@ -2652,6 +2648,17 @@ auto Parser::parse_builtin_offsetof_expression(ExpressionAST*& yyast,
26522648 parse_expression (ast->expression , ctx);
26532649 expect (TokenKind::T_RPAREN, ast->rparenLoc );
26542650
2651+ auto classType = type_cast<ClassType>(ast->typeId ->type );
2652+ auto id = ast_cast<IdExpressionAST>(ast->expression );
2653+
2654+ if (classType && id && !id->nestedNameSpecifier ) {
2655+ auto symbol = classType->symbol ();
2656+ auto name = convertName (id->unqualifiedId );
2657+ auto member = Lookup{scope_}.qualifiedLookup (symbol->scope (), name);
2658+ auto field = symbol_cast<FieldSymbol>(member);
2659+ ast->symbol = field;
2660+ }
2661+
26552662 return true ;
26562663}
26572664
@@ -5631,7 +5638,10 @@ auto Parser::parse_defining_type_specifier(
56315638 if (parse_enum_specifier (yyast, specs)) {
56325639 lookahead.commit ();
56335640
5641+ auto enumSpec = ast_cast<EnumSpecifierAST>(yyast);
5642+
56345643 specs.setTypeSpecifier (yyast);
5644+ specs.type = enumSpec->symbol ->type ();
56355645
56365646 return true ;
56375647 }
@@ -5641,6 +5651,7 @@ auto Parser::parse_defining_type_specifier(
56415651 lookahead.commit ();
56425652
56435653 specs.setTypeSpecifier (classSpecifier);
5654+ specs.type = classSpecifier->symbol ->type ();
56445655 yyast = classSpecifier;
56455656
56465657 return true ;
@@ -6867,6 +6878,7 @@ auto Parser::parse_elaborated_type_specifier(
68676878 }
68686879
68696880 ast->symbol = classSymbol;
6881+ specs.type = classSymbol->type ();
68706882
68716883 return true ;
68726884}
@@ -7971,6 +7983,7 @@ auto Parser::parse_enum_specifier(SpecifierAST*& yyast, DeclSpecs& specs)
79717983 ast->colonLoc = colonLoc;
79727984 ast->typeSpecifierList = typeSpecifierList;
79737985 ast->lbraceLoc = lbraceLoc;
7986+ ast->symbol = symbol;
79747987
79757988 if (!match (TokenKind::T_RBRACE, ast->rbraceLoc )) {
79767989 parse_enumerator_list (ast->enumeratorList , symbol->type ());
@@ -9416,7 +9429,69 @@ auto Parser::parse_class_specifier(
94169429 expect (TokenKind::T_RBRACE, ast->rbraceLoc );
94179430 }
94189431
9419- ast->symbol ->setComplete (true );
9432+ if (!is_template (classSymbol)) {
9433+ int offset = 0 ;
9434+ int alignment = 1 ;
9435+
9436+ for (auto base : classSymbol->baseClasses ()) {
9437+ auto baseClassSymbol = symbol_cast<ClassSymbol>(base->symbol ());
9438+
9439+ if (!baseClassSymbol) {
9440+ if (config_.checkTypes ) {
9441+ parse_error (base->location (), std::format (" base class '{}' not found" ,
9442+ to_string (base->name ())));
9443+ }
9444+ continue ;
9445+ }
9446+
9447+ offset = align_to (offset, baseClassSymbol->alignment ());
9448+ offset += baseClassSymbol->sizeInBytes ();
9449+ alignment = std::max (alignment, baseClassSymbol->alignment ());
9450+ }
9451+
9452+ for (auto member : classSymbol->scope ()->symbols ()) {
9453+ auto field = symbol_cast<FieldSymbol>(member);
9454+ if (!field) continue ;
9455+ if (field->isStatic ()) continue ;
9456+
9457+ if (!field->alignment ()) {
9458+ if (config_.checkTypes ) {
9459+ parse_error (field->location (),
9460+ std::format (" alignment of incomplete type '{}'" ,
9461+ to_string (field->type (), field->name ())));
9462+ }
9463+ continue ;
9464+ }
9465+
9466+ auto size = control_->memoryLayout ()->sizeOf (field->type ());
9467+
9468+ if (!size.has_value ()) {
9469+ if (config_.checkTypes ) {
9470+ parse_error (field->location (),
9471+ std::format (" size of incomplete type '{}'" ,
9472+ to_string (field->type (), field->name ())));
9473+ }
9474+ continue ;
9475+ }
9476+
9477+ if (classSymbol->isUnion ()) {
9478+ offset = std::max (offset, int (size.value ()));
9479+ } else {
9480+ offset = align_to (offset, field->alignment ());
9481+ field->setOffset (offset);
9482+ offset += size.value ();
9483+ }
9484+
9485+ alignment = std::max (alignment, field->alignment ());
9486+ }
9487+
9488+ offset = align_to (offset, alignment);
9489+
9490+ classSymbol->setAlignment (alignment);
9491+ classSymbol->setSizeInBytes (offset);
9492+ }
9493+
9494+ classSymbol->setComplete (true );
94209495
94219496 return true ;
94229497}
@@ -9798,6 +9873,9 @@ auto Parser::declareField(DeclaratorAST* declarator, const Decl& decl)
97989873 applySpecifiers (fieldSymbol, decl.specs );
97999874 fieldSymbol->setName (name);
98009875 fieldSymbol->setType (type);
9876+ if (auto alignment = control_->memoryLayout ()->alignmentOf (type)) {
9877+ fieldSymbol->setAlignment (alignment.value ());
9878+ }
98019879 scope_->addSymbol (fieldSymbol);
98029880 return fieldSymbol;
98039881}
0 commit comments