Пример #1
0
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;
}
Пример #2
0
// 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;
}
Пример #3
0
/// 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();
}
Пример #4
0
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);
  }
}
Пример #5
0
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);
}
Пример #6
0
/// 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();
}
Пример #7
0
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;
}
Пример #8
0
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();
}
Пример #9
0
// 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]);
}
Пример #10
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());
}
Пример #11
0
ExprResult LogOrOpNode::eval()
{
	ExprResult left = mLeft->eval();
	ExprResult right = mRight->eval();
	ExprResult result("bool", (Val*)new BoolVal(left.getBoolVal() || right.getBoolVal()));
	return result;
}
Пример #12
0
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()));
}
Пример #13
0
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()));
}
Пример #14
0
IntegerResult ParserImpl::ParseIntegerConstant(Expr::Width Type) {
  ExprResult Res = ParseNumber(Type);

  if (!Res.isValid())
    return IntegerResult();

  return cast<ConstantExpr>(Res.get())->getZExtValue(Type);
}
Пример #15
0
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;
}
Пример #16
0
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));
}
Пример #17
0
/// \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());
}
Пример #18
0
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;
}
Пример #19
0
/// 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;
  }
}
Пример #20
0
/// 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);
}
Пример #21
0
/// 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;
}
Пример #22
0
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);
}
Пример #23
0
// 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;
}
Пример #24
0
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;
}
Пример #25
0
// 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;
}
Пример #26
0
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);
}
Пример #27
0
/// 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.");
}
Пример #28
0
/// 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);
}
Пример #29
0
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());
    }
}
Пример #30
0
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);
}