[clang] [Clang][Sema] Don't warn on accessing virtual base from abstract class (PR #217715)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 20 11:20:53 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Aaron Puchert (aaronpuchert)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/217715.diff
2 Files Affected:
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+6-1)
- (modified) clang/test/SemaCXX/uninitialized.cpp (+18)
``````````diff
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 at -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 at -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 at -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 at -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 {
``````````
</details>
https://github.com/llvm/llvm-project/pull/217715
More information about the cfe-commits
mailing list