Fix crash-on-invalid and name lookup when recovering from ~X::X() typo.

llvm-svn: 226067
This commit is contained in:
Richard Smith 2015-01-15 00:48:52 +00:00
parent 8ffce23cda
commit 64e033f9c4
5 changed files with 27 additions and 4 deletions

View File

@ -4916,7 +4916,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
}
if (D.getCXXScopeSpec().isValid()) {
if (Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
if (Actions.ShouldEnterDeclaratorScope(getCurScope(),
D.getCXXScopeSpec()))
// Change the declaration context for name lookup, until this function
// is exited (and the declarator has been parsed).
DeclScopeObj.EnterDeclaratorScope();
@ -4968,6 +4969,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
AllowConstructorName = (D.getContext() == Declarator::MemberContext);
SourceLocation TemplateKWLoc;
bool HadScope = D.getCXXScopeSpec().isValid();
if (ParseUnqualifiedId(D.getCXXScopeSpec(),
/*EnteringContext=*/true,
/*AllowDestructorName=*/true,
@ -4981,6 +4983,13 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
D.SetIdentifier(nullptr, Tok.getLocation());
D.setInvalidType(true);
} else {
// ParseUnqualifiedId might have parsed a scope specifier during error
// recovery. If it did so, enter that scope.
if (!HadScope && D.getCXXScopeSpec().isValid() &&
Actions.ShouldEnterDeclaratorScope(getCurScope(),
D.getCXXScopeSpec()))
DeclScopeObj.EnterDeclaratorScope();
// Parsed the unqualified-id; update range information and move along.
if (D.getSourceRange().getBegin().isInvalid())
D.SetRangeBegin(D.getName().getSourceRange().getBegin());

View File

@ -2504,6 +2504,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
}
// If the user wrote ~T::T, correct it to T::~T.
DeclaratorScopeObj DeclScopeObj(*this, SS);
if (!TemplateSpecified && NextToken().is(tok::coloncolon)) {
if (SS.isSet()) {
AnnotateScopeToken(SS, /*NewAnnotation*/true);
@ -2520,6 +2521,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
Diag(TildeLoc, diag::err_destructor_tilde_scope)
<< FixItHint::CreateRemoval(TildeLoc)
<< FixItHint::CreateInsertion(Tok.getLocation(), "~");
// Temporarily enter the scope for the rest of this function.
if (Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
DeclScopeObj.EnterDeclaratorScope();
}
// Parse the class-name (or template-name in a simple-template-id).

View File

@ -113,6 +113,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
bool isDependent = false;
bool LookInScope = false;
if (SS.isInvalid())
return ParsedType();
// If we have an object type, it's because we are in a
// pseudo-destructor-expression or a member access expression, and
// we know what type we're looking for.

View File

@ -140,8 +140,8 @@ namespace CtorErrors {
}
namespace DtorErrors {
struct A { ~A(); } a;
~A::A() {} // expected-error {{'~' in destructor name should be after nested name specifier}} expected-note {{previous}}
struct A { ~A(); int n; } a;
~A::A() { n = 0; } // expected-error {{'~' in destructor name should be after nested name specifier}} expected-note {{previous}}
A::~A() {} // expected-error {{redefinition}}
struct B { ~B(); } *b;
@ -151,6 +151,12 @@ namespace DtorErrors {
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}}
}
struct C; // expected-note {{forward decl}}
~C::C() {} // expected-error {{incomplete}} expected-error {{'~' in destructor name should be after nested name specifier}}
struct D { struct X {}; ~D() throw(X); };
~D::D() throw(X) {} // expected-error {{'~' in destructor name should be after nested name specifier}}
}
namespace BadFriend {

View File

@ -17,7 +17,7 @@ namespace PR6161 {
{
static locale::id id; // expected-error{{use of undeclared identifier}}
};
numpunct<char>::~numpunct(); // expected-error{{expected the class name after '~' to name a destructor}}
numpunct<char>::~numpunct();
}
namespace PR12331 {