Commit 7a3ea201 by Richard Henderson

c-parse.in (OFFSETOF, [...]): New.

        * c-parse.in (OFFSETOF, offsetof_member_designator): New.
        (primary): Handle offsetof.  Add error productions for faux functions.
        Move component_ref objc checking to build_component_ref.
        (reswords): Add offsetof.
        (rid_to_yy): Add offsetof.
        * c-tree.h (build_offsetof): Declare.
        * c-common.h (objc_is_public): Declare.
        * c-typeck.c (build_component_ref): Check objc_is_public.
        (build_offsetof): New.
        * stub-objc.c (objc_is_public): New.
        * objc/objc-act.c, objc/objc-act.h (objc_is_public): Rename
        from is_public.
        * ginclude/stddef.h (offsetof): Use __builtin_offsetof.
        * doc/extend.texi (Offsetof): Move from C++ section to C section
        and rewrite for __builtin_offsetof.
cp/
        * lex.c (reswords): Rename "__offsetof" to "__builtin_offsetof".
        * parser.c (struct cp_parser): Remove in_offsetof.
        (cp_parser_new): Don't set it.
        (cp_parser_unary_expression): Don't check it.
        (cp_parser_postfix_open_square_expression): Split out from ...
        (cp_parser_postfix_expression): ... here.
        (cp_parser_postfix_dot_deref_expression): Likewise.
        (cp_parser_builtin_offsetof): New.
        (cp_parser_primary_expression): Use it.
testsuite/
        * g++.dg/template/dependent-expr4.C: Use __builtin_offsetof.

From-SVN: r82549
parent c4ec6988
2004-06-01 Richard Henderson <rth@redhat.com>
Andrew Pinski <pinskia@physics.uc.edu>
* c-parse.in (OFFSETOF, offsetof_member_designator): New.
(primary): Handle offsetof. Add error productions for faux functions.
Move component_ref objc checking to build_component_ref.
(reswords): Add offsetof.
(rid_to_yy): Add offsetof.
* c-tree.h (build_offsetof): Declare.
* c-common.h (objc_is_public): Declare.
* c-typeck.c (build_component_ref): Check objc_is_public.
(build_offsetof): New.
* stub-objc.c (objc_is_public): New.
* objc/objc-act.c, objc/objc-act.h (objc_is_public): Rename
from is_public.
* ginclude/stddef.h (offsetof): Use __builtin_offsetof.
* doc/extend.texi (Offsetof): Move from C++ section to C section
and rewrite for __builtin_offsetof.
2004-06-01 Peter Barada <peter@the-baradas.com> 2004-06-01 Peter Barada <peter@the-baradas.com>
Peter Jakubek <peter@laseranimation.com> Peter Jakubek <peter@laseranimation.com>
......
...@@ -1236,6 +1236,7 @@ extern tree objc_message_selector (void); ...@@ -1236,6 +1236,7 @@ extern tree objc_message_selector (void);
extern tree lookup_objc_ivar (tree); extern tree lookup_objc_ivar (tree);
extern void *get_current_scope (void); extern void *get_current_scope (void);
extern void objc_mark_locals_volatile (void *); extern void objc_mark_locals_volatile (void *);
extern int objc_is_public (tree, tree);
/* In c-ppoutput.c */ /* In c-ppoutput.c */
extern void init_pp_output (FILE *); extern void init_pp_output (FILE *);
......
...@@ -146,7 +146,7 @@ do { \ ...@@ -146,7 +146,7 @@ do { \
%token ATTRIBUTE EXTENSION LABEL %token ATTRIBUTE EXTENSION LABEL
%token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P %token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P
%token PTR_VALUE PTR_BASE PTR_EXTENT %token PTR_VALUE PTR_BASE PTR_EXTENT
%token FUNC_NAME %token FUNC_NAME OFFSETOF
/* Add precedence rules to solve dangling else s/r conflict */ /* Add precedence rules to solve dangling else s/r conflict */
%nonassoc IF %nonassoc IF
...@@ -199,6 +199,7 @@ do { \ ...@@ -199,6 +199,7 @@ do { \
%type <ttype> maybe_type_quals_attrs typespec_nonattr typespec_attr %type <ttype> maybe_type_quals_attrs typespec_nonattr typespec_attr
%type <ttype> typespec_reserved_nonattr typespec_reserved_attr %type <ttype> typespec_reserved_nonattr typespec_reserved_attr
%type <ttype> typespec_nonreserved_nonattr %type <ttype> typespec_nonreserved_nonattr
%type <ttype> offsetof_member_designator
%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_volatile %type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_volatile
%type <ttype> initdecls notype_initdecls initdcl notype_initdcl init %type <ttype> initdecls notype_initdecls initdcl notype_initdcl init
...@@ -674,17 +675,25 @@ primary: ...@@ -674,17 +675,25 @@ primary:
| VA_ARG '(' expr_no_commas ',' typename ')' | VA_ARG '(' expr_no_commas ',' typename ')'
{ $$ = build_va_arg ($3, groktypename ($5)); } { $$ = build_va_arg ($3, groktypename ($5)); }
| CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ',' expr_no_commas ')' | OFFSETOF '(' typename ',' offsetof_member_designator ')'
{ $$ = build_offsetof (groktypename ($3), $5); }
| OFFSETOF '(' error ')'
{ $$ = error_mark_node; }
| CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ','
expr_no_commas ')'
{ {
tree c; tree c;
c = fold ($3); c = fold ($3);
STRIP_NOPS (c); STRIP_NOPS (c);
if (TREE_CODE (c) != INTEGER_CST) if (TREE_CODE (c) != INTEGER_CST)
error ("first argument to __builtin_choose_expr not a constant"); error ("first argument to __builtin_choose_expr not"
" a constant");
$$ = integer_zerop (c) ? $7 : $5; $$ = integer_zerop (c) ? $7 : $5;
} }
| TYPES_COMPATIBLE_P '(' typename ',' typename ')' | CHOOSE_EXPR '(' error ')'
{ $$ = error_mark_node; }
| TYPES_COMPATIBLE_P '(' typename ',' typename ')'
{ {
tree e1, e2; tree e1, e2;
...@@ -694,27 +703,16 @@ primary: ...@@ -694,27 +703,16 @@ primary:
$$ = comptypes (e1, e2, COMPARE_STRICT) $$ = comptypes (e1, e2, COMPARE_STRICT)
? build_int_2 (1, 0) : build_int_2 (0, 0); ? build_int_2 (1, 0) : build_int_2 (0, 0);
} }
| TYPES_COMPATIBLE_P '(' error ')'
{ $$ = error_mark_node; }
| primary '[' expr ']' %prec '.' | primary '[' expr ']' %prec '.'
{ $$ = build_array_ref ($1, $3); } { $$ = build_array_ref ($1, $3); }
| primary '.' identifier | primary '.' identifier
{ { $$ = build_component_ref ($1, $3); }
@@ifobjc
if (!is_public ($1, $3))
$$ = error_mark_node;
else
@@end_ifobjc
$$ = build_component_ref ($1, $3);
}
| primary POINTSAT identifier | primary POINTSAT identifier
{ {
tree expr = build_indirect_ref ($1, "->"); tree expr = build_indirect_ref ($1, "->");
$$ = build_component_ref (expr, $3);
@@ifobjc
if (!is_public (expr, $3))
$$ = error_mark_node;
else
@@end_ifobjc
$$ = build_component_ref (expr, $3);
} }
| primary PLUSPLUS | primary PLUSPLUS
{ $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); } { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
...@@ -734,6 +732,21 @@ primary: ...@@ -734,6 +732,21 @@ primary:
@@end_ifobjc @@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:
/* empty */ /* empty */
| datadecls | datadecls
...@@ -3273,6 +3286,7 @@ static const struct resword reswords[] = ...@@ -3273,6 +3286,7 @@ static const struct resword reswords[] =
{ "__attribute", RID_ATTRIBUTE, 0 }, { "__attribute", RID_ATTRIBUTE, 0 },
{ "__attribute__", RID_ATTRIBUTE, 0 }, { "__attribute__", RID_ATTRIBUTE, 0 },
{ "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 }, { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
{ "__builtin_offsetof", RID_OFFSETOF, 0 },
{ "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 }, { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 },
{ "__builtin_va_arg", RID_VA_ARG, 0 }, { "__builtin_va_arg", RID_VA_ARG, 0 },
{ "__complex", RID_COMPLEX, 0 }, { "__complex", RID_COMPLEX, 0 },
...@@ -3469,7 +3483,7 @@ static const short rid_to_yy[RID_MAX] = ...@@ -3469,7 +3483,7 @@ static const short rid_to_yy[RID_MAX] =
/* RID_FALSE */ 0, /* RID_FALSE */ 0,
/* RID_NAMESPACE */ 0, /* RID_NAMESPACE */ 0,
/* RID_NEW */ 0, /* RID_NEW */ 0,
/* RID_OFFSETOF */ 0, /* RID_OFFSETOF */ OFFSETOF,
/* RID_OPERATOR */ 0, /* RID_OPERATOR */ 0,
/* RID_THIS */ 0, /* RID_THIS */ 0,
/* RID_THROW */ 0, /* RID_THROW */ 0,
......
...@@ -258,6 +258,7 @@ extern tree build_asm_expr (tree, tree, tree, tree, bool); ...@@ -258,6 +258,7 @@ extern tree build_asm_expr (tree, tree, tree, tree, bool);
extern tree build_asm_stmt (tree, tree); extern tree build_asm_stmt (tree, tree);
extern tree c_convert_parm_for_inlining (tree, tree, tree, int); extern tree c_convert_parm_for_inlining (tree, tree, tree, int);
extern int c_types_compatible_p (tree, tree); extern int c_types_compatible_p (tree, tree);
extern tree build_offsetof (tree, tree);
/* Set to 0 at beginning of a function definition, set to 1 if /* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */ a return statement that specifies a return value is seen. */
......
...@@ -1347,6 +1347,9 @@ build_component_ref (tree datum, tree component) ...@@ -1347,6 +1347,9 @@ build_component_ref (tree datum, tree component)
tree field = NULL; tree field = NULL;
tree ref; tree ref;
if (!objc_is_public (datum, component))
return error_mark_node;
/* If DATUM is a COMPOUND_EXPR, move our reference inside it. /* If DATUM is a COMPOUND_EXPR, move our reference inside it.
Ensure that the arguments are not lvalues; otherwise, Ensure that the arguments are not lvalues; otherwise,
if the component is an array, it would wrongly decay to a pointer in if the component is an array, it would wrongly decay to a pointer in
...@@ -7114,3 +7117,30 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, ...@@ -7114,3 +7117,30 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
} }
} }
/* 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);
}
2004-06-01 Richard Henderson <rth@redhat.com>
Andrew Pinski <pinskia@physics.uc.edu>
* lex.c (reswords): Rename "__offsetof" to "__builtin_offsetof".
* parser.c (struct cp_parser): Remove in_offsetof.
(cp_parser_new): Don't set it.
(cp_parser_unary_expression): Don't check it.
(cp_parser_postfix_open_square_expression): Split out from ...
(cp_parser_postfix_expression): ... here.
(cp_parser_postfix_dot_deref_expression): Likewise.
(cp_parser_builtin_offsetof): New.
(cp_parser_primary_expression): Use it.
2004-06-01 Giovanni Bajo <giovannibajo@gcc.gnu.org> 2004-06-01 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/14932 PR c++/14932
......
...@@ -253,6 +253,7 @@ static const struct resword reswords[] = ...@@ -253,6 +253,7 @@ static const struct resword reswords[] =
{ "__asm__", RID_ASM, 0 }, { "__asm__", RID_ASM, 0 },
{ "__attribute", RID_ATTRIBUTE, 0 }, { "__attribute", RID_ATTRIBUTE, 0 },
{ "__attribute__", RID_ATTRIBUTE, 0 }, { "__attribute__", RID_ATTRIBUTE, 0 },
{ "__builtin_offsetof", RID_OFFSETOF, 0 },
{ "__builtin_va_arg", RID_VA_ARG, 0 }, { "__builtin_va_arg", RID_VA_ARG, 0 },
{ "__complex", RID_COMPLEX, 0 }, { "__complex", RID_COMPLEX, 0 },
{ "__complex__", RID_COMPLEX, 0 }, { "__complex__", RID_COMPLEX, 0 },
...@@ -266,8 +267,6 @@ static const struct resword reswords[] = ...@@ -266,8 +267,6 @@ static const struct resword reswords[] =
{ "__inline__", RID_INLINE, 0 }, { "__inline__", RID_INLINE, 0 },
{ "__label__", RID_LABEL, 0 }, { "__label__", RID_LABEL, 0 },
{ "__null", RID_NULL, 0 }, { "__null", RID_NULL, 0 },
{ "__offsetof", RID_OFFSETOF, 0 },
{ "__offsetof__", RID_OFFSETOF, 0 },
{ "__real", RID_REALPART, 0 }, { "__real", RID_REALPART, 0 },
{ "__real__", RID_REALPART, 0 }, { "__real__", RID_REALPART, 0 },
{ "__restrict", RID_RESTRICT, 0 }, { "__restrict", RID_RESTRICT, 0 },
......
...@@ -469,6 +469,7 @@ extensions, accepted by GCC in C89 mode and in C++. ...@@ -469,6 +469,7 @@ extensions, accepted by GCC in C89 mode and in C++.
function. function.
* Return Address:: Getting the return or frame address of a function. * Return Address:: Getting the return or frame address of a function.
* Vector Extensions:: Using vector instructions through built-in functions. * Vector Extensions:: Using vector instructions through built-in functions.
* Offsetof:: Special syntax for implementing @code{offsetof}.
* Other Builtins:: Other built-in functions. * Other Builtins:: Other built-in functions.
* Target Builtins:: Built-in functions specific to particular targets. * Target Builtins:: Built-in functions specific to particular targets.
* Pragmas:: Pragmas accepted by GCC. * Pragmas:: Pragmas accepted by GCC.
...@@ -4704,6 +4705,33 @@ v4si f (v4si a, v4si b, v4si c) ...@@ -4704,6 +4705,33 @@ v4si f (v4si a, v4si b, v4si c)
@end smallexample @end smallexample
@node Offsetof
@section Offsetof
@findex __builtin_offsetof
GCC implements for both C and C++ a syntactic extension to implement
the @code{offsetof} macro.
@smallexample
primary:
"__builtin_offsetof" "(" @code{typename} "," offsetof_member_designator ")"
offsetof_member_designator:
@code{identifier}
| offsetof_member_designator "." @code{identifier}
| offsetof_member_designator "[" @code{expr} "]"
@end smallexample
This extension is sufficient such that
@smallexample
#define offsetof(@var{type}, @var{member}) __builtin_offsetof (@var{type}, @var{member})
@end smallexample
is a suitable definition of the @code{offsetof} macro. In C++, @var{type}
may be dependent. In either case, @var{member} may consist of a single
identifier, or a sequence of member accesses and array references.
@node Other Builtins @node Other Builtins
@section Other built-in functions provided by GCC @section Other built-in functions provided by GCC
@cindex built-in functions @cindex built-in functions
...@@ -7620,7 +7648,6 @@ Predefined Macros,cpp,The GNU C Preprocessor}). ...@@ -7620,7 +7648,6 @@ Predefined Macros,cpp,The GNU C Preprocessor}).
method denoted by a @samp{->*} or @samp{.*} expression. method denoted by a @samp{->*} or @samp{.*} expression.
* C++ Attributes:: Variable, function, and type attributes for C++ only. * C++ Attributes:: Variable, function, and type attributes for C++ only.
* Strong Using:: Strong using-directives for namespace composition. * Strong Using:: Strong using-directives for namespace composition.
* Offsetof:: Special syntax for implementing @code{offsetof}.
* Java Exceptions:: Tweaking exception handling to work with Java. * Java Exceptions:: Tweaking exception handling to work with Java.
* Deprecated Features:: Things will disappear from g++. * Deprecated Features:: Things will disappear from g++.
* Backwards Compatibility:: Compatibilities with earlier definitions of C++. * Backwards Compatibility:: Compatibilities with earlier definitions of C++.
...@@ -8265,25 +8292,6 @@ int main() ...@@ -8265,25 +8292,6 @@ int main()
@} @}
@end smallexample @end smallexample
@node Offsetof
@section Offsetof
G++ uses a syntactic extension to implement the @code{offsetof} macro.
In particular:
@smallexample
__offsetof__ (expression)
@end smallexample
is equivalent to the parenthesized expression, except that the
expression is considered an integral constant expression even if it
contains certain operators that are not normally permitted in an
integral constant expression. Users should never use
@code{__offsetof__} directly; the only valid use of
@code{__offsetof__} is to implement the @code{offsetof} macro in
@code{<stddef.h>}.
@node Java Exceptions @node Java Exceptions
@section Java Exceptions @section Java Exceptions
......
/* Copyright (C) 1989, 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. /* Copyright (C) 1989, 1997, 1998, 1999, 2000, 2002, 2004
Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -410,16 +411,8 @@ typedef __WINT_TYPE__ wint_t; ...@@ -410,16 +411,8 @@ typedef __WINT_TYPE__ wint_t;
#ifdef _STDDEF_H #ifdef _STDDEF_H
/* Offset of member MEMBER in a struct of type TYPE. */ /* Offset of member MEMBER in a struct of type TYPE. */
#ifndef __cplusplus #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else
/* The cast to "char &" below avoids problems with user-defined
"operator &", which can appear in a POD type. */
#define offsetof(TYPE, MEMBER) \
(__offsetof__ (reinterpret_cast <size_t> \
(&reinterpret_cast <char &> \
(static_cast<TYPE *> (0)->MEMBER))))
#endif /* C++ */
#endif /* _STDDEF_H was defined this time */ #endif /* _STDDEF_H was defined this time */
#endif /* !_STDDEF_H && !_STDDEF_H_ && !_ANSI_STDDEF_H && !__STDDEF_H__ #endif /* !_STDDEF_H && !_STDDEF_H_ && !_ANSI_STDDEF_H && !__STDDEF_H__
......
...@@ -6475,7 +6475,7 @@ is_private (tree decl) ...@@ -6475,7 +6475,7 @@ is_private (tree decl)
/* We have an instance variable reference;, check to see if it is public. */ /* We have an instance variable reference;, check to see if it is public. */
int int
is_public (tree expr, tree identifier) objc_is_public (tree expr, tree identifier)
{ {
tree basetype = TREE_TYPE (expr); tree basetype = TREE_TYPE (expr);
enum tree_code code = TREE_CODE (basetype); enum tree_code code = TREE_CODE (basetype);
......
...@@ -52,7 +52,7 @@ tree objc_build_finally_epilogue (void); ...@@ -52,7 +52,7 @@ tree objc_build_finally_epilogue (void);
tree is_ivar (tree, tree); tree is_ivar (tree, tree);
int is_private (tree); int is_private (tree);
int is_public (tree, tree); int objc_is_public (tree, tree);
tree add_instance_variable (tree, int, tree, tree, tree); tree add_instance_variable (tree, int, tree, tree, tree);
tree objc_add_method (tree, tree, int); tree objc_add_method (tree, tree, int);
tree get_super_receiver (void); tree get_super_receiver (void);
...@@ -126,7 +126,7 @@ tree build_encode_expr (tree); ...@@ -126,7 +126,7 @@ tree build_encode_expr (tree);
? (TYPE)->type.context : NULL_TREE) ? (TYPE)->type.context : NULL_TREE)
#define SET_TYPE_PROTOCOL_LIST(TYPE, P) (TYPE_CHECK (TYPE)->type.context = (P)) #define SET_TYPE_PROTOCOL_LIST(TYPE, P) (TYPE_CHECK (TYPE)->type.context = (P))
/* Set by `continue_class' and checked by `is_public'. */ /* Set by `continue_class' and checked by `objc_is_public'. */
#define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type)) #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
#define TYPED_OBJECT(type) \ #define TYPED_OBJECT(type) \
......
...@@ -69,3 +69,8 @@ objc_message_selector (void) ...@@ -69,3 +69,8 @@ objc_message_selector (void)
return 0; return 0;
} }
int
objc_is_public (tree expr ATTRIBUTE_UNUSED, tree identifier ATTRIBUTE_UNUSED)
{
return 1;
}
2004-06-01 Richard Hederson <rth@redhat.com>
* g++.dg/template/dependent-expr4.C: Use __builtin_offsetof.
2004-06-01 Giovanni Bajo <giovannibajo@gcc.gnu.org> 2004-06-01 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/14932 PR c++/14932
......
// { dg-do compile } // { dg-do compile }
// Origin: jbrandmeyer at users dot sourceforge dot net // Origin: jbrandmeyer at users dot sourceforge dot net
// PR c++/12573: COMPONENT_REFs must be inspected for dependness. // PR c++/12573: COMPONENT_REFs must be inspected for dependness.
// Or, more specifically OFFSETOF.
template <bool> struct S; template <bool> struct S;
...@@ -9,6 +10,6 @@ template <typename K> struct Y { ...@@ -9,6 +10,6 @@ template <typename K> struct Y {
}; };
template <class T> struct Z { template <class T> struct Z {
S< (bool)(__offsetof__(&static_cast<Y<T>*>(0)->x) == 0) > S< (bool)(__builtin_offsetof (Y<T>*, x) == 0) >
s; s;
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment