Skip to content

Commit 1b5d6ec

Browse files
authored
[clang-tidy] count class member initializers as statements in 'readability-function-size' (#131669)
Improve `readability-function-size` by counting class member initializers as statements. Relates to #131126
1 parent 369e840 commit 1b5d6ec

File tree

6 files changed

+156
-1
lines changed

6 files changed

+156
-1
lines changed

clang-tools-extra/clang-tidy/readability/FunctionSizeCheck.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ class FunctionASTVisitor : public RecursiveASTVisitor<FunctionASTVisitor> {
108108
return true;
109109
}
110110

111+
bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
112+
if (CountMemberInitAsStmt)
113+
++Info.Statements;
114+
115+
Base::TraverseConstructorInitializer(Init);
116+
return true;
117+
}
118+
111119
struct FunctionInfo {
112120
unsigned Lines = 0;
113121
unsigned Statements = 0;
@@ -120,6 +128,7 @@ class FunctionASTVisitor : public RecursiveASTVisitor<FunctionASTVisitor> {
120128
llvm::BitVector TrackedParent;
121129
unsigned StructNesting = 0;
122130
unsigned CurrentNestingLevel = 0;
131+
bool CountMemberInitAsStmt;
123132
};
124133

125134
} // namespace
@@ -135,7 +144,9 @@ FunctionSizeCheck::FunctionSizeCheck(StringRef Name, ClangTidyContext *Context)
135144
NestingThreshold(
136145
Options.get("NestingThreshold", DefaultNestingThreshold)),
137146
VariableThreshold(
138-
Options.get("VariableThreshold", DefaultVariableThreshold)) {}
147+
Options.get("VariableThreshold", DefaultVariableThreshold)),
148+
CountMemberInitAsStmt(
149+
Options.get("CountMemberInitAsStmt", DefaultCountMemberInitAsStmt)) {}
139150

140151
void FunctionSizeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
141152
Options.store(Opts, "LineThreshold", LineThreshold);
@@ -144,6 +155,7 @@ void FunctionSizeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
144155
Options.store(Opts, "ParameterThreshold", ParameterThreshold);
145156
Options.store(Opts, "NestingThreshold", NestingThreshold);
146157
Options.store(Opts, "VariableThreshold", VariableThreshold);
158+
Options.store(Opts, "CountMemberInitAsStmt", CountMemberInitAsStmt);
147159
}
148160

149161
void FunctionSizeCheck::registerMatchers(MatchFinder *Finder) {
@@ -160,6 +172,7 @@ void FunctionSizeCheck::check(const MatchFinder::MatchResult &Result) {
160172

161173
FunctionASTVisitor Visitor;
162174
Visitor.Info.NestingThreshold = NestingThreshold.value_or(-1);
175+
Visitor.CountMemberInitAsStmt = CountMemberInitAsStmt;
163176
Visitor.TraverseDecl(const_cast<FunctionDecl *>(Func));
164177
auto &FI = Visitor.Info;
165178

clang-tools-extra/clang-tidy/readability/FunctionSizeCheck.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class FunctionSizeCheck : public ClangTidyCheck {
4747
const std::optional<unsigned> ParameterThreshold;
4848
const std::optional<unsigned> NestingThreshold;
4949
const std::optional<unsigned> VariableThreshold;
50+
const bool CountMemberInitAsStmt;
5051

5152
static constexpr std::optional<unsigned> DefaultLineThreshold = std::nullopt;
5253
static constexpr std::optional<unsigned> DefaultStatementThreshold = 800U;
@@ -58,6 +59,7 @@ class FunctionSizeCheck : public ClangTidyCheck {
5859
std::nullopt;
5960
static constexpr std::optional<unsigned> DefaultVariableThreshold =
6061
std::nullopt;
62+
static constexpr bool DefaultCountMemberInitAsStmt = true;
6163
};
6264

6365
} // namespace clang::tidy::readability

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,11 @@ Changes in existing checks
278278
<clang-tidy/checks/readability/convert-member-functions-to-static>` check by
279279
fixing false positives on member functions with an explicit object parameter.
280280

281+
- Improved :doc:`readability-function-size
282+
<clang-tidy/checks/readability/function-size>` check by adding new option
283+
`CountMemberInitAsStmt` that allows counting class member initializers in
284+
constructors as statements.
285+
281286
- Improved :doc:`readability-math-missing-parentheses
282287
<clang-tidy/checks/readability/math-missing-parentheses>` check by fixing
283288
false negatives where math expressions are the operand of assignment operators

clang-tools-extra/docs/clang-tidy/checks/readability/function-size.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,8 @@ Options
4343
The default is `none` (ignore the number of variables).
4444
Please note that function parameters and variables declared in lambdas,
4545
GNU Statement Expressions, and nested class inline functions are not counted.
46+
47+
.. option:: CountMemberInitAsStmt
48+
49+
When `true`, count class member initializers in constructors as statements.
50+
Default is `true`.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// RUN: %check_clang_tidy %s readability-function-size %t -- \
2+
// RUN: -config='{CheckOptions: { \
3+
// RUN: readability-function-size.LineThreshold: 0, \
4+
// RUN: readability-function-size.StatementThreshold: 0, \
5+
// RUN: readability-function-size.BranchThreshold: 0, \
6+
// RUN: readability-function-size.ParameterThreshold: 5, \
7+
// RUN: readability-function-size.NestingThreshold: 2, \
8+
// RUN: readability-function-size.VariableThreshold: 1, \
9+
// RUN: readability-function-size.CountMemberInitAsStmt: false \
10+
// RUN: }}'
11+
12+
// Bad formatting is intentional, don't run clang-format over the whole file!
13+
14+
void foo1() {
15+
}
16+
17+
void foo2() {;}
18+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'foo2' exceeds recommended size/complexity thresholds [readability-function-size]
19+
// CHECK-MESSAGES: :[[@LINE-2]]:6: note: 1 statements (threshold 0)
20+
21+
struct A {
22+
A(int c, int d) : a(0), b(c) { ; }
23+
int a;
24+
int b;
25+
};
26+
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: function 'A' exceeds recommended size/complexity thresholds [readability-function-size]
27+
// CHECK-MESSAGES: :[[@LINE-5]]:3: note: 1 statements (threshold 0)
28+
29+
struct B {
30+
B(int x, int y, int z) : a(x + y * z), b(), c_a(y, z) {
31+
;
32+
}
33+
int a;
34+
int b;
35+
A c_a;
36+
};
37+
// CHECK-MESSAGES: :[[@LINE-7]]:3: warning: function 'B' exceeds recommended size/complexity thresholds [readability-function-size]
38+
// CHECK-MESSAGES: :[[@LINE-8]]:3: note: 2 lines including whitespace and comments (threshold 0)
39+
// CHECK-MESSAGES: :[[@LINE-9]]:3: note: 1 statements (threshold 0)
40+
41+
struct C : A, B {
42+
// 0 statements
43+
C() : A(0, 4), B(1, 2, 3) {}
44+
};
45+
46+
template<typename T>
47+
struct TemplateC {
48+
// 0 statements
49+
TemplateC() : a(3) {}
50+
T a;
51+
};
52+
53+
template<typename T>
54+
struct TemplateD {
55+
template<typename U>
56+
TemplateD(U&& val) : member(val) {
57+
;
58+
}
59+
60+
T member;
61+
};
62+
// CHECK-MESSAGES: :[[@LINE-6]]:3: warning: function 'TemplateD<T>' exceeds recommended size/complexity thresholds [readability-function-size]
63+
// CHECK-MESSAGES: :[[@LINE-7]]:3: note: 2 lines including whitespace and comments (threshold 0)
64+
// CHECK-MESSAGES: :[[@LINE-8]]:3: note: 1 statements (threshold 0)
65+
66+
void instantiate() {
67+
TemplateC<int> c;
68+
TemplateD<int> d(5);
69+
}
70+
// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'instantiate' exceeds recommended size/complexity thresholds [readability-function-size]
71+
// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
72+
// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 2 statements (threshold 0)
73+
// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 2 variables (threshold 1)

clang-tools-extra/test/clang-tidy/checkers/readability/function-size.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,60 @@ void variables_16() {
319319
// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
320320
// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 statements (threshold 0)
321321
// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 2 variables (threshold 1)
322+
323+
struct A {
324+
A(int c, int d) : a(0), b(c) { ; }
325+
int a;
326+
int b;
327+
};
328+
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: function 'A' exceeds recommended size/complexity thresholds [readability-function-size]
329+
// CHECK-MESSAGES: :[[@LINE-5]]:3: note: 3 statements (threshold 0)
330+
331+
struct B {
332+
B(int x, int y, int z) : a(x + y * z), b(), c_a(y, z) {
333+
;
334+
}
335+
int a;
336+
int b;
337+
A c_a;
338+
};
339+
// CHECK-MESSAGES: :[[@LINE-7]]:3: warning: function 'B' exceeds recommended size/complexity thresholds [readability-function-size]
340+
// CHECK-MESSAGES: :[[@LINE-8]]:3: note: 2 lines including whitespace and comments (threshold 0)
341+
// CHECK-MESSAGES: :[[@LINE-9]]:3: note: 4 statements (threshold 0)
342+
343+
struct C : A, B {
344+
C() : A(0, 4), B(1, 2, 3) {}
345+
};
346+
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: function 'C' exceeds recommended size/complexity thresholds [readability-function-size]
347+
// CHECK-MESSAGES: :[[@LINE-3]]:3: note: 2 statements (threshold 0)
348+
349+
template<typename T>
350+
struct TemplateC {
351+
// 0 statements
352+
TemplateC() : a(3) {}
353+
T a;
354+
};
355+
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: function 'TemplateC<T>' exceeds recommended size/complexity thresholds [readability-function-size]
356+
// CHECK-MESSAGES: :[[@LINE-4]]:3: note: 1 statements (threshold 0)
357+
358+
template<typename T>
359+
struct TemplateD {
360+
template<typename U>
361+
TemplateD(U&& val) : member(val) {
362+
;
363+
}
364+
365+
T member;
366+
};
367+
// CHECK-MESSAGES: :[[@LINE-6]]:3: warning: function 'TemplateD<T>' exceeds recommended size/complexity thresholds [readability-function-size]
368+
// CHECK-MESSAGES: :[[@LINE-7]]:3: note: 2 lines including whitespace and comments (threshold 0)
369+
// CHECK-MESSAGES: :[[@LINE-8]]:3: note: 2 statements (threshold 0)
370+
371+
void instantiate() {
372+
TemplateC<int> c;
373+
TemplateD<int> d(5);
374+
}
375+
// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'instantiate' exceeds recommended size/complexity thresholds [readability-function-size]
376+
// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
377+
// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 2 statements (threshold 0)
378+
// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 2 variables (threshold 1)

0 commit comments

Comments
 (0)