소스 검색

Add a C++ style guide for the project (#113)

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.

This adopts the Google C++ style guide as a baseline, and then makes minimal,
focused additions and adjustments to it to suit the needs of Carbon.

Co-authored-by: Thomas Köppe <tkoeppe@google.com>
Co-authored-by: Jon Meow <46229924+jonmeow@users.noreply.github.com>
Co-authored-by: Geoff Romer <gromer@google.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: austern <austern@google.com>
Co-authored-by: Dmitri Gribenko <gribozavr@gmail.com>
Chandler Carruth 5 년 전
부모
커밋
f44cf22924
4개의 변경된 파일367개의 추가작업 그리고 0개의 파일을 삭제
  1. 13 0
      .clang-format
  2. 156 0
      docs/project/cpp_style_guide.md
  3. 2 0
      proposals/README.md
  4. 196 0
      proposals/p0113.md

+ 13 - 0
.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

+ 156 - 0
docs/project/cpp_style_guide.md

@@ -0,0 +1,156 @@
+# C++ style guide
+
+<!--
+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
+-->
+
+## Table of contents
+
+<!-- toc -->
+
+-   [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)
+
+<!-- tocstop -->
+
+## 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).

+ 2 - 0
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)

+ 196 - 0
proposals/p0113.md

@@ -0,0 +1,196 @@
+# Add a C++ style guide
+
+<!--
+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
+-->
+
+[Pull request](https://github.com/carbon-language/carbon-lang/pull/113)
+
+## Table of contents
+
+<!-- toc -->
+
+-   [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)
+
+<!-- tocstop -->
+
+## 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 `<type> <identifier>;` 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 <type> <id>;` 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.