diff options
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7ce9a9c..8d7d37c 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6650,48 +6650,66 @@ void Parser::ParseDeclaratorInternal(Declarator &D, (Tok.is(tok::identifier) && (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) || Tok.is(tok::annot_cxxscope))) { + TentativeParsingAction TPA(*this, /*Unannotated=*/true); bool EnteringContext = D.getContext() == DeclaratorContext::File || D.getContext() == DeclaratorContext::Member; CXXScopeSpec SS; SS.setTemplateParamLists(D.getTemplateParameterLists()); - ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, - /*ObjectHasErrors=*/false, EnteringContext); - if (SS.isNotEmpty()) { - if (Tok.isNot(tok::star)) { - // The scope spec really belongs to the direct-declarator. - if (D.mayHaveIdentifier()) - D.getCXXScopeSpec() = SS; - else - AnnotateScopeToken(SS, true); + if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHasErrors=*/false, + /*EnteringContext=*/false, + /*MayBePseudoDestructor=*/nullptr, + /*IsTypename=*/false, /*LastII=*/nullptr, + /*OnlyNamespace=*/false, + /*InUsingDeclaration=*/false, + /*Disambiguation=*/EnteringContext) || + + SS.isEmpty() || SS.isInvalid() || !EnteringContext || + Tok.is(tok::star)) { + TPA.Commit(); + if (SS.isNotEmpty() && Tok.is(tok::star)) { + if (SS.isValid()) { + checkCompoundToken(SS.getEndLoc(), tok::coloncolon, + CompoundToken::MemberPtr); + } - if (DirectDeclParser) - (this->*DirectDeclParser)(D); + SourceLocation StarLoc = ConsumeToken(); + D.SetRangeEnd(StarLoc); + DeclSpec DS(AttrFactory); + ParseTypeQualifierListOpt(DS); + D.ExtendWithDeclSpec(DS); + + // Recurse to parse whatever is left. + Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] { + ParseDeclaratorInternal(D, DirectDeclParser); + }); + + // Sema will have to catch (syntactically invalid) pointers into global + // scope. It has to catch pointers into namespace scope anyway. + D.AddTypeInfo(DeclaratorChunk::getMemberPointer( + SS, DS.getTypeQualifiers(), StarLoc, DS.getEndLoc()), + std::move(DS.getAttributes()), + /*EndLoc=*/SourceLocation()); return; } + } else { + TPA.Revert(); + SS.clear(); + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHasErrors=*/false, + /*EnteringContext=*/true); + } - if (SS.isValid()) { - checkCompoundToken(SS.getEndLoc(), tok::coloncolon, - CompoundToken::MemberPtr); - } + if (SS.isNotEmpty()) { + // The scope spec really belongs to the direct-declarator. + if (D.mayHaveIdentifier()) + D.getCXXScopeSpec() = SS; + else + AnnotateScopeToken(SS, true); - SourceLocation StarLoc = ConsumeToken(); - D.SetRangeEnd(StarLoc); - DeclSpec DS(AttrFactory); - ParseTypeQualifierListOpt(DS); - D.ExtendWithDeclSpec(DS); - - // Recurse to parse whatever is left. - Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] { - ParseDeclaratorInternal(D, DirectDeclParser); - }); - - // Sema will have to catch (syntactically invalid) pointers into global - // scope. It has to catch pointers into namespace scope anyway. - D.AddTypeInfo(DeclaratorChunk::getMemberPointer( - SS, DS.getTypeQualifiers(), StarLoc, DS.getEndLoc()), - std::move(DS.getAttributes()), - /* Don't replace range end. */ SourceLocation()); + if (DirectDeclParser) + (this->*DirectDeclParser)(D); return; } } |