diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp | 769 | 
1 files changed, 651 insertions, 118 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp index 52a68f6d6935..1095919baa7d 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp @@ -12,13 +12,16 @@  #include "clang/AST/ASTContext.h"  #include "clang/AST/StmtOpenMP.h" +#include "clang/Basic/OpenMPKinds.h"  #include "clang/Parse/ParseDiagnostic.h"  #include "clang/Parse/Parser.h"  #include "clang/Parse/RAIIObjectsForParser.h"  #include "clang/Sema/Scope.h"  #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/UniqueVector.h"  using namespace clang; +using namespace llvm::omp;  //===----------------------------------------------------------------------===//  // OpenMP declarative directives. @@ -26,7 +29,7 @@ using namespace clang;  namespace {  enum OpenMPDirectiveKindEx { -  OMPD_cancellation = OMPD_unknown + 1, +  OMPD_cancellation = unsigned(OMPD_unknown) + 1,    OMPD_data,    OMPD_declare,    OMPD_end, @@ -42,6 +45,21 @@ enum OpenMPDirectiveKindEx {    OMPD_teams_distribute_parallel,    OMPD_target_teams_distribute_parallel,    OMPD_mapper, +  OMPD_variant, +}; + +// Helper to unify the enum class OpenMPDirectiveKind with its extension +// the OpenMPDirectiveKindEx enum which allows to use them together as if they +// are unsigned values. +struct OpenMPDirectiveKindExWrapper { +  OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {} +  OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {} +  bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); } +  bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); } +  bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); } +  operator unsigned() const { return Value; } +  operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); } +  unsigned Value;  };  class DeclDirectiveListParserHelper final { @@ -65,11 +83,11 @@ public:  // Map token string to extended OMP token kind that are  // OpenMPDirectiveKind + OpenMPDirectiveKindEx.  static unsigned getOpenMPDirectiveKindEx(StringRef S) { -  auto DKind = getOpenMPDirectiveKind(S); +  OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);    if (DKind != OMPD_unknown)      return DKind; -  return llvm::StringSwitch<unsigned>(S) +  return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)        .Case("cancellation", OMPD_cancellation)        .Case("data", OMPD_data)        .Case("declare", OMPD_declare) @@ -80,19 +98,21 @@ static unsigned getOpenMPDirectiveKindEx(StringRef S) {        .Case("reduction", OMPD_reduction)        .Case("update", OMPD_update)        .Case("mapper", OMPD_mapper) +      .Case("variant", OMPD_variant)        .Default(OMPD_unknown);  } -static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { +static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {    // Array of foldings: F[i][0] F[i][1] ===> F[i][2].    // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd    // TODO: add other combined directives in topological order. -  static const unsigned F[][3] = { +  static const OpenMPDirectiveKindExWrapper F[][3] = {        {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},        {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},        {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},        {OMPD_declare, OMPD_simd, OMPD_declare_simd},        {OMPD_declare, OMPD_target, OMPD_declare_target}, +      {OMPD_declare, OMPD_variant, OMPD_declare_variant},        {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},        {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},        {OMPD_distribute_parallel_for, OMPD_simd, @@ -131,10 +151,16 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {        {OMPD_target_teams_distribute_parallel, OMPD_for,         OMPD_target_teams_distribute_parallel_for},        {OMPD_target_teams_distribute_parallel_for, OMPD_simd, -       OMPD_target_teams_distribute_parallel_for_simd}}; +       OMPD_target_teams_distribute_parallel_for_simd}, +      {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, +      {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, +      {OMPD_parallel, OMPD_master, OMPD_parallel_master}, +      {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}, +      {OMPD_parallel_master_taskloop, OMPD_simd, +       OMPD_parallel_master_taskloop_simd}};    enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };    Token Tok = P.getCurToken(); -  unsigned DKind = +  OpenMPDirectiveKindExWrapper DKind =        Tok.isAnnotation()            ? static_cast<unsigned>(OMPD_unknown)            : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); @@ -146,7 +172,7 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {        continue;      Tok = P.getPreprocessor().LookAhead(0); -    unsigned SDKind = +    OpenMPDirectiveKindExWrapper SDKind =          Tok.isAnnotation()              ? static_cast<unsigned>(OMPD_unknown)              : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); @@ -228,8 +254,9 @@ Parser::DeclGroupPtrTy  Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {    // Parse '('.    BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); -  if (T.expectAndConsume(diag::err_expected_lparen_after, -                         getOpenMPDirectiveName(OMPD_declare_reduction))) { +  if (T.expectAndConsume( +          diag::err_expected_lparen_after, +          getOpenMPDirectiveName(OMPD_declare_reduction).data())) {      SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);      return DeclGroupPtrTy();    } @@ -316,9 +343,8 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {                                      Scope::OpenMPDirectiveScope);      // Parse <combiner> expression.      Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); -    ExprResult CombinerResult = -        Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), -                                    D->getLocation(), /*DiscardedValue*/ false); +    ExprResult CombinerResult = Actions.ActOnFinishFullExpr( +        ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);      Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());      if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && @@ -357,14 +383,8 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {          // Check if initializer is omp_priv <init_expr> or something else.          if (Tok.is(tok::identifier) &&              Tok.getIdentifierInfo()->isStr("omp_priv")) { -          if (Actions.getLangOpts().CPlusPlus) { -            InitializerResult = Actions.ActOnFinishFullExpr( -                ParseAssignmentExpression().get(), D->getLocation(), -                /*DiscardedValue*/ false); -          } else { -            ConsumeToken(); -            ParseOpenMPReductionInitializerForDecl(OmpPrivParm); -          } +          ConsumeToken(); +          ParseOpenMPReductionInitializerForDecl(OmpPrivParm);          } else {            InitializerResult = Actions.ActOnFinishFullExpr(                ParseAssignmentExpression().get(), D->getLocation(), @@ -408,7 +428,8 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {        return;      } -    ExprResult Init(ParseInitializer()); +    PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm); +    ExprResult Init = ParseInitializer();      if (Init.isInvalid()) {        SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); @@ -486,7 +507,7 @@ Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {    // Parse '('    BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);    if (T.expectAndConsume(diag::err_expected_lparen_after, -                         getOpenMPDirectiveName(OMPD_declare_mapper))) { +                         getOpenMPDirectiveName(OMPD_declare_mapper).data())) {      SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);      return DeclGroupPtrTy();    } @@ -713,10 +734,12 @@ static bool parseDeclareSimdClauses(            CKind == OMPC_linear) {          Parser::OpenMPVarListDataTy Data;          SmallVectorImpl<Expr *> *Vars = &Uniforms; -        if (CKind == OMPC_aligned) +        if (CKind == OMPC_aligned) {            Vars = &Aligneds; -        else if (CKind == OMPC_linear) +        } else if (CKind == OMPC_linear) { +          Data.ExtraModifier = OMPC_LINEAR_val;            Vars = &Linears; +        }          P.ConsumeToken();          if (P.ParseOpenMPVarList(OMPD_declare_simd, @@ -725,11 +748,15 @@ static bool parseDeclareSimdClauses(          if (CKind == OMPC_aligned) {            Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);          } else if (CKind == OMPC_linear) { -          if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind, -                                                       Data.DepLinMapLoc)) -            Data.LinKind = OMPC_LINEAR_val; +          assert(0 <= Data.ExtraModifier && +                 Data.ExtraModifier <= OMPC_LINEAR_unknown && +                 "Unexpected linear modifier."); +          if (P.getActions().CheckOpenMPLinearModifier( +                  static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier), +                  Data.DepLinMapLastLoc)) +            Data.ExtraModifier = OMPC_LINEAR_val;            LinModifiers.append(Linears.size() - LinModifiers.size(), -                              Data.LinKind); +                              Data.ExtraModifier);            Steps.append(Linears.size() - Steps.size(), Data.TailExpr);          }        } else @@ -752,6 +779,7 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,                        /*IsReinject*/ true);    // Consume the previously pushed token.    ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); +  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);    FNContextRAII FnContext(*this, Ptr);    OMPDeclareSimdDeclAttr::BranchStateTy BS = @@ -782,25 +810,458 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,        LinModifiers, Steps, SourceRange(Loc, EndLoc));  } +/// Parse optional 'score' '(' <expr> ')' ':'. +static ExprResult parseContextScore(Parser &P) { +  ExprResult ScoreExpr; +  Sema::OMPCtxStringType Buffer; +  StringRef SelectorName = +      P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); +  if (!SelectorName.equals("score")) +    return ScoreExpr; +  (void)P.ConsumeToken(); +  SourceLocation RLoc; +  ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); +  // Parse ':' +  if (P.getCurToken().is(tok::colon)) +    (void)P.ConsumeAnyToken(); +  else +    P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon) +        << "context selector score clause"; +  return ScoreExpr; +} + +/// Parse context selector for 'implementation' selector set: +/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> } +/// ')' +static void +parseImplementationSelector(Parser &P, SourceLocation Loc, +                            llvm::StringMap<SourceLocation> &UsedCtx, +                            SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) { +  const Token &Tok = P.getCurToken(); +  // Parse inner context selector set name, if any. +  if (!Tok.is(tok::identifier)) { +    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) +        << "implementation"; +    // Skip until either '}', ')', or end of directive. +    while (!P.SkipUntil(tok::r_brace, tok::r_paren, +                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) +      ; +    return; +  } +  Sema::OMPCtxStringType Buffer; +  StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer); +  auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation()); +  if (!Res.second) { +    // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. +    // Each trait-selector-name can only be specified once. +    P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use) +        << CtxSelectorName << "implementation"; +    P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) +        << CtxSelectorName; +  } +  OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName); +  (void)P.ConsumeToken(); +  switch (CSKind) { +  case OMP_CTX_vendor: { +    // Parse '('. +    BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); +    (void)T.expectAndConsume(diag::err_expected_lparen_after, +                             CtxSelectorName.data()); +    ExprResult Score = parseContextScore(P); +    llvm::UniqueVector<Sema::OMPCtxStringType> Vendors; +    do { +      // Parse <vendor>. +      StringRef VendorName; +      if (Tok.is(tok::identifier)) { +        Buffer.clear(); +        VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); +        (void)P.ConsumeToken(); +        if (!VendorName.empty()) +          Vendors.insert(VendorName); +      } else { +        P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) +            << "vendor identifier" +            << "vendor" +            << "implementation"; +      } +      if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) { +        P.Diag(Tok, diag::err_expected_punc) +            << (VendorName.empty() ? "vendor name" : VendorName); +      } +    } while (Tok.is(tok::identifier)); +    // Parse ')'. +    (void)T.consumeClose(); +    if (!Vendors.empty()) +      Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors); +    break; +  } +  case OMP_CTX_kind: +  case OMP_CTX_unknown: +    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) +        << "implementation"; +    // Skip until either '}', ')', or end of directive. +    while (!P.SkipUntil(tok::r_brace, tok::r_paren, +                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) +      ; +    return; +  } +} + +/// Parse context selector for 'device' selector set: +/// 'kind' '(' <kind> { ',' <kind> } ')' +static void +parseDeviceSelector(Parser &P, SourceLocation Loc, +                    llvm::StringMap<SourceLocation> &UsedCtx, +                    SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) { +  const Token &Tok = P.getCurToken(); +  // Parse inner context selector set name, if any. +  if (!Tok.is(tok::identifier)) { +    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) +        << "device"; +    // Skip until either '}', ')', or end of directive. +    while (!P.SkipUntil(tok::r_brace, tok::r_paren, +                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) +      ; +    return; +  } +  Sema::OMPCtxStringType Buffer; +  StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer); +  auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation()); +  if (!Res.second) { +    // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. +    // Each trait-selector-name can only be specified once. +    P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use) +        << CtxSelectorName << "device"; +    P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) +        << CtxSelectorName; +  } +  OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName); +  (void)P.ConsumeToken(); +  switch (CSKind) { +  case OMP_CTX_kind: { +    // Parse '('. +    BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); +    (void)T.expectAndConsume(diag::err_expected_lparen_after, +                             CtxSelectorName.data()); +    llvm::UniqueVector<Sema::OMPCtxStringType> Kinds; +    do { +      // Parse <kind>. +      StringRef KindName; +      if (Tok.is(tok::identifier)) { +        Buffer.clear(); +        KindName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); +        SourceLocation SLoc = P.getCurToken().getLocation(); +        (void)P.ConsumeToken(); +        if (llvm::StringSwitch<bool>(KindName) +                .Case("host", false) +                .Case("nohost", false) +                .Case("cpu", false) +                .Case("gpu", false) +                .Case("fpga", false) +                .Default(true)) { +          P.Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName; +        } else { +          Kinds.insert(KindName); +        } +      } else { +        P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) +            << "'host', 'nohost', 'cpu', 'gpu', or 'fpga'" +            << "kind" +            << "device"; +      } +      if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) { +        P.Diag(Tok, diag::err_expected_punc) +            << (KindName.empty() ? "kind of device" : KindName); +      } +    } while (Tok.is(tok::identifier)); +    // Parse ')'. +    (void)T.consumeClose(); +    if (!Kinds.empty()) +      Data.emplace_back(OMP_CTX_SET_device, CSKind, ExprResult(), Kinds); +    break; +  } +  case OMP_CTX_vendor: +  case OMP_CTX_unknown: +    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) +        << "device"; +    // Skip until either '}', ')', or end of directive. +    while (!P.SkipUntil(tok::r_brace, tok::r_paren, +                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) +      ; +    return; +  } +} + +/// Parses clauses for 'declare variant' directive. +/// clause: +/// <selector_set_name> '=' '{' <context_selectors> '}' +/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ] +bool Parser::parseOpenMPContextSelectors( +    SourceLocation Loc, SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) { +  llvm::StringMap<SourceLocation> UsedCtxSets; +  do { +    // Parse inner context selector set name. +    if (!Tok.is(tok::identifier)) { +      Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector) +          << getOpenMPClauseName(OMPC_match); +      return true; +    } +    Sema::OMPCtxStringType Buffer; +    StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer); +    auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation()); +    if (!Res.second) { +      // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. +      // Each trait-set-selector-name can only be specified once. +      Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_set_mutiple_use) +          << CtxSelectorSetName; +      Diag(Res.first->getValue(), +           diag::note_omp_declare_variant_ctx_set_used_here) +          << CtxSelectorSetName; +    } +    // Parse '='. +    (void)ConsumeToken(); +    if (Tok.isNot(tok::equal)) { +      Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected) +          << CtxSelectorSetName; +      return true; +    } +    (void)ConsumeToken(); +    // TBD: add parsing of known context selectors. +    // Unknown selector - just ignore it completely. +    { +      // Parse '{'. +      BalancedDelimiterTracker TBr(*this, tok::l_brace, +                                   tok::annot_pragma_openmp_end); +      if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "=")) +        return true; +      OpenMPContextSelectorSetKind CSSKind = +          getOpenMPContextSelectorSet(CtxSelectorSetName); +      llvm::StringMap<SourceLocation> UsedCtx; +      do { +        switch (CSSKind) { +        case OMP_CTX_SET_implementation: +          parseImplementationSelector(*this, Loc, UsedCtx, Data); +          break; +        case OMP_CTX_SET_device: +          parseDeviceSelector(*this, Loc, UsedCtx, Data); +          break; +        case OMP_CTX_SET_unknown: +          // Skip until either '}', ')', or end of directive. +          while (!SkipUntil(tok::r_brace, tok::r_paren, +                            tok::annot_pragma_openmp_end, StopBeforeMatch)) +            ; +          break; +        } +        const Token PrevTok = Tok; +        if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace)) +          Diag(Tok, diag::err_omp_expected_comma_brace) +              << (PrevTok.isAnnotation() ? "context selector trait" +                                         : PP.getSpelling(PrevTok)); +      } while (Tok.is(tok::identifier)); +      // Parse '}'. +      (void)TBr.consumeClose(); +    } +    // Consume ',' +    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) +      (void)ExpectAndConsume(tok::comma); +  } while (Tok.isAnyIdentifier()); +  return false; +} + +/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'. +void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, +                                           CachedTokens &Toks, +                                           SourceLocation Loc) { +  PP.EnterToken(Tok, /*IsReinject*/ true); +  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, +                      /*IsReinject*/ true); +  // Consume the previously pushed token. +  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); +  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); + +  FNContextRAII FnContext(*this, Ptr); +  // Parse function declaration id. +  SourceLocation RLoc; +  // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs +  // instead of MemberExprs. +  ExprResult AssociatedFunction; +  { +    // Do not mark function as is used to prevent its emission if this is the +    // only place where it is used. +    EnterExpressionEvaluationContext Unevaluated( +        Actions, Sema::ExpressionEvaluationContext::Unevaluated); +    AssociatedFunction = ParseOpenMPParensExpr( +        getOpenMPDirectiveName(OMPD_declare_variant), RLoc, +        /*IsAddressOfOperand=*/true); +  } +  if (!AssociatedFunction.isUsable()) { +    if (!Tok.is(tok::annot_pragma_openmp_end)) +      while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) +        ; +    // Skip the last annot_pragma_openmp_end. +    (void)ConsumeAnnotationToken(); +    return; +  } +  Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = +      Actions.checkOpenMPDeclareVariantFunction( +          Ptr, AssociatedFunction.get(), SourceRange(Loc, Tok.getLocation())); + +  // Parse 'match'. +  OpenMPClauseKind CKind = Tok.isAnnotation() +                               ? OMPC_unknown +                               : getOpenMPClauseKind(PP.getSpelling(Tok)); +  if (CKind != OMPC_match) { +    Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) +        << getOpenMPClauseName(OMPC_match); +    while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) +      ; +    // Skip the last annot_pragma_openmp_end. +    (void)ConsumeAnnotationToken(); +    return; +  } +  (void)ConsumeToken(); +  // Parse '('. +  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); +  if (T.expectAndConsume(diag::err_expected_lparen_after, +                         getOpenMPClauseName(OMPC_match))) { +    while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) +      ; +    // Skip the last annot_pragma_openmp_end. +    (void)ConsumeAnnotationToken(); +    return; +  } + +  // Parse inner context selectors. +  SmallVector<Sema::OMPCtxSelectorData, 4> Data; +  if (!parseOpenMPContextSelectors(Loc, Data)) { +    // Parse ')'. +    (void)T.consumeClose(); +    // Need to check for extra tokens. +    if (Tok.isNot(tok::annot_pragma_openmp_end)) { +      Diag(Tok, diag::warn_omp_extra_tokens_at_eol) +          << getOpenMPDirectiveName(OMPD_declare_variant); +    } +  } + +  // Skip last tokens. +  while (Tok.isNot(tok::annot_pragma_openmp_end)) +    ConsumeAnyToken(); +  if (DeclVarData.hasValue()) +    Actions.ActOnOpenMPDeclareVariantDirective( +        DeclVarData.getValue().first, DeclVarData.getValue().second, +        SourceRange(Loc, Tok.getLocation()), Data); +  // Skip the last annot_pragma_openmp_end. +  (void)ConsumeAnnotationToken(); +} + +/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. +/// +///    default-clause: +///         'default' '(' 'none' | 'shared' ') +/// +///    proc_bind-clause: +///         'proc_bind' '(' 'master' | 'close' | 'spread' ') +/// +///    device_type-clause: +///         'device_type' '(' 'host' | 'nohost' | 'any' )' +namespace { +  struct SimpleClauseData { +    unsigned Type; +    SourceLocation Loc; +    SourceLocation LOpen; +    SourceLocation TypeLoc; +    SourceLocation RLoc; +    SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen, +                     SourceLocation TypeLoc, SourceLocation RLoc) +        : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {} +  }; +} // anonymous namespace + +static Optional<SimpleClauseData> +parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { +  const Token &Tok = P.getCurToken(); +  SourceLocation Loc = Tok.getLocation(); +  SourceLocation LOpen = P.ConsumeToken(); +  // Parse '('. +  BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); +  if (T.expectAndConsume(diag::err_expected_lparen_after, +                         getOpenMPClauseName(Kind))) +    return llvm::None; + +  unsigned Type = getOpenMPSimpleClauseType( +      Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok)); +  SourceLocation TypeLoc = Tok.getLocation(); +  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && +      Tok.isNot(tok::annot_pragma_openmp_end)) +    P.ConsumeAnyToken(); + +  // Parse ')'. +  SourceLocation RLoc = Tok.getLocation(); +  if (!T.consumeClose()) +    RLoc = T.getCloseLocation(); + +  return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc); +} +  Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {    // OpenMP 4.5 syntax with list of entities.    Sema::NamedDeclSetType SameDirectiveDecls; +  SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation, +                         NamedDecl *>, +              4> +      DeclareTargetDecls; +  OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any; +  SourceLocation DeviceTypeLoc;    while (Tok.isNot(tok::annot_pragma_openmp_end)) {      OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;      if (Tok.is(tok::identifier)) {        IdentifierInfo *II = Tok.getIdentifierInfo();        StringRef ClauseName = II->getName(); -      // Parse 'to|link' clauses. -      if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) { -        Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName; +      bool IsDeviceTypeClause = +          getLangOpts().OpenMP >= 50 && +          getOpenMPClauseKind(ClauseName) == OMPC_device_type; +      // Parse 'to|link|device_type' clauses. +      if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) && +          !IsDeviceTypeClause) { +        Diag(Tok, diag::err_omp_declare_target_unexpected_clause) +            << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);          break;        } +      // Parse 'device_type' clause and go to next clause if any. +      if (IsDeviceTypeClause) { +        Optional<SimpleClauseData> DevTypeData = +            parseOpenMPSimpleClause(*this, OMPC_device_type); +        if (DevTypeData.hasValue()) { +          if (DeviceTypeLoc.isValid()) { +            // We already saw another device_type clause, diagnose it. +            Diag(DevTypeData.getValue().Loc, +                 diag::warn_omp_more_one_device_type_clause); +          } +          switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) { +          case OMPC_DEVICE_TYPE_any: +            DT = OMPDeclareTargetDeclAttr::DT_Any; +            break; +          case OMPC_DEVICE_TYPE_host: +            DT = OMPDeclareTargetDeclAttr::DT_Host; +            break; +          case OMPC_DEVICE_TYPE_nohost: +            DT = OMPDeclareTargetDeclAttr::DT_NoHost; +            break; +          case OMPC_DEVICE_TYPE_unknown: +            llvm_unreachable("Unexpected device_type"); +          } +          DeviceTypeLoc = DevTypeData.getValue().Loc; +        } +        continue; +      }        ConsumeToken();      } -    auto &&Callback = [this, MT, &SameDirectiveDecls]( -        CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { -      Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, -                                           SameDirectiveDecls); +    auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls]( +                          CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { +      NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName( +          getCurScope(), SS, NameInfo, SameDirectiveDecls); +      if (ND) +        DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);      };      if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,                                   /*AllowScopeSpecifier=*/true)) @@ -812,6 +1273,15 @@ Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {    }    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);    ConsumeAnyToken(); +  for (auto &MTLocDecl : DeclareTargetDecls) { +    OMPDeclareTargetDeclAttr::MapTypeTy MT; +    SourceLocation Loc; +    NamedDecl *ND; +    std::tie(MT, Loc, ND) = MTLocDecl; +    // device_type clause is applied only to functions. +    Actions.ActOnOpenMPDeclareTargetName( +        ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT); +  }    SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),                                 SameDirectiveDecls.end());    if (Decls.empty()) @@ -865,13 +1335,45 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,  ///         annot_pragma_openmp_end  ///  Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( -    AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, +    AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,      DeclSpec::TST TagType, Decl *Tag) {    assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); +  ParsingOpenMPDirectiveRAII DirScope(*this);    ParenBraceBracketBalancer BalancerRAIIObj(*this); -  SourceLocation Loc = ConsumeAnnotationToken(); -  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); +  SourceLocation Loc; +  OpenMPDirectiveKind DKind; +  if (Delayed) { +    TentativeParsingAction TPA(*this); +    Loc = ConsumeAnnotationToken(); +    DKind = parseOpenMPDirectiveKind(*this); +    if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) { +      // Need to delay parsing until completion of the parent class. +      TPA.Revert(); +      CachedTokens Toks; +      unsigned Cnt = 1; +      Toks.push_back(Tok); +      while (Cnt && Tok.isNot(tok::eof)) { +        (void)ConsumeAnyToken(); +        if (Tok.is(tok::annot_pragma_openmp)) +          ++Cnt; +        else if (Tok.is(tok::annot_pragma_openmp_end)) +          --Cnt; +        Toks.push_back(Tok); +      } +      // Skip last annot_pragma_openmp_end. +      if (Cnt == 0) +        (void)ConsumeAnyToken(); +      auto *LP = new LateParsedPragma(this, AS); +      LP->takeToks(Toks); +      getCurrentClass().LateParsedDeclarations.push_back(LP); +      return nullptr; +    } +    TPA.Commit(); +  } else { +    Loc = ConsumeAnnotationToken(); +    DKind = parseOpenMPDirectiveKind(*this); +  }    switch (DKind) {    case OMPD_threadprivate: { @@ -1005,13 +1507,15 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(      }      break;    } +  case OMPD_declare_variant:    case OMPD_declare_simd: {      // The syntax is: -    // { #pragma omp declare simd } +    // { #pragma omp declare {simd|variant} }      // <function-declaration-or-definition>      // -    ConsumeToken();      CachedTokens Toks; +    Toks.push_back(Tok); +    ConsumeToken();      while(Tok.isNot(tok::annot_pragma_openmp_end)) {        Toks.push_back(Tok);        ConsumeAnyToken(); @@ -1021,7 +1525,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(      DeclGroupPtrTy Ptr;      if (Tok.is(tok::annot_pragma_openmp)) { -      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag); +      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, +                                                       TagType, Tag);      } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {        // Here we expect to see some function declaration.        if (AS == AS_none) { @@ -1035,10 +1540,16 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(        }      }      if (!Ptr) { -      Diag(Loc, diag::err_omp_decl_in_declare_simd); +      Diag(Loc, diag::err_omp_decl_in_declare_simd_variant) +          << (DKind == OMPD_declare_simd ? 0 : 1);        return DeclGroupPtrTy();      } -    return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); +    if (DKind == OMPD_declare_simd) +      return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); +    assert(DKind == OMPD_declare_variant && +           "Expected declare variant directive only"); +    ParseOMPDeclareVariantClauses(Ptr, Toks, Loc); +    return Ptr;    }    case OMPD_declare_target: {      SourceLocation DTLoc = ConsumeAnyToken(); @@ -1108,6 +1619,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(    case OMPD_parallel_for:    case OMPD_parallel_for_simd:    case OMPD_parallel_sections: +  case OMPD_parallel_master:    case OMPD_atomic:    case OMPD_target:    case OMPD_teams: @@ -1120,6 +1632,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(    case OMPD_target_parallel_for:    case OMPD_taskloop:    case OMPD_taskloop_simd: +  case OMPD_master_taskloop: +  case OMPD_master_taskloop_simd: +  case OMPD_parallel_master_taskloop: +  case OMPD_parallel_master_taskloop_simd:    case OMPD_distribute:    case OMPD_end_declare_target:    case OMPD_target_update: @@ -1171,27 +1687,26 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(  ///       executable-directive:  ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |  ///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | -///         'parallel for' | 'parallel sections' | 'task' | 'taskyield' | -///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | -///         'for simd' | 'parallel for simd' | 'target' | 'target data' | -///         'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | -///         'distribute' | 'target enter data' | 'target exit data' | -///         'target parallel' | 'target parallel for' | -///         'target update' | 'distribute parallel for' | -///         'distribute paralle for simd' | 'distribute simd' | -///         'target parallel for simd' | 'target simd' | -///         'teams distribute' | 'teams distribute simd' | -///         'teams distribute parallel for simd' | -///         'teams distribute parallel for' | 'target teams' | -///         'target teams distribute' | -///         'target teams distribute parallel for' | -///         'target teams distribute parallel for simd' | -///         'target teams distribute simd' {clause} +///         'parallel for' | 'parallel sections' | 'parallel master' | 'task' | +///         'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | +///         'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target +///         data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | +///         'master taskloop' | 'master taskloop simd' | 'parallel master +///         taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target +///         enter data' | 'target exit data' | 'target parallel' | 'target +///         parallel for' | 'target update' | 'distribute parallel for' | +///         'distribute paralle for simd' | 'distribute simd' | 'target parallel +///         for simd' | 'target simd' | 'teams distribute' | 'teams distribute +///         simd' | 'teams distribute parallel for simd' | 'teams distribute +///         parallel for' | 'target teams' | 'target teams distribute' | 'target +///         teams distribute parallel for' | 'target teams distribute parallel +///         for simd' | 'target teams distribute simd' {clause}  ///         annot_pragma_openmp_end  ///  StmtResult  Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {    assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); +  ParsingOpenMPDirectiveRAII DirScope(*this);    ParenBraceBracketBalancer BalancerRAIIObj(*this);    SmallVector<OMPClause *, 5> Clauses;    SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> @@ -1351,6 +1866,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {    case OMPD_parallel_for:    case OMPD_parallel_for_simd:    case OMPD_parallel_sections: +  case OMPD_parallel_master:    case OMPD_task:    case OMPD_ordered:    case OMPD_atomic: @@ -1362,6 +1878,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {    case OMPD_target_parallel_for:    case OMPD_taskloop:    case OMPD_taskloop_simd: +  case OMPD_master_taskloop: +  case OMPD_master_taskloop_simd: +  case OMPD_parallel_master_taskloop: +  case OMPD_parallel_master_taskloop_simd:    case OMPD_distribute:    case OMPD_distribute_parallel_for:    case OMPD_distribute_parallel_for_simd: @@ -1474,6 +1994,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {    case OMPD_declare_target:    case OMPD_end_declare_target:    case OMPD_requires: +  case OMPD_declare_variant:      Diag(Tok, diag::err_omp_unexpected_directive)          << 1 << getOpenMPDirectiveName(DKind);      SkipUntil(tok::annot_pragma_openmp_end); @@ -1498,7 +2019,7 @@ bool Parser::ParseOpenMPSimpleVarList(    // Parse '('.    BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);    if (T.expectAndConsume(diag::err_expected_lparen_after, -                         getOpenMPDirectiveName(Kind))) +                         getOpenMPDirectiveName(Kind).data()))      return true;    bool IsCorrect = true;    bool NoIdentIsFound = true; @@ -1571,7 +2092,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,    bool ErrorFound = false;    bool WrongDirective = false;    // Check if clause is allowed for the given directive. -  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { +  if (CKind != OMPC_unknown && +      !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {      Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)                                                 << getOpenMPDirectiveName(DKind);      ErrorFound = true; @@ -1650,15 +2172,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,    case OMPC_defaultmap:      // OpenMP [2.7.1, Restrictions, p. 3]      //  Only one schedule clause can appear on a loop directive. -    // OpenMP [2.10.4, Restrictions, p. 106] +    // OpenMP 4.5 [2.10.4, Restrictions, p. 106]      //  At most one defaultmap clause can appear on the directive. -    if (!FirstClause) { +    if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && +        !FirstClause) {        Diag(Tok, diag::err_omp_more_one_clause)            << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;        ErrorFound = true;      }      LLVM_FALLTHROUGH; -    case OMPC_if:      Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);      break; @@ -1710,8 +2232,10 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,    case OMPC_use_device_ptr:    case OMPC_is_device_ptr:    case OMPC_allocate: +  case OMPC_nontemporal:      Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);      break; +  case OMPC_device_type:    case OMPC_unknown:      Diag(Tok, diag::warn_omp_extra_tokens_at_eol)          << getOpenMPDirectiveName(DKind); @@ -1719,6 +2243,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,      break;    case OMPC_threadprivate:    case OMPC_uniform: +  case OMPC_match:      if (!WrongDirective)        Diag(Tok, diag::err_omp_unexpected_clause)            << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); @@ -1732,14 +2257,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,  /// constructs.  /// \param RLoc Returned location of right paren.  ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, -                                         SourceLocation &RLoc) { +                                         SourceLocation &RLoc, +                                         bool IsAddressOfOperand) {    BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);    if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))      return ExprError();    SourceLocation ELoc = Tok.getLocation(); -  ExprResult LHS(ParseCastExpression( -      /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); +  ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand, +                                     NotTypeCast));    ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));    Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); @@ -1811,29 +2337,12 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,  ///  OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,                                             bool ParseOnly) { -  SourceLocation Loc = Tok.getLocation(); -  SourceLocation LOpen = ConsumeToken(); -  // Parse '('. -  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); -  if (T.expectAndConsume(diag::err_expected_lparen_after, -                         getOpenMPClauseName(Kind))) -    return nullptr; - -  unsigned Type = getOpenMPSimpleClauseType( -      Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); -  SourceLocation TypeLoc = Tok.getLocation(); -  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && -      Tok.isNot(tok::annot_pragma_openmp_end)) -    ConsumeAnyToken(); - -  // Parse ')'. -  SourceLocation RLoc = Tok.getLocation(); -  if (!T.consumeClose()) -    RLoc = T.getCloseLocation(); - -  if (ParseOnly) +  llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); +  if (!Val || ParseOnly)      return nullptr; -  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc); +  return Actions.ActOnOpenMPSimpleClause( +      Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, +      Val.getValue().Loc, Val.getValue().RLoc);  }  /// Parsing of OpenMP clauses like 'ordered'. @@ -1956,8 +2465,13 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,        DelimLoc = ConsumeAnyToken();    } else if (Kind == OMPC_defaultmap) {      // Get a defaultmap modifier -    Arg.push_back(getOpenMPSimpleClauseType( -        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); +    unsigned Modifier = getOpenMPSimpleClauseType( +        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); +    // Set defaultmap modifier to unknown if it is either scalar, aggregate, or +    // pointer +    if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) +      Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; +    Arg.push_back(Modifier);      KLoc.push_back(Tok.getLocation());      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&          Tok.isNot(tok::annot_pragma_openmp_end)) @@ -1978,15 +2492,16 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,      assert(Kind == OMPC_if);      KLoc.push_back(Tok.getLocation());      TentativeParsingAction TPA(*this); -    Arg.push_back(parseOpenMPDirectiveKind(*this)); -    if (Arg.back() != OMPD_unknown) { +    auto DK = parseOpenMPDirectiveKind(*this); +    Arg.push_back(DK); +    if (DK != OMPD_unknown) {        ConsumeToken();        if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {          TPA.Commit();          DelimLoc = ConsumeToken();        } else {          TPA.Revert(); -        Arg.back() = OMPD_unknown; +        Arg.back() = unsigned(OMPD_unknown);        }      } else {        TPA.Revert(); @@ -1998,7 +2513,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,                            Kind == OMPC_if;    if (NeedAnExpression) {      SourceLocation ELoc = Tok.getLocation(); -    ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); +    ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));      Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);      Val =          Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); @@ -2163,8 +2678,8 @@ static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {      P.Diag(Tok, diag::err_omp_map_type_missing);      return;    } -  Data.MapType = isMapType(P); -  if (Data.MapType == OMPC_MAP_unknown) +  Data.ExtraModifier = isMapType(P); +  if (Data.ExtraModifier == OMPC_MAP_unknown)      P.Diag(Tok, diag::err_omp_unknown_map_type);    P.ConsumeToken();  } @@ -2209,20 +2724,18 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,        Data.ReductionOrMapperId =            Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);    } else if (Kind == OMPC_depend) { -  // Handle dependency type for depend clause. +    // Handle dependency type for depend clause.      ColonProtectionRAIIObject ColonRAII(*this); -    Data.DepKind = -        static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( -            Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); -    Data.DepLinMapLoc = Tok.getLocation(); - -    if (Data.DepKind == OMPC_DEPEND_unknown) { +    Data.ExtraModifier = getOpenMPSimpleClauseType( +        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""); +    Data.DepLinMapLastLoc = Tok.getLocation(); +    if (Data.ExtraModifier == OMPC_DEPEND_unknown) {        SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,                  StopBeforeMatch);      } else {        ConsumeToken();        // Special processing for depend(source) clause. -      if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) { +      if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) {          // Parse ')'.          T.consumeClose();          return false; @@ -2237,13 +2750,32 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,      }    } else if (Kind == OMPC_linear) {      // Try to parse modifier if any. +    Data.ExtraModifier = OMPC_LINEAR_val;      if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { -      Data.LinKind = static_cast<OpenMPLinearClauseKind>( -          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); -      Data.DepLinMapLoc = ConsumeToken(); +      Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); +      Data.DepLinMapLastLoc = ConsumeToken();        LinearT.consumeOpen();        NeedRParenForLinear = true;      } +  } else if (Kind == OMPC_lastprivate) { +    // Try to parse modifier if any. +    Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; +    // Conditional modifier allowed only in OpenMP 5.0 and not supported in +    // distribute and taskloop based directives. +    if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && +         !isOpenMPTaskLoopDirective(DKind)) && +        Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { +      Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); +      Data.DepLinMapLastLoc = Tok.getLocation(); +      if (Data.ExtraModifier == OMPC_LASTPRIVATE_unknown) { +        SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, +                  StopBeforeMatch); +      } else { +        ConsumeToken(); +      } +      assert(Tok.is(tok::colon) && "Expected colon."); +      Data.ColonLoc = ConsumeToken(); +    }    } else if (Kind == OMPC_map) {      // Handle map type for map clause.      ColonProtectionRAIIObject ColonRAII(*this); @@ -2251,7 +2783,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,      // The first identifier may be a list item, a map-type or a      // map-type-modifier. The map-type can also be delete which has the same      // spelling of the C++ delete keyword. -    Data.DepLinMapLoc = Tok.getLocation(); +    Data.ExtraModifier = OMPC_MAP_unknown; +    Data.DepLinMapLastLoc = Tok.getLocation();      // Check for presence of a colon in the map clause.      TentativeParsingAction TPA(*this); @@ -2271,8 +2804,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,        else          SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);      } -    if (Data.MapType == OMPC_MAP_unknown) { -      Data.MapType = OMPC_MAP_tofrom; +    if (Data.ExtraModifier == OMPC_MAP_unknown) { +      Data.ExtraModifier = OMPC_MAP_tofrom;        Data.IsMapTypeImplicit = true;      } @@ -2338,8 +2871,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,        (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&         Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||        (Kind == OMPC_reduction && !InvalidReductionId) || -      (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) || -      (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); +      (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || +      (Kind == OMPC_depend && Data.ExtraModifier != 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))) { @@ -2389,7 +2922,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,    Data.RLoc = Tok.getLocation();    if (!T.consumeClose())      Data.RLoc = T.getCloseLocation(); -  return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && +  return (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown &&            Vars.empty()) ||           (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||           (MustHaveTail && !Data.TailExpr) || InvalidReductionId || @@ -2459,8 +2992,8 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,    OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);    return Actions.ActOnOpenMPVarListClause(        Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc, -      Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, Data.DepKind, -      Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, -      Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc); +      Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, +      Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, +      Data.IsMapTypeImplicit, Data.DepLinMapLastLoc);  }  | 
