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@-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 { `````````` </details> https://github.com/llvm/llvm-project/pull/217715 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
