[clang] 502915c - PR45142: 'template ~X<T>' is ill-formed; reject it rather than crashing.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 23 15:07:17 PDT 2020
Author: Richard Smith
Date: 2020-03-23T15:07:06-07:00
New Revision: 502915c619a32972ddc525be585794371bfbd27b
URL: https://github.com/llvm/llvm-project/commit/502915c619a32972ddc525be585794371bfbd27b
DIFF: https://github.com/llvm/llvm-project/commit/502915c619a32972ddc525be585794371bfbd27b.diff
LOG: PR45142: 'template ~X<T>' is ill-formed; reject it rather than crashing.
Added:
Modified:
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/lib/Parse/ParseExprCXX.cpp
clang/test/CXX/drs/dr4xx.cpp
clang/test/SemaCXX/pseudo-destructors.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index acb229225ea1..dcbb0d3f8799 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -706,6 +706,8 @@ def err_id_after_template_in_nested_name_spec : Error<
"expected template name after 'template' keyword in nested name specifier">;
def err_unexpected_template_in_unqualified_id : Error<
"'template' keyword not permitted here">;
+def err_unexpected_template_in_destructor_name : Error<
+ "'template' keyword not permitted in destructor name">;
def err_unexpected_template_after_using : Error<
"'template' keyword not permitted after 'using' keyword">;
def err_two_right_angle_brackets_need_space : Error<
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index b8d91c19228f..a0b97ea7514d 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -2884,6 +2884,22 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
// Parse the '~'.
SourceLocation TildeLoc = ConsumeToken();
+ if (TemplateSpecified) {
+ // C++ [temp.names]p3:
+ // A name prefixed by the keyword template shall be a template-id [...]
+ //
+ // A template-id cannot begin with a '~' token. This would never work
+ // anyway: x.~A<int>() would specify that the destructor is a template,
+ // not that 'A' is a template.
+ //
+ // FIXME: Suggest replacing the attempted destructor name with a correct
+ // destructor name and recover. (This is not trivial if this would become
+ // a pseudo-destructor name).
+ Diag(*TemplateKWLoc, diag::err_unexpected_template_in_destructor_name)
+ << Tok.getLocation();
+ return true;
+ }
+
if (SS.isEmpty() && Tok.is(tok::kw_decltype)) {
DeclSpec DS(AttrFactory);
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
@@ -2903,7 +2919,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
// If the user wrote ~T::T, correct it to T::~T.
DeclaratorScopeObj DeclScopeObj(*this, SS);
- if (!TemplateSpecified && NextToken().is(tok::coloncolon)) {
+ if (NextToken().is(tok::coloncolon)) {
// Don't let ParseOptionalCXXScopeSpecifier() "correct"
// `int A; struct { ~A::A(); };` to `int A; struct { ~A:A(); };`,
// it will confuse this recovery logic.
diff --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp
index 35fd15f0cc64..2c762237037d 100644
--- a/clang/test/CXX/drs/dr4xx.cpp
+++ b/clang/test/CXX/drs/dr4xx.cpp
@@ -297,13 +297,11 @@ namespace dr420 { // dr420: yes
void test2(T p) {
p->template Y<int>::~Y<int>();
p->~Y<int>();
- // FIXME: This is ill-formed, but this diagnostic is terrible. We should
- // reject this in the parser.
- p->template ~Y<int>(); // expected-error 2{{no member named '~typename Y<int>'}}
+ p->template ~Y<int>(); // expected-error {{'template' keyword not permitted in destructor name}}
}
template<typename T> struct Y {};
- template void test2(Y<int>*); // expected-note {{instantiation}}
- template void test2(ptr<Y<int> >); // expected-note {{instantiation}}
+ template void test2(Y<int>*);
+ template void test2(ptr<Y<int> >);
void test3(int *p, ptr<int> q) {
typedef int Int;
diff --git a/clang/test/SemaCXX/pseudo-destructors.cpp b/clang/test/SemaCXX/pseudo-destructors.cpp
index 0cd139047432..b71b523de683 100644
--- a/clang/test/SemaCXX/pseudo-destructors.cpp
+++ b/clang/test/SemaCXX/pseudo-destructors.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -emit-llvm-only -verify -std=c++11 %s
struct A {};
enum Foo { F };
@@ -92,6 +92,9 @@ namespace PR11339 {
template<typename T> using Id = T;
void AliasTemplate(int *p) {
p->~Id<int>();
+ p->template ~Id<int>(); // expected-error {{'template' keyword not permitted in destructor name}}
+ (0).~Id<int>();
+ (0).template ~Id<int>(); // expected-error {{'template' keyword not permitted in destructor name}}
}
namespace dotPointerAccess {
More information about the cfe-commits
mailing list