Path: blob/main/contrib/llvm-project/clang/lib/Parse/ParseExpr.cpp
35233 views
//===--- ParseExpr.cpp - Expression Parsing -------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// Provides the Expression parsing implementation.10///11/// Expressions in C99 basically consist of a bunch of binary operators with12/// unary operators and other random stuff at the leaves.13///14/// In the C99 grammar, these unary operators bind tightest and are represented15/// as the 'cast-expression' production. Everything else is either a binary16/// operator (e.g. '/') or a ternary operator ("?:"). The unary leaves are17/// handled by ParseCastExpression, the higher level pieces are handled by18/// ParseBinaryExpression.19///20//===----------------------------------------------------------------------===//2122#include "clang/AST/ASTContext.h"23#include "clang/AST/ExprCXX.h"24#include "clang/Basic/PrettyStackTrace.h"25#include "clang/Lex/LiteralSupport.h"26#include "clang/Parse/Parser.h"27#include "clang/Parse/RAIIObjectsForParser.h"28#include "clang/Sema/DeclSpec.h"29#include "clang/Sema/EnterExpressionEvaluationContext.h"30#include "clang/Sema/ParsedTemplate.h"31#include "clang/Sema/Scope.h"32#include "clang/Sema/SemaCUDA.h"33#include "clang/Sema/SemaCodeCompletion.h"34#include "clang/Sema/SemaObjC.h"35#include "clang/Sema/SemaOpenACC.h"36#include "clang/Sema/SemaOpenMP.h"37#include "clang/Sema/SemaSYCL.h"38#include "clang/Sema/TypoCorrection.h"39#include "llvm/ADT/SmallVector.h"40#include <optional>41using namespace clang;4243/// Simple precedence-based parser for binary/ternary operators.44///45/// Note: we diverge from the C99 grammar when parsing the assignment-expression46/// production. C99 specifies that the LHS of an assignment operator should be47/// parsed as a unary-expression, but consistency dictates that it be a48/// conditional-expession. In practice, the important thing here is that the49/// LHS of an assignment has to be an l-value, which productions between50/// unary-expression and conditional-expression don't produce. Because we want51/// consistency, we parse the LHS as a conditional-expression, then check for52/// l-value-ness in semantic analysis stages.53///54/// \verbatim55/// pm-expression: [C++ 5.5]56/// cast-expression57/// pm-expression '.*' cast-expression58/// pm-expression '->*' cast-expression59///60/// multiplicative-expression: [C99 6.5.5]61/// Note: in C++, apply pm-expression instead of cast-expression62/// cast-expression63/// multiplicative-expression '*' cast-expression64/// multiplicative-expression '/' cast-expression65/// multiplicative-expression '%' cast-expression66///67/// additive-expression: [C99 6.5.6]68/// multiplicative-expression69/// additive-expression '+' multiplicative-expression70/// additive-expression '-' multiplicative-expression71///72/// shift-expression: [C99 6.5.7]73/// additive-expression74/// shift-expression '<<' additive-expression75/// shift-expression '>>' additive-expression76///77/// compare-expression: [C++20 expr.spaceship]78/// shift-expression79/// compare-expression '<=>' shift-expression80///81/// relational-expression: [C99 6.5.8]82/// compare-expression83/// relational-expression '<' compare-expression84/// relational-expression '>' compare-expression85/// relational-expression '<=' compare-expression86/// relational-expression '>=' compare-expression87///88/// equality-expression: [C99 6.5.9]89/// relational-expression90/// equality-expression '==' relational-expression91/// equality-expression '!=' relational-expression92///93/// AND-expression: [C99 6.5.10]94/// equality-expression95/// AND-expression '&' equality-expression96///97/// exclusive-OR-expression: [C99 6.5.11]98/// AND-expression99/// exclusive-OR-expression '^' AND-expression100///101/// inclusive-OR-expression: [C99 6.5.12]102/// exclusive-OR-expression103/// inclusive-OR-expression '|' exclusive-OR-expression104///105/// logical-AND-expression: [C99 6.5.13]106/// inclusive-OR-expression107/// logical-AND-expression '&&' inclusive-OR-expression108///109/// logical-OR-expression: [C99 6.5.14]110/// logical-AND-expression111/// logical-OR-expression '||' logical-AND-expression112///113/// conditional-expression: [C99 6.5.15]114/// logical-OR-expression115/// logical-OR-expression '?' expression ':' conditional-expression116/// [GNU] logical-OR-expression '?' ':' conditional-expression117/// [C++] the third operand is an assignment-expression118///119/// assignment-expression: [C99 6.5.16]120/// conditional-expression121/// unary-expression assignment-operator assignment-expression122/// [C++] throw-expression [C++ 15]123///124/// assignment-operator: one of125/// = *= /= %= += -= <<= >>= &= ^= |=126///127/// expression: [C99 6.5.17]128/// assignment-expression ...[opt]129/// expression ',' assignment-expression ...[opt]130/// \endverbatim131ExprResult Parser::ParseExpression(TypeCastState isTypeCast) {132ExprResult LHS(ParseAssignmentExpression(isTypeCast));133return ParseRHSOfBinaryExpression(LHS, prec::Comma);134}135136/// This routine is called when the '@' is seen and consumed.137/// Current token is an Identifier and is not a 'try'. This138/// routine is necessary to disambiguate \@try-statement from,139/// for example, \@encode-expression.140///141ExprResult142Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {143ExprResult LHS(ParseObjCAtExpression(AtLoc));144return ParseRHSOfBinaryExpression(LHS, prec::Comma);145}146147/// This routine is called when a leading '__extension__' is seen and148/// consumed. This is necessary because the token gets consumed in the149/// process of disambiguating between an expression and a declaration.150ExprResult151Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {152ExprResult LHS(true);153{154// Silence extension warnings in the sub-expression155ExtensionRAIIObject O(Diags);156157LHS = ParseCastExpression(AnyCastExpr);158}159160if (!LHS.isInvalid())161LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__,162LHS.get());163164return ParseRHSOfBinaryExpression(LHS, prec::Comma);165}166167/// Parse an expr that doesn't include (top-level) commas.168ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {169if (Tok.is(tok::code_completion)) {170cutOffParsing();171Actions.CodeCompletion().CodeCompleteExpression(172getCurScope(), PreferredType.get(Tok.getLocation()));173return ExprError();174}175176if (Tok.is(tok::kw_throw))177return ParseThrowExpression();178if (Tok.is(tok::kw_co_yield))179return ParseCoyieldExpression();180181ExprResult LHS = ParseCastExpression(AnyCastExpr,182/*isAddressOfOperand=*/false,183isTypeCast);184return ParseRHSOfBinaryExpression(LHS, prec::Assignment);185}186187ExprResult Parser::ParseConditionalExpression() {188if (Tok.is(tok::code_completion)) {189cutOffParsing();190Actions.CodeCompletion().CodeCompleteExpression(191getCurScope(), PreferredType.get(Tok.getLocation()));192return ExprError();193}194195ExprResult LHS = ParseCastExpression(196AnyCastExpr, /*isAddressOfOperand=*/false, NotTypeCast);197return ParseRHSOfBinaryExpression(LHS, prec::Conditional);198}199200/// Parse an assignment expression where part of an Objective-C message201/// send has already been parsed.202///203/// In this case \p LBracLoc indicates the location of the '[' of the message204/// send, and either \p ReceiverName or \p ReceiverExpr is non-null indicating205/// the receiver of the message.206///207/// Since this handles full assignment-expression's, it handles postfix208/// expressions and other binary operators for these expressions as well.209ExprResult210Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,211SourceLocation SuperLoc,212ParsedType ReceiverType,213Expr *ReceiverExpr) {214ExprResult R215= ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,216ReceiverType, ReceiverExpr);217R = ParsePostfixExpressionSuffix(R);218return ParseRHSOfBinaryExpression(R, prec::Assignment);219}220221ExprResult222Parser::ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast) {223assert(Actions.ExprEvalContexts.back().Context ==224Sema::ExpressionEvaluationContext::ConstantEvaluated &&225"Call this function only if your ExpressionEvaluationContext is "226"already ConstantEvaluated");227ExprResult LHS(ParseCastExpression(AnyCastExpr, false, isTypeCast));228ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));229return Actions.ActOnConstantExpression(Res);230}231232ExprResult Parser::ParseConstantExpression() {233// C++03 [basic.def.odr]p2:234// An expression is potentially evaluated unless it appears where an235// integral constant expression is required (see 5.19) [...].236// C++98 and C++11 have no such rule, but this is only a defect in C++98.237EnterExpressionEvaluationContext ConstantEvaluated(238Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);239return ParseConstantExpressionInExprEvalContext(NotTypeCast);240}241242ExprResult Parser::ParseArrayBoundExpression() {243EnterExpressionEvaluationContext ConstantEvaluated(244Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);245// If we parse the bound of a VLA... we parse a non-constant246// constant-expression!247Actions.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true;248return ParseConstantExpressionInExprEvalContext(NotTypeCast);249}250251ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {252EnterExpressionEvaluationContext ConstantEvaluated(253Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);254ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));255ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));256return Actions.ActOnCaseExpr(CaseLoc, Res);257}258259/// Parse a constraint-expression.260///261/// \verbatim262/// constraint-expression: C++2a[temp.constr.decl]p1263/// logical-or-expression264/// \endverbatim265ExprResult Parser::ParseConstraintExpression() {266EnterExpressionEvaluationContext ConstantEvaluated(267Actions, Sema::ExpressionEvaluationContext::Unevaluated);268ExprResult LHS(ParseCastExpression(AnyCastExpr));269ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));270if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) {271Actions.CorrectDelayedTyposInExpr(Res);272return ExprError();273}274return Res;275}276277/// \brief Parse a constraint-logical-and-expression.278///279/// \verbatim280/// C++2a[temp.constr.decl]p1281/// constraint-logical-and-expression:282/// primary-expression283/// constraint-logical-and-expression '&&' primary-expression284///285/// \endverbatim286ExprResult287Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {288EnterExpressionEvaluationContext ConstantEvaluated(289Actions, Sema::ExpressionEvaluationContext::Unevaluated);290bool NotPrimaryExpression = false;291auto ParsePrimary = [&] () {292ExprResult E = ParseCastExpression(PrimaryExprOnly,293/*isAddressOfOperand=*/false,294/*isTypeCast=*/NotTypeCast,295/*isVectorLiteral=*/false,296&NotPrimaryExpression);297if (E.isInvalid())298return ExprError();299auto RecoverFromNonPrimary = [&] (ExprResult E, bool Note) {300E = ParsePostfixExpressionSuffix(E);301// Use InclusiveOr, the precedence just after '&&' to not parse the302// next arguments to the logical and.303E = ParseRHSOfBinaryExpression(E, prec::InclusiveOr);304if (!E.isInvalid())305Diag(E.get()->getExprLoc(),306Note307? diag::note_unparenthesized_non_primary_expr_in_requires_clause308: diag::err_unparenthesized_non_primary_expr_in_requires_clause)309<< FixItHint::CreateInsertion(E.get()->getBeginLoc(), "(")310<< FixItHint::CreateInsertion(311PP.getLocForEndOfToken(E.get()->getEndLoc()), ")")312<< E.get()->getSourceRange();313return E;314};315316if (NotPrimaryExpression ||317// Check if the following tokens must be a part of a non-primary318// expression319getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,320/*CPlusPlus11=*/true) > prec::LogicalAnd ||321// Postfix operators other than '(' (which will be checked for in322// CheckConstraintExpression).323Tok.isOneOf(tok::period, tok::plusplus, tok::minusminus) ||324(Tok.is(tok::l_square) && !NextToken().is(tok::l_square))) {325E = RecoverFromNonPrimary(E, /*Note=*/false);326if (E.isInvalid())327return ExprError();328NotPrimaryExpression = false;329}330bool PossibleNonPrimary;331bool IsConstraintExpr =332Actions.CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary,333IsTrailingRequiresClause);334if (!IsConstraintExpr || PossibleNonPrimary) {335// Atomic constraint might be an unparenthesized non-primary expression336// (such as a binary operator), in which case we might get here (e.g. in337// 'requires 0 + 1 && true' we would now be at '+', and parse and ignore338// the rest of the addition expression). Try to parse the rest of it here.339if (PossibleNonPrimary)340E = RecoverFromNonPrimary(E, /*Note=*/!IsConstraintExpr);341Actions.CorrectDelayedTyposInExpr(E);342return ExprError();343}344return E;345};346ExprResult LHS = ParsePrimary();347if (LHS.isInvalid())348return ExprError();349while (Tok.is(tok::ampamp)) {350SourceLocation LogicalAndLoc = ConsumeToken();351ExprResult RHS = ParsePrimary();352if (RHS.isInvalid()) {353Actions.CorrectDelayedTyposInExpr(LHS);354return ExprError();355}356ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalAndLoc,357tok::ampamp, LHS.get(), RHS.get());358if (!Op.isUsable()) {359Actions.CorrectDelayedTyposInExpr(RHS);360Actions.CorrectDelayedTyposInExpr(LHS);361return ExprError();362}363LHS = Op;364}365return LHS;366}367368/// \brief Parse a constraint-logical-or-expression.369///370/// \verbatim371/// C++2a[temp.constr.decl]p1372/// constraint-logical-or-expression:373/// constraint-logical-and-expression374/// constraint-logical-or-expression '||'375/// constraint-logical-and-expression376///377/// \endverbatim378ExprResult379Parser::ParseConstraintLogicalOrExpression(bool IsTrailingRequiresClause) {380ExprResult LHS(ParseConstraintLogicalAndExpression(IsTrailingRequiresClause));381if (!LHS.isUsable())382return ExprError();383while (Tok.is(tok::pipepipe)) {384SourceLocation LogicalOrLoc = ConsumeToken();385ExprResult RHS =386ParseConstraintLogicalAndExpression(IsTrailingRequiresClause);387if (!RHS.isUsable()) {388Actions.CorrectDelayedTyposInExpr(LHS);389return ExprError();390}391ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalOrLoc,392tok::pipepipe, LHS.get(), RHS.get());393if (!Op.isUsable()) {394Actions.CorrectDelayedTyposInExpr(RHS);395Actions.CorrectDelayedTyposInExpr(LHS);396return ExprError();397}398LHS = Op;399}400return LHS;401}402403bool Parser::isNotExpressionStart() {404tok::TokenKind K = Tok.getKind();405if (K == tok::l_brace || K == tok::r_brace ||406K == tok::kw_for || K == tok::kw_while ||407K == tok::kw_if || K == tok::kw_else ||408K == tok::kw_goto || K == tok::kw_try)409return true;410// If this is a decl-specifier, we can't be at the start of an expression.411return isKnownToBeDeclarationSpecifier();412}413414bool Parser::isFoldOperator(prec::Level Level) const {415return Level > prec::Unknown && Level != prec::Conditional &&416Level != prec::Spaceship;417}418419bool Parser::isFoldOperator(tok::TokenKind Kind) const {420return isFoldOperator(getBinOpPrecedence(Kind, GreaterThanIsOperator, true));421}422423/// Parse a binary expression that starts with \p LHS and has a424/// precedence of at least \p MinPrec.425ExprResult426Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {427prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(),428GreaterThanIsOperator,429getLangOpts().CPlusPlus11);430SourceLocation ColonLoc;431432auto SavedType = PreferredType;433while (true) {434// Every iteration may rely on a preferred type for the whole expression.435PreferredType = SavedType;436// If this token has a lower precedence than we are allowed to parse (e.g.437// because we are called recursively, or because the token is not a binop),438// then we are done!439if (NextTokPrec < MinPrec)440return LHS;441442// Consume the operator, saving the operator token for error reporting.443Token OpToken = Tok;444ConsumeToken();445446if (OpToken.is(tok::caretcaret)) {447return ExprError(Diag(Tok, diag::err_opencl_logical_exclusive_or));448}449450// If we're potentially in a template-id, we may now be able to determine451// whether we're actually in one or not.452if (OpToken.isOneOf(tok::comma, tok::greater, tok::greatergreater,453tok::greatergreatergreater) &&454checkPotentialAngleBracketDelimiter(OpToken))455return ExprError();456457// Bail out when encountering a comma followed by a token which can't458// possibly be the start of an expression. For instance:459// int f() { return 1, }460// We can't do this before consuming the comma, because461// isNotExpressionStart() looks at the token stream.462if (OpToken.is(tok::comma) && isNotExpressionStart()) {463PP.EnterToken(Tok, /*IsReinject*/true);464Tok = OpToken;465return LHS;466}467468// If the next token is an ellipsis, then this is a fold-expression. Leave469// it alone so we can handle it in the paren expression.470if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) {471// FIXME: We can't check this via lookahead before we consume the token472// because that tickles a lexer bug.473PP.EnterToken(Tok, /*IsReinject*/true);474Tok = OpToken;475return LHS;476}477478// In Objective-C++, alternative operator tokens can be used as keyword args479// in message expressions. Unconsume the token so that it can reinterpreted480// as an identifier in ParseObjCMessageExpressionBody. i.e., we support:481// [foo meth:0 and:0];482// [foo not_eq];483if (getLangOpts().ObjC && getLangOpts().CPlusPlus &&484Tok.isOneOf(tok::colon, tok::r_square) &&485OpToken.getIdentifierInfo() != nullptr) {486PP.EnterToken(Tok, /*IsReinject*/true);487Tok = OpToken;488return LHS;489}490491// Special case handling for the ternary operator.492ExprResult TernaryMiddle(true);493if (NextTokPrec == prec::Conditional) {494if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {495// Parse a braced-init-list here for error recovery purposes.496SourceLocation BraceLoc = Tok.getLocation();497TernaryMiddle = ParseBraceInitializer();498if (!TernaryMiddle.isInvalid()) {499Diag(BraceLoc, diag::err_init_list_bin_op)500<< /*RHS*/ 1 << PP.getSpelling(OpToken)501<< Actions.getExprRange(TernaryMiddle.get());502TernaryMiddle = ExprError();503}504} else if (Tok.isNot(tok::colon)) {505// Don't parse FOO:BAR as if it were a typo for FOO::BAR.506ColonProtectionRAIIObject X(*this);507508// Handle this production specially:509// logical-OR-expression '?' expression ':' conditional-expression510// In particular, the RHS of the '?' is 'expression', not511// 'logical-OR-expression' as we might expect.512TernaryMiddle = ParseExpression();513} else {514// Special case handling of "X ? Y : Z" where Y is empty:515// logical-OR-expression '?' ':' conditional-expression [GNU]516TernaryMiddle = nullptr;517Diag(Tok, diag::ext_gnu_conditional_expr);518}519520if (TernaryMiddle.isInvalid()) {521Actions.CorrectDelayedTyposInExpr(LHS);522LHS = ExprError();523TernaryMiddle = nullptr;524}525526if (!TryConsumeToken(tok::colon, ColonLoc)) {527// Otherwise, we're missing a ':'. Assume that this was a typo that528// the user forgot. If we're not in a macro expansion, we can suggest529// a fixit hint. If there were two spaces before the current token,530// suggest inserting the colon in between them, otherwise insert ": ".531SourceLocation FILoc = Tok.getLocation();532const char *FIText = ": ";533const SourceManager &SM = PP.getSourceManager();534if (FILoc.isFileID() || PP.isAtStartOfMacroExpansion(FILoc, &FILoc)) {535assert(FILoc.isFileID());536bool IsInvalid = false;537const char *SourcePtr =538SM.getCharacterData(FILoc.getLocWithOffset(-1), &IsInvalid);539if (!IsInvalid && *SourcePtr == ' ') {540SourcePtr =541SM.getCharacterData(FILoc.getLocWithOffset(-2), &IsInvalid);542if (!IsInvalid && *SourcePtr == ' ') {543FILoc = FILoc.getLocWithOffset(-1);544FIText = ":";545}546}547}548549Diag(Tok, diag::err_expected)550<< tok::colon << FixItHint::CreateInsertion(FILoc, FIText);551Diag(OpToken, diag::note_matching) << tok::question;552ColonLoc = Tok.getLocation();553}554}555556PreferredType.enterBinary(Actions, Tok.getLocation(), LHS.get(),557OpToken.getKind());558// Parse another leaf here for the RHS of the operator.559// ParseCastExpression works here because all RHS expressions in C have it560// as a prefix, at least. However, in C++, an assignment-expression could561// be a throw-expression, which is not a valid cast-expression.562// Therefore we need some special-casing here.563// Also note that the third operand of the conditional operator is564// an assignment-expression in C++, and in C++11, we can have a565// braced-init-list on the RHS of an assignment. For better diagnostics,566// parse as if we were allowed braced-init-lists everywhere, and check that567// they only appear on the RHS of assignments later.568ExprResult RHS;569bool RHSIsInitList = false;570if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {571RHS = ParseBraceInitializer();572RHSIsInitList = true;573} else if (getLangOpts().CPlusPlus && NextTokPrec <= prec::Conditional)574RHS = ParseAssignmentExpression();575else576RHS = ParseCastExpression(AnyCastExpr);577578if (RHS.isInvalid()) {579// FIXME: Errors generated by the delayed typo correction should be580// printed before errors from parsing the RHS, not after.581Actions.CorrectDelayedTyposInExpr(LHS);582if (TernaryMiddle.isUsable())583TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);584LHS = ExprError();585}586587// Remember the precedence of this operator and get the precedence of the588// operator immediately to the right of the RHS.589prec::Level ThisPrec = NextTokPrec;590NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,591getLangOpts().CPlusPlus11);592593// Assignment and conditional expressions are right-associative.594bool isRightAssoc = ThisPrec == prec::Conditional ||595ThisPrec == prec::Assignment;596597// Get the precedence of the operator to the right of the RHS. If it binds598// more tightly with RHS than we do, evaluate it completely first.599if (ThisPrec < NextTokPrec ||600(ThisPrec == NextTokPrec && isRightAssoc)) {601if (!RHS.isInvalid() && RHSIsInitList) {602Diag(Tok, diag::err_init_list_bin_op)603<< /*LHS*/0 << PP.getSpelling(Tok) << Actions.getExprRange(RHS.get());604RHS = ExprError();605}606// If this is left-associative, only parse things on the RHS that bind607// more tightly than the current operator. If it is left-associative, it608// is okay, to bind exactly as tightly. For example, compile A=B=C=D as609// A=(B=(C=D)), where each paren is a level of recursion here.610// The function takes ownership of the RHS.611RHS = ParseRHSOfBinaryExpression(RHS,612static_cast<prec::Level>(ThisPrec + !isRightAssoc));613RHSIsInitList = false;614615if (RHS.isInvalid()) {616// FIXME: Errors generated by the delayed typo correction should be617// printed before errors from ParseRHSOfBinaryExpression, not after.618Actions.CorrectDelayedTyposInExpr(LHS);619if (TernaryMiddle.isUsable())620TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);621LHS = ExprError();622}623624NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,625getLangOpts().CPlusPlus11);626}627628if (!RHS.isInvalid() && RHSIsInitList) {629if (ThisPrec == prec::Assignment) {630Diag(OpToken, diag::warn_cxx98_compat_generalized_initializer_lists)631<< Actions.getExprRange(RHS.get());632} else if (ColonLoc.isValid()) {633Diag(ColonLoc, diag::err_init_list_bin_op)634<< /*RHS*/1 << ":"635<< Actions.getExprRange(RHS.get());636LHS = ExprError();637} else {638Diag(OpToken, diag::err_init_list_bin_op)639<< /*RHS*/1 << PP.getSpelling(OpToken)640<< Actions.getExprRange(RHS.get());641LHS = ExprError();642}643}644645ExprResult OrigLHS = LHS;646if (!LHS.isInvalid()) {647// Combine the LHS and RHS into the LHS (e.g. build AST).648if (TernaryMiddle.isInvalid()) {649// If we're using '>>' as an operator within a template650// argument list (in C++98), suggest the addition of651// parentheses so that the code remains well-formed in C++0x.652if (!GreaterThanIsOperator && OpToken.is(tok::greatergreater))653SuggestParentheses(OpToken.getLocation(),654diag::warn_cxx11_right_shift_in_template_arg,655SourceRange(Actions.getExprRange(LHS.get()).getBegin(),656Actions.getExprRange(RHS.get()).getEnd()));657658ExprResult BinOp =659Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),660OpToken.getKind(), LHS.get(), RHS.get());661if (BinOp.isInvalid())662BinOp = Actions.CreateRecoveryExpr(LHS.get()->getBeginLoc(),663RHS.get()->getEndLoc(),664{LHS.get(), RHS.get()});665666LHS = BinOp;667} else {668ExprResult CondOp = Actions.ActOnConditionalOp(669OpToken.getLocation(), ColonLoc, LHS.get(), TernaryMiddle.get(),670RHS.get());671if (CondOp.isInvalid()) {672std::vector<clang::Expr *> Args;673// TernaryMiddle can be null for the GNU conditional expr extension.674if (TernaryMiddle.get())675Args = {LHS.get(), TernaryMiddle.get(), RHS.get()};676else677Args = {LHS.get(), RHS.get()};678CondOp = Actions.CreateRecoveryExpr(LHS.get()->getBeginLoc(),679RHS.get()->getEndLoc(), Args);680}681682LHS = CondOp;683}684// In this case, ActOnBinOp or ActOnConditionalOp performed the685// CorrectDelayedTyposInExpr check.686if (!getLangOpts().CPlusPlus)687continue;688}689690// Ensure potential typos aren't left undiagnosed.691if (LHS.isInvalid()) {692Actions.CorrectDelayedTyposInExpr(OrigLHS);693Actions.CorrectDelayedTyposInExpr(TernaryMiddle);694Actions.CorrectDelayedTyposInExpr(RHS);695}696}697}698699/// Parse a cast-expression, unary-expression or primary-expression, based700/// on \p ExprType.701///702/// \p isAddressOfOperand exists because an id-expression that is the703/// operand of address-of gets special treatment due to member pointers.704///705ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,706bool isAddressOfOperand,707TypeCastState isTypeCast,708bool isVectorLiteral,709bool *NotPrimaryExpression) {710bool NotCastExpr;711ExprResult Res = ParseCastExpression(ParseKind,712isAddressOfOperand,713NotCastExpr,714isTypeCast,715isVectorLiteral,716NotPrimaryExpression);717if (NotCastExpr)718Diag(Tok, diag::err_expected_expression);719return Res;720}721722namespace {723class CastExpressionIdValidator final : public CorrectionCandidateCallback {724public:725CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes)726: NextToken(Next), AllowNonTypes(AllowNonTypes) {727WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes;728}729730bool ValidateCandidate(const TypoCorrection &candidate) override {731NamedDecl *ND = candidate.getCorrectionDecl();732if (!ND)733return candidate.isKeyword();734735if (isa<TypeDecl>(ND))736return WantTypeSpecifiers;737738if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate))739return false;740741if (!NextToken.isOneOf(tok::equal, tok::arrow, tok::period))742return true;743744for (auto *C : candidate) {745NamedDecl *ND = C->getUnderlyingDecl();746if (isa<ValueDecl>(ND) && !isa<FunctionDecl>(ND))747return true;748}749return false;750}751752std::unique_ptr<CorrectionCandidateCallback> clone() override {753return std::make_unique<CastExpressionIdValidator>(*this);754}755756private:757Token NextToken;758bool AllowNonTypes;759};760}761762bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II,763tok::TokenKind *Kind) {764if (RevertibleTypeTraits.empty()) {765// Revertible type trait is a feature for backwards compatibility with older766// standard libraries that declare their own structs with the same name as767// the builtins listed below. New builtins should NOT be added to this list.768#define RTT_JOIN(X, Y) X##Y769#define REVERTIBLE_TYPE_TRAIT(Name) \770RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] = RTT_JOIN(tok::kw_, Name)771772REVERTIBLE_TYPE_TRAIT(__is_abstract);773REVERTIBLE_TYPE_TRAIT(__is_aggregate);774REVERTIBLE_TYPE_TRAIT(__is_arithmetic);775REVERTIBLE_TYPE_TRAIT(__is_array);776REVERTIBLE_TYPE_TRAIT(__is_assignable);777REVERTIBLE_TYPE_TRAIT(__is_base_of);778REVERTIBLE_TYPE_TRAIT(__is_bounded_array);779REVERTIBLE_TYPE_TRAIT(__is_class);780REVERTIBLE_TYPE_TRAIT(__is_complete_type);781REVERTIBLE_TYPE_TRAIT(__is_compound);782REVERTIBLE_TYPE_TRAIT(__is_const);783REVERTIBLE_TYPE_TRAIT(__is_constructible);784REVERTIBLE_TYPE_TRAIT(__is_convertible);785REVERTIBLE_TYPE_TRAIT(__is_convertible_to);786REVERTIBLE_TYPE_TRAIT(__is_destructible);787REVERTIBLE_TYPE_TRAIT(__is_empty);788REVERTIBLE_TYPE_TRAIT(__is_enum);789REVERTIBLE_TYPE_TRAIT(__is_floating_point);790REVERTIBLE_TYPE_TRAIT(__is_final);791REVERTIBLE_TYPE_TRAIT(__is_function);792REVERTIBLE_TYPE_TRAIT(__is_fundamental);793REVERTIBLE_TYPE_TRAIT(__is_integral);794REVERTIBLE_TYPE_TRAIT(__is_interface_class);795REVERTIBLE_TYPE_TRAIT(__is_literal);796REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);797REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);798REVERTIBLE_TYPE_TRAIT(__is_member_function_pointer);799REVERTIBLE_TYPE_TRAIT(__is_member_object_pointer);800REVERTIBLE_TYPE_TRAIT(__is_member_pointer);801REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable);802REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible);803REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible);804REVERTIBLE_TYPE_TRAIT(__is_nullptr);805REVERTIBLE_TYPE_TRAIT(__is_object);806REVERTIBLE_TYPE_TRAIT(__is_pod);807REVERTIBLE_TYPE_TRAIT(__is_pointer);808REVERTIBLE_TYPE_TRAIT(__is_polymorphic);809REVERTIBLE_TYPE_TRAIT(__is_reference);810REVERTIBLE_TYPE_TRAIT(__is_referenceable);811REVERTIBLE_TYPE_TRAIT(__is_rvalue_expr);812REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference);813REVERTIBLE_TYPE_TRAIT(__is_same);814REVERTIBLE_TYPE_TRAIT(__is_scalar);815REVERTIBLE_TYPE_TRAIT(__is_scoped_enum);816REVERTIBLE_TYPE_TRAIT(__is_sealed);817REVERTIBLE_TYPE_TRAIT(__is_signed);818REVERTIBLE_TYPE_TRAIT(__is_standard_layout);819REVERTIBLE_TYPE_TRAIT(__is_trivial);820REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable);821REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible);822REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable);823REVERTIBLE_TYPE_TRAIT(__is_unbounded_array);824REVERTIBLE_TYPE_TRAIT(__is_union);825REVERTIBLE_TYPE_TRAIT(__is_unsigned);826REVERTIBLE_TYPE_TRAIT(__is_void);827REVERTIBLE_TYPE_TRAIT(__is_volatile);828REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary);829#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \830REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait));831#include "clang/Basic/TransformTypeTraits.def"832#undef REVERTIBLE_TYPE_TRAIT833#undef RTT_JOIN834}835llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known =836RevertibleTypeTraits.find(II);837if (Known != RevertibleTypeTraits.end()) {838if (Kind)839*Kind = Known->second;840return true;841}842return false;843}844845ExprResult Parser::ParseBuiltinPtrauthTypeDiscriminator() {846SourceLocation Loc = ConsumeToken();847848BalancedDelimiterTracker T(*this, tok::l_paren);849if (T.expectAndConsume())850return ExprError();851852TypeResult Ty = ParseTypeName();853if (Ty.isInvalid()) {854SkipUntil(tok::r_paren, StopAtSemi);855return ExprError();856}857858SourceLocation EndLoc = Tok.getLocation();859T.consumeClose();860return Actions.ActOnUnaryExprOrTypeTraitExpr(861Loc, UETT_PtrAuthTypeDiscriminator,862/*isType=*/true, Ty.get().getAsOpaquePtr(), SourceRange(Loc, EndLoc));863}864865/// Parse a cast-expression, or, if \pisUnaryExpression is true, parse866/// a unary-expression.867///868/// \p isAddressOfOperand exists because an id-expression that is the operand869/// of address-of gets special treatment due to member pointers. NotCastExpr870/// is set to true if the token is not the start of a cast-expression, and no871/// diagnostic is emitted in this case and no tokens are consumed.872///873/// \verbatim874/// cast-expression: [C99 6.5.4]875/// unary-expression876/// '(' type-name ')' cast-expression877///878/// unary-expression: [C99 6.5.3]879/// postfix-expression880/// '++' unary-expression881/// '--' unary-expression882/// [Coro] 'co_await' cast-expression883/// unary-operator cast-expression884/// 'sizeof' unary-expression885/// 'sizeof' '(' type-name ')'886/// [C++11] 'sizeof' '...' '(' identifier ')'887/// [GNU] '__alignof' unary-expression888/// [GNU] '__alignof' '(' type-name ')'889/// [C11] '_Alignof' '(' type-name ')'890/// [C++11] 'alignof' '(' type-id ')'891/// [GNU] '&&' identifier892/// [C++11] 'noexcept' '(' expression ')' [C++11 5.3.7]893/// [C++] new-expression894/// [C++] delete-expression895///896/// unary-operator: one of897/// '&' '*' '+' '-' '~' '!'898/// [GNU] '__extension__' '__real' '__imag'899///900/// primary-expression: [C99 6.5.1]901/// [C99] identifier902/// [C++] id-expression903/// constant904/// string-literal905/// [C++] boolean-literal [C++ 2.13.5]906/// [C++11] 'nullptr' [C++11 2.14.7]907/// [C++11] user-defined-literal908/// '(' expression ')'909/// [C11] generic-selection910/// [C++2a] requires-expression911/// '__func__' [C99 6.4.2.2]912/// [GNU] '__FUNCTION__'913/// [MS] '__FUNCDNAME__'914/// [MS] 'L__FUNCTION__'915/// [MS] '__FUNCSIG__'916/// [MS] 'L__FUNCSIG__'917/// [GNU] '__PRETTY_FUNCTION__'918/// [GNU] '(' compound-statement ')'919/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'920/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'921/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','922/// assign-expr ')'923/// [GNU] '__builtin_FILE' '(' ')'924/// [CLANG] '__builtin_FILE_NAME' '(' ')'925/// [GNU] '__builtin_FUNCTION' '(' ')'926/// [MS] '__builtin_FUNCSIG' '(' ')'927/// [GNU] '__builtin_LINE' '(' ')'928/// [CLANG] '__builtin_COLUMN' '(' ')'929/// [GNU] '__builtin_source_location' '(' ')'930/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'931/// [GNU] '__null'932/// [OBJC] '[' objc-message-expr ']'933/// [OBJC] '\@selector' '(' objc-selector-arg ')'934/// [OBJC] '\@protocol' '(' identifier ')'935/// [OBJC] '\@encode' '(' type-name ')'936/// [OBJC] objc-string-literal937/// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]938/// [C++11] simple-type-specifier braced-init-list [C++11 5.2.3]939/// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3]940/// [C++11] typename-specifier braced-init-list [C++11 5.2.3]941/// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]942/// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]943/// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]944/// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]945/// [C++] 'typeid' '(' expression ')' [C++ 5.2p1]946/// [C++] 'typeid' '(' type-id ')' [C++ 5.2p1]947/// [C++] 'this' [C++ 9.3.2]948/// [G++] unary-type-trait '(' type-id ')'949/// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO]950/// [EMBT] array-type-trait '(' type-id ',' integer ')'951/// [clang] '^' block-literal952///953/// constant: [C99 6.4.4]954/// integer-constant955/// floating-constant956/// enumeration-constant -> identifier957/// character-constant958///959/// id-expression: [C++ 5.1]960/// unqualified-id961/// qualified-id962///963/// unqualified-id: [C++ 5.1]964/// identifier965/// operator-function-id966/// conversion-function-id967/// '~' class-name968/// template-id969///970/// new-expression: [C++ 5.3.4]971/// '::'[opt] 'new' new-placement[opt] new-type-id972/// new-initializer[opt]973/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'974/// new-initializer[opt]975///976/// delete-expression: [C++ 5.3.5]977/// '::'[opt] 'delete' cast-expression978/// '::'[opt] 'delete' '[' ']' cast-expression979///980/// [GNU/Embarcadero] unary-type-trait:981/// '__is_arithmetic'982/// '__is_floating_point'983/// '__is_integral'984/// '__is_lvalue_expr'985/// '__is_rvalue_expr'986/// '__is_complete_type'987/// '__is_void'988/// '__is_array'989/// '__is_function'990/// '__is_reference'991/// '__is_lvalue_reference'992/// '__is_rvalue_reference'993/// '__is_fundamental'994/// '__is_object'995/// '__is_scalar'996/// '__is_compound'997/// '__is_pointer'998/// '__is_member_object_pointer'999/// '__is_member_function_pointer'1000/// '__is_member_pointer'1001/// '__is_const'1002/// '__is_volatile'1003/// '__is_trivial'1004/// '__is_standard_layout'1005/// '__is_signed'1006/// '__is_unsigned'1007///1008/// [GNU] unary-type-trait:1009/// '__has_nothrow_assign'1010/// '__has_nothrow_copy'1011/// '__has_nothrow_constructor'1012/// '__has_trivial_assign' [TODO]1013/// '__has_trivial_copy' [TODO]1014/// '__has_trivial_constructor'1015/// '__has_trivial_destructor'1016/// '__has_virtual_destructor'1017/// '__is_abstract' [TODO]1018/// '__is_class'1019/// '__is_empty' [TODO]1020/// '__is_enum'1021/// '__is_final'1022/// '__is_pod'1023/// '__is_polymorphic'1024/// '__is_sealed' [MS]1025/// '__is_trivial'1026/// '__is_union'1027/// '__has_unique_object_representations'1028///1029/// [Clang] unary-type-trait:1030/// '__is_aggregate'1031/// '__trivially_copyable'1032///1033/// binary-type-trait:1034/// [GNU] '__is_base_of'1035/// [MS] '__is_convertible_to'1036/// '__is_convertible'1037/// '__is_same'1038///1039/// [Embarcadero] array-type-trait:1040/// '__array_rank'1041/// '__array_extent'1042///1043/// [Embarcadero] expression-trait:1044/// '__is_lvalue_expr'1045/// '__is_rvalue_expr'1046/// \endverbatim1047///1048ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,1049bool isAddressOfOperand,1050bool &NotCastExpr,1051TypeCastState isTypeCast,1052bool isVectorLiteral,1053bool *NotPrimaryExpression) {1054ExprResult Res;1055tok::TokenKind SavedKind = Tok.getKind();1056auto SavedType = PreferredType;1057NotCastExpr = false;10581059// Are postfix-expression suffix operators permitted after this1060// cast-expression? If not, and we find some, we'll parse them anyway and1061// diagnose them.1062bool AllowSuffix = true;10631064// This handles all of cast-expression, unary-expression, postfix-expression,1065// and primary-expression. We handle them together like this for efficiency1066// and to simplify handling of an expression starting with a '(' token: which1067// may be one of a parenthesized expression, cast-expression, compound literal1068// expression, or statement expression.1069//1070// If the parsed tokens consist of a primary-expression, the cases below1071// break out of the switch; at the end we call ParsePostfixExpressionSuffix1072// to handle the postfix expression suffixes. Cases that cannot be followed1073// by postfix exprs should set AllowSuffix to false.1074switch (SavedKind) {1075case tok::l_paren: {1076// If this expression is limited to being a unary-expression, the paren can1077// not start a cast expression.1078ParenParseOption ParenExprType;1079switch (ParseKind) {1080case CastParseKind::UnaryExprOnly:1081assert(getLangOpts().CPlusPlus && "not possible to get here in C");1082[[fallthrough]];1083case CastParseKind::AnyCastExpr:1084ParenExprType = ParenParseOption::CastExpr;1085break;1086case CastParseKind::PrimaryExprOnly:1087ParenExprType = FoldExpr;1088break;1089}1090ParsedType CastTy;1091SourceLocation RParenLoc;1092Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,1093isTypeCast == IsTypeCast, CastTy, RParenLoc);10941095// FIXME: What should we do if a vector literal is followed by a1096// postfix-expression suffix? Usually postfix operators are permitted on1097// literals.1098if (isVectorLiteral)1099return Res;11001101switch (ParenExprType) {1102case SimpleExpr: break; // Nothing else to do.1103case CompoundStmt: break; // Nothing else to do.1104case CompoundLiteral:1105// We parsed '(' type-name ')' '{' ... '}'. If any suffixes of1106// postfix-expression exist, parse them now.1107break;1108case CastExpr:1109// We have parsed the cast-expression and no postfix-expr pieces are1110// following.1111return Res;1112case FoldExpr:1113// We only parsed a fold-expression. There might be postfix-expr pieces1114// afterwards; parse them now.1115break;1116}11171118break;1119}11201121// primary-expression1122case tok::numeric_constant:1123case tok::binary_data:1124// constant: integer-constant1125// constant: floating-constant11261127Res = Actions.ActOnNumericConstant(Tok, /*UDLScope*/getCurScope());1128ConsumeToken();1129break;11301131case tok::kw_true:1132case tok::kw_false:1133Res = ParseCXXBoolLiteral();1134break;11351136case tok::kw___objc_yes:1137case tok::kw___objc_no:1138Res = ParseObjCBoolLiteral();1139break;11401141case tok::kw_nullptr:1142if (getLangOpts().CPlusPlus)1143Diag(Tok, diag::warn_cxx98_compat_nullptr);1144else1145Diag(Tok, getLangOpts().C23 ? diag::warn_c23_compat_keyword1146: diag::ext_c_nullptr) << Tok.getName();11471148Res = Actions.ActOnCXXNullPtrLiteral(ConsumeToken());1149break;11501151case tok::annot_primary_expr:1152case tok::annot_overload_set:1153Res = getExprAnnotation(Tok);1154if (!Res.isInvalid() && Tok.getKind() == tok::annot_overload_set)1155Res = Actions.ActOnNameClassifiedAsOverloadSet(getCurScope(), Res.get());1156ConsumeAnnotationToken();1157if (!Res.isInvalid() && Tok.is(tok::less))1158checkPotentialAngleBracket(Res);1159break;11601161case tok::annot_non_type:1162case tok::annot_non_type_dependent:1163case tok::annot_non_type_undeclared: {1164CXXScopeSpec SS;1165Token Replacement;1166Res = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement);1167assert(!Res.isUnset() &&1168"should not perform typo correction on annotation token");1169break;1170}11711172case tok::annot_embed: {1173injectEmbedTokens();1174return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast,1175isVectorLiteral, NotPrimaryExpression);1176}11771178case tok::kw___super:1179case tok::kw_decltype:1180// Annotate the token and tail recurse.1181if (TryAnnotateTypeOrScopeToken())1182return ExprError();1183assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));1184return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast,1185isVectorLiteral, NotPrimaryExpression);11861187case tok::identifier:1188ParseIdentifier: { // primary-expression: identifier1189// unqualified-id: identifier1190// constant: enumeration-constant1191// Turn a potentially qualified name into a annot_typename or1192// annot_cxxscope if it would be valid. This handles things like x::y, etc.1193if (getLangOpts().CPlusPlus) {1194// Avoid the unnecessary parse-time lookup in the common case1195// where the syntax forbids a type.1196Token Next = NextToken();11971198if (Next.is(tok::ellipsis) && Tok.is(tok::identifier) &&1199GetLookAheadToken(2).is(tok::l_square)) {1200// Annotate the token and tail recurse.1201// If the token is not annotated, then it might be an expression pack1202// indexing1203if (!TryAnnotateTypeOrScopeToken() &&1204Tok.is(tok::annot_pack_indexing_type))1205return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast,1206isVectorLiteral, NotPrimaryExpression);1207}12081209// If this identifier was reverted from a token ID, and the next token1210// is a parenthesis, this is likely to be a use of a type trait. Check1211// those tokens.1212else if (Next.is(tok::l_paren) && Tok.is(tok::identifier) &&1213Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) {1214IdentifierInfo *II = Tok.getIdentifierInfo();1215tok::TokenKind Kind;1216if (isRevertibleTypeTrait(II, &Kind)) {1217Tok.setKind(Kind);1218return ParseCastExpression(ParseKind, isAddressOfOperand,1219NotCastExpr, isTypeCast,1220isVectorLiteral, NotPrimaryExpression);1221}1222}12231224else if ((!ColonIsSacred && Next.is(tok::colon)) ||1225Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren,1226tok::l_brace)) {1227// If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.1228if (TryAnnotateTypeOrScopeToken())1229return ExprError();1230if (!Tok.is(tok::identifier))1231return ParseCastExpression(ParseKind, isAddressOfOperand,1232NotCastExpr, isTypeCast,1233isVectorLiteral,1234NotPrimaryExpression);1235}1236}12371238// Consume the identifier so that we can see if it is followed by a '(' or1239// '.'.1240IdentifierInfo &II = *Tok.getIdentifierInfo();1241SourceLocation ILoc = ConsumeToken();12421243// Support 'Class.property' and 'super.property' notation.1244if (getLangOpts().ObjC && Tok.is(tok::period) &&1245(Actions.getTypeName(II, ILoc, getCurScope()) ||1246// Allow the base to be 'super' if in an objc-method.1247(&II == Ident_super && getCurScope()->isInObjcMethodScope()))) {1248ConsumeToken();12491250if (Tok.is(tok::code_completion) && &II != Ident_super) {1251cutOffParsing();1252Actions.CodeCompletion().CodeCompleteObjCClassPropertyRefExpr(1253getCurScope(), II, ILoc, ExprStatementTokLoc == ILoc);1254return ExprError();1255}1256// Allow either an identifier or the keyword 'class' (in C++).1257if (Tok.isNot(tok::identifier) &&1258!(getLangOpts().CPlusPlus && Tok.is(tok::kw_class))) {1259Diag(Tok, diag::err_expected_property_name);1260return ExprError();1261}1262IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();1263SourceLocation PropertyLoc = ConsumeToken();12641265Res = Actions.ObjC().ActOnClassPropertyRefExpr(II, PropertyName, ILoc,1266PropertyLoc);1267break;1268}12691270// In an Objective-C method, if we have "super" followed by an identifier,1271// the token sequence is ill-formed. However, if there's a ':' or ']' after1272// that identifier, this is probably a message send with a missing open1273// bracket. Treat it as such.1274if (getLangOpts().ObjC && &II == Ident_super && !InMessageExpression &&1275getCurScope()->isInObjcMethodScope() &&1276((Tok.is(tok::identifier) &&1277(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||1278Tok.is(tok::code_completion))) {1279Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, nullptr,1280nullptr);1281break;1282}12831284// If we have an Objective-C class name followed by an identifier1285// and either ':' or ']', this is an Objective-C class message1286// send that's missing the opening '['. Recovery1287// appropriately. Also take this path if we're performing code1288// completion after an Objective-C class name.1289if (getLangOpts().ObjC &&1290((Tok.is(tok::identifier) && !InMessageExpression) ||1291Tok.is(tok::code_completion))) {1292const Token& Next = NextToken();1293if (Tok.is(tok::code_completion) ||1294Next.is(tok::colon) || Next.is(tok::r_square))1295if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope()))1296if (Typ.get()->isObjCObjectOrInterfaceType()) {1297// Fake up a Declarator to use with ActOnTypeName.1298DeclSpec DS(AttrFactory);1299DS.SetRangeStart(ILoc);1300DS.SetRangeEnd(ILoc);1301const char *PrevSpec = nullptr;1302unsigned DiagID;1303DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,1304Actions.getASTContext().getPrintingPolicy());13051306Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),1307DeclaratorContext::TypeName);1308TypeResult Ty = Actions.ActOnTypeName(DeclaratorInfo);1309if (Ty.isInvalid())1310break;13111312Res = ParseObjCMessageExpressionBody(SourceLocation(),1313SourceLocation(),1314Ty.get(), nullptr);1315break;1316}1317}13181319// Make sure to pass down the right value for isAddressOfOperand.1320if (isAddressOfOperand && isPostfixExpressionSuffixStart())1321isAddressOfOperand = false;13221323// Function designators are allowed to be undeclared (C99 6.5.1p2), so we1324// need to know whether or not this identifier is a function designator or1325// not.1326UnqualifiedId Name;1327CXXScopeSpec ScopeSpec;1328SourceLocation TemplateKWLoc;1329Token Replacement;1330CastExpressionIdValidator Validator(1331/*Next=*/Tok,1332/*AllowTypes=*/isTypeCast != NotTypeCast,1333/*AllowNonTypes=*/isTypeCast != IsTypeCast);1334Validator.IsAddressOfOperand = isAddressOfOperand;1335if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) {1336Validator.WantExpressionKeywords = false;1337Validator.WantRemainingKeywords = false;1338} else {1339Validator.WantRemainingKeywords = Tok.isNot(tok::r_paren);1340}1341Name.setIdentifier(&II, ILoc);1342Res = Actions.ActOnIdExpression(1343getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren),1344isAddressOfOperand, &Validator,1345/*IsInlineAsmIdentifier=*/false,1346Tok.is(tok::r_paren) ? nullptr : &Replacement);1347if (!Res.isInvalid() && Res.isUnset()) {1348UnconsumeToken(Replacement);1349return ParseCastExpression(ParseKind, isAddressOfOperand,1350NotCastExpr, isTypeCast,1351/*isVectorLiteral=*/false,1352NotPrimaryExpression);1353}1354Res = tryParseCXXPackIndexingExpression(Res);1355if (!Res.isInvalid() && Tok.is(tok::less))1356checkPotentialAngleBracket(Res);1357break;1358}1359case tok::char_constant: // constant: character-constant1360case tok::wide_char_constant:1361case tok::utf8_char_constant:1362case tok::utf16_char_constant:1363case tok::utf32_char_constant:1364Res = Actions.ActOnCharacterConstant(Tok, /*UDLScope*/getCurScope());1365ConsumeToken();1366break;1367case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]1368case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]1369case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS]1370case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS]1371case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS]1372case tok::kw_L__FUNCSIG__: // primary-expression: L__FUNCSIG__ [MS]1373case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]1374// Function local predefined macros are represented by PredefinedExpr except1375// when Microsoft extensions are enabled and one of these macros is adjacent1376// to a string literal or another one of these macros.1377if (!(getLangOpts().MicrosoftExt &&1378tokenIsLikeStringLiteral(Tok, getLangOpts()) &&1379tokenIsLikeStringLiteral(NextToken(), getLangOpts()))) {1380Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);1381ConsumeToken();1382break;1383}1384[[fallthrough]]; // treat MS function local macros as concatenable strings1385case tok::string_literal: // primary-expression: string-literal1386case tok::wide_string_literal:1387case tok::utf8_string_literal:1388case tok::utf16_string_literal:1389case tok::utf32_string_literal:1390Res = ParseStringLiteralExpression(true);1391break;1392case tok::kw__Generic: // primary-expression: generic-selection [C11 6.5.1]1393Res = ParseGenericSelectionExpression();1394break;1395case tok::kw___builtin_available:1396Res = ParseAvailabilityCheckExpr(Tok.getLocation());1397break;1398case tok::kw___builtin_va_arg:1399case tok::kw___builtin_offsetof:1400case tok::kw___builtin_choose_expr:1401case tok::kw___builtin_astype: // primary-expression: [OCL] as_type()1402case tok::kw___builtin_convertvector:1403case tok::kw___builtin_COLUMN:1404case tok::kw___builtin_FILE:1405case tok::kw___builtin_FILE_NAME:1406case tok::kw___builtin_FUNCTION:1407case tok::kw___builtin_FUNCSIG:1408case tok::kw___builtin_LINE:1409case tok::kw___builtin_source_location:1410if (NotPrimaryExpression)1411*NotPrimaryExpression = true;1412// This parses the complete suffix; we can return early.1413return ParseBuiltinPrimaryExpression();1414case tok::kw___null:1415Res = Actions.ActOnGNUNullExpr(ConsumeToken());1416break;14171418case tok::plusplus: // unary-expression: '++' unary-expression [C99]1419case tok::minusminus: { // unary-expression: '--' unary-expression [C99]1420if (NotPrimaryExpression)1421*NotPrimaryExpression = true;1422// C++ [expr.unary] has:1423// unary-expression:1424// ++ cast-expression1425// -- cast-expression1426Token SavedTok = Tok;1427ConsumeToken();14281429PreferredType.enterUnary(Actions, Tok.getLocation(), SavedTok.getKind(),1430SavedTok.getLocation());1431// One special case is implicitly handled here: if the preceding tokens are1432// an ambiguous cast expression, such as "(T())++", then we recurse to1433// determine whether the '++' is prefix or postfix.1434Res = ParseCastExpression(getLangOpts().CPlusPlus ?1435UnaryExprOnly : AnyCastExpr,1436/*isAddressOfOperand*/false, NotCastExpr,1437NotTypeCast);1438if (NotCastExpr) {1439// If we return with NotCastExpr = true, we must not consume any tokens,1440// so put the token back where we found it.1441assert(Res.isInvalid());1442UnconsumeToken(SavedTok);1443return ExprError();1444}1445if (!Res.isInvalid()) {1446Expr *Arg = Res.get();1447Res = Actions.ActOnUnaryOp(getCurScope(), SavedTok.getLocation(),1448SavedKind, Arg);1449if (Res.isInvalid())1450Res = Actions.CreateRecoveryExpr(SavedTok.getLocation(),1451Arg->getEndLoc(), Arg);1452}1453return Res;1454}1455case tok::amp: { // unary-expression: '&' cast-expression1456if (NotPrimaryExpression)1457*NotPrimaryExpression = true;1458// Special treatment because of member pointers1459SourceLocation SavedLoc = ConsumeToken();1460PreferredType.enterUnary(Actions, Tok.getLocation(), tok::amp, SavedLoc);14611462Res = ParseCastExpression(AnyCastExpr, /*isAddressOfOperand=*/true);1463if (!Res.isInvalid()) {1464Expr *Arg = Res.get();1465Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg);1466if (Res.isInvalid())1467Res = Actions.CreateRecoveryExpr(Tok.getLocation(), Arg->getEndLoc(),1468Arg);1469}1470return Res;1471}14721473case tok::star: // unary-expression: '*' cast-expression1474case tok::plus: // unary-expression: '+' cast-expression1475case tok::minus: // unary-expression: '-' cast-expression1476case tok::tilde: // unary-expression: '~' cast-expression1477case tok::exclaim: // unary-expression: '!' cast-expression1478case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]1479case tok::kw___imag: { // unary-expression: '__imag' cast-expression [GNU]1480if (NotPrimaryExpression)1481*NotPrimaryExpression = true;1482SourceLocation SavedLoc = ConsumeToken();1483PreferredType.enterUnary(Actions, Tok.getLocation(), SavedKind, SavedLoc);1484Res = ParseCastExpression(AnyCastExpr);1485if (!Res.isInvalid()) {1486Expr *Arg = Res.get();1487Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg,1488isAddressOfOperand);1489if (Res.isInvalid())1490Res = Actions.CreateRecoveryExpr(SavedLoc, Arg->getEndLoc(), Arg);1491}1492return Res;1493}14941495case tok::kw_co_await: { // unary-expression: 'co_await' cast-expression1496if (NotPrimaryExpression)1497*NotPrimaryExpression = true;1498SourceLocation CoawaitLoc = ConsumeToken();1499Res = ParseCastExpression(AnyCastExpr);1500if (!Res.isInvalid())1501Res = Actions.ActOnCoawaitExpr(getCurScope(), CoawaitLoc, Res.get());1502return Res;1503}15041505case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]1506// __extension__ silences extension warnings in the subexpression.1507if (NotPrimaryExpression)1508*NotPrimaryExpression = true;1509ExtensionRAIIObject O(Diags); // Use RAII to do this.1510SourceLocation SavedLoc = ConsumeToken();1511Res = ParseCastExpression(AnyCastExpr);1512if (!Res.isInvalid())1513Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());1514return Res;1515}1516case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')'1517diagnoseUseOfC11Keyword(Tok);1518[[fallthrough]];1519case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')'1520case tok::kw___alignof: // unary-expression: '__alignof' unary-expression1521// unary-expression: '__alignof' '(' type-name ')'1522case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression1523// unary-expression: 'sizeof' '(' type-name ')'1524// unary-expression: '__datasizeof' unary-expression1525// unary-expression: '__datasizeof' '(' type-name ')'1526case tok::kw___datasizeof:1527case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression1528// unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'1529case tok::kw___builtin_omp_required_simd_align:1530case tok::kw___builtin_vectorelements:1531if (NotPrimaryExpression)1532*NotPrimaryExpression = true;1533AllowSuffix = false;1534Res = ParseUnaryExprOrTypeTraitExpression();1535break;1536case tok::ampamp: { // unary-expression: '&&' identifier1537if (NotPrimaryExpression)1538*NotPrimaryExpression = true;1539SourceLocation AmpAmpLoc = ConsumeToken();1540if (Tok.isNot(tok::identifier))1541return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);15421543if (getCurScope()->getFnParent() == nullptr)1544return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));15451546Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);1547LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),1548Tok.getLocation());1549Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD);1550ConsumeToken();1551AllowSuffix = false;1552break;1553}1554case tok::kw_const_cast:1555case tok::kw_dynamic_cast:1556case tok::kw_reinterpret_cast:1557case tok::kw_static_cast:1558case tok::kw_addrspace_cast:1559if (NotPrimaryExpression)1560*NotPrimaryExpression = true;1561Res = ParseCXXCasts();1562break;1563case tok::kw___builtin_bit_cast:1564if (NotPrimaryExpression)1565*NotPrimaryExpression = true;1566Res = ParseBuiltinBitCast();1567break;1568case tok::kw_typeid:1569if (NotPrimaryExpression)1570*NotPrimaryExpression = true;1571Res = ParseCXXTypeid();1572break;1573case tok::kw___uuidof:1574if (NotPrimaryExpression)1575*NotPrimaryExpression = true;1576Res = ParseCXXUuidof();1577break;1578case tok::kw_this:1579Res = ParseCXXThis();1580break;1581case tok::kw___builtin_sycl_unique_stable_name:1582Res = ParseSYCLUniqueStableNameExpression();1583break;15841585case tok::annot_typename:1586if (isStartOfObjCClassMessageMissingOpenBracket()) {1587TypeResult Type = getTypeAnnotation(Tok);15881589// Fake up a Declarator to use with ActOnTypeName.1590DeclSpec DS(AttrFactory);1591DS.SetRangeStart(Tok.getLocation());1592DS.SetRangeEnd(Tok.getLastLoc());15931594const char *PrevSpec = nullptr;1595unsigned DiagID;1596DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(),1597PrevSpec, DiagID, Type,1598Actions.getASTContext().getPrintingPolicy());15991600Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),1601DeclaratorContext::TypeName);1602TypeResult Ty = Actions.ActOnTypeName(DeclaratorInfo);1603if (Ty.isInvalid())1604break;16051606ConsumeAnnotationToken();1607Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),1608Ty.get(), nullptr);1609break;1610}1611[[fallthrough]];16121613case tok::annot_decltype:1614case tok::annot_pack_indexing_type:1615case tok::kw_char:1616case tok::kw_wchar_t:1617case tok::kw_char8_t:1618case tok::kw_char16_t:1619case tok::kw_char32_t:1620case tok::kw_bool:1621case tok::kw_short:1622case tok::kw_int:1623case tok::kw_long:1624case tok::kw___int64:1625case tok::kw___int128:1626case tok::kw__ExtInt:1627case tok::kw__BitInt:1628case tok::kw_signed:1629case tok::kw_unsigned:1630case tok::kw_half:1631case tok::kw_float:1632case tok::kw_double:1633case tok::kw___bf16:1634case tok::kw__Float16:1635case tok::kw___float128:1636case tok::kw___ibm128:1637case tok::kw_void:1638case tok::kw_auto:1639case tok::kw_typename:1640case tok::kw_typeof:1641case tok::kw___vector:1642case tok::kw__Accum:1643case tok::kw__Fract:1644case tok::kw__Sat:1645#define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:1646#include "clang/Basic/OpenCLImageTypes.def"1647{1648if (!getLangOpts().CPlusPlus) {1649Diag(Tok, diag::err_expected_expression);1650return ExprError();1651}16521653// Everything henceforth is a postfix-expression.1654if (NotPrimaryExpression)1655*NotPrimaryExpression = true;16561657if (SavedKind == tok::kw_typename) {1658// postfix-expression: typename-specifier '(' expression-list[opt] ')'1659// typename-specifier braced-init-list1660if (TryAnnotateTypeOrScopeToken())1661return ExprError();16621663if (!Tok.isSimpleTypeSpecifier(getLangOpts()))1664// We are trying to parse a simple-type-specifier but might not get such1665// a token after error recovery.1666return ExprError();1667}16681669// postfix-expression: simple-type-specifier '(' expression-list[opt] ')'1670// simple-type-specifier braced-init-list1671//1672DeclSpec DS(AttrFactory);16731674ParseCXXSimpleTypeSpecifier(DS);1675if (Tok.isNot(tok::l_paren) &&1676(!getLangOpts().CPlusPlus11 || Tok.isNot(tok::l_brace)))1677return ExprError(Diag(Tok, diag::err_expected_lparen_after_type)1678<< DS.getSourceRange());16791680if (Tok.is(tok::l_brace))1681Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);16821683Res = ParseCXXTypeConstructExpression(DS);1684break;1685}16861687case tok::annot_cxxscope: { // [C++] id-expression: qualified-id1688// If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.1689// (We can end up in this situation after tentative parsing.)1690if (TryAnnotateTypeOrScopeToken())1691return ExprError();1692if (!Tok.is(tok::annot_cxxscope))1693return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,1694isTypeCast, isVectorLiteral,1695NotPrimaryExpression);16961697Token Next = NextToken();1698if (Next.is(tok::annot_template_id)) {1699TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next);1700if (TemplateId->Kind == TNK_Type_template) {1701// We have a qualified template-id that we know refers to a1702// type, translate it into a type and continue parsing as a1703// cast expression.1704CXXScopeSpec SS;1705ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,1706/*ObjectHasErrors=*/false,1707/*EnteringContext=*/false);1708AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::Yes);1709return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,1710isTypeCast, isVectorLiteral,1711NotPrimaryExpression);1712}1713}17141715// Parse as an id-expression.1716Res = ParseCXXIdExpression(isAddressOfOperand);1717break;1718}17191720case tok::annot_template_id: { // [C++] template-id1721TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);1722if (TemplateId->Kind == TNK_Type_template) {1723// We have a template-id that we know refers to a type,1724// translate it into a type and continue parsing as a cast1725// expression.1726CXXScopeSpec SS;1727AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::Yes);1728return ParseCastExpression(ParseKind, isAddressOfOperand,1729NotCastExpr, isTypeCast, isVectorLiteral,1730NotPrimaryExpression);1731}17321733// Fall through to treat the template-id as an id-expression.1734[[fallthrough]];1735}17361737case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id1738Res = ParseCXXIdExpression(isAddressOfOperand);1739break;17401741case tok::coloncolon: {1742// ::foo::bar -> global qualified name etc. If TryAnnotateTypeOrScopeToken1743// annotates the token, tail recurse.1744if (TryAnnotateTypeOrScopeToken())1745return ExprError();1746if (!Tok.is(tok::coloncolon))1747return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast,1748isVectorLiteral, NotPrimaryExpression);17491750// ::new -> [C++] new-expression1751// ::delete -> [C++] delete-expression1752SourceLocation CCLoc = ConsumeToken();1753if (Tok.is(tok::kw_new)) {1754if (NotPrimaryExpression)1755*NotPrimaryExpression = true;1756Res = ParseCXXNewExpression(true, CCLoc);1757AllowSuffix = false;1758break;1759}1760if (Tok.is(tok::kw_delete)) {1761if (NotPrimaryExpression)1762*NotPrimaryExpression = true;1763Res = ParseCXXDeleteExpression(true, CCLoc);1764AllowSuffix = false;1765break;1766}17671768// This is not a type name or scope specifier, it is an invalid expression.1769Diag(CCLoc, diag::err_expected_expression);1770return ExprError();1771}17721773case tok::kw_new: // [C++] new-expression1774if (NotPrimaryExpression)1775*NotPrimaryExpression = true;1776Res = ParseCXXNewExpression(false, Tok.getLocation());1777AllowSuffix = false;1778break;17791780case tok::kw_delete: // [C++] delete-expression1781if (NotPrimaryExpression)1782*NotPrimaryExpression = true;1783Res = ParseCXXDeleteExpression(false, Tok.getLocation());1784AllowSuffix = false;1785break;17861787case tok::kw_requires: // [C++2a] requires-expression1788Res = ParseRequiresExpression();1789AllowSuffix = false;1790break;17911792case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')'1793if (NotPrimaryExpression)1794*NotPrimaryExpression = true;1795Diag(Tok, diag::warn_cxx98_compat_noexcept_expr);1796SourceLocation KeyLoc = ConsumeToken();1797BalancedDelimiterTracker T(*this, tok::l_paren);17981799if (T.expectAndConsume(diag::err_expected_lparen_after, "noexcept"))1800return ExprError();1801// C++11 [expr.unary.noexcept]p1:1802// The noexcept operator determines whether the evaluation of its operand,1803// which is an unevaluated operand, can throw an exception.1804EnterExpressionEvaluationContext Unevaluated(1805Actions, Sema::ExpressionEvaluationContext::Unevaluated);1806Res = ParseExpression();18071808T.consumeClose();18091810if (!Res.isInvalid())1811Res = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(), Res.get(),1812T.getCloseLocation());1813AllowSuffix = false;1814break;1815}18161817#define TYPE_TRAIT(N,Spelling,K) \1818case tok::kw_##Spelling:1819#include "clang/Basic/TokenKinds.def"1820Res = ParseTypeTrait();1821break;18221823case tok::kw___array_rank:1824case tok::kw___array_extent:1825if (NotPrimaryExpression)1826*NotPrimaryExpression = true;1827Res = ParseArrayTypeTrait();1828break;18291830case tok::kw___builtin_ptrauth_type_discriminator:1831return ParseBuiltinPtrauthTypeDiscriminator();18321833case tok::kw___is_lvalue_expr:1834case tok::kw___is_rvalue_expr:1835if (NotPrimaryExpression)1836*NotPrimaryExpression = true;1837Res = ParseExpressionTrait();1838break;18391840case tok::at: {1841if (NotPrimaryExpression)1842*NotPrimaryExpression = true;1843SourceLocation AtLoc = ConsumeToken();1844return ParseObjCAtExpression(AtLoc);1845}1846case tok::caret:1847Res = ParseBlockLiteralExpression();1848break;1849case tok::code_completion: {1850cutOffParsing();1851Actions.CodeCompletion().CodeCompleteExpression(1852getCurScope(), PreferredType.get(Tok.getLocation()));1853return ExprError();1854}1855#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:1856#include "clang/Basic/TransformTypeTraits.def"1857// HACK: libstdc++ uses some of the transform-type-traits as alias1858// templates, so we need to work around this.1859if (!NextToken().is(tok::l_paren)) {1860Tok.setKind(tok::identifier);1861Diag(Tok, diag::ext_keyword_as_ident)1862<< Tok.getIdentifierInfo()->getName() << 0;1863goto ParseIdentifier;1864}1865goto ExpectedExpression;1866case tok::l_square:1867if (getLangOpts().CPlusPlus) {1868if (getLangOpts().ObjC) {1869// C++11 lambda expressions and Objective-C message sends both start with a1870// square bracket. There are three possibilities here:1871// we have a valid lambda expression, we have an invalid lambda1872// expression, or we have something that doesn't appear to be a lambda.1873// If we're in the last case, we fall back to ParseObjCMessageExpression.1874Res = TryParseLambdaExpression();1875if (!Res.isInvalid() && !Res.get()) {1876// We assume Objective-C++ message expressions are not1877// primary-expressions.1878if (NotPrimaryExpression)1879*NotPrimaryExpression = true;1880Res = ParseObjCMessageExpression();1881}1882break;1883}1884Res = ParseLambdaExpression();1885break;1886}1887if (getLangOpts().ObjC) {1888Res = ParseObjCMessageExpression();1889break;1890}1891[[fallthrough]];1892default:1893ExpectedExpression:1894NotCastExpr = true;1895return ExprError();1896}18971898// Check to see whether Res is a function designator only. If it is and we1899// are compiling for OpenCL, we need to return an error as this implies1900// that the address of the function is being taken, which is illegal in CL.19011902if (ParseKind == PrimaryExprOnly)1903// This is strictly a primary-expression - no postfix-expr pieces should be1904// parsed.1905return Res;19061907if (!AllowSuffix) {1908// FIXME: Don't parse a primary-expression suffix if we encountered a parse1909// error already.1910if (Res.isInvalid())1911return Res;19121913switch (Tok.getKind()) {1914case tok::l_square:1915case tok::l_paren:1916case tok::plusplus:1917case tok::minusminus:1918// "expected ';'" or similar is probably the right diagnostic here. Let1919// the caller decide what to do.1920if (Tok.isAtStartOfLine())1921return Res;19221923[[fallthrough]];1924case tok::period:1925case tok::arrow:1926break;19271928default:1929return Res;1930}19311932// This was a unary-expression for which a postfix-expression suffix is1933// not permitted by the grammar (eg, a sizeof expression or1934// new-expression or similar). Diagnose but parse the suffix anyway.1935Diag(Tok.getLocation(), diag::err_postfix_after_unary_requires_parens)1936<< Tok.getKind() << Res.get()->getSourceRange()1937<< FixItHint::CreateInsertion(Res.get()->getBeginLoc(), "(")1938<< FixItHint::CreateInsertion(PP.getLocForEndOfToken(PrevTokLocation),1939")");1940}19411942// These can be followed by postfix-expr pieces.1943PreferredType = SavedType;1944Res = ParsePostfixExpressionSuffix(Res);1945if (getLangOpts().OpenCL &&1946!getActions().getOpenCLOptions().isAvailableOption(1947"__cl_clang_function_pointers", getLangOpts()))1948if (Expr *PostfixExpr = Res.get()) {1949QualType Ty = PostfixExpr->getType();1950if (!Ty.isNull() && Ty->isFunctionType()) {1951Diag(PostfixExpr->getExprLoc(),1952diag::err_opencl_taking_function_address_parser);1953return ExprError();1954}1955}19561957return Res;1958}19591960/// Once the leading part of a postfix-expression is parsed, this1961/// method parses any suffixes that apply.1962///1963/// \verbatim1964/// postfix-expression: [C99 6.5.2]1965/// primary-expression1966/// postfix-expression '[' expression ']'1967/// postfix-expression '[' braced-init-list ']'1968/// postfix-expression '[' expression-list [opt] ']' [C++23 12.4.5]1969/// postfix-expression '(' argument-expression-list[opt] ')'1970/// postfix-expression '.' identifier1971/// postfix-expression '->' identifier1972/// postfix-expression '++'1973/// postfix-expression '--'1974/// '(' type-name ')' '{' initializer-list '}'1975/// '(' type-name ')' '{' initializer-list ',' '}'1976///1977/// argument-expression-list: [C99 6.5.2]1978/// argument-expression ...[opt]1979/// argument-expression-list ',' assignment-expression ...[opt]1980/// \endverbatim1981ExprResult1982Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {1983// Now that the primary-expression piece of the postfix-expression has been1984// parsed, see if there are any postfix-expression pieces here.1985SourceLocation Loc;1986auto SavedType = PreferredType;1987while (true) {1988// Each iteration relies on preferred type for the whole expression.1989PreferredType = SavedType;1990switch (Tok.getKind()) {1991case tok::code_completion:1992if (InMessageExpression)1993return LHS;19941995cutOffParsing();1996Actions.CodeCompletion().CodeCompletePostfixExpression(1997getCurScope(), LHS, PreferredType.get(Tok.getLocation()));1998return ExprError();19992000case tok::identifier:2001// If we see identifier: after an expression, and we're not already in a2002// message send, then this is probably a message send with a missing2003// opening bracket '['.2004if (getLangOpts().ObjC && !InMessageExpression &&2005(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {2006LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),2007nullptr, LHS.get());2008break;2009}2010// Fall through; this isn't a message send.2011[[fallthrough]];20122013default: // Not a postfix-expression suffix.2014return LHS;2015case tok::l_square: { // postfix-expression: p-e '[' expression ']'2016// If we have a array postfix expression that starts on a new line and2017// Objective-C is enabled, it is highly likely that the user forgot a2018// semicolon after the base expression and that the array postfix-expr is2019// actually another message send. In this case, do some look-ahead to see2020// if the contents of the square brackets are obviously not a valid2021// expression and recover by pretending there is no suffix.2022if (getLangOpts().ObjC && Tok.isAtStartOfLine() &&2023isSimpleObjCMessageExpression())2024return LHS;20252026// Reject array indices starting with a lambda-expression. '[[' is2027// reserved for attributes.2028if (CheckProhibitedCXX11Attribute()) {2029(void)Actions.CorrectDelayedTyposInExpr(LHS);2030return ExprError();2031}2032BalancedDelimiterTracker T(*this, tok::l_square);2033T.consumeOpen();2034Loc = T.getOpenLocation();2035ExprResult Length, Stride;2036SourceLocation ColonLocFirst, ColonLocSecond;2037ExprVector ArgExprs;2038bool HasError = false;2039PreferredType.enterSubscript(Actions, Tok.getLocation(), LHS.get());20402041// We try to parse a list of indexes in all language mode first2042// and, in we find 0 or one index, we try to parse an OpenMP/OpenACC array2043// section. This allow us to support C++23 multi dimensional subscript and2044// OpenMP/OpenACC sections in the same language mode.2045if ((!getLangOpts().OpenMP && !AllowOpenACCArraySections) ||2046Tok.isNot(tok::colon)) {2047if (!getLangOpts().CPlusPlus23) {2048ExprResult Idx;2049if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {2050Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);2051Idx = ParseBraceInitializer();2052} else {2053Idx = ParseExpression(); // May be a comma expression2054}2055LHS = Actions.CorrectDelayedTyposInExpr(LHS);2056Idx = Actions.CorrectDelayedTyposInExpr(Idx);2057if (Idx.isInvalid()) {2058HasError = true;2059} else {2060ArgExprs.push_back(Idx.get());2061}2062} else if (Tok.isNot(tok::r_square)) {2063if (ParseExpressionList(ArgExprs)) {2064LHS = Actions.CorrectDelayedTyposInExpr(LHS);2065HasError = true;2066}2067}2068}20692070// Handle OpenACC first, since 'AllowOpenACCArraySections' is only enabled2071// when actively parsing a 'var' in a 'var-list' during clause/'cache'2072// parsing, so it is the most specific, and best allows us to handle2073// OpenACC and OpenMP at the same time.2074if (ArgExprs.size() <= 1 && AllowOpenACCArraySections) {2075ColonProtectionRAIIObject RAII(*this);2076if (Tok.is(tok::colon)) {2077// Consume ':'2078ColonLocFirst = ConsumeToken();2079if (Tok.isNot(tok::r_square))2080Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());2081}2082} else if (ArgExprs.size() <= 1 && getLangOpts().OpenMP) {2083ColonProtectionRAIIObject RAII(*this);2084if (Tok.is(tok::colon)) {2085// Consume ':'2086ColonLocFirst = ConsumeToken();2087if (Tok.isNot(tok::r_square) &&2088(getLangOpts().OpenMP < 50 ||2089((Tok.isNot(tok::colon) && getLangOpts().OpenMP >= 50)))) {2090Length = ParseExpression();2091Length = Actions.CorrectDelayedTyposInExpr(Length);2092}2093}2094if (getLangOpts().OpenMP >= 50 &&2095(OMPClauseKind == llvm::omp::Clause::OMPC_to ||2096OMPClauseKind == llvm::omp::Clause::OMPC_from) &&2097Tok.is(tok::colon)) {2098// Consume ':'2099ColonLocSecond = ConsumeToken();2100if (Tok.isNot(tok::r_square)) {2101Stride = ParseExpression();2102}2103}2104}21052106SourceLocation RLoc = Tok.getLocation();2107LHS = Actions.CorrectDelayedTyposInExpr(LHS);21082109if (!LHS.isInvalid() && !HasError && !Length.isInvalid() &&2110!Stride.isInvalid() && Tok.is(tok::r_square)) {2111if (ColonLocFirst.isValid() || ColonLocSecond.isValid()) {2112// Like above, AllowOpenACCArraySections is 'more specific' and only2113// enabled when actively parsing a 'var' in a 'var-list' during2114// clause/'cache' construct parsing, so it is more specific. So we2115// should do it first, so that the correct node gets created.2116if (AllowOpenACCArraySections) {2117assert(!Stride.isUsable() && !ColonLocSecond.isValid() &&2118"Stride/second colon not allowed for OpenACC");2119LHS = Actions.OpenACC().ActOnArraySectionExpr(2120LHS.get(), Loc, ArgExprs.empty() ? nullptr : ArgExprs[0],2121ColonLocFirst, Length.get(), RLoc);2122} else {2123LHS = Actions.OpenMP().ActOnOMPArraySectionExpr(2124LHS.get(), Loc, ArgExprs.empty() ? nullptr : ArgExprs[0],2125ColonLocFirst, ColonLocSecond, Length.get(), Stride.get(),2126RLoc);2127}2128} else {2129LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc,2130ArgExprs, RLoc);2131}2132} else {2133LHS = ExprError();2134}21352136// Match the ']'.2137T.consumeClose();2138break;2139}21402141case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'2142case tok::lesslessless: { // p-e: p-e '<<<' argument-expression-list '>>>'2143// '(' argument-expression-list[opt] ')'2144tok::TokenKind OpKind = Tok.getKind();2145InMessageExpressionRAIIObject InMessage(*this, false);21462147Expr *ExecConfig = nullptr;21482149BalancedDelimiterTracker PT(*this, tok::l_paren);21502151if (OpKind == tok::lesslessless) {2152ExprVector ExecConfigExprs;2153SourceLocation OpenLoc = ConsumeToken();21542155if (ParseSimpleExpressionList(ExecConfigExprs)) {2156(void)Actions.CorrectDelayedTyposInExpr(LHS);2157LHS = ExprError();2158}21592160SourceLocation CloseLoc;2161if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) {2162} else if (LHS.isInvalid()) {2163SkipUntil(tok::greatergreatergreater, StopAtSemi);2164} else {2165// There was an error closing the brackets2166Diag(Tok, diag::err_expected) << tok::greatergreatergreater;2167Diag(OpenLoc, diag::note_matching) << tok::lesslessless;2168SkipUntil(tok::greatergreatergreater, StopAtSemi);2169LHS = ExprError();2170}21712172if (!LHS.isInvalid()) {2173if (ExpectAndConsume(tok::l_paren))2174LHS = ExprError();2175else2176Loc = PrevTokLocation;2177}21782179if (!LHS.isInvalid()) {2180ExprResult ECResult = Actions.CUDA().ActOnExecConfigExpr(2181getCurScope(), OpenLoc, ExecConfigExprs, CloseLoc);2182if (ECResult.isInvalid())2183LHS = ExprError();2184else2185ExecConfig = ECResult.get();2186}2187} else {2188PT.consumeOpen();2189Loc = PT.getOpenLocation();2190}21912192ExprVector ArgExprs;2193auto RunSignatureHelp = [&]() -> QualType {2194QualType PreferredType =2195Actions.CodeCompletion().ProduceCallSignatureHelp(2196LHS.get(), ArgExprs, PT.getOpenLocation());2197CalledSignatureHelp = true;2198return PreferredType;2199};2200if (OpKind == tok::l_paren || !LHS.isInvalid()) {2201if (Tok.isNot(tok::r_paren)) {2202if (ParseExpressionList(ArgExprs, [&] {2203PreferredType.enterFunctionArgument(Tok.getLocation(),2204RunSignatureHelp);2205})) {2206(void)Actions.CorrectDelayedTyposInExpr(LHS);2207// If we got an error when parsing expression list, we don't call2208// the CodeCompleteCall handler inside the parser. So call it here2209// to make sure we get overload suggestions even when we are in the2210// middle of a parameter.2211if (PP.isCodeCompletionReached() && !CalledSignatureHelp)2212RunSignatureHelp();2213LHS = ExprError();2214} else if (LHS.isInvalid()) {2215for (auto &E : ArgExprs)2216Actions.CorrectDelayedTyposInExpr(E);2217}2218}2219}22202221// Match the ')'.2222if (LHS.isInvalid()) {2223SkipUntil(tok::r_paren, StopAtSemi);2224} else if (Tok.isNot(tok::r_paren)) {2225bool HadDelayedTypo = false;2226if (Actions.CorrectDelayedTyposInExpr(LHS).get() != LHS.get())2227HadDelayedTypo = true;2228for (auto &E : ArgExprs)2229if (Actions.CorrectDelayedTyposInExpr(E).get() != E)2230HadDelayedTypo = true;2231// If there were delayed typos in the LHS or ArgExprs, call SkipUntil2232// instead of PT.consumeClose() to avoid emitting extra diagnostics for2233// the unmatched l_paren.2234if (HadDelayedTypo)2235SkipUntil(tok::r_paren, StopAtSemi);2236else2237PT.consumeClose();2238LHS = ExprError();2239} else {2240Expr *Fn = LHS.get();2241SourceLocation RParLoc = Tok.getLocation();2242LHS = Actions.ActOnCallExpr(getCurScope(), Fn, Loc, ArgExprs, RParLoc,2243ExecConfig);2244if (LHS.isInvalid()) {2245ArgExprs.insert(ArgExprs.begin(), Fn);2246LHS =2247Actions.CreateRecoveryExpr(Fn->getBeginLoc(), RParLoc, ArgExprs);2248}2249PT.consumeClose();2250}22512252break;2253}2254case tok::arrow:2255case tok::period: {2256// postfix-expression: p-e '->' template[opt] id-expression2257// postfix-expression: p-e '.' template[opt] id-expression2258tok::TokenKind OpKind = Tok.getKind();2259SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token.22602261CXXScopeSpec SS;2262ParsedType ObjectType;2263bool MayBePseudoDestructor = false;2264Expr* OrigLHS = !LHS.isInvalid() ? LHS.get() : nullptr;22652266PreferredType.enterMemAccess(Actions, Tok.getLocation(), OrigLHS);22672268if (getLangOpts().CPlusPlus && !LHS.isInvalid()) {2269Expr *Base = OrigLHS;2270const Type* BaseType = Base->getType().getTypePtrOrNull();2271if (BaseType && Tok.is(tok::l_paren) &&2272(BaseType->isFunctionType() ||2273BaseType->isSpecificPlaceholderType(BuiltinType::BoundMember))) {2274Diag(OpLoc, diag::err_function_is_not_record)2275<< OpKind << Base->getSourceRange()2276<< FixItHint::CreateRemoval(OpLoc);2277return ParsePostfixExpressionSuffix(Base);2278}22792280LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), Base, OpLoc,2281OpKind, ObjectType,2282MayBePseudoDestructor);2283if (LHS.isInvalid()) {2284// Clang will try to perform expression based completion as a2285// fallback, which is confusing in case of member references. So we2286// stop here without any completions.2287if (Tok.is(tok::code_completion)) {2288cutOffParsing();2289return ExprError();2290}2291break;2292}2293ParseOptionalCXXScopeSpecifier(2294SS, ObjectType, LHS.get() && LHS.get()->containsErrors(),2295/*EnteringContext=*/false, &MayBePseudoDestructor);2296if (SS.isNotEmpty())2297ObjectType = nullptr;2298}22992300if (Tok.is(tok::code_completion)) {2301tok::TokenKind CorrectedOpKind =2302OpKind == tok::arrow ? tok::period : tok::arrow;2303ExprResult CorrectedLHS(/*Invalid=*/true);2304if (getLangOpts().CPlusPlus && OrigLHS) {2305// FIXME: Creating a TentativeAnalysisScope from outside Sema is a2306// hack.2307Sema::TentativeAnalysisScope Trap(Actions);2308CorrectedLHS = Actions.ActOnStartCXXMemberReference(2309getCurScope(), OrigLHS, OpLoc, CorrectedOpKind, ObjectType,2310MayBePseudoDestructor);2311}23122313Expr *Base = LHS.get();2314Expr *CorrectedBase = CorrectedLHS.get();2315if (!CorrectedBase && !getLangOpts().CPlusPlus)2316CorrectedBase = Base;23172318// Code completion for a member access expression.2319cutOffParsing();2320Actions.CodeCompletion().CodeCompleteMemberReferenceExpr(2321getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow,2322Base && ExprStatementTokLoc == Base->getBeginLoc(),2323PreferredType.get(Tok.getLocation()));23242325return ExprError();2326}23272328if (MayBePseudoDestructor && !LHS.isInvalid()) {2329LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,2330ObjectType);2331break;2332}23332334// Either the action has told us that this cannot be a2335// pseudo-destructor expression (based on the type of base2336// expression), or we didn't see a '~' in the right place. We2337// can still parse a destructor name here, but in that case it2338// names a real destructor.2339// Allow explicit constructor calls in Microsoft mode.2340// FIXME: Add support for explicit call of template constructor.2341SourceLocation TemplateKWLoc;2342UnqualifiedId Name;2343if (getLangOpts().ObjC && OpKind == tok::period &&2344Tok.is(tok::kw_class)) {2345// Objective-C++:2346// After a '.' in a member access expression, treat the keyword2347// 'class' as if it were an identifier.2348//2349// This hack allows property access to the 'class' method because it is2350// such a common method name. For other C++ keywords that are2351// Objective-C method names, one must use the message send syntax.2352IdentifierInfo *Id = Tok.getIdentifierInfo();2353SourceLocation Loc = ConsumeToken();2354Name.setIdentifier(Id, Loc);2355} else if (ParseUnqualifiedId(2356SS, ObjectType, LHS.get() && LHS.get()->containsErrors(),2357/*EnteringContext=*/false,2358/*AllowDestructorName=*/true,2359/*AllowConstructorName=*/2360getLangOpts().MicrosoftExt && SS.isNotEmpty(),2361/*AllowDeductionGuide=*/false, &TemplateKWLoc, Name)) {2362(void)Actions.CorrectDelayedTyposInExpr(LHS);2363LHS = ExprError();2364}23652366if (!LHS.isInvalid())2367LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,2368OpKind, SS, TemplateKWLoc, Name,2369CurParsedObjCImpl ? CurParsedObjCImpl->Dcl2370: nullptr);2371if (!LHS.isInvalid()) {2372if (Tok.is(tok::less))2373checkPotentialAngleBracket(LHS);2374} else if (OrigLHS && Name.isValid()) {2375// Preserve the LHS if the RHS is an invalid member.2376LHS = Actions.CreateRecoveryExpr(OrigLHS->getBeginLoc(),2377Name.getEndLoc(), {OrigLHS});2378}2379break;2380}2381case tok::plusplus: // postfix-expression: postfix-expression '++'2382case tok::minusminus: // postfix-expression: postfix-expression '--'2383if (!LHS.isInvalid()) {2384Expr *Arg = LHS.get();2385LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(),2386Tok.getKind(), Arg);2387if (LHS.isInvalid())2388LHS = Actions.CreateRecoveryExpr(Arg->getBeginLoc(),2389Tok.getLocation(), Arg);2390}2391ConsumeToken();2392break;2393}2394}2395}23962397/// ParseExprAfterUnaryExprOrTypeTrait - We parsed a typeof/sizeof/alignof/2398/// vec_step and we are at the start of an expression or a parenthesized2399/// type-id. OpTok is the operand token (typeof/sizeof/alignof). Returns the2400/// expression (isCastExpr == false) or the type (isCastExpr == true).2401///2402/// \verbatim2403/// unary-expression: [C99 6.5.3]2404/// 'sizeof' unary-expression2405/// 'sizeof' '(' type-name ')'2406/// [Clang] '__datasizeof' unary-expression2407/// [Clang] '__datasizeof' '(' type-name ')'2408/// [GNU] '__alignof' unary-expression2409/// [GNU] '__alignof' '(' type-name ')'2410/// [C11] '_Alignof' '(' type-name ')'2411/// [C++0x] 'alignof' '(' type-id ')'2412///2413/// [GNU] typeof-specifier:2414/// typeof ( expressions )2415/// typeof ( type-name )2416/// [GNU/C++] typeof unary-expression2417/// [C23] typeof-specifier:2418/// typeof '(' typeof-specifier-argument ')'2419/// typeof_unqual '(' typeof-specifier-argument ')'2420///2421/// typeof-specifier-argument:2422/// expression2423/// type-name2424///2425/// [OpenCL 1.1 6.11.12] vec_step built-in function:2426/// vec_step ( expressions )2427/// vec_step ( type-name )2428/// \endverbatim2429ExprResult2430Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,2431bool &isCastExpr,2432ParsedType &CastTy,2433SourceRange &CastRange) {24342435assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual, tok::kw_sizeof,2436tok::kw___datasizeof, tok::kw___alignof, tok::kw_alignof,2437tok::kw__Alignof, tok::kw_vec_step,2438tok::kw___builtin_omp_required_simd_align,2439tok::kw___builtin_vectorelements) &&2440"Not a typeof/sizeof/alignof/vec_step expression!");24412442ExprResult Operand;24432444// If the operand doesn't start with an '(', it must be an expression.2445if (Tok.isNot(tok::l_paren)) {2446// If construct allows a form without parenthesis, user may forget to put2447// pathenthesis around type name.2448if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,2449tok::kw_alignof, tok::kw__Alignof)) {2450if (isTypeIdUnambiguously()) {2451DeclSpec DS(AttrFactory);2452ParseSpecifierQualifierList(DS);2453Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),2454DeclaratorContext::TypeName);2455ParseDeclarator(DeclaratorInfo);24562457SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation());2458SourceLocation RParenLoc = PP.getLocForEndOfToken(PrevTokLocation);2459if (LParenLoc.isInvalid() || RParenLoc.isInvalid()) {2460Diag(OpTok.getLocation(),2461diag::err_expected_parentheses_around_typename)2462<< OpTok.getName();2463} else {2464Diag(LParenLoc, diag::err_expected_parentheses_around_typename)2465<< OpTok.getName() << FixItHint::CreateInsertion(LParenLoc, "(")2466<< FixItHint::CreateInsertion(RParenLoc, ")");2467}2468isCastExpr = true;2469return ExprEmpty();2470}2471}24722473isCastExpr = false;2474if (OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) &&2475!getLangOpts().CPlusPlus) {2476Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo()2477<< tok::l_paren;2478return ExprError();2479}24802481Operand = ParseCastExpression(UnaryExprOnly);2482} else {2483// If it starts with a '(', we know that it is either a parenthesized2484// type-name, or it is a unary-expression that starts with a compound2485// literal, or starts with a primary-expression that is a parenthesized2486// expression.2487ParenParseOption ExprType = CastExpr;2488SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;24892490Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,2491false, CastTy, RParenLoc);2492CastRange = SourceRange(LParenLoc, RParenLoc);24932494// If ParseParenExpression parsed a '(typename)' sequence only, then this is2495// a type.2496if (ExprType == CastExpr) {2497isCastExpr = true;2498return ExprEmpty();2499}25002501if (getLangOpts().CPlusPlus ||2502!OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual)) {2503// GNU typeof in C requires the expression to be parenthesized. Not so for2504// sizeof/alignof or in C++. Therefore, the parenthesized expression is2505// the start of a unary-expression, but doesn't include any postfix2506// pieces. Parse these now if present.2507if (!Operand.isInvalid())2508Operand = ParsePostfixExpressionSuffix(Operand.get());2509}2510}25112512// If we get here, the operand to the typeof/sizeof/alignof was an expression.2513isCastExpr = false;2514return Operand;2515}25162517/// Parse a __builtin_sycl_unique_stable_name expression. Accepts a type-id as2518/// a parameter.2519ExprResult Parser::ParseSYCLUniqueStableNameExpression() {2520assert(Tok.is(tok::kw___builtin_sycl_unique_stable_name) &&2521"Not __builtin_sycl_unique_stable_name");25222523SourceLocation OpLoc = ConsumeToken();2524BalancedDelimiterTracker T(*this, tok::l_paren);25252526// __builtin_sycl_unique_stable_name expressions are always parenthesized.2527if (T.expectAndConsume(diag::err_expected_lparen_after,2528"__builtin_sycl_unique_stable_name"))2529return ExprError();25302531TypeResult Ty = ParseTypeName();25322533if (Ty.isInvalid()) {2534T.skipToEnd();2535return ExprError();2536}25372538if (T.consumeClose())2539return ExprError();25402541return Actions.SYCL().ActOnUniqueStableNameExpr(2542OpLoc, T.getOpenLocation(), T.getCloseLocation(), Ty.get());2543}25442545/// Parse a sizeof or alignof expression.2546///2547/// \verbatim2548/// unary-expression: [C99 6.5.3]2549/// 'sizeof' unary-expression2550/// 'sizeof' '(' type-name ')'2551/// [C++11] 'sizeof' '...' '(' identifier ')'2552/// [Clang] '__datasizeof' unary-expression2553/// [Clang] '__datasizeof' '(' type-name ')'2554/// [GNU] '__alignof' unary-expression2555/// [GNU] '__alignof' '(' type-name ')'2556/// [C11] '_Alignof' '(' type-name ')'2557/// [C++11] 'alignof' '(' type-id ')'2558/// \endverbatim2559ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {2560assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,2561tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step,2562tok::kw___builtin_omp_required_simd_align,2563tok::kw___builtin_vectorelements) &&2564"Not a sizeof/alignof/vec_step expression!");2565Token OpTok = Tok;2566ConsumeToken();25672568// [C++11] 'sizeof' '...' '(' identifier ')'2569if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) {2570SourceLocation EllipsisLoc = ConsumeToken();2571SourceLocation LParenLoc, RParenLoc;2572IdentifierInfo *Name = nullptr;2573SourceLocation NameLoc;2574if (Tok.is(tok::l_paren)) {2575BalancedDelimiterTracker T(*this, tok::l_paren);2576T.consumeOpen();2577LParenLoc = T.getOpenLocation();2578if (Tok.is(tok::identifier)) {2579Name = Tok.getIdentifierInfo();2580NameLoc = ConsumeToken();2581T.consumeClose();2582RParenLoc = T.getCloseLocation();2583if (RParenLoc.isInvalid())2584RParenLoc = PP.getLocForEndOfToken(NameLoc);2585} else {2586Diag(Tok, diag::err_expected_parameter_pack);2587SkipUntil(tok::r_paren, StopAtSemi);2588}2589} else if (Tok.is(tok::identifier)) {2590Name = Tok.getIdentifierInfo();2591NameLoc = ConsumeToken();2592LParenLoc = PP.getLocForEndOfToken(EllipsisLoc);2593RParenLoc = PP.getLocForEndOfToken(NameLoc);2594Diag(LParenLoc, diag::err_paren_sizeof_parameter_pack)2595<< Name2596<< FixItHint::CreateInsertion(LParenLoc, "(")2597<< FixItHint::CreateInsertion(RParenLoc, ")");2598} else {2599Diag(Tok, diag::err_sizeof_parameter_pack);2600}26012602if (!Name)2603return ExprError();26042605EnterExpressionEvaluationContext Unevaluated(2606Actions, Sema::ExpressionEvaluationContext::Unevaluated,2607Sema::ReuseLambdaContextDecl);26082609return Actions.ActOnSizeofParameterPackExpr(getCurScope(),2610OpTok.getLocation(),2611*Name, NameLoc,2612RParenLoc);2613}26142615if (getLangOpts().CPlusPlus &&2616OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))2617Diag(OpTok, diag::warn_cxx98_compat_alignof);2618else if (getLangOpts().C23 && OpTok.is(tok::kw_alignof))2619Diag(OpTok, diag::warn_c23_compat_keyword) << OpTok.getName();26202621EnterExpressionEvaluationContext Unevaluated(2622Actions, Sema::ExpressionEvaluationContext::Unevaluated,2623Sema::ReuseLambdaContextDecl);26242625bool isCastExpr;2626ParsedType CastTy;2627SourceRange CastRange;2628ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok,2629isCastExpr,2630CastTy,2631CastRange);26322633UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;2634switch (OpTok.getKind()) {2635case tok::kw_alignof:2636case tok::kw__Alignof:2637ExprKind = UETT_AlignOf;2638break;2639case tok::kw___alignof:2640ExprKind = UETT_PreferredAlignOf;2641break;2642case tok::kw_vec_step:2643ExprKind = UETT_VecStep;2644break;2645case tok::kw___builtin_omp_required_simd_align:2646ExprKind = UETT_OpenMPRequiredSimdAlign;2647break;2648case tok::kw___datasizeof:2649ExprKind = UETT_DataSizeOf;2650break;2651case tok::kw___builtin_vectorelements:2652ExprKind = UETT_VectorElements;2653break;2654default:2655break;2656}26572658if (isCastExpr)2659return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),2660ExprKind,2661/*IsType=*/true,2662CastTy.getAsOpaquePtr(),2663CastRange);26642665if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))2666Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo();26672668// If we get here, the operand to the sizeof/alignof was an expression.2669if (!Operand.isInvalid())2670Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),2671ExprKind,2672/*IsType=*/false,2673Operand.get(),2674CastRange);2675return Operand;2676}26772678/// ParseBuiltinPrimaryExpression2679///2680/// \verbatim2681/// primary-expression: [C99 6.5.1]2682/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'2683/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'2684/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','2685/// assign-expr ')'2686/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'2687/// [GNU] '__builtin_FILE' '(' ')'2688/// [CLANG] '__builtin_FILE_NAME' '(' ')'2689/// [GNU] '__builtin_FUNCTION' '(' ')'2690/// [MS] '__builtin_FUNCSIG' '(' ')'2691/// [GNU] '__builtin_LINE' '(' ')'2692/// [CLANG] '__builtin_COLUMN' '(' ')'2693/// [GNU] '__builtin_source_location' '(' ')'2694/// [OCL] '__builtin_astype' '(' assignment-expression ',' type-name ')'2695///2696/// [GNU] offsetof-member-designator:2697/// [GNU] identifier2698/// [GNU] offsetof-member-designator '.' identifier2699/// [GNU] offsetof-member-designator '[' expression ']'2700/// \endverbatim2701ExprResult Parser::ParseBuiltinPrimaryExpression() {2702ExprResult Res;2703const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();27042705tok::TokenKind T = Tok.getKind();2706SourceLocation StartLoc = ConsumeToken(); // Eat the builtin identifier.27072708// All of these start with an open paren.2709if (Tok.isNot(tok::l_paren))2710return ExprError(Diag(Tok, diag::err_expected_after) << BuiltinII2711<< tok::l_paren);27122713BalancedDelimiterTracker PT(*this, tok::l_paren);2714PT.consumeOpen();27152716// TODO: Build AST.27172718switch (T) {2719default: llvm_unreachable("Not a builtin primary expression!");2720case tok::kw___builtin_va_arg: {2721ExprResult Expr(ParseAssignmentExpression());27222723if (ExpectAndConsume(tok::comma)) {2724SkipUntil(tok::r_paren, StopAtSemi);2725Expr = ExprError();2726}27272728TypeResult Ty = ParseTypeName();27292730if (Tok.isNot(tok::r_paren)) {2731Diag(Tok, diag::err_expected) << tok::r_paren;2732Expr = ExprError();2733}27342735if (Expr.isInvalid() || Ty.isInvalid())2736Res = ExprError();2737else2738Res = Actions.ActOnVAArg(StartLoc, Expr.get(), Ty.get(), ConsumeParen());2739break;2740}2741case tok::kw___builtin_offsetof: {2742SourceLocation TypeLoc = Tok.getLocation();2743auto OOK = Sema::OffsetOfKind::OOK_Builtin;2744if (Tok.getLocation().isMacroID()) {2745StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(2746Tok.getLocation(), PP.getSourceManager(), getLangOpts());2747if (MacroName == "offsetof")2748OOK = Sema::OffsetOfKind::OOK_Macro;2749}2750TypeResult Ty;2751{2752OffsetOfStateRAIIObject InOffsetof(*this, OOK);2753Ty = ParseTypeName();2754if (Ty.isInvalid()) {2755SkipUntil(tok::r_paren, StopAtSemi);2756return ExprError();2757}2758}27592760if (ExpectAndConsume(tok::comma)) {2761SkipUntil(tok::r_paren, StopAtSemi);2762return ExprError();2763}27642765// We must have at least one identifier here.2766if (Tok.isNot(tok::identifier)) {2767Diag(Tok, diag::err_expected) << tok::identifier;2768SkipUntil(tok::r_paren, StopAtSemi);2769return ExprError();2770}27712772// Keep track of the various subcomponents we see.2773SmallVector<Sema::OffsetOfComponent, 4> Comps;27742775Comps.push_back(Sema::OffsetOfComponent());2776Comps.back().isBrackets = false;2777Comps.back().U.IdentInfo = Tok.getIdentifierInfo();2778Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();27792780// FIXME: This loop leaks the index expressions on error.2781while (true) {2782if (Tok.is(tok::period)) {2783// offsetof-member-designator: offsetof-member-designator '.' identifier2784Comps.push_back(Sema::OffsetOfComponent());2785Comps.back().isBrackets = false;2786Comps.back().LocStart = ConsumeToken();27872788if (Tok.isNot(tok::identifier)) {2789Diag(Tok, diag::err_expected) << tok::identifier;2790SkipUntil(tok::r_paren, StopAtSemi);2791return ExprError();2792}2793Comps.back().U.IdentInfo = Tok.getIdentifierInfo();2794Comps.back().LocEnd = ConsumeToken();2795} else if (Tok.is(tok::l_square)) {2796if (CheckProhibitedCXX11Attribute())2797return ExprError();27982799// offsetof-member-designator: offsetof-member-design '[' expression ']'2800Comps.push_back(Sema::OffsetOfComponent());2801Comps.back().isBrackets = true;2802BalancedDelimiterTracker ST(*this, tok::l_square);2803ST.consumeOpen();2804Comps.back().LocStart = ST.getOpenLocation();2805Res = ParseExpression();2806if (Res.isInvalid()) {2807SkipUntil(tok::r_paren, StopAtSemi);2808return Res;2809}2810Comps.back().U.E = Res.get();28112812ST.consumeClose();2813Comps.back().LocEnd = ST.getCloseLocation();2814} else {2815if (Tok.isNot(tok::r_paren)) {2816PT.consumeClose();2817Res = ExprError();2818} else if (Ty.isInvalid()) {2819Res = ExprError();2820} else {2821PT.consumeClose();2822Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc,2823Ty.get(), Comps,2824PT.getCloseLocation());2825}2826break;2827}2828}2829break;2830}2831case tok::kw___builtin_choose_expr: {2832ExprResult Cond(ParseAssignmentExpression());2833if (Cond.isInvalid()) {2834SkipUntil(tok::r_paren, StopAtSemi);2835return Cond;2836}2837if (ExpectAndConsume(tok::comma)) {2838SkipUntil(tok::r_paren, StopAtSemi);2839return ExprError();2840}28412842ExprResult Expr1(ParseAssignmentExpression());2843if (Expr1.isInvalid()) {2844SkipUntil(tok::r_paren, StopAtSemi);2845return Expr1;2846}2847if (ExpectAndConsume(tok::comma)) {2848SkipUntil(tok::r_paren, StopAtSemi);2849return ExprError();2850}28512852ExprResult Expr2(ParseAssignmentExpression());2853if (Expr2.isInvalid()) {2854SkipUntil(tok::r_paren, StopAtSemi);2855return Expr2;2856}2857if (Tok.isNot(tok::r_paren)) {2858Diag(Tok, diag::err_expected) << tok::r_paren;2859return ExprError();2860}2861Res = Actions.ActOnChooseExpr(StartLoc, Cond.get(), Expr1.get(),2862Expr2.get(), ConsumeParen());2863break;2864}2865case tok::kw___builtin_astype: {2866// The first argument is an expression to be converted, followed by a comma.2867ExprResult Expr(ParseAssignmentExpression());2868if (Expr.isInvalid()) {2869SkipUntil(tok::r_paren, StopAtSemi);2870return ExprError();2871}28722873if (ExpectAndConsume(tok::comma)) {2874SkipUntil(tok::r_paren, StopAtSemi);2875return ExprError();2876}28772878// Second argument is the type to bitcast to.2879TypeResult DestTy = ParseTypeName();2880if (DestTy.isInvalid())2881return ExprError();28822883// Attempt to consume the r-paren.2884if (Tok.isNot(tok::r_paren)) {2885Diag(Tok, diag::err_expected) << tok::r_paren;2886SkipUntil(tok::r_paren, StopAtSemi);2887return ExprError();2888}28892890Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc,2891ConsumeParen());2892break;2893}2894case tok::kw___builtin_convertvector: {2895// The first argument is an expression to be converted, followed by a comma.2896ExprResult Expr(ParseAssignmentExpression());2897if (Expr.isInvalid()) {2898SkipUntil(tok::r_paren, StopAtSemi);2899return ExprError();2900}29012902if (ExpectAndConsume(tok::comma)) {2903SkipUntil(tok::r_paren, StopAtSemi);2904return ExprError();2905}29062907// Second argument is the type to bitcast to.2908TypeResult DestTy = ParseTypeName();2909if (DestTy.isInvalid())2910return ExprError();29112912// Attempt to consume the r-paren.2913if (Tok.isNot(tok::r_paren)) {2914Diag(Tok, diag::err_expected) << tok::r_paren;2915SkipUntil(tok::r_paren, StopAtSemi);2916return ExprError();2917}29182919Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc,2920ConsumeParen());2921break;2922}2923case tok::kw___builtin_COLUMN:2924case tok::kw___builtin_FILE:2925case tok::kw___builtin_FILE_NAME:2926case tok::kw___builtin_FUNCTION:2927case tok::kw___builtin_FUNCSIG:2928case tok::kw___builtin_LINE:2929case tok::kw___builtin_source_location: {2930// Attempt to consume the r-paren.2931if (Tok.isNot(tok::r_paren)) {2932Diag(Tok, diag::err_expected) << tok::r_paren;2933SkipUntil(tok::r_paren, StopAtSemi);2934return ExprError();2935}2936SourceLocIdentKind Kind = [&] {2937switch (T) {2938case tok::kw___builtin_FILE:2939return SourceLocIdentKind::File;2940case tok::kw___builtin_FILE_NAME:2941return SourceLocIdentKind::FileName;2942case tok::kw___builtin_FUNCTION:2943return SourceLocIdentKind::Function;2944case tok::kw___builtin_FUNCSIG:2945return SourceLocIdentKind::FuncSig;2946case tok::kw___builtin_LINE:2947return SourceLocIdentKind::Line;2948case tok::kw___builtin_COLUMN:2949return SourceLocIdentKind::Column;2950case tok::kw___builtin_source_location:2951return SourceLocIdentKind::SourceLocStruct;2952default:2953llvm_unreachable("invalid keyword");2954}2955}();2956Res = Actions.ActOnSourceLocExpr(Kind, StartLoc, ConsumeParen());2957break;2958}2959}29602961if (Res.isInvalid())2962return ExprError();29632964// These can be followed by postfix-expr pieces because they are2965// primary-expressions.2966return ParsePostfixExpressionSuffix(Res.get());2967}29682969bool Parser::tryParseOpenMPArrayShapingCastPart() {2970assert(Tok.is(tok::l_square) && "Expected open bracket");2971bool ErrorFound = true;2972TentativeParsingAction TPA(*this);2973do {2974if (Tok.isNot(tok::l_square))2975break;2976// Consume '['2977ConsumeBracket();2978// Skip inner expression.2979while (!SkipUntil(tok::r_square, tok::annot_pragma_openmp_end,2980StopAtSemi | StopBeforeMatch))2981;2982if (Tok.isNot(tok::r_square))2983break;2984// Consume ']'2985ConsumeBracket();2986// Found ')' - done.2987if (Tok.is(tok::r_paren)) {2988ErrorFound = false;2989break;2990}2991} while (Tok.isNot(tok::annot_pragma_openmp_end));2992TPA.Revert();2993return !ErrorFound;2994}29952996/// ParseParenExpression - This parses the unit that starts with a '(' token,2997/// based on what is allowed by ExprType. The actual thing parsed is returned2998/// in ExprType. If stopIfCastExpr is true, it will only return the parsed type,2999/// not the parsed cast-expression.3000///3001/// \verbatim3002/// primary-expression: [C99 6.5.1]3003/// '(' expression ')'3004/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)3005/// postfix-expression: [C99 6.5.2]3006/// '(' type-name ')' '{' initializer-list '}'3007/// '(' type-name ')' '{' initializer-list ',' '}'3008/// cast-expression: [C99 6.5.4]3009/// '(' type-name ')' cast-expression3010/// [ARC] bridged-cast-expression3011/// [ARC] bridged-cast-expression:3012/// (__bridge type-name) cast-expression3013/// (__bridge_transfer type-name) cast-expression3014/// (__bridge_retained type-name) cast-expression3015/// fold-expression: [C++1z]3016/// '(' cast-expression fold-operator '...' ')'3017/// '(' '...' fold-operator cast-expression ')'3018/// '(' cast-expression fold-operator '...'3019/// fold-operator cast-expression ')'3020/// [OPENMP] Array shaping operation3021/// '(' '[' expression ']' { '[' expression ']' } cast-expression3022/// \endverbatim3023ExprResult3024Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,3025bool isTypeCast, ParsedType &CastTy,3026SourceLocation &RParenLoc) {3027assert(Tok.is(tok::l_paren) && "Not a paren expr!");3028ColonProtectionRAIIObject ColonProtection(*this, false);3029BalancedDelimiterTracker T(*this, tok::l_paren);3030if (T.consumeOpen())3031return ExprError();3032SourceLocation OpenLoc = T.getOpenLocation();30333034PreferredType.enterParenExpr(Tok.getLocation(), OpenLoc);30353036ExprResult Result(true);3037bool isAmbiguousTypeId;3038CastTy = nullptr;30393040if (Tok.is(tok::code_completion)) {3041cutOffParsing();3042Actions.CodeCompletion().CodeCompleteExpression(3043getCurScope(), PreferredType.get(Tok.getLocation()),3044/*IsParenthesized=*/ExprType >= CompoundLiteral);3045return ExprError();3046}30473048// Diagnose use of bridge casts in non-arc mode.3049bool BridgeCast = (getLangOpts().ObjC &&3050Tok.isOneOf(tok::kw___bridge,3051tok::kw___bridge_transfer,3052tok::kw___bridge_retained,3053tok::kw___bridge_retain));3054if (BridgeCast && !getLangOpts().ObjCAutoRefCount) {3055if (!TryConsumeToken(tok::kw___bridge)) {3056StringRef BridgeCastName = Tok.getName();3057SourceLocation BridgeKeywordLoc = ConsumeToken();3058if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))3059Diag(BridgeKeywordLoc, diag::warn_arc_bridge_cast_nonarc)3060<< BridgeCastName3061<< FixItHint::CreateReplacement(BridgeKeywordLoc, "");3062}3063BridgeCast = false;3064}30653066// None of these cases should fall through with an invalid Result3067// unless they've already reported an error.3068if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {3069Diag(Tok, OpenLoc.isMacroID() ? diag::ext_gnu_statement_expr_macro3070: diag::ext_gnu_statement_expr);30713072checkCompoundToken(OpenLoc, tok::l_paren, CompoundToken::StmtExprBegin);30733074if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) {3075Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope));3076} else {3077// Find the nearest non-record decl context. Variables declared in a3078// statement expression behave as if they were declared in the enclosing3079// function, block, or other code construct.3080DeclContext *CodeDC = Actions.CurContext;3081while (CodeDC->isRecord() || isa<EnumDecl>(CodeDC)) {3082CodeDC = CodeDC->getParent();3083assert(CodeDC && !CodeDC->isFileContext() &&3084"statement expr not in code context");3085}3086Sema::ContextRAII SavedContext(Actions, CodeDC, /*NewThisContext=*/false);30873088Actions.ActOnStartStmtExpr();30893090StmtResult Stmt(ParseCompoundStatement(true));3091ExprType = CompoundStmt;30923093// If the substmt parsed correctly, build the AST node.3094if (!Stmt.isInvalid()) {3095Result = Actions.ActOnStmtExpr(getCurScope(), OpenLoc, Stmt.get(),3096Tok.getLocation());3097} else {3098Actions.ActOnStmtExprError();3099}3100}3101} else if (ExprType >= CompoundLiteral && BridgeCast) {3102tok::TokenKind tokenKind = Tok.getKind();3103SourceLocation BridgeKeywordLoc = ConsumeToken();31043105// Parse an Objective-C ARC ownership cast expression.3106ObjCBridgeCastKind Kind;3107if (tokenKind == tok::kw___bridge)3108Kind = OBC_Bridge;3109else if (tokenKind == tok::kw___bridge_transfer)3110Kind = OBC_BridgeTransfer;3111else if (tokenKind == tok::kw___bridge_retained)3112Kind = OBC_BridgeRetained;3113else {3114// As a hopefully temporary workaround, allow __bridge_retain as3115// a synonym for __bridge_retained, but only in system headers.3116assert(tokenKind == tok::kw___bridge_retain);3117Kind = OBC_BridgeRetained;3118if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))3119Diag(BridgeKeywordLoc, diag::err_arc_bridge_retain)3120<< FixItHint::CreateReplacement(BridgeKeywordLoc,3121"__bridge_retained");3122}31233124TypeResult Ty = ParseTypeName();3125T.consumeClose();3126ColonProtection.restore();3127RParenLoc = T.getCloseLocation();31283129PreferredType.enterTypeCast(Tok.getLocation(), Ty.get().get());3130ExprResult SubExpr = ParseCastExpression(AnyCastExpr);31313132if (Ty.isInvalid() || SubExpr.isInvalid())3133return ExprError();31343135return Actions.ObjC().ActOnObjCBridgedCast(getCurScope(), OpenLoc, Kind,3136BridgeKeywordLoc, Ty.get(),3137RParenLoc, SubExpr.get());3138} else if (ExprType >= CompoundLiteral &&3139isTypeIdInParens(isAmbiguousTypeId)) {31403141// Otherwise, this is a compound literal expression or cast expression.31423143// In C++, if the type-id is ambiguous we disambiguate based on context.3144// If stopIfCastExpr is true the context is a typeof/sizeof/alignof3145// in which case we should treat it as type-id.3146// if stopIfCastExpr is false, we need to determine the context past the3147// parens, so we defer to ParseCXXAmbiguousParenExpression for that.3148if (isAmbiguousTypeId && !stopIfCastExpr) {3149ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T,3150ColonProtection);3151RParenLoc = T.getCloseLocation();3152return res;3153}31543155// Parse the type declarator.3156DeclSpec DS(AttrFactory);3157ParseSpecifierQualifierList(DS);3158Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),3159DeclaratorContext::TypeName);3160ParseDeclarator(DeclaratorInfo);31613162// If our type is followed by an identifier and either ':' or ']', then3163// this is probably an Objective-C message send where the leading '[' is3164// missing. Recover as if that were the case.3165if (!DeclaratorInfo.isInvalidType() && Tok.is(tok::identifier) &&3166!InMessageExpression && getLangOpts().ObjC &&3167(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {3168TypeResult Ty;3169{3170InMessageExpressionRAIIObject InMessage(*this, false);3171Ty = Actions.ActOnTypeName(DeclaratorInfo);3172}3173Result = ParseObjCMessageExpressionBody(SourceLocation(),3174SourceLocation(),3175Ty.get(), nullptr);3176} else {3177// Match the ')'.3178T.consumeClose();3179ColonProtection.restore();3180RParenLoc = T.getCloseLocation();3181if (Tok.is(tok::l_brace)) {3182ExprType = CompoundLiteral;3183TypeResult Ty;3184{3185InMessageExpressionRAIIObject InMessage(*this, false);3186Ty = Actions.ActOnTypeName(DeclaratorInfo);3187}3188return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);3189}31903191if (Tok.is(tok::l_paren)) {3192// This could be OpenCL vector Literals3193if (getLangOpts().OpenCL)3194{3195TypeResult Ty;3196{3197InMessageExpressionRAIIObject InMessage(*this, false);3198Ty = Actions.ActOnTypeName(DeclaratorInfo);3199}3200if(Ty.isInvalid())3201{3202return ExprError();3203}3204QualType QT = Ty.get().get().getCanonicalType();3205if (QT->isVectorType())3206{3207// We parsed '(' vector-type-name ')' followed by '('32083209// Parse the cast-expression that follows it next.3210// isVectorLiteral = true will make sure we don't parse any3211// Postfix expression yet3212Result = ParseCastExpression(/*isUnaryExpression=*/AnyCastExpr,3213/*isAddressOfOperand=*/false,3214/*isTypeCast=*/IsTypeCast,3215/*isVectorLiteral=*/true);32163217if (!Result.isInvalid()) {3218Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,3219DeclaratorInfo, CastTy,3220RParenLoc, Result.get());3221}32223223// After we performed the cast we can check for postfix-expr pieces.3224if (!Result.isInvalid()) {3225Result = ParsePostfixExpressionSuffix(Result);3226}32273228return Result;3229}3230}3231}32323233if (ExprType == CastExpr) {3234// We parsed '(' type-name ')' and the thing after it wasn't a '{'.32353236if (DeclaratorInfo.isInvalidType())3237return ExprError();32383239// Note that this doesn't parse the subsequent cast-expression, it just3240// returns the parsed type to the callee.3241if (stopIfCastExpr) {3242TypeResult Ty;3243{3244InMessageExpressionRAIIObject InMessage(*this, false);3245Ty = Actions.ActOnTypeName(DeclaratorInfo);3246}3247CastTy = Ty.get();3248return ExprResult();3249}32503251// Reject the cast of super idiom in ObjC.3252if (Tok.is(tok::identifier) && getLangOpts().ObjC &&3253Tok.getIdentifierInfo() == Ident_super &&3254getCurScope()->isInObjcMethodScope() &&3255GetLookAheadToken(1).isNot(tok::period)) {3256Diag(Tok.getLocation(), diag::err_illegal_super_cast)3257<< SourceRange(OpenLoc, RParenLoc);3258return ExprError();3259}32603261PreferredType.enterTypeCast(Tok.getLocation(), CastTy.get());3262// Parse the cast-expression that follows it next.3263// TODO: For cast expression with CastTy.3264Result = ParseCastExpression(/*isUnaryExpression=*/AnyCastExpr,3265/*isAddressOfOperand=*/false,3266/*isTypeCast=*/IsTypeCast);3267if (!Result.isInvalid()) {3268Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,3269DeclaratorInfo, CastTy,3270RParenLoc, Result.get());3271}3272return Result;3273}32743275Diag(Tok, diag::err_expected_lbrace_in_compound_literal);3276return ExprError();3277}3278} else if (ExprType >= FoldExpr && Tok.is(tok::ellipsis) &&3279isFoldOperator(NextToken().getKind())) {3280ExprType = FoldExpr;3281return ParseFoldExpression(ExprResult(), T);3282} else if (isTypeCast) {3283// Parse the expression-list.3284InMessageExpressionRAIIObject InMessage(*this, false);3285ExprVector ArgExprs;32863287if (!ParseSimpleExpressionList(ArgExprs)) {3288// FIXME: If we ever support comma expressions as operands to3289// fold-expressions, we'll need to allow multiple ArgExprs here.3290if (ExprType >= FoldExpr && ArgExprs.size() == 1 &&3291isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {3292ExprType = FoldExpr;3293return ParseFoldExpression(ArgExprs[0], T);3294}32953296ExprType = SimpleExpr;3297Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),3298ArgExprs);3299}3300} else if (getLangOpts().OpenMP >= 50 && OpenMPDirectiveParsing &&3301ExprType == CastExpr && Tok.is(tok::l_square) &&3302tryParseOpenMPArrayShapingCastPart()) {3303bool ErrorFound = false;3304SmallVector<Expr *, 4> OMPDimensions;3305SmallVector<SourceRange, 4> OMPBracketsRanges;3306do {3307BalancedDelimiterTracker TS(*this, tok::l_square);3308TS.consumeOpen();3309ExprResult NumElements =3310Actions.CorrectDelayedTyposInExpr(ParseExpression());3311if (!NumElements.isUsable()) {3312ErrorFound = true;3313while (!SkipUntil(tok::r_square, tok::r_paren,3314StopAtSemi | StopBeforeMatch))3315;3316}3317TS.consumeClose();3318OMPDimensions.push_back(NumElements.get());3319OMPBracketsRanges.push_back(TS.getRange());3320} while (Tok.isNot(tok::r_paren));3321// Match the ')'.3322T.consumeClose();3323RParenLoc = T.getCloseLocation();3324Result = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());3325if (ErrorFound) {3326Result = ExprError();3327} else if (!Result.isInvalid()) {3328Result = Actions.OpenMP().ActOnOMPArrayShapingExpr(3329Result.get(), OpenLoc, RParenLoc, OMPDimensions, OMPBracketsRanges);3330}3331return Result;3332} else {3333InMessageExpressionRAIIObject InMessage(*this, false);33343335Result = ParseExpression(MaybeTypeCast);3336if (!getLangOpts().CPlusPlus && Result.isUsable()) {3337// Correct typos in non-C++ code earlier so that implicit-cast-like3338// expressions are parsed correctly.3339Result = Actions.CorrectDelayedTyposInExpr(Result);3340}33413342if (ExprType >= FoldExpr && isFoldOperator(Tok.getKind()) &&3343NextToken().is(tok::ellipsis)) {3344ExprType = FoldExpr;3345return ParseFoldExpression(Result, T);3346}3347ExprType = SimpleExpr;33483349// Don't build a paren expression unless we actually match a ')'.3350if (!Result.isInvalid() && Tok.is(tok::r_paren))3351Result =3352Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.get());3353}33543355// Match the ')'.3356if (Result.isInvalid()) {3357SkipUntil(tok::r_paren, StopAtSemi);3358return ExprError();3359}33603361T.consumeClose();3362RParenLoc = T.getCloseLocation();3363return Result;3364}33653366/// ParseCompoundLiteralExpression - We have parsed the parenthesized type-name3367/// and we are at the left brace.3368///3369/// \verbatim3370/// postfix-expression: [C99 6.5.2]3371/// '(' type-name ')' '{' initializer-list '}'3372/// '(' type-name ')' '{' initializer-list ',' '}'3373/// \endverbatim3374ExprResult3375Parser::ParseCompoundLiteralExpression(ParsedType Ty,3376SourceLocation LParenLoc,3377SourceLocation RParenLoc) {3378assert(Tok.is(tok::l_brace) && "Not a compound literal!");3379if (!getLangOpts().C99) // Compound literals don't exist in C90.3380Diag(LParenLoc, diag::ext_c99_compound_literal);3381PreferredType.enterTypeCast(Tok.getLocation(), Ty.get());3382ExprResult Result = ParseInitializer();3383if (!Result.isInvalid() && Ty)3384return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.get());3385return Result;3386}33873388/// ParseStringLiteralExpression - This handles the various token types that3389/// form string literals, and also handles string concatenation [C99 5.1.1.2,3390/// translation phase #6].3391///3392/// \verbatim3393/// primary-expression: [C99 6.5.1]3394/// string-literal3395/// \verbatim3396ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) {3397return ParseStringLiteralExpression(AllowUserDefinedLiteral,3398/*Unevaluated=*/false);3399}34003401ExprResult Parser::ParseUnevaluatedStringLiteralExpression() {3402return ParseStringLiteralExpression(/*AllowUserDefinedLiteral=*/false,3403/*Unevaluated=*/true);3404}34053406ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral,3407bool Unevaluated) {3408assert(tokenIsLikeStringLiteral(Tok, getLangOpts()) &&3409"Not a string-literal-like token!");34103411// String concatenation.3412// Note: some keywords like __FUNCTION__ are not considered to be strings3413// for concatenation purposes, unless Microsoft extensions are enabled.3414SmallVector<Token, 4> StringToks;34153416do {3417StringToks.push_back(Tok);3418ConsumeAnyToken();3419} while (tokenIsLikeStringLiteral(Tok, getLangOpts()));34203421if (Unevaluated) {3422assert(!AllowUserDefinedLiteral && "UDL are always evaluated");3423return Actions.ActOnUnevaluatedStringLiteral(StringToks);3424}34253426// Pass the set of string tokens, ready for concatenation, to the actions.3427return Actions.ActOnStringLiteral(StringToks,3428AllowUserDefinedLiteral ? getCurScope()3429: nullptr);3430}34313432/// ParseGenericSelectionExpression - Parse a C11 generic-selection3433/// [C11 6.5.1.1].3434///3435/// \verbatim3436/// generic-selection:3437/// _Generic ( assignment-expression , generic-assoc-list )3438/// generic-assoc-list:3439/// generic-association3440/// generic-assoc-list , generic-association3441/// generic-association:3442/// type-name : assignment-expression3443/// default : assignment-expression3444/// \endverbatim3445///3446/// As an extension, Clang also accepts:3447/// \verbatim3448/// generic-selection:3449/// _Generic ( type-name, generic-assoc-list )3450/// \endverbatim3451ExprResult Parser::ParseGenericSelectionExpression() {3452assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected");34533454diagnoseUseOfC11Keyword(Tok);34553456SourceLocation KeyLoc = ConsumeToken();3457BalancedDelimiterTracker T(*this, tok::l_paren);3458if (T.expectAndConsume())3459return ExprError();34603461// We either have a controlling expression or we have a controlling type, and3462// we need to figure out which it is.3463TypeResult ControllingType;3464ExprResult ControllingExpr;3465if (isTypeIdForGenericSelection()) {3466ControllingType = ParseTypeName();3467if (ControllingType.isInvalid()) {3468SkipUntil(tok::r_paren, StopAtSemi);3469return ExprError();3470}3471const auto *LIT = cast<LocInfoType>(ControllingType.get().get());3472SourceLocation Loc = LIT->getTypeSourceInfo()->getTypeLoc().getBeginLoc();3473Diag(Loc, getLangOpts().C2y ? diag::warn_c2y_compat_generic_with_type_arg3474: diag::ext_c2y_generic_with_type_arg);3475} else {3476// C11 6.5.1.1p3 "The controlling expression of a generic selection is3477// not evaluated."3478EnterExpressionEvaluationContext Unevaluated(3479Actions, Sema::ExpressionEvaluationContext::Unevaluated);3480ControllingExpr =3481Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());3482if (ControllingExpr.isInvalid()) {3483SkipUntil(tok::r_paren, StopAtSemi);3484return ExprError();3485}3486}34873488if (ExpectAndConsume(tok::comma)) {3489SkipUntil(tok::r_paren, StopAtSemi);3490return ExprError();3491}34923493SourceLocation DefaultLoc;3494SmallVector<ParsedType, 12> Types;3495ExprVector Exprs;3496do {3497ParsedType Ty;3498if (Tok.is(tok::kw_default)) {3499// C11 6.5.1.1p2 "A generic selection shall have no more than one default3500// generic association."3501if (!DefaultLoc.isInvalid()) {3502Diag(Tok, diag::err_duplicate_default_assoc);3503Diag(DefaultLoc, diag::note_previous_default_assoc);3504SkipUntil(tok::r_paren, StopAtSemi);3505return ExprError();3506}3507DefaultLoc = ConsumeToken();3508Ty = nullptr;3509} else {3510ColonProtectionRAIIObject X(*this);3511TypeResult TR = ParseTypeName(nullptr, DeclaratorContext::Association);3512if (TR.isInvalid()) {3513SkipUntil(tok::r_paren, StopAtSemi);3514return ExprError();3515}3516Ty = TR.get();3517}3518Types.push_back(Ty);35193520if (ExpectAndConsume(tok::colon)) {3521SkipUntil(tok::r_paren, StopAtSemi);3522return ExprError();3523}35243525// FIXME: These expressions should be parsed in a potentially potentially3526// evaluated context.3527ExprResult ER(3528Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));3529if (ER.isInvalid()) {3530SkipUntil(tok::r_paren, StopAtSemi);3531return ExprError();3532}3533Exprs.push_back(ER.get());3534} while (TryConsumeToken(tok::comma));35353536T.consumeClose();3537if (T.getCloseLocation().isInvalid())3538return ExprError();35393540void *ExprOrTy = ControllingExpr.isUsable()3541? ControllingExpr.get()3542: ControllingType.get().getAsOpaquePtr();35433544return Actions.ActOnGenericSelectionExpr(3545KeyLoc, DefaultLoc, T.getCloseLocation(), ControllingExpr.isUsable(),3546ExprOrTy, Types, Exprs);3547}35483549/// Parse A C++1z fold-expression after the opening paren and optional3550/// left-hand-side expression.3551///3552/// \verbatim3553/// fold-expression:3554/// ( cast-expression fold-operator ... )3555/// ( ... fold-operator cast-expression )3556/// ( cast-expression fold-operator ... fold-operator cast-expression )3557ExprResult Parser::ParseFoldExpression(ExprResult LHS,3558BalancedDelimiterTracker &T) {3559if (LHS.isInvalid()) {3560T.skipToEnd();3561return true;3562}35633564tok::TokenKind Kind = tok::unknown;3565SourceLocation FirstOpLoc;3566if (LHS.isUsable()) {3567Kind = Tok.getKind();3568assert(isFoldOperator(Kind) && "missing fold-operator");3569FirstOpLoc = ConsumeToken();3570}35713572assert(Tok.is(tok::ellipsis) && "not a fold-expression");3573SourceLocation EllipsisLoc = ConsumeToken();35743575ExprResult RHS;3576if (Tok.isNot(tok::r_paren)) {3577if (!isFoldOperator(Tok.getKind()))3578return Diag(Tok.getLocation(), diag::err_expected_fold_operator);35793580if (Kind != tok::unknown && Tok.getKind() != Kind)3581Diag(Tok.getLocation(), diag::err_fold_operator_mismatch)3582<< SourceRange(FirstOpLoc);3583Kind = Tok.getKind();3584ConsumeToken();35853586RHS = ParseExpression();3587if (RHS.isInvalid()) {3588T.skipToEnd();3589return true;3590}3591}35923593Diag(EllipsisLoc, getLangOpts().CPlusPlus173594? diag::warn_cxx14_compat_fold_expression3595: diag::ext_fold_expression);35963597T.consumeClose();3598return Actions.ActOnCXXFoldExpr(getCurScope(), T.getOpenLocation(), LHS.get(),3599Kind, EllipsisLoc, RHS.get(),3600T.getCloseLocation());3601}36023603void Parser::injectEmbedTokens() {3604EmbedAnnotationData *Data =3605reinterpret_cast<EmbedAnnotationData *>(Tok.getAnnotationValue());3606MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3607Data->BinaryData.size() * 2 - 1),3608Data->BinaryData.size() * 2 - 1);3609unsigned I = 0;3610for (auto &Byte : Data->BinaryData) {3611Toks[I].startToken();3612Toks[I].setKind(tok::binary_data);3613Toks[I].setLocation(Tok.getLocation());3614Toks[I].setLength(1);3615Toks[I].setLiteralData(&Byte);3616if (I != ((Data->BinaryData.size() - 1) * 2)) {3617Toks[I + 1].startToken();3618Toks[I + 1].setKind(tok::comma);3619Toks[I + 1].setLocation(Tok.getLocation());3620}3621I += 2;3622}3623PP.EnterTokenStream(std::move(Toks), /*DisableMacroExpansion=*/true,3624/*IsReinject=*/true);3625ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);3626}36273628/// ParseExpressionList - Used for C/C++ (argument-)expression-list.3629///3630/// \verbatim3631/// argument-expression-list:3632/// assignment-expression3633/// argument-expression-list , assignment-expression3634///3635/// [C++] expression-list:3636/// [C++] assignment-expression3637/// [C++] expression-list , assignment-expression3638///3639/// [C++0x] expression-list:3640/// [C++0x] initializer-list3641///3642/// [C++0x] initializer-list3643/// [C++0x] initializer-clause ...[opt]3644/// [C++0x] initializer-list , initializer-clause ...[opt]3645///3646/// [C++0x] initializer-clause:3647/// [C++0x] assignment-expression3648/// [C++0x] braced-init-list3649/// \endverbatim3650bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,3651llvm::function_ref<void()> ExpressionStarts,3652bool FailImmediatelyOnInvalidExpr,3653bool EarlyTypoCorrection) {3654bool SawError = false;3655while (true) {3656if (ExpressionStarts)3657ExpressionStarts();36583659ExprResult Expr;3660if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {3661Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);3662Expr = ParseBraceInitializer();3663} else3664Expr = ParseAssignmentExpression();36653666if (EarlyTypoCorrection)3667Expr = Actions.CorrectDelayedTyposInExpr(Expr);36683669if (Tok.is(tok::ellipsis))3670Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());3671else if (Tok.is(tok::code_completion)) {3672// There's nothing to suggest in here as we parsed a full expression.3673// Instead fail and propagate the error since caller might have something3674// the suggest, e.g. signature help in function call. Note that this is3675// performed before pushing the \p Expr, so that signature help can report3676// current argument correctly.3677SawError = true;3678cutOffParsing();3679break;3680}3681if (Expr.isInvalid()) {3682SawError = true;3683if (FailImmediatelyOnInvalidExpr)3684break;3685SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch);3686} else {3687Exprs.push_back(Expr.get());3688}36893690if (Tok.isNot(tok::comma))3691break;3692// Move to the next argument, remember where the comma was.3693Token Comma = Tok;3694ConsumeToken();3695checkPotentialAngleBracketDelimiter(Comma);3696}3697if (SawError) {3698// Ensure typos get diagnosed when errors were encountered while parsing the3699// expression list.3700for (auto &E : Exprs) {3701ExprResult Expr = Actions.CorrectDelayedTyposInExpr(E);3702if (Expr.isUsable()) E = Expr.get();3703}3704}3705return SawError;3706}37073708/// ParseSimpleExpressionList - A simple comma-separated list of expressions,3709/// used for misc language extensions.3710///3711/// \verbatim3712/// simple-expression-list:3713/// assignment-expression3714/// simple-expression-list , assignment-expression3715/// \endverbatim3716bool Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr *> &Exprs) {3717while (true) {3718ExprResult Expr = ParseAssignmentExpression();3719if (Expr.isInvalid())3720return true;37213722Exprs.push_back(Expr.get());37233724// We might be parsing the LHS of a fold-expression. If we reached the fold3725// operator, stop.3726if (Tok.isNot(tok::comma) || NextToken().is(tok::ellipsis))3727return false;37283729// Move to the next argument, remember where the comma was.3730Token Comma = Tok;3731ConsumeToken();3732checkPotentialAngleBracketDelimiter(Comma);3733}3734}37353736/// ParseBlockId - Parse a block-id, which roughly looks like int (int x).3737///3738/// \verbatim3739/// [clang] block-id:3740/// [clang] specifier-qualifier-list block-declarator3741/// \endverbatim3742void Parser::ParseBlockId(SourceLocation CaretLoc) {3743if (Tok.is(tok::code_completion)) {3744cutOffParsing();3745Actions.CodeCompletion().CodeCompleteOrdinaryName(3746getCurScope(), SemaCodeCompletion::PCC_Type);3747return;3748}37493750// Parse the specifier-qualifier-list piece.3751DeclSpec DS(AttrFactory);3752ParseSpecifierQualifierList(DS);37533754// Parse the block-declarator.3755Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),3756DeclaratorContext::BlockLiteral);3757DeclaratorInfo.setFunctionDefinitionKind(FunctionDefinitionKind::Definition);3758ParseDeclarator(DeclaratorInfo);37593760MaybeParseGNUAttributes(DeclaratorInfo);37613762// Inform sema that we are starting a block.3763Actions.ActOnBlockArguments(CaretLoc, DeclaratorInfo, getCurScope());3764}37653766/// ParseBlockLiteralExpression - Parse a block literal, which roughly looks3767/// like ^(int x){ return x+1; }3768///3769/// \verbatim3770/// block-literal:3771/// [clang] '^' block-args[opt] compound-statement3772/// [clang] '^' block-id compound-statement3773/// [clang] block-args:3774/// [clang] '(' parameter-list ')'3775/// \endverbatim3776ExprResult Parser::ParseBlockLiteralExpression() {3777assert(Tok.is(tok::caret) && "block literal starts with ^");3778SourceLocation CaretLoc = ConsumeToken();37793780PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), CaretLoc,3781"block literal parsing");37823783// Enter a scope to hold everything within the block. This includes the3784// argument decls, decls within the compound expression, etc. This also3785// allows determining whether a variable reference inside the block is3786// within or outside of the block.3787ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |3788Scope::CompoundStmtScope | Scope::DeclScope);37893790// Inform sema that we are starting a block.3791Actions.ActOnBlockStart(CaretLoc, getCurScope());37923793// Parse the return type if present.3794DeclSpec DS(AttrFactory);3795Declarator ParamInfo(DS, ParsedAttributesView::none(),3796DeclaratorContext::BlockLiteral);3797ParamInfo.setFunctionDefinitionKind(FunctionDefinitionKind::Definition);3798// FIXME: Since the return type isn't actually parsed, it can't be used to3799// fill ParamInfo with an initial valid range, so do it manually.3800ParamInfo.SetSourceRange(SourceRange(Tok.getLocation(), Tok.getLocation()));38013802// If this block has arguments, parse them. There is no ambiguity here with3803// the expression case, because the expression case requires a parameter list.3804if (Tok.is(tok::l_paren)) {3805ParseParenDeclarator(ParamInfo);3806// Parse the pieces after the identifier as if we had "int(...)".3807// SetIdentifier sets the source range end, but in this case we're past3808// that location.3809SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();3810ParamInfo.SetIdentifier(nullptr, CaretLoc);3811ParamInfo.SetRangeEnd(Tmp);3812if (ParamInfo.isInvalidType()) {3813// If there was an error parsing the arguments, they may have3814// tried to use ^(x+y) which requires an argument list. Just3815// skip the whole block literal.3816Actions.ActOnBlockError(CaretLoc, getCurScope());3817return ExprError();3818}38193820MaybeParseGNUAttributes(ParamInfo);38213822// Inform sema that we are starting a block.3823Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());3824} else if (!Tok.is(tok::l_brace)) {3825ParseBlockId(CaretLoc);3826} else {3827// Otherwise, pretend we saw (void).3828SourceLocation NoLoc;3829ParamInfo.AddTypeInfo(3830DeclaratorChunk::getFunction(/*HasProto=*/true,3831/*IsAmbiguous=*/false,3832/*RParenLoc=*/NoLoc,3833/*ArgInfo=*/nullptr,3834/*NumParams=*/0,3835/*EllipsisLoc=*/NoLoc,3836/*RParenLoc=*/NoLoc,3837/*RefQualifierIsLvalueRef=*/true,3838/*RefQualifierLoc=*/NoLoc,3839/*MutableLoc=*/NoLoc, EST_None,3840/*ESpecRange=*/SourceRange(),3841/*Exceptions=*/nullptr,3842/*ExceptionRanges=*/nullptr,3843/*NumExceptions=*/0,3844/*NoexceptExpr=*/nullptr,3845/*ExceptionSpecTokens=*/nullptr,3846/*DeclsInPrototype=*/std::nullopt,3847CaretLoc, CaretLoc, ParamInfo),3848CaretLoc);38493850MaybeParseGNUAttributes(ParamInfo);38513852// Inform sema that we are starting a block.3853Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());3854}385538563857ExprResult Result(true);3858if (!Tok.is(tok::l_brace)) {3859// Saw something like: ^expr3860Diag(Tok, diag::err_expected_expression);3861Actions.ActOnBlockError(CaretLoc, getCurScope());3862return ExprError();3863}38643865StmtResult Stmt(ParseCompoundStatementBody());3866BlockScope.Exit();3867if (!Stmt.isInvalid())3868Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope());3869else3870Actions.ActOnBlockError(CaretLoc, getCurScope());3871return Result;3872}38733874/// ParseObjCBoolLiteral - This handles the objective-c Boolean literals.3875///3876/// '__objc_yes'3877/// '__objc_no'3878ExprResult Parser::ParseObjCBoolLiteral() {3879tok::TokenKind Kind = Tok.getKind();3880return Actions.ObjC().ActOnObjCBoolLiteral(ConsumeToken(), Kind);3881}38823883/// Validate availability spec list, emitting diagnostics if necessary. Returns3884/// true if invalid.3885static bool CheckAvailabilitySpecList(Parser &P,3886ArrayRef<AvailabilitySpec> AvailSpecs) {3887llvm::SmallSet<StringRef, 4> Platforms;3888bool HasOtherPlatformSpec = false;3889bool Valid = true;3890for (const auto &Spec : AvailSpecs) {3891if (Spec.isOtherPlatformSpec()) {3892if (HasOtherPlatformSpec) {3893P.Diag(Spec.getBeginLoc(), diag::err_availability_query_repeated_star);3894Valid = false;3895}38963897HasOtherPlatformSpec = true;3898continue;3899}39003901bool Inserted = Platforms.insert(Spec.getPlatform()).second;3902if (!Inserted) {3903// Rule out multiple version specs referring to the same platform.3904// For example, we emit an error for:3905// @available(macos 10.10, macos 10.11, *)3906StringRef Platform = Spec.getPlatform();3907P.Diag(Spec.getBeginLoc(), diag::err_availability_query_repeated_platform)3908<< Spec.getEndLoc() << Platform;3909Valid = false;3910}3911}39123913if (!HasOtherPlatformSpec) {3914SourceLocation InsertWildcardLoc = AvailSpecs.back().getEndLoc();3915P.Diag(InsertWildcardLoc, diag::err_availability_query_wildcard_required)3916<< FixItHint::CreateInsertion(InsertWildcardLoc, ", *");3917return true;3918}39193920return !Valid;3921}39223923/// Parse availability query specification.3924///3925/// availability-spec:3926/// '*'3927/// identifier version-tuple3928std::optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() {3929if (Tok.is(tok::star)) {3930return AvailabilitySpec(ConsumeToken());3931} else {3932// Parse the platform name.3933if (Tok.is(tok::code_completion)) {3934cutOffParsing();3935Actions.CodeCompletion().CodeCompleteAvailabilityPlatformName();3936return std::nullopt;3937}3938if (Tok.isNot(tok::identifier)) {3939Diag(Tok, diag::err_avail_query_expected_platform_name);3940return std::nullopt;3941}39423943IdentifierLoc *PlatformIdentifier = ParseIdentifierLoc();3944SourceRange VersionRange;3945VersionTuple Version = ParseVersionTuple(VersionRange);39463947if (Version.empty())3948return std::nullopt;39493950StringRef GivenPlatform = PlatformIdentifier->Ident->getName();3951StringRef Platform =3952AvailabilityAttr::canonicalizePlatformName(GivenPlatform);39533954if (AvailabilityAttr::getPrettyPlatformName(Platform).empty() ||3955(GivenPlatform.contains("xros") || GivenPlatform.contains("xrOS"))) {3956Diag(PlatformIdentifier->Loc,3957diag::err_avail_query_unrecognized_platform_name)3958<< GivenPlatform;3959return std::nullopt;3960}39613962return AvailabilitySpec(Version, Platform, PlatformIdentifier->Loc,3963VersionRange.getEnd());3964}3965}39663967ExprResult Parser::ParseAvailabilityCheckExpr(SourceLocation BeginLoc) {3968assert(Tok.is(tok::kw___builtin_available) ||3969Tok.isObjCAtKeyword(tok::objc_available));39703971// Eat the available or __builtin_available.3972ConsumeToken();39733974BalancedDelimiterTracker Parens(*this, tok::l_paren);3975if (Parens.expectAndConsume())3976return ExprError();39773978SmallVector<AvailabilitySpec, 4> AvailSpecs;3979bool HasError = false;3980while (true) {3981std::optional<AvailabilitySpec> Spec = ParseAvailabilitySpec();3982if (!Spec)3983HasError = true;3984else3985AvailSpecs.push_back(*Spec);39863987if (!TryConsumeToken(tok::comma))3988break;3989}39903991if (HasError) {3992SkipUntil(tok::r_paren, StopAtSemi);3993return ExprError();3994}39953996CheckAvailabilitySpecList(*this, AvailSpecs);39973998if (Parens.consumeClose())3999return ExprError();40004001return Actions.ObjC().ActOnObjCAvailabilityCheckExpr(4002AvailSpecs, BeginLoc, Parens.getCloseLocation());4003}400440054006