xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Parse/ParseOpenMP.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg /// \file
97330f729Sjoerg /// This file implements parsing of all OpenMP directives and clauses.
107330f729Sjoerg ///
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "clang/AST/ASTContext.h"
14*e038c9c4Sjoerg #include "clang/AST/OpenMPClause.h"
157330f729Sjoerg #include "clang/AST/StmtOpenMP.h"
16*e038c9c4Sjoerg #include "clang/Basic/OpenMPKinds.h"
17*e038c9c4Sjoerg #include "clang/Basic/TargetInfo.h"
18*e038c9c4Sjoerg #include "clang/Basic/TokenKinds.h"
197330f729Sjoerg #include "clang/Parse/ParseDiagnostic.h"
207330f729Sjoerg #include "clang/Parse/Parser.h"
217330f729Sjoerg #include "clang/Parse/RAIIObjectsForParser.h"
227330f729Sjoerg #include "clang/Sema/Scope.h"
237330f729Sjoerg #include "llvm/ADT/PointerIntPair.h"
24*e038c9c4Sjoerg #include "llvm/ADT/StringSwitch.h"
257330f729Sjoerg #include "llvm/ADT/UniqueVector.h"
26*e038c9c4Sjoerg #include "llvm/Frontend/OpenMP/OMPContext.h"
277330f729Sjoerg 
287330f729Sjoerg using namespace clang;
29*e038c9c4Sjoerg using namespace llvm::omp;
307330f729Sjoerg 
317330f729Sjoerg //===----------------------------------------------------------------------===//
327330f729Sjoerg // OpenMP declarative directives.
337330f729Sjoerg //===----------------------------------------------------------------------===//
347330f729Sjoerg 
357330f729Sjoerg namespace {
367330f729Sjoerg enum OpenMPDirectiveKindEx {
37*e038c9c4Sjoerg   OMPD_cancellation = llvm::omp::Directive_enumSize + 1,
387330f729Sjoerg   OMPD_data,
397330f729Sjoerg   OMPD_declare,
407330f729Sjoerg   OMPD_end,
417330f729Sjoerg   OMPD_end_declare,
427330f729Sjoerg   OMPD_enter,
437330f729Sjoerg   OMPD_exit,
447330f729Sjoerg   OMPD_point,
457330f729Sjoerg   OMPD_reduction,
467330f729Sjoerg   OMPD_target_enter,
477330f729Sjoerg   OMPD_target_exit,
487330f729Sjoerg   OMPD_update,
497330f729Sjoerg   OMPD_distribute_parallel,
507330f729Sjoerg   OMPD_teams_distribute_parallel,
517330f729Sjoerg   OMPD_target_teams_distribute_parallel,
527330f729Sjoerg   OMPD_mapper,
537330f729Sjoerg   OMPD_variant,
54*e038c9c4Sjoerg   OMPD_begin,
55*e038c9c4Sjoerg   OMPD_begin_declare,
56*e038c9c4Sjoerg };
57*e038c9c4Sjoerg 
58*e038c9c4Sjoerg // Helper to unify the enum class OpenMPDirectiveKind with its extension
59*e038c9c4Sjoerg // the OpenMPDirectiveKindEx enum which allows to use them together as if they
60*e038c9c4Sjoerg // are unsigned values.
61*e038c9c4Sjoerg struct OpenMPDirectiveKindExWrapper {
OpenMPDirectiveKindExWrapper__anonc154ddd90111::OpenMPDirectiveKindExWrapper62*e038c9c4Sjoerg   OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
OpenMPDirectiveKindExWrapper__anonc154ddd90111::OpenMPDirectiveKindExWrapper63*e038c9c4Sjoerg   OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
operator ==__anonc154ddd90111::OpenMPDirectiveKindExWrapper64*e038c9c4Sjoerg   bool operator==(OpenMPDirectiveKindExWrapper V) const {
65*e038c9c4Sjoerg     return Value == V.Value;
66*e038c9c4Sjoerg   }
operator !=__anonc154ddd90111::OpenMPDirectiveKindExWrapper67*e038c9c4Sjoerg   bool operator!=(OpenMPDirectiveKindExWrapper V) const {
68*e038c9c4Sjoerg     return Value != V.Value;
69*e038c9c4Sjoerg   }
operator ==__anonc154ddd90111::OpenMPDirectiveKindExWrapper70*e038c9c4Sjoerg   bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
operator !=__anonc154ddd90111::OpenMPDirectiveKindExWrapper71*e038c9c4Sjoerg   bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
operator <__anonc154ddd90111::OpenMPDirectiveKindExWrapper72*e038c9c4Sjoerg   bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
operator unsigned__anonc154ddd90111::OpenMPDirectiveKindExWrapper73*e038c9c4Sjoerg   operator unsigned() const { return Value; }
operator OpenMPDirectiveKind__anonc154ddd90111::OpenMPDirectiveKindExWrapper74*e038c9c4Sjoerg   operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
75*e038c9c4Sjoerg   unsigned Value;
767330f729Sjoerg };
777330f729Sjoerg 
787330f729Sjoerg class DeclDirectiveListParserHelper final {
797330f729Sjoerg   SmallVector<Expr *, 4> Identifiers;
807330f729Sjoerg   Parser *P;
817330f729Sjoerg   OpenMPDirectiveKind Kind;
827330f729Sjoerg 
837330f729Sjoerg public:
DeclDirectiveListParserHelper(Parser * P,OpenMPDirectiveKind Kind)847330f729Sjoerg   DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
857330f729Sjoerg       : P(P), Kind(Kind) {}
operator ()(CXXScopeSpec & SS,DeclarationNameInfo NameInfo)867330f729Sjoerg   void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
877330f729Sjoerg     ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
887330f729Sjoerg         P->getCurScope(), SS, NameInfo, Kind);
897330f729Sjoerg     if (Res.isUsable())
907330f729Sjoerg       Identifiers.push_back(Res.get());
917330f729Sjoerg   }
getIdentifiers() const927330f729Sjoerg   llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
937330f729Sjoerg };
947330f729Sjoerg } // namespace
957330f729Sjoerg 
967330f729Sjoerg // Map token string to extended OMP token kind that are
977330f729Sjoerg // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
getOpenMPDirectiveKindEx(StringRef S)987330f729Sjoerg static unsigned getOpenMPDirectiveKindEx(StringRef S) {
99*e038c9c4Sjoerg   OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
1007330f729Sjoerg   if (DKind != OMPD_unknown)
1017330f729Sjoerg     return DKind;
1027330f729Sjoerg 
103*e038c9c4Sjoerg   return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
1047330f729Sjoerg       .Case("cancellation", OMPD_cancellation)
1057330f729Sjoerg       .Case("data", OMPD_data)
1067330f729Sjoerg       .Case("declare", OMPD_declare)
1077330f729Sjoerg       .Case("end", OMPD_end)
1087330f729Sjoerg       .Case("enter", OMPD_enter)
1097330f729Sjoerg       .Case("exit", OMPD_exit)
1107330f729Sjoerg       .Case("point", OMPD_point)
1117330f729Sjoerg       .Case("reduction", OMPD_reduction)
1127330f729Sjoerg       .Case("update", OMPD_update)
1137330f729Sjoerg       .Case("mapper", OMPD_mapper)
1147330f729Sjoerg       .Case("variant", OMPD_variant)
115*e038c9c4Sjoerg       .Case("begin", OMPD_begin)
1167330f729Sjoerg       .Default(OMPD_unknown);
1177330f729Sjoerg }
1187330f729Sjoerg 
parseOpenMPDirectiveKind(Parser & P)119*e038c9c4Sjoerg static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
1207330f729Sjoerg   // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
1217330f729Sjoerg   // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
1227330f729Sjoerg   // TODO: add other combined directives in topological order.
123*e038c9c4Sjoerg   static const OpenMPDirectiveKindExWrapper F[][3] = {
124*e038c9c4Sjoerg       {OMPD_begin, OMPD_declare, OMPD_begin_declare},
125*e038c9c4Sjoerg       {OMPD_begin, OMPD_assumes, OMPD_begin_assumes},
126*e038c9c4Sjoerg       {OMPD_end, OMPD_declare, OMPD_end_declare},
127*e038c9c4Sjoerg       {OMPD_end, OMPD_assumes, OMPD_end_assumes},
1287330f729Sjoerg       {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
1297330f729Sjoerg       {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
1307330f729Sjoerg       {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
1317330f729Sjoerg       {OMPD_declare, OMPD_simd, OMPD_declare_simd},
1327330f729Sjoerg       {OMPD_declare, OMPD_target, OMPD_declare_target},
1337330f729Sjoerg       {OMPD_declare, OMPD_variant, OMPD_declare_variant},
134*e038c9c4Sjoerg       {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
135*e038c9c4Sjoerg       {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
136*e038c9c4Sjoerg       {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
1377330f729Sjoerg       {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
1387330f729Sjoerg       {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
1397330f729Sjoerg       {OMPD_distribute_parallel_for, OMPD_simd,
1407330f729Sjoerg        OMPD_distribute_parallel_for_simd},
1417330f729Sjoerg       {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
1427330f729Sjoerg       {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
1437330f729Sjoerg       {OMPD_target, OMPD_data, OMPD_target_data},
1447330f729Sjoerg       {OMPD_target, OMPD_enter, OMPD_target_enter},
1457330f729Sjoerg       {OMPD_target, OMPD_exit, OMPD_target_exit},
1467330f729Sjoerg       {OMPD_target, OMPD_update, OMPD_target_update},
1477330f729Sjoerg       {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
1487330f729Sjoerg       {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
1497330f729Sjoerg       {OMPD_for, OMPD_simd, OMPD_for_simd},
1507330f729Sjoerg       {OMPD_parallel, OMPD_for, OMPD_parallel_for},
1517330f729Sjoerg       {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
1527330f729Sjoerg       {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
1537330f729Sjoerg       {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
1547330f729Sjoerg       {OMPD_target, OMPD_parallel, OMPD_target_parallel},
1557330f729Sjoerg       {OMPD_target, OMPD_simd, OMPD_target_simd},
1567330f729Sjoerg       {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
1577330f729Sjoerg       {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
1587330f729Sjoerg       {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
1597330f729Sjoerg       {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
1607330f729Sjoerg       {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
1617330f729Sjoerg       {OMPD_teams_distribute_parallel, OMPD_for,
1627330f729Sjoerg        OMPD_teams_distribute_parallel_for},
1637330f729Sjoerg       {OMPD_teams_distribute_parallel_for, OMPD_simd,
1647330f729Sjoerg        OMPD_teams_distribute_parallel_for_simd},
1657330f729Sjoerg       {OMPD_target, OMPD_teams, OMPD_target_teams},
1667330f729Sjoerg       {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
1677330f729Sjoerg       {OMPD_target_teams_distribute, OMPD_parallel,
1687330f729Sjoerg        OMPD_target_teams_distribute_parallel},
1697330f729Sjoerg       {OMPD_target_teams_distribute, OMPD_simd,
1707330f729Sjoerg        OMPD_target_teams_distribute_simd},
1717330f729Sjoerg       {OMPD_target_teams_distribute_parallel, OMPD_for,
1727330f729Sjoerg        OMPD_target_teams_distribute_parallel_for},
1737330f729Sjoerg       {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
1747330f729Sjoerg        OMPD_target_teams_distribute_parallel_for_simd},
1757330f729Sjoerg       {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
1767330f729Sjoerg       {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
1777330f729Sjoerg       {OMPD_parallel, OMPD_master, OMPD_parallel_master},
178*e038c9c4Sjoerg       {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
179*e038c9c4Sjoerg       {OMPD_parallel_master_taskloop, OMPD_simd,
180*e038c9c4Sjoerg        OMPD_parallel_master_taskloop_simd}};
1817330f729Sjoerg   enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
1827330f729Sjoerg   Token Tok = P.getCurToken();
183*e038c9c4Sjoerg   OpenMPDirectiveKindExWrapper DKind =
1847330f729Sjoerg       Tok.isAnnotation()
1857330f729Sjoerg           ? static_cast<unsigned>(OMPD_unknown)
1867330f729Sjoerg           : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
1877330f729Sjoerg   if (DKind == OMPD_unknown)
1887330f729Sjoerg     return OMPD_unknown;
1897330f729Sjoerg 
1907330f729Sjoerg   for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
1917330f729Sjoerg     if (DKind != F[I][0])
1927330f729Sjoerg       continue;
1937330f729Sjoerg 
1947330f729Sjoerg     Tok = P.getPreprocessor().LookAhead(0);
195*e038c9c4Sjoerg     OpenMPDirectiveKindExWrapper SDKind =
1967330f729Sjoerg         Tok.isAnnotation()
1977330f729Sjoerg             ? static_cast<unsigned>(OMPD_unknown)
1987330f729Sjoerg             : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
1997330f729Sjoerg     if (SDKind == OMPD_unknown)
2007330f729Sjoerg       continue;
2017330f729Sjoerg 
2027330f729Sjoerg     if (SDKind == F[I][1]) {
2037330f729Sjoerg       P.ConsumeToken();
2047330f729Sjoerg       DKind = F[I][2];
2057330f729Sjoerg     }
2067330f729Sjoerg   }
207*e038c9c4Sjoerg   return unsigned(DKind) < llvm::omp::Directive_enumSize
208*e038c9c4Sjoerg              ? static_cast<OpenMPDirectiveKind>(DKind)
2097330f729Sjoerg              : OMPD_unknown;
2107330f729Sjoerg }
2117330f729Sjoerg 
parseOpenMPReductionId(Parser & P)2127330f729Sjoerg static DeclarationName parseOpenMPReductionId(Parser &P) {
2137330f729Sjoerg   Token Tok = P.getCurToken();
2147330f729Sjoerg   Sema &Actions = P.getActions();
2157330f729Sjoerg   OverloadedOperatorKind OOK = OO_None;
2167330f729Sjoerg   // Allow to use 'operator' keyword for C++ operators
2177330f729Sjoerg   bool WithOperator = false;
2187330f729Sjoerg   if (Tok.is(tok::kw_operator)) {
2197330f729Sjoerg     P.ConsumeToken();
2207330f729Sjoerg     Tok = P.getCurToken();
2217330f729Sjoerg     WithOperator = true;
2227330f729Sjoerg   }
2237330f729Sjoerg   switch (Tok.getKind()) {
2247330f729Sjoerg   case tok::plus: // '+'
2257330f729Sjoerg     OOK = OO_Plus;
2267330f729Sjoerg     break;
2277330f729Sjoerg   case tok::minus: // '-'
2287330f729Sjoerg     OOK = OO_Minus;
2297330f729Sjoerg     break;
2307330f729Sjoerg   case tok::star: // '*'
2317330f729Sjoerg     OOK = OO_Star;
2327330f729Sjoerg     break;
2337330f729Sjoerg   case tok::amp: // '&'
2347330f729Sjoerg     OOK = OO_Amp;
2357330f729Sjoerg     break;
2367330f729Sjoerg   case tok::pipe: // '|'
2377330f729Sjoerg     OOK = OO_Pipe;
2387330f729Sjoerg     break;
2397330f729Sjoerg   case tok::caret: // '^'
2407330f729Sjoerg     OOK = OO_Caret;
2417330f729Sjoerg     break;
2427330f729Sjoerg   case tok::ampamp: // '&&'
2437330f729Sjoerg     OOK = OO_AmpAmp;
2447330f729Sjoerg     break;
2457330f729Sjoerg   case tok::pipepipe: // '||'
2467330f729Sjoerg     OOK = OO_PipePipe;
2477330f729Sjoerg     break;
2487330f729Sjoerg   case tok::identifier: // identifier
2497330f729Sjoerg     if (!WithOperator)
2507330f729Sjoerg       break;
2517330f729Sjoerg     LLVM_FALLTHROUGH;
2527330f729Sjoerg   default:
2537330f729Sjoerg     P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
2547330f729Sjoerg     P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2557330f729Sjoerg                 Parser::StopBeforeMatch);
2567330f729Sjoerg     return DeclarationName();
2577330f729Sjoerg   }
2587330f729Sjoerg   P.ConsumeToken();
2597330f729Sjoerg   auto &DeclNames = Actions.getASTContext().DeclarationNames;
2607330f729Sjoerg   return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
2617330f729Sjoerg                         : DeclNames.getCXXOperatorName(OOK);
2627330f729Sjoerg }
2637330f729Sjoerg 
2647330f729Sjoerg /// Parse 'omp declare reduction' construct.
2657330f729Sjoerg ///
2667330f729Sjoerg ///       declare-reduction-directive:
2677330f729Sjoerg ///        annot_pragma_openmp 'declare' 'reduction'
2687330f729Sjoerg ///        '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
2697330f729Sjoerg ///        ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
2707330f729Sjoerg ///        annot_pragma_openmp_end
2717330f729Sjoerg /// <reduction_id> is either a base language identifier or one of the following
2727330f729Sjoerg /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
2737330f729Sjoerg ///
2747330f729Sjoerg Parser::DeclGroupPtrTy
ParseOpenMPDeclareReductionDirective(AccessSpecifier AS)2757330f729Sjoerg Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
2767330f729Sjoerg   // Parse '('.
2777330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
278*e038c9c4Sjoerg   if (T.expectAndConsume(
279*e038c9c4Sjoerg           diag::err_expected_lparen_after,
280*e038c9c4Sjoerg           getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
2817330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
2827330f729Sjoerg     return DeclGroupPtrTy();
2837330f729Sjoerg   }
2847330f729Sjoerg 
2857330f729Sjoerg   DeclarationName Name = parseOpenMPReductionId(*this);
2867330f729Sjoerg   if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
2877330f729Sjoerg     return DeclGroupPtrTy();
2887330f729Sjoerg 
2897330f729Sjoerg   // Consume ':'.
2907330f729Sjoerg   bool IsCorrect = !ExpectAndConsume(tok::colon);
2917330f729Sjoerg 
2927330f729Sjoerg   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
2937330f729Sjoerg     return DeclGroupPtrTy();
2947330f729Sjoerg 
2957330f729Sjoerg   IsCorrect = IsCorrect && !Name.isEmpty();
2967330f729Sjoerg 
2977330f729Sjoerg   if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
2987330f729Sjoerg     Diag(Tok.getLocation(), diag::err_expected_type);
2997330f729Sjoerg     IsCorrect = false;
3007330f729Sjoerg   }
3017330f729Sjoerg 
3027330f729Sjoerg   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
3037330f729Sjoerg     return DeclGroupPtrTy();
3047330f729Sjoerg 
3057330f729Sjoerg   SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
3067330f729Sjoerg   // Parse list of types until ':' token.
3077330f729Sjoerg   do {
3087330f729Sjoerg     ColonProtectionRAIIObject ColonRAII(*this);
3097330f729Sjoerg     SourceRange Range;
310*e038c9c4Sjoerg     TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS);
3117330f729Sjoerg     if (TR.isUsable()) {
3127330f729Sjoerg       QualType ReductionType =
3137330f729Sjoerg           Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
3147330f729Sjoerg       if (!ReductionType.isNull()) {
3157330f729Sjoerg         ReductionTypes.push_back(
3167330f729Sjoerg             std::make_pair(ReductionType, Range.getBegin()));
3177330f729Sjoerg       }
3187330f729Sjoerg     } else {
3197330f729Sjoerg       SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
3207330f729Sjoerg                 StopBeforeMatch);
3217330f729Sjoerg     }
3227330f729Sjoerg 
3237330f729Sjoerg     if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
3247330f729Sjoerg       break;
3257330f729Sjoerg 
3267330f729Sjoerg     // Consume ','.
3277330f729Sjoerg     if (ExpectAndConsume(tok::comma)) {
3287330f729Sjoerg       IsCorrect = false;
3297330f729Sjoerg       if (Tok.is(tok::annot_pragma_openmp_end)) {
3307330f729Sjoerg         Diag(Tok.getLocation(), diag::err_expected_type);
3317330f729Sjoerg         return DeclGroupPtrTy();
3327330f729Sjoerg       }
3337330f729Sjoerg     }
3347330f729Sjoerg   } while (Tok.isNot(tok::annot_pragma_openmp_end));
3357330f729Sjoerg 
3367330f729Sjoerg   if (ReductionTypes.empty()) {
3377330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
3387330f729Sjoerg     return DeclGroupPtrTy();
3397330f729Sjoerg   }
3407330f729Sjoerg 
3417330f729Sjoerg   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
3427330f729Sjoerg     return DeclGroupPtrTy();
3437330f729Sjoerg 
3447330f729Sjoerg   // Consume ':'.
3457330f729Sjoerg   if (ExpectAndConsume(tok::colon))
3467330f729Sjoerg     IsCorrect = false;
3477330f729Sjoerg 
3487330f729Sjoerg   if (Tok.is(tok::annot_pragma_openmp_end)) {
3497330f729Sjoerg     Diag(Tok.getLocation(), diag::err_expected_expression);
3507330f729Sjoerg     return DeclGroupPtrTy();
3517330f729Sjoerg   }
3527330f729Sjoerg 
3537330f729Sjoerg   DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
3547330f729Sjoerg       getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
3557330f729Sjoerg 
3567330f729Sjoerg   // Parse <combiner> expression and then parse initializer if any for each
3577330f729Sjoerg   // correct type.
3587330f729Sjoerg   unsigned I = 0, E = ReductionTypes.size();
3597330f729Sjoerg   for (Decl *D : DRD.get()) {
3607330f729Sjoerg     TentativeParsingAction TPA(*this);
3617330f729Sjoerg     ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
3627330f729Sjoerg                                     Scope::CompoundStmtScope |
3637330f729Sjoerg                                     Scope::OpenMPDirectiveScope);
3647330f729Sjoerg     // Parse <combiner> expression.
3657330f729Sjoerg     Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
366*e038c9c4Sjoerg     ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
367*e038c9c4Sjoerg         ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
3687330f729Sjoerg     Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
3697330f729Sjoerg 
3707330f729Sjoerg     if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
3717330f729Sjoerg         Tok.isNot(tok::annot_pragma_openmp_end)) {
3727330f729Sjoerg       TPA.Commit();
3737330f729Sjoerg       IsCorrect = false;
3747330f729Sjoerg       break;
3757330f729Sjoerg     }
3767330f729Sjoerg     IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
3777330f729Sjoerg     ExprResult InitializerResult;
3787330f729Sjoerg     if (Tok.isNot(tok::annot_pragma_openmp_end)) {
3797330f729Sjoerg       // Parse <initializer> expression.
3807330f729Sjoerg       if (Tok.is(tok::identifier) &&
3817330f729Sjoerg           Tok.getIdentifierInfo()->isStr("initializer")) {
3827330f729Sjoerg         ConsumeToken();
3837330f729Sjoerg       } else {
3847330f729Sjoerg         Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
3857330f729Sjoerg         TPA.Commit();
3867330f729Sjoerg         IsCorrect = false;
3877330f729Sjoerg         break;
3887330f729Sjoerg       }
3897330f729Sjoerg       // Parse '('.
3907330f729Sjoerg       BalancedDelimiterTracker T(*this, tok::l_paren,
3917330f729Sjoerg                                  tok::annot_pragma_openmp_end);
3927330f729Sjoerg       IsCorrect =
3937330f729Sjoerg           !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
3947330f729Sjoerg           IsCorrect;
3957330f729Sjoerg       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
3967330f729Sjoerg         ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
3977330f729Sjoerg                                         Scope::CompoundStmtScope |
3987330f729Sjoerg                                         Scope::OpenMPDirectiveScope);
3997330f729Sjoerg         // Parse expression.
4007330f729Sjoerg         VarDecl *OmpPrivParm =
4017330f729Sjoerg             Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
4027330f729Sjoerg                                                                 D);
4037330f729Sjoerg         // Check if initializer is omp_priv <init_expr> or something else.
4047330f729Sjoerg         if (Tok.is(tok::identifier) &&
4057330f729Sjoerg             Tok.getIdentifierInfo()->isStr("omp_priv")) {
4067330f729Sjoerg           ConsumeToken();
4077330f729Sjoerg           ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
4087330f729Sjoerg         } else {
4097330f729Sjoerg           InitializerResult = Actions.ActOnFinishFullExpr(
4107330f729Sjoerg               ParseAssignmentExpression().get(), D->getLocation(),
4117330f729Sjoerg               /*DiscardedValue*/ false);
4127330f729Sjoerg         }
4137330f729Sjoerg         Actions.ActOnOpenMPDeclareReductionInitializerEnd(
4147330f729Sjoerg             D, InitializerResult.get(), OmpPrivParm);
4157330f729Sjoerg         if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
4167330f729Sjoerg             Tok.isNot(tok::annot_pragma_openmp_end)) {
4177330f729Sjoerg           TPA.Commit();
4187330f729Sjoerg           IsCorrect = false;
4197330f729Sjoerg           break;
4207330f729Sjoerg         }
4217330f729Sjoerg         IsCorrect =
4227330f729Sjoerg             !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
4237330f729Sjoerg       }
4247330f729Sjoerg     }
4257330f729Sjoerg 
4267330f729Sjoerg     ++I;
4277330f729Sjoerg     // Revert parsing if not the last type, otherwise accept it, we're done with
4287330f729Sjoerg     // parsing.
4297330f729Sjoerg     if (I != E)
4307330f729Sjoerg       TPA.Revert();
4317330f729Sjoerg     else
4327330f729Sjoerg       TPA.Commit();
4337330f729Sjoerg   }
4347330f729Sjoerg   return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
4357330f729Sjoerg                                                          IsCorrect);
4367330f729Sjoerg }
4377330f729Sjoerg 
ParseOpenMPReductionInitializerForDecl(VarDecl * OmpPrivParm)4387330f729Sjoerg void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
4397330f729Sjoerg   // Parse declarator '=' initializer.
4407330f729Sjoerg   // If a '==' or '+=' is found, suggest a fixit to '='.
4417330f729Sjoerg   if (isTokenEqualOrEqualTypo()) {
4427330f729Sjoerg     ConsumeToken();
4437330f729Sjoerg 
4447330f729Sjoerg     if (Tok.is(tok::code_completion)) {
445*e038c9c4Sjoerg       cutOffParsing();
4467330f729Sjoerg       Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
4477330f729Sjoerg       Actions.FinalizeDeclaration(OmpPrivParm);
4487330f729Sjoerg       return;
4497330f729Sjoerg     }
4507330f729Sjoerg 
451*e038c9c4Sjoerg     PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
452*e038c9c4Sjoerg     ExprResult Init = ParseInitializer();
4537330f729Sjoerg 
4547330f729Sjoerg     if (Init.isInvalid()) {
4557330f729Sjoerg       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
4567330f729Sjoerg       Actions.ActOnInitializerError(OmpPrivParm);
4577330f729Sjoerg     } else {
4587330f729Sjoerg       Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
4597330f729Sjoerg                                    /*DirectInit=*/false);
4607330f729Sjoerg     }
4617330f729Sjoerg   } else if (Tok.is(tok::l_paren)) {
4627330f729Sjoerg     // Parse C++ direct initializer: '(' expression-list ')'
4637330f729Sjoerg     BalancedDelimiterTracker T(*this, tok::l_paren);
4647330f729Sjoerg     T.consumeOpen();
4657330f729Sjoerg 
4667330f729Sjoerg     ExprVector Exprs;
4677330f729Sjoerg     CommaLocsTy CommaLocs;
4687330f729Sjoerg 
4697330f729Sjoerg     SourceLocation LParLoc = T.getOpenLocation();
4707330f729Sjoerg     auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
4717330f729Sjoerg       QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
4727330f729Sjoerg           getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
4737330f729Sjoerg           OmpPrivParm->getLocation(), Exprs, LParLoc);
4747330f729Sjoerg       CalledSignatureHelp = true;
4757330f729Sjoerg       return PreferredType;
4767330f729Sjoerg     };
4777330f729Sjoerg     if (ParseExpressionList(Exprs, CommaLocs, [&] {
4787330f729Sjoerg           PreferredType.enterFunctionArgument(Tok.getLocation(),
4797330f729Sjoerg                                               RunSignatureHelp);
4807330f729Sjoerg         })) {
4817330f729Sjoerg       if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
4827330f729Sjoerg         RunSignatureHelp();
4837330f729Sjoerg       Actions.ActOnInitializerError(OmpPrivParm);
4847330f729Sjoerg       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
4857330f729Sjoerg     } else {
4867330f729Sjoerg       // Match the ')'.
4877330f729Sjoerg       SourceLocation RLoc = Tok.getLocation();
4887330f729Sjoerg       if (!T.consumeClose())
4897330f729Sjoerg         RLoc = T.getCloseLocation();
4907330f729Sjoerg 
4917330f729Sjoerg       assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
4927330f729Sjoerg              "Unexpected number of commas!");
4937330f729Sjoerg 
4947330f729Sjoerg       ExprResult Initializer =
4957330f729Sjoerg           Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
4967330f729Sjoerg       Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
4977330f729Sjoerg                                    /*DirectInit=*/true);
4987330f729Sjoerg     }
4997330f729Sjoerg   } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
5007330f729Sjoerg     // Parse C++0x braced-init-list.
5017330f729Sjoerg     Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
5027330f729Sjoerg 
5037330f729Sjoerg     ExprResult Init(ParseBraceInitializer());
5047330f729Sjoerg 
5057330f729Sjoerg     if (Init.isInvalid()) {
5067330f729Sjoerg       Actions.ActOnInitializerError(OmpPrivParm);
5077330f729Sjoerg     } else {
5087330f729Sjoerg       Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
5097330f729Sjoerg                                    /*DirectInit=*/true);
5107330f729Sjoerg     }
5117330f729Sjoerg   } else {
5127330f729Sjoerg     Actions.ActOnUninitializedDecl(OmpPrivParm);
5137330f729Sjoerg   }
5147330f729Sjoerg }
5157330f729Sjoerg 
5167330f729Sjoerg /// Parses 'omp declare mapper' directive.
5177330f729Sjoerg ///
5187330f729Sjoerg ///       declare-mapper-directive:
5197330f729Sjoerg ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
5207330f729Sjoerg ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
5217330f729Sjoerg ///         annot_pragma_openmp_end
5227330f729Sjoerg /// <mapper-identifier> and <var> are base language identifiers.
5237330f729Sjoerg ///
5247330f729Sjoerg Parser::DeclGroupPtrTy
ParseOpenMPDeclareMapperDirective(AccessSpecifier AS)5257330f729Sjoerg Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
5267330f729Sjoerg   bool IsCorrect = true;
5277330f729Sjoerg   // Parse '('
5287330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5297330f729Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after,
530*e038c9c4Sjoerg                          getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
5317330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
5327330f729Sjoerg     return DeclGroupPtrTy();
5337330f729Sjoerg   }
5347330f729Sjoerg 
5357330f729Sjoerg   // Parse <mapper-identifier>
5367330f729Sjoerg   auto &DeclNames = Actions.getASTContext().DeclarationNames;
5377330f729Sjoerg   DeclarationName MapperId;
5387330f729Sjoerg   if (PP.LookAhead(0).is(tok::colon)) {
5397330f729Sjoerg     if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
5407330f729Sjoerg       Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
5417330f729Sjoerg       IsCorrect = false;
5427330f729Sjoerg     } else {
5437330f729Sjoerg       MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
5447330f729Sjoerg     }
5457330f729Sjoerg     ConsumeToken();
5467330f729Sjoerg     // Consume ':'.
5477330f729Sjoerg     ExpectAndConsume(tok::colon);
5487330f729Sjoerg   } else {
5497330f729Sjoerg     // If no mapper identifier is provided, its name is "default" by default
5507330f729Sjoerg     MapperId =
5517330f729Sjoerg         DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
5527330f729Sjoerg   }
5537330f729Sjoerg 
5547330f729Sjoerg   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
5557330f729Sjoerg     return DeclGroupPtrTy();
5567330f729Sjoerg 
5577330f729Sjoerg   // Parse <type> <var>
5587330f729Sjoerg   DeclarationName VName;
5597330f729Sjoerg   QualType MapperType;
5607330f729Sjoerg   SourceRange Range;
5617330f729Sjoerg   TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
5627330f729Sjoerg   if (ParsedType.isUsable())
5637330f729Sjoerg     MapperType =
5647330f729Sjoerg         Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
5657330f729Sjoerg   if (MapperType.isNull())
5667330f729Sjoerg     IsCorrect = false;
5677330f729Sjoerg   if (!IsCorrect) {
5687330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
5697330f729Sjoerg     return DeclGroupPtrTy();
5707330f729Sjoerg   }
5717330f729Sjoerg 
5727330f729Sjoerg   // Consume ')'.
5737330f729Sjoerg   IsCorrect &= !T.consumeClose();
5747330f729Sjoerg   if (!IsCorrect) {
5757330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
5767330f729Sjoerg     return DeclGroupPtrTy();
5777330f729Sjoerg   }
5787330f729Sjoerg 
5797330f729Sjoerg   // Enter scope.
5807330f729Sjoerg   DeclarationNameInfo DirName;
5817330f729Sjoerg   SourceLocation Loc = Tok.getLocation();
5827330f729Sjoerg   unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
5837330f729Sjoerg                         Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
5847330f729Sjoerg   ParseScope OMPDirectiveScope(this, ScopeFlags);
5857330f729Sjoerg   Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
5867330f729Sjoerg 
5877330f729Sjoerg   // Add the mapper variable declaration.
588*e038c9c4Sjoerg   ExprResult MapperVarRef = Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
589*e038c9c4Sjoerg       getCurScope(), MapperType, Range.getBegin(), VName);
5907330f729Sjoerg 
5917330f729Sjoerg   // Parse map clauses.
5927330f729Sjoerg   SmallVector<OMPClause *, 6> Clauses;
5937330f729Sjoerg   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
5947330f729Sjoerg     OpenMPClauseKind CKind = Tok.isAnnotation()
5957330f729Sjoerg                                  ? OMPC_unknown
5967330f729Sjoerg                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
5977330f729Sjoerg     Actions.StartOpenMPClause(CKind);
5987330f729Sjoerg     OMPClause *Clause =
599*e038c9c4Sjoerg         ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
6007330f729Sjoerg     if (Clause)
6017330f729Sjoerg       Clauses.push_back(Clause);
6027330f729Sjoerg     else
6037330f729Sjoerg       IsCorrect = false;
6047330f729Sjoerg     // Skip ',' if any.
6057330f729Sjoerg     if (Tok.is(tok::comma))
6067330f729Sjoerg       ConsumeToken();
6077330f729Sjoerg     Actions.EndOpenMPClause();
6087330f729Sjoerg   }
6097330f729Sjoerg   if (Clauses.empty()) {
6107330f729Sjoerg     Diag(Tok, diag::err_omp_expected_clause)
6117330f729Sjoerg         << getOpenMPDirectiveName(OMPD_declare_mapper);
6127330f729Sjoerg     IsCorrect = false;
6137330f729Sjoerg   }
6147330f729Sjoerg 
6157330f729Sjoerg   // Exit scope.
6167330f729Sjoerg   Actions.EndOpenMPDSABlock(nullptr);
6177330f729Sjoerg   OMPDirectiveScope.Exit();
618*e038c9c4Sjoerg   DeclGroupPtrTy DG = Actions.ActOnOpenMPDeclareMapperDirective(
619*e038c9c4Sjoerg       getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
620*e038c9c4Sjoerg       Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);
6217330f729Sjoerg   if (!IsCorrect)
6227330f729Sjoerg     return DeclGroupPtrTy();
623*e038c9c4Sjoerg 
624*e038c9c4Sjoerg   return DG;
6257330f729Sjoerg }
6267330f729Sjoerg 
parseOpenMPDeclareMapperVarDecl(SourceRange & Range,DeclarationName & Name,AccessSpecifier AS)6277330f729Sjoerg TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
6287330f729Sjoerg                                                    DeclarationName &Name,
6297330f729Sjoerg                                                    AccessSpecifier AS) {
6307330f729Sjoerg   // Parse the common declaration-specifiers piece.
6317330f729Sjoerg   Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
6327330f729Sjoerg   DeclSpec DS(AttrFactory);
6337330f729Sjoerg   ParseSpecifierQualifierList(DS, AS, DSC);
6347330f729Sjoerg 
6357330f729Sjoerg   // Parse the declarator.
636*e038c9c4Sjoerg   DeclaratorContext Context = DeclaratorContext::Prototype;
6377330f729Sjoerg   Declarator DeclaratorInfo(DS, Context);
6387330f729Sjoerg   ParseDeclarator(DeclaratorInfo);
6397330f729Sjoerg   Range = DeclaratorInfo.getSourceRange();
6407330f729Sjoerg   if (DeclaratorInfo.getIdentifier() == nullptr) {
6417330f729Sjoerg     Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
6427330f729Sjoerg     return true;
6437330f729Sjoerg   }
6447330f729Sjoerg   Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
6457330f729Sjoerg 
6467330f729Sjoerg   return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
6477330f729Sjoerg }
6487330f729Sjoerg 
6497330f729Sjoerg namespace {
6507330f729Sjoerg /// RAII that recreates function context for correct parsing of clauses of
6517330f729Sjoerg /// 'declare simd' construct.
6527330f729Sjoerg /// OpenMP, 2.8.2 declare simd Construct
6537330f729Sjoerg /// The expressions appearing in the clauses of this directive are evaluated in
6547330f729Sjoerg /// the scope of the arguments of the function declaration or definition.
6557330f729Sjoerg class FNContextRAII final {
6567330f729Sjoerg   Parser &P;
6577330f729Sjoerg   Sema::CXXThisScopeRAII *ThisScope;
658*e038c9c4Sjoerg   Parser::MultiParseScope Scopes;
6597330f729Sjoerg   bool HasFunScope = false;
6607330f729Sjoerg   FNContextRAII() = delete;
6617330f729Sjoerg   FNContextRAII(const FNContextRAII &) = delete;
6627330f729Sjoerg   FNContextRAII &operator=(const FNContextRAII &) = delete;
6637330f729Sjoerg 
6647330f729Sjoerg public:
FNContextRAII(Parser & P,Parser::DeclGroupPtrTy Ptr)665*e038c9c4Sjoerg   FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) {
6667330f729Sjoerg     Decl *D = *Ptr.get().begin();
6677330f729Sjoerg     NamedDecl *ND = dyn_cast<NamedDecl>(D);
6687330f729Sjoerg     RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
6697330f729Sjoerg     Sema &Actions = P.getActions();
6707330f729Sjoerg 
6717330f729Sjoerg     // Allow 'this' within late-parsed attributes.
6727330f729Sjoerg     ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
6737330f729Sjoerg                                            ND && ND->isCXXInstanceMember());
6747330f729Sjoerg 
6757330f729Sjoerg     // If the Decl is templatized, add template parameters to scope.
676*e038c9c4Sjoerg     // FIXME: Track CurTemplateDepth?
677*e038c9c4Sjoerg     P.ReenterTemplateScopes(Scopes, D);
6787330f729Sjoerg 
6797330f729Sjoerg     // If the Decl is on a function, add function parameters to the scope.
680*e038c9c4Sjoerg     if (D->isFunctionOrFunctionTemplate()) {
681*e038c9c4Sjoerg       HasFunScope = true;
682*e038c9c4Sjoerg       Scopes.Enter(Scope::FnScope | Scope::DeclScope |
683*e038c9c4Sjoerg                    Scope::CompoundStmtScope);
6847330f729Sjoerg       Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
6857330f729Sjoerg     }
6867330f729Sjoerg   }
~FNContextRAII()687*e038c9c4Sjoerg   ~FNContextRAII() {
688*e038c9c4Sjoerg     if (HasFunScope)
689*e038c9c4Sjoerg       P.getActions().ActOnExitFunctionContext();
6907330f729Sjoerg     delete ThisScope;
6917330f729Sjoerg   }
6927330f729Sjoerg };
6937330f729Sjoerg } // namespace
6947330f729Sjoerg 
6957330f729Sjoerg /// Parses clauses for 'declare simd' directive.
6967330f729Sjoerg ///    clause:
6977330f729Sjoerg ///      'inbranch' | 'notinbranch'
6987330f729Sjoerg ///      'simdlen' '(' <expr> ')'
6997330f729Sjoerg ///      { 'uniform' '(' <argument_list> ')' }
7007330f729Sjoerg ///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
7017330f729Sjoerg ///      { 'linear '(' <argument_list> [ ':' <step> ] ')' }
parseDeclareSimdClauses(Parser & P,OMPDeclareSimdDeclAttr::BranchStateTy & BS,ExprResult & SimdLen,SmallVectorImpl<Expr * > & Uniforms,SmallVectorImpl<Expr * > & Aligneds,SmallVectorImpl<Expr * > & Alignments,SmallVectorImpl<Expr * > & Linears,SmallVectorImpl<unsigned> & LinModifiers,SmallVectorImpl<Expr * > & Steps)7027330f729Sjoerg static bool parseDeclareSimdClauses(
7037330f729Sjoerg     Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
7047330f729Sjoerg     SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
7057330f729Sjoerg     SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
7067330f729Sjoerg     SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
7077330f729Sjoerg   SourceRange BSRange;
7087330f729Sjoerg   const Token &Tok = P.getCurToken();
7097330f729Sjoerg   bool IsError = false;
7107330f729Sjoerg   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
7117330f729Sjoerg     if (Tok.isNot(tok::identifier))
7127330f729Sjoerg       break;
7137330f729Sjoerg     OMPDeclareSimdDeclAttr::BranchStateTy Out;
7147330f729Sjoerg     IdentifierInfo *II = Tok.getIdentifierInfo();
7157330f729Sjoerg     StringRef ClauseName = II->getName();
7167330f729Sjoerg     // Parse 'inranch|notinbranch' clauses.
7177330f729Sjoerg     if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
7187330f729Sjoerg       if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
7197330f729Sjoerg         P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
7207330f729Sjoerg             << ClauseName
7217330f729Sjoerg             << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
7227330f729Sjoerg         IsError = true;
7237330f729Sjoerg       }
7247330f729Sjoerg       BS = Out;
7257330f729Sjoerg       BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
7267330f729Sjoerg       P.ConsumeToken();
7277330f729Sjoerg     } else if (ClauseName.equals("simdlen")) {
7287330f729Sjoerg       if (SimdLen.isUsable()) {
7297330f729Sjoerg         P.Diag(Tok, diag::err_omp_more_one_clause)
7307330f729Sjoerg             << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
7317330f729Sjoerg         IsError = true;
7327330f729Sjoerg       }
7337330f729Sjoerg       P.ConsumeToken();
7347330f729Sjoerg       SourceLocation RLoc;
7357330f729Sjoerg       SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
7367330f729Sjoerg       if (SimdLen.isInvalid())
7377330f729Sjoerg         IsError = true;
7387330f729Sjoerg     } else {
7397330f729Sjoerg       OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
7407330f729Sjoerg       if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
7417330f729Sjoerg           CKind == OMPC_linear) {
7427330f729Sjoerg         Parser::OpenMPVarListDataTy Data;
7437330f729Sjoerg         SmallVectorImpl<Expr *> *Vars = &Uniforms;
744*e038c9c4Sjoerg         if (CKind == OMPC_aligned) {
7457330f729Sjoerg           Vars = &Aligneds;
746*e038c9c4Sjoerg         } else if (CKind == OMPC_linear) {
747*e038c9c4Sjoerg           Data.ExtraModifier = OMPC_LINEAR_val;
7487330f729Sjoerg           Vars = &Linears;
749*e038c9c4Sjoerg         }
7507330f729Sjoerg 
7517330f729Sjoerg         P.ConsumeToken();
7527330f729Sjoerg         if (P.ParseOpenMPVarList(OMPD_declare_simd,
7537330f729Sjoerg                                  getOpenMPClauseKind(ClauseName), *Vars, Data))
7547330f729Sjoerg           IsError = true;
7557330f729Sjoerg         if (CKind == OMPC_aligned) {
756*e038c9c4Sjoerg           Alignments.append(Aligneds.size() - Alignments.size(),
757*e038c9c4Sjoerg                             Data.DepModOrTailExpr);
7587330f729Sjoerg         } else if (CKind == OMPC_linear) {
759*e038c9c4Sjoerg           assert(0 <= Data.ExtraModifier &&
760*e038c9c4Sjoerg                  Data.ExtraModifier <= OMPC_LINEAR_unknown &&
761*e038c9c4Sjoerg                  "Unexpected linear modifier.");
762*e038c9c4Sjoerg           if (P.getActions().CheckOpenMPLinearModifier(
763*e038c9c4Sjoerg                   static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
764*e038c9c4Sjoerg                   Data.ExtraModifierLoc))
765*e038c9c4Sjoerg             Data.ExtraModifier = OMPC_LINEAR_val;
7667330f729Sjoerg           LinModifiers.append(Linears.size() - LinModifiers.size(),
767*e038c9c4Sjoerg                               Data.ExtraModifier);
768*e038c9c4Sjoerg           Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
7697330f729Sjoerg         }
7707330f729Sjoerg       } else
7717330f729Sjoerg         // TODO: add parsing of other clauses.
7727330f729Sjoerg         break;
7737330f729Sjoerg     }
7747330f729Sjoerg     // Skip ',' if any.
7757330f729Sjoerg     if (Tok.is(tok::comma))
7767330f729Sjoerg       P.ConsumeToken();
7777330f729Sjoerg   }
7787330f729Sjoerg   return IsError;
7797330f729Sjoerg }
7807330f729Sjoerg 
7817330f729Sjoerg /// Parse clauses for '#pragma omp declare simd'.
7827330f729Sjoerg Parser::DeclGroupPtrTy
ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,CachedTokens & Toks,SourceLocation Loc)7837330f729Sjoerg Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
7847330f729Sjoerg                                    CachedTokens &Toks, SourceLocation Loc) {
7857330f729Sjoerg   PP.EnterToken(Tok, /*IsReinject*/ true);
7867330f729Sjoerg   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
7877330f729Sjoerg                       /*IsReinject*/ true);
7887330f729Sjoerg   // Consume the previously pushed token.
7897330f729Sjoerg   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
7907330f729Sjoerg   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
7917330f729Sjoerg 
7927330f729Sjoerg   FNContextRAII FnContext(*this, Ptr);
7937330f729Sjoerg   OMPDeclareSimdDeclAttr::BranchStateTy BS =
7947330f729Sjoerg       OMPDeclareSimdDeclAttr::BS_Undefined;
7957330f729Sjoerg   ExprResult Simdlen;
7967330f729Sjoerg   SmallVector<Expr *, 4> Uniforms;
7977330f729Sjoerg   SmallVector<Expr *, 4> Aligneds;
7987330f729Sjoerg   SmallVector<Expr *, 4> Alignments;
7997330f729Sjoerg   SmallVector<Expr *, 4> Linears;
8007330f729Sjoerg   SmallVector<unsigned, 4> LinModifiers;
8017330f729Sjoerg   SmallVector<Expr *, 4> Steps;
8027330f729Sjoerg   bool IsError =
8037330f729Sjoerg       parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
8047330f729Sjoerg                               Alignments, Linears, LinModifiers, Steps);
805*e038c9c4Sjoerg   skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
8067330f729Sjoerg   // Skip the last annot_pragma_openmp_end.
8077330f729Sjoerg   SourceLocation EndLoc = ConsumeAnnotationToken();
8087330f729Sjoerg   if (IsError)
8097330f729Sjoerg     return Ptr;
8107330f729Sjoerg   return Actions.ActOnOpenMPDeclareSimdDirective(
8117330f729Sjoerg       Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
8127330f729Sjoerg       LinModifiers, Steps, SourceRange(Loc, EndLoc));
8137330f729Sjoerg }
8147330f729Sjoerg 
815*e038c9c4Sjoerg namespace {
816*e038c9c4Sjoerg /// Constant used in the diagnostics to distinguish the levels in an OpenMP
817*e038c9c4Sjoerg /// contexts: selector-set={selector(trait, ...), ...}, ....
818*e038c9c4Sjoerg enum OMPContextLvl {
819*e038c9c4Sjoerg   CONTEXT_SELECTOR_SET_LVL = 0,
820*e038c9c4Sjoerg   CONTEXT_SELECTOR_LVL = 1,
821*e038c9c4Sjoerg   CONTEXT_TRAIT_LVL = 2,
822*e038c9c4Sjoerg };
823*e038c9c4Sjoerg 
stringLiteralParser(Parser & P)824*e038c9c4Sjoerg static StringRef stringLiteralParser(Parser &P) {
825*e038c9c4Sjoerg   ExprResult Res = P.ParseStringLiteralExpression(true);
826*e038c9c4Sjoerg   return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
827*e038c9c4Sjoerg }
828*e038c9c4Sjoerg 
getNameFromIdOrString(Parser & P,Token & Tok,OMPContextLvl Lvl)829*e038c9c4Sjoerg static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
830*e038c9c4Sjoerg                                        OMPContextLvl Lvl) {
831*e038c9c4Sjoerg   if (Tok.is(tok::identifier)) {
832*e038c9c4Sjoerg     llvm::SmallString<16> Buffer;
833*e038c9c4Sjoerg     StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
834*e038c9c4Sjoerg     (void)P.ConsumeToken();
835*e038c9c4Sjoerg     return Name;
836*e038c9c4Sjoerg   }
837*e038c9c4Sjoerg 
838*e038c9c4Sjoerg   if (tok::isStringLiteral(Tok.getKind()))
839*e038c9c4Sjoerg     return stringLiteralParser(P);
840*e038c9c4Sjoerg 
841*e038c9c4Sjoerg   P.Diag(Tok.getLocation(),
842*e038c9c4Sjoerg          diag::warn_omp_declare_variant_string_literal_or_identifier)
843*e038c9c4Sjoerg       << Lvl;
844*e038c9c4Sjoerg   return "";
845*e038c9c4Sjoerg }
846*e038c9c4Sjoerg 
checkForDuplicates(Parser & P,StringRef Name,SourceLocation NameLoc,llvm::StringMap<SourceLocation> & Seen,OMPContextLvl Lvl)847*e038c9c4Sjoerg static bool checkForDuplicates(Parser &P, StringRef Name,
848*e038c9c4Sjoerg                                SourceLocation NameLoc,
849*e038c9c4Sjoerg                                llvm::StringMap<SourceLocation> &Seen,
850*e038c9c4Sjoerg                                OMPContextLvl Lvl) {
851*e038c9c4Sjoerg   auto Res = Seen.try_emplace(Name, NameLoc);
852*e038c9c4Sjoerg   if (Res.second)
853*e038c9c4Sjoerg     return false;
854*e038c9c4Sjoerg 
855*e038c9c4Sjoerg   // Each trait-set-selector-name, trait-selector-name and trait-name can
856*e038c9c4Sjoerg   // only be specified once.
857*e038c9c4Sjoerg   P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
858*e038c9c4Sjoerg       << Lvl << Name;
859*e038c9c4Sjoerg   P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
860*e038c9c4Sjoerg       << Lvl << Name;
861*e038c9c4Sjoerg   return true;
862*e038c9c4Sjoerg }
863*e038c9c4Sjoerg } // namespace
864*e038c9c4Sjoerg 
parseOMPTraitPropertyKind(OMPTraitProperty & TIProperty,llvm::omp::TraitSet Set,llvm::omp::TraitSelector Selector,llvm::StringMap<SourceLocation> & Seen)865*e038c9c4Sjoerg void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,
866*e038c9c4Sjoerg                                        llvm::omp::TraitSet Set,
867*e038c9c4Sjoerg                                        llvm::omp::TraitSelector Selector,
868*e038c9c4Sjoerg                                        llvm::StringMap<SourceLocation> &Seen) {
869*e038c9c4Sjoerg   TIProperty.Kind = TraitProperty::invalid;
870*e038c9c4Sjoerg 
871*e038c9c4Sjoerg   SourceLocation NameLoc = Tok.getLocation();
872*e038c9c4Sjoerg   StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
873*e038c9c4Sjoerg   if (Name.empty()) {
874*e038c9c4Sjoerg     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
875*e038c9c4Sjoerg         << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
876*e038c9c4Sjoerg     return;
877*e038c9c4Sjoerg   }
878*e038c9c4Sjoerg 
879*e038c9c4Sjoerg   TIProperty.RawString = Name;
880*e038c9c4Sjoerg   TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
881*e038c9c4Sjoerg   if (TIProperty.Kind != TraitProperty::invalid) {
882*e038c9c4Sjoerg     if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
883*e038c9c4Sjoerg       TIProperty.Kind = TraitProperty::invalid;
884*e038c9c4Sjoerg     return;
885*e038c9c4Sjoerg   }
886*e038c9c4Sjoerg 
887*e038c9c4Sjoerg   // It follows diagnosis and helping notes.
888*e038c9c4Sjoerg   // FIXME: We should move the diagnosis string generation into libFrontend.
889*e038c9c4Sjoerg   Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
890*e038c9c4Sjoerg       << Name << getOpenMPContextTraitSelectorName(Selector)
891*e038c9c4Sjoerg       << getOpenMPContextTraitSetName(Set);
892*e038c9c4Sjoerg 
893*e038c9c4Sjoerg   TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
894*e038c9c4Sjoerg   if (SetForName != TraitSet::invalid) {
895*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
896*e038c9c4Sjoerg         << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
897*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
898*e038c9c4Sjoerg         << Name << "<selector-name>"
899*e038c9c4Sjoerg         << "(<property-name>)";
900*e038c9c4Sjoerg     return;
901*e038c9c4Sjoerg   }
902*e038c9c4Sjoerg   TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
903*e038c9c4Sjoerg   if (SelectorForName != TraitSelector::invalid) {
904*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
905*e038c9c4Sjoerg         << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
906*e038c9c4Sjoerg     bool AllowsTraitScore = false;
907*e038c9c4Sjoerg     bool RequiresProperty = false;
908*e038c9c4Sjoerg     isValidTraitSelectorForTraitSet(
909*e038c9c4Sjoerg         SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
910*e038c9c4Sjoerg         AllowsTraitScore, RequiresProperty);
911*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
912*e038c9c4Sjoerg         << getOpenMPContextTraitSetName(
913*e038c9c4Sjoerg                getOpenMPContextTraitSetForSelector(SelectorForName))
914*e038c9c4Sjoerg         << Name << (RequiresProperty ? "(<property-name>)" : "");
915*e038c9c4Sjoerg     return;
916*e038c9c4Sjoerg   }
917*e038c9c4Sjoerg   for (const auto &PotentialSet :
918*e038c9c4Sjoerg        {TraitSet::construct, TraitSet::user, TraitSet::implementation,
919*e038c9c4Sjoerg         TraitSet::device}) {
920*e038c9c4Sjoerg     TraitProperty PropertyForName =
921*e038c9c4Sjoerg         getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
922*e038c9c4Sjoerg     if (PropertyForName == TraitProperty::invalid)
923*e038c9c4Sjoerg       continue;
924*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
925*e038c9c4Sjoerg         << getOpenMPContextTraitSetName(
926*e038c9c4Sjoerg                getOpenMPContextTraitSetForProperty(PropertyForName))
927*e038c9c4Sjoerg         << getOpenMPContextTraitSelectorName(
928*e038c9c4Sjoerg                getOpenMPContextTraitSelectorForProperty(PropertyForName))
929*e038c9c4Sjoerg         << ("(" + Name + ")").str();
930*e038c9c4Sjoerg     return;
931*e038c9c4Sjoerg   }
932*e038c9c4Sjoerg   Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
933*e038c9c4Sjoerg       << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
934*e038c9c4Sjoerg }
935*e038c9c4Sjoerg 
checkExtensionProperty(Parser & P,SourceLocation Loc,OMPTraitProperty & TIProperty,OMPTraitSelector & TISelector,llvm::StringMap<SourceLocation> & Seen)936*e038c9c4Sjoerg static bool checkExtensionProperty(Parser &P, SourceLocation Loc,
937*e038c9c4Sjoerg                                    OMPTraitProperty &TIProperty,
938*e038c9c4Sjoerg                                    OMPTraitSelector &TISelector,
939*e038c9c4Sjoerg                                    llvm::StringMap<SourceLocation> &Seen) {
940*e038c9c4Sjoerg   assert(TISelector.Kind ==
941*e038c9c4Sjoerg              llvm::omp::TraitSelector::implementation_extension &&
942*e038c9c4Sjoerg          "Only for extension properties, e.g., "
943*e038c9c4Sjoerg          "`implementation={extension(PROPERTY)}`");
944*e038c9c4Sjoerg   if (TIProperty.Kind == TraitProperty::invalid)
945*e038c9c4Sjoerg     return false;
946*e038c9c4Sjoerg 
947*e038c9c4Sjoerg   if (TIProperty.Kind ==
948*e038c9c4Sjoerg       TraitProperty::implementation_extension_disable_implicit_base)
949*e038c9c4Sjoerg     return true;
950*e038c9c4Sjoerg 
951*e038c9c4Sjoerg   if (TIProperty.Kind ==
952*e038c9c4Sjoerg       TraitProperty::implementation_extension_allow_templates)
953*e038c9c4Sjoerg     return true;
954*e038c9c4Sjoerg 
955*e038c9c4Sjoerg   auto IsMatchExtension = [](OMPTraitProperty &TP) {
956*e038c9c4Sjoerg     return (TP.Kind ==
957*e038c9c4Sjoerg                 llvm::omp::TraitProperty::implementation_extension_match_all ||
958*e038c9c4Sjoerg             TP.Kind ==
959*e038c9c4Sjoerg                 llvm::omp::TraitProperty::implementation_extension_match_any ||
960*e038c9c4Sjoerg             TP.Kind ==
961*e038c9c4Sjoerg                 llvm::omp::TraitProperty::implementation_extension_match_none);
962*e038c9c4Sjoerg   };
963*e038c9c4Sjoerg 
964*e038c9c4Sjoerg   if (IsMatchExtension(TIProperty)) {
965*e038c9c4Sjoerg     for (OMPTraitProperty &SeenProp : TISelector.Properties)
966*e038c9c4Sjoerg       if (IsMatchExtension(SeenProp)) {
967*e038c9c4Sjoerg         P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
968*e038c9c4Sjoerg         StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
969*e038c9c4Sjoerg             SeenProp.Kind, SeenProp.RawString);
970*e038c9c4Sjoerg         SourceLocation SeenLoc = Seen[SeenName];
971*e038c9c4Sjoerg         P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
972*e038c9c4Sjoerg             << CONTEXT_TRAIT_LVL << SeenName;
973*e038c9c4Sjoerg         return false;
974*e038c9c4Sjoerg       }
975*e038c9c4Sjoerg     return true;
976*e038c9c4Sjoerg   }
977*e038c9c4Sjoerg 
978*e038c9c4Sjoerg   llvm_unreachable("Unknown extension property!");
979*e038c9c4Sjoerg }
980*e038c9c4Sjoerg 
parseOMPContextProperty(OMPTraitSelector & TISelector,llvm::omp::TraitSet Set,llvm::StringMap<SourceLocation> & Seen)981*e038c9c4Sjoerg void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
982*e038c9c4Sjoerg                                      llvm::omp::TraitSet Set,
983*e038c9c4Sjoerg                                      llvm::StringMap<SourceLocation> &Seen) {
984*e038c9c4Sjoerg   assert(TISelector.Kind != TraitSelector::user_condition &&
985*e038c9c4Sjoerg          "User conditions are special properties not handled here!");
986*e038c9c4Sjoerg 
987*e038c9c4Sjoerg   SourceLocation PropertyLoc = Tok.getLocation();
988*e038c9c4Sjoerg   OMPTraitProperty TIProperty;
989*e038c9c4Sjoerg   parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);
990*e038c9c4Sjoerg 
991*e038c9c4Sjoerg   if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)
992*e038c9c4Sjoerg     if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,
993*e038c9c4Sjoerg                                 TISelector, Seen))
994*e038c9c4Sjoerg       TIProperty.Kind = TraitProperty::invalid;
995*e038c9c4Sjoerg 
996*e038c9c4Sjoerg   // If we have an invalid property here we already issued a warning.
997*e038c9c4Sjoerg   if (TIProperty.Kind == TraitProperty::invalid) {
998*e038c9c4Sjoerg     if (PropertyLoc != Tok.getLocation())
999*e038c9c4Sjoerg       Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1000*e038c9c4Sjoerg           << CONTEXT_TRAIT_LVL;
1001*e038c9c4Sjoerg     return;
1002*e038c9c4Sjoerg   }
1003*e038c9c4Sjoerg 
1004*e038c9c4Sjoerg   if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
1005*e038c9c4Sjoerg                                                  TISelector.Kind, Set)) {
1006*e038c9c4Sjoerg 
1007*e038c9c4Sjoerg     // If we make it here the property, selector, set, score, condition, ... are
1008*e038c9c4Sjoerg     // all valid (or have been corrected). Thus we can record the property.
1009*e038c9c4Sjoerg     TISelector.Properties.push_back(TIProperty);
1010*e038c9c4Sjoerg     return;
1011*e038c9c4Sjoerg   }
1012*e038c9c4Sjoerg 
1013*e038c9c4Sjoerg   Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
1014*e038c9c4Sjoerg       << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1015*e038c9c4Sjoerg                                            TIProperty.RawString)
1016*e038c9c4Sjoerg       << getOpenMPContextTraitSelectorName(TISelector.Kind)
1017*e038c9c4Sjoerg       << getOpenMPContextTraitSetName(Set);
1018*e038c9c4Sjoerg   Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
1019*e038c9c4Sjoerg       << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1020*e038c9c4Sjoerg                                            TIProperty.RawString)
1021*e038c9c4Sjoerg       << getOpenMPContextTraitSelectorName(
1022*e038c9c4Sjoerg              getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
1023*e038c9c4Sjoerg       << getOpenMPContextTraitSetName(
1024*e038c9c4Sjoerg              getOpenMPContextTraitSetForProperty(TIProperty.Kind));
1025*e038c9c4Sjoerg   Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1026*e038c9c4Sjoerg       << CONTEXT_TRAIT_LVL;
1027*e038c9c4Sjoerg }
1028*e038c9c4Sjoerg 
parseOMPTraitSelectorKind(OMPTraitSelector & TISelector,llvm::omp::TraitSet Set,llvm::StringMap<SourceLocation> & Seen)1029*e038c9c4Sjoerg void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,
1030*e038c9c4Sjoerg                                        llvm::omp::TraitSet Set,
1031*e038c9c4Sjoerg                                        llvm::StringMap<SourceLocation> &Seen) {
1032*e038c9c4Sjoerg   TISelector.Kind = TraitSelector::invalid;
1033*e038c9c4Sjoerg 
1034*e038c9c4Sjoerg   SourceLocation NameLoc = Tok.getLocation();
1035*e038c9c4Sjoerg   StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);
1036*e038c9c4Sjoerg   if (Name.empty()) {
1037*e038c9c4Sjoerg     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1038*e038c9c4Sjoerg         << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1039*e038c9c4Sjoerg     return;
1040*e038c9c4Sjoerg   }
1041*e038c9c4Sjoerg 
1042*e038c9c4Sjoerg   TISelector.Kind = getOpenMPContextTraitSelectorKind(Name);
1043*e038c9c4Sjoerg   if (TISelector.Kind != TraitSelector::invalid) {
1044*e038c9c4Sjoerg     if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
1045*e038c9c4Sjoerg       TISelector.Kind = TraitSelector::invalid;
1046*e038c9c4Sjoerg     return;
1047*e038c9c4Sjoerg   }
1048*e038c9c4Sjoerg 
1049*e038c9c4Sjoerg   // It follows diagnosis and helping notes.
1050*e038c9c4Sjoerg   Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1051*e038c9c4Sjoerg       << Name << getOpenMPContextTraitSetName(Set);
1052*e038c9c4Sjoerg 
1053*e038c9c4Sjoerg   TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1054*e038c9c4Sjoerg   if (SetForName != TraitSet::invalid) {
1055*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1056*e038c9c4Sjoerg         << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1057*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1058*e038c9c4Sjoerg         << Name << "<selector-name>"
1059*e038c9c4Sjoerg         << "<property-name>";
1060*e038c9c4Sjoerg     return;
1061*e038c9c4Sjoerg   }
1062*e038c9c4Sjoerg   for (const auto &PotentialSet :
1063*e038c9c4Sjoerg        {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1064*e038c9c4Sjoerg         TraitSet::device}) {
1065*e038c9c4Sjoerg     TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1066*e038c9c4Sjoerg         PotentialSet, TraitSelector::invalid, Name);
1067*e038c9c4Sjoerg     if (PropertyForName == TraitProperty::invalid)
1068*e038c9c4Sjoerg       continue;
1069*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1070*e038c9c4Sjoerg         << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1071*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1072*e038c9c4Sjoerg         << getOpenMPContextTraitSetName(
1073*e038c9c4Sjoerg                getOpenMPContextTraitSetForProperty(PropertyForName))
1074*e038c9c4Sjoerg         << getOpenMPContextTraitSelectorName(
1075*e038c9c4Sjoerg                getOpenMPContextTraitSelectorForProperty(PropertyForName))
1076*e038c9c4Sjoerg         << ("(" + Name + ")").str();
1077*e038c9c4Sjoerg     return;
1078*e038c9c4Sjoerg   }
1079*e038c9c4Sjoerg   Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1080*e038c9c4Sjoerg       << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1081*e038c9c4Sjoerg }
1082*e038c9c4Sjoerg 
10837330f729Sjoerg /// Parse optional 'score' '(' <expr> ')' ':'.
parseContextScore(Parser & P)10847330f729Sjoerg static ExprResult parseContextScore(Parser &P) {
10857330f729Sjoerg   ExprResult ScoreExpr;
1086*e038c9c4Sjoerg   llvm::SmallString<16> Buffer;
10877330f729Sjoerg   StringRef SelectorName =
10887330f729Sjoerg       P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
1089*e038c9c4Sjoerg   if (!SelectorName.equals("score"))
10907330f729Sjoerg     return ScoreExpr;
10917330f729Sjoerg   (void)P.ConsumeToken();
10927330f729Sjoerg   SourceLocation RLoc;
10937330f729Sjoerg   ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
10947330f729Sjoerg   // Parse ':'
10957330f729Sjoerg   if (P.getCurToken().is(tok::colon))
10967330f729Sjoerg     (void)P.ConsumeAnyToken();
10977330f729Sjoerg   else
1098*e038c9c4Sjoerg     P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
1099*e038c9c4Sjoerg         << "':'"
1100*e038c9c4Sjoerg         << "score expression";
11017330f729Sjoerg   return ScoreExpr;
11027330f729Sjoerg }
11037330f729Sjoerg 
1104*e038c9c4Sjoerg /// Parses an OpenMP context selector.
1105*e038c9c4Sjoerg ///
1106*e038c9c4Sjoerg /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')']
parseOMPContextSelector(OMPTraitSelector & TISelector,llvm::omp::TraitSet Set,llvm::StringMap<SourceLocation> & SeenSelectors)1107*e038c9c4Sjoerg void Parser::parseOMPContextSelector(
1108*e038c9c4Sjoerg     OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
1109*e038c9c4Sjoerg     llvm::StringMap<SourceLocation> &SeenSelectors) {
1110*e038c9c4Sjoerg   unsigned short OuterPC = ParenCount;
1111*e038c9c4Sjoerg 
1112*e038c9c4Sjoerg   // If anything went wrong we issue an error or warning and then skip the rest
1113*e038c9c4Sjoerg   // of the selector. However, commas are ambiguous so we look for the nesting
1114*e038c9c4Sjoerg   // of parentheses here as well.
1115*e038c9c4Sjoerg   auto FinishSelector = [OuterPC, this]() -> void {
1116*e038c9c4Sjoerg     bool Done = false;
1117*e038c9c4Sjoerg     while (!Done) {
1118*e038c9c4Sjoerg       while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1119*e038c9c4Sjoerg                          tok::annot_pragma_openmp_end},
1120*e038c9c4Sjoerg                         StopBeforeMatch))
11217330f729Sjoerg         ;
1122*e038c9c4Sjoerg       if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
1123*e038c9c4Sjoerg         (void)ConsumeParen();
1124*e038c9c4Sjoerg       if (OuterPC <= ParenCount) {
1125*e038c9c4Sjoerg         Done = true;
11267330f729Sjoerg         break;
11277330f729Sjoerg       }
1128*e038c9c4Sjoerg       if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
1129*e038c9c4Sjoerg         Done = true;
1130*e038c9c4Sjoerg         break;
1131*e038c9c4Sjoerg       }
1132*e038c9c4Sjoerg       (void)ConsumeAnyToken();
1133*e038c9c4Sjoerg     }
1134*e038c9c4Sjoerg     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1135*e038c9c4Sjoerg         << CONTEXT_SELECTOR_LVL;
1136*e038c9c4Sjoerg   };
1137*e038c9c4Sjoerg 
1138*e038c9c4Sjoerg   SourceLocation SelectorLoc = Tok.getLocation();
1139*e038c9c4Sjoerg   parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
1140*e038c9c4Sjoerg   if (TISelector.Kind == TraitSelector::invalid)
1141*e038c9c4Sjoerg     return FinishSelector();
1142*e038c9c4Sjoerg 
1143*e038c9c4Sjoerg   bool AllowsTraitScore = false;
1144*e038c9c4Sjoerg   bool RequiresProperty = false;
1145*e038c9c4Sjoerg   if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
1146*e038c9c4Sjoerg                                        RequiresProperty)) {
1147*e038c9c4Sjoerg     Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1148*e038c9c4Sjoerg         << getOpenMPContextTraitSelectorName(TISelector.Kind)
1149*e038c9c4Sjoerg         << getOpenMPContextTraitSetName(Set);
1150*e038c9c4Sjoerg     Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1151*e038c9c4Sjoerg         << getOpenMPContextTraitSelectorName(TISelector.Kind)
1152*e038c9c4Sjoerg         << getOpenMPContextTraitSetName(
1153*e038c9c4Sjoerg                getOpenMPContextTraitSetForSelector(TISelector.Kind))
1154*e038c9c4Sjoerg         << RequiresProperty;
1155*e038c9c4Sjoerg     return FinishSelector();
1156*e038c9c4Sjoerg   }
1157*e038c9c4Sjoerg 
1158*e038c9c4Sjoerg   if (!RequiresProperty) {
1159*e038c9c4Sjoerg     TISelector.Properties.push_back(
1160*e038c9c4Sjoerg         {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
1161*e038c9c4Sjoerg          getOpenMPContextTraitSelectorName(TISelector.Kind)});
11627330f729Sjoerg     return;
11637330f729Sjoerg   }
1164*e038c9c4Sjoerg 
1165*e038c9c4Sjoerg   if (!Tok.is(tok::l_paren)) {
1166*e038c9c4Sjoerg     Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1167*e038c9c4Sjoerg         << getOpenMPContextTraitSelectorName(TISelector.Kind)
1168*e038c9c4Sjoerg         << getOpenMPContextTraitSetName(Set);
1169*e038c9c4Sjoerg     return FinishSelector();
1170*e038c9c4Sjoerg   }
1171*e038c9c4Sjoerg 
1172*e038c9c4Sjoerg   if (TISelector.Kind == TraitSelector::user_condition) {
1173*e038c9c4Sjoerg     SourceLocation RLoc;
1174*e038c9c4Sjoerg     ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
1175*e038c9c4Sjoerg     if (!Condition.isUsable())
1176*e038c9c4Sjoerg       return FinishSelector();
1177*e038c9c4Sjoerg     TISelector.ScoreOrCondition = Condition.get();
1178*e038c9c4Sjoerg     TISelector.Properties.push_back(
1179*e038c9c4Sjoerg         {TraitProperty::user_condition_unknown, "<condition>"});
1180*e038c9c4Sjoerg     return;
1181*e038c9c4Sjoerg   }
1182*e038c9c4Sjoerg 
1183*e038c9c4Sjoerg   BalancedDelimiterTracker BDT(*this, tok::l_paren,
1184*e038c9c4Sjoerg                                tok::annot_pragma_openmp_end);
1185*e038c9c4Sjoerg   // Parse '('.
1186*e038c9c4Sjoerg   (void)BDT.consumeOpen();
1187*e038c9c4Sjoerg 
1188*e038c9c4Sjoerg   SourceLocation ScoreLoc = Tok.getLocation();
1189*e038c9c4Sjoerg   ExprResult Score = parseContextScore(*this);
1190*e038c9c4Sjoerg 
1191*e038c9c4Sjoerg   if (!AllowsTraitScore && !Score.isUnset()) {
1192*e038c9c4Sjoerg     if (Score.isUsable()) {
1193*e038c9c4Sjoerg       Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1194*e038c9c4Sjoerg           << getOpenMPContextTraitSelectorName(TISelector.Kind)
1195*e038c9c4Sjoerg           << getOpenMPContextTraitSetName(Set) << Score.get();
1196*e038c9c4Sjoerg     } else {
1197*e038c9c4Sjoerg       Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1198*e038c9c4Sjoerg           << getOpenMPContextTraitSelectorName(TISelector.Kind)
1199*e038c9c4Sjoerg           << getOpenMPContextTraitSetName(Set) << "<invalid>";
1200*e038c9c4Sjoerg     }
1201*e038c9c4Sjoerg     Score = ExprResult();
1202*e038c9c4Sjoerg   }
1203*e038c9c4Sjoerg 
1204*e038c9c4Sjoerg   if (Score.isUsable())
1205*e038c9c4Sjoerg     TISelector.ScoreOrCondition = Score.get();
1206*e038c9c4Sjoerg 
1207*e038c9c4Sjoerg   llvm::StringMap<SourceLocation> SeenProperties;
1208*e038c9c4Sjoerg   do {
1209*e038c9c4Sjoerg     parseOMPContextProperty(TISelector, Set, SeenProperties);
1210*e038c9c4Sjoerg   } while (TryConsumeToken(tok::comma));
1211*e038c9c4Sjoerg 
1212*e038c9c4Sjoerg   // Parse ')'.
1213*e038c9c4Sjoerg   BDT.consumeClose();
1214*e038c9c4Sjoerg }
1215*e038c9c4Sjoerg 
parseOMPTraitSetKind(OMPTraitSet & TISet,llvm::StringMap<SourceLocation> & Seen)1216*e038c9c4Sjoerg void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
1217*e038c9c4Sjoerg                                   llvm::StringMap<SourceLocation> &Seen) {
1218*e038c9c4Sjoerg   TISet.Kind = TraitSet::invalid;
1219*e038c9c4Sjoerg 
1220*e038c9c4Sjoerg   SourceLocation NameLoc = Tok.getLocation();
1221*e038c9c4Sjoerg   StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);
1222*e038c9c4Sjoerg   if (Name.empty()) {
1223*e038c9c4Sjoerg     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1224*e038c9c4Sjoerg         << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1225*e038c9c4Sjoerg     return;
1226*e038c9c4Sjoerg   }
1227*e038c9c4Sjoerg 
1228*e038c9c4Sjoerg   TISet.Kind = getOpenMPContextTraitSetKind(Name);
1229*e038c9c4Sjoerg   if (TISet.Kind != TraitSet::invalid) {
1230*e038c9c4Sjoerg     if (checkForDuplicates(*this, Name, NameLoc, Seen,
1231*e038c9c4Sjoerg                            CONTEXT_SELECTOR_SET_LVL))
1232*e038c9c4Sjoerg       TISet.Kind = TraitSet::invalid;
1233*e038c9c4Sjoerg     return;
1234*e038c9c4Sjoerg   }
1235*e038c9c4Sjoerg 
1236*e038c9c4Sjoerg   // It follows diagnosis and helping notes.
1237*e038c9c4Sjoerg   Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1238*e038c9c4Sjoerg 
1239*e038c9c4Sjoerg   TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
1240*e038c9c4Sjoerg   if (SelectorForName != TraitSelector::invalid) {
1241*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1242*e038c9c4Sjoerg         << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1243*e038c9c4Sjoerg     bool AllowsTraitScore = false;
1244*e038c9c4Sjoerg     bool RequiresProperty = false;
1245*e038c9c4Sjoerg     isValidTraitSelectorForTraitSet(
1246*e038c9c4Sjoerg         SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1247*e038c9c4Sjoerg         AllowsTraitScore, RequiresProperty);
1248*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1249*e038c9c4Sjoerg         << getOpenMPContextTraitSetName(
1250*e038c9c4Sjoerg                getOpenMPContextTraitSetForSelector(SelectorForName))
1251*e038c9c4Sjoerg         << Name << (RequiresProperty ? "(<property-name>)" : "");
1252*e038c9c4Sjoerg     return;
1253*e038c9c4Sjoerg   }
1254*e038c9c4Sjoerg   for (const auto &PotentialSet :
1255*e038c9c4Sjoerg        {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1256*e038c9c4Sjoerg         TraitSet::device}) {
1257*e038c9c4Sjoerg     TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1258*e038c9c4Sjoerg         PotentialSet, TraitSelector::invalid, Name);
1259*e038c9c4Sjoerg     if (PropertyForName == TraitProperty::invalid)
1260*e038c9c4Sjoerg       continue;
1261*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1262*e038c9c4Sjoerg         << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1263*e038c9c4Sjoerg     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1264*e038c9c4Sjoerg         << getOpenMPContextTraitSetName(
1265*e038c9c4Sjoerg                getOpenMPContextTraitSetForProperty(PropertyForName))
1266*e038c9c4Sjoerg         << getOpenMPContextTraitSelectorName(
1267*e038c9c4Sjoerg                getOpenMPContextTraitSelectorForProperty(PropertyForName))
1268*e038c9c4Sjoerg         << ("(" + Name + ")").str();
1269*e038c9c4Sjoerg     return;
1270*e038c9c4Sjoerg   }
1271*e038c9c4Sjoerg   Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1272*e038c9c4Sjoerg       << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1273*e038c9c4Sjoerg }
1274*e038c9c4Sjoerg 
1275*e038c9c4Sjoerg /// Parses an OpenMP context selector set.
1276*e038c9c4Sjoerg ///
1277*e038c9c4Sjoerg /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}'
parseOMPContextSelectorSet(OMPTraitSet & TISet,llvm::StringMap<SourceLocation> & SeenSets)1278*e038c9c4Sjoerg void Parser::parseOMPContextSelectorSet(
1279*e038c9c4Sjoerg     OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
1280*e038c9c4Sjoerg   auto OuterBC = BraceCount;
1281*e038c9c4Sjoerg 
1282*e038c9c4Sjoerg   // If anything went wrong we issue an error or warning and then skip the rest
1283*e038c9c4Sjoerg   // of the set. However, commas are ambiguous so we look for the nesting
1284*e038c9c4Sjoerg   // of braces here as well.
1285*e038c9c4Sjoerg   auto FinishSelectorSet = [this, OuterBC]() -> void {
1286*e038c9c4Sjoerg     bool Done = false;
1287*e038c9c4Sjoerg     while (!Done) {
1288*e038c9c4Sjoerg       while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1289*e038c9c4Sjoerg                          tok::annot_pragma_openmp_end},
1290*e038c9c4Sjoerg                         StopBeforeMatch))
1291*e038c9c4Sjoerg         ;
1292*e038c9c4Sjoerg       if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
1293*e038c9c4Sjoerg         (void)ConsumeBrace();
1294*e038c9c4Sjoerg       if (OuterBC <= BraceCount) {
1295*e038c9c4Sjoerg         Done = true;
1296*e038c9c4Sjoerg         break;
1297*e038c9c4Sjoerg       }
1298*e038c9c4Sjoerg       if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
1299*e038c9c4Sjoerg         Done = true;
1300*e038c9c4Sjoerg         break;
1301*e038c9c4Sjoerg       }
1302*e038c9c4Sjoerg       (void)ConsumeAnyToken();
1303*e038c9c4Sjoerg     }
1304*e038c9c4Sjoerg     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1305*e038c9c4Sjoerg         << CONTEXT_SELECTOR_SET_LVL;
1306*e038c9c4Sjoerg   };
1307*e038c9c4Sjoerg 
1308*e038c9c4Sjoerg   parseOMPTraitSetKind(TISet, SeenSets);
1309*e038c9c4Sjoerg   if (TISet.Kind == TraitSet::invalid)
1310*e038c9c4Sjoerg     return FinishSelectorSet();
1311*e038c9c4Sjoerg 
1312*e038c9c4Sjoerg   // Parse '='.
1313*e038c9c4Sjoerg   if (!TryConsumeToken(tok::equal))
1314*e038c9c4Sjoerg     Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1315*e038c9c4Sjoerg         << "="
1316*e038c9c4Sjoerg         << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
1317*e038c9c4Sjoerg             "\"")
1318*e038c9c4Sjoerg                .str();
1319*e038c9c4Sjoerg 
1320*e038c9c4Sjoerg   // Parse '{'.
1321*e038c9c4Sjoerg   if (Tok.is(tok::l_brace)) {
1322*e038c9c4Sjoerg     (void)ConsumeBrace();
1323*e038c9c4Sjoerg   } else {
1324*e038c9c4Sjoerg     Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1325*e038c9c4Sjoerg         << "{"
1326*e038c9c4Sjoerg         << ("'=' that follows the context set name \"" +
1327*e038c9c4Sjoerg             getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1328*e038c9c4Sjoerg                .str();
1329*e038c9c4Sjoerg   }
1330*e038c9c4Sjoerg 
1331*e038c9c4Sjoerg   llvm::StringMap<SourceLocation> SeenSelectors;
1332*e038c9c4Sjoerg   do {
1333*e038c9c4Sjoerg     OMPTraitSelector TISelector;
1334*e038c9c4Sjoerg     parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
1335*e038c9c4Sjoerg     if (TISelector.Kind != TraitSelector::invalid &&
1336*e038c9c4Sjoerg         !TISelector.Properties.empty())
1337*e038c9c4Sjoerg       TISet.Selectors.push_back(TISelector);
1338*e038c9c4Sjoerg   } while (TryConsumeToken(tok::comma));
1339*e038c9c4Sjoerg 
1340*e038c9c4Sjoerg   // Parse '}'.
1341*e038c9c4Sjoerg   if (Tok.is(tok::r_brace)) {
1342*e038c9c4Sjoerg     (void)ConsumeBrace();
1343*e038c9c4Sjoerg   } else {
1344*e038c9c4Sjoerg     Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1345*e038c9c4Sjoerg         << "}"
1346*e038c9c4Sjoerg         << ("context selectors for the context set \"" +
1347*e038c9c4Sjoerg             getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1348*e038c9c4Sjoerg                .str();
1349*e038c9c4Sjoerg   }
13507330f729Sjoerg }
13517330f729Sjoerg 
1352*e038c9c4Sjoerg /// Parse OpenMP context selectors:
1353*e038c9c4Sjoerg ///
1354*e038c9c4Sjoerg /// <trait-set-selector> [, <trait-set-selector>]*
parseOMPContextSelectors(SourceLocation Loc,OMPTraitInfo & TI)1355*e038c9c4Sjoerg bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
1356*e038c9c4Sjoerg   llvm::StringMap<SourceLocation> SeenSets;
13577330f729Sjoerg   do {
1358*e038c9c4Sjoerg     OMPTraitSet TISet;
1359*e038c9c4Sjoerg     parseOMPContextSelectorSet(TISet, SeenSets);
1360*e038c9c4Sjoerg     if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
1361*e038c9c4Sjoerg       TI.Sets.push_back(TISet);
1362*e038c9c4Sjoerg   } while (TryConsumeToken(tok::comma));
1363*e038c9c4Sjoerg 
13647330f729Sjoerg   return false;
13657330f729Sjoerg }
13667330f729Sjoerg 
13677330f729Sjoerg /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,CachedTokens & Toks,SourceLocation Loc)13687330f729Sjoerg void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
13697330f729Sjoerg                                            CachedTokens &Toks,
13707330f729Sjoerg                                            SourceLocation Loc) {
13717330f729Sjoerg   PP.EnterToken(Tok, /*IsReinject*/ true);
13727330f729Sjoerg   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
13737330f729Sjoerg                       /*IsReinject*/ true);
13747330f729Sjoerg   // Consume the previously pushed token.
13757330f729Sjoerg   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
13767330f729Sjoerg   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
13777330f729Sjoerg 
13787330f729Sjoerg   FNContextRAII FnContext(*this, Ptr);
13797330f729Sjoerg   // Parse function declaration id.
13807330f729Sjoerg   SourceLocation RLoc;
13817330f729Sjoerg   // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
13827330f729Sjoerg   // instead of MemberExprs.
1383*e038c9c4Sjoerg   ExprResult AssociatedFunction;
1384*e038c9c4Sjoerg   {
1385*e038c9c4Sjoerg     // Do not mark function as is used to prevent its emission if this is the
1386*e038c9c4Sjoerg     // only place where it is used.
1387*e038c9c4Sjoerg     EnterExpressionEvaluationContext Unevaluated(
1388*e038c9c4Sjoerg         Actions, Sema::ExpressionEvaluationContext::Unevaluated);
1389*e038c9c4Sjoerg     AssociatedFunction = ParseOpenMPParensExpr(
1390*e038c9c4Sjoerg         getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
13917330f729Sjoerg         /*IsAddressOfOperand=*/true);
1392*e038c9c4Sjoerg   }
13937330f729Sjoerg   if (!AssociatedFunction.isUsable()) {
13947330f729Sjoerg     if (!Tok.is(tok::annot_pragma_openmp_end))
13957330f729Sjoerg       while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
13967330f729Sjoerg         ;
13977330f729Sjoerg     // Skip the last annot_pragma_openmp_end.
13987330f729Sjoerg     (void)ConsumeAnnotationToken();
13997330f729Sjoerg     return;
14007330f729Sjoerg   }
1401*e038c9c4Sjoerg 
1402*e038c9c4Sjoerg   OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
1403*e038c9c4Sjoerg   ASTContext &ASTCtx = Actions.getASTContext();
1404*e038c9c4Sjoerg   OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
1405*e038c9c4Sjoerg   if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
1406*e038c9c4Sjoerg     return;
1407*e038c9c4Sjoerg 
14087330f729Sjoerg   Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
14097330f729Sjoerg       Actions.checkOpenMPDeclareVariantFunction(
1410*e038c9c4Sjoerg           Ptr, AssociatedFunction.get(), TI,
1411*e038c9c4Sjoerg           SourceRange(Loc, Tok.getLocation()));
14127330f729Sjoerg 
1413*e038c9c4Sjoerg   // Skip last tokens.
1414*e038c9c4Sjoerg   while (Tok.isNot(tok::annot_pragma_openmp_end))
1415*e038c9c4Sjoerg     ConsumeAnyToken();
1416*e038c9c4Sjoerg   if (DeclVarData && !TI.Sets.empty())
1417*e038c9c4Sjoerg     Actions.ActOnOpenMPDeclareVariantDirective(
1418*e038c9c4Sjoerg         DeclVarData->first, DeclVarData->second, TI,
1419*e038c9c4Sjoerg         SourceRange(Loc, Tok.getLocation()));
1420*e038c9c4Sjoerg 
1421*e038c9c4Sjoerg   // Skip the last annot_pragma_openmp_end.
1422*e038c9c4Sjoerg   (void)ConsumeAnnotationToken();
1423*e038c9c4Sjoerg }
1424*e038c9c4Sjoerg 
parseOMPDeclareVariantMatchClause(SourceLocation Loc,OMPTraitInfo & TI,OMPTraitInfo * ParentTI)1425*e038c9c4Sjoerg bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
1426*e038c9c4Sjoerg                                                OMPTraitInfo &TI,
1427*e038c9c4Sjoerg                                                OMPTraitInfo *ParentTI) {
14287330f729Sjoerg   // Parse 'match'.
14297330f729Sjoerg   OpenMPClauseKind CKind = Tok.isAnnotation()
14307330f729Sjoerg                                ? OMPC_unknown
14317330f729Sjoerg                                : getOpenMPClauseKind(PP.getSpelling(Tok));
14327330f729Sjoerg   if (CKind != OMPC_match) {
14337330f729Sjoerg     Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
14347330f729Sjoerg         << getOpenMPClauseName(OMPC_match);
14357330f729Sjoerg     while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
14367330f729Sjoerg       ;
14377330f729Sjoerg     // Skip the last annot_pragma_openmp_end.
14387330f729Sjoerg     (void)ConsumeAnnotationToken();
1439*e038c9c4Sjoerg     return true;
14407330f729Sjoerg   }
14417330f729Sjoerg   (void)ConsumeToken();
14427330f729Sjoerg   // Parse '('.
14437330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
14447330f729Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after,
1445*e038c9c4Sjoerg                          getOpenMPClauseName(OMPC_match).data())) {
14467330f729Sjoerg     while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
14477330f729Sjoerg       ;
14487330f729Sjoerg     // Skip the last annot_pragma_openmp_end.
14497330f729Sjoerg     (void)ConsumeAnnotationToken();
1450*e038c9c4Sjoerg     return true;
14517330f729Sjoerg   }
14527330f729Sjoerg 
14537330f729Sjoerg   // Parse inner context selectors.
1454*e038c9c4Sjoerg   parseOMPContextSelectors(Loc, TI);
1455*e038c9c4Sjoerg 
1456*e038c9c4Sjoerg   // Parse ')'
14577330f729Sjoerg   (void)T.consumeClose();
1458*e038c9c4Sjoerg 
1459*e038c9c4Sjoerg   if (!ParentTI)
1460*e038c9c4Sjoerg     return false;
1461*e038c9c4Sjoerg 
1462*e038c9c4Sjoerg   // Merge the parent/outer trait info into the one we just parsed and diagnose
1463*e038c9c4Sjoerg   // problems.
1464*e038c9c4Sjoerg   // TODO: Keep some source location in the TI to provide better diagnostics.
1465*e038c9c4Sjoerg   // TODO: Perform some kind of equivalence check on the condition and score
1466*e038c9c4Sjoerg   //       expressions.
1467*e038c9c4Sjoerg   for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
1468*e038c9c4Sjoerg     bool MergedSet = false;
1469*e038c9c4Sjoerg     for (OMPTraitSet &Set : TI.Sets) {
1470*e038c9c4Sjoerg       if (Set.Kind != ParentSet.Kind)
1471*e038c9c4Sjoerg         continue;
1472*e038c9c4Sjoerg       MergedSet = true;
1473*e038c9c4Sjoerg       for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
1474*e038c9c4Sjoerg         bool MergedSelector = false;
1475*e038c9c4Sjoerg         for (OMPTraitSelector &Selector : Set.Selectors) {
1476*e038c9c4Sjoerg           if (Selector.Kind != ParentSelector.Kind)
1477*e038c9c4Sjoerg             continue;
1478*e038c9c4Sjoerg           MergedSelector = true;
1479*e038c9c4Sjoerg           for (const OMPTraitProperty &ParentProperty :
1480*e038c9c4Sjoerg                ParentSelector.Properties) {
1481*e038c9c4Sjoerg             bool MergedProperty = false;
1482*e038c9c4Sjoerg             for (OMPTraitProperty &Property : Selector.Properties) {
1483*e038c9c4Sjoerg               // Ignore "equivalent" properties.
1484*e038c9c4Sjoerg               if (Property.Kind != ParentProperty.Kind)
1485*e038c9c4Sjoerg                 continue;
1486*e038c9c4Sjoerg 
1487*e038c9c4Sjoerg               // If the kind is the same but the raw string not, we don't want
1488*e038c9c4Sjoerg               // to skip out on the property.
1489*e038c9c4Sjoerg               MergedProperty |= Property.RawString == ParentProperty.RawString;
1490*e038c9c4Sjoerg 
1491*e038c9c4Sjoerg               if (Property.RawString == ParentProperty.RawString &&
1492*e038c9c4Sjoerg                   Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
1493*e038c9c4Sjoerg                 continue;
1494*e038c9c4Sjoerg 
1495*e038c9c4Sjoerg               if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1496*e038c9c4Sjoerg                 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1497*e038c9c4Sjoerg               } else if (Selector.ScoreOrCondition !=
1498*e038c9c4Sjoerg                          ParentSelector.ScoreOrCondition) {
1499*e038c9c4Sjoerg                 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1500*e038c9c4Sjoerg                     << getOpenMPContextTraitPropertyName(
1501*e038c9c4Sjoerg                            ParentProperty.Kind, ParentProperty.RawString)
1502*e038c9c4Sjoerg                     << getOpenMPContextTraitSelectorName(ParentSelector.Kind)
1503*e038c9c4Sjoerg                     << getOpenMPContextTraitSetName(ParentSet.Kind);
15047330f729Sjoerg               }
15057330f729Sjoerg             }
1506*e038c9c4Sjoerg             if (!MergedProperty)
1507*e038c9c4Sjoerg               Selector.Properties.push_back(ParentProperty);
1508*e038c9c4Sjoerg           }
1509*e038c9c4Sjoerg         }
1510*e038c9c4Sjoerg         if (!MergedSelector)
1511*e038c9c4Sjoerg           Set.Selectors.push_back(ParentSelector);
1512*e038c9c4Sjoerg       }
1513*e038c9c4Sjoerg     }
1514*e038c9c4Sjoerg     if (!MergedSet)
1515*e038c9c4Sjoerg       TI.Sets.push_back(ParentSet);
1516*e038c9c4Sjoerg   }
15177330f729Sjoerg 
1518*e038c9c4Sjoerg   return false;
1519*e038c9c4Sjoerg }
1520*e038c9c4Sjoerg 
1521*e038c9c4Sjoerg /// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
1522*e038c9c4Sjoerg /// where
1523*e038c9c4Sjoerg ///
1524*e038c9c4Sjoerg ///   clause:
1525*e038c9c4Sjoerg ///     'ext_IMPL_DEFINED'
1526*e038c9c4Sjoerg ///     'absent' '(' directive-name [, directive-name]* ')'
1527*e038c9c4Sjoerg ///     'contains' '(' directive-name [, directive-name]* ')'
1528*e038c9c4Sjoerg ///     'holds' '(' scalar-expression ')'
1529*e038c9c4Sjoerg ///     'no_openmp'
1530*e038c9c4Sjoerg ///     'no_openmp_routines'
1531*e038c9c4Sjoerg ///     'no_parallelism'
1532*e038c9c4Sjoerg ///
ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,SourceLocation Loc)1533*e038c9c4Sjoerg void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
1534*e038c9c4Sjoerg                                          SourceLocation Loc) {
1535*e038c9c4Sjoerg   SmallVector<StringRef, 4> Assumptions;
1536*e038c9c4Sjoerg   bool SkippedClauses = false;
1537*e038c9c4Sjoerg 
1538*e038c9c4Sjoerg   auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
1539*e038c9c4Sjoerg     BalancedDelimiterTracker T(*this, tok::l_paren,
1540*e038c9c4Sjoerg                                tok::annot_pragma_openmp_end);
1541*e038c9c4Sjoerg     if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1542*e038c9c4Sjoerg       return;
1543*e038c9c4Sjoerg     T.skipToEnd();
1544*e038c9c4Sjoerg     if (IssueNote && T.getCloseLocation().isValid())
1545*e038c9c4Sjoerg       Diag(T.getCloseLocation(),
1546*e038c9c4Sjoerg            diag::note_omp_assumption_clause_continue_here);
1547*e038c9c4Sjoerg   };
1548*e038c9c4Sjoerg 
1549*e038c9c4Sjoerg   /// Helper to determine which AssumptionClauseMapping (ACM) in the
1550*e038c9c4Sjoerg   /// AssumptionClauseMappings table matches \p RawString. The return value is
1551*e038c9c4Sjoerg   /// the index of the matching ACM into the table or -1 if there was no match.
1552*e038c9c4Sjoerg   auto MatchACMClause = [&](StringRef RawString) {
1553*e038c9c4Sjoerg     llvm::StringSwitch<int> SS(RawString);
1554*e038c9c4Sjoerg     unsigned ACMIdx = 0;
1555*e038c9c4Sjoerg     for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1556*e038c9c4Sjoerg       if (ACMI.StartsWith)
1557*e038c9c4Sjoerg         SS.StartsWith(ACMI.Identifier, ACMIdx++);
1558*e038c9c4Sjoerg       else
1559*e038c9c4Sjoerg         SS.Case(ACMI.Identifier, ACMIdx++);
1560*e038c9c4Sjoerg     }
1561*e038c9c4Sjoerg     return SS.Default(-1);
1562*e038c9c4Sjoerg   };
1563*e038c9c4Sjoerg 
1564*e038c9c4Sjoerg   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1565*e038c9c4Sjoerg     IdentifierInfo *II = nullptr;
1566*e038c9c4Sjoerg     SourceLocation StartLoc = Tok.getLocation();
1567*e038c9c4Sjoerg     int Idx = -1;
1568*e038c9c4Sjoerg     if (Tok.isAnyIdentifier()) {
1569*e038c9c4Sjoerg       II = Tok.getIdentifierInfo();
1570*e038c9c4Sjoerg       Idx = MatchACMClause(II->getName());
1571*e038c9c4Sjoerg     }
15727330f729Sjoerg     ConsumeAnyToken();
1573*e038c9c4Sjoerg 
1574*e038c9c4Sjoerg     bool NextIsLPar = Tok.is(tok::l_paren);
1575*e038c9c4Sjoerg     // Handle unknown clauses by skipping them.
1576*e038c9c4Sjoerg     if (Idx == -1) {
1577*e038c9c4Sjoerg       Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1578*e038c9c4Sjoerg           << llvm::omp::getOpenMPDirectiveName(DKind)
1579*e038c9c4Sjoerg           << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1580*e038c9c4Sjoerg       if (NextIsLPar)
1581*e038c9c4Sjoerg         SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
1582*e038c9c4Sjoerg       SkippedClauses = true;
1583*e038c9c4Sjoerg       continue;
1584*e038c9c4Sjoerg     }
1585*e038c9c4Sjoerg     const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1586*e038c9c4Sjoerg     if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1587*e038c9c4Sjoerg       // TODO: We ignore absent, contains, and holds assumptions for now. We
1588*e038c9c4Sjoerg       //       also do not verify the content in the parenthesis at all.
1589*e038c9c4Sjoerg       SkippedClauses = true;
1590*e038c9c4Sjoerg       SkipBraces(II->getName(), /* IssueNote */ false);
1591*e038c9c4Sjoerg       continue;
1592*e038c9c4Sjoerg     }
1593*e038c9c4Sjoerg 
1594*e038c9c4Sjoerg     if (NextIsLPar) {
1595*e038c9c4Sjoerg       Diag(Tok.getLocation(),
1596*e038c9c4Sjoerg            diag::warn_omp_unknown_assumption_clause_without_args)
1597*e038c9c4Sjoerg           << II;
1598*e038c9c4Sjoerg       SkipBraces(II->getName(), /* IssueNote */ true);
1599*e038c9c4Sjoerg     }
1600*e038c9c4Sjoerg 
1601*e038c9c4Sjoerg     assert(II && "Expected an identifier clause!");
1602*e038c9c4Sjoerg     StringRef Assumption = II->getName();
1603*e038c9c4Sjoerg     if (ACMI.StartsWith)
1604*e038c9c4Sjoerg       Assumption = Assumption.substr(ACMI.Identifier.size());
1605*e038c9c4Sjoerg     Assumptions.push_back(Assumption);
1606*e038c9c4Sjoerg   }
1607*e038c9c4Sjoerg 
1608*e038c9c4Sjoerg   Actions.ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions, SkippedClauses);
1609*e038c9c4Sjoerg }
1610*e038c9c4Sjoerg 
ParseOpenMPEndAssumesDirective(SourceLocation Loc)1611*e038c9c4Sjoerg void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
1612*e038c9c4Sjoerg   if (Actions.isInOpenMPAssumeScope())
1613*e038c9c4Sjoerg     Actions.ActOnOpenMPEndAssumesDirective();
1614*e038c9c4Sjoerg   else
1615*e038c9c4Sjoerg     Diag(Loc, diag::err_expected_begin_assumes);
16167330f729Sjoerg }
16177330f729Sjoerg 
16187330f729Sjoerg /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
16197330f729Sjoerg ///
16207330f729Sjoerg ///    default-clause:
1621*e038c9c4Sjoerg ///         'default' '(' 'none' | 'shared'  | 'firstprivate' ')
16227330f729Sjoerg ///
16237330f729Sjoerg ///    proc_bind-clause:
16247330f729Sjoerg ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
16257330f729Sjoerg ///
16267330f729Sjoerg ///    device_type-clause:
16277330f729Sjoerg ///         'device_type' '(' 'host' | 'nohost' | 'any' )'
16287330f729Sjoerg namespace {
16297330f729Sjoerg struct SimpleClauseData {
16307330f729Sjoerg   unsigned Type;
16317330f729Sjoerg   SourceLocation Loc;
16327330f729Sjoerg   SourceLocation LOpen;
16337330f729Sjoerg   SourceLocation TypeLoc;
16347330f729Sjoerg   SourceLocation RLoc;
SimpleClauseData__anonc154ddd90c11::SimpleClauseData16357330f729Sjoerg   SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
16367330f729Sjoerg                    SourceLocation TypeLoc, SourceLocation RLoc)
16377330f729Sjoerg       : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
16387330f729Sjoerg };
16397330f729Sjoerg } // anonymous namespace
16407330f729Sjoerg 
16417330f729Sjoerg static Optional<SimpleClauseData>
parseOpenMPSimpleClause(Parser & P,OpenMPClauseKind Kind)16427330f729Sjoerg parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
16437330f729Sjoerg   const Token &Tok = P.getCurToken();
16447330f729Sjoerg   SourceLocation Loc = Tok.getLocation();
16457330f729Sjoerg   SourceLocation LOpen = P.ConsumeToken();
16467330f729Sjoerg   // Parse '('.
16477330f729Sjoerg   BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
16487330f729Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after,
1649*e038c9c4Sjoerg                          getOpenMPClauseName(Kind).data()))
16507330f729Sjoerg     return llvm::None;
16517330f729Sjoerg 
16527330f729Sjoerg   unsigned Type = getOpenMPSimpleClauseType(
1653*e038c9c4Sjoerg       Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
1654*e038c9c4Sjoerg       P.getLangOpts().OpenMP);
16557330f729Sjoerg   SourceLocation TypeLoc = Tok.getLocation();
16567330f729Sjoerg   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
16577330f729Sjoerg       Tok.isNot(tok::annot_pragma_openmp_end))
16587330f729Sjoerg     P.ConsumeAnyToken();
16597330f729Sjoerg 
16607330f729Sjoerg   // Parse ')'.
16617330f729Sjoerg   SourceLocation RLoc = Tok.getLocation();
16627330f729Sjoerg   if (!T.consumeClose())
16637330f729Sjoerg     RLoc = T.getCloseLocation();
16647330f729Sjoerg 
16657330f729Sjoerg   return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
16667330f729Sjoerg }
16677330f729Sjoerg 
ParseOMPDeclareTargetClauses(Sema::DeclareTargetContextInfo & DTCI)1668*e038c9c4Sjoerg void Parser::ParseOMPDeclareTargetClauses(
1669*e038c9c4Sjoerg     Sema::DeclareTargetContextInfo &DTCI) {
16707330f729Sjoerg   SourceLocation DeviceTypeLoc;
1671*e038c9c4Sjoerg   bool RequiresToOrLinkClause = false;
1672*e038c9c4Sjoerg   bool HasToOrLinkClause = false;
16737330f729Sjoerg   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
16747330f729Sjoerg     OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1675*e038c9c4Sjoerg     bool HasIdentifier = Tok.is(tok::identifier);
1676*e038c9c4Sjoerg     if (HasIdentifier) {
1677*e038c9c4Sjoerg       // If we see any clause we need a to or link clause.
1678*e038c9c4Sjoerg       RequiresToOrLinkClause = true;
16797330f729Sjoerg       IdentifierInfo *II = Tok.getIdentifierInfo();
16807330f729Sjoerg       StringRef ClauseName = II->getName();
16817330f729Sjoerg       bool IsDeviceTypeClause =
16827330f729Sjoerg           getLangOpts().OpenMP >= 50 &&
16837330f729Sjoerg           getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1684*e038c9c4Sjoerg 
1685*e038c9c4Sjoerg       bool IsToOrLinkClause =
1686*e038c9c4Sjoerg           OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1687*e038c9c4Sjoerg       assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!");
1688*e038c9c4Sjoerg 
1689*e038c9c4Sjoerg       if (!IsDeviceTypeClause && DTCI.Kind == OMPD_begin_declare_target) {
16907330f729Sjoerg         Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1691*e038c9c4Sjoerg             << ClauseName << 0;
16927330f729Sjoerg         break;
16937330f729Sjoerg       }
1694*e038c9c4Sjoerg       if (!IsDeviceTypeClause && !IsToOrLinkClause) {
1695*e038c9c4Sjoerg         Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1696*e038c9c4Sjoerg             << ClauseName << (getLangOpts().OpenMP >= 50 ? 2 : 1);
1697*e038c9c4Sjoerg         break;
1698*e038c9c4Sjoerg       }
1699*e038c9c4Sjoerg 
1700*e038c9c4Sjoerg       if (IsToOrLinkClause)
1701*e038c9c4Sjoerg         HasToOrLinkClause = true;
1702*e038c9c4Sjoerg 
17037330f729Sjoerg       // Parse 'device_type' clause and go to next clause if any.
17047330f729Sjoerg       if (IsDeviceTypeClause) {
17057330f729Sjoerg         Optional<SimpleClauseData> DevTypeData =
17067330f729Sjoerg             parseOpenMPSimpleClause(*this, OMPC_device_type);
17077330f729Sjoerg         if (DevTypeData.hasValue()) {
17087330f729Sjoerg           if (DeviceTypeLoc.isValid()) {
17097330f729Sjoerg             // We already saw another device_type clause, diagnose it.
17107330f729Sjoerg             Diag(DevTypeData.getValue().Loc,
17117330f729Sjoerg                  diag::warn_omp_more_one_device_type_clause);
1712*e038c9c4Sjoerg             break;
17137330f729Sjoerg           }
17147330f729Sjoerg           switch (static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
17157330f729Sjoerg           case OMPC_DEVICE_TYPE_any:
1716*e038c9c4Sjoerg             DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
17177330f729Sjoerg             break;
17187330f729Sjoerg           case OMPC_DEVICE_TYPE_host:
1719*e038c9c4Sjoerg             DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
17207330f729Sjoerg             break;
17217330f729Sjoerg           case OMPC_DEVICE_TYPE_nohost:
1722*e038c9c4Sjoerg             DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
17237330f729Sjoerg             break;
17247330f729Sjoerg           case OMPC_DEVICE_TYPE_unknown:
17257330f729Sjoerg             llvm_unreachable("Unexpected device_type");
17267330f729Sjoerg           }
17277330f729Sjoerg           DeviceTypeLoc = DevTypeData.getValue().Loc;
17287330f729Sjoerg         }
17297330f729Sjoerg         continue;
17307330f729Sjoerg       }
17317330f729Sjoerg       ConsumeToken();
17327330f729Sjoerg     }
1733*e038c9c4Sjoerg 
1734*e038c9c4Sjoerg     if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1735*e038c9c4Sjoerg       auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
1736*e038c9c4Sjoerg                                           DeclarationNameInfo NameInfo) {
1737*e038c9c4Sjoerg         NamedDecl *ND =
1738*e038c9c4Sjoerg             Actions.lookupOpenMPDeclareTargetName(getCurScope(), SS, NameInfo);
1739*e038c9c4Sjoerg         if (!ND)
1740*e038c9c4Sjoerg           return;
1741*e038c9c4Sjoerg         Sema::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
1742*e038c9c4Sjoerg         bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
1743*e038c9c4Sjoerg         if (!FirstMapping)
1744*e038c9c4Sjoerg           Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
1745*e038c9c4Sjoerg               << NameInfo.getName();
17467330f729Sjoerg       };
17477330f729Sjoerg       if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
17487330f729Sjoerg                                    /*AllowScopeSpecifier=*/true))
17497330f729Sjoerg         break;
1750*e038c9c4Sjoerg     }
1751*e038c9c4Sjoerg 
1752*e038c9c4Sjoerg     if (Tok.is(tok::l_paren)) {
1753*e038c9c4Sjoerg       Diag(Tok,
1754*e038c9c4Sjoerg            diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1755*e038c9c4Sjoerg       break;
1756*e038c9c4Sjoerg     }
1757*e038c9c4Sjoerg     if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
1758*e038c9c4Sjoerg       Diag(Tok,
1759*e038c9c4Sjoerg            diag::err_omp_declare_target_unexpected_clause_after_implicit_to);
1760*e038c9c4Sjoerg       break;
1761*e038c9c4Sjoerg     }
17627330f729Sjoerg 
17637330f729Sjoerg     // Consume optional ','.
17647330f729Sjoerg     if (Tok.is(tok::comma))
17657330f729Sjoerg       ConsumeToken();
17667330f729Sjoerg   }
1767*e038c9c4Sjoerg 
1768*e038c9c4Sjoerg   // For declare target require at least 'to' or 'link' to be present.
1769*e038c9c4Sjoerg   if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkClause &&
1770*e038c9c4Sjoerg       !HasToOrLinkClause)
1771*e038c9c4Sjoerg     Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause);
1772*e038c9c4Sjoerg 
17737330f729Sjoerg   SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
17747330f729Sjoerg }
17757330f729Sjoerg 
skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind)1776*e038c9c4Sjoerg void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1777*e038c9c4Sjoerg   // The last seen token is annot_pragma_openmp_end - need to check for
1778*e038c9c4Sjoerg   // extra tokens.
1779*e038c9c4Sjoerg   if (Tok.is(tok::annot_pragma_openmp_end))
1780*e038c9c4Sjoerg     return;
1781*e038c9c4Sjoerg 
1782*e038c9c4Sjoerg   Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1783*e038c9c4Sjoerg       << getOpenMPDirectiveName(DKind);
1784*e038c9c4Sjoerg   while (Tok.isNot(tok::annot_pragma_openmp_end))
1785*e038c9c4Sjoerg     ConsumeAnyToken();
1786*e038c9c4Sjoerg }
1787*e038c9c4Sjoerg 
parseOMPEndDirective(OpenMPDirectiveKind BeginKind,OpenMPDirectiveKind ExpectedKind,OpenMPDirectiveKind FoundKind,SourceLocation BeginLoc,SourceLocation FoundLoc,bool SkipUntilOpenMPEnd)1788*e038c9c4Sjoerg void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1789*e038c9c4Sjoerg                                   OpenMPDirectiveKind ExpectedKind,
1790*e038c9c4Sjoerg                                   OpenMPDirectiveKind FoundKind,
1791*e038c9c4Sjoerg                                   SourceLocation BeginLoc,
1792*e038c9c4Sjoerg                                   SourceLocation FoundLoc,
1793*e038c9c4Sjoerg                                   bool SkipUntilOpenMPEnd) {
1794*e038c9c4Sjoerg   int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1795*e038c9c4Sjoerg 
1796*e038c9c4Sjoerg   if (FoundKind == ExpectedKind) {
1797*e038c9c4Sjoerg     ConsumeAnyToken();
1798*e038c9c4Sjoerg     skipUntilPragmaOpenMPEnd(ExpectedKind);
17997330f729Sjoerg     return;
18007330f729Sjoerg   }
1801*e038c9c4Sjoerg 
1802*e038c9c4Sjoerg   Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1803*e038c9c4Sjoerg       << DiagSelection;
1804*e038c9c4Sjoerg   Diag(BeginLoc, diag::note_matching)
1805*e038c9c4Sjoerg       << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();
1806*e038c9c4Sjoerg   if (SkipUntilOpenMPEnd)
18077330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
18087330f729Sjoerg }
1809*e038c9c4Sjoerg 
ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,OpenMPDirectiveKind EndDKind,SourceLocation DKLoc)1810*e038c9c4Sjoerg void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
1811*e038c9c4Sjoerg                                                OpenMPDirectiveKind EndDKind,
1812*e038c9c4Sjoerg                                                SourceLocation DKLoc) {
1813*e038c9c4Sjoerg   parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
1814*e038c9c4Sjoerg                        Tok.getLocation(),
1815*e038c9c4Sjoerg                        /* SkipUntilOpenMPEnd */ false);
18167330f729Sjoerg   // Skip the last annot_pragma_openmp_end.
1817*e038c9c4Sjoerg   if (Tok.is(tok::annot_pragma_openmp_end))
1818*e038c9c4Sjoerg     ConsumeAnnotationToken();
18197330f729Sjoerg }
18207330f729Sjoerg 
18217330f729Sjoerg /// Parsing of declarative OpenMP directives.
18227330f729Sjoerg ///
18237330f729Sjoerg ///       threadprivate-directive:
18247330f729Sjoerg ///         annot_pragma_openmp 'threadprivate' simple-variable-list
18257330f729Sjoerg ///         annot_pragma_openmp_end
18267330f729Sjoerg ///
18277330f729Sjoerg ///       allocate-directive:
18287330f729Sjoerg ///         annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
18297330f729Sjoerg ///         annot_pragma_openmp_end
18307330f729Sjoerg ///
18317330f729Sjoerg ///       declare-reduction-directive:
18327330f729Sjoerg ///        annot_pragma_openmp 'declare' 'reduction' [...]
18337330f729Sjoerg ///        annot_pragma_openmp_end
18347330f729Sjoerg ///
18357330f729Sjoerg ///       declare-mapper-directive:
18367330f729Sjoerg ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
18377330f729Sjoerg ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
18387330f729Sjoerg ///         annot_pragma_openmp_end
18397330f729Sjoerg ///
18407330f729Sjoerg ///       declare-simd-directive:
18417330f729Sjoerg ///         annot_pragma_openmp 'declare simd' {<clause> [,]}
18427330f729Sjoerg ///         annot_pragma_openmp_end
18437330f729Sjoerg ///         <function declaration/definition>
18447330f729Sjoerg ///
18457330f729Sjoerg ///       requires directive:
18467330f729Sjoerg ///         annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
18477330f729Sjoerg ///         annot_pragma_openmp_end
18487330f729Sjoerg ///
1849*e038c9c4Sjoerg ///       assumes directive:
1850*e038c9c4Sjoerg ///         annot_pragma_openmp 'assumes' <clause> [[[,] <clause>] ... ]
1851*e038c9c4Sjoerg ///         annot_pragma_openmp_end
1852*e038c9c4Sjoerg ///       or
1853*e038c9c4Sjoerg ///         annot_pragma_openmp 'begin assumes' <clause> [[[,] <clause>] ... ]
1854*e038c9c4Sjoerg ///         annot_pragma_openmp 'end assumes'
1855*e038c9c4Sjoerg ///         annot_pragma_openmp_end
1856*e038c9c4Sjoerg ///
ParseOpenMPDeclarativeDirectiveWithExtDecl(AccessSpecifier & AS,ParsedAttributesWithRange & Attrs,bool Delayed,DeclSpec::TST TagType,Decl * Tag)18577330f729Sjoerg Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1858*e038c9c4Sjoerg     AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
18597330f729Sjoerg     DeclSpec::TST TagType, Decl *Tag) {
18607330f729Sjoerg   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1861*e038c9c4Sjoerg   ParsingOpenMPDirectiveRAII DirScope(*this);
18627330f729Sjoerg   ParenBraceBracketBalancer BalancerRAIIObj(*this);
18637330f729Sjoerg 
1864*e038c9c4Sjoerg   SourceLocation Loc;
1865*e038c9c4Sjoerg   OpenMPDirectiveKind DKind;
1866*e038c9c4Sjoerg   if (Delayed) {
1867*e038c9c4Sjoerg     TentativeParsingAction TPA(*this);
1868*e038c9c4Sjoerg     Loc = ConsumeAnnotationToken();
1869*e038c9c4Sjoerg     DKind = parseOpenMPDirectiveKind(*this);
1870*e038c9c4Sjoerg     if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1871*e038c9c4Sjoerg       // Need to delay parsing until completion of the parent class.
1872*e038c9c4Sjoerg       TPA.Revert();
1873*e038c9c4Sjoerg       CachedTokens Toks;
1874*e038c9c4Sjoerg       unsigned Cnt = 1;
1875*e038c9c4Sjoerg       Toks.push_back(Tok);
1876*e038c9c4Sjoerg       while (Cnt && Tok.isNot(tok::eof)) {
1877*e038c9c4Sjoerg         (void)ConsumeAnyToken();
1878*e038c9c4Sjoerg         if (Tok.is(tok::annot_pragma_openmp))
1879*e038c9c4Sjoerg           ++Cnt;
1880*e038c9c4Sjoerg         else if (Tok.is(tok::annot_pragma_openmp_end))
1881*e038c9c4Sjoerg           --Cnt;
1882*e038c9c4Sjoerg         Toks.push_back(Tok);
1883*e038c9c4Sjoerg       }
1884*e038c9c4Sjoerg       // Skip last annot_pragma_openmp_end.
1885*e038c9c4Sjoerg       if (Cnt == 0)
1886*e038c9c4Sjoerg         (void)ConsumeAnyToken();
1887*e038c9c4Sjoerg       auto *LP = new LateParsedPragma(this, AS);
1888*e038c9c4Sjoerg       LP->takeToks(Toks);
1889*e038c9c4Sjoerg       getCurrentClass().LateParsedDeclarations.push_back(LP);
1890*e038c9c4Sjoerg       return nullptr;
1891*e038c9c4Sjoerg     }
1892*e038c9c4Sjoerg     TPA.Commit();
1893*e038c9c4Sjoerg   } else {
1894*e038c9c4Sjoerg     Loc = ConsumeAnnotationToken();
1895*e038c9c4Sjoerg     DKind = parseOpenMPDirectiveKind(*this);
1896*e038c9c4Sjoerg   }
18977330f729Sjoerg 
18987330f729Sjoerg   switch (DKind) {
18997330f729Sjoerg   case OMPD_threadprivate: {
19007330f729Sjoerg     ConsumeToken();
19017330f729Sjoerg     DeclDirectiveListParserHelper Helper(this, DKind);
19027330f729Sjoerg     if (!ParseOpenMPSimpleVarList(DKind, Helper,
19037330f729Sjoerg                                   /*AllowScopeSpecifier=*/true)) {
1904*e038c9c4Sjoerg       skipUntilPragmaOpenMPEnd(DKind);
19057330f729Sjoerg       // Skip the last annot_pragma_openmp_end.
19067330f729Sjoerg       ConsumeAnnotationToken();
19077330f729Sjoerg       return Actions.ActOnOpenMPThreadprivateDirective(Loc,
19087330f729Sjoerg                                                        Helper.getIdentifiers());
19097330f729Sjoerg     }
19107330f729Sjoerg     break;
19117330f729Sjoerg   }
19127330f729Sjoerg   case OMPD_allocate: {
19137330f729Sjoerg     ConsumeToken();
19147330f729Sjoerg     DeclDirectiveListParserHelper Helper(this, DKind);
19157330f729Sjoerg     if (!ParseOpenMPSimpleVarList(DKind, Helper,
19167330f729Sjoerg                                   /*AllowScopeSpecifier=*/true)) {
19177330f729Sjoerg       SmallVector<OMPClause *, 1> Clauses;
19187330f729Sjoerg       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
19197330f729Sjoerg         SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1920*e038c9c4Sjoerg                     llvm::omp::Clause_enumSize + 1>
1921*e038c9c4Sjoerg             FirstClauses(llvm::omp::Clause_enumSize + 1);
19227330f729Sjoerg         while (Tok.isNot(tok::annot_pragma_openmp_end)) {
19237330f729Sjoerg           OpenMPClauseKind CKind =
19247330f729Sjoerg               Tok.isAnnotation() ? OMPC_unknown
19257330f729Sjoerg                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
19267330f729Sjoerg           Actions.StartOpenMPClause(CKind);
1927*e038c9c4Sjoerg           OMPClause *Clause = ParseOpenMPClause(
1928*e038c9c4Sjoerg               OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt());
19297330f729Sjoerg           SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
19307330f729Sjoerg                     StopBeforeMatch);
1931*e038c9c4Sjoerg           FirstClauses[unsigned(CKind)].setInt(true);
19327330f729Sjoerg           if (Clause != nullptr)
19337330f729Sjoerg             Clauses.push_back(Clause);
19347330f729Sjoerg           if (Tok.is(tok::annot_pragma_openmp_end)) {
19357330f729Sjoerg             Actions.EndOpenMPClause();
19367330f729Sjoerg             break;
19377330f729Sjoerg           }
19387330f729Sjoerg           // Skip ',' if any.
19397330f729Sjoerg           if (Tok.is(tok::comma))
19407330f729Sjoerg             ConsumeToken();
19417330f729Sjoerg           Actions.EndOpenMPClause();
19427330f729Sjoerg         }
1943*e038c9c4Sjoerg         skipUntilPragmaOpenMPEnd(DKind);
19447330f729Sjoerg       }
19457330f729Sjoerg       // Skip the last annot_pragma_openmp_end.
19467330f729Sjoerg       ConsumeAnnotationToken();
19477330f729Sjoerg       return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
19487330f729Sjoerg                                                   Clauses);
19497330f729Sjoerg     }
19507330f729Sjoerg     break;
19517330f729Sjoerg   }
19527330f729Sjoerg   case OMPD_requires: {
19537330f729Sjoerg     SourceLocation StartLoc = ConsumeToken();
19547330f729Sjoerg     SmallVector<OMPClause *, 5> Clauses;
1955*e038c9c4Sjoerg     SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1956*e038c9c4Sjoerg                 llvm::omp::Clause_enumSize + 1>
1957*e038c9c4Sjoerg         FirstClauses(llvm::omp::Clause_enumSize + 1);
19587330f729Sjoerg     if (Tok.is(tok::annot_pragma_openmp_end)) {
19597330f729Sjoerg       Diag(Tok, diag::err_omp_expected_clause)
19607330f729Sjoerg           << getOpenMPDirectiveName(OMPD_requires);
19617330f729Sjoerg       break;
19627330f729Sjoerg     }
19637330f729Sjoerg     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
19647330f729Sjoerg       OpenMPClauseKind CKind = Tok.isAnnotation()
19657330f729Sjoerg                                    ? OMPC_unknown
19667330f729Sjoerg                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
19677330f729Sjoerg       Actions.StartOpenMPClause(CKind);
1968*e038c9c4Sjoerg       OMPClause *Clause = ParseOpenMPClause(
1969*e038c9c4Sjoerg           OMPD_requires, CKind, !FirstClauses[unsigned(CKind)].getInt());
19707330f729Sjoerg       SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
19717330f729Sjoerg                 StopBeforeMatch);
1972*e038c9c4Sjoerg       FirstClauses[unsigned(CKind)].setInt(true);
19737330f729Sjoerg       if (Clause != nullptr)
19747330f729Sjoerg         Clauses.push_back(Clause);
19757330f729Sjoerg       if (Tok.is(tok::annot_pragma_openmp_end)) {
19767330f729Sjoerg         Actions.EndOpenMPClause();
19777330f729Sjoerg         break;
19787330f729Sjoerg       }
19797330f729Sjoerg       // Skip ',' if any.
19807330f729Sjoerg       if (Tok.is(tok::comma))
19817330f729Sjoerg         ConsumeToken();
19827330f729Sjoerg       Actions.EndOpenMPClause();
19837330f729Sjoerg     }
19847330f729Sjoerg     // Consume final annot_pragma_openmp_end
1985*e038c9c4Sjoerg     if (Clauses.empty()) {
19867330f729Sjoerg       Diag(Tok, diag::err_omp_expected_clause)
19877330f729Sjoerg           << getOpenMPDirectiveName(OMPD_requires);
19887330f729Sjoerg       ConsumeAnnotationToken();
19897330f729Sjoerg       return nullptr;
19907330f729Sjoerg     }
19917330f729Sjoerg     ConsumeAnnotationToken();
19927330f729Sjoerg     return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
19937330f729Sjoerg   }
1994*e038c9c4Sjoerg   case OMPD_assumes:
1995*e038c9c4Sjoerg   case OMPD_begin_assumes:
1996*e038c9c4Sjoerg     ParseOpenMPAssumesDirective(DKind, ConsumeToken());
1997*e038c9c4Sjoerg     break;
1998*e038c9c4Sjoerg   case OMPD_end_assumes:
1999*e038c9c4Sjoerg     ParseOpenMPEndAssumesDirective(ConsumeToken());
2000*e038c9c4Sjoerg     break;
20017330f729Sjoerg   case OMPD_declare_reduction:
20027330f729Sjoerg     ConsumeToken();
20037330f729Sjoerg     if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2004*e038c9c4Sjoerg       skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
20057330f729Sjoerg       // Skip the last annot_pragma_openmp_end.
20067330f729Sjoerg       ConsumeAnnotationToken();
20077330f729Sjoerg       return Res;
20087330f729Sjoerg     }
20097330f729Sjoerg     break;
20107330f729Sjoerg   case OMPD_declare_mapper: {
20117330f729Sjoerg     ConsumeToken();
20127330f729Sjoerg     if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
20137330f729Sjoerg       // Skip the last annot_pragma_openmp_end.
20147330f729Sjoerg       ConsumeAnnotationToken();
20157330f729Sjoerg       return Res;
20167330f729Sjoerg     }
20177330f729Sjoerg     break;
20187330f729Sjoerg   }
2019*e038c9c4Sjoerg   case OMPD_begin_declare_variant: {
2020*e038c9c4Sjoerg     // The syntax is:
2021*e038c9c4Sjoerg     // { #pragma omp begin declare variant clause }
2022*e038c9c4Sjoerg     // <function-declaration-or-definition-sequence>
2023*e038c9c4Sjoerg     // { #pragma omp end declare variant }
2024*e038c9c4Sjoerg     //
2025*e038c9c4Sjoerg     ConsumeToken();
2026*e038c9c4Sjoerg     OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
2027*e038c9c4Sjoerg     ASTContext &ASTCtx = Actions.getASTContext();
2028*e038c9c4Sjoerg     OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
2029*e038c9c4Sjoerg     if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
2030*e038c9c4Sjoerg       break;
2031*e038c9c4Sjoerg 
2032*e038c9c4Sjoerg     // Skip last tokens.
2033*e038c9c4Sjoerg     skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
2034*e038c9c4Sjoerg 
2035*e038c9c4Sjoerg     ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2036*e038c9c4Sjoerg 
2037*e038c9c4Sjoerg     VariantMatchInfo VMI;
2038*e038c9c4Sjoerg     TI.getAsVariantMatchInfo(ASTCtx, VMI);
2039*e038c9c4Sjoerg 
2040*e038c9c4Sjoerg     std::function<void(StringRef)> DiagUnknownTrait = [this, Loc](
2041*e038c9c4Sjoerg                                                           StringRef ISATrait) {
2042*e038c9c4Sjoerg       // TODO Track the selector locations in a way that is accessible here to
2043*e038c9c4Sjoerg       // improve the diagnostic location.
2044*e038c9c4Sjoerg       Diag(Loc, diag::warn_unknown_begin_declare_variant_isa_trait) << ISATrait;
2045*e038c9c4Sjoerg     };
2046*e038c9c4Sjoerg     TargetOMPContext OMPCtx(ASTCtx, std::move(DiagUnknownTrait),
2047*e038c9c4Sjoerg                             /* CurrentFunctionDecl */ nullptr);
2048*e038c9c4Sjoerg 
2049*e038c9c4Sjoerg     if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) {
2050*e038c9c4Sjoerg       Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI);
2051*e038c9c4Sjoerg       break;
2052*e038c9c4Sjoerg     }
2053*e038c9c4Sjoerg 
2054*e038c9c4Sjoerg     // Elide all the code till the matching end declare variant was found.
2055*e038c9c4Sjoerg     unsigned Nesting = 1;
2056*e038c9c4Sjoerg     SourceLocation DKLoc;
2057*e038c9c4Sjoerg     OpenMPDirectiveKind DK = OMPD_unknown;
2058*e038c9c4Sjoerg     do {
2059*e038c9c4Sjoerg       DKLoc = Tok.getLocation();
2060*e038c9c4Sjoerg       DK = parseOpenMPDirectiveKind(*this);
2061*e038c9c4Sjoerg       if (DK == OMPD_end_declare_variant)
2062*e038c9c4Sjoerg         --Nesting;
2063*e038c9c4Sjoerg       else if (DK == OMPD_begin_declare_variant)
2064*e038c9c4Sjoerg         ++Nesting;
2065*e038c9c4Sjoerg       if (!Nesting || isEofOrEom())
2066*e038c9c4Sjoerg         break;
2067*e038c9c4Sjoerg       ConsumeAnyToken();
2068*e038c9c4Sjoerg     } while (true);
2069*e038c9c4Sjoerg 
2070*e038c9c4Sjoerg     parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
2071*e038c9c4Sjoerg                          DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
2072*e038c9c4Sjoerg     if (isEofOrEom())
2073*e038c9c4Sjoerg       return nullptr;
2074*e038c9c4Sjoerg     break;
2075*e038c9c4Sjoerg   }
2076*e038c9c4Sjoerg   case OMPD_end_declare_variant: {
2077*e038c9c4Sjoerg     if (Actions.isInOpenMPDeclareVariantScope())
2078*e038c9c4Sjoerg       Actions.ActOnOpenMPEndDeclareVariant();
2079*e038c9c4Sjoerg     else
2080*e038c9c4Sjoerg       Diag(Loc, diag::err_expected_begin_declare_variant);
2081*e038c9c4Sjoerg     ConsumeToken();
2082*e038c9c4Sjoerg     break;
2083*e038c9c4Sjoerg   }
20847330f729Sjoerg   case OMPD_declare_variant:
20857330f729Sjoerg   case OMPD_declare_simd: {
20867330f729Sjoerg     // The syntax is:
20877330f729Sjoerg     // { #pragma omp declare {simd|variant} }
20887330f729Sjoerg     // <function-declaration-or-definition>
20897330f729Sjoerg     //
20907330f729Sjoerg     CachedTokens Toks;
20917330f729Sjoerg     Toks.push_back(Tok);
20927330f729Sjoerg     ConsumeToken();
20937330f729Sjoerg     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
20947330f729Sjoerg       Toks.push_back(Tok);
20957330f729Sjoerg       ConsumeAnyToken();
20967330f729Sjoerg     }
20977330f729Sjoerg     Toks.push_back(Tok);
20987330f729Sjoerg     ConsumeAnyToken();
20997330f729Sjoerg 
21007330f729Sjoerg     DeclGroupPtrTy Ptr;
21017330f729Sjoerg     if (Tok.is(tok::annot_pragma_openmp)) {
2102*e038c9c4Sjoerg       Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2103*e038c9c4Sjoerg                                                        TagType, Tag);
21047330f729Sjoerg     } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
21057330f729Sjoerg       // Here we expect to see some function declaration.
21067330f729Sjoerg       if (AS == AS_none) {
21077330f729Sjoerg         assert(TagType == DeclSpec::TST_unspecified);
21087330f729Sjoerg         MaybeParseCXX11Attributes(Attrs);
21097330f729Sjoerg         ParsingDeclSpec PDS(*this);
21107330f729Sjoerg         Ptr = ParseExternalDeclaration(Attrs, &PDS);
21117330f729Sjoerg       } else {
21127330f729Sjoerg         Ptr =
21137330f729Sjoerg             ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
21147330f729Sjoerg       }
21157330f729Sjoerg     }
21167330f729Sjoerg     if (!Ptr) {
21177330f729Sjoerg       Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
21187330f729Sjoerg           << (DKind == OMPD_declare_simd ? 0 : 1);
21197330f729Sjoerg       return DeclGroupPtrTy();
21207330f729Sjoerg     }
21217330f729Sjoerg     if (DKind == OMPD_declare_simd)
21227330f729Sjoerg       return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
21237330f729Sjoerg     assert(DKind == OMPD_declare_variant &&
21247330f729Sjoerg            "Expected declare variant directive only");
21257330f729Sjoerg     ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
21267330f729Sjoerg     return Ptr;
21277330f729Sjoerg   }
2128*e038c9c4Sjoerg   case OMPD_begin_declare_target:
21297330f729Sjoerg   case OMPD_declare_target: {
21307330f729Sjoerg     SourceLocation DTLoc = ConsumeAnyToken();
2131*e038c9c4Sjoerg     bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2132*e038c9c4Sjoerg     bool HasImplicitMappings =
2133*e038c9c4Sjoerg         DKind == OMPD_begin_declare_target || !HasClauses;
2134*e038c9c4Sjoerg     Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2135*e038c9c4Sjoerg     if (HasClauses)
2136*e038c9c4Sjoerg       ParseOMPDeclareTargetClauses(DTCI);
21377330f729Sjoerg 
21387330f729Sjoerg     // Skip the last annot_pragma_openmp_end.
21397330f729Sjoerg     ConsumeAnyToken();
21407330f729Sjoerg 
2141*e038c9c4Sjoerg     if (HasImplicitMappings) {
2142*e038c9c4Sjoerg       Actions.ActOnStartOpenMPDeclareTargetContext(DTCI);
2143*e038c9c4Sjoerg       return nullptr;
2144*e038c9c4Sjoerg     }
21457330f729Sjoerg 
2146*e038c9c4Sjoerg     Actions.ActOnFinishedOpenMPDeclareTargetContext(DTCI);
21477330f729Sjoerg     llvm::SmallVector<Decl *, 4> Decls;
2148*e038c9c4Sjoerg     for (auto &It : DTCI.ExplicitlyMapped)
2149*e038c9c4Sjoerg       Decls.push_back(It.first);
21507330f729Sjoerg     return Actions.BuildDeclaratorGroup(Decls);
21517330f729Sjoerg   }
2152*e038c9c4Sjoerg   case OMPD_end_declare_target: {
2153*e038c9c4Sjoerg     if (!Actions.isInOpenMPDeclareTargetContext()) {
2154*e038c9c4Sjoerg       Diag(Tok, diag::err_omp_unexpected_directive)
2155*e038c9c4Sjoerg           << 1 << getOpenMPDirectiveName(DKind);
2156*e038c9c4Sjoerg       break;
2157*e038c9c4Sjoerg     }
2158*e038c9c4Sjoerg     const Sema::DeclareTargetContextInfo &DTCI =
2159*e038c9c4Sjoerg         Actions.ActOnOpenMPEndDeclareTargetDirective();
2160*e038c9c4Sjoerg     ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2161*e038c9c4Sjoerg     return nullptr;
2162*e038c9c4Sjoerg   }
21637330f729Sjoerg   case OMPD_unknown:
21647330f729Sjoerg     Diag(Tok, diag::err_omp_unknown_directive);
21657330f729Sjoerg     break;
21667330f729Sjoerg   case OMPD_parallel:
21677330f729Sjoerg   case OMPD_simd:
2168*e038c9c4Sjoerg   case OMPD_tile:
21697330f729Sjoerg   case OMPD_task:
21707330f729Sjoerg   case OMPD_taskyield:
21717330f729Sjoerg   case OMPD_barrier:
21727330f729Sjoerg   case OMPD_taskwait:
21737330f729Sjoerg   case OMPD_taskgroup:
21747330f729Sjoerg   case OMPD_flush:
2175*e038c9c4Sjoerg   case OMPD_depobj:
2176*e038c9c4Sjoerg   case OMPD_scan:
21777330f729Sjoerg   case OMPD_for:
21787330f729Sjoerg   case OMPD_for_simd:
21797330f729Sjoerg   case OMPD_sections:
21807330f729Sjoerg   case OMPD_section:
21817330f729Sjoerg   case OMPD_single:
21827330f729Sjoerg   case OMPD_master:
21837330f729Sjoerg   case OMPD_ordered:
21847330f729Sjoerg   case OMPD_critical:
21857330f729Sjoerg   case OMPD_parallel_for:
21867330f729Sjoerg   case OMPD_parallel_for_simd:
21877330f729Sjoerg   case OMPD_parallel_sections:
2188*e038c9c4Sjoerg   case OMPD_parallel_master:
21897330f729Sjoerg   case OMPD_atomic:
21907330f729Sjoerg   case OMPD_target:
21917330f729Sjoerg   case OMPD_teams:
21927330f729Sjoerg   case OMPD_cancellation_point:
21937330f729Sjoerg   case OMPD_cancel:
21947330f729Sjoerg   case OMPD_target_data:
21957330f729Sjoerg   case OMPD_target_enter_data:
21967330f729Sjoerg   case OMPD_target_exit_data:
21977330f729Sjoerg   case OMPD_target_parallel:
21987330f729Sjoerg   case OMPD_target_parallel_for:
21997330f729Sjoerg   case OMPD_taskloop:
22007330f729Sjoerg   case OMPD_taskloop_simd:
22017330f729Sjoerg   case OMPD_master_taskloop:
22027330f729Sjoerg   case OMPD_master_taskloop_simd:
22037330f729Sjoerg   case OMPD_parallel_master_taskloop:
2204*e038c9c4Sjoerg   case OMPD_parallel_master_taskloop_simd:
22057330f729Sjoerg   case OMPD_distribute:
22067330f729Sjoerg   case OMPD_target_update:
22077330f729Sjoerg   case OMPD_distribute_parallel_for:
22087330f729Sjoerg   case OMPD_distribute_parallel_for_simd:
22097330f729Sjoerg   case OMPD_distribute_simd:
22107330f729Sjoerg   case OMPD_target_parallel_for_simd:
22117330f729Sjoerg   case OMPD_target_simd:
22127330f729Sjoerg   case OMPD_teams_distribute:
22137330f729Sjoerg   case OMPD_teams_distribute_simd:
22147330f729Sjoerg   case OMPD_teams_distribute_parallel_for_simd:
22157330f729Sjoerg   case OMPD_teams_distribute_parallel_for:
22167330f729Sjoerg   case OMPD_target_teams:
22177330f729Sjoerg   case OMPD_target_teams_distribute:
22187330f729Sjoerg   case OMPD_target_teams_distribute_parallel_for:
22197330f729Sjoerg   case OMPD_target_teams_distribute_parallel_for_simd:
22207330f729Sjoerg   case OMPD_target_teams_distribute_simd:
2221*e038c9c4Sjoerg   case OMPD_dispatch:
2222*e038c9c4Sjoerg   case OMPD_masked:
22237330f729Sjoerg     Diag(Tok, diag::err_omp_unexpected_directive)
22247330f729Sjoerg         << 1 << getOpenMPDirectiveName(DKind);
22257330f729Sjoerg     break;
2226*e038c9c4Sjoerg   default:
2227*e038c9c4Sjoerg     break;
22287330f729Sjoerg   }
22297330f729Sjoerg   while (Tok.isNot(tok::annot_pragma_openmp_end))
22307330f729Sjoerg     ConsumeAnyToken();
22317330f729Sjoerg   ConsumeAnyToken();
22327330f729Sjoerg   return nullptr;
22337330f729Sjoerg }
22347330f729Sjoerg 
22357330f729Sjoerg /// Parsing of declarative or executable OpenMP directives.
22367330f729Sjoerg ///
22377330f729Sjoerg ///       threadprivate-directive:
22387330f729Sjoerg ///         annot_pragma_openmp 'threadprivate' simple-variable-list
22397330f729Sjoerg ///         annot_pragma_openmp_end
22407330f729Sjoerg ///
22417330f729Sjoerg ///       allocate-directive:
22427330f729Sjoerg ///         annot_pragma_openmp 'allocate' simple-variable-list
22437330f729Sjoerg ///         annot_pragma_openmp_end
22447330f729Sjoerg ///
22457330f729Sjoerg ///       declare-reduction-directive:
22467330f729Sjoerg ///         annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
22477330f729Sjoerg ///         <type> {',' <type>} ':' <expression> ')' ['initializer' '('
22487330f729Sjoerg ///         ('omp_priv' '=' <expression>|<function_call>) ')']
22497330f729Sjoerg ///         annot_pragma_openmp_end
22507330f729Sjoerg ///
22517330f729Sjoerg ///       declare-mapper-directive:
22527330f729Sjoerg ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
22537330f729Sjoerg ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
22547330f729Sjoerg ///         annot_pragma_openmp_end
22557330f729Sjoerg ///
22567330f729Sjoerg ///       executable-directive:
22577330f729Sjoerg ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
22587330f729Sjoerg ///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
2259*e038c9c4Sjoerg ///         'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
2260*e038c9c4Sjoerg ///         'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' |
2261*e038c9c4Sjoerg ///         'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
2262*e038c9c4Sjoerg ///         data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
2263*e038c9c4Sjoerg ///         'master taskloop' | 'master taskloop simd' | 'parallel master
2264*e038c9c4Sjoerg ///         taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
2265*e038c9c4Sjoerg ///         enter data' | 'target exit data' | 'target parallel' | 'target
2266*e038c9c4Sjoerg ///         parallel for' | 'target update' | 'distribute parallel for' |
2267*e038c9c4Sjoerg ///         'distribute paralle for simd' | 'distribute simd' | 'target parallel
2268*e038c9c4Sjoerg ///         for simd' | 'target simd' | 'teams distribute' | 'teams distribute
2269*e038c9c4Sjoerg ///         simd' | 'teams distribute parallel for simd' | 'teams distribute
2270*e038c9c4Sjoerg ///         parallel for' | 'target teams' | 'target teams distribute' | 'target
2271*e038c9c4Sjoerg ///         teams distribute parallel for' | 'target teams distribute parallel
2272*e038c9c4Sjoerg ///         for simd' | 'target teams distribute simd' | 'masked' {clause}
2273*e038c9c4Sjoerg ///         annot_pragma_openmp_end
22747330f729Sjoerg ///
22757330f729Sjoerg StmtResult
ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx)22767330f729Sjoerg Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
22777330f729Sjoerg   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
2278*e038c9c4Sjoerg   ParsingOpenMPDirectiveRAII DirScope(*this);
22797330f729Sjoerg   ParenBraceBracketBalancer BalancerRAIIObj(*this);
22807330f729Sjoerg   SmallVector<OMPClause *, 5> Clauses;
2281*e038c9c4Sjoerg   SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
2282*e038c9c4Sjoerg               llvm::omp::Clause_enumSize + 1>
2283*e038c9c4Sjoerg       FirstClauses(llvm::omp::Clause_enumSize + 1);
22847330f729Sjoerg   unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
22857330f729Sjoerg                         Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
22867330f729Sjoerg   SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
22877330f729Sjoerg   OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
22887330f729Sjoerg   OpenMPDirectiveKind CancelRegion = OMPD_unknown;
22897330f729Sjoerg   // Name of critical directive.
22907330f729Sjoerg   DeclarationNameInfo DirName;
22917330f729Sjoerg   StmtResult Directive = StmtError();
22927330f729Sjoerg   bool HasAssociatedStatement = true;
22937330f729Sjoerg 
22947330f729Sjoerg   switch (DKind) {
22957330f729Sjoerg   case OMPD_threadprivate: {
22967330f729Sjoerg     // FIXME: Should this be permitted in C++?
22977330f729Sjoerg     if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
22987330f729Sjoerg         ParsedStmtContext()) {
22997330f729Sjoerg       Diag(Tok, diag::err_omp_immediate_directive)
23007330f729Sjoerg           << getOpenMPDirectiveName(DKind) << 0;
23017330f729Sjoerg     }
23027330f729Sjoerg     ConsumeToken();
23037330f729Sjoerg     DeclDirectiveListParserHelper Helper(this, DKind);
23047330f729Sjoerg     if (!ParseOpenMPSimpleVarList(DKind, Helper,
23057330f729Sjoerg                                   /*AllowScopeSpecifier=*/false)) {
2306*e038c9c4Sjoerg       skipUntilPragmaOpenMPEnd(DKind);
23077330f729Sjoerg       DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
23087330f729Sjoerg           Loc, Helper.getIdentifiers());
23097330f729Sjoerg       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
23107330f729Sjoerg     }
23117330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end);
23127330f729Sjoerg     break;
23137330f729Sjoerg   }
23147330f729Sjoerg   case OMPD_allocate: {
23157330f729Sjoerg     // FIXME: Should this be permitted in C++?
23167330f729Sjoerg     if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
23177330f729Sjoerg         ParsedStmtContext()) {
23187330f729Sjoerg       Diag(Tok, diag::err_omp_immediate_directive)
23197330f729Sjoerg           << getOpenMPDirectiveName(DKind) << 0;
23207330f729Sjoerg     }
23217330f729Sjoerg     ConsumeToken();
23227330f729Sjoerg     DeclDirectiveListParserHelper Helper(this, DKind);
23237330f729Sjoerg     if (!ParseOpenMPSimpleVarList(DKind, Helper,
23247330f729Sjoerg                                   /*AllowScopeSpecifier=*/false)) {
23257330f729Sjoerg       SmallVector<OMPClause *, 1> Clauses;
23267330f729Sjoerg       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
23277330f729Sjoerg         SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
2328*e038c9c4Sjoerg                     llvm::omp::Clause_enumSize + 1>
2329*e038c9c4Sjoerg             FirstClauses(llvm::omp::Clause_enumSize + 1);
23307330f729Sjoerg         while (Tok.isNot(tok::annot_pragma_openmp_end)) {
23317330f729Sjoerg           OpenMPClauseKind CKind =
23327330f729Sjoerg               Tok.isAnnotation() ? OMPC_unknown
23337330f729Sjoerg                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
23347330f729Sjoerg           Actions.StartOpenMPClause(CKind);
2335*e038c9c4Sjoerg           OMPClause *Clause = ParseOpenMPClause(
2336*e038c9c4Sjoerg               OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt());
23377330f729Sjoerg           SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
23387330f729Sjoerg                     StopBeforeMatch);
2339*e038c9c4Sjoerg           FirstClauses[unsigned(CKind)].setInt(true);
23407330f729Sjoerg           if (Clause != nullptr)
23417330f729Sjoerg             Clauses.push_back(Clause);
23427330f729Sjoerg           if (Tok.is(tok::annot_pragma_openmp_end)) {
23437330f729Sjoerg             Actions.EndOpenMPClause();
23447330f729Sjoerg             break;
23457330f729Sjoerg           }
23467330f729Sjoerg           // Skip ',' if any.
23477330f729Sjoerg           if (Tok.is(tok::comma))
23487330f729Sjoerg             ConsumeToken();
23497330f729Sjoerg           Actions.EndOpenMPClause();
23507330f729Sjoerg         }
2351*e038c9c4Sjoerg         skipUntilPragmaOpenMPEnd(DKind);
23527330f729Sjoerg       }
23537330f729Sjoerg       DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
23547330f729Sjoerg           Loc, Helper.getIdentifiers(), Clauses);
23557330f729Sjoerg       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
23567330f729Sjoerg     }
23577330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end);
23587330f729Sjoerg     break;
23597330f729Sjoerg   }
23607330f729Sjoerg   case OMPD_declare_reduction:
23617330f729Sjoerg     ConsumeToken();
23627330f729Sjoerg     if (DeclGroupPtrTy Res =
23637330f729Sjoerg             ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2364*e038c9c4Sjoerg       skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
23657330f729Sjoerg       ConsumeAnyToken();
23667330f729Sjoerg       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
23677330f729Sjoerg     } else {
23687330f729Sjoerg       SkipUntil(tok::annot_pragma_openmp_end);
23697330f729Sjoerg     }
23707330f729Sjoerg     break;
23717330f729Sjoerg   case OMPD_declare_mapper: {
23727330f729Sjoerg     ConsumeToken();
23737330f729Sjoerg     if (DeclGroupPtrTy Res =
23747330f729Sjoerg             ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
23757330f729Sjoerg       // Skip the last annot_pragma_openmp_end.
23767330f729Sjoerg       ConsumeAnnotationToken();
23777330f729Sjoerg       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
23787330f729Sjoerg     } else {
23797330f729Sjoerg       SkipUntil(tok::annot_pragma_openmp_end);
23807330f729Sjoerg     }
23817330f729Sjoerg     break;
23827330f729Sjoerg   }
23837330f729Sjoerg   case OMPD_flush:
2384*e038c9c4Sjoerg   case OMPD_depobj:
2385*e038c9c4Sjoerg   case OMPD_scan:
23867330f729Sjoerg   case OMPD_taskyield:
23877330f729Sjoerg   case OMPD_barrier:
23887330f729Sjoerg   case OMPD_taskwait:
23897330f729Sjoerg   case OMPD_cancellation_point:
23907330f729Sjoerg   case OMPD_cancel:
23917330f729Sjoerg   case OMPD_target_enter_data:
23927330f729Sjoerg   case OMPD_target_exit_data:
23937330f729Sjoerg   case OMPD_target_update:
2394*e038c9c4Sjoerg   case OMPD_interop:
23957330f729Sjoerg     if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
23967330f729Sjoerg         ParsedStmtContext()) {
23977330f729Sjoerg       Diag(Tok, diag::err_omp_immediate_directive)
23987330f729Sjoerg           << getOpenMPDirectiveName(DKind) << 0;
23997330f729Sjoerg     }
24007330f729Sjoerg     HasAssociatedStatement = false;
24017330f729Sjoerg     // Fall through for further analysis.
24027330f729Sjoerg     LLVM_FALLTHROUGH;
24037330f729Sjoerg   case OMPD_parallel:
24047330f729Sjoerg   case OMPD_simd:
2405*e038c9c4Sjoerg   case OMPD_tile:
24067330f729Sjoerg   case OMPD_for:
24077330f729Sjoerg   case OMPD_for_simd:
24087330f729Sjoerg   case OMPD_sections:
24097330f729Sjoerg   case OMPD_single:
24107330f729Sjoerg   case OMPD_section:
24117330f729Sjoerg   case OMPD_master:
24127330f729Sjoerg   case OMPD_critical:
24137330f729Sjoerg   case OMPD_parallel_for:
24147330f729Sjoerg   case OMPD_parallel_for_simd:
24157330f729Sjoerg   case OMPD_parallel_sections:
2416*e038c9c4Sjoerg   case OMPD_parallel_master:
24177330f729Sjoerg   case OMPD_task:
24187330f729Sjoerg   case OMPD_ordered:
24197330f729Sjoerg   case OMPD_atomic:
24207330f729Sjoerg   case OMPD_target:
24217330f729Sjoerg   case OMPD_teams:
24227330f729Sjoerg   case OMPD_taskgroup:
24237330f729Sjoerg   case OMPD_target_data:
24247330f729Sjoerg   case OMPD_target_parallel:
24257330f729Sjoerg   case OMPD_target_parallel_for:
24267330f729Sjoerg   case OMPD_taskloop:
24277330f729Sjoerg   case OMPD_taskloop_simd:
24287330f729Sjoerg   case OMPD_master_taskloop:
24297330f729Sjoerg   case OMPD_master_taskloop_simd:
24307330f729Sjoerg   case OMPD_parallel_master_taskloop:
2431*e038c9c4Sjoerg   case OMPD_parallel_master_taskloop_simd:
24327330f729Sjoerg   case OMPD_distribute:
24337330f729Sjoerg   case OMPD_distribute_parallel_for:
24347330f729Sjoerg   case OMPD_distribute_parallel_for_simd:
24357330f729Sjoerg   case OMPD_distribute_simd:
24367330f729Sjoerg   case OMPD_target_parallel_for_simd:
24377330f729Sjoerg   case OMPD_target_simd:
24387330f729Sjoerg   case OMPD_teams_distribute:
24397330f729Sjoerg   case OMPD_teams_distribute_simd:
24407330f729Sjoerg   case OMPD_teams_distribute_parallel_for_simd:
24417330f729Sjoerg   case OMPD_teams_distribute_parallel_for:
24427330f729Sjoerg   case OMPD_target_teams:
24437330f729Sjoerg   case OMPD_target_teams_distribute:
24447330f729Sjoerg   case OMPD_target_teams_distribute_parallel_for:
24457330f729Sjoerg   case OMPD_target_teams_distribute_parallel_for_simd:
2446*e038c9c4Sjoerg   case OMPD_target_teams_distribute_simd:
2447*e038c9c4Sjoerg   case OMPD_dispatch:
2448*e038c9c4Sjoerg   case OMPD_masked: {
2449*e038c9c4Sjoerg     // Special processing for flush and depobj clauses.
2450*e038c9c4Sjoerg     Token ImplicitTok;
2451*e038c9c4Sjoerg     bool ImplicitClauseAllowed = false;
2452*e038c9c4Sjoerg     if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2453*e038c9c4Sjoerg       ImplicitTok = Tok;
2454*e038c9c4Sjoerg       ImplicitClauseAllowed = true;
2455*e038c9c4Sjoerg     }
24567330f729Sjoerg     ConsumeToken();
24577330f729Sjoerg     // Parse directive name of the 'critical' directive if any.
24587330f729Sjoerg     if (DKind == OMPD_critical) {
24597330f729Sjoerg       BalancedDelimiterTracker T(*this, tok::l_paren,
24607330f729Sjoerg                                  tok::annot_pragma_openmp_end);
24617330f729Sjoerg       if (!T.consumeOpen()) {
24627330f729Sjoerg         if (Tok.isAnyIdentifier()) {
24637330f729Sjoerg           DirName =
24647330f729Sjoerg               DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
24657330f729Sjoerg           ConsumeAnyToken();
24667330f729Sjoerg         } else {
24677330f729Sjoerg           Diag(Tok, diag::err_omp_expected_identifier_for_critical);
24687330f729Sjoerg         }
24697330f729Sjoerg         T.consumeClose();
24707330f729Sjoerg       }
24717330f729Sjoerg     } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
24727330f729Sjoerg       CancelRegion = parseOpenMPDirectiveKind(*this);
24737330f729Sjoerg       if (Tok.isNot(tok::annot_pragma_openmp_end))
24747330f729Sjoerg         ConsumeToken();
24757330f729Sjoerg     }
24767330f729Sjoerg 
24777330f729Sjoerg     if (isOpenMPLoopDirective(DKind))
24787330f729Sjoerg       ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
24797330f729Sjoerg     if (isOpenMPSimdDirective(DKind))
24807330f729Sjoerg       ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
24817330f729Sjoerg     ParseScope OMPDirectiveScope(this, ScopeFlags);
24827330f729Sjoerg     Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
24837330f729Sjoerg 
24847330f729Sjoerg     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2485*e038c9c4Sjoerg       bool HasImplicitClause = false;
2486*e038c9c4Sjoerg       if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2487*e038c9c4Sjoerg         HasImplicitClause = true;
2488*e038c9c4Sjoerg         // Push copy of the current token back to stream to properly parse
2489*e038c9c4Sjoerg         // pseudo-clause OMPFlushClause or OMPDepobjClause.
2490*e038c9c4Sjoerg         PP.EnterToken(Tok, /*IsReinject*/ true);
2491*e038c9c4Sjoerg         PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2492*e038c9c4Sjoerg         ConsumeAnyToken();
2493*e038c9c4Sjoerg       }
2494*e038c9c4Sjoerg       OpenMPClauseKind CKind = Tok.isAnnotation()
24957330f729Sjoerg                                    ? OMPC_unknown
24967330f729Sjoerg                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
2497*e038c9c4Sjoerg       if (HasImplicitClause) {
2498*e038c9c4Sjoerg         assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2499*e038c9c4Sjoerg         if (DKind == OMPD_flush) {
2500*e038c9c4Sjoerg           CKind = OMPC_flush;
2501*e038c9c4Sjoerg         } else {
2502*e038c9c4Sjoerg           assert(DKind == OMPD_depobj &&
2503*e038c9c4Sjoerg                  "Expected flush or depobj directives.");
2504*e038c9c4Sjoerg           CKind = OMPC_depobj;
2505*e038c9c4Sjoerg         }
2506*e038c9c4Sjoerg       }
2507*e038c9c4Sjoerg       // No more implicit clauses allowed.
2508*e038c9c4Sjoerg       ImplicitClauseAllowed = false;
25097330f729Sjoerg       Actions.StartOpenMPClause(CKind);
2510*e038c9c4Sjoerg       HasImplicitClause = false;
2511*e038c9c4Sjoerg       OMPClause *Clause = ParseOpenMPClause(
2512*e038c9c4Sjoerg           DKind, CKind, !FirstClauses[unsigned(CKind)].getInt());
2513*e038c9c4Sjoerg       FirstClauses[unsigned(CKind)].setInt(true);
25147330f729Sjoerg       if (Clause) {
2515*e038c9c4Sjoerg         FirstClauses[unsigned(CKind)].setPointer(Clause);
25167330f729Sjoerg         Clauses.push_back(Clause);
25177330f729Sjoerg       }
25187330f729Sjoerg 
25197330f729Sjoerg       // Skip ',' if any.
25207330f729Sjoerg       if (Tok.is(tok::comma))
25217330f729Sjoerg         ConsumeToken();
25227330f729Sjoerg       Actions.EndOpenMPClause();
25237330f729Sjoerg     }
25247330f729Sjoerg     // End location of the directive.
25257330f729Sjoerg     EndLoc = Tok.getLocation();
25267330f729Sjoerg     // Consume final annot_pragma_openmp_end.
25277330f729Sjoerg     ConsumeAnnotationToken();
25287330f729Sjoerg 
25297330f729Sjoerg     // OpenMP [2.13.8, ordered Construct, Syntax]
25307330f729Sjoerg     // If the depend clause is specified, the ordered construct is a stand-alone
25317330f729Sjoerg     // directive.
2532*e038c9c4Sjoerg     if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) {
25337330f729Sjoerg       if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
25347330f729Sjoerg           ParsedStmtContext()) {
25357330f729Sjoerg         Diag(Loc, diag::err_omp_immediate_directive)
25367330f729Sjoerg             << getOpenMPDirectiveName(DKind) << 1
25377330f729Sjoerg             << getOpenMPClauseName(OMPC_depend);
25387330f729Sjoerg       }
25397330f729Sjoerg       HasAssociatedStatement = false;
25407330f729Sjoerg     }
25417330f729Sjoerg 
2542*e038c9c4Sjoerg     if (DKind == OMPD_tile && !FirstClauses[unsigned(OMPC_sizes)].getInt()) {
2543*e038c9c4Sjoerg       Diag(Loc, diag::err_omp_required_clause)
2544*e038c9c4Sjoerg           << getOpenMPDirectiveName(OMPD_tile) << "sizes";
2545*e038c9c4Sjoerg     }
2546*e038c9c4Sjoerg 
25477330f729Sjoerg     StmtResult AssociatedStmt;
25487330f729Sjoerg     if (HasAssociatedStatement) {
25497330f729Sjoerg       // The body is a block scope like in Lambdas and Blocks.
25507330f729Sjoerg       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
25517330f729Sjoerg       // FIXME: We create a bogus CompoundStmt scope to hold the contents of
25527330f729Sjoerg       // the captured region. Code elsewhere assumes that any FunctionScopeInfo
25537330f729Sjoerg       // should have at least one compound statement scope within it.
2554*e038c9c4Sjoerg       ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2555*e038c9c4Sjoerg       {
2556*e038c9c4Sjoerg         Sema::CompoundScopeRAII Scope(Actions);
2557*e038c9c4Sjoerg         AssociatedStmt = ParseStatement();
2558*e038c9c4Sjoerg 
2559*e038c9c4Sjoerg         if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2560*e038c9c4Sjoerg             getLangOpts().OpenMPIRBuilder)
2561*e038c9c4Sjoerg           AssociatedStmt =
2562*e038c9c4Sjoerg               Actions.ActOnOpenMPCanonicalLoop(AssociatedStmt.get());
2563*e038c9c4Sjoerg       }
25647330f729Sjoerg       AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
25657330f729Sjoerg     } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
25667330f729Sjoerg                DKind == OMPD_target_exit_data) {
25677330f729Sjoerg       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
25687330f729Sjoerg       AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
25697330f729Sjoerg                         Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
25707330f729Sjoerg                                                   /*isStmtExpr=*/false));
25717330f729Sjoerg       AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
25727330f729Sjoerg     }
25737330f729Sjoerg     Directive = Actions.ActOnOpenMPExecutableDirective(
25747330f729Sjoerg         DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
25757330f729Sjoerg         EndLoc);
25767330f729Sjoerg 
25777330f729Sjoerg     // Exit scope.
25787330f729Sjoerg     Actions.EndOpenMPDSABlock(Directive.get());
25797330f729Sjoerg     OMPDirectiveScope.Exit();
25807330f729Sjoerg     break;
25817330f729Sjoerg   }
25827330f729Sjoerg   case OMPD_declare_simd:
25837330f729Sjoerg   case OMPD_declare_target:
2584*e038c9c4Sjoerg   case OMPD_begin_declare_target:
25857330f729Sjoerg   case OMPD_end_declare_target:
25867330f729Sjoerg   case OMPD_requires:
2587*e038c9c4Sjoerg   case OMPD_begin_declare_variant:
2588*e038c9c4Sjoerg   case OMPD_end_declare_variant:
25897330f729Sjoerg   case OMPD_declare_variant:
25907330f729Sjoerg     Diag(Tok, diag::err_omp_unexpected_directive)
25917330f729Sjoerg         << 1 << getOpenMPDirectiveName(DKind);
25927330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end);
25937330f729Sjoerg     break;
25947330f729Sjoerg   case OMPD_unknown:
2595*e038c9c4Sjoerg   default:
25967330f729Sjoerg     Diag(Tok, diag::err_omp_unknown_directive);
25977330f729Sjoerg     SkipUntil(tok::annot_pragma_openmp_end);
25987330f729Sjoerg     break;
25997330f729Sjoerg   }
26007330f729Sjoerg   return Directive;
26017330f729Sjoerg }
26027330f729Sjoerg 
26037330f729Sjoerg // Parses simple list:
26047330f729Sjoerg //   simple-variable-list:
26057330f729Sjoerg //         '(' id-expression {, id-expression} ')'
26067330f729Sjoerg //
ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,const llvm::function_ref<void (CXXScopeSpec &,DeclarationNameInfo)> & Callback,bool AllowScopeSpecifier)26077330f729Sjoerg bool Parser::ParseOpenMPSimpleVarList(
26087330f729Sjoerg     OpenMPDirectiveKind Kind,
2609*e038c9c4Sjoerg     const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
2610*e038c9c4Sjoerg         &Callback,
26117330f729Sjoerg     bool AllowScopeSpecifier) {
26127330f729Sjoerg   // Parse '('.
26137330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
26147330f729Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after,
2615*e038c9c4Sjoerg                          getOpenMPDirectiveName(Kind).data()))
26167330f729Sjoerg     return true;
26177330f729Sjoerg   bool IsCorrect = true;
26187330f729Sjoerg   bool NoIdentIsFound = true;
26197330f729Sjoerg 
26207330f729Sjoerg   // Read tokens while ')' or annot_pragma_openmp_end is not found.
26217330f729Sjoerg   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
26227330f729Sjoerg     CXXScopeSpec SS;
26237330f729Sjoerg     UnqualifiedId Name;
26247330f729Sjoerg     // Read var name.
26257330f729Sjoerg     Token PrevTok = Tok;
26267330f729Sjoerg     NoIdentIsFound = false;
26277330f729Sjoerg 
26287330f729Sjoerg     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2629*e038c9c4Sjoerg         ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
2630*e038c9c4Sjoerg                                        /*ObjectHadErrors=*/false, false)) {
26317330f729Sjoerg       IsCorrect = false;
26327330f729Sjoerg       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
26337330f729Sjoerg                 StopBeforeMatch);
2634*e038c9c4Sjoerg     } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
2635*e038c9c4Sjoerg                                   /*ObjectHadErrors=*/false, false, false,
2636*e038c9c4Sjoerg                                   false, false, nullptr, Name)) {
26377330f729Sjoerg       IsCorrect = false;
26387330f729Sjoerg       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
26397330f729Sjoerg                 StopBeforeMatch);
26407330f729Sjoerg     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
26417330f729Sjoerg                Tok.isNot(tok::annot_pragma_openmp_end)) {
26427330f729Sjoerg       IsCorrect = false;
26437330f729Sjoerg       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
26447330f729Sjoerg                 StopBeforeMatch);
26457330f729Sjoerg       Diag(PrevTok.getLocation(), diag::err_expected)
26467330f729Sjoerg           << tok::identifier
26477330f729Sjoerg           << SourceRange(PrevTok.getLocation(), PrevTokLocation);
26487330f729Sjoerg     } else {
26497330f729Sjoerg       Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
26507330f729Sjoerg     }
26517330f729Sjoerg     // Consume ','.
26527330f729Sjoerg     if (Tok.is(tok::comma)) {
26537330f729Sjoerg       ConsumeToken();
26547330f729Sjoerg     }
26557330f729Sjoerg   }
26567330f729Sjoerg 
26577330f729Sjoerg   if (NoIdentIsFound) {
26587330f729Sjoerg     Diag(Tok, diag::err_expected) << tok::identifier;
26597330f729Sjoerg     IsCorrect = false;
26607330f729Sjoerg   }
26617330f729Sjoerg 
26627330f729Sjoerg   // Parse ')'.
26637330f729Sjoerg   IsCorrect = !T.consumeClose() && IsCorrect;
26647330f729Sjoerg 
26657330f729Sjoerg   return !IsCorrect;
26667330f729Sjoerg }
26677330f729Sjoerg 
ParseOpenMPSizesClause()2668*e038c9c4Sjoerg OMPClause *Parser::ParseOpenMPSizesClause() {
2669*e038c9c4Sjoerg   SourceLocation ClauseNameLoc = ConsumeToken();
2670*e038c9c4Sjoerg   SmallVector<Expr *, 4> ValExprs;
2671*e038c9c4Sjoerg 
2672*e038c9c4Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2673*e038c9c4Sjoerg   if (T.consumeOpen()) {
2674*e038c9c4Sjoerg     Diag(Tok, diag::err_expected) << tok::l_paren;
2675*e038c9c4Sjoerg     return nullptr;
2676*e038c9c4Sjoerg   }
2677*e038c9c4Sjoerg 
2678*e038c9c4Sjoerg   while (true) {
2679*e038c9c4Sjoerg     ExprResult Val = ParseConstantExpression();
2680*e038c9c4Sjoerg     if (!Val.isUsable()) {
2681*e038c9c4Sjoerg       T.skipToEnd();
2682*e038c9c4Sjoerg       return nullptr;
2683*e038c9c4Sjoerg     }
2684*e038c9c4Sjoerg 
2685*e038c9c4Sjoerg     ValExprs.push_back(Val.get());
2686*e038c9c4Sjoerg 
2687*e038c9c4Sjoerg     if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
2688*e038c9c4Sjoerg       break;
2689*e038c9c4Sjoerg 
2690*e038c9c4Sjoerg     ExpectAndConsume(tok::comma);
2691*e038c9c4Sjoerg   }
2692*e038c9c4Sjoerg 
2693*e038c9c4Sjoerg   T.consumeClose();
2694*e038c9c4Sjoerg 
2695*e038c9c4Sjoerg   return Actions.ActOnOpenMPSizesClause(
2696*e038c9c4Sjoerg       ValExprs, ClauseNameLoc, T.getOpenLocation(), T.getCloseLocation());
2697*e038c9c4Sjoerg }
2698*e038c9c4Sjoerg 
ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind)2699*e038c9c4Sjoerg OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
2700*e038c9c4Sjoerg   SourceLocation Loc = Tok.getLocation();
2701*e038c9c4Sjoerg   ConsumeAnyToken();
2702*e038c9c4Sjoerg 
2703*e038c9c4Sjoerg   // Parse '('.
2704*e038c9c4Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2705*e038c9c4Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
2706*e038c9c4Sjoerg     return nullptr;
2707*e038c9c4Sjoerg   SmallVector<Sema::UsesAllocatorsData, 4> Data;
2708*e038c9c4Sjoerg   do {
2709*e038c9c4Sjoerg     ExprResult Allocator = ParseCXXIdExpression();
2710*e038c9c4Sjoerg     if (Allocator.isInvalid()) {
2711*e038c9c4Sjoerg       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2712*e038c9c4Sjoerg                 StopBeforeMatch);
2713*e038c9c4Sjoerg       break;
2714*e038c9c4Sjoerg     }
2715*e038c9c4Sjoerg     Sema::UsesAllocatorsData &D = Data.emplace_back();
2716*e038c9c4Sjoerg     D.Allocator = Allocator.get();
2717*e038c9c4Sjoerg     if (Tok.is(tok::l_paren)) {
2718*e038c9c4Sjoerg       BalancedDelimiterTracker T(*this, tok::l_paren,
2719*e038c9c4Sjoerg                                  tok::annot_pragma_openmp_end);
2720*e038c9c4Sjoerg       T.consumeOpen();
2721*e038c9c4Sjoerg       ExprResult AllocatorTraits = ParseCXXIdExpression();
2722*e038c9c4Sjoerg       T.consumeClose();
2723*e038c9c4Sjoerg       if (AllocatorTraits.isInvalid()) {
2724*e038c9c4Sjoerg         SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2725*e038c9c4Sjoerg                   StopBeforeMatch);
2726*e038c9c4Sjoerg         break;
2727*e038c9c4Sjoerg       }
2728*e038c9c4Sjoerg       D.AllocatorTraits = AllocatorTraits.get();
2729*e038c9c4Sjoerg       D.LParenLoc = T.getOpenLocation();
2730*e038c9c4Sjoerg       D.RParenLoc = T.getCloseLocation();
2731*e038c9c4Sjoerg     }
2732*e038c9c4Sjoerg     if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
2733*e038c9c4Sjoerg       Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
2734*e038c9c4Sjoerg     // Parse ','
2735*e038c9c4Sjoerg     if (Tok.is(tok::comma))
2736*e038c9c4Sjoerg       ConsumeAnyToken();
2737*e038c9c4Sjoerg   } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
2738*e038c9c4Sjoerg   T.consumeClose();
2739*e038c9c4Sjoerg   return Actions.ActOnOpenMPUsesAllocatorClause(Loc, T.getOpenLocation(),
2740*e038c9c4Sjoerg                                                 T.getCloseLocation(), Data);
2741*e038c9c4Sjoerg }
2742*e038c9c4Sjoerg 
27437330f729Sjoerg /// Parsing of OpenMP clauses.
27447330f729Sjoerg ///
27457330f729Sjoerg ///    clause:
27467330f729Sjoerg ///       if-clause | final-clause | num_threads-clause | safelen-clause |
27477330f729Sjoerg ///       default-clause | private-clause | firstprivate-clause | shared-clause
27487330f729Sjoerg ///       | linear-clause | aligned-clause | collapse-clause |
27497330f729Sjoerg ///       lastprivate-clause | reduction-clause | proc_bind-clause |
27507330f729Sjoerg ///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
27517330f729Sjoerg ///       mergeable-clause | flush-clause | read-clause | write-clause |
27527330f729Sjoerg ///       update-clause | capture-clause | seq_cst-clause | device-clause |
27537330f729Sjoerg ///       simdlen-clause | threads-clause | simd-clause | num_teams-clause |
27547330f729Sjoerg ///       thread_limit-clause | priority-clause | grainsize-clause |
27557330f729Sjoerg ///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
27567330f729Sjoerg ///       from-clause | is_device_ptr-clause | task_reduction-clause |
2757*e038c9c4Sjoerg ///       in_reduction-clause | allocator-clause | allocate-clause |
2758*e038c9c4Sjoerg ///       acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
2759*e038c9c4Sjoerg ///       depobj-clause | destroy-clause | detach-clause | inclusive-clause |
2760*e038c9c4Sjoerg ///       exclusive-clause | uses_allocators-clause | use_device_addr-clause
27617330f729Sjoerg ///
ParseOpenMPClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,bool FirstClause)27627330f729Sjoerg OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
27637330f729Sjoerg                                      OpenMPClauseKind CKind, bool FirstClause) {
2764*e038c9c4Sjoerg   OMPClauseKind = CKind;
27657330f729Sjoerg   OMPClause *Clause = nullptr;
27667330f729Sjoerg   bool ErrorFound = false;
27677330f729Sjoerg   bool WrongDirective = false;
27687330f729Sjoerg   // Check if clause is allowed for the given directive.
2769*e038c9c4Sjoerg   if (CKind != OMPC_unknown &&
2770*e038c9c4Sjoerg       !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
2771*e038c9c4Sjoerg     Diag(Tok, diag::err_omp_unexpected_clause)
2772*e038c9c4Sjoerg         << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
27737330f729Sjoerg     ErrorFound = true;
27747330f729Sjoerg     WrongDirective = true;
27757330f729Sjoerg   }
27767330f729Sjoerg 
27777330f729Sjoerg   switch (CKind) {
27787330f729Sjoerg   case OMPC_final:
27797330f729Sjoerg   case OMPC_num_threads:
27807330f729Sjoerg   case OMPC_safelen:
27817330f729Sjoerg   case OMPC_simdlen:
27827330f729Sjoerg   case OMPC_collapse:
27837330f729Sjoerg   case OMPC_ordered:
27847330f729Sjoerg   case OMPC_num_teams:
27857330f729Sjoerg   case OMPC_thread_limit:
27867330f729Sjoerg   case OMPC_priority:
27877330f729Sjoerg   case OMPC_grainsize:
27887330f729Sjoerg   case OMPC_num_tasks:
27897330f729Sjoerg   case OMPC_hint:
27907330f729Sjoerg   case OMPC_allocator:
2791*e038c9c4Sjoerg   case OMPC_depobj:
2792*e038c9c4Sjoerg   case OMPC_detach:
2793*e038c9c4Sjoerg   case OMPC_novariants:
2794*e038c9c4Sjoerg   case OMPC_nocontext:
2795*e038c9c4Sjoerg   case OMPC_filter:
27967330f729Sjoerg     // OpenMP [2.5, Restrictions]
27977330f729Sjoerg     //  At most one num_threads clause can appear on the directive.
27987330f729Sjoerg     // OpenMP [2.8.1, simd construct, Restrictions]
27997330f729Sjoerg     //  Only one safelen  clause can appear on a simd directive.
28007330f729Sjoerg     //  Only one simdlen  clause can appear on a simd directive.
28017330f729Sjoerg     //  Only one collapse clause can appear on a simd directive.
28027330f729Sjoerg     // OpenMP [2.11.1, task Construct, Restrictions]
28037330f729Sjoerg     //  At most one if clause can appear on the directive.
28047330f729Sjoerg     //  At most one final clause can appear on the directive.
28057330f729Sjoerg     // OpenMP [teams Construct, Restrictions]
28067330f729Sjoerg     //  At most one num_teams clause can appear on the directive.
28077330f729Sjoerg     //  At most one thread_limit clause can appear on the directive.
28087330f729Sjoerg     // OpenMP [2.9.1, task Construct, Restrictions]
28097330f729Sjoerg     // At most one priority clause can appear on the directive.
28107330f729Sjoerg     // OpenMP [2.9.2, taskloop Construct, Restrictions]
28117330f729Sjoerg     // At most one grainsize clause can appear on the directive.
28127330f729Sjoerg     // OpenMP [2.9.2, taskloop Construct, Restrictions]
28137330f729Sjoerg     // At most one num_tasks clause can appear on the directive.
28147330f729Sjoerg     // OpenMP [2.11.3, allocate Directive, Restrictions]
28157330f729Sjoerg     // At most one allocator clause can appear on the directive.
2816*e038c9c4Sjoerg     // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
2817*e038c9c4Sjoerg     // At most one detach clause can appear on the directive.
2818*e038c9c4Sjoerg     // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
2819*e038c9c4Sjoerg     // At most one novariants clause can appear on a dispatch directive.
2820*e038c9c4Sjoerg     // At most one nocontext clause can appear on a dispatch directive.
28217330f729Sjoerg     if (!FirstClause) {
28227330f729Sjoerg       Diag(Tok, diag::err_omp_more_one_clause)
28237330f729Sjoerg           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
28247330f729Sjoerg       ErrorFound = true;
28257330f729Sjoerg     }
28267330f729Sjoerg 
28277330f729Sjoerg     if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
28287330f729Sjoerg       Clause = ParseOpenMPClause(CKind, WrongDirective);
28297330f729Sjoerg     else
28307330f729Sjoerg       Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
28317330f729Sjoerg     break;
28327330f729Sjoerg   case OMPC_default:
28337330f729Sjoerg   case OMPC_proc_bind:
28347330f729Sjoerg   case OMPC_atomic_default_mem_order:
2835*e038c9c4Sjoerg   case OMPC_order:
28367330f729Sjoerg     // OpenMP [2.14.3.1, Restrictions]
28377330f729Sjoerg     //  Only a single default clause may be specified on a parallel, task or
28387330f729Sjoerg     //  teams directive.
28397330f729Sjoerg     // OpenMP [2.5, parallel Construct, Restrictions]
28407330f729Sjoerg     //  At most one proc_bind clause can appear on the directive.
28417330f729Sjoerg     // OpenMP [5.0, Requires directive, Restrictions]
28427330f729Sjoerg     //  At most one atomic_default_mem_order clause can appear
28437330f729Sjoerg     //  on the directive
2844*e038c9c4Sjoerg     if (!FirstClause && CKind != OMPC_order) {
28457330f729Sjoerg       Diag(Tok, diag::err_omp_more_one_clause)
28467330f729Sjoerg           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
28477330f729Sjoerg       ErrorFound = true;
28487330f729Sjoerg     }
28497330f729Sjoerg 
28507330f729Sjoerg     Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
28517330f729Sjoerg     break;
2852*e038c9c4Sjoerg   case OMPC_device:
28537330f729Sjoerg   case OMPC_schedule:
28547330f729Sjoerg   case OMPC_dist_schedule:
28557330f729Sjoerg   case OMPC_defaultmap:
28567330f729Sjoerg     // OpenMP [2.7.1, Restrictions, p. 3]
28577330f729Sjoerg     //  Only one schedule clause can appear on a loop directive.
2858*e038c9c4Sjoerg     // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
28597330f729Sjoerg     //  At most one defaultmap clause can appear on the directive.
2860*e038c9c4Sjoerg     // OpenMP 5.0 [2.12.5, target construct, Restrictions]
2861*e038c9c4Sjoerg     //  At most one device clause can appear on the directive.
2862*e038c9c4Sjoerg     if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
2863*e038c9c4Sjoerg         !FirstClause) {
28647330f729Sjoerg       Diag(Tok, diag::err_omp_more_one_clause)
28657330f729Sjoerg           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
28667330f729Sjoerg       ErrorFound = true;
28677330f729Sjoerg     }
28687330f729Sjoerg     LLVM_FALLTHROUGH;
28697330f729Sjoerg   case OMPC_if:
2870*e038c9c4Sjoerg     Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
28717330f729Sjoerg     break;
28727330f729Sjoerg   case OMPC_nowait:
28737330f729Sjoerg   case OMPC_untied:
28747330f729Sjoerg   case OMPC_mergeable:
28757330f729Sjoerg   case OMPC_read:
28767330f729Sjoerg   case OMPC_write:
28777330f729Sjoerg   case OMPC_capture:
28787330f729Sjoerg   case OMPC_seq_cst:
2879*e038c9c4Sjoerg   case OMPC_acq_rel:
2880*e038c9c4Sjoerg   case OMPC_acquire:
2881*e038c9c4Sjoerg   case OMPC_release:
2882*e038c9c4Sjoerg   case OMPC_relaxed:
28837330f729Sjoerg   case OMPC_threads:
28847330f729Sjoerg   case OMPC_simd:
28857330f729Sjoerg   case OMPC_nogroup:
28867330f729Sjoerg   case OMPC_unified_address:
28877330f729Sjoerg   case OMPC_unified_shared_memory:
28887330f729Sjoerg   case OMPC_reverse_offload:
28897330f729Sjoerg   case OMPC_dynamic_allocators:
28907330f729Sjoerg     // OpenMP [2.7.1, Restrictions, p. 9]
28917330f729Sjoerg     //  Only one ordered clause can appear on a loop directive.
28927330f729Sjoerg     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
28937330f729Sjoerg     //  Only one nowait clause can appear on a for directive.
28947330f729Sjoerg     // OpenMP [5.0, Requires directive, Restrictions]
28957330f729Sjoerg     //   Each of the requires clauses can appear at most once on the directive.
28967330f729Sjoerg     if (!FirstClause) {
28977330f729Sjoerg       Diag(Tok, diag::err_omp_more_one_clause)
28987330f729Sjoerg           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
28997330f729Sjoerg       ErrorFound = true;
29007330f729Sjoerg     }
29017330f729Sjoerg 
29027330f729Sjoerg     Clause = ParseOpenMPClause(CKind, WrongDirective);
29037330f729Sjoerg     break;
2904*e038c9c4Sjoerg   case OMPC_update:
2905*e038c9c4Sjoerg     if (!FirstClause) {
2906*e038c9c4Sjoerg       Diag(Tok, diag::err_omp_more_one_clause)
2907*e038c9c4Sjoerg           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2908*e038c9c4Sjoerg       ErrorFound = true;
2909*e038c9c4Sjoerg     }
2910*e038c9c4Sjoerg 
2911*e038c9c4Sjoerg     Clause = (DKind == OMPD_depobj)
2912*e038c9c4Sjoerg                  ? ParseOpenMPSimpleClause(CKind, WrongDirective)
2913*e038c9c4Sjoerg                  : ParseOpenMPClause(CKind, WrongDirective);
2914*e038c9c4Sjoerg     break;
29157330f729Sjoerg   case OMPC_private:
29167330f729Sjoerg   case OMPC_firstprivate:
29177330f729Sjoerg   case OMPC_lastprivate:
29187330f729Sjoerg   case OMPC_shared:
29197330f729Sjoerg   case OMPC_reduction:
29207330f729Sjoerg   case OMPC_task_reduction:
29217330f729Sjoerg   case OMPC_in_reduction:
29227330f729Sjoerg   case OMPC_linear:
29237330f729Sjoerg   case OMPC_aligned:
29247330f729Sjoerg   case OMPC_copyin:
29257330f729Sjoerg   case OMPC_copyprivate:
29267330f729Sjoerg   case OMPC_flush:
29277330f729Sjoerg   case OMPC_depend:
29287330f729Sjoerg   case OMPC_map:
29297330f729Sjoerg   case OMPC_to:
29307330f729Sjoerg   case OMPC_from:
29317330f729Sjoerg   case OMPC_use_device_ptr:
2932*e038c9c4Sjoerg   case OMPC_use_device_addr:
29337330f729Sjoerg   case OMPC_is_device_ptr:
29347330f729Sjoerg   case OMPC_allocate:
2935*e038c9c4Sjoerg   case OMPC_nontemporal:
2936*e038c9c4Sjoerg   case OMPC_inclusive:
2937*e038c9c4Sjoerg   case OMPC_exclusive:
2938*e038c9c4Sjoerg   case OMPC_affinity:
29397330f729Sjoerg     Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
29407330f729Sjoerg     break;
2941*e038c9c4Sjoerg   case OMPC_sizes:
2942*e038c9c4Sjoerg     if (!FirstClause) {
2943*e038c9c4Sjoerg       Diag(Tok, diag::err_omp_more_one_clause)
2944*e038c9c4Sjoerg           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2945*e038c9c4Sjoerg       ErrorFound = true;
2946*e038c9c4Sjoerg     }
2947*e038c9c4Sjoerg 
2948*e038c9c4Sjoerg     Clause = ParseOpenMPSizesClause();
2949*e038c9c4Sjoerg     break;
2950*e038c9c4Sjoerg   case OMPC_uses_allocators:
2951*e038c9c4Sjoerg     Clause = ParseOpenMPUsesAllocatorClause(DKind);
2952*e038c9c4Sjoerg     break;
2953*e038c9c4Sjoerg   case OMPC_destroy:
2954*e038c9c4Sjoerg     if (DKind != OMPD_interop) {
2955*e038c9c4Sjoerg       if (!FirstClause) {
2956*e038c9c4Sjoerg         Diag(Tok, diag::err_omp_more_one_clause)
2957*e038c9c4Sjoerg             << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2958*e038c9c4Sjoerg         ErrorFound = true;
2959*e038c9c4Sjoerg       }
2960*e038c9c4Sjoerg       Clause = ParseOpenMPClause(CKind, WrongDirective);
2961*e038c9c4Sjoerg       break;
2962*e038c9c4Sjoerg     }
2963*e038c9c4Sjoerg     LLVM_FALLTHROUGH;
2964*e038c9c4Sjoerg   case OMPC_init:
2965*e038c9c4Sjoerg   case OMPC_use:
2966*e038c9c4Sjoerg     Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
2967*e038c9c4Sjoerg     break;
29687330f729Sjoerg   case OMPC_device_type:
29697330f729Sjoerg   case OMPC_unknown:
2970*e038c9c4Sjoerg     skipUntilPragmaOpenMPEnd(DKind);
29717330f729Sjoerg     break;
29727330f729Sjoerg   case OMPC_threadprivate:
29737330f729Sjoerg   case OMPC_uniform:
29747330f729Sjoerg   case OMPC_match:
29757330f729Sjoerg     if (!WrongDirective)
29767330f729Sjoerg       Diag(Tok, diag::err_omp_unexpected_clause)
29777330f729Sjoerg           << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
29787330f729Sjoerg     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
29797330f729Sjoerg     break;
2980*e038c9c4Sjoerg   default:
2981*e038c9c4Sjoerg     break;
29827330f729Sjoerg   }
29837330f729Sjoerg   return ErrorFound ? nullptr : Clause;
29847330f729Sjoerg }
29857330f729Sjoerg 
29867330f729Sjoerg /// Parses simple expression in parens for single-expression clauses of OpenMP
29877330f729Sjoerg /// constructs.
29887330f729Sjoerg /// \param RLoc Returned location of right paren.
ParseOpenMPParensExpr(StringRef ClauseName,SourceLocation & RLoc,bool IsAddressOfOperand)29897330f729Sjoerg ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
29907330f729Sjoerg                                          SourceLocation &RLoc,
29917330f729Sjoerg                                          bool IsAddressOfOperand) {
29927330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
29937330f729Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
29947330f729Sjoerg     return ExprError();
29957330f729Sjoerg 
29967330f729Sjoerg   SourceLocation ELoc = Tok.getLocation();
2997*e038c9c4Sjoerg   ExprResult LHS(
2998*e038c9c4Sjoerg       ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast));
29997330f729Sjoerg   ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
30007330f729Sjoerg   Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
30017330f729Sjoerg 
30027330f729Sjoerg   // Parse ')'.
30037330f729Sjoerg   RLoc = Tok.getLocation();
30047330f729Sjoerg   if (!T.consumeClose())
30057330f729Sjoerg     RLoc = T.getCloseLocation();
30067330f729Sjoerg 
30077330f729Sjoerg   return Val;
30087330f729Sjoerg }
30097330f729Sjoerg 
30107330f729Sjoerg /// Parsing of OpenMP clauses with single expressions like 'final',
30117330f729Sjoerg /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
3012*e038c9c4Sjoerg /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
3013*e038c9c4Sjoerg /// 'detach'.
30147330f729Sjoerg ///
30157330f729Sjoerg ///    final-clause:
30167330f729Sjoerg ///      'final' '(' expression ')'
30177330f729Sjoerg ///
30187330f729Sjoerg ///    num_threads-clause:
30197330f729Sjoerg ///      'num_threads' '(' expression ')'
30207330f729Sjoerg ///
30217330f729Sjoerg ///    safelen-clause:
30227330f729Sjoerg ///      'safelen' '(' expression ')'
30237330f729Sjoerg ///
30247330f729Sjoerg ///    simdlen-clause:
30257330f729Sjoerg ///      'simdlen' '(' expression ')'
30267330f729Sjoerg ///
30277330f729Sjoerg ///    collapse-clause:
30287330f729Sjoerg ///      'collapse' '(' expression ')'
30297330f729Sjoerg ///
30307330f729Sjoerg ///    priority-clause:
30317330f729Sjoerg ///      'priority' '(' expression ')'
30327330f729Sjoerg ///
30337330f729Sjoerg ///    grainsize-clause:
30347330f729Sjoerg ///      'grainsize' '(' expression ')'
30357330f729Sjoerg ///
30367330f729Sjoerg ///    num_tasks-clause:
30377330f729Sjoerg ///      'num_tasks' '(' expression ')'
30387330f729Sjoerg ///
30397330f729Sjoerg ///    hint-clause:
30407330f729Sjoerg ///      'hint' '(' expression ')'
30417330f729Sjoerg ///
30427330f729Sjoerg ///    allocator-clause:
30437330f729Sjoerg ///      'allocator' '(' expression ')'
30447330f729Sjoerg ///
3045*e038c9c4Sjoerg ///    detach-clause:
3046*e038c9c4Sjoerg ///      'detach' '(' event-handler-expression ')'
3047*e038c9c4Sjoerg ///
ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,bool ParseOnly)30487330f729Sjoerg OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
30497330f729Sjoerg                                                bool ParseOnly) {
30507330f729Sjoerg   SourceLocation Loc = ConsumeToken();
30517330f729Sjoerg   SourceLocation LLoc = Tok.getLocation();
30527330f729Sjoerg   SourceLocation RLoc;
30537330f729Sjoerg 
30547330f729Sjoerg   ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
30557330f729Sjoerg 
30567330f729Sjoerg   if (Val.isInvalid())
30577330f729Sjoerg     return nullptr;
30587330f729Sjoerg 
30597330f729Sjoerg   if (ParseOnly)
30607330f729Sjoerg     return nullptr;
30617330f729Sjoerg   return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
30627330f729Sjoerg }
30637330f729Sjoerg 
3064*e038c9c4Sjoerg /// Parsing of OpenMP clauses that use an interop-var.
3065*e038c9c4Sjoerg ///
3066*e038c9c4Sjoerg /// init-clause:
3067*e038c9c4Sjoerg ///   init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
3068*e038c9c4Sjoerg ///
3069*e038c9c4Sjoerg /// destroy-clause:
3070*e038c9c4Sjoerg ///   destroy(interop-var)
3071*e038c9c4Sjoerg ///
3072*e038c9c4Sjoerg /// use-clause:
3073*e038c9c4Sjoerg ///   use(interop-var)
3074*e038c9c4Sjoerg ///
3075*e038c9c4Sjoerg /// interop-modifier:
3076*e038c9c4Sjoerg ///   prefer_type(preference-list)
3077*e038c9c4Sjoerg ///
3078*e038c9c4Sjoerg /// preference-list:
3079*e038c9c4Sjoerg ///   foreign-runtime-id [, foreign-runtime-id]...
3080*e038c9c4Sjoerg ///
3081*e038c9c4Sjoerg /// foreign-runtime-id:
3082*e038c9c4Sjoerg ///   <string-literal> | <constant-integral-expression>
3083*e038c9c4Sjoerg ///
3084*e038c9c4Sjoerg /// interop-type:
3085*e038c9c4Sjoerg ///   target | targetsync
3086*e038c9c4Sjoerg ///
ParseOpenMPInteropClause(OpenMPClauseKind Kind,bool ParseOnly)3087*e038c9c4Sjoerg OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3088*e038c9c4Sjoerg                                             bool ParseOnly) {
3089*e038c9c4Sjoerg   SourceLocation Loc = ConsumeToken();
3090*e038c9c4Sjoerg   // Parse '('.
3091*e038c9c4Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3092*e038c9c4Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after,
3093*e038c9c4Sjoerg                          getOpenMPClauseName(Kind).data()))
3094*e038c9c4Sjoerg     return nullptr;
3095*e038c9c4Sjoerg 
3096*e038c9c4Sjoerg   bool IsTarget = false;
3097*e038c9c4Sjoerg   bool IsTargetSync = false;
3098*e038c9c4Sjoerg   SmallVector<Expr *, 4> Prefs;
3099*e038c9c4Sjoerg 
3100*e038c9c4Sjoerg   if (Kind == OMPC_init) {
3101*e038c9c4Sjoerg 
3102*e038c9c4Sjoerg     // Parse optional interop-modifier.
3103*e038c9c4Sjoerg     if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "prefer_type") {
3104*e038c9c4Sjoerg       ConsumeToken();
3105*e038c9c4Sjoerg       BalancedDelimiterTracker PT(*this, tok::l_paren,
3106*e038c9c4Sjoerg                                   tok::annot_pragma_openmp_end);
3107*e038c9c4Sjoerg       if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3108*e038c9c4Sjoerg         return nullptr;
3109*e038c9c4Sjoerg 
3110*e038c9c4Sjoerg       while (Tok.isNot(tok::r_paren)) {
3111*e038c9c4Sjoerg         SourceLocation Loc = Tok.getLocation();
3112*e038c9c4Sjoerg         ExprResult LHS = ParseCastExpression(AnyCastExpr);
3113*e038c9c4Sjoerg         ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
3114*e038c9c4Sjoerg             ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3115*e038c9c4Sjoerg         PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
3116*e038c9c4Sjoerg                                              /*DiscardedValue=*/false);
3117*e038c9c4Sjoerg         if (PTExpr.isUsable())
3118*e038c9c4Sjoerg           Prefs.push_back(PTExpr.get());
3119*e038c9c4Sjoerg         else
3120*e038c9c4Sjoerg           SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3121*e038c9c4Sjoerg                     StopBeforeMatch);
3122*e038c9c4Sjoerg 
3123*e038c9c4Sjoerg         if (Tok.is(tok::comma))
3124*e038c9c4Sjoerg           ConsumeToken();
3125*e038c9c4Sjoerg       }
3126*e038c9c4Sjoerg       PT.consumeClose();
3127*e038c9c4Sjoerg     }
3128*e038c9c4Sjoerg 
3129*e038c9c4Sjoerg     if (!Prefs.empty()) {
3130*e038c9c4Sjoerg       if (Tok.is(tok::comma))
3131*e038c9c4Sjoerg         ConsumeToken();
3132*e038c9c4Sjoerg       else
3133*e038c9c4Sjoerg         Diag(Tok, diag::err_omp_expected_punc_after_interop_mod);
3134*e038c9c4Sjoerg     }
3135*e038c9c4Sjoerg 
3136*e038c9c4Sjoerg     // Parse the interop-types.
3137*e038c9c4Sjoerg     bool HasError = false;
3138*e038c9c4Sjoerg     while (Tok.is(tok::identifier)) {
3139*e038c9c4Sjoerg       if (PP.getSpelling(Tok) == "target") {
3140*e038c9c4Sjoerg         // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3141*e038c9c4Sjoerg         // Each interop-type may be specified on an action-clause at most
3142*e038c9c4Sjoerg         // once.
3143*e038c9c4Sjoerg         if (IsTarget)
3144*e038c9c4Sjoerg           Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3145*e038c9c4Sjoerg         IsTarget = true;
3146*e038c9c4Sjoerg       } else if (PP.getSpelling(Tok) == "targetsync") {
3147*e038c9c4Sjoerg         if (IsTargetSync)
3148*e038c9c4Sjoerg           Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3149*e038c9c4Sjoerg         IsTargetSync = true;
3150*e038c9c4Sjoerg       } else {
3151*e038c9c4Sjoerg         HasError = true;
3152*e038c9c4Sjoerg         Diag(Tok, diag::err_omp_expected_interop_type);
3153*e038c9c4Sjoerg       }
3154*e038c9c4Sjoerg       ConsumeToken();
3155*e038c9c4Sjoerg 
3156*e038c9c4Sjoerg       if (!Tok.is(tok::comma))
3157*e038c9c4Sjoerg         break;
3158*e038c9c4Sjoerg       ConsumeToken();
3159*e038c9c4Sjoerg     }
3160*e038c9c4Sjoerg     if (!HasError && !IsTarget && !IsTargetSync)
3161*e038c9c4Sjoerg       Diag(Tok, diag::err_omp_expected_interop_type);
3162*e038c9c4Sjoerg 
3163*e038c9c4Sjoerg     if (Tok.is(tok::colon))
3164*e038c9c4Sjoerg       ConsumeToken();
3165*e038c9c4Sjoerg     else if (IsTarget || IsTargetSync)
3166*e038c9c4Sjoerg       Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
3167*e038c9c4Sjoerg   }
3168*e038c9c4Sjoerg 
3169*e038c9c4Sjoerg   // Parse the variable.
3170*e038c9c4Sjoerg   SourceLocation VarLoc = Tok.getLocation();
3171*e038c9c4Sjoerg   ExprResult InteropVarExpr =
3172*e038c9c4Sjoerg       Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
3173*e038c9c4Sjoerg   if (!InteropVarExpr.isUsable()) {
3174*e038c9c4Sjoerg     SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3175*e038c9c4Sjoerg               StopBeforeMatch);
3176*e038c9c4Sjoerg   }
3177*e038c9c4Sjoerg 
3178*e038c9c4Sjoerg   // Parse ')'.
3179*e038c9c4Sjoerg   SourceLocation RLoc = Tok.getLocation();
3180*e038c9c4Sjoerg   if (!T.consumeClose())
3181*e038c9c4Sjoerg     RLoc = T.getCloseLocation();
3182*e038c9c4Sjoerg 
3183*e038c9c4Sjoerg   if (ParseOnly || !InteropVarExpr.isUsable() ||
3184*e038c9c4Sjoerg       (Kind == OMPC_init && !IsTarget && !IsTargetSync))
3185*e038c9c4Sjoerg     return nullptr;
3186*e038c9c4Sjoerg 
3187*e038c9c4Sjoerg   if (Kind == OMPC_init)
3188*e038c9c4Sjoerg     return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), Prefs, IsTarget,
3189*e038c9c4Sjoerg                                          IsTargetSync, Loc, T.getOpenLocation(),
3190*e038c9c4Sjoerg                                          VarLoc, RLoc);
3191*e038c9c4Sjoerg   if (Kind == OMPC_use)
3192*e038c9c4Sjoerg     return Actions.ActOnOpenMPUseClause(InteropVarExpr.get(), Loc,
3193*e038c9c4Sjoerg                                         T.getOpenLocation(), VarLoc, RLoc);
3194*e038c9c4Sjoerg 
3195*e038c9c4Sjoerg   if (Kind == OMPC_destroy)
3196*e038c9c4Sjoerg     return Actions.ActOnOpenMPDestroyClause(InteropVarExpr.get(), Loc,
3197*e038c9c4Sjoerg                                             T.getOpenLocation(), VarLoc, RLoc);
3198*e038c9c4Sjoerg 
3199*e038c9c4Sjoerg   llvm_unreachable("Unexpected interop variable clause.");
3200*e038c9c4Sjoerg }
3201*e038c9c4Sjoerg 
32027330f729Sjoerg /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
32037330f729Sjoerg ///
32047330f729Sjoerg ///    default-clause:
3205*e038c9c4Sjoerg ///         'default' '(' 'none' | 'shared' | 'firstprivate' ')'
32067330f729Sjoerg ///
32077330f729Sjoerg ///    proc_bind-clause:
3208*e038c9c4Sjoerg ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')'
3209*e038c9c4Sjoerg ///
3210*e038c9c4Sjoerg ///    update-clause:
3211*e038c9c4Sjoerg ///         'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')'
32127330f729Sjoerg ///
ParseOpenMPSimpleClause(OpenMPClauseKind Kind,bool ParseOnly)32137330f729Sjoerg OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
32147330f729Sjoerg                                            bool ParseOnly) {
32157330f729Sjoerg   llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
32167330f729Sjoerg   if (!Val || ParseOnly)
32177330f729Sjoerg     return nullptr;
3218*e038c9c4Sjoerg   if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3219*e038c9c4Sjoerg       static_cast<DefaultKind>(Val.getValue().Type) ==
3220*e038c9c4Sjoerg           OMP_DEFAULT_firstprivate) {
3221*e038c9c4Sjoerg     Diag(Val.getValue().LOpen, diag::err_omp_invalid_dsa)
3222*e038c9c4Sjoerg         << getOpenMPClauseName(OMPC_firstprivate)
3223*e038c9c4Sjoerg         << getOpenMPClauseName(OMPC_default) << "5.1";
3224*e038c9c4Sjoerg     return nullptr;
3225*e038c9c4Sjoerg   }
32267330f729Sjoerg   return Actions.ActOnOpenMPSimpleClause(
32277330f729Sjoerg       Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
32287330f729Sjoerg       Val.getValue().Loc, Val.getValue().RLoc);
32297330f729Sjoerg }
32307330f729Sjoerg 
32317330f729Sjoerg /// Parsing of OpenMP clauses like 'ordered'.
32327330f729Sjoerg ///
32337330f729Sjoerg ///    ordered-clause:
32347330f729Sjoerg ///         'ordered'
32357330f729Sjoerg ///
32367330f729Sjoerg ///    nowait-clause:
32377330f729Sjoerg ///         'nowait'
32387330f729Sjoerg ///
32397330f729Sjoerg ///    untied-clause:
32407330f729Sjoerg ///         'untied'
32417330f729Sjoerg ///
32427330f729Sjoerg ///    mergeable-clause:
32437330f729Sjoerg ///         'mergeable'
32447330f729Sjoerg ///
32457330f729Sjoerg ///    read-clause:
32467330f729Sjoerg ///         'read'
32477330f729Sjoerg ///
32487330f729Sjoerg ///    threads-clause:
32497330f729Sjoerg ///         'threads'
32507330f729Sjoerg ///
32517330f729Sjoerg ///    simd-clause:
32527330f729Sjoerg ///         'simd'
32537330f729Sjoerg ///
32547330f729Sjoerg ///    nogroup-clause:
32557330f729Sjoerg ///         'nogroup'
32567330f729Sjoerg ///
ParseOpenMPClause(OpenMPClauseKind Kind,bool ParseOnly)32577330f729Sjoerg OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
32587330f729Sjoerg   SourceLocation Loc = Tok.getLocation();
32597330f729Sjoerg   ConsumeAnyToken();
32607330f729Sjoerg 
32617330f729Sjoerg   if (ParseOnly)
32627330f729Sjoerg     return nullptr;
32637330f729Sjoerg   return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
32647330f729Sjoerg }
32657330f729Sjoerg 
32667330f729Sjoerg /// Parsing of OpenMP clauses with single expressions and some additional
32677330f729Sjoerg /// argument like 'schedule' or 'dist_schedule'.
32687330f729Sjoerg ///
32697330f729Sjoerg ///    schedule-clause:
32707330f729Sjoerg ///      'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
32717330f729Sjoerg ///      ')'
32727330f729Sjoerg ///
32737330f729Sjoerg ///    if-clause:
32747330f729Sjoerg ///      'if' '(' [ directive-name-modifier ':' ] expression ')'
32757330f729Sjoerg ///
32767330f729Sjoerg ///    defaultmap:
3277*e038c9c4Sjoerg ///      'defaultmap' '(' modifier [ ':' kind ] ')'
32787330f729Sjoerg ///
3279*e038c9c4Sjoerg ///    device-clause:
3280*e038c9c4Sjoerg ///      'device' '(' [ device-modifier ':' ] expression ')'
3281*e038c9c4Sjoerg ///
ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,bool ParseOnly)3282*e038c9c4Sjoerg OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
3283*e038c9c4Sjoerg                                                       OpenMPClauseKind Kind,
32847330f729Sjoerg                                                       bool ParseOnly) {
32857330f729Sjoerg   SourceLocation Loc = ConsumeToken();
32867330f729Sjoerg   SourceLocation DelimLoc;
32877330f729Sjoerg   // Parse '('.
32887330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
32897330f729Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after,
3290*e038c9c4Sjoerg                          getOpenMPClauseName(Kind).data()))
32917330f729Sjoerg     return nullptr;
32927330f729Sjoerg 
32937330f729Sjoerg   ExprResult Val;
32947330f729Sjoerg   SmallVector<unsigned, 4> Arg;
32957330f729Sjoerg   SmallVector<SourceLocation, 4> KLoc;
32967330f729Sjoerg   if (Kind == OMPC_schedule) {
32977330f729Sjoerg     enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
32987330f729Sjoerg     Arg.resize(NumberOfElements);
32997330f729Sjoerg     KLoc.resize(NumberOfElements);
33007330f729Sjoerg     Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
33017330f729Sjoerg     Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
33027330f729Sjoerg     Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
33037330f729Sjoerg     unsigned KindModifier = getOpenMPSimpleClauseType(
3304*e038c9c4Sjoerg         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3305*e038c9c4Sjoerg         getLangOpts().OpenMP);
33067330f729Sjoerg     if (KindModifier > OMPC_SCHEDULE_unknown) {
33077330f729Sjoerg       // Parse 'modifier'
33087330f729Sjoerg       Arg[Modifier1] = KindModifier;
33097330f729Sjoerg       KLoc[Modifier1] = Tok.getLocation();
33107330f729Sjoerg       if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
33117330f729Sjoerg           Tok.isNot(tok::annot_pragma_openmp_end))
33127330f729Sjoerg         ConsumeAnyToken();
33137330f729Sjoerg       if (Tok.is(tok::comma)) {
33147330f729Sjoerg         // Parse ',' 'modifier'
33157330f729Sjoerg         ConsumeAnyToken();
33167330f729Sjoerg         KindModifier = getOpenMPSimpleClauseType(
3317*e038c9c4Sjoerg             Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3318*e038c9c4Sjoerg             getLangOpts().OpenMP);
33197330f729Sjoerg         Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
33207330f729Sjoerg                              ? KindModifier
33217330f729Sjoerg                              : (unsigned)OMPC_SCHEDULE_unknown;
33227330f729Sjoerg         KLoc[Modifier2] = Tok.getLocation();
33237330f729Sjoerg         if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
33247330f729Sjoerg             Tok.isNot(tok::annot_pragma_openmp_end))
33257330f729Sjoerg           ConsumeAnyToken();
33267330f729Sjoerg       }
33277330f729Sjoerg       // Parse ':'
33287330f729Sjoerg       if (Tok.is(tok::colon))
33297330f729Sjoerg         ConsumeAnyToken();
33307330f729Sjoerg       else
33317330f729Sjoerg         Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
33327330f729Sjoerg       KindModifier = getOpenMPSimpleClauseType(
3333*e038c9c4Sjoerg           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3334*e038c9c4Sjoerg           getLangOpts().OpenMP);
33357330f729Sjoerg     }
33367330f729Sjoerg     Arg[ScheduleKind] = KindModifier;
33377330f729Sjoerg     KLoc[ScheduleKind] = Tok.getLocation();
33387330f729Sjoerg     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
33397330f729Sjoerg         Tok.isNot(tok::annot_pragma_openmp_end))
33407330f729Sjoerg       ConsumeAnyToken();
33417330f729Sjoerg     if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
33427330f729Sjoerg          Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
33437330f729Sjoerg          Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
33447330f729Sjoerg         Tok.is(tok::comma))
33457330f729Sjoerg       DelimLoc = ConsumeAnyToken();
33467330f729Sjoerg   } else if (Kind == OMPC_dist_schedule) {
33477330f729Sjoerg     Arg.push_back(getOpenMPSimpleClauseType(
3348*e038c9c4Sjoerg         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3349*e038c9c4Sjoerg         getLangOpts().OpenMP));
33507330f729Sjoerg     KLoc.push_back(Tok.getLocation());
33517330f729Sjoerg     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
33527330f729Sjoerg         Tok.isNot(tok::annot_pragma_openmp_end))
33537330f729Sjoerg       ConsumeAnyToken();
33547330f729Sjoerg     if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
33557330f729Sjoerg       DelimLoc = ConsumeAnyToken();
33567330f729Sjoerg   } else if (Kind == OMPC_defaultmap) {
33577330f729Sjoerg     // Get a defaultmap modifier
3358*e038c9c4Sjoerg     unsigned Modifier = getOpenMPSimpleClauseType(
3359*e038c9c4Sjoerg         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3360*e038c9c4Sjoerg         getLangOpts().OpenMP);
3361*e038c9c4Sjoerg     // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
3362*e038c9c4Sjoerg     // pointer
3363*e038c9c4Sjoerg     if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
3364*e038c9c4Sjoerg       Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
3365*e038c9c4Sjoerg     Arg.push_back(Modifier);
33667330f729Sjoerg     KLoc.push_back(Tok.getLocation());
33677330f729Sjoerg     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
33687330f729Sjoerg         Tok.isNot(tok::annot_pragma_openmp_end))
33697330f729Sjoerg       ConsumeAnyToken();
33707330f729Sjoerg     // Parse ':'
3371*e038c9c4Sjoerg     if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
33727330f729Sjoerg       if (Tok.is(tok::colon))
33737330f729Sjoerg         ConsumeAnyToken();
33747330f729Sjoerg       else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
33757330f729Sjoerg         Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
33767330f729Sjoerg       // Get a defaultmap kind
33777330f729Sjoerg       Arg.push_back(getOpenMPSimpleClauseType(
3378*e038c9c4Sjoerg           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3379*e038c9c4Sjoerg           getLangOpts().OpenMP));
33807330f729Sjoerg       KLoc.push_back(Tok.getLocation());
33817330f729Sjoerg       if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
33827330f729Sjoerg           Tok.isNot(tok::annot_pragma_openmp_end))
33837330f729Sjoerg         ConsumeAnyToken();
33847330f729Sjoerg     } else {
3385*e038c9c4Sjoerg       Arg.push_back(OMPC_DEFAULTMAP_unknown);
3386*e038c9c4Sjoerg       KLoc.push_back(SourceLocation());
3387*e038c9c4Sjoerg     }
3388*e038c9c4Sjoerg   } else if (Kind == OMPC_device) {
3389*e038c9c4Sjoerg     // Only target executable directives support extended device construct.
3390*e038c9c4Sjoerg     if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
3391*e038c9c4Sjoerg         NextToken().is(tok::colon)) {
3392*e038c9c4Sjoerg       // Parse optional <device modifier> ':'
3393*e038c9c4Sjoerg       Arg.push_back(getOpenMPSimpleClauseType(
3394*e038c9c4Sjoerg           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3395*e038c9c4Sjoerg           getLangOpts().OpenMP));
3396*e038c9c4Sjoerg       KLoc.push_back(Tok.getLocation());
3397*e038c9c4Sjoerg       ConsumeAnyToken();
3398*e038c9c4Sjoerg       // Parse ':'
3399*e038c9c4Sjoerg       ConsumeAnyToken();
3400*e038c9c4Sjoerg     } else {
3401*e038c9c4Sjoerg       Arg.push_back(OMPC_DEVICE_unknown);
3402*e038c9c4Sjoerg       KLoc.emplace_back();
3403*e038c9c4Sjoerg     }
3404*e038c9c4Sjoerg   } else {
34057330f729Sjoerg     assert(Kind == OMPC_if);
34067330f729Sjoerg     KLoc.push_back(Tok.getLocation());
34077330f729Sjoerg     TentativeParsingAction TPA(*this);
3408*e038c9c4Sjoerg     auto DK = parseOpenMPDirectiveKind(*this);
3409*e038c9c4Sjoerg     Arg.push_back(DK);
3410*e038c9c4Sjoerg     if (DK != OMPD_unknown) {
34117330f729Sjoerg       ConsumeToken();
34127330f729Sjoerg       if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
34137330f729Sjoerg         TPA.Commit();
34147330f729Sjoerg         DelimLoc = ConsumeToken();
34157330f729Sjoerg       } else {
34167330f729Sjoerg         TPA.Revert();
3417*e038c9c4Sjoerg         Arg.back() = unsigned(OMPD_unknown);
34187330f729Sjoerg       }
34197330f729Sjoerg     } else {
34207330f729Sjoerg       TPA.Revert();
34217330f729Sjoerg     }
34227330f729Sjoerg   }
34237330f729Sjoerg 
34247330f729Sjoerg   bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
34257330f729Sjoerg                           (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
3426*e038c9c4Sjoerg                           Kind == OMPC_if || Kind == OMPC_device;
34277330f729Sjoerg   if (NeedAnExpression) {
34287330f729Sjoerg     SourceLocation ELoc = Tok.getLocation();
3429*e038c9c4Sjoerg     ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
34307330f729Sjoerg     Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
34317330f729Sjoerg     Val =
34327330f729Sjoerg         Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
34337330f729Sjoerg   }
34347330f729Sjoerg 
34357330f729Sjoerg   // Parse ')'.
34367330f729Sjoerg   SourceLocation RLoc = Tok.getLocation();
34377330f729Sjoerg   if (!T.consumeClose())
34387330f729Sjoerg     RLoc = T.getCloseLocation();
34397330f729Sjoerg 
34407330f729Sjoerg   if (NeedAnExpression && Val.isInvalid())
34417330f729Sjoerg     return nullptr;
34427330f729Sjoerg 
34437330f729Sjoerg   if (ParseOnly)
34447330f729Sjoerg     return nullptr;
34457330f729Sjoerg   return Actions.ActOnOpenMPSingleExprWithArgClause(
34467330f729Sjoerg       Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
34477330f729Sjoerg }
34487330f729Sjoerg 
ParseReductionId(Parser & P,CXXScopeSpec & ReductionIdScopeSpec,UnqualifiedId & ReductionId)34497330f729Sjoerg static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
34507330f729Sjoerg                              UnqualifiedId &ReductionId) {
34517330f729Sjoerg   if (ReductionIdScopeSpec.isEmpty()) {
34527330f729Sjoerg     auto OOK = OO_None;
34537330f729Sjoerg     switch (P.getCurToken().getKind()) {
34547330f729Sjoerg     case tok::plus:
34557330f729Sjoerg       OOK = OO_Plus;
34567330f729Sjoerg       break;
34577330f729Sjoerg     case tok::minus:
34587330f729Sjoerg       OOK = OO_Minus;
34597330f729Sjoerg       break;
34607330f729Sjoerg     case tok::star:
34617330f729Sjoerg       OOK = OO_Star;
34627330f729Sjoerg       break;
34637330f729Sjoerg     case tok::amp:
34647330f729Sjoerg       OOK = OO_Amp;
34657330f729Sjoerg       break;
34667330f729Sjoerg     case tok::pipe:
34677330f729Sjoerg       OOK = OO_Pipe;
34687330f729Sjoerg       break;
34697330f729Sjoerg     case tok::caret:
34707330f729Sjoerg       OOK = OO_Caret;
34717330f729Sjoerg       break;
34727330f729Sjoerg     case tok::ampamp:
34737330f729Sjoerg       OOK = OO_AmpAmp;
34747330f729Sjoerg       break;
34757330f729Sjoerg     case tok::pipepipe:
34767330f729Sjoerg       OOK = OO_PipePipe;
34777330f729Sjoerg       break;
34787330f729Sjoerg     default:
34797330f729Sjoerg       break;
34807330f729Sjoerg     }
34817330f729Sjoerg     if (OOK != OO_None) {
34827330f729Sjoerg       SourceLocation OpLoc = P.ConsumeToken();
34837330f729Sjoerg       SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
34847330f729Sjoerg       ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
34857330f729Sjoerg       return false;
34867330f729Sjoerg     }
34877330f729Sjoerg   }
3488*e038c9c4Sjoerg   return P.ParseUnqualifiedId(
3489*e038c9c4Sjoerg       ReductionIdScopeSpec, /*ObjectType=*/nullptr,
3490*e038c9c4Sjoerg       /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
34917330f729Sjoerg       /*AllowDestructorName*/ false,
34927330f729Sjoerg       /*AllowConstructorName*/ false,
3493*e038c9c4Sjoerg       /*AllowDeductionGuide*/ false, nullptr, ReductionId);
34947330f729Sjoerg }
34957330f729Sjoerg 
34967330f729Sjoerg /// Checks if the token is a valid map-type-modifier.
3497*e038c9c4Sjoerg /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
isMapModifier(Parser & P)34987330f729Sjoerg static OpenMPMapModifierKind isMapModifier(Parser &P) {
34997330f729Sjoerg   Token Tok = P.getCurToken();
35007330f729Sjoerg   if (!Tok.is(tok::identifier))
35017330f729Sjoerg     return OMPC_MAP_MODIFIER_unknown;
35027330f729Sjoerg 
35037330f729Sjoerg   Preprocessor &PP = P.getPreprocessor();
3504*e038c9c4Sjoerg   OpenMPMapModifierKind TypeModifier =
3505*e038c9c4Sjoerg       static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType(
3506*e038c9c4Sjoerg           OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP));
35077330f729Sjoerg   return TypeModifier;
35087330f729Sjoerg }
35097330f729Sjoerg 
35107330f729Sjoerg /// Parse the mapper modifier in map, to, and from clauses.
parseMapperModifier(OpenMPVarListDataTy & Data)35117330f729Sjoerg bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
35127330f729Sjoerg   // Parse '('.
35137330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
35147330f729Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
35157330f729Sjoerg     SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
35167330f729Sjoerg               StopBeforeMatch);
35177330f729Sjoerg     return true;
35187330f729Sjoerg   }
35197330f729Sjoerg   // Parse mapper-identifier
35207330f729Sjoerg   if (getLangOpts().CPlusPlus)
35217330f729Sjoerg     ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
35227330f729Sjoerg                                    /*ObjectType=*/nullptr,
3523*e038c9c4Sjoerg                                    /*ObjectHadErrors=*/false,
35247330f729Sjoerg                                    /*EnteringContext=*/false);
35257330f729Sjoerg   if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
35267330f729Sjoerg     Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
35277330f729Sjoerg     SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
35287330f729Sjoerg               StopBeforeMatch);
35297330f729Sjoerg     return true;
35307330f729Sjoerg   }
35317330f729Sjoerg   auto &DeclNames = Actions.getASTContext().DeclarationNames;
35327330f729Sjoerg   Data.ReductionOrMapperId = DeclarationNameInfo(
35337330f729Sjoerg       DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
35347330f729Sjoerg   ConsumeToken();
35357330f729Sjoerg   // Parse ')'.
35367330f729Sjoerg   return T.consumeClose();
35377330f729Sjoerg }
35387330f729Sjoerg 
35397330f729Sjoerg /// Parse map-type-modifiers in map clause.
35407330f729Sjoerg /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
3541*e038c9c4Sjoerg /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) |
3542*e038c9c4Sjoerg /// present
parseMapTypeModifiers(OpenMPVarListDataTy & Data)35437330f729Sjoerg bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
35447330f729Sjoerg   while (getCurToken().isNot(tok::colon)) {
35457330f729Sjoerg     OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
35467330f729Sjoerg     if (TypeModifier == OMPC_MAP_MODIFIER_always ||
3547*e038c9c4Sjoerg         TypeModifier == OMPC_MAP_MODIFIER_close ||
3548*e038c9c4Sjoerg         TypeModifier == OMPC_MAP_MODIFIER_present) {
35497330f729Sjoerg       Data.MapTypeModifiers.push_back(TypeModifier);
35507330f729Sjoerg       Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
35517330f729Sjoerg       ConsumeToken();
35527330f729Sjoerg     } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
35537330f729Sjoerg       Data.MapTypeModifiers.push_back(TypeModifier);
35547330f729Sjoerg       Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
35557330f729Sjoerg       ConsumeToken();
35567330f729Sjoerg       if (parseMapperModifier(Data))
35577330f729Sjoerg         return true;
35587330f729Sjoerg     } else {
35597330f729Sjoerg       // For the case of unknown map-type-modifier or a map-type.
35607330f729Sjoerg       // Map-type is followed by a colon; the function returns when it
35617330f729Sjoerg       // encounters a token followed by a colon.
35627330f729Sjoerg       if (Tok.is(tok::comma)) {
35637330f729Sjoerg         Diag(Tok, diag::err_omp_map_type_modifier_missing);
35647330f729Sjoerg         ConsumeToken();
35657330f729Sjoerg         continue;
35667330f729Sjoerg       }
35677330f729Sjoerg       // Potential map-type token as it is followed by a colon.
35687330f729Sjoerg       if (PP.LookAhead(0).is(tok::colon))
35697330f729Sjoerg         return false;
3570*e038c9c4Sjoerg       Diag(Tok, diag::err_omp_unknown_map_type_modifier)
3571*e038c9c4Sjoerg           << (getLangOpts().OpenMP >= 51 ? 1 : 0);
35727330f729Sjoerg       ConsumeToken();
35737330f729Sjoerg     }
35747330f729Sjoerg     if (getCurToken().is(tok::comma))
35757330f729Sjoerg       ConsumeToken();
35767330f729Sjoerg   }
35777330f729Sjoerg   return false;
35787330f729Sjoerg }
35797330f729Sjoerg 
35807330f729Sjoerg /// Checks if the token is a valid map-type.
3581*e038c9c4Sjoerg /// FIXME: It will return an OpenMPMapModifierKind if that's what it parses.
isMapType(Parser & P)35827330f729Sjoerg static OpenMPMapClauseKind isMapType(Parser &P) {
35837330f729Sjoerg   Token Tok = P.getCurToken();
35847330f729Sjoerg   // The map-type token can be either an identifier or the C++ delete keyword.
35857330f729Sjoerg   if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
35867330f729Sjoerg     return OMPC_MAP_unknown;
35877330f729Sjoerg   Preprocessor &PP = P.getPreprocessor();
3588*e038c9c4Sjoerg   OpenMPMapClauseKind MapType =
3589*e038c9c4Sjoerg       static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
3590*e038c9c4Sjoerg           OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP));
35917330f729Sjoerg   return MapType;
35927330f729Sjoerg }
35937330f729Sjoerg 
35947330f729Sjoerg /// Parse map-type in map clause.
35957330f729Sjoerg /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
35967330f729Sjoerg /// where, map-type ::= to | from | tofrom | alloc | release | delete
parseMapType(Parser & P,Parser::OpenMPVarListDataTy & Data)35977330f729Sjoerg static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
35987330f729Sjoerg   Token Tok = P.getCurToken();
35997330f729Sjoerg   if (Tok.is(tok::colon)) {
36007330f729Sjoerg     P.Diag(Tok, diag::err_omp_map_type_missing);
36017330f729Sjoerg     return;
36027330f729Sjoerg   }
3603*e038c9c4Sjoerg   Data.ExtraModifier = isMapType(P);
3604*e038c9c4Sjoerg   if (Data.ExtraModifier == OMPC_MAP_unknown)
36057330f729Sjoerg     P.Diag(Tok, diag::err_omp_unknown_map_type);
36067330f729Sjoerg   P.ConsumeToken();
36077330f729Sjoerg }
36087330f729Sjoerg 
3609*e038c9c4Sjoerg /// Parses simple expression in parens for single-expression clauses of OpenMP
3610*e038c9c4Sjoerg /// constructs.
ParseOpenMPIteratorsExpr()3611*e038c9c4Sjoerg ExprResult Parser::ParseOpenMPIteratorsExpr() {
3612*e038c9c4Sjoerg   assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
3613*e038c9c4Sjoerg          "Expected 'iterator' token.");
3614*e038c9c4Sjoerg   SourceLocation IteratorKwLoc = ConsumeToken();
3615*e038c9c4Sjoerg 
3616*e038c9c4Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3617*e038c9c4Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
3618*e038c9c4Sjoerg     return ExprError();
3619*e038c9c4Sjoerg 
3620*e038c9c4Sjoerg   SourceLocation LLoc = T.getOpenLocation();
3621*e038c9c4Sjoerg   SmallVector<Sema::OMPIteratorData, 4> Data;
3622*e038c9c4Sjoerg   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
3623*e038c9c4Sjoerg     // Check if the type parsing is required.
3624*e038c9c4Sjoerg     ParsedType IteratorType;
3625*e038c9c4Sjoerg     if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
3626*e038c9c4Sjoerg       // identifier '=' is not found - parse type.
3627*e038c9c4Sjoerg       TypeResult TR = ParseTypeName();
3628*e038c9c4Sjoerg       if (TR.isInvalid()) {
3629*e038c9c4Sjoerg         T.skipToEnd();
3630*e038c9c4Sjoerg         return ExprError();
3631*e038c9c4Sjoerg       }
3632*e038c9c4Sjoerg       IteratorType = TR.get();
3633*e038c9c4Sjoerg     }
3634*e038c9c4Sjoerg 
3635*e038c9c4Sjoerg     // Parse identifier.
3636*e038c9c4Sjoerg     IdentifierInfo *II = nullptr;
3637*e038c9c4Sjoerg     SourceLocation IdLoc;
3638*e038c9c4Sjoerg     if (Tok.is(tok::identifier)) {
3639*e038c9c4Sjoerg       II = Tok.getIdentifierInfo();
3640*e038c9c4Sjoerg       IdLoc = ConsumeToken();
3641*e038c9c4Sjoerg     } else {
3642*e038c9c4Sjoerg       Diag(Tok, diag::err_expected_unqualified_id) << 0;
3643*e038c9c4Sjoerg     }
3644*e038c9c4Sjoerg 
3645*e038c9c4Sjoerg     // Parse '='.
3646*e038c9c4Sjoerg     SourceLocation AssignLoc;
3647*e038c9c4Sjoerg     if (Tok.is(tok::equal))
3648*e038c9c4Sjoerg       AssignLoc = ConsumeToken();
3649*e038c9c4Sjoerg     else
3650*e038c9c4Sjoerg       Diag(Tok, diag::err_omp_expected_equal_in_iterator);
3651*e038c9c4Sjoerg 
3652*e038c9c4Sjoerg     // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
3653*e038c9c4Sjoerg     ColonProtectionRAIIObject ColonRAII(*this);
3654*e038c9c4Sjoerg     // Parse <begin>
3655*e038c9c4Sjoerg     SourceLocation Loc = Tok.getLocation();
3656*e038c9c4Sjoerg     ExprResult LHS = ParseCastExpression(AnyCastExpr);
3657*e038c9c4Sjoerg     ExprResult Begin = Actions.CorrectDelayedTyposInExpr(
3658*e038c9c4Sjoerg         ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3659*e038c9c4Sjoerg     Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
3660*e038c9c4Sjoerg                                         /*DiscardedValue=*/false);
3661*e038c9c4Sjoerg     // Parse ':'.
3662*e038c9c4Sjoerg     SourceLocation ColonLoc;
3663*e038c9c4Sjoerg     if (Tok.is(tok::colon))
3664*e038c9c4Sjoerg       ColonLoc = ConsumeToken();
3665*e038c9c4Sjoerg 
3666*e038c9c4Sjoerg     // Parse <end>
3667*e038c9c4Sjoerg     Loc = Tok.getLocation();
3668*e038c9c4Sjoerg     LHS = ParseCastExpression(AnyCastExpr);
3669*e038c9c4Sjoerg     ExprResult End = Actions.CorrectDelayedTyposInExpr(
3670*e038c9c4Sjoerg         ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3671*e038c9c4Sjoerg     End = Actions.ActOnFinishFullExpr(End.get(), Loc,
3672*e038c9c4Sjoerg                                       /*DiscardedValue=*/false);
3673*e038c9c4Sjoerg 
3674*e038c9c4Sjoerg     SourceLocation SecColonLoc;
3675*e038c9c4Sjoerg     ExprResult Step;
3676*e038c9c4Sjoerg     // Parse optional step.
3677*e038c9c4Sjoerg     if (Tok.is(tok::colon)) {
3678*e038c9c4Sjoerg       // Parse ':'
3679*e038c9c4Sjoerg       SecColonLoc = ConsumeToken();
3680*e038c9c4Sjoerg       // Parse <step>
3681*e038c9c4Sjoerg       Loc = Tok.getLocation();
3682*e038c9c4Sjoerg       LHS = ParseCastExpression(AnyCastExpr);
3683*e038c9c4Sjoerg       Step = Actions.CorrectDelayedTyposInExpr(
3684*e038c9c4Sjoerg           ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3685*e038c9c4Sjoerg       Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
3686*e038c9c4Sjoerg                                          /*DiscardedValue=*/false);
3687*e038c9c4Sjoerg     }
3688*e038c9c4Sjoerg 
3689*e038c9c4Sjoerg     // Parse ',' or ')'
3690*e038c9c4Sjoerg     if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3691*e038c9c4Sjoerg       Diag(Tok, diag::err_omp_expected_punc_after_iterator);
3692*e038c9c4Sjoerg     if (Tok.is(tok::comma))
3693*e038c9c4Sjoerg       ConsumeToken();
3694*e038c9c4Sjoerg 
3695*e038c9c4Sjoerg     Sema::OMPIteratorData &D = Data.emplace_back();
3696*e038c9c4Sjoerg     D.DeclIdent = II;
3697*e038c9c4Sjoerg     D.DeclIdentLoc = IdLoc;
3698*e038c9c4Sjoerg     D.Type = IteratorType;
3699*e038c9c4Sjoerg     D.AssignLoc = AssignLoc;
3700*e038c9c4Sjoerg     D.ColonLoc = ColonLoc;
3701*e038c9c4Sjoerg     D.SecColonLoc = SecColonLoc;
3702*e038c9c4Sjoerg     D.Range.Begin = Begin.get();
3703*e038c9c4Sjoerg     D.Range.End = End.get();
3704*e038c9c4Sjoerg     D.Range.Step = Step.get();
3705*e038c9c4Sjoerg   }
3706*e038c9c4Sjoerg 
3707*e038c9c4Sjoerg   // Parse ')'.
3708*e038c9c4Sjoerg   SourceLocation RLoc = Tok.getLocation();
3709*e038c9c4Sjoerg   if (!T.consumeClose())
3710*e038c9c4Sjoerg     RLoc = T.getCloseLocation();
3711*e038c9c4Sjoerg 
3712*e038c9c4Sjoerg   return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc,
3713*e038c9c4Sjoerg                                       Data);
3714*e038c9c4Sjoerg }
3715*e038c9c4Sjoerg 
37167330f729Sjoerg /// Parses clauses with list.
ParseOpenMPVarList(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,SmallVectorImpl<Expr * > & Vars,OpenMPVarListDataTy & Data)37177330f729Sjoerg bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
37187330f729Sjoerg                                 OpenMPClauseKind Kind,
37197330f729Sjoerg                                 SmallVectorImpl<Expr *> &Vars,
37207330f729Sjoerg                                 OpenMPVarListDataTy &Data) {
37217330f729Sjoerg   UnqualifiedId UnqualifiedReductionId;
37227330f729Sjoerg   bool InvalidReductionId = false;
37237330f729Sjoerg   bool IsInvalidMapperModifier = false;
37247330f729Sjoerg 
37257330f729Sjoerg   // Parse '('.
37267330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
37277330f729Sjoerg   if (T.expectAndConsume(diag::err_expected_lparen_after,
3728*e038c9c4Sjoerg                          getOpenMPClauseName(Kind).data()))
37297330f729Sjoerg     return true;
37307330f729Sjoerg 
3731*e038c9c4Sjoerg   bool HasIterator = false;
37327330f729Sjoerg   bool NeedRParenForLinear = false;
37337330f729Sjoerg   BalancedDelimiterTracker LinearT(*this, tok::l_paren,
37347330f729Sjoerg                                    tok::annot_pragma_openmp_end);
37357330f729Sjoerg   // Handle reduction-identifier for reduction clause.
37367330f729Sjoerg   if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
37377330f729Sjoerg       Kind == OMPC_in_reduction) {
3738*e038c9c4Sjoerg     Data.ExtraModifier = OMPC_REDUCTION_unknown;
3739*e038c9c4Sjoerg     if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
3740*e038c9c4Sjoerg         (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
3741*e038c9c4Sjoerg         NextToken().is(tok::comma)) {
3742*e038c9c4Sjoerg       // Parse optional reduction modifier.
3743*e038c9c4Sjoerg       Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok),
3744*e038c9c4Sjoerg                                                      getLangOpts().OpenMP);
3745*e038c9c4Sjoerg       Data.ExtraModifierLoc = Tok.getLocation();
3746*e038c9c4Sjoerg       ConsumeToken();
3747*e038c9c4Sjoerg       assert(Tok.is(tok::comma) && "Expected comma.");
3748*e038c9c4Sjoerg       (void)ConsumeToken();
3749*e038c9c4Sjoerg     }
37507330f729Sjoerg     ColonProtectionRAIIObject ColonRAII(*this);
37517330f729Sjoerg     if (getLangOpts().CPlusPlus)
37527330f729Sjoerg       ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
37537330f729Sjoerg                                      /*ObjectType=*/nullptr,
3754*e038c9c4Sjoerg                                      /*ObjectHadErrors=*/false,
37557330f729Sjoerg                                      /*EnteringContext=*/false);
37567330f729Sjoerg     InvalidReductionId = ParseReductionId(
37577330f729Sjoerg         *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
37587330f729Sjoerg     if (InvalidReductionId) {
37597330f729Sjoerg       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
37607330f729Sjoerg                 StopBeforeMatch);
37617330f729Sjoerg     }
37627330f729Sjoerg     if (Tok.is(tok::colon))
37637330f729Sjoerg       Data.ColonLoc = ConsumeToken();
37647330f729Sjoerg     else
37657330f729Sjoerg       Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
37667330f729Sjoerg     if (!InvalidReductionId)
37677330f729Sjoerg       Data.ReductionOrMapperId =
37687330f729Sjoerg           Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
37697330f729Sjoerg   } else if (Kind == OMPC_depend) {
3770*e038c9c4Sjoerg     if (getLangOpts().OpenMP >= 50) {
3771*e038c9c4Sjoerg       if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
3772*e038c9c4Sjoerg         // Handle optional dependence modifier.
3773*e038c9c4Sjoerg         // iterator(iterators-definition)
3774*e038c9c4Sjoerg         // where iterators-definition is iterator-specifier [,
3775*e038c9c4Sjoerg         // iterators-definition ]
3776*e038c9c4Sjoerg         // where iterator-specifier is [ iterator-type ] identifier =
3777*e038c9c4Sjoerg         // range-specification
3778*e038c9c4Sjoerg         HasIterator = true;
3779*e038c9c4Sjoerg         EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
3780*e038c9c4Sjoerg         ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
3781*e038c9c4Sjoerg         Data.DepModOrTailExpr = IteratorRes.get();
3782*e038c9c4Sjoerg         // Parse ','
3783*e038c9c4Sjoerg         ExpectAndConsume(tok::comma);
3784*e038c9c4Sjoerg       }
3785*e038c9c4Sjoerg     }
37867330f729Sjoerg     // Handle dependency type for depend clause.
37877330f729Sjoerg     ColonProtectionRAIIObject ColonRAII(*this);
3788*e038c9c4Sjoerg     Data.ExtraModifier = getOpenMPSimpleClauseType(
3789*e038c9c4Sjoerg         Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
3790*e038c9c4Sjoerg         getLangOpts().OpenMP);
3791*e038c9c4Sjoerg     Data.ExtraModifierLoc = Tok.getLocation();
3792*e038c9c4Sjoerg     if (Data.ExtraModifier == OMPC_DEPEND_unknown) {
37937330f729Sjoerg       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
37947330f729Sjoerg                 StopBeforeMatch);
37957330f729Sjoerg     } else {
37967330f729Sjoerg       ConsumeToken();
37977330f729Sjoerg       // Special processing for depend(source) clause.
3798*e038c9c4Sjoerg       if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) {
37997330f729Sjoerg         // Parse ')'.
38007330f729Sjoerg         T.consumeClose();
38017330f729Sjoerg         return false;
38027330f729Sjoerg       }
38037330f729Sjoerg     }
38047330f729Sjoerg     if (Tok.is(tok::colon)) {
38057330f729Sjoerg       Data.ColonLoc = ConsumeToken();
38067330f729Sjoerg     } else {
38077330f729Sjoerg       Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
38087330f729Sjoerg                                       : diag::warn_pragma_expected_colon)
38097330f729Sjoerg           << "dependency type";
38107330f729Sjoerg     }
38117330f729Sjoerg   } else if (Kind == OMPC_linear) {
38127330f729Sjoerg     // Try to parse modifier if any.
3813*e038c9c4Sjoerg     Data.ExtraModifier = OMPC_LINEAR_val;
38147330f729Sjoerg     if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
3815*e038c9c4Sjoerg       Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok),
3816*e038c9c4Sjoerg                                                      getLangOpts().OpenMP);
3817*e038c9c4Sjoerg       Data.ExtraModifierLoc = ConsumeToken();
38187330f729Sjoerg       LinearT.consumeOpen();
38197330f729Sjoerg       NeedRParenForLinear = true;
38207330f729Sjoerg     }
3821*e038c9c4Sjoerg   } else if (Kind == OMPC_lastprivate) {
3822*e038c9c4Sjoerg     // Try to parse modifier if any.
3823*e038c9c4Sjoerg     Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
3824*e038c9c4Sjoerg     // Conditional modifier allowed only in OpenMP 5.0 and not supported in
3825*e038c9c4Sjoerg     // distribute and taskloop based directives.
3826*e038c9c4Sjoerg     if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
3827*e038c9c4Sjoerg          !isOpenMPTaskLoopDirective(DKind)) &&
3828*e038c9c4Sjoerg         Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
3829*e038c9c4Sjoerg       Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok),
3830*e038c9c4Sjoerg                                                      getLangOpts().OpenMP);
3831*e038c9c4Sjoerg       Data.ExtraModifierLoc = Tok.getLocation();
3832*e038c9c4Sjoerg       ConsumeToken();
3833*e038c9c4Sjoerg       assert(Tok.is(tok::colon) && "Expected colon.");
3834*e038c9c4Sjoerg       Data.ColonLoc = ConsumeToken();
3835*e038c9c4Sjoerg     }
38367330f729Sjoerg   } else if (Kind == OMPC_map) {
38377330f729Sjoerg     // Handle map type for map clause.
38387330f729Sjoerg     ColonProtectionRAIIObject ColonRAII(*this);
38397330f729Sjoerg 
38407330f729Sjoerg     // The first identifier may be a list item, a map-type or a
38417330f729Sjoerg     // map-type-modifier. The map-type can also be delete which has the same
38427330f729Sjoerg     // spelling of the C++ delete keyword.
3843*e038c9c4Sjoerg     Data.ExtraModifier = OMPC_MAP_unknown;
3844*e038c9c4Sjoerg     Data.ExtraModifierLoc = Tok.getLocation();
38457330f729Sjoerg 
38467330f729Sjoerg     // Check for presence of a colon in the map clause.
38477330f729Sjoerg     TentativeParsingAction TPA(*this);
38487330f729Sjoerg     bool ColonPresent = false;
38497330f729Sjoerg     if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
38507330f729Sjoerg                   StopBeforeMatch)) {
38517330f729Sjoerg       if (Tok.is(tok::colon))
38527330f729Sjoerg         ColonPresent = true;
38537330f729Sjoerg     }
38547330f729Sjoerg     TPA.Revert();
38557330f729Sjoerg     // Only parse map-type-modifier[s] and map-type if a colon is present in
38567330f729Sjoerg     // the map clause.
38577330f729Sjoerg     if (ColonPresent) {
38587330f729Sjoerg       IsInvalidMapperModifier = parseMapTypeModifiers(Data);
38597330f729Sjoerg       if (!IsInvalidMapperModifier)
38607330f729Sjoerg         parseMapType(*this, Data);
38617330f729Sjoerg       else
38627330f729Sjoerg         SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
38637330f729Sjoerg     }
3864*e038c9c4Sjoerg     if (Data.ExtraModifier == OMPC_MAP_unknown) {
3865*e038c9c4Sjoerg       Data.ExtraModifier = OMPC_MAP_tofrom;
38667330f729Sjoerg       Data.IsMapTypeImplicit = true;
38677330f729Sjoerg     }
38687330f729Sjoerg 
38697330f729Sjoerg     if (Tok.is(tok::colon))
38707330f729Sjoerg       Data.ColonLoc = ConsumeToken();
38717330f729Sjoerg   } else if (Kind == OMPC_to || Kind == OMPC_from) {
3872*e038c9c4Sjoerg     while (Tok.is(tok::identifier)) {
3873*e038c9c4Sjoerg       auto Modifier =
3874*e038c9c4Sjoerg           static_cast<OpenMPMotionModifierKind>(getOpenMPSimpleClauseType(
3875*e038c9c4Sjoerg               Kind, PP.getSpelling(Tok), getLangOpts().OpenMP));
3876*e038c9c4Sjoerg       if (Modifier == OMPC_MOTION_MODIFIER_unknown)
3877*e038c9c4Sjoerg         break;
3878*e038c9c4Sjoerg       Data.MotionModifiers.push_back(Modifier);
3879*e038c9c4Sjoerg       Data.MotionModifiersLoc.push_back(Tok.getLocation());
38807330f729Sjoerg       ConsumeToken();
3881*e038c9c4Sjoerg       if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
38827330f729Sjoerg         IsInvalidMapperModifier = parseMapperModifier(Data);
3883*e038c9c4Sjoerg         if (IsInvalidMapperModifier)
3884*e038c9c4Sjoerg           break;
3885*e038c9c4Sjoerg       }
3886*e038c9c4Sjoerg       // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
3887*e038c9c4Sjoerg       if (getLangOpts().OpenMP < 51)
3888*e038c9c4Sjoerg         break;
3889*e038c9c4Sjoerg       // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
3890*e038c9c4Sjoerg       // TODO: Is that intentional?
3891*e038c9c4Sjoerg       if (Tok.is(tok::comma))
3892*e038c9c4Sjoerg         ConsumeToken();
3893*e038c9c4Sjoerg     }
3894*e038c9c4Sjoerg     if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
3895*e038c9c4Sjoerg       if (!IsInvalidMapperModifier) {
3896*e038c9c4Sjoerg         if (getLangOpts().OpenMP < 51)
38977330f729Sjoerg           Diag(Tok, diag::warn_pragma_expected_colon) << ")";
3898*e038c9c4Sjoerg         else
3899*e038c9c4Sjoerg           Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
3900*e038c9c4Sjoerg       }
39017330f729Sjoerg       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
39027330f729Sjoerg                 StopBeforeMatch);
39037330f729Sjoerg     }
3904*e038c9c4Sjoerg     // OpenMP 5.1 permits a ':' even without a preceding modifier.  TODO: Is
3905*e038c9c4Sjoerg     // that intentional?
3906*e038c9c4Sjoerg     if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
3907*e038c9c4Sjoerg         Tok.is(tok::colon))
3908*e038c9c4Sjoerg       Data.ColonLoc = ConsumeToken();
3909*e038c9c4Sjoerg   } else if (Kind == OMPC_allocate ||
3910*e038c9c4Sjoerg              (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
3911*e038c9c4Sjoerg               PP.getSpelling(Tok) == "iterator")) {
39127330f729Sjoerg     // Handle optional allocator expression followed by colon delimiter.
39137330f729Sjoerg     ColonProtectionRAIIObject ColonRAII(*this);
39147330f729Sjoerg     TentativeParsingAction TPA(*this);
3915*e038c9c4Sjoerg     // OpenMP 5.0, 2.10.1, task Construct.
3916*e038c9c4Sjoerg     // where aff-modifier is one of the following:
3917*e038c9c4Sjoerg     // iterator(iterators-definition)
3918*e038c9c4Sjoerg     ExprResult Tail;
3919*e038c9c4Sjoerg     if (Kind == OMPC_allocate) {
3920*e038c9c4Sjoerg       Tail = ParseAssignmentExpression();
3921*e038c9c4Sjoerg     } else {
3922*e038c9c4Sjoerg       HasIterator = true;
3923*e038c9c4Sjoerg       EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
3924*e038c9c4Sjoerg       Tail = ParseOpenMPIteratorsExpr();
3925*e038c9c4Sjoerg     }
3926*e038c9c4Sjoerg     Tail = Actions.CorrectDelayedTyposInExpr(Tail);
39277330f729Sjoerg     Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
39287330f729Sjoerg                                        /*DiscardedValue=*/false);
39297330f729Sjoerg     if (Tail.isUsable()) {
39307330f729Sjoerg       if (Tok.is(tok::colon)) {
3931*e038c9c4Sjoerg         Data.DepModOrTailExpr = Tail.get();
39327330f729Sjoerg         Data.ColonLoc = ConsumeToken();
39337330f729Sjoerg         TPA.Commit();
39347330f729Sjoerg       } else {
3935*e038c9c4Sjoerg         // Colon not found, parse only list of variables.
39367330f729Sjoerg         TPA.Revert();
39377330f729Sjoerg       }
39387330f729Sjoerg     } else {
39397330f729Sjoerg       // Parsing was unsuccessfull, revert and skip to the end of clause or
39407330f729Sjoerg       // directive.
39417330f729Sjoerg       TPA.Revert();
39427330f729Sjoerg       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
39437330f729Sjoerg                 StopBeforeMatch);
39447330f729Sjoerg     }
39457330f729Sjoerg   }
39467330f729Sjoerg 
39477330f729Sjoerg   bool IsComma =
39487330f729Sjoerg       (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
39497330f729Sjoerg        Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
39507330f729Sjoerg       (Kind == OMPC_reduction && !InvalidReductionId) ||
3951*e038c9c4Sjoerg       (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
3952*e038c9c4Sjoerg       (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown);
39537330f729Sjoerg   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
39547330f729Sjoerg   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
39557330f729Sjoerg                      Tok.isNot(tok::annot_pragma_openmp_end))) {
3956*e038c9c4Sjoerg     ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
39577330f729Sjoerg     ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
39587330f729Sjoerg     // Parse variable
39597330f729Sjoerg     ExprResult VarExpr =
39607330f729Sjoerg         Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
39617330f729Sjoerg     if (VarExpr.isUsable()) {
39627330f729Sjoerg       Vars.push_back(VarExpr.get());
39637330f729Sjoerg     } else {
39647330f729Sjoerg       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
39657330f729Sjoerg                 StopBeforeMatch);
39667330f729Sjoerg     }
39677330f729Sjoerg     // Skip ',' if any
39687330f729Sjoerg     IsComma = Tok.is(tok::comma);
39697330f729Sjoerg     if (IsComma)
39707330f729Sjoerg       ConsumeToken();
39717330f729Sjoerg     else if (Tok.isNot(tok::r_paren) &&
39727330f729Sjoerg              Tok.isNot(tok::annot_pragma_openmp_end) &&
39737330f729Sjoerg              (!MayHaveTail || Tok.isNot(tok::colon)))
39747330f729Sjoerg       Diag(Tok, diag::err_omp_expected_punc)
39757330f729Sjoerg           << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
39767330f729Sjoerg                                    : getOpenMPClauseName(Kind))
39777330f729Sjoerg           << (Kind == OMPC_flush);
39787330f729Sjoerg   }
39797330f729Sjoerg 
39807330f729Sjoerg   // Parse ')' for linear clause with modifier.
39817330f729Sjoerg   if (NeedRParenForLinear)
39827330f729Sjoerg     LinearT.consumeClose();
39837330f729Sjoerg 
39847330f729Sjoerg   // Parse ':' linear-step (or ':' alignment).
39857330f729Sjoerg   const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
39867330f729Sjoerg   if (MustHaveTail) {
39877330f729Sjoerg     Data.ColonLoc = Tok.getLocation();
39887330f729Sjoerg     SourceLocation ELoc = ConsumeToken();
39897330f729Sjoerg     ExprResult Tail = ParseAssignmentExpression();
39907330f729Sjoerg     Tail =
39917330f729Sjoerg         Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
39927330f729Sjoerg     if (Tail.isUsable())
3993*e038c9c4Sjoerg       Data.DepModOrTailExpr = Tail.get();
39947330f729Sjoerg     else
39957330f729Sjoerg       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
39967330f729Sjoerg                 StopBeforeMatch);
39977330f729Sjoerg   }
39987330f729Sjoerg 
39997330f729Sjoerg   // Parse ')'.
40007330f729Sjoerg   Data.RLoc = Tok.getLocation();
40017330f729Sjoerg   if (!T.consumeClose())
40027330f729Sjoerg     Data.RLoc = T.getCloseLocation();
4003*e038c9c4Sjoerg   // Exit from scope when the iterator is used in depend clause.
4004*e038c9c4Sjoerg   if (HasIterator)
4005*e038c9c4Sjoerg     ExitScope();
4006*e038c9c4Sjoerg   return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
4007*e038c9c4Sjoerg          (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId ||
40087330f729Sjoerg          IsInvalidMapperModifier;
40097330f729Sjoerg }
40107330f729Sjoerg 
40117330f729Sjoerg /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
4012*e038c9c4Sjoerg /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction',
4013*e038c9c4Sjoerg /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'.
40147330f729Sjoerg ///
40157330f729Sjoerg ///    private-clause:
40167330f729Sjoerg ///       'private' '(' list ')'
40177330f729Sjoerg ///    firstprivate-clause:
40187330f729Sjoerg ///       'firstprivate' '(' list ')'
40197330f729Sjoerg ///    lastprivate-clause:
40207330f729Sjoerg ///       'lastprivate' '(' list ')'
40217330f729Sjoerg ///    shared-clause:
40227330f729Sjoerg ///       'shared' '(' list ')'
40237330f729Sjoerg ///    linear-clause:
40247330f729Sjoerg ///       'linear' '(' linear-list [ ':' linear-step ] ')'
40257330f729Sjoerg ///    aligned-clause:
40267330f729Sjoerg ///       'aligned' '(' list [ ':' alignment ] ')'
40277330f729Sjoerg ///    reduction-clause:
4028*e038c9c4Sjoerg ///       'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')'
40297330f729Sjoerg ///    task_reduction-clause:
40307330f729Sjoerg ///       'task_reduction' '(' reduction-identifier ':' list ')'
40317330f729Sjoerg ///    in_reduction-clause:
40327330f729Sjoerg ///       'in_reduction' '(' reduction-identifier ':' list ')'
40337330f729Sjoerg ///    copyprivate-clause:
40347330f729Sjoerg ///       'copyprivate' '(' list ')'
40357330f729Sjoerg ///    flush-clause:
40367330f729Sjoerg ///       'flush' '(' list ')'
40377330f729Sjoerg ///    depend-clause:
40387330f729Sjoerg ///       'depend' '(' in | out | inout : list | source ')'
40397330f729Sjoerg ///    map-clause:
40407330f729Sjoerg ///       'map' '(' [ [ always [,] ] [ close [,] ]
40417330f729Sjoerg ///          [ mapper '(' mapper-identifier ')' [,] ]
40427330f729Sjoerg ///          to | from | tofrom | alloc | release | delete ':' ] list ')';
40437330f729Sjoerg ///    to-clause:
40447330f729Sjoerg ///       'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
40457330f729Sjoerg ///    from-clause:
40467330f729Sjoerg ///       'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
40477330f729Sjoerg ///    use_device_ptr-clause:
40487330f729Sjoerg ///       'use_device_ptr' '(' list ')'
4049*e038c9c4Sjoerg ///    use_device_addr-clause:
4050*e038c9c4Sjoerg ///       'use_device_addr' '(' list ')'
40517330f729Sjoerg ///    is_device_ptr-clause:
40527330f729Sjoerg ///       'is_device_ptr' '(' list ')'
40537330f729Sjoerg ///    allocate-clause:
40547330f729Sjoerg ///       'allocate' '(' [ allocator ':' ] list ')'
4055*e038c9c4Sjoerg ///    nontemporal-clause:
4056*e038c9c4Sjoerg ///       'nontemporal' '(' list ')'
4057*e038c9c4Sjoerg ///    inclusive-clause:
4058*e038c9c4Sjoerg ///       'inclusive' '(' list ')'
4059*e038c9c4Sjoerg ///    exclusive-clause:
4060*e038c9c4Sjoerg ///       'exclusive' '(' list ')'
40617330f729Sjoerg ///
40627330f729Sjoerg /// For 'linear' clause linear-list may have the following forms:
40637330f729Sjoerg ///  list
40647330f729Sjoerg ///  modifier(list)
40657330f729Sjoerg /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,bool ParseOnly)40667330f729Sjoerg OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
40677330f729Sjoerg                                             OpenMPClauseKind Kind,
40687330f729Sjoerg                                             bool ParseOnly) {
40697330f729Sjoerg   SourceLocation Loc = Tok.getLocation();
40707330f729Sjoerg   SourceLocation LOpen = ConsumeToken();
40717330f729Sjoerg   SmallVector<Expr *, 4> Vars;
40727330f729Sjoerg   OpenMPVarListDataTy Data;
40737330f729Sjoerg 
40747330f729Sjoerg   if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
40757330f729Sjoerg     return nullptr;
40767330f729Sjoerg 
40777330f729Sjoerg   if (ParseOnly)
40787330f729Sjoerg     return nullptr;
40797330f729Sjoerg   OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
40807330f729Sjoerg   return Actions.ActOnOpenMPVarListClause(
4081*e038c9c4Sjoerg       Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc,
4082*e038c9c4Sjoerg       Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
4083*e038c9c4Sjoerg       Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
4084*e038c9c4Sjoerg       Data.IsMapTypeImplicit, Data.ExtraModifierLoc, Data.MotionModifiers,
4085*e038c9c4Sjoerg       Data.MotionModifiersLoc);
40867330f729Sjoerg }
4087