GCC 7 gives floating-point formats distinct C types
GCC 7 implements the floating types from TS 18661-3. Their names specify formats more directly, while distinct type identity and target support still shape how interfaces use them.
An interface that accepts long double does not identify its representation as precisely as its name might suggest. GCC's target documentation describes several extended formats, including IEEE binary128 and the IBM extended double format. GCC 7 adds the _FloatN and _FloatNx names from ISO/IEC TS 18661-3:2015 to its C front end. These names give numerical code a more explicit vocabulary for the format it intends to use.
The GCC 7 release page records the first release, 7.1, on May 2. The C changes distinguish the interchange-format _FloatN family from the extended-format _FloatNx family. They also state an important rule about identity. These types are distinct from one another and from float, double and long double, even when the underlying encoding is the same.
I regard that separation as useful for C interfaces. A representation can happen to match on one machine while the declared type still communicates a different requirement. C is often the language used to express interoperation, so confusing an implementation's current representation with the interface's promised type creates avoidable ambiguity.
A format name also names a type
The release notes say that most targets support _Float32, _Float32x and _Float64. _Float128 is available where GCC already supports the binary128 encoding through long double or __float128. _Float64x is available on targets with either binary128 or Intel extended precision. The set is explicitly target-dependent, so recognizing the naming scheme does not imply that every member exists everywhere.
The GCC 7.1 floating-type manual describes arithmetic, comparisons and conversions for these additional types. It also documents literal suffixes. An fN suffix selects an interchange type and fNx selects an extended type, with uppercase spellings available as well. This lets the literal itself express the intended type instead of relying on conversion from a different floating type.
For a target supporting _Float64, a small arithmetic interface can keep the type consistent throughout its calculation. This example uses the new suffix on constants as well as the new type on parameters and the return value.
_Float64 midpoint(_Float64 left, _Float64 right)
{
return left * 0.5f64 + right * 0.5f64;
}
The example illustrates typing, not a universal numerical algorithm. It does not promise an exact real-number midpoint for every pair of representable arguments. The point is that the parameter declarations and constants all ask for the same supported interchange type, so the choice is visible in the source.
Distinct identity matters when another part of the program expects a different declared type. Equal storage size does not erase the language-level distinction recorded in the release notes. A header that changes a parameter from double to _Float64 is making a type change even on a target where the encodings match. That deserves treatment as an interface decision, with corresponding declarations kept consistent across translation units.
Availability remains a target property
The manual gives concrete examples of why the implementation qualification matters. On several targets, __float128 is an alias for _Float128, while on HP-UX targets described there it is an alias for long double. _Float64x corresponds to the existing 80-bit extension on certain targets. These are documented mappings, not a general rule that every spelling means the same thing on every machine.
PowerPC Linux use of _Float128, __float128 and __ibm128 requires -mfloat128 in the versioned manual. That condition belongs to GCC 7.1's supported configuration. A source file cannot establish availability merely by choosing a type name from the technical specification. Compiler configuration and the selected target still determine whether the declaration is accepted.
GCC also documents that it supports no _Float128x implementation in this release. This is a useful counterexample to treating the family as an unlimited set generated by substituting any number into the name. The specification supplies a naming scheme, while a particular compiler release supplies a finite set of implementations.
The manual places another boundary around language mode. These TS type names are supported for C and are not supported when compiling C++. Existing GNU floating extensions have their own C++ support, but that does not make the newly implemented C vocabulary interchangeable with them in a shared header. A project exposing one interface to both languages must account for the language modes it actually compiles.
Constants and classification need corresponding support
The release notes describe <float.h> macros such as FLT128_MAX, made visible by defining __STDC_WANT_IEC_60559_TYPES_EXT__ before the include. The feature request belongs before the header, since it controls which declarations and macros the header exposes. That is separate from whether the compiler's target implements the type itself.
This fragment illustrates the placement on a target with _Float128 support. It does not assume the macro exists for unsupported targets.
#define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
#include <float.h>
_Float128 maximum_value(void)
{
return FLT128_MAX;
}
GCC's type-generic classification built-ins, including __builtin_isinf, support the new types. The notes also list type-specific versions of selected built-ins, including absolute value, copy-sign and infinity construction. Complex forms such as _Complex _Float128 are supported as well. Each of those is a stated compiler facility, so a program can use the documented operation appropriate to its type.
That should not be expanded into a claim that every system library now supplies every mathematical operation for every additional type. The compiler changes describe the front end and selected built-ins. A complete numerical application also depends on the declarations and libraries used for its other operations. Distinguishing compiler support from library support keeps the compatibility claim tied to the component that actually makes it.
Memory diagnostics describe another kind of precision
The same release improves the compiler's account of byte counts. -Wmemset-elt-size, included in -Wall, warns about calls whose size argument equals an array's element count instead of its byte size. This concerns a mismatch between a programmer's apparent unit and the unit accepted by the function. It is unrelated to floating-point accuracy, but it reflects the same practical need to state what a quantity means.
The new allocation warnings also reason about arithmetic. -Walloc-size-larger-than can diagnose excessive allocation requests, and it checks multiplication overflow for two-argument allocation functions such as calloc. Its default threshold is PTRDIFF_MAX, and the documented default form belongs to -Wall. Passing dimensions separately can leave the compiler with information that a precomputed, already overflowed byte count would obscure.
Formatted output receives more specific analysis too. -Wformat-overflow concerns output that can exceed a destination, while -Wformat-truncation concerns output that may be truncated by a bounded call. The latter distinction matters because adding a bound changes the failure mode without guaranteeing that the intended text fits. The notes' example accounts for the terminating null byte as well as the visible characters.
These diagnostics are analyses of particular calls and available information. They do not turn every buffer calculation into a checked operation at runtime. Their practical benefit is to identify concrete inconsistencies during compilation, with messages tied to a size or a format expression. The documented relationship with optimization also matters, since some diagnostics can use facts established by the compiler's analysis passes.
The release also adds the predicate forms __builtin_add_overflow_p, __builtin_sub_overflow_p and __builtin_mul_overflow_p. They report whether an integer operation would overflow without storing an arithmetic result. Calls with integer constant arguments can be integer constant expressions, according to the release notes. That gives a compile-time calculation a way to ask about representability before selecting an expression that uses the result.
This is a separate facility from the floating-type implementation. It applies to integer arithmetic, including the kinds of counts that appear around numerical buffers. Its significance is that asking whether a result fits does not itself require first storing the overflowing result. The release notes demonstrate that distinction with an enumeration initialized through a conditional multiplication.
A more explicit numerical interface
I prefer the floating-type addition to an informal convention that a particular project uses long double to mean a particular format. The new names let an interface state that requirement directly where the compiler supports it. They also force the availability question into the build, instead of leaving it implicit in an assumption about an implementation's traditional types.
For GCC 7.1, that explicitness has concrete limits. The selected target determines which types exist, C++ does not accept the TS type names, and the type remains distinct even when another type has the same encoding. Constants and header macros have matching rules of their own. A public C declaration using _Float64 or _Float128 therefore communicates more than a desired storage size. It specifies a compiler-recognized type whose supported operations and availability can be read in the versioned documentation.