Enforcing Strict Conformance to the C++ Standard
Problem
You want your compiler to accept only programs that conform to the C++ language standard.
Solution
Command-line options for specifying strict conformance to the C++ standard are listed in Table 1-37. Instructions for enforcing strict conformance from your IDE are given in Table 1-38.
|
Toolset |
Command-line compiler options |
---|---|
GCC |
-ansi -pedantic-errors |
Visual C++ |
-Za |
Intel (Windows) |
-Za -Qms0 |
Intel (Linux) |
-strict-ansi[19] |
Metrowerks |
-ansi strict -iso_templates on -msext off |
Comeau (Windows) |
A |
Comeau (Unix) |
strict or -A |
Borland |
-A[20] |
Digital Mars |
-A |
[19] Versions of the Intel compiler for Linux prior to 9.0 used the option -strict_ansi. When using -strict-ansi or -strict_ansi, it may be necessary to enable Intel's standard library, using the option -cxxlib-icc.
[20] With the option -A, some of the standard headers from the STLPort library may fail to compile.
IDE |
Configuration |
---|---|
Visual C++ |
From your project's property pages, go to Configuration Properties |
Metrowerks |
From the Target Settings Window, go to Language Settings |
C++Builder |
From Project Options, go to Advanced Compiler and check ANSI under Language Compliance. |
Dev-C++ |
See the entry for GCC in Table 1-37 and refer to Recipe 1.20. |
Discussion
The C++ language was standardized in 1998 by the International Standards Organization (ISO); in the same year, the ISO standard was adopted by the American National Standards Institute (ANSI). In 2003, a second edition of the standard was approved; the second edition contained corrections and clarifications, but introduced no new language features. Work is currently underway on an updated version of the C++ standard that will contain some important new language features and an expanded standard library.
At the time the standard was approved in 1998, no compiler came close to meeting its requirementsthough many were advertised as "ANSI-compliant." Over the years, however, vendors have worked hard to bring their tools into conformance. As of September 2005, the latest versions of the GNU, Microsoft, Intel, Metrowerks, and Comeau compilers are all highly conformant. Comeau and Intel, with their support for exported templates, can now almost claim to be 100% conformant.[21]
[21] Why almost? Because even Comeau and Intel have some bugs, and the interpretations of some parts of the standard are disputed.
No compiler is able to enforce perfect conformance to the standard, if that means refusing to compile any invalid program. This is not just because no compiler is 100% conformant: a more fundamental reason is that the C++ standard does not require a compiler to reject all invalid programs. There is a carefully delimited set of circumstances in which a compiler is required to issue a diagnostic, indicating an ill-formed program; for many invalid programs, however, no diagnostic is required. These are the programs that invoke what the standard calls undefined behavior at runtime. And even when a diagnostic is required, a compiler is permitted to issue the diagnostic and continue with compilation, possibly leading to the successful creation of an executable or library.
The main reason that compilers are not required to reject all nonconforming programs is that in many cases nonconformance is computationally difficultor even impossibleto detect. Another reason, discussed later, is that nonconforming programs are sometimes useful.
I recommend that you use your compiler's strict conformance option as often as you can. There are some cases where it may not be appropriate, however; to better understand this, let's look at several varieties of nonconforming code.
First, there is code that was legal in an early dialect of C++, before the language was standardized. For example, in the early days of C++, the scope of a variable declared in the initializer of a for loop extended to the end of the block containing the loop:
// WARNING: invalid code! int main( ) { for (int i = 0; i < 10; ++i) ; int j = i; // j == 10 }
This is not permitted by the standard, and offers no advantage over the standard scoping rules. The need to compile code like the above should arise only when maintaining legacy applications.
Another category of nonconforming code is code that uses experimental language extensions that might eventually be incorporated into the C++ standard. For example, many compilers provide an integral type long long guaranteed to have a size of at least 64 bits. As another example, several compilers provide a built-in operator typeof, with the same syntax as the sizeof operator, which returns the type of an expression. Both of these features are likely to appear in the next version of the C++ standard, although the spelling of typeof is expected to change, probably to decltype.
Be very careful before using an extension like this: before you know it, you may have to port your code to a platform that does not implement the extension, or that implements it with different semantics.
A third category of nonconforming code is code that makes use of platform-specific language extensions necessary to take advantage of operating system features. The attributes _ _declspec(dllexport) and _ _declspec(dllimport), for building dynamic libraries on Windows, and the attributes _ _stdcall, _ _fastcall and _ _cdecl, for representing Windows calling conventions, fall into this category. Although these are language extensions, most Windows compilers will accept code containing them even in their strict-conformance mode.
A final category of nonconforming code is code that violates the C++ standard but is perfectly valid according to some other useful standard. A prime example of such a standard is C++/CLI, which is currently in the final stages of standardization by the ECMA. C++/CLI is an extension to C++ that constitutes the C++ interface to the Command Language Infrastructure, the core of Microsoft's .NET Framework. When compiling an application that uses certain C++/CLI extensions, a conforming C++ compiler is required to issue a diagnostic, but it's free to generate a valid C++/CLI application, if it supports the C++/CLI standard.
If you need to compile nonconforming code, first see whether it will compile using the options in Table 1-37 and Table 1-38. If not, some compilers offer a range of more fine-grained conformance options that allow some nonconforming constructs to compile but not others. For example, Comeau provides the option long_long to specify that the type long long should be recognized. Finally, some compilers provide options that cause them to report many violations of the standard as warnings rather than errors. For example, GCC provides the option -pedantic for this purpose and Comeau provides the options a, for Windows, and strict_warnings or -a, for other platforms.
See Also
Recipe 1.2