Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can clang-format break my code?

Tags:

c

clang-format

As clang-format is a tool to only reformat code, is it possible that such formatting can break working code or at least change how it works? Is there some kind of contract that it will/can not change how code works?

We have a lot of code that we want to format with clang-format. This means, many lines of code will change. Not having to review every single line of code that only changed due to a clang-format would be a big simplification of this process.

I would say that clang-format will not change how code works. On the other hand I am not 100% sure, if this can be guaranteed.

like image 633
JFB Avatar asked Jun 20 '16 16:06

JFB


People also ask

Should I use clang-format?

clang-format is a tool to automatically format C/C++/Objective-C code, so that developers don't need to worry about style issues during code reviews. It is highly recommended to format your changed C++ code before opening pull requests, which will save you and the reviewers' time.

Does Google use clang-format?

Clang-Format Style Options are flags that are supported by the ClangFormat tool, which became the de-facto standard to format C++ code. Clang offers the option to use one of the predefined styles (LLVM, Google, Chromium, Mozilla, WebKit, Microsoft) or to create a custom configuration by using the given flags.

What is the use of clang-format?

Clang-Format is a widely-used C++ code formatter. As it provides an option to define code style options in YAML-formatted files — named . clang-format or _clang-format — these files often become a part of your project where you keep all code style rules.

Does clang-format work for C?

clang-format is located in clang/tools/clang-format and can be used to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code.


1 Answers

Short answer: YES.


The clang-format tool has a -sort-includes option. Changing the order of #include directives can definitely change the behavior of existing code, and may break existing code.

Since the corresponding SortIncludes option is set to true by several of the built-in styles, it might not be obvious that clang-format is going to reorder your includes.

MyStruct.h:

struct MyStruct {     uint8_t value; }; 

original.c:

#include <stdint.h> #include <stddef.h> #include "MyStruct.h"  int main (int argc, char **argv) {     struct MyStruct s = { 0 };     return s.value; } 

Now let's say we run clang-format -style=llvm original.c > restyled.c.

restyled.c:

#include "MyStruct.h" #include <stddef.h> #include <stdint.h>  int main(int argc, char **argv) {   struct MyStruct s = {0};   return s.value; } 

Due to the reordering of the header files, I get the following error when compiling restyled.c:

In file included from restyled.c:1: ./MyStruct.h:2:5: error: unknown type name 'uint8_t'     uint8_t value;     ^ 1 error generated. 

However, this issue should be easy to work around. It's unlikely that you have order-dependent includes like this, but if you do, you can fix the problem by putting a blank line between groups of headers that require a specific order, since apparently clang-format only sorts groups of #include directives with no non-#include lines in between.

fixed-original.c:

#include <stdint.h> #include <stddef.h>  #include "MyStruct.h"  int main (int argc, char **argv) {     struct MyStruct s = { 0 };     return s.value; } 

fixed-restyled.c:

#include <stddef.h> #include <stdint.h>  #include "MyStruct.h"  int main(int argc, char **argv) {   struct MyStruct s = {0};   return s.value; } 

Note that stdint.h and stddef.h were still reordered since their includes are still "grouped", but that the new blank line prevented MyStruct.h from being moved before the standard library includes.


However...

If reordering your #include directives breaks your code, you should probably do one of the following anyway:

  1. Explicitly include the dependencies for each header in the header file. In my example, I'd need to include stdint.h in MyStruct.h.

  2. Add a comment line between the include groups that explicitly states the ordering dependency. Remember that any non-#include line should break up a group, so comment lines work as well. The comment line in the following code also prevents clang-format from including MyStruct.h before the standard library headers.

alternate-original.c:

#include <stdint.h> #include <stddef.h> // must come after stdint.h #include "MyStruct.h"  int main (int argc, char **argv) {     struct MyStruct s = { 0 };     return s.value; } 
like image 58
DaoWen Avatar answered Sep 25 '22 03:09

DaoWen