This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++ PATCH: Fix PR 13275


On Tue, Dec 16, 2003 at 04:46:51PM -0800, Zack Weinberg wrote:
> "Objected" is too strong a word.  "Would prefer __builtin_offsetof but
> is open to demonstrations that this is too hard" is more accurate.

The following patch appears to work for C.  I would recind my
earlier claim that it made the grammar too nasty.

Given this, does this seem the approach we want to take?


r~


	* c-parse.in (OFFSETOF): New.
	(primary): Add error fallbacks for function-like elements.  Add
	new productions for __builtin_addressof.  Move objc is_public
	checks to build_component_ref.
	(offsetof_member_designator): New.
	(reswords): Add __builtin_offsetof.
	(rid_to_yy): Handle RID_OFFSETOF.
	* c-tree.h (build_offsetof): Declare.
	* c-typeck.c (build_component_ref): Check objc_is_public.
	(build_offsetof): New.

	* c-common.h (objc_is_public): Declare.
	* stub-objc.c (objc_is_public): New.
	* objc/objc-act.c (objc_is_public): Rename from is_public.
	* objc/objc-act.h: Likewise.

Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.212
diff -c -p -d -r1.212 c-common.h
*** c-common.h	16 Dec 2003 16:09:03 -0000	1.212
--- c-common.h	17 Dec 2003 23:09:36 -0000
*************** extern tree objc_message_selector (void)
*** 1345,1350 ****
--- 1345,1351 ----
  extern tree lookup_objc_ivar (tree);
  extern void *get_current_scope (void);
  extern void objc_mark_locals_volatile (void *);
+ extern int objc_is_public (tree, tree);
  
  /* In c-ppoutput.c  */
  extern void init_pp_output (FILE *);
Index: c-parse.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parse.in,v
retrieving revision 1.193
diff -c -p -d -r1.193 c-parse.in
*** c-parse.in	16 Dec 2003 16:09:04 -0000	1.193
--- c-parse.in	17 Dec 2003 23:09:38 -0000
*************** do {									\
*** 145,151 ****
  %token ATTRIBUTE EXTENSION LABEL
  %token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P
  %token PTR_VALUE PTR_BASE PTR_EXTENT
! %token FUNC_NAME
  
  /* Add precedence rules to solve dangling else s/r conflict */
  %nonassoc IF
--- 145,151 ----
  %token ATTRIBUTE EXTENSION LABEL
  %token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P
  %token PTR_VALUE PTR_BASE PTR_EXTENT
! %token FUNC_NAME OFFSETOF
  
  /* Add precedence rules to solve dangling else s/r conflict */
  %nonassoc IF
*************** do {									\
*** 198,203 ****
--- 198,204 ----
  %type <ttype> maybe_type_quals_attrs typespec_nonattr typespec_attr
  %type <ttype> typespec_reserved_nonattr typespec_reserved_attr
  %type <ttype> typespec_nonreserved_nonattr
+ %type <ttype> offsetof_member_designator
  
  %type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_type_qual
  %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
*************** static int compstmt_count;
*** 261,267 ****
     used by the stmt-rule immediately after simple_if returns.  */
  static location_t if_stmt_locus;
  
- 
  /* List of types and structure classes of the current declaration.  */
  static GTY(()) tree current_declspecs;
  static GTY(()) tree prefix_attributes;
--- 262,267 ----
*************** primary:
*** 687,704 ****
  		{ $$ = build_function_call ($1, $3); }
  	| VA_ARG '(' expr_no_commas ',' typename ')'
  		{ $$ = build_va_arg ($3, groktypename ($5)); }
! 
!       | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ',' expr_no_commas ')'
  		{
                    tree c;
  
                    c = fold ($3);
                    STRIP_NOPS (c);
                    if (TREE_CODE (c) != INTEGER_CST)
!                     error ("first argument to __builtin_choose_expr not a constant");
                    $$ = integer_zerop (c) ? $7 : $5;
  		}
!       | TYPES_COMPATIBLE_P '(' typename ',' typename ')'
  		{
  		  tree e1, e2;
  
--- 687,713 ----
  		{ $$ = build_function_call ($1, $3); }
  	| VA_ARG '(' expr_no_commas ',' typename ')'
  		{ $$ = build_va_arg ($3, groktypename ($5)); }
! 	| VA_ARG '(' error ')'
! 		{ $$ = error_mark_node; }
! 	| OFFSETOF '(' typespec_nonattr ',' offsetof_member_designator ')'
! 		{ $$ = build_offsetof ($3, $5); }
! 	| OFFSETOF '(' error ')'
! 		{ $$ = error_mark_node; }
! 	| CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ','
! 			  expr_no_commas ')'
  		{
                    tree c;
  
                    c = fold ($3);
                    STRIP_NOPS (c);
                    if (TREE_CODE (c) != INTEGER_CST)
!                     error ("first argument to __builtin_choose_expr not"
! 			   " a constant");
                    $$ = integer_zerop (c) ? $7 : $5;
  		}
! 	| CHOOSE_EXPR '(' error ')'
! 		{ $$ = error_mark_node; }
! 	| TYPES_COMPATIBLE_P '(' typename ',' typename ')'
  		{
  		  tree e1, e2;
  
*************** primary:
*** 708,734 ****
  		  $$ = comptypes (e1, e2, COMPARE_STRICT)
  		    ? build_int_2 (1, 0) : build_int_2 (0, 0);
  		}
  	| primary '[' expr ']'   %prec '.'
  		{ $$ = build_array_ref ($1, $3); }
  	| primary '.' identifier
! 		{
! @@ifobjc
! 		    if (!is_public ($1, $3))
! 		      $$ = error_mark_node;
! 		    else
! @@end_ifobjc
! 		      $$ = build_component_ref ($1, $3);
! 		}
  	| primary POINTSAT identifier
  		{
                    tree expr = build_indirect_ref ($1, "->");
! 
! @@ifobjc
! 		      if (!is_public (expr, $3))
! 			$$ = error_mark_node;
! 		      else
! @@end_ifobjc
! 			$$ = build_component_ref (expr, $3);
  		}
  	| primary PLUSPLUS
  		{ $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
--- 717,732 ----
  		  $$ = comptypes (e1, e2, COMPARE_STRICT)
  		    ? build_int_2 (1, 0) : build_int_2 (0, 0);
  		}
+ 	| TYPES_COMPATIBLE_P '(' error ')'
+ 		{ $$ = error_mark_node; }
  	| primary '[' expr ']'   %prec '.'
  		{ $$ = build_array_ref ($1, $3); }
  	| primary '.' identifier
! 		{ $$ = build_component_ref ($1, $3); }
  	| primary POINTSAT identifier
  		{
                    tree expr = build_indirect_ref ($1, "->");
! 		  $$ = build_component_ref (expr, $3);
  		}
  	| primary PLUSPLUS
  		{ $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
*************** primary:
*** 748,753 ****
--- 746,766 ----
  @@end_ifobjc
  	;
  
+ /* This is the second argument to __builtin_offsetof.  We must have one
+    identifier, and beyond that we want to accept sub structure and sub
+    array references.  We return tree list where each element has
+    PURPOSE set for component refs or VALUE set for array refs.  We'll
+    turn this into something real inside build_offsetof.  */
+ 
+ offsetof_member_designator:
+ 	  identifier
+ 		{ $$ = tree_cons ($1, NULL_TREE, NULL_TREE); }
+ 	| offsetof_member_designator '.' identifier
+ 		{ $$ = tree_cons ($3, NULL_TREE, $1); }
+ 	| offsetof_member_designator '[' expr ']'
+ 		{ $$ = tree_cons (NULL_TREE, $3, $1); }
+ 	;
+ 
  old_style_parm_decls:
  	old_style_parm_decls_1
  	{
*************** static const struct resword reswords[] =
*** 3288,3293 ****
--- 3301,3307 ----
    { "__attribute",	RID_ATTRIBUTE,	0 },
    { "__attribute__",	RID_ATTRIBUTE,	0 },
    { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
+   { "__builtin_offsetof", RID_OFFSETOF, 0 },
    { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 },
    { "__builtin_va_arg",	RID_VA_ARG,	0 },
    { "__complex",	RID_COMPLEX,	0 },
*************** static const short rid_to_yy[RID_MAX] =
*** 3484,3490 ****
    /* RID_FALSE */	0,
    /* RID_NAMESPACE */	0,
    /* RID_NEW */		0,
!   /* RID_OFFSETOF */    0,
    /* RID_OPERATOR */	0,
    /* RID_THIS */	0,
    /* RID_THROW */	0,
--- 3498,3504 ----
    /* RID_FALSE */	0,
    /* RID_NAMESPACE */	0,
    /* RID_NEW */		0,
!   /* RID_OFFSETOF */    OFFSETOF,
    /* RID_OPERATOR */	0,
    /* RID_THIS */	0,
    /* RID_THROW */	0,
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.136
diff -c -p -d -r1.136 c-tree.h
*** c-tree.h	3 Dec 2003 23:33:48 -0000	1.136
--- c-tree.h	17 Dec 2003 23:09:39 -0000
*************** extern void c_finish_case (void);
*** 293,298 ****
--- 293,299 ----
  extern tree simple_asm_stmt (tree);
  extern tree build_asm_stmt (tree, tree, tree, tree, tree);
  extern tree c_convert_parm_for_inlining (tree, tree, tree, int);
+ extern tree build_offsetof (tree, tree);
  
  /* Set to 0 at beginning of a function definition, set to 1 if
     a return statement that specifies a return value is seen.  */
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.265
diff -c -p -d -r1.265 c-typeck.c
*** c-typeck.c	13 Dec 2003 04:11:19 -0000	1.265
--- c-typeck.c	17 Dec 2003 23:09:44 -0000
*************** build_component_ref (tree datum, tree co
*** 1301,1306 ****
--- 1301,1309 ----
    tree field = NULL;
    tree ref;
  
+   if (!objc_is_public (datum, component))
+     return error_mark_node;
+ 
    /* If DATUM is a COMPOUND_EXPR, move our reference inside it.
       If pedantic ensure that the arguments are not lvalues; otherwise,
       if the component is an array, it would wrongly decay to a pointer in
*************** build_binary_op (enum tree_code code, tr
*** 7215,7217 ****
--- 7218,7247 ----
    }
  }
  
+ /* Build the result of __builtin_offsetof.  TYPE is the first argument to
+    offsetof, i.e. a type.  LIST is a tree_list that encodes component and
+    array references; PURPOSE is set for the former and VALUE is set for
+    the later.  */
+ 
+ tree
+ build_offsetof (tree type, tree list)
+ {
+   tree t;
+ 
+   /* Build "*(type *)0".  */
+   t = convert (build_pointer_type (type), null_pointer_node);
+   t = build_indirect_ref (t, "");
+ 
+   /* Build COMPONENT and ARRAY_REF expressions as needed.  */
+   for (list = nreverse (list); list ; list = TREE_CHAIN (list))
+     if (TREE_PURPOSE (list))
+       t = build_component_ref (t, TREE_PURPOSE (list));
+     else
+       t = build_array_ref (t, TREE_VALUE (list));
+ 
+   /* Finalize the offsetof expression.  For now all we need to do is take
+      the address of the expression we created, and cast that to an integer
+      type; this mirrors the traditional macro implementation of offsetof.  */
+   t = build_unary_op (ADDR_EXPR, t, 0);
+   return convert (size_type_node, t);
+ }
Index: stub-objc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stub-objc.c,v
retrieving revision 2.1
diff -c -p -d -r2.1 stub-objc.c
*** stub-objc.c	25 Sep 2003 01:25:50 -0000	2.1
--- stub-objc.c	17 Dec 2003 23:09:45 -0000
*************** objc_message_selector (void)
*** 69,71 ****
--- 69,76 ----
    return 0;
  }
  
+ int
+ objc_is_public (tree expr ATTRIBUTE_UNUSED, tree identifier ATTRIBUTE_UNUSED)
+ {
+   return 1;
+ }
Index: objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.202
diff -c -p -d -r1.202 objc-act.c
*** objc/objc-act.c	13 Dec 2003 00:23:51 -0000	1.202
--- objc/objc-act.c	17 Dec 2003 23:09:51 -0000
*************** is_private (tree decl)
*** 6501,6507 ****
  /* We have an instance variable reference;, check to see if it is public.  */
  
  int
! is_public (tree expr, tree identifier)
  {
    tree basetype = TREE_TYPE (expr);
    enum tree_code code = TREE_CODE (basetype);
--- 6501,6507 ----
  /* We have an instance variable reference;, check to see if it is public.  */
  
  int
! objc_is_public (tree expr, tree identifier)
  {
    tree basetype = TREE_TYPE (expr);
    enum tree_code code = TREE_CODE (basetype);
Index: objc/objc-act.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.h,v
retrieving revision 1.20
diff -c -p -d -r1.20 objc-act.h
*** objc/objc-act.h	15 Oct 2003 00:10:27 -0000	1.20
--- objc/objc-act.h	17 Dec 2003 23:09:52 -0000
*************** tree objc_build_finally_epilogue (void);
*** 52,58 ****
  
  tree is_ivar (tree, tree);
  int is_private (tree);
! int is_public (tree, tree);
  tree add_instance_variable (tree, int, tree, tree, tree);
  tree objc_add_method (tree, tree, int);
  tree get_super_receiver (void);
--- 52,58 ----
  
  tree is_ivar (tree, tree);
  int is_private (tree);
! int objc_is_public (tree, tree);
  tree add_instance_variable (tree, int, tree, tree, tree);
  tree objc_add_method (tree, tree, int);
  tree get_super_receiver (void);
*************** tree build_encode_expr (tree);
*** 126,132 ****
  	 ? (TYPE)->type.context : NULL_TREE)
  #define SET_TYPE_PROTOCOL_LIST(TYPE, P) (TYPE_CHECK (TYPE)->type.context = (P))
  
! /* Set by `continue_class' and checked by `is_public'.  */
  
  #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
  #define TYPED_OBJECT(type) \
--- 126,132 ----
  	 ? (TYPE)->type.context : NULL_TREE)
  #define SET_TYPE_PROTOCOL_LIST(TYPE, P) (TYPE_CHECK (TYPE)->type.context = (P))
  
! /* Set by `continue_class' and checked by `objc_is_public'.  */
  
  #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
  #define TYPED_OBJECT(type) \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]