https://github.com/steakhal created https://github.com/llvm/llvm-project/pull/141232
Resolves https://github.com/llvm/llvm-project/issues/76208#issuecomment-2830854351 Quoting the docs of `[[clang::flag_enum]]`: https://clang.llvm.org/docs/AttributeReference.html#flag-enum > This attribute can be added to an enumerator to signal to the compiler that it > is intended to be used as a flag type. This will cause the compiler to assume > that the range of the type includes all of the values that you can get by > manipulating bits of the enumerator when issuing warnings. >From 8ddc451d9017bbf68c847008878c2c8436f95a46 Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Fri, 23 May 2025 15:04:52 +0200 Subject: [PATCH] [analyzer] Ignore [[clang::flag_enum]] enums in the EnumCastOutOfRange checker Resolves https://github.com/llvm/llvm-project/issues/76208#issuecomment-2830854351 Quoting the docs of [[clang::flag_enum]]: https://clang.llvm.org/docs/AttributeReference.html#flag-enum > This attribute can be added to an enumerator to signal to the compiler that it > is intended to be used as a flag type. This will cause the compiler to assume > that the range of the type includes all of the values that you can get by > manipulating bits of the enumerator when issuing warnings. --- clang/docs/analyzer/checkers.rst | 6 +++++- .../Checkers/EnumCastOutOfRangeChecker.cpp | 5 +++++ clang/test/Analysis/enum-cast-out-of-range.c | 11 +++++++++++ clang/test/Analysis/enum-cast-out-of-range.cpp | 11 +++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index c2ae80c47eca1..26c5028e04955 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -773,7 +773,11 @@ enumerators at all. **Limitations** This checker does not accept the coding pattern where an enum type is used to -store combinations of flag values: +store combinations of flag values. +Such enums should be annotated with the `__attribute__((flag_enum))` or by the +`[[clang::flag_enum]]` attribute to signal this intent. Refer to the +`documentation <https://clang.llvm.org/docs/AttributeReference.html#flag-enum>`_ +of this Clang attribute. .. code-block:: cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp index 0fa20428c1b56..355e82e465e82 100644 --- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp @@ -19,6 +19,7 @@ // enumeration value //===----------------------------------------------------------------------===// +#include "clang/AST/Attr.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" @@ -149,6 +150,10 @@ void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE, // function to handle this. const EnumDecl *ED = T->castAs<EnumType>()->getDecl(); + // [[clang::flag_enum]] annotated enums are by definition should be ignored. + if (ED->hasAttr<FlagEnumAttr>()) + return; + EnumValueVector DeclValues = getDeclValuesForEnum(ED); // If the declarator list is empty, bail out. diff --git a/clang/test/Analysis/enum-cast-out-of-range.c b/clang/test/Analysis/enum-cast-out-of-range.c index a6eef92f418d1..f9f7aac5ae1b7 100644 --- a/clang/test/Analysis/enum-cast-out-of-range.c +++ b/clang/test/Analysis/enum-cast-out-of-range.c @@ -64,3 +64,14 @@ void testTrackExpression(int i) { (void)(enum En_t)(i); // expected-warning {{not in the valid range of values for 'En_t'}} // expected-note@-1 {{not in the valid range of values for 'En_t'}} } + +enum __attribute__((flag_enum)) FlagEnum { + FE_BIT_1 = 1 << 0, + FE_BIT_2 = 1 << 1, + FE_BIT_3 = 1 << 2, +}; + +void testFlagEnum_gh_76208(void) { + enum FlagEnum First2BitsSet = (enum FlagEnum)(FE_BIT_1 | FE_BIT_2); // no-warning: Enums with the attribute 'flag_enum' are not checked + (void)First2BitsSet; +} diff --git a/clang/test/Analysis/enum-cast-out-of-range.cpp b/clang/test/Analysis/enum-cast-out-of-range.cpp index a5ac4f3fd0567..81763ae893135 100644 --- a/clang/test/Analysis/enum-cast-out-of-range.cpp +++ b/clang/test/Analysis/enum-cast-out-of-range.cpp @@ -230,3 +230,14 @@ void foo() { ignore_unused(c, x, d); } + +enum [[clang::flag_enum]] FlagEnum { + FE_BIT_1 = 1 << 0, + FE_BIT_2 = 1 << 1, + FE_BIT_3 = 1 << 2, +}; + +void testFlagEnum_gh_76208(void) { + FlagEnum First2BitsSet = (FlagEnum)(FE_BIT_1 | FE_BIT_2); // no-warning: Enums with the attribute 'flag_enum' are not checked + (void)First2BitsSet; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits