File tree Expand file tree Collapse file tree 9 files changed +128
-8
lines changed Expand file tree Collapse file tree 9 files changed +128
-8
lines changed Original file line number Diff line number Diff line change @@ -105,11 +105,15 @@ void TaggedUnionMemberCountCheck::storeOptions(
105
105
106
106
void TaggedUnionMemberCountCheck::registerMatchers (MatchFinder *Finder) {
107
107
108
- auto UnionField = fieldDecl ( hasType ( qualType (
109
- hasCanonicalType ( recordType ( hasDeclaration ( recordDecl ( isUnion ())))) )));
108
+ auto NotFromSystemHeaderOrStdNamespace =
109
+ unless ( anyOf ( isExpansionInSystemHeader (), isInStdNamespace ( )));
110
110
111
- auto EnumField = fieldDecl (hasType (
112
- qualType (hasCanonicalType (enumType (hasDeclaration (enumDecl ()))))));
111
+ auto UnionField =
112
+ fieldDecl (hasType (qualType (hasCanonicalType (recordType (hasDeclaration (
113
+ recordDecl (isUnion (), NotFromSystemHeaderOrStdNamespace)))))));
114
+
115
+ auto EnumField = fieldDecl (hasType (qualType (hasCanonicalType (
116
+ enumType (hasDeclaration (enumDecl (NotFromSystemHeaderOrStdNamespace)))))));
113
117
114
118
auto HasOneUnionField = fieldCountOfKindIsOne (UnionField, UnionMatchBindName);
115
119
auto HasOneEnumField = fieldCountOfKindIsOne (EnumField, TagMatchBindName);
Original file line number Diff line number Diff line change @@ -142,6 +142,12 @@ Changes in existing checks
142
142
<clang-tidy/checks/bugprone/signed-char-misuse>` check by fixing
143
143
false positives on C23 enums with the fixed underlying type of signed char.
144
144
145
+ - Improved :doc: `bugprone-tagged-union-member-count
146
+ <clang-tidy/checks/bugprone/tagged-union-member-count>` by fixing a false
147
+ positive when enums or unions from system header files or the ``std ``
148
+ namespace are treated as the tag or the data part of a user-defined
149
+ tagged union respectively.
150
+
145
151
- Improved :doc: `bugprone-unhandled-self-assignment
146
152
<clang-tidy/checks/bugprone/unhandled-self-assignment>` check by adding
147
153
an additional matcher that generalizes the copy-and-swap idiom pattern
Original file line number Diff line number Diff line change @@ -9,6 +9,8 @@ different from the number of data members inside the union.
9
9
A struct or a class is considered to be a tagged union if it has
10
10
exactly one union data member and exactly one enum data member and
11
11
any number of other data members that are neither unions or enums.
12
+ Furthermore, the types of the union and the enum members must
13
+ not come from system header files nor the ``std `` namespace.
12
14
13
15
Example:
14
16
@@ -28,6 +30,25 @@ Example:
28
30
} Data;
29
31
};
30
32
33
+ The following example illustrates the exception for unions and enums from
34
+ system header files and the ``std `` namespace.
35
+
36
+ .. code-block :: c++
37
+
38
+ #include <pthread.h>
39
+
40
+ struct NotTaggedUnion {
41
+ enum MyEnum { MyEnumConstant1, MyEnumConstant2 } En;
42
+ pthread_mutex_t Mutex;
43
+ };
44
+
45
+ The ``pthread_mutex_t `` type may be defined as a union behind a ``typedef ``,
46
+ in which case the check could mistake this type as a user-defined tagged union.
47
+ After all, it has exactly one enum data member and exactly one union data member.
48
+ To avoid false-positive cases originating from this, unions and enums from
49
+ system headers and the ``std `` namespace are ignored when pinpointing the
50
+ union part and the enum part of a potential user-defined tagged union.
51
+
31
52
How enum constants are counted
32
53
------------------------------
33
54
Original file line number Diff line number Diff line change
1
+ #define __SIZEOF_PTHREAD_MUTEX_T 40
2
+
3
+ namespace std {
4
+ typedef union {
5
+ struct __pthread_mutex_s {
6
+ int __lock;
7
+ unsigned int __count;
8
+ } __data;
9
+ char __size[__SIZEOF_PTHREAD_MUTEX_T];
10
+ long int __align;
11
+ } pthread_mutex_t ;
12
+ };
Original file line number Diff line number Diff line change
1
+ #define __SIZEOF_PTHREAD_MUTEX_T 40
2
+
3
+ typedef union {
4
+ struct __pthread_mutex_s {
5
+ int __lock ;
6
+ unsigned int __count ;
7
+ } __data ;
8
+ char __size [__SIZEOF_PTHREAD_MUTEX_T ];
9
+ long int __align ;
10
+ } pthread_mutex_t ;
Original file line number Diff line number Diff line change 1
- // RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t
1
+ // RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t -- -- \
2
+ // RUN: -isystem %S/Inputs/tagged-union-member-count/system
2
3
3
4
typedef enum Tags3 {
4
5
tags3_1 ,
@@ -147,3 +148,16 @@ struct Name {\
147
148
148
149
// CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3)
149
150
DECLARE_TAGGED_UNION_STRUCT (Tags3 , Union4 , TaggedUnionStructFromMacro );
151
+
152
+ // Unions from system header files should be ignored when
153
+ // we are trying to pinpoint the union part in a user-defined tagged union.
154
+ #include <pthread.h>
155
+
156
+ // This should not be analyzed as a user-defined tagged union,
157
+ // even though pthread_mutex_t could be a union.
158
+ struct SystemTypedefedUnionDataMemberShouldBeIgnored {
159
+ pthread_mutex_t Mutex ;
160
+ enum {
161
+ MyEnum
162
+ } EnumField ;
163
+ };
Original file line number Diff line number Diff line change 1
- // RUN: %check_clang_tidy -std=c++98-or-later %s bugprone-tagged-union-member-count %t
1
+ // RUN: %check_clang_tidy -std=c++98-or-later %s bugprone-tagged-union-member-count %t -- -- \
2
+ // RUN: -I%S/Inputs/tagged-union-member-count \
3
+ // RUN: -isystem %S/Inputs/tagged-union-member-count/system
2
4
// Test check with C++ features
3
5
4
6
typedef enum Tags3 {
@@ -308,3 +310,26 @@ void DoNotMatchLambdas() {
308
310
} u;
309
311
auto L = [e, u] () {};
310
312
}
313
+
314
+ // Typedefed unions from system header files should be ignored when
315
+ // we are trying to pinpoint the union part in a user-defined tagged union.
316
+ #include < pthread.h>
317
+
318
+ // This should not be analyzed as a user-defined tagged union,
319
+ // even though pthread_mutex_t may be declared as a typedefed union.
320
+ struct SystemTypedefedUnionDataMemberShouldBeIgnored {
321
+ pthread_mutex_t Mutex;
322
+ enum {
323
+ MyEnum
324
+ } EnumField;
325
+ };
326
+
327
+ // Filter when union or enum comes from the std namespace but not a system header
328
+ #include " stdnamespace.h"
329
+
330
+ struct StdNameSpaceUnionDataMemberShouldBeIgnored {
331
+ std::pthread_mutex_t Mutex;
332
+ enum {
333
+ MyEnum
334
+ } EnumField;
335
+ };
Original file line number Diff line number Diff line change 1
- // RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t
1
+ // RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t -- -- \
2
+ // RUN: -isystem %S/Inputs/tagged-union-member-count/system
2
3
3
4
typedef enum Tags3 {
4
5
tags3_1,
147
148
148
149
// CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3)
149
150
DECLARE_TAGGED_UNION_STRUCT (Tags3, Union4, TaggedUnionStructFromMacro);
151
+
152
+ // Typedefed unions from system header files should be ignored when
153
+ // we are trying to pinpoint the union part in a user-defined tagged union.
154
+ #include < pthread.h>
155
+
156
+ // This should not be analyzed as a user-defined tagged union,
157
+ // even though pthread_mutex_t may be declared as a typedefed union.
158
+ struct SystemTypedefedUnionDataMemberShouldBeIgnored {
159
+ pthread_mutex_t Mutex;
160
+ enum {
161
+ MyEnum
162
+ } EnumField;
163
+ };
Original file line number Diff line number Diff line change 1
- // RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t
1
+ // RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t -- -- \
2
+ // RUN: -isystem %S/Inputs/tagged-union-member-count/system
2
3
3
4
typedef enum Tags3 {
4
5
tags3_1,
@@ -307,3 +308,16 @@ void DoNotMatchLambdas() {
307
308
} u;
308
309
auto L = [e, u] () {};
309
310
}
311
+
312
+ // Typedefed unions from system header files should be ignored when
313
+ // we are trying to pinpoint the union part in a user-defined tagged union.
314
+ #include < pthread.h>
315
+
316
+ // This should not be analyzed as a user-defined tagged union,
317
+ // even though pthread_mutex_t may be declared as a typedefed union.
318
+ struct SystemTypedefedUnionDataMemberShouldBeIgnored {
319
+ pthread_mutex_t Mutex;
320
+ enum {
321
+ MyEnum
322
+ } EnumField;
323
+ };
You can’t perform that action at this time.
0 commit comments