[clang] 45b5cc0 - [Clang] Fix the warning group of several compatibilty diagnostics (#138872)
via cfe-commits
cfe-commits at lists.llvm.org
Wed May 7 16:42:00 PDT 2025
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 at -1 {{missing 'typename' prior to dependent type name 'B::X'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -1 {{missing 'typename' prior to dependent type name 'B::X' is a C++20 extension}}
struct C : B { X x; };
// expected-error at -1 {{unknown type name 'X'}}
};
@@ -321,7 +321,7 @@ namespace cwg121 { // cwg121: 2.7
X::Y<T> x;
T::Y<T> y;
// expected-error at -1 {{use 'template' keyword to treat 'Y' as a dependent template name}}
- // cxx98-17-error at -2 {{missing 'typename' prior to dependent type name 'T::Y'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -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 at -1 {{missing 'typename' prior to dependent type name 'A<T *>::type'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -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 at -1 {{missing 'typename' prior to dependent type name 'A<T *>::type'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -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 at -1 {{missing 'typename' prior to dependent type name 'A<T *>::B::type'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -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 at -1 {{missing 'typename' prior to dependent type name 'A<T>::type'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -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 at -1 {{missing 'typename' prior to dependent type name 'B<T2, T1, I>::type'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -1 {{missing 'typename' prior to dependent type name 'X<A<T *>::i, long>::type'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -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 at -1 {{missing 'typename' prior to dependent type name 'A<T *>::B'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -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 at -1 {{missing 'typename' prior to dependent type name 'X<(N)>::type'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -1 {{missing 'typename' prior to dependent type name 'X<(N)>::type' is a C++20 extension}}
X<+N>::type v3;
- // cxx98-17-error at -1 {{missing 'typename' prior to dependent type name 'X<+N>::type'; implicit 'typename' is a C++20 extension}}
+ // cxx98-17-error at -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 at -1 {{missing 'typename' prior to dependent type name 'Outer<T>::Inner'; implicit 'typename' is a C++20 extension}}
+// cxx98-17-error at -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 at +4 {{unknown type name 'consteval'; did you mean 'constexpr'}}
+// cxx17-warning at +3 {{missing 'typename' prior to dependent type name 'T::type' is a C++20 extension}}
+// pre-cxx20-compat-warning at +2 {{'consteval' specifier is incompatible with C++ standards before C++20}}
+// pre-cxx20-compat-warning at +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 at +2 {{unknown type name 'constinit'}}
+// pre-cxx20-compat-warning at +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 at -1 {{implicit 'typename' is a C++20 extension}}
+// expected-warning at -1 {{missing 'typename' prior to dependent type name 'b::a' is a C++20 extension}}
// expected-error at -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 at -1{{implicit 'typename' is a C++20 extension}}
+// expected-warning at -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}}
};
};
More information about the cfe-commits
mailing list