3478 lines · cpp
1//===--- ParseExpr.cpp - Expression Parsing -------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// Provides the Expression parsing implementation.11///12/// Expressions in C99 basically consist of a bunch of binary operators with13/// unary operators and other random stuff at the leaves.14///15/// In the C99 grammar, these unary operators bind tightest and are represented16/// as the 'cast-expression' production. Everything else is either a binary17/// operator (e.g. '/') or a ternary operator ("?:"). The unary leaves are18/// handled by ParseCastExpression, the higher level pieces are handled by19/// ParseBinaryExpression.20///21//===----------------------------------------------------------------------===//22 23#include "clang/AST/ASTContext.h"24#include "clang/AST/Availability.h"25#include "clang/AST/ExprCXX.h"26#include "clang/AST/LocInfoType.h"27#include "clang/Basic/PrettyStackTrace.h"28#include "clang/Lex/LiteralSupport.h"29#include "clang/Parse/Parser.h"30#include "clang/Parse/RAIIObjectsForParser.h"31#include "clang/Sema/DeclSpec.h"32#include "clang/Sema/EnterExpressionEvaluationContext.h"33#include "clang/Sema/ParsedTemplate.h"34#include "clang/Sema/Scope.h"35#include "clang/Sema/SemaCUDA.h"36#include "clang/Sema/SemaCodeCompletion.h"37#include "clang/Sema/SemaObjC.h"38#include "clang/Sema/SemaOpenACC.h"39#include "clang/Sema/SemaOpenMP.h"40#include "clang/Sema/SemaSYCL.h"41#include "clang/Sema/TypoCorrection.h"42#include "llvm/ADT/SmallVector.h"43#include <optional>44using namespace clang;45 46ExprResult47Parser::ParseExpression(TypoCorrectionTypeBehavior CorrectionBehavior) {48 ExprResult LHS(ParseAssignmentExpression(CorrectionBehavior));49 return ParseRHSOfBinaryExpression(LHS, prec::Comma);50}51 52ExprResult53Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {54 ExprResult LHS(ParseObjCAtExpression(AtLoc));55 return ParseRHSOfBinaryExpression(LHS, prec::Comma);56}57 58ExprResult59Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {60 ExprResult LHS(true);61 {62 // Silence extension warnings in the sub-expression63 ExtensionRAIIObject O(Diags);64 65 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);66 }67 68 if (!LHS.isInvalid())69 LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__,70 LHS.get());71 72 return ParseRHSOfBinaryExpression(LHS, prec::Comma);73}74 75ExprResult Parser::ParseAssignmentExpression(76 TypoCorrectionTypeBehavior CorrectionBehavior) {77 if (Tok.is(tok::code_completion)) {78 cutOffParsing();79 Actions.CodeCompletion().CodeCompleteExpression(80 getCurScope(), PreferredType.get(Tok.getLocation()));81 return ExprError();82 }83 84 if (Tok.is(tok::kw_throw))85 return ParseThrowExpression();86 if (Tok.is(tok::kw_co_yield))87 return ParseCoyieldExpression();88 89 ExprResult LHS =90 ParseCastExpression(CastParseKind::AnyCastExpr,91 /*isAddressOfOperand=*/false, CorrectionBehavior);92 return ParseRHSOfBinaryExpression(LHS, prec::Assignment);93}94 95ExprResult Parser::ParseConditionalExpression() {96 if (Tok.is(tok::code_completion)) {97 cutOffParsing();98 Actions.CodeCompletion().CodeCompleteExpression(99 getCurScope(), PreferredType.get(Tok.getLocation()));100 return ExprError();101 }102 103 ExprResult LHS = ParseCastExpression(104 CastParseKind::AnyCastExpr,105 /*isAddressOfOperand=*/false, TypoCorrectionTypeBehavior::AllowNonTypes);106 return ParseRHSOfBinaryExpression(LHS, prec::Conditional);107}108 109ExprResult110Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,111 SourceLocation SuperLoc,112 ParsedType ReceiverType,113 Expr *ReceiverExpr) {114 ExprResult R115 = ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,116 ReceiverType, ReceiverExpr);117 R = ParsePostfixExpressionSuffix(R);118 return ParseRHSOfBinaryExpression(R, prec::Assignment);119}120 121ExprResult Parser::ParseConstantExpressionInExprEvalContext(122 TypoCorrectionTypeBehavior CorrectionBehavior) {123 assert(Actions.ExprEvalContexts.back().Context ==124 Sema::ExpressionEvaluationContext::ConstantEvaluated &&125 "Call this function only if your ExpressionEvaluationContext is "126 "already ConstantEvaluated");127 ExprResult LHS(ParseCastExpression(CastParseKind::AnyCastExpr, false,128 CorrectionBehavior));129 ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));130 return Actions.ActOnConstantExpression(Res);131}132 133ExprResult Parser::ParseConstantExpression() {134 // C++03 [basic.def.odr]p2:135 // An expression is potentially evaluated unless it appears where an136 // integral constant expression is required (see 5.19) [...].137 // C++98 and C++11 have no such rule, but this is only a defect in C++98.138 EnterExpressionEvaluationContext ConstantEvaluated(139 Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);140 return ParseConstantExpressionInExprEvalContext(141 TypoCorrectionTypeBehavior::AllowNonTypes);142}143 144ExprResult Parser::ParseArrayBoundExpression() {145 EnterExpressionEvaluationContext ConstantEvaluated(146 Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);147 // If we parse the bound of a VLA... we parse a non-constant148 // constant-expression!149 Actions.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true;150 // For a VLA type inside an unevaluated operator like:151 //152 // sizeof(typeof(*(int (*)[N])array))153 //154 // N and array are supposed to be ODR-used.155 // Initially when encountering `array`, it is deemed unevaluated and non-ODR156 // used because that occurs before parsing the type cast. Therefore we use157 // Sema::TransformToPotentiallyEvaluated() to rebuild the expression to ensure158 // it's actually ODR-used.159 //160 // However, in other unevaluated contexts as in constraint substitution, it161 // would end up rebuilding the type twice which is unnecessary. So we push up162 // a flag to help distinguish these cases.163 for (auto Iter = Actions.ExprEvalContexts.rbegin() + 1;164 Iter != Actions.ExprEvalContexts.rend(); ++Iter) {165 if (!Iter->isUnevaluated())166 break;167 Iter->InConditionallyConstantEvaluateContext = true;168 }169 return ParseConstantExpressionInExprEvalContext(170 TypoCorrectionTypeBehavior::AllowNonTypes);171}172 173ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {174 EnterExpressionEvaluationContext ConstantEvaluated(175 Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);176 Actions.currentEvaluationContext().IsCaseExpr = true;177 178 ExprResult LHS(179 ParseCastExpression(CastParseKind::AnyCastExpr, false,180 TypoCorrectionTypeBehavior::AllowNonTypes));181 ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));182 return Actions.ActOnCaseExpr(CaseLoc, Res);183}184 185ExprResult Parser::ParseConstraintExpression() {186 EnterExpressionEvaluationContext ConstantEvaluated(187 Actions, Sema::ExpressionEvaluationContext::Unevaluated);188 ExprResult LHS(ParseCastExpression(CastParseKind::AnyCastExpr));189 ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));190 if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) {191 return ExprError();192 }193 return Res;194}195 196ExprResult197Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {198 EnterExpressionEvaluationContext ConstantEvaluated(199 Actions, Sema::ExpressionEvaluationContext::Unevaluated);200 bool NotPrimaryExpression = false;201 auto ParsePrimary = [&]() {202 ExprResult E = ParseCastExpression(203 CastParseKind::PrimaryExprOnly,204 /*isAddressOfOperand=*/false, TypoCorrectionTypeBehavior::AllowNonTypes,205 /*isVectorLiteral=*/false, &NotPrimaryExpression);206 if (E.isInvalid())207 return ExprError();208 auto RecoverFromNonPrimary = [&] (ExprResult E, bool Note) {209 E = ParsePostfixExpressionSuffix(E);210 // Use InclusiveOr, the precedence just after '&&' to not parse the211 // next arguments to the logical and.212 E = ParseRHSOfBinaryExpression(E, prec::InclusiveOr);213 if (!E.isInvalid())214 Diag(E.get()->getExprLoc(),215 Note216 ? diag::note_unparenthesized_non_primary_expr_in_requires_clause217 : diag::err_unparenthesized_non_primary_expr_in_requires_clause)218 << FixItHint::CreateInsertion(E.get()->getBeginLoc(), "(")219 << FixItHint::CreateInsertion(220 PP.getLocForEndOfToken(E.get()->getEndLoc()), ")")221 << E.get()->getSourceRange();222 return E;223 };224 225 if (NotPrimaryExpression ||226 // Check if the following tokens must be a part of a non-primary227 // expression228 getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,229 /*CPlusPlus11=*/true) > prec::LogicalAnd ||230 // Postfix operators other than '(' (which will be checked for in231 // CheckConstraintExpression).232 Tok.isOneOf(tok::period, tok::plusplus, tok::minusminus) ||233 (Tok.is(tok::l_square) && !NextToken().is(tok::l_square))) {234 E = RecoverFromNonPrimary(E, /*Note=*/false);235 if (E.isInvalid())236 return ExprError();237 NotPrimaryExpression = false;238 }239 bool PossibleNonPrimary;240 bool IsConstraintExpr =241 Actions.CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary,242 IsTrailingRequiresClause);243 if (!IsConstraintExpr || PossibleNonPrimary) {244 // Atomic constraint might be an unparenthesized non-primary expression245 // (such as a binary operator), in which case we might get here (e.g. in246 // 'requires 0 + 1 && true' we would now be at '+', and parse and ignore247 // the rest of the addition expression). Try to parse the rest of it here.248 if (PossibleNonPrimary)249 E = RecoverFromNonPrimary(E, /*Note=*/!IsConstraintExpr);250 return ExprError();251 }252 return E;253 };254 ExprResult LHS = ParsePrimary();255 if (LHS.isInvalid())256 return ExprError();257 while (Tok.is(tok::ampamp)) {258 SourceLocation LogicalAndLoc = ConsumeToken();259 ExprResult RHS = ParsePrimary();260 if (RHS.isInvalid()) {261 return ExprError();262 }263 ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalAndLoc,264 tok::ampamp, LHS.get(), RHS.get());265 if (!Op.isUsable()) {266 return ExprError();267 }268 LHS = Op;269 }270 return LHS;271}272 273ExprResult274Parser::ParseConstraintLogicalOrExpression(bool IsTrailingRequiresClause) {275 ExprResult LHS(ParseConstraintLogicalAndExpression(IsTrailingRequiresClause));276 if (!LHS.isUsable())277 return ExprError();278 while (Tok.is(tok::pipepipe)) {279 SourceLocation LogicalOrLoc = ConsumeToken();280 ExprResult RHS =281 ParseConstraintLogicalAndExpression(IsTrailingRequiresClause);282 if (!RHS.isUsable()) {283 return ExprError();284 }285 ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalOrLoc,286 tok::pipepipe, LHS.get(), RHS.get());287 if (!Op.isUsable()) {288 return ExprError();289 }290 LHS = Op;291 }292 return LHS;293}294 295bool Parser::isNotExpressionStart() {296 tok::TokenKind K = Tok.getKind();297 if (K == tok::l_brace || K == tok::r_brace ||298 K == tok::kw_for || K == tok::kw_while ||299 K == tok::kw_if || K == tok::kw_else ||300 K == tok::kw_goto || K == tok::kw_try)301 return true;302 // If this is a decl-specifier, we can't be at the start of an expression.303 return isKnownToBeDeclarationSpecifier();304}305 306bool Parser::isFoldOperator(prec::Level Level) const {307 return Level > prec::Unknown && Level != prec::Conditional &&308 Level != prec::Spaceship;309}310 311bool Parser::isFoldOperator(tok::TokenKind Kind) const {312 return isFoldOperator(getBinOpPrecedence(Kind, GreaterThanIsOperator, true));313}314 315ExprResult316Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {317 prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(),318 GreaterThanIsOperator,319 getLangOpts().CPlusPlus11);320 SourceLocation ColonLoc;321 322 auto SavedType = PreferredType;323 while (true) {324 // Every iteration may rely on a preferred type for the whole expression.325 PreferredType = SavedType;326 // If this token has a lower precedence than we are allowed to parse (e.g.327 // because we are called recursively, or because the token is not a binop),328 // then we are done!329 if (NextTokPrec < MinPrec)330 return LHS;331 332 // Consume the operator, saving the operator token for error reporting.333 Token OpToken = Tok;334 ConsumeToken();335 336 // If we're potentially in a template-id, we may now be able to determine337 // whether we're actually in one or not.338 if (OpToken.isOneOf(tok::comma, tok::greater, tok::greatergreater,339 tok::greatergreatergreater) &&340 checkPotentialAngleBracketDelimiter(OpToken))341 return ExprError();342 343 // Bail out when encountering a comma followed by a token which can't344 // possibly be the start of an expression. For instance:345 // int f() { return 1, }346 // We can't do this before consuming the comma, because347 // isNotExpressionStart() looks at the token stream.348 if (OpToken.is(tok::comma) && isNotExpressionStart()) {349 PP.EnterToken(Tok, /*IsReinject*/true);350 Tok = OpToken;351 return LHS;352 }353 354 // If the next token is an ellipsis, then this is a fold-expression. Leave355 // it alone so we can handle it in the paren expression.356 if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) {357 // FIXME: We can't check this via lookahead before we consume the token358 // because that tickles a lexer bug.359 PP.EnterToken(Tok, /*IsReinject*/true);360 Tok = OpToken;361 return LHS;362 }363 364 // In Objective-C++, alternative operator tokens can be used as keyword args365 // in message expressions. Unconsume the token so that it can reinterpreted366 // as an identifier in ParseObjCMessageExpressionBody. i.e., we support:367 // [foo meth:0 and:0];368 // [foo not_eq];369 if (getLangOpts().ObjC && getLangOpts().CPlusPlus &&370 Tok.isOneOf(tok::colon, tok::r_square) &&371 OpToken.getIdentifierInfo() != nullptr) {372 PP.EnterToken(Tok, /*IsReinject*/true);373 Tok = OpToken;374 return LHS;375 }376 377 // Special case handling for the ternary operator.378 ExprResult TernaryMiddle(true);379 if (NextTokPrec == prec::Conditional) {380 if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {381 // Parse a braced-init-list here for error recovery purposes.382 SourceLocation BraceLoc = Tok.getLocation();383 TernaryMiddle = ParseBraceInitializer();384 if (!TernaryMiddle.isInvalid()) {385 Diag(BraceLoc, diag::err_init_list_bin_op)386 << /*RHS*/ 1 << PP.getSpelling(OpToken)387 << Actions.getExprRange(TernaryMiddle.get());388 TernaryMiddle = ExprError();389 }390 } else if (Tok.isNot(tok::colon)) {391 // Don't parse FOO:BAR as if it were a typo for FOO::BAR.392 ColonProtectionRAIIObject X(*this);393 394 // Handle this production specially:395 // logical-OR-expression '?' expression ':' conditional-expression396 // In particular, the RHS of the '?' is 'expression', not397 // 'logical-OR-expression' as we might expect.398 TernaryMiddle = ParseExpression();399 } else {400 // Special case handling of "X ? Y : Z" where Y is empty:401 // logical-OR-expression '?' ':' conditional-expression [GNU]402 TernaryMiddle = nullptr;403 Diag(Tok, diag::ext_gnu_conditional_expr);404 }405 406 if (TernaryMiddle.isInvalid()) {407 LHS = ExprError();408 TernaryMiddle = nullptr;409 }410 411 if (!TryConsumeToken(tok::colon, ColonLoc)) {412 // Otherwise, we're missing a ':'. Assume that this was a typo that413 // the user forgot. If we're not in a macro expansion, we can suggest414 // a fixit hint. If there were two spaces before the current token,415 // suggest inserting the colon in between them, otherwise insert ": ".416 SourceLocation FILoc = Tok.getLocation();417 const char *FIText = ": ";418 const SourceManager &SM = PP.getSourceManager();419 if (FILoc.isFileID() || PP.isAtStartOfMacroExpansion(FILoc, &FILoc)) {420 assert(FILoc.isFileID());421 bool IsInvalid = false;422 const char *SourcePtr =423 SM.getCharacterData(FILoc.getLocWithOffset(-1), &IsInvalid);424 if (!IsInvalid && *SourcePtr == ' ') {425 SourcePtr =426 SM.getCharacterData(FILoc.getLocWithOffset(-2), &IsInvalid);427 if (!IsInvalid && *SourcePtr == ' ') {428 FILoc = FILoc.getLocWithOffset(-1);429 FIText = ":";430 }431 }432 }433 434 Diag(Tok, diag::err_expected)435 << tok::colon << FixItHint::CreateInsertion(FILoc, FIText);436 Diag(OpToken, diag::note_matching) << tok::question;437 ColonLoc = Tok.getLocation();438 }439 }440 441 PreferredType.enterBinary(Actions, Tok.getLocation(), LHS.get(),442 OpToken.getKind());443 // Parse another leaf here for the RHS of the operator.444 // ParseCastExpression works here because all RHS expressions in C have it445 // as a prefix, at least. However, in C++, an assignment-expression could446 // be a throw-expression, which is not a valid cast-expression.447 // Therefore we need some special-casing here.448 // Also note that the third operand of the conditional operator is449 // an assignment-expression in C++, and in C++11, we can have a450 // braced-init-list on the RHS of an assignment. For better diagnostics,451 // parse as if we were allowed braced-init-lists everywhere, and check that452 // they only appear on the RHS of assignments later.453 ExprResult RHS;454 bool RHSIsInitList = false;455 if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {456 RHS = ParseBraceInitializer();457 RHSIsInitList = true;458 } else if (getLangOpts().CPlusPlus && NextTokPrec <= prec::Conditional)459 RHS = ParseAssignmentExpression();460 else461 RHS = ParseCastExpression(CastParseKind::AnyCastExpr);462 463 if (RHS.isInvalid()) {464 LHS = ExprError();465 }466 467 // Remember the precedence of this operator and get the precedence of the468 // operator immediately to the right of the RHS.469 prec::Level ThisPrec = NextTokPrec;470 NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,471 getLangOpts().CPlusPlus11);472 473 // Assignment and conditional expressions are right-associative.474 bool isRightAssoc = ThisPrec == prec::Conditional ||475 ThisPrec == prec::Assignment;476 477 // Get the precedence of the operator to the right of the RHS. If it binds478 // more tightly with RHS than we do, evaluate it completely first.479 if (ThisPrec < NextTokPrec ||480 (ThisPrec == NextTokPrec && isRightAssoc)) {481 if (!RHS.isInvalid() && RHSIsInitList) {482 Diag(Tok, diag::err_init_list_bin_op)483 << /*LHS*/0 << PP.getSpelling(Tok) << Actions.getExprRange(RHS.get());484 RHS = ExprError();485 }486 // If this is left-associative, only parse things on the RHS that bind487 // more tightly than the current operator. If it is right-associative, it488 // is okay, to bind exactly as tightly. For example, compile A=B=C=D as489 // A=(B=(C=D)), where each paren is a level of recursion here.490 // The function takes ownership of the RHS.491 RHS = ParseRHSOfBinaryExpression(RHS,492 static_cast<prec::Level>(ThisPrec + !isRightAssoc));493 RHSIsInitList = false;494 495 if (RHS.isInvalid()) {496 LHS = ExprError();497 }498 499 NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,500 getLangOpts().CPlusPlus11);501 }502 503 if (!RHS.isInvalid() && RHSIsInitList) {504 if (ThisPrec == prec::Assignment) {505 Diag(OpToken, diag::warn_cxx98_compat_generalized_initializer_lists)506 << Actions.getExprRange(RHS.get());507 } else if (ColonLoc.isValid()) {508 Diag(ColonLoc, diag::err_init_list_bin_op)509 << /*RHS*/1 << ":"510 << Actions.getExprRange(RHS.get());511 LHS = ExprError();512 } else {513 Diag(OpToken, diag::err_init_list_bin_op)514 << /*RHS*/1 << PP.getSpelling(OpToken)515 << Actions.getExprRange(RHS.get());516 LHS = ExprError();517 }518 }519 520 if (!LHS.isInvalid()) {521 // Combine the LHS and RHS into the LHS (e.g. build AST).522 if (TernaryMiddle.isInvalid()) {523 // If we're using '>>' as an operator within a template524 // argument list (in C++98), suggest the addition of525 // parentheses so that the code remains well-formed in C++0x.526 if (!GreaterThanIsOperator && OpToken.is(tok::greatergreater))527 SuggestParentheses(OpToken.getLocation(),528 diag::warn_cxx11_right_shift_in_template_arg,529 SourceRange(Actions.getExprRange(LHS.get()).getBegin(),530 Actions.getExprRange(RHS.get()).getEnd()));531 532 ExprResult BinOp =533 Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),534 OpToken.getKind(), LHS.get(), RHS.get());535 if (BinOp.isInvalid())536 BinOp = Actions.CreateRecoveryExpr(LHS.get()->getBeginLoc(),537 RHS.get()->getEndLoc(),538 {LHS.get(), RHS.get()});539 540 LHS = BinOp;541 } else {542 ExprResult CondOp = Actions.ActOnConditionalOp(543 OpToken.getLocation(), ColonLoc, LHS.get(), TernaryMiddle.get(),544 RHS.get());545 if (CondOp.isInvalid()) {546 std::vector<clang::Expr *> Args;547 // TernaryMiddle can be null for the GNU conditional expr extension.548 if (TernaryMiddle.get())549 Args = {LHS.get(), TernaryMiddle.get(), RHS.get()};550 else551 Args = {LHS.get(), RHS.get()};552 CondOp = Actions.CreateRecoveryExpr(LHS.get()->getBeginLoc(),553 RHS.get()->getEndLoc(), Args);554 }555 556 LHS = CondOp;557 }558 }559 }560}561 562ExprResult563Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand,564 TypoCorrectionTypeBehavior CorrectionBehavior,565 bool isVectorLiteral, bool *NotPrimaryExpression) {566 bool NotCastExpr;567 ExprResult Res = ParseCastExpression(ParseKind, isAddressOfOperand,568 NotCastExpr, CorrectionBehavior,569 isVectorLiteral, NotPrimaryExpression);570 if (NotCastExpr)571 Diag(Tok, diag::err_expected_expression);572 return Res;573}574 575namespace {576class CastExpressionIdValidator final : public CorrectionCandidateCallback {577public:578 CastExpressionIdValidator(Token Next,579 TypoCorrectionTypeBehavior CorrectionBehavior)580 : NextToken(Next) {581 WantTypeSpecifiers = WantFunctionLikeCasts =582 (CorrectionBehavior != TypoCorrectionTypeBehavior::AllowNonTypes);583 AllowNonTypes =584 (CorrectionBehavior != TypoCorrectionTypeBehavior::AllowTypes);585 }586 587 bool ValidateCandidate(const TypoCorrection &candidate) override {588 NamedDecl *ND = candidate.getCorrectionDecl();589 if (!ND)590 return candidate.isKeyword();591 592 if (isa<TypeDecl>(ND))593 return WantTypeSpecifiers;594 595 if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate))596 return false;597 598 if (!NextToken.isOneOf(tok::equal, tok::arrow, tok::period))599 return true;600 601 for (auto *C : candidate) {602 NamedDecl *ND = C->getUnderlyingDecl();603 if (isa<ValueDecl>(ND) && !isa<FunctionDecl>(ND))604 return true;605 }606 return false;607 }608 609 std::unique_ptr<CorrectionCandidateCallback> clone() override {610 return std::make_unique<CastExpressionIdValidator>(*this);611 }612 613 private:614 Token NextToken;615 bool AllowNonTypes;616};617}618 619bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II,620 tok::TokenKind *Kind) {621 if (RevertibleTypeTraits.empty()) {622// Revertible type trait is a feature for backwards compatibility with older623// standard libraries that declare their own structs with the same name as624// the builtins listed below. New builtins should NOT be added to this list.625#define RTT_JOIN(X, Y) X##Y626#define REVERTIBLE_TYPE_TRAIT(Name) \627 RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] = RTT_JOIN(tok::kw_, Name)628 629 REVERTIBLE_TYPE_TRAIT(__is_abstract);630 REVERTIBLE_TYPE_TRAIT(__is_aggregate);631 REVERTIBLE_TYPE_TRAIT(__is_arithmetic);632 REVERTIBLE_TYPE_TRAIT(__is_array);633 REVERTIBLE_TYPE_TRAIT(__is_assignable);634 REVERTIBLE_TYPE_TRAIT(__is_base_of);635 REVERTIBLE_TYPE_TRAIT(__is_bounded_array);636 REVERTIBLE_TYPE_TRAIT(__is_class);637 REVERTIBLE_TYPE_TRAIT(__is_complete_type);638 REVERTIBLE_TYPE_TRAIT(__is_compound);639 REVERTIBLE_TYPE_TRAIT(__is_const);640 REVERTIBLE_TYPE_TRAIT(__is_constructible);641 REVERTIBLE_TYPE_TRAIT(__is_convertible);642 REVERTIBLE_TYPE_TRAIT(__is_convertible_to);643 REVERTIBLE_TYPE_TRAIT(__is_destructible);644 REVERTIBLE_TYPE_TRAIT(__is_empty);645 REVERTIBLE_TYPE_TRAIT(__is_enum);646 REVERTIBLE_TYPE_TRAIT(__is_floating_point);647 REVERTIBLE_TYPE_TRAIT(__is_final);648 REVERTIBLE_TYPE_TRAIT(__is_function);649 REVERTIBLE_TYPE_TRAIT(__is_fundamental);650 REVERTIBLE_TYPE_TRAIT(__is_integral);651 REVERTIBLE_TYPE_TRAIT(__is_interface_class);652 REVERTIBLE_TYPE_TRAIT(__is_literal);653 REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);654 REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);655 REVERTIBLE_TYPE_TRAIT(__is_member_function_pointer);656 REVERTIBLE_TYPE_TRAIT(__is_member_object_pointer);657 REVERTIBLE_TYPE_TRAIT(__is_member_pointer);658 REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable);659 REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible);660 REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible);661 REVERTIBLE_TYPE_TRAIT(__is_object);662 REVERTIBLE_TYPE_TRAIT(__is_pod);663 REVERTIBLE_TYPE_TRAIT(__is_pointer);664 REVERTIBLE_TYPE_TRAIT(__is_polymorphic);665 REVERTIBLE_TYPE_TRAIT(__is_reference);666 REVERTIBLE_TYPE_TRAIT(__is_rvalue_expr);667 REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference);668 REVERTIBLE_TYPE_TRAIT(__is_same);669 REVERTIBLE_TYPE_TRAIT(__is_scalar);670 REVERTIBLE_TYPE_TRAIT(__is_scoped_enum);671 REVERTIBLE_TYPE_TRAIT(__is_sealed);672 REVERTIBLE_TYPE_TRAIT(__is_signed);673 REVERTIBLE_TYPE_TRAIT(__is_standard_layout);674 REVERTIBLE_TYPE_TRAIT(__is_trivial);675 REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable);676 REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible);677 REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable);678 REVERTIBLE_TYPE_TRAIT(__is_unbounded_array);679 REVERTIBLE_TYPE_TRAIT(__is_union);680 REVERTIBLE_TYPE_TRAIT(__is_unsigned);681 REVERTIBLE_TYPE_TRAIT(__is_void);682 REVERTIBLE_TYPE_TRAIT(__is_volatile);683 REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary);684#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \685 REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait));686#include "clang/Basic/TransformTypeTraits.def"687#undef REVERTIBLE_TYPE_TRAIT688#undef RTT_JOIN689 }690 llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known =691 RevertibleTypeTraits.find(II);692 if (Known != RevertibleTypeTraits.end()) {693 if (Kind)694 *Kind = Known->second;695 return true;696 }697 return false;698}699 700ExprResult Parser::ParseBuiltinPtrauthTypeDiscriminator() {701 SourceLocation Loc = ConsumeToken();702 703 BalancedDelimiterTracker T(*this, tok::l_paren);704 if (T.expectAndConsume())705 return ExprError();706 707 TypeResult Ty = ParseTypeName();708 if (Ty.isInvalid()) {709 SkipUntil(tok::r_paren, StopAtSemi);710 return ExprError();711 }712 713 SourceLocation EndLoc = Tok.getLocation();714 T.consumeClose();715 return Actions.ActOnUnaryExprOrTypeTraitExpr(716 Loc, UETT_PtrAuthTypeDiscriminator,717 /*isType=*/true, Ty.get().getAsOpaquePtr(), SourceRange(Loc, EndLoc));718}719 720ExprResult721Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand,722 bool &NotCastExpr,723 TypoCorrectionTypeBehavior CorrectionBehavior,724 bool isVectorLiteral, bool *NotPrimaryExpression) {725 ExprResult Res;726 tok::TokenKind SavedKind = Tok.getKind();727 auto SavedType = PreferredType;728 NotCastExpr = false;729 730 // Are postfix-expression suffix operators permitted after this731 // cast-expression? If not, and we find some, we'll parse them anyway and732 // diagnose them.733 bool AllowSuffix = true;734 735 // This handles all of cast-expression, unary-expression, postfix-expression,736 // and primary-expression. We handle them together like this for efficiency737 // and to simplify handling of an expression starting with a '(' token: which738 // may be one of a parenthesized expression, cast-expression, compound literal739 // expression, or statement expression.740 //741 // If the parsed tokens consist of a primary-expression, the cases below742 // break out of the switch; at the end we call ParsePostfixExpressionSuffix743 // to handle the postfix expression suffixes. Cases that cannot be followed744 // by postfix exprs should set AllowSuffix to false.745 switch (SavedKind) {746 case tok::l_paren: {747 // If this expression is limited to being a unary-expression, the paren can748 // not start a cast expression.749 ParenParseOption ParenExprType;750 switch (ParseKind) {751 case CastParseKind::UnaryExprOnly:752 assert(getLangOpts().CPlusPlus && "not possible to get here in C");753 [[fallthrough]];754 case CastParseKind::AnyCastExpr:755 ParenExprType = ParenParseOption::CastExpr;756 break;757 case CastParseKind::PrimaryExprOnly:758 ParenExprType = ParenParseOption::FoldExpr;759 break;760 }761 ParsedType CastTy;762 SourceLocation RParenLoc;763 Res = ParseParenExpression(ParenExprType, /*StopIfCastExr=*/false,764 ParenExprKind::Unknown, CorrectionBehavior,765 CastTy, RParenLoc);766 767 // FIXME: What should we do if a vector literal is followed by a768 // postfix-expression suffix? Usually postfix operators are permitted on769 // literals.770 if (isVectorLiteral)771 return Res;772 773 switch (ParenExprType) {774 case ParenParseOption::SimpleExpr:775 break; // Nothing else to do.776 case ParenParseOption::CompoundStmt:777 break; // Nothing else to do.778 case ParenParseOption::CompoundLiteral:779 // We parsed '(' type-name ')' '{' ... '}'. If any suffixes of780 // postfix-expression exist, parse them now.781 break;782 case ParenParseOption::CastExpr:783 // We have parsed the cast-expression and no postfix-expr pieces are784 // following.785 return Res;786 case ParenParseOption::FoldExpr:787 // We only parsed a fold-expression. There might be postfix-expr pieces788 // afterwards; parse them now.789 break;790 }791 792 break;793 }794 795 // primary-expression796 case tok::numeric_constant:797 case tok::binary_data:798 // constant: integer-constant799 // constant: floating-constant800 801 Res = Actions.ActOnNumericConstant(Tok, /*UDLScope*/getCurScope());802 ConsumeToken();803 break;804 805 case tok::kw_true:806 case tok::kw_false:807 Res = ParseCXXBoolLiteral();808 break;809 810 case tok::kw___objc_yes:811 case tok::kw___objc_no:812 Res = ParseObjCBoolLiteral();813 break;814 815 case tok::kw_nullptr:816 if (getLangOpts().CPlusPlus)817 Diag(Tok, diag::warn_cxx98_compat_nullptr);818 else819 Diag(Tok, getLangOpts().C23 ? diag::warn_c23_compat_keyword820 : diag::ext_c_nullptr) << Tok.getName();821 822 Res = Actions.ActOnCXXNullPtrLiteral(ConsumeToken());823 break;824 825 case tok::annot_primary_expr:826 case tok::annot_overload_set:827 Res = getExprAnnotation(Tok);828 if (!Res.isInvalid() && Tok.getKind() == tok::annot_overload_set)829 Res = Actions.ActOnNameClassifiedAsOverloadSet(getCurScope(), Res.get());830 ConsumeAnnotationToken();831 if (!Res.isInvalid() && Tok.is(tok::less))832 checkPotentialAngleBracket(Res);833 break;834 835 case tok::annot_non_type:836 case tok::annot_non_type_dependent:837 case tok::annot_non_type_undeclared: {838 CXXScopeSpec SS;839 Token Replacement;840 Res = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement);841 assert(!Res.isUnset() &&842 "should not perform typo correction on annotation token");843 break;844 }845 846 case tok::annot_embed: {847 injectEmbedTokens();848 return ParseCastExpression(ParseKind, isAddressOfOperand,849 CorrectionBehavior, isVectorLiteral,850 NotPrimaryExpression);851 }852 853 case tok::kw___super:854 case tok::kw_decltype:855 // Annotate the token and tail recurse.856 if (TryAnnotateTypeOrScopeToken())857 return ExprError();858 assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));859 return ParseCastExpression(ParseKind, isAddressOfOperand,860 CorrectionBehavior, isVectorLiteral,861 NotPrimaryExpression);862 863 case tok::identifier:864 ParseIdentifier: { // primary-expression: identifier865 // unqualified-id: identifier866 // constant: enumeration-constant867 // Turn a potentially qualified name into a annot_typename or868 // annot_cxxscope if it would be valid. This handles things like x::y, etc.869 if (getLangOpts().CPlusPlus) {870 // Avoid the unnecessary parse-time lookup in the common case871 // where the syntax forbids a type.872 Token Next = NextToken();873 874 if (Next.is(tok::ellipsis) && Tok.is(tok::identifier) &&875 GetLookAheadToken(2).is(tok::l_square)) {876 // Annotate the token and tail recurse.877 // If the token is not annotated, then it might be an expression pack878 // indexing879 if (!TryAnnotateTypeOrScopeToken() &&880 Tok.isOneOf(tok::annot_pack_indexing_type, tok::annot_cxxscope))881 return ParseCastExpression(ParseKind, isAddressOfOperand,882 CorrectionBehavior, isVectorLiteral,883 NotPrimaryExpression);884 }885 886 // If this identifier was reverted from a token ID, and the next token887 // is a parenthesis, this is likely to be a use of a type trait. Check888 // those tokens.889 else if (Next.is(tok::l_paren) && Tok.is(tok::identifier) &&890 Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) {891 IdentifierInfo *II = Tok.getIdentifierInfo();892 tok::TokenKind Kind;893 if (isRevertibleTypeTrait(II, &Kind)) {894 Tok.setKind(Kind);895 return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,896 CorrectionBehavior, isVectorLiteral,897 NotPrimaryExpression);898 }899 }900 901 else if ((!ColonIsSacred && Next.is(tok::colon)) ||902 Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren,903 tok::l_brace)) {904 // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.905 if (TryAnnotateTypeOrScopeToken())906 return ExprError();907 if (!Tok.is(tok::identifier))908 return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,909 CorrectionBehavior, isVectorLiteral,910 NotPrimaryExpression);911 }912 }913 914 // Consume the identifier so that we can see if it is followed by a '(' or915 // '.'.916 IdentifierInfo &II = *Tok.getIdentifierInfo();917 SourceLocation ILoc = ConsumeToken();918 919 // Support 'Class.property' and 'super.property' notation.920 if (getLangOpts().ObjC && Tok.is(tok::period) &&921 (Actions.getTypeName(II, ILoc, getCurScope()) ||922 // Allow the base to be 'super' if in an objc-method.923 (&II == Ident_super && getCurScope()->isInObjcMethodScope()))) {924 ConsumeToken();925 926 if (Tok.is(tok::code_completion) && &II != Ident_super) {927 cutOffParsing();928 Actions.CodeCompletion().CodeCompleteObjCClassPropertyRefExpr(929 getCurScope(), II, ILoc, ExprStatementTokLoc == ILoc);930 return ExprError();931 }932 // Allow either an identifier or the keyword 'class' (in C++).933 if (Tok.isNot(tok::identifier) &&934 !(getLangOpts().CPlusPlus && Tok.is(tok::kw_class))) {935 Diag(Tok, diag::err_expected_property_name);936 return ExprError();937 }938 IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();939 SourceLocation PropertyLoc = ConsumeToken();940 941 Res = Actions.ObjC().ActOnClassPropertyRefExpr(II, PropertyName, ILoc,942 PropertyLoc);943 break;944 }945 946 // In an Objective-C method, if we have "super" followed by an identifier,947 // the token sequence is ill-formed. However, if there's a ':' or ']' after948 // that identifier, this is probably a message send with a missing open949 // bracket. Treat it as such.950 if (getLangOpts().ObjC && &II == Ident_super && !InMessageExpression &&951 getCurScope()->isInObjcMethodScope() &&952 ((Tok.is(tok::identifier) &&953 (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||954 Tok.is(tok::code_completion))) {955 Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, nullptr,956 nullptr);957 break;958 }959 960 // If we have an Objective-C class name followed by an identifier961 // and either ':' or ']', this is an Objective-C class message962 // send that's missing the opening '['. Recovery963 // appropriately. Also take this path if we're performing code964 // completion after an Objective-C class name.965 if (getLangOpts().ObjC &&966 ((Tok.is(tok::identifier) && !InMessageExpression) ||967 Tok.is(tok::code_completion))) {968 const Token& Next = NextToken();969 if (Tok.is(tok::code_completion) ||970 Next.is(tok::colon) || Next.is(tok::r_square))971 if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope()))972 if (Typ.get()->isObjCObjectOrInterfaceType()) {973 // Fake up a Declarator to use with ActOnTypeName.974 DeclSpec DS(AttrFactory);975 DS.SetRangeStart(ILoc);976 DS.SetRangeEnd(ILoc);977 const char *PrevSpec = nullptr;978 unsigned DiagID;979 DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,980 Actions.getASTContext().getPrintingPolicy());981 982 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),983 DeclaratorContext::TypeName);984 TypeResult Ty = Actions.ActOnTypeName(DeclaratorInfo);985 if (Ty.isInvalid())986 break;987 988 Res = ParseObjCMessageExpressionBody(SourceLocation(),989 SourceLocation(),990 Ty.get(), nullptr);991 break;992 }993 }994 995 // Make sure to pass down the right value for isAddressOfOperand.996 if (isAddressOfOperand && isPostfixExpressionSuffixStart())997 isAddressOfOperand = false;998 999 // Function designators are allowed to be undeclared (C99 6.5.1p2), so we1000 // need to know whether or not this identifier is a function designator or1001 // not.1002 UnqualifiedId Name;1003 CXXScopeSpec ScopeSpec;1004 SourceLocation TemplateKWLoc;1005 Token Replacement;1006 CastExpressionIdValidator Validator(Tok, CorrectionBehavior);1007 Validator.IsAddressOfOperand = isAddressOfOperand;1008 if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) {1009 Validator.WantExpressionKeywords = false;1010 Validator.WantRemainingKeywords = false;1011 } else {1012 Validator.WantRemainingKeywords = Tok.isNot(tok::r_paren);1013 }1014 Name.setIdentifier(&II, ILoc);1015 Res = Actions.ActOnIdExpression(1016 getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren),1017 isAddressOfOperand, &Validator,1018 /*IsInlineAsmIdentifier=*/false,1019 Tok.is(tok::r_paren) ? nullptr : &Replacement);1020 if (!Res.isInvalid() && Res.isUnset()) {1021 UnconsumeToken(Replacement);1022 return ParseCastExpression(1023 ParseKind, isAddressOfOperand, NotCastExpr, CorrectionBehavior,1024 /*isVectorLiteral=*/false, NotPrimaryExpression);1025 }1026 Res = tryParseCXXPackIndexingExpression(Res);1027 if (!Res.isInvalid() && Tok.is(tok::less))1028 checkPotentialAngleBracket(Res);1029 break;1030 }1031 case tok::char_constant: // constant: character-constant1032 case tok::wide_char_constant:1033 case tok::utf8_char_constant:1034 case tok::utf16_char_constant:1035 case tok::utf32_char_constant:1036 Res = Actions.ActOnCharacterConstant(Tok, /*UDLScope*/getCurScope());1037 ConsumeToken();1038 break;1039 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]1040 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]1041 case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS]1042 case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS]1043 case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS]1044 case tok::kw_L__FUNCSIG__: // primary-expression: L__FUNCSIG__ [MS]1045 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]1046 // Function local predefined macros are represented by PredefinedExpr except1047 // when Microsoft extensions are enabled and one of these macros is adjacent1048 // to a string literal or another one of these macros.1049 if (!(getLangOpts().MicrosoftExt &&1050 tokenIsLikeStringLiteral(Tok, getLangOpts()) &&1051 tokenIsLikeStringLiteral(NextToken(), getLangOpts()))) {1052 Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);1053 ConsumeToken();1054 break;1055 }1056 [[fallthrough]]; // treat MS function local macros as concatenable strings1057 case tok::string_literal: // primary-expression: string-literal1058 case tok::wide_string_literal:1059 case tok::utf8_string_literal:1060 case tok::utf16_string_literal:1061 case tok::utf32_string_literal:1062 Res = ParseStringLiteralExpression(true);1063 break;1064 case tok::kw__Generic: // primary-expression: generic-selection [C11 6.5.1]1065 Res = ParseGenericSelectionExpression();1066 break;1067 case tok::kw___builtin_available:1068 Res = ParseAvailabilityCheckExpr(Tok.getLocation());1069 break;1070 case tok::kw___builtin_va_arg:1071 case tok::kw___builtin_offsetof:1072 case tok::kw___builtin_choose_expr:1073 case tok::kw___builtin_astype: // primary-expression: [OCL] as_type()1074 case tok::kw___builtin_convertvector:1075 case tok::kw___builtin_COLUMN:1076 case tok::kw___builtin_FILE:1077 case tok::kw___builtin_FILE_NAME:1078 case tok::kw___builtin_FUNCTION:1079 case tok::kw___builtin_FUNCSIG:1080 case tok::kw___builtin_LINE:1081 case tok::kw___builtin_source_location:1082 if (NotPrimaryExpression)1083 *NotPrimaryExpression = true;1084 // This parses the complete suffix; we can return early.1085 return ParseBuiltinPrimaryExpression();1086 case tok::kw___null:1087 Res = Actions.ActOnGNUNullExpr(ConsumeToken());1088 break;1089 1090 case tok::plusplus: // unary-expression: '++' unary-expression [C99]1091 case tok::minusminus: { // unary-expression: '--' unary-expression [C99]1092 if (NotPrimaryExpression)1093 *NotPrimaryExpression = true;1094 // C++ [expr.unary] has:1095 // unary-expression:1096 // ++ cast-expression1097 // -- cast-expression1098 Token SavedTok = Tok;1099 ConsumeToken();1100 1101 PreferredType.enterUnary(Actions, Tok.getLocation(), SavedTok.getKind(),1102 SavedTok.getLocation());1103 // One special case is implicitly handled here: if the preceding tokens are1104 // an ambiguous cast expression, such as "(T())++", then we recurse to1105 // determine whether the '++' is prefix or postfix.1106 Res = ParseCastExpression(getLangOpts().CPlusPlus1107 ? CastParseKind::UnaryExprOnly1108 : CastParseKind::AnyCastExpr,1109 /*isAddressOfOperand*/ false, NotCastExpr,1110 TypoCorrectionTypeBehavior::AllowNonTypes);1111 if (NotCastExpr) {1112 // If we return with NotCastExpr = true, we must not consume any tokens,1113 // so put the token back where we found it.1114 assert(Res.isInvalid());1115 UnconsumeToken(SavedTok);1116 return ExprError();1117 }1118 if (!Res.isInvalid()) {1119 Expr *Arg = Res.get();1120 Res = Actions.ActOnUnaryOp(getCurScope(), SavedTok.getLocation(),1121 SavedKind, Arg);1122 if (Res.isInvalid())1123 Res = Actions.CreateRecoveryExpr(SavedTok.getLocation(),1124 Arg->getEndLoc(), Arg);1125 }1126 return Res;1127 }1128 case tok::amp: { // unary-expression: '&' cast-expression1129 if (NotPrimaryExpression)1130 *NotPrimaryExpression = true;1131 // Special treatment because of member pointers1132 SourceLocation SavedLoc = ConsumeToken();1133 PreferredType.enterUnary(Actions, Tok.getLocation(), tok::amp, SavedLoc);1134 1135 Res = ParseCastExpression(CastParseKind::AnyCastExpr,1136 /*isAddressOfOperand=*/true);1137 if (!Res.isInvalid()) {1138 Expr *Arg = Res.get();1139 Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg);1140 if (Res.isInvalid())1141 Res = Actions.CreateRecoveryExpr(Tok.getLocation(), Arg->getEndLoc(),1142 Arg);1143 }1144 return Res;1145 }1146 1147 case tok::star: // unary-expression: '*' cast-expression1148 case tok::plus: // unary-expression: '+' cast-expression1149 case tok::minus: // unary-expression: '-' cast-expression1150 case tok::tilde: // unary-expression: '~' cast-expression1151 case tok::exclaim: // unary-expression: '!' cast-expression1152 case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]1153 case tok::kw___imag: { // unary-expression: '__imag' cast-expression [GNU]1154 if (NotPrimaryExpression)1155 *NotPrimaryExpression = true;1156 SourceLocation SavedLoc = ConsumeToken();1157 PreferredType.enterUnary(Actions, Tok.getLocation(), SavedKind, SavedLoc);1158 Res = ParseCastExpression(CastParseKind::AnyCastExpr);1159 if (!Res.isInvalid()) {1160 Expr *Arg = Res.get();1161 Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg,1162 isAddressOfOperand);1163 if (Res.isInvalid())1164 Res = Actions.CreateRecoveryExpr(SavedLoc, Arg->getEndLoc(), Arg);1165 }1166 return Res;1167 }1168 1169 case tok::kw_co_await: { // unary-expression: 'co_await' cast-expression1170 if (NotPrimaryExpression)1171 *NotPrimaryExpression = true;1172 SourceLocation CoawaitLoc = ConsumeToken();1173 Res = ParseCastExpression(CastParseKind::AnyCastExpr);1174 if (!Res.isInvalid())1175 Res = Actions.ActOnCoawaitExpr(getCurScope(), CoawaitLoc, Res.get());1176 return Res;1177 }1178 1179 case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]1180 // __extension__ silences extension warnings in the subexpression.1181 if (NotPrimaryExpression)1182 *NotPrimaryExpression = true;1183 ExtensionRAIIObject O(Diags); // Use RAII to do this.1184 SourceLocation SavedLoc = ConsumeToken();1185 Res = ParseCastExpression(CastParseKind::AnyCastExpr);1186 if (!Res.isInvalid())1187 Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());1188 return Res;1189 }1190 case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')'1191 diagnoseUseOfC11Keyword(Tok);1192 [[fallthrough]];1193 case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')'1194 case tok::kw___alignof: // unary-expression: '__alignof' unary-expression1195 // unary-expression: '__alignof' '(' type-name ')'1196 case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression1197 // unary-expression: 'sizeof' '(' type-name ')'1198 // unary-expression: '__datasizeof' unary-expression1199 // unary-expression: '__datasizeof' '(' type-name ')'1200 case tok::kw___datasizeof:1201 case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression1202 // unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'1203 case tok::kw___builtin_omp_required_simd_align:1204 case tok::kw___builtin_vectorelements:1205 case tok::kw__Countof:1206 if (NotPrimaryExpression)1207 *NotPrimaryExpression = true;1208 AllowSuffix = false;1209 Res = ParseUnaryExprOrTypeTraitExpression();1210 break;1211 case tok::ampamp: { // unary-expression: '&&' identifier1212 if (NotPrimaryExpression)1213 *NotPrimaryExpression = true;1214 SourceLocation AmpAmpLoc = ConsumeToken();1215 if (Tok.isNot(tok::identifier))1216 return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);1217 1218 if (getCurScope()->getFnParent() == nullptr)1219 return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));1220 1221 Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);1222 LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),1223 Tok.getLocation());1224 Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD);1225 ConsumeToken();1226 AllowSuffix = false;1227 break;1228 }1229 case tok::kw_const_cast:1230 case tok::kw_dynamic_cast:1231 case tok::kw_reinterpret_cast:1232 case tok::kw_static_cast:1233 case tok::kw_addrspace_cast:1234 if (NotPrimaryExpression)1235 *NotPrimaryExpression = true;1236 Res = ParseCXXCasts();1237 break;1238 case tok::kw___builtin_bit_cast:1239 if (NotPrimaryExpression)1240 *NotPrimaryExpression = true;1241 Res = ParseBuiltinBitCast();1242 break;1243 case tok::kw_typeid:1244 if (NotPrimaryExpression)1245 *NotPrimaryExpression = true;1246 Res = ParseCXXTypeid();1247 break;1248 case tok::kw___uuidof:1249 if (NotPrimaryExpression)1250 *NotPrimaryExpression = true;1251 Res = ParseCXXUuidof();1252 break;1253 case tok::kw_this:1254 Res = ParseCXXThis();1255 break;1256 case tok::kw___builtin_sycl_unique_stable_name:1257 Res = ParseSYCLUniqueStableNameExpression();1258 break;1259 1260 case tok::annot_typename:1261 if (isStartOfObjCClassMessageMissingOpenBracket()) {1262 TypeResult Type = getTypeAnnotation(Tok);1263 1264 // Fake up a Declarator to use with ActOnTypeName.1265 DeclSpec DS(AttrFactory);1266 DS.SetRangeStart(Tok.getLocation());1267 DS.SetRangeEnd(Tok.getLastLoc());1268 1269 const char *PrevSpec = nullptr;1270 unsigned DiagID;1271 DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(),1272 PrevSpec, DiagID, Type,1273 Actions.getASTContext().getPrintingPolicy());1274 1275 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),1276 DeclaratorContext::TypeName);1277 TypeResult Ty = Actions.ActOnTypeName(DeclaratorInfo);1278 if (Ty.isInvalid())1279 break;1280 1281 ConsumeAnnotationToken();1282 Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),1283 Ty.get(), nullptr);1284 break;1285 }1286 [[fallthrough]];1287 1288 case tok::annot_decltype:1289 case tok::annot_pack_indexing_type:1290 case tok::kw_char:1291 case tok::kw_wchar_t:1292 case tok::kw_char8_t:1293 case tok::kw_char16_t:1294 case tok::kw_char32_t:1295 case tok::kw_bool:1296 case tok::kw_short:1297 case tok::kw_int:1298 case tok::kw_long:1299 case tok::kw___int64:1300 case tok::kw___int128:1301 case tok::kw__ExtInt:1302 case tok::kw__BitInt:1303 case tok::kw_signed:1304 case tok::kw_unsigned:1305 case tok::kw_half:1306 case tok::kw_float:1307 case tok::kw_double:1308 case tok::kw___bf16:1309 case tok::kw__Float16:1310 case tok::kw___float128:1311 case tok::kw___ibm128:1312 case tok::kw_void:1313 case tok::kw_auto:1314 case tok::kw_typename:1315 case tok::kw_typeof:1316 case tok::kw___vector:1317 case tok::kw__Accum:1318 case tok::kw__Fract:1319 case tok::kw__Sat:1320#define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:1321#include "clang/Basic/OpenCLImageTypes.def"1322#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name:1323#include "clang/Basic/HLSLIntangibleTypes.def"1324 {1325 if (!getLangOpts().CPlusPlus) {1326 Diag(Tok, diag::err_expected_expression);1327 return ExprError();1328 }1329 1330 // Everything henceforth is a postfix-expression.1331 if (NotPrimaryExpression)1332 *NotPrimaryExpression = true;1333 1334 if (SavedKind == tok::kw_typename) {1335 // postfix-expression: typename-specifier '(' expression-list[opt] ')'1336 // typename-specifier braced-init-list1337 if (TryAnnotateTypeOrScopeToken())1338 return ExprError();1339 1340 if (!Tok.isSimpleTypeSpecifier(getLangOpts()))1341 // We are trying to parse a simple-type-specifier but might not get such1342 // a token after error recovery.1343 return ExprError();1344 }1345 1346 // postfix-expression: simple-type-specifier '(' expression-list[opt] ')'1347 // simple-type-specifier braced-init-list1348 //1349 DeclSpec DS(AttrFactory);1350 1351 ParseCXXSimpleTypeSpecifier(DS);1352 if (Tok.isNot(tok::l_paren) &&1353 (!getLangOpts().CPlusPlus11 || Tok.isNot(tok::l_brace)))1354 return ExprError(Diag(Tok, diag::err_expected_lparen_after_type)1355 << DS.getSourceRange());1356 1357 if (Tok.is(tok::l_brace))1358 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);1359 1360 Res = ParseCXXTypeConstructExpression(DS);1361 break;1362 }1363 1364 case tok::annot_cxxscope: { // [C++] id-expression: qualified-id1365 // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.1366 // (We can end up in this situation after tentative parsing.)1367 if (TryAnnotateTypeOrScopeToken())1368 return ExprError();1369 if (!Tok.is(tok::annot_cxxscope))1370 return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,1371 CorrectionBehavior, isVectorLiteral,1372 NotPrimaryExpression);1373 1374 Token Next = NextToken();1375 if (Next.is(tok::annot_template_id)) {1376 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next);1377 if (TemplateId->Kind == TNK_Type_template) {1378 // We have a qualified template-id that we know refers to a1379 // type, translate it into a type and continue parsing as a1380 // cast expression.1381 CXXScopeSpec SS;1382 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,1383 /*ObjectHasErrors=*/false,1384 /*EnteringContext=*/false);1385 AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::Yes);1386 return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,1387 CorrectionBehavior, isVectorLiteral,1388 NotPrimaryExpression);1389 }1390 }1391 1392 // Parse as an id-expression.1393 Res = ParseCXXIdExpression(isAddressOfOperand);1394 break;1395 }1396 1397 case tok::annot_template_id: { // [C++] template-id1398 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);1399 if (TemplateId->Kind == TNK_Type_template) {1400 // We have a template-id that we know refers to a type,1401 // translate it into a type and continue parsing as a cast1402 // expression.1403 CXXScopeSpec SS;1404 AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::Yes);1405 return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,1406 CorrectionBehavior, isVectorLiteral,1407 NotPrimaryExpression);1408 }1409 1410 // Fall through to treat the template-id as an id-expression.1411 [[fallthrough]];1412 }1413 1414 case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id1415 Res = ParseCXXIdExpression(isAddressOfOperand);1416 break;1417 1418 case tok::coloncolon: {1419 // ::foo::bar -> global qualified name etc. If TryAnnotateTypeOrScopeToken1420 // annotates the token, tail recurse.1421 if (TryAnnotateTypeOrScopeToken())1422 return ExprError();1423 if (!Tok.is(tok::coloncolon))1424 return ParseCastExpression(ParseKind, isAddressOfOperand,1425 CorrectionBehavior, isVectorLiteral,1426 NotPrimaryExpression);1427 1428 // ::new -> [C++] new-expression1429 // ::delete -> [C++] delete-expression1430 SourceLocation CCLoc = ConsumeToken();1431 if (Tok.is(tok::kw_new)) {1432 if (NotPrimaryExpression)1433 *NotPrimaryExpression = true;1434 Res = ParseCXXNewExpression(true, CCLoc);1435 AllowSuffix = false;1436 break;1437 }1438 if (Tok.is(tok::kw_delete)) {1439 if (NotPrimaryExpression)1440 *NotPrimaryExpression = true;1441 Res = ParseCXXDeleteExpression(true, CCLoc);1442 AllowSuffix = false;1443 break;1444 }1445 1446 // This is not a type name or scope specifier, it is an invalid expression.1447 Diag(CCLoc, diag::err_expected_expression);1448 return ExprError();1449 }1450 1451 case tok::kw_new: // [C++] new-expression1452 if (NotPrimaryExpression)1453 *NotPrimaryExpression = true;1454 Res = ParseCXXNewExpression(false, Tok.getLocation());1455 AllowSuffix = false;1456 break;1457 1458 case tok::kw_delete: // [C++] delete-expression1459 if (NotPrimaryExpression)1460 *NotPrimaryExpression = true;1461 Res = ParseCXXDeleteExpression(false, Tok.getLocation());1462 AllowSuffix = false;1463 break;1464 1465 case tok::kw_requires: // [C++2a] requires-expression1466 Res = ParseRequiresExpression();1467 AllowSuffix = false;1468 break;1469 1470 case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')'1471 if (NotPrimaryExpression)1472 *NotPrimaryExpression = true;1473 Diag(Tok, diag::warn_cxx98_compat_noexcept_expr);1474 SourceLocation KeyLoc = ConsumeToken();1475 BalancedDelimiterTracker T(*this, tok::l_paren);1476 1477 if (T.expectAndConsume(diag::err_expected_lparen_after, "noexcept"))1478 return ExprError();1479 // C++11 [expr.unary.noexcept]p1:1480 // The noexcept operator determines whether the evaluation of its operand,1481 // which is an unevaluated operand, can throw an exception.1482 EnterExpressionEvaluationContext Unevaluated(1483 Actions, Sema::ExpressionEvaluationContext::Unevaluated);1484 Res = ParseExpression();1485 1486 T.consumeClose();1487 1488 if (!Res.isInvalid())1489 Res = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(), Res.get(),1490 T.getCloseLocation());1491 AllowSuffix = false;1492 break;1493 }1494 1495#define TYPE_TRAIT(N,Spelling,K) \1496 case tok::kw_##Spelling:1497#include "clang/Basic/TokenKinds.def"1498 Res = ParseTypeTrait();1499 break;1500 1501 case tok::kw___array_rank:1502 case tok::kw___array_extent:1503 if (NotPrimaryExpression)1504 *NotPrimaryExpression = true;1505 Res = ParseArrayTypeTrait();1506 break;1507 1508 case tok::kw___builtin_ptrauth_type_discriminator:1509 return ParseBuiltinPtrauthTypeDiscriminator();1510 1511 case tok::kw___is_lvalue_expr:1512 case tok::kw___is_rvalue_expr:1513 if (NotPrimaryExpression)1514 *NotPrimaryExpression = true;1515 Res = ParseExpressionTrait();1516 break;1517 1518 case tok::at: {1519 if (NotPrimaryExpression)1520 *NotPrimaryExpression = true;1521 SourceLocation AtLoc = ConsumeToken();1522 return ParseObjCAtExpression(AtLoc);1523 }1524 case tok::caret:1525 Res = ParseBlockLiteralExpression();1526 break;1527 case tok::code_completion: {1528 cutOffParsing();1529 Actions.CodeCompletion().CodeCompleteExpression(1530 getCurScope(), PreferredType.get(Tok.getLocation()));1531 return ExprError();1532 }1533#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:1534#include "clang/Basic/TransformTypeTraits.def"1535 // HACK: libstdc++ uses some of the transform-type-traits as alias1536 // templates, so we need to work around this.1537 if (!NextToken().is(tok::l_paren)) {1538 Tok.setKind(tok::identifier);1539 Diag(Tok, diag::ext_keyword_as_ident)1540 << Tok.getIdentifierInfo()->getName() << 0;1541 goto ParseIdentifier;1542 }1543 goto ExpectedExpression;1544 case tok::l_square:1545 if (getLangOpts().CPlusPlus) {1546 if (getLangOpts().ObjC) {1547 // C++11 lambda expressions and Objective-C message sends both start with a1548 // square bracket. There are three possibilities here:1549 // we have a valid lambda expression, we have an invalid lambda1550 // expression, or we have something that doesn't appear to be a lambda.1551 // If we're in the last case, we fall back to ParseObjCMessageExpression.1552 Res = TryParseLambdaExpression();1553 if (!Res.isInvalid() && !Res.get()) {1554 // We assume Objective-C++ message expressions are not1555 // primary-expressions.1556 if (NotPrimaryExpression)1557 *NotPrimaryExpression = true;1558 Res = ParseObjCMessageExpression();1559 }1560 break;1561 }1562 Res = ParseLambdaExpression();1563 break;1564 }1565 if (getLangOpts().ObjC) {1566 Res = ParseObjCMessageExpression();1567 break;1568 }1569 [[fallthrough]];1570 default:1571 ExpectedExpression:1572 NotCastExpr = true;1573 return ExprError();1574 }1575 1576 // Check to see whether Res is a function designator only. If it is and we1577 // are compiling for OpenCL, we need to return an error as this implies1578 // that the address of the function is being taken, which is illegal in CL.1579 1580 if (ParseKind == CastParseKind::PrimaryExprOnly)1581 // This is strictly a primary-expression - no postfix-expr pieces should be1582 // parsed.1583 return Res;1584 1585 if (!AllowSuffix) {1586 // FIXME: Don't parse a primary-expression suffix if we encountered a parse1587 // error already.1588 if (Res.isInvalid())1589 return Res;1590 1591 switch (Tok.getKind()) {1592 case tok::l_square:1593 case tok::l_paren:1594 case tok::plusplus:1595 case tok::minusminus:1596 // "expected ';'" or similar is probably the right diagnostic here. Let1597 // the caller decide what to do.1598 if (Tok.isAtStartOfLine())1599 return Res;1600 1601 [[fallthrough]];1602 case tok::period:1603 case tok::arrow:1604 break;1605 1606 default:1607 return Res;1608 }1609 1610 // This was a unary-expression for which a postfix-expression suffix is1611 // not permitted by the grammar (eg, a sizeof expression or1612 // new-expression or similar). Diagnose but parse the suffix anyway.1613 Diag(Tok.getLocation(), diag::err_postfix_after_unary_requires_parens)1614 << Tok.getKind() << Res.get()->getSourceRange()1615 << FixItHint::CreateInsertion(Res.get()->getBeginLoc(), "(")1616 << FixItHint::CreateInsertion(PP.getLocForEndOfToken(PrevTokLocation),1617 ")");1618 }1619 1620 // These can be followed by postfix-expr pieces.1621 PreferredType = SavedType;1622 Res = ParsePostfixExpressionSuffix(Res);1623 if (getLangOpts().OpenCL &&1624 !getActions().getOpenCLOptions().isAvailableOption(1625 "__cl_clang_function_pointers", getLangOpts()))1626 if (Expr *PostfixExpr = Res.get()) {1627 QualType Ty = PostfixExpr->getType();1628 if (!Ty.isNull() && Ty->isFunctionType()) {1629 Diag(PostfixExpr->getExprLoc(),1630 diag::err_opencl_taking_function_address_parser);1631 return ExprError();1632 }1633 }1634 1635 return Res;1636}1637 1638ExprResult1639Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {1640 // Now that the primary-expression piece of the postfix-expression has been1641 // parsed, see if there are any postfix-expression pieces here.1642 SourceLocation Loc;1643 auto SavedType = PreferredType;1644 while (true) {1645 // Each iteration relies on preferred type for the whole expression.1646 PreferredType = SavedType;1647 switch (Tok.getKind()) {1648 case tok::code_completion:1649 if (InMessageExpression)1650 return LHS;1651 1652 cutOffParsing();1653 Actions.CodeCompletion().CodeCompletePostfixExpression(1654 getCurScope(), LHS, PreferredType.get(Tok.getLocation()));1655 return ExprError();1656 1657 case tok::identifier:1658 // If we see identifier: after an expression, and we're not already in a1659 // message send, then this is probably a message send with a missing1660 // opening bracket '['.1661 if (getLangOpts().ObjC && !InMessageExpression &&1662 (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {1663 LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),1664 nullptr, LHS.get());1665 break;1666 }1667 // Fall through; this isn't a message send.1668 [[fallthrough]];1669 1670 default: // Not a postfix-expression suffix.1671 return LHS;1672 case tok::l_square: { // postfix-expression: p-e '[' expression ']'1673 // If we have a array postfix expression that starts on a new line and1674 // Objective-C is enabled, it is highly likely that the user forgot a1675 // semicolon after the base expression and that the array postfix-expr is1676 // actually another message send. In this case, do some look-ahead to see1677 // if the contents of the square brackets are obviously not a valid1678 // expression and recover by pretending there is no suffix.1679 if (getLangOpts().ObjC && Tok.isAtStartOfLine() &&1680 isSimpleObjCMessageExpression())1681 return LHS;1682 1683 // Reject array indices starting with a lambda-expression. '[[' is1684 // reserved for attributes.1685 if (CheckProhibitedCXX11Attribute()) {1686 return ExprError();1687 }1688 BalancedDelimiterTracker T(*this, tok::l_square);1689 T.consumeOpen();1690 Loc = T.getOpenLocation();1691 ExprResult Length, Stride;1692 SourceLocation ColonLocFirst, ColonLocSecond;1693 ExprVector ArgExprs;1694 bool HasError = false;1695 PreferredType.enterSubscript(Actions, Tok.getLocation(), LHS.get());1696 1697 // We try to parse a list of indexes in all language mode first1698 // and, in we find 0 or one index, we try to parse an OpenMP/OpenACC array1699 // section. This allow us to support C++23 multi dimensional subscript and1700 // OpenMP/OpenACC sections in the same language mode.1701 if ((!getLangOpts().OpenMP && !AllowOpenACCArraySections) ||1702 Tok.isNot(tok::colon)) {1703 if (!getLangOpts().CPlusPlus23) {1704 ExprResult Idx;1705 if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {1706 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);1707 Idx = ParseBraceInitializer();1708 } else {1709 Idx = ParseExpression(); // May be a comma expression1710 }1711 if (Idx.isInvalid()) {1712 HasError = true;1713 } else {1714 ArgExprs.push_back(Idx.get());1715 }1716 } else if (Tok.isNot(tok::r_square)) {1717 if (ParseExpressionList(ArgExprs)) {1718 HasError = true;1719 }1720 }1721 }1722 1723 // Handle OpenACC first, since 'AllowOpenACCArraySections' is only enabled1724 // when actively parsing a 'var' in a 'var-list' during clause/'cache'1725 // parsing, so it is the most specific, and best allows us to handle1726 // OpenACC and OpenMP at the same time.1727 if (ArgExprs.size() <= 1 && AllowOpenACCArraySections) {1728 ColonProtectionRAIIObject RAII(*this);1729 if (Tok.is(tok::colon)) {1730 // Consume ':'1731 ColonLocFirst = ConsumeToken();1732 if (Tok.isNot(tok::r_square))1733 Length = ParseExpression();1734 }1735 } else if (ArgExprs.size() <= 1 && getLangOpts().OpenMP) {1736 ColonProtectionRAIIObject RAII(*this);1737 if (Tok.is(tok::colon)) {1738 // Consume ':'1739 ColonLocFirst = ConsumeToken();1740 if (Tok.isNot(tok::r_square) &&1741 (getLangOpts().OpenMP < 50 ||1742 ((Tok.isNot(tok::colon) && getLangOpts().OpenMP >= 50)))) {1743 Length = ParseExpression();1744 }1745 }1746 if (getLangOpts().OpenMP >= 50 &&1747 (OMPClauseKind == llvm::omp::Clause::OMPC_to ||1748 OMPClauseKind == llvm::omp::Clause::OMPC_from) &&1749 Tok.is(tok::colon)) {1750 // Consume ':'1751 ColonLocSecond = ConsumeToken();1752 if (Tok.isNot(tok::r_square)) {1753 Stride = ParseExpression();1754 }1755 }1756 }1757 1758 SourceLocation RLoc = Tok.getLocation();1759 if (!LHS.isInvalid() && !HasError && !Length.isInvalid() &&1760 !Stride.isInvalid() && Tok.is(tok::r_square)) {1761 if (ColonLocFirst.isValid() || ColonLocSecond.isValid()) {1762 // Like above, AllowOpenACCArraySections is 'more specific' and only1763 // enabled when actively parsing a 'var' in a 'var-list' during1764 // clause/'cache' construct parsing, so it is more specific. So we1765 // should do it first, so that the correct node gets created.1766 if (AllowOpenACCArraySections) {1767 assert(!Stride.isUsable() && !ColonLocSecond.isValid() &&1768 "Stride/second colon not allowed for OpenACC");1769 LHS = Actions.OpenACC().ActOnArraySectionExpr(1770 LHS.get(), Loc, ArgExprs.empty() ? nullptr : ArgExprs[0],1771 ColonLocFirst, Length.get(), RLoc);1772 } else {1773 LHS = Actions.OpenMP().ActOnOMPArraySectionExpr(1774 LHS.get(), Loc, ArgExprs.empty() ? nullptr : ArgExprs[0],1775 ColonLocFirst, ColonLocSecond, Length.get(), Stride.get(),1776 RLoc);1777 }1778 } else {1779 LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc,1780 ArgExprs, RLoc);1781 }1782 } else {1783 LHS = ExprError();1784 }1785 1786 // Match the ']'.1787 T.consumeClose();1788 break;1789 }1790 1791 case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'1792 case tok::lesslessless: { // p-e: p-e '<<<' argument-expression-list '>>>'1793 // '(' argument-expression-list[opt] ')'1794 tok::TokenKind OpKind = Tok.getKind();1795 InMessageExpressionRAIIObject InMessage(*this, false);1796 1797 Expr *ExecConfig = nullptr;1798 1799 BalancedDelimiterTracker PT(*this, tok::l_paren);1800 1801 if (OpKind == tok::lesslessless) {1802 ExprVector ExecConfigExprs;1803 SourceLocation OpenLoc = ConsumeToken();1804 1805 if (ParseSimpleExpressionList(ExecConfigExprs)) {1806 LHS = ExprError();1807 }1808 1809 SourceLocation CloseLoc;1810 if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) {1811 } else if (LHS.isInvalid()) {1812 SkipUntil(tok::greatergreatergreater, StopAtSemi);1813 } else {1814 // There was an error closing the brackets1815 Diag(Tok, diag::err_expected) << tok::greatergreatergreater;1816 Diag(OpenLoc, diag::note_matching) << tok::lesslessless;1817 SkipUntil(tok::greatergreatergreater, StopAtSemi);1818 LHS = ExprError();1819 }1820 1821 if (!LHS.isInvalid()) {1822 if (ExpectAndConsume(tok::l_paren))1823 LHS = ExprError();1824 else1825 Loc = PrevTokLocation;1826 }1827 1828 if (!LHS.isInvalid()) {1829 ExprResult ECResult = Actions.CUDA().ActOnExecConfigExpr(1830 getCurScope(), OpenLoc, ExecConfigExprs, CloseLoc);1831 if (ECResult.isInvalid())1832 LHS = ExprError();1833 else1834 ExecConfig = ECResult.get();1835 }1836 } else {1837 PT.consumeOpen();1838 Loc = PT.getOpenLocation();1839 }1840 1841 ExprVector ArgExprs;1842 auto RunSignatureHelp = [&]() -> QualType {1843 QualType PreferredType =1844 Actions.CodeCompletion().ProduceCallSignatureHelp(1845 LHS.get(), ArgExprs, PT.getOpenLocation());1846 CalledSignatureHelp = true;1847 return PreferredType;1848 };1849 bool ExpressionListIsInvalid = false;1850 if (OpKind == tok::l_paren || !LHS.isInvalid()) {1851 if (Tok.isNot(tok::r_paren)) {1852 if ((ExpressionListIsInvalid = ParseExpressionList(ArgExprs, [&] {1853 PreferredType.enterFunctionArgument(Tok.getLocation(),1854 RunSignatureHelp);1855 }))) {1856 // If we got an error when parsing expression list, we don't call1857 // the CodeCompleteCall handler inside the parser. So call it here1858 // to make sure we get overload suggestions even when we are in the1859 // middle of a parameter.1860 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)1861 RunSignatureHelp();1862 }1863 }1864 }1865 1866 // Match the ')'.1867 if (LHS.isInvalid()) {1868 SkipUntil(tok::r_paren, StopAtSemi);1869 } else if (ExpressionListIsInvalid) {1870 Expr *Fn = LHS.get();1871 ArgExprs.insert(ArgExprs.begin(), Fn);1872 LHS = Actions.CreateRecoveryExpr(Fn->getBeginLoc(), Tok.getLocation(),1873 ArgExprs);1874 SkipUntil(tok::r_paren, StopAtSemi);1875 } else if (Tok.isNot(tok::r_paren)) {1876 bool HadErrors = false;1877 if (LHS.get()->containsErrors())1878 HadErrors = true;1879 for (auto &E : ArgExprs)1880 if (E->containsErrors())1881 HadErrors = true;1882 // If there were errors in the LHS or ArgExprs, call SkipUntil instead1883 // of PT.consumeClose() to avoid emitting extra diagnostics for the1884 // unmatched l_paren.1885 if (HadErrors)1886 SkipUntil(tok::r_paren, StopAtSemi);1887 else1888 PT.consumeClose();1889 LHS = ExprError();1890 } else {1891 Expr *Fn = LHS.get();1892 SourceLocation RParLoc = Tok.getLocation();1893 LHS = Actions.ActOnCallExpr(getCurScope(), Fn, Loc, ArgExprs, RParLoc,1894 ExecConfig);1895 if (LHS.isInvalid()) {1896 ArgExprs.insert(ArgExprs.begin(), Fn);1897 LHS =1898 Actions.CreateRecoveryExpr(Fn->getBeginLoc(), RParLoc, ArgExprs);1899 }1900 PT.consumeClose();1901 }1902 1903 break;1904 }1905 case tok::arrow:1906 case tok::period: {1907 // postfix-expression: p-e '->' template[opt] id-expression1908 // postfix-expression: p-e '.' template[opt] id-expression1909 tok::TokenKind OpKind = Tok.getKind();1910 SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token.1911 1912 CXXScopeSpec SS;1913 ParsedType ObjectType;1914 bool MayBePseudoDestructor = false;1915 Expr* OrigLHS = !LHS.isInvalid() ? LHS.get() : nullptr;1916 1917 PreferredType.enterMemAccess(Actions, Tok.getLocation(), OrigLHS);1918 1919 if (getLangOpts().CPlusPlus && !LHS.isInvalid()) {1920 Expr *Base = OrigLHS;1921 const Type* BaseType = Base->getType().getTypePtrOrNull();1922 if (BaseType && Tok.is(tok::l_paren) &&1923 (BaseType->isFunctionType() ||1924 BaseType->isSpecificPlaceholderType(BuiltinType::BoundMember))) {1925 Diag(OpLoc, diag::err_function_is_not_record)1926 << OpKind << Base->getSourceRange()1927 << FixItHint::CreateRemoval(OpLoc);1928 return ParsePostfixExpressionSuffix(Base);1929 }1930 1931 LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), Base, OpLoc,1932 OpKind, ObjectType,1933 MayBePseudoDestructor);1934 if (LHS.isInvalid()) {1935 // Clang will try to perform expression based completion as a1936 // fallback, which is confusing in case of member references. So we1937 // stop here without any completions.1938 if (Tok.is(tok::code_completion)) {1939 cutOffParsing();1940 return ExprError();1941 }1942 break;1943 }1944 ParseOptionalCXXScopeSpecifier(1945 SS, ObjectType, LHS.get() && LHS.get()->containsErrors(),1946 /*EnteringContext=*/false, &MayBePseudoDestructor);1947 if (SS.isNotEmpty())1948 ObjectType = nullptr;1949 }1950 1951 if (Tok.is(tok::code_completion)) {1952 tok::TokenKind CorrectedOpKind =1953 OpKind == tok::arrow ? tok::period : tok::arrow;1954 ExprResult CorrectedLHS(/*Invalid=*/true);1955 if (getLangOpts().CPlusPlus && OrigLHS) {1956 // FIXME: Creating a TentativeAnalysisScope from outside Sema is a1957 // hack.1958 Sema::TentativeAnalysisScope Trap(Actions);1959 CorrectedLHS = Actions.ActOnStartCXXMemberReference(1960 getCurScope(), OrigLHS, OpLoc, CorrectedOpKind, ObjectType,1961 MayBePseudoDestructor);1962 }1963 1964 Expr *Base = LHS.get();1965 Expr *CorrectedBase = CorrectedLHS.get();1966 if (!CorrectedBase && !getLangOpts().CPlusPlus)1967 CorrectedBase = Base;1968 1969 // Code completion for a member access expression.1970 cutOffParsing();1971 Actions.CodeCompletion().CodeCompleteMemberReferenceExpr(1972 getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow,1973 Base && ExprStatementTokLoc == Base->getBeginLoc(),1974 PreferredType.get(Tok.getLocation()));1975 1976 return ExprError();1977 }1978 1979 if (MayBePseudoDestructor && !LHS.isInvalid()) {1980 LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,1981 ObjectType);1982 break;1983 }1984 1985 // Either the action has told us that this cannot be a1986 // pseudo-destructor expression (based on the type of base1987 // expression), or we didn't see a '~' in the right place. We1988 // can still parse a destructor name here, but in that case it1989 // names a real destructor.1990 // Allow explicit constructor calls in Microsoft mode.1991 // FIXME: Add support for explicit call of template constructor.1992 SourceLocation TemplateKWLoc;1993 UnqualifiedId Name;1994 if (getLangOpts().ObjC && OpKind == tok::period &&1995 Tok.is(tok::kw_class)) {1996 // Objective-C++:1997 // After a '.' in a member access expression, treat the keyword1998 // 'class' as if it were an identifier.1999 //2000 // This hack allows property access to the 'class' method because it is2001 // such a common method name. For other C++ keywords that are2002 // Objective-C method names, one must use the message send syntax.2003 IdentifierInfo *Id = Tok.getIdentifierInfo();2004 SourceLocation Loc = ConsumeToken();2005 Name.setIdentifier(Id, Loc);2006 } else if (ParseUnqualifiedId(2007 SS, ObjectType, LHS.get() && LHS.get()->containsErrors(),2008 /*EnteringContext=*/false,2009 /*AllowDestructorName=*/true,2010 /*AllowConstructorName=*/2011 getLangOpts().MicrosoftExt && SS.isNotEmpty(),2012 /*AllowDeductionGuide=*/false, &TemplateKWLoc, Name)) {2013 LHS = ExprError();2014 }2015 2016 if (!LHS.isInvalid())2017 LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,2018 OpKind, SS, TemplateKWLoc, Name,2019 CurParsedObjCImpl ? CurParsedObjCImpl->Dcl2020 : nullptr);2021 if (!LHS.isInvalid()) {2022 if (Tok.is(tok::less))2023 checkPotentialAngleBracket(LHS);2024 } else if (OrigLHS && Name.isValid()) {2025 // Preserve the LHS if the RHS is an invalid member.2026 LHS = Actions.CreateRecoveryExpr(OrigLHS->getBeginLoc(),2027 Name.getEndLoc(), {OrigLHS});2028 }2029 break;2030 }2031 case tok::plusplus: // postfix-expression: postfix-expression '++'2032 case tok::minusminus: // postfix-expression: postfix-expression '--'2033 if (!LHS.isInvalid()) {2034 Expr *Arg = LHS.get();2035 LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(),2036 Tok.getKind(), Arg);2037 if (LHS.isInvalid())2038 LHS = Actions.CreateRecoveryExpr(Arg->getBeginLoc(),2039 Tok.getLocation(), Arg);2040 }2041 ConsumeToken();2042 break;2043 }2044 }2045}2046 2047ExprResult2048Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,2049 bool &isCastExpr,2050 ParsedType &CastTy,2051 SourceRange &CastRange) {2052 2053 assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual, tok::kw_sizeof,2054 tok::kw___datasizeof, tok::kw___alignof, tok::kw_alignof,2055 tok::kw__Alignof, tok::kw_vec_step,2056 tok::kw___builtin_omp_required_simd_align,2057 tok::kw___builtin_vectorelements, tok::kw__Countof) &&2058 "Not a typeof/sizeof/alignof/vec_step expression!");2059 2060 ExprResult Operand;2061 2062 // If the operand doesn't start with an '(', it must be an expression.2063 if (Tok.isNot(tok::l_paren)) {2064 // If construct allows a form without parenthesis, user may forget to put2065 // pathenthesis around type name.2066 if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,2067 tok::kw_alignof, tok::kw__Alignof)) {2068 if (isTypeIdUnambiguously()) {2069 DeclSpec DS(AttrFactory);2070 ParseSpecifierQualifierList(DS);2071 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),2072 DeclaratorContext::TypeName);2073 ParseDeclarator(DeclaratorInfo);2074 2075 SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation());2076 SourceLocation RParenLoc = PP.getLocForEndOfToken(PrevTokLocation);2077 if (LParenLoc.isInvalid() || RParenLoc.isInvalid()) {2078 Diag(OpTok.getLocation(),2079 diag::err_expected_parentheses_around_typename)2080 << OpTok.getName();2081 } else {2082 Diag(LParenLoc, diag::err_expected_parentheses_around_typename)2083 << OpTok.getName() << FixItHint::CreateInsertion(LParenLoc, "(")2084 << FixItHint::CreateInsertion(RParenLoc, ")");2085 }2086 isCastExpr = true;2087 return ExprEmpty();2088 }2089 }2090 2091 isCastExpr = false;2092 if (OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) &&2093 !getLangOpts().CPlusPlus) {2094 Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo()2095 << tok::l_paren;2096 return ExprError();2097 }2098 2099 // If we're parsing a chain that consists of keywords that could be2100 // followed by a non-parenthesized expression, BalancedDelimiterTracker2101 // is not going to help when the nesting is too deep. In this corner case2102 // we continue to parse with sufficient stack space to avoid crashing.2103 if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,2104 tok::kw_alignof, tok::kw__Alignof, tok::kw__Countof) &&2105 Tok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,2106 tok::kw_alignof, tok::kw__Alignof, tok::kw__Countof))2107 Actions.runWithSufficientStackSpace(Tok.getLocation(), [&] {2108 Operand = ParseCastExpression(CastParseKind::UnaryExprOnly);2109 });2110 else2111 Operand = ParseCastExpression(CastParseKind::UnaryExprOnly);2112 } else {2113 // If it starts with a '(', we know that it is either a parenthesized2114 // type-name, or it is a unary-expression that starts with a compound2115 // literal, or starts with a primary-expression that is a parenthesized2116 // expression. Most unary operators have an expression form without parens2117 // as part of the grammar for the operator, and a type form with the parens2118 // as part of the grammar for the operator. However, typeof and2119 // typeof_unqual require parens for both forms. This means that we *know*2120 // that the open and close parens cannot be part of a cast expression,2121 // which means we definitely are not parsing a compound literal expression.2122 // This disambiguates a case like enum E : typeof(int) { }; where we've2123 // parsed typeof and need to handle the (int){} tokens properly despite2124 // them looking like a compound literal, as in sizeof (int){}; where the2125 // parens could be part of a parenthesized type name or for a cast2126 // expression of some kind.2127 bool ParenKnownToBeNonCast =2128 OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual);2129 ParenParseOption ExprType = ParenParseOption::CastExpr;2130 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;2131 2132 Operand = ParseParenExpression(2133 ExprType, /*StopIfCastExr=*/true,2134 ParenKnownToBeNonCast ? ParenExprKind::PartOfOperator2135 : ParenExprKind::Unknown,2136 TypoCorrectionTypeBehavior::AllowBoth, CastTy, RParenLoc);2137 CastRange = SourceRange(LParenLoc, RParenLoc);2138 2139 // If ParseParenExpression parsed a '(typename)' sequence only, then this is2140 // a type.2141 if (ExprType == ParenParseOption::CastExpr) {2142 isCastExpr = true;2143 return ExprEmpty();2144 }2145 2146 if (getLangOpts().CPlusPlus ||2147 !OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual)) {2148 // GNU typeof in C requires the expression to be parenthesized. Not so for2149 // sizeof/alignof or in C++. Therefore, the parenthesized expression is2150 // the start of a unary-expression, but doesn't include any postfix2151 // pieces. Parse these now if present.2152 if (!Operand.isInvalid())2153 Operand = ParsePostfixExpressionSuffix(Operand.get());2154 }2155 }2156 2157 // If we get here, the operand to the typeof/sizeof/alignof was an expression.2158 isCastExpr = false;2159 return Operand;2160}2161 2162ExprResult Parser::ParseSYCLUniqueStableNameExpression() {2163 assert(Tok.is(tok::kw___builtin_sycl_unique_stable_name) &&2164 "Not __builtin_sycl_unique_stable_name");2165 2166 SourceLocation OpLoc = ConsumeToken();2167 BalancedDelimiterTracker T(*this, tok::l_paren);2168 2169 // __builtin_sycl_unique_stable_name expressions are always parenthesized.2170 if (T.expectAndConsume(diag::err_expected_lparen_after,2171 "__builtin_sycl_unique_stable_name"))2172 return ExprError();2173 2174 TypeResult Ty = ParseTypeName();2175 2176 if (Ty.isInvalid()) {2177 T.skipToEnd();2178 return ExprError();2179 }2180 2181 if (T.consumeClose())2182 return ExprError();2183 2184 return Actions.SYCL().ActOnUniqueStableNameExpr(2185 OpLoc, T.getOpenLocation(), T.getCloseLocation(), Ty.get());2186}2187 2188ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {2189 assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,2190 tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step,2191 tok::kw___builtin_omp_required_simd_align,2192 tok::kw___builtin_vectorelements, tok::kw__Countof) &&2193 "Not a sizeof/alignof/vec_step expression!");2194 Token OpTok = Tok;2195 ConsumeToken();2196 2197 // [C++11] 'sizeof' '...' '(' identifier ')'2198 if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) {2199 SourceLocation EllipsisLoc = ConsumeToken();2200 SourceLocation LParenLoc, RParenLoc;2201 IdentifierInfo *Name = nullptr;2202 SourceLocation NameLoc;2203 if (Tok.is(tok::l_paren)) {2204 BalancedDelimiterTracker T(*this, tok::l_paren);2205 T.consumeOpen();2206 LParenLoc = T.getOpenLocation();2207 if (Tok.is(tok::identifier)) {2208 Name = Tok.getIdentifierInfo();2209 NameLoc = ConsumeToken();2210 T.consumeClose();2211 RParenLoc = T.getCloseLocation();2212 if (RParenLoc.isInvalid())2213 RParenLoc = PP.getLocForEndOfToken(NameLoc);2214 } else {2215 Diag(Tok, diag::err_expected_parameter_pack);2216 SkipUntil(tok::r_paren, StopAtSemi);2217 }2218 } else if (Tok.is(tok::identifier)) {2219 Name = Tok.getIdentifierInfo();2220 NameLoc = ConsumeToken();2221 LParenLoc = PP.getLocForEndOfToken(EllipsisLoc);2222 RParenLoc = PP.getLocForEndOfToken(NameLoc);2223 Diag(LParenLoc, diag::err_paren_sizeof_parameter_pack)2224 << Name2225 << FixItHint::CreateInsertion(LParenLoc, "(")2226 << FixItHint::CreateInsertion(RParenLoc, ")");2227 } else {2228 Diag(Tok, diag::err_sizeof_parameter_pack);2229 }2230 2231 if (!Name)2232 return ExprError();2233 2234 EnterExpressionEvaluationContext Unevaluated(2235 Actions, Sema::ExpressionEvaluationContext::Unevaluated,2236 Sema::ReuseLambdaContextDecl);2237 2238 return Actions.ActOnSizeofParameterPackExpr(getCurScope(),2239 OpTok.getLocation(),2240 *Name, NameLoc,2241 RParenLoc);2242 }2243 2244 if (getLangOpts().CPlusPlus &&2245 OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))2246 Diag(OpTok, diag::warn_cxx98_compat_alignof);2247 else if (getLangOpts().C23 && OpTok.is(tok::kw_alignof))2248 Diag(OpTok, diag::warn_c23_compat_keyword) << OpTok.getName();2249 else if (getLangOpts().C2y && OpTok.is(tok::kw__Countof))2250 Diag(OpTok, diag::warn_c2y_compat_keyword) << OpTok.getName();2251 2252 EnterExpressionEvaluationContext Unevaluated(2253 Actions, Sema::ExpressionEvaluationContext::Unevaluated,2254 Sema::ReuseLambdaContextDecl);2255 2256 bool isCastExpr;2257 ParsedType CastTy;2258 SourceRange CastRange;2259 ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok,2260 isCastExpr,2261 CastTy,2262 CastRange);2263 2264 UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;2265 switch (OpTok.getKind()) {2266 case tok::kw_alignof:2267 case tok::kw__Alignof:2268 ExprKind = UETT_AlignOf;2269 break;2270 case tok::kw___alignof:2271 ExprKind = UETT_PreferredAlignOf;2272 break;2273 case tok::kw_vec_step:2274 ExprKind = UETT_VecStep;2275 break;2276 case tok::kw___builtin_omp_required_simd_align:2277 ExprKind = UETT_OpenMPRequiredSimdAlign;2278 break;2279 case tok::kw___datasizeof:2280 ExprKind = UETT_DataSizeOf;2281 break;2282 case tok::kw___builtin_vectorelements:2283 ExprKind = UETT_VectorElements;2284 break;2285 case tok::kw__Countof:2286 ExprKind = UETT_CountOf;2287 assert(!getLangOpts().CPlusPlus && "_Countof in C++ mode?");2288 if (!getLangOpts().C2y)2289 Diag(OpTok, diag::ext_c2y_feature) << OpTok.getName();2290 break;2291 default:2292 break;2293 }2294 2295 if (isCastExpr)2296 return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),2297 ExprKind,2298 /*IsType=*/true,2299 CastTy.getAsOpaquePtr(),2300 CastRange);2301 2302 if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))2303 Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo();2304 2305 // If we get here, the operand to the sizeof/alignof was an expression.2306 if (!Operand.isInvalid())2307 Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),2308 ExprKind,2309 /*IsType=*/false,2310 Operand.get(),2311 CastRange);2312 return Operand;2313}2314 2315ExprResult Parser::ParseBuiltinPrimaryExpression() {2316 ExprResult Res;2317 const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();2318 2319 tok::TokenKind T = Tok.getKind();2320 SourceLocation StartLoc = ConsumeToken(); // Eat the builtin identifier.2321 2322 // All of these start with an open paren.2323 if (Tok.isNot(tok::l_paren))2324 return ExprError(Diag(Tok, diag::err_expected_after) << BuiltinII2325 << tok::l_paren);2326 2327 BalancedDelimiterTracker PT(*this, tok::l_paren);2328 PT.consumeOpen();2329 2330 // TODO: Build AST.2331 2332 switch (T) {2333 default: llvm_unreachable("Not a builtin primary expression!");2334 case tok::kw___builtin_va_arg: {2335 ExprResult Expr(ParseAssignmentExpression());2336 2337 if (ExpectAndConsume(tok::comma)) {2338 SkipUntil(tok::r_paren, StopAtSemi);2339 Expr = ExprError();2340 }2341 2342 TypeResult Ty = ParseTypeName();2343 2344 if (Tok.isNot(tok::r_paren)) {2345 Diag(Tok, diag::err_expected) << tok::r_paren;2346 Expr = ExprError();2347 }2348 2349 if (Expr.isInvalid() || Ty.isInvalid())2350 Res = ExprError();2351 else2352 Res = Actions.ActOnVAArg(StartLoc, Expr.get(), Ty.get(), ConsumeParen());2353 break;2354 }2355 case tok::kw___builtin_offsetof: {2356 SourceLocation TypeLoc = Tok.getLocation();2357 auto OOK = OffsetOfKind::Builtin;2358 if (Tok.getLocation().isMacroID()) {2359 StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(2360 Tok.getLocation(), PP.getSourceManager(), getLangOpts());2361 if (MacroName == "offsetof")2362 OOK = OffsetOfKind::Macro;2363 }2364 TypeResult Ty;2365 {2366 OffsetOfStateRAIIObject InOffsetof(*this, OOK);2367 Ty = ParseTypeName();2368 if (Ty.isInvalid()) {2369 SkipUntil(tok::r_paren, StopAtSemi);2370 return ExprError();2371 }2372 }2373 2374 if (ExpectAndConsume(tok::comma)) {2375 SkipUntil(tok::r_paren, StopAtSemi);2376 return ExprError();2377 }2378 2379 // We must have at least one identifier here.2380 if (Tok.isNot(tok::identifier)) {2381 Diag(Tok, diag::err_expected) << tok::identifier;2382 SkipUntil(tok::r_paren, StopAtSemi);2383 return ExprError();2384 }2385 2386 // Keep track of the various subcomponents we see.2387 SmallVector<Sema::OffsetOfComponent, 4> Comps;2388 2389 Comps.push_back(Sema::OffsetOfComponent());2390 Comps.back().isBrackets = false;2391 Comps.back().U.IdentInfo = Tok.getIdentifierInfo();2392 Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();2393 2394 // FIXME: This loop leaks the index expressions on error.2395 while (true) {2396 if (Tok.is(tok::period)) {2397 // offsetof-member-designator: offsetof-member-designator '.' identifier2398 Comps.push_back(Sema::OffsetOfComponent());2399 Comps.back().isBrackets = false;2400 Comps.back().LocStart = ConsumeToken();2401 2402 if (Tok.isNot(tok::identifier)) {2403 Diag(Tok, diag::err_expected) << tok::identifier;2404 SkipUntil(tok::r_paren, StopAtSemi);2405 return ExprError();2406 }2407 Comps.back().U.IdentInfo = Tok.getIdentifierInfo();2408 Comps.back().LocEnd = ConsumeToken();2409 } else if (Tok.is(tok::l_square)) {2410 if (CheckProhibitedCXX11Attribute())2411 return ExprError();2412 2413 // offsetof-member-designator: offsetof-member-design '[' expression ']'2414 Comps.push_back(Sema::OffsetOfComponent());2415 Comps.back().isBrackets = true;2416 BalancedDelimiterTracker ST(*this, tok::l_square);2417 ST.consumeOpen();2418 Comps.back().LocStart = ST.getOpenLocation();2419 Res = ParseExpression();2420 if (Res.isInvalid()) {2421 SkipUntil(tok::r_paren, StopAtSemi);2422 return Res;2423 }2424 Comps.back().U.E = Res.get();2425 2426 ST.consumeClose();2427 Comps.back().LocEnd = ST.getCloseLocation();2428 } else {2429 if (Tok.isNot(tok::r_paren)) {2430 PT.consumeClose();2431 Res = ExprError();2432 } else if (Ty.isInvalid()) {2433 Res = ExprError();2434 } else {2435 PT.consumeClose();2436 Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc,2437 Ty.get(), Comps,2438 PT.getCloseLocation());2439 }2440 break;2441 }2442 }2443 break;2444 }2445 case tok::kw___builtin_choose_expr: {2446 ExprResult Cond(ParseAssignmentExpression());2447 if (Cond.isInvalid()) {2448 SkipUntil(tok::r_paren, StopAtSemi);2449 return Cond;2450 }2451 if (ExpectAndConsume(tok::comma)) {2452 SkipUntil(tok::r_paren, StopAtSemi);2453 return ExprError();2454 }2455 2456 ExprResult Expr1(ParseAssignmentExpression());2457 if (Expr1.isInvalid()) {2458 SkipUntil(tok::r_paren, StopAtSemi);2459 return Expr1;2460 }2461 if (ExpectAndConsume(tok::comma)) {2462 SkipUntil(tok::r_paren, StopAtSemi);2463 return ExprError();2464 }2465 2466 ExprResult Expr2(ParseAssignmentExpression());2467 if (Expr2.isInvalid()) {2468 SkipUntil(tok::r_paren, StopAtSemi);2469 return Expr2;2470 }2471 if (Tok.isNot(tok::r_paren)) {2472 Diag(Tok, diag::err_expected) << tok::r_paren;2473 return ExprError();2474 }2475 Res = Actions.ActOnChooseExpr(StartLoc, Cond.get(), Expr1.get(),2476 Expr2.get(), ConsumeParen());2477 break;2478 }2479 case tok::kw___builtin_astype: {2480 // The first argument is an expression to be converted, followed by a comma.2481 ExprResult Expr(ParseAssignmentExpression());2482 if (Expr.isInvalid()) {2483 SkipUntil(tok::r_paren, StopAtSemi);2484 return ExprError();2485 }2486 2487 if (ExpectAndConsume(tok::comma)) {2488 SkipUntil(tok::r_paren, StopAtSemi);2489 return ExprError();2490 }2491 2492 // Second argument is the type to bitcast to.2493 TypeResult DestTy = ParseTypeName();2494 if (DestTy.isInvalid())2495 return ExprError();2496 2497 // Attempt to consume the r-paren.2498 if (Tok.isNot(tok::r_paren)) {2499 Diag(Tok, diag::err_expected) << tok::r_paren;2500 SkipUntil(tok::r_paren, StopAtSemi);2501 return ExprError();2502 }2503 2504 Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc,2505 ConsumeParen());2506 break;2507 }2508 case tok::kw___builtin_convertvector: {2509 // The first argument is an expression to be converted, followed by a comma.2510 ExprResult Expr(ParseAssignmentExpression());2511 if (Expr.isInvalid()) {2512 SkipUntil(tok::r_paren, StopAtSemi);2513 return ExprError();2514 }2515 2516 if (ExpectAndConsume(tok::comma)) {2517 SkipUntil(tok::r_paren, StopAtSemi);2518 return ExprError();2519 }2520 2521 // Second argument is the type to bitcast to.2522 TypeResult DestTy = ParseTypeName();2523 if (DestTy.isInvalid())2524 return ExprError();2525 2526 // Attempt to consume the r-paren.2527 if (Tok.isNot(tok::r_paren)) {2528 Diag(Tok, diag::err_expected) << tok::r_paren;2529 SkipUntil(tok::r_paren, StopAtSemi);2530 return ExprError();2531 }2532 2533 Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc,2534 ConsumeParen());2535 break;2536 }2537 case tok::kw___builtin_COLUMN:2538 case tok::kw___builtin_FILE:2539 case tok::kw___builtin_FILE_NAME:2540 case tok::kw___builtin_FUNCTION:2541 case tok::kw___builtin_FUNCSIG:2542 case tok::kw___builtin_LINE:2543 case tok::kw___builtin_source_location: {2544 // Attempt to consume the r-paren.2545 if (Tok.isNot(tok::r_paren)) {2546 Diag(Tok, diag::err_expected) << tok::r_paren;2547 SkipUntil(tok::r_paren, StopAtSemi);2548 return ExprError();2549 }2550 SourceLocIdentKind Kind = [&] {2551 switch (T) {2552 case tok::kw___builtin_FILE:2553 return SourceLocIdentKind::File;2554 case tok::kw___builtin_FILE_NAME:2555 return SourceLocIdentKind::FileName;2556 case tok::kw___builtin_FUNCTION:2557 return SourceLocIdentKind::Function;2558 case tok::kw___builtin_FUNCSIG:2559 return SourceLocIdentKind::FuncSig;2560 case tok::kw___builtin_LINE:2561 return SourceLocIdentKind::Line;2562 case tok::kw___builtin_COLUMN:2563 return SourceLocIdentKind::Column;2564 case tok::kw___builtin_source_location:2565 return SourceLocIdentKind::SourceLocStruct;2566 default:2567 llvm_unreachable("invalid keyword");2568 }2569 }();2570 Res = Actions.ActOnSourceLocExpr(Kind, StartLoc, ConsumeParen());2571 break;2572 }2573 }2574 2575 if (Res.isInvalid())2576 return ExprError();2577 2578 // These can be followed by postfix-expr pieces because they are2579 // primary-expressions.2580 return ParsePostfixExpressionSuffix(Res.get());2581}2582 2583bool Parser::tryParseOpenMPArrayShapingCastPart() {2584 assert(Tok.is(tok::l_square) && "Expected open bracket");2585 bool ErrorFound = true;2586 TentativeParsingAction TPA(*this);2587 do {2588 if (Tok.isNot(tok::l_square))2589 break;2590 // Consume '['2591 ConsumeBracket();2592 // Skip inner expression.2593 while (!SkipUntil(tok::r_square, tok::annot_pragma_openmp_end,2594 StopAtSemi | StopBeforeMatch))2595 ;2596 if (Tok.isNot(tok::r_square))2597 break;2598 // Consume ']'2599 ConsumeBracket();2600 // Found ')' - done.2601 if (Tok.is(tok::r_paren)) {2602 ErrorFound = false;2603 break;2604 }2605 } while (Tok.isNot(tok::annot_pragma_openmp_end));2606 TPA.Revert();2607 return !ErrorFound;2608}2609 2610ExprResult2611Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,2612 ParenExprKind ParenBehavior,2613 TypoCorrectionTypeBehavior CorrectionBehavior,2614 ParsedType &CastTy, SourceLocation &RParenLoc) {2615 assert(Tok.is(tok::l_paren) && "Not a paren expr!");2616 ColonProtectionRAIIObject ColonProtection(*this, false);2617 BalancedDelimiterTracker T(*this, tok::l_paren);2618 if (T.consumeOpen())2619 return ExprError();2620 SourceLocation OpenLoc = T.getOpenLocation();2621 2622 PreferredType.enterParenExpr(Tok.getLocation(), OpenLoc);2623 2624 ExprResult Result(true);2625 bool isAmbiguousTypeId;2626 CastTy = nullptr;2627 2628 if (Tok.is(tok::code_completion)) {2629 cutOffParsing();2630 Actions.CodeCompletion().CodeCompleteExpression(2631 getCurScope(), PreferredType.get(Tok.getLocation()),2632 /*IsParenthesized=*/ExprType >= ParenParseOption::CompoundLiteral);2633 return ExprError();2634 }2635 2636 // Diagnose use of bridge casts in non-arc mode.2637 bool BridgeCast = (getLangOpts().ObjC &&2638 Tok.isOneOf(tok::kw___bridge,2639 tok::kw___bridge_transfer,2640 tok::kw___bridge_retained,2641 tok::kw___bridge_retain));2642 if (BridgeCast && !getLangOpts().ObjCAutoRefCount) {2643 if (!TryConsumeToken(tok::kw___bridge)) {2644 StringRef BridgeCastName = Tok.getName();2645 SourceLocation BridgeKeywordLoc = ConsumeToken();2646 if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))2647 Diag(BridgeKeywordLoc, diag::warn_arc_bridge_cast_nonarc)2648 << BridgeCastName2649 << FixItHint::CreateReplacement(BridgeKeywordLoc, "");2650 }2651 BridgeCast = false;2652 }2653 2654 // None of these cases should fall through with an invalid Result2655 // unless they've already reported an error.2656 if (ExprType >= ParenParseOption::CompoundStmt && Tok.is(tok::l_brace)) {2657 Diag(Tok, OpenLoc.isMacroID() ? diag::ext_gnu_statement_expr_macro2658 : diag::ext_gnu_statement_expr);2659 2660 checkCompoundToken(OpenLoc, tok::l_paren, CompoundToken::StmtExprBegin);2661 2662 if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) {2663 Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope));2664 } else {2665 // Find the nearest non-record decl context. Variables declared in a2666 // statement expression behave as if they were declared in the enclosing2667 // function, block, or other code construct.2668 DeclContext *CodeDC = Actions.CurContext;2669 while (CodeDC->isRecord() || isa<EnumDecl>(CodeDC)) {2670 CodeDC = CodeDC->getParent();2671 assert(CodeDC && !CodeDC->isFileContext() &&2672 "statement expr not in code context");2673 }2674 Sema::ContextRAII SavedContext(Actions, CodeDC, /*NewThisContext=*/false);2675 2676 Actions.ActOnStartStmtExpr();2677 2678 StmtResult Stmt(ParseCompoundStatement(true));2679 ExprType = ParenParseOption::CompoundStmt;2680 2681 // If the substmt parsed correctly, build the AST node.2682 if (!Stmt.isInvalid()) {2683 Result = Actions.ActOnStmtExpr(getCurScope(), OpenLoc, Stmt.get(),2684 Tok.getLocation());2685 } else {2686 Actions.ActOnStmtExprError();2687 }2688 }2689 } else if (ExprType >= ParenParseOption::CompoundLiteral && BridgeCast) {2690 tok::TokenKind tokenKind = Tok.getKind();2691 SourceLocation BridgeKeywordLoc = ConsumeToken();2692 2693 // Parse an Objective-C ARC ownership cast expression.2694 ObjCBridgeCastKind Kind;2695 if (tokenKind == tok::kw___bridge)2696 Kind = OBC_Bridge;2697 else if (tokenKind == tok::kw___bridge_transfer)2698 Kind = OBC_BridgeTransfer;2699 else if (tokenKind == tok::kw___bridge_retained)2700 Kind = OBC_BridgeRetained;2701 else {2702 // As a hopefully temporary workaround, allow __bridge_retain as2703 // a synonym for __bridge_retained, but only in system headers.2704 assert(tokenKind == tok::kw___bridge_retain);2705 Kind = OBC_BridgeRetained;2706 if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))2707 Diag(BridgeKeywordLoc, diag::err_arc_bridge_retain)2708 << FixItHint::CreateReplacement(BridgeKeywordLoc,2709 "__bridge_retained");2710 }2711 2712 TypeResult Ty = ParseTypeName();2713 T.consumeClose();2714 ColonProtection.restore();2715 RParenLoc = T.getCloseLocation();2716 2717 PreferredType.enterTypeCast(Tok.getLocation(), Ty.get().get());2718 ExprResult SubExpr = ParseCastExpression(CastParseKind::AnyCastExpr);2719 2720 if (Ty.isInvalid() || SubExpr.isInvalid())2721 return ExprError();2722 2723 return Actions.ObjC().ActOnObjCBridgedCast(getCurScope(), OpenLoc, Kind,2724 BridgeKeywordLoc, Ty.get(),2725 RParenLoc, SubExpr.get());2726 } else if (ExprType >= ParenParseOption::CompoundLiteral &&2727 isTypeIdInParens(isAmbiguousTypeId)) {2728 2729 // Otherwise, this is a compound literal expression or cast expression.2730 2731 // In C++, if the type-id is ambiguous we disambiguate based on context.2732 // If stopIfCastExpr is true the context is a typeof/sizeof/alignof2733 // in which case we should treat it as type-id.2734 // if stopIfCastExpr is false, we need to determine the context past the2735 // parens, so we defer to ParseCXXAmbiguousParenExpression for that.2736 if (isAmbiguousTypeId && !StopIfCastExpr) {2737 ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T,2738 ColonProtection);2739 RParenLoc = T.getCloseLocation();2740 return res;2741 }2742 2743 // Parse the type declarator.2744 DeclSpec DS(AttrFactory);2745 ParseSpecifierQualifierList(DS);2746 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),2747 DeclaratorContext::TypeName);2748 ParseDeclarator(DeclaratorInfo);2749 2750 // If our type is followed by an identifier and either ':' or ']', then2751 // this is probably an Objective-C message send where the leading '[' is2752 // missing. Recover as if that were the case.2753 if (!DeclaratorInfo.isInvalidType() && Tok.is(tok::identifier) &&2754 !InMessageExpression && getLangOpts().ObjC &&2755 (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {2756 TypeResult Ty;2757 {2758 InMessageExpressionRAIIObject InMessage(*this, false);2759 Ty = Actions.ActOnTypeName(DeclaratorInfo);2760 }2761 Result = ParseObjCMessageExpressionBody(SourceLocation(),2762 SourceLocation(),2763 Ty.get(), nullptr);2764 } else {2765 // Match the ')'.2766 T.consumeClose();2767 ColonProtection.restore();2768 RParenLoc = T.getCloseLocation();2769 if (ParenBehavior == ParenExprKind::Unknown && Tok.is(tok::l_brace)) {2770 ExprType = ParenParseOption::CompoundLiteral;2771 TypeResult Ty;2772 {2773 InMessageExpressionRAIIObject InMessage(*this, false);2774 Ty = Actions.ActOnTypeName(DeclaratorInfo);2775 }2776 return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);2777 }2778 2779 if (ParenBehavior == ParenExprKind::Unknown && Tok.is(tok::l_paren)) {2780 // This could be OpenCL vector Literals2781 if (getLangOpts().OpenCL)2782 {2783 TypeResult Ty;2784 {2785 InMessageExpressionRAIIObject InMessage(*this, false);2786 Ty = Actions.ActOnTypeName(DeclaratorInfo);2787 }2788 if(Ty.isInvalid())2789 {2790 return ExprError();2791 }2792 QualType QT = Ty.get().get().getCanonicalType();2793 if (QT->isVectorType())2794 {2795 // We parsed '(' vector-type-name ')' followed by '('2796 2797 // Parse the cast-expression that follows it next.2798 // isVectorLiteral = true will make sure we don't parse any2799 // Postfix expression yet2800 Result = ParseCastExpression(2801 /*isUnaryExpression=*/CastParseKind::AnyCastExpr,2802 /*isAddressOfOperand=*/false,2803 TypoCorrectionTypeBehavior::AllowTypes,2804 /*isVectorLiteral=*/true);2805 2806 if (!Result.isInvalid()) {2807 Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,2808 DeclaratorInfo, CastTy,2809 RParenLoc, Result.get());2810 }2811 2812 // After we performed the cast we can check for postfix-expr pieces.2813 if (!Result.isInvalid()) {2814 Result = ParsePostfixExpressionSuffix(Result);2815 }2816 2817 return Result;2818 }2819 }2820 }2821 2822 if (ExprType == ParenParseOption::CastExpr) {2823 // We parsed '(' type-name ')' and the thing after it wasn't a '{'.2824 2825 if (DeclaratorInfo.isInvalidType())2826 return ExprError();2827 2828 // Note that this doesn't parse the subsequent cast-expression, it just2829 // returns the parsed type to the callee.2830 if (StopIfCastExpr) {2831 TypeResult Ty;2832 {2833 InMessageExpressionRAIIObject InMessage(*this, false);2834 Ty = Actions.ActOnTypeName(DeclaratorInfo);2835 }2836 CastTy = Ty.get();2837 return ExprResult();2838 }2839 2840 // Reject the cast of super idiom in ObjC.2841 if (Tok.is(tok::identifier) && getLangOpts().ObjC &&2842 Tok.getIdentifierInfo() == Ident_super &&2843 getCurScope()->isInObjcMethodScope() &&2844 GetLookAheadToken(1).isNot(tok::period)) {2845 Diag(Tok.getLocation(), diag::err_illegal_super_cast)2846 << SourceRange(OpenLoc, RParenLoc);2847 return ExprError();2848 }2849 2850 PreferredType.enterTypeCast(Tok.getLocation(), CastTy.get());2851 // Parse the cast-expression that follows it next.2852 // TODO: For cast expression with CastTy.2853 Result = ParseCastExpression(2854 /*isUnaryExpression=*/CastParseKind::AnyCastExpr,2855 /*isAddressOfOperand=*/false,2856 TypoCorrectionTypeBehavior::AllowTypes);2857 if (!Result.isInvalid()) {2858 Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,2859 DeclaratorInfo, CastTy,2860 RParenLoc, Result.get());2861 }2862 return Result;2863 }2864 2865 Diag(Tok, diag::err_expected_lbrace_in_compound_literal);2866 return ExprError();2867 }2868 } else if (ExprType >= ParenParseOption::FoldExpr && Tok.is(tok::ellipsis) &&2869 isFoldOperator(NextToken().getKind())) {2870 ExprType = ParenParseOption::FoldExpr;2871 return ParseFoldExpression(ExprResult(), T);2872 } else if (CorrectionBehavior == TypoCorrectionTypeBehavior::AllowTypes) {2873 // FIXME: This should not be predicated on typo correction behavior.2874 // Parse the expression-list.2875 InMessageExpressionRAIIObject InMessage(*this, false);2876 ExprVector ArgExprs;2877 2878 if (!ParseSimpleExpressionList(ArgExprs)) {2879 // FIXME: If we ever support comma expressions as operands to2880 // fold-expressions, we'll need to allow multiple ArgExprs here.2881 if (ExprType >= ParenParseOption::FoldExpr && ArgExprs.size() == 1 &&2882 isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {2883 ExprType = ParenParseOption::FoldExpr;2884 return ParseFoldExpression(ArgExprs[0], T);2885 }2886 2887 ExprType = ParenParseOption::SimpleExpr;2888 Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),2889 ArgExprs);2890 }2891 } else if (getLangOpts().OpenMP >= 50 && OpenMPDirectiveParsing &&2892 ExprType == ParenParseOption::CastExpr && Tok.is(tok::l_square) &&2893 tryParseOpenMPArrayShapingCastPart()) {2894 bool ErrorFound = false;2895 SmallVector<Expr *, 4> OMPDimensions;2896 SmallVector<SourceRange, 4> OMPBracketsRanges;2897 do {2898 BalancedDelimiterTracker TS(*this, tok::l_square);2899 TS.consumeOpen();2900 ExprResult NumElements = ParseExpression();2901 if (!NumElements.isUsable()) {2902 ErrorFound = true;2903 while (!SkipUntil(tok::r_square, tok::r_paren,2904 StopAtSemi | StopBeforeMatch))2905 ;2906 }2907 TS.consumeClose();2908 OMPDimensions.push_back(NumElements.get());2909 OMPBracketsRanges.push_back(TS.getRange());2910 } while (Tok.isNot(tok::r_paren));2911 // Match the ')'.2912 T.consumeClose();2913 RParenLoc = T.getCloseLocation();2914 Result = ParseAssignmentExpression();2915 if (ErrorFound) {2916 Result = ExprError();2917 } else if (!Result.isInvalid()) {2918 Result = Actions.OpenMP().ActOnOMPArrayShapingExpr(2919 Result.get(), OpenLoc, RParenLoc, OMPDimensions, OMPBracketsRanges);2920 }2921 return Result;2922 } else {2923 InMessageExpressionRAIIObject InMessage(*this, false);2924 2925 Result = ParseExpression(TypoCorrectionTypeBehavior::AllowBoth);2926 if (ExprType >= ParenParseOption::FoldExpr &&2927 isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {2928 ExprType = ParenParseOption::FoldExpr;2929 return ParseFoldExpression(Result, T);2930 }2931 ExprType = ParenParseOption::SimpleExpr;2932 2933 // Don't build a paren expression unless we actually match a ')'.2934 if (!Result.isInvalid() && Tok.is(tok::r_paren))2935 Result =2936 Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.get());2937 }2938 2939 // Match the ')'.2940 if (Result.isInvalid()) {2941 SkipUntil(tok::r_paren, StopAtSemi);2942 return ExprError();2943 }2944 2945 T.consumeClose();2946 RParenLoc = T.getCloseLocation();2947 return Result;2948}2949 2950ExprResult2951Parser::ParseCompoundLiteralExpression(ParsedType Ty,2952 SourceLocation LParenLoc,2953 SourceLocation RParenLoc) {2954 assert(Tok.is(tok::l_brace) && "Not a compound literal!");2955 if (!getLangOpts().C99) // Compound literals don't exist in C90.2956 Diag(LParenLoc, diag::ext_c99_compound_literal);2957 PreferredType.enterTypeCast(Tok.getLocation(), Ty.get());2958 ExprResult Result = ParseInitializer();2959 if (!Result.isInvalid() && Ty)2960 return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.get());2961 return Result;2962}2963 2964ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) {2965 return ParseStringLiteralExpression(AllowUserDefinedLiteral,2966 /*Unevaluated=*/false);2967}2968 2969ExprResult Parser::ParseUnevaluatedStringLiteralExpression() {2970 return ParseStringLiteralExpression(/*AllowUserDefinedLiteral=*/false,2971 /*Unevaluated=*/true);2972}2973 2974ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral,2975 bool Unevaluated) {2976 assert(tokenIsLikeStringLiteral(Tok, getLangOpts()) &&2977 "Not a string-literal-like token!");2978 2979 // String concatenation.2980 // Note: some keywords like __FUNCTION__ are not considered to be strings2981 // for concatenation purposes, unless Microsoft extensions are enabled.2982 SmallVector<Token, 4> StringToks;2983 2984 do {2985 StringToks.push_back(Tok);2986 ConsumeAnyToken();2987 } while (tokenIsLikeStringLiteral(Tok, getLangOpts()));2988 2989 if (Unevaluated) {2990 assert(!AllowUserDefinedLiteral && "UDL are always evaluated");2991 return Actions.ActOnUnevaluatedStringLiteral(StringToks);2992 }2993 2994 // Pass the set of string tokens, ready for concatenation, to the actions.2995 return Actions.ActOnStringLiteral(StringToks,2996 AllowUserDefinedLiteral ? getCurScope()2997 : nullptr);2998}2999 3000ExprResult Parser::ParseGenericSelectionExpression() {3001 assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected");3002 3003 diagnoseUseOfC11Keyword(Tok);3004 3005 SourceLocation KeyLoc = ConsumeToken();3006 BalancedDelimiterTracker T(*this, tok::l_paren);3007 if (T.expectAndConsume())3008 return ExprError();3009 3010 // We either have a controlling expression or we have a controlling type, and3011 // we need to figure out which it is.3012 TypeResult ControllingType;3013 ExprResult ControllingExpr;3014 if (isTypeIdForGenericSelection()) {3015 ControllingType = ParseTypeName();3016 if (ControllingType.isInvalid()) {3017 SkipUntil(tok::r_paren, StopAtSemi);3018 return ExprError();3019 }3020 const auto *LIT = cast<LocInfoType>(ControllingType.get().get());3021 SourceLocation Loc = LIT->getTypeSourceInfo()->getTypeLoc().getBeginLoc();3022 Diag(Loc, getLangOpts().C2y ? diag::warn_c2y_compat_generic_with_type_arg3023 : diag::ext_c2y_generic_with_type_arg);3024 } else {3025 // C11 6.5.1.1p3 "The controlling expression of a generic selection is3026 // not evaluated."3027 EnterExpressionEvaluationContext Unevaluated(3028 Actions, Sema::ExpressionEvaluationContext::Unevaluated);3029 ControllingExpr = ParseAssignmentExpression();3030 if (ControllingExpr.isInvalid()) {3031 SkipUntil(tok::r_paren, StopAtSemi);3032 return ExprError();3033 }3034 }3035 3036 if (ExpectAndConsume(tok::comma)) {3037 SkipUntil(tok::r_paren, StopAtSemi);3038 return ExprError();3039 }3040 3041 SourceLocation DefaultLoc;3042 SmallVector<ParsedType, 12> Types;3043 ExprVector Exprs;3044 do {3045 ParsedType Ty;3046 if (Tok.is(tok::kw_default)) {3047 // C11 6.5.1.1p2 "A generic selection shall have no more than one default3048 // generic association."3049 if (!DefaultLoc.isInvalid()) {3050 Diag(Tok, diag::err_duplicate_default_assoc);3051 Diag(DefaultLoc, diag::note_previous_default_assoc);3052 SkipUntil(tok::r_paren, StopAtSemi);3053 return ExprError();3054 }3055 DefaultLoc = ConsumeToken();3056 Ty = nullptr;3057 } else {3058 ColonProtectionRAIIObject X(*this);3059 TypeResult TR = ParseTypeName(nullptr, DeclaratorContext::Association);3060 if (TR.isInvalid()) {3061 SkipUntil(tok::r_paren, StopAtSemi);3062 return ExprError();3063 }3064 Ty = TR.get();3065 }3066 Types.push_back(Ty);3067 3068 if (ExpectAndConsume(tok::colon)) {3069 SkipUntil(tok::r_paren, StopAtSemi);3070 return ExprError();3071 }3072 3073 // FIXME: These expressions should be parsed in a potentially potentially3074 // evaluated context.3075 ExprResult ER = ParseAssignmentExpression();3076 if (ER.isInvalid()) {3077 SkipUntil(tok::r_paren, StopAtSemi);3078 return ExprError();3079 }3080 Exprs.push_back(ER.get());3081 } while (TryConsumeToken(tok::comma));3082 3083 T.consumeClose();3084 if (T.getCloseLocation().isInvalid())3085 return ExprError();3086 3087 void *ExprOrTy = ControllingExpr.isUsable()3088 ? ControllingExpr.get()3089 : ControllingType.get().getAsOpaquePtr();3090 3091 return Actions.ActOnGenericSelectionExpr(3092 KeyLoc, DefaultLoc, T.getCloseLocation(), ControllingExpr.isUsable(),3093 ExprOrTy, Types, Exprs);3094}3095 3096ExprResult Parser::ParseFoldExpression(ExprResult LHS,3097 BalancedDelimiterTracker &T) {3098 if (LHS.isInvalid()) {3099 T.skipToEnd();3100 return true;3101 }3102 3103 tok::TokenKind Kind = tok::unknown;3104 SourceLocation FirstOpLoc;3105 if (LHS.isUsable()) {3106 Kind = Tok.getKind();3107 assert(isFoldOperator(Kind) && "missing fold-operator");3108 FirstOpLoc = ConsumeToken();3109 }3110 3111 assert(Tok.is(tok::ellipsis) && "not a fold-expression");3112 SourceLocation EllipsisLoc = ConsumeToken();3113 3114 ExprResult RHS;3115 if (Tok.isNot(tok::r_paren)) {3116 if (!isFoldOperator(Tok.getKind()))3117 return Diag(Tok.getLocation(), diag::err_expected_fold_operator);3118 3119 if (Kind != tok::unknown && Tok.getKind() != Kind)3120 Diag(Tok.getLocation(), diag::err_fold_operator_mismatch)3121 << SourceRange(FirstOpLoc);3122 Kind = Tok.getKind();3123 ConsumeToken();3124 3125 RHS = ParseExpression();3126 if (RHS.isInvalid()) {3127 T.skipToEnd();3128 return true;3129 }3130 }3131 3132 Diag(EllipsisLoc, getLangOpts().CPlusPlus173133 ? diag::warn_cxx14_compat_fold_expression3134 : diag::ext_fold_expression);3135 3136 T.consumeClose();3137 return Actions.ActOnCXXFoldExpr(getCurScope(), T.getOpenLocation(), LHS.get(),3138 Kind, EllipsisLoc, RHS.get(),3139 T.getCloseLocation());3140}3141 3142void Parser::injectEmbedTokens() {3143 EmbedAnnotationData *Data =3144 reinterpret_cast<EmbedAnnotationData *>(Tok.getAnnotationValue());3145 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3146 Data->BinaryData.size() * 2 - 1),3147 Data->BinaryData.size() * 2 - 1);3148 unsigned I = 0;3149 for (auto &Byte : Data->BinaryData) {3150 Toks[I].startToken();3151 Toks[I].setKind(tok::binary_data);3152 Toks[I].setLocation(Tok.getLocation());3153 Toks[I].setLength(1);3154 Toks[I].setLiteralData(&Byte);3155 if (I != ((Data->BinaryData.size() - 1) * 2)) {3156 Toks[I + 1].startToken();3157 Toks[I + 1].setKind(tok::comma);3158 Toks[I + 1].setLocation(Tok.getLocation());3159 }3160 I += 2;3161 }3162 PP.EnterTokenStream(std::move(Toks), /*DisableMacroExpansion=*/true,3163 /*IsReinject=*/true);3164 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);3165}3166 3167bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,3168 llvm::function_ref<void()> ExpressionStarts,3169 bool FailImmediatelyOnInvalidExpr) {3170 bool SawError = false;3171 while (true) {3172 if (ExpressionStarts)3173 ExpressionStarts();3174 3175 ExprResult Expr;3176 if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {3177 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);3178 Expr = ParseBraceInitializer();3179 } else3180 Expr = ParseAssignmentExpression();3181 3182 if (Tok.is(tok::ellipsis))3183 Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());3184 else if (Tok.is(tok::code_completion)) {3185 // There's nothing to suggest in here as we parsed a full expression.3186 // Instead fail and propagate the error since caller might have something3187 // the suggest, e.g. signature help in function call. Note that this is3188 // performed before pushing the \p Expr, so that signature help can report3189 // current argument correctly.3190 SawError = true;3191 cutOffParsing();3192 break;3193 }3194 if (Expr.isInvalid()) {3195 SawError = true;3196 if (FailImmediatelyOnInvalidExpr)3197 break;3198 SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);3199 } else {3200 Exprs.push_back(Expr.get());3201 }3202 3203 if (Tok.isNot(tok::comma))3204 break;3205 // Move to the next argument, remember where the comma was.3206 Token Comma = Tok;3207 ConsumeToken();3208 checkPotentialAngleBracketDelimiter(Comma);3209 }3210 return SawError;3211}3212 3213bool Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr *> &Exprs) {3214 while (true) {3215 ExprResult Expr = ParseAssignmentExpression();3216 if (Expr.isInvalid())3217 return true;3218 3219 Exprs.push_back(Expr.get());3220 3221 // We might be parsing the LHS of a fold-expression. If we reached the fold3222 // operator, stop.3223 if (Tok.isNot(tok::comma) || NextToken().is(tok::ellipsis))3224 return false;3225 3226 // Move to the next argument, remember where the comma was.3227 Token Comma = Tok;3228 ConsumeToken();3229 checkPotentialAngleBracketDelimiter(Comma);3230 }3231}3232 3233void Parser::ParseBlockId(SourceLocation CaretLoc) {3234 if (Tok.is(tok::code_completion)) {3235 cutOffParsing();3236 Actions.CodeCompletion().CodeCompleteOrdinaryName(3237 getCurScope(), SemaCodeCompletion::PCC_Type);3238 return;3239 }3240 3241 // Parse the specifier-qualifier-list piece.3242 DeclSpec DS(AttrFactory);3243 ParseSpecifierQualifierList(DS);3244 3245 // Parse the block-declarator.3246 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),3247 DeclaratorContext::BlockLiteral);3248 DeclaratorInfo.setFunctionDefinitionKind(FunctionDefinitionKind::Definition);3249 ParseDeclarator(DeclaratorInfo);3250 3251 MaybeParseGNUAttributes(DeclaratorInfo);3252 3253 // Inform sema that we are starting a block.3254 Actions.ActOnBlockArguments(CaretLoc, DeclaratorInfo, getCurScope());3255}3256 3257ExprResult Parser::ParseBlockLiteralExpression() {3258 assert(Tok.is(tok::caret) && "block literal starts with ^");3259 SourceLocation CaretLoc = ConsumeToken();3260 3261 PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), CaretLoc,3262 "block literal parsing");3263 3264 // Enter a scope to hold everything within the block. This includes the3265 // argument decls, decls within the compound expression, etc. This also3266 // allows determining whether a variable reference inside the block is3267 // within or outside of the block.3268 ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |3269 Scope::CompoundStmtScope | Scope::DeclScope);3270 3271 // Inform sema that we are starting a block.3272 Actions.ActOnBlockStart(CaretLoc, getCurScope());3273 3274 // Parse the return type if present.3275 DeclSpec DS(AttrFactory);3276 Declarator ParamInfo(DS, ParsedAttributesView::none(),3277 DeclaratorContext::BlockLiteral);3278 ParamInfo.setFunctionDefinitionKind(FunctionDefinitionKind::Definition);3279 // FIXME: Since the return type isn't actually parsed, it can't be used to3280 // fill ParamInfo with an initial valid range, so do it manually.3281 ParamInfo.SetSourceRange(SourceRange(Tok.getLocation(), Tok.getLocation()));3282 3283 // If this block has arguments, parse them. There is no ambiguity here with3284 // the expression case, because the expression case requires a parameter list.3285 if (Tok.is(tok::l_paren)) {3286 ParseParenDeclarator(ParamInfo);3287 // Parse the pieces after the identifier as if we had "int(...)".3288 // SetIdentifier sets the source range end, but in this case we're past3289 // that location.3290 SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();3291 ParamInfo.SetIdentifier(nullptr, CaretLoc);3292 ParamInfo.SetRangeEnd(Tmp);3293 if (ParamInfo.isInvalidType()) {3294 // If there was an error parsing the arguments, they may have3295 // tried to use ^(x+y) which requires an argument list. Just3296 // skip the whole block literal.3297 Actions.ActOnBlockError(CaretLoc, getCurScope());3298 return ExprError();3299 }3300 3301 MaybeParseGNUAttributes(ParamInfo);3302 3303 // Inform sema that we are starting a block.3304 Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());3305 } else if (!Tok.is(tok::l_brace)) {3306 ParseBlockId(CaretLoc);3307 } else {3308 // Otherwise, pretend we saw (void).3309 SourceLocation NoLoc;3310 ParamInfo.AddTypeInfo(3311 DeclaratorChunk::getFunction(/*HasProto=*/true,3312 /*IsAmbiguous=*/false,3313 /*RParenLoc=*/NoLoc,3314 /*ArgInfo=*/nullptr,3315 /*NumParams=*/0,3316 /*EllipsisLoc=*/NoLoc,3317 /*RParenLoc=*/NoLoc,3318 /*RefQualifierIsLvalueRef=*/true,3319 /*RefQualifierLoc=*/NoLoc,3320 /*MutableLoc=*/NoLoc, EST_None,3321 /*ESpecRange=*/SourceRange(),3322 /*Exceptions=*/nullptr,3323 /*ExceptionRanges=*/nullptr,3324 /*NumExceptions=*/0,3325 /*NoexceptExpr=*/nullptr,3326 /*ExceptionSpecTokens=*/nullptr,3327 /*DeclsInPrototype=*/{}, CaretLoc,3328 CaretLoc, ParamInfo),3329 CaretLoc);3330 3331 MaybeParseGNUAttributes(ParamInfo);3332 3333 // Inform sema that we are starting a block.3334 Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());3335 }3336 3337 3338 ExprResult Result(true);3339 if (!Tok.is(tok::l_brace)) {3340 // Saw something like: ^expr3341 Diag(Tok, diag::err_expected_expression);3342 Actions.ActOnBlockError(CaretLoc, getCurScope());3343 return ExprError();3344 }3345 EnterExpressionEvaluationContextForFunction PotentiallyEvaluated(3346 Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);3347 StmtResult Stmt(ParseCompoundStatementBody());3348 BlockScope.Exit();3349 if (!Stmt.isInvalid())3350 Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope());3351 else3352 Actions.ActOnBlockError(CaretLoc, getCurScope());3353 return Result;3354}3355 3356ExprResult Parser::ParseObjCBoolLiteral() {3357 tok::TokenKind Kind = Tok.getKind();3358 return Actions.ObjC().ActOnObjCBoolLiteral(ConsumeToken(), Kind);3359}3360 3361/// Validate availability spec list, emitting diagnostics if necessary. Returns3362/// true if invalid.3363static bool CheckAvailabilitySpecList(Parser &P,3364 ArrayRef<AvailabilitySpec> AvailSpecs) {3365 llvm::SmallSet<StringRef, 4> Platforms;3366 bool HasOtherPlatformSpec = false;3367 bool Valid = true;3368 for (const auto &Spec : AvailSpecs) {3369 if (Spec.isOtherPlatformSpec()) {3370 if (HasOtherPlatformSpec) {3371 P.Diag(Spec.getBeginLoc(), diag::err_availability_query_repeated_star);3372 Valid = false;3373 }3374 3375 HasOtherPlatformSpec = true;3376 continue;3377 }3378 3379 bool Inserted = Platforms.insert(Spec.getPlatform()).second;3380 if (!Inserted) {3381 // Rule out multiple version specs referring to the same platform.3382 // For example, we emit an error for:3383 // @available(macos 10.10, macos 10.11, *)3384 StringRef Platform = Spec.getPlatform();3385 P.Diag(Spec.getBeginLoc(), diag::err_availability_query_repeated_platform)3386 << Spec.getEndLoc() << Platform;3387 Valid = false;3388 }3389 }3390 3391 if (!HasOtherPlatformSpec) {3392 SourceLocation InsertWildcardLoc = AvailSpecs.back().getEndLoc();3393 P.Diag(InsertWildcardLoc, diag::err_availability_query_wildcard_required)3394 << FixItHint::CreateInsertion(InsertWildcardLoc, ", *");3395 return true;3396 }3397 3398 return !Valid;3399}3400 3401std::optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() {3402 if (Tok.is(tok::star)) {3403 return AvailabilitySpec(ConsumeToken());3404 } else {3405 // Parse the platform name.3406 if (Tok.is(tok::code_completion)) {3407 cutOffParsing();3408 Actions.CodeCompletion().CodeCompleteAvailabilityPlatformName();3409 return std::nullopt;3410 }3411 if (Tok.isNot(tok::identifier)) {3412 Diag(Tok, diag::err_avail_query_expected_platform_name);3413 return std::nullopt;3414 }3415 3416 IdentifierLoc *PlatformIdentifier = ParseIdentifierLoc();3417 SourceRange VersionRange;3418 VersionTuple Version = ParseVersionTuple(VersionRange);3419 3420 if (Version.empty())3421 return std::nullopt;3422 3423 StringRef GivenPlatform =3424 PlatformIdentifier->getIdentifierInfo()->getName();3425 StringRef Platform =3426 AvailabilityAttr::canonicalizePlatformName(GivenPlatform);3427 3428 if (AvailabilityAttr::getPrettyPlatformName(Platform).empty() ||3429 (GivenPlatform.contains("xros") || GivenPlatform.contains("xrOS"))) {3430 Diag(PlatformIdentifier->getLoc(),3431 diag::err_avail_query_unrecognized_platform_name)3432 << GivenPlatform;3433 return std::nullopt;3434 }3435 3436 return AvailabilitySpec(Version, Platform, PlatformIdentifier->getLoc(),3437 VersionRange.getEnd());3438 }3439}3440 3441ExprResult Parser::ParseAvailabilityCheckExpr(SourceLocation BeginLoc) {3442 assert(Tok.is(tok::kw___builtin_available) ||3443 Tok.isObjCAtKeyword(tok::objc_available));3444 3445 // Eat the available or __builtin_available.3446 ConsumeToken();3447 3448 BalancedDelimiterTracker Parens(*this, tok::l_paren);3449 if (Parens.expectAndConsume())3450 return ExprError();3451 3452 SmallVector<AvailabilitySpec, 4> AvailSpecs;3453 bool HasError = false;3454 while (true) {3455 std::optional<AvailabilitySpec> Spec = ParseAvailabilitySpec();3456 if (!Spec)3457 HasError = true;3458 else3459 AvailSpecs.push_back(*Spec);3460 3461 if (!TryConsumeToken(tok::comma))3462 break;3463 }3464 3465 if (HasError) {3466 SkipUntil(tok::r_paren, StopAtSemi);3467 return ExprError();3468 }3469 3470 CheckAvailabilitySpecList(*this, AvailSpecs);3471 3472 if (Parens.consumeClose())3473 return ExprError();3474 3475 return Actions.ObjC().ActOnObjCAvailabilityCheckExpr(3476 AvailSpecs, BeginLoc, Parens.getCloseLocation());3477}3478