docs: Split the style guide: C++

Moves the C++ style guide into its own file.

Change-Id: I6d28ac5d7e8e94268499ad1d7c0da22f634e3636
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/178952
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Kayce Basques <kayce@google.com>
Commit-Queue: Kayce Basques <kayce@google.com>
diff --git a/docs/BUILD.gn b/docs/BUILD.gn
index 65d8616..fae38d7 100644
--- a/docs/BUILD.gn
+++ b/docs/BUILD.gn
@@ -64,6 +64,7 @@
     "overview.rst",
     "size_optimizations.rst",
     "style/commit_message.rst",
+    "style/cpp.rst",
     "style_guide.rst",
   ]
 }
diff --git a/docs/style/cpp.rst b/docs/style/cpp.rst
new file mode 100644
index 0000000..73b78f4
--- /dev/null
+++ b/docs/style/cpp.rst
@@ -0,0 +1,826 @@
+.. _docs-pw-style-cpp:
+
+=========
+C++ style
+=========
+The Pigweed C++ style guide is closely based on Google's external C++ Style
+Guide, which is found on the web at
+https://google.github.io/styleguide/cppguide.html. The Google C++ Style Guide
+applies to Pigweed except as described in this document.
+
+The Pigweed style guide only applies to Pigweed itself. It does not apply to
+projects that use Pigweed or to the third-party code included with Pigweed.
+Non-Pigweed code is free to use features restricted by Pigweed, such as dynamic
+memory allocation and the entirety of the C++ Standard Library.
+
+Recommendations in the :ref:`docs-embedded-cpp` are considered part of the
+Pigweed style guide, but are separated out since it covers more general
+embedded development beyond just C++ style.
+
+C++ standard
+============
+All Pigweed C++ code must compile with ``-std=c++17`` in Clang and GCC. C++20
+features may be used as long as the code still compiles unmodified with C++17.
+See ``pw_polyfill/language_feature_macros.h`` for macros that provide C++20
+features when supported.
+
+Compiler extensions should not be used unless wrapped in a macro or properly
+guarded in the preprocessor. See ``pw_processor/compiler.h`` for macros that
+wrap compiler-specific features.
+
+Automatic formatting
+====================
+Pigweed uses `clang-format <https://clang.llvm.org/docs/ClangFormat.html>`_ to
+automatically format Pigweed source code. A ``.clang-format`` configuration is
+provided with the Pigweed repository.
+
+Automatic formatting is essential to facilitate large-scale, automated changes
+in Pigweed. Therefore, all code in Pigweed is expected to be formatted with
+``clang-format`` prior to submission. Existing code may be reformatted at any
+time.
+
+If ``clang-format`` formats code in an undesirable or incorrect way, it can be
+disabled for the affected lines by adding ``// clang-format off``.
+``clang-format`` must then be re-enabled with a ``// clang-format on`` comment.
+
+.. code-block:: cpp
+
+  // clang-format off
+  constexpr int kMyMatrix[] = {
+      100,  23,   0,
+        0, 542,  38,
+        1,   2, 201,
+  };
+  // clang-format on
+
+C Standard Library
+==================
+In C++ headers, always use the C++ versions of C Standard Library headers (e.g.
+``<cstdlib>`` instead of ``<stdlib.h>``). If the header is used by both C and
+C++ code, only the C header should be used.
+
+In C++ code, it is preferred to use C functions from the ``std`` namespace. For
+example, use ``std::memcpy`` instead of ``memcpy``. The C++ standard does not
+require the global namespace versions of the functions to be provided. Using
+``std::`` is more consistent with the C++ Standard Library and makes it easier
+to distinguish Pigweed functions from library functions.
+
+Within core Pigweed, do not use C standard library functions that allocate
+memory, such as ``std::malloc``. There are exceptions to this for when dynamic
+allocation is enabled for a system; Pigweed modules are allowed to add extra
+functionality when a heap is present; but this must be optional.
+
+C++ Standard Library
+====================
+Much of the C++ Standard Library is not a good fit for embedded software. Many
+of the classes and functions were not designed with the RAM, flash, and
+performance constraints of a microcontroller in mind. For example, simply
+adding the line ``#include <iostream>`` can increase the binary size by 150 KB!
+This is larger than many microcontrollers' entire internal storage.
+
+However, with appropriate caution, a limited set of standard C++ libraries can
+be used to great effect. Developers can leverage familiar, well-tested
+abstractions instead of writing their own. C++ library algorithms and classes
+can give equivalent or better performance than hand-written C code.
+
+A limited subset of the C++ Standard Library is permitted in Pigweed. To keep
+Pigweed small, flexible, and portable, functions that allocate dynamic memory
+must be avoided. Care must be exercised when using multiple instantiations of a
+template function, which can lead to code bloat.
+
+Permitted Headers
+-----------------
+.. admonition:: The following C++ Standard Library headers are always permitted:
+   :class: checkmark
+
+   * ``<array>``
+   * ``<complex>``
+   * ``<initializer_list>``
+   * ``<iterator>``
+   * ``<limits>``
+   * ``<optional>``
+   * ``<random>``
+   * ``<ratio>``
+   * ``<string_view>``
+   * ``<tuple>``
+   * ``<type_traits>``
+   * ``<utility>``
+   * ``<variant>``
+   * C Standard Library headers (``<c*>``)
+
+.. admonition:: With caution, parts of the following headers can be used:
+   :class: warning
+
+   * ``<algorithm>`` -- be wary of potential memory allocation
+   * ``<atomic>`` -- not all MCUs natively support atomic operations
+   * ``<bitset>`` -- conversions to or from strings are disallowed
+   * ``<functional>`` -- do **not** use ``std::function``; use
+     :ref:`module-pw_function`
+   * ``<mutex>`` -- can use ``std::lock_guard``, use :ref:`module-pw_sync` for
+     mutexes
+   * ``<new>`` -- for placement new
+   * ``<numeric>`` -- be wary of code size with multiple template instantiations
+
+.. admonition:: Never use any of these headers:
+   :class: error
+
+   * Dynamic containers (``<list>``, ``<map>``, ``<set>``, ``<vector>``, etc.)
+   * Streams (``<iostream>``, ``<ostream>``, ``<fstream>``, ``<sstream>`` etc.)
+     -- in some cases :ref:`module-pw_stream` can work instead
+   * ``<span>`` -- use :ref:`module-pw_span` instead. Downstream projects may
+     want to directly use ``std::span`` if it is available, but upstream must
+     use the ``pw::span`` version for compatability
+   * ``<string>`` -- can use :ref:`module-pw_string`
+   * ``<thread>`` -- can use :ref:`module-pw_thread`
+   * ``<future>`` -- eventually :ref:`module-pw_async` will offer this
+   * ``<exception>``, ``<stdexcept>`` -- no exceptions
+   * ``<memory>``, ``<scoped_allocator>`` -- no allocations
+   * ``<regex>``
+   * ``<valarray>``
+
+Headers not listed here should be carefully evaluated before they are used.
+
+These restrictions do not apply to third party code or to projects that use
+Pigweed.
+
+Combining C and C++
+===================
+Prefer to write C++ code over C code, using ``extern "C"`` for symbols that must
+have C linkage. ``extern "C"`` functions should be defined within C++
+namespaces to simplify referring to other code.
+
+C++ functions with no parameters do not include ``void`` in the parameter list.
+C functions with no parameters must include ``void``.
+
+.. code-block:: cpp
+
+  namespace pw {
+
+  bool ThisIsACppFunction() { return true; }
+
+  extern "C" int pw_ThisIsACFunction(void) { return -1; }
+
+  extern "C" {
+
+  int pw_ThisIsAlsoACFunction(void) {
+    return ThisIsACppFunction() ? 100 : 0;
+  }
+
+  }  // extern "C"
+
+  }  // namespace pw
+
+Comments
+========
+Prefer C++-style (``//``) comments over C-style comments (``/* */``). C-style
+comments should only be used for inline comments.
+
+.. code-block:: cpp
+
+  // Use C++-style comments, except where C-style comments are necessary.
+  // This returns a random number using an algorithm I found on the internet.
+  #define RANDOM_NUMBER() [] {                \
+    return 4;  /* chosen by fair dice roll */ \
+  }()
+
+Indent code in comments with two additional spaces, making a total of three
+spaces after the ``//``. All code blocks must begin and end with an empty
+comment line, even if the blank comment line is the last line in the block.
+
+.. code-block:: cpp
+
+  // Here is an example of code in comments.
+  //
+  //   int indentation_spaces = 2;
+  //   int total_spaces = 3;
+  //
+  //   engine_1.thrust = RANDOM_NUMBER() * indentation_spaces + total_spaces;
+  //
+  bool SomeFunction();
+
+Control statements
+==================
+
+Loops and conditionals
+----------------------
+All loops and conditional statements must use braces, and be on their own line.
+
+.. admonition:: **Yes**: Always use braces for line conditionals and loops:
+   :class: checkmark
+
+   .. code-block:: cpp
+
+      while (SomeCondition()) {
+        x += 2;
+      }
+      if (OtherCondition()) {
+        DoTheThing();
+      }
+
+
+.. admonition:: **No**: Missing braces
+   :class: error
+
+   .. code-block:: cpp
+
+      while (SomeCondition())
+        x += 2;
+      if (OtherCondition())
+        DoTheThing();
+
+.. admonition:: **No**: Statement on same line as condition
+   :class: error
+
+   .. code-block:: cpp
+
+      while (SomeCondition()) { x += 2; }
+      if (OtherCondition()) { DoTheThing(); }
+
+
+The syntax ``while (true)`` is preferred over ``for (;;)`` for infinite loops.
+
+.. admonition:: **Yes**:
+   :class: checkmark
+
+   .. code-block:: cpp
+
+      while (true) {
+        DoSomethingForever();
+      }
+
+.. admonition:: **No**:
+   :class: error
+
+   .. code-block:: cpp
+
+      for (;;) {
+        DoSomethingForever();
+      }
+
+
+Prefer early exit with ``return`` and ``continue``
+--------------------------------------------------
+Prefer to exit early from functions and loops to simplify code. This is the
+same same conventions as `LLVM
+<https://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code>`_.
+We find this approach is superior to the "one return per function" style for a
+multitude of reasons:
+
+* **Visually**, the code is easier to follow, and takes less horizontal screen
+  space.
+* It makes it clear what part of the code is the **"main business" versus "edge
+  case handling"**.
+* For **functions**, parameter checking is in its own section at the top of the
+  function, rather than scattered around in the fuction body.
+* For **loops**, element checking is in its own section at the top of the loop,
+  rather than scattered around in the loop body.
+* Commit **deltas are simpler to follow** in code reviews; since adding a new
+  parameter check or loop element condition doesn't cause an indentation change
+  in the rest of the function.
+
+The guidance applies in two cases:
+
+* **Function early exit** - Early exits are for function parameter checking
+  and edge case checking at the top. The main functionality follows.
+* **Loop early exit** - Early exits in loops are for skipping an iteration
+  due to some edge case with an item getting iterated over. Loops may also
+  contain function exits, which should be structured the same way (see example
+  below).
+
+.. admonition:: **Yes**: Exit early from functions; keeping the main handling
+   at the bottom and de-dentend.
+   :class: checkmark
+
+   .. code-block:: cpp
+
+      Status DoSomething(Parameter parameter) {
+        // Parameter validation first; detecting incoming use errors.
+        PW_CHECK_INT_EQ(parameter.property(), 3, "Programmer error: frobnitz");
+
+        // Error case: Not in correct state.
+        if (parameter.other() == MyEnum::kBrokenState) {
+          LOG_ERROR("Device in strange state: %s", parametr.state_str());
+          return Status::InvalidPrecondition();
+        }
+
+        // Error case: Not in low power mode; shouldn't do anything.
+        if (parameter.power() != MyEnum::kLowPower) {
+          LOG_ERROR("Not in low power mode");
+          return Status::InvalidPrecondition();
+        }
+
+        // Main business for the function here.
+        MainBody();
+        MoreMainBodyStuff();
+      }
+
+.. admonition:: **No**: Main body of function is buried and right creeping.
+   Even though this is shorter than the version preferred by Pigweed due to
+   factoring the return statement, the logical structure is less obvious. A
+   function in Pigweed containing **nested conditionals indicates that
+   something complicated is happening with the flow**; otherwise it would have
+   the early bail structure; so pay close attention.
+   :class: error
+
+   .. code-block:: cpp
+
+      Status DoSomething(Parameter parameter) {
+        // Parameter validation first; detecting incoming use errors.
+        PW_CHECK_INT_EQ(parameter.property(), 3, "Programmer error: frobnitz");
+
+        // Error case: Not in correct state.
+        if (parameter.other() != MyEnum::kBrokenState) {
+          // Error case: Not in low power mode; shouldn't do anything.
+          if (parameter.power() == MyEnum::kLowPower) {
+            // Main business for the function here.
+            MainBody();
+            MoreMainBodyStuff();
+          } else {
+            LOG_ERROR("Not in low power mode");
+          }
+        } else {
+          LOG_ERROR("Device in strange state: %s", parametr.state_str());
+        }
+        return Status::InvalidPrecondition();
+      }
+
+.. admonition:: **Yes**: Bail early from loops; keeping the main handling at
+   the bottom and de-dentend.
+   :class: checkmark
+
+   .. code-block:: cpp
+
+      for (int i = 0; i < LoopSize(); ++i) {
+        // Early skip of item based on edge condition.
+        if (!CommonCase()) {
+          continue;
+        }
+        // Early exit of function based on error case.
+        int my_measurement = GetSomeMeasurement();
+        if (my_measurement < 10) {
+          LOG_ERROR("Found something strange; bailing");
+          return Status::Unknown();
+        }
+
+        // Main body of the loop.
+        ProcessItem(my_items[i], my_measurement);
+        ProcessItemMore(my_items[i], my_measurement, other_details);
+        ...
+      }
+
+.. admonition:: **No**: Right-creeping code with the main body buried inside
+   some nested conditional. This makes it harder to understand what is the
+   main purpose of the loop versus what is edge case handling.
+   :class: error
+
+   .. code-block:: cpp
+
+      for (int i = 0; i < LoopSize(); ++i) {
+        if (CommonCase()) {
+          int my_measurement = GetSomeMeasurement();
+          if (my_measurement >= 10) {
+            // Main body of the loop.
+            ProcessItem(my_items[i], my_measurement);
+            ProcessItemMore(my_items[i], my_measurement, other_details);
+            ...
+          } else {
+            LOG_ERROR("Found something strange; bailing");
+            return Status::Unknown();
+          }
+        }
+      }
+
+There are cases where this structure doesn't work, and in those cases, it is
+fine to structure the code differently.
+
+No ``else`` after ``return`` or ``continue``
+--------------------------------------------
+Do not put unnecessary ``} else {`` blocks after blocks that terminate with a
+return, since this causes unnecessary rightward indentation creep. This
+guidance pairs with the preference for early exits to reduce code duplication
+and standardize loop/function structure.
+
+.. admonition:: **Yes**: No else after return or continue
+   :class: checkmark
+
+   .. code-block:: cpp
+
+      // Note lack of else block due to return.
+      if (Failure()) {
+        DoTheThing();
+        return Status::ResourceExausted();
+      }
+
+      // Note lack of else block due to continue.
+      while (MyCondition()) {
+        if (SomeEarlyBail()) {
+          continue;
+        }
+        // Main handling of item
+        ...
+      }
+
+      DoOtherThing();
+      return OkStatus();
+
+.. admonition:: **No**: Else after return needlessly creeps right
+   :class: error
+
+   .. code-block:: cpp
+
+      if (Failure()) {
+        DoTheThing();
+        return Status::ResourceExausted();
+      } else {
+        while (MyCondition()) {
+          if (SomeEarlyBail()) {
+            continue;
+          } else {
+            // Main handling of item
+            ...
+          }
+        }
+        DoOtherThing();
+        return OkStatus();
+      }
+
+Include guards
+==============
+The first non-comment line of every header file must be ``#pragma once``. Do
+not use traditional macro include guards. The ``#pragma once`` should come
+directly after the Pigweed copyright block, with no blank line, followed by a
+blank, like this:
+
+.. code-block:: cpp
+
+  // Copyright 2021 The Pigweed Authors
+  //
+  // Licensed under the Apache License, Version 2.0 (the "License"); you may not
+  // use this file except in compliance with the License. You may obtain a copy of
+  // the License at
+  //
+  //     https://www.apache.org/licenses/LICENSE-2.0
+  //
+  // Unless required by applicable law or agreed to in writing, software
+  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+  // License for the specific language governing permissions and limitations under
+  // the License.
+  #pragma once
+
+  // Header file-level comment goes here...
+
+Memory allocation
+=================
+Dynamic memory allocation can be problematic. Heap allocations and deallocations
+occupy valuable CPU cycles. Memory usage becomes nondeterministic, which can
+result in a system crashing without a clear culprit.
+
+To keep Pigweed portable, core Pigweed code is not permitted to dynamically
+(heap) allocate memory, such as with ``malloc`` or ``new``. All memory should be
+allocated with automatic (stack) or static (global) storage duration. Pigweed
+must not use C++ libraries that use dynamic allocation.
+
+Projects that use Pigweed are free to use dynamic allocation, provided they
+have selected a target that enables the heap.
+
+Naming
+======
+Entities shall be named according to the `Google style guide
+<https://google.github.io/styleguide/cppguide.html>`_, with the following
+additional requirements.
+
+C++ code
+--------
+* All Pigweed C++ code must be in the ``pw`` namespace. Namespaces for modules
+  should be nested under ``pw``. For example, ``pw::string::Format()``.
+* Whenever possible, private code should be in a source (.cc) file and placed in
+  anonymous namespace nested under ``pw``.
+* If private code must be exposed in a header file, it must be in a namespace
+  nested under ``pw``. The namespace may be named for its subsystem or use a
+  name that designates it as private, such as ``internal``.
+* Template arguments for non-type names (e.g. ``template <int kFooBar>``) should
+  follow the constexpr and const variable Google naming convention, which means
+  k prefixed camel case (e.g.  ``kCamelCase``). This matches the Google C++
+  style for variable naming, however the wording in the official style guide
+  isn't explicit for template arguments and could be interpreted to use
+  ``foo_bar`` style naming.  For consistency with other variables whose value is
+  always fixed for the duration of the program, the naming convention is
+  ``kCamelCase``, and so that is the style we use in Pigweed.
+* Trivial membor accessors should be named with ``snake_case()``. The Google
+  C++ style allows either ``snake_case()`` or ``CapsCase()``, but Pigweed
+  always uses ``snake_case()``.
+* Abstract base classes should be named generically, with derived types named
+  specifically. For example, ``Stream`` is an abstract base, and
+  ``SocketStream`` and ``StdioStream`` are an implementations of that
+  interface.  Any prefix or postfix indicating whether something is abstract or
+  concrete is not permitted; for example, ``IStream`` or ``SocketStreamImpl``
+  are both not permitted. These pre-/post-fixes add additional visual noise and
+  are irrelevant to consumers of these interfaces.
+
+C code
+------
+In general, C symbols should be prefixed with the module name. If the symbol is
+not associated with a module, use just ``pw`` as the module name. Facade
+backends may chose to prefix symbols with the facade's name to help reduce the
+length of the prefix.
+
+* Public names used by C code must be prefixed with the module name (e.g.
+  ``pw_tokenizer_*``).
+* If private code must be exposed in a header, private names used by C code must
+  be prefixed with an underscore followed by the module name (e.g.
+  ``_pw_assert_*``).
+* Avoid writing C source (.c) files in Pigweed. Prefer to write C++ code with C
+  linkage using ``extern "C"``. Within C source, private C functions and
+  variables must be named with the ``_pw_my_module_*`` prefix and should be
+  declared ``static`` whenever possible; for example,
+  ``_pw_my_module_MyPrivateFunction``.
+* The C prefix rules apply to
+
+  * C functions (``int pw_foo_FunctionName(void);``),
+  * variables used by C code (``int pw_foo_variable_name;``),
+  * constant variables used by C code (``const int pw_foo_kConstantName;``),
+  * structs used by C code (``typedef struct {} pw_foo_StructName;``), and
+  * all of the above for ``extern "C"`` names in C++ code.
+
+  The prefix does not apply to struct members, which use normal Google style.
+
+Preprocessor macros
+-------------------
+* Public Pigweed macros must be prefixed with the module name (e.g.
+  ``PW_MY_MODULE_*``).
+* Private Pigweed macros must be prefixed with an underscore followed by the
+  module name (e.g. ``_PW_MY_MODULE_*``). (This style may change, see
+  `b/234886184 <https://issuetracker.google.com/issues/234886184>`_).
+
+**Example**
+
+.. code-block:: cpp
+
+  namespace pw::my_module {
+  namespace nested_namespace {
+
+  // C++ names (types, variables, functions) must be in the pw namespace.
+  // They are named according to the Google style guide.
+  constexpr int kGlobalConstant = 123;
+
+  // Prefer using functions over extern global variables.
+  extern int global_variable;
+
+  class Class {};
+
+  void Function();
+
+  extern "C" {
+
+  // Public Pigweed code used from C must be prefixed with pw_.
+  extern const int pw_my_module_kGlobalConstant;
+
+  extern int pw_my_module_global_variable;
+
+  void pw_my_module_Function(void);
+
+  typedef struct {
+    int member_variable;
+  } pw_my_module_Struct;
+
+  // Private Pigweed code used from C must be prefixed with _pw_.
+  extern const int _pw_my_module_kPrivateGlobalConstant;
+
+  extern int _pw_my_module_private_global_variable;
+
+  void _pw_my_module_PrivateFunction(void);
+
+  typedef struct {
+    int member_variable;
+  } _pw_my_module_PrivateStruct;
+
+  }  // extern "C"
+
+  // Public macros must be prefixed with PW_.
+  #define PW_MY_MODULE_PUBLIC_MACRO(arg) arg
+
+  // Private macros must be prefixed with _PW_.
+  #define _PW_MY_MODULE_PRIVATE_MACRO(arg) arg
+
+  }  // namespace nested_namespace
+  }  // namespace pw::my_module
+
+See :ref:`docs-pw-style-macros` for details about macro usage.
+
+Namespace scope formatting
+==========================
+All non-indented blocks (namespaces, ``extern "C"`` blocks, and preprocessor
+conditionals) must have a comment on their closing line with the
+contents of the starting line.
+
+All nested namespaces should be declared together with no blank lines between
+them.
+
+.. code-block:: cpp
+
+  #include "some/header.h"
+
+  namespace pw::nested {
+  namespace {
+
+  constexpr int kAnonConstantGoesHere = 0;
+
+  }  // namespace
+
+  namespace other {
+
+  const char* SomeClass::yes = "no";
+
+  bool ThisIsAFunction() {
+  #if PW_CONFIG_IS_SET
+    return true;
+  #else
+    return false;
+  #endif  // PW_CONFIG_IS_SET
+  }
+
+  extern "C" {
+
+  const int pw_kSomeConstant = 10;
+  int pw_some_global_variable = 600;
+
+  void pw_CFunction() { ... }
+
+  }  // extern "C"
+
+  }  // namespace
+  }  // namespace pw::nested
+
+Using directives for literals
+=============================
+`Using-directives
+<https://en.cppreference.com/w/cpp/language/namespace#Using-directives>`_ (e.g.
+``using namespace ...``) are permitted in implementation files only for the
+purposes of importing literals such as ``std::chrono_literals`` or
+``pw::bytes::unit_literals``. Namespaces that contain any symbols other than
+literals are not permitted in a using-directive. This guidance also has no
+impact on `using-declarations
+<https://en.cppreference.com/w/cpp/language/namespace#Using-declarations>`_
+(e.g. ``using foo::Bar;``).
+
+Rationale: Literals improve code readability, making units clearer at the point
+of definition.
+
+.. code-block:: cpp
+
+  using namespace std::chrono;                    // Not allowed
+  using namespace std::literals::chrono_literals; // Allowed
+
+  constexpr std::chrono::duration delay = 250ms;
+
+Pointers and references
+=======================
+For pointer and reference types, place the asterisk or ampersand next to the
+type.
+
+.. code-block:: cpp
+
+  int* const number = &that_thing;
+  constexpr const char* kString = "theory!"
+
+  bool FindTheOneRing(const Region& where_to_look) { ... }
+
+Prefer storing references over storing pointers. Pointers are required when the
+pointer can change its target or may be ``nullptr``. Otherwise, a reference or
+const reference should be used.
+
+.. _docs-pw-style-macros:
+
+Preprocessor macros
+===================
+Macros should only be used when they significantly improve upon the C++ code
+they replace. Macros should make code more readable, robust, and safe, or
+provide features not possible with standard C++, such as stringification, line
+number capturing, or conditional compilation. When possible, use C++ constructs
+like constexpr variables in place of macros. Never use macros as constants,
+except when a string literal is needed or the value must be used by C code.
+
+When macros are needed, the macros should be accompanied with extensive tests
+to ensure the macros are hard to use wrong.
+
+Stand-alone statement macros
+----------------------------
+Macros that are standalone statements must require the caller to terminate the
+macro invocation with a semicolon (see `Swalling the Semicolon
+<https://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html>`_). For
+example, the following does *not* conform to Pigweed's macro style:
+
+.. code-block:: cpp
+
+  // BAD! Definition has built-in semicolon.
+  #define PW_LOG_IF_BAD(mj) \
+    CallSomeFunction(mj);
+
+  // BAD! Compiles without error; semicolon is missing.
+  PW_LOG_IF_BAD("foo")
+
+Here's how to do this instead:
+
+.. code-block:: cpp
+
+  // GOOD; requires semicolon to compile.
+  #define PW_LOG_IF_BAD(mj) \
+    CallSomeFunction(mj)
+
+  // GOOD; fails to compile due to lacking semicolon.
+  PW_LOG_IF_BAD("foo")
+
+For macros in function scope that do not already require a semicolon, the
+contents can be placed in a ``do { ... } while (0)`` loop.
+
+.. code-block:: cpp
+
+  #define PW_LOG_IF_BAD(mj)  \
+    do {                     \
+      if (mj.Bad()) {        \
+        Log(#mj " is bad")   \
+      }                      \
+    } while (0)
+
+Standalone macros at global scope that do not already require a semicolon can
+add a ``static_assert`` declaration statement as their last line.
+
+.. code-block:: cpp
+
+  #define PW_NEAT_THING(thing)             \
+    bool IsNeat_##thing() { return true; } \
+    static_assert(true, "Macros must be terminated with a semicolon")
+
+Private macros in public headers
+--------------------------------
+Private macros in public headers must be prefixed with ``_PW_``, even if they
+are undefined after use; this prevents collisions with downstream users. For
+example:
+
+.. code-block:: cpp
+
+  #define _PW_MY_SPECIAL_MACRO(op) ...
+  ...
+  // Code that uses _PW_MY_SPECIAL_MACRO()
+  ...
+  #undef _PW_MY_SPECIAL_MACRO
+
+Macros in private implementation files (.cc)
+--------------------------------------------
+Macros within .cc files that should only be used within one file should be
+undefined after their last use; for example:
+
+.. code-block:: cpp
+
+  #define DEFINE_OPERATOR(op) \
+    T operator ## op(T x, T y) { return x op y; } \
+    static_assert(true, "Macros must be terminated with a semicolon") \
+
+  DEFINE_OPERATOR(+);
+  DEFINE_OPERATOR(-);
+  DEFINE_OPERATOR(/);
+  DEFINE_OPERATOR(*);
+
+  #undef DEFINE_OPERATOR
+
+Preprocessor conditional statements
+===================================
+When using macros for conditional compilation, prefer to use ``#if`` over
+``#ifdef``. This checks the value of the macro rather than whether it exists.
+
+* ``#if`` handles undefined macros equivalently to ``#ifdef``. Undefined
+  macros expand to 0 in preprocessor conditional statements.
+* ``#if`` evaluates false for macros defined as 0, while ``#ifdef`` evaluates
+  true.
+* Macros defined using compiler flags have a default value of 1 in GCC and
+  Clang, so they work equivalently for ``#if`` and ``#ifdef``.
+* Macros defined to an empty statement cause compile-time errors in ``#if``
+  statements, which avoids ambiguity about how the macro should be used.
+
+All ``#endif`` statements should be commented with the expression from their
+corresponding ``#if``. Do not indent within preprocessor conditional statements.
+
+.. code-block:: cpp
+
+  #if USE_64_BIT_WORD
+  using Word = uint64_t;
+  #else
+  using Word = uint32_t;
+  #endif  // USE_64_BIT_WORD
+
+Unsigned integers
+=================
+Unsigned integers are permitted in Pigweed. Aim for consistency with existing
+code and the C++ Standard Library. Be very careful mixing signed and unsigned
+integers.
+
+Features not in the C++ standard
+================================
+Avoid features not available in standard C++. This includes compiler extensions
+and features from other standards like POSIX.
+
+For example, use ``ptrdiff_t`` instead of POSIX's ``ssize_t``, unless
+interacting with a POSIX API in intentionally non-portable code. Never use
+POSIX functions with suitable standard or Pigweed alternatives, such as
+``strnlen`` (use ``pw::string::NullTerminatedLength`` instead).
diff --git a/docs/style_guide.rst b/docs/style_guide.rst
index 24a55b7..59fc81d 100644
--- a/docs/style_guide.rst
+++ b/docs/style_guide.rst
@@ -3,11 +3,11 @@
 ===========
 Style Guide
 ===========
-- :ref:`cpp-style`
-- :ref:`owners-style`
+- :ref:`docs-pw-style-cpp`
 - :ref:`python-style`
-- :ref:`documentation-style`
 - :ref:`docs-pw-style-commit-message`
+- :ref:`documentation-style`
+- :ref:`owners-style`
 
 .. tip::
    Pigweed runs ``pw format`` as part of ``pw presubmit`` to perform some code
@@ -17,856 +17,6 @@
 
 .. _cpp-style:
 
----------
-C++ style
----------
-The Pigweed C++ style guide is closely based on Google's external C++ Style
-Guide, which is found on the web at
-https://google.github.io/styleguide/cppguide.html. The Google C++ Style Guide
-applies to Pigweed except as described in this document.
-
-The Pigweed style guide only applies to Pigweed itself. It does not apply to
-projects that use Pigweed or to the third-party code included with Pigweed.
-Non-Pigweed code is free to use features restricted by Pigweed, such as dynamic
-memory allocation and the entirety of the C++ Standard Library.
-
-Recommendations in the :doc:`embedded_cpp_guide` are considered part of the
-Pigweed style guide, but are separated out since it covers more general
-embedded development beyond just C++ style.
-
-C++ standard
-============
-All Pigweed C++ code must compile with ``-std=c++17`` in Clang and GCC. C++20
-features may be used as long as the code still compiles unmodified with C++17.
-See ``pw_polyfill/language_feature_macros.h`` for macros that provide C++20
-features when supported.
-
-Compiler extensions should not be used unless wrapped in a macro or properly
-guarded in the preprocessor. See ``pw_processor/compiler.h`` for macros that
-wrap compiler-specific features.
-
-Automatic formatting
-====================
-Pigweed uses `clang-format <https://clang.llvm.org/docs/ClangFormat.html>`_ to
-automatically format Pigweed source code. A ``.clang-format`` configuration is
-provided with the Pigweed repository.
-
-Automatic formatting is essential to facilitate large-scale, automated changes
-in Pigweed. Therefore, all code in Pigweed is expected to be formatted with
-``clang-format`` prior to submission. Existing code may be reformatted at any
-time.
-
-If ``clang-format`` formats code in an undesirable or incorrect way, it can be
-disabled for the affected lines by adding ``// clang-format off``.
-``clang-format`` must then be re-enabled with a ``// clang-format on`` comment.
-
-.. code-block:: cpp
-
-  // clang-format off
-  constexpr int kMyMatrix[] = {
-      100,  23,   0,
-        0, 542,  38,
-        1,   2, 201,
-  };
-  // clang-format on
-
-C Standard Library
-==================
-In C++ headers, always use the C++ versions of C Standard Library headers (e.g.
-``<cstdlib>`` instead of ``<stdlib.h>``). If the header is used by both C and
-C++ code, only the C header should be used.
-
-In C++ code, it is preferred to use C functions from the ``std`` namespace. For
-example, use ``std::memcpy`` instead of ``memcpy``. The C++ standard does not
-require the global namespace versions of the functions to be provided. Using
-``std::`` is more consistent with the C++ Standard Library and makes it easier
-to distinguish Pigweed functions from library functions.
-
-Within core Pigweed, do not use C standard library functions that allocate
-memory, such as ``std::malloc``. There are exceptions to this for when dynamic
-allocation is enabled for a system; Pigweed modules are allowed to add extra
-functionality when a heap is present; but this must be optional.
-
-C++ Standard Library
-====================
-Much of the C++ Standard Library is not a good fit for embedded software. Many
-of the classes and functions were not designed with the RAM, flash, and
-performance constraints of a microcontroller in mind. For example, simply
-adding the line ``#include <iostream>`` can increase the binary size by 150 KB!
-This is larger than many microcontrollers' entire internal storage.
-
-However, with appropriate caution, a limited set of standard C++ libraries can
-be used to great effect. Developers can leverage familiar, well-tested
-abstractions instead of writing their own. C++ library algorithms and classes
-can give equivalent or better performance than hand-written C code.
-
-A limited subset of the C++ Standard Library is permitted in Pigweed. To keep
-Pigweed small, flexible, and portable, functions that allocate dynamic memory
-must be avoided. Care must be exercised when using multiple instantiations of a
-template function, which can lead to code bloat.
-
-Permitted Headers
------------------
-.. admonition:: The following C++ Standard Library headers are always permitted:
-   :class: checkmark
-
-   * ``<array>``
-   * ``<complex>``
-   * ``<initializer_list>``
-   * ``<iterator>``
-   * ``<limits>``
-   * ``<optional>``
-   * ``<random>``
-   * ``<ratio>``
-   * ``<string_view>``
-   * ``<tuple>``
-   * ``<type_traits>``
-   * ``<utility>``
-   * ``<variant>``
-   * C Standard Library headers (``<c*>``)
-
-.. admonition:: With caution, parts of the following headers can be used:
-   :class: warning
-
-   * ``<algorithm>`` -- be wary of potential memory allocation
-   * ``<atomic>`` -- not all MCUs natively support atomic operations
-   * ``<bitset>`` -- conversions to or from strings are disallowed
-   * ``<functional>`` -- do **not** use ``std::function``; use
-     :ref:`module-pw_function`
-   * ``<mutex>`` -- can use ``std::lock_guard``, use :ref:`module-pw_sync` for
-     mutexes
-   * ``<new>`` -- for placement new
-   * ``<numeric>`` -- be wary of code size with multiple template instantiations
-
-.. admonition:: Never use any of these headers:
-   :class: error
-
-   * Dynamic containers (``<list>``, ``<map>``, ``<set>``, ``<vector>``, etc.)
-   * Streams (``<iostream>``, ``<ostream>``, ``<fstream>``, ``<sstream>`` etc.)
-     -- in some cases :ref:`module-pw_stream` can work instead
-   * ``<span>`` -- use :ref:`module-pw_span` instead. Downstream projects may
-     want to directly use ``std::span`` if it is available, but upstream must
-     use the ``pw::span`` version for compatability
-   * ``<string>`` -- can use :ref:`module-pw_string`
-   * ``<thread>`` -- can use :ref:`module-pw_thread`
-   * ``<future>`` -- eventually :ref:`module-pw_async` will offer this
-   * ``<exception>``, ``<stdexcept>`` -- no exceptions
-   * ``<memory>``, ``<scoped_allocator>`` -- no allocations
-   * ``<regex>``
-   * ``<valarray>``
-
-Headers not listed here should be carefully evaluated before they are used.
-
-These restrictions do not apply to third party code or to projects that use
-Pigweed.
-
-Combining C and C++
-===================
-Prefer to write C++ code over C code, using ``extern "C"`` for symbols that must
-have C linkage. ``extern "C"`` functions should be defined within C++
-namespaces to simplify referring to other code.
-
-C++ functions with no parameters do not include ``void`` in the parameter list.
-C functions with no parameters must include ``void``.
-
-.. code-block:: cpp
-
-  namespace pw {
-
-  bool ThisIsACppFunction() { return true; }
-
-  extern "C" int pw_ThisIsACFunction(void) { return -1; }
-
-  extern "C" {
-
-  int pw_ThisIsAlsoACFunction(void) {
-    return ThisIsACppFunction() ? 100 : 0;
-  }
-
-  }  // extern "C"
-
-  }  // namespace pw
-
-Comments
-========
-Prefer C++-style (``//``) comments over C-style comments (``/* */``). C-style
-comments should only be used for inline comments.
-
-.. code-block:: cpp
-
-  // Use C++-style comments, except where C-style comments are necessary.
-  // This returns a random number using an algorithm I found on the internet.
-  #define RANDOM_NUMBER() [] {                \
-    return 4;  /* chosen by fair dice roll */ \
-  }()
-
-Indent code in comments with two additional spaces, making a total of three
-spaces after the ``//``. All code blocks must begin and end with an empty
-comment line, even if the blank comment line is the last line in the block.
-
-.. code-block:: cpp
-
-  // Here is an example of code in comments.
-  //
-  //   int indentation_spaces = 2;
-  //   int total_spaces = 3;
-  //
-  //   engine_1.thrust = RANDOM_NUMBER() * indentation_spaces + total_spaces;
-  //
-  bool SomeFunction();
-
-Control statements
-==================
-
-Loops and conditionals
-----------------------
-All loops and conditional statements must use braces, and be on their own line.
-
-.. admonition:: **Yes**: Always use braces for line conditionals and loops:
-   :class: checkmark
-
-   .. code-block:: cpp
-
-      while (SomeCondition()) {
-        x += 2;
-      }
-      if (OtherCondition()) {
-        DoTheThing();
-      }
-
-
-.. admonition:: **No**: Missing braces
-   :class: error
-
-   .. code-block:: cpp
-
-      while (SomeCondition())
-        x += 2;
-      if (OtherCondition())
-        DoTheThing();
-
-.. admonition:: **No**: Statement on same line as condition
-   :class: error
-
-   .. code-block:: cpp
-
-      while (SomeCondition()) { x += 2; }
-      if (OtherCondition()) { DoTheThing(); }
-
-
-The syntax ``while (true)`` is preferred over ``for (;;)`` for infinite loops.
-
-.. admonition:: **Yes**:
-   :class: checkmark
-
-   .. code-block:: cpp
-
-      while (true) {
-        DoSomethingForever();
-      }
-
-.. admonition:: **No**:
-   :class: error
-
-   .. code-block:: cpp
-
-      for (;;) {
-        DoSomethingForever();
-      }
-
-
-Prefer early exit with ``return`` and ``continue``
---------------------------------------------------
-Prefer to exit early from functions and loops to simplify code. This is the
-same same conventions as `LLVM
-<https://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code>`_.
-We find this approach is superior to the "one return per function" style for a
-multitude of reasons:
-
-* **Visually**, the code is easier to follow, and takes less horizontal screen
-  space.
-* It makes it clear what part of the code is the **"main business" versus "edge
-  case handling"**.
-* For **functions**, parameter checking is in its own section at the top of the
-  function, rather than scattered around in the fuction body.
-* For **loops**, element checking is in its own section at the top of the loop,
-  rather than scattered around in the loop body.
-* Commit **deltas are simpler to follow** in code reviews; since adding a new
-  parameter check or loop element condition doesn't cause an indentation change
-  in the rest of the function.
-
-The guidance applies in two cases:
-
-* **Function early exit** - Early exits are for function parameter checking
-  and edge case checking at the top. The main functionality follows.
-* **Loop early exit** - Early exits in loops are for skipping an iteration
-  due to some edge case with an item getting iterated over. Loops may also
-  contain function exits, which should be structured the same way (see example
-  below).
-
-.. admonition:: **Yes**: Exit early from functions; keeping the main handling
-   at the bottom and de-dentend.
-   :class: checkmark
-
-   .. code-block:: cpp
-
-      Status DoSomething(Parameter parameter) {
-        // Parameter validation first; detecting incoming use errors.
-        PW_CHECK_INT_EQ(parameter.property(), 3, "Programmer error: frobnitz");
-
-        // Error case: Not in correct state.
-        if (parameter.other() == MyEnum::kBrokenState) {
-          LOG_ERROR("Device in strange state: %s", parametr.state_str());
-          return Status::InvalidPrecondition();
-        }
-
-        // Error case: Not in low power mode; shouldn't do anything.
-        if (parameter.power() != MyEnum::kLowPower) {
-          LOG_ERROR("Not in low power mode");
-          return Status::InvalidPrecondition();
-        }
-
-        // Main business for the function here.
-        MainBody();
-        MoreMainBodyStuff();
-      }
-
-.. admonition:: **No**: Main body of function is buried and right creeping.
-   Even though this is shorter than the version preferred by Pigweed due to
-   factoring the return statement, the logical structure is less obvious. A
-   function in Pigweed containing **nested conditionals indicates that
-   something complicated is happening with the flow**; otherwise it would have
-   the early bail structure; so pay close attention.
-   :class: error
-
-   .. code-block:: cpp
-
-      Status DoSomething(Parameter parameter) {
-        // Parameter validation first; detecting incoming use errors.
-        PW_CHECK_INT_EQ(parameter.property(), 3, "Programmer error: frobnitz");
-
-        // Error case: Not in correct state.
-        if (parameter.other() != MyEnum::kBrokenState) {
-          // Error case: Not in low power mode; shouldn't do anything.
-          if (parameter.power() == MyEnum::kLowPower) {
-            // Main business for the function here.
-            MainBody();
-            MoreMainBodyStuff();
-          } else {
-            LOG_ERROR("Not in low power mode");
-          }
-        } else {
-          LOG_ERROR("Device in strange state: %s", parametr.state_str());
-        }
-        return Status::InvalidPrecondition();
-      }
-
-.. admonition:: **Yes**: Bail early from loops; keeping the main handling at
-   the bottom and de-dentend.
-   :class: checkmark
-
-   .. code-block:: cpp
-
-      for (int i = 0; i < LoopSize(); ++i) {
-        // Early skip of item based on edge condition.
-        if (!CommonCase()) {
-          continue;
-        }
-        // Early exit of function based on error case.
-        int my_measurement = GetSomeMeasurement();
-        if (my_measurement < 10) {
-          LOG_ERROR("Found something strange; bailing");
-          return Status::Unknown();
-        }
-
-        // Main body of the loop.
-        ProcessItem(my_items[i], my_measurement);
-        ProcessItemMore(my_items[i], my_measurement, other_details);
-        ...
-      }
-
-.. admonition:: **No**: Right-creeping code with the main body buried inside
-   some nested conditional. This makes it harder to understand what is the
-   main purpose of the loop versus what is edge case handling.
-   :class: error
-
-   .. code-block:: cpp
-
-      for (int i = 0; i < LoopSize(); ++i) {
-        if (CommonCase()) {
-          int my_measurement = GetSomeMeasurement();
-          if (my_measurement >= 10) {
-            // Main body of the loop.
-            ProcessItem(my_items[i], my_measurement);
-            ProcessItemMore(my_items[i], my_measurement, other_details);
-            ...
-          } else {
-            LOG_ERROR("Found something strange; bailing");
-            return Status::Unknown();
-          }
-        }
-      }
-
-There are cases where this structure doesn't work, and in those cases, it is
-fine to structure the code differently.
-
-No ``else`` after ``return`` or ``continue``
---------------------------------------------
-Do not put unnecessary ``} else {`` blocks after blocks that terminate with a
-return, since this causes unnecessary rightward indentation creep. This
-guidance pairs with the preference for early exits to reduce code duplication
-and standardize loop/function structure.
-
-.. admonition:: **Yes**: No else after return or continue
-   :class: checkmark
-
-   .. code-block:: cpp
-
-      // Note lack of else block due to return.
-      if (Failure()) {
-        DoTheThing();
-        return Status::ResourceExausted();
-      }
-
-      // Note lack of else block due to continue.
-      while (MyCondition()) {
-        if (SomeEarlyBail()) {
-          continue;
-        }
-        // Main handling of item
-        ...
-      }
-
-      DoOtherThing();
-      return OkStatus();
-
-.. admonition:: **No**: Else after return needlessly creeps right
-   :class: error
-
-   .. code-block:: cpp
-
-      if (Failure()) {
-        DoTheThing();
-        return Status::ResourceExausted();
-      } else {
-        while (MyCondition()) {
-          if (SomeEarlyBail()) {
-            continue;
-          } else {
-            // Main handling of item
-            ...
-          }
-        }
-        DoOtherThing();
-        return OkStatus();
-      }
-
-Include guards
-==============
-The first non-comment line of every header file must be ``#pragma once``. Do
-not use traditional macro include guards. The ``#pragma once`` should come
-directly after the Pigweed copyright block, with no blank line, followed by a
-blank, like this:
-
-.. code-block:: cpp
-
-  // Copyright 2021 The Pigweed Authors
-  //
-  // Licensed under the Apache License, Version 2.0 (the "License"); you may not
-  // use this file except in compliance with the License. You may obtain a copy of
-  // the License at
-  //
-  //     https://www.apache.org/licenses/LICENSE-2.0
-  //
-  // Unless required by applicable law or agreed to in writing, software
-  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-  // License for the specific language governing permissions and limitations under
-  // the License.
-  #pragma once
-
-  // Header file-level comment goes here...
-
-Memory allocation
-=================
-Dynamic memory allocation can be problematic. Heap allocations and deallocations
-occupy valuable CPU cycles. Memory usage becomes nondeterministic, which can
-result in a system crashing without a clear culprit.
-
-To keep Pigweed portable, core Pigweed code is not permitted to dynamically
-(heap) allocate memory, such as with ``malloc`` or ``new``. All memory should be
-allocated with automatic (stack) or static (global) storage duration. Pigweed
-must not use C++ libraries that use dynamic allocation.
-
-Projects that use Pigweed are free to use dynamic allocation, provided they
-have selected a target that enables the heap.
-
-Naming
-======
-Entities shall be named according to the `Google style guide
-<https://google.github.io/styleguide/cppguide.html>`_, with the following
-additional requirements.
-
-C++ code
---------
-* All Pigweed C++ code must be in the ``pw`` namespace. Namespaces for modules
-  should be nested under ``pw``. For example, ``pw::string::Format()``.
-* Whenever possible, private code should be in a source (.cc) file and placed in
-  anonymous namespace nested under ``pw``.
-* If private code must be exposed in a header file, it must be in a namespace
-  nested under ``pw``. The namespace may be named for its subsystem or use a
-  name that designates it as private, such as ``internal``.
-* Template arguments for non-type names (e.g. ``template <int kFooBar>``) should
-  follow the constexpr and const variable Google naming convention, which means
-  k prefixed camel case (e.g.  ``kCamelCase``). This matches the Google C++
-  style for variable naming, however the wording in the official style guide
-  isn't explicit for template arguments and could be interpreted to use
-  ``foo_bar`` style naming.  For consistency with other variables whose value is
-  always fixed for the duration of the program, the naming convention is
-  ``kCamelCase``, and so that is the style we use in Pigweed.
-* Trivial membor accessors should be named with ``snake_case()``. The Google
-  C++ style allows either ``snake_case()`` or ``CapsCase()``, but Pigweed
-  always uses ``snake_case()``.
-* Abstract base classes should be named generically, with derived types named
-  specifically. For example, ``Stream`` is an abstract base, and
-  ``SocketStream`` and ``StdioStream`` are an implementations of that
-  interface.  Any prefix or postfix indicating whether something is abstract or
-  concrete is not permitted; for example, ``IStream`` or ``SocketStreamImpl``
-  are both not permitted. These pre-/post-fixes add additional visual noise and
-  are irrelevant to consumers of these interfaces.
-
-C code
-------
-In general, C symbols should be prefixed with the module name. If the symbol is
-not associated with a module, use just ``pw`` as the module name. Facade
-backends may chose to prefix symbols with the facade's name to help reduce the
-length of the prefix.
-
-* Public names used by C code must be prefixed with the module name (e.g.
-  ``pw_tokenizer_*``).
-* If private code must be exposed in a header, private names used by C code must
-  be prefixed with an underscore followed by the module name (e.g.
-  ``_pw_assert_*``).
-* Avoid writing C source (.c) files in Pigweed. Prefer to write C++ code with C
-  linkage using ``extern "C"``. Within C source, private C functions and
-  variables must be named with the ``_pw_my_module_*`` prefix and should be
-  declared ``static`` whenever possible; for example,
-  ``_pw_my_module_MyPrivateFunction``.
-* The C prefix rules apply to
-
-  * C functions (``int pw_foo_FunctionName(void);``),
-  * variables used by C code (``int pw_foo_variable_name;``),
-  * constant variables used by C code (``const int pw_foo_kConstantName;``),
-  * structs used by C code (``typedef struct {} pw_foo_StructName;``), and
-  * all of the above for ``extern "C"`` names in C++ code.
-
-  The prefix does not apply to struct members, which use normal Google style.
-
-Preprocessor macros
--------------------
-* Public Pigweed macros must be prefixed with the module name (e.g.
-  ``PW_MY_MODULE_*``).
-* Private Pigweed macros must be prefixed with an underscore followed by the
-  module name (e.g. ``_PW_MY_MODULE_*``). (This style may change, see
-  `b/234886184 <https://issuetracker.google.com/issues/234886184>`_).
-
-**Example**
-
-.. code-block:: cpp
-
-  namespace pw::my_module {
-  namespace nested_namespace {
-
-  // C++ names (types, variables, functions) must be in the pw namespace.
-  // They are named according to the Google style guide.
-  constexpr int kGlobalConstant = 123;
-
-  // Prefer using functions over extern global variables.
-  extern int global_variable;
-
-  class Class {};
-
-  void Function();
-
-  extern "C" {
-
-  // Public Pigweed code used from C must be prefixed with pw_.
-  extern const int pw_my_module_kGlobalConstant;
-
-  extern int pw_my_module_global_variable;
-
-  void pw_my_module_Function(void);
-
-  typedef struct {
-    int member_variable;
-  } pw_my_module_Struct;
-
-  // Private Pigweed code used from C must be prefixed with _pw_.
-  extern const int _pw_my_module_kPrivateGlobalConstant;
-
-  extern int _pw_my_module_private_global_variable;
-
-  void _pw_my_module_PrivateFunction(void);
-
-  typedef struct {
-    int member_variable;
-  } _pw_my_module_PrivateStruct;
-
-  }  // extern "C"
-
-  // Public macros must be prefixed with PW_.
-  #define PW_MY_MODULE_PUBLIC_MACRO(arg) arg
-
-  // Private macros must be prefixed with _PW_.
-  #define _PW_MY_MODULE_PRIVATE_MACRO(arg) arg
-
-  }  // namespace nested_namespace
-  }  // namespace pw::my_module
-
-See :ref:`docs-pw-style-macros` for details about macro usage.
-
-Namespace scope formatting
-==========================
-All non-indented blocks (namespaces, ``extern "C"`` blocks, and preprocessor
-conditionals) must have a comment on their closing line with the
-contents of the starting line.
-
-All nested namespaces should be declared together with no blank lines between
-them.
-
-.. code-block:: cpp
-
-  #include "some/header.h"
-
-  namespace pw::nested {
-  namespace {
-
-  constexpr int kAnonConstantGoesHere = 0;
-
-  }  // namespace
-
-  namespace other {
-
-  const char* SomeClass::yes = "no";
-
-  bool ThisIsAFunction() {
-  #if PW_CONFIG_IS_SET
-    return true;
-  #else
-    return false;
-  #endif  // PW_CONFIG_IS_SET
-  }
-
-  extern "C" {
-
-  const int pw_kSomeConstant = 10;
-  int pw_some_global_variable = 600;
-
-  void pw_CFunction() { ... }
-
-  }  // extern "C"
-
-  }  // namespace
-  }  // namespace pw::nested
-
-Using directives for literals
-=============================
-`Using-directives
-<https://en.cppreference.com/w/cpp/language/namespace#Using-directives>`_ (e.g.
-``using namespace ...``) are permitted in implementation files only for the
-purposes of importing literals such as ``std::chrono_literals`` or
-``pw::bytes::unit_literals``. Namespaces that contain any symbols other than
-literals are not permitted in a using-directive. This guidance also has no
-impact on `using-declarations
-<https://en.cppreference.com/w/cpp/language/namespace#Using-declarations>`_
-(e.g. ``using foo::Bar;``).
-
-Rationale: Literals improve code readability, making units clearer at the point
-of definition.
-
-.. code-block:: cpp
-
-  using namespace std::chrono;                    // Not allowed
-  using namespace std::literals::chrono_literals; // Allowed
-
-  constexpr std::chrono::duration delay = 250ms;
-
-Pointers and references
-=======================
-For pointer and reference types, place the asterisk or ampersand next to the
-type.
-
-.. code-block:: cpp
-
-  int* const number = &that_thing;
-  constexpr const char* kString = "theory!"
-
-  bool FindTheOneRing(const Region& where_to_look) { ... }
-
-Prefer storing references over storing pointers. Pointers are required when the
-pointer can change its target or may be ``nullptr``. Otherwise, a reference or
-const reference should be used.
-
-.. _docs-pw-style-macros:
-
-Preprocessor macros
-===================
-Macros should only be used when they significantly improve upon the C++ code
-they replace. Macros should make code more readable, robust, and safe, or
-provide features not possible with standard C++, such as stringification, line
-number capturing, or conditional compilation. When possible, use C++ constructs
-like constexpr variables in place of macros. Never use macros as constants,
-except when a string literal is needed or the value must be used by C code.
-
-When macros are needed, the macros should be accompanied with extensive tests
-to ensure the macros are hard to use wrong.
-
-Stand-alone statement macros
-----------------------------
-Macros that are standalone statements must require the caller to terminate the
-macro invocation with a semicolon (see `Swalling the Semicolon
-<https://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html>`_). For
-example, the following does *not* conform to Pigweed's macro style:
-
-.. code-block:: cpp
-
-  // BAD! Definition has built-in semicolon.
-  #define PW_LOG_IF_BAD(mj) \
-    CallSomeFunction(mj);
-
-  // BAD! Compiles without error; semicolon is missing.
-  PW_LOG_IF_BAD("foo")
-
-Here's how to do this instead:
-
-.. code-block:: cpp
-
-  // GOOD; requires semicolon to compile.
-  #define PW_LOG_IF_BAD(mj) \
-    CallSomeFunction(mj)
-
-  // GOOD; fails to compile due to lacking semicolon.
-  PW_LOG_IF_BAD("foo")
-
-For macros in function scope that do not already require a semicolon, the
-contents can be placed in a ``do { ... } while (0)`` loop.
-
-.. code-block:: cpp
-
-  #define PW_LOG_IF_BAD(mj)  \
-    do {                     \
-      if (mj.Bad()) {        \
-        Log(#mj " is bad")   \
-      }                      \
-    } while (0)
-
-Standalone macros at global scope that do not already require a semicolon can
-add a ``static_assert`` declaration statement as their last line.
-
-.. code-block:: cpp
-
-  #define PW_NEAT_THING(thing)             \
-    bool IsNeat_##thing() { return true; } \
-    static_assert(true, "Macros must be terminated with a semicolon")
-
-Private macros in public headers
---------------------------------
-Private macros in public headers must be prefixed with ``_PW_``, even if they
-are undefined after use; this prevents collisions with downstream users. For
-example:
-
-.. code-block:: cpp
-
-  #define _PW_MY_SPECIAL_MACRO(op) ...
-  ...
-  // Code that uses _PW_MY_SPECIAL_MACRO()
-  ...
-  #undef _PW_MY_SPECIAL_MACRO
-
-Macros in private implementation files (.cc)
---------------------------------------------
-Macros within .cc files that should only be used within one file should be
-undefined after their last use; for example:
-
-.. code-block:: cpp
-
-  #define DEFINE_OPERATOR(op) \
-    T operator ## op(T x, T y) { return x op y; } \
-    static_assert(true, "Macros must be terminated with a semicolon") \
-
-  DEFINE_OPERATOR(+);
-  DEFINE_OPERATOR(-);
-  DEFINE_OPERATOR(/);
-  DEFINE_OPERATOR(*);
-
-  #undef DEFINE_OPERATOR
-
-Preprocessor conditional statements
-===================================
-When using macros for conditional compilation, prefer to use ``#if`` over
-``#ifdef``. This checks the value of the macro rather than whether it exists.
-
-* ``#if`` handles undefined macros equivalently to ``#ifdef``. Undefined
-  macros expand to 0 in preprocessor conditional statements.
-* ``#if`` evaluates false for macros defined as 0, while ``#ifdef`` evaluates
-  true.
-* Macros defined using compiler flags have a default value of 1 in GCC and
-  Clang, so they work equivalently for ``#if`` and ``#ifdef``.
-* Macros defined to an empty statement cause compile-time errors in ``#if``
-  statements, which avoids ambiguity about how the macro should be used.
-
-All ``#endif`` statements should be commented with the expression from their
-corresponding ``#if``. Do not indent within preprocessor conditional statements.
-
-.. code-block:: cpp
-
-  #if USE_64_BIT_WORD
-  using Word = uint64_t;
-  #else
-  using Word = uint32_t;
-  #endif  // USE_64_BIT_WORD
-
-Unsigned integers
-=================
-Unsigned integers are permitted in Pigweed. Aim for consistency with existing
-code and the C++ Standard Library. Be very careful mixing signed and unsigned
-integers.
-
-Features not in the C++ standard
-================================
-Avoid features not available in standard C++. This includes compiler extensions
-and features from other standards like POSIX.
-
-For example, use ``ptrdiff_t`` instead of POSIX's ``ssize_t``, unless
-interacting with a POSIX API in intentionally non-portable code. Never use
-POSIX functions with suitable standard or Pigweed alternatives, such as
-``strnlen`` (use ``pw::string::NullTerminatedLength`` instead).
-
-.. _owners-style:
-
---------------------
-Code Owners (OWNERS)
---------------------
-If you use Gerrit for source code hosting and have the
-`code-owners <https://android-review.googlesource.com/plugins/code-owners/Documentation/backend-find-owners.html>`__
-plug-in enabled Pigweed can help you enforce consistent styling on those files
-and also detects some errors.
-
-The styling follows these rules.
-
-#. Content is grouped by type of line (Access grant, include, etc).
-#. Each grouping is sorted alphabetically.
-#. Groups are placed the following order with a blank line separating each
-   grouping.
-
-   * "set noparent" line
-   * "include" lines
-   * "file:" lines
-   * user grants (some examples: "*", "foo@example.com")
-   * "per-file:" lines
-
-This plugin will, by default, act upon any file named "OWNERS".
-
 .. _python-style:
 
 ------------
@@ -1821,7 +971,33 @@
 
       More Windows instructions...
 
+.. _owners-style:
+
+--------------------
+Code Owners (OWNERS)
+--------------------
+If you use Gerrit for source code hosting and have the
+`code-owners <https://android-review.googlesource.com/plugins/code-owners/Documentation/backend-find-owners.html>`__
+plug-in enabled Pigweed can help you enforce consistent styling on those files
+and also detects some errors.
+
+The styling follows these rules.
+
+#. Content is grouped by type of line (Access grant, include, etc).
+#. Each grouping is sorted alphabetically.
+#. Groups are placed the following order with a blank line separating each
+   grouping.
+
+   * "set noparent" line
+   * "include" lines
+   * "file:" lines
+   * user grants (some examples: "*", "foo@example.com")
+   * "per-file:" lines
+
+This plugin will, by default, act upon any file named "OWNERS".
+
 .. toctree::
    :hidden:
 
+   C++ <style/cpp>
    Commit message <style/commit_message>