@@ -998,6 +998,11 @@ c_common_post_options (const char **pfilename)
warn_deprecated_enum_float_conv,
cxx_dialect >= cxx20 && warn_deprecated);
+ /* -Wdeprecated-template-id-cdtor is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_template_id_cdtor,
+ cxx_dialect >= cxx20 || warn_cxx20_compat);
+
/* Declone C++ 'structors if -Os. */
if (flag_declone_ctor_dtor == -1)
flag_declone_ctor_dtor = optimize_size;
@@ -642,6 +642,10 @@ C++ ObjC++ Var(warn_deprecated_enum_float_conv) Warning
Warn about deprecated arithmetic conversions on operands where one is of enumeration
type and the other is of a floating-point type.
+Wdeprecated-template-id-cdtor
+C++ ObjC++ Var(warn_deprecated_template_id_cdtor) Warning
+Warn about deprecated simple-template-id in a constructor or destructor.
+
Wdesignated-init
C ObjC Var(warn_designated_init) Init(1) Warning
Warn about positional initialization of structs requiring designated initializers.
@@ -6719,12 +6719,19 @@ cp_parser_unqualified_id (cp_parser* parser,
/* DR 2237 (C++20 only): A simple-template-id is no longer valid as the
declarator-id of a constructor or destructor. */
- if (token->type == CPP_TEMPLATE_ID && declarator_p
- && cxx_dialect >= cxx20)
+ if (token->type == CPP_TEMPLATE_ID && declarator_p)
{
- if (!cp_parser_simulate_error (parser))
- error_at (tilde_loc, "template-id not allowed for destructor");
- return error_mark_node;
+ auto_diagnostic_group d;
+ bool w = false;
+ if (cxx_dialect >= cxx20 && !cp_parser_simulate_error (parser))
+ w = pedwarn (tilde_loc, OPT_Wdeprecated_template_id_cdtor,
+ "template-id not allowed for destructor in C++20");
+ else if (cxx_dialect < cxx20
+ && !cp_parser_uncommitted_to_tentative_parse_p (parser))
+ w = warning_at (tilde_loc, OPT_Wdeprecated_template_id_cdtor,
+ "template-id not allowed for destructor in C++20");
+ if (w)
+ inform (tilde_loc, "remove the %qs", "< >");
}
/* If there was an explicit qualification (S::~T), first look
@@ -32331,11 +32338,11 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
if (next_token->type != CPP_NAME
&& next_token->type != CPP_SCOPE
&& next_token->type != CPP_NESTED_NAME_SPECIFIER
- /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the
- declarator-id of a constructor or destructor. */
- && (next_token->type != CPP_TEMPLATE_ID || cxx_dialect >= cxx20))
+ && next_token->type != CPP_TEMPLATE_ID)
return false;
+ const bool saw_template_id = (next_token->type == CPP_TEMPLATE_ID);
+
/* Parse tentatively; we are going to roll back all of the tokens
consumed here. */
cp_parser_parse_tentatively (parser);
@@ -32552,6 +32559,19 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
/* We did not really want to consume any tokens. */
cp_parser_abort_tentative_parse (parser);
+ /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the
+ declarator-id of a constructor or destructor. */
+ if (constructor_p && saw_template_id)
+ {
+ gcc_checking_assert
+ (!cp_parser_uncommitted_to_tentative_parse_p (parser));
+ auto_diagnostic_group d;
+ if (emit_diagnostic (cxx_dialect >= cxx20 ? DK_PEDWARN : DK_WARNING,
+ input_location, OPT_Wdeprecated_template_id_cdtor,
+ "template-id not allowed for constructor in C++20"))
+ inform (input_location, "remove the %qs", "< >");
+ }
+
return constructor_p;
}
@@ -255,6 +255,7 @@ in the following sections.
-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare
-Wdeprecated-copy -Wdeprecated-copy-dtor
-Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion
+-Wno-deprecated-template-id-cdtor
-Weffc++ -Wno-elaborated-enum-base
-Wno-exceptions -Wextra-semi -Wno-inaccessible-base
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime
@@ -3989,6 +3990,23 @@ bool b = e <= 3.7;
@option{-std=c++20}. In pre-C++20 dialects, this warning can be enabled
by @option{-Wenum-conversion}.
+@opindex Wdeprecated-template-id-cdtor
+@opindex Wno-deprecated-template-id-cdtor
+@item -Wno-deprecated-template-id-cdtor @r{(C++ and Objective-C++ only)}
+Disable the warning about the deprecated use of simple-template-id as the
+declarator-id of a constructor or destructor, which became invalid in C++20
+via DR 2237. For example:
+
+@smallexample
+template<typename T> struct S @{
+ S<T>(); // should be S();
+ ~S<T>(); // should be ~S();
+@};
+@end smallexample
+
+@option{-Wdeprecated-template-id-cdtor} is enabled by default with
+@option{-std=c++20}; it is also enabled by @option{-Wc++20-compat}.
+
@opindex Welaborated-enum-base
@opindex Wno-elaborated-enum-base
@item -Wno-elaborated-enum-base
new file mode 100644
@@ -0,0 +1,9 @@
+// DR 2237 - Can a template-id name a constructor?
+// { dg-options "" }
+
+template<class T>
+struct X {
+ X<T>(); // { dg-warning "template-id not allowed for constructor" "" { target c++20 } }
+ X(int); // OK, injected-class-name used
+ ~X<T>(); // { dg-warning "template-id not allowed for destructor" "" { target c++20 } }
+};
new file mode 100644
@@ -0,0 +1,16 @@
+// PR c++/107126
+// { dg-options "" }
+
+template<typename T>
+struct C
+{
+ ~C();
+};
+template<typename T>
+C<T>::~C<T>() // { dg-warning "template-id not allowed for destructor" "" { target c++20 } }
+{
+}
+int main()
+{
+ C<int> c;;
+}
new file mode 100644
@@ -0,0 +1,11 @@
+// PR c++/97202
+// { dg-options "" }
+
+template<typename T>
+struct F
+{
+ F<T>(); // { dg-warning "template-id not allowed for constructor" "" { target c++20 } }
+};
+
+template<typename T>
+inline F<T>::F() { }
@@ -2,7 +2,7 @@
template<class T>
struct X {
- X<T>(); // { dg-error "expected" "" { target c++20 } }
+ X<T>(); // { dg-error "template-id not allowed for constructor" "" { target c++20 } }
X(int); // OK, injected-class-name used
~X<T>(); // { dg-error "template-id not allowed for destructor" "" { target c++20 } }
};
@@ -1,11 +1,11 @@
// PR c++/14260
-template <class TClass>
-class T
-{
-public:
- T(short,short f=0) {}
- T<TClass>(int f) {} // { dg-error "expected" "" { target c++20 } }
- T<TClass>(int f=0,const char* b=0) {} // { dg-error "expected" "" { target c++20 } }
-};
+template <class TClass>
+class T
+{
+public:
+ T(short,short f=0) {}
+ T<TClass>(int f) {} // { dg-error "template-id not allowed for constructor" "" { target c++20 } }
+ T<TClass>(int f=0,const char* b=0) {} // { dg-error "template-id not allowed for constructor" "" { target c++20 } }
+};
@@ -3,27 +3,27 @@
template<typename T> struct A
{
- A<__builtin_offsetof(T, x)>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\)|expected" }
+ A<__builtin_offsetof(T, x)>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\)|template-id" }
};
template<typename T> struct B
{
- B<__builtin_offsetof(T, x.y)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\)|expected" }
+ B<__builtin_offsetof(T, x.y)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\)|template-id" }
};
template<typename T> struct C
{
- C<__builtin_offsetof(T, x[6])>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\\[6\\\]\\)|expected" }
+ C<__builtin_offsetof(T, x[6])>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\\[6\\\]\\)|template-id" }
};
template<typename T> struct D
{
- D<__builtin_offsetof(T, x.y[6].z)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\\[6\\\].z\\)|expected" }
+ D<__builtin_offsetof(T, x.y[6].z)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\\[6\\\].z\\)|template-id" }
};
struct E { int x; };
template<typename T> struct F
{
- F<__builtin_offsetof(E, x)>(); // { dg-error "type/value mismatch|offsetof\\(E, x\\)|expected" }
+ F<__builtin_offsetof(E, x)>(); // { dg-error "type/value mismatch|offsetof\\(E, x\\)|template-id" }
};
new file mode 100644
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wc++20-compat" }
+
+template<class T>
+struct X {
+ X<T>(); // { dg-warning "template-id not allowed for constructor" }
+ ~X<T>(); // { dg-warning "template-id not allowed for destructor" }
+};
new file mode 100644
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wdeprecated-template-id-cdtor" }
+
+template<class T>
+struct X {
+ X<T>(); // { dg-warning "template-id not allowed for constructor" }
+ ~X<T>(); // { dg-warning "template-id not allowed for destructor" }
+};
new file mode 100644
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wc++20-compat -Wno-deprecated-template-id-cdtor" }
+
+template<class T>
+struct X {
+ X<T>(); // { dg-bogus "template-id not allowed for constructor" }
+ ~X<T>(); // { dg-bogus "template-id not allowed for destructor" }
+};
new file mode 100644
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wdeprecated-template-id-cdtor -Wno-c++20-compat" }
+
+template<class T>
+struct X {
+ X<T>(); // { dg-warning "template-id not allowed for constructor" }
+ ~X<T>(); // { dg-warning "template-id not allowed for destructor" }
+};
@@ -4,7 +4,7 @@
template <class T>
struct A {
- A<T>(); // { dg-error "expected" "" { target c++20 } }
+ A<T>(); // { dg-error "template-id" "" { target c++20 } }
};
template <class T>