SlideShare a Scribd company logo
Hands on clang-format
Adding (n)one feature at a time
Kai Wolf
kai-wolf.me
March 31, 2016
A quick reality check - please raise hand
• We have a (living) coding style guide
• We use code generators
• We do (semi-)automatized refactoring (clang-tidy, Clang
MapReduce, awk | grep | sed, ...)
• We use automatic code formatting tools
• We utilize pre/post-commit hooks for these kind of stuff
2 / 25
Why is it important?
• Inconsistent formatting distracts the reader
• Formatting code by hand is tedious
• Nobody reads the style guide anyways
• Automatic/large scale refactoring not feasible without automatic
code formatting
3 / 25
Lots of auto formatting tools available
Artistic Style (AStyle)
Works. Focuses only on indentation and brace/bracket placement
Uncrustify
Many, many, many rules (around ~200). Might take a whole day to
adjust to own style guide.
GNU indent
Works most of the time (see OpenSSL Blog - CodeReformat Finished).
Basically has three presets available (Ansi, GNU, K&R). Indent needs
to know about all types used within the code.
GC GreatCode
Intrusive formatting rules. May break your code.
4 / 25
How to use clang-format
$ cat bbox.cpp
cv::Rect BoundingBox::getBoundingRect(const cv::Mat& Binary) const {
assert(Binary.channels() == 1);
using Contour = std::vector<cv::Point>;
std::vector<Contour> contours;
auto hierarchy = std::vector<cv::Vec4i>();
cv::findContours(Binary.clone(),contours,hierarchy,CV_RETR_TREE,
CV_CHAIN_APPROX_SIMPLE);
auto result = *std::max_element(contours.begin(), contours.end(),
[](Contour a, Contour b) {
return cv::contourArea(a) < cv::contourArea(b);});
return cv::boundingRect(cv::Mat(result));}
5 / 25
How to use clang-format
$ cat bbox.cpp | clang-format -style=’{BasedOnStyle: Google, IndentWidth: 4’
cv::Rect BoundingBox::getBoundingRect(const cv::Mat& Binary) const {
assert(Binary.channels() == 1);
using Contour = std::vector<cv::Point>;
std::vector<Contour> contours;
auto hierarchy = std::vector<cv::Vec4i>();
cv::findContours(Binary.clone(), contours, hierarchy, CV_RETR_TREE,
CV_CHAIN_APPROX_SIMPLE);
auto result = *std::max_element(
contours.begin(), contours.end(), [](Contour a, Contour b) {
return cv::contourArea(a) < cv::contourArea(b);
});
return cv::boundingRect(cv::Mat(result));
}
6 / 25
How to use clang-format
Plugins available for Vi, Emacs, Visual Studio etc. Custom integration
almost always possible. For example: CLion
7 / 25
How to use clang-format
There are many deliberate options available:
Release Number of options
clang-format v3.5 53
clang-format v3.6 62
clang-format v3.7 65
clang-format v3.8 70
clang-format v3.9 75
8 / 25
Motivating example
Say for example, our style guide suggests that this:
void foo(int a, int b, double c, const char* str);
should be formatted like this:
void foo(int a,int b,double c,const char* str);
9 / 25
What does clang-format offer here?
10 / 25
Let’s try to fix that
In order to start hacking we need the llvm repository with the
following subprojects:
$ export LLVM_SVN=http://llvm.org/svn/llvm-project
$ svn co ${LLVM_SVN}/llvm/trunk llvm
$ cd llvm/tools
$ svn co ${LLVM_SVN}/cfe/trunk clang
$ cd ../projects
$ svn co ${LLVM_SVN}/test-suite/trunk test-suite
$ cd ../tools/clang/tools
$ svn co ${LLVM_SVN}/clang-tools-extra/trunk extra
11 / 25
Navigate around the code base
Formatting rules for clang-format are located in
llvm/tools/clang/lib/Format/
Unittests are located in
llvm/tools/clang/unittests/Format/
Frontend for clang-format
$ cd llvm/tools/clang # clang subproject
$ cat tools/clang-format/ClangFormat.cpp
int main(int argc, const char **argv) {
...
for (unsigned i = 0; i < FileNames.size(); ++i)
Error |= clang::format::format(FileNames[i]);
12 / 25
clang::format::format
static bool format(StringRef FileName) {
...
if (fillRanges(Code.get(), Ranges))
return true;
...
FormatStyle FormatStyle =
getStyle(Style, AssumedFileName, FallbackStyle)
...
Replacements Replaces =
sortIncludes(FormatStyle, Code, Ranges)
...
Replacements FormatChanges =
reformat(FormatStyle, ChangedCode, Ranges)
}
13 / 25
clang::format::reformat
...
for (const tooling::Range &Range : Ranges) {
SourceLocation Start =
StartOfFile.getLocWithOffset(
Range.getOffset());
SourceLocation End =
Start.getLocWithOffset(Range.getLength());
CharRanges.push_back(
CharSourceRange::getCharRange(Start, End));
}
return reformat(Style, SourceMgr, ID, CharRanges,
IncompleteFormat);
14 / 25
clang::format::reformat
FormatStyle Expanded = expandPresets(Style);
if (Expanded.DisableFormat)
return tooling::Replacements();
Formatter formatter(Expanded, SourceMgr, ID,
Ranges);
return formatter.format(IncompleteFormat);
15 / 25
clang::tok::TokenKind
void foo(int a, int b);
UnwrappedLineParser Parser();
-> readTokens();
-> parseFile();
-> parseLevel();
-> parseStructuralElement();
<- AnnotatedLines
0 kw_void
1 identifier
2 l_param
3 kw_int
4 identifier
5 comma
6 kw_int
7 identifier
8 r_param
9 semi
16 / 25
clang::format
For each annotated line (TokenAnnotator.cpp):
void TokenAnnotator::
calculateFormattingInformation(
AnnotatedLine &Line);
Fortunately not much to do here for us:
bool TokenAnnotator::spaceRequiredBetween(
const AnnotatedLine &Line,
const FormatToken &Left,
const FormatToken &Right);
17 / 25
Our patch (excerpt)
Format.h
/// b If c true, spaces will be inserted between
/// function parameters.
bool SpacesBetweenFunctionParameters;
TokenAnnotator.cpp
...
if (Right.is(TT_OverloadedOperatorLParen))
return Style.SpaceBeforeParens ==
FormatStyle::SBPO_Always;
if (Left.is(tok::comma))
// return true;
return Style.SpacesBetweenFunctionParameters;
if (Right.is(tok::comma))
return false;
18 / 25
Preparing the patch
Tests are looking good.
TEST_F(FormatTest, SpacesBetweenFunctionParameters) {
FormatStyle Spaces = getLLVMStyle();
Spaces.SpacesBetweenFunctionParameters = false;
verifyFormat("void foo(int a);", Spaces);
verifyFormat("void foo(int a,double b);", Spaces);
verifyFormat("void foo(int a,double b,char c);", Spaces);
Spaces.SpacesBetweenFunctionParameters = true;
verifyFormat("void foo(int a, double b);", Spaces);
verifyFormat("void foo(int a, double b, char c);", Spaces);
}
By the way: If you manage an open source project, make sure to
explain how to contribute!
• How to get going? How to submit your patch?
• Who decides what patches are accepted?
• Who should review your patch?
• What should be included in the patch? (doc, unittests, full file
context diff etc.)
19 / 25
Oops..
http://reviews.llvm.org/D16765
20 / 25
That paragraph must be new...
21 / 25
Yes, indeed
By the time I’ve created the patch, clang-format 3.7 was the current
release
22 / 25
Yet there’s hope..
https://github.com/hankhank/clang
23 / 25
I don’t always accidentally...
24 / 25
25 / 25

More Related Content

PDF
Boosting Developer Productivity with Clang
PDF
Clang Analyzer Tool Review
PDF
Clang: More than just a C/C++ Compiler
PDF
[COSCUP 2020] How to use llvm frontend library-libtooling
PDF
차세대컴파일러, VM의미래: 애플 오픈소스 LLVM
PDF
[COSCUP 2021] A trip about how I contribute to LLVM
PDF
Thesis - LLVM toolchain support as a plug-in for Eclipse CDT
PDF
Introduction to the LLVM Compiler System
Boosting Developer Productivity with Clang
Clang Analyzer Tool Review
Clang: More than just a C/C++ Compiler
[COSCUP 2020] How to use llvm frontend library-libtooling
차세대컴파일러, VM의미래: 애플 오픈소스 LLVM
[COSCUP 2021] A trip about how I contribute to LLVM
Thesis - LLVM toolchain support as a plug-in for Eclipse CDT
Introduction to the LLVM Compiler System

What's hot (20)

PDF
LAS16-501: Introduction to LLVM - Projects, Components, Integration, Internals
PDF
Ruxmon.2013-08.-.CodeBro!
PPT
PDF
Where is LLVM Being Used Today?
ODP
GCC, GNU compiler collection
PDF
A Close Look at ARM Code Size
PDF
GCC Compiler as a Performance Testing tool for C programs
PDF
Whirlwind tour of the Runtime Dynamic Linker
PDF
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
PPT
Virtual platform
PDF
Semi-Automatic Code Cleanup with Clang-Tidy
PPTX
MinGw Compiler
PDF
LLVM Compiler - Link Time Optimization
PDF
Claire protorpc
PDF
Code quality par Simone Civetta
PDF
Debugging of (C)Python applications
PDF
Fast and Reliable Swift APIs with gRPC
PDF
CSW2017 Henry li how to find the vulnerability to bypass the control flow gua...
PPTX
Review: Apitrace and Vogl
PDF
Debugging Python with gdb
LAS16-501: Introduction to LLVM - Projects, Components, Integration, Internals
Ruxmon.2013-08.-.CodeBro!
Where is LLVM Being Used Today?
GCC, GNU compiler collection
A Close Look at ARM Code Size
GCC Compiler as a Performance Testing tool for C programs
Whirlwind tour of the Runtime Dynamic Linker
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Virtual platform
Semi-Automatic Code Cleanup with Clang-Tidy
MinGw Compiler
LLVM Compiler - Link Time Optimization
Claire protorpc
Code quality par Simone Civetta
Debugging of (C)Python applications
Fast and Reliable Swift APIs with gRPC
CSW2017 Henry li how to find the vulnerability to bypass the control flow gua...
Review: Apitrace and Vogl
Debugging Python with gdb
Ad

Similar to Hands on clang-format (20)

DOCX
hw1.docxCS 211 Homework #1Please complete the homework problem.docx
PPTX
CPP Homework Help
PDF
Design Patterns in Modern C++
PDF
Introduction to CMake
PDF
talk at Virginia Bioinformatics Institute, December 5, 2013
PDF
Effective CMake
PPTX
Computer Science Assignment Help
PPTX
Дмитрий Нестерук, Паттерны проектирования в XXI веке
PPTX
C++ process new
PDF
Editors l21 l24
PPTX
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
PDF
The use of the code analysis library OpenC++: modifications, improvements, er...
PDF
I am trying to create a program That works with two other programs i.pdf
PDF
Building reusable libraries
PDF
ez-clang C++ REPL for bare-metal embedded devices
PDF
Bioinformatica: Esercizi su Perl, espressioni regolari e altre amenità (BMR G...
PDF
Simple Ways To Be A Better Programmer (OSCON 2007)
PDF
Perl6 Regexen: Reduce the line noise in your code.
PDF
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
PDF
Introduction-to-C-Part-1.pdf
hw1.docxCS 211 Homework #1Please complete the homework problem.docx
CPP Homework Help
Design Patterns in Modern C++
Introduction to CMake
talk at Virginia Bioinformatics Institute, December 5, 2013
Effective CMake
Computer Science Assignment Help
Дмитрий Нестерук, Паттерны проектирования в XXI веке
C++ process new
Editors l21 l24
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
The use of the code analysis library OpenC++: modifications, improvements, er...
I am trying to create a program That works with two other programs i.pdf
Building reusable libraries
ez-clang C++ REPL for bare-metal embedded devices
Bioinformatica: Esercizi su Perl, espressioni regolari e altre amenità (BMR G...
Simple Ways To Be A Better Programmer (OSCON 2007)
Perl6 Regexen: Reduce the line noise in your code.
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
Introduction-to-C-Part-1.pdf
Ad

Recently uploaded (20)

PPTX
sap open course for s4hana steps from ECC to s4
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Electronic commerce courselecture one. Pdf
PDF
cuic standard and advanced reporting.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Machine learning based COVID-19 study performance prediction
PDF
KodekX | Application Modernization Development
PDF
Encapsulation theory and applications.pdf
PPTX
Spectroscopy.pptx food analysis technology
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
sap open course for s4hana steps from ECC to s4
Reach Out and Touch Someone: Haptics and Empathic Computing
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Spectral efficient network and resource selection model in 5G networks
Electronic commerce courselecture one. Pdf
cuic standard and advanced reporting.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Empathic Computing: Creating Shared Understanding
Digital-Transformation-Roadmap-for-Companies.pptx
Machine learning based COVID-19 study performance prediction
KodekX | Application Modernization Development
Encapsulation theory and applications.pdf
Spectroscopy.pptx food analysis technology
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Advanced methodologies resolving dimensionality complications for autism neur...
Network Security Unit 5.pdf for BCA BBA.
Diabetes mellitus diagnosis method based random forest with bat algorithm

Hands on clang-format

  • 1. Hands on clang-format Adding (n)one feature at a time Kai Wolf kai-wolf.me March 31, 2016
  • 2. A quick reality check - please raise hand • We have a (living) coding style guide • We use code generators • We do (semi-)automatized refactoring (clang-tidy, Clang MapReduce, awk | grep | sed, ...) • We use automatic code formatting tools • We utilize pre/post-commit hooks for these kind of stuff 2 / 25
  • 3. Why is it important? • Inconsistent formatting distracts the reader • Formatting code by hand is tedious • Nobody reads the style guide anyways • Automatic/large scale refactoring not feasible without automatic code formatting 3 / 25
  • 4. Lots of auto formatting tools available Artistic Style (AStyle) Works. Focuses only on indentation and brace/bracket placement Uncrustify Many, many, many rules (around ~200). Might take a whole day to adjust to own style guide. GNU indent Works most of the time (see OpenSSL Blog - CodeReformat Finished). Basically has three presets available (Ansi, GNU, K&R). Indent needs to know about all types used within the code. GC GreatCode Intrusive formatting rules. May break your code. 4 / 25
  • 5. How to use clang-format $ cat bbox.cpp cv::Rect BoundingBox::getBoundingRect(const cv::Mat& Binary) const { assert(Binary.channels() == 1); using Contour = std::vector<cv::Point>; std::vector<Contour> contours; auto hierarchy = std::vector<cv::Vec4i>(); cv::findContours(Binary.clone(),contours,hierarchy,CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); auto result = *std::max_element(contours.begin(), contours.end(), [](Contour a, Contour b) { return cv::contourArea(a) < cv::contourArea(b);}); return cv::boundingRect(cv::Mat(result));} 5 / 25
  • 6. How to use clang-format $ cat bbox.cpp | clang-format -style=’{BasedOnStyle: Google, IndentWidth: 4’ cv::Rect BoundingBox::getBoundingRect(const cv::Mat& Binary) const { assert(Binary.channels() == 1); using Contour = std::vector<cv::Point>; std::vector<Contour> contours; auto hierarchy = std::vector<cv::Vec4i>(); cv::findContours(Binary.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); auto result = *std::max_element( contours.begin(), contours.end(), [](Contour a, Contour b) { return cv::contourArea(a) < cv::contourArea(b); }); return cv::boundingRect(cv::Mat(result)); } 6 / 25
  • 7. How to use clang-format Plugins available for Vi, Emacs, Visual Studio etc. Custom integration almost always possible. For example: CLion 7 / 25
  • 8. How to use clang-format There are many deliberate options available: Release Number of options clang-format v3.5 53 clang-format v3.6 62 clang-format v3.7 65 clang-format v3.8 70 clang-format v3.9 75 8 / 25
  • 9. Motivating example Say for example, our style guide suggests that this: void foo(int a, int b, double c, const char* str); should be formatted like this: void foo(int a,int b,double c,const char* str); 9 / 25
  • 10. What does clang-format offer here? 10 / 25
  • 11. Let’s try to fix that In order to start hacking we need the llvm repository with the following subprojects: $ export LLVM_SVN=http://llvm.org/svn/llvm-project $ svn co ${LLVM_SVN}/llvm/trunk llvm $ cd llvm/tools $ svn co ${LLVM_SVN}/cfe/trunk clang $ cd ../projects $ svn co ${LLVM_SVN}/test-suite/trunk test-suite $ cd ../tools/clang/tools $ svn co ${LLVM_SVN}/clang-tools-extra/trunk extra 11 / 25
  • 12. Navigate around the code base Formatting rules for clang-format are located in llvm/tools/clang/lib/Format/ Unittests are located in llvm/tools/clang/unittests/Format/ Frontend for clang-format $ cd llvm/tools/clang # clang subproject $ cat tools/clang-format/ClangFormat.cpp int main(int argc, const char **argv) { ... for (unsigned i = 0; i < FileNames.size(); ++i) Error |= clang::format::format(FileNames[i]); 12 / 25
  • 13. clang::format::format static bool format(StringRef FileName) { ... if (fillRanges(Code.get(), Ranges)) return true; ... FormatStyle FormatStyle = getStyle(Style, AssumedFileName, FallbackStyle) ... Replacements Replaces = sortIncludes(FormatStyle, Code, Ranges) ... Replacements FormatChanges = reformat(FormatStyle, ChangedCode, Ranges) } 13 / 25
  • 14. clang::format::reformat ... for (const tooling::Range &Range : Ranges) { SourceLocation Start = StartOfFile.getLocWithOffset( Range.getOffset()); SourceLocation End = Start.getLocWithOffset(Range.getLength()); CharRanges.push_back( CharSourceRange::getCharRange(Start, End)); } return reformat(Style, SourceMgr, ID, CharRanges, IncompleteFormat); 14 / 25
  • 15. clang::format::reformat FormatStyle Expanded = expandPresets(Style); if (Expanded.DisableFormat) return tooling::Replacements(); Formatter formatter(Expanded, SourceMgr, ID, Ranges); return formatter.format(IncompleteFormat); 15 / 25
  • 16. clang::tok::TokenKind void foo(int a, int b); UnwrappedLineParser Parser(); -> readTokens(); -> parseFile(); -> parseLevel(); -> parseStructuralElement(); <- AnnotatedLines 0 kw_void 1 identifier 2 l_param 3 kw_int 4 identifier 5 comma 6 kw_int 7 identifier 8 r_param 9 semi 16 / 25
  • 17. clang::format For each annotated line (TokenAnnotator.cpp): void TokenAnnotator:: calculateFormattingInformation( AnnotatedLine &Line); Fortunately not much to do here for us: bool TokenAnnotator::spaceRequiredBetween( const AnnotatedLine &Line, const FormatToken &Left, const FormatToken &Right); 17 / 25
  • 18. Our patch (excerpt) Format.h /// b If c true, spaces will be inserted between /// function parameters. bool SpacesBetweenFunctionParameters; TokenAnnotator.cpp ... if (Right.is(TT_OverloadedOperatorLParen)) return Style.SpaceBeforeParens == FormatStyle::SBPO_Always; if (Left.is(tok::comma)) // return true; return Style.SpacesBetweenFunctionParameters; if (Right.is(tok::comma)) return false; 18 / 25
  • 19. Preparing the patch Tests are looking good. TEST_F(FormatTest, SpacesBetweenFunctionParameters) { FormatStyle Spaces = getLLVMStyle(); Spaces.SpacesBetweenFunctionParameters = false; verifyFormat("void foo(int a);", Spaces); verifyFormat("void foo(int a,double b);", Spaces); verifyFormat("void foo(int a,double b,char c);", Spaces); Spaces.SpacesBetweenFunctionParameters = true; verifyFormat("void foo(int a, double b);", Spaces); verifyFormat("void foo(int a, double b, char c);", Spaces); } By the way: If you manage an open source project, make sure to explain how to contribute! • How to get going? How to submit your patch? • Who decides what patches are accepted? • Who should review your patch? • What should be included in the patch? (doc, unittests, full file context diff etc.) 19 / 25
  • 21. That paragraph must be new... 21 / 25
  • 22. Yes, indeed By the time I’ve created the patch, clang-format 3.7 was the current release 22 / 25
  • 24. I don’t always accidentally... 24 / 25