GCC C++ Code
...the code is more like what you would call guidelines than actual rules
This is a proposed set of coding conventions when using C++ as an implementation language for GNU Compiler Collection projects, either compilers (aka GCC) or target libraries. This is intended to be the common subset of C++ guidance. The intention is to develop this on the wiki, and move them to http://gcc.gnu.org/codingconventions.html when they are stable.
Dialect, Flags, Restrictions
For GCC, C++ restricted to the directories gcc, libcpp and fixincludes. C++ code must conform to the C++03 standard, with GNU extensions (-std=gnu++98). In addition, code should conform to the C++11 standard. For libraries, use whatever dialect is most suitable.
Must be -fno-exceptions -fno-rtti clean.
Must be -Wall -Wextra clean.
Build Requirements
- Every version of GCC must boostrap. It must be buildable by the previous version of GCC. It is desirable that it be buildable with C++ compilers other than GCC itself.
Formatting Conventions
- The general guideline is to continue to follow the current C coding conventions.
- Lines are limited to 80 characters.
- Variables which are used in a restricted scope should be defined at the point of first use, rather than at the top of the function.
- Namespaces.
- Open a namespace with the namespace name followed by a left brace and a new line, like so:
1 namespace gnutool { - Close a namespace with a right brace, semicolon, optional comment with closed namespace name, and a new line, like so:
- Definitions within the body of a namespace are not indented.
- Open a namespace with the namespace name followed by a left brace and a new line, like so:
- Classes.
- When defining a class, first define all public types, then all types, then all data members, then all public constructors, then the public destructor, then all public methods, then all other methods.
- Indent member elements within the body of a class by two spaces.
- Definitions that use a single colon are to be either all one line or failing that, start with the colon left most aligned under the class name. or
1 class gnuclass : member_or_base() { }; - All data members may have names which annotate member status with either a prefix or suffix underscore.
When a method refers to a non-static data member, it may qualify the reference with this->.
- Functions.
- In C++, function names are often longer due to explicit class, namespaces, or template scope or qualification. Typenames can be long for the same reasons. Therefore, we seek to maximize horizontal space, moving name into the left-most possible column.
- Return type is on a separate line, left-most aligned.
- The space between the function name and the left parenthesis in a function call can vary. All current GCC code uses a space. Essentially all C++ code omits that space, which is more consistent with C++ syntax. Accept either.
- Templates.
- Template scope should be left-most aligned and end with a newline.
Template parameter names are rendered in StudlyCaps.
Prefer typename over class in template scope.
- There is no indentation following template scope.
Use
C++ is a complex language. We do not want to use all aspects of it.
Prohibited
The following features of the C++ language may not be used in GCC code.
RTTI and dynamic_cast (these features may be permitted when certain non-default --enable-checking options are enabled so as to allow checkers to report dynamic types).
- Exceptions and throw specifications, as current code is not exception safe.
Best Avoided
The following features of the C++ language should in general be avoided in GCC code.
- Conversion operators. All conversions should be explicit named functions to avoid confusion
using statements in header files. In general a reference to a given name should mean the same thing in any GCC source file. Using declarations may be used in class definitions to manage names within an inheritance hierarchy.
Preferred
- Namespaces.
- Are encouraged. All separable libraries should have a unique global namespace. All individual tools should have a unique global namespace.
- Nested include directories names should map to nested namespaces when possible.
- Classes.
- Classes and structs are the same, with different default access rules.
- Use public inheritance to describe 'is-a' relationships. Private and protected inheritance should normally be avoided.
- There are four special member functions: the default constructor, the copy constructor, the copy assignment operator, and the destructor. The compiler will usually provide a default implementation for these functions. If that default does the right thing, document the use of the default explicitly. Otherwise, define the function. Defining any of these functions may make the class non-POD, which some psABIs interpret as not able to be passed in registers, which can reduce efficiency.
Single argument constructors should always be declared explicit.
- All constructors should initialize all data members in the member initializer list. (If not, the compiler will implicitly initialize non-POD fields, and any initialization in the body of the constructor implies extra work.)
Method bodies may only appear in the class definition if they can be inlined as per -Winline. Otherwise the method body should be defined outside of the class definition.
- Using virtual functions increases the size of an object of an instance of the class by one pointer. Use with care.
- All data members should be private, with optional public accessors or public with no accessors. Prefer data members in base classes.
- Functions.
- Overloading can be confusing. Exercise care, and be wary of implicit conversions among argument types.
Function overload sets should be semantically identical or at least very similar. Preferr overloads of function signatures differing by a single argument. For example,
- Virtual functions should not be overloaded.
- Virtual functions should not have default arguments.
- Operators.
- Operator overloading may cause surprising conversions and should be used with extreme care. Here are examples of acceptable use:
operator<< may be implemented as appropriate to print a value to a stream.
- Operators may be overloaded for types that implement numeric values, where the overloaded operators implement the usual numeric semantics.
operator() may be implemented as necessary for use with standard classes, such as for a std::sort comparator.
- Appropriate operators required for iterators and smart pointers.
operator[] for data structure element access
- Operator overloading may cause surprising conversions and should be used with extreme care. Here are examples of acceptable use: