Thoughts on -std=c11
Arran Cudbard-Bell
a.cudbardb at freeradius.org
Wed Dec 3 05:55:53 CET 2014
What are people's opinions of passing -std=c1x in master?
Given that 3.1 or 4.0 is probably at least a year away, is four years enough time?
Packages are more or less ubiquitous now, with the exception of Gentoo and other
from src distributions, the average user never needs to touch a compiler.
Many projects distribute their own packages now (as do we, through NetworkRADIUS).
So even if distributions lag behind in providing updated versions of compilers like
GCC or clang, or using them internally in their build farms, it's not an huge
issue.
GCC 4.6 was the first version to accept '-std=c1x'. It was released March 25th 2011,
about five months before the standard was ratified (although full support wasn't
completed until very recently).
clang 3.1 was the first version to implement significant c11 features. It was released
22nd May 2012.
We already use some of the major C11 features now like _Thread_local _Static_assert
and _Noreturn, though where we use them, we also degrade gracefully to C99 compliant
code.
The big features that we want to use and can't emulate using compiler extensions,
or at least can't emulate and degrade back to C99 behaviour, are anonymous structs
and unions, and possibly _Generic.
Anonymous unions allow:
typedef struct {
union {
char const *strvalue; //!< Pointer to UTF-8 string.
uint8_t const *octets; //!< Pointer to binary string.
uint32_t integer; //!< 32bit unsigned integer.
struct in_addr ipaddr; //!< IPv4 Address.
uint32_t date; //!< Date (32bit Unix timestamp).
size_t filter[32/sizeof(size_t)]; //!< Ascend binary format a packed data
//!< structure.
uint8_t ifid[8]; //!< IPv6 interface ID (should be struct?).
struct in6_addr ipv6addr; //!< IPv6 Address.
uint8_t ipv6prefix[18]; //!< IPv6 prefix (should be struct?).
uint8_t byte; //!< 8bit unsigned integer.
uint16_t ushort; //!< 16bit unsigned integer.
uint8_t ether[6]; //!< Ethernet (MAC) address.
int32_t sinteger; //!< 32bit signed integer.
uint64_t integer64; //!< 64bit unsigned integer.
uint8_t ipv4prefix[6]; //!< IPv4 prefix (should be struct?).
uint8_t *tlv; //!< Nested TLV (should go away).
void *ptr; //!< generic pointer.
};
size_t length; //!< Length of the value.
PW_TYPE type; //!< Type of value.
} value_data_t;
value_data_t data;
data.length = 4;
data.integer = 1337;
And would allow us to remove the convenience macros like:
#define vp_strvalue data.value.strvalue
Which are annoying and sometimes confusing.
They would become more useful in the near future, as In order to add attribute
grouping support, we'll likely need another union within VALUE_PAIRs to hold
different collections of attributes.
A single VALUE_PAIR could then have a list of values, or a tree of children,
and you end up needing something like:
vp->data.values->value.strvalue
Just to get the string ptr for a VALUE_PAIR.
Anonymous unions allow that to be flattened to:
vp->values->strvalue
Which is much more readable.
Aside from syntactical enhancements, the other extremely useful feature in C11 is the
atomics. These expose atomic operations like check/set, and handle insertion of
memory barriers to prevent reordering.
In some cases atomics can be used to replace mutexes, which on some systems still always
involve a system call, and are relatively slow.
Atomics are not well supported yet, but switching to -std=c1x/-std=c11 would allow us
to use them where present, and emulate them using pthread concurrency control where not.
TL;DR Do people see a huge issue with requiring a compiler version no more than ~3
years old to build the master branch of the server, given that it'll likely be ~4-5
years when the code is released?
Arran Cudbard-Bell <a.cudbardb at freeradius.org>
FreeRADIUS development team
FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
More information about the Freeradius-Devel
mailing list