OSDN Git Service

PR c++/13275
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 16 Dec 2003 16:09:23 +0000 (16:09 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 16 Dec 2003 16:09:23 +0000 (16:09 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@74702 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/ChangeLog
gcc/c-common.h
gcc/c-parse.in
gcc/cp/ChangeLog
gcc/cp/lex.c
gcc/cp/parser.c
gcc/doc/extend.texi
gcc/ginclude/stddef.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/other/offsetof2.C
gcc/testsuite/g++.dg/parse/offsetof1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/offsetof2.C [new file with mode: 0644]

index a9a86f3..6b0eee4 100644 (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.
index 326fe51..28e8356 100644 (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,
index b36ab06..954c370 100644 (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,
index 4a19573..31876c9 100644 (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>\r
+\r
+       PR c++/2294\r
+       * name-lookup.c (push_overloaded_decl): always construct an OVERLOAD\r
+       if the declaration comes from an using declaration.\r
+
 2003-12-16  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
 
        * semantics.c (finish_id_expression): Refactor the code to handle
        * 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
        * 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.
        * 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.
 
        * 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.
 
        (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.
        (__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.
index 37baa48..50af117 100644 (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 },
index 14923b1..8980611 100644 (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);
index 4afe784..21456db 100644 (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
 
index d19d78a..1bb3e90 100644 (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 */
 
index e31d5d5..72832a8 100644 (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.
index 64b4fbd..3ab6398 100644 (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
diff --git a/gcc/testsuite/g++.dg/parse/offsetof1.C b/gcc/testsuite/g++.dg/parse/offsetof1.C
new file mode 100644 (file)
index 0000000..ae9d311
--- /dev/null
@@ -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 (file)
index 0000000..4552d39
--- /dev/null
@@ -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);
+};