summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mmitchel@gcc.gnu.org>2003-12-16 16:09:23 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-12-16 16:09:23 +0000
commit263ee052390366c2476124b43a53cec7e5540187 (patch)
tree2b4a4284864e77f0905c40d1a718bb9eb360f8ac /gcc
parentff5034c5be89c496e39b79b52cd496130c51fdb2 (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/c-common.h7
-rw-r--r--gcc/c-parse.in1
-rw-r--r--gcc/cp/ChangeLog40
-rw-r--r--gcc/cp/lex.c2
-rw-r--r--gcc/cp/parser.c44
-rw-r--r--gcc/doc/extend.texi20
-rw-r--r--gcc/ginclude/stddef.h21
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/other/offsetof2.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/offsetof1.C11
-rw-r--r--gcc/testsuite/g++.dg/parse/offsetof2.C12
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);
+};