- 
                Notifications
    You must be signed in to change notification settings 
- Fork 15k
[clang-tidy] New Option Invalid Enum Default Initialization #159220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| @llvm/pr-subscribers-clang-tidy Author: Félix-Antoine Constantin (felix642) ChangesAdded a new Option IgnoredEnums to bugprone invalid enum default initialization to limit the scope of the analysis. This is needed to remove warnings on enums like std::errc where the enum doesn't define a value of 0, but is still used to check if some function calls like std::from_chars are executed correctly. The C++ Standard section 22.13.2 mentions the following : "[...] If the member ec of the return value is such that the value is equal to the value of a value-initialized errc, the conversion was successful [...]" This means that a call to  Full diff: https://github.com/llvm/llvm-project/pull/159220.diff 5 Files Affected: 
 diff --git a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp
index 1e657888b0fc0..55bcec27b1863 100644
--- a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "InvalidEnumDefaultInitializationCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/TypeVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -88,12 +90,22 @@ class FindEnumMember : public TypeVisitor<FindEnumMember, bool> {
 
 InvalidEnumDefaultInitializationCheck::InvalidEnumDefaultInitializationCheck(
     StringRef Name, ClangTidyContext *Context)
-    : ClangTidyCheck(Name, Context) {}
+    : ClangTidyCheck(Name, Context),
+      IgnoredEnums(utils::options::parseStringList(
+          Options.get("IgnoredEnums", "::std::errc"))) {}
+
+void InvalidEnumDefaultInitializationCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoredEnums",
+                utils::options::serializeStringList(IgnoredEnums));
+}
 
 void InvalidEnumDefaultInitializationCheck::registerMatchers(
     MatchFinder *Finder) {
-  auto EnumWithoutZeroValue = enumType(
-      hasDeclaration(enumDecl(isCompleteAndHasNoZeroValue()).bind("enum")));
+  auto EnumWithoutZeroValue = enumType(hasDeclaration(
+      enumDecl(isCompleteAndHasNoZeroValue(),
+               unless(matchers::matchesAnyListedName(IgnoredEnums)))
+          .bind("enum")));
   auto EnumOrArrayOfEnum = qualType(hasUnqualifiedDesugaredType(
       anyOf(EnumWithoutZeroValue,
             arrayType(hasElementType(qualType(
diff --git a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h
index b9b4f20d111fc..af4a97ae12cec 100644
--- a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h
@@ -24,6 +24,10 @@ class InvalidEnumDefaultInitializationCheck : public ClangTidyCheck {
                                         ClangTidyContext *Context);
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const std::vector<StringRef> IgnoredEnums;
 };
 
 } // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 3f403c42a168a..a678be2dbb4e9 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -219,6 +219,10 @@ Changes in existing checks
   <clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for
   variables introduced by structured bindings.
 
+- Improved :doc:`bugprone-invalid-enum-default-initialization
+  <clang-tidy/checks/bugprone/invalid-enum-default-initialization>` with new
+  ``IgnoredEnums`` option to ignore some enums during analysis.
+
 - Improved :doc:`bugprone-narrowing-conversions
   <clang-tidy/checks/bugprone/narrowing-conversions>` check by fixing
   false positive from analysis of a conditional expression in C.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
index a3bd2b6d85c37..92a51d5ec0a31 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
@@ -70,3 +70,8 @@ enum type) are set to 0.
   enum Enum1 Array3[2][2] = {{Enum1_A, Enum1_A}}; // warn: elements of second array are initialized to 0
 
   struct Struct1 S1 = {1}; // warn: element 'b' is initialized to 0
+
+.. option:: IgnoredContainers
+
+Semicolon-separated list of enums regexp for which this check won't be
+enforced. Default is `::std::errc`.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp
index eb3d5632eaef7..54e37fa32e187 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp
@@ -1,4 +1,5 @@
-// RUN: %check_clang_tidy -std=c++17 %s bugprone-invalid-enum-default-initialization %t
+// RUN: %check_clang_tidy -check-suffixes=,DEFAULT -std=c++17 %s bugprone-invalid-enum-default-initialization %t
+// RUN: %check_clang_tidy -std=c++17 %s bugprone-invalid-enum-default-initialization %t -- -config="{CheckOptions: {bugprone-invalid-enum-default-initialization.IgnoredEnums: '::MyEnum'}}"
 
 enum class Enum0: int {
   A = 0,
@@ -24,10 +25,10 @@ Enum0 E0_6{Enum0::B};
 
 Enum1 E1_1{};
 // CHECK-NOTES: :[[@LINE-1]]:11: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 Enum1 E1_2 = Enum1();
 // CHECK-NOTES: :[[@LINE-1]]:14: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 Enum1 E1_3;
 Enum1 E1_4{0};
 Enum1 E1_5{Enum1::A};
@@ -35,44 +36,44 @@ Enum1 E1_6{Enum1::B};
 
 Enum2 E2_1{};
 // CHECK-NOTES: :[[@LINE-1]]:11: warning: enum value of type 'Enum2' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 Enum2 E2_2 = Enum2();
 // CHECK-NOTES: :[[@LINE-1]]:14: warning: enum value of type 'Enum2' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 
 void f1() {
   static Enum1 S; // FIMXE: warn for this?
   Enum1 A;
   Enum1 B = Enum1();
   // CHECK-NOTES: :[[@LINE-1]]:13: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   int C = int();
 }
 
 void f2() {
   Enum1 A{};
   // CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 B = Enum1();
   // CHECK-NOTES: :[[@LINE-1]]:13: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 C[5] = {{}};
   // CHECK-NOTES: :[[@LINE-1]]:16: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   // CHECK-NOTES: :[[@LINE-3]]:17: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 D[5] = {}; // FIMXE: warn for this?
   // CHECK-NOTES: :[[@LINE-1]]:16: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
 }
 
 struct S1 {
   Enum1 E_1{};
   // CHECK-NOTES: :[[@LINE-1]]:12: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 E_2 = Enum1();
   // CHECK-NOTES: :[[@LINE-1]]:15: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 E_3;
   Enum1 E_4;
   Enum1 E_5;
@@ -80,10 +81,10 @@ struct S1 {
   S1() :
     E_3{},
     // CHECK-NOTES: :[[@LINE-1]]:8: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-    // CHECK-NOTES: :8:12: note: enum is defined here
+    // CHECK-NOTES: :9:12: note: enum is defined here
     E_4(),
     // CHECK-NOTES: :[[@LINE-1]]:8: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-    // CHECK-NOTES: :8:12: note: enum is defined here
+    // CHECK-NOTES: :9:12: note: enum is defined here
     E_5{Enum1::B}
   {}
 };
@@ -110,22 +111,22 @@ struct S5 {
 
 S2 VarS2{};
 // CHECK-NOTES: :[[@LINE-1]]:9: warning: enum value of type 'Enum1' initialized with invalid value of 0
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 // CHECK-NOTES: :[[@LINE-3]]:9: warning: enum value of type 'Enum2' initialized with invalid value of 0
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 S3 VarS3{};
 // CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 // CHECK-NOTES: :[[@LINE-3]]:10: warning: enum value of type 'Enum2' initialized with invalid value of 0
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 S4 VarS4{};
 // CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 // CHECK-NOTES: :[[@LINE-3]]:10: warning: enum value of type 'Enum2' initialized with invalid value of 0
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 S5 VarS5{};
 // CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 
 enum class EnumFwd;
 
@@ -139,7 +140,16 @@ template<typename T>
 struct Templ {
   T Mem1{};
   // CHECK-NOTES: :[[@LINE-1]]:9: warning: enum value of type 'Enum1' initialized with invalid value of 0
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
 };
 
 Templ<Enum1> TemplVar;
+
+enum MyEnum {
+  A = 1,
+  B
+};
+
+MyEnum MyEnumVar{};
+// CHECK-NOTES-DEFAULT: :[[@LINE-1]]:17: warning: enum value of type 'MyEnum' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES-DEFAULT: :148:6: note: enum is defined here
 | 
| @llvm/pr-subscribers-clang-tools-extra Author: Félix-Antoine Constantin (felix642) ChangesAdded a new Option IgnoredEnums to bugprone invalid enum default initialization to limit the scope of the analysis. This is needed to remove warnings on enums like std::errc where the enum doesn't define a value of 0, but is still used to check if some function calls like std::from_chars are executed correctly. The C++ Standard section 22.13.2 mentions the following : "[...] If the member ec of the return value is such that the value is equal to the value of a value-initialized errc, the conversion was successful [...]" This means that a call to  Full diff: https://github.com/llvm/llvm-project/pull/159220.diff 5 Files Affected: 
 diff --git a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp
index 1e657888b0fc0..55bcec27b1863 100644
--- a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "InvalidEnumDefaultInitializationCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/TypeVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -88,12 +90,22 @@ class FindEnumMember : public TypeVisitor<FindEnumMember, bool> {
 
 InvalidEnumDefaultInitializationCheck::InvalidEnumDefaultInitializationCheck(
     StringRef Name, ClangTidyContext *Context)
-    : ClangTidyCheck(Name, Context) {}
+    : ClangTidyCheck(Name, Context),
+      IgnoredEnums(utils::options::parseStringList(
+          Options.get("IgnoredEnums", "::std::errc"))) {}
+
+void InvalidEnumDefaultInitializationCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoredEnums",
+                utils::options::serializeStringList(IgnoredEnums));
+}
 
 void InvalidEnumDefaultInitializationCheck::registerMatchers(
     MatchFinder *Finder) {
-  auto EnumWithoutZeroValue = enumType(
-      hasDeclaration(enumDecl(isCompleteAndHasNoZeroValue()).bind("enum")));
+  auto EnumWithoutZeroValue = enumType(hasDeclaration(
+      enumDecl(isCompleteAndHasNoZeroValue(),
+               unless(matchers::matchesAnyListedName(IgnoredEnums)))
+          .bind("enum")));
   auto EnumOrArrayOfEnum = qualType(hasUnqualifiedDesugaredType(
       anyOf(EnumWithoutZeroValue,
             arrayType(hasElementType(qualType(
diff --git a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h
index b9b4f20d111fc..af4a97ae12cec 100644
--- a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h
@@ -24,6 +24,10 @@ class InvalidEnumDefaultInitializationCheck : public ClangTidyCheck {
                                         ClangTidyContext *Context);
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const std::vector<StringRef> IgnoredEnums;
 };
 
 } // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 3f403c42a168a..a678be2dbb4e9 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -219,6 +219,10 @@ Changes in existing checks
   <clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for
   variables introduced by structured bindings.
 
+- Improved :doc:`bugprone-invalid-enum-default-initialization
+  <clang-tidy/checks/bugprone/invalid-enum-default-initialization>` with new
+  ``IgnoredEnums`` option to ignore some enums during analysis.
+
 - Improved :doc:`bugprone-narrowing-conversions
   <clang-tidy/checks/bugprone/narrowing-conversions>` check by fixing
   false positive from analysis of a conditional expression in C.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
index a3bd2b6d85c37..92a51d5ec0a31 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
@@ -70,3 +70,8 @@ enum type) are set to 0.
   enum Enum1 Array3[2][2] = {{Enum1_A, Enum1_A}}; // warn: elements of second array are initialized to 0
 
   struct Struct1 S1 = {1}; // warn: element 'b' is initialized to 0
+
+.. option:: IgnoredContainers
+
+Semicolon-separated list of enums regexp for which this check won't be
+enforced. Default is `::std::errc`.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp
index eb3d5632eaef7..54e37fa32e187 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp
@@ -1,4 +1,5 @@
-// RUN: %check_clang_tidy -std=c++17 %s bugprone-invalid-enum-default-initialization %t
+// RUN: %check_clang_tidy -check-suffixes=,DEFAULT -std=c++17 %s bugprone-invalid-enum-default-initialization %t
+// RUN: %check_clang_tidy -std=c++17 %s bugprone-invalid-enum-default-initialization %t -- -config="{CheckOptions: {bugprone-invalid-enum-default-initialization.IgnoredEnums: '::MyEnum'}}"
 
 enum class Enum0: int {
   A = 0,
@@ -24,10 +25,10 @@ Enum0 E0_6{Enum0::B};
 
 Enum1 E1_1{};
 // CHECK-NOTES: :[[@LINE-1]]:11: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 Enum1 E1_2 = Enum1();
 // CHECK-NOTES: :[[@LINE-1]]:14: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 Enum1 E1_3;
 Enum1 E1_4{0};
 Enum1 E1_5{Enum1::A};
@@ -35,44 +36,44 @@ Enum1 E1_6{Enum1::B};
 
 Enum2 E2_1{};
 // CHECK-NOTES: :[[@LINE-1]]:11: warning: enum value of type 'Enum2' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 Enum2 E2_2 = Enum2();
 // CHECK-NOTES: :[[@LINE-1]]:14: warning: enum value of type 'Enum2' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 
 void f1() {
   static Enum1 S; // FIMXE: warn for this?
   Enum1 A;
   Enum1 B = Enum1();
   // CHECK-NOTES: :[[@LINE-1]]:13: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   int C = int();
 }
 
 void f2() {
   Enum1 A{};
   // CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 B = Enum1();
   // CHECK-NOTES: :[[@LINE-1]]:13: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 C[5] = {{}};
   // CHECK-NOTES: :[[@LINE-1]]:16: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   // CHECK-NOTES: :[[@LINE-3]]:17: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 D[5] = {}; // FIMXE: warn for this?
   // CHECK-NOTES: :[[@LINE-1]]:16: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
 }
 
 struct S1 {
   Enum1 E_1{};
   // CHECK-NOTES: :[[@LINE-1]]:12: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 E_2 = Enum1();
   // CHECK-NOTES: :[[@LINE-1]]:15: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
   Enum1 E_3;
   Enum1 E_4;
   Enum1 E_5;
@@ -80,10 +81,10 @@ struct S1 {
   S1() :
     E_3{},
     // CHECK-NOTES: :[[@LINE-1]]:8: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-    // CHECK-NOTES: :8:12: note: enum is defined here
+    // CHECK-NOTES: :9:12: note: enum is defined here
     E_4(),
     // CHECK-NOTES: :[[@LINE-1]]:8: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
-    // CHECK-NOTES: :8:12: note: enum is defined here
+    // CHECK-NOTES: :9:12: note: enum is defined here
     E_5{Enum1::B}
   {}
 };
@@ -110,22 +111,22 @@ struct S5 {
 
 S2 VarS2{};
 // CHECK-NOTES: :[[@LINE-1]]:9: warning: enum value of type 'Enum1' initialized with invalid value of 0
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 // CHECK-NOTES: :[[@LINE-3]]:9: warning: enum value of type 'Enum2' initialized with invalid value of 0
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 S3 VarS3{};
 // CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 // CHECK-NOTES: :[[@LINE-3]]:10: warning: enum value of type 'Enum2' initialized with invalid value of 0
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 S4 VarS4{};
 // CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 // CHECK-NOTES: :[[@LINE-3]]:10: warning: enum value of type 'Enum2' initialized with invalid value of 0
-// CHECK-NOTES: :13:6: note: enum is defined here
+// CHECK-NOTES: :14:6: note: enum is defined here
 S5 VarS5{};
 // CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0
-// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :9:12: note: enum is defined here
 
 enum class EnumFwd;
 
@@ -139,7 +140,16 @@ template<typename T>
 struct Templ {
   T Mem1{};
   // CHECK-NOTES: :[[@LINE-1]]:9: warning: enum value of type 'Enum1' initialized with invalid value of 0
-  // CHECK-NOTES: :8:12: note: enum is defined here
+  // CHECK-NOTES: :9:12: note: enum is defined here
 };
 
 Templ<Enum1> TemplVar;
+
+enum MyEnum {
+  A = 1,
+  B
+};
+
+MyEnum MyEnumVar{};
+// CHECK-NOTES-DEFAULT: :[[@LINE-1]]:17: warning: enum value of type 'MyEnum' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES-DEFAULT: :148:6: note: enum is defined here
 | 
| @balazske, this check was recently added by you. If you have time to review this PR I would greatly appreciate it. | 
        
          
                clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
              
                Outdated
          
            Show resolved
            Hide resolved
        
              
          
                clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
              
                Outdated
          
            Show resolved
            Hide resolved
        
              
          
                clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp
              
                Outdated
          
            Show resolved
            Hide resolved
        
              
          
                clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
              
                Outdated
          
            Show resolved
            Hide resolved
        
              
          
                clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
          
            Show resolved
            Hide resolved
        
              
          
                clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp
              
                Outdated
          
            Show resolved
            Hide resolved
        
      | Would it be better to add the  | 
| 
 I think you're right. I wanted to give the user as much control as possible hence why I added an option with  I think, I'll keep the option, but move the  | 
| ✅ With the latest revision this PR passed the C/C++ code formatter. | 
| Code is good, just documentation can be updated ( | 
| 
 Should we explicitly mention  
 This way we won't have to change the check description if we add other enumerators in the future. | 
| 
 I think it is more accurate to have the exact list of ignored enums. Probably (but I am not familiar with the standard) this kind of initialization is always valid (no undefined behavior), just it may be confusing and probably indication of a coding error. | 
        
          
                clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
              
                Outdated
          
            Show resolved
            Hide resolved
        
      There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Added a new Option IgnoredEnums to bugprone invalid enum default initialization to limit the scope of the analysis. This is needed to remove warnings on enums like std::errc where the enum doesn't define a value of 0, but is still used to check if some function calls like std::from_chars are executed correctly.
10f5dd2    to
    1c05947      
    Compare
  
    | Please make your email public - https://llvm.org/docs/DeveloperPolicy.html#email-addresses | 
| Thank you for the info. I don't know why this setting was changed. Could you please confirm that everything looks good now or if my email still appears as private ? | 
| 
 Everything is fine, thanks. | 
) Added a new Option IgnoredEnums to bugprone invalid enum default initialization to limit the scope of the analysis. This is needed to remove warnings on enums like std::errc where the enum doesn't define a value of 0, but is still used to check if some function calls like std::from_chars are executed correctly. The C++ Standard section 22.13.2 mentions the following : "[...] If the member ec of the return value is such that the value is equal to the value of a value-initialized errc, the conversion was successful [...]" This means that a call to `std::errc{}` is clearly defined by the standard and should not raise any warning under this check.
Added a new Option IgnoredEnums to bugprone invalid enum default initialization to limit the scope of the analysis. This is needed to remove warnings on enums like std::errc where the enum doesn't define a value of 0, but is still used to check if some function calls like std::from_chars are executed correctly.
The C++ Standard section 22.13.2 mentions the following : "[...] If the member ec of the return value is such that the value is equal to the value of a value-initialized errc, the conversion was successful [...]"
This means that a call to
std::errc{}is clearly defined by the standard and should not raise any warning under this check.