@@ -2118,7 +2118,7 @@ struct expression* _Owner _Opt postfix_expression_tail(struct parser_ctx* ctx, s
21182118 else
21192119 {
21202120 /* not fixed yet */
2121- /* assert(false); */
2121+ /* assert(false); */
21222122 }
21232123 }
21242124 else
@@ -2640,10 +2640,6 @@ static int check_sizeof_argument(struct parser_ctx* ctx,
26402640 const struct expression * p_expression ,
26412641 const struct type * const p_type )
26422642{
2643- //sizeof(type) p_expression is the sizeof expression
2644- //sizeof(expression) p_expression is expression
2645-
2646-
26472643 enum type_category category = type_get_category (p_type );
26482644
26492645 if (category == TYPE_CATEGORY_FUNCTION )
@@ -2900,6 +2896,46 @@ struct expression* _Owner _Opt unary_expression(struct parser_ctx* ctx, enum exp
29002896 */
29012897 new_expression -> expression_type = UNARY_EXPRESSION_ADDRESSOF ;
29022898
2899+ if (new_expression -> right -> expression_type == POSTFIX_ARROW &&
2900+ object_has_constant_value (& new_expression -> right -> left -> object ))
2901+ {
2902+ /*
2903+ offsetof pattern evaluated at compile time
2904+
2905+ Sample:
2906+ & ((struct { int i; int i2; }*)0)->i2
2907+
2908+ If the pointer has a constant value, we compute the member's
2909+ offset and then add it to that constant value that is generally zero.
2910+ */
2911+
2912+ const unsigned long long pointer_value =
2913+ object_to_unsigned_long_long (& new_expression -> right -> left -> object );
2914+
2915+ struct type struct_type = type_remove_pointer (& new_expression -> right -> left -> type );
2916+ if (type_is_struct_or_union (& struct_type ))
2917+ {
2918+ size_t offset_of ;
2919+ enum sizeof_result e =
2920+ type_get_offsetof (& struct_type ,
2921+ new_expression -> right -> last_token -> lexeme /*member identifier*/ ,
2922+ & offset_of ,
2923+ ctx -> options .target );
2924+ switch (e )
2925+ {
2926+ case SIZEOF_RESULT_OK :
2927+ new_expression -> object = object_make_size_t (ctx -> options .target , pointer_value + offset_of );
2928+ break ;
2929+ case SIZEOF_RESULT_OVERLOW :
2930+ case SIZEOF_RESULT_RUNTIME :
2931+ case SIZEOF_RESULT_INCOMPLETE :
2932+ case SIZEOF_RESULT_FUNCTION :
2933+ break ;
2934+ }
2935+ }
2936+ type_destroy (& struct_type );
2937+ }
2938+
29032939 if (!expression_is_lvalue (new_expression -> right ))
29042940 {
29052941 compiler_diagnostic (C_ERROR_ADDRESS_OF_REGISTER ,
@@ -3273,20 +3309,23 @@ struct expression* _Owner _Opt unary_expression(struct parser_ctx* ctx, enum exp
32733309 }
32743310 else
32753311 {
3276- if (type_is_vla (& new_expression -> type_name -> abstract_declarator -> type ))
3277- {
3278- /* not a constant */
3279- }
3280- else
3312+ size_t sz = 0 ;
3313+ enum sizeof_result sizeof_result =
3314+ type_get_sizeof (& new_expression -> type_name -> abstract_declarator -> type , & sz , ctx -> options .target );
3315+ switch (sizeof_result )
32813316 {
3282- size_t type_sizeof = 0 ;
3283- if ( type_get_sizeof ( & new_expression -> type_name -> abstract_declarator -> type , & type_sizeof , ctx -> options .target ) != 0 )
3284- {
3285- expression_delete ( new_expression );
3286- throw ;
3287- }
3317+ case SIZEOF_RESULT_OK :
3318+ new_expression -> object = object_make_size_t ( ctx -> options .target , sz );
3319+ break ;
3320+
3321+ case SIZEOF_RESULT_RUNTIME :
3322+ break ;
32883323
3289- new_expression -> object = object_make_size_t (ctx -> options .target , type_sizeof );
3324+ case SIZEOF_RESULT_OVERLOW :
3325+ case SIZEOF_RESULT_INCOMPLETE :
3326+ case SIZEOF_RESULT_FUNCTION :
3327+ expression_delete (new_expression );
3328+ throw ;
32903329 }
32913330 }
32923331 }
@@ -3314,12 +3353,12 @@ struct expression* _Owner _Opt unary_expression(struct parser_ctx* ctx, enum exp
33143353 switch (res )
33153354 {
33163355 case SIZEOF_RESULT_OK :
3356+ new_expression -> object = object_make_size_t (ctx -> options .target , sz3 );
33173357 break ;
3318- case SIZEOF_RESULT_OVERLOW :
3319- expression_delete (new_expression );
3320- throw ;
33213358 case SIZEOF_RESULT_RUNTIME :
33223359 break ;
3360+
3361+ case SIZEOF_RESULT_OVERLOW :
33233362 case SIZEOF_RESULT_INCOMPLETE :
33243363 expression_delete (new_expression );
33253364 throw ;
@@ -3333,15 +3372,6 @@ struct expression* _Owner _Opt unary_expression(struct parser_ctx* ctx, enum exp
33333372 "size of function" );
33343373 break ;
33353374 }
3336-
3337- if (res == SIZEOF_RESULT_RUNTIME )
3338- {
3339- /* not a constant */
3340- }
3341- else
3342- {
3343- new_expression -> object = object_make_size_t (ctx -> options .target , sz3 );
3344- }
33453375 }
33463376
33473377 type_destroy (& new_expression -> type );
0 commit comments