Skip to content

Commit 46fd550

Browse files
mikeafhanau
authored andcommitted
[nfc] clang-tidy
1 parent 2c1d590 commit 46fd550

File tree

15 files changed

+320
-8
lines changed

15 files changed

+320
-8
lines changed

.bazelrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ build --incompatible_autoload_externally="+py_binary,+py_library,+ProtoInfo,+sh_
3030
# Import CI-specific configuration. As the amount of custom configuration settings we use grows,
3131
# consider moving more flags out to separate files.
3232
import %workspace%/build/ci.bazelrc
33-
3433
import %workspace%/build/rust_lint.bazelrc
34+
import %workspace%/build/tools/clang_tidy/clang_tidy.bazelrc
3535

3636
# Prevents bazel cache invalidation when switching terminals
3737
build --incompatible_strict_action_env

.clang-tidy

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,35 @@
44
# TODO: these checks are in progress of cleaning up
55
Checks: >
66
-*,
7+
bugprone-argument-comment,
78
bugprone-capturing-this-in-member-variable,
9+
bugprone-forward-declaration-namespace,
810
bugprone-move-forwarding-reference,
9-
bugprone-return-const-ref-from-parameter,
1011
bugprone-use-after-move,
12+
cppcoreguidelines-misleading-capture-default-by-value,
13+
misc-confusable-identifiers,
1114
misc-header-include-cycle,
15+
misc-throw-by-value-catch-by-reference,
16+
misc-unused-alias-decls,
17+
modernize-macro-to-enum,
18+
modernize-redundant-void-arg,
19+
modernize-unary-static-assert,
20+
modernize-use-bool-literals,
21+
performance-for-range-copy,
22+
performance-move-constructor-init,
23+
readability-container-contains,
1224
readability-duplicate-include,
25+
readability-redundant-access-specifiers,
26+
readability-static-accessed-through-instance
27+
28+
# TODO: Fix and re-enable
29+
# bugprone-return-const-ref-from-parameter
30+
# modernize-type-traits
31+
# modernize-use-override
32+
# readability-redundant-casting
33+
1334
WarningsAsErrors: '*'
35+
HeaderFilterRegex: '.*/workerd/.*'
1436

1537
CheckOptions:
1638
# JSG has very entrenched include cycles

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ jobs:
9898
lint:
9999
uses: ./.github/workflows/_bazel.yml
100100
with:
101-
extra_bazel_args: '--config=lint --config=ci-test --config=ci-linux'
101+
extra_bazel_args: '--config=lint --config=clang-tidy --config=ci-test --config=ci-linux'
102102
run_tests: false
103103
parse_headers: true
104104
secrets:

BUILD.bazel

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ wd_cc_embed(
2222
alias(
2323
name = "v8_icu",
2424
actual = "@v8//:v8_icu",
25+
tags = ["manual"],
2526
visibility = ["//visibility:public"],
2627
)
2728

@@ -122,3 +123,10 @@ selects.config_setting_group(
122123
":not_dbg_build",
123124
],
124125
)
126+
127+
# Clang-tidy config to use
128+
label_flag(
129+
name = "clang_tidy_config",
130+
build_setting_default = ":.clang-tidy",
131+
visibility = ["//visibility:public"],
132+
)

MODULE.bazel

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,33 @@ git_override(
3232
remote = "https://chromium.googlesource.com/chromium/src/third_party/zlib.git",
3333
)
3434

35+
# clang-tidy
36+
http_file = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
37+
http_file(
38+
name = "clang_tidy_macos_arm64",
39+
url = "https://github.com/cloudflare/workerd-tools/releases/download/clang-tidy-21.1.4/llvm-21.1.4-darwin-arm64-clang-tidy",
40+
executable = True,
41+
integrity = "sha256-vzU7J99wf6a/DMsLJ7/q5f3JckU0i3kbNAtck3vO5oA="
42+
)
43+
http_file(
44+
name = "clang_tidy_linux_amd64",
45+
url = "https://github.com/cloudflare/workerd-tools/releases/download/clang-tidy-21.1.4/llvm-21.1.4-linux-amd64-clang-tidy",
46+
executable = True,
47+
integrity = "sha256-6B+qIjJhCXJpRPp9nSQxnchEzuHH7UL5mWNrcGU/3z8="
48+
)
49+
http_file(
50+
name = "clang_tidy_linux_arm64",
51+
url = "https://github.com/cloudflare/workerd-tools/releases/download/clang-tidy-21.1.4/llvm-21.1.4-linux-arm64-clang-tidy",
52+
executable = True,
53+
integrity = "sha256-o4grMwBpnxMv+291b4ZbNHvmgtzUhjJL6KlGENuq/5E="
54+
)
55+
http_file(
56+
name = "clang_tidy_windows_amd64",
57+
url = "https://github.com/cloudflare/workerd-tools/releases/download/clang-tidy-21.1.4/llvm-21.1.4-windows-amd64-clang-tidy.exe",
58+
executable = True,
59+
integrity = "sha256-9KJLz6bHbwpj5yAkjJzUQV0oL+ZrFsI2Wo5Rpjg69vc="
60+
)
61+
3562
# BoringSSL may subtly break backwards compatibility and behave differently than the latest FIPS
3663
# version, often by rejecting key values that it considers invalid/unsafe even though they are still
3764
# accepted by BoringSSL. Update with caution and only after confirming this is compatible with the

build/tools/clang_tidy/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
exports_files(["clang_tidy_wrapper.sh"])
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# enable clang tidy checks with default configuration
2+
build:clang-tidy --aspects //build/tools/clang_tidy:clang_tidy.bzl%clang_tidy_aspect --output_groups=+clang_tidy_checks
3+
4+
# enable clang tidy check with all issues reported as warnings
5+
build:clang-tidy-warnings --config=clang-tidy --aspects_parameters=clang_tidy_args=--warnings-as-errors=-*
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
"""Clang tidy aspect.
2+
3+
The aspect, when enabled runs clang_tidy on every compiled c++ file.
4+
"""
5+
6+
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
7+
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain")
8+
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
9+
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
10+
11+
def _clang_tidy_aspect_impl(target, ctx):
12+
# not a c++ target
13+
if not CcInfo in target:
14+
return []
15+
16+
cc_toolchain = find_cc_toolchain(ctx)
17+
feature_configuration = cc_common.configure_features(
18+
ctx = ctx,
19+
cc_toolchain = cc_toolchain,
20+
)
21+
compile_variables = cc_common.create_compile_variables(
22+
feature_configuration = feature_configuration,
23+
cc_toolchain = cc_toolchain,
24+
user_compile_flags = ctx.fragments.cpp.cxxopts + ctx.fragments.cpp.copts,
25+
)
26+
toolchain_flags = cc_common.get_memory_inefficient_command_line(
27+
feature_configuration = feature_configuration,
28+
action_name = ACTION_NAMES.cpp_compile,
29+
variables = compile_variables,
30+
)
31+
32+
compilation_context = target[CcInfo].compilation_context
33+
34+
rule_copts = getattr(ctx.rule.attr, "copts", [])
35+
36+
# we use $location in our copts, expand it
37+
rule_copts = [ctx.expand_location(opt) for opt in rule_copts]
38+
39+
srcs = []
40+
if hasattr(ctx.rule.attr, "srcs"):
41+
for src in ctx.rule.attr.srcs:
42+
srcs += [
43+
src
44+
for src in src.files.to_list()
45+
if src.is_source and src.short_path.endswith((".c++", ".c", ".h"))
46+
]
47+
if hasattr(ctx.rule.attr, "hdrs"):
48+
for src in ctx.rule.attr.hdrs:
49+
srcs += [
50+
src
51+
for src in src.files.to_list()
52+
if src.is_source and src.short_path.endswith((".c++", ".c", ".h"))
53+
]
54+
55+
defines = compilation_context.defines.to_list()
56+
local_defines = compilation_context.local_defines.to_list()
57+
includes = compilation_context.includes.to_list()
58+
quote_includes = compilation_context.quote_includes.to_list()
59+
system_includes = compilation_context.system_includes.to_list()
60+
headers = compilation_context.headers
61+
62+
# disable clang tidy if no-clang-tidy tag is defined.
63+
# todo: figure out a better way to control clang tidy on a per-target basis.
64+
if "no-clang-tidy" in ctx.rule.attr.tags:
65+
return []
66+
67+
# bazel doesn't expose implementation deps through compilation context
68+
# https://github.com/bazelbuild/bazel/issues/19663
69+
if hasattr(ctx.rule.attr, "implementation_deps"):
70+
deps = [dep[CcInfo].compilation_context for dep in ctx.rule.attr.implementation_deps if CcInfo in dep]
71+
defines = depset(
72+
defines,
73+
transitive = [dep.defines for dep in deps],
74+
)
75+
includes = depset(
76+
includes,
77+
transitive = [dep.includes for dep in deps],
78+
)
79+
system_includes = depset(
80+
system_includes,
81+
transitive = [dep.system_includes for dep in deps],
82+
)
83+
quote_includes = depset(
84+
quote_includes,
85+
transitive = [dep.quote_includes for dep in deps],
86+
)
87+
headers = depset(
88+
headers.to_list(),
89+
transitive = [dep.headers for dep in deps],
90+
)
91+
92+
tools = [
93+
ctx.attr._clang_tidy_executable.files,
94+
ctx.attr._clang_tidy_wrapper.files,
95+
ctx.attr._clang_tidy_config.files,
96+
]
97+
98+
outs = []
99+
for src in srcs:
100+
# run actions need to produce something, declare a dummy file
101+
# multiple labels can use the same path, so disambiguate.
102+
out = ctx.actions.declare_file(src.path + "." + ctx.label.name + ".clang_tidy")
103+
outs.append(out)
104+
105+
args = ctx.actions.args()
106+
107+
# these are consumed by clang_tidy_wrapper,sh
108+
args.add(ctx.attr._clang_tidy_executable.files_to_run.executable)
109+
args.add(out)
110+
111+
# clang-tidy arguments
112+
# do not print statistics
113+
args.add("--quiet")
114+
args.add("--config-file=" + ctx.attr._clang_tidy_config.files.to_list()[0].short_path)
115+
116+
if ctx.attr.clang_tidy_args:
117+
args.add_all(ctx.attr.clang_tidy_args.split(" "))
118+
119+
args.add(src.path)
120+
121+
# compiler arguments
122+
args.add("--")
123+
124+
args.add("-xc++")
125+
126+
args.add_all(ctx.attr._clang_tidy_compiler_flags)
127+
args.add_all(rule_copts)
128+
args.add_all(defines, before_each = "-D")
129+
args.add_all(local_defines, before_each = "-D")
130+
args.add_all(includes, before_each = "-I")
131+
args.add_all(quote_includes, before_each = "-iquote")
132+
args.add_all(system_includes, before_each = "-isystem")
133+
134+
args.add_all(toolchain_flags)
135+
136+
# Silence warnings about unused functions or #pragma once being present in header files. For
137+
# source files, we already cover these warnings in regular compilation
138+
args.add("-Wno-pragma-once-outside-header")
139+
args.add("-Wno-unused")
140+
141+
# TODO(cleanup): These paths provide required includes, but if the toolchain was working
142+
# properly we wouldn't need them in the first place...
143+
# Linux includes
144+
args.add("-isystem/usr/lib/llvm-19/include/c++/v1")
145+
args.add("-isystem/usr/lib/llvm-19/lib/clang/19/include")
146+
args.add("-isystem/usr/include")
147+
args.add("-isystem/usr/include/x86_64-linux-gnu")
148+
149+
# macOS includes
150+
args.add("-isystem/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1")
151+
args.add("-isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/17/include")
152+
args.add("-isystem/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include")
153+
154+
inputs = depset(
155+
direct = [src],
156+
transitive = [headers],
157+
)
158+
159+
ctx.actions.run(
160+
outputs = [out],
161+
arguments = [args],
162+
executable = ctx.attr._clang_tidy_wrapper.files_to_run.executable,
163+
progress_message = "Run clang-tidy on {}".format(src.short_path),
164+
tools = tools,
165+
mnemonic = "ClangTidy",
166+
inputs = inputs,
167+
)
168+
169+
return [
170+
OutputGroupInfo(clang_tidy_checks = depset(direct = outs)),
171+
]
172+
173+
clang_tidy_aspect = aspect(
174+
implementation = _clang_tidy_aspect_impl,
175+
fragments = ["cpp"],
176+
attrs = {
177+
"_clang_tidy_wrapper": attr.label(
178+
default = Label("@//build/tools/clang_tidy:clang_tidy_wrapper.sh"),
179+
allow_single_file = True,
180+
),
181+
"_clang_tidy_executable": attr.label(
182+
default = Label("//tools:clang-tidy"),
183+
allow_single_file = True,
184+
),
185+
"_clang_tidy_config": attr.label(
186+
default = Label("//:clang_tidy_config"),
187+
allow_single_file = True,
188+
),
189+
"_clang_tidy_compiler_flags": attr.string_list(
190+
default = [],
191+
),
192+
"clang_tidy_args": attr.string(default = ""),
193+
},
194+
toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
195+
)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#! /bin/bash
2+
# simple wrapper script to execute clang-tidy
3+
4+
set -euo pipefail
5+
6+
CLANG_TIDY_BIN=$1
7+
shift
8+
9+
OUTPUT=$1
10+
shift
11+
12+
PWD=$(pwd)/
13+
ESCAPED_PWD=$(sed 's/[\*\.&/]/\\&/g' <<< "$PWD")
14+
15+
# Interestingly clang-tidy prints real errors to stdout, but system message like
16+
# `4 warnings generated` when they are filtered out, to stderr.
17+
# Save stderr and print only on errors to reduce the clutter.
18+
CLANG_TIDY_STDERR=$(mktemp)
19+
20+
set +e
21+
"${CLANG_TIDY_BIN}" "$@" 2>"$CLANG_TIDY_STDERR" | \
22+
# clang-tidy insists on printing absolute file paths, chop current dir off
23+
sed "s/$ESCAPED_PWD//g"
24+
CLANG_TIDY_EXIT_CODE=$?
25+
set -e
26+
27+
if [[ $CLANG_TIDY_EXIT_CODE -ne 0 ]]; then
28+
cat "$CLANG_TIDY_STDERR" >&2
29+
rm -f "$CLANG_TIDY_STDERR"
30+
exit $CLANG_TIDY_EXIT_CODE
31+
fi
32+
33+
rm -f "$CLANG_TIDY_STDERR"
34+
35+
# bazel needs run action to produce some output, touch the file
36+
touch "$OUTPUT"

src/workerd/api/eventsource.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#pragma once
66
#include "basics.h"
7+
#include "http.h"
78

89
#include <workerd/jsg/jsg.h>
910
#include <workerd/jsg/url.h>

0 commit comments

Comments
 (0)