Example #1
0
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
///
///    private-clause:
///       'private' '(' list ')'
///    firstprivate-clause:
///       'firstprivate' '(' list ')'
///    lastprivate-clause:
///       'lastprivate' '(' list ')'
///    shared-clause:
///       'shared' '(' list ')'
///    linear-clause:
///       'linear' '(' list [ ':' linear-step ] ')'
///    aligned-clause:
///       'aligned' '(' list [ ':' alignment ] ')'
///    reduction-clause:
///       'reduction' '(' reduction-identifier ':' list ')'
///    copyprivate-clause:
///       'copyprivate' '(' list ')'
///    flush-clause:
///       'flush' '(' list ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
    SourceLocation Loc = Tok.getLocation();
    SourceLocation LOpen = ConsumeToken();
    SourceLocation ColonLoc = SourceLocation();
    // Optional scope specifier and unqualified id for reduction identifier.
    CXXScopeSpec ReductionIdScopeSpec;
    UnqualifiedId ReductionId;
    bool InvalidReductionId = false;
    // Parse '('.
    BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    if (T.expectAndConsume(diag::err_expected_lparen_after,
                           getOpenMPClauseName(Kind)))
        return nullptr;

    // Handle reduction-identifier for reduction clause.
    if (Kind == OMPC_reduction) {
        ColonProtectionRAIIObject ColonRAII(*this);
        if (getLangOpts().CPlusPlus) {
            ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
        }
        InvalidReductionId =
            ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
        if (InvalidReductionId) {
            SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                      StopBeforeMatch);
        }
        if (Tok.is(tok::colon)) {
            ColonLoc = ConsumeToken();
        } else {
            Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
        }
    }

    SmallVector<Expr *, 5> Vars;
    bool IsComma = !InvalidReductionId;
    const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
    while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
                       Tok.isNot(tok::annot_pragma_openmp_end))) {
        ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
        // Parse variable
        ExprResult VarExpr = ParseAssignmentExpression();
        if (VarExpr.isUsable()) {
            Vars.push_back(VarExpr.get());
        } else {
            SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                      StopBeforeMatch);
        }
        // Skip ',' if any
        IsComma = Tok.is(tok::comma);
        if (IsComma)
            ConsumeToken();
        else if (Tok.isNot(tok::r_paren) &&
                 Tok.isNot(tok::annot_pragma_openmp_end) &&
                 (!MayHaveTail || Tok.isNot(tok::colon)))
            Diag(Tok, diag::err_omp_expected_punc)
                    << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
                        : getOpenMPClauseName(Kind))
                    << (Kind == OMPC_flush);
    }

    // Parse ':' linear-step (or ':' alignment).
    Expr *TailExpr = nullptr;
    const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
    if (MustHaveTail) {
        ColonLoc = Tok.getLocation();
        ConsumeToken();
        ExprResult Tail = ParseAssignmentExpression();
        if (Tail.isUsable())
            TailExpr = Tail.get();
        else
            SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                      StopBeforeMatch);
    }

    // Parse ')'.
    T.consumeClose();
    if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
        return nullptr;

    return Actions.ActOnOpenMPVarListClause(
               Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
               ReductionIdScopeSpec,
               ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
               : DeclarationNameInfo());
}
Example #2
0
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
///
///    private-clause:
///       'private' '(' list ')'
///    firstprivate-clause:
///       'firstprivate' '(' list ')'
///    lastprivate-clause:
///       'lastprivate' '(' list ')'
///    shared-clause:
///       'shared' '(' list ')'
///    linear-clause:
///       'linear' '(' linear-list [ ':' linear-step ] ')'
///    aligned-clause:
///       'aligned' '(' list [ ':' alignment ] ')'
///    reduction-clause:
///       'reduction' '(' reduction-identifier ':' list ')'
///    copyprivate-clause:
///       'copyprivate' '(' list ')'
///    flush-clause:
///       'flush' '(' list ')'
///    depend-clause:
///       'depend' '(' in | out | inout : list ')'
///
/// For 'linear' clause linear-list may have the following forms:
///  list
///  modifier(list)
/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  SourceLocation ColonLoc = SourceLocation();
  // Optional scope specifier and unqualified id for reduction identifier.
  CXXScopeSpec ReductionIdScopeSpec;
  UnqualifiedId ReductionId;
  bool InvalidReductionId = false;
  OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
  // OpenMP 4.1 [2.15.3.7, linear Clause]
  //  If no modifier is specified it is assumed to be val.
  OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val;
  SourceLocation DepLinLoc;

  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return nullptr;

  bool NeedRParenForLinear = false;
  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
                                  tok::annot_pragma_openmp_end);
  // Handle reduction-identifier for reduction clause.
  if (Kind == OMPC_reduction) {
    ColonProtectionRAIIObject ColonRAII(*this);
    if (getLangOpts().CPlusPlus) {
      ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
    }
    InvalidReductionId =
        ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
    if (InvalidReductionId) {
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    if (Tok.is(tok::colon)) {
      ColonLoc = ConsumeToken();
    } else {
      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
    }
  } else if (Kind == OMPC_depend) {
  // Handle dependency type for depend clause.
    ColonProtectionRAIIObject ColonRAII(*this);
    DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
    DepLinLoc = Tok.getLocation();

    if (DepKind == OMPC_DEPEND_unknown) {
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else {
      ConsumeToken();
    }
    if (Tok.is(tok::colon)) {
      ColonLoc = ConsumeToken();
    } else {
      Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type";
    }
  } else if (Kind == OMPC_linear) {
    // Try to parse modifier if any.
    if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
      LinearModifier = static_cast<OpenMPLinearClauseKind>(
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
      DepLinLoc = ConsumeToken();
      LinearT.consumeOpen();
      NeedRParenForLinear = true;
    }
  }

  SmallVector<Expr *, 5> Vars;
  bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) ||
                 ((Kind == OMPC_reduction) && !InvalidReductionId) ||
                 ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
                     Tok.isNot(tok::annot_pragma_openmp_end))) {
    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
    // Parse variable
    ExprResult VarExpr =
        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
    if (VarExpr.isUsable()) {
      Vars.push_back(VarExpr.get());
    } else {
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    // Skip ',' if any
    IsComma = Tok.is(tok::comma);
    if (IsComma)
      ConsumeToken();
    else if (Tok.isNot(tok::r_paren) &&
             Tok.isNot(tok::annot_pragma_openmp_end) &&
             (!MayHaveTail || Tok.isNot(tok::colon)))
      Diag(Tok, diag::err_omp_expected_punc)
          << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
                                   : getOpenMPClauseName(Kind))
          << (Kind == OMPC_flush);
  }

  // Parse ')' for linear clause with modifier.
  if (NeedRParenForLinear)
    LinearT.consumeClose();

  // Parse ':' linear-step (or ':' alignment).
  Expr *TailExpr = nullptr;
  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
  if (MustHaveTail) {
    ColonLoc = Tok.getLocation();
    ConsumeToken();
    ExprResult Tail =
        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
    if (Tail.isUsable())
      TailExpr = Tail.get();
    else
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
  }

  // Parse ')'.
  T.consumeClose();
  if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
      (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
      InvalidReductionId)
    return nullptr;

  return Actions.ActOnOpenMPVarListClause(
      Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
      ReductionIdScopeSpec,
      ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
                            : DeclarationNameInfo(),
      DepKind, LinearModifier, DepLinLoc);
}