@@ -4401,6 +4401,25 @@ bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind,
44014401 return false ;
44024402}
44034403
4404+ // / Parse step size expression. Returns true if parsing is successfull,
4405+ // / otherwise returns false.
4406+ static bool parseStepSize (Parser &P, Sema::OpenMPVarListDataTy &Data,
4407+ OpenMPClauseKind CKind, SourceLocation ELoc) {
4408+ ExprResult Tail = P.ParseAssignmentExpression ();
4409+ Sema &Actions = P.getActions ();
4410+ Tail = Actions.ActOnFinishFullExpr (Tail.get (), ELoc,
4411+ /* DiscardedValue*/ false );
4412+ if (Tail.isUsable ()) {
4413+ Data.DepModOrTailExpr = Tail.get ();
4414+ Token CurTok = P.getCurToken ();
4415+ if (CurTok.isNot (tok::r_paren) && CurTok.isNot (tok::comma)) {
4416+ P.Diag (CurTok, diag::err_expected_punc) << " step expression" ;
4417+ }
4418+ return true ;
4419+ }
4420+ return false ;
4421+ }
4422+
44044423// / Parses clauses with list.
44054424bool Parser::ParseOpenMPVarList (OpenMPDirectiveKind DKind,
44064425 OpenMPClauseKind Kind,
@@ -4763,19 +4782,76 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
47634782 if (NeedRParenForLinear)
47644783 LinearT.consumeClose ();
47654784
4766- // Parse ':' linear-step (or ':' alignment).
4785+ // Parse ':' linear modifiers (val, uval, ref or step(step-size))
4786+ // or parse ':' alignment.
47674787 const bool MustHaveTail = MayHaveTail && Tok.is (tok::colon);
4788+ bool StepFound = false ;
4789+ bool ModifierFound = false ;
47684790 if (MustHaveTail) {
47694791 Data.ColonLoc = Tok.getLocation ();
47704792 SourceLocation ELoc = ConsumeToken ();
4771- ExprResult Tail = ParseAssignmentExpression ();
4772- Tail =
4773- Actions.ActOnFinishFullExpr (Tail.get (), ELoc, /* DiscardedValue*/ false );
4774- if (Tail.isUsable ())
4775- Data.DepModOrTailExpr = Tail.get ();
4776- else
4777- SkipUntil (tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4778- StopBeforeMatch);
4793+
4794+ if (getLangOpts ().OpenMP >= 52 && Kind == OMPC_linear) {
4795+ while (Tok.isNot (tok::r_paren)) {
4796+ if (Tok.is (tok::identifier)) {
4797+ // identifier could be a linear kind (val, uval, ref) or step
4798+ // modifier or step size
4799+ OpenMPLinearClauseKind LinKind =
4800+ static_cast <OpenMPLinearClauseKind>(getOpenMPSimpleClauseType (
4801+ Kind, Tok.isAnnotation () ? " " : PP.getSpelling (Tok),
4802+ getLangOpts ()));
4803+
4804+ if (LinKind == OMPC_LINEAR_step) {
4805+ if (StepFound)
4806+ Diag (Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0 ;
4807+
4808+ BalancedDelimiterTracker StepT (*this , tok::l_paren,
4809+ tok::annot_pragma_openmp_end);
4810+ SourceLocation StepModifierLoc = ConsumeToken ();
4811+ // parse '('
4812+ if (StepT.consumeOpen ())
4813+ Diag (StepModifierLoc, diag::err_expected_lparen_after) << " step" ;
4814+
4815+ // parse step size expression
4816+ StepFound = parseStepSize (*this , Data, Kind, Tok.getLocation ());
4817+ if (StepFound)
4818+ Data.StepModifierLoc = StepModifierLoc;
4819+
4820+ // parse ')'
4821+ StepT.consumeClose ();
4822+ } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
4823+ if (ModifierFound)
4824+ Diag (Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1 ;
4825+
4826+ Data.ExtraModifier = LinKind;
4827+ Data.ExtraModifierLoc = ConsumeToken ();
4828+ ModifierFound = true ;
4829+ } else {
4830+ StepFound = parseStepSize (*this , Data, Kind, Tok.getLocation ());
4831+ }
4832+ } else {
4833+ // parse an integer expression as step size
4834+ StepFound = parseStepSize (*this , Data, Kind, Tok.getLocation ());
4835+ }
4836+
4837+ if (Tok.is (tok::comma))
4838+ ConsumeToken ();
4839+ if (Tok.is (tok::r_paren) || Tok.is (tok::annot_pragma_openmp_end))
4840+ break ;
4841+ }
4842+ if (!StepFound && !ModifierFound)
4843+ Diag (ELoc, diag::err_expected_expression);
4844+ } else {
4845+ // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
4846+ ExprResult Tail = ParseAssignmentExpression ();
4847+ Tail = Actions.ActOnFinishFullExpr (Tail.get (), ELoc,
4848+ /* DiscardedValue*/ false );
4849+ if (Tail.isUsable ())
4850+ Data.DepModOrTailExpr = Tail.get ();
4851+ else
4852+ SkipUntil (tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4853+ StopBeforeMatch);
4854+ }
47794855 }
47804856
47814857 // Parse ')'.
@@ -4787,8 +4863,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
47874863 ExitScope ();
47884864 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
47894865 Vars.empty ()) ||
4790- (MustHaveTail && !Data.DepModOrTailExpr ) || InvalidReductionId ||
4791- IsInvalidMapperModifier || InvalidIterator;
4866+ (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
4867+ InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
47924868}
47934869
47944870// / Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
0 commit comments