Skip to content

Commit 61847fc

Browse files
committed
[clang-tidy] Fix bugprone-tagged-union-member-count false-positive
Types from system headers and the std namespace are no longer considered as the enum part or the union part of a user-defined tagged union. Fixes #134840
1 parent 690c3ee commit 61847fc

File tree

6 files changed

+82
-4
lines changed

6 files changed

+82
-4
lines changed

clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,15 @@ void TaggedUnionMemberCountCheck::storeOptions(
105105

106106
void 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);

clang-tools-extra/docs/clang-tidy/checks/bugprone/tagged-union-member-count.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ different from the number of data members inside the union.
99
A struct or a class is considered to be a tagged union if it has
1010
exactly one union data member and exactly one enum data member and
1111
any number of other data members that are neither unions or enums.
12+
The union and enum data members that are from system header files or
13+
the std namespace are not considered to make up the tagged union part
14+
of a user-defined tagged union type.
1215

1316
Example:
1417

@@ -28,6 +31,25 @@ Example:
2831
} Data;
2932
};
3033
34+
The following example illustrates the exception for unions and enums from
35+
system header files and the std namespace.
36+
37+
.. code-block:: c++
38+
39+
#include <pthread.h>
40+
41+
struct NotTaggedUnion {
42+
enum MyEnum { MyEnumConstant1, MyEnumConstant2 } En;
43+
pthread_mutex_t Mutex;
44+
};
45+
46+
The pthread_mutex_t type may be defined as a union behind a typedef,
47+
in which case the check could mistake this type as a user-defined tagged union.
48+
After all it has exactly one enum data member and exactly one union data member.
49+
To avoid false-positive cases originating from this, unions and enums from
50+
system headers and the std namespace are ignored when pinpointing the
51+
union part and the enum part of a potential user-defined tagged union.
52+
3153
How enum constants are counted
3254
------------------------------
3355

clang-tools-extra/test/clang-tidy/checkers/bugprone/tagged-union-member-count.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,16 @@ struct Name {\
147147

148148
// CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3)
149149
DECLARE_TAGGED_UNION_STRUCT(Tags3, Union4, TaggedUnionStructFromMacro);
150+
151+
// Typedefed unions from system header files should be ignored when
152+
// we are trying to pinpoint the union part in a user-defined tagged union.
153+
#include "pthread.h"
154+
155+
// This should not be analyzed as a user-defined tagged union,
156+
// even though pthread_mutex_t may be declared as a typedefed union.
157+
struct SystemTypedefedUnionDataMemberShouldBeIgnored {
158+
pthread_mutex_t Mutex;
159+
enum {
160+
MyEnum
161+
} EnumField;
162+
};

clang-tools-extra/test/clang-tidy/checkers/bugprone/tagged-union-member-count.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,16 @@ void DoNotMatchLambdas() {
308308
} u;
309309
auto L = [e, u] () {};
310310
}
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+
};

clang-tools-extra/test/clang-tidy/checkers/bugprone/tagged-union-member-count.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,16 @@
147147

148148
// CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3)
149149
DECLARE_TAGGED_UNION_STRUCT(Tags3, Union4, TaggedUnionStructFromMacro);
150+
151+
// Typedefed unions from system header files should be ignored when
152+
// we are trying to pinpoint the union part in a user-defined tagged union.
153+
#include "pthread.h"
154+
155+
// This should not be analyzed as a user-defined tagged union,
156+
// even though pthread_mutex_t may be declared as a typedefed union.
157+
struct SystemTypedefedUnionDataMemberShouldBeIgnored {
158+
pthread_mutex_t Mutex;
159+
enum {
160+
MyEnum
161+
} EnumField;
162+
};

clang-tools-extra/test/clang-tidy/checkers/bugprone/tagged-union-member-count.mm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,16 @@ void DoNotMatchLambdas() {
307307
} u;
308308
auto L = [e, u] () {};
309309
}
310+
311+
// Typedefed unions from system header files should be ignored when
312+
// we are trying to pinpoint the union part in a user-defined tagged union.
313+
#include "pthread.h"
314+
315+
// This should not be analyzed as a user-defined tagged union,
316+
// even though pthread_mutex_t may be declared as a typedefed union.
317+
struct SystemTypedefedUnionDataMemberShouldBeIgnored {
318+
pthread_mutex_t Mutex;
319+
enum {
320+
MyEnum
321+
} EnumField;
322+
};

0 commit comments

Comments
 (0)