User account creation filtered due to spam.

Bug 14932 - [3.4/4.0 Regression] cannot use offsetof to get offsets of array elements in g++ 3.4.0 prerelease
Summary: [3.4/4.0 Regression] cannot use offsetof to get offsets of array elements in ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.0
: P2 normal
Target Milestone: 3.4.1
Assignee: Giovanni Bajo
URL:
Keywords: patch, rejects-valid
: 15270 16868 (view as bug list)
Depends on:
Blocks:
 
Reported: 2004-04-13 01:47 UTC by Bill Helfinstine
Modified: 2014-05-29 01:46 UTC (History)
8 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work: 3.3.3
Known to fail: 3.4.0 4.0.0
Last reconfirmed: 2004-04-14 10:15:19


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bill Helfinstine 2004-04-13 01:47:46 UTC
In the gcc 3.4.0 prerelase, taking the offset of an array element works in gcc
but not in g++.  This does work in 3.3.x and earlier versions of g++.


Version:
g++ (GCC) 3.4.0 20040407 (prerelease)

System:
i686-pc-linux-gnu  Red Hat 9  AthlonXP

GCC Configuration:
/usr2/stow/gcc/3.4.0_prerelease/gcc-3.4.0-20040406/configure
--prefix=/usr2/stow/gcc/3.4.0_prerelease/ --enable-languages=c,c++

GCC Invocation:
/usr2/stow/gcc/3.4.0_prerelease/bin/g++ tt.c

GCC Output:
tt.c: In function `int main(int, char**)':
tt.c:16: error: an array reference cannot appear in a constant-expression

Testcase (unpreprocessed):

#include <stddef.h>

#ifdef __cplusplus
extern "C" int printf (__const char *__restrict __format, ...);
#endif

struct foobar
{
    int bar;
    int foo[22];
};

int main(int argc, char **argv)
{
    printf("%u\n", (unsigned)offsetof(struct foobar, foo[12]));
}



Testcase (preprocessed):
# 1 "tt.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "tt.c"

# 1
"/usr2/stow/gcc/3.4.0_prerelease/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/include/stddef.h"
1 3 4
# 151
"/usr2/stow/gcc/3.4.0_prerelease/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/include/stddef.h"
3 4
typedef int ptrdiff_t;
# 213
"/usr2/stow/gcc/3.4.0_prerelease/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/include/stddef.h"
3 4
typedef unsigned int size_t;
# 3 "tt.c" 2


extern "C" int printf (__const char *__restrict __format, ...);


struct foobar
{
    int bar;
    int foo[22];
};

int main(int argc, char **argv)
{
    printf("%u\n", (unsigned)(__offsetof__ (reinterpret_cast <size_t>
(&reinterpret_cast <char &> (static_cast<struct foobar *> (0)->foo[12])))));
}
Comment 1 Andrew Pinski 2004-04-13 01:53:07 UTC
I have a fix for 3.5.0 if this is a valid code as I think it is.  But it is too invasive fix for 3.4.x.
Comment 2 Giovanni Bajo 2004-04-14 10:15:18 UTC
Not sure how your fix looks like, but the correct fix looks to me a one liner 
in parser.c, where it checks if '[]' is allowed in constant expressions. The 
code is valid.
Comment 3 Bill Helfinstine 2004-04-27 04:55:06 UTC
I added a one-liner check for !in_offsetof_p to the code in parser.c that
detects the case of an array index and it does seem to fix the problem.  Here's
the patch that I tried.  No regressions in the testsuite (tested on
i686-pc-linux-gnu).

Index: parser.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.157.2.25
diff -u -c -r1.157.2.25 parser.c
*** parser.c    19 Mar 2004 11:41:15 -0000      1.157.2.25
--- parser.c    27 Apr 2004 04:46:47 -0000
***************
*** 3705,3712 ****
            idk = CP_ID_KIND_NONE;
            /* Array references are not permitted in
               constant-expressions.  */
!           if (cp_parser_non_integral_constant_expression
!               (parser, "an array reference"))
              postfix_expression = error_mark_node;
          }
          break;
--- 3705,3715 ----
            idk = CP_ID_KIND_NONE;
            /* Array references are not permitted in
               constant-expressions.  */
!           if (/* The "[]" operator is allowed in the implementation
!                  of "offsetof".  */
!               !parser->in_offsetof_p
!               && (cp_parser_non_integral_constant_expression
!                   (parser, "an array reference")))
              postfix_expression = error_mark_node;
          }
          break;
Comment 4 Giovanni Bajo 2004-04-27 07:11:53 UTC
That is the patch I was thinking of. You want to take care of asking for 
approval yourself? Otherwise I can take care of it.
Comment 5 Wolfgang Bangerth 2004-04-27 12:45:55 UTC
Giovanni, please take care of this -- patches from unknown contributors 
are unfortunately too often ignored :-( 
 
W. 
Comment 6 Bill Helfinstine 2004-04-27 20:47:57 UTC
Giovanni, 

If you could request it, that'd be great!  The patch is just based on your
comment #2 and I thought it might be helpful to do the quick cut-n-paste and run
the regression tests.  

I don't have all the paperwork in place to actually submit patches, however.  I
don't have a good idea what the dividing line between a trivial and a nontrivial
patch is, but I do know that all I did was copy an if clause from elsewhere in
that file, so I didn't really _write_ anything.

And I suspect that Wolfgang's comment has truth to it as well.

Thank you all for your help and comments and for your work on such a cool project!
Comment 7 Giovanni Bajo 2004-04-27 23:35:09 UTC
Not that my patches are being reviewed that much lately, but I'll add this to 
the can ;)
Comment 8 Andrew Pinski 2004-05-03 19:03:27 UTC
*** Bug 15270 has been marked as a duplicate of this bug. ***
Comment 9 Giovanni Bajo 2004-06-01 02:33:36 UTC
Patch submitted:
http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00004.html

waiting for review (Mark?)
Comment 10 CVS Commits 2004-06-01 10:22:23 UTC
Subject: Bug 14932

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	giovannibajo@gcc.gnu.org	2004-06-01 10:22:12

Modified files:
	gcc/cp         : ChangeLog parser.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/parse: offsetof4.C 

Log message:
	PR c++/14932
	* parser.c (cp_parser_postfix_expression): Allow subscript
	operator in offsetof.
	
	PR c++/14932
	* g++.dg/parse/offsetof4.C: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4072&r2=1.4073
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/parser.c.diff?cvsroot=gcc&r1=1.197&r2=1.198
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3801&r2=1.3802
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/parse/offsetof4.C.diff?cvsroot=gcc&r1=NONE&r2=1.1

Comment 12 Giovanni Bajo 2004-06-01 10:49:12 UTC
Fixed for 3.4.1 and 3.5.0. Thank you for your report (and for your patch)!
Comment 13 Giovanni Bajo 2004-08-04 00:18:00 UTC
*** Bug 16868 has been marked as a duplicate of this bug. ***
Comment 14 zhangjingwang 2013-08-30 10:52:15 UTC
#include <stdio.h>
#include <stddef.h>

struct TestStruct {
  int array[13];
};

struct TempStruct {
  int index;
};

int array_offset(struct TempStruct *index)
{
  return offsetof(struct TestStruct, array[index->index]);
}

int main(int argc, char **argv)
{
  struct TempStruct tmp = {3};
  printf("Offset of array[3] is %d.\n", array_offset(&tmp));
}

test.c: In function 'int array_offset(TempStruct*)':
test.c:14: error: 'index' cannot appear in a constant-expression
test.c:14: error: '->' cannot appear in a constant-expression

This can't be compiled by the following versions of g++ (while it is accepted by gcc of the same version and clang++ 3.4):
g++ (Debian 4.4.5-8) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
:AND:
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

So I don't think this bug is fixed for those versions.
Comment 15 zhangjingwang 2013-08-31 17:28:49 UTC
(In reply to zhangjingwang from comment #14)
> #include <stdio.h>
> #include <stddef.h>
> 
> struct TestStruct {
>   int array[13];
> };
> 
> struct TempStruct {
>   int index;
> };
> 
> int array_offset(struct TempStruct *index)
> {
>   return offsetof(struct TestStruct, array[index->index]);
> }
> 
> int main(int argc, char **argv)
> {
>   struct TempStruct tmp = {3};
>   printf("Offset of array[3] is %d.\n", array_offset(&tmp));
> }
> 
> test.c: In function 'int array_offset(TempStruct*)':
> test.c:14: error: 'index' cannot appear in a constant-expression
> test.c:14: error: '->' cannot appear in a constant-expression
> 
> This can't be compiled by the following versions of g++ (while it is
> accepted by gcc of the same version and clang++ 3.4):
> g++ (Debian 4.4.5-8) 4.4.5
> Copyright (C) 2010 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.  There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> :AND:
> g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)
> Copyright (C) 2010 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.  There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> 
> So I don't think this bug is fixed for those versions.

OK, I've tested the latest gcc 4.8.1 and the problem is fixed in the latest version. g++ there will accept the code above without any problem.
Comment 16 Ryan Johnson 2014-05-29 01:46:32 UTC
A very similar problem arises with gcc-4.8.2 (and 4.9.0):

#include <stdio.h>
struct foo {
    char data[10];
};
int main() {
    int x = 4;
    printf("%zd\n", offsetof(struct foo, data[x]));
    return 0;
}


gcc-4.8.2 accepts it (with -xc), as does clang-3.0. In both cases, the resulting binary prints "4" as expected. g++-4.8.2 rejects:

bug.cpp: In function ‘int main()’:
bug.cpp:9:47: error: ‘x’ cannot appear in a constant-expression
     printf("%zd\n", offsetof(struct foo, data[x]));

So again, I don't think this bug is fixed... but I'll happily file a new PR if that's preferred.