Follow-up to r217302 and r227555: Don't crash on inline ~A::A() if A is an int.

Even with r227555, this still crashed:

  struct S {
    int A;
    ~A::A() {}
  };

That's because ParseOptionalCXXScopeSpecifier()'s call to
ActOnCXXNestedNameSpecifier() doesn't mark the scope spec as invalid if sema
thought it's a good idea to fixit-correct "::" to ":".  For the diagnostic
improvement done in r217302, we never want :: to be interpreted as :, so fix
this by setting ColonSacred to false temporarily.

Found by SLi's bot.

llvm-svn: 227581
This commit is contained in:
Nico Weber 2015-01-30 16:53:11 +00:00
parent 655b59854f
commit f9e37be2d6
2 changed files with 22 additions and 1 deletions

View File

@ -2509,7 +2509,13 @@ 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 (!TemplateSpecified && //!ColonIsSacred &&
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.
ColonProtectionRAIIObject ColonRAII(*this, false);
if (SS.isSet()) {
AnnotateScopeToken(SS, /*NewAnnotation*/true);
SS.clear();

View File

@ -159,6 +159,21 @@ namespace DtorErrors {
~D::D() throw(X) {} // expected-error {{'~' in destructor name should be after nested name specifier}}
~Undeclared::Undeclared() {} // expected-error {{use of undeclared identifier 'Undeclared'}} expected-error {{'~' in destructor name should be after nested name specifier}}
struct S {
// For another struct's destructor, emit the same diagnostic like for
// A::~A() in addition to the "~ in the wrong place" one.
~A::A() {} // expected-error {{'~' in destructor name should be after nested name specifier}} expected-error {{non-friend class member '~A' cannot have a qualified name}}
A::~A() {} // expected-error {{non-friend class member '~A' cannot have a qualified name}}
// An inline destructor with a redundant class name should also get the
// same diagnostic as S::~S.
~S::S() {} // expected-error {{'~' in destructor name should be after nested name specifier}} expected-error {{extra qualification on member '~S'}}
// This just shouldn't crash.
int I; // expected-note {{declared here}}
~I::I() {} // expected-error {{'I' is not a class, namespace, or enumeration}} expected-error {{'~' in destructor name should be after nested name specifier}}
};
}
namespace BadFriend {