October 12, 2020·4 min read·engineeringcclangbuildsstandards

Clang 11 makes GNU C17 the default language mode

Clang 11 selects gnu17 when a C build omits -std. Making the language mode explicit separates a compiler upgrade from a change to the build's source assumptions.

A compiler invocation can select a language revision without spelling it out. That choice remains part of the build even when the command line leaves it to the compiler. The Clang 11 release notes change the default C mode from gnu11 to gnu17 when no -std= option is present. The October 12 release therefore changes an input to builds whose visible arguments can remain identical.

This is a useful distinction between the source file and the program being compiled. Source text needs an interpretation, and the selected language mode supplies part of it. Upgrading a compiler can change that interpretation through a default, alongside the implementation's other changes.

I value C's small language, but its practical use depends on knowing which rules a build requests. An explicit language option makes that request available to the reader of the build command. It also gives a maintainer a way to discuss a compiler upgrade separately from a decision about language mode.

The default is an argument supplied elsewhere

A command such as clang -c parser.c delegates the language-mode choice to Clang's default. The command has not avoided making a choice. It has selected a policy in which the compiler version determines that choice.

This becomes visible when two machines run the same command with different compiler versions. The source path and command text can agree while the effective language settings differ. Explaining the resulting compilation therefore requires knowing both the explicit arguments and the defaults supplied by the selected executable.

The new default can be requested explicitly. That records the language request in the invocation even if another compiler release changes its own default.

clang -std=gnu17 -c parser.c

A project intending to retain the preceding default mode can state that intention too. Its build then explains why the older language mode remains part of the source contract.

clang -std=gnu11 -c parser.c

These commands describe different build policies. The second keeps the language request explicit while allowing the compiler implementation to change. It does not promise identical diagnostics or generated instructions across compiler releases.

That last qualification matters because the language option is one input among several. A compiler can improve diagnostics or fix its implementation within the same language mode. Pinning the mode provides a clearer explanation of the source contract without pretending to freeze every property of the toolchain.

GNU mode is a specific choice

The new default is GNU C17. The mode name includes a language revision and a choice about extensions. Calling it simply C17 leaves out information about the actual option selected by the compiler.

A project's decision about extensions should follow its portability requirements. Code intended for a particular compiler family can deliberately use capabilities associated with that environment. Code intended for a narrower common language needs a different agreement about what source constructs it permits.

The default change does not choose that agreement on the project's behalf. It supplies an interpretation for a command that has not already made the choice. Making the option explicit lets the build's author state which interpretation is intentional.

This is especially relevant to libraries whose consumers use different build systems. The library's own compilation mode does not establish how a consumer compiles its public headers. A header containing definitions or conditional declarations participates in the consumer's translation unit.

For that reason, a library's portability claim needs to account for the environments in which its headers are interpreted. A successful internal build supplies evidence about one such environment. It does not establish every consumer's language settings.

Defaults interact with generated build commands

A generated build command can omit a language option even when a high-level configuration appears to name a language. The useful artifact for this question is the actual invocation passed to the compiler. That invocation determines whether the new default applies.

This is a consequence of delegation through build tools. One layer describes a desired project configuration. Another layer turns that configuration into commands. The compiler receives those commands, including whatever decisions the translation preserved or left unspecified.

A project that records generated commands can therefore answer a concrete question about this release. Did its C compilations pass a -std option already? If they did, the release-note default change is not the mechanism selecting their language revision. Other Clang 11 changes can still affect them.

The distinction prevents an imprecise diagnosis of an upgrade problem. A failure that begins with the new compiler is evidence of a changed toolchain, but it does not identify which change caused the failure. The actual invocation helps establish whether language-mode selection is a plausible explanation.

I prefer that level of specificity when assessing C builds. It connects the observed behavior to a documented compiler choice and a command that can be inspected. A general statement that the language changed omits the information needed to understand the affected source.

A different default concerns the linker

The release notes also make -fno-common the default on all targets. This is independent of the GNU C17 selection. Both affect builds with omitted options, but they govern different behavior.

The GCC 10 porting guide explains the shared source issue behind common-symbol failures. A tentative definition in a header can produce definitions in multiple translation units. An extern declaration in the header and one implementation definition express the intended shared object.

The connection matters because a multiple-definition failure can appear during the same compiler upgrade as the language-default change. Treating every failure as a consequence of C17 would misidentify this particular cause. The linker behavior has its own option and its own source-level repair.

An upgrade report can consequently describe each changed assumption in concrete terms. The build either requests its language mode or accepts the compiler's default. Separately, its object definitions either satisfy the stricter linking behavior or depend on common-symbol merging. Clang 11 makes both choices visible, and an explicit build can record which policies the project intends to maintain.