diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp index 43812fe17a1c77..a191598415217e 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp @@ -433,17 +433,25 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer( [&](const FieldDecl *F) { OrderedFields.push_back(F); }); // Collect all the fields we need to initialize, including indirect fields. + // It only includes fields that have not been fixed SmallPtrSet AllFieldsToInit; - forEachField(ClassDecl, FieldsToInit, - [&](const FieldDecl *F) { AllFieldsToInit.insert(F); }); - if (AllFieldsToInit.empty()) + forEachField(ClassDecl, FieldsToInit, [&](const FieldDecl *F) { + if (!HasRecordClassMemberSet.contains(F)) { + AllFieldsToInit.insert(F); + HasRecordClassMemberSet.insert(F); + } + }); + if (FieldsToInit.empty()) return; DiagnosticBuilder Diag = diag(Ctor ? Ctor->getBeginLoc() : ClassDecl.getLocation(), "%select{|union }0constructor %select{does not|should}0 initialize " "%select{|one of }0these fields: %1") - << IsUnion << toCommaSeparatedString(OrderedFields, AllFieldsToInit); + << IsUnion << toCommaSeparatedString(OrderedFields, FieldsToInit); + + if (AllFieldsToInit.empty()) + return; // Do not propose fixes for constructors in macros since we cannot place them // correctly. diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h index 5b4144396eab4d..af7b14ec68ad9c 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h @@ -10,6 +10,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_MEMBER_INIT_H #include "../ClangTidyCheck.h" +#include "llvm/ADT/DenseSet.h" namespace clang { namespace tidy { @@ -72,6 +73,10 @@ class ProTypeMemberInitCheck : public ClangTidyCheck { // instead of brace initialization. Only effective in C++11 mode. Default is // false. bool UseAssignment; + + // Record the member variables that have been initialized to prevent repeated + // initialization. + llvm::DenseSet HasRecordClassMemberSet; }; } // namespace cppcoreguidelines diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp index 403f28baf99d49..8cab4fd755752f 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp @@ -208,9 +208,8 @@ struct PositiveMultipleConstructors { PositiveMultipleConstructors(const PositiveMultipleConstructors &) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B - // FIXME: The fix-its here collide providing an erroneous fix int A, B; - // CHECK-FIXES: int A{}{}{}, B{}{}{}; + // CHECK-FIXES: int A{}, B{}; }; typedef struct {