[clang] [clang-tools-extra] [Sema]Report error for non-base types in constructor initializers before causing issue in initializer order (PR #201379)

via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 5 01:05:59 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tools-extra

Author: Gábor Spaits (spaits)

<details>
<summary>Changes</summary>

Fixes #<!-- -->201593 .

---
Full diff: https://github.com/llvm/llvm-project/pull/201379.diff


4 Files Affected:

- (modified) clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.cpp (+1-1) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+27-24) 
- (modified) clang/test/SemaCXX/constructor-initializer.cpp (+18) 
- (modified) clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp (-10) 


``````````diff
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 55963eae2c1b5..e1724c3c1e338 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
@@ -647,7 +647,7 @@ namespace gh192510 {
   };
 
   template<typename T>
-  class X: public Base {
+  class X: public Base, private C<T> {
     using INT = C<T>;
 
     X(INT i) : INT(i) {} // no crash
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 9f9e76bf336b0..6f5baf9166287 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/ComparisonCategories.h"
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DynamicRecursiveASTVisitor.h"
@@ -4819,33 +4820,35 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
       return true;
   }
 
+  if (!Dependent &&
+      declaresSameEntity(ClassDecl, BaseType->getAsCXXRecordDecl()))
+    return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl);
+
   // Check for direct and virtual base classes.
   const CXXBaseSpecifier *DirectBaseSpec = nullptr;
   const CXXBaseSpecifier *VirtualBaseSpec = nullptr;
-  if (!Dependent) {
-    if (declaresSameEntity(ClassDecl, BaseType->getAsCXXRecordDecl()))
-      return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl);
-
-    FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
-                        VirtualBaseSpec);
-
-    // C++ [base.class.init]p2:
-    // Unless the mem-initializer-id names a nonstatic data member of the
-    // constructor's class or a direct or virtual base of that class, the
-    // mem-initializer is ill-formed.
-    if (!DirectBaseSpec && !VirtualBaseSpec) {
-      // If the class has any dependent bases, then it's possible that
-      // one of those types will resolve to the same type as
-      // BaseType. Therefore, just treat this as a dependent base
-      // class initialization.  FIXME: Should we try to check the
-      // initialization anyway? It seems odd.
-      if (ClassDecl->hasAnyDependentBases())
-        Dependent = true;
-      else
-        return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
-               << BaseType << Context.getCanonicalTagType(ClassDecl)
-               << BaseTInfo->getTypeLoc().getSourceRange();
-    }
+
+  FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
+                      VirtualBaseSpec);
+
+  // C++ [base.class.init]p2:
+  // Unless the mem-initializer-id names a nonstatic data member of the
+  // constructor's class or a direct or virtual base of that class, the
+  // mem-initializer is ill-formed.
+  if (!DirectBaseSpec && !VirtualBaseSpec) {
+    // If the class has any dependent bases, then it's possible that one of
+    // those types will resolve to the same type as BaseType. Therefore, just
+    // treat this as a dependent base class initialization.
+    // FIXME: Should we try to check the initialization anyway? It seems odd.
+    if (ClassDecl->hasAnyDependentBases())
+      Dependent = true;
+    // We may have a delegating initializer here but in a dependent context.
+    // Since that is also a type, that isn't a direct or virtual base of the
+    // instantiated type. That will be handled later.
+    else if (!declaresSameEntity(ClassDecl, BaseType->getAsCXXRecordDecl()))
+      return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
+             << BaseType << Context.getCanonicalTagType(ClassDecl)
+             << BaseTInfo->getTypeLoc().getSourceRange();
   }
 
   if (Dependent) {
diff --git a/clang/test/SemaCXX/constructor-initializer.cpp b/clang/test/SemaCXX/constructor-initializer.cpp
index 96be8dda97735..ff6374d6eb6ef 100644
--- a/clang/test/SemaCXX/constructor-initializer.cpp
+++ b/clang/test/SemaCXX/constructor-initializer.cpp
@@ -323,3 +323,21 @@ A f2(const B &b) {
   return b; // expected-error {{no matching constructor for initialization of 'B'}}
 }
 }
+
+namespace PR7179 {
+struct X
+{
+  struct Y
+  {
+    template <class T> Y(T x) : X(x) { } // expected-error {{type 'X' is not a direct or virtual base of 'PR7179::X::Y'}}
+  };
+};
+}
+
+namespace PR201379 {
+struct S1 {
+  template<typename T>
+  S1(T) : d(), T()  {} // expected-error {{type 'T' is not a direct or virtual base of 'PR201379::S1'}}
+  int d;
+};
+}
diff --git a/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp b/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp
index 0613338945978..b0153c6984b5b 100644
--- a/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp
+++ b/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp
@@ -120,16 +120,6 @@ namespace test3 {
   };
 }
 
-namespace PR7179 {
-  struct X
-  {
-    struct Y
-    {
-      template <class T> Y(T x) : X(x) { }
-    };
-  };
-}
-
 namespace test3 {
   struct foo {
     struct {

``````````

</details>


https://github.com/llvm/llvm-project/pull/201379


More information about the cfe-commits mailing list