Commit 263ee052 by Mark Mitchell

re PR c++/13275 (Implementation of offsetof macro)

	PR c++/13275
	* c-common.h (enum rid): Add RID_OFFSETOF.
	* c-parser.in (rid_to_yy): Ignore RID_OFFSETOF.
	* ginclude/stddef.h (offsetof): Reimplement for C++, using
	__offsetof__.
	* doc/extend.texi: Document __offsetof__.

	PR c++/13275
	* lex.c (reswords): Add "__offsetof" and "__offsetof__".
	* parser.c (cp_parser): Add in_offsetof_p.
	(cp_parser_new): Initialize it.
	(cp_parser_primary_expression): Handle __offsetof__ (...).
	(cp_parser_postfix_expression): Allow casts to pointer type and
	uses of "->" in a constant expression if implementing offsetof.
	(cp_parser_unary_expression): Allow the use of "&" in a constant
	expression if implementing offsetof.

	PR c++/13275
	* g++.dg/other/offsetof2.C: Remove XFAIL.
	* g++.dg/parse/offsetof1.C: New test.
	* g++.gd/parse/offsetof2.C: Likewise.

From-SVN: r74702
parent ff5034c5
2003-12-16 Mark Mitchell <mark@codesourcery.com>
PR c++/13275
* c-common.h (enum rid): Add RID_OFFSETOF.
* c-parser.in (rid_to_yy): Ignore RID_OFFSETOF.
* ginclude/stddef.h (offsetof): Reimplement for C++, using
__offsetof__.
* doc/extend.texi: Document __offsetof__.
2003-12-16 Stan Cox <scox@redhat.com> 2003-12-16 Stan Cox <scox@redhat.com>
* config/iq2000/iq2000.h: Formatting. * config/iq2000/iq2000.h: Formatting.
......
...@@ -88,9 +88,10 @@ enum rid ...@@ -88,9 +88,10 @@ enum rid
RID_PUBLIC, RID_PRIVATE, RID_PROTECTED, RID_PUBLIC, RID_PRIVATE, RID_PROTECTED,
RID_TEMPLATE, RID_NULL, RID_CATCH, RID_TEMPLATE, RID_NULL, RID_CATCH,
RID_DELETE, RID_FALSE, RID_NAMESPACE, RID_DELETE, RID_FALSE, RID_NAMESPACE,
RID_NEW, RID_OPERATOR, RID_THIS, RID_NEW, RID_OFFSETOF, RID_OPERATOR,
RID_THROW, RID_TRUE, RID_TRY, RID_THIS, RID_THROW, RID_TRUE,
RID_TYPENAME, RID_TYPEID, RID_USING, RID_TRY, RID_TYPENAME, RID_TYPEID,
RID_USING,
/* casts */ /* casts */
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST, RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
......
...@@ -3484,6 +3484,7 @@ static const short rid_to_yy[RID_MAX] = ...@@ -3484,6 +3484,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_OPERATOR */ 0, /* RID_OPERATOR */ 0,
/* RID_THIS */ 0, /* RID_THIS */ 0,
/* RID_THROW */ 0, /* RID_THROW */ 0,
......
2003-12-16 Mark Mitchell <mark@codesourcery.com>
PR c++/13275
* lex.c (reswords): Add "__offsetof" and "__offsetof__".
* parser.c (cp_parser): Add in_offsetof_p.
(cp_parser_new): Initialize it.
(cp_parser_primary_expression): Handle __offsetof__ (...).
(cp_parser_postfix_expression): Allow casts to pointer type and
uses of "->" in a constant expression if implementing offsetof.
(cp_parser_unary_expression): Allow the use of "&" in a constant
expression if implementing offsetof.
2003-12-16 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/2294
* name-lookup.c (push_overloaded_decl): always construct an OVERLOAD
if the declaration comes from an using declaration.
2003-12-16 Giovanni Bajo <giovannibajo@gcc.gnu.org> 2003-12-16 Giovanni Bajo <giovannibajo@gcc.gnu.org>
* semantics.c (finish_id_expression): Refactor the code to handle * semantics.c (finish_id_expression): Refactor the code to handle
...@@ -17385,7 +17403,7 @@ ...@@ -17385,7 +17403,7 @@
* parse.y (member_init): Just pass in the type. * parse.y (member_init): Just pass in the type.
* init.c (expand_member_init): Handle getting a type. * init.c (expand_member_init): Handle getting a type.
2000-07-04 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-07-04 Martin v. Löwis <loewis@informatik.hu-berlin.de>
Jason Merrill <jason@redhat.com> Jason Merrill <jason@redhat.com>
* decl.c (finish_function): Warn if a function has no return * decl.c (finish_function): Warn if a function has no return
...@@ -17731,7 +17749,7 @@ ...@@ -17731,7 +17749,7 @@
* decl.c (pushdecl): Don't set DECL_CONTEXT from current_namespace. * decl.c (pushdecl): Don't set DECL_CONTEXT from current_namespace.
(push_namespace): Set DECL_CONTEXT for a new NAMESPACE_DECL. (push_namespace): Set DECL_CONTEXT for a new NAMESPACE_DECL.
2000-06-24 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-06-24 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* parse.y (complex_direct_notype_declarator): Support global_scope. * parse.y (complex_direct_notype_declarator): Support global_scope.
* Makefile.in: Adjust conflict count. * Makefile.in: Adjust conflict count.
...@@ -18916,7 +18934,7 @@ ...@@ -18916,7 +18934,7 @@
* semantics.c (finish_member_declaration): Don't mark members of * semantics.c (finish_member_declaration): Don't mark members of
classes declared in an extern "C" region as extern "C". classes declared in an extern "C" region as extern "C".
2000-05-22 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-05-22 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* decl2.c (qualified_lookup_using_namespace): Look through * decl2.c (qualified_lookup_using_namespace): Look through
namespace aliases. namespace aliases.
...@@ -19370,7 +19388,7 @@ ...@@ -19370,7 +19388,7 @@
* ir.texi: Correct typo. * ir.texi: Correct typo.
2000-04-25 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-04-25 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* decl.c (grokdeclarator): Reject VLAs as members. * decl.c (grokdeclarator): Reject VLAs as members.
...@@ -19669,7 +19687,7 @@ ...@@ -19669,7 +19687,7 @@
(interface_only): Don't declare. (interface_only): Don't declare.
(interface_unknown): Likewise. (interface_unknown): Likewise.
2000-04-11 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-04-11 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* tree.h (HAVE_TEMPLATES): Remove definition. * tree.h (HAVE_TEMPLATES): Remove definition.
* lang-options.h (-fthis-is-variable): Remove documentation. * lang-options.h (-fthis-is-variable): Remove documentation.
...@@ -19724,7 +19742,7 @@ ...@@ -19724,7 +19742,7 @@
(__pointer_to_member_type_info::__do_catch): Remove. (__pointer_to_member_type_info::__do_catch): Remove.
(__pointer_to_member_type_info::__pointer_catch): Implement. (__pointer_to_member_type_info::__pointer_catch): Implement.
2000-04-10 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-04-10 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* lex.c (init_parse): Remove traces of classof and headof. * lex.c (init_parse): Remove traces of classof and headof.
* decl2.c (flag_operator_names): Default to 1. * decl2.c (flag_operator_names): Default to 1.
...@@ -20437,7 +20455,7 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz> ...@@ -20437,7 +20455,7 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz>
* init.c (build_offset_ref): Handle the case of a templated member * init.c (build_offset_ref): Handle the case of a templated member
function. function.
2000-03-19 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-03-19 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* except.c (expand_exception_blocks): Clear catch_clauses_last. * except.c (expand_exception_blocks): Clear catch_clauses_last.
...@@ -20463,7 +20481,7 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz> ...@@ -20463,7 +20481,7 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz>
(layout_class_type): Implement new ABI handling of bitfields (layout_class_type): Implement new ABI handling of bitfields
longer than their types. longer than their types.
2000-03-18 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-03-18 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* parse.y (extdefs): Call ggc_collect. * parse.y (extdefs): Call ggc_collect.
* parse.c: Regenerated. * parse.c: Regenerated.
...@@ -21073,7 +21091,7 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz> ...@@ -21073,7 +21091,7 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz>
* decl.c (decls_match): Remove obsolete static member nadgering. * decl.c (decls_match): Remove obsolete static member nadgering.
2000-02-21 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-02-21 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* decl.c (grokdeclarator): Change ANSI to ISO. * decl.c (grokdeclarator): Change ANSI to ISO.
* lex.c (consume_string, readescape, do_identifier): Likewise. * lex.c (consume_string, readescape, do_identifier): Likewise.
...@@ -22100,7 +22118,7 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz> ...@@ -22100,7 +22118,7 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz>
* optimize.c (copy_body_r): Clear the operand three of a * optimize.c (copy_body_r): Clear the operand three of a
TARGET_EXPR when copying it. TARGET_EXPR when copying it.
2000-01-14 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-01-14 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* method.c (build_decl_overload_real): Check whether we are in :: * method.c (build_decl_overload_real): Check whether we are in ::
before returning __builtin_new/delete. before returning __builtin_new/delete.
...@@ -22397,6 +22415,6 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz> ...@@ -22397,6 +22415,6 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz>
(fixup_vtable_deltas1): Likewise. (fixup_vtable_deltas1): Likewise.
(finish_struct_1): Likewise. (finish_struct_1): Likewise.
2000-01-01 Martin v. Lwis <loewis@informatik.hu-berlin.de> 2000-01-01 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* call.c (build_new_method_call): Also check destructors. * call.c (build_new_method_call): Also check destructors.
...@@ -266,6 +266,8 @@ static const struct resword reswords[] = ...@@ -266,6 +266,8 @@ 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 },
......
...@@ -1230,6 +1230,9 @@ typedef struct cp_parser GTY(()) ...@@ -1230,6 +1230,9 @@ typedef struct cp_parser GTY(())
been seen that makes the expression non-constant. */ been seen that makes the expression non-constant. */
bool non_constant_expression_p; bool non_constant_expression_p;
/* TRUE if we are parsing the argument to "__offsetof__". */
bool in_offsetof_p;
/* TRUE if local variable names and `this' are forbidden in the /* TRUE if local variable names and `this' are forbidden in the
current context. */ current context. */
bool local_variables_forbidden_p; bool local_variables_forbidden_p;
...@@ -2225,6 +2228,9 @@ cp_parser_new (void) ...@@ -2225,6 +2228,9 @@ cp_parser_new (void)
parser->allow_non_constant_expression_p = false; parser->allow_non_constant_expression_p = false;
parser->non_constant_expression_p = false; parser->non_constant_expression_p = false;
/* We are not parsing offsetof. */
parser->in_offsetof_p = false;
/* Local variable names are not forbidden. */ /* Local variable names are not forbidden. */
parser->local_variables_forbidden_p = false; parser->local_variables_forbidden_p = false;
...@@ -2503,6 +2509,29 @@ cp_parser_primary_expression (cp_parser *parser, ...@@ -2503,6 +2509,29 @@ cp_parser_primary_expression (cp_parser *parser,
return build_x_va_arg (expression, type); return build_x_va_arg (expression, type);
} }
case RID_OFFSETOF:
{
tree expression;
bool saved_in_offsetof_p;
/* Consume the "__offsetof__" token. */
cp_lexer_consume_token (parser->lexer);
/* Consume the opening `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
/* Parse the parenthesized (almost) constant-expression. */
saved_in_offsetof_p = parser->in_offsetof_p;
parser->in_offsetof_p = true;
expression
= cp_parser_constant_expression (parser,
/*allow_non_constant_p=*/false,
/*non_constant_p=*/NULL);
parser->in_offsetof_p = saved_in_offsetof_p;
/* Consume the closing ')'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
return expression;
}
default: default:
cp_parser_error (parser, "expected primary-expression"); cp_parser_error (parser, "expected primary-expression");
return error_mark_node; return error_mark_node;
...@@ -3394,7 +3423,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) ...@@ -3394,7 +3423,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
can be used in constant-expressions. */ can be used in constant-expressions. */
if (parser->constant_expression_p if (parser->constant_expression_p
&& !dependent_type_p (type) && !dependent_type_p (type)
&& !INTEGRAL_OR_ENUMERATION_TYPE_P (type)) && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
/* A cast to pointer or reference type is allowed in the
implementation of "offsetof". */
&& !(parser->in_offsetof_p && POINTER_TYPE_P (type)))
{ {
if (!parser->allow_non_constant_expression_p) if (!parser->allow_non_constant_expression_p)
return (cp_parser_non_constant_expression return (cp_parser_non_constant_expression
...@@ -3854,7 +3886,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) ...@@ -3854,7 +3886,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
operator. */ operator. */
parser->context->object_type = NULL_TREE; parser->context->object_type = NULL_TREE;
/* These operators may not appear in constant-expressions. */ /* These operators may not appear in constant-expressions. */
if (parser->constant_expression_p) if (parser->constant_expression_p
/* The "->" operator is allowed in the implementation
of "offsetof". */
&& !(parser->in_offsetof_p && token_type == CPP_DEREF))
{ {
if (!parser->allow_non_constant_expression_p) if (!parser->allow_non_constant_expression_p)
postfix_expression postfix_expression
...@@ -4259,6 +4294,9 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p) ...@@ -4259,6 +4294,9 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
break; break;
case ADDR_EXPR: case ADDR_EXPR:
/* The "&" operator is allowed in the implementation of
"offsetof". */
if (!parser->in_offsetof_p)
non_constant_p = "`&'"; non_constant_p = "`&'";
/* Fall through. */ /* Fall through. */
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
......
...@@ -7656,6 +7656,7 @@ Predefined Macros,cpp,The GNU C Preprocessor}). ...@@ -7656,6 +7656,7 @@ 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++.
...@@ -8295,6 +8296,25 @@ int main() ...@@ -8295,6 +8296,25 @@ 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
......
...@@ -413,21 +413,12 @@ typedef __WINT_TYPE__ wint_t; ...@@ -413,21 +413,12 @@ typedef __WINT_TYPE__ wint_t;
#ifndef __cplusplus #ifndef __cplusplus
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else #else
/* In C++ a POD type can have a user defined address-of operator, and /* The cast to "char &" below avoids problems with user-defined
that will break offsetof. C++ core defect 273 addresses this and "operator &", which can appear in a POD type. */
claims that reinterpret_casts to char & type are sufficient to #define offsetof(TYPE, MEMBER) \
overcome this problem. (__offsetof__ (reinterpret_cast <size_t> \
(&reinterpret_cast <char &> \
(reinterpret_cast <size_t> (static_cast<TYPE *> (0)->MEMBER))))
(&reinterpret_cast <char &>(static_cast <TYPE *> (0)->MEMBER)))
But, such casts are not permitted in integral constant expressions,
which offsetof is supposed to be.
It appears that offsetof is unimplementable in C++ without a
compiler extension. */
#define offsetof(TYPE, MEMBER) (reinterpret_cast <size_t> \
(&static_cast<TYPE *> (0)->MEMBER))
#endif /* C++ */ #endif /* C++ */
#endif /* _STDDEF_H was defined this time */ #endif /* _STDDEF_H was defined this time */
......
2003-12-16 Mark Mitchell <mark@codesourcery.com>
PR c++/13275
* g++.dg/other/offsetof2.C: Remove XFAIL.
* g++.dg/parse/offsetof1.C: New test.
* g++.gd/parse/offsetof2.C: Likewise.
2003-12-16 Giovanni Bajo <giovannibajo@gcc.gnu.org> 2003-12-16 Giovanni Bajo <giovannibajo@gcc.gnu.org>
* g++.dg/template/nontype3.C: New test. * g++.dg/template/nontype3.C: New test.
......
// { dg-do run { xfail *-*-* } } // { dg-do run }
// { dg-options -Wold-style-cast } // { dg-options -Wold-style-cast }
// Copyright (C) 2003 Free Software Foundation, Inc. // Copyright (C) 2003 Free Software Foundation, Inc.
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
// DR273 POD can have an operator&, offsetof is still required to work // DR273 POD can have an operator&, offsetof is still required to work
// XFAILED - you can't write offsetof without an extension
#include <stddef.h> #include <stddef.h>
struct POD1 struct POD1
......
#include <stddef.h>
template <bool> struct StaticAssert;
template <> struct StaticAssert<true> {};
struct MyPOD
{
int a; int b; int c;
};
StaticAssert<(offsetof(MyPOD, a) == 0)> s;
#include <cstddef>
struct choke_me
{
int size;
char storage[1];
};
struct offset_is_broken
{
static const int offset = offsetof(choke_me, storage);
};
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