"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<
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,
EnteringContext, ObjectType,
Result, TemplateSpecified);
}
-
+
// Note that this is a destructor name.
ParsedType Ty = Actions.getDestructorName(TildeLoc, *ClassName,
ClassNameLoc, getCurScope(),
~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 {
};
}
+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}}