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:
parent
ff5034c5be
commit
263ee05239
12 changed files with 143 additions and 35 deletions
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
11
gcc/testsuite/g++.dg/parse/offsetof1.C
Normal file
11
gcc/testsuite/g++.dg/parse/offsetof1.C
Normal 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;
|
12
gcc/testsuite/g++.dg/parse/offsetof2.C
Normal file
12
gcc/testsuite/g++.dg/parse/offsetof2.C
Normal 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);
|
||||
};
|
Loading…
Add table
Reference in a new issue