https://github.com/aaronpuchert created 
https://github.com/llvm/llvm-project/pull/217715

Virtual bases are initialized by the most derived class, and they come before 
non-virtual base class initializers. So an abstract class can assume that 
virtual bases are already initialized by the time their constructor runs.

It seems that the warning generally doesn't take indirect bases into account, 
otherwise this would become a bit more complicated.

Fixes #204858.

>From 6c8d70a0c324c259a3964d5db107901bb75f8d5c Mon Sep 17 00:00:00 2001
From: Aaron Puchert <[email protected]>
Date: Thu, 20 Aug 2026 19:16:11 +0200
Subject: [PATCH] [Clang][Sema] Don't warn on accessing virtual base from
 abstract class

Virtual bases are initialized by the most derived class, and they come
before non-virtual base class initializers. So an abstract class can
assume that virtual bases are already initialized by the time their
constructor runs.

It seems that the warning generally doesn't take indirect bases into
account, otherwise this would become a bit more complicated.

Fixes #204858.
---
 clang/lib/Sema/SemaDeclCXX.cpp       |  7 ++++++-
 clang/test/SemaCXX/uninitialized.cpp | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index e84d35b2b5ecb..34bf0207b478e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4158,8 +4158,13 @@ namespace {
     }
 
     llvm::SmallPtrSet<QualType, 4> UninitializedBaseClasses;
-    for (const auto &I : RD->bases())
+    for (const auto &I : RD->bases()) {
+      // Virtual bases are initialized from the most derived class, so an
+      // abstract base class constructor can assume it to be initialized.
+      if (I.isVirtual() && RD->isAbstract())
+        continue;
       UninitializedBaseClasses.insert(I.getType().getCanonicalType());
+    }
 
     if (UninitializedFields.empty() && UninitializedBaseClasses.empty())
       return;
diff --git a/clang/test/SemaCXX/uninitialized.cpp 
b/clang/test/SemaCXX/uninitialized.cpp
index cc368c22e0776..b9dc64d70f555 100644
--- a/clang/test/SemaCXX/uninitialized.cpp
+++ b/clang/test/SemaCXX/uninitialized.cpp
@@ -1411,6 +1411,8 @@ struct B : public A {
 
   B(int (*)[4]) : A(foo()) {}
   // expected-warning@-1 {{base_class_access::A' is uninitialized when used 
here to access 'base_class_access::A::foo'}}
+
+  virtual void f() = 0;
 };
 
 struct C {
@@ -1428,6 +1430,22 @@ struct D : public C, public A {
   // expected-warning@-1 {{base_class_access::A' is uninitialized when used 
here to access 'base_class_access::A::foo'}}
 };
 
+struct E : public virtual A {
+  E(int (*)[3]) : A(i) {}
+  // expected-warning@-1 {{base class 'base_class_access::A' is uninitialized 
when used here to access 'base_class_access::A::i'}}
+
+  E(int (*)[4]) : A(foo()) {}
+  // expected-warning@-1 {{base_class_access::A' is uninitialized when used 
here to access 'base_class_access::A::foo'}}
+};
+
+// Accessing virtual base class members from an abstract class is fine.
+struct F : public virtual A {
+  F(int (*)[3]) : A(i) {}
+  F(int (*)[4]) : A(foo()) {}
+
+  virtual void f() = 0;
+};
+
 }
 
 namespace value {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to