@@ -361,7 +361,8 @@ void ProTypeMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
361361}
362362
363363// FIXME: Copied from clang/lib/Sema/SemaDeclCXX.cpp.
364- static bool isIncompleteOrZeroLengthArrayType (ASTContext &Context, QualType T) {
364+ static bool isIncompleteOrZeroLengthArrayType (const ASTContext &Context,
365+ QualType T) {
365366 if (T->isIncompleteArrayType ())
366367 return true ;
367368
@@ -375,7 +376,7 @@ static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
375376 return false ;
376377}
377378
378- static bool isEmpty (ASTContext &Context, const QualType &Type) {
379+ static bool isEmpty (const ASTContext &Context, const QualType &Type) {
379380 if (const CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl ()) {
380381 return ClassDecl->isEmpty ();
381382 }
@@ -431,19 +432,13 @@ static llvm::StringLiteral getInitializer(QualType QT, bool UseAssignment) {
431432 }
432433}
433434
434- void ProTypeMemberInitCheck::checkMissingMemberInitializer (
435- ASTContext &Context, const CXXRecordDecl &ClassDecl,
436- const CXXConstructorDecl *Ctor) {
437- const bool IsUnion = ClassDecl.isUnion ();
438-
439- if (IsUnion && ClassDecl.hasInClassInitializer ())
440- return ;
441-
442- // Gather all fields (direct and indirect) that need to be initialized.
443- SmallPtrSet<const FieldDecl *, 16 > FieldsToInit;
435+ static void
436+ computeFieldsToInit (const ASTContext &Context, const RecordDecl &Record,
437+ bool IgnoreArrays,
438+ SmallPtrSetImpl<const FieldDecl *> &FieldsToInit) {
444439 bool AnyMemberHasInitPerUnion = false ;
445440 forEachFieldWithFilter (
446- ClassDecl, ClassDecl .fields (), AnyMemberHasInitPerUnion,
441+ Record, Record .fields (), AnyMemberHasInitPerUnion,
447442 [&](const FieldDecl *F) {
448443 if (IgnoreArrays && F->getType ()->isArrayType ())
449444 return ;
@@ -458,6 +453,19 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer(
458453 !AnyMemberHasInitPerUnion)
459454 FieldsToInit.insert (F);
460455 });
456+ }
457+
458+ void ProTypeMemberInitCheck::checkMissingMemberInitializer (
459+ ASTContext &Context, const CXXRecordDecl &ClassDecl,
460+ const CXXConstructorDecl *Ctor) {
461+ const bool IsUnion = ClassDecl.isUnion ();
462+
463+ if (IsUnion && ClassDecl.hasInClassInitializer ())
464+ return ;
465+
466+ // Gather all fields (direct and indirect) that need to be initialized.
467+ SmallPtrSet<const FieldDecl *, 16 > FieldsToInit;
468+ computeFieldsToInit (Context, ClassDecl, IgnoreArrays, FieldsToInit);
461469 if (FieldsToInit.empty ())
462470 return ;
463471
@@ -507,7 +515,7 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer(
507515 // Collect all fields but only suggest a fix for the first member of unions,
508516 // as initializing more than one union member is an error.
509517 SmallPtrSet<const FieldDecl *, 16 > FieldsToFix;
510- AnyMemberHasInitPerUnion = false ;
518+ bool AnyMemberHasInitPerUnion = false ;
511519 forEachFieldWithFilter (ClassDecl, ClassDecl.fields (),
512520 AnyMemberHasInitPerUnion, [&](const FieldDecl *F) {
513521 if (!FieldsToInit.contains (F))
@@ -582,6 +590,17 @@ void ProTypeMemberInitCheck::checkMissingBaseClassInitializer(
582590
583591void ProTypeMemberInitCheck::checkUninitializedTrivialType (
584592 const ASTContext &Context, const VarDecl *Var) {
593+ // Verify that the record actually needs initialization
594+ const CXXRecordDecl *Record = Var->getType ()->getAsCXXRecordDecl ();
595+ if (!Record)
596+ return ;
597+
598+ SmallPtrSet<const FieldDecl *, 16 > FieldsToInit;
599+ computeFieldsToInit (Context, *Record, IgnoreArrays, FieldsToInit);
600+
601+ if (FieldsToInit.empty ())
602+ return ;
603+
585604 const DiagnosticBuilder Diag =
586605 diag (Var->getBeginLoc (), " uninitialized record type: %0" ) << Var;
587606
0 commit comments