Parser::ExprResult Parser::ParseAddOperand() { ExprResult E = ParseMultOperand(); if (E.isInvalid()) return E; while (true) { SourceLocation OpLoc = Tok.getLocation(); BinaryExpr::Operator Op = BinaryExpr::None; switch (Tok.getKind()) { default: return E; case tok::star: Op = BinaryExpr::Multiply; break; case tok::slash: Op = BinaryExpr::Divide; break; } Lex(); ExprResult MulOp = ParseMultOperand(); if (MulOp.isInvalid()) return MulOp; E = Actions.ActOnBinaryExpr(Context, OpLoc, Op, E, MulOp); } return E; }
// Return true if a comma (or closing brace) is necessary after the // __if_exists/if_not_exists statement. bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, bool &InitExprsOk) { bool trailingComma = false; IfExistsCondition Result; if (ParseMicrosoftIfExistsCondition(Result)) return false; BalancedDelimiterTracker Braces(*this, tok::l_brace); if (Braces.consumeOpen()) { Diag(Tok, diag::err_expected) << tok::l_brace; return false; } switch (Result.Behavior) { case IEB_Parse: // Parse the declarations below. break; case IEB_Dependent: Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. case IEB_Skip: Braces.skipToEnd(); return false; } while (!isEofOrEom()) { trailingComma = false; // If we know that this cannot be a designation, just parse the nested // initializer directly. ExprResult SubElt; if (MayBeDesignationStart()) SubElt = ParseInitializerWithPotentialDesignator(); else SubElt = ParseInitializer(); if (Tok.is(tok::ellipsis)) SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken()); // If we couldn't parse the subelement, bail out. if (!SubElt.isInvalid()) InitExprs.push_back(SubElt.release()); else InitExprsOk = false; if (Tok.is(tok::comma)) { ConsumeToken(); trailingComma = true; } if (Tok.is(tok::r_brace)) break; } Braces.consumeClose(); return !trailingComma; }
/// ParseUnaryExpression - Parse a unary-expression. /// unary-expression: /// inc-dec-expression /// ++ unary-expression /// -- unary-expression /// unary-operator unary-expression ExprResult Parser::ParseUnaryExpression() { ExprResult Res; tok::TokenKind SavedKind = Tok.getKind(); switch (SavedKind) { case tok::DoubleAdd: case tok::DoubleSub: // unary operators case tok::Addition: case tok::Subtraction: case tok::Tilde: case tok::At: { SourceLocation SavedLoc = ConsumeToken(); Res = ParsePostfixExpression(); if (!Res.isInvalid()) { Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind,false, Res.get()); } return move(Res); } default: break; } return ParsePostfixExpression(); }
ExprResult ParserImpl::ParseUnaryParenExpr(const Token &Name, unsigned Kind, bool IsFixed, Expr::Width ResTy) { if (Tok.kind == Token::RParen) { Error("unexpected end of arguments.", Name); ConsumeRParen(); return Builder->Constant(0, ResTy); } ExprResult Arg = ParseExpr(IsFixed ? ResTy : TypeResult()); if (!Arg.isValid()) Arg = Builder->Constant(0, ResTy); ExpectRParen("unexpected argument in unary expression."); ExprHandle E = Arg.get(); switch (Kind) { case eMacroKind_Neg: return Builder->Sub(Builder->Constant(0, E->getWidth()), E); case Expr::Not: // FIXME: Type check arguments. return Builder->Not(E); case Expr::SExt: // FIXME: Type check arguments. return Builder->SExt(E, ResTy); case Expr::ZExt: // FIXME: Type check arguments. return Builder->ZExt(E, ResTy); default: Error("internal error, unhandled kind.", Name); return Builder->Constant(0, ResTy); } }
static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, SourceLocation Loc) { QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc); if (CoroHandleType.isNull()) return ExprError(); DeclContext *LookupCtx = S.computeDeclContext(CoroHandleType); LookupResult Found(S, &S.PP.getIdentifierTable().get("from_address"), Loc, Sema::LookupOrdinaryName); if (!S.LookupQualifiedName(Found, LookupCtx)) { S.Diag(Loc, diag::err_coroutine_handle_missing_member) << "from_address"; return ExprError(); } Expr *FramePtr = buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {}); CXXScopeSpec SS; ExprResult FromAddr = S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false); if (FromAddr.isInvalid()) return ExprError(); return S.ActOnCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc); }
/// Look up the std::nothrow object. static Expr *buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc) { NamespaceDecl *Std = S.getStdNamespace(); assert(Std && "Should already be diagnosed"); LookupResult Result(S, &S.PP.getIdentifierTable().get("nothrow"), Loc, Sema::LookupOrdinaryName); if (!S.LookupQualifiedName(Result, Std)) { // FIXME: <experimental/coroutine> should have been included already. // If we require it to include <new> then this diagnostic is no longer // needed. S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found); return nullptr; } // FIXME: Mark the variable as ODR used. This currently does not work // likely due to the scope at in which this function is called. auto *VD = Result.getAsSingle<VarDecl>(); if (!VD) { Result.suppressDiagnostics(); // We found something weird. Complain about the first thing we found. NamedDecl *Found = *Result.begin(); S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow); return nullptr; } ExprResult DR = S.BuildDeclRefExpr(VD, VD->getType(), VK_LValue, Loc); if (DR.isInvalid()) return nullptr; return DR.get(); }
ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) { auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield"); if (!Coroutine) return ExprError(); if (E->getType()->isPlaceholderType()) { ExprResult R = CheckPlaceholderExpr(E); if (R.isInvalid()) return ExprError(); E = R.get(); } if (E->getType()->isDependentType()) { Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E); return Res; } // If the expression is a temporary, materialize it as an lvalue so that we // can use it multiple times. if (E->getValueKind() == VK_RValue) E = CreateMaterializeTemporaryExpr(E->getType(), E, true); // Build the await_ready, await_suspend, await_resume calls. ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E); if (RSS.IsInvalid) return ExprError(); Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1], RSS.Results[2], RSS.OpaqueValue); return Res; }
void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { if (!MI.Field || MI.Field->isInvalidDecl()) return; // Append the current token at the end of the new token stream so that it // doesn't get lost. MI.Toks.push_back(Tok); PP.EnterTokenStream(MI.Toks.data(), MI.Toks.size(), true, false); // Consume the previously pushed token. ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); SourceLocation EqualLoc; ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false, EqualLoc); Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release()); // The next token should be our artificial terminating EOF token. if (Tok.isNot(tok::eof)) { SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); if (!EndLoc.isValid()) EndLoc = Tok.getLocation(); // No fixit; we can't recover as if there were a semicolon here. Diag(EndLoc, diag::err_expected_semi_decl_list); // Consume tokens until we hit the artificial EOF. while (Tok.isNot(tok::eof)) ConsumeAnyToken(); } ConsumeAnyToken(); }
// FIXME: Rewrite to only accept binary form. Make type optional. ExprResult ParserImpl::ParseConcatParenExpr(const Token &Name, Expr::Width ResTy) { std::vector<ExprHandle> Kids; unsigned Width = 0; while (Tok.kind != Token::RParen) { ExprResult E = ParseExpr(TypeResult()); // Skip to end of expr on error. if (!E.isValid()) { SkipUntilRParen(); return Builder->Constant(0, ResTy); } Kids.push_back(E.get()); Width += E.get()->getWidth(); } ConsumeRParen(); if (Width != ResTy) { Error("concat does not match expected result size."); return Builder->Constant(0, ResTy); } // FIXME: Use builder! return ConcatExpr::createN(Kids.size(), &Kids[0]); }
/// \brief Parsing of OpenMP clauses with single expressions and some additional /// argument like 'schedule' or 'dist_schedule'. /// /// schedule-clause: /// 'schedule' '(' kind [',' expression ] ')' /// OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { SourceLocation Loc = ConsumeToken(); SourceLocation CommaLoc; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, getOpenMPClauseName(Kind))) return nullptr; ExprResult Val; unsigned Type = getOpenMPSimpleClauseType( Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); SourceLocation KLoc = Tok.getLocation(); if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && Tok.isNot(tok::annot_pragma_openmp_end)) ConsumeAnyToken(); if (Kind == OMPC_schedule && (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic || Type == OMPC_SCHEDULE_guided) && Tok.is(tok::comma)) { CommaLoc = ConsumeAnyToken(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); if (Val.isInvalid()) return nullptr; } // Parse ')'. T.consumeClose(); return Actions.ActOnOpenMPSingleExprWithArgClause( Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc, T.getCloseLocation()); }
ExprResult LogOrOpNode::eval() { ExprResult left = mLeft->eval(); ExprResult right = mRight->eval(); ExprResult result("bool", (Val*)new BoolVal(left.getBoolVal() || right.getBoolVal())); return result; }
static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, SourceLocation Loc, Expr *E) { ExprResult R = buildOperatorCoawaitLookupExpr(SemaRef, S, Loc); if (R.isInvalid()) return ExprError(); return buildOperatorCoawaitCall(SemaRef, Loc, E, cast<UnresolvedLookupExpr>(R.get())); }
C2::ExprResult C2Sema::ActOnArrayDesignatorExpr(SourceLocation left, ExprResult Designator, ExprResult InitValue) { #ifdef SEMA_DEBUG std::cerr << COL_SEMA"SEMA: ArrayDesignatorExpr at "; left_.dump(SourceMgr); std::cerr << ANSI_NORMAL"\n"; #endif return ExprResult(new DesignatedInitExpr(left, Designator.get(), InitValue.get())); }
IntegerResult ParserImpl::ParseIntegerConstant(Expr::Width Type) { ExprResult Res = ParseNumber(Type); if (!Res.isValid()) return IntegerResult(); return cast<ConstantExpr>(Res.get())->getZExtValue(Type); }
ExprResult Sema::ActOnCoyieldExpr(SourceLocation Loc, Expr *E) { auto *Context = checkCoroutineContext(*this, Loc, "co_yield"); ExprResult Res = ExprError(); if (Context && !Res.isInvalid()) Context->CoroutineStmts.push_back(Res.get()); return Res; }
static ExprResult BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo) { // x.a is an l-value if 'a' has a reference type. Otherwise: // x.a is an l-value/x-value/pr-value if the base is (and note // that *x is always an l-value), except that if the base isn't // an ordinary object then we must have an rvalue. ExprValueKind VK = VK_LValue; ExprObjectKind OK = OK_Ordinary; if (!IsArrow) { if (BaseExpr->getObjectKind() == OK_Ordinary) VK = BaseExpr->getValueKind(); else VK = VK_RValue; } if (VK != VK_RValue && Field->isBitField()) OK = OK_BitField; // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] QualType MemberType = Field->getType(); if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) { MemberType = Ref->getPointeeType(); VK = VK_LValue; } else { QualType BaseType = BaseExpr->getType(); if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType(); Qualifiers BaseQuals = BaseType.getQualifiers(); // CVR attributes from the base are picked up by members, // except that 'mutable' members don't pick up 'const'. if (Field->isMutable()) BaseQuals.removeConst(); Qualifiers MemberQuals = S.Context.getCanonicalType(MemberType).getQualifiers(); assert(!MemberQuals.hasAddressSpace()); Qualifiers Combined = BaseQuals + MemberQuals; if (Combined != MemberQuals) MemberType = S.Context.getQualifiedType(MemberType, Combined); } S.UnusedPrivateFields.remove(Field); ExprResult Base = S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), FoundDecl, Field); if (Base.isInvalid()) return ExprError(); return S.Owned(BuildMemberExpr(S, S.Context, Base.take(), IsArrow, Field, FoundDecl, MemberNameInfo, MemberType, VK, OK)); }
/// \brief Parsing of OpenMP clauses with single expressions and some additional /// argument like 'schedule' or 'dist_schedule'. /// /// schedule-clause: /// 'schedule' '(' kind [',' expression ] ')' /// /// if-clause: /// 'if' '(' [ directive-name-modifier ':' ] expression ')' /// OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { SourceLocation Loc = ConsumeToken(); SourceLocation DelimLoc; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, getOpenMPClauseName(Kind))) return nullptr; ExprResult Val; unsigned Arg; SourceLocation KLoc; if (Kind == OMPC_schedule) { Arg = getOpenMPSimpleClauseType( Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); KLoc = Tok.getLocation(); if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && Tok.isNot(tok::annot_pragma_openmp_end)) ConsumeAnyToken(); if ((Arg == OMPC_SCHEDULE_static || Arg == OMPC_SCHEDULE_dynamic || Arg == OMPC_SCHEDULE_guided) && Tok.is(tok::comma)) DelimLoc = ConsumeAnyToken(); } else { assert(Kind == OMPC_if); KLoc = Tok.getLocation(); Arg = ParseOpenMPDirectiveKind(*this); if (Arg != OMPD_unknown) { ConsumeToken(); if (Tok.is(tok::colon)) DelimLoc = ConsumeToken(); else Diag(Tok, diag::warn_pragma_expected_colon) << "directive name modifier"; } } bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || Kind == OMPC_if; if (NeedAnExpression) { SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); } // Parse ')'. T.consumeClose(); if (NeedAnExpression && Val.isInvalid()) return nullptr; return Actions.ActOnOpenMPSingleExprWithArgClause( Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, T.getCloseLocation()); }
ExprResult Parser::ParseExpectedConditionExpression(const char *DiagAfter) { if (!ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, DiagAfter)) return ExprError(); ExprResult Condition = ParseExpectedFollowupExpression("("); if(Condition.isInvalid()) return Condition; if (!ExpectAndConsume(tok::r_paren)) return ExprError(); return Condition; }
/// ParseAsmOperands - Parse the asm-operands production as used by /// asm-statement, assuming the leading ':' token was eaten. /// /// [GNU] asm-operands: /// asm-operand /// asm-operands ',' asm-operand /// /// [GNU] asm-operand: /// asm-string-literal '(' expression ')' /// '[' identifier ']' asm-string-literal '(' expression ')' /// // // FIXME: Avoid unnecessary std::string trashing. bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names, SmallVectorImpl<Expr *> &Constraints, SmallVectorImpl<Expr *> &Exprs) { // 'asm-operands' isn't present? if (!isTokenStringLiteral() && Tok.isNot(tok::l_square)) return false; while (1) { // Read the [id] if present. if (Tok.is(tok::l_square)) { BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::r_paren, StopAtSemi); return true; } IdentifierInfo *II = Tok.getIdentifierInfo(); ConsumeToken(); Names.push_back(II); T.consumeClose(); } else Names.push_back(nullptr); ExprResult Constraint(ParseAsmStringLiteral()); if (Constraint.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return true; } Constraints.push_back(Constraint.get()); if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::err_expected_lparen_after) << "asm operand"; SkipUntil(tok::r_paren, StopAtSemi); return true; } // Read the parenthesized expression. BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression()); T.consumeClose(); if (Res.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return true; } Exprs.push_back(Res.get()); // Eat the comma and continue parsing if it exists. if (!TryConsumeToken(tok::comma)) return false; } }
/// ParseDataReference - Parse a data reference. /// /// R611: /// data-ref := /// part-ref [ % part-ref ] ... ExprResult Parser::ParseDataReference() { std::vector<ExprResult> Exprs; do { ExprResult E = ParsePartReference(); if (E.isInvalid()) return E; Exprs.push_back(E); } while (ConsumeIfPresent(tok::percent) || ConsumeIfPresent(tok::period)); return Actions.ActOnDataReference(Exprs); }
/// Build calls to await_ready, await_suspend, and await_resume for a co_await /// expression. static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, SourceLocation Loc, Expr *E) { OpaqueValueExpr *Operand = new (S.Context) OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E); // Assume invalid until we see otherwise. ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/true}; ExprResult CoroHandleRes = buildCoroutineHandle(S, CoroPromise->getType(), Loc); if (CoroHandleRes.isInvalid()) return Calls; Expr *CoroHandle = CoroHandleRes.get(); const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"}; MultiExprArg Args[] = {None, CoroHandle, None}; for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) { ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], Args[I]); if (Result.isInvalid()) return Calls; Calls.Results[I] = Result.get(); } // Assume the calls are valid; all further checking should make them invalid. Calls.IsInvalid = false; using ACT = ReadySuspendResumeResult::AwaitCallType; CallExpr *AwaitReady = cast<CallExpr>(Calls.Results[ACT::ACT_Ready]); if (!AwaitReady->getType()->isDependentType()) { // [expr.await]p3 [...] // — await-ready is the expression e.await_ready(), contextually converted // to bool. ExprResult Conv = S.PerformContextuallyConvertToBool(AwaitReady); if (Conv.isInvalid()) { S.Diag(AwaitReady->getDirectCallee()->getLocStart(), diag::note_await_ready_no_bool_conversion); S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required) << AwaitReady->getDirectCallee() << E->getSourceRange(); Calls.IsInvalid = true; } Calls.Results[ACT::ACT_Ready] = Conv.get(); } CallExpr *AwaitSuspend = cast<CallExpr>(Calls.Results[ACT::ACT_Suspend]); if (!AwaitSuspend->getType()->isDependentType()) { // [expr.await]p3 [...] // - await-suspend is the expression e.await_suspend(h), which shall be // a prvalue of type void or bool. QualType RetType = AwaitSuspend->getType(); if (RetType != S.Context.BoolTy && RetType != S.Context.VoidTy) { S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(), diag::err_await_suspend_invalid_return_type) << RetType; S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required) << AwaitSuspend->getDirectCallee(); Calls.IsInvalid = true; } } return Calls; }
Parser::StmtResult Parser::ParseDoStmt() { auto Loc = ConsumeToken(); auto CurStmtLoc = LocFirstStmtToken; ExprResult TerminalStmt; VarExpr *DoVar = nullptr; ExprResult E1, E2, E3; auto EqLoc = Loc; if(IsPresent(tok::int_literal_constant)) { TerminalStmt = ParseStatementLabelReference(); if(TerminalStmt.isInvalid()) return StmtError(); } bool isDo = ConsumeIfPresent(tok::comma); if(isDo && IsPresent(tok::kw_WHILE)) return ParseDoWhileStmt(isDo); // the do var auto IDInfo = Tok.getIdentifierInfo(); auto IDRange = getTokenRange(); auto IDLoc = Tok.getLocation(); if(!ExpectAndConsume(tok::identifier)) goto error; EqLoc = getMaxLocationOfCurrentToken(); if(Features.FixedForm && !isDo && IsPresent(tok::l_paren)) return ReparseAmbiguousAssignmentStatement(); if(!ExpectAndConsume(tok::equal)) goto error; E1 = ParseExpectedFollowupExpression("="); if(E1.isInvalid()) goto error; if(Features.FixedForm && !isDo && Tok.isAtStartOfStatement()) return ReparseAmbiguousAssignmentStatement(CurStmtLoc); if(!ExpectAndConsume(tok::comma)) goto error; E2 = ParseExpectedFollowupExpression(","); if(E2.isInvalid()) goto error; if(ConsumeIfPresent(tok::comma)) { E3 = ParseExpectedFollowupExpression(","); if(E3.isInvalid()) goto error; } if(auto VD = Actions.ExpectVarRefOrDeclImplicitVar(IDLoc, IDInfo)) DoVar = VarExpr::Create(Context, IDRange, VD); return Actions.ActOnDoStmt(Context, Loc, EqLoc, TerminalStmt, DoVar, E1, E2, E3, StmtConstructName, StmtLabel); error: if(IDInfo) { if(auto VD = Actions.ExpectVarRefOrDeclImplicitVar(IDLoc, IDInfo)) DoVar = VarExpr::Create(Context, IDRange, VD); } SkipUntilNextStatement(); return Actions.ActOnDoStmt(Context, Loc, EqLoc, TerminalStmt, DoVar, E1, E2, E3, StmtConstructName, StmtLabel); }
// ParseLevel5Expr - Level-5 expressions are level-4 expressions optionally // involving the logical operators. // // R717: // level-5-expr := // [ level-5-expr equiv-op ] equiv-operand // R716: // equiv-operand := // [ equiv-operand or-op ] or-operand // R715: // or-operand := // [ or-operand and-op ] and-operand // R714: // and-operand := // [ not-op ] level-4-expr // // R718: // not-op := // .NOT. // R719: // and-op := // .AND. // R720: // or-op := // .OR. // R721: // equiv-op := // .EQV. // or .NEQV. Parser::ExprResult Parser::ParseAndOperand() { llvm::SMLoc NotLoc = Tok.getLocation(); bool Negate = EatIfPresent(tok::kw_NOT); ExprResult E = ParseLevel4Expr(); if (E.isInvalid()) return ExprResult(); if (Negate) E = UnaryExpr::Create(Context, NotLoc, UnaryExpr::Not, E); return E; }
bool CoroutineStmtBuilder::makeReturnObject() { // Build implicit 'p.get_return_object()' expression and form initialization // of return type from it. ExprResult ReturnObject = buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None); if (ReturnObject.isInvalid()) return false; this->ReturnValue = ReturnObject.get(); return true; }
// ParseLevel5Expr - Level-5 expressions are level-4 expressions optionally // involving the logical operators. // // R717: // level-5-expr := // [ level-5-expr equiv-op ] equiv-operand // R716: // equiv-operand := // [ equiv-operand or-op ] or-operand // R715: // or-operand := // [ or-operand and-op ] and-operand // R714: // and-operand := // [ not-op ] level-4-expr // // R718: // not-op := // .NOT. // R719: // and-op := // .AND. // R720: // or-op := // .OR. // R721: // equiv-op := // .EQV. // or .NEQV. Parser::ExprResult Parser::ParseAndOperand() { SourceLocation NotLoc = Tok.getLocation(); bool Negate = ConsumeIfPresent(tok::kw_NOT); ExprResult E = ParseLevel4Expr(); if (E.isInvalid()) return E; if (Negate) E = Actions.ActOnUnaryExpr(Context, NotLoc, UnaryExpr::Not, E); return E; }
static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise, SourceLocation Loc, StringRef Name, MultiExprArg Args) { // Form a reference to the promise. ExprResult PromiseRef = S.BuildDeclRefExpr( Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc); if (PromiseRef.isInvalid()) return ExprError(); return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args); }
/// ParseMatchedBinaryArgs - Parse a pair of arguments who are /// expected to be of the same type. Upon return, if both LHS and RHS /// are valid then they are guaranteed to have the same type. /// /// Name - The name token of the expression, for diagnostics. /// ExpectType - The expected type of the arguments, if known. void ParserImpl::ParseMatchedBinaryArgs(const Token &Name, TypeResult ExpectType, ExprResult &LHS, ExprResult &RHS) { if (Tok.kind == Token::RParen) { Error("unexpected end of arguments.", Name); ConsumeRParen(); return; } // Avoid NumberOrExprResult overhead and give more precise // diagnostics when we know the type. if (ExpectType.isValid()) { LHS = ParseExpr(ExpectType); if (Tok.kind == Token::RParen) { Error("unexpected end of arguments.", Name); ConsumeRParen(); return; } RHS = ParseExpr(ExpectType); } else { NumberOrExprResult LHS_NOE = ParseNumberOrExpr(); if (Tok.kind == Token::RParen) { Error("unexpected end of arguments.", Name); ConsumeRParen(); return; } if (LHS_NOE.isNumber()) { NumberOrExprResult RHS_NOE = ParseNumberOrExpr(); if (RHS_NOE.isNumber()) { Error("ambiguous arguments to expression.", Name); } else { RHS = RHS_NOE.getExpr(); if (RHS.isValid()) LHS = ParseNumberToken(RHS.get()->getWidth(), LHS_NOE.getNumber()); } } else { LHS = LHS_NOE.getExpr(); if (!LHS.isValid()) { // FIXME: Should suppress ambiguity warnings here. RHS = ParseExpr(TypeResult()); } else { RHS = ParseExpr(LHS.get()->getWidth()); } } } ExpectRParen("unexpected argument to expression."); }
/// ParsePARAMETERStmt - Parse the PARAMETER statement. /// /// [R548]: /// parameter-stmt := /// PARAMETER ( named-constant-def-list ) Parser::StmtResult Parser::ParsePARAMETERStmt() { // Check if this is an assignment. if (IsNextToken(tok::equal)) return StmtResult(); auto Loc = ConsumeToken(); SmallVector<Stmt*, 8> StmtList; if(!ExpectAndConsume(tok::l_paren)) { if(!SkipUntil(tok::l_paren)) return StmtError(); } while(true) { auto IDLoc = Tok.getLocation(); auto II = Tok.getIdentifierInfo(); if(!ExpectAndConsume(tok::identifier)) { if(!SkipUntil(tok::comma)) break; else continue; } auto EqualLoc = Tok.getLocation(); if(!ExpectAndConsume(tok::equal)) { if(!SkipUntil(tok::comma)) break; else continue; } ExprResult ConstExpr = ParseExpression(); if(ConstExpr.isUsable()) { auto Stmt = Actions.ActOnPARAMETER(Context, Loc, EqualLoc, IDLoc, II, ConstExpr, nullptr); if(Stmt.isUsable()) StmtList.push_back(Stmt.take()); } if(ConsumeIfPresent(tok::comma)) continue; if(isTokenIdentifier() && !Tok.isAtStartOfStatement()) { ExpectAndConsume(tok::comma); continue; } break; } if(!ExpectAndConsume(tok::r_paren)) SkipUntilNextStatement(); return Actions.ActOnCompoundStmt(Context, Loc, StmtList, StmtLabel); }
ExprResult Snowda::assignLed(Parser &parser, const Expr *left, Token token) { // TODO: Figure out an exhaustive list of what left can be // if (left->nodeType() != NodeType::IdentifierExpr) { // return ParserError(parser.currentToken(), "Expected lhs to be an identifier"); // } ExprResult result = parser.parseExpression(parser.grammar().bp(token)); if (result.hasError()) { return result; } else { return parser.create<AssignExpr>(left, result.value()); } }
void Parser::HandlePragmaPack() { assert(Tok.is(tok::annot_pragma_pack)); PragmaPackInfo *Info = static_cast<PragmaPackInfo *>(Tok.getAnnotationValue()); SourceLocation PragmaLoc = ConsumeToken(); ExprResult Alignment; if (Info->Alignment.is(tok::numeric_constant)) { Alignment = Actions.ActOnNumericConstant(Info->Alignment); if (Alignment.isInvalid()) return; } Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc, Info->LParenLoc, Info->RParenLoc); }