diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp | 198 |
1 files changed, 134 insertions, 64 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index 83121a8..355503c 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -108,35 +108,37 @@ void Parser::CheckForLParenAfterColonColon() { if (!Tok.is(tok::l_paren)) return; - SourceLocation l_parenLoc = ConsumeParen(), r_parenLoc; - Token Tok1 = getCurToken(); - if (!Tok1.is(tok::identifier) && !Tok1.is(tok::star)) + Token LParen = Tok; + Token NextTok = GetLookAheadToken(1); + Token StarTok = NextTok; + // Check for (identifier or (*identifier + Token IdentifierTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : StarTok; + if (IdentifierTok.isNot(tok::identifier)) return; - - if (Tok1.is(tok::identifier)) { - Token Tok2 = GetLookAheadToken(1); - if (Tok2.is(tok::r_paren)) { + // Eat the '('. + ConsumeParen(); + Token RParen; + // Do we have a ')' ? + NextTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : GetLookAheadToken(1); + if (NextTok.is(tok::r_paren)) { + RParen = NextTok; + // Eat the '*' if it is present. + if (StarTok.is(tok::star)) ConsumeToken(); - PP.EnterToken(Tok1); - r_parenLoc = ConsumeParen(); - } - } else if (Tok1.is(tok::star)) { - Token Tok2 = GetLookAheadToken(1); - if (Tok2.is(tok::identifier)) { - Token Tok3 = GetLookAheadToken(2); - if (Tok3.is(tok::r_paren)) { - ConsumeToken(); - ConsumeToken(); - PP.EnterToken(Tok2); - PP.EnterToken(Tok1); - r_parenLoc = ConsumeParen(); - } - } - } - - Diag(l_parenLoc, diag::err_paren_after_colon_colon) - << FixItHint::CreateRemoval(l_parenLoc) - << FixItHint::CreateRemoval(r_parenLoc); + // Eat the identifier. + ConsumeToken(); + // Add the identifier token back. + PP.EnterToken(IdentifierTok); + // Add the '*' back if it was present. + if (StarTok.is(tok::star)) + PP.EnterToken(StarTok); + // Eat the ')'. + ConsumeParen(); + } + + Diag(LParen.getLocation(), diag::err_paren_after_colon_colon) + << FixItHint::CreateRemoval(LParen.getLocation()) + << FixItHint::CreateRemoval(RParen.getLocation()); } /// \brief Parse global scope or nested-name-specifier if present. @@ -217,13 +219,29 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (NextKind == tok::kw_new || NextKind == tok::kw_delete) return false; - // '::' - Global scope qualifier. - if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS)) - return true; + if (NextKind == tok::l_brace) { + // It is invalid to have :: {, consume the scope qualifier and pretend + // like we never saw it. + Diag(ConsumeToken(), diag::err_expected) << tok::identifier; + } else { + // '::' - Global scope qualifier. + if (Actions.ActOnCXXGlobalScopeSpecifier(ConsumeToken(), SS)) + return true; - CheckForLParenAfterColonColon(); + CheckForLParenAfterColonColon(); - HasScopeSpecifier = true; + HasScopeSpecifier = true; + } + } + + if (Tok.is(tok::kw___super)) { + SourceLocation SuperLoc = ConsumeToken(); + if (!Tok.is(tok::coloncolon)) { + Diag(Tok.getLocation(), diag::err_expected_coloncolon_after_super); + return true; + } + + return Actions.ActOnSuperScopeSpecifier(SuperLoc, ConsumeToken(), SS); } bool CheckForDestructor = false; @@ -232,7 +250,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, *MayBePseudoDestructor = false; } - if (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) { + if (!HasScopeSpecifier && + (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))) { DeclSpec DS(AttrFactory); SourceLocation DeclLoc = Tok.getLocation(); SourceLocation EndLoc = ParseDecltypeSpecifier(DS); @@ -423,11 +442,22 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, Next.setKind(tok::coloncolon); } } - + + if (Next.is(tok::coloncolon) && GetLookAheadToken(2).is(tok::l_brace)) { + // It is invalid to have :: {, consume the scope qualifier and pretend + // like we never saw it. + Token Identifier = Tok; // Stash away the identifier. + ConsumeToken(); // Eat the identifier, current token is now '::'. + Diag(PP.getLocForEndOfToken(ConsumeToken()), diag::err_expected) + << tok::identifier; + UnconsumeToken(Identifier); // Stick the identifier back. + Next = NextToken(); // Point Next at the '{' token. + } + if (Next.is(tok::coloncolon)) { if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde) && - !Actions.isNonTypeNestedNameSpecifier(getCurScope(), SS, Tok.getLocation(), - II, ObjectType)) { + !Actions.isNonTypeNestedNameSpecifier( + getCurScope(), SS, Tok.getLocation(), II, ObjectType)) { *MayBePseudoDestructor = true; return false; } @@ -556,6 +586,28 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } +ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOperand, + Token &Replacement) { + SourceLocation TemplateKWLoc; + UnqualifiedId Name; + if (ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/false, + /*AllowConstructorName=*/false, + /*ObjectType=*/ParsedType(), TemplateKWLoc, Name)) + return ExprError(); + + // This is only the direct operand of an & operator if it is not + // followed by a postfix-expression suffix. + if (isAddressOfOperand && isPostfixExpressionSuffixStart()) + isAddressOfOperand = false; + + return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, + Tok.is(tok::l_paren), isAddressOfOperand, + nullptr, /*IsInlineAsmIdentifier=*/false, + &Replacement); +} + /// ParseCXXIdExpression - Handle id-expression. /// /// id-expression: @@ -606,24 +658,17 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); - SourceLocation TemplateKWLoc; - UnqualifiedId Name; - if (ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/false, - /*AllowConstructorName=*/false, - /*ObjectType=*/ ParsedType(), - TemplateKWLoc, - Name)) - return ExprError(); - - // This is only the direct operand of an & operator if it is not - // followed by a postfix-expression suffix. - if (isAddressOfOperand && isPostfixExpressionSuffixStart()) - isAddressOfOperand = false; - - return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, - Tok.is(tok::l_paren), isAddressOfOperand); + Token Replacement; + ExprResult Result = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement); + if (Result.isUnset()) { + // If the ExprResult is valid but null, then typo correction suggested a + // keyword replacement that needs to be reparsed. + UnconsumeToken(Replacement); + Result = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement); + } + assert(!Result.isUnset() && "Typo correction suggested a keyword replacement " + "for a previous keyword suggestion"); + return Result; } /// ParseLambdaExpression - Parse a C++11 lambda expression. @@ -1007,6 +1052,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); Actions.PushLambdaScope(); + TypeResult TrailingReturnType; if (Tok.is(tok::l_paren)) { ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | @@ -1050,10 +1096,13 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( SmallVector<ParsedType, 2> DynamicExceptions; SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; - ESpecType = tryParseExceptionSpecification(ESpecRange, + CachedTokens *ExceptionSpecTokens; + ESpecType = tryParseExceptionSpecification(/*Delayed=*/false, + ESpecRange, DynamicExceptions, DynamicExceptionRanges, - NoexceptExpr); + NoexceptExpr, + ExceptionSpecTokens); if (ESpecType != EST_None) DeclEndLoc = ESpecRange.getEnd(); @@ -1064,7 +1113,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( SourceLocation FunLocalRangeEnd = DeclEndLoc; // Parse trailing-return-type[opt]. - TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { FunLocalRangeEnd = Tok.getLocation(); SourceRange Range; @@ -1086,6 +1134,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*RefQualifierLoc=*/NoLoc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, ESpecType, ESpecRange.getBegin(), DynamicExceptions.data(), @@ -1093,6 +1142,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + /*ExceptionSpecTokens*/nullptr, LParenLoc, FunLocalRangeEnd, D, TrailingReturnType), Attr, DeclEndLoc); @@ -1132,12 +1182,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( MaybeParseCXX11Attributes(Attr, &DeclEndLoc); // Parse the return type, if there is one. - TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { SourceRange Range; TrailingReturnType = ParseTrailingReturnType(Range); if (Range.getEnd().isValid()) - DeclEndLoc = Range.getEnd(); + DeclEndLoc = Range.getEnd(); } SourceLocation NoLoc; @@ -1153,6 +1202,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*RefQualifierLoc=*/NoLoc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None, /*ESpecLoc=*/NoLoc, @@ -1160,6 +1210,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, DeclLoc, DeclEndLoc, D, TrailingReturnType), Attr, DeclEndLoc); @@ -1183,9 +1234,9 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( StmtResult Stmt(ParseCompoundStatementBody()); BodyScope.Exit(); - if (!Stmt.isInvalid()) + if (!Stmt.isInvalid() && !TrailingReturnType.isInvalid()) return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get(), getCurScope()); - + Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); return ExprError(); } @@ -1389,7 +1440,7 @@ ExprResult Parser::ParseCXXUuidof() { /// ::[opt] nested-name-specifier[opt] ~type-name /// ExprResult -Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, +Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, ParsedType ObjectType) { @@ -2452,10 +2503,29 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, 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, @@ -2463,7 +2533,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, EnteringContext, ObjectType, Result, TemplateSpecified); } - + // Note that this is a destructor name. ParsedType Ty = Actions.getDestructorName(TildeLoc, *ClassName, ClassNameLoc, getCurScope(), |