Index: clang/include/clang/Sema/Initialization.h =================================================================== --- clang/include/clang/Sema/Initialization.h +++ clang/include/clang/Sema/Initialization.h @@ -1103,6 +1103,9 @@ /// List-copy-initialization chose an explicit constructor. FK_ExplicitConstructor, + + /// Parenthesized list initialization failed at some point. + FK_ParenthesizedListInitFailed, }; private: Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -3580,6 +3580,7 @@ case FK_PlaceholderType: case FK_ExplicitConstructor: case FK_AddressOfUnaddressableFunction: + case FK_ParenthesizedListInitFailed: return false; case FK_ReferenceInitOverloadFailed: @@ -4085,9 +4086,8 @@ InitializationSequence Seq(S, SubEntity, SubKind, E); if (Seq.Failed()) { - // FIXME: We should have diagnosed which member intialization fails. But - // that would break some existing tests, and I'm not sure whether it's - // acceptable. + if (!VerifyOnly) + Seq.Diagnose(S, SubEntity, SubKind, E); return false; } if (!VerifyOnly) { @@ -4141,12 +4141,16 @@ ResultType = Entity.getType(); } - if (Index != Args.size()) - // FIXME: We should have also diagnosed that the initializers - // exceeds the limit. But, as I mentioned earlier, I don't - // want to break existing tests unless an agreement has - // been forged among the community. + if (Index != Args.size()) { + if (!VerifyOnly) { + QualType T = Entity.getType(); + // FIXME: Union type unsupported. + int InitKind = T->isArrayType() ? 0 : 4; + S.Diag(Kind.getLocation(), diag::err_excess_initializers) + << InitKind << Args[Index]->getSourceRange(); + } return false; + } if (!VerifyOnly && Result) *Result = CXXParenListInitExpr::Create(S.getASTContext(), InitExprs, @@ -4289,10 +4293,13 @@ DestRecordDecl->isAggregate()) { bool IsValid = VerifyOrPerformParenthesizedListInit(S, Entity, Kind, Args, /*VerifyOnly=*/true); - if (IsValid) { + if (IsValid) Sequence.AddParenthesizedListInitStep(DestType); - return; - } + else + Sequence.SetFailed( + InitializationSequence::FK_ParenthesizedListInitFailed); + + return; } if (Result) { @@ -6030,10 +6037,12 @@ TryListInitialization(S, Entity, Kind, cast(Initializer), *this, TreatUnavailableAsInvalid); AddParenthesizedArrayInitStep(DestType); - } else if (S.getLangOpts().CPlusPlus20 && !TopLevelOfInitList && - VerifyOrPerformParenthesizedListInit(S, Entity, Kind, Args, - /*VerifyOnly=*/true)) - AddParenthesizedListInitStep(DestType); + } else if (S.getLangOpts().CPlusPlus20 && !TopLevelOfInitList) + if (VerifyOrPerformParenthesizedListInit(S, Entity, Kind, Args, + /*VerifyOnly=*/true)) + AddParenthesizedListInitStep(DestType); + else + SetFailed(FK_ParenthesizedListInitFailed); else if (DestAT->getElementType()->isCharType()) SetFailed(FK_ArrayNeedsInitListOrStringLiteral); else if (IsWideCharCompatible(DestAT->getElementType(), Context)) @@ -9638,6 +9647,11 @@ diag::note_explicit_ctor_deduction_guide_here) << false; break; } + + case FK_ParenthesizedListInitFailed: { + VerifyOrPerformParenthesizedListInit(S, Entity, Kind, Args, + /*VerifyOnly=*/false); + } } PrintInitLocationNote(S, Entity); @@ -9804,6 +9818,10 @@ case FK_ExplicitConstructor: OS << "list copy initialization chose explicit constructor"; break; + + case FK_ParenthesizedListInitFailed: + OS << "parenthesized list initialization for aggregate failed"; + break; } OS << '\n'; return; Index: clang/test/CXX/class/class.compare/class.spaceship/p1.cpp =================================================================== --- clang/test/CXX/class/class.compare/class.spaceship/p1.cpp +++ clang/test/CXX/class/class.compare/class.spaceship/p1.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions namespace std { - struct strong_ordering { // expected-note 6{{candidate}} + struct strong_ordering { int n; constexpr operator int() const { return n; } static const strong_ordering less, equal, greater; @@ -103,7 +103,7 @@ Cmp() <=> Cmp(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}G1>' first required here}}j // expected-error@#cmp {{value of type 'void' is not contextually convertible to 'bool'}} Cmp() <=> Cmp(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}G2>' first required here}}j - // expected-error@#cmp {{no matching conversion for static_cast from 'void' to 'std::strong_ordering'}} + // expected-error@#cmp {{static_cast from 'void' to 'std::strong_ordering' is not allowed}} Cmp() <=> Cmp(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}H>' first required here}}j 0 ); @@ -134,7 +134,7 @@ CmpArray() <=> CmpArray(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}G1>' first required here}}j // expected-error@#cmparray {{value of type 'void' is not contextually convertible to 'bool'}} CmpArray() <=> CmpArray(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}G2>' first required here}}j - // expected-error@#cmparray {{no matching conversion for static_cast from 'void' to 'std::strong_ordering'}} + // expected-error@#cmparray {{static_cast from 'void' to 'std::strong_ordering' is not allowed}} CmpArray() <=> CmpArray(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}H>' first required here}}j 0 ); Index: clang/test/CXX/drs/dr2xx.cpp =================================================================== --- clang/test/CXX/drs/dr2xx.cpp +++ clang/test/CXX/drs/dr2xx.cpp @@ -157,6 +157,8 @@ void test3(A::S as) { using A::f; f(as); } // ok void test4(A::S as) { using B::f; f(as); } // ok void test5(A::S as) { int f; f(as); } // expected-error {{called object type 'int'}} + // FIXME: The error message given by C++20 is different to pre-C++20. + // How to resolve this ? void test6(A::S as) { struct f {}; (void) f(as); } // expected-error {{no matching conversion}} expected-note +{{}} }; Index: clang/test/CXX/over/over.match/over.match.viable/p3.cpp =================================================================== --- clang/test/CXX/over/over.match/over.match.viable/p3.cpp +++ clang/test/CXX/over/over.match/over.match.viable/p3.cpp @@ -1,9 +1,6 @@ // RUN: %clang_cc1 -std=c++2a -verify %s struct S2 {}; -// expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'S1' to 'const S2' for 1st argument}} -// expected-note@-2 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'S1' to 'S2' for 1st argument}} -// expected-note@-3 {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} template struct S1 { @@ -14,8 +11,6 @@ operator bool() const requires true { return true; } explicit operator bool() const requires false; explicit operator S2() const requires false; - // expected-note@-1 {{candidate function not viable: constraints not satisfied}} - // expected-note@-2 {{because 'false' evaluated to false}} }; void foo() { @@ -24,7 +19,7 @@ // expected-error@-1 {{invalid reference to function 'bar': constraints not satisfied}} (void) static_cast(S1()); (void) static_cast(S1()); - // expected-error@-1 {{no matching conversion for static_cast from 'S1' to 'S2'}} + // expected-error@-1 {{static_cast from 'S1' to 'S2' is not allowed}} } // Test that constraints are checked before implicit conversions are formed. Index: clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp =================================================================== --- clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp +++ clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -126,6 +126,8 @@ template HasMixins::HasMixins(int i): Mixins(i)... { } +// FIXME: The error message given by C++20 is different to pre-C++20. +// How to resolve this ? // expected-error@-1 {{no matching constructor for initialization of 'A'}} // expected-error@-2 {{no matching constructor for initialization of 'B'}} Index: clang/test/SemaCXX/P0960R3.cpp =================================================================== --- clang/test/SemaCXX/P0960R3.cpp +++ clang/test/SemaCXX/P0960R3.cpp @@ -1,28 +1,28 @@ // RUN: %clang_cc1 -verify -std=c++20 %s -fsyntax-only -struct A { // expected-note 3{{candidate constructor}} +struct A { // expected-note 4{{candidate constructor}} char i; double j; }; -struct B { // expected-note 3{{candidate constructor}} +struct B { A a; int b[20]; int &&c; // expected-note {{reference member declared here}} }; -struct C { // expected-note 6{{candidate constructor}} +struct C { // expected-note 2{{candidate constructor}} A a; int b[20]; }; -struct D : public C, public A { // expected-note 6{{candidate constructor}} +struct D : public C, public A { int a; }; void foo() { A a1(2.0, 2, 11); - // expected-error@-1 {{no matching constructor for initialization}} + // expected-error@-1 {{excess elements in struct initializer}} A a2(2.1); // expected-warning@-1 {{implicit conversion from 'double' to 'char'}} A a3(-1.2, 9.8); @@ -35,21 +35,21 @@ // expected-warning@-1 {{implicit conversion from 'double' to 'char'}} B b1(1, {2, 3}); - // expected-error@-1 {{no matching constructor for initialization}} + // expected-error@-1 {{no viable conversion from 'int' to 'A'}} B b2(A(1), {}, 1); // expected-error@-1 {{reference member 'c' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} C c1(A(1), 1, 2, 3, 4); - // expected-error@-1 {{no matching constructor for initialization}} + // expected-error@-1 {{excess elements in struct initializer}} D d1(1); - // expected-error@-1 {{no matching constructor for initialization}} + // expected-error@-1 {{no viable conversion from 'int' to 'C'}} D d2(C(1)); - // expected-error@-1 {{no matching conversion for functional-style cast from 'int' to 'C'}} + // expected-error@-1 {{functional-style cast from 'int' to 'C' is not allowed}} D d3(C(A(1)), 1); - // expected-error@-1 {{no matching constructor for initialization}} + // expected-error@-1 {{no viable conversion from 'int' to 'A'}} int arr1[](0, 1, 2, A(1)); - // expected-error@-1 {{array initializer must be an initializer list}} + // expected-error@-1 {{no viable conversion from 'A' to 'int'}} int arr2[2](0, 1, 2); - // expected-error@-1 {{array initializer must be an initializer list}} + // expected-error@-1 {{excess elements in array initializer}} } Index: clang/test/SemaCXX/cxx2a-explicit-bool.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-explicit-bool.cpp +++ clang/test/SemaCXX/cxx2a-explicit-bool.cpp @@ -28,6 +28,8 @@ }; A<-1> a(0); +// FIXME: The error message given by C++20 is different to pre-C++20. +// How to resolve this ? // expected-error@-1 {{no matching constructor}} // expected-note@-2 {{in instantiation of template class}}