Skip site navigation (1)Skip section navigation (2)
Date:      Mon,  4 Oct 2004 08:10:41 -0500 (CDT)
From:      Patrick Hartling <patrick@137.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   misc/72307: offsetof() macro emits non-compliant code for C++
Message-ID:  <20041004131041.B3AE53A1D4@dsl.80.187.networkiowa.com>
Resent-Message-ID: <200410041320.i94DKLn0050867@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         72307
>Category:       misc
>Synopsis:       offsetof() macro emits non-compliant code for C++
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 04 13:20:21 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Patrick Hartling
>Release:        FreeBSD 5.3-BETA5 i386
>Organization:
>Environment:
System: FreeBSD dsl.80.187.networkiowa.com 5.3-BETA5 FreeBSD 5.3-BETA5 #59: Sat Sep 25 10:17:05 CDT 2004 root@dsl.80.187.networkiowa.com:/usr/obj/usr/src/sys/HOME i386

This problem applies to all FreeBSD 5.3 beta releases and to 6.0-current.

>Description:

The offsetof() macro defined in /usr/includestddef.h emits code that
violates the C++ standard depending upon the context of its use (see
Section 5.19, Paragraph 1 of the ISO C++ Standard).  With the import
of GCC 3.4.2, this is a serious problem because the C++ compiler is
now much more strict in its enforcement of the C++ standard.  The
included code fails to compile with GCC 3.4.2 in the base system
with the following errors:

const-exp.cpp:14: error: a casts to a type other than an integral or enumeration type cannot appear in a constant-expression
const-exp.cpp:14: error: '->' cannot appear in a constant-expression
const-exp.cpp:14: error: `&' cannot appear in a constant-expression

GCC 3.4.2 built from the Ports Collection (gcc-3.4.2_20040827) builds
the code without problem.  I believe that this is because this GCC
version gets offsetof() from its own stddef.h, which has a C++-friendly
variant.

The following code demonstrates the problem.  It is adapated from code
used by the Boost.Python library (http://www.boost.org/libs/python/)
found in the header boost/python/object/instance.hpp (the struct
additional_instance_size at the end of the file).  This offsetof()
macro breaks compiling of Boost.Python from Boost 1.31.0 and from the
upcoming Boost 1.32.0 code base.  It could affect other Boost libraries
as well as other C++ code in general.

#include <stdlib.h>
#include <stddef.h>

struct instance_char
{
   union
   {
      char bytes[sizeof(char)];
   } storage;
};

struct myType
{
   static const size_t value = offsetof(instance_char, storage);
};

void f()
{
   myType t;
}

>How-To-Repeat:

Compile the above code using GCC 3.4.2 from the base system:

% g++ -c const-exp.cpp

>Fix:

Fixing this problem should be as easy as using the offsetof() definition
from the GCC 3.4.2 stddef.h:

/* Offset of member MEMBER in a struct of type TYPE. */
#ifndef __cplusplus
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else
/* 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 <const volatile char &>     \
                  (static_cast<TYPE *> (0)->MEMBER))))
#endif /* C++ */

The ease of fixing this may not be so simple if there are copyright
issues...
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041004131041.B3AE53A1D4>