LLVM Coding Standards(译注)

博客迁移已迁移到https://www.guyuemeng.com

LLVM Coding Standards(LLVM编码规范)

Introduction(简介)

This document attempts to describe a few coding standards that are being used in the LLVM source tree. Although no coding standards should be regarded as absolute requirements to be followed in all instances, coding standards are particularly important for large-scale code bases that follow a library-based design (like LLVM).

【译】本文描述了一些LLVM源码库中正在使用的编码规范。虽说并不存在可以完美适用于所有场景的编码规范,但编码规范对大规模代码工程还是比较重要的,尤其是做类库设计(如LLVM)。

While this document may provide guidance for some mechanical formatting issues, whitespace, or other “microscopic details”, these are not fixed standards. Always follow the golden rule:

If you are extending, enhancing, or bug fixing already implemented code, use the style that is already being used so that the source is uniform and easy to follow.

【译】虽然本文对一些纯格式问题(如空格等小细节)提供了指导,但这并不是一成不变的标准。往往遵循以下黄金准则:

如果在存量代码中进行扩展、增强或问题修复,遵循存量代码的编码风格。这样保证了源码风格统一,大家更容易去遵循。

Note that some code bases (e.g. libc++) have really good reasons to deviate from the coding standards. In the case of libc++, this is because the naming and other conventions are dictated by the C++ standard. If you think there is a specific good reason to deviate from the standards here, please bring it up on the LLVM-dev mailing list.

【译】请注意,有一些代码库有比较好的理由不遵从该编码规范,如libc++,其命名以及其他约定由C++标准所制定。如果你有一个明确的好理由需要违反该编码规范,请在LLVM-dev邮件列表中提出。

There are some conventions that are not uniformly followed in the code base (e.g. the naming convention). This is because they are relatively new, and a lot of code was written before they were put in place. Our long term goal is for the entire codebase to follow the convention, but we explicitly do not want patches that do large-scale reformatting of existing code. On the other hand, it is reasonable to rename the methods of a class if you’re about to change it in some other way. Just do the reformatting as a separate commit from the functionality change.

【译】代码库中,有一些约定(如命名规则)并没有统一遵守,这是因为在它们之前就已经编写了大量代码,它们的添加相对较新。我们的长期目标肯定是使整个代码库都遵循该规范,但我们也不希望在补丁包中做大量的基础代码重构。另一方面,如果你想以其他方式重命名类成员函数,这是合理的,但需要将重构代码单独提交,请勿和功能代码混在一起。

The ultimate goal of these guidelines is to increase the readability and maintainability of our common source base. If you have suggestions for topics to be included, please mail them to Chris.

【译】这些指导的最终目标是提升我们公共代码库的可读性和可维护性。如果你有些新增项的建议,请给Chris邮件。

【注】编码规范大致可以分为格式规范与安全规范两类,而安全规范又可以分为功能性规范与攻击防护型规范。格式规范往往遵从工作模块的整体风格,其注重团队成员编码和阅读无障碍,并不是所有规范都有完善的理由,更倾向于公约;功能性规范关注在编程语言使用上的陷阱,由于编程语言设计的通用性、应用场景的扩张、软硬件的革新等等原因,一些写法或组合更容易导致功能性问题,或在可扩展性可阅读性等方面有更好的设计,这类规范的理由比较充分;攻击防护型规范指的是编程语言设计的缺陷,或应用场景的限制,如脚本注入、不安全随机数等。

Languages, Libraries, and Standards(语言、库和标准)

Most source code in LLVM and other LLVM projects using these coding standards is C++ code. There are some places where C code is used either due to environment restrictions, historical restrictions, or due to third-party source code imported into the tree. Generally, our preference is for standards conforming, modern, and portable C++ code as the implementation language of choice.

【译】LLVM以及使用该编码规范的其他LLVM工程,其大部分源码均是用C++编写,但由于环境限制、历史原因或第三方源码库的导入,目前仍存在一些C代码。通常来说,我们更倾向于把符合规范的、可移植的C++代码作为实现语言的首选。

C++ Standard Versions(C++标准版本)

LLVM, Clang, and LLD are currently written using C++11 conforming code, although we restrict ourselves to features which are available in the major toolchains supported as host compilers. The LLDB project is even more aggressive in the set of host compilers supported and thus uses still more features. Regardless of the supported features, code is expected to (when reasonable) be standard, portable, and modern C++11 code. We avoid unnecessary vendor-specific extensions, etc.

【译】虽然我们仅限于使用主流编译器支持的核心工具链所使用的C++特性,但当前LLVM、Clang和LLD均使用C++实现。LLDB工程在使用各主流编译器支持的特性上,显得更为激进,它使用了更多的C++特性。除了已支持的特性,在合理的情况下,代码都应该由标准的、可移植的C++11编写。我们不会接纳非必要的、小众特化的扩展。

C++ Standard Library(C++标准库)

Use the C++ standard library facilities whenever they are available for a particular task. LLVM and related projects emphasize and rely on the standard library facilities for as much as possible. Common support libraries providing functionality missing from the standard library for which there are standard interfaces or active work on adding standard interfaces will often be implemented in the LLVM namespace following the expected standard interface.

【译】只要对特定任务可用,请使用C++标准库。LLVM以及相关项目都尽可能的依赖于标准库。对于公共库中缺失的功能,如果有标准接口或待添加标准接口,那么通常会在LLVM命名空间下,按照期望的标准接口实现。

There are some exceptions such as the standard I/O streams library which are avoided. Also, there is much more detailed information on these subjects in the LLVM Programmer’s Manual.

【译】也有一些例外,如标准库中的I/O流操作是被禁用的。另外,对于这块更多的详情可参考《LLVM Programmer’s Manual》。

Supported C++11 Language and Library Features(支持的C++11语言与库特性)

While LLVM, Clang, and LLD use C++11, not all features are available in all of the toolchains which we support. The set of features supported for use in LLVM is the intersection of those supported in the minimum requirements described in the Getting Started with the LLVM System page, section Software. The ultimate definition of this set is what build bots with those respective toolchains accept. Don’t argue with the build bots. However, we have some guidance below to help you know what to expect.

【译】虽然LLVM、Clang和LLD均使用C++11,但并不是所有C++11特性都可用于我们支持的全部工具链。LLVM可用的C++11特性集是《Getting Started with the LLVM System》中Software章节所描述的最小需求的交集。这个特性集的最终确立来源于各工具链所接纳特性集的自动构建。一切以自动构建为准。同时,我们下面有一些指导来帮助了解哪些特性是可用的。

Each toolchain provides a good reference for what it accepts:

【译】每个工具链均对其接纳的特性提供了很好地参考:

In most cases, the MSVC list will be the dominating factor. Here is a summary of the features that are expected to work. Features not on this list are unlikely to be supported by our host compilers.

【译】大多数情况下,MSVC列表将是主导因素。以下是可用特性的概要信息,除此之外的特性并不太可能被我们主流编译器所支持。

  • Rvalue references: N2118

    • But not Rvalue references for *this or member qualifiers (N2439)

【注】右值引用:除*this和成员修饰符(ref-qualifiers)的右值引用

【注】静态断言:static_assert,对常量表达式和模板参数在编译期进行检查

【注】自动类型推导:auto关键字

  • Trailing return types: N2541

【注】尾置返回类型:lambda返回值类型表示,以及解决通过decltype推导依赖输入的返回值类型时,编译器尚未捕获输入类型的缺陷。

Trailing return type, useful if the return type depends on argument names, such as

template <class T, class U>
auto add(T t, U u) -> decltype(t + u);

or is complicated, such as in

auto fpif(int)->int(*)(int)
  • Lambdas: N2927

    • But not lambdas with default arguments.

【注】lambda表达式:除默认参数上的lambda表达式***(存疑)***

A lambda-expression appearing in a default argument shall not implicitly or explicitly capture any entity. [ Example:

void f2() {
  int i = 1;
  void g1(int = ([i]{ return i; })());			// ill-formed
  void g2(int = ([i]{ return 0; })());			// ill-formed
  void g3(int = ([=]{ return i; })());			// ill-formed
  void g4(int = ([=]{ return 0; })());			// OK
  void g5(int = ([]{ return sizeof i; })());	// OK
}

—end example ]

  • decltype: N2343
  • Nested closing right angle brackets: N1757

【注】模板右尖括号嵌套:c98版本模板中>>会被解析为右移,需要添加空格隔开> >,C++11开始支持叠用

  • Extern templates: N1987

【注】外部模板:非模板函数的extern声明关键字,扩展到模板函数

【注】模板特化场景下,0NULL作为空指针时,推导类型为int而非*,导致匹配错误。

  • Strongly-typed and forward declarable enums: N2347, N2764

【注】强类型枚举:enum class代替enum可解决同命名空间下不同枚举类型拥有相同枚举成员名会报错的问题;C++03版本枚举类型视为整数,可与整数、其他枚举类型比较和互转,强枚举类型限制了这种不安全的隐式转换。

  • Local and unnamed types as template arguments: N2657

【译】局部类型和匿名类型作为模板实参

  • Range-based for-loop: N2930

    • But {} are required around inner do {} while() loops. As a result, {} are required around function-like macros inside range-based for loops.

【注】基于范围的for循环:内部使用do {} while()时,需要添加{}。同样,基于范围的for循环内部的函数式宏也需要{}包围。

【注】override通过编译检查,确保子类虚函数重写基类虚函数,若子类与基类虚函数不一致,则编译报错;final标记在类上时,该类无法被继承,final标记在虚函数上,虚函数无法被子类重写,否则编译报错。

  • Atomic operations and the C++11 memory model: N2429

【注】原子操作与C++11内存模型:并发与线程安全

  • Variadic templates: N2242

【译】变参模板

  • Explicit conversion operators: N2437

【注】显示类型转换运算符:

struct B {
    explicit B(int) { }
    explicit B(int, int) { }
    explicit operator bool() const { return true; }
};
B b1 = 1;      // 错误:复制初始化不考虑 B::B(int)
B b2(2);       // OK:直接初始化选择 B::B(int)
B b3 {4, 5};   // OK:直接列表初始化选择 B::B(int, int)
B b4 = {4, 5}; // 错误:复制列表初始化不考虑 B::B(int,int)
B b5 = (B)1;   // OK:显式转型进行 static_cast
if (b2);       // OK:B::operator bool()
bool nb1 = b2; // 错误:复制初始化不考虑 B::operator bool()
bool nb2 = static_cast<bool>(b2); // OK:static_cast 进行直接初始化
  • Defaulted and deleted functions: N2346

【注】默认函数:default关键字;删除函数:delete关键字

  • Initializer lists: N2627

【译】初始化列表

  • Delegating constructors: N1986

【注】委托构造函数:一个类的构造函数可以通过调用它的其他构造进行初始化,但其自身不能再初始化成员变量。

  • Default member initializers (non-static data member initializers): N2756

    • Feel free to use these wherever they make sense and where the = syntax is allowed. Don’t use braced initialization syntax.

【注】默认成员初始化(非静态成员初始化):成员初始化列表优先级高于默认成员初始化。此场景下,请勿使用大括号初始化语法C c4 = C{};

The supported features in the C++11 standard libraries are less well tracked, but also much greater. Most of the standard libraries implement most of C++11’s library. The most likely lowest common denominator is Linux support. For libc++, the support is just poorly tested and undocumented but expected to be largely complete. YMMV. For libstdc++, the support is documented in detail in the libstdc++ manual. There are some very minor missing facilities that are unlikely to be common problems, and there are a few larger gaps that are worth being aware of:

【译】C++11标准库中支持的特性跟踪的不太好,而且这个量还比较大。大多数标准库实现了大部分C++11库中的特性。目测Linux支持的特性可能是最少的。对于libc++,支持的特性也缺少测试和文档,但预计大部分会完善。对于libstdc++,其中手册中详细记录支持的特性。有一些非常小的缺失特性,这不太可能是普遍的问题,倒是有一些大的缺口需要特别注意:

  • Not all of the type traits are implemented

【译】不是所有类型萃取都已实现

  • No regular expression library.

【译】无正则表达式库

  • While most of the atomics library is well implemented, the fences are missing. Fortunately, they are rarely needed.

【译】大多数原子库都实现的很好,但栅栏(约束内存乱序)相关内容缺失了。幸运的是,他们极少被用到。

  • The locale support is incomplete.

【译】系统区域设置(国家或地区设置)的支持不完善。

Other than these areas you should assume the standard library is available and working as expected until some build bot tells you otherwise. If you’re in an uncertain area of one of the above points, but you cannot test on a Linux system, your best approach is to minimize your use of these features, and watch the Linux build bots to find out if your usage triggered a bug. For example, if you hit a type trait which doesn’t work we can then add support to LLVM’s traits header to emulate it.

【译】除了这些点,你应该认为标准库是可用的,而且会按照预期工作,直到某些构建工具提示错误。如果你对上述某个点不确认,而且无法在Linux系统上进行测试,那最好少用这些特性,以及通过Linux构建工具来找出你的使用是否触发了缺陷。

Other Languages(其他语言)

Any code written in the Go programming language is not subject to the formatting rules below. Instead, we adopt the formatting rules enforced by the gofmt tool.

【译】Go语言编写的代码不受以下格式限制。作为替代,我们选用gofmt工具强制执行格式规范。

Go code should strive to be idiomatic. Two good sets of guidelines for what this means are Effective Go and Go Code Review Comments.

【译】Go代码应该尽量符合其语言习惯。《Effective Go》和《Go Code Review Comments》对Go语言都是很好的指导 。

Mechanical Source Issues

Source Code Formatting(源码格式)

Commenting(注释)

Comments are one critical part of readability and maintainability. Everyone knows they should comment their code, and so should you. When writing comments, write them as English prose, which means they should use proper capitalization, punctuation, etc. Aim to describe what the code is trying to do and why, not how it does it at a micro level. Here are a few critical things to document:

【译】注释是可读性和可维护性的关键组成部分。每个人都知道他们应该给代码添加注释,你也是。像写英语散文一样去写注释,这也意味着注释应该使用适当的大写、标点等。**着重描述代码在做什么、为什么这么做,而不是微观层面的代码是怎么实现的。**以下是一些比较重要的内容,需要添加注释:

File Headers(文件头)

Every source file should have a header on it that describes the basic purpose of the file. If a file does not have a header, it should not be checked into the tree. The standard header looks like this:

每个源文件都应该有一个描述其基础用途的文件头注释。如果没有文件头注释,那么该文件不应该添加进代码分支中。标准文件头注释格式如下:

//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the declaration of the Instruction class, which is the
/// base class for all of the VM instructions.
///
//===----------------------------------------------------------------------===//

A few things to note about this particular format: The “-*- C++ -*-” string on the first line is there to tell Emacs that the source file is a C++ file, not a C file (Emacs assumes .h files are C files by default).

【译】关于这种特殊格式需要注意:第一行的“-*- C++ -*-”用于告知Emacs这是个C++文件,而非C文件(Emacs默认.h为C文件)。

Note(注意)

This tag is not necessary in .cpp files. The name of the file is also on the first line, along with a very short description of the purpose of the file. This is important when printing out code and flipping though lots of pages.

【译】.cpp文件中无需这个标记。文件名以及很短的文件用途描述也写在第一行,这在打印代码并且要翻阅很多页面时非常重要。

The next section in the file is a concise note that defines the license that the file is released under. This makes it perfectly clear what terms the source code can be distributed under and should not be modified in any way.

【译】文件的下一段是对文件发布许可的简明注释。这清楚的表明了,在什么条件下源码可以传播,以及不应以任何方式进行修改。

The main body is a doxygen comment (identified by the /// comment marker instead of the usual //) describing the purpose of the file. The first sentence (or a passage beginning with \brief) is used as an abstract. Any additional information should be separated by a blank line. If an algorithm is being implemented or something tricky is going on, a reference to the paper where it is published should be included, as well as any notes or gotchas in the code to watch out for.

【译】主体部分以doxygen注释格式(用///注释标记而非//)描述了该文件的目的。第一句(以\brief开头的段落)作为摘要,任何其他信息应以空行分隔。如果有正在实现的算法或正在处理的棘手问题,则需要包含相关论文的引用,以及代码注意项或陷阱。

Class overviews(类的概述)

Classes are one fundamental part of a good object oriented design. As such, a class definition should have a comment block that explains what the class is used for and how it works. Every non-trivial class is expected to have adoxygen comment block.

【译】类是一个良好面向对象设计的基础部分。因此,类定义需要包含一个注释块,用于解释类的用途以及工作原理。每个重要类都需要有

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值