Thoughts on -std=c11

Arran Cudbard-Bell a.cudbardb at
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 

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 

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:


Just to get the string ptr for a VALUE_PAIR.

Anonymous unions allow that to be flattened to:


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 development team

FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2

More information about the Freeradius-Devel mailing list