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
