https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/137773
>From 53dea9e3d96c622c7e1ffc892117723ff1d3831c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Tue, 29 Apr 2025 11:11:08 +0200 Subject: [PATCH] [clang] Mark constructors with invalid initializers as invalid If a member or base initializer of a constructor turns out to be invalid, mark the entire constructor as invalid. --- clang/lib/Parse/ParseDeclCXX.cpp | 4 +++- .../AST/ByteCode/constexpr-subobj-initialization.cpp | 12 +++++------- clang/test/SemaCXX/class-base-member-init.cpp | 2 +- clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp | 4 ++-- .../test/SemaCXX/constexpr-subobj-initialization.cpp | 8 ++++---- clang/test/SemaCXX/constructor-initializer.cpp | 10 +++++++--- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 51fe0663a8d1a..7212ac8daea23 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -4064,8 +4064,10 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { MemInitResult MemInit = ParseMemInitializer(ConstructorDecl); if (!MemInit.isInvalid()) MemInitializers.push_back(MemInit.get()); - else + else { + ConstructorDecl->setInvalidDecl(); AnyErrors = true; + } if (Tok.is(tok::comma)) ConsumeToken(); diff --git a/clang/test/AST/ByteCode/constexpr-subobj-initialization.cpp b/clang/test/AST/ByteCode/constexpr-subobj-initialization.cpp index 1a35994944190..fbb27fa9f8653 100644 --- a/clang/test/AST/ByteCode/constexpr-subobj-initialization.cpp +++ b/clang/test/AST/ByteCode/constexpr-subobj-initialization.cpp @@ -12,29 +12,27 @@ struct DelBase { constexpr DelBase() = delete; // expected-note {{'DelBase' has been explicitly marked deleted here}} }; -struct Foo : DelBase { // expected-note 2{{constructor of base class 'baseclass_uninit::DelBase' is not called}} +struct Foo : DelBase { // expected-note-re 2{{constructor of base class '{{.*}}DelBase' is not called}} constexpr Foo() {}; // expected-error {{call to deleted constructor of 'DelBase'}} }; constexpr Foo f; // expected-error {{must be initialized by a constant expression}} - struct Bar : Foo { constexpr Bar() {}; }; constexpr Bar bar; // expected-error {{must be initialized by a constant expression}} struct Base {}; -struct A : Base { // expected-note {{constructor of base class 'baseclass_uninit::Base' is not called}} +struct A : Base { // expected-note 2{{candidate constructor}} constexpr A() : value() {} // expected-error {{member initializer 'value' does not name a non-static data member or base class}} }; -constexpr A a; // expected-error {{must be initialized by a constant expression}} - +constexpr A a; // expected-error {{no matching constructor}} -struct B : Base { // expected-note {{constructor of base class 'baseclass_uninit::Base' is not called}} +struct B : Base { // expected-note 2{{candidate constructor}} constexpr B() : {} // expected-error {{expected class member or base class name}} }; -constexpr B b; // expected-error {{must be initialized by a constant expression}} +constexpr B b; // expected-error {{no matching constructor}} } // namespace baseclass_uninit diff --git a/clang/test/SemaCXX/class-base-member-init.cpp b/clang/test/SemaCXX/class-base-member-init.cpp index a6bb4410a81c8..cf297328c1f83 100644 --- a/clang/test/SemaCXX/class-base-member-init.cpp +++ b/clang/test/SemaCXX/class-base-member-init.cpp @@ -86,7 +86,7 @@ namespace test5 { decltype(Base(1))(2), // expected-error {{multiple initializations given for base 'decltype(Base(1))' (aka 'test5::Base')}} decltype(int())() { // expected-error {{constructor initializer 'decltype(int())' (aka 'int') does not name a class}} } - A(float) : decltype(A())(3) { + A(float) : decltype(A())(3) { // expected-error {{constructor for 'A' creates a delegation cycle}} } }; } diff --git a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp index 7a6d7cb353158..474ad587bacc6 100644 --- a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp +++ b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp @@ -535,9 +535,9 @@ namespace InvalidBaseClass { }; class InBetween : public F{}; - class E : public InBetween { + class E : public InBetween { // expected-note 2{{candidate constructor}} public: constexpr E() : F{3} {} // expected-error {{not a direct or virtual base}} }; - static_assert(__builtin_bit_cast(char, E()) == 0); // expected-error {{not an integral constant expression}} + static_assert(__builtin_bit_cast(char, E()) == 0); // expected-error {{no matching constructor}} } diff --git a/clang/test/SemaCXX/constexpr-subobj-initialization.cpp b/clang/test/SemaCXX/constexpr-subobj-initialization.cpp index f0252df1e2ce1..f0abe09d23bf4 100644 --- a/clang/test/SemaCXX/constexpr-subobj-initialization.cpp +++ b/clang/test/SemaCXX/constexpr-subobj-initialization.cpp @@ -16,17 +16,17 @@ struct Bar : Foo { constexpr Bar bar; // expected-error {{must be initialized by a constant expression}} struct Base {}; -struct A : Base { // expected-note-re {{constructor of base class '{{.*}}Base' is not called}} +struct A : Base { // expected-note 2{{candidate constructor}} constexpr A() : value() {} // expected-error {{member initializer 'value' does not name a non-static data member or base class}} }; -constexpr A a; // expected-error {{must be initialized by a constant expression}} +constexpr A a; // expected-error {{no matching constructor}} -struct B : Base { // expected-note-re {{constructor of base class '{{.*}}Base' is not called}} +struct B : Base { // expected-note 2{{candidate constructor}} constexpr B() : {} // expected-error {{expected class member or base class name}} }; -constexpr B b; // expected-error {{must be initialized by a constant expression}} +constexpr B b; // expected-error {{no matching constructor}} } // namespace baseclass_uninit diff --git a/clang/test/SemaCXX/constructor-initializer.cpp b/clang/test/SemaCXX/constructor-initializer.cpp index 96be8dda97735..c8b1cfbae65ce 100644 --- a/clang/test/SemaCXX/constructor-initializer.cpp +++ b/clang/test/SemaCXX/constructor-initializer.cpp @@ -2,16 +2,20 @@ // RUN: %clang_cc1 -Wreorder -fsyntax-only -verify -std=c++98 %s // RUN: %clang_cc1 -Wreorder -fsyntax-only -verify -std=c++11 %s -class A { +class A { + // expected-note@-1 {{candidate constructor}} +#if __cplusplus >= 201103L // C++11 or later + // expected-note@-3 {{candidate constructor}} +#endif int m; public: A() : A::m(17) { } // expected-error {{member initializer 'm' does not name a non-static data member or base class}} - A(int); + A(int); // expected-note {{candidate constructor}} }; class B : public A { public: - B() : A(), m(1), n(3.14) { } + B() : A(), m(1), n(3.14) { } // expected-error {{no matching constructor for initialization of 'A'}} private: int m; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits