Overview
Dolphin uses clang-format 19.1 to enforce consistent code formatting across the entire codebase. This guide details the specific coding standards and formatting rules.
In case of conflicts between this guide and clang-format rules, follow clang-format.
Command Line
Pre-commit Hook
Git Filter Driver
Visual Studio
Format all staged files before committing: git diff --cached --name-only | grep -E '[.](cpp|h|mm)$' | xargs -I {} clang-format -i {}
Enable automatic formatting checks: ln -s ../../Tools/lint.sh .git/hooks/pre-commit
Automatically reformat changes transparently: git config filter.clang_format.smudge 'cat'
git config filter.clang_format.clean 'clang-format %f'
echo '/Source/Core/**/*.cpp filter=clang_format' >> .git/info/attributes
echo '/Source/Core/**/*.h filter=clang_format' >> .git/info/attributes
echo '/Source/Core/**/*.mm filter=clang_format' >> .git/info/attributes
Press Ctrl+K followed by Ctrl+D (or select Edit → Advanced → Format Document ). Visual Studio has built-in clang-format support - no separate installation required.
Line Endings
Windows users must configure git to checkout UNIX-style line endings: git config core.autocrlf input
Line Length and Indentation
Maximum line length : 100 characters
Indentation : 2 spaces per level (no tabs)
Tab width : 2 spaces
Try to keep lines under 80-90 characters when possible for better readability.
Brace Placement
Opening braces go on the next line for:
Namespaces
Classes
Functions
Enums, structs, unions
Conditionals and loops
// Correct
void MyFunction ()
{
if (condition)
{
DoSomething ();
}
}
// Exception: Array initializers and lambdas can keep braces on same line
auto lambda = []( int x ) { return x * 2 ; };
int array[] = { 1 , 2 , 3 };
Pointers and References
Place the * or & against the type name , not the variable name:
// Correct
int * pointer;
int & reference;
// Incorrect
int * pointer;
int & reference;
Use single-line comments (//), not multi-line comments (/* */):
// This is correct
// Multiple lines use multiple single-line comments
/* This is incorrect */
Conditionals and Loops
Don’t collapse single-line bodies onto the same line as the header:
// Correct
if (condition)
return 0 ;
while (var != 0 )
var -- ;
// Incorrect
if (condition) return 0 ;
while (var != 0 ) var -- ;
Naming Conventions
Classes, Enums, Functions, Structs
Use UpperCamelCase . Uppercase abbreviations:
class SomeClassName { };
enum IPCCommandType { };
void ProcessRequest ();
struct GameMetadata { };
Constants
Fully uppercase with underscores:
constexpr double PI = 3.14159 ;
constexpr int MAX_PATH = 260 ;
Variables
Lowercase with underscores:
int this_variable_name;
float player_speed;
Variable Prefixes
Do not use Hungarian notation except for these specific prefixes:
Prefix Usage Example g_Global variables g_video_backendm_Class member variables m_widths_Static variables s_instance_count
class ExampleClass
{
private:
int m_x; // Member variable
static int s_instance_count; // Static variable
};
int g_global_counter; // Global variable
Conditional Statements
Don’t leave else or else if dangling unless the if lacks braces:
// Correct
if (condition)
{
// code
}
else
{
// code
}
// Also acceptable
if (condition)
// single line
else
// single line
// Incorrect - inconsistent bracing
if (condition)
{
// code
}
else
// single line
Classes and Structs
When to Use Each
Class Layout
Order sections as: public, protected, private
Within each section, order as:
Constructor
Destructor
Operator overloads
Functions
Variables (static before non-static)
class ExampleClass : public SomeParent
{
public:
ExampleClass ( int x , int y );
~ExampleClass ();
int GetX () const ;
int GetY () const ;
protected:
virtual void SomeProtectedFunction () = 0 ;
static float s_some_variable;
private:
int m_x;
int m_y;
};
Final and Override Specifiers
Mark classes/functions that shouldn’t be inherited/overridden with final:
class ClassName final : ParentClass
{
public:
void Update () final ; // Cannot be overridden
};
Mark overridden functions with override:
class ClassName : ParentClass
{
public:
void Update () override ; // Overrides parent's Update()
};
Code-Specific Guidelines
Modern C++ Practices
Use nullptr
Use nullptr instead of the NULL macro: int * ptr = nullptr ; // Correct
int * ptr = NULL ; // Incorrect
Prefer range-based for loops
Use range-based for loops over iterators when possible: for ( const auto & item : container)
{
// process item
}
Avoid raw pointers
Prefer STL containers and smart pointers: std ::vector < int > data; // Instead of int*
std ::unique_ptr < Object > obj; // For single ownership
Raw pointers are acceptable when interfacing with C libraries or when unavoidable.
Limit auto usage
Only use auto when the type is obvious: // Good - type is clear
auto it = map . begin ();
auto lambda = []( int x ) { return x * 2 ; };
// Bad - type is not obvious
auto result = CalculateComplexValue ();
Use #pragma once
This project uses #pragma once as header guards.
Include order
Order includes in source files as:
The header for this source file
Standard library headers (alphabetically)
System-specific headers (in #ifdef blocks)
Other Dolphin headers (alphabetically)
#include "Core/MyClass.h"
#include <algorithm>
#include <vector>
#ifdef _WIN32
#include <windows.h>
#endif
#include "Common/CommonTypes.h"
#include "Core/ConfigManager.h"
Relative paths
Include project headers relative to [Dolphin Root]/Source/Core: #include "VideoCommon/RenderBase.h"
Remove unused includes
Remove unnecessary or duplicate includes.
Loops
// Infinite loops
while ( true ) // Correct
{
}
for (;;) // Incorrect
{
}
// Empty loops
while (condition) {} // Correct - use braces
while (condition); // Incorrect - don't use semicolon
// Do-while loops
do
{
// code
} while ( false ); // 'while' on same line as closing brace
// Prefer prefix increment
for ( int i = 0 ; i < n; ++ i) // Correct
for ( int i = 0 ; i < n; i ++ ) // Less preferred
Functions
Const-correctness for parameters:
void ProcessData ( const int* data , const size_t size );
Pointer parameters for modification:
Make modification syntactically obvious by using pointers:
// Correct - obvious that val is modified
template < class T >
inline void Clamp ( T * val , const T & min , const T & max )
{
if ( * val < min)
* val = min;
else if ( * val > max)
* val = max;
}
// Usage makes modification clear
Clamp ( & var, 1000 , 5000 );
Miscellaneous
Avoid goto unless you have a really good reason
Fix compiler warnings when found
Don’t use using namespace [x]; in headers (avoid it elsewhere too)
Use prefix increment in for-loops: ++var instead of var++
The project’s .clang-format file (located at Source/.clang-format) defines:
ColumnLimit : 100
IndentWidth : 2
PointerAlignment : Left
BreakBeforeBraces : Custom
BraceWrapping :
AfterClass : true
AfterControlStatement : true
AfterEnum : true
AfterFunction : true
AfterNamespace : true
AfterStruct : true
Standard : Latest
InsertNewlineAtEOF : true
View the complete configuration at Source/.clang-format in the repository.
Android Code Style
Kotlin
Use the built-in official Kotlin code style in Android Studio.
Java
Import the Dolphin Java code style:
Open Code Style settings
Navigate to Settings → Code Style in Android Studio.
Import scheme
Click the gear icon, select Import Scheme , and choose dolphin/Source/Android/code-style-java.xml.
Format code
Select code and press Ctrl+Alt+L to automatically format it.
Next Steps
Testing Learn about testing practices and frameworks
Debugging Explore debugging tools and techniques