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,19 @@ 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+
2662+ ast->type = control_->getSizeType ();
2663+
26552664 return true ;
26562665}
26572666
@@ -5631,7 +5640,10 @@ auto Parser::parse_defining_type_specifier(
56315640 if (parse_enum_specifier (yyast, specs)) {
56325641 lookahead.commit ();
56335642
5643+ auto enumSpec = ast_cast<EnumSpecifierAST>(yyast);
5644+
56345645 specs.setTypeSpecifier (yyast);
5646+ specs.type = enumSpec->symbol ->type ();
56355647
56365648 return true ;
56375649 }
@@ -5641,6 +5653,7 @@ auto Parser::parse_defining_type_specifier(
56415653 lookahead.commit ();
56425654
56435655 specs.setTypeSpecifier (classSpecifier);
5656+ specs.type = classSpecifier->symbol ->type ();
56445657 yyast = classSpecifier;
56455658
56465659 return true ;
@@ -6867,6 +6880,7 @@ auto Parser::parse_elaborated_type_specifier(
68676880 }
68686881
68696882 ast->symbol = classSymbol;
6883+ specs.type = classSymbol->type ();
68706884
68716885 return true ;
68726886}
@@ -7971,6 +7985,7 @@ auto Parser::parse_enum_specifier(SpecifierAST*& yyast, DeclSpecs& specs)
79717985 ast->colonLoc = colonLoc;
79727986 ast->typeSpecifierList = typeSpecifierList;
79737987 ast->lbraceLoc = lbraceLoc;
7988+ ast->symbol = symbol;
79747989
79757990 if (!match (TokenKind::T_RBRACE, ast->rbraceLoc )) {
79767991 parse_enumerator_list (ast->enumeratorList , symbol->type ());
@@ -9416,7 +9431,69 @@ auto Parser::parse_class_specifier(
94169431 expect (TokenKind::T_RBRACE, ast->rbraceLoc );
94179432 }
94189433
9419- ast->symbol ->setComplete (true );
9434+ if (!is_template (classSymbol)) {
9435+ int offset = 0 ;
9436+ int alignment = 1 ;
9437+
9438+ for (auto base : classSymbol->baseClasses ()) {
9439+ auto baseClassSymbol = symbol_cast<ClassSymbol>(base->symbol ());
9440+
9441+ if (!baseClassSymbol) {
9442+ if (config_.checkTypes ) {
9443+ parse_error (base->location (), std::format (" base class '{}' not found" ,
9444+ to_string (base->name ())));
9445+ }
9446+ continue ;
9447+ }
9448+
9449+ offset = align_to (offset, baseClassSymbol->alignment ());
9450+ offset += baseClassSymbol->sizeInBytes ();
9451+ alignment = std::max (alignment, baseClassSymbol->alignment ());
9452+ }
9453+
9454+ for (auto member : classSymbol->scope ()->symbols ()) {
9455+ auto field = symbol_cast<FieldSymbol>(member);
9456+ if (!field) continue ;
9457+ if (field->isStatic ()) continue ;
9458+
9459+ if (!field->alignment ()) {
9460+ if (config_.checkTypes ) {
9461+ parse_error (field->location (),
9462+ std::format (" alignment of incomplete type '{}'" ,
9463+ to_string (field->type (), field->name ())));
9464+ }
9465+ continue ;
9466+ }
9467+
9468+ auto size = control_->memoryLayout ()->sizeOf (field->type ());
9469+
9470+ if (!size.has_value ()) {
9471+ if (config_.checkTypes ) {
9472+ parse_error (field->location (),
9473+ std::format (" size of incomplete type '{}'" ,
9474+ to_string (field->type (), field->name ())));
9475+ }
9476+ continue ;
9477+ }
9478+
9479+ if (classSymbol->isUnion ()) {
9480+ offset = std::max (offset, int (size.value ()));
9481+ } else {
9482+ offset = align_to (offset, field->alignment ());
9483+ field->setOffset (offset);
9484+ offset += size.value ();
9485+ }
9486+
9487+ alignment = std::max (alignment, field->alignment ());
9488+ }
9489+
9490+ offset = align_to (offset, alignment);
9491+
9492+ classSymbol->setAlignment (alignment);
9493+ classSymbol->setSizeInBytes (offset);
9494+ }
9495+
9496+ classSymbol->setComplete (true );
94209497
94219498 return true ;
94229499}
@@ -9798,6 +9875,9 @@ auto Parser::declareField(DeclaratorAST* declarator, const Decl& decl)
97989875 applySpecifiers (fieldSymbol, decl.specs );
97999876 fieldSymbol->setName (name);
98009877 fieldSymbol->setType (type);
9878+ if (auto alignment = control_->memoryLayout ()->alignmentOf (type)) {
9879+ fieldSymbol->setAlignment (alignment.value ());
9880+ }
98019881 scope_->addSymbol (fieldSymbol);
98029882 return fieldSymbol;
98039883}
0 commit comments