Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp +++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp @@ -372,8 +372,6 @@ class PositiveSelfInitialization : NegativeAggregateType { PositiveSelfInitialization() : PositiveSelfInitialization() {} - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType - // CHECK-FIXES: PositiveSelfInitialization() : NegativeAggregateType(), PositiveSelfInitialization() {} }; class PositiveIndirectMember { @@ -552,3 +550,18 @@ int A; // CHECK-FIXES-NOT: int A{}; }; + +// Check that a delegating constructor in a template does not trigger false positives (PR#37902). +template +struct TemplateWithDelegatingCtor { + int X; + TemplateWithDelegatingCtor() : X{} {}; + TemplateWithDelegatingCtor(int) : TemplateWithDelegatingCtor(){}; +}; + +template +struct TemplateWithDelegatingCtorNSDMI { + int X{}; + TemplateWithDelegatingCtorNSDMI() = default; + TemplateWithDelegatingCtorNSDMI(int) : TemplateWithDelegatingCtorNSDMI() {} +}; Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -4496,6 +4496,8 @@ // (broken) code in a non-template! SetCtorInitializers does not expect this. bool Dependent = CurContext->isDependentContext() && (BaseType->isDependentType() || Init->isTypeDependent()); + bool Delegating = Context.hasSameUnqualifiedType( + QualType(ClassDecl->getTypeForDecl(), 0), BaseType); SourceRange InitRange = Init->getSourceRange(); if (EllipsisLoc.isValid()) { @@ -4519,8 +4521,7 @@ const CXXBaseSpecifier *DirectBaseSpec = nullptr; const CXXBaseSpecifier *VirtualBaseSpec = nullptr; if (!Dependent) { - if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), - BaseType)) + if (Delegating) return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, @@ -4548,10 +4549,14 @@ if (Dependent) { DiscardCleanupsInEvaluationContext(); - return new (Context) CXXCtorInitializer(Context, BaseTInfo, - /*IsVirtual=*/false, - InitRange.getBegin(), Init, - InitRange.getEnd(), EllipsisLoc); + if (!Delegating) + return new (Context) + CXXCtorInitializer(Context, BaseTInfo, + /*IsVirtual=*/false, InitRange.getBegin(), Init, + InitRange.getEnd(), EllipsisLoc); + else + return new (Context) CXXCtorInitializer( + Context, BaseTInfo, InitRange.getBegin(), Init, InitRange.getEnd()); } // C++ [base.class.init]p2: @@ -5063,14 +5068,16 @@ memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*)); Constructor->setCtorInitializers(initializer); - if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { - MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor); - DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation()); - } + if (!Constructor->isDependentContext()) { + if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { + MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor); + DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation()); + } - DelegatingCtorDecls.push_back(Constructor); + DelegatingCtorDecls.push_back(Constructor); - DiagnoseUninitializedFields(*this, Constructor); + DiagnoseUninitializedFields(*this, Constructor); + } return false; }