-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[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.