diff options
author | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-12-16 16:09:23 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-12-16 16:09:23 +0000 |
commit | 263ee052390366c2476124b43a53cec7e5540187 (patch) | |
tree | 2b4a4284864e77f0905c40d1a718bb9eb360f8ac /gcc | |
parent | ff5034c5be89c496e39b79b52cd496130c51fdb2 (diff) | |
download | gcc-263ee052390366c2476124b43a53cec7e5540187.tar.gz |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/c-common.h | 7 | ||||
-rw-r--r-- | gcc/c-parse.in | 1 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 40 | ||||
-rw-r--r-- | gcc/cp/lex.c | 2 | ||||
-rw-r--r-- | gcc/cp/parser.c | 44 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 20 | ||||
-rw-r--r-- | gcc/ginclude/stddef.h | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/offsetof2.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/offsetof1.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/offsetof2.C | 12 |
12 files changed, 143 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a9a86f312f7..6b0eee4d5bf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/c-common.h b/gcc/c-common.h index 326fe519be4..28e8356004b 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -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, diff --git a/gcc/c-parse.in b/gcc/c-parse.in index b36ab06524a..954c37067ff 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -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, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4a19573adf6..31876c98145 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 37baa485ce9..50af1178470 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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 }, diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 14923b17ce4..89806116055 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 4afe78463a1..21456db1ba6 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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 diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h index d19d78a3140..1bb3e90bc9b 100644 --- a/gcc/ginclude/stddef.h +++ b/gcc/ginclude/stddef.h @@ -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 */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e31d5d54a61..72832a8c0e6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.dg/other/offsetof2.C b/gcc/testsuite/g++.dg/other/offsetof2.C index 64b4fbdc84d..3ab63981d9b 100644 --- a/gcc/testsuite/g++.dg/other/offsetof2.C +++ b/gcc/testsuite/g++.dg/other/offsetof2.C @@ -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 diff --git a/gcc/testsuite/g++.dg/parse/offsetof1.C b/gcc/testsuite/g++.dg/parse/offsetof1.C new file mode 100644 index 00000000000..ae9d3110aba --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/offsetof1.C @@ -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; diff --git a/gcc/testsuite/g++.dg/parse/offsetof2.C b/gcc/testsuite/g++.dg/parse/offsetof2.C new file mode 100644 index 00000000000..4552d39fea2 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/offsetof2.C @@ -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); +}; |