[clang] [clang] Mark constructors with invalid initializers as invalid (PR #137773)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 29 02:14:41 PDT 2025
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/137773
If a member or base initializer of a constructor turns out to be invalid, mark the entire constructor as invalid.
>From eaa78a369c3a1577b040b6b3e78d6812af6f1348 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at 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 +++-
clang/test/SemaCXX/class-base-member-init.cpp | 2 +-
clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp | 4 ++--
clang/test/SemaCXX/constexpr-subobj-initialization.cpp | 8 ++++----
clang/test/SemaCXX/constructor-initializer.cpp | 10 +++++++---
5 files changed, 17 insertions(+), 11 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/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 at -1 {{candidate constructor}}
+#if __cplusplus >= 201103L // C++11 or later
+ // expected-note at -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;
More information about the cfe-commits
mailing list