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
This commit is contained in:
Mark Mitchell 2003-12-16 16:09:23 +00:00
parent ff5034c5be
commit 263ee05239
12 changed files with 143 additions and 35 deletions

View File

@ -1,3 +1,12 @@
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>
* config/iq2000/iq2000.h: Formatting.

View File

@ -88,9 +88,10 @@ enum rid
RID_PUBLIC, RID_PRIVATE, RID_PROTECTED,
RID_TEMPLATE, RID_NULL, RID_CATCH,
RID_DELETE, RID_FALSE, RID_NAMESPACE,
RID_NEW, RID_OPERATOR, RID_THIS,
RID_THROW, RID_TRUE, RID_TRY,
RID_TYPENAME, RID_TYPEID, RID_USING,
RID_NEW, RID_OFFSETOF, RID_OPERATOR,
RID_THIS, RID_THROW, RID_TRUE,
RID_TRY, RID_TYPENAME, RID_TYPEID,
RID_USING,
/* casts */
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,

View File

@ -3484,6 +3484,7 @@ static const short rid_to_yy[RID_MAX] =
/* RID_FALSE */ 0,
/* RID_NAMESPACE */ 0,
/* RID_NEW */ 0,
/* RID_OFFSETOF */ 0,
/* RID_OPERATOR */ 0,
/* RID_THIS */ 0,
/* RID_THROW */ 0,

View File

@ -1,3 +1,21 @@
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>
* semantics.c (finish_id_expression): Refactor the code to handle
@ -17385,7 +17403,7 @@
* parse.y (member_init): Just pass in the type.
* init.c (expand_member_init): Handle getting a type.
2000-07-04 Martin v. Löwis <loewis@informatik.hu-berlin.de>
2000-07-04 Martin v. Löwis <loewis@informatik.hu-berlin.de>
Jason Merrill <jason@redhat.com>
* decl.c (finish_function): Warn if a function has no return
@ -17731,7 +17749,7 @@
* decl.c (pushdecl): Don't set DECL_CONTEXT from current_namespace.
(push_namespace): Set DECL_CONTEXT for a new NAMESPACE_DECL.
2000-06-24 Martin v. Löwis <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.
* Makefile.in: Adjust conflict count.
@ -18916,7 +18934,7 @@
* semantics.c (finish_member_declaration): Don't mark members of
classes declared in an extern "C" region as extern "C".
2000-05-22 Martin v. Löwis <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
namespace aliases.
@ -19370,7 +19388,7 @@
* ir.texi: Correct typo.
2000-04-25 Martin v. Löwis <loewis@informatik.hu-berlin.de>
2000-04-25 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* decl.c (grokdeclarator): Reject VLAs as members.
@ -19669,7 +19687,7 @@
(interface_only): Don't declare.
(interface_unknown): Likewise.
2000-04-11 Martin v. Löwis <loewis@informatik.hu-berlin.de>
2000-04-11 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* tree.h (HAVE_TEMPLATES): Remove definition.
* lang-options.h (-fthis-is-variable): Remove documentation.
@ -19724,7 +19742,7 @@
(__pointer_to_member_type_info::__do_catch): Remove.
(__pointer_to_member_type_info::__pointer_catch): Implement.
2000-04-10 Martin v. Löwis <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.
* 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>
* init.c (build_offset_ref): Handle the case of a templated member
function.
2000-03-19 Martin v. Löwis <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.
@ -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
longer than their types.
2000-03-18 Martin v. Löwis <loewis@informatik.hu-berlin.de>
2000-03-18 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* parse.y (extdefs): Call ggc_collect.
* parse.c: Regenerated.
@ -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.
2000-02-21 Martin v. Löwis <loewis@informatik.hu-berlin.de>
2000-02-21 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* decl.c (grokdeclarator): Change ANSI to ISO.
* 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>
* optimize.c (copy_body_r): Clear the operand three of a
TARGET_EXPR when copying it.
2000-01-14 Martin v. Löwis <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 ::
before returning __builtin_new/delete.
@ -22397,6 +22415,6 @@ Wed Apr 5 15:12:18 MET DST 2000 Jan Hubicka <jh@suse.cz>
(fixup_vtable_deltas1): Likewise.
(finish_struct_1): Likewise.
2000-01-01 Martin v. Löwis <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.

View File

@ -266,6 +266,8 @@ static const struct resword reswords[] =
{ "__inline__", RID_INLINE, 0 },
{ "__label__", RID_LABEL, 0 },
{ "__null", RID_NULL, 0 },
{ "__offsetof", RID_OFFSETOF, 0 },
{ "__offsetof__", RID_OFFSETOF, 0 },
{ "__real", RID_REALPART, 0 },
{ "__real__", RID_REALPART, 0 },
{ "__restrict", RID_RESTRICT, 0 },

View File

@ -1230,6 +1230,9 @@ typedef struct cp_parser GTY(())
been seen that makes the expression non-constant. */
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
current context. */
bool local_variables_forbidden_p;
@ -2225,6 +2228,9 @@ cp_parser_new (void)
parser->allow_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. */
parser->local_variables_forbidden_p = false;
@ -2503,6 +2509,29 @@ cp_parser_primary_expression (cp_parser *parser,
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:
cp_parser_error (parser, "expected primary-expression");
return error_mark_node;
@ -3394,7 +3423,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
can be used in constant-expressions. */
if (parser->constant_expression_p
&& !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)
return (cp_parser_non_constant_expression
@ -3854,7 +3886,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
operator. */
parser->context->object_type = NULL_TREE;
/* 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)
postfix_expression
@ -4259,7 +4294,10 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
break;
case ADDR_EXPR:
non_constant_p = "`&'";
/* The "&" operator is allowed in the implementation of
"offsetof". */
if (!parser->in_offsetof_p)
non_constant_p = "`&'";
/* Fall through. */
case BIT_NOT_EXPR:
expression = build_x_unary_op (unary_operator, cast_expression);

View File

@ -7656,6 +7656,7 @@ Predefined Macros,cpp,The GNU C Preprocessor}).
method denoted by a @samp{->*} or @samp{.*} expression.
* C++ Attributes:: Variable, function, and type attributes for C++ only.
* Strong Using:: Strong using-directives for namespace composition.
* Offsetof:: Special syntax for implementing @code{offsetof}.
* Java Exceptions:: Tweaking exception handling to work with Java.
* Deprecated Features:: Things will disappear from g++.
* Backwards Compatibility:: Compatibilities with earlier definitions of C++.
@ -8295,6 +8296,25 @@ int main()
@}
@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
@section Java Exceptions

View File

@ -413,21 +413,12 @@ typedef __WINT_TYPE__ wint_t;
#ifndef __cplusplus
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else
/* In C++ a POD type can have a user defined address-of operator, and
that will break offsetof. C++ core defect 273 addresses this and
claims that reinterpret_casts to char & type are sufficient to
overcome this problem.
(reinterpret_cast <size_t>
(&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))
/* 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 */

View File

@ -1,3 +1,10 @@
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>
* g++.dg/template/nontype3.C: New test.

View File

@ -1,4 +1,4 @@
// { dg-do run { xfail *-*-* } }
// { dg-do run }
// { dg-options -Wold-style-cast }
// Copyright (C) 2003 Free Software Foundation, Inc.
@ -6,8 +6,6 @@
// DR273 POD can have an operator&, offsetof is still required to work
// XFAILED - you can't write offsetof without an extension
#include <stddef.h>
struct POD1

View File

@ -0,0 +1,11 @@
#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;

View File

@ -0,0 +1,12 @@
#include <cstddef>
struct choke_me
{
int size;
char storage[1];
};
struct offset_is_broken
{
static const int offset = offsetof(choke_me, storage);
};