Add error, recovery and fixit for "~A::A() {...}".

llvm-svn: 217302
This commit is contained in:
Richard Smith 2014-09-06 02:06:12 +00:00
parent d650b82b22
commit efa6f736e6
4 changed files with 44 additions and 2 deletions

View File

@ -492,6 +492,8 @@ def err_constructor_bad_name : Error<
"missing return type for function %0; did you mean the constructor name %1?">;
def err_destructor_tilde_identifier : Error<
"expected a class name after '~' to name a destructor">;
def err_destructor_tilde_scope : Error<
"'~' in destructor name should be after nested name specifier">;
def err_destructor_template_id : Error<
"destructor name %0 does not refer to a template">;
def err_default_arg_unparsed : Error<

View File

@ -2452,10 +2452,29 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
return true;
}
// If the user wrote ~T::T, correct it to T::~T.
if (!TemplateSpecified && NextToken().is(tok::coloncolon)) {
if (SS.isSet()) {
AnnotateScopeToken(SS, /*NewAnnotation*/true);
SS.clear();
}
if (ParseOptionalCXXScopeSpecifier(SS, ObjectType, EnteringContext))
return true;
if (Tok.isNot(tok::identifier) || NextToken().is(tok::coloncolon)) {
Diag(TildeLoc, diag::err_destructor_tilde_scope);
return true;
}
// Recover as if the tilde had been written before the identifier.
Diag(TildeLoc, diag::err_destructor_tilde_scope)
<< FixItHint::CreateRemoval(TildeLoc)
<< FixItHint::CreateInsertion(Tok.getLocation(), "~");
}
// Parse the class-name (or template-name in a simple-template-id).
IdentifierInfo *ClassName = Tok.getIdentifierInfo();
SourceLocation ClassNameLoc = ConsumeToken();
if (TemplateSpecified || Tok.is(tok::less)) {
Result.setDestructorName(TildeLoc, ParsedType(), ClassNameLoc);
return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
@ -2463,7 +2482,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
EnteringContext, ObjectType,
Result, TemplateSpecified);
}
// Note that this is a destructor name.
ParsedType Ty = Actions.getDestructorName(TildeLoc, *ClassName,
ClassNameLoc, getCurScope(),

View File

@ -308,6 +308,13 @@ namespace dtor_fixit {
~bar() { } // expected-error {{expected the class name after '~' to name a destructor}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:9}:"foo"
};
class bar {
~bar();
};
~bar::bar() {} // expected-error {{'~' in destructor name should be after nested name specifier}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:4}:""
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:9-[[@LINE-2]]:9}:"~"
}
namespace PR5066 {

View File

@ -139,6 +139,20 @@ namespace CtorErrors {
};
}
namespace DtorErrors {
struct A { ~A(); } a;
~A::A() {} // expected-error {{'~' in destructor name should be after nested name specifier}} expected-note {{previous}}
A::~A() {} // expected-error {{redefinition}}
struct B { ~B(); } *b;
DtorErrors::~B::B() {} // expected-error {{'~' in destructor name should be after nested name specifier}}
void f() {
a.~A::A(); // expected-error {{'~' in destructor name should be after nested name specifier}}
b->~DtorErrors::~B::B(); // expected-error {{'~' in destructor name should be after nested name specifier}}
}
}
namespace BadFriend {
struct A {
friend int : 3; // expected-error {{friends can only be classes or functions}}