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

Reply via email to