diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000000..faa5636305a6 --- /dev/null +++ b/.clang-format @@ -0,0 +1,13 @@ +# Part of the Carbon Language project, under the Apache License v2.0 with LLVM +# Exceptions. See /LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +--- +BasedOnStyle: Google +AllowShortBlocksOnASingleLine: 'false' +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: 'false' +DerivePointerAlignment: 'false' +ExperimentalAutoDetectBinPacking: 'false' +FixNamespaceComments: 'true' +PointerAlignment: Left diff --git a/docs/project/cpp_style_guide.md b/docs/project/cpp_style_guide.md new file mode 100644 index 000000000000..4c86ee806ae0 --- /dev/null +++ b/docs/project/cpp_style_guide.md @@ -0,0 +1,156 @@ +# C++ style guide + + + +## Table of contents + + + +- [Background](#background) +- [Baseline](#baseline) +- [Carbon-local guidance](#carbon-local-guidance) + - [General naming rules](#general-naming-rules) + - [File names](#file-names) + - [Syntax and formatting](#syntax-and-formatting) + - [Copyable and movable types](#copyable-and-movable-types) + - [Static and global variables](#static-and-global-variables) + - [Foundational libraries and data types](#foundational-libraries-and-data-types) +- [Suggested `.clang-format` contents](#suggested-clang-format-contents) + + + +## Background + +C++ code in the Carbon project should use a consistent and well documented style +guide. Where possible, this should be enacted and enforced with tooling to avoid +toil both for authors of C++ code in the Carbon project and for code reviewers. + +However, we are not in the business of innovating significantly in the space of +writing clean and maintainable C++ code, and so we work primarily to reuse +existing best practices and guidelines. + +## Baseline + +The baseline style guidance is the +[Google C++ style guide](https://google.github.io/styleguide/cppguide.html). + +## Carbon-local guidance + +We provide some local guidance beyond the baseline. This are typically motived +either by specific value provided to the project, or to give simpler and more +strict guidance for Carbon's narrow use of C++. + +### General naming rules + +Carbon's C++ code tries to match the proposed Carbon naming convention as +closely as is reasonable in C++ in order to better understand and familiarize +ourselves with the practice of using this convention. It happens that this is +fairly similar to the naming convention in the Google style guide and largely +serves to simplify it. + +- Known, compile-time constants use `UpperCamelCase`, referencing Proper + Nouns. + - This includes namespaces, type names, functions, member functions, + template parameters, `constexpr` variables, enumerators, etc. + - Note that virtual member functions should be named with + `UpperCamelCase`. The distinction between a virtual function and a + non-virtual function should be invisible, especially at the call site, + as that is an internal implementation detail. We want to be able to + freely change that without updating the name. +- All other names use `snake_case`, including function parameters, and + non-constant local and member variables. + - Notably, don't use the `_` suffix for member variable names. + +### File names + +- Always use `snake_case` for files, directories, and build system rules. + Avoid `-`s in these as well. +- Use `.cpp` for source files, which is the most common open source extension + and matches other places where "C++" is written without punctuation. + +### Syntax and formatting + +These are minor issues where any of the options would be fine and we simply need +to pick a consistent option. Where possible, +[`clang-format`](#suggested-clang-format-contents) should be used to enforce +these. + +- Always use trailing return type syntax for functions and methods. +- Place the pointer `*` adjacent to the type: `TypeName* variable_name`. +- Only declare one variable at a time (declaring multiple variables requires + confusing repetition of part of the type). +- Write `const` before the type when at the outer level: `const int N = 42;`. +- Only use line comments (with `//`, not `/* ... */`), on a line by + themselves, except for + [argument name comments](https://clang.llvm.org/extra/clang-tidy/checks/bugprone-argument-comment.html#bugprone-argument-comment), + [closing namespace comments](https://google.github.io/styleguide/cppguide.html#Namespaces), + and similar structural comments. In particular, don't append comments about + a line of code to the end of its line: + + ``` + int bad = 42; // Don't comment here. + + // Instead comment here. + int good = 42; + + // Closing namespace comments are structural, and both okay and expected. + } // namespace MyNamespace + ``` + + This dogfoods our planned commenting syntax for Carbon. It also provides a + single, consistent placement rule. It also provides more resilience against + automated refactorings. Those changes often make code longer, which forces + ever more difficult formatting decisions, and can easily spread one line + across multiple lines, leaving it impossible to know where to place the + comment. Comments on their own line preceding such code, while still + imprecise, are at least less confusing over the course of such refactorings. + +- Use the `using`-based type alias syntax instead of `typedef`. +- Follow the rules for initialization outlined in + [Abseil's tip #88](https://abseil.io/tips/88#best-practices-for-initialization). + To summarize, omitting some details from the article: + - Use assignment syntax (`=`) when initializing directly with the intended + value (or with a braced initializer directly specifying that value). + - Use the traditional constructor syntax (with parentheses) when the + initialization is performing some active logic, rather than simply + composing values together. + - Use `{}` initialization without the `=` only if the above options don't + compile. + - Never mix `{}` initialization and `auto`. +- Don't put both the `if`-condition and subsequent statement onto a single + line. + +### Copyable and movable types + +- Types should have value semantics and support both move and copy where + possible. +- Types that cannot be copied should still be movable where possible. +- If supported, moving should be as efficient as possible. + +### Static and global variables + +- Global and static variables, whether at file, class, or function scope, + should be declared `constexpr`. + +### Foundational libraries and data types + +- Generally prefer LLVM libraries and data structures to standard C++ ones. + - These are optimized significantly for performance, especially when used + without exception handling or safety requirements, and when used in + patterns that tend to occur while building compilers. + - They also minimize the vocabulary type friction when using actual LLVM + and Clang APIs. +- Do not add third-party library dependencies to any code that might + conceivably be used as part of the compiler or runtime. + - Compilers and runtime libraries have unique constraints on their + licensing. For simplicity, we want all transitive dependencies of these + layers to be under the LLVM license that the Carbon project as a whole + uses (as well as LLVM itself). + +## Suggested `.clang-format` contents + +See this repository's [`.clang-format` file](/.clang-format). diff --git a/proposals/README.md b/proposals/README.md index d31b5d1b567f..d6796f4547ee 100644 --- a/proposals/README.md +++ b/proposals/README.md @@ -37,6 +37,8 @@ request: - [Decision](p0083_decision.md) - [0107 - Code and name organization](p0107.md) - [Decision](p0107_decision.md) +- [0113 - Add a C++ style guide](p0113.md) + - [Decision](p0113_decision.md) - [0120 - Add idiomatic code performance and developer-facing docs to goals](p0120.md) - [Decision](p0120_decision.md) - [0142 - Unicode source files](p0142.md) diff --git a/proposals/p0113.md b/proposals/p0113.md new file mode 100644 index 000000000000..a02eda10fdb7 --- /dev/null +++ b/proposals/p0113.md @@ -0,0 +1,196 @@ +# Add a C++ style guide + + + +[Pull request](https://github.com/carbon-language/carbon-lang/pull/113) + +## Table of contents + + + +- [Problem](#problem) +- [Background](#background) +- [Proposal](#proposal) +- [Details](#details) + - [Rationale](#rationale) +- [Alternatives considered](#alternatives-considered) + - [Different variations on the baseline of the Google C++ style guide](#different-variations-on-the-baseline-of-the-google-c-style-guide) + - [Use exceptions](#use-exceptions) + - [Format functions with one-per-line arguments and parameters](#format-functions-with-one-per-line-arguments-and-parameters) + - [Place `*` and `&` with the variable in pointer declarations](#place--and--with-the-variable-in-pointer-declarations) + - [Place `const` after the type](#place-const-after-the-type) + - [Use the LLVM coding standards](#use-the-llvm-coding-standards) + + + +## Problem + +When writing C++ code for Carbon, we want to keep all of our code consistent, +easy to learn, and help avoid spending undue code review time arguing about the +same core style and idiomatic issues. + +## Background + +- [C++ Coding Standards](https://dl.acm.org/doi/book/10.5555/1036281) +- [C++ Core Guidelines](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) +- [Chromium C++ style guide](https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md) +- [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) +- [Joint Strike Fighter Air Vehicle C++ Coding Standards](https://stroustrup.com/JSF-AV-rules.pdf) +- [LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html) +- [Mozilla C++ Style Guide](https://firefox-source-docs.mozilla.org/code-quality/coding-style/coding_style_cpp.html) +- [Programming style](https://en.wikipedia.org/wiki/Programming_style) +- [The Elements of Programming Style](https://dl.acm.org/doi/book/10.5555/578130) +- [WebKit Code Style Guidelines](https://webkit.org/code-style-guidelines/) + +## Proposal + +I propose to use the Google C++ style guide as a baseline, and then make +minimal, focused additions and adjustments to it to suit the needs of Carbon. + +## Details + +The Google C++ style guide is widely used even outside of Google. Both Mozilla +and Chromium use it as their base style guide. It is both comprehensive and +specific, providing a strong foundation with wide coverage. + +However, there are a small number of places that seem worth adjusting. I propose +to use the Google style guide as a baseline and then have a minimal, and focused +list of changes and clarifications. + +The most expensive cases are those where we _actively diverge_ from this +baseline. Doing this outside of mechanical formatting issues would require +careful thought and justification that seems likely to have a higher cost than +the benefit. I propose focusing only on specific places where there is a direct +_benefit_ to Carbon by diverging. The only place where I suggest this is the +naming convention. The convention suggested by Google's style guide is more +complex than necessary, in part due to its desire to not invalidate a large +historical codebase. That is not a concern for Carbon, and there is a specific +advantage: using and learning how the proposed naming convention for Carbon +itself works in practice. Thus, the +[proposal](/docs/project/cpp_style_guide.md#naming-conventions) is to replace +the naming conventions suggested by the Google style guide with those suggested +for Carbon. + +The remaining suggested modifications simply consist of selecting one of several +allowed options in order to increase consistency and modernness. Many of the +cases allowing multiple options only exist to retain consistency with an +existing code base that isn't a factor for Carbon. I suggest we take advantage +of this to have a more consistent and modern style. See the proposed +[section](/docs/project/cpp_style_guide.md#carbon-local-guidance) for details. + +### Rationale + +Some aspects of this proposal warrant specific rationale. + +## Alternatives considered + +### Different variations on the baseline of the Google C++ style guide + +#### Use exceptions + +Advantages: + +- Better aligned with standard C++, Boost, and some other C++ communities. + +Disadvantages: + +- Significant performance problems, especially of data structures that need to + provide strong exception safety guarantees. +- LLVM does not use exceptions and is not exception safe. + +#### Format functions with one-per-line arguments and parameters + +Note: this is likely a bikeshed that we should not invest significant time +debating. + +Advantages: + +- Simpler for editors and authors of code to get correct. +- Minimizes diffs during refactorings. +- Regular horizontal rhythm (independent of name lengths) and no hard-to-spot + additional parameters on the right, which for some subset of readers + improves readability. + +Disadvantages: + +- A non-trivial change from Google's style guide. +- Readability problems caused by bin packing of function parameters and + arguments are typically better solved by factoring (either into variables or + option structs) than a formatting change. We should not have interfaces that + are hard to read due to their number of parameters. +- Increases vertical space of code, which for some subset of readers is + expensive, and for them may outweigh any benefit of the regular horizontal + rhythm. + +#### Place `*` and `&` with the variable in pointer declarations + +Note: this is likely a bikeshed that we should not invest significant time +debating. + +Advantages: + +- This spacing matches the language grammar more closely than the alternative + spacing. +- Declaration syntax parallels the usage syntax. Given `int *p;`, the type of + `*p` is `int`. +- Enables coherent declaration of multiple variables in a single declaration. + - However, even with this formatting these declarations are hard to read + and should not be used. + +Disadvantages: + +- Many people think of the declaration structure as ` ;` and + the `*` is part of the type. + - However, that intuitive understanding doesn't generalize to a few + different constructs in C++. For example: arrays and function pointers. + +#### Place `const` after the type + +Note: this is likely a bikeshed that we should not invest significant time +debating. + +Advantages: + +- Makes multiple layers of `const` alternating with pointers or references + more obviously readable. + - However, using type aliases to avoid multiple layers of `const` often + provides even better readability. + +Disadvantages: + +- For declarations without any pointer in the type, `const ;` is + much more conventional. + - And most declarations are of this form. + +### Use the LLVM coding standards + +Carbon will end up heavily using LLVM and Clang for its reference +implementation. This will both involve interfacing with those APIs and heavily +using libraries from those projects. We could adopt the LLVM coding standards to +gain consistency with those APIs. + +Advantages: + +- Consistent coding style between Carbon code and any LLVM or Clang APIs used. +- If it eventually becomes desirable to contribute Carbon's reference + implementation to the LLVM project, it would avoid updating the code to + adhere to the relevant coding standards. + +Disadvantages: + +- The LLVM coding standards are neither precise nor specific on a number of + points. They leave a large number of issues to the judgement of code + reviewers to stay consistent with the LLVM codebase. This isn't practical + for Carbon nor is it an efficient policy. + - LLVM and Clang don't _consistently_ follow the standards either, making + it impossible to have complete consistency with them. +- Contributing the reference implementation to LLVM seems unlikely and + necessarily at least a year away which minimizes any concerns around style + matching. +- LLVM has not yet adopted C++17 due to existing users who still need C++14. + However, Carbon has no such need to constrain its version of C++ and can + effectively adopt and use more modern C++ versions.