Thread: pgsql: Provide some static-assertion functionality on all compilers.

pgsql: Provide some static-assertion functionality on all compilers.

From
Tom Lane
Date:
Provide some static-assertion functionality on all compilers.

On reflection (especially after noticing how many buildfarm critters have
__builtin_types_compatible_p but not _Static_assert), it seems like we
ought to try a bit harder to make these macros do something everywhere.
The initial cut at it would have been no help to code that is compiled only
on platforms without _Static_assert, for instance; and in any case not all
our contributors do their initial coding on the latest gcc version.

Some googling about static assertions turns up quite a bit of prior art
for making it work in compilers that lack _Static_assert.  The method
that seems closest to our needs involves defining a struct with a bit-field
that has negative width if the assertion condition fails.  There seems no
reliable way to get the error message string to be output, but throwing a
compile error with a confusing message is better than missing the problem
altogether.

In the same spirit, if we don't have __builtin_types_compatible_p we can at
least insist that the variable have the same width as the type.  This won't
catch errors such as "wrong pointer type", but it's far better than
nothing.

In addition to changing the macro definitions, adjust a
compile-time-constant Assert in contrib/hstore to use StaticAssertStmt,
so we can get some buildfarm coverage on whether that macro behaves sanely
or not.  There's surely more places that could be converted, but this is
the first one I came across.

Branch
------
master

Details
-------
http://git.postgresql.org/pg/commitdiff/0d0aa5d29175c539db1981be27dbbf059be6f3b1

Modified Files
--------------
contrib/hstore/hstore_compat.c |    5 +++--
src/include/c.h                |   26 ++++++++++++++++++++------
2 files changed, 23 insertions(+), 8 deletions(-)


Re: pgsql: Provide some static-assertion functionality on all compilers.

From
Andres Freund
Date:
On Monday, October 01, 2012 04:46:41 AM Tom Lane wrote:
> Provide some static-assertion functionality on all compilers.
>
> On reflection (especially after noticing how many buildfarm critters have
> __builtin_types_compatible_p but not _Static_assert), it seems like we
> ought to try a bit harder to make these macros do something everywhere.
> The initial cut at it would have been no help to code that is compiled only
> on platforms without _Static_assert, for instance; and in any case not all
> our contributors do their initial coding on the latest gcc version.
>
> Some googling about static assertions turns up quite a bit of prior art
> for making it work in compilers that lack _Static_assert.  The method
> that seems closest to our needs involves defining a struct with a bit-field
> that has negative width if the assertion condition fails.  There seems no
> reliable way to get the error message string to be output, but throwing a
> compile error with a confusing message is better than missing the problem
> altogether.

The current method used here doesn't allow the macro to be used in file scope
which imo would be rather useful. What about adding something like:

#ifdef !HAVE__STATIC_ASSERT
#define StaticAssertTop(condition, errmessage) \
    _Static_assert(condition, errmessage)
#else /* !HAVE__STATIC_ASSERT */
#define StaticAssertLine2(condition, line) \
    typedef struct { int static_assert_failure_in_line##line : \
        (condition) ? 1 : -1; } static_assert_failure_in_line##line
#define StaticAssertLine1(condition, line, errmsg) \
        StaticAssertLine2(condition, line)
#define StaticAssertTop(condition, errmessage) \
        StaticAssertLine1(condition, __LINE__, errmessage)
#endif /* HAVE__STATIC_ASSERT */

Annoyingly that would mean you cannot have two errors in the same line in two
files that are in one translation unit if your compiler doesn't allow repeated
typedefs. Not sure if thats a realistic problem?

Independently from this it might be worthwile to add the __LINE__ hackery to
the existing fallback for StaticAssertStmt?

Greetings,

Andres
--
 Andres Freund                       http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


Re: pgsql: Provide some static-assertion functionality on all compilers.

From
Tom Lane
Date:
Andres Freund <andres@2ndquadrant.com> writes:
> On Monday, October 01, 2012 04:46:41 AM Tom Lane wrote:
>> Provide some static-assertion functionality on all compilers.

> The current method used here doesn't allow the macro to be used in file scope
> which imo would be rather useful. What about adding something like:

I deliberately didn't go that way, because I didn't see any methods to
do it that weren't utter hacks, with deficiencies like this one:

> Annoyingly that would mean you cannot have two errors in the same line
> in two files that are in one translation unit if your compiler doesn't
> allow repeated typedefs. Not sure if thats a realistic problem?

If it came up even once, it would annoy people no end.  I don't see any
very strong reason not to just put the assertions inside functions
instead.

> Independently from this it might be worthwile to add the __LINE__ hackery to
> the existing fallback for StaticAssertStmt?

Uh, why?  It's going to be a static compile error, so surely your
compiler will give you a line number already.

            regards, tom lane


Re: pgsql: Provide some static-assertion functionality on all compilers.

From
Andres Freund
Date:
On Tuesday, October 16, 2012 11:50:48 PM Tom Lane wrote:
> Andres Freund <andres@2ndquadrant.com> writes:
> > On Monday, October 01, 2012 04:46:41 AM Tom Lane wrote:
> >> Provide some static-assertion functionality on all compilers.
> >
> > The current method used here doesn't allow the macro to be used in file
> > scope
>
> > which imo would be rather useful. What about adding something like:
> I deliberately didn't go that way, because I didn't see any methods to
>
> do it that weren't utter hacks, with deficiencies like this one:
> > Annoyingly that would mean you cannot have two errors in the same line
> > in two files that are in one translation unit if your compiler doesn't
> > allow repeated typedefs. Not sure if thats a realistic problem?
>
> If it came up even once, it would annoy people no end.  I don't see any
> very strong reason not to just put the assertions inside functions
> instead.

In the case that made me think about it I wanted to assert that internal and
external data structures are compatible. Putting the static asserts in a
function relatively far away from the data structures seems to make it more
likely that adding new asserts will be forgotten.

Unfortunately I don't have a better idea to fix the above deficiency than
adding another parameter for disambiguation :(

Andres

--
 Andres Freund                       http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services