Author: Sirraide Date: 2025-05-08T01:41:57+02:00 New Revision: 45b5cc08e5823c59802f88ec3f27108ab98c1eb9
URL: https://github.com/llvm/llvm-project/commit/45b5cc08e5823c59802f88ec3f27108ab98c1eb9 DIFF: https://github.com/llvm/llvm-project/commit/45b5cc08e5823c59802f88ec3f27108ab98c1eb9.diff LOG: [Clang] Fix the warning group of several compatibilty diagnostics (#138872) There are a few diagnostics that are incorrectly grouped under `-Wc++20-compat` instead of `-Wpre-c++20-compat`. I grepped for any remaining `-Wc++xy-compat` diagnostics, but they all seem to actually be about compatibility with C++XY. Fixes #138775. Added: clang/test/SemaCXX/gh138775.cpp Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticCommonKinds.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaTemplate.cpp clang/test/CXX/drs/cwg1xx.cpp clang/test/CXX/drs/cwg2xx.cpp clang/test/CXX/drs/cwg4xx.cpp clang/test/CXX/drs/cwg5xx.cpp clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp clang/test/FixIt/fixit.cpp clang/test/SemaCXX/MicrosoftCompatibility.cpp clang/test/SemaCXX/MicrosoftExtensions.cpp clang/test/SemaCXX/MicrosoftSuper.cpp clang/test/SemaCXX/rounding-math-crash.cpp clang/test/SemaCXX/unknown-type-name.cpp clang/test/SemaTemplate/typename-specifier-3.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9c4ab80537ac9..4c25d6d4d515a 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<CXX20Compat>, DefaultIgnore; +def warn_cxx20_compat_consteval + : Warning<"'consteval' specifier is incompatible with C++ standards before " + "C++20">, + InGroup<CXXPre20Compat>, + DefaultIgnore; def warn_missing_type_specifier : Warning< "type specifier missing, defaults to 'int'">, InGroup<ImplicitInt>, 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<CXX20Compat>, - DefaultIgnore; -def ext_implicit_typename - : ExtWarn<"missing 'typename' prior to dependent " - "type name %0; implicit 'typename' is a C++20 extension">, - InGroup<CXX20>; - +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<CXX20Compat>, DefaultIgnore; +def warn_cxx20_compat_constinit + : Warning<"'constinit' specifier is incompatible with C++ standards before " + "C++20">, + InGroup<CXXPre20Compat>, + 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<typename T> 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<T> x; T::Y<T> 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<X> 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<T>::type b; A<T*>::type c; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T *>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T *>::type' is a C++20 extension}} ::cwg224::example1::A<T>::type d; class B { @@ -435,13 +435,13 @@ namespace cwg224 { // cwg224: 16 A::type a; A<T>::type b; A<T*>::type c; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T *>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T *>::type' is a C++20 extension}} ::cwg224::example1::A<T>::type d; B::type e; A<T>::B::type f; A<T*>::B::type g; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T *>::B::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T *>::B::type' is a C++20 extension}} typename A<T*>::B::type h; }; }; @@ -450,25 +450,25 @@ namespace cwg224 { // cwg224: 16 typedef int type; A<T*>::type a; A<T>::type b; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T>::type' is a C++20 extension}} }; template <class T1, class T2, int I> struct B { typedef int type; B<T1, T2, I>::type b1; B<T2, T1, I>::type b2; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B<T2, T1, I>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B<T2, T1, I>::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<my_T1, T2, my_I>::type b3; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B<my_T1, T2, my_I>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B<my_T1, T2, my_I>::type' is a C++20 extension}} B<my_T1, T2, my_I2>::type b4; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B<my_T1, T2, my_I2>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B<my_T1, T2, my_I2>::type' is a C++20 extension}} B<my_T1, T2, my_I3>::type b5; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B<my_T1, T2, my_I3>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'B<my_T1, T2, my_I3>::type' is a C++20 extension}} }; } @@ -480,7 +480,7 @@ namespace cwg224 { // cwg224: 16 X<A::i, char>::type x; X<A<T>::i, double>::type y; X<A<T*>::i, long>::type z; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'X<A<T *>::i, long>::type'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'X<A<T *>::i, long>::type' is a C++20 extension}} int f(); }; template <class T> int A<T>::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<T>::B b3; A<T*>::B b4; - // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T *>::B'; implicit 'typename' is a C++20 extension}} + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'A<T *>::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<N>::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 <class T> Outer<T>::Inner* Outer<T>::Inner::self() { return this; } -// cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'Outer<T>::Inner'; implicit 'typename' is a C++20 extension}} +// cxx98-17-error@-1 {{missing 'typename' prior to dependent type name 'Outer<T>::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<class T> struct A<A<A<T>>> { struct C {}; - B<B<T>>::C bc; // expected-warning {{implicit 'typename' is a C++20 extension}} + B<B<T>>::C bc; // expected-warning {{missing 'typename' prior to dependent type name 'B<B<T>>::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<class T> struct Mystery; template<class T> typedef Mystery<T>::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<T>::type' is a C++20 extension}} return Mystery<T>::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<T>, public B<U> { typedef B<U> Base2; typedef A<U> Base3; - A<T>::TYPE a1; // expected-warning {{implicit 'typename' is a C++20 extension}} - Base1::TYPE a2; // expected-warning {{implicit 'typename' is a C++20 extension}} + A<T>::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name 'A<T>::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<U>::TYPE a3; // expected-warning {{implicit 'typename' is a C++20 extension}} - Base2::TYPE a4; // expected-warning {{implicit 'typename' is a C++20 extension}} + B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name 'B<U>::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<U>::TYPE a5; // expected-warning {{implicit 'typename' is a C++20 extension}} - Base3::TYPE a6; // expected-warning {{implicit 'typename' is a C++20 extension}} + A<U>::TYPE a5; // expected-warning {{missing 'typename' prior to dependent type name 'A<U>::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<typename T> struct A {}; -template<typename T> struct B : A<A<T>> { A<T>::C::D d; }; // expected-warning {{implicit 'typename' is a C++20 extension}} +template<typename T> struct B : A<A<T>> { A<T>::C::D d; }; // expected-warning {{missing 'typename' prior to dependent type name 'A<T>::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<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; @@ -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<typename T> 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 <class b> 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<typename T> -A<T>::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++20 extension}} +A<T>::type g(T t) { return t; } // expected-warning{{missing 'typename'}} template<typename T> -A<T>::type A<T>::f() { return type(); } // expected-warning{{implicit 'typename' is a C++20 extension}} +A<T>::type A<T>::f() { return type(); } // expected-warning{{missing 'typename'}} template<typename T> void f(T::type) { } // expected-error{{missing 'typename'}} @@ -84,11 +84,11 @@ int *test(UnknownType *fool) { return 0; } // expected-error{{unknown type name template<typename T> int A<T>::n(T::value); // ok template<typename T> -A<T>::type // expected-warning {{implicit 'typename' is a C++20 extension}} +A<T>::type // expected-warning {{missing 'typename'}} A<T>::m(T::value, 0); // ok -template<typename T> int A<T>::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++20 extension}} -template<typename T> int A<T>::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++20 extension}} +template<typename T> int A<T>::h(T::type, int) {} // expected-warning{{missing 'typename'}} +template<typename T> int A<T>::h(T::type x, char) {} // expected-warning{{missing 'typename'}} template<typename T> int h(T::type, int); // expected-error{{missing 'typename'}} template<typename T> int h(T::type x, char); // expected-error{{missing 'typename'}} @@ -117,4 +117,4 @@ template<typename T> int i(T::type, int()); // a fix-it to add 'typename A<T>::type' template<typename T> A<T>::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<typename B::arg> x; // precxx17-warning{{missing 'typename' prior to dependent type name 'B::X'; implicit 'typename' is a C++20 extension}} + typedef B::X<typename B::arg> x; // precxx17-warning{{missing 'typename' prior to dependent type name 'B::X' is a C++20 extension}} }; }; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits