diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index df3ad20f955ea..7631f3b5a561b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -182,6 +182,10 @@ Bug Fixes to Attribute Support Bug Fixes to C++ Support ^^^^^^^^^^^^^^^^^^^^^^^^ +- Fix crash when calling the constructor of an invalid class. + Fixes (`#10518 `_), + (`#67914 `_), + and (`#78388 `_) - Fix crash when using lifetimebound attribute in function with trailing return. Fixes (`#73619 `_) - Addressed an issue where constraints involving injected class types are perceived diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index fea8c5036c80b..ba233c9e2f35d 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5998,6 +5998,10 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { if (CXXConstructorDecl *Constructor = dyn_cast(CDtorDecl)) { + if (CXXRecordDecl *ClassDecl = Constructor->getParent(); + !ClassDecl || ClassDecl->isInvalidDecl()) { + return; + } SetCtorInitializers(Constructor, /*AnyErrors=*/false); DiagnoseUninitializedFields(*this, Constructor); } @@ -14038,6 +14042,9 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = Constructor->getParent(); assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); + if (ClassDecl->isInvalidDecl()) { + return; + } SynthesizedFunctionScope Scope(*this, Constructor); diff --git a/clang/test/SemaCXX/crash-GH10518.cpp b/clang/test/SemaCXX/crash-GH10518.cpp new file mode 100644 index 0000000000000..6c5f80afd3cf8 --- /dev/null +++ b/clang/test/SemaCXX/crash-GH10518.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s +// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++14 %s +// RUN: %clang_cc1 -verify -std=c++17 %s +// RUN: %clang_cc1 -verify -std=c++20 %s +// RUN: %clang_cc1 -verify -std=c++23 %s +// RUN: %clang_cc1 -verify -std=c++2c %s + +// https://github.com/llvm/llvm-project/issues/10518 + +template +class A : public T { +}; + +template +class B : public A { +}; + +template +class B : public A { // expected-error 0-1 {{}} + B(T *t) {} +}; diff --git a/clang/test/SemaCXX/crash-GH49103-2.cpp b/clang/test/SemaCXX/crash-GH49103-2.cpp new file mode 100644 index 0000000000000..4c17a054c73af --- /dev/null +++ b/clang/test/SemaCXX/crash-GH49103-2.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s +// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++14 %s +// RUN: %clang_cc1 -verify -std=c++17 %s +// RUN: %clang_cc1 -verify -std=c++20 %s +// RUN: %clang_cc1 -verify -std=c++23 %s +// RUN: %clang_cc1 -verify -std=c++2c %s + +// https://github.com/llvm/llvm-project/issues/49103 + +template struct A; // expected-note 0+ {{}} +struct S : __make_integer_seq { }; // expected-error 0+ {{}} +S s; diff --git a/clang/test/SemaCXX/crash-GH67914.cpp b/clang/test/SemaCXX/crash-GH67914.cpp new file mode 100644 index 0000000000000..fbaeac636c0db --- /dev/null +++ b/clang/test/SemaCXX/crash-GH67914.cpp @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s +// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++14 %s +// RUN: %clang_cc1 -verify -std=c++17 %s +// RUN: %clang_cc1 -verify -std=c++20 %s +// RUN: %clang_cc1 -verify -std=c++23 %s +// RUN: %clang_cc1 -verify -std=c++2c %s + +// https://github.com/llvm/llvm-project/issues/67914 + +template < typename, int > +struct Mask; + +template < int, class > +struct conditional { + using type = Mask< int, 16 >; // expected-warning 0+ {{}} +}; + +template < class _Then > +struct conditional< 0, _Then > { + using type = _Then; // expected-warning 0+ {{}} +}; + +template < int _Bp, class, class _Then > +using conditional_t = typename conditional< _Bp, _Then >::type; // expected-warning 0+ {{}} + +template < typename, int > +struct Array; + +template < typename, int, bool, typename > +struct StaticArrayImpl; + +template < typename Value_, int Size_ > +struct Mask : StaticArrayImpl< Value_, Size_, 1, Mask< Value_, Size_ > > { // expected-note 0+ {{}} + template < typename T1 > + Mask(T1) {} // expected-note 0+ {{}} +}; + +template < typename T > +void load(typename T::MaskType mask) { + T::load_(mask); // expected-note 0+ {{}} +} + +template < typename Value_, int IsMask_, typename Derived_ > +struct StaticArrayImpl< Value_, 32, IsMask_, Derived_ > { + using Array1 = conditional_t< IsMask_, void, Array< Value_, 16 > >; // expected-warning 0+ {{}} + + template < typename Mask > + static Derived_ load_(Mask mask) { + return Derived_{load< Array1 >(mask.a1), Mask{}}; // expected-error 0+ {{}} + } + + Array1 a1; +}; + +template < typename Derived_ > +struct KMaskBase; + +template < typename Derived_ > +struct StaticArrayImpl< float, 16, 0, Derived_ > { + template < typename Mask > + static Derived_ load_(Mask mask); +}; + +template < typename Derived_ > +struct StaticArrayImpl< float, 16, 1, Mask< float, 16 > > : KMaskBase< Derived_ > {}; // expected-error 0+ {{}} + +template < typename Derived_ > +struct StaticArrayImpl< int, 16, 1, Derived_ > {}; + +template < typename Value_, int Size_ > +struct Array : StaticArrayImpl< Value_, Size_, 0, Array< Value_, Size_ > > { + using MaskType = Mask< Value_, Size_ >; // expected-warning 0+ {{}} +}; + +void test11_load_masked() { + load< Array< float, 32 > >{} == 0; // expected-error 0+ {{}} expected-warning 0+ {{}} expected-note 0+ {{}} +} diff --git a/clang/test/SemaCXX/crash-GH78388.cpp b/clang/test/SemaCXX/crash-GH78388.cpp new file mode 100644 index 0000000000000..cdec4d5bedef4 --- /dev/null +++ b/clang/test/SemaCXX/crash-GH78388.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s +// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++14 %s +// RUN: %clang_cc1 -verify -std=c++17 %s +// RUN: %clang_cc1 -verify -std=c++20 %s +// RUN: %clang_cc1 -verify -std=c++23 %s +// RUN: %clang_cc1 -verify -std=c++2c %s + +// https://github.com/llvm/llvm-project/issues/78388 + +typedef mbstate_t; // expected-error 0+ {{}} expected-note 0+ {{}} + template < typename , typename , typename > + class a // expected-error 0+ {{}} + class b { // expected-error 0+ {{}} + namespace { // expected-note 0+ {{}} expected-note 0+ {{}} + template < typename c > b::operator=() { // expected-error 0+ {{}} expected-note 0+ {{}} + struct :a< c, char, stdmbstate_t > d // expected-error 0+ {{}} expected-warning 0+ {{}} diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp index 4f4f5839361e2..508b01a7bcea3 100644 --- a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp +++ b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp @@ -56,7 +56,7 @@ void test() { e.transform_error(return_unexpected); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected with a E that is not a valid argument for unexpected is ill-formed}} - // expected-error-re@*:* {{call to deleted constructor of {{.*}}}} + // expected-error-re@*:* 0-1 {{call to deleted constructor of {{.*}}}} // expected-error-re@*:* {{union member {{.*}} has reference type {{.*}}}} e.transform_error(return_no_object); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}