diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 55f774f5a672e..d828b679a4d4c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -505,6 +505,9 @@ Improvements to Clang's diagnostics - ``-Wreserved-identifier`` now fires on reserved parameter names in a function declaration which is not a definition. +- Several compatibility diagnostics that were incorrectly being grouped under + ``-Wpre-c++20-compat`` are now part of ``-Wc++20-compat``. (#GH138775) + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index f26c906b46447..e4d94fefbbf3d 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -130,9 +130,11 @@ def err_attribute_not_type_attr : Error< "%0%select{ attribute|}1 cannot be applied to types">; def err_enum_template : Error<"enumeration cannot be a template">; -def warn_cxx20_compat_consteval : Warning< - "'consteval' specifier is incompatible with C++ standards before C++20">, - InGroup, DefaultIgnore; +def warn_cxx20_compat_consteval + : Warning<"'consteval' specifier is incompatible with C++ standards before " + "C++20">, + InGroup, + DefaultIgnore; def warn_missing_type_specifier : Warning< "type specifier missing, defaults to 'int'">, InGroup, DefaultIgnore; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 195e1202880b9..e1b9ed0647bb9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -51,6 +51,8 @@ defm adl_only_template_id : CXX20Compat< "with explicit template arguments is">; defm ctad_for_alias_templates : CXX20Compat<"class template argument deduction for alias templates is">; +defm implicit_typename + : CXX20Compat<"missing 'typename' prior to dependent type name %0 is">; // C++23 compatibility with C++20 and earlier. defm constexpr_static_var : CXX23Compat< @@ -5867,16 +5869,8 @@ def ext_typename_missing def err_typename_refers_to_using_value_decl : Error< "typename specifier refers to a dependent using declaration for a value " "%0 in %1">; -def note_using_value_decl_missing_typename : Note< - "add 'typename' to treat this using declaration as a type">; -def warn_cxx17_compat_implicit_typename : Warning<"use of implicit 'typename' is " - "incompatible with C++ standards before C++20">, InGroup, - DefaultIgnore; -def ext_implicit_typename - : ExtWarn<"missing 'typename' prior to dependent " - "type name %0; implicit 'typename' is a C++20 extension">, - InGroup; - +def note_using_value_decl_missing_typename + : Note<"add 'typename' to treat this using declaration as a type">; def err_template_kw_refers_to_non_template : Error< "%0%select{| following the 'template' keyword}1 " "does not refer to a template">; @@ -9572,9 +9566,11 @@ def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">, NoSFINAE; // C++20 constinit and require_constant_initialization attribute -def warn_cxx20_compat_constinit : Warning< - "'constinit' specifier is incompatible with C++ standards before C++20">, - InGroup, DefaultIgnore; +def warn_cxx20_compat_constinit + : Warning<"'constinit' specifier is incompatible with C++ standards before " + "C++20">, + InGroup, + DefaultIgnore; def err_constinit_local_variable : Error< "local variable cannot be declared 'constinit'">; def err_require_constant_init_failed : Error< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6b561d7bfc6e7..5a45198a7ce02 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -349,12 +349,11 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, if (AllowImplicitTypename == ImplicitTypenameContext::No) return nullptr; SourceLocation QualifiedLoc = SS->getRange().getBegin(); - if (getLangOpts().CPlusPlus20) - Diag(QualifiedLoc, diag::warn_cxx17_compat_implicit_typename); - else - Diag(QualifiedLoc, diag::ext_implicit_typename) - << NestedNameSpecifier::Create(Context, SS->getScopeRep(), &II) - << FixItHint::CreateInsertion(QualifiedLoc, "typename "); + auto DB = + DiagCompat(QualifiedLoc, diag_compat::implicit_typename) + << NestedNameSpecifier::Create(Context, SS->getScopeRep(), &II); + if (!getLangOpts().CPlusPlus20) + DB << FixItHint::CreateInsertion(QualifiedLoc, "typename "); } // We know from the grammar that this name refers to a type, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 65706d4b15455..94f4c1c46c1fb 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3775,12 +3775,10 @@ TypeResult Sema::ActOnTemplateIdType( NestedNameSpecifier *NNS = NestedNameSpecifier::Create(Context, SS.getScopeRep(), TemplateII); if (AllowImplicitTypename == ImplicitTypenameContext::Yes) { - if (getLangOpts().CPlusPlus20) - Diag(SS.getBeginLoc(), diag::warn_cxx17_compat_implicit_typename); - else - Diag(SS.getBeginLoc(), diag::ext_implicit_typename) - << NNS - << FixItHint::CreateInsertion(SS.getBeginLoc(), "typename "); + auto DB = DiagCompat(SS.getBeginLoc(), diag_compat::implicit_typename) + << NNS; + if (!getLangOpts().CPlusPlus20) + DB << FixItHint::CreateInsertion(SS.getBeginLoc(), "typename "); } else Diag(SS.getBeginLoc(), diag::err_typename_missing_template) << NNS; diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp index 6b9ad31bffbcd..8b84de0ab5a9a 100644 --- a/clang/test/CXX/drs/cwg1xx.cpp +++ b/clang/test/CXX/drs/cwg1xx.cpp @@ -96,7 +96,7 @@ namespace cwg108 { // cwg108: 2.9 template struct A { struct B { typedef int X; }; B::X x; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::X'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::X' is a C++20 extension}} struct C : B { X x; }; // expected-error@-1 {{unknown type name 'X'}} }; @@ -321,7 +321,7 @@ namespace cwg121 { // cwg121: 2.7 X::Y x; T::Y y; // expected-error@-1 {{use 'template' keyword to treat 'Y' as a dependent template name}} - // cxx98-17-error@-2 {{missing 'typename' prior to dependent type name 'T::Y'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-2 {{missing 'typename' prior to dependent type name 'T::Y' is a C++20 extension}} }; Z z; } // namespace cwg121 diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp index b2ae8f88ead74..a53a8d1ed64a8 100644 --- a/clang/test/CXX/drs/cwg2xx.cpp +++ b/clang/test/CXX/drs/cwg2xx.cpp @@ -426,7 +426,7 @@ namespace cwg224 { // cwg224: 16 A::type a; A::type b; A::type c; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::type' is a C++20 extension}} ::cwg224::example1::A::type d; class B { @@ -435,13 +435,13 @@ namespace cwg224 { // cwg224: 16 A::type a; A::type b; A::type c; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::type' is a C++20 extension}} ::cwg224::example1::A::type d; B::type e; A::B::type f; A::B::type g; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::B::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::B::type' is a C++20 extension}} typename A::B::type h; }; }; @@ -450,25 +450,25 @@ namespace cwg224 { // cwg224: 16 typedef int type; A::type a; A::type b; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::type' is a C++20 extension}} }; template struct B { typedef int type; B::type b1; B::type b2; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::type' is a C++20 extension}} typedef T1 my_T1; static const int my_I = I; static const int my_I2 = I+0; static const int my_I3 = my_I; B::type b3; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::type' is a C++20 extension}} B::type b4; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::type' is a C++20 extension}} B::type b5; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B::type' is a C++20 extension}} }; } @@ -480,7 +480,7 @@ namespace cwg224 { // cwg224: 16 X::type x; X::i, double>::type y; X::i, long>::type z; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'X::i, long>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'X::i, long>::type' is a C++20 extension}} int f(); }; template int A::f() { diff --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp index e8e2600870233..210f7ae71ec04 100644 --- a/clang/test/CXX/drs/cwg4xx.cpp +++ b/clang/test/CXX/drs/cwg4xx.cpp @@ -257,7 +257,7 @@ namespace cwg409 { // cwg409: 2.7 A::B b2; A::B b3; A::B b4; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::B'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A::B' is a C++20 extension}} }; } // namespace cwg409 diff --git a/clang/test/CXX/drs/cwg5xx.cpp b/clang/test/CXX/drs/cwg5xx.cpp index 0825b52653b4d..1d505adecfb27 100644 --- a/clang/test/CXX/drs/cwg5xx.cpp +++ b/clang/test/CXX/drs/cwg5xx.cpp @@ -254,9 +254,9 @@ namespace cwg526 { // cwg526: 2.7 typedef int type; X::type v1; X<(N)>::type v2; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'X<(N)>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'X<(N)>::type' is a C++20 extension}} X<+N>::type v3; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'X<+N>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'X<+N>::type' is a C++20 extension}} }; } // namespace cwg526 @@ -783,7 +783,7 @@ struct Outer { }; template Outer::Inner* Outer::Inner::self() { return this; } -// cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'Outer::Inner'; implicit 'typename' is a C++20 extension}} +// cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'Outer::Inner' is a C++20 extension}} } // namespace cwg560 diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp index 910dab11ee5e1..acaeea9e70e3f 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp @@ -17,7 +17,7 @@ namespace Example1 { template struct A>> { struct C {}; - B>::C bc; // expected-warning {{implicit 'typename' is a C++20 extension}} + B>::C bc; // expected-warning {{missing 'typename' prior to dependent type name 'B>::C' is a C++20 extension}} }; } diff --git a/clang/test/FixIt/fixit.cpp b/clang/test/FixIt/fixit.cpp index 605c2d0bd0235..3e5040969c3ee 100644 --- a/clang/test/FixIt/fixit.cpp +++ b/clang/test/FixIt/fixit.cpp @@ -211,7 +211,7 @@ struct MoreAccidentalCommas { template struct Mystery; template typedef Mystery::type getMysteriousThing() { // \ expected-error {{function definition declared 'typedef'}} \ - expected-warning {{implicit 'typename' is a C++20 extension}} + expected-warning {{missing 'typename' prior to dependent type name 'Mystery::type' is a C++20 extension}} return Mystery::get(); } diff --git a/clang/test/SemaCXX/MicrosoftCompatibility.cpp b/clang/test/SemaCXX/MicrosoftCompatibility.cpp index a830883280173..b8cd22ad350a5 100644 --- a/clang/test/SemaCXX/MicrosoftCompatibility.cpp +++ b/clang/test/SemaCXX/MicrosoftCompatibility.cpp @@ -211,14 +211,14 @@ class C : private A, public B { typedef B Base2; typedef A Base3; - A::TYPE a1; // expected-warning {{implicit 'typename' is a C++20 extension}} - Base1::TYPE a2; // expected-warning {{implicit 'typename' is a C++20 extension}} + A::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name 'A::TYPE' is a C++20 extension}} + Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name 'Base1::TYPE' is a C++20 extension}} - B::TYPE a3; // expected-warning {{implicit 'typename' is a C++20 extension}} - Base2::TYPE a4; // expected-warning {{implicit 'typename' is a C++20 extension}} + B::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name 'B::TYPE' is a C++20 extension}} + Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name 'Base2::TYPE' is a C++20 extension}} - A::TYPE a5; // expected-warning {{implicit 'typename' is a C++20 extension}} - Base3::TYPE a6; // expected-warning {{implicit 'typename' is a C++20 extension}} + A::TYPE a5; // expected-warning {{missing 'typename' prior to dependent type name 'A::TYPE' is a C++20 extension}} + Base3::TYPE a6; // expected-warning {{missing 'typename' prior to dependent type name 'Base3::TYPE' is a C++20 extension}} }; class D { diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp index 7454a01158f6b..4dff2b1c362a7 100644 --- a/clang/test/SemaCXX/MicrosoftExtensions.cpp +++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -613,7 +613,7 @@ typedef char __unaligned *aligned_type; // expected-error {{expected ';' after t namespace PR32750 { template struct A {}; -template struct B : A> { A::C::D d; }; // expected-warning {{implicit 'typename' is a C++20 extension}} +template struct B : A> { A::C::D d; }; // expected-warning {{missing 'typename' prior to dependent type name 'A::C::D' is a C++20 extension}} } #endif diff --git a/clang/test/SemaCXX/MicrosoftSuper.cpp b/clang/test/SemaCXX/MicrosoftSuper.cpp index 94e29b23ef11c..d117b93523363 100644 --- a/clang/test/SemaCXX/MicrosoftSuper.cpp +++ b/clang/test/SemaCXX/MicrosoftSuper.cpp @@ -108,8 +108,8 @@ struct DerivedFromDependentBase : BaseTemplate { typename __super::XXX a; typedef typename __super::XXX b; - __super::XXX c; // expected-warning {{implicit 'typename' is a C++20 extension}} - typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++20 extension}} + __super::XXX c; // expected-warning {{missing 'typename'}} + typedef __super::XXX d; // expected-warning {{missing 'typename'}} void foo() { typename __super::XXX e; @@ -127,8 +127,8 @@ struct DerivedFromTemplateParameter : T { typename __super::XXX a; typedef typename __super::XXX b; - __super::XXX c; // expected-warning {{implicit 'typename' is a C++20 extension}} - typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++20 extension}} + __super::XXX c; // expected-warning {{missing 'typename'}} + typedef __super::XXX d; // expected-warning {{missing 'typename'}} void foo() { typename __super::XXX e; diff --git a/clang/test/SemaCXX/gh138775.cpp b/clang/test/SemaCXX/gh138775.cpp new file mode 100644 index 0000000000000..854e25f84fe49 --- /dev/null +++ b/clang/test/SemaCXX/gh138775.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify=cxx17 %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=pre-cxx20-compat -Wpre-c++20-compat %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=cxx20-compat -Wc++20-compat %s +// cxx20-compat-no-diagnostics + +// cxx17-error@+4 {{unknown type name 'consteval'; did you mean 'constexpr'}} +// cxx17-warning@+3 {{missing 'typename' prior to dependent type name 'T::type' is a C++20 extension}} +// pre-cxx20-compat-warning@+2 {{'consteval' specifier is incompatible with C++ standards before C++20}} +// pre-cxx20-compat-warning@+1 {{missing 'typename' prior to dependent type name 'T::type' is incompatible with C++ standards before C++20}} +template consteval T::type f(); + +// cxx17-error@+2 {{unknown type name 'constinit'}} +// pre-cxx20-compat-warning@+1 {{'constinit' specifier is incompatible with C++ standards before C++20}} +constinit int x = 4; diff --git a/clang/test/SemaCXX/rounding-math-crash.cpp b/clang/test/SemaCXX/rounding-math-crash.cpp index 2a09b02fe9cef..f9c5ada2a403e 100644 --- a/clang/test/SemaCXX/rounding-math-crash.cpp +++ b/clang/test/SemaCXX/rounding-math-crash.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -frounding-math -verify %s template b::a() {} -// expected-warning@-1 {{implicit 'typename' is a C++20 extension}} +// expected-warning@-1 {{missing 'typename' prior to dependent type name 'b::a' is a C++20 extension}} // expected-error@-2 {{expected unqualified-id}} diff --git a/clang/test/SemaCXX/unknown-type-name.cpp b/clang/test/SemaCXX/unknown-type-name.cpp index 602f8f9ec7d29..9ce8b69c5bd22 100644 --- a/clang/test/SemaCXX/unknown-type-name.cpp +++ b/clang/test/SemaCXX/unknown-type-name.cpp @@ -36,15 +36,15 @@ struct A { static int n; static type m; - static int h(T::type, int); // expected-warning{{implicit 'typename' is a C++20 extension}} - static int h(T::type x, char); // expected-warning{{implicit 'typename' is a C++20 extension}} + static int h(T::type, int); // expected-warning{{missing 'typename'}} + static int h(T::type x, char); // expected-warning{{missing 'typename'}} }; template -A::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++20 extension}} +A::type g(T t) { return t; } // expected-warning{{missing 'typename'}} template -A::type A::f() { return type(); } // expected-warning{{implicit 'typename' is a C++20 extension}} +A::type A::f() { return type(); } // expected-warning{{missing 'typename'}} template void f(T::type) { } // expected-error{{missing 'typename'}} @@ -84,11 +84,11 @@ int *test(UnknownType *fool) { return 0; } // expected-error{{unknown type name template int A::n(T::value); // ok template -A::type // expected-warning {{implicit 'typename' is a C++20 extension}} +A::type // expected-warning {{missing 'typename'}} A::m(T::value, 0); // ok -template int A::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++20 extension}} -template int A::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++20 extension}} +template int A::h(T::type, int) {} // expected-warning{{missing 'typename'}} +template int A::h(T::type x, char) {} // expected-warning{{missing 'typename'}} template int h(T::type, int); // expected-error{{missing 'typename'}} template int h(T::type x, char); // expected-error{{missing 'typename'}} @@ -117,4 +117,4 @@ template int i(T::type, int()); // a fix-it to add 'typename A::type' template A::g() { } // expected-error{{expected unqualified-id}} -// expected-warning@-1{{implicit 'typename' is a C++20 extension}} +// expected-warning@-1{{missing 'typename'}} diff --git a/clang/test/SemaTemplate/typename-specifier-3.cpp b/clang/test/SemaTemplate/typename-specifier-3.cpp index cdd065c98bb0a..6e09012a86e6a 100644 --- a/clang/test/SemaTemplate/typename-specifier-3.cpp +++ b/clang/test/SemaTemplate/typename-specifier-3.cpp @@ -28,7 +28,7 @@ namespace PR12884_original { typedef int arg; }; struct C { - typedef B::X x; // precxx17-warning{{missing 'typename' prior to dependent type name 'B::X'; implicit 'typename' is a C++20 extension}} + typedef B::X x; // precxx17-warning{{missing 'typename' prior to dependent type name 'B::X' is a C++20 extension}} }; };