diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-02-21 18:36:56 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-02-21 18:36:56 +0000 |
commit | b10cd04880672103660e5844e51ee91af7361a20 (patch) | |
tree | 6ea428d3b9d0b09b9533f8bec9ff66f2392dc74c /lib/Parse/ParseExprCXX.cpp | |
parent | 12116062c8243c6f88d79dac9663a359b77741c6 (diff) |
Implement support for parsing pseudo-destructor expression with a nested-name-specifier, e.g.,
typedef int Int;
int *p;
p->Int::~Int();
This weakens the invariant that the only types in nested-name-specifiers are tag types (restricted to class types in C++98/03). However, we weaken this invariant as little as possible, accepting arbitrary types in nested-name-specifiers only when we're in a member access expression that looks like a pseudo-destructor expression.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96743 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 932d6ebf97..a8fbaff015 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -45,10 +45,14 @@ using namespace clang; /// \param EnteringContext whether we will be entering into the context of /// the nested-name-specifier after parsing it. /// +/// \param InMemberAccessExpr Whether this scope specifier is within a +/// member access expression, e.g., the \p T:: in \p p->T::m. +/// /// \returns true if a scope specifier was parsed. bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, Action::TypeTy *ObjectType, - bool EnteringContext) { + bool EnteringContext, + bool InMemberAccessExpr) { assert(getLang().CPlusPlus && "Call sites of this function should be guarded by checking for C++"); @@ -169,7 +173,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // convert it into a type within the nested-name-specifier. TemplateIdAnnotation *TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); - + bool MayBePseudoDestructor + = InMemberAccessExpr && GetLookAheadToken(2).is(tok::tilde); if (TemplateId->Kind == TNK_Type_template || TemplateId->Kind == TNK_Dependent_template_name) { AnnotateTemplateIdTokenAsType(&SS); @@ -191,7 +196,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, TypeToken.getAnnotationValue(), TypeToken.getAnnotationRange(), - CCLoc)); + CCLoc, + MayBePseudoDestructor)); else SS.setScopeRep(0); SS.setEndLoc(CCLoc); @@ -217,18 +223,23 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // If we get foo:bar, this is almost certainly a typo for foo::bar. Recover // and emit a fixit hint for it. - if (Next.is(tok::colon) && !ColonIsSacred && - Actions.IsInvalidUnlessNestedName(CurScope, SS, II, ObjectType, - EnteringContext) && - // If the token after the colon isn't an identifier, it's still an - // error, but they probably meant something else strange so don't - // recover like this. - PP.LookAhead(1).is(tok::identifier)) { - Diag(Next, diag::err_unexected_colon_in_nested_name_spec) - << CodeModificationHint::CreateReplacement(Next.getLocation(), "::"); + if (Next.is(tok::colon) && !ColonIsSacred) { + bool MayBePseudoDestructor + = InMemberAccessExpr && GetLookAheadToken(2).is(tok::tilde); - // Recover as if the user wrote '::'. - Next.setKind(tok::coloncolon); + if (Actions.IsInvalidUnlessNestedName(CurScope, SS, II, + MayBePseudoDestructor, ObjectType, + EnteringContext) && + // If the token after the colon isn't an identifier, it's still an + // error, but they probably meant something else strange so don't + // recover like this. + PP.LookAhead(1).is(tok::identifier)) { + Diag(Next, diag::err_unexected_colon_in_nested_name_spec) + << CodeModificationHint::CreateReplacement(Next.getLocation(), "::"); + + // Recover as if the user wrote '::'. + Next.setKind(tok::coloncolon); + } } if (Next.is(tok::coloncolon)) { @@ -247,9 +258,12 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (SS.isInvalid()) continue; + bool MayBePseudoDestructor = InMemberAccessExpr && Tok.is(tok::tilde); + SS.setScopeRep( Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II, - ObjectType, EnteringContext)); + MayBePseudoDestructor, ObjectType, + EnteringContext)); SS.setEndLoc(CCLoc); continue; } |