-
Notifications
You must be signed in to change notification settings - Fork 1
Home
This fork of LLVM/Clang allows you to define static analysis rules in .clang-rules
files and have them automatically run during compilation. You do not need to update any other tooling, and it can be used as a drop-in replacement for normal Clang in Unreal Engine builds.
This version of Clang also understands the Unreal Engine UCLASS
etc. specifiers so you can match against them. See the AST Matcher Reference page which provides a list of available matchers you can use.
You can download the latest version of Clang for Unreal Engine from GitHub Actions. The latest successfully built version is shown at the top of that page; click through to it and you can download the version of your platform from the "Artifacts" section.
The llvm-*
artifacts include Clang, and these are what you want to download. The MSI artifact provides a ZIP file with an .msi
installer. This will install LLVM/Clang in the correct location for UnrealBuildTool to find it.
To use Clang instead of MSVC in the Unreal build system, open %appdata%\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml
(create it if it does not exist), and set the WindowsPlatform/Compiler
setting like so:
<?xml version="1.0" encoding="utf-8"?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
<WindowsPlatform>
<Compiler>Clang</Compiler>
</WindowsPlatform>
</Configuration>
After installing this fork of Clang, in any directory that you want to have static analysis rules run, create a .clang-rules
file. The rules and rulesets you define in this file will apply to all header and source files within and under the directory that the .clang-rules
file is in.
When you're creating a .clang-rules
file, you'll need to pick a namespace. This should be something unique to your organisation. If you need to reference rules across namespaces in rulesets, use the form namespace/rule
.
An example .clang-rules
file that we use internally for EOS Online Subsystem looks as follows:
Namespace: redpoint.games
Rules:
# Disallow 'using namespace' outside of functions.
- Name: using-namespace-in-namespace
Matcher: |
namespaceDecl(has(usingDirectiveDecl().bind("using_decl")))
ErrorMessage: |
'using namespace' outside of functions pollutes unqualified symbol name resolution
Callsite: using_decl
# Detects if a field in a class or struct is not initialized in the
# constructor's initialization list when at least one member is initialized
# via the initializer list.
- Name: field-not-initialized
Matcher: |
cxxConstructorDecl(
unless(isImplicit()),
unless(isDelegatingConstructor()),
unless(isDeleted()),
unless(isDefaulted()),
hasBody(stmt()),
unless(ofClass(cxxRecordDecl(isUClass()))),
unless(ofClass(cxxRecordDecl(isUInterface()))),
ofClass(cxxRecordDecl(forEach(fieldDecl().bind("declared_field")))),
forNone(cxxCtorInitializer(forField(fieldDecl(equalsBoundNode("declared_field")).bind("referenced_field"))))
).bind("bad_constructor")
ErrorMessage: |
one or more fields will be uninitialized when class or struct is constructed; please add the field to the initializer list.
Callsite: bad_constructor
Hints:
declared_field: this field must be initialized
# Detects when a type must be exported. This is not enabled globally, but rather is enabled
# via additional .clang-rules files inside 'Public' folders.
- Name: type-must-be-exported
Matcher: |
cxxRecordDecl(isMissingDllImportOrExport()).bind('decl')
ErrorMessage: |
expected '..._API' to mark this type as exported
Callsite: decl
WindowsOnly: true
Rulesets:
# Ruleset for EOS Online Subsystem plugin.
- Name: eos-online-subsystem
Severity: Error
Rules:
- using-namespace-in-namespace
- field-not-initialized