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(
105105
106106void TaggedUnionMemberCountCheck::registerMatchers (MatchFinder *Finder) {
107107
108- auto UnionField = fieldDecl ( hasType ( qualType (
109- hasCanonicalType ( recordType ( hasDeclaration ( recordDecl ( isUnion ())))) )));
108+ auto NotFromSystemHeaderOrStdNamespace =
109+ unless ( anyOf ( isExpansionInSystemHeader (), isInStdNamespace ( )));
110110
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)))))));
113117
114118 auto HasOneUnionField = fieldCountOfKindIsOne (UnionField, UnionMatchBindName);
115119 auto HasOneEnumField = fieldCountOfKindIsOne (EnumField, TagMatchBindName);
Original file line number Diff line number Diff line change @@ -142,6 +142,12 @@ Changes in existing checks
142142 <clang-tidy/checks/bugprone/signed-char-misuse>` check by fixing
143143 false positives on C23 enums with the fixed underlying type of signed char.
144144
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+
145151- Improved :doc: `bugprone-unhandled-self-assignment
146152 <clang-tidy/checks/bugprone/unhandled-self-assignment>` check by adding
147153 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.
99A struct or a class is considered to be a tagged union if it has
1010exactly one union data member and exactly one enum data member and
1111any 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.
1214
1315Example:
1416
@@ -28,6 +30,25 @@ Example:
2830 } Data;
2931 };
3032
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+
3152How enum constants are counted
3253------------------------------
3354
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
23
34typedef enum Tags3 {
45 tags3_1 ,
@@ -147,3 +148,16 @@ struct Name {\
147148
148149// CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3)
149150DECLARE_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
24// Test check with C++ features
35
46typedef enum Tags3 {
@@ -308,3 +310,26 @@ void DoNotMatchLambdas() {
308310 } u;
309311 auto L = [e, u] () {};
310312}
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
23
34typedef enum Tags3 {
45 tags3_1,
147148
148149// CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3)
149150DECLARE_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
23
34typedef enum Tags3 {
45 tags3_1,
@@ -307,3 +308,16 @@ void DoNotMatchLambdas() {
307308 } u;
308309 auto L = [e, u] () {};
309310}
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