c++: DR2237, cdtor and template-id tweaks [PR107126]
Since my r11-532 changes to implement DR2237, for this test: template<typename T> struct S { S<T>(); }; in C++20 we emit the ugly: q.C:3:8: error: expected unqualified-id before ')' token 3 | S<T>(); which doesn't explain what the problem is. This patch improves that diagnostic, reduces the error to a pedwarn, and adds a -Wc++20-compat diagnostic. We now say: q.C:3:7: warning: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor] 3 | S<T>(); q.C:3:7: note: remove the '< >' This patch also fixes <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8> where the C++20 diagnostic was missing altogether: The problem was that I checked for CPP_TEMPLATE_ID too early, at a point at which cp_parser_template_id may not have been called yet. So let's check for it at the end of the function, after the tentative parse and rollback. -Wc++20-compat triggered in libitm/; I sent a patch for that. DR 2237 PR c++/107126 PR c++/97202 gcc/c-family/ChangeLog: * c-opts.cc (c_common_post_options): In C++20 or with -Wc++20-compat, turn on -Wtemplate-id-cdtor. * c.opt (Wtemplate-id-cdtor): New. gcc/cp/ChangeLog: * parser.cc (cp_parser_unqualified_id): Downgrade the DR2237 error to a pedwarn. (cp_parser_constructor_declarator_p): Likewise. gcc/ChangeLog: * doc/invoke.texi: Document -Wtemplate-id-cdtor. gcc/testsuite/ChangeLog: * g++.dg/DRs/dr2237.C: Adjust dg-error. * g++.dg/parse/constructor2.C: Likewise. * g++.dg/template/error34.C: Likewise. * g++.old-deja/g++.pt/ctor2.C: Likewise. * g++.dg/DRs/dr2237-2.C: New test. * g++.dg/DRs/dr2237-3.C: New test. * g++.dg/DRs/dr2237-4.C: New test. * g++.dg/DRs/dr2237-5.C: New test. * g++.dg/warn/Wtemplate-id-cdtor-1.C: New test. * g++.dg/warn/Wtemplate-id-cdtor-2.C: New test. * g++.dg/warn/Wtemplate-id-cdtor-3.C: New test. * g++.dg/warn/Wtemplate-id-cdtor-4.C: New test.
This commit is contained in:
parent
f88219333e
commit
cff174fabd
16 changed files with 146 additions and 24 deletions
|
@ -998,6 +998,11 @@ c_common_post_options (const char **pfilename)
|
|||
warn_deprecated_enum_float_conv,
|
||||
cxx_dialect >= cxx20 && warn_deprecated);
|
||||
|
||||
/* -Wtemplate-id-cdtor is enabled by default in C++20. */
|
||||
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
|
||||
warn_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;
|
||||
|
|
|
@ -1408,6 +1408,10 @@ Wtautological-compare
|
|||
C ObjC C++ ObjC++ Var(warn_tautological_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
|
||||
Warn if a comparison always evaluates to true or false.
|
||||
|
||||
Wtemplate-id-cdtor
|
||||
C++ ObjC++ Var(warn_template_id_cdtor) Warning
|
||||
Warn about simple-template-id in a constructor or destructor.
|
||||
|
||||
Wterminate
|
||||
C++ ObjC++ Warning Var(warn_terminate) Init(1)
|
||||
Warn if a throw expression will always result in a call to terminate().
|
||||
|
|
|
@ -6720,12 +6720,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_Wtemplate_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_Wtemplate_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
|
||||
|
@ -32332,9 +32339,7 @@ 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;
|
||||
|
||||
/* Parse tentatively; we are going to roll back all of the tokens
|
||||
|
@ -32553,6 +32558,18 @@ 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
|
||||
&& cp_lexer_peek_token (parser->lexer)->type == CPP_TEMPLATE_ID)
|
||||
{
|
||||
auto_diagnostic_group d;
|
||||
if (emit_diagnostic (cxx_dialect >= cxx20 ? DK_PEDWARN : DK_WARNING,
|
||||
input_location, OPT_Wtemplate_id_cdtor,
|
||||
"template-id not allowed for constructor in C++20"))
|
||||
inform (input_location, "remove the %qs", "< >");
|
||||
}
|
||||
|
||||
return constructor_p;
|
||||
}
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ in the following sections.
|
|||
-Wno-non-template-friend -Wold-style-cast
|
||||
-Woverloaded-virtual -Wno-pmf-conversions -Wself-move -Wsign-promo
|
||||
-Wsized-deallocation -Wsuggest-final-methods
|
||||
-Wsuggest-final-types -Wsuggest-override
|
||||
-Wsuggest-final-types -Wsuggest-override -Wno-template-id-cdtor
|
||||
-Wno-terminate -Wno-vexing-parse -Wvirtual-inheritance
|
||||
-Wno-virtual-move-assign -Wvolatile -Wzero-as-null-pointer-constant}
|
||||
|
||||
|
@ -4604,6 +4604,23 @@ namespaces, and this may be used to enforce that rule. The warning is
|
|||
inactive inside a system header file, such as the STL, so one can still
|
||||
use the STL. One may also use using directives and qualified names.
|
||||
|
||||
@opindex Wtemplate-id-cdtor
|
||||
@opindex Wno-template-id-cdtor
|
||||
@item -Wno-template-id-cdtor @r{(C++ and Objective-C++ only)}
|
||||
Disable the warning about the 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{-Wtemplate-id-cdtor} is enabled by default with
|
||||
@option{-std=c++20}; it is also enabled by @option{-Wc++20-compat}.
|
||||
|
||||
@opindex Wterminate
|
||||
@opindex Wno-terminate
|
||||
@item -Wno-terminate @r{(C++ and Objective-C++ only)}
|
||||
|
|
9
gcc/testsuite/g++.dg/DRs/dr2237-2.C
Normal file
9
gcc/testsuite/g++.dg/DRs/dr2237-2.C
Normal file
|
@ -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 } }
|
||||
};
|
16
gcc/testsuite/g++.dg/DRs/dr2237-3.C
Normal file
16
gcc/testsuite/g++.dg/DRs/dr2237-3.C
Normal file
|
@ -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;;
|
||||
}
|
11
gcc/testsuite/g++.dg/DRs/dr2237-4.C
Normal file
11
gcc/testsuite/g++.dg/DRs/dr2237-4.C
Normal file
|
@ -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() { }
|
7
gcc/testsuite/g++.dg/DRs/dr2237-5.C
Normal file
7
gcc/testsuite/g++.dg/DRs/dr2237-5.C
Normal file
|
@ -0,0 +1,7 @@
|
|||
// PR c++/97202
|
||||
// { dg-options "" }
|
||||
|
||||
template<typename Base> struct S : Base {
|
||||
inline S<Base>() {} // { dg-warning "template-id not allowed for constructor" "" { target c++20 } }
|
||||
inline ~S<Base>() {} // { dg-warning "template-id not allowed for destructor" "" { target c++20 } }
|
||||
};
|
|
@ -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" }
|
||||
};
|
||||
|
|
9
gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-1.C
Normal file
9
gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-1.C
Normal file
|
@ -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" }
|
||||
};
|
9
gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-2.C
Normal file
9
gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-2.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
// PR c++/107126
|
||||
// { dg-do compile }
|
||||
// { dg-options "-Wtemplate-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" }
|
||||
};
|
9
gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-3.C
Normal file
9
gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-3.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
// PR c++/107126
|
||||
// { dg-do compile }
|
||||
// { dg-options "-Wc++20-compat -Wno-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" }
|
||||
};
|
9
gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-4.C
Normal file
9
gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-4.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
// PR c++/107126
|
||||
// { dg-do compile }
|
||||
// { dg-options "-Wtemplate-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>
|
||||
|
|
Loading…
Add table
Reference in a new issue