diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp @@ -129,6 +129,14 @@ const EnumDecl *ED = T->castAs()->getDecl(); EnumValueVector DeclValues = getDeclValuesForEnum(ED); + + // If the declarator list is empty, bail out. + // Every initialization an enum with a fixed underlying type but without any + // enumerators would produce a warning if we were to continue at this point. + // The most notable example is std::byte in the C++17 standard library. + if (DeclValues.size() == 0) + return; + // Check if any of the enum values possibly match. bool PossibleValueMatch = llvm::any_of( DeclValues, ConstraintBasedEQEvaluator(C, *ValueToCast)); diff --git a/clang/test/Analysis/enum-cast-out-of-range.cpp b/clang/test/Analysis/enum-cast-out-of-range.cpp --- a/clang/test/Analysis/enum-cast-out-of-range.cpp +++ b/clang/test/Analysis/enum-cast-out-of-range.cpp @@ -198,3 +198,20 @@ s.E = static_cast(4); // OK. s.E = static_cast(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}} } + + +enum class empty_unfixed {}; + +enum class empty_fixed: char {}; + +enum class empty_fixed_unsigned: unsigned char {}; + +void ignore_unused(...); + +void empty_enums_init_with_zero_should_not_warn() { + empty_unfixed eu = static_cast(0); //should always be OK to zero initialize any enum + empty_fixed ef = static_cast(0); + empty_fixed_unsigned efu = static_cast(0); + + ignore_unused(eu, ef, efu); +}