xref: /freebsd/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric /// This file implements parsing of all OpenMP directives and clauses.
100b57cec5SDimitry Andric ///
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
145ffd83dbSDimitry Andric #include "clang/AST/OpenMPClause.h"
150b57cec5SDimitry Andric #include "clang/AST/StmtOpenMP.h"
16480093f4SDimitry Andric #include "clang/Basic/OpenMPKinds.h"
175ffd83dbSDimitry Andric #include "clang/Basic/TargetInfo.h"
185ffd83dbSDimitry Andric #include "clang/Basic/TokenKinds.h"
190b57cec5SDimitry Andric #include "clang/Parse/ParseDiagnostic.h"
200b57cec5SDimitry Andric #include "clang/Parse/Parser.h"
210b57cec5SDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h"
2206c3fb27SDimitry Andric #include "clang/Sema/EnterExpressionEvaluationContext.h"
230b57cec5SDimitry Andric #include "clang/Sema/Scope.h"
24*0fca6ea1SDimitry Andric #include "clang/Sema/SemaAMDGPU.h"
25*0fca6ea1SDimitry Andric #include "clang/Sema/SemaCodeCompletion.h"
26*0fca6ea1SDimitry Andric #include "clang/Sema/SemaOpenMP.h"
27*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallBitVector.h"
28e8d8bef9SDimitry Andric #include "llvm/ADT/StringSwitch.h"
2904eeddc0SDimitry Andric #include "llvm/Frontend/OpenMP/OMPAssume.h"
305ffd83dbSDimitry Andric #include "llvm/Frontend/OpenMP/OMPContext.h"
31bdd1243dSDimitry Andric #include <optional>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace clang;
34480093f4SDimitry Andric using namespace llvm::omp;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
370b57cec5SDimitry Andric // OpenMP declarative directives.
380b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric namespace {
410b57cec5SDimitry Andric enum OpenMPDirectiveKindEx {
425ffd83dbSDimitry Andric   OMPD_cancellation = llvm::omp::Directive_enumSize + 1,
430b57cec5SDimitry Andric   OMPD_data,
440b57cec5SDimitry Andric   OMPD_declare,
450b57cec5SDimitry Andric   OMPD_end,
460b57cec5SDimitry Andric   OMPD_end_declare,
470b57cec5SDimitry Andric   OMPD_enter,
480b57cec5SDimitry Andric   OMPD_exit,
490b57cec5SDimitry Andric   OMPD_point,
500b57cec5SDimitry Andric   OMPD_reduction,
510b57cec5SDimitry Andric   OMPD_target_enter,
520b57cec5SDimitry Andric   OMPD_target_exit,
530b57cec5SDimitry Andric   OMPD_update,
540b57cec5SDimitry Andric   OMPD_distribute_parallel,
550b57cec5SDimitry Andric   OMPD_teams_distribute_parallel,
560b57cec5SDimitry Andric   OMPD_target_teams_distribute_parallel,
570b57cec5SDimitry Andric   OMPD_mapper,
58a7dea167SDimitry Andric   OMPD_variant,
595ffd83dbSDimitry Andric   OMPD_begin,
605ffd83dbSDimitry Andric   OMPD_begin_declare,
61480093f4SDimitry Andric };
62480093f4SDimitry Andric 
63480093f4SDimitry Andric // Helper to unify the enum class OpenMPDirectiveKind with its extension
64480093f4SDimitry Andric // the OpenMPDirectiveKindEx enum which allows to use them together as if they
65480093f4SDimitry Andric // are unsigned values.
66480093f4SDimitry Andric struct OpenMPDirectiveKindExWrapper {
OpenMPDirectiveKindExWrapper__anon6a7266ce0111::OpenMPDirectiveKindExWrapper67480093f4SDimitry Andric   OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
OpenMPDirectiveKindExWrapper__anon6a7266ce0111::OpenMPDirectiveKindExWrapper68480093f4SDimitry Andric   OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
operator ==__anon6a7266ce0111::OpenMPDirectiveKindExWrapper69e8d8bef9SDimitry Andric   bool operator==(OpenMPDirectiveKindExWrapper V) const {
70e8d8bef9SDimitry Andric     return Value == V.Value;
71e8d8bef9SDimitry Andric   }
operator !=__anon6a7266ce0111::OpenMPDirectiveKindExWrapper72e8d8bef9SDimitry Andric   bool operator!=(OpenMPDirectiveKindExWrapper V) const {
73e8d8bef9SDimitry Andric     return Value != V.Value;
74e8d8bef9SDimitry Andric   }
operator ==__anon6a7266ce0111::OpenMPDirectiveKindExWrapper75480093f4SDimitry Andric   bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
operator !=__anon6a7266ce0111::OpenMPDirectiveKindExWrapper76480093f4SDimitry Andric   bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
operator <__anon6a7266ce0111::OpenMPDirectiveKindExWrapper77480093f4SDimitry Andric   bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
operator unsigned__anon6a7266ce0111::OpenMPDirectiveKindExWrapper78480093f4SDimitry Andric   operator unsigned() const { return Value; }
operator OpenMPDirectiveKind__anon6a7266ce0111::OpenMPDirectiveKindExWrapper79480093f4SDimitry Andric   operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
80480093f4SDimitry Andric   unsigned Value;
810b57cec5SDimitry Andric };
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric class DeclDirectiveListParserHelper final {
840b57cec5SDimitry Andric   SmallVector<Expr *, 4> Identifiers;
850b57cec5SDimitry Andric   Parser *P;
860b57cec5SDimitry Andric   OpenMPDirectiveKind Kind;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric public:
DeclDirectiveListParserHelper(Parser * P,OpenMPDirectiveKind Kind)890b57cec5SDimitry Andric   DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
900b57cec5SDimitry Andric       : P(P), Kind(Kind) {}
operator ()(CXXScopeSpec & SS,DeclarationNameInfo NameInfo)910b57cec5SDimitry Andric   void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
92*0fca6ea1SDimitry Andric     ExprResult Res = P->getActions().OpenMP().ActOnOpenMPIdExpression(
930b57cec5SDimitry Andric         P->getCurScope(), SS, NameInfo, Kind);
940b57cec5SDimitry Andric     if (Res.isUsable())
950b57cec5SDimitry Andric       Identifiers.push_back(Res.get());
960b57cec5SDimitry Andric   }
getIdentifiers() const970b57cec5SDimitry Andric   llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
980b57cec5SDimitry Andric };
990b57cec5SDimitry Andric } // namespace
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric // Map token string to extended OMP token kind that are
1020b57cec5SDimitry Andric // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
getOpenMPDirectiveKindEx(StringRef S)1030b57cec5SDimitry Andric static unsigned getOpenMPDirectiveKindEx(StringRef S) {
104480093f4SDimitry Andric   OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
1050b57cec5SDimitry Andric   if (DKind != OMPD_unknown)
1060b57cec5SDimitry Andric     return DKind;
1070b57cec5SDimitry Andric 
108480093f4SDimitry Andric   return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
1090b57cec5SDimitry Andric       .Case("cancellation", OMPD_cancellation)
1100b57cec5SDimitry Andric       .Case("data", OMPD_data)
1110b57cec5SDimitry Andric       .Case("declare", OMPD_declare)
1120b57cec5SDimitry Andric       .Case("end", OMPD_end)
1130b57cec5SDimitry Andric       .Case("enter", OMPD_enter)
1140b57cec5SDimitry Andric       .Case("exit", OMPD_exit)
1150b57cec5SDimitry Andric       .Case("point", OMPD_point)
1160b57cec5SDimitry Andric       .Case("reduction", OMPD_reduction)
1170b57cec5SDimitry Andric       .Case("update", OMPD_update)
1180b57cec5SDimitry Andric       .Case("mapper", OMPD_mapper)
119a7dea167SDimitry Andric       .Case("variant", OMPD_variant)
1205ffd83dbSDimitry Andric       .Case("begin", OMPD_begin)
1210b57cec5SDimitry Andric       .Default(OMPD_unknown);
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
parseOpenMPDirectiveKind(Parser & P)124480093f4SDimitry Andric static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
1250b57cec5SDimitry Andric   // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
1260b57cec5SDimitry Andric   // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
1270b57cec5SDimitry Andric   // TODO: add other combined directives in topological order.
128480093f4SDimitry Andric   static const OpenMPDirectiveKindExWrapper F[][3] = {
1295ffd83dbSDimitry Andric       {OMPD_begin, OMPD_declare, OMPD_begin_declare},
130e8d8bef9SDimitry Andric       {OMPD_begin, OMPD_assumes, OMPD_begin_assumes},
1315ffd83dbSDimitry Andric       {OMPD_end, OMPD_declare, OMPD_end_declare},
132e8d8bef9SDimitry Andric       {OMPD_end, OMPD_assumes, OMPD_end_assumes},
1330b57cec5SDimitry Andric       {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
1340b57cec5SDimitry Andric       {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
1350b57cec5SDimitry Andric       {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
1360b57cec5SDimitry Andric       {OMPD_declare, OMPD_simd, OMPD_declare_simd},
1370b57cec5SDimitry Andric       {OMPD_declare, OMPD_target, OMPD_declare_target},
138a7dea167SDimitry Andric       {OMPD_declare, OMPD_variant, OMPD_declare_variant},
139fe6060f1SDimitry Andric       {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
1405ffd83dbSDimitry Andric       {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
1415ffd83dbSDimitry Andric       {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
1420b57cec5SDimitry Andric       {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
1430b57cec5SDimitry Andric       {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
1440b57cec5SDimitry Andric       {OMPD_distribute_parallel_for, OMPD_simd,
1450b57cec5SDimitry Andric        OMPD_distribute_parallel_for_simd},
1460b57cec5SDimitry Andric       {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
1470b57cec5SDimitry Andric       {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
1480b57cec5SDimitry Andric       {OMPD_target, OMPD_data, OMPD_target_data},
1490b57cec5SDimitry Andric       {OMPD_target, OMPD_enter, OMPD_target_enter},
1500b57cec5SDimitry Andric       {OMPD_target, OMPD_exit, OMPD_target_exit},
1510b57cec5SDimitry Andric       {OMPD_target, OMPD_update, OMPD_target_update},
1520b57cec5SDimitry Andric       {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
1530b57cec5SDimitry Andric       {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
1540b57cec5SDimitry Andric       {OMPD_for, OMPD_simd, OMPD_for_simd},
1550b57cec5SDimitry Andric       {OMPD_parallel, OMPD_for, OMPD_parallel_for},
1560b57cec5SDimitry Andric       {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
15781ad6265SDimitry Andric       {OMPD_parallel, OMPD_loop, OMPD_parallel_loop},
1580b57cec5SDimitry Andric       {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
1590b57cec5SDimitry Andric       {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
1600b57cec5SDimitry Andric       {OMPD_target, OMPD_parallel, OMPD_target_parallel},
1610b57cec5SDimitry Andric       {OMPD_target, OMPD_simd, OMPD_target_simd},
16281ad6265SDimitry Andric       {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop},
1630b57cec5SDimitry Andric       {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
1640b57cec5SDimitry Andric       {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
1650b57cec5SDimitry Andric       {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
1660b57cec5SDimitry Andric       {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
1670b57cec5SDimitry Andric       {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
1680b57cec5SDimitry Andric       {OMPD_teams_distribute_parallel, OMPD_for,
1690b57cec5SDimitry Andric        OMPD_teams_distribute_parallel_for},
1700b57cec5SDimitry Andric       {OMPD_teams_distribute_parallel_for, OMPD_simd,
1710b57cec5SDimitry Andric        OMPD_teams_distribute_parallel_for_simd},
17281ad6265SDimitry Andric       {OMPD_teams, OMPD_loop, OMPD_teams_loop},
1730b57cec5SDimitry Andric       {OMPD_target, OMPD_teams, OMPD_target_teams},
1740b57cec5SDimitry Andric       {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
17581ad6265SDimitry Andric       {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop},
1760b57cec5SDimitry Andric       {OMPD_target_teams_distribute, OMPD_parallel,
1770b57cec5SDimitry Andric        OMPD_target_teams_distribute_parallel},
1780b57cec5SDimitry Andric       {OMPD_target_teams_distribute, OMPD_simd,
1790b57cec5SDimitry Andric        OMPD_target_teams_distribute_simd},
1800b57cec5SDimitry Andric       {OMPD_target_teams_distribute_parallel, OMPD_for,
1810b57cec5SDimitry Andric        OMPD_target_teams_distribute_parallel_for},
1820b57cec5SDimitry Andric       {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
183a7dea167SDimitry Andric        OMPD_target_teams_distribute_parallel_for_simd},
184a7dea167SDimitry Andric       {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
18581ad6265SDimitry Andric       {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop},
186a7dea167SDimitry Andric       {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
18781ad6265SDimitry Andric       {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd},
188a7dea167SDimitry Andric       {OMPD_parallel, OMPD_master, OMPD_parallel_master},
18981ad6265SDimitry Andric       {OMPD_parallel, OMPD_masked, OMPD_parallel_masked},
190480093f4SDimitry Andric       {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
19181ad6265SDimitry Andric       {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop},
192480093f4SDimitry Andric       {OMPD_parallel_master_taskloop, OMPD_simd,
19381ad6265SDimitry Andric        OMPD_parallel_master_taskloop_simd},
19481ad6265SDimitry Andric       {OMPD_parallel_masked_taskloop, OMPD_simd,
19581ad6265SDimitry Andric        OMPD_parallel_masked_taskloop_simd}};
1960b57cec5SDimitry Andric   enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
1970b57cec5SDimitry Andric   Token Tok = P.getCurToken();
198480093f4SDimitry Andric   OpenMPDirectiveKindExWrapper DKind =
1990b57cec5SDimitry Andric       Tok.isAnnotation()
2000b57cec5SDimitry Andric           ? static_cast<unsigned>(OMPD_unknown)
2010b57cec5SDimitry Andric           : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
2020b57cec5SDimitry Andric   if (DKind == OMPD_unknown)
2030b57cec5SDimitry Andric     return OMPD_unknown;
2040b57cec5SDimitry Andric 
205bdd1243dSDimitry Andric   for (const auto &I : F) {
206bdd1243dSDimitry Andric     if (DKind != I[0])
2070b57cec5SDimitry Andric       continue;
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     Tok = P.getPreprocessor().LookAhead(0);
210480093f4SDimitry Andric     OpenMPDirectiveKindExWrapper SDKind =
2110b57cec5SDimitry Andric         Tok.isAnnotation()
2120b57cec5SDimitry Andric             ? static_cast<unsigned>(OMPD_unknown)
2130b57cec5SDimitry Andric             : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
2140b57cec5SDimitry Andric     if (SDKind == OMPD_unknown)
2150b57cec5SDimitry Andric       continue;
2160b57cec5SDimitry Andric 
217bdd1243dSDimitry Andric     if (SDKind == I[1]) {
2180b57cec5SDimitry Andric       P.ConsumeToken();
219bdd1243dSDimitry Andric       DKind = I[2];
2200b57cec5SDimitry Andric     }
2210b57cec5SDimitry Andric   }
2225ffd83dbSDimitry Andric   return unsigned(DKind) < llvm::omp::Directive_enumSize
2235ffd83dbSDimitry Andric              ? static_cast<OpenMPDirectiveKind>(DKind)
2240b57cec5SDimitry Andric              : OMPD_unknown;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
parseOpenMPReductionId(Parser & P)2270b57cec5SDimitry Andric static DeclarationName parseOpenMPReductionId(Parser &P) {
2280b57cec5SDimitry Andric   Token Tok = P.getCurToken();
2290b57cec5SDimitry Andric   Sema &Actions = P.getActions();
2300b57cec5SDimitry Andric   OverloadedOperatorKind OOK = OO_None;
2310b57cec5SDimitry Andric   // Allow to use 'operator' keyword for C++ operators
2320b57cec5SDimitry Andric   bool WithOperator = false;
2330b57cec5SDimitry Andric   if (Tok.is(tok::kw_operator)) {
2340b57cec5SDimitry Andric     P.ConsumeToken();
2350b57cec5SDimitry Andric     Tok = P.getCurToken();
2360b57cec5SDimitry Andric     WithOperator = true;
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric   switch (Tok.getKind()) {
2390b57cec5SDimitry Andric   case tok::plus: // '+'
2400b57cec5SDimitry Andric     OOK = OO_Plus;
2410b57cec5SDimitry Andric     break;
2420b57cec5SDimitry Andric   case tok::minus: // '-'
2430b57cec5SDimitry Andric     OOK = OO_Minus;
2440b57cec5SDimitry Andric     break;
2450b57cec5SDimitry Andric   case tok::star: // '*'
2460b57cec5SDimitry Andric     OOK = OO_Star;
2470b57cec5SDimitry Andric     break;
2480b57cec5SDimitry Andric   case tok::amp: // '&'
2490b57cec5SDimitry Andric     OOK = OO_Amp;
2500b57cec5SDimitry Andric     break;
2510b57cec5SDimitry Andric   case tok::pipe: // '|'
2520b57cec5SDimitry Andric     OOK = OO_Pipe;
2530b57cec5SDimitry Andric     break;
2540b57cec5SDimitry Andric   case tok::caret: // '^'
2550b57cec5SDimitry Andric     OOK = OO_Caret;
2560b57cec5SDimitry Andric     break;
2570b57cec5SDimitry Andric   case tok::ampamp: // '&&'
2580b57cec5SDimitry Andric     OOK = OO_AmpAmp;
2590b57cec5SDimitry Andric     break;
2600b57cec5SDimitry Andric   case tok::pipepipe: // '||'
2610b57cec5SDimitry Andric     OOK = OO_PipePipe;
2620b57cec5SDimitry Andric     break;
2630b57cec5SDimitry Andric   case tok::identifier: // identifier
2640b57cec5SDimitry Andric     if (!WithOperator)
2650b57cec5SDimitry Andric       break;
266bdd1243dSDimitry Andric     [[fallthrough]];
2670b57cec5SDimitry Andric   default:
2680b57cec5SDimitry Andric     P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
2690b57cec5SDimitry Andric     P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2700b57cec5SDimitry Andric                 Parser::StopBeforeMatch);
2710b57cec5SDimitry Andric     return DeclarationName();
2720b57cec5SDimitry Andric   }
2730b57cec5SDimitry Andric   P.ConsumeToken();
2740b57cec5SDimitry Andric   auto &DeclNames = Actions.getASTContext().DeclarationNames;
2750b57cec5SDimitry Andric   return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
2760b57cec5SDimitry Andric                         : DeclNames.getCXXOperatorName(OOK);
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric /// Parse 'omp declare reduction' construct.
2800b57cec5SDimitry Andric ///
2810b57cec5SDimitry Andric ///       declare-reduction-directive:
2820b57cec5SDimitry Andric ///        annot_pragma_openmp 'declare' 'reduction'
2830b57cec5SDimitry Andric ///        '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
2840b57cec5SDimitry Andric ///        ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
2850b57cec5SDimitry Andric ///        annot_pragma_openmp_end
2860b57cec5SDimitry Andric /// <reduction_id> is either a base language identifier or one of the following
2870b57cec5SDimitry Andric /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
2880b57cec5SDimitry Andric ///
2890b57cec5SDimitry Andric Parser::DeclGroupPtrTy
ParseOpenMPDeclareReductionDirective(AccessSpecifier AS)2900b57cec5SDimitry Andric Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
2910b57cec5SDimitry Andric   // Parse '('.
2920b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
293480093f4SDimitry Andric   if (T.expectAndConsume(
294480093f4SDimitry Andric           diag::err_expected_lparen_after,
295480093f4SDimitry Andric           getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
2960b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
2970b57cec5SDimitry Andric     return DeclGroupPtrTy();
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   DeclarationName Name = parseOpenMPReductionId(*this);
3010b57cec5SDimitry Andric   if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
3020b57cec5SDimitry Andric     return DeclGroupPtrTy();
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   // Consume ':'.
3050b57cec5SDimitry Andric   bool IsCorrect = !ExpectAndConsume(tok::colon);
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
3080b57cec5SDimitry Andric     return DeclGroupPtrTy();
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   IsCorrect = IsCorrect && !Name.isEmpty();
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
3130b57cec5SDimitry Andric     Diag(Tok.getLocation(), diag::err_expected_type);
3140b57cec5SDimitry Andric     IsCorrect = false;
3150b57cec5SDimitry Andric   }
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
3180b57cec5SDimitry Andric     return DeclGroupPtrTy();
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
3210b57cec5SDimitry Andric   // Parse list of types until ':' token.
3220b57cec5SDimitry Andric   do {
3230b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
3240b57cec5SDimitry Andric     SourceRange Range;
325e8d8bef9SDimitry Andric     TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS);
3260b57cec5SDimitry Andric     if (TR.isUsable()) {
327*0fca6ea1SDimitry Andric       QualType ReductionType = Actions.OpenMP().ActOnOpenMPDeclareReductionType(
328*0fca6ea1SDimitry Andric           Range.getBegin(), TR);
3290b57cec5SDimitry Andric       if (!ReductionType.isNull()) {
3300b57cec5SDimitry Andric         ReductionTypes.push_back(
3310b57cec5SDimitry Andric             std::make_pair(ReductionType, Range.getBegin()));
3320b57cec5SDimitry Andric       }
3330b57cec5SDimitry Andric     } else {
3340b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
3350b57cec5SDimitry Andric                 StopBeforeMatch);
3360b57cec5SDimitry Andric     }
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric     if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
3390b57cec5SDimitry Andric       break;
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     // Consume ','.
3420b57cec5SDimitry Andric     if (ExpectAndConsume(tok::comma)) {
3430b57cec5SDimitry Andric       IsCorrect = false;
3440b57cec5SDimitry Andric       if (Tok.is(tok::annot_pragma_openmp_end)) {
3450b57cec5SDimitry Andric         Diag(Tok.getLocation(), diag::err_expected_type);
3460b57cec5SDimitry Andric         return DeclGroupPtrTy();
3470b57cec5SDimitry Andric       }
3480b57cec5SDimitry Andric     }
3490b57cec5SDimitry Andric   } while (Tok.isNot(tok::annot_pragma_openmp_end));
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   if (ReductionTypes.empty()) {
3520b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
3530b57cec5SDimitry Andric     return DeclGroupPtrTy();
3540b57cec5SDimitry Andric   }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
3570b57cec5SDimitry Andric     return DeclGroupPtrTy();
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   // Consume ':'.
3600b57cec5SDimitry Andric   if (ExpectAndConsume(tok::colon))
3610b57cec5SDimitry Andric     IsCorrect = false;
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   if (Tok.is(tok::annot_pragma_openmp_end)) {
3640b57cec5SDimitry Andric     Diag(Tok.getLocation(), diag::err_expected_expression);
3650b57cec5SDimitry Andric     return DeclGroupPtrTy();
3660b57cec5SDimitry Andric   }
3670b57cec5SDimitry Andric 
368*0fca6ea1SDimitry Andric   DeclGroupPtrTy DRD =
369*0fca6ea1SDimitry Andric       Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveStart(
370*0fca6ea1SDimitry Andric           getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes,
371*0fca6ea1SDimitry Andric           AS);
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric   // Parse <combiner> expression and then parse initializer if any for each
3740b57cec5SDimitry Andric   // correct type.
3750b57cec5SDimitry Andric   unsigned I = 0, E = ReductionTypes.size();
3760b57cec5SDimitry Andric   for (Decl *D : DRD.get()) {
3770b57cec5SDimitry Andric     TentativeParsingAction TPA(*this);
3780b57cec5SDimitry Andric     ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
3790b57cec5SDimitry Andric                                     Scope::CompoundStmtScope |
3800b57cec5SDimitry Andric                                     Scope::OpenMPDirectiveScope);
3810b57cec5SDimitry Andric     // Parse <combiner> expression.
382*0fca6ea1SDimitry Andric     Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
383480093f4SDimitry Andric     ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
384480093f4SDimitry Andric         ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
385*0fca6ea1SDimitry Andric     Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerEnd(
386*0fca6ea1SDimitry Andric         D, CombinerResult.get());
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric     if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
3890b57cec5SDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end)) {
3900b57cec5SDimitry Andric       TPA.Commit();
3910b57cec5SDimitry Andric       IsCorrect = false;
3920b57cec5SDimitry Andric       break;
3930b57cec5SDimitry Andric     }
3940b57cec5SDimitry Andric     IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
3950b57cec5SDimitry Andric     ExprResult InitializerResult;
3960b57cec5SDimitry Andric     if (Tok.isNot(tok::annot_pragma_openmp_end)) {
3970b57cec5SDimitry Andric       // Parse <initializer> expression.
3980b57cec5SDimitry Andric       if (Tok.is(tok::identifier) &&
3990b57cec5SDimitry Andric           Tok.getIdentifierInfo()->isStr("initializer")) {
4000b57cec5SDimitry Andric         ConsumeToken();
4010b57cec5SDimitry Andric       } else {
4020b57cec5SDimitry Andric         Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
4030b57cec5SDimitry Andric         TPA.Commit();
4040b57cec5SDimitry Andric         IsCorrect = false;
4050b57cec5SDimitry Andric         break;
4060b57cec5SDimitry Andric       }
4070b57cec5SDimitry Andric       // Parse '('.
4080b57cec5SDimitry Andric       BalancedDelimiterTracker T(*this, tok::l_paren,
4090b57cec5SDimitry Andric                                  tok::annot_pragma_openmp_end);
4100b57cec5SDimitry Andric       IsCorrect =
4110b57cec5SDimitry Andric           !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
4120b57cec5SDimitry Andric           IsCorrect;
4130b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
4140b57cec5SDimitry Andric         ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
4150b57cec5SDimitry Andric                                         Scope::CompoundStmtScope |
4160b57cec5SDimitry Andric                                         Scope::OpenMPDirectiveScope);
4170b57cec5SDimitry Andric         // Parse expression.
4180b57cec5SDimitry Andric         VarDecl *OmpPrivParm =
419*0fca6ea1SDimitry Andric             Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerStart(
420*0fca6ea1SDimitry Andric                 getCurScope(), D);
4210b57cec5SDimitry Andric         // Check if initializer is omp_priv <init_expr> or something else.
4220b57cec5SDimitry Andric         if (Tok.is(tok::identifier) &&
4230b57cec5SDimitry Andric             Tok.getIdentifierInfo()->isStr("omp_priv")) {
4240b57cec5SDimitry Andric           ConsumeToken();
4250b57cec5SDimitry Andric           ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
4260b57cec5SDimitry Andric         } else {
4270b57cec5SDimitry Andric           InitializerResult = Actions.ActOnFinishFullExpr(
4280b57cec5SDimitry Andric               ParseAssignmentExpression().get(), D->getLocation(),
4290b57cec5SDimitry Andric               /*DiscardedValue*/ false);
4300b57cec5SDimitry Andric         }
431*0fca6ea1SDimitry Andric         Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerEnd(
4320b57cec5SDimitry Andric             D, InitializerResult.get(), OmpPrivParm);
4330b57cec5SDimitry Andric         if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
4340b57cec5SDimitry Andric             Tok.isNot(tok::annot_pragma_openmp_end)) {
4350b57cec5SDimitry Andric           TPA.Commit();
4360b57cec5SDimitry Andric           IsCorrect = false;
4370b57cec5SDimitry Andric           break;
4380b57cec5SDimitry Andric         }
4390b57cec5SDimitry Andric         IsCorrect =
4400b57cec5SDimitry Andric             !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
4410b57cec5SDimitry Andric       }
4420b57cec5SDimitry Andric     }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric     ++I;
4450b57cec5SDimitry Andric     // Revert parsing if not the last type, otherwise accept it, we're done with
4460b57cec5SDimitry Andric     // parsing.
4470b57cec5SDimitry Andric     if (I != E)
4480b57cec5SDimitry Andric       TPA.Revert();
4490b57cec5SDimitry Andric     else
4500b57cec5SDimitry Andric       TPA.Commit();
4510b57cec5SDimitry Andric   }
452*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveEnd(
453*0fca6ea1SDimitry Andric       getCurScope(), DRD, IsCorrect);
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric 
ParseOpenMPReductionInitializerForDecl(VarDecl * OmpPrivParm)4560b57cec5SDimitry Andric void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
4570b57cec5SDimitry Andric   // Parse declarator '=' initializer.
4580b57cec5SDimitry Andric   // If a '==' or '+=' is found, suggest a fixit to '='.
4590b57cec5SDimitry Andric   if (isTokenEqualOrEqualTypo()) {
4600b57cec5SDimitry Andric     ConsumeToken();
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
463fe6060f1SDimitry Andric       cutOffParsing();
464*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(),
465*0fca6ea1SDimitry Andric                                                        OmpPrivParm);
4660b57cec5SDimitry Andric       Actions.FinalizeDeclaration(OmpPrivParm);
4670b57cec5SDimitry Andric       return;
4680b57cec5SDimitry Andric     }
4690b57cec5SDimitry Andric 
470480093f4SDimitry Andric     PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
471480093f4SDimitry Andric     ExprResult Init = ParseInitializer();
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric     if (Init.isInvalid()) {
4740b57cec5SDimitry Andric       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
4750b57cec5SDimitry Andric       Actions.ActOnInitializerError(OmpPrivParm);
4760b57cec5SDimitry Andric     } else {
4770b57cec5SDimitry Andric       Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
4780b57cec5SDimitry Andric                                    /*DirectInit=*/false);
4790b57cec5SDimitry Andric     }
4800b57cec5SDimitry Andric   } else if (Tok.is(tok::l_paren)) {
4810b57cec5SDimitry Andric     // Parse C++ direct initializer: '(' expression-list ')'
4820b57cec5SDimitry Andric     BalancedDelimiterTracker T(*this, tok::l_paren);
4830b57cec5SDimitry Andric     T.consumeOpen();
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric     ExprVector Exprs;
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric     SourceLocation LParLoc = T.getOpenLocation();
4880b57cec5SDimitry Andric     auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
489*0fca6ea1SDimitry Andric       QualType PreferredType =
490*0fca6ea1SDimitry Andric           Actions.CodeCompletion().ProduceConstructorSignatureHelp(
49104eeddc0SDimitry Andric               OmpPrivParm->getType()->getCanonicalTypeInternal(),
49204eeddc0SDimitry Andric               OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
4930b57cec5SDimitry Andric       CalledSignatureHelp = true;
4940b57cec5SDimitry Andric       return PreferredType;
4950b57cec5SDimitry Andric     };
496bdd1243dSDimitry Andric     if (ParseExpressionList(Exprs, [&] {
4970b57cec5SDimitry Andric           PreferredType.enterFunctionArgument(Tok.getLocation(),
4980b57cec5SDimitry Andric                                               RunSignatureHelp);
4990b57cec5SDimitry Andric         })) {
5000b57cec5SDimitry Andric       if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
5010b57cec5SDimitry Andric         RunSignatureHelp();
5020b57cec5SDimitry Andric       Actions.ActOnInitializerError(OmpPrivParm);
5030b57cec5SDimitry Andric       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5040b57cec5SDimitry Andric     } else {
5050b57cec5SDimitry Andric       // Match the ')'.
5060b57cec5SDimitry Andric       SourceLocation RLoc = Tok.getLocation();
5070b57cec5SDimitry Andric       if (!T.consumeClose())
5080b57cec5SDimitry Andric         RLoc = T.getCloseLocation();
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric       ExprResult Initializer =
5110b57cec5SDimitry Andric           Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
5120b57cec5SDimitry Andric       Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
5130b57cec5SDimitry Andric                                    /*DirectInit=*/true);
5140b57cec5SDimitry Andric     }
5150b57cec5SDimitry Andric   } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
5160b57cec5SDimitry Andric     // Parse C++0x braced-init-list.
5170b57cec5SDimitry Andric     Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric     ExprResult Init(ParseBraceInitializer());
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric     if (Init.isInvalid()) {
5220b57cec5SDimitry Andric       Actions.ActOnInitializerError(OmpPrivParm);
5230b57cec5SDimitry Andric     } else {
5240b57cec5SDimitry Andric       Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
5250b57cec5SDimitry Andric                                    /*DirectInit=*/true);
5260b57cec5SDimitry Andric     }
5270b57cec5SDimitry Andric   } else {
5280b57cec5SDimitry Andric     Actions.ActOnUninitializedDecl(OmpPrivParm);
5290b57cec5SDimitry Andric   }
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric /// Parses 'omp declare mapper' directive.
5330b57cec5SDimitry Andric ///
5340b57cec5SDimitry Andric ///       declare-mapper-directive:
5350b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
5360b57cec5SDimitry Andric ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
5370b57cec5SDimitry Andric ///         annot_pragma_openmp_end
5380b57cec5SDimitry Andric /// <mapper-identifier> and <var> are base language identifiers.
5390b57cec5SDimitry Andric ///
5400b57cec5SDimitry Andric Parser::DeclGroupPtrTy
ParseOpenMPDeclareMapperDirective(AccessSpecifier AS)5410b57cec5SDimitry Andric Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
5420b57cec5SDimitry Andric   bool IsCorrect = true;
5430b57cec5SDimitry Andric   // Parse '('
5440b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5450b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
546480093f4SDimitry Andric                          getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
5470b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
5480b57cec5SDimitry Andric     return DeclGroupPtrTy();
5490b57cec5SDimitry Andric   }
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric   // Parse <mapper-identifier>
5520b57cec5SDimitry Andric   auto &DeclNames = Actions.getASTContext().DeclarationNames;
5530b57cec5SDimitry Andric   DeclarationName MapperId;
5540b57cec5SDimitry Andric   if (PP.LookAhead(0).is(tok::colon)) {
5550b57cec5SDimitry Andric     if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
5560b57cec5SDimitry Andric       Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
5570b57cec5SDimitry Andric       IsCorrect = false;
5580b57cec5SDimitry Andric     } else {
5590b57cec5SDimitry Andric       MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
5600b57cec5SDimitry Andric     }
5610b57cec5SDimitry Andric     ConsumeToken();
5620b57cec5SDimitry Andric     // Consume ':'.
5630b57cec5SDimitry Andric     ExpectAndConsume(tok::colon);
5640b57cec5SDimitry Andric   } else {
5650b57cec5SDimitry Andric     // If no mapper identifier is provided, its name is "default" by default
5660b57cec5SDimitry Andric     MapperId =
5670b57cec5SDimitry Andric         DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
5680b57cec5SDimitry Andric   }
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
5710b57cec5SDimitry Andric     return DeclGroupPtrTy();
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric   // Parse <type> <var>
5740b57cec5SDimitry Andric   DeclarationName VName;
5750b57cec5SDimitry Andric   QualType MapperType;
5760b57cec5SDimitry Andric   SourceRange Range;
5770b57cec5SDimitry Andric   TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
5780b57cec5SDimitry Andric   if (ParsedType.isUsable())
579*0fca6ea1SDimitry Andric     MapperType = Actions.OpenMP().ActOnOpenMPDeclareMapperType(Range.getBegin(),
580*0fca6ea1SDimitry Andric                                                                ParsedType);
5810b57cec5SDimitry Andric   if (MapperType.isNull())
5820b57cec5SDimitry Andric     IsCorrect = false;
5830b57cec5SDimitry Andric   if (!IsCorrect) {
5840b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
5850b57cec5SDimitry Andric     return DeclGroupPtrTy();
5860b57cec5SDimitry Andric   }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   // Consume ')'.
5890b57cec5SDimitry Andric   IsCorrect &= !T.consumeClose();
5900b57cec5SDimitry Andric   if (!IsCorrect) {
5910b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
5920b57cec5SDimitry Andric     return DeclGroupPtrTy();
5930b57cec5SDimitry Andric   }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   // Enter scope.
5960b57cec5SDimitry Andric   DeclarationNameInfo DirName;
5970b57cec5SDimitry Andric   SourceLocation Loc = Tok.getLocation();
5980b57cec5SDimitry Andric   unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
5990b57cec5SDimitry Andric                         Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
6000b57cec5SDimitry Andric   ParseScope OMPDirectiveScope(this, ScopeFlags);
601*0fca6ea1SDimitry Andric   Actions.OpenMP().StartOpenMPDSABlock(OMPD_declare_mapper, DirName,
602*0fca6ea1SDimitry Andric                                        getCurScope(), Loc);
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   // Add the mapper variable declaration.
605*0fca6ea1SDimitry Andric   ExprResult MapperVarRef =
606*0fca6ea1SDimitry Andric       Actions.OpenMP().ActOnOpenMPDeclareMapperDirectiveVarDecl(
607e8d8bef9SDimitry Andric           getCurScope(), MapperType, Range.getBegin(), VName);
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric   // Parse map clauses.
6100b57cec5SDimitry Andric   SmallVector<OMPClause *, 6> Clauses;
6110b57cec5SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
6120b57cec5SDimitry Andric     OpenMPClauseKind CKind = Tok.isAnnotation()
6130b57cec5SDimitry Andric                                  ? OMPC_unknown
6140b57cec5SDimitry Andric                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
615*0fca6ea1SDimitry Andric     Actions.OpenMP().StartOpenMPClause(CKind);
6160b57cec5SDimitry Andric     OMPClause *Clause =
617e8d8bef9SDimitry Andric         ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
6180b57cec5SDimitry Andric     if (Clause)
6190b57cec5SDimitry Andric       Clauses.push_back(Clause);
6200b57cec5SDimitry Andric     else
6210b57cec5SDimitry Andric       IsCorrect = false;
6220b57cec5SDimitry Andric     // Skip ',' if any.
6230b57cec5SDimitry Andric     if (Tok.is(tok::comma))
6240b57cec5SDimitry Andric       ConsumeToken();
625*0fca6ea1SDimitry Andric     Actions.OpenMP().EndOpenMPClause();
6260b57cec5SDimitry Andric   }
6270b57cec5SDimitry Andric   if (Clauses.empty()) {
6280b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_expected_clause)
6290b57cec5SDimitry Andric         << getOpenMPDirectiveName(OMPD_declare_mapper);
6300b57cec5SDimitry Andric     IsCorrect = false;
6310b57cec5SDimitry Andric   }
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   // Exit scope.
634*0fca6ea1SDimitry Andric   Actions.OpenMP().EndOpenMPDSABlock(nullptr);
6350b57cec5SDimitry Andric   OMPDirectiveScope.Exit();
636*0fca6ea1SDimitry Andric   DeclGroupPtrTy DG = Actions.OpenMP().ActOnOpenMPDeclareMapperDirective(
637e8d8bef9SDimitry Andric       getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
638e8d8bef9SDimitry Andric       Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);
6390b57cec5SDimitry Andric   if (!IsCorrect)
6400b57cec5SDimitry Andric     return DeclGroupPtrTy();
641e8d8bef9SDimitry Andric 
642e8d8bef9SDimitry Andric   return DG;
6430b57cec5SDimitry Andric }
6440b57cec5SDimitry Andric 
parseOpenMPDeclareMapperVarDecl(SourceRange & Range,DeclarationName & Name,AccessSpecifier AS)6450b57cec5SDimitry Andric TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
6460b57cec5SDimitry Andric                                                    DeclarationName &Name,
6470b57cec5SDimitry Andric                                                    AccessSpecifier AS) {
6480b57cec5SDimitry Andric   // Parse the common declaration-specifiers piece.
6490b57cec5SDimitry Andric   Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
6500b57cec5SDimitry Andric   DeclSpec DS(AttrFactory);
6510b57cec5SDimitry Andric   ParseSpecifierQualifierList(DS, AS, DSC);
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   // Parse the declarator.
654e8d8bef9SDimitry Andric   DeclaratorContext Context = DeclaratorContext::Prototype;
65581ad6265SDimitry Andric   Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);
6560b57cec5SDimitry Andric   ParseDeclarator(DeclaratorInfo);
6570b57cec5SDimitry Andric   Range = DeclaratorInfo.getSourceRange();
6580b57cec5SDimitry Andric   if (DeclaratorInfo.getIdentifier() == nullptr) {
6590b57cec5SDimitry Andric     Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
6600b57cec5SDimitry Andric     return true;
6610b57cec5SDimitry Andric   }
6620b57cec5SDimitry Andric   Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
6630b57cec5SDimitry Andric 
664*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPDeclareMapperVarDecl(getCurScope(),
665*0fca6ea1SDimitry Andric                                                           DeclaratorInfo);
6660b57cec5SDimitry Andric }
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric namespace {
6690b57cec5SDimitry Andric /// RAII that recreates function context for correct parsing of clauses of
6700b57cec5SDimitry Andric /// 'declare simd' construct.
6710b57cec5SDimitry Andric /// OpenMP, 2.8.2 declare simd Construct
6720b57cec5SDimitry Andric /// The expressions appearing in the clauses of this directive are evaluated in
6730b57cec5SDimitry Andric /// the scope of the arguments of the function declaration or definition.
6740b57cec5SDimitry Andric class FNContextRAII final {
6750b57cec5SDimitry Andric   Parser &P;
6760b57cec5SDimitry Andric   Sema::CXXThisScopeRAII *ThisScope;
6775ffd83dbSDimitry Andric   Parser::MultiParseScope Scopes;
6780b57cec5SDimitry Andric   bool HasFunScope = false;
6790b57cec5SDimitry Andric   FNContextRAII() = delete;
6800b57cec5SDimitry Andric   FNContextRAII(const FNContextRAII &) = delete;
6810b57cec5SDimitry Andric   FNContextRAII &operator=(const FNContextRAII &) = delete;
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric public:
FNContextRAII(Parser & P,Parser::DeclGroupPtrTy Ptr)6845ffd83dbSDimitry Andric   FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) {
6850b57cec5SDimitry Andric     Decl *D = *Ptr.get().begin();
6860b57cec5SDimitry Andric     NamedDecl *ND = dyn_cast<NamedDecl>(D);
6870b57cec5SDimitry Andric     RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
6880b57cec5SDimitry Andric     Sema &Actions = P.getActions();
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric     // Allow 'this' within late-parsed attributes.
6910b57cec5SDimitry Andric     ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
6920b57cec5SDimitry Andric                                            ND && ND->isCXXInstanceMember());
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric     // If the Decl is templatized, add template parameters to scope.
6955ffd83dbSDimitry Andric     // FIXME: Track CurTemplateDepth?
6965ffd83dbSDimitry Andric     P.ReenterTemplateScopes(Scopes, D);
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric     // If the Decl is on a function, add function parameters to the scope.
6995ffd83dbSDimitry Andric     if (D->isFunctionOrFunctionTemplate()) {
7005ffd83dbSDimitry Andric       HasFunScope = true;
7015ffd83dbSDimitry Andric       Scopes.Enter(Scope::FnScope | Scope::DeclScope |
7025ffd83dbSDimitry Andric                    Scope::CompoundStmtScope);
7030b57cec5SDimitry Andric       Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
7040b57cec5SDimitry Andric     }
7050b57cec5SDimitry Andric   }
~FNContextRAII()7065ffd83dbSDimitry Andric   ~FNContextRAII() {
7075ffd83dbSDimitry Andric     if (HasFunScope)
7085ffd83dbSDimitry Andric       P.getActions().ActOnExitFunctionContext();
7090b57cec5SDimitry Andric     delete ThisScope;
7100b57cec5SDimitry Andric   }
7110b57cec5SDimitry Andric };
7120b57cec5SDimitry Andric } // namespace
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric /// Parses clauses for 'declare simd' directive.
7150b57cec5SDimitry Andric ///    clause:
7160b57cec5SDimitry Andric ///      'inbranch' | 'notinbranch'
7170b57cec5SDimitry Andric ///      'simdlen' '(' <expr> ')'
7180b57cec5SDimitry Andric ///      { 'uniform' '(' <argument_list> ')' }
7190b57cec5SDimitry Andric ///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
7200b57cec5SDimitry Andric ///      { '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)7210b57cec5SDimitry Andric static bool parseDeclareSimdClauses(
7220b57cec5SDimitry Andric     Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
7230b57cec5SDimitry Andric     SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
7240b57cec5SDimitry Andric     SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
7250b57cec5SDimitry Andric     SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
7260b57cec5SDimitry Andric   SourceRange BSRange;
7270b57cec5SDimitry Andric   const Token &Tok = P.getCurToken();
7280b57cec5SDimitry Andric   bool IsError = false;
7290b57cec5SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
7300b57cec5SDimitry Andric     if (Tok.isNot(tok::identifier))
7310b57cec5SDimitry Andric       break;
7320b57cec5SDimitry Andric     OMPDeclareSimdDeclAttr::BranchStateTy Out;
7330b57cec5SDimitry Andric     IdentifierInfo *II = Tok.getIdentifierInfo();
7340b57cec5SDimitry Andric     StringRef ClauseName = II->getName();
7350b57cec5SDimitry Andric     // Parse 'inranch|notinbranch' clauses.
7360b57cec5SDimitry Andric     if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
7370b57cec5SDimitry Andric       if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
7380b57cec5SDimitry Andric         P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
7390b57cec5SDimitry Andric             << ClauseName
7400b57cec5SDimitry Andric             << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
7410b57cec5SDimitry Andric         IsError = true;
7420b57cec5SDimitry Andric       }
7430b57cec5SDimitry Andric       BS = Out;
7440b57cec5SDimitry Andric       BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
7450b57cec5SDimitry Andric       P.ConsumeToken();
746*0fca6ea1SDimitry Andric     } else if (ClauseName == "simdlen") {
7470b57cec5SDimitry Andric       if (SimdLen.isUsable()) {
7480b57cec5SDimitry Andric         P.Diag(Tok, diag::err_omp_more_one_clause)
7490b57cec5SDimitry Andric             << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
7500b57cec5SDimitry Andric         IsError = true;
7510b57cec5SDimitry Andric       }
7520b57cec5SDimitry Andric       P.ConsumeToken();
7530b57cec5SDimitry Andric       SourceLocation RLoc;
7540b57cec5SDimitry Andric       SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
7550b57cec5SDimitry Andric       if (SimdLen.isInvalid())
7560b57cec5SDimitry Andric         IsError = true;
7570b57cec5SDimitry Andric     } else {
7580b57cec5SDimitry Andric       OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
7590b57cec5SDimitry Andric       if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
7600b57cec5SDimitry Andric           CKind == OMPC_linear) {
761*0fca6ea1SDimitry Andric         SemaOpenMP::OpenMPVarListDataTy Data;
7620b57cec5SDimitry Andric         SmallVectorImpl<Expr *> *Vars = &Uniforms;
763480093f4SDimitry Andric         if (CKind == OMPC_aligned) {
7640b57cec5SDimitry Andric           Vars = &Aligneds;
765480093f4SDimitry Andric         } else if (CKind == OMPC_linear) {
766480093f4SDimitry Andric           Data.ExtraModifier = OMPC_LINEAR_val;
7670b57cec5SDimitry Andric           Vars = &Linears;
768480093f4SDimitry Andric         }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric         P.ConsumeToken();
7710b57cec5SDimitry Andric         if (P.ParseOpenMPVarList(OMPD_declare_simd,
7720b57cec5SDimitry Andric                                  getOpenMPClauseKind(ClauseName), *Vars, Data))
7730b57cec5SDimitry Andric           IsError = true;
7740b57cec5SDimitry Andric         if (CKind == OMPC_aligned) {
7755ffd83dbSDimitry Andric           Alignments.append(Aligneds.size() - Alignments.size(),
7765ffd83dbSDimitry Andric                             Data.DepModOrTailExpr);
7770b57cec5SDimitry Andric         } else if (CKind == OMPC_linear) {
778480093f4SDimitry Andric           assert(0 <= Data.ExtraModifier &&
779480093f4SDimitry Andric                  Data.ExtraModifier <= OMPC_LINEAR_unknown &&
780480093f4SDimitry Andric                  "Unexpected linear modifier.");
781*0fca6ea1SDimitry Andric           if (P.getActions().OpenMP().CheckOpenMPLinearModifier(
782480093f4SDimitry Andric                   static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
7835ffd83dbSDimitry Andric                   Data.ExtraModifierLoc))
784480093f4SDimitry Andric             Data.ExtraModifier = OMPC_LINEAR_val;
7850b57cec5SDimitry Andric           LinModifiers.append(Linears.size() - LinModifiers.size(),
786480093f4SDimitry Andric                               Data.ExtraModifier);
7875ffd83dbSDimitry Andric           Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
7880b57cec5SDimitry Andric         }
7890b57cec5SDimitry Andric       } else
7900b57cec5SDimitry Andric         // TODO: add parsing of other clauses.
7910b57cec5SDimitry Andric         break;
7920b57cec5SDimitry Andric     }
7930b57cec5SDimitry Andric     // Skip ',' if any.
7940b57cec5SDimitry Andric     if (Tok.is(tok::comma))
7950b57cec5SDimitry Andric       P.ConsumeToken();
7960b57cec5SDimitry Andric   }
7970b57cec5SDimitry Andric   return IsError;
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric /// Parse clauses for '#pragma omp declare simd'.
8010b57cec5SDimitry Andric Parser::DeclGroupPtrTy
ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,CachedTokens & Toks,SourceLocation Loc)8020b57cec5SDimitry Andric Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
8030b57cec5SDimitry Andric                                    CachedTokens &Toks, SourceLocation Loc) {
8040b57cec5SDimitry Andric   PP.EnterToken(Tok, /*IsReinject*/ true);
8050b57cec5SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
8060b57cec5SDimitry Andric                       /*IsReinject*/ true);
8070b57cec5SDimitry Andric   // Consume the previously pushed token.
8080b57cec5SDimitry Andric   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
809a7dea167SDimitry Andric   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric   FNContextRAII FnContext(*this, Ptr);
8120b57cec5SDimitry Andric   OMPDeclareSimdDeclAttr::BranchStateTy BS =
8130b57cec5SDimitry Andric       OMPDeclareSimdDeclAttr::BS_Undefined;
8140b57cec5SDimitry Andric   ExprResult Simdlen;
8150b57cec5SDimitry Andric   SmallVector<Expr *, 4> Uniforms;
8160b57cec5SDimitry Andric   SmallVector<Expr *, 4> Aligneds;
8170b57cec5SDimitry Andric   SmallVector<Expr *, 4> Alignments;
8180b57cec5SDimitry Andric   SmallVector<Expr *, 4> Linears;
8190b57cec5SDimitry Andric   SmallVector<unsigned, 4> LinModifiers;
8200b57cec5SDimitry Andric   SmallVector<Expr *, 4> Steps;
8210b57cec5SDimitry Andric   bool IsError =
8220b57cec5SDimitry Andric       parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
8230b57cec5SDimitry Andric                               Alignments, Linears, LinModifiers, Steps);
8245ffd83dbSDimitry Andric   skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
8250b57cec5SDimitry Andric   // Skip the last annot_pragma_openmp_end.
8260b57cec5SDimitry Andric   SourceLocation EndLoc = ConsumeAnnotationToken();
8270b57cec5SDimitry Andric   if (IsError)
8280b57cec5SDimitry Andric     return Ptr;
829*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPDeclareSimdDirective(
8300b57cec5SDimitry Andric       Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
8310b57cec5SDimitry Andric       LinModifiers, Steps, SourceRange(Loc, EndLoc));
8320b57cec5SDimitry Andric }
8330b57cec5SDimitry Andric 
8345ffd83dbSDimitry Andric namespace {
8355ffd83dbSDimitry Andric /// Constant used in the diagnostics to distinguish the levels in an OpenMP
8365ffd83dbSDimitry Andric /// contexts: selector-set={selector(trait, ...), ...}, ....
8375ffd83dbSDimitry Andric enum OMPContextLvl {
8385ffd83dbSDimitry Andric   CONTEXT_SELECTOR_SET_LVL = 0,
8395ffd83dbSDimitry Andric   CONTEXT_SELECTOR_LVL = 1,
8405ffd83dbSDimitry Andric   CONTEXT_TRAIT_LVL = 2,
8415ffd83dbSDimitry Andric };
8425ffd83dbSDimitry Andric 
stringLiteralParser(Parser & P)8435ffd83dbSDimitry Andric static StringRef stringLiteralParser(Parser &P) {
8445ffd83dbSDimitry Andric   ExprResult Res = P.ParseStringLiteralExpression(true);
8455ffd83dbSDimitry Andric   return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
8465ffd83dbSDimitry Andric }
8475ffd83dbSDimitry Andric 
getNameFromIdOrString(Parser & P,Token & Tok,OMPContextLvl Lvl)8485ffd83dbSDimitry Andric static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
8495ffd83dbSDimitry Andric                                        OMPContextLvl Lvl) {
850349cc55cSDimitry Andric   if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {
8515ffd83dbSDimitry Andric     llvm::SmallString<16> Buffer;
8525ffd83dbSDimitry Andric     StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
8535ffd83dbSDimitry Andric     (void)P.ConsumeToken();
8545ffd83dbSDimitry Andric     return Name;
8555ffd83dbSDimitry Andric   }
8565ffd83dbSDimitry Andric 
8575ffd83dbSDimitry Andric   if (tok::isStringLiteral(Tok.getKind()))
8585ffd83dbSDimitry Andric     return stringLiteralParser(P);
8595ffd83dbSDimitry Andric 
8605ffd83dbSDimitry Andric   P.Diag(Tok.getLocation(),
8615ffd83dbSDimitry Andric          diag::warn_omp_declare_variant_string_literal_or_identifier)
8625ffd83dbSDimitry Andric       << Lvl;
8635ffd83dbSDimitry Andric   return "";
8645ffd83dbSDimitry Andric }
8655ffd83dbSDimitry Andric 
checkForDuplicates(Parser & P,StringRef Name,SourceLocation NameLoc,llvm::StringMap<SourceLocation> & Seen,OMPContextLvl Lvl)8665ffd83dbSDimitry Andric static bool checkForDuplicates(Parser &P, StringRef Name,
8675ffd83dbSDimitry Andric                                SourceLocation NameLoc,
8685ffd83dbSDimitry Andric                                llvm::StringMap<SourceLocation> &Seen,
8695ffd83dbSDimitry Andric                                OMPContextLvl Lvl) {
8705ffd83dbSDimitry Andric   auto Res = Seen.try_emplace(Name, NameLoc);
8715ffd83dbSDimitry Andric   if (Res.second)
8725ffd83dbSDimitry Andric     return false;
8735ffd83dbSDimitry Andric 
8745ffd83dbSDimitry Andric   // Each trait-set-selector-name, trait-selector-name and trait-name can
8755ffd83dbSDimitry Andric   // only be specified once.
8765ffd83dbSDimitry Andric   P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
8775ffd83dbSDimitry Andric       << Lvl << Name;
8785ffd83dbSDimitry Andric   P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
8795ffd83dbSDimitry Andric       << Lvl << Name;
8805ffd83dbSDimitry Andric   return true;
8815ffd83dbSDimitry Andric }
8825ffd83dbSDimitry Andric } // namespace
8835ffd83dbSDimitry Andric 
parseOMPTraitPropertyKind(OMPTraitProperty & TIProperty,llvm::omp::TraitSet Set,llvm::omp::TraitSelector Selector,llvm::StringMap<SourceLocation> & Seen)884e8d8bef9SDimitry Andric void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,
885e8d8bef9SDimitry Andric                                        llvm::omp::TraitSet Set,
886e8d8bef9SDimitry Andric                                        llvm::omp::TraitSelector Selector,
887e8d8bef9SDimitry Andric                                        llvm::StringMap<SourceLocation> &Seen) {
8885ffd83dbSDimitry Andric   TIProperty.Kind = TraitProperty::invalid;
8895ffd83dbSDimitry Andric 
8905ffd83dbSDimitry Andric   SourceLocation NameLoc = Tok.getLocation();
891e8d8bef9SDimitry Andric   StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
8925ffd83dbSDimitry Andric   if (Name.empty()) {
8935ffd83dbSDimitry Andric     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
8945ffd83dbSDimitry Andric         << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
8955ffd83dbSDimitry Andric     return;
8965ffd83dbSDimitry Andric   }
8975ffd83dbSDimitry Andric 
898e8d8bef9SDimitry Andric   TIProperty.RawString = Name;
899e8d8bef9SDimitry Andric   TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
9005ffd83dbSDimitry Andric   if (TIProperty.Kind != TraitProperty::invalid) {
9015ffd83dbSDimitry Andric     if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
9025ffd83dbSDimitry Andric       TIProperty.Kind = TraitProperty::invalid;
9035ffd83dbSDimitry Andric     return;
9045ffd83dbSDimitry Andric   }
9055ffd83dbSDimitry Andric 
9065ffd83dbSDimitry Andric   // It follows diagnosis and helping notes.
9075ffd83dbSDimitry Andric   // FIXME: We should move the diagnosis string generation into libFrontend.
9085ffd83dbSDimitry Andric   Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
9095ffd83dbSDimitry Andric       << Name << getOpenMPContextTraitSelectorName(Selector)
9105ffd83dbSDimitry Andric       << getOpenMPContextTraitSetName(Set);
9115ffd83dbSDimitry Andric 
9125ffd83dbSDimitry Andric   TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
9135ffd83dbSDimitry Andric   if (SetForName != TraitSet::invalid) {
9145ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
9155ffd83dbSDimitry Andric         << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
9165ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
9175ffd83dbSDimitry Andric         << Name << "<selector-name>"
9185ffd83dbSDimitry Andric         << "(<property-name>)";
9195ffd83dbSDimitry Andric     return;
9205ffd83dbSDimitry Andric   }
9215ffd83dbSDimitry Andric   TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
9225ffd83dbSDimitry Andric   if (SelectorForName != TraitSelector::invalid) {
9235ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
9245ffd83dbSDimitry Andric         << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
9255ffd83dbSDimitry Andric     bool AllowsTraitScore = false;
9265ffd83dbSDimitry Andric     bool RequiresProperty = false;
9275ffd83dbSDimitry Andric     isValidTraitSelectorForTraitSet(
9285ffd83dbSDimitry Andric         SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
9295ffd83dbSDimitry Andric         AllowsTraitScore, RequiresProperty);
9305ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
9315ffd83dbSDimitry Andric         << getOpenMPContextTraitSetName(
9325ffd83dbSDimitry Andric                getOpenMPContextTraitSetForSelector(SelectorForName))
9335ffd83dbSDimitry Andric         << Name << (RequiresProperty ? "(<property-name>)" : "");
9345ffd83dbSDimitry Andric     return;
9355ffd83dbSDimitry Andric   }
9365ffd83dbSDimitry Andric   for (const auto &PotentialSet :
9375ffd83dbSDimitry Andric        {TraitSet::construct, TraitSet::user, TraitSet::implementation,
9385ffd83dbSDimitry Andric         TraitSet::device}) {
9395ffd83dbSDimitry Andric     TraitProperty PropertyForName =
940e8d8bef9SDimitry Andric         getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
9415ffd83dbSDimitry Andric     if (PropertyForName == TraitProperty::invalid)
9425ffd83dbSDimitry Andric       continue;
9435ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
9445ffd83dbSDimitry Andric         << getOpenMPContextTraitSetName(
9455ffd83dbSDimitry Andric                getOpenMPContextTraitSetForProperty(PropertyForName))
9465ffd83dbSDimitry Andric         << getOpenMPContextTraitSelectorName(
9475ffd83dbSDimitry Andric                getOpenMPContextTraitSelectorForProperty(PropertyForName))
9485ffd83dbSDimitry Andric         << ("(" + Name + ")").str();
9495ffd83dbSDimitry Andric     return;
9505ffd83dbSDimitry Andric   }
9515ffd83dbSDimitry Andric   Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
9525ffd83dbSDimitry Andric       << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
9535ffd83dbSDimitry Andric }
9545ffd83dbSDimitry Andric 
checkExtensionProperty(Parser & P,SourceLocation Loc,OMPTraitProperty & TIProperty,OMPTraitSelector & TISelector,llvm::StringMap<SourceLocation> & Seen)9555ffd83dbSDimitry Andric static bool checkExtensionProperty(Parser &P, SourceLocation Loc,
9565ffd83dbSDimitry Andric                                    OMPTraitProperty &TIProperty,
9575ffd83dbSDimitry Andric                                    OMPTraitSelector &TISelector,
9585ffd83dbSDimitry Andric                                    llvm::StringMap<SourceLocation> &Seen) {
9595ffd83dbSDimitry Andric   assert(TISelector.Kind ==
9605ffd83dbSDimitry Andric              llvm::omp::TraitSelector::implementation_extension &&
9615ffd83dbSDimitry Andric          "Only for extension properties, e.g., "
9625ffd83dbSDimitry Andric          "`implementation={extension(PROPERTY)}`");
9635ffd83dbSDimitry Andric   if (TIProperty.Kind == TraitProperty::invalid)
9645ffd83dbSDimitry Andric     return false;
9655ffd83dbSDimitry Andric 
966e8d8bef9SDimitry Andric   if (TIProperty.Kind ==
967e8d8bef9SDimitry Andric       TraitProperty::implementation_extension_disable_implicit_base)
968e8d8bef9SDimitry Andric     return true;
969e8d8bef9SDimitry Andric 
970e8d8bef9SDimitry Andric   if (TIProperty.Kind ==
971e8d8bef9SDimitry Andric       TraitProperty::implementation_extension_allow_templates)
972e8d8bef9SDimitry Andric     return true;
973e8d8bef9SDimitry Andric 
97481ad6265SDimitry Andric   if (TIProperty.Kind ==
97581ad6265SDimitry Andric       TraitProperty::implementation_extension_bind_to_declaration)
97681ad6265SDimitry Andric     return true;
97781ad6265SDimitry Andric 
9785ffd83dbSDimitry Andric   auto IsMatchExtension = [](OMPTraitProperty &TP) {
9795ffd83dbSDimitry Andric     return (TP.Kind ==
9805ffd83dbSDimitry Andric                 llvm::omp::TraitProperty::implementation_extension_match_all ||
9815ffd83dbSDimitry Andric             TP.Kind ==
9825ffd83dbSDimitry Andric                 llvm::omp::TraitProperty::implementation_extension_match_any ||
9835ffd83dbSDimitry Andric             TP.Kind ==
9845ffd83dbSDimitry Andric                 llvm::omp::TraitProperty::implementation_extension_match_none);
9855ffd83dbSDimitry Andric   };
9865ffd83dbSDimitry Andric 
9875ffd83dbSDimitry Andric   if (IsMatchExtension(TIProperty)) {
9885ffd83dbSDimitry Andric     for (OMPTraitProperty &SeenProp : TISelector.Properties)
9895ffd83dbSDimitry Andric       if (IsMatchExtension(SeenProp)) {
9905ffd83dbSDimitry Andric         P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
991e8d8bef9SDimitry Andric         StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
992e8d8bef9SDimitry Andric             SeenProp.Kind, SeenProp.RawString);
9935ffd83dbSDimitry Andric         SourceLocation SeenLoc = Seen[SeenName];
9945ffd83dbSDimitry Andric         P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
9955ffd83dbSDimitry Andric             << CONTEXT_TRAIT_LVL << SeenName;
9965ffd83dbSDimitry Andric         return false;
9975ffd83dbSDimitry Andric       }
9985ffd83dbSDimitry Andric     return true;
9995ffd83dbSDimitry Andric   }
10005ffd83dbSDimitry Andric 
10015ffd83dbSDimitry Andric   llvm_unreachable("Unknown extension property!");
10025ffd83dbSDimitry Andric }
10035ffd83dbSDimitry Andric 
parseOMPContextProperty(OMPTraitSelector & TISelector,llvm::omp::TraitSet Set,llvm::StringMap<SourceLocation> & Seen)10045ffd83dbSDimitry Andric void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
10055ffd83dbSDimitry Andric                                      llvm::omp::TraitSet Set,
10065ffd83dbSDimitry Andric                                      llvm::StringMap<SourceLocation> &Seen) {
10075ffd83dbSDimitry Andric   assert(TISelector.Kind != TraitSelector::user_condition &&
10085ffd83dbSDimitry Andric          "User conditions are special properties not handled here!");
10095ffd83dbSDimitry Andric 
10105ffd83dbSDimitry Andric   SourceLocation PropertyLoc = Tok.getLocation();
10115ffd83dbSDimitry Andric   OMPTraitProperty TIProperty;
10125ffd83dbSDimitry Andric   parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);
10135ffd83dbSDimitry Andric 
10145ffd83dbSDimitry Andric   if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)
10155ffd83dbSDimitry Andric     if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,
10165ffd83dbSDimitry Andric                                 TISelector, Seen))
10175ffd83dbSDimitry Andric       TIProperty.Kind = TraitProperty::invalid;
10185ffd83dbSDimitry Andric 
10195ffd83dbSDimitry Andric   // If we have an invalid property here we already issued a warning.
10205ffd83dbSDimitry Andric   if (TIProperty.Kind == TraitProperty::invalid) {
10215ffd83dbSDimitry Andric     if (PropertyLoc != Tok.getLocation())
10225ffd83dbSDimitry Andric       Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
10235ffd83dbSDimitry Andric           << CONTEXT_TRAIT_LVL;
10245ffd83dbSDimitry Andric     return;
10255ffd83dbSDimitry Andric   }
10265ffd83dbSDimitry Andric 
10275ffd83dbSDimitry Andric   if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
10285ffd83dbSDimitry Andric                                                  TISelector.Kind, Set)) {
10295ffd83dbSDimitry Andric 
10305ffd83dbSDimitry Andric     // If we make it here the property, selector, set, score, condition, ... are
10315ffd83dbSDimitry Andric     // all valid (or have been corrected). Thus we can record the property.
10325ffd83dbSDimitry Andric     TISelector.Properties.push_back(TIProperty);
10335ffd83dbSDimitry Andric     return;
10345ffd83dbSDimitry Andric   }
10355ffd83dbSDimitry Andric 
10365ffd83dbSDimitry Andric   Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
1037e8d8bef9SDimitry Andric       << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1038e8d8bef9SDimitry Andric                                            TIProperty.RawString)
10395ffd83dbSDimitry Andric       << getOpenMPContextTraitSelectorName(TISelector.Kind)
10405ffd83dbSDimitry Andric       << getOpenMPContextTraitSetName(Set);
10415ffd83dbSDimitry Andric   Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
1042e8d8bef9SDimitry Andric       << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1043e8d8bef9SDimitry Andric                                            TIProperty.RawString)
10445ffd83dbSDimitry Andric       << getOpenMPContextTraitSelectorName(
10455ffd83dbSDimitry Andric              getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
10465ffd83dbSDimitry Andric       << getOpenMPContextTraitSetName(
10475ffd83dbSDimitry Andric              getOpenMPContextTraitSetForProperty(TIProperty.Kind));
10485ffd83dbSDimitry Andric   Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
10495ffd83dbSDimitry Andric       << CONTEXT_TRAIT_LVL;
10505ffd83dbSDimitry Andric }
10515ffd83dbSDimitry Andric 
parseOMPTraitSelectorKind(OMPTraitSelector & TISelector,llvm::omp::TraitSet Set,llvm::StringMap<SourceLocation> & Seen)1052e8d8bef9SDimitry Andric void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,
1053e8d8bef9SDimitry Andric                                        llvm::omp::TraitSet Set,
10545ffd83dbSDimitry Andric                                        llvm::StringMap<SourceLocation> &Seen) {
10555ffd83dbSDimitry Andric   TISelector.Kind = TraitSelector::invalid;
10565ffd83dbSDimitry Andric 
10575ffd83dbSDimitry Andric   SourceLocation NameLoc = Tok.getLocation();
1058e8d8bef9SDimitry Andric   StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);
10595ffd83dbSDimitry Andric   if (Name.empty()) {
10605ffd83dbSDimitry Andric     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
10615ffd83dbSDimitry Andric         << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
10625ffd83dbSDimitry Andric     return;
10635ffd83dbSDimitry Andric   }
10645ffd83dbSDimitry Andric 
10655ffd83dbSDimitry Andric   TISelector.Kind = getOpenMPContextTraitSelectorKind(Name);
10665ffd83dbSDimitry Andric   if (TISelector.Kind != TraitSelector::invalid) {
10675ffd83dbSDimitry Andric     if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
10685ffd83dbSDimitry Andric       TISelector.Kind = TraitSelector::invalid;
10695ffd83dbSDimitry Andric     return;
10705ffd83dbSDimitry Andric   }
10715ffd83dbSDimitry Andric 
10725ffd83dbSDimitry Andric   // It follows diagnosis and helping notes.
10735ffd83dbSDimitry Andric   Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
10745ffd83dbSDimitry Andric       << Name << getOpenMPContextTraitSetName(Set);
10755ffd83dbSDimitry Andric 
10765ffd83dbSDimitry Andric   TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
10775ffd83dbSDimitry Andric   if (SetForName != TraitSet::invalid) {
10785ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
10795ffd83dbSDimitry Andric         << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
10805ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
10815ffd83dbSDimitry Andric         << Name << "<selector-name>"
10825ffd83dbSDimitry Andric         << "<property-name>";
10835ffd83dbSDimitry Andric     return;
10845ffd83dbSDimitry Andric   }
10855ffd83dbSDimitry Andric   for (const auto &PotentialSet :
10865ffd83dbSDimitry Andric        {TraitSet::construct, TraitSet::user, TraitSet::implementation,
10875ffd83dbSDimitry Andric         TraitSet::device}) {
1088e8d8bef9SDimitry Andric     TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1089e8d8bef9SDimitry Andric         PotentialSet, TraitSelector::invalid, Name);
10905ffd83dbSDimitry Andric     if (PropertyForName == TraitProperty::invalid)
10915ffd83dbSDimitry Andric       continue;
10925ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
10935ffd83dbSDimitry Andric         << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
10945ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
10955ffd83dbSDimitry Andric         << getOpenMPContextTraitSetName(
10965ffd83dbSDimitry Andric                getOpenMPContextTraitSetForProperty(PropertyForName))
10975ffd83dbSDimitry Andric         << getOpenMPContextTraitSelectorName(
10985ffd83dbSDimitry Andric                getOpenMPContextTraitSelectorForProperty(PropertyForName))
10995ffd83dbSDimitry Andric         << ("(" + Name + ")").str();
11005ffd83dbSDimitry Andric     return;
11015ffd83dbSDimitry Andric   }
11025ffd83dbSDimitry Andric   Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
11035ffd83dbSDimitry Andric       << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
11045ffd83dbSDimitry Andric }
11055ffd83dbSDimitry Andric 
1106a7dea167SDimitry Andric /// Parse optional 'score' '(' <expr> ')' ':'.
parseContextScore(Parser & P)1107a7dea167SDimitry Andric static ExprResult parseContextScore(Parser &P) {
1108a7dea167SDimitry Andric   ExprResult ScoreExpr;
11095ffd83dbSDimitry Andric   llvm::SmallString<16> Buffer;
1110a7dea167SDimitry Andric   StringRef SelectorName =
1111a7dea167SDimitry Andric       P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
1112*0fca6ea1SDimitry Andric   if (SelectorName != "score")
1113a7dea167SDimitry Andric     return ScoreExpr;
1114a7dea167SDimitry Andric   (void)P.ConsumeToken();
1115a7dea167SDimitry Andric   SourceLocation RLoc;
1116a7dea167SDimitry Andric   ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
1117a7dea167SDimitry Andric   // Parse ':'
1118a7dea167SDimitry Andric   if (P.getCurToken().is(tok::colon))
1119a7dea167SDimitry Andric     (void)P.ConsumeAnyToken();
1120a7dea167SDimitry Andric   else
11215ffd83dbSDimitry Andric     P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
11225ffd83dbSDimitry Andric         << "':'"
11235ffd83dbSDimitry Andric         << "score expression";
1124a7dea167SDimitry Andric   return ScoreExpr;
1125a7dea167SDimitry Andric }
1126a7dea167SDimitry Andric 
11275ffd83dbSDimitry Andric /// Parses an OpenMP context selector.
11285ffd83dbSDimitry Andric ///
11295ffd83dbSDimitry Andric /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')']
parseOMPContextSelector(OMPTraitSelector & TISelector,llvm::omp::TraitSet Set,llvm::StringMap<SourceLocation> & SeenSelectors)11305ffd83dbSDimitry Andric void Parser::parseOMPContextSelector(
11315ffd83dbSDimitry Andric     OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
11325ffd83dbSDimitry Andric     llvm::StringMap<SourceLocation> &SeenSelectors) {
11335ffd83dbSDimitry Andric   unsigned short OuterPC = ParenCount;
11345ffd83dbSDimitry Andric 
11355ffd83dbSDimitry Andric   // If anything went wrong we issue an error or warning and then skip the rest
11365ffd83dbSDimitry Andric   // of the selector. However, commas are ambiguous so we look for the nesting
11375ffd83dbSDimitry Andric   // of parentheses here as well.
11385ffd83dbSDimitry Andric   auto FinishSelector = [OuterPC, this]() -> void {
11395ffd83dbSDimitry Andric     bool Done = false;
11405ffd83dbSDimitry Andric     while (!Done) {
11415ffd83dbSDimitry Andric       while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
11425ffd83dbSDimitry Andric                          tok::annot_pragma_openmp_end},
11435ffd83dbSDimitry Andric                         StopBeforeMatch))
1144a7dea167SDimitry Andric         ;
11455ffd83dbSDimitry Andric       if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
11465ffd83dbSDimitry Andric         (void)ConsumeParen();
11475ffd83dbSDimitry Andric       if (OuterPC <= ParenCount) {
11485ffd83dbSDimitry Andric         Done = true;
1149a7dea167SDimitry Andric         break;
1150a7dea167SDimitry Andric       }
11515ffd83dbSDimitry Andric       if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
11525ffd83dbSDimitry Andric         Done = true;
1153480093f4SDimitry Andric         break;
1154480093f4SDimitry Andric       }
11555ffd83dbSDimitry Andric       (void)ConsumeAnyToken();
1156480093f4SDimitry Andric     }
11575ffd83dbSDimitry Andric     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
11585ffd83dbSDimitry Andric         << CONTEXT_SELECTOR_LVL;
11595ffd83dbSDimitry Andric   };
11605ffd83dbSDimitry Andric 
11615ffd83dbSDimitry Andric   SourceLocation SelectorLoc = Tok.getLocation();
11625ffd83dbSDimitry Andric   parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
11635ffd83dbSDimitry Andric   if (TISelector.Kind == TraitSelector::invalid)
11645ffd83dbSDimitry Andric     return FinishSelector();
11655ffd83dbSDimitry Andric 
11665ffd83dbSDimitry Andric   bool AllowsTraitScore = false;
11675ffd83dbSDimitry Andric   bool RequiresProperty = false;
11685ffd83dbSDimitry Andric   if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
11695ffd83dbSDimitry Andric                                        RequiresProperty)) {
11705ffd83dbSDimitry Andric     Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
11715ffd83dbSDimitry Andric         << getOpenMPContextTraitSelectorName(TISelector.Kind)
11725ffd83dbSDimitry Andric         << getOpenMPContextTraitSetName(Set);
11735ffd83dbSDimitry Andric     Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
11745ffd83dbSDimitry Andric         << getOpenMPContextTraitSelectorName(TISelector.Kind)
11755ffd83dbSDimitry Andric         << getOpenMPContextTraitSetName(
11765ffd83dbSDimitry Andric                getOpenMPContextTraitSetForSelector(TISelector.Kind))
11775ffd83dbSDimitry Andric         << RequiresProperty;
11785ffd83dbSDimitry Andric     return FinishSelector();
1179480093f4SDimitry Andric   }
1180480093f4SDimitry Andric 
11815ffd83dbSDimitry Andric   if (!RequiresProperty) {
11825ffd83dbSDimitry Andric     TISelector.Properties.push_back(
1183e8d8bef9SDimitry Andric         {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
1184e8d8bef9SDimitry Andric          getOpenMPContextTraitSelectorName(TISelector.Kind)});
11855ffd83dbSDimitry Andric     return;
1186a7dea167SDimitry Andric   }
11875ffd83dbSDimitry Andric 
11885ffd83dbSDimitry Andric   if (!Tok.is(tok::l_paren)) {
11895ffd83dbSDimitry Andric     Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
11905ffd83dbSDimitry Andric         << getOpenMPContextTraitSelectorName(TISelector.Kind)
11915ffd83dbSDimitry Andric         << getOpenMPContextTraitSetName(Set);
11925ffd83dbSDimitry Andric     return FinishSelector();
1193a7dea167SDimitry Andric   }
11945ffd83dbSDimitry Andric 
11955ffd83dbSDimitry Andric   if (TISelector.Kind == TraitSelector::user_condition) {
11965ffd83dbSDimitry Andric     SourceLocation RLoc;
11975ffd83dbSDimitry Andric     ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
11985ffd83dbSDimitry Andric     if (!Condition.isUsable())
11995ffd83dbSDimitry Andric       return FinishSelector();
12005ffd83dbSDimitry Andric     TISelector.ScoreOrCondition = Condition.get();
1201e8d8bef9SDimitry Andric     TISelector.Properties.push_back(
1202e8d8bef9SDimitry Andric         {TraitProperty::user_condition_unknown, "<condition>"});
12035ffd83dbSDimitry Andric     return;
1204a7dea167SDimitry Andric   }
12055ffd83dbSDimitry Andric 
12065ffd83dbSDimitry Andric   BalancedDelimiterTracker BDT(*this, tok::l_paren,
1207a7dea167SDimitry Andric                                tok::annot_pragma_openmp_end);
12085ffd83dbSDimitry Andric   // Parse '('.
12095ffd83dbSDimitry Andric   (void)BDT.consumeOpen();
12105ffd83dbSDimitry Andric 
12115ffd83dbSDimitry Andric   SourceLocation ScoreLoc = Tok.getLocation();
12125ffd83dbSDimitry Andric   ExprResult Score = parseContextScore(*this);
12135ffd83dbSDimitry Andric 
12145ffd83dbSDimitry Andric   if (!AllowsTraitScore && !Score.isUnset()) {
12155ffd83dbSDimitry Andric     if (Score.isUsable()) {
12165ffd83dbSDimitry Andric       Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
12175ffd83dbSDimitry Andric           << getOpenMPContextTraitSelectorName(TISelector.Kind)
12185ffd83dbSDimitry Andric           << getOpenMPContextTraitSetName(Set) << Score.get();
12195ffd83dbSDimitry Andric     } else {
12205ffd83dbSDimitry Andric       Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
12215ffd83dbSDimitry Andric           << getOpenMPContextTraitSelectorName(TISelector.Kind)
12225ffd83dbSDimitry Andric           << getOpenMPContextTraitSetName(Set) << "<invalid>";
12235ffd83dbSDimitry Andric     }
12245ffd83dbSDimitry Andric     Score = ExprResult();
12255ffd83dbSDimitry Andric   }
12265ffd83dbSDimitry Andric 
12275ffd83dbSDimitry Andric   if (Score.isUsable())
12285ffd83dbSDimitry Andric     TISelector.ScoreOrCondition = Score.get();
12295ffd83dbSDimitry Andric 
12305ffd83dbSDimitry Andric   llvm::StringMap<SourceLocation> SeenProperties;
1231a7dea167SDimitry Andric   do {
12325ffd83dbSDimitry Andric     parseOMPContextProperty(TISelector, Set, SeenProperties);
12335ffd83dbSDimitry Andric   } while (TryConsumeToken(tok::comma));
12345ffd83dbSDimitry Andric 
12355ffd83dbSDimitry Andric   // Parse ')'.
12365ffd83dbSDimitry Andric   BDT.consumeClose();
12375ffd83dbSDimitry Andric }
12385ffd83dbSDimitry Andric 
parseOMPTraitSetKind(OMPTraitSet & TISet,llvm::StringMap<SourceLocation> & Seen)12395ffd83dbSDimitry Andric void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
12405ffd83dbSDimitry Andric                                   llvm::StringMap<SourceLocation> &Seen) {
12415ffd83dbSDimitry Andric   TISet.Kind = TraitSet::invalid;
12425ffd83dbSDimitry Andric 
12435ffd83dbSDimitry Andric   SourceLocation NameLoc = Tok.getLocation();
1244e8d8bef9SDimitry Andric   StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);
12455ffd83dbSDimitry Andric   if (Name.empty()) {
12465ffd83dbSDimitry Andric     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
12475ffd83dbSDimitry Andric         << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
12485ffd83dbSDimitry Andric     return;
12495ffd83dbSDimitry Andric   }
12505ffd83dbSDimitry Andric 
12515ffd83dbSDimitry Andric   TISet.Kind = getOpenMPContextTraitSetKind(Name);
12525ffd83dbSDimitry Andric   if (TISet.Kind != TraitSet::invalid) {
12535ffd83dbSDimitry Andric     if (checkForDuplicates(*this, Name, NameLoc, Seen,
12545ffd83dbSDimitry Andric                            CONTEXT_SELECTOR_SET_LVL))
12555ffd83dbSDimitry Andric       TISet.Kind = TraitSet::invalid;
12565ffd83dbSDimitry Andric     return;
12575ffd83dbSDimitry Andric   }
12585ffd83dbSDimitry Andric 
12595ffd83dbSDimitry Andric   // It follows diagnosis and helping notes.
12605ffd83dbSDimitry Andric   Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
12615ffd83dbSDimitry Andric 
12625ffd83dbSDimitry Andric   TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
12635ffd83dbSDimitry Andric   if (SelectorForName != TraitSelector::invalid) {
12645ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
12655ffd83dbSDimitry Andric         << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
12665ffd83dbSDimitry Andric     bool AllowsTraitScore = false;
12675ffd83dbSDimitry Andric     bool RequiresProperty = false;
12685ffd83dbSDimitry Andric     isValidTraitSelectorForTraitSet(
12695ffd83dbSDimitry Andric         SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
12705ffd83dbSDimitry Andric         AllowsTraitScore, RequiresProperty);
12715ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
12725ffd83dbSDimitry Andric         << getOpenMPContextTraitSetName(
12735ffd83dbSDimitry Andric                getOpenMPContextTraitSetForSelector(SelectorForName))
12745ffd83dbSDimitry Andric         << Name << (RequiresProperty ? "(<property-name>)" : "");
12755ffd83dbSDimitry Andric     return;
12765ffd83dbSDimitry Andric   }
12775ffd83dbSDimitry Andric   for (const auto &PotentialSet :
12785ffd83dbSDimitry Andric        {TraitSet::construct, TraitSet::user, TraitSet::implementation,
12795ffd83dbSDimitry Andric         TraitSet::device}) {
1280e8d8bef9SDimitry Andric     TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1281e8d8bef9SDimitry Andric         PotentialSet, TraitSelector::invalid, Name);
12825ffd83dbSDimitry Andric     if (PropertyForName == TraitProperty::invalid)
12835ffd83dbSDimitry Andric       continue;
12845ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
12855ffd83dbSDimitry Andric         << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
12865ffd83dbSDimitry Andric     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
12875ffd83dbSDimitry Andric         << getOpenMPContextTraitSetName(
12885ffd83dbSDimitry Andric                getOpenMPContextTraitSetForProperty(PropertyForName))
12895ffd83dbSDimitry Andric         << getOpenMPContextTraitSelectorName(
12905ffd83dbSDimitry Andric                getOpenMPContextTraitSelectorForProperty(PropertyForName))
12915ffd83dbSDimitry Andric         << ("(" + Name + ")").str();
12925ffd83dbSDimitry Andric     return;
12935ffd83dbSDimitry Andric   }
12945ffd83dbSDimitry Andric   Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
12955ffd83dbSDimitry Andric       << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
12965ffd83dbSDimitry Andric }
12975ffd83dbSDimitry Andric 
12985ffd83dbSDimitry Andric /// Parses an OpenMP context selector set.
12995ffd83dbSDimitry Andric ///
13005ffd83dbSDimitry Andric /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}'
parseOMPContextSelectorSet(OMPTraitSet & TISet,llvm::StringMap<SourceLocation> & SeenSets)13015ffd83dbSDimitry Andric void Parser::parseOMPContextSelectorSet(
1302e8d8bef9SDimitry Andric     OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
13035ffd83dbSDimitry Andric   auto OuterBC = BraceCount;
13045ffd83dbSDimitry Andric 
13055ffd83dbSDimitry Andric   // If anything went wrong we issue an error or warning and then skip the rest
13065ffd83dbSDimitry Andric   // of the set. However, commas are ambiguous so we look for the nesting
13075ffd83dbSDimitry Andric   // of braces here as well.
13085ffd83dbSDimitry Andric   auto FinishSelectorSet = [this, OuterBC]() -> void {
13095ffd83dbSDimitry Andric     bool Done = false;
13105ffd83dbSDimitry Andric     while (!Done) {
13115ffd83dbSDimitry Andric       while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
13125ffd83dbSDimitry Andric                          tok::annot_pragma_openmp_end},
13135ffd83dbSDimitry Andric                         StopBeforeMatch))
1314a7dea167SDimitry Andric         ;
13155ffd83dbSDimitry Andric       if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
13165ffd83dbSDimitry Andric         (void)ConsumeBrace();
13175ffd83dbSDimitry Andric       if (OuterBC <= BraceCount) {
13185ffd83dbSDimitry Andric         Done = true;
1319a7dea167SDimitry Andric         break;
1320a7dea167SDimitry Andric       }
13215ffd83dbSDimitry Andric       if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
13225ffd83dbSDimitry Andric         Done = true;
13235ffd83dbSDimitry Andric         break;
1324a7dea167SDimitry Andric       }
13255ffd83dbSDimitry Andric       (void)ConsumeAnyToken();
13265ffd83dbSDimitry Andric     }
13275ffd83dbSDimitry Andric     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
13285ffd83dbSDimitry Andric         << CONTEXT_SELECTOR_SET_LVL;
13295ffd83dbSDimitry Andric   };
13305ffd83dbSDimitry Andric 
13315ffd83dbSDimitry Andric   parseOMPTraitSetKind(TISet, SeenSets);
13325ffd83dbSDimitry Andric   if (TISet.Kind == TraitSet::invalid)
13335ffd83dbSDimitry Andric     return FinishSelectorSet();
13345ffd83dbSDimitry Andric 
13355ffd83dbSDimitry Andric   // Parse '='.
13365ffd83dbSDimitry Andric   if (!TryConsumeToken(tok::equal))
13375ffd83dbSDimitry Andric     Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
13385ffd83dbSDimitry Andric         << "="
13395ffd83dbSDimitry Andric         << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
13405ffd83dbSDimitry Andric             "\"")
13415ffd83dbSDimitry Andric                .str();
13425ffd83dbSDimitry Andric 
13435ffd83dbSDimitry Andric   // Parse '{'.
13445ffd83dbSDimitry Andric   if (Tok.is(tok::l_brace)) {
13455ffd83dbSDimitry Andric     (void)ConsumeBrace();
13465ffd83dbSDimitry Andric   } else {
13475ffd83dbSDimitry Andric     Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
13485ffd83dbSDimitry Andric         << "{"
13495ffd83dbSDimitry Andric         << ("'=' that follows the context set name \"" +
13505ffd83dbSDimitry Andric             getOpenMPContextTraitSetName(TISet.Kind) + "\"")
13515ffd83dbSDimitry Andric                .str();
13525ffd83dbSDimitry Andric   }
13535ffd83dbSDimitry Andric 
13545ffd83dbSDimitry Andric   llvm::StringMap<SourceLocation> SeenSelectors;
13555ffd83dbSDimitry Andric   do {
13565ffd83dbSDimitry Andric     OMPTraitSelector TISelector;
13575ffd83dbSDimitry Andric     parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
13585ffd83dbSDimitry Andric     if (TISelector.Kind != TraitSelector::invalid &&
13595ffd83dbSDimitry Andric         !TISelector.Properties.empty())
13605ffd83dbSDimitry Andric       TISet.Selectors.push_back(TISelector);
13615ffd83dbSDimitry Andric   } while (TryConsumeToken(tok::comma));
13625ffd83dbSDimitry Andric 
13635ffd83dbSDimitry Andric   // Parse '}'.
13645ffd83dbSDimitry Andric   if (Tok.is(tok::r_brace)) {
13655ffd83dbSDimitry Andric     (void)ConsumeBrace();
13665ffd83dbSDimitry Andric   } else {
13675ffd83dbSDimitry Andric     Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
13685ffd83dbSDimitry Andric         << "}"
13695ffd83dbSDimitry Andric         << ("context selectors for the context set \"" +
13705ffd83dbSDimitry Andric             getOpenMPContextTraitSetName(TISet.Kind) + "\"")
13715ffd83dbSDimitry Andric                .str();
13725ffd83dbSDimitry Andric   }
13735ffd83dbSDimitry Andric }
13745ffd83dbSDimitry Andric 
13755ffd83dbSDimitry Andric /// Parse OpenMP context selectors:
13765ffd83dbSDimitry Andric ///
13775ffd83dbSDimitry Andric /// <trait-set-selector> [, <trait-set-selector>]*
parseOMPContextSelectors(SourceLocation Loc,OMPTraitInfo & TI)13785ffd83dbSDimitry Andric bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
13795ffd83dbSDimitry Andric   llvm::StringMap<SourceLocation> SeenSets;
13805ffd83dbSDimitry Andric   do {
13815ffd83dbSDimitry Andric     OMPTraitSet TISet;
13825ffd83dbSDimitry Andric     parseOMPContextSelectorSet(TISet, SeenSets);
13835ffd83dbSDimitry Andric     if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
13845ffd83dbSDimitry Andric       TI.Sets.push_back(TISet);
13855ffd83dbSDimitry Andric   } while (TryConsumeToken(tok::comma));
13865ffd83dbSDimitry Andric 
1387a7dea167SDimitry Andric   return false;
1388a7dea167SDimitry Andric }
1389a7dea167SDimitry Andric 
1390a7dea167SDimitry Andric /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,CachedTokens & Toks,SourceLocation Loc)1391a7dea167SDimitry Andric void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1392a7dea167SDimitry Andric                                            CachedTokens &Toks,
1393a7dea167SDimitry Andric                                            SourceLocation Loc) {
1394a7dea167SDimitry Andric   PP.EnterToken(Tok, /*IsReinject*/ true);
1395a7dea167SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1396a7dea167SDimitry Andric                       /*IsReinject*/ true);
1397a7dea167SDimitry Andric   // Consume the previously pushed token.
1398a7dea167SDimitry Andric   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1399a7dea167SDimitry Andric   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1400a7dea167SDimitry Andric 
1401a7dea167SDimitry Andric   FNContextRAII FnContext(*this, Ptr);
1402a7dea167SDimitry Andric   // Parse function declaration id.
1403a7dea167SDimitry Andric   SourceLocation RLoc;
1404a7dea167SDimitry Andric   // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1405a7dea167SDimitry Andric   // instead of MemberExprs.
1406480093f4SDimitry Andric   ExprResult AssociatedFunction;
1407480093f4SDimitry Andric   {
1408480093f4SDimitry Andric     // Do not mark function as is used to prevent its emission if this is the
1409480093f4SDimitry Andric     // only place where it is used.
1410480093f4SDimitry Andric     EnterExpressionEvaluationContext Unevaluated(
1411480093f4SDimitry Andric         Actions, Sema::ExpressionEvaluationContext::Unevaluated);
1412480093f4SDimitry Andric     AssociatedFunction = ParseOpenMPParensExpr(
1413480093f4SDimitry Andric         getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1414a7dea167SDimitry Andric         /*IsAddressOfOperand=*/true);
1415480093f4SDimitry Andric   }
1416a7dea167SDimitry Andric   if (!AssociatedFunction.isUsable()) {
1417a7dea167SDimitry Andric     if (!Tok.is(tok::annot_pragma_openmp_end))
1418a7dea167SDimitry Andric       while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1419a7dea167SDimitry Andric         ;
1420a7dea167SDimitry Andric     // Skip the last annot_pragma_openmp_end.
1421a7dea167SDimitry Andric     (void)ConsumeAnnotationToken();
1422a7dea167SDimitry Andric     return;
1423a7dea167SDimitry Andric   }
14245ffd83dbSDimitry Andric 
1425*0fca6ea1SDimitry Andric   OMPTraitInfo *ParentTI =
1426*0fca6ea1SDimitry Andric       Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
1427e8d8bef9SDimitry Andric   ASTContext &ASTCtx = Actions.getASTContext();
1428e8d8bef9SDimitry Andric   OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
1429349cc55cSDimitry Andric   SmallVector<Expr *, 6> AdjustNothing;
1430349cc55cSDimitry Andric   SmallVector<Expr *, 6> AdjustNeedDevicePtr;
1431bdd1243dSDimitry Andric   SmallVector<OMPInteropInfo, 3> AppendArgs;
1432349cc55cSDimitry Andric   SourceLocation AdjustArgsLoc, AppendArgsLoc;
1433349cc55cSDimitry Andric 
1434349cc55cSDimitry Andric   // At least one clause is required.
1435349cc55cSDimitry Andric   if (Tok.is(tok::annot_pragma_openmp_end)) {
1436349cc55cSDimitry Andric     Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1437349cc55cSDimitry Andric         << (getLangOpts().OpenMP < 51 ? 0 : 1);
1438349cc55cSDimitry Andric   }
1439349cc55cSDimitry Andric 
1440349cc55cSDimitry Andric   bool IsError = false;
1441349cc55cSDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1442349cc55cSDimitry Andric     OpenMPClauseKind CKind = Tok.isAnnotation()
1443349cc55cSDimitry Andric                                  ? OMPC_unknown
1444349cc55cSDimitry Andric                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
1445349cc55cSDimitry Andric     if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
1446349cc55cSDimitry Andric                                      getLangOpts().OpenMP)) {
1447349cc55cSDimitry Andric       Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1448349cc55cSDimitry Andric           << (getLangOpts().OpenMP < 51 ? 0 : 1);
1449349cc55cSDimitry Andric       IsError = true;
1450349cc55cSDimitry Andric     }
1451349cc55cSDimitry Andric     if (!IsError) {
1452349cc55cSDimitry Andric       switch (CKind) {
1453349cc55cSDimitry Andric       case OMPC_match:
1454349cc55cSDimitry Andric         IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
1455349cc55cSDimitry Andric         break;
1456349cc55cSDimitry Andric       case OMPC_adjust_args: {
1457349cc55cSDimitry Andric         AdjustArgsLoc = Tok.getLocation();
1458349cc55cSDimitry Andric         ConsumeToken();
1459*0fca6ea1SDimitry Andric         SemaOpenMP::OpenMPVarListDataTy Data;
1460349cc55cSDimitry Andric         SmallVector<Expr *> Vars;
1461349cc55cSDimitry Andric         IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
1462349cc55cSDimitry Andric                                      Vars, Data);
1463349cc55cSDimitry Andric         if (!IsError)
1464349cc55cSDimitry Andric           llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
1465349cc55cSDimitry Andric                                  ? AdjustNothing
1466349cc55cSDimitry Andric                                  : AdjustNeedDevicePtr,
1467349cc55cSDimitry Andric                              Vars);
1468349cc55cSDimitry Andric         break;
1469349cc55cSDimitry Andric       }
1470349cc55cSDimitry Andric       case OMPC_append_args:
1471349cc55cSDimitry Andric         if (!AppendArgs.empty()) {
1472349cc55cSDimitry Andric           Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
1473349cc55cSDimitry Andric               << getOpenMPDirectiveName(OMPD_declare_variant)
1474349cc55cSDimitry Andric               << getOpenMPClauseName(CKind) << 0;
1475349cc55cSDimitry Andric           IsError = true;
1476349cc55cSDimitry Andric         }
1477349cc55cSDimitry Andric         if (!IsError) {
1478349cc55cSDimitry Andric           AppendArgsLoc = Tok.getLocation();
1479349cc55cSDimitry Andric           ConsumeToken();
1480349cc55cSDimitry Andric           IsError = parseOpenMPAppendArgs(AppendArgs);
1481349cc55cSDimitry Andric         }
1482349cc55cSDimitry Andric         break;
1483349cc55cSDimitry Andric       default:
1484349cc55cSDimitry Andric         llvm_unreachable("Unexpected clause for declare variant.");
1485349cc55cSDimitry Andric       }
1486349cc55cSDimitry Andric     }
1487349cc55cSDimitry Andric     if (IsError) {
1488349cc55cSDimitry Andric       while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1489349cc55cSDimitry Andric         ;
1490349cc55cSDimitry Andric       // Skip the last annot_pragma_openmp_end.
1491349cc55cSDimitry Andric       (void)ConsumeAnnotationToken();
14925ffd83dbSDimitry Andric       return;
1493349cc55cSDimitry Andric     }
1494349cc55cSDimitry Andric     // Skip ',' if any.
1495349cc55cSDimitry Andric     if (Tok.is(tok::comma))
1496349cc55cSDimitry Andric       ConsumeToken();
1497349cc55cSDimitry Andric   }
14985ffd83dbSDimitry Andric 
1499bdd1243dSDimitry Andric   std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1500*0fca6ea1SDimitry Andric       Actions.OpenMP().checkOpenMPDeclareVariantFunction(
1501349cc55cSDimitry Andric           Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
15025ffd83dbSDimitry Andric           SourceRange(Loc, Tok.getLocation()));
1503a7dea167SDimitry Andric 
15045ffd83dbSDimitry Andric   if (DeclVarData && !TI.Sets.empty())
1505*0fca6ea1SDimitry Andric     Actions.OpenMP().ActOnOpenMPDeclareVariantDirective(
1506349cc55cSDimitry Andric         DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
1507349cc55cSDimitry Andric         AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,
15085ffd83dbSDimitry Andric         SourceRange(Loc, Tok.getLocation()));
15095ffd83dbSDimitry Andric 
15105ffd83dbSDimitry Andric   // Skip the last annot_pragma_openmp_end.
15115ffd83dbSDimitry Andric   (void)ConsumeAnnotationToken();
15125ffd83dbSDimitry Andric }
15135ffd83dbSDimitry Andric 
parseOpenMPAppendArgs(SmallVectorImpl<OMPInteropInfo> & InteropInfos)1514349cc55cSDimitry Andric bool Parser::parseOpenMPAppendArgs(
1515bdd1243dSDimitry Andric     SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
1516349cc55cSDimitry Andric   bool HasError = false;
1517349cc55cSDimitry Andric   // Parse '('.
1518349cc55cSDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1519349cc55cSDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
1520349cc55cSDimitry Andric                          getOpenMPClauseName(OMPC_append_args).data()))
1521349cc55cSDimitry Andric     return true;
1522349cc55cSDimitry Andric 
1523349cc55cSDimitry Andric   // Parse the list of append-ops, each is;
1524349cc55cSDimitry Andric   // interop(interop-type[,interop-type]...)
1525349cc55cSDimitry Andric   while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {
1526349cc55cSDimitry Andric     ConsumeToken();
1527349cc55cSDimitry Andric     BalancedDelimiterTracker IT(*this, tok::l_paren,
1528349cc55cSDimitry Andric                                 tok::annot_pragma_openmp_end);
1529349cc55cSDimitry Andric     if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
1530349cc55cSDimitry Andric       return true;
1531349cc55cSDimitry Andric 
1532bdd1243dSDimitry Andric     OMPInteropInfo InteropInfo;
1533bdd1243dSDimitry Andric     if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
1534349cc55cSDimitry Andric       HasError = true;
1535bdd1243dSDimitry Andric     else
1536bdd1243dSDimitry Andric       InteropInfos.push_back(InteropInfo);
1537349cc55cSDimitry Andric 
1538349cc55cSDimitry Andric     IT.consumeClose();
1539349cc55cSDimitry Andric     if (Tok.is(tok::comma))
1540349cc55cSDimitry Andric       ConsumeToken();
1541349cc55cSDimitry Andric   }
1542bdd1243dSDimitry Andric   if (!HasError && InteropInfos.empty()) {
1543349cc55cSDimitry Andric     HasError = true;
1544349cc55cSDimitry Andric     Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);
1545349cc55cSDimitry Andric     SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1546349cc55cSDimitry Andric               StopBeforeMatch);
1547349cc55cSDimitry Andric   }
1548349cc55cSDimitry Andric   HasError = T.consumeClose() || HasError;
1549349cc55cSDimitry Andric   return HasError;
1550349cc55cSDimitry Andric }
1551349cc55cSDimitry Andric 
parseOMPDeclareVariantMatchClause(SourceLocation Loc,OMPTraitInfo & TI,OMPTraitInfo * ParentTI)15525ffd83dbSDimitry Andric bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
1553e8d8bef9SDimitry Andric                                                OMPTraitInfo &TI,
1554e8d8bef9SDimitry Andric                                                OMPTraitInfo *ParentTI) {
1555a7dea167SDimitry Andric   // Parse 'match'.
1556a7dea167SDimitry Andric   OpenMPClauseKind CKind = Tok.isAnnotation()
1557a7dea167SDimitry Andric                                ? OMPC_unknown
1558a7dea167SDimitry Andric                                : getOpenMPClauseKind(PP.getSpelling(Tok));
1559a7dea167SDimitry Andric   if (CKind != OMPC_match) {
1560a7dea167SDimitry Andric     Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1561349cc55cSDimitry Andric         << (getLangOpts().OpenMP < 51 ? 0 : 1);
15625ffd83dbSDimitry Andric     return true;
1563a7dea167SDimitry Andric   }
1564a7dea167SDimitry Andric   (void)ConsumeToken();
1565a7dea167SDimitry Andric   // Parse '('.
1566a7dea167SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1567a7dea167SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
1568349cc55cSDimitry Andric                          getOpenMPClauseName(OMPC_match).data()))
15695ffd83dbSDimitry Andric     return true;
1570a7dea167SDimitry Andric 
1571a7dea167SDimitry Andric   // Parse inner context selectors.
15725ffd83dbSDimitry Andric   parseOMPContextSelectors(Loc, TI);
1573a7dea167SDimitry Andric 
15745ffd83dbSDimitry Andric   // Parse ')'
15755ffd83dbSDimitry Andric   (void)T.consumeClose();
1576e8d8bef9SDimitry Andric 
1577e8d8bef9SDimitry Andric   if (!ParentTI)
15785ffd83dbSDimitry Andric     return false;
1579e8d8bef9SDimitry Andric 
1580e8d8bef9SDimitry Andric   // Merge the parent/outer trait info into the one we just parsed and diagnose
1581e8d8bef9SDimitry Andric   // problems.
1582e8d8bef9SDimitry Andric   // TODO: Keep some source location in the TI to provide better diagnostics.
1583e8d8bef9SDimitry Andric   // TODO: Perform some kind of equivalence check on the condition and score
1584e8d8bef9SDimitry Andric   //       expressions.
1585e8d8bef9SDimitry Andric   for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
1586e8d8bef9SDimitry Andric     bool MergedSet = false;
1587e8d8bef9SDimitry Andric     for (OMPTraitSet &Set : TI.Sets) {
1588e8d8bef9SDimitry Andric       if (Set.Kind != ParentSet.Kind)
1589e8d8bef9SDimitry Andric         continue;
1590e8d8bef9SDimitry Andric       MergedSet = true;
1591e8d8bef9SDimitry Andric       for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
1592e8d8bef9SDimitry Andric         bool MergedSelector = false;
1593e8d8bef9SDimitry Andric         for (OMPTraitSelector &Selector : Set.Selectors) {
1594e8d8bef9SDimitry Andric           if (Selector.Kind != ParentSelector.Kind)
1595e8d8bef9SDimitry Andric             continue;
1596e8d8bef9SDimitry Andric           MergedSelector = true;
1597e8d8bef9SDimitry Andric           for (const OMPTraitProperty &ParentProperty :
1598e8d8bef9SDimitry Andric                ParentSelector.Properties) {
1599e8d8bef9SDimitry Andric             bool MergedProperty = false;
1600e8d8bef9SDimitry Andric             for (OMPTraitProperty &Property : Selector.Properties) {
1601e8d8bef9SDimitry Andric               // Ignore "equivalent" properties.
1602e8d8bef9SDimitry Andric               if (Property.Kind != ParentProperty.Kind)
1603e8d8bef9SDimitry Andric                 continue;
1604e8d8bef9SDimitry Andric 
1605e8d8bef9SDimitry Andric               // If the kind is the same but the raw string not, we don't want
1606e8d8bef9SDimitry Andric               // to skip out on the property.
1607e8d8bef9SDimitry Andric               MergedProperty |= Property.RawString == ParentProperty.RawString;
1608e8d8bef9SDimitry Andric 
1609e8d8bef9SDimitry Andric               if (Property.RawString == ParentProperty.RawString &&
1610e8d8bef9SDimitry Andric                   Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
1611e8d8bef9SDimitry Andric                 continue;
1612e8d8bef9SDimitry Andric 
1613e8d8bef9SDimitry Andric               if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1614e8d8bef9SDimitry Andric                 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1615e8d8bef9SDimitry Andric               } else if (Selector.ScoreOrCondition !=
1616e8d8bef9SDimitry Andric                          ParentSelector.ScoreOrCondition) {
1617e8d8bef9SDimitry Andric                 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1618e8d8bef9SDimitry Andric                     << getOpenMPContextTraitPropertyName(
1619e8d8bef9SDimitry Andric                            ParentProperty.Kind, ParentProperty.RawString)
1620e8d8bef9SDimitry Andric                     << getOpenMPContextTraitSelectorName(ParentSelector.Kind)
1621e8d8bef9SDimitry Andric                     << getOpenMPContextTraitSetName(ParentSet.Kind);
1622e8d8bef9SDimitry Andric               }
1623e8d8bef9SDimitry Andric             }
1624e8d8bef9SDimitry Andric             if (!MergedProperty)
1625e8d8bef9SDimitry Andric               Selector.Properties.push_back(ParentProperty);
1626e8d8bef9SDimitry Andric           }
1627e8d8bef9SDimitry Andric         }
1628e8d8bef9SDimitry Andric         if (!MergedSelector)
1629e8d8bef9SDimitry Andric           Set.Selectors.push_back(ParentSelector);
1630e8d8bef9SDimitry Andric       }
1631e8d8bef9SDimitry Andric     }
1632e8d8bef9SDimitry Andric     if (!MergedSet)
1633e8d8bef9SDimitry Andric       TI.Sets.push_back(ParentSet);
1634e8d8bef9SDimitry Andric   }
1635e8d8bef9SDimitry Andric 
1636e8d8bef9SDimitry Andric   return false;
1637e8d8bef9SDimitry Andric }
1638e8d8bef9SDimitry Andric 
1639bdd1243dSDimitry Andric /// <clause> [clause[ [,] clause] ... ]
1640bdd1243dSDimitry Andric ///
1641bdd1243dSDimitry Andric ///  clauses: for error directive
1642bdd1243dSDimitry Andric ///     'at' '(' compilation | execution ')'
1643bdd1243dSDimitry Andric ///     'severity' '(' fatal | warning ')'
1644bdd1243dSDimitry Andric ///     'message' '(' msg-string ')'
1645bdd1243dSDimitry Andric /// ....
ParseOpenMPClauses(OpenMPDirectiveKind DKind,SmallVectorImpl<OMPClause * > & Clauses,SourceLocation Loc)1646bdd1243dSDimitry Andric void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
1647bdd1243dSDimitry Andric                                 SmallVectorImpl<OMPClause *> &Clauses,
1648bdd1243dSDimitry Andric                                 SourceLocation Loc) {
1649*0fca6ea1SDimitry Andric   std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
1650bdd1243dSDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1651bdd1243dSDimitry Andric     OpenMPClauseKind CKind = Tok.isAnnotation()
1652bdd1243dSDimitry Andric                                  ? OMPC_unknown
1653bdd1243dSDimitry Andric                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
1654*0fca6ea1SDimitry Andric     Actions.OpenMP().StartOpenMPClause(CKind);
1655*0fca6ea1SDimitry Andric     OMPClause *Clause =
1656*0fca6ea1SDimitry Andric         ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
1657bdd1243dSDimitry Andric     SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1658bdd1243dSDimitry Andric               StopBeforeMatch);
1659*0fca6ea1SDimitry Andric     SeenClauses[unsigned(CKind)] = true;
1660bdd1243dSDimitry Andric     if (Clause != nullptr)
1661bdd1243dSDimitry Andric       Clauses.push_back(Clause);
1662bdd1243dSDimitry Andric     if (Tok.is(tok::annot_pragma_openmp_end)) {
1663*0fca6ea1SDimitry Andric       Actions.OpenMP().EndOpenMPClause();
1664bdd1243dSDimitry Andric       break;
1665bdd1243dSDimitry Andric     }
1666bdd1243dSDimitry Andric     // Skip ',' if any.
1667bdd1243dSDimitry Andric     if (Tok.is(tok::comma))
1668bdd1243dSDimitry Andric       ConsumeToken();
1669*0fca6ea1SDimitry Andric     Actions.OpenMP().EndOpenMPClause();
1670bdd1243dSDimitry Andric   }
1671bdd1243dSDimitry Andric }
1672bdd1243dSDimitry Andric 
1673e8d8bef9SDimitry Andric /// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
1674e8d8bef9SDimitry Andric /// where
1675e8d8bef9SDimitry Andric ///
1676e8d8bef9SDimitry Andric ///   clause:
1677e8d8bef9SDimitry Andric ///     'ext_IMPL_DEFINED'
1678e8d8bef9SDimitry Andric ///     'absent' '(' directive-name [, directive-name]* ')'
1679e8d8bef9SDimitry Andric ///     'contains' '(' directive-name [, directive-name]* ')'
1680e8d8bef9SDimitry Andric ///     'holds' '(' scalar-expression ')'
1681e8d8bef9SDimitry Andric ///     'no_openmp'
1682e8d8bef9SDimitry Andric ///     'no_openmp_routines'
1683e8d8bef9SDimitry Andric ///     'no_parallelism'
1684e8d8bef9SDimitry Andric ///
ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,SourceLocation Loc)1685e8d8bef9SDimitry Andric void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
1686e8d8bef9SDimitry Andric                                          SourceLocation Loc) {
1687349cc55cSDimitry Andric   SmallVector<std::string, 4> Assumptions;
1688e8d8bef9SDimitry Andric   bool SkippedClauses = false;
1689e8d8bef9SDimitry Andric 
1690e8d8bef9SDimitry Andric   auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
1691e8d8bef9SDimitry Andric     BalancedDelimiterTracker T(*this, tok::l_paren,
1692e8d8bef9SDimitry Andric                                tok::annot_pragma_openmp_end);
1693e8d8bef9SDimitry Andric     if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1694e8d8bef9SDimitry Andric       return;
1695e8d8bef9SDimitry Andric     T.skipToEnd();
1696e8d8bef9SDimitry Andric     if (IssueNote && T.getCloseLocation().isValid())
1697e8d8bef9SDimitry Andric       Diag(T.getCloseLocation(),
1698e8d8bef9SDimitry Andric            diag::note_omp_assumption_clause_continue_here);
1699e8d8bef9SDimitry Andric   };
1700e8d8bef9SDimitry Andric 
1701e8d8bef9SDimitry Andric   /// Helper to determine which AssumptionClauseMapping (ACM) in the
1702e8d8bef9SDimitry Andric   /// AssumptionClauseMappings table matches \p RawString. The return value is
1703e8d8bef9SDimitry Andric   /// the index of the matching ACM into the table or -1 if there was no match.
1704e8d8bef9SDimitry Andric   auto MatchACMClause = [&](StringRef RawString) {
1705e8d8bef9SDimitry Andric     llvm::StringSwitch<int> SS(RawString);
1706e8d8bef9SDimitry Andric     unsigned ACMIdx = 0;
1707e8d8bef9SDimitry Andric     for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1708e8d8bef9SDimitry Andric       if (ACMI.StartsWith)
1709e8d8bef9SDimitry Andric         SS.StartsWith(ACMI.Identifier, ACMIdx++);
1710e8d8bef9SDimitry Andric       else
1711e8d8bef9SDimitry Andric         SS.Case(ACMI.Identifier, ACMIdx++);
1712e8d8bef9SDimitry Andric     }
1713e8d8bef9SDimitry Andric     return SS.Default(-1);
1714e8d8bef9SDimitry Andric   };
1715e8d8bef9SDimitry Andric 
1716e8d8bef9SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1717e8d8bef9SDimitry Andric     IdentifierInfo *II = nullptr;
1718e8d8bef9SDimitry Andric     SourceLocation StartLoc = Tok.getLocation();
1719e8d8bef9SDimitry Andric     int Idx = -1;
1720e8d8bef9SDimitry Andric     if (Tok.isAnyIdentifier()) {
1721e8d8bef9SDimitry Andric       II = Tok.getIdentifierInfo();
1722e8d8bef9SDimitry Andric       Idx = MatchACMClause(II->getName());
1723e8d8bef9SDimitry Andric     }
1724e8d8bef9SDimitry Andric     ConsumeAnyToken();
1725e8d8bef9SDimitry Andric 
1726e8d8bef9SDimitry Andric     bool NextIsLPar = Tok.is(tok::l_paren);
1727e8d8bef9SDimitry Andric     // Handle unknown clauses by skipping them.
1728e8d8bef9SDimitry Andric     if (Idx == -1) {
1729e8d8bef9SDimitry Andric       Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1730e8d8bef9SDimitry Andric           << llvm::omp::getOpenMPDirectiveName(DKind)
1731e8d8bef9SDimitry Andric           << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1732e8d8bef9SDimitry Andric       if (NextIsLPar)
1733e8d8bef9SDimitry Andric         SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
1734e8d8bef9SDimitry Andric       SkippedClauses = true;
1735e8d8bef9SDimitry Andric       continue;
1736e8d8bef9SDimitry Andric     }
1737e8d8bef9SDimitry Andric     const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1738e8d8bef9SDimitry Andric     if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1739e8d8bef9SDimitry Andric       // TODO: We ignore absent, contains, and holds assumptions for now. We
1740e8d8bef9SDimitry Andric       //       also do not verify the content in the parenthesis at all.
1741e8d8bef9SDimitry Andric       SkippedClauses = true;
1742e8d8bef9SDimitry Andric       SkipBraces(II->getName(), /* IssueNote */ false);
1743e8d8bef9SDimitry Andric       continue;
1744e8d8bef9SDimitry Andric     }
1745e8d8bef9SDimitry Andric 
1746e8d8bef9SDimitry Andric     if (NextIsLPar) {
1747e8d8bef9SDimitry Andric       Diag(Tok.getLocation(),
1748e8d8bef9SDimitry Andric            diag::warn_omp_unknown_assumption_clause_without_args)
1749e8d8bef9SDimitry Andric           << II;
1750e8d8bef9SDimitry Andric       SkipBraces(II->getName(), /* IssueNote */ true);
1751e8d8bef9SDimitry Andric     }
1752e8d8bef9SDimitry Andric 
1753e8d8bef9SDimitry Andric     assert(II && "Expected an identifier clause!");
1754349cc55cSDimitry Andric     std::string Assumption = II->getName().str();
1755e8d8bef9SDimitry Andric     if (ACMI.StartsWith)
1756349cc55cSDimitry Andric       Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());
1757349cc55cSDimitry Andric     else
1758349cc55cSDimitry Andric       Assumption = "omp_" + Assumption;
1759e8d8bef9SDimitry Andric     Assumptions.push_back(Assumption);
1760e8d8bef9SDimitry Andric   }
1761e8d8bef9SDimitry Andric 
1762*0fca6ea1SDimitry Andric   Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,
1763*0fca6ea1SDimitry Andric                                                SkippedClauses);
1764e8d8bef9SDimitry Andric }
1765e8d8bef9SDimitry Andric 
ParseOpenMPEndAssumesDirective(SourceLocation Loc)1766e8d8bef9SDimitry Andric void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
1767*0fca6ea1SDimitry Andric   if (Actions.OpenMP().isInOpenMPAssumeScope())
1768*0fca6ea1SDimitry Andric     Actions.OpenMP().ActOnOpenMPEndAssumesDirective();
1769e8d8bef9SDimitry Andric   else
1770e8d8bef9SDimitry Andric     Diag(Loc, diag::err_expected_begin_assumes);
1771a7dea167SDimitry Andric }
1772a7dea167SDimitry Andric 
1773a7dea167SDimitry Andric /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1774a7dea167SDimitry Andric ///
1775a7dea167SDimitry Andric ///    default-clause:
177681ad6265SDimitry Andric ///         'default' '(' 'none' | 'shared'  | 'private' | 'firstprivate' ')
1777a7dea167SDimitry Andric ///
1778a7dea167SDimitry Andric ///    proc_bind-clause:
1779a7dea167SDimitry Andric ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
1780a7dea167SDimitry Andric ///
1781a7dea167SDimitry Andric ///    device_type-clause:
1782a7dea167SDimitry Andric ///         'device_type' '(' 'host' | 'nohost' | 'any' )'
1783a7dea167SDimitry Andric namespace {
1784a7dea167SDimitry Andric struct SimpleClauseData {
1785a7dea167SDimitry Andric   unsigned Type;
1786a7dea167SDimitry Andric   SourceLocation Loc;
1787a7dea167SDimitry Andric   SourceLocation LOpen;
1788a7dea167SDimitry Andric   SourceLocation TypeLoc;
1789a7dea167SDimitry Andric   SourceLocation RLoc;
SimpleClauseData__anon6a7266ce0c11::SimpleClauseData1790a7dea167SDimitry Andric   SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1791a7dea167SDimitry Andric                    SourceLocation TypeLoc, SourceLocation RLoc)
1792a7dea167SDimitry Andric       : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1793a7dea167SDimitry Andric };
1794a7dea167SDimitry Andric } // anonymous namespace
1795a7dea167SDimitry Andric 
1796bdd1243dSDimitry Andric static std::optional<SimpleClauseData>
parseOpenMPSimpleClause(Parser & P,OpenMPClauseKind Kind)1797a7dea167SDimitry Andric parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
1798a7dea167SDimitry Andric   const Token &Tok = P.getCurToken();
1799a7dea167SDimitry Andric   SourceLocation Loc = Tok.getLocation();
1800a7dea167SDimitry Andric   SourceLocation LOpen = P.ConsumeToken();
1801a7dea167SDimitry Andric   // Parse '('.
1802a7dea167SDimitry Andric   BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1803a7dea167SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
18045ffd83dbSDimitry Andric                          getOpenMPClauseName(Kind).data()))
1805bdd1243dSDimitry Andric     return std::nullopt;
1806a7dea167SDimitry Andric 
1807a7dea167SDimitry Andric   unsigned Type = getOpenMPSimpleClauseType(
1808e8d8bef9SDimitry Andric       Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
1809349cc55cSDimitry Andric       P.getLangOpts());
1810a7dea167SDimitry Andric   SourceLocation TypeLoc = Tok.getLocation();
1811a7dea167SDimitry Andric   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1812a7dea167SDimitry Andric       Tok.isNot(tok::annot_pragma_openmp_end))
1813a7dea167SDimitry Andric     P.ConsumeAnyToken();
1814a7dea167SDimitry Andric 
1815a7dea167SDimitry Andric   // Parse ')'.
1816a7dea167SDimitry Andric   SourceLocation RLoc = Tok.getLocation();
1817a7dea167SDimitry Andric   if (!T.consumeClose())
1818a7dea167SDimitry Andric     RLoc = T.getCloseLocation();
1819a7dea167SDimitry Andric 
1820a7dea167SDimitry Andric   return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1821a7dea167SDimitry Andric }
1822a7dea167SDimitry Andric 
ParseOMPDeclareTargetClauses(SemaOpenMP::DeclareTargetContextInfo & DTCI)1823fe6060f1SDimitry Andric void Parser::ParseOMPDeclareTargetClauses(
1824*0fca6ea1SDimitry Andric     SemaOpenMP::DeclareTargetContextInfo &DTCI) {
1825a7dea167SDimitry Andric   SourceLocation DeviceTypeLoc;
182604eeddc0SDimitry Andric   bool RequiresToOrLinkOrIndirectClause = false;
182704eeddc0SDimitry Andric   bool HasToOrLinkOrIndirectClause = false;
18280b57cec5SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
18290b57cec5SDimitry Andric     OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1830fe6060f1SDimitry Andric     bool HasIdentifier = Tok.is(tok::identifier);
1831fe6060f1SDimitry Andric     if (HasIdentifier) {
1832fe6060f1SDimitry Andric       // If we see any clause we need a to or link clause.
183304eeddc0SDimitry Andric       RequiresToOrLinkOrIndirectClause = true;
18340b57cec5SDimitry Andric       IdentifierInfo *II = Tok.getIdentifierInfo();
18350b57cec5SDimitry Andric       StringRef ClauseName = II->getName();
1836a7dea167SDimitry Andric       bool IsDeviceTypeClause =
1837a7dea167SDimitry Andric           getLangOpts().OpenMP >= 50 &&
1838a7dea167SDimitry Andric           getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1839fe6060f1SDimitry Andric 
184004eeddc0SDimitry Andric       bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
184104eeddc0SDimitry Andric                               getOpenMPClauseKind(ClauseName) == OMPC_indirect;
184281ad6265SDimitry Andric       if (DTCI.Indirect && IsIndirectClause) {
184304eeddc0SDimitry Andric         Diag(Tok, diag::err_omp_more_one_clause)
184404eeddc0SDimitry Andric             << getOpenMPDirectiveName(OMPD_declare_target)
184504eeddc0SDimitry Andric             << getOpenMPClauseName(OMPC_indirect) << 0;
184604eeddc0SDimitry Andric         break;
184704eeddc0SDimitry Andric       }
1848bdd1243dSDimitry Andric       bool IsToEnterOrLinkClause =
1849fe6060f1SDimitry Andric           OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1850bdd1243dSDimitry Andric       assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
1851bdd1243dSDimitry Andric              "Cannot be both!");
1852bdd1243dSDimitry Andric 
1853bdd1243dSDimitry Andric       // Starting with OpenMP 5.2 the `to` clause has been replaced by the
1854bdd1243dSDimitry Andric       // `enter` clause.
1855bdd1243dSDimitry Andric       if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
1856bdd1243dSDimitry Andric         Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1857bdd1243dSDimitry Andric         break;
1858bdd1243dSDimitry Andric       }
1859bdd1243dSDimitry Andric       if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
1860bdd1243dSDimitry Andric         Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1861bdd1243dSDimitry Andric         break;
1862bdd1243dSDimitry Andric       }
1863fe6060f1SDimitry Andric 
186404eeddc0SDimitry Andric       if (!IsDeviceTypeClause && !IsIndirectClause &&
186504eeddc0SDimitry Andric           DTCI.Kind == OMPD_begin_declare_target) {
1866a7dea167SDimitry Andric         Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
186704eeddc0SDimitry Andric             << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
18680b57cec5SDimitry Andric         break;
18690b57cec5SDimitry Andric       }
1870bdd1243dSDimitry Andric       if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
1871bdd1243dSDimitry Andric         Diag(Tok, getLangOpts().OpenMP >= 52
1872bdd1243dSDimitry Andric                       ? diag::err_omp_declare_target_unexpected_clause_52
1873bdd1243dSDimitry Andric                       : diag::err_omp_declare_target_unexpected_clause)
187404eeddc0SDimitry Andric             << ClauseName
1875bdd1243dSDimitry Andric             << (getLangOpts().OpenMP >= 51
1876bdd1243dSDimitry Andric                     ? 4
1877bdd1243dSDimitry Andric                     : getLangOpts().OpenMP >= 50 ? 2 : 1);
1878fe6060f1SDimitry Andric         break;
1879fe6060f1SDimitry Andric       }
1880fe6060f1SDimitry Andric 
1881bdd1243dSDimitry Andric       if (IsToEnterOrLinkClause || IsIndirectClause)
188204eeddc0SDimitry Andric         HasToOrLinkOrIndirectClause = true;
1883fe6060f1SDimitry Andric 
188404eeddc0SDimitry Andric       if (IsIndirectClause) {
188504eeddc0SDimitry Andric         if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
188604eeddc0SDimitry Andric           break;
188704eeddc0SDimitry Andric         continue;
188804eeddc0SDimitry Andric       }
1889a7dea167SDimitry Andric       // Parse 'device_type' clause and go to next clause if any.
1890a7dea167SDimitry Andric       if (IsDeviceTypeClause) {
1891bdd1243dSDimitry Andric         std::optional<SimpleClauseData> DevTypeData =
1892a7dea167SDimitry Andric             parseOpenMPSimpleClause(*this, OMPC_device_type);
189381ad6265SDimitry Andric         if (DevTypeData) {
1894a7dea167SDimitry Andric           if (DeviceTypeLoc.isValid()) {
1895a7dea167SDimitry Andric             // We already saw another device_type clause, diagnose it.
1896bdd1243dSDimitry Andric             Diag(DevTypeData->Loc,
1897a7dea167SDimitry Andric                  diag::warn_omp_more_one_device_type_clause);
1898fe6060f1SDimitry Andric             break;
1899a7dea167SDimitry Andric           }
1900bdd1243dSDimitry Andric           switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
1901a7dea167SDimitry Andric           case OMPC_DEVICE_TYPE_any:
1902fe6060f1SDimitry Andric             DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
1903a7dea167SDimitry Andric             break;
1904a7dea167SDimitry Andric           case OMPC_DEVICE_TYPE_host:
1905fe6060f1SDimitry Andric             DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
1906a7dea167SDimitry Andric             break;
1907a7dea167SDimitry Andric           case OMPC_DEVICE_TYPE_nohost:
1908fe6060f1SDimitry Andric             DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1909a7dea167SDimitry Andric             break;
1910a7dea167SDimitry Andric           case OMPC_DEVICE_TYPE_unknown:
1911a7dea167SDimitry Andric             llvm_unreachable("Unexpected device_type");
1912a7dea167SDimitry Andric           }
191381ad6265SDimitry Andric           DeviceTypeLoc = DevTypeData->Loc;
1914a7dea167SDimitry Andric         }
1915a7dea167SDimitry Andric         continue;
1916a7dea167SDimitry Andric       }
19170b57cec5SDimitry Andric       ConsumeToken();
19180b57cec5SDimitry Andric     }
1919fe6060f1SDimitry Andric 
1920fe6060f1SDimitry Andric     if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1921fe6060f1SDimitry Andric       auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
1922fe6060f1SDimitry Andric                                           DeclarationNameInfo NameInfo) {
1923*0fca6ea1SDimitry Andric         NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(
1924*0fca6ea1SDimitry Andric             getCurScope(), SS, NameInfo);
1925fe6060f1SDimitry Andric         if (!ND)
1926fe6060f1SDimitry Andric           return;
1927*0fca6ea1SDimitry Andric         SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
1928fe6060f1SDimitry Andric         bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
1929fe6060f1SDimitry Andric         if (!FirstMapping)
1930fe6060f1SDimitry Andric           Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
1931fe6060f1SDimitry Andric               << NameInfo.getName();
19320b57cec5SDimitry Andric       };
19330b57cec5SDimitry Andric       if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
19340b57cec5SDimitry Andric                                    /*AllowScopeSpecifier=*/true))
19350b57cec5SDimitry Andric         break;
1936fe6060f1SDimitry Andric     }
1937fe6060f1SDimitry Andric 
1938fe6060f1SDimitry Andric     if (Tok.is(tok::l_paren)) {
1939fe6060f1SDimitry Andric       Diag(Tok,
1940fe6060f1SDimitry Andric            diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1941fe6060f1SDimitry Andric       break;
1942fe6060f1SDimitry Andric     }
1943fe6060f1SDimitry Andric     if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
1944fe6060f1SDimitry Andric       Diag(Tok,
1945bdd1243dSDimitry Andric            getLangOpts().OpenMP >= 52
1946bdd1243dSDimitry Andric                ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1947bdd1243dSDimitry Andric                : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1948fe6060f1SDimitry Andric       break;
1949fe6060f1SDimitry Andric     }
19500b57cec5SDimitry Andric 
19510b57cec5SDimitry Andric     // Consume optional ','.
19520b57cec5SDimitry Andric     if (Tok.is(tok::comma))
19530b57cec5SDimitry Andric       ConsumeToken();
19540b57cec5SDimitry Andric   }
1955fe6060f1SDimitry Andric 
195681ad6265SDimitry Andric   if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
195704eeddc0SDimitry Andric     Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
195804eeddc0SDimitry Andric 
1959fe6060f1SDimitry Andric   // For declare target require at least 'to' or 'link' to be present.
196004eeddc0SDimitry Andric   if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
196104eeddc0SDimitry Andric       !HasToOrLinkOrIndirectClause)
1962bdd1243dSDimitry Andric     Diag(DTCI.Loc,
1963bdd1243dSDimitry Andric          getLangOpts().OpenMP >= 52
1964bdd1243dSDimitry Andric              ? diag::err_omp_declare_target_missing_enter_or_link_clause
1965bdd1243dSDimitry Andric              : diag::err_omp_declare_target_missing_to_or_link_clause)
196604eeddc0SDimitry Andric         << (getLangOpts().OpenMP >= 51 ? 1 : 0);
1967fe6060f1SDimitry Andric 
19680b57cec5SDimitry Andric   SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
19690b57cec5SDimitry Andric }
19700b57cec5SDimitry Andric 
skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind)19715ffd83dbSDimitry Andric void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
19725ffd83dbSDimitry Andric   // The last seen token is annot_pragma_openmp_end - need to check for
19735ffd83dbSDimitry Andric   // extra tokens.
19745ffd83dbSDimitry Andric   if (Tok.is(tok::annot_pragma_openmp_end))
19755ffd83dbSDimitry Andric     return;
19765ffd83dbSDimitry Andric 
19775ffd83dbSDimitry Andric   Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
19785ffd83dbSDimitry Andric       << getOpenMPDirectiveName(DKind);
19795ffd83dbSDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end))
19805ffd83dbSDimitry Andric     ConsumeAnyToken();
19815ffd83dbSDimitry Andric }
19825ffd83dbSDimitry Andric 
parseOMPEndDirective(OpenMPDirectiveKind BeginKind,OpenMPDirectiveKind ExpectedKind,OpenMPDirectiveKind FoundKind,SourceLocation BeginLoc,SourceLocation FoundLoc,bool SkipUntilOpenMPEnd)19835ffd83dbSDimitry Andric void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
19845ffd83dbSDimitry Andric                                   OpenMPDirectiveKind ExpectedKind,
19855ffd83dbSDimitry Andric                                   OpenMPDirectiveKind FoundKind,
19865ffd83dbSDimitry Andric                                   SourceLocation BeginLoc,
19875ffd83dbSDimitry Andric                                   SourceLocation FoundLoc,
19885ffd83dbSDimitry Andric                                   bool SkipUntilOpenMPEnd) {
19895ffd83dbSDimitry Andric   int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
19905ffd83dbSDimitry Andric 
19915ffd83dbSDimitry Andric   if (FoundKind == ExpectedKind) {
19925ffd83dbSDimitry Andric     ConsumeAnyToken();
19935ffd83dbSDimitry Andric     skipUntilPragmaOpenMPEnd(ExpectedKind);
19940b57cec5SDimitry Andric     return;
19950b57cec5SDimitry Andric   }
19965ffd83dbSDimitry Andric 
19975ffd83dbSDimitry Andric   Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
19985ffd83dbSDimitry Andric       << DiagSelection;
19995ffd83dbSDimitry Andric   Diag(BeginLoc, diag::note_matching)
20005ffd83dbSDimitry Andric       << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();
20015ffd83dbSDimitry Andric   if (SkipUntilOpenMPEnd)
20020b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
20030b57cec5SDimitry Andric }
20045ffd83dbSDimitry Andric 
ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,OpenMPDirectiveKind EndDKind,SourceLocation DKLoc)2005fe6060f1SDimitry Andric void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
2006fe6060f1SDimitry Andric                                                OpenMPDirectiveKind EndDKind,
20075ffd83dbSDimitry Andric                                                SourceLocation DKLoc) {
2008fe6060f1SDimitry Andric   parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
2009fe6060f1SDimitry Andric                        Tok.getLocation(),
20105ffd83dbSDimitry Andric                        /* SkipUntilOpenMPEnd */ false);
20110b57cec5SDimitry Andric   // Skip the last annot_pragma_openmp_end.
20125ffd83dbSDimitry Andric   if (Tok.is(tok::annot_pragma_openmp_end))
20135ffd83dbSDimitry Andric     ConsumeAnnotationToken();
20140b57cec5SDimitry Andric }
20150b57cec5SDimitry Andric 
20160b57cec5SDimitry Andric /// Parsing of declarative OpenMP directives.
20170b57cec5SDimitry Andric ///
20180b57cec5SDimitry Andric ///       threadprivate-directive:
20190b57cec5SDimitry Andric ///         annot_pragma_openmp 'threadprivate' simple-variable-list
20200b57cec5SDimitry Andric ///         annot_pragma_openmp_end
20210b57cec5SDimitry Andric ///
20220b57cec5SDimitry Andric ///       allocate-directive:
20230b57cec5SDimitry Andric ///         annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
20240b57cec5SDimitry Andric ///         annot_pragma_openmp_end
20250b57cec5SDimitry Andric ///
20260b57cec5SDimitry Andric ///       declare-reduction-directive:
20270b57cec5SDimitry Andric ///        annot_pragma_openmp 'declare' 'reduction' [...]
20280b57cec5SDimitry Andric ///        annot_pragma_openmp_end
20290b57cec5SDimitry Andric ///
20300b57cec5SDimitry Andric ///       declare-mapper-directive:
20310b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
20320b57cec5SDimitry Andric ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
20330b57cec5SDimitry Andric ///         annot_pragma_openmp_end
20340b57cec5SDimitry Andric ///
20350b57cec5SDimitry Andric ///       declare-simd-directive:
20360b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare simd' {<clause> [,]}
20370b57cec5SDimitry Andric ///         annot_pragma_openmp_end
20380b57cec5SDimitry Andric ///         <function declaration/definition>
20390b57cec5SDimitry Andric ///
20400b57cec5SDimitry Andric ///       requires directive:
20410b57cec5SDimitry Andric ///         annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
20420b57cec5SDimitry Andric ///         annot_pragma_openmp_end
20430b57cec5SDimitry Andric ///
2044e8d8bef9SDimitry Andric ///       assumes directive:
2045e8d8bef9SDimitry Andric ///         annot_pragma_openmp 'assumes' <clause> [[[,] <clause>] ... ]
2046e8d8bef9SDimitry Andric ///         annot_pragma_openmp_end
2047e8d8bef9SDimitry Andric ///       or
2048e8d8bef9SDimitry Andric ///         annot_pragma_openmp 'begin assumes' <clause> [[[,] <clause>] ... ]
2049e8d8bef9SDimitry Andric ///         annot_pragma_openmp 'end assumes'
2050e8d8bef9SDimitry Andric ///         annot_pragma_openmp_end
2051e8d8bef9SDimitry Andric ///
ParseOpenMPDeclarativeDirectiveWithExtDecl(AccessSpecifier & AS,ParsedAttributes & Attrs,bool Delayed,DeclSpec::TST TagType,Decl * Tag)20520b57cec5SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
205381ad6265SDimitry Andric     AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
20540b57cec5SDimitry Andric     DeclSpec::TST TagType, Decl *Tag) {
2055fe6060f1SDimitry Andric   assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2056fe6060f1SDimitry Andric          "Not an OpenMP directive!");
2057480093f4SDimitry Andric   ParsingOpenMPDirectiveRAII DirScope(*this);
20580b57cec5SDimitry Andric   ParenBraceBracketBalancer BalancerRAIIObj(*this);
20590b57cec5SDimitry Andric 
2060480093f4SDimitry Andric   SourceLocation Loc;
2061480093f4SDimitry Andric   OpenMPDirectiveKind DKind;
2062480093f4SDimitry Andric   if (Delayed) {
2063480093f4SDimitry Andric     TentativeParsingAction TPA(*this);
2064480093f4SDimitry Andric     Loc = ConsumeAnnotationToken();
2065480093f4SDimitry Andric     DKind = parseOpenMPDirectiveKind(*this);
2066480093f4SDimitry Andric     if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
2067480093f4SDimitry Andric       // Need to delay parsing until completion of the parent class.
2068480093f4SDimitry Andric       TPA.Revert();
2069480093f4SDimitry Andric       CachedTokens Toks;
2070480093f4SDimitry Andric       unsigned Cnt = 1;
2071480093f4SDimitry Andric       Toks.push_back(Tok);
2072480093f4SDimitry Andric       while (Cnt && Tok.isNot(tok::eof)) {
2073480093f4SDimitry Andric         (void)ConsumeAnyToken();
2074fe6060f1SDimitry Andric         if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
2075480093f4SDimitry Andric           ++Cnt;
2076480093f4SDimitry Andric         else if (Tok.is(tok::annot_pragma_openmp_end))
2077480093f4SDimitry Andric           --Cnt;
2078480093f4SDimitry Andric         Toks.push_back(Tok);
2079480093f4SDimitry Andric       }
2080480093f4SDimitry Andric       // Skip last annot_pragma_openmp_end.
2081480093f4SDimitry Andric       if (Cnt == 0)
2082480093f4SDimitry Andric         (void)ConsumeAnyToken();
2083480093f4SDimitry Andric       auto *LP = new LateParsedPragma(this, AS);
2084480093f4SDimitry Andric       LP->takeToks(Toks);
2085480093f4SDimitry Andric       getCurrentClass().LateParsedDeclarations.push_back(LP);
2086480093f4SDimitry Andric       return nullptr;
2087480093f4SDimitry Andric     }
2088480093f4SDimitry Andric     TPA.Commit();
2089480093f4SDimitry Andric   } else {
2090480093f4SDimitry Andric     Loc = ConsumeAnnotationToken();
2091480093f4SDimitry Andric     DKind = parseOpenMPDirectiveKind(*this);
2092480093f4SDimitry Andric   }
20930b57cec5SDimitry Andric 
20940b57cec5SDimitry Andric   switch (DKind) {
20950b57cec5SDimitry Andric   case OMPD_threadprivate: {
20960b57cec5SDimitry Andric     ConsumeToken();
20970b57cec5SDimitry Andric     DeclDirectiveListParserHelper Helper(this, DKind);
20980b57cec5SDimitry Andric     if (!ParseOpenMPSimpleVarList(DKind, Helper,
20990b57cec5SDimitry Andric                                   /*AllowScopeSpecifier=*/true)) {
21005ffd83dbSDimitry Andric       skipUntilPragmaOpenMPEnd(DKind);
21010b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
21020b57cec5SDimitry Andric       ConsumeAnnotationToken();
2103*0fca6ea1SDimitry Andric       return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2104*0fca6ea1SDimitry Andric           Loc, Helper.getIdentifiers());
21050b57cec5SDimitry Andric     }
21060b57cec5SDimitry Andric     break;
21070b57cec5SDimitry Andric   }
21080b57cec5SDimitry Andric   case OMPD_allocate: {
21090b57cec5SDimitry Andric     ConsumeToken();
21100b57cec5SDimitry Andric     DeclDirectiveListParserHelper Helper(this, DKind);
21110b57cec5SDimitry Andric     if (!ParseOpenMPSimpleVarList(DKind, Helper,
21120b57cec5SDimitry Andric                                   /*AllowScopeSpecifier=*/true)) {
21130b57cec5SDimitry Andric       SmallVector<OMPClause *, 1> Clauses;
21140b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2115*0fca6ea1SDimitry Andric         std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
21160b57cec5SDimitry Andric         while (Tok.isNot(tok::annot_pragma_openmp_end)) {
21170b57cec5SDimitry Andric           OpenMPClauseKind CKind =
21180b57cec5SDimitry Andric               Tok.isAnnotation() ? OMPC_unknown
21190b57cec5SDimitry Andric                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
2120*0fca6ea1SDimitry Andric           Actions.OpenMP().StartOpenMPClause(CKind);
2121*0fca6ea1SDimitry Andric           OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2122*0fca6ea1SDimitry Andric                                                 !SeenClauses[unsigned(CKind)]);
21230b57cec5SDimitry Andric           SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
21240b57cec5SDimitry Andric                     StopBeforeMatch);
2125*0fca6ea1SDimitry Andric           SeenClauses[unsigned(CKind)] = true;
21260b57cec5SDimitry Andric           if (Clause != nullptr)
21270b57cec5SDimitry Andric             Clauses.push_back(Clause);
21280b57cec5SDimitry Andric           if (Tok.is(tok::annot_pragma_openmp_end)) {
2129*0fca6ea1SDimitry Andric             Actions.OpenMP().EndOpenMPClause();
21300b57cec5SDimitry Andric             break;
21310b57cec5SDimitry Andric           }
21320b57cec5SDimitry Andric           // Skip ',' if any.
21330b57cec5SDimitry Andric           if (Tok.is(tok::comma))
21340b57cec5SDimitry Andric             ConsumeToken();
2135*0fca6ea1SDimitry Andric           Actions.OpenMP().EndOpenMPClause();
21360b57cec5SDimitry Andric         }
21375ffd83dbSDimitry Andric         skipUntilPragmaOpenMPEnd(DKind);
21380b57cec5SDimitry Andric       }
21390b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
21400b57cec5SDimitry Andric       ConsumeAnnotationToken();
2141*0fca6ea1SDimitry Andric       return Actions.OpenMP().ActOnOpenMPAllocateDirective(
2142*0fca6ea1SDimitry Andric           Loc, Helper.getIdentifiers(), Clauses);
21430b57cec5SDimitry Andric     }
21440b57cec5SDimitry Andric     break;
21450b57cec5SDimitry Andric   }
21460b57cec5SDimitry Andric   case OMPD_requires: {
21470b57cec5SDimitry Andric     SourceLocation StartLoc = ConsumeToken();
21480b57cec5SDimitry Andric     SmallVector<OMPClause *, 5> Clauses;
2149*0fca6ea1SDimitry Andric     llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
21500b57cec5SDimitry Andric     if (Tok.is(tok::annot_pragma_openmp_end)) {
21510b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_expected_clause)
21520b57cec5SDimitry Andric           << getOpenMPDirectiveName(OMPD_requires);
21530b57cec5SDimitry Andric       break;
21540b57cec5SDimitry Andric     }
21550b57cec5SDimitry Andric     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
21560b57cec5SDimitry Andric       OpenMPClauseKind CKind = Tok.isAnnotation()
21570b57cec5SDimitry Andric                                    ? OMPC_unknown
21580b57cec5SDimitry Andric                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
2159*0fca6ea1SDimitry Andric       Actions.OpenMP().StartOpenMPClause(CKind);
2160*0fca6ea1SDimitry Andric       OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
2161*0fca6ea1SDimitry Andric                                             !SeenClauses[unsigned(CKind)]);
21620b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
21630b57cec5SDimitry Andric                 StopBeforeMatch);
2164*0fca6ea1SDimitry Andric       SeenClauses[unsigned(CKind)] = true;
21650b57cec5SDimitry Andric       if (Clause != nullptr)
21660b57cec5SDimitry Andric         Clauses.push_back(Clause);
21670b57cec5SDimitry Andric       if (Tok.is(tok::annot_pragma_openmp_end)) {
2168*0fca6ea1SDimitry Andric         Actions.OpenMP().EndOpenMPClause();
21690b57cec5SDimitry Andric         break;
21700b57cec5SDimitry Andric       }
21710b57cec5SDimitry Andric       // Skip ',' if any.
21720b57cec5SDimitry Andric       if (Tok.is(tok::comma))
21730b57cec5SDimitry Andric         ConsumeToken();
2174*0fca6ea1SDimitry Andric       Actions.OpenMP().EndOpenMPClause();
21750b57cec5SDimitry Andric     }
21760b57cec5SDimitry Andric     // Consume final annot_pragma_openmp_end
21775ffd83dbSDimitry Andric     if (Clauses.empty()) {
21780b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_expected_clause)
21790b57cec5SDimitry Andric           << getOpenMPDirectiveName(OMPD_requires);
21800b57cec5SDimitry Andric       ConsumeAnnotationToken();
21810b57cec5SDimitry Andric       return nullptr;
21820b57cec5SDimitry Andric     }
21830b57cec5SDimitry Andric     ConsumeAnnotationToken();
2184*0fca6ea1SDimitry Andric     return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);
21850b57cec5SDimitry Andric   }
2186bdd1243dSDimitry Andric   case OMPD_error: {
2187bdd1243dSDimitry Andric     SmallVector<OMPClause *, 1> Clauses;
2188bdd1243dSDimitry Andric     SourceLocation StartLoc = ConsumeToken();
2189bdd1243dSDimitry Andric     ParseOpenMPClauses(DKind, Clauses, StartLoc);
2190*0fca6ea1SDimitry Andric     Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
2191*0fca6ea1SDimitry Andric                                                SourceLocation(),
2192bdd1243dSDimitry Andric                                                /*InExContext = */ false);
2193bdd1243dSDimitry Andric     break;
2194bdd1243dSDimitry Andric   }
2195e8d8bef9SDimitry Andric   case OMPD_assumes:
2196e8d8bef9SDimitry Andric   case OMPD_begin_assumes:
2197e8d8bef9SDimitry Andric     ParseOpenMPAssumesDirective(DKind, ConsumeToken());
2198e8d8bef9SDimitry Andric     break;
2199e8d8bef9SDimitry Andric   case OMPD_end_assumes:
2200e8d8bef9SDimitry Andric     ParseOpenMPEndAssumesDirective(ConsumeToken());
2201e8d8bef9SDimitry Andric     break;
22020b57cec5SDimitry Andric   case OMPD_declare_reduction:
22030b57cec5SDimitry Andric     ConsumeToken();
22040b57cec5SDimitry Andric     if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
22055ffd83dbSDimitry Andric       skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
22060b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
22070b57cec5SDimitry Andric       ConsumeAnnotationToken();
22080b57cec5SDimitry Andric       return Res;
22090b57cec5SDimitry Andric     }
22100b57cec5SDimitry Andric     break;
22110b57cec5SDimitry Andric   case OMPD_declare_mapper: {
22120b57cec5SDimitry Andric     ConsumeToken();
22130b57cec5SDimitry Andric     if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
22140b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
22150b57cec5SDimitry Andric       ConsumeAnnotationToken();
22160b57cec5SDimitry Andric       return Res;
22170b57cec5SDimitry Andric     }
22180b57cec5SDimitry Andric     break;
22190b57cec5SDimitry Andric   }
22205ffd83dbSDimitry Andric   case OMPD_begin_declare_variant: {
22215ffd83dbSDimitry Andric     // The syntax is:
22225ffd83dbSDimitry Andric     // { #pragma omp begin declare variant clause }
22235ffd83dbSDimitry Andric     // <function-declaration-or-definition-sequence>
22245ffd83dbSDimitry Andric     // { #pragma omp end declare variant }
22255ffd83dbSDimitry Andric     //
22265ffd83dbSDimitry Andric     ConsumeToken();
2227*0fca6ea1SDimitry Andric     OMPTraitInfo *ParentTI =
2228*0fca6ea1SDimitry Andric         Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
2229e8d8bef9SDimitry Andric     ASTContext &ASTCtx = Actions.getASTContext();
2230e8d8bef9SDimitry Andric     OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
2231349cc55cSDimitry Andric     if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
2232349cc55cSDimitry Andric       while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
2233349cc55cSDimitry Andric         ;
2234349cc55cSDimitry Andric       // Skip the last annot_pragma_openmp_end.
2235349cc55cSDimitry Andric       (void)ConsumeAnnotationToken();
22365ffd83dbSDimitry Andric       break;
2237349cc55cSDimitry Andric     }
22385ffd83dbSDimitry Andric 
22395ffd83dbSDimitry Andric     // Skip last tokens.
22405ffd83dbSDimitry Andric     skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
22415ffd83dbSDimitry Andric 
22425ffd83dbSDimitry Andric     ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
22435ffd83dbSDimitry Andric 
22445ffd83dbSDimitry Andric     VariantMatchInfo VMI;
22455ffd83dbSDimitry Andric     TI.getAsVariantMatchInfo(ASTCtx, VMI);
2246e8d8bef9SDimitry Andric 
224704eeddc0SDimitry Andric     std::function<void(StringRef)> DiagUnknownTrait =
224804eeddc0SDimitry Andric         [this, Loc](StringRef ISATrait) {
224904eeddc0SDimitry Andric           // TODO Track the selector locations in a way that is accessible here
225004eeddc0SDimitry Andric           // to improve the diagnostic location.
225104eeddc0SDimitry Andric           Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2252e8d8bef9SDimitry Andric         };
2253349cc55cSDimitry Andric     TargetOMPContext OMPCtx(
2254349cc55cSDimitry Andric         ASTCtx, std::move(DiagUnknownTrait),
2255349cc55cSDimitry Andric         /* CurrentFunctionDecl */ nullptr,
2256349cc55cSDimitry Andric         /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>());
22575ffd83dbSDimitry Andric 
22585ffd83dbSDimitry Andric     if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) {
2259*0fca6ea1SDimitry Andric       Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);
22605ffd83dbSDimitry Andric       break;
22615ffd83dbSDimitry Andric     }
22625ffd83dbSDimitry Andric 
22635ffd83dbSDimitry Andric     // Elide all the code till the matching end declare variant was found.
22645ffd83dbSDimitry Andric     unsigned Nesting = 1;
22655ffd83dbSDimitry Andric     SourceLocation DKLoc;
22665ffd83dbSDimitry Andric     OpenMPDirectiveKind DK = OMPD_unknown;
22675ffd83dbSDimitry Andric     do {
22685ffd83dbSDimitry Andric       DKLoc = Tok.getLocation();
22695ffd83dbSDimitry Andric       DK = parseOpenMPDirectiveKind(*this);
22705ffd83dbSDimitry Andric       if (DK == OMPD_end_declare_variant)
22715ffd83dbSDimitry Andric         --Nesting;
22725ffd83dbSDimitry Andric       else if (DK == OMPD_begin_declare_variant)
22735ffd83dbSDimitry Andric         ++Nesting;
22745ffd83dbSDimitry Andric       if (!Nesting || isEofOrEom())
22755ffd83dbSDimitry Andric         break;
22765ffd83dbSDimitry Andric       ConsumeAnyToken();
22775ffd83dbSDimitry Andric     } while (true);
22785ffd83dbSDimitry Andric 
22795ffd83dbSDimitry Andric     parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
22805ffd83dbSDimitry Andric                          DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
22815ffd83dbSDimitry Andric     if (isEofOrEom())
22825ffd83dbSDimitry Andric       return nullptr;
22835ffd83dbSDimitry Andric     break;
22845ffd83dbSDimitry Andric   }
22855ffd83dbSDimitry Andric   case OMPD_end_declare_variant: {
2286*0fca6ea1SDimitry Andric     if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2287*0fca6ea1SDimitry Andric       Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
22885ffd83dbSDimitry Andric     else
22895ffd83dbSDimitry Andric       Diag(Loc, diag::err_expected_begin_declare_variant);
22905ffd83dbSDimitry Andric     ConsumeToken();
22915ffd83dbSDimitry Andric     break;
22925ffd83dbSDimitry Andric   }
2293a7dea167SDimitry Andric   case OMPD_declare_variant:
22940b57cec5SDimitry Andric   case OMPD_declare_simd: {
22950b57cec5SDimitry Andric     // The syntax is:
2296a7dea167SDimitry Andric     // { #pragma omp declare {simd|variant} }
22970b57cec5SDimitry Andric     // <function-declaration-or-definition>
22980b57cec5SDimitry Andric     //
22990b57cec5SDimitry Andric     CachedTokens Toks;
2300a7dea167SDimitry Andric     Toks.push_back(Tok);
2301a7dea167SDimitry Andric     ConsumeToken();
23020b57cec5SDimitry Andric     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
23030b57cec5SDimitry Andric       Toks.push_back(Tok);
23040b57cec5SDimitry Andric       ConsumeAnyToken();
23050b57cec5SDimitry Andric     }
23060b57cec5SDimitry Andric     Toks.push_back(Tok);
23070b57cec5SDimitry Andric     ConsumeAnyToken();
23080b57cec5SDimitry Andric 
23090b57cec5SDimitry Andric     DeclGroupPtrTy Ptr;
2310fe6060f1SDimitry Andric     if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2311480093f4SDimitry Andric       Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2312480093f4SDimitry Andric                                                        TagType, Tag);
23130b57cec5SDimitry Andric     } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
23140b57cec5SDimitry Andric       // Here we expect to see some function declaration.
23150b57cec5SDimitry Andric       if (AS == AS_none) {
23160b57cec5SDimitry Andric         assert(TagType == DeclSpec::TST_unspecified);
2317bdd1243dSDimitry Andric         ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
23180b57cec5SDimitry Andric         MaybeParseCXX11Attributes(Attrs);
23190b57cec5SDimitry Andric         ParsingDeclSpec PDS(*this);
2320bdd1243dSDimitry Andric         Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
23210b57cec5SDimitry Andric       } else {
23220b57cec5SDimitry Andric         Ptr =
23230b57cec5SDimitry Andric             ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
23240b57cec5SDimitry Andric       }
23250b57cec5SDimitry Andric     }
23260b57cec5SDimitry Andric     if (!Ptr) {
2327a7dea167SDimitry Andric       Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2328a7dea167SDimitry Andric           << (DKind == OMPD_declare_simd ? 0 : 1);
23290b57cec5SDimitry Andric       return DeclGroupPtrTy();
23300b57cec5SDimitry Andric     }
2331a7dea167SDimitry Andric     if (DKind == OMPD_declare_simd)
23320b57cec5SDimitry Andric       return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2333a7dea167SDimitry Andric     assert(DKind == OMPD_declare_variant &&
2334a7dea167SDimitry Andric            "Expected declare variant directive only");
2335a7dea167SDimitry Andric     ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2336a7dea167SDimitry Andric     return Ptr;
23370b57cec5SDimitry Andric   }
2338fe6060f1SDimitry Andric   case OMPD_begin_declare_target:
23390b57cec5SDimitry Andric   case OMPD_declare_target: {
23400b57cec5SDimitry Andric     SourceLocation DTLoc = ConsumeAnyToken();
2341fe6060f1SDimitry Andric     bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2342*0fca6ea1SDimitry Andric     SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2343fe6060f1SDimitry Andric     if (HasClauses)
2344fe6060f1SDimitry Andric       ParseOMPDeclareTargetClauses(DTCI);
234581ad6265SDimitry Andric     bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
234681ad6265SDimitry Andric                                !HasClauses ||
234781ad6265SDimitry Andric                                (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
23480b57cec5SDimitry Andric 
23490b57cec5SDimitry Andric     // Skip the last annot_pragma_openmp_end.
23500b57cec5SDimitry Andric     ConsumeAnyToken();
23510b57cec5SDimitry Andric 
2352fe6060f1SDimitry Andric     if (HasImplicitMappings) {
2353*0fca6ea1SDimitry Andric       Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);
2354fe6060f1SDimitry Andric       return nullptr;
2355fe6060f1SDimitry Andric     }
23560b57cec5SDimitry Andric 
2357*0fca6ea1SDimitry Andric     Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
23580b57cec5SDimitry Andric     llvm::SmallVector<Decl *, 4> Decls;
2359fe6060f1SDimitry Andric     for (auto &It : DTCI.ExplicitlyMapped)
2360fe6060f1SDimitry Andric       Decls.push_back(It.first);
23610b57cec5SDimitry Andric     return Actions.BuildDeclaratorGroup(Decls);
23620b57cec5SDimitry Andric   }
2363fe6060f1SDimitry Andric   case OMPD_end_declare_target: {
2364*0fca6ea1SDimitry Andric     if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
2365fe6060f1SDimitry Andric       Diag(Tok, diag::err_omp_unexpected_directive)
2366fe6060f1SDimitry Andric           << 1 << getOpenMPDirectiveName(DKind);
2367fe6060f1SDimitry Andric       break;
2368fe6060f1SDimitry Andric     }
2369*0fca6ea1SDimitry Andric     const SemaOpenMP::DeclareTargetContextInfo &DTCI =
2370*0fca6ea1SDimitry Andric         Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();
2371fe6060f1SDimitry Andric     ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2372fe6060f1SDimitry Andric     return nullptr;
2373fe6060f1SDimitry Andric   }
23740b57cec5SDimitry Andric   case OMPD_unknown:
23750b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_unknown_directive);
23760b57cec5SDimitry Andric     break;
2377*0fca6ea1SDimitry Andric   default:
2378*0fca6ea1SDimitry Andric     switch (getDirectiveCategory(DKind)) {
2379*0fca6ea1SDimitry Andric     case Category::Executable:
2380*0fca6ea1SDimitry Andric     case Category::Meta:
2381*0fca6ea1SDimitry Andric     case Category::Subsidiary:
2382*0fca6ea1SDimitry Andric     case Category::Utility:
23830b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_unexpected_directive)
23840b57cec5SDimitry Andric           << 1 << getOpenMPDirectiveName(DKind);
23850b57cec5SDimitry Andric       break;
2386*0fca6ea1SDimitry Andric     case Category::Declarative:
2387*0fca6ea1SDimitry Andric     case Category::Informational:
23885ffd83dbSDimitry Andric       break;
23890b57cec5SDimitry Andric     }
2390*0fca6ea1SDimitry Andric   }
23910b57cec5SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end))
23920b57cec5SDimitry Andric     ConsumeAnyToken();
23930b57cec5SDimitry Andric   ConsumeAnyToken();
23940b57cec5SDimitry Andric   return nullptr;
23950b57cec5SDimitry Andric }
23960b57cec5SDimitry Andric 
ParseOpenMPExecutableDirective(ParsedStmtContext StmtCtx,OpenMPDirectiveKind DKind,SourceLocation Loc,bool ReadDirectiveWithinMetadirective)2397*0fca6ea1SDimitry Andric StmtResult Parser::ParseOpenMPExecutableDirective(
2398*0fca6ea1SDimitry Andric     ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2399*0fca6ea1SDimitry Andric     bool ReadDirectiveWithinMetadirective) {
2400*0fca6ea1SDimitry Andric   assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
2401*0fca6ea1SDimitry Andric 
2402*0fca6ea1SDimitry Andric   bool HasAssociatedStatement = true;
2403*0fca6ea1SDimitry Andric   Association Assoc = getDirectiveAssociation(DKind);
2404*0fca6ea1SDimitry Andric 
2405*0fca6ea1SDimitry Andric   // OMPD_ordered has None as association, but it comes in two variants,
2406*0fca6ea1SDimitry Andric   // the second of which is associated with a block.
2407*0fca6ea1SDimitry Andric   // OMPD_scan and OMPD_section are both "separating", but section is treated
2408*0fca6ea1SDimitry Andric   // as if it was associated with a statement, while scan is not.
2409*0fca6ea1SDimitry Andric   if (DKind != OMPD_ordered && DKind != OMPD_section &&
2410*0fca6ea1SDimitry Andric       (Assoc == Association::None || Assoc == Association::Separating)) {
2411*0fca6ea1SDimitry Andric     if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2412*0fca6ea1SDimitry Andric         ParsedStmtContext()) {
2413*0fca6ea1SDimitry Andric       Diag(Tok, diag::err_omp_immediate_directive)
2414*0fca6ea1SDimitry Andric           << getOpenMPDirectiveName(DKind) << 0;
2415*0fca6ea1SDimitry Andric       if (DKind == OMPD_error) {
2416*0fca6ea1SDimitry Andric         SkipUntil(tok::annot_pragma_openmp_end);
2417*0fca6ea1SDimitry Andric         return StmtError();
2418*0fca6ea1SDimitry Andric       }
2419*0fca6ea1SDimitry Andric     }
2420*0fca6ea1SDimitry Andric     HasAssociatedStatement = false;
2421*0fca6ea1SDimitry Andric   }
2422*0fca6ea1SDimitry Andric 
2423*0fca6ea1SDimitry Andric   SourceLocation EndLoc;
2424*0fca6ea1SDimitry Andric   SmallVector<OMPClause *, 5> Clauses;
2425*0fca6ea1SDimitry Andric   llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2426*0fca6ea1SDimitry Andric   DeclarationNameInfo DirName;
2427*0fca6ea1SDimitry Andric   OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2428*0fca6ea1SDimitry Andric   unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2429*0fca6ea1SDimitry Andric                         Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
2430*0fca6ea1SDimitry Andric 
2431*0fca6ea1SDimitry Andric   // Special processing for flush and depobj clauses.
2432*0fca6ea1SDimitry Andric   Token ImplicitTok;
2433*0fca6ea1SDimitry Andric   bool ImplicitClauseAllowed = false;
2434*0fca6ea1SDimitry Andric   if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2435*0fca6ea1SDimitry Andric     ImplicitTok = Tok;
2436*0fca6ea1SDimitry Andric     ImplicitClauseAllowed = true;
2437*0fca6ea1SDimitry Andric   }
2438*0fca6ea1SDimitry Andric   ConsumeToken();
2439*0fca6ea1SDimitry Andric   // Parse directive name of the 'critical' directive if any.
2440*0fca6ea1SDimitry Andric   if (DKind == OMPD_critical) {
2441*0fca6ea1SDimitry Andric     BalancedDelimiterTracker T(*this, tok::l_paren,
2442*0fca6ea1SDimitry Andric                                tok::annot_pragma_openmp_end);
2443*0fca6ea1SDimitry Andric     if (!T.consumeOpen()) {
2444*0fca6ea1SDimitry Andric       if (Tok.isAnyIdentifier()) {
2445*0fca6ea1SDimitry Andric         DirName =
2446*0fca6ea1SDimitry Andric             DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
2447*0fca6ea1SDimitry Andric         ConsumeAnyToken();
2448*0fca6ea1SDimitry Andric       } else {
2449*0fca6ea1SDimitry Andric         Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2450*0fca6ea1SDimitry Andric       }
2451*0fca6ea1SDimitry Andric       T.consumeClose();
2452*0fca6ea1SDimitry Andric     }
2453*0fca6ea1SDimitry Andric   } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2454*0fca6ea1SDimitry Andric     CancelRegion = parseOpenMPDirectiveKind(*this);
2455*0fca6ea1SDimitry Andric     if (Tok.isNot(tok::annot_pragma_openmp_end))
2456*0fca6ea1SDimitry Andric       ConsumeToken();
2457*0fca6ea1SDimitry Andric   }
2458*0fca6ea1SDimitry Andric 
2459*0fca6ea1SDimitry Andric   if (isOpenMPLoopDirective(DKind))
2460*0fca6ea1SDimitry Andric     ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2461*0fca6ea1SDimitry Andric   if (isOpenMPSimdDirective(DKind))
2462*0fca6ea1SDimitry Andric     ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2463*0fca6ea1SDimitry Andric   ParseScope OMPDirectiveScope(this, ScopeFlags);
2464*0fca6ea1SDimitry Andric   Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2465*0fca6ea1SDimitry Andric                                        Loc);
2466*0fca6ea1SDimitry Andric 
2467*0fca6ea1SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2468*0fca6ea1SDimitry Andric     // If we are parsing for a directive within a metadirective, the directive
2469*0fca6ea1SDimitry Andric     // ends with a ')'.
2470*0fca6ea1SDimitry Andric     if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2471*0fca6ea1SDimitry Andric       while (Tok.isNot(tok::annot_pragma_openmp_end))
2472*0fca6ea1SDimitry Andric         ConsumeAnyToken();
2473*0fca6ea1SDimitry Andric       break;
2474*0fca6ea1SDimitry Andric     }
2475*0fca6ea1SDimitry Andric     bool HasImplicitClause = false;
2476*0fca6ea1SDimitry Andric     if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2477*0fca6ea1SDimitry Andric       HasImplicitClause = true;
2478*0fca6ea1SDimitry Andric       // Push copy of the current token back to stream to properly parse
2479*0fca6ea1SDimitry Andric       // pseudo-clause OMPFlushClause or OMPDepobjClause.
2480*0fca6ea1SDimitry Andric       PP.EnterToken(Tok, /*IsReinject*/ true);
2481*0fca6ea1SDimitry Andric       PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2482*0fca6ea1SDimitry Andric       ConsumeAnyToken();
2483*0fca6ea1SDimitry Andric     }
2484*0fca6ea1SDimitry Andric     OpenMPClauseKind CKind = Tok.isAnnotation()
2485*0fca6ea1SDimitry Andric                                  ? OMPC_unknown
2486*0fca6ea1SDimitry Andric                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
2487*0fca6ea1SDimitry Andric     if (HasImplicitClause) {
2488*0fca6ea1SDimitry Andric       assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2489*0fca6ea1SDimitry Andric       if (DKind == OMPD_flush) {
2490*0fca6ea1SDimitry Andric         CKind = OMPC_flush;
2491*0fca6ea1SDimitry Andric       } else {
2492*0fca6ea1SDimitry Andric         assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
2493*0fca6ea1SDimitry Andric         CKind = OMPC_depobj;
2494*0fca6ea1SDimitry Andric       }
2495*0fca6ea1SDimitry Andric     }
2496*0fca6ea1SDimitry Andric     // No more implicit clauses allowed.
2497*0fca6ea1SDimitry Andric     ImplicitClauseAllowed = false;
2498*0fca6ea1SDimitry Andric     Actions.OpenMP().StartOpenMPClause(CKind);
2499*0fca6ea1SDimitry Andric     HasImplicitClause = false;
2500*0fca6ea1SDimitry Andric     OMPClause *Clause =
2501*0fca6ea1SDimitry Andric         ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2502*0fca6ea1SDimitry Andric     SeenClauses[unsigned(CKind)] = true;
2503*0fca6ea1SDimitry Andric     if (Clause)
2504*0fca6ea1SDimitry Andric       Clauses.push_back(Clause);
2505*0fca6ea1SDimitry Andric 
2506*0fca6ea1SDimitry Andric     // Skip ',' if any.
2507*0fca6ea1SDimitry Andric     if (Tok.is(tok::comma))
2508*0fca6ea1SDimitry Andric       ConsumeToken();
2509*0fca6ea1SDimitry Andric     Actions.OpenMP().EndOpenMPClause();
2510*0fca6ea1SDimitry Andric   }
2511*0fca6ea1SDimitry Andric   // End location of the directive.
2512*0fca6ea1SDimitry Andric   EndLoc = Tok.getLocation();
2513*0fca6ea1SDimitry Andric   // Consume final annot_pragma_openmp_end.
2514*0fca6ea1SDimitry Andric   ConsumeAnnotationToken();
2515*0fca6ea1SDimitry Andric 
2516*0fca6ea1SDimitry Andric   if (DKind == OMPD_ordered) {
2517*0fca6ea1SDimitry Andric     // If the depend or doacross clause is specified, the ordered construct
2518*0fca6ea1SDimitry Andric     // is a stand-alone directive.
2519*0fca6ea1SDimitry Andric     for (auto CK : {OMPC_depend, OMPC_doacross}) {
2520*0fca6ea1SDimitry Andric       if (SeenClauses[unsigned(CK)]) {
2521*0fca6ea1SDimitry Andric         if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2522*0fca6ea1SDimitry Andric             ParsedStmtContext()) {
2523*0fca6ea1SDimitry Andric           Diag(Loc, diag::err_omp_immediate_directive)
2524*0fca6ea1SDimitry Andric               << getOpenMPDirectiveName(DKind) << 1 << getOpenMPClauseName(CK);
2525*0fca6ea1SDimitry Andric         }
2526*0fca6ea1SDimitry Andric         HasAssociatedStatement = false;
2527*0fca6ea1SDimitry Andric       }
2528*0fca6ea1SDimitry Andric     }
2529*0fca6ea1SDimitry Andric   }
2530*0fca6ea1SDimitry Andric 
2531*0fca6ea1SDimitry Andric   if (DKind == OMPD_tile && !SeenClauses[unsigned(OMPC_sizes)]) {
2532*0fca6ea1SDimitry Andric     Diag(Loc, diag::err_omp_required_clause)
2533*0fca6ea1SDimitry Andric         << getOpenMPDirectiveName(OMPD_tile) << "sizes";
2534*0fca6ea1SDimitry Andric   }
2535*0fca6ea1SDimitry Andric 
2536*0fca6ea1SDimitry Andric   StmtResult AssociatedStmt;
2537*0fca6ea1SDimitry Andric   if (HasAssociatedStatement) {
2538*0fca6ea1SDimitry Andric     // The body is a block scope like in Lambdas and Blocks.
2539*0fca6ea1SDimitry Andric     Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2540*0fca6ea1SDimitry Andric     // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2541*0fca6ea1SDimitry Andric     // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2542*0fca6ea1SDimitry Andric     // should have at least one compound statement scope within it.
2543*0fca6ea1SDimitry Andric     ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2544*0fca6ea1SDimitry Andric     {
2545*0fca6ea1SDimitry Andric       Sema::CompoundScopeRAII Scope(Actions);
2546*0fca6ea1SDimitry Andric       AssociatedStmt = ParseStatement();
2547*0fca6ea1SDimitry Andric 
2548*0fca6ea1SDimitry Andric       if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2549*0fca6ea1SDimitry Andric           getLangOpts().OpenMPIRBuilder)
2550*0fca6ea1SDimitry Andric         AssociatedStmt =
2551*0fca6ea1SDimitry Andric             Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
2552*0fca6ea1SDimitry Andric     }
2553*0fca6ea1SDimitry Andric     AssociatedStmt =
2554*0fca6ea1SDimitry Andric         Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2555*0fca6ea1SDimitry Andric   } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2556*0fca6ea1SDimitry Andric              DKind == OMPD_target_exit_data) {
2557*0fca6ea1SDimitry Andric     Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2558*0fca6ea1SDimitry Andric     AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2559*0fca6ea1SDimitry Andric                       Actions.ActOnCompoundStmt(Loc, Loc, std::nullopt,
2560*0fca6ea1SDimitry Andric                                                 /*isStmtExpr=*/false));
2561*0fca6ea1SDimitry Andric     AssociatedStmt =
2562*0fca6ea1SDimitry Andric         Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2563*0fca6ea1SDimitry Andric   }
2564*0fca6ea1SDimitry Andric 
2565*0fca6ea1SDimitry Andric   StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(
2566*0fca6ea1SDimitry Andric       DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2567*0fca6ea1SDimitry Andric 
2568*0fca6ea1SDimitry Andric   // Exit scope.
2569*0fca6ea1SDimitry Andric   Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2570*0fca6ea1SDimitry Andric   OMPDirectiveScope.Exit();
2571*0fca6ea1SDimitry Andric 
2572*0fca6ea1SDimitry Andric   return Directive;
2573*0fca6ea1SDimitry Andric }
2574*0fca6ea1SDimitry Andric 
25750b57cec5SDimitry Andric /// Parsing of declarative or executable OpenMP directives.
25760b57cec5SDimitry Andric ///
25770b57cec5SDimitry Andric ///       threadprivate-directive:
25780b57cec5SDimitry Andric ///         annot_pragma_openmp 'threadprivate' simple-variable-list
25790b57cec5SDimitry Andric ///         annot_pragma_openmp_end
25800b57cec5SDimitry Andric ///
25810b57cec5SDimitry Andric ///       allocate-directive:
25820b57cec5SDimitry Andric ///         annot_pragma_openmp 'allocate' simple-variable-list
25830b57cec5SDimitry Andric ///         annot_pragma_openmp_end
25840b57cec5SDimitry Andric ///
25850b57cec5SDimitry Andric ///       declare-reduction-directive:
25860b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
25870b57cec5SDimitry Andric ///         <type> {',' <type>} ':' <expression> ')' ['initializer' '('
25880b57cec5SDimitry Andric ///         ('omp_priv' '=' <expression>|<function_call>) ')']
25890b57cec5SDimitry Andric ///         annot_pragma_openmp_end
25900b57cec5SDimitry Andric ///
25910b57cec5SDimitry Andric ///       declare-mapper-directive:
25920b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
25930b57cec5SDimitry Andric ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
25940b57cec5SDimitry Andric ///         annot_pragma_openmp_end
25950b57cec5SDimitry Andric ///
25960b57cec5SDimitry Andric ///       executable-directive:
25970b57cec5SDimitry Andric ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
25980b57cec5SDimitry Andric ///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
2599480093f4SDimitry Andric ///         'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
2600bdd1243dSDimitry Andric ///         'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error'
2601bdd1243dSDimitry Andric ///         | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
2602480093f4SDimitry Andric ///         data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
2603480093f4SDimitry Andric ///         'master taskloop' | 'master taskloop simd' | 'parallel master
2604480093f4SDimitry Andric ///         taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
2605480093f4SDimitry Andric ///         enter data' | 'target exit data' | 'target parallel' | 'target
2606480093f4SDimitry Andric ///         parallel for' | 'target update' | 'distribute parallel for' |
2607480093f4SDimitry Andric ///         'distribute paralle for simd' | 'distribute simd' | 'target parallel
2608480093f4SDimitry Andric ///         for simd' | 'target simd' | 'teams distribute' | 'teams distribute
2609480093f4SDimitry Andric ///         simd' | 'teams distribute parallel for simd' | 'teams distribute
2610480093f4SDimitry Andric ///         parallel for' | 'target teams' | 'target teams distribute' | 'target
2611480093f4SDimitry Andric ///         teams distribute parallel for' | 'target teams distribute parallel
261206c3fb27SDimitry Andric ///         for simd' | 'target teams distribute simd' | 'masked' |
261306c3fb27SDimitry Andric ///         'parallel masked' {clause} annot_pragma_openmp_end
26140b57cec5SDimitry Andric ///
ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx,bool ReadDirectiveWithinMetadirective)261581ad6265SDimitry Andric StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
261681ad6265SDimitry Andric     ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
2617349cc55cSDimitry Andric   if (!ReadDirectiveWithinMetadirective)
2618fe6060f1SDimitry Andric     assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2619fe6060f1SDimitry Andric            "Not an OpenMP directive!");
2620480093f4SDimitry Andric   ParsingOpenMPDirectiveRAII DirScope(*this);
26210b57cec5SDimitry Andric   ParenBraceBracketBalancer BalancerRAIIObj(*this);
2622349cc55cSDimitry Andric   SourceLocation Loc = ReadDirectiveWithinMetadirective
2623349cc55cSDimitry Andric                            ? Tok.getLocation()
2624*0fca6ea1SDimitry Andric                            : ConsumeAnnotationToken();
26250b57cec5SDimitry Andric   OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
2626349cc55cSDimitry Andric   if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2627349cc55cSDimitry Andric     Diag(Tok, diag::err_omp_unknown_directive);
2628349cc55cSDimitry Andric     return StmtError();
2629349cc55cSDimitry Andric   }
2630*0fca6ea1SDimitry Andric 
26310b57cec5SDimitry Andric   StmtResult Directive = StmtError();
2632*0fca6ea1SDimitry Andric 
2633*0fca6ea1SDimitry Andric   bool IsExecutable = [&]() {
2634*0fca6ea1SDimitry Andric     if (DKind == OMPD_error) // OMPD_error is handled as executable
2635*0fca6ea1SDimitry Andric       return true;
2636*0fca6ea1SDimitry Andric     auto Res = getDirectiveCategory(DKind);
2637*0fca6ea1SDimitry Andric     return Res == Category::Executable || Res == Category::Subsidiary;
2638*0fca6ea1SDimitry Andric   }();
2639*0fca6ea1SDimitry Andric 
2640*0fca6ea1SDimitry Andric   if (IsExecutable) {
2641*0fca6ea1SDimitry Andric     Directive = ParseOpenMPExecutableDirective(
2642*0fca6ea1SDimitry Andric         StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2643*0fca6ea1SDimitry Andric     assert(!Directive.isUnset() && "Executable directive remained unprocessed");
2644*0fca6ea1SDimitry Andric     return Directive;
2645*0fca6ea1SDimitry Andric   }
26460b57cec5SDimitry Andric 
26470b57cec5SDimitry Andric   switch (DKind) {
264881ad6265SDimitry Andric   case OMPD_nothing:
264981ad6265SDimitry Andric     ConsumeToken();
26505f757f3fSDimitry Andric     // If we are parsing the directive within a metadirective, the directive
26515f757f3fSDimitry Andric     // ends with a ')'.
26525f757f3fSDimitry Andric     if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
26535f757f3fSDimitry Andric       while (Tok.isNot(tok::annot_pragma_openmp_end))
26545f757f3fSDimitry Andric         ConsumeAnyToken();
26555f757f3fSDimitry Andric     else
265681ad6265SDimitry Andric       skipUntilPragmaOpenMPEnd(DKind);
265781ad6265SDimitry Andric     if (Tok.is(tok::annot_pragma_openmp_end))
265881ad6265SDimitry Andric       ConsumeAnnotationToken();
26595f757f3fSDimitry Andric     // return an empty statement
26605f757f3fSDimitry Andric     return StmtEmpty();
2661349cc55cSDimitry Andric   case OMPD_metadirective: {
2662349cc55cSDimitry Andric     ConsumeToken();
2663349cc55cSDimitry Andric     SmallVector<VariantMatchInfo, 4> VMIs;
2664349cc55cSDimitry Andric 
2665349cc55cSDimitry Andric     // First iteration of parsing all clauses of metadirective.
2666349cc55cSDimitry Andric     // This iteration only parses and collects all context selector ignoring the
2667349cc55cSDimitry Andric     // associated directives.
2668349cc55cSDimitry Andric     TentativeParsingAction TPA(*this);
2669349cc55cSDimitry Andric     ASTContext &ASTContext = Actions.getASTContext();
2670349cc55cSDimitry Andric 
2671349cc55cSDimitry Andric     BalancedDelimiterTracker T(*this, tok::l_paren,
2672349cc55cSDimitry Andric                                tok::annot_pragma_openmp_end);
2673349cc55cSDimitry Andric     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2674349cc55cSDimitry Andric       OpenMPClauseKind CKind = Tok.isAnnotation()
2675349cc55cSDimitry Andric                                    ? OMPC_unknown
2676349cc55cSDimitry Andric                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
2677349cc55cSDimitry Andric       SourceLocation Loc = ConsumeToken();
2678349cc55cSDimitry Andric 
2679349cc55cSDimitry Andric       // Parse '('.
2680349cc55cSDimitry Andric       if (T.expectAndConsume(diag::err_expected_lparen_after,
2681349cc55cSDimitry Andric                              getOpenMPClauseName(CKind).data()))
2682349cc55cSDimitry Andric         return Directive;
2683349cc55cSDimitry Andric 
2684349cc55cSDimitry Andric       OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2685349cc55cSDimitry Andric       if (CKind == OMPC_when) {
2686349cc55cSDimitry Andric         // parse and get OMPTraitInfo to pass to the When clause
2687349cc55cSDimitry Andric         parseOMPContextSelectors(Loc, TI);
2688349cc55cSDimitry Andric         if (TI.Sets.size() == 0) {
2689349cc55cSDimitry Andric           Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
2690349cc55cSDimitry Andric           TPA.Commit();
2691349cc55cSDimitry Andric           return Directive;
2692349cc55cSDimitry Andric         }
2693349cc55cSDimitry Andric 
2694349cc55cSDimitry Andric         // Parse ':'
2695349cc55cSDimitry Andric         if (Tok.is(tok::colon))
2696349cc55cSDimitry Andric           ConsumeAnyToken();
2697349cc55cSDimitry Andric         else {
2698349cc55cSDimitry Andric           Diag(Tok, diag::err_omp_expected_colon) << "when clause";
2699349cc55cSDimitry Andric           TPA.Commit();
2700349cc55cSDimitry Andric           return Directive;
2701349cc55cSDimitry Andric         }
2702349cc55cSDimitry Andric       }
2703349cc55cSDimitry Andric       // Skip Directive for now. We will parse directive in the second iteration
2704349cc55cSDimitry Andric       int paren = 0;
2705349cc55cSDimitry Andric       while (Tok.isNot(tok::r_paren) || paren != 0) {
2706349cc55cSDimitry Andric         if (Tok.is(tok::l_paren))
2707349cc55cSDimitry Andric           paren++;
2708349cc55cSDimitry Andric         if (Tok.is(tok::r_paren))
2709349cc55cSDimitry Andric           paren--;
2710349cc55cSDimitry Andric         if (Tok.is(tok::annot_pragma_openmp_end)) {
2711349cc55cSDimitry Andric           Diag(Tok, diag::err_omp_expected_punc)
2712349cc55cSDimitry Andric               << getOpenMPClauseName(CKind) << 0;
2713349cc55cSDimitry Andric           TPA.Commit();
2714349cc55cSDimitry Andric           return Directive;
2715349cc55cSDimitry Andric         }
2716349cc55cSDimitry Andric         ConsumeAnyToken();
2717349cc55cSDimitry Andric       }
2718349cc55cSDimitry Andric       // Parse ')'
2719349cc55cSDimitry Andric       if (Tok.is(tok::r_paren))
2720349cc55cSDimitry Andric         T.consumeClose();
2721349cc55cSDimitry Andric 
2722349cc55cSDimitry Andric       VariantMatchInfo VMI;
2723349cc55cSDimitry Andric       TI.getAsVariantMatchInfo(ASTContext, VMI);
2724349cc55cSDimitry Andric 
2725349cc55cSDimitry Andric       VMIs.push_back(VMI);
2726349cc55cSDimitry Andric     }
2727349cc55cSDimitry Andric 
2728349cc55cSDimitry Andric     TPA.Revert();
2729349cc55cSDimitry Andric     // End of the first iteration. Parser is reset to the start of metadirective
2730349cc55cSDimitry Andric 
273104eeddc0SDimitry Andric     std::function<void(StringRef)> DiagUnknownTrait =
273204eeddc0SDimitry Andric         [this, Loc](StringRef ISATrait) {
273304eeddc0SDimitry Andric           // TODO Track the selector locations in a way that is accessible here
273404eeddc0SDimitry Andric           // to improve the diagnostic location.
273504eeddc0SDimitry Andric           Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
273604eeddc0SDimitry Andric         };
273704eeddc0SDimitry Andric     TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
2738349cc55cSDimitry Andric                             /* CurrentFunctionDecl */ nullptr,
2739349cc55cSDimitry Andric                             ArrayRef<llvm::omp::TraitProperty>());
2740349cc55cSDimitry Andric 
2741349cc55cSDimitry Andric     // A single match is returned for OpenMP 5.0
2742349cc55cSDimitry Andric     int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2743349cc55cSDimitry Andric 
2744349cc55cSDimitry Andric     int Idx = 0;
2745349cc55cSDimitry Andric     // In OpenMP 5.0 metadirective is either replaced by another directive or
2746349cc55cSDimitry Andric     // ignored.
2747349cc55cSDimitry Andric     // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2748349cc55cSDimitry Andric     // found by getBestWhenMatchForContext.
2749349cc55cSDimitry Andric     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2750349cc55cSDimitry Andric       // OpenMP 5.0 implementation - Skip to the best index found.
2751349cc55cSDimitry Andric       if (Idx++ != BestIdx) {
2752349cc55cSDimitry Andric         ConsumeToken();  // Consume clause name
2753349cc55cSDimitry Andric         T.consumeOpen(); // Consume '('
2754349cc55cSDimitry Andric         int paren = 0;
2755349cc55cSDimitry Andric         // Skip everything inside the clause
2756349cc55cSDimitry Andric         while (Tok.isNot(tok::r_paren) || paren != 0) {
2757349cc55cSDimitry Andric           if (Tok.is(tok::l_paren))
2758349cc55cSDimitry Andric             paren++;
2759349cc55cSDimitry Andric           if (Tok.is(tok::r_paren))
2760349cc55cSDimitry Andric             paren--;
2761349cc55cSDimitry Andric           ConsumeAnyToken();
2762349cc55cSDimitry Andric         }
2763349cc55cSDimitry Andric         // Parse ')'
2764349cc55cSDimitry Andric         if (Tok.is(tok::r_paren))
2765349cc55cSDimitry Andric           T.consumeClose();
2766349cc55cSDimitry Andric         continue;
2767349cc55cSDimitry Andric       }
2768349cc55cSDimitry Andric 
2769349cc55cSDimitry Andric       OpenMPClauseKind CKind = Tok.isAnnotation()
2770349cc55cSDimitry Andric                                    ? OMPC_unknown
2771349cc55cSDimitry Andric                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
2772349cc55cSDimitry Andric       SourceLocation Loc = ConsumeToken();
2773349cc55cSDimitry Andric 
2774349cc55cSDimitry Andric       // Parse '('.
2775349cc55cSDimitry Andric       T.consumeOpen();
2776349cc55cSDimitry Andric 
2777349cc55cSDimitry Andric       // Skip ContextSelectors for when clause
2778349cc55cSDimitry Andric       if (CKind == OMPC_when) {
2779349cc55cSDimitry Andric         OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2780349cc55cSDimitry Andric         // parse and skip the ContextSelectors
2781349cc55cSDimitry Andric         parseOMPContextSelectors(Loc, TI);
2782349cc55cSDimitry Andric 
2783349cc55cSDimitry Andric         // Parse ':'
2784349cc55cSDimitry Andric         ConsumeAnyToken();
2785349cc55cSDimitry Andric       }
2786349cc55cSDimitry Andric 
2787349cc55cSDimitry Andric       // If no directive is passed, skip in OpenMP 5.0.
2788349cc55cSDimitry Andric       // TODO: Generate nothing directive from OpenMP 5.1.
2789349cc55cSDimitry Andric       if (Tok.is(tok::r_paren)) {
2790349cc55cSDimitry Andric         SkipUntil(tok::annot_pragma_openmp_end);
2791349cc55cSDimitry Andric         break;
2792349cc55cSDimitry Andric       }
2793349cc55cSDimitry Andric 
2794349cc55cSDimitry Andric       // Parse Directive
279581ad6265SDimitry Andric       Directive = ParseOpenMPDeclarativeOrExecutableDirective(
279681ad6265SDimitry Andric           StmtCtx,
279781ad6265SDimitry Andric           /*ReadDirectiveWithinMetadirective=*/true);
2798349cc55cSDimitry Andric       break;
2799349cc55cSDimitry Andric     }
2800349cc55cSDimitry Andric     break;
2801349cc55cSDimitry Andric   }
28020b57cec5SDimitry Andric   case OMPD_threadprivate: {
28030b57cec5SDimitry Andric     // FIXME: Should this be permitted in C++?
28045f757f3fSDimitry Andric     if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
28050b57cec5SDimitry Andric         ParsedStmtContext()) {
28060b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_immediate_directive)
28070b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << 0;
28080b57cec5SDimitry Andric     }
28090b57cec5SDimitry Andric     ConsumeToken();
28100b57cec5SDimitry Andric     DeclDirectiveListParserHelper Helper(this, DKind);
28110b57cec5SDimitry Andric     if (!ParseOpenMPSimpleVarList(DKind, Helper,
28120b57cec5SDimitry Andric                                   /*AllowScopeSpecifier=*/false)) {
28135ffd83dbSDimitry Andric       skipUntilPragmaOpenMPEnd(DKind);
2814*0fca6ea1SDimitry Andric       DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
28150b57cec5SDimitry Andric           Loc, Helper.getIdentifiers());
28160b57cec5SDimitry Andric       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
28170b57cec5SDimitry Andric     }
28180b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end);
28190b57cec5SDimitry Andric     break;
28200b57cec5SDimitry Andric   }
28210b57cec5SDimitry Andric   case OMPD_allocate: {
28220b57cec5SDimitry Andric     // FIXME: Should this be permitted in C++?
28235f757f3fSDimitry Andric     if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
28240b57cec5SDimitry Andric         ParsedStmtContext()) {
28250b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_immediate_directive)
28260b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << 0;
28270b57cec5SDimitry Andric     }
28280b57cec5SDimitry Andric     ConsumeToken();
28290b57cec5SDimitry Andric     DeclDirectiveListParserHelper Helper(this, DKind);
28300b57cec5SDimitry Andric     if (!ParseOpenMPSimpleVarList(DKind, Helper,
28310b57cec5SDimitry Andric                                   /*AllowScopeSpecifier=*/false)) {
28320b57cec5SDimitry Andric       SmallVector<OMPClause *, 1> Clauses;
28330b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2834*0fca6ea1SDimitry Andric         llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
28350b57cec5SDimitry Andric         while (Tok.isNot(tok::annot_pragma_openmp_end)) {
28360b57cec5SDimitry Andric           OpenMPClauseKind CKind =
28370b57cec5SDimitry Andric               Tok.isAnnotation() ? OMPC_unknown
28380b57cec5SDimitry Andric                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
2839*0fca6ea1SDimitry Andric           Actions.OpenMP().StartOpenMPClause(CKind);
2840*0fca6ea1SDimitry Andric           OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2841*0fca6ea1SDimitry Andric                                                 !SeenClauses[unsigned(CKind)]);
28420b57cec5SDimitry Andric           SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
28430b57cec5SDimitry Andric                     StopBeforeMatch);
2844*0fca6ea1SDimitry Andric           SeenClauses[unsigned(CKind)] = true;
28450b57cec5SDimitry Andric           if (Clause != nullptr)
28460b57cec5SDimitry Andric             Clauses.push_back(Clause);
28470b57cec5SDimitry Andric           if (Tok.is(tok::annot_pragma_openmp_end)) {
2848*0fca6ea1SDimitry Andric             Actions.OpenMP().EndOpenMPClause();
28490b57cec5SDimitry Andric             break;
28500b57cec5SDimitry Andric           }
28510b57cec5SDimitry Andric           // Skip ',' if any.
28520b57cec5SDimitry Andric           if (Tok.is(tok::comma))
28530b57cec5SDimitry Andric             ConsumeToken();
2854*0fca6ea1SDimitry Andric           Actions.OpenMP().EndOpenMPClause();
28550b57cec5SDimitry Andric         }
28565ffd83dbSDimitry Andric         skipUntilPragmaOpenMPEnd(DKind);
28570b57cec5SDimitry Andric       }
2858*0fca6ea1SDimitry Andric       DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
28590b57cec5SDimitry Andric           Loc, Helper.getIdentifiers(), Clauses);
28600b57cec5SDimitry Andric       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
28610b57cec5SDimitry Andric     }
28620b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end);
28630b57cec5SDimitry Andric     break;
28640b57cec5SDimitry Andric   }
28650b57cec5SDimitry Andric   case OMPD_declare_reduction:
28660b57cec5SDimitry Andric     ConsumeToken();
28670b57cec5SDimitry Andric     if (DeclGroupPtrTy Res =
28680b57cec5SDimitry Andric             ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
28695ffd83dbSDimitry Andric       skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
28700b57cec5SDimitry Andric       ConsumeAnyToken();
28710b57cec5SDimitry Andric       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
28720b57cec5SDimitry Andric     } else {
28730b57cec5SDimitry Andric       SkipUntil(tok::annot_pragma_openmp_end);
28740b57cec5SDimitry Andric     }
28750b57cec5SDimitry Andric     break;
28760b57cec5SDimitry Andric   case OMPD_declare_mapper: {
28770b57cec5SDimitry Andric     ConsumeToken();
28780b57cec5SDimitry Andric     if (DeclGroupPtrTy Res =
28790b57cec5SDimitry Andric             ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
28800b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
28810b57cec5SDimitry Andric       ConsumeAnnotationToken();
28820b57cec5SDimitry Andric       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
28830b57cec5SDimitry Andric     } else {
28840b57cec5SDimitry Andric       SkipUntil(tok::annot_pragma_openmp_end);
28850b57cec5SDimitry Andric     }
28860b57cec5SDimitry Andric     break;
28870b57cec5SDimitry Andric   }
2888*0fca6ea1SDimitry Andric   case OMPD_reverse:
2889*0fca6ea1SDimitry Andric   case OMPD_interchange:
2890*0fca6ea1SDimitry Andric   case OMPD_declare_target: {
2891*0fca6ea1SDimitry Andric     SourceLocation DTLoc = ConsumeAnyToken();
2892*0fca6ea1SDimitry Andric     bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2893*0fca6ea1SDimitry Andric     SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2894*0fca6ea1SDimitry Andric     if (HasClauses)
2895*0fca6ea1SDimitry Andric       ParseOMPDeclareTargetClauses(DTCI);
2896*0fca6ea1SDimitry Andric     bool HasImplicitMappings =
2897*0fca6ea1SDimitry Andric         !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2898*0fca6ea1SDimitry Andric 
2899*0fca6ea1SDimitry Andric     if (HasImplicitMappings) {
2900*0fca6ea1SDimitry Andric       Diag(Tok, diag::err_omp_unexpected_directive)
2901*0fca6ea1SDimitry Andric           << 1 << getOpenMPDirectiveName(DKind);
2902bdd1243dSDimitry Andric       SkipUntil(tok::annot_pragma_openmp_end);
2903bdd1243dSDimitry Andric       break;
2904bdd1243dSDimitry Andric     }
2905*0fca6ea1SDimitry Andric 
2906*0fca6ea1SDimitry Andric     // Skip the last annot_pragma_openmp_end.
29070b57cec5SDimitry Andric     ConsumeAnyToken();
29080b57cec5SDimitry Andric 
2909*0fca6ea1SDimitry Andric     Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
29100b57cec5SDimitry Andric     break;
29110b57cec5SDimitry Andric   }
29120b57cec5SDimitry Andric   case OMPD_declare_simd:
2913fe6060f1SDimitry Andric   case OMPD_begin_declare_target:
29140b57cec5SDimitry Andric   case OMPD_end_declare_target:
29150b57cec5SDimitry Andric   case OMPD_requires:
29165ffd83dbSDimitry Andric   case OMPD_begin_declare_variant:
29175ffd83dbSDimitry Andric   case OMPD_end_declare_variant:
2918a7dea167SDimitry Andric   case OMPD_declare_variant:
29190b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_unexpected_directive)
29200b57cec5SDimitry Andric         << 1 << getOpenMPDirectiveName(DKind);
29210b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end);
29220b57cec5SDimitry Andric     break;
29230b57cec5SDimitry Andric   case OMPD_unknown:
29245ffd83dbSDimitry Andric   default:
29250b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_unknown_directive);
29260b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end);
29270b57cec5SDimitry Andric     break;
29280b57cec5SDimitry Andric   }
29290b57cec5SDimitry Andric   return Directive;
29300b57cec5SDimitry Andric }
29310b57cec5SDimitry Andric 
29320b57cec5SDimitry Andric // Parses simple list:
29330b57cec5SDimitry Andric //   simple-variable-list:
29340b57cec5SDimitry Andric //         '(' id-expression {, id-expression} ')'
29350b57cec5SDimitry Andric //
ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,const llvm::function_ref<void (CXXScopeSpec &,DeclarationNameInfo)> & Callback,bool AllowScopeSpecifier)29360b57cec5SDimitry Andric bool Parser::ParseOpenMPSimpleVarList(
29370b57cec5SDimitry Andric     OpenMPDirectiveKind Kind,
2938e8d8bef9SDimitry Andric     const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
2939e8d8bef9SDimitry Andric         &Callback,
29400b57cec5SDimitry Andric     bool AllowScopeSpecifier) {
29410b57cec5SDimitry Andric   // Parse '('.
29420b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
29430b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
2944480093f4SDimitry Andric                          getOpenMPDirectiveName(Kind).data()))
29450b57cec5SDimitry Andric     return true;
29460b57cec5SDimitry Andric   bool IsCorrect = true;
29470b57cec5SDimitry Andric   bool NoIdentIsFound = true;
29480b57cec5SDimitry Andric 
29490b57cec5SDimitry Andric   // Read tokens while ')' or annot_pragma_openmp_end is not found.
29500b57cec5SDimitry Andric   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
29510b57cec5SDimitry Andric     CXXScopeSpec SS;
29520b57cec5SDimitry Andric     UnqualifiedId Name;
29530b57cec5SDimitry Andric     // Read var name.
29540b57cec5SDimitry Andric     Token PrevTok = Tok;
29550b57cec5SDimitry Andric     NoIdentIsFound = false;
29560b57cec5SDimitry Andric 
29570b57cec5SDimitry Andric     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
29585ffd83dbSDimitry Andric         ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
295904eeddc0SDimitry Andric                                        /*ObjectHasErrors=*/false, false)) {
29600b57cec5SDimitry Andric       IsCorrect = false;
29610b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
29620b57cec5SDimitry Andric                 StopBeforeMatch);
29635ffd83dbSDimitry Andric     } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
29645ffd83dbSDimitry Andric                                   /*ObjectHadErrors=*/false, false, false,
29655ffd83dbSDimitry Andric                                   false, false, nullptr, Name)) {
29660b57cec5SDimitry Andric       IsCorrect = false;
29670b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
29680b57cec5SDimitry Andric                 StopBeforeMatch);
29690b57cec5SDimitry Andric     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
29700b57cec5SDimitry Andric                Tok.isNot(tok::annot_pragma_openmp_end)) {
29710b57cec5SDimitry Andric       IsCorrect = false;
29720b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
29730b57cec5SDimitry Andric                 StopBeforeMatch);
29740b57cec5SDimitry Andric       Diag(PrevTok.getLocation(), diag::err_expected)
29750b57cec5SDimitry Andric           << tok::identifier
29760b57cec5SDimitry Andric           << SourceRange(PrevTok.getLocation(), PrevTokLocation);
29770b57cec5SDimitry Andric     } else {
29780b57cec5SDimitry Andric       Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
29790b57cec5SDimitry Andric     }
29800b57cec5SDimitry Andric     // Consume ','.
29810b57cec5SDimitry Andric     if (Tok.is(tok::comma)) {
29820b57cec5SDimitry Andric       ConsumeToken();
29830b57cec5SDimitry Andric     }
29840b57cec5SDimitry Andric   }
29850b57cec5SDimitry Andric 
29860b57cec5SDimitry Andric   if (NoIdentIsFound) {
29870b57cec5SDimitry Andric     Diag(Tok, diag::err_expected) << tok::identifier;
29880b57cec5SDimitry Andric     IsCorrect = false;
29890b57cec5SDimitry Andric   }
29900b57cec5SDimitry Andric 
29910b57cec5SDimitry Andric   // Parse ')'.
29920b57cec5SDimitry Andric   IsCorrect = !T.consumeClose() && IsCorrect;
29930b57cec5SDimitry Andric 
29940b57cec5SDimitry Andric   return !IsCorrect;
29950b57cec5SDimitry Andric }
29960b57cec5SDimitry Andric 
ParseOpenMPSizesClause()2997fe6060f1SDimitry Andric OMPClause *Parser::ParseOpenMPSizesClause() {
2998*0fca6ea1SDimitry Andric   SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
2999fe6060f1SDimitry Andric   SmallVector<Expr *, 4> ValExprs;
3000*0fca6ea1SDimitry Andric   if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
3001*0fca6ea1SDimitry Andric                                 ValExprs))
3002fe6060f1SDimitry Andric     return nullptr;
3003fe6060f1SDimitry Andric 
3004*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
3005*0fca6ea1SDimitry Andric                                                  OpenLoc, CloseLoc);
3006fe6060f1SDimitry Andric }
3007fe6060f1SDimitry Andric 
ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind)30085ffd83dbSDimitry Andric OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
30095ffd83dbSDimitry Andric   SourceLocation Loc = Tok.getLocation();
30105ffd83dbSDimitry Andric   ConsumeAnyToken();
30115ffd83dbSDimitry Andric 
30125ffd83dbSDimitry Andric   // Parse '('.
30135ffd83dbSDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
30145ffd83dbSDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
30155ffd83dbSDimitry Andric     return nullptr;
3016*0fca6ea1SDimitry Andric   SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
30175ffd83dbSDimitry Andric   do {
301806c3fb27SDimitry Andric     CXXScopeSpec SS;
301906c3fb27SDimitry Andric     Token Replacement;
3020fe6060f1SDimitry Andric     ExprResult Allocator =
302106c3fb27SDimitry Andric         getLangOpts().CPlusPlus
302206c3fb27SDimitry Andric             ? ParseCXXIdExpression()
302306c3fb27SDimitry Andric             : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
302406c3fb27SDimitry Andric                                       Replacement);
30255ffd83dbSDimitry Andric     if (Allocator.isInvalid()) {
30265ffd83dbSDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
30275ffd83dbSDimitry Andric                 StopBeforeMatch);
30285ffd83dbSDimitry Andric       break;
30295ffd83dbSDimitry Andric     }
3030*0fca6ea1SDimitry Andric     SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
30315ffd83dbSDimitry Andric     D.Allocator = Allocator.get();
30325ffd83dbSDimitry Andric     if (Tok.is(tok::l_paren)) {
30335ffd83dbSDimitry Andric       BalancedDelimiterTracker T(*this, tok::l_paren,
30345ffd83dbSDimitry Andric                                  tok::annot_pragma_openmp_end);
30355ffd83dbSDimitry Andric       T.consumeOpen();
3036fe6060f1SDimitry Andric       ExprResult AllocatorTraits =
3037fe6060f1SDimitry Andric           getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
30385ffd83dbSDimitry Andric       T.consumeClose();
30395ffd83dbSDimitry Andric       if (AllocatorTraits.isInvalid()) {
30405ffd83dbSDimitry Andric         SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
30415ffd83dbSDimitry Andric                   StopBeforeMatch);
30425ffd83dbSDimitry Andric         break;
30435ffd83dbSDimitry Andric       }
30445ffd83dbSDimitry Andric       D.AllocatorTraits = AllocatorTraits.get();
30455ffd83dbSDimitry Andric       D.LParenLoc = T.getOpenLocation();
30465ffd83dbSDimitry Andric       D.RParenLoc = T.getCloseLocation();
30475ffd83dbSDimitry Andric     }
30485ffd83dbSDimitry Andric     if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
30495ffd83dbSDimitry Andric       Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
30505ffd83dbSDimitry Andric     // Parse ','
30515ffd83dbSDimitry Andric     if (Tok.is(tok::comma))
30525ffd83dbSDimitry Andric       ConsumeAnyToken();
30535ffd83dbSDimitry Andric   } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
30545ffd83dbSDimitry Andric   T.consumeClose();
3055*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
3056*0fca6ea1SDimitry Andric       Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
30575ffd83dbSDimitry Andric }
30585ffd83dbSDimitry Andric 
30590b57cec5SDimitry Andric /// Parsing of OpenMP clauses.
30600b57cec5SDimitry Andric ///
30610b57cec5SDimitry Andric ///    clause:
30620b57cec5SDimitry Andric ///       if-clause | final-clause | num_threads-clause | safelen-clause |
30630b57cec5SDimitry Andric ///       default-clause | private-clause | firstprivate-clause | shared-clause
3064349cc55cSDimitry Andric ///       | linear-clause | aligned-clause | collapse-clause | bind-clause |
30650b57cec5SDimitry Andric ///       lastprivate-clause | reduction-clause | proc_bind-clause |
30660b57cec5SDimitry Andric ///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
30670b57cec5SDimitry Andric ///       mergeable-clause | flush-clause | read-clause | write-clause |
30680b57cec5SDimitry Andric ///       update-clause | capture-clause | seq_cst-clause | device-clause |
30690b57cec5SDimitry Andric ///       simdlen-clause | threads-clause | simd-clause | num_teams-clause |
30700b57cec5SDimitry Andric ///       thread_limit-clause | priority-clause | grainsize-clause |
30710b57cec5SDimitry Andric ///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
30720b57cec5SDimitry Andric ///       from-clause | is_device_ptr-clause | task_reduction-clause |
30735ffd83dbSDimitry Andric ///       in_reduction-clause | allocator-clause | allocate-clause |
30745ffd83dbSDimitry Andric ///       acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
30755ffd83dbSDimitry Andric ///       depobj-clause | destroy-clause | detach-clause | inclusive-clause |
307681ad6265SDimitry Andric ///       exclusive-clause | uses_allocators-clause | use_device_addr-clause |
307781ad6265SDimitry Andric ///       has_device_addr
30780b57cec5SDimitry Andric ///
ParseOpenMPClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,bool FirstClause)30790b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
30800b57cec5SDimitry Andric                                      OpenMPClauseKind CKind, bool FirstClause) {
30815ffd83dbSDimitry Andric   OMPClauseKind = CKind;
30820b57cec5SDimitry Andric   OMPClause *Clause = nullptr;
30830b57cec5SDimitry Andric   bool ErrorFound = false;
30840b57cec5SDimitry Andric   bool WrongDirective = false;
30850b57cec5SDimitry Andric   // Check if clause is allowed for the given directive.
3086480093f4SDimitry Andric   if (CKind != OMPC_unknown &&
3087480093f4SDimitry Andric       !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
3088e8d8bef9SDimitry Andric     Diag(Tok, diag::err_omp_unexpected_clause)
3089e8d8bef9SDimitry Andric         << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
30900b57cec5SDimitry Andric     ErrorFound = true;
30910b57cec5SDimitry Andric     WrongDirective = true;
30920b57cec5SDimitry Andric   }
30930b57cec5SDimitry Andric 
30940b57cec5SDimitry Andric   switch (CKind) {
30950b57cec5SDimitry Andric   case OMPC_final:
30960b57cec5SDimitry Andric   case OMPC_num_threads:
30970b57cec5SDimitry Andric   case OMPC_safelen:
30980b57cec5SDimitry Andric   case OMPC_simdlen:
30990b57cec5SDimitry Andric   case OMPC_collapse:
31000b57cec5SDimitry Andric   case OMPC_ordered:
31010b57cec5SDimitry Andric   case OMPC_num_teams:
31020b57cec5SDimitry Andric   case OMPC_thread_limit:
31030b57cec5SDimitry Andric   case OMPC_priority:
31040b57cec5SDimitry Andric   case OMPC_grainsize:
31050b57cec5SDimitry Andric   case OMPC_num_tasks:
31060b57cec5SDimitry Andric   case OMPC_hint:
31070b57cec5SDimitry Andric   case OMPC_allocator:
31085ffd83dbSDimitry Andric   case OMPC_depobj:
31095ffd83dbSDimitry Andric   case OMPC_detach:
3110fe6060f1SDimitry Andric   case OMPC_novariants:
3111fe6060f1SDimitry Andric   case OMPC_nocontext:
3112fe6060f1SDimitry Andric   case OMPC_filter:
3113fe6060f1SDimitry Andric   case OMPC_partial:
3114349cc55cSDimitry Andric   case OMPC_align:
3115bdd1243dSDimitry Andric   case OMPC_message:
3116bdd1243dSDimitry Andric   case OMPC_ompx_dyn_cgroup_mem:
31170b57cec5SDimitry Andric     // OpenMP [2.5, Restrictions]
31180b57cec5SDimitry Andric     //  At most one num_threads clause can appear on the directive.
31190b57cec5SDimitry Andric     // OpenMP [2.8.1, simd construct, Restrictions]
31200b57cec5SDimitry Andric     //  Only one safelen  clause can appear on a simd directive.
31210b57cec5SDimitry Andric     //  Only one simdlen  clause can appear on a simd directive.
31220b57cec5SDimitry Andric     //  Only one collapse clause can appear on a simd directive.
31230b57cec5SDimitry Andric     // OpenMP [2.11.1, task Construct, Restrictions]
31240b57cec5SDimitry Andric     //  At most one if clause can appear on the directive.
31250b57cec5SDimitry Andric     //  At most one final clause can appear on the directive.
31260b57cec5SDimitry Andric     // OpenMP [teams Construct, Restrictions]
31270b57cec5SDimitry Andric     //  At most one num_teams clause can appear on the directive.
31280b57cec5SDimitry Andric     //  At most one thread_limit clause can appear on the directive.
31290b57cec5SDimitry Andric     // OpenMP [2.9.1, task Construct, Restrictions]
31300b57cec5SDimitry Andric     // At most one priority clause can appear on the directive.
31310b57cec5SDimitry Andric     // OpenMP [2.9.2, taskloop Construct, Restrictions]
31320b57cec5SDimitry Andric     // At most one grainsize clause can appear on the directive.
31330b57cec5SDimitry Andric     // OpenMP [2.9.2, taskloop Construct, Restrictions]
31340b57cec5SDimitry Andric     // At most one num_tasks clause can appear on the directive.
31350b57cec5SDimitry Andric     // OpenMP [2.11.3, allocate Directive, Restrictions]
31360b57cec5SDimitry Andric     // At most one allocator clause can appear on the directive.
31375ffd83dbSDimitry Andric     // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
31385ffd83dbSDimitry Andric     // At most one detach clause can appear on the directive.
3139fe6060f1SDimitry Andric     // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3140fe6060f1SDimitry Andric     // At most one novariants clause can appear on a dispatch directive.
3141fe6060f1SDimitry Andric     // At most one nocontext clause can appear on a dispatch directive.
3142bdd1243dSDimitry Andric     // OpenMP [5.1, error directive, Restrictions]
3143bdd1243dSDimitry Andric     // At most one message clause can appear on the directive
31440b57cec5SDimitry Andric     if (!FirstClause) {
31450b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
31460b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
31470b57cec5SDimitry Andric       ErrorFound = true;
31480b57cec5SDimitry Andric     }
31490b57cec5SDimitry Andric 
3150fe6060f1SDimitry Andric     if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3151fe6060f1SDimitry Andric         PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
31520b57cec5SDimitry Andric       Clause = ParseOpenMPClause(CKind, WrongDirective);
3153bdd1243dSDimitry Andric     else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
3154bdd1243dSDimitry Andric       Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
31550b57cec5SDimitry Andric     else
31560b57cec5SDimitry Andric       Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
31570b57cec5SDimitry Andric     break;
31585f757f3fSDimitry Andric   case OMPC_fail:
31590b57cec5SDimitry Andric   case OMPC_default:
31600b57cec5SDimitry Andric   case OMPC_proc_bind:
31610b57cec5SDimitry Andric   case OMPC_atomic_default_mem_order:
3162bdd1243dSDimitry Andric   case OMPC_at:
3163bdd1243dSDimitry Andric   case OMPC_severity:
3164349cc55cSDimitry Andric   case OMPC_bind:
31650b57cec5SDimitry Andric     // OpenMP [2.14.3.1, Restrictions]
31660b57cec5SDimitry Andric     //  Only a single default clause may be specified on a parallel, task or
31670b57cec5SDimitry Andric     //  teams directive.
31680b57cec5SDimitry Andric     // OpenMP [2.5, parallel Construct, Restrictions]
31690b57cec5SDimitry Andric     //  At most one proc_bind clause can appear on the directive.
31700b57cec5SDimitry Andric     // OpenMP [5.0, Requires directive, Restrictions]
31710b57cec5SDimitry Andric     //  At most one atomic_default_mem_order clause can appear
31720b57cec5SDimitry Andric     //  on the directive
3173bdd1243dSDimitry Andric     // OpenMP [5.1, error directive, Restrictions]
3174bdd1243dSDimitry Andric     //  At most one at clause can appear on the directive
3175bdd1243dSDimitry Andric     //  At most one severity clause can appear on the directive
3176349cc55cSDimitry Andric     // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3177349cc55cSDimitry Andric     // At most one bind clause can appear on a loop directive.
3178bdd1243dSDimitry Andric     if (!FirstClause) {
31790b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
31800b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
31810b57cec5SDimitry Andric       ErrorFound = true;
31820b57cec5SDimitry Andric     }
31830b57cec5SDimitry Andric 
31840b57cec5SDimitry Andric     Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
31850b57cec5SDimitry Andric     break;
31865ffd83dbSDimitry Andric   case OMPC_device:
31870b57cec5SDimitry Andric   case OMPC_schedule:
31880b57cec5SDimitry Andric   case OMPC_dist_schedule:
31890b57cec5SDimitry Andric   case OMPC_defaultmap:
3190bdd1243dSDimitry Andric   case OMPC_order:
31910b57cec5SDimitry Andric     // OpenMP [2.7.1, Restrictions, p. 3]
31920b57cec5SDimitry Andric     //  Only one schedule clause can appear on a loop directive.
3193480093f4SDimitry Andric     // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
31940b57cec5SDimitry Andric     //  At most one defaultmap clause can appear on the directive.
31955ffd83dbSDimitry Andric     // OpenMP 5.0 [2.12.5, target construct, Restrictions]
31965ffd83dbSDimitry Andric     //  At most one device clause can appear on the directive.
3197bdd1243dSDimitry Andric     // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3198bdd1243dSDimitry Andric     //  At most one order clause may appear on a construct.
3199480093f4SDimitry Andric     if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3200bdd1243dSDimitry Andric         (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
32010b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
32020b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
32030b57cec5SDimitry Andric       ErrorFound = true;
32040b57cec5SDimitry Andric     }
3205bdd1243dSDimitry Andric     [[fallthrough]];
32060b57cec5SDimitry Andric   case OMPC_if:
32075ffd83dbSDimitry Andric     Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
32080b57cec5SDimitry Andric     break;
32090b57cec5SDimitry Andric   case OMPC_nowait:
32100b57cec5SDimitry Andric   case OMPC_untied:
32110b57cec5SDimitry Andric   case OMPC_mergeable:
32120b57cec5SDimitry Andric   case OMPC_read:
32130b57cec5SDimitry Andric   case OMPC_write:
32140b57cec5SDimitry Andric   case OMPC_capture:
32150eae32dcSDimitry Andric   case OMPC_compare:
32160b57cec5SDimitry Andric   case OMPC_seq_cst:
32175ffd83dbSDimitry Andric   case OMPC_acq_rel:
32185ffd83dbSDimitry Andric   case OMPC_acquire:
32195ffd83dbSDimitry Andric   case OMPC_release:
32205ffd83dbSDimitry Andric   case OMPC_relaxed:
3221*0fca6ea1SDimitry Andric   case OMPC_weak:
32220b57cec5SDimitry Andric   case OMPC_threads:
32230b57cec5SDimitry Andric   case OMPC_simd:
32240b57cec5SDimitry Andric   case OMPC_nogroup:
32250b57cec5SDimitry Andric   case OMPC_unified_address:
32260b57cec5SDimitry Andric   case OMPC_unified_shared_memory:
32270b57cec5SDimitry Andric   case OMPC_reverse_offload:
32280b57cec5SDimitry Andric   case OMPC_dynamic_allocators:
3229fe6060f1SDimitry Andric   case OMPC_full:
32300b57cec5SDimitry Andric     // OpenMP [2.7.1, Restrictions, p. 9]
32310b57cec5SDimitry Andric     //  Only one ordered clause can appear on a loop directive.
32320b57cec5SDimitry Andric     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
32330b57cec5SDimitry Andric     //  Only one nowait clause can appear on a for directive.
32340b57cec5SDimitry Andric     // OpenMP [5.0, Requires directive, Restrictions]
32350b57cec5SDimitry Andric     //   Each of the requires clauses can appear at most once on the directive.
32360b57cec5SDimitry Andric     if (!FirstClause) {
32370b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
32380b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
32390b57cec5SDimitry Andric       ErrorFound = true;
32400b57cec5SDimitry Andric     }
32410b57cec5SDimitry Andric 
32420b57cec5SDimitry Andric     Clause = ParseOpenMPClause(CKind, WrongDirective);
32430b57cec5SDimitry Andric     break;
32445ffd83dbSDimitry Andric   case OMPC_update:
32455ffd83dbSDimitry Andric     if (!FirstClause) {
32465ffd83dbSDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
32475ffd83dbSDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
32485ffd83dbSDimitry Andric       ErrorFound = true;
32495ffd83dbSDimitry Andric     }
32505ffd83dbSDimitry Andric 
32515ffd83dbSDimitry Andric     Clause = (DKind == OMPD_depobj)
32525ffd83dbSDimitry Andric                  ? ParseOpenMPSimpleClause(CKind, WrongDirective)
32535ffd83dbSDimitry Andric                  : ParseOpenMPClause(CKind, WrongDirective);
32545ffd83dbSDimitry Andric     break;
32550b57cec5SDimitry Andric   case OMPC_private:
32560b57cec5SDimitry Andric   case OMPC_firstprivate:
32570b57cec5SDimitry Andric   case OMPC_lastprivate:
32580b57cec5SDimitry Andric   case OMPC_shared:
32590b57cec5SDimitry Andric   case OMPC_reduction:
32600b57cec5SDimitry Andric   case OMPC_task_reduction:
32610b57cec5SDimitry Andric   case OMPC_in_reduction:
32620b57cec5SDimitry Andric   case OMPC_linear:
32630b57cec5SDimitry Andric   case OMPC_aligned:
32640b57cec5SDimitry Andric   case OMPC_copyin:
32650b57cec5SDimitry Andric   case OMPC_copyprivate:
32660b57cec5SDimitry Andric   case OMPC_flush:
32670b57cec5SDimitry Andric   case OMPC_depend:
32680b57cec5SDimitry Andric   case OMPC_map:
32690b57cec5SDimitry Andric   case OMPC_to:
32700b57cec5SDimitry Andric   case OMPC_from:
32710b57cec5SDimitry Andric   case OMPC_use_device_ptr:
32725ffd83dbSDimitry Andric   case OMPC_use_device_addr:
32730b57cec5SDimitry Andric   case OMPC_is_device_ptr:
327481ad6265SDimitry Andric   case OMPC_has_device_addr:
32750b57cec5SDimitry Andric   case OMPC_allocate:
3276480093f4SDimitry Andric   case OMPC_nontemporal:
32775ffd83dbSDimitry Andric   case OMPC_inclusive:
32785ffd83dbSDimitry Andric   case OMPC_exclusive:
32795ffd83dbSDimitry Andric   case OMPC_affinity:
328006c3fb27SDimitry Andric   case OMPC_doacross:
32815f757f3fSDimitry Andric   case OMPC_enter:
328206c3fb27SDimitry Andric     if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
328306c3fb27SDimitry Andric         CKind == OMPC_depend)
328406c3fb27SDimitry Andric       Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
32850b57cec5SDimitry Andric     Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
32860b57cec5SDimitry Andric     break;
3287fe6060f1SDimitry Andric   case OMPC_sizes:
3288fe6060f1SDimitry Andric     if (!FirstClause) {
3289fe6060f1SDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
3290fe6060f1SDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3291fe6060f1SDimitry Andric       ErrorFound = true;
3292fe6060f1SDimitry Andric     }
3293fe6060f1SDimitry Andric 
3294fe6060f1SDimitry Andric     Clause = ParseOpenMPSizesClause();
3295fe6060f1SDimitry Andric     break;
32965ffd83dbSDimitry Andric   case OMPC_uses_allocators:
32975ffd83dbSDimitry Andric     Clause = ParseOpenMPUsesAllocatorClause(DKind);
32985ffd83dbSDimitry Andric     break;
3299fe6060f1SDimitry Andric   case OMPC_destroy:
3300fe6060f1SDimitry Andric     if (DKind != OMPD_interop) {
3301fe6060f1SDimitry Andric       if (!FirstClause) {
3302fe6060f1SDimitry Andric         Diag(Tok, diag::err_omp_more_one_clause)
3303fe6060f1SDimitry Andric             << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3304fe6060f1SDimitry Andric         ErrorFound = true;
3305fe6060f1SDimitry Andric       }
3306fe6060f1SDimitry Andric       Clause = ParseOpenMPClause(CKind, WrongDirective);
3307fe6060f1SDimitry Andric       break;
3308fe6060f1SDimitry Andric     }
3309bdd1243dSDimitry Andric     [[fallthrough]];
3310fe6060f1SDimitry Andric   case OMPC_init:
3311fe6060f1SDimitry Andric   case OMPC_use:
3312fe6060f1SDimitry Andric     Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3313fe6060f1SDimitry Andric     break;
3314a7dea167SDimitry Andric   case OMPC_device_type:
33150b57cec5SDimitry Andric   case OMPC_unknown:
33165ffd83dbSDimitry Andric     skipUntilPragmaOpenMPEnd(DKind);
33170b57cec5SDimitry Andric     break;
33180b57cec5SDimitry Andric   case OMPC_threadprivate:
33190b57cec5SDimitry Andric   case OMPC_uniform:
3320a7dea167SDimitry Andric   case OMPC_match:
33210b57cec5SDimitry Andric     if (!WrongDirective)
33220b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_unexpected_clause)
33230b57cec5SDimitry Andric           << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
33240b57cec5SDimitry Andric     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
33250b57cec5SDimitry Andric     break;
33265f757f3fSDimitry Andric   case OMPC_ompx_attribute:
33275f757f3fSDimitry Andric     Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
33285f757f3fSDimitry Andric     break;
33295f757f3fSDimitry Andric   case OMPC_ompx_bare:
33305f757f3fSDimitry Andric     if (WrongDirective)
33315f757f3fSDimitry Andric       Diag(Tok, diag::note_ompx_bare_clause)
33325f757f3fSDimitry Andric           << getOpenMPClauseName(CKind) << "target teams";
33335f757f3fSDimitry Andric     if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
33345f757f3fSDimitry Andric       Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
33355f757f3fSDimitry Andric           << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
33365f757f3fSDimitry Andric       ErrorFound = true;
33375f757f3fSDimitry Andric     }
33385f757f3fSDimitry Andric     Clause = ParseOpenMPClause(CKind, WrongDirective);
33395f757f3fSDimitry Andric     break;
33405ffd83dbSDimitry Andric   default:
33415ffd83dbSDimitry Andric     break;
33420b57cec5SDimitry Andric   }
33430b57cec5SDimitry Andric   return ErrorFound ? nullptr : Clause;
33440b57cec5SDimitry Andric }
33450b57cec5SDimitry Andric 
33460b57cec5SDimitry Andric /// Parses simple expression in parens for single-expression clauses of OpenMP
33470b57cec5SDimitry Andric /// constructs.
33480b57cec5SDimitry Andric /// \param RLoc Returned location of right paren.
ParseOpenMPParensExpr(StringRef ClauseName,SourceLocation & RLoc,bool IsAddressOfOperand)33490b57cec5SDimitry Andric ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
3350a7dea167SDimitry Andric                                          SourceLocation &RLoc,
3351a7dea167SDimitry Andric                                          bool IsAddressOfOperand) {
33520b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
33530b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
33540b57cec5SDimitry Andric     return ExprError();
33550b57cec5SDimitry Andric 
33560b57cec5SDimitry Andric   SourceLocation ELoc = Tok.getLocation();
3357e8d8bef9SDimitry Andric   ExprResult LHS(
3358e8d8bef9SDimitry Andric       ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast));
33590b57cec5SDimitry Andric   ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
33600b57cec5SDimitry Andric   Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
33610b57cec5SDimitry Andric 
33620b57cec5SDimitry Andric   // Parse ')'.
33630b57cec5SDimitry Andric   RLoc = Tok.getLocation();
33640b57cec5SDimitry Andric   if (!T.consumeClose())
33650b57cec5SDimitry Andric     RLoc = T.getCloseLocation();
33660b57cec5SDimitry Andric 
33670b57cec5SDimitry Andric   return Val;
33680b57cec5SDimitry Andric }
33690b57cec5SDimitry Andric 
33700b57cec5SDimitry Andric /// Parsing of OpenMP clauses with single expressions like 'final',
33710b57cec5SDimitry Andric /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
33725ffd83dbSDimitry Andric /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
33735ffd83dbSDimitry Andric /// 'detach'.
33740b57cec5SDimitry Andric ///
33750b57cec5SDimitry Andric ///    final-clause:
33760b57cec5SDimitry Andric ///      'final' '(' expression ')'
33770b57cec5SDimitry Andric ///
33780b57cec5SDimitry Andric ///    num_threads-clause:
33790b57cec5SDimitry Andric ///      'num_threads' '(' expression ')'
33800b57cec5SDimitry Andric ///
33810b57cec5SDimitry Andric ///    safelen-clause:
33820b57cec5SDimitry Andric ///      'safelen' '(' expression ')'
33830b57cec5SDimitry Andric ///
33840b57cec5SDimitry Andric ///    simdlen-clause:
33850b57cec5SDimitry Andric ///      'simdlen' '(' expression ')'
33860b57cec5SDimitry Andric ///
33870b57cec5SDimitry Andric ///    collapse-clause:
33880b57cec5SDimitry Andric ///      'collapse' '(' expression ')'
33890b57cec5SDimitry Andric ///
33900b57cec5SDimitry Andric ///    priority-clause:
33910b57cec5SDimitry Andric ///      'priority' '(' expression ')'
33920b57cec5SDimitry Andric ///
33930b57cec5SDimitry Andric ///    grainsize-clause:
33940b57cec5SDimitry Andric ///      'grainsize' '(' expression ')'
33950b57cec5SDimitry Andric ///
33960b57cec5SDimitry Andric ///    num_tasks-clause:
33970b57cec5SDimitry Andric ///      'num_tasks' '(' expression ')'
33980b57cec5SDimitry Andric ///
33990b57cec5SDimitry Andric ///    hint-clause:
34000b57cec5SDimitry Andric ///      'hint' '(' expression ')'
34010b57cec5SDimitry Andric ///
34020b57cec5SDimitry Andric ///    allocator-clause:
34030b57cec5SDimitry Andric ///      'allocator' '(' expression ')'
34040b57cec5SDimitry Andric ///
34055ffd83dbSDimitry Andric ///    detach-clause:
34065ffd83dbSDimitry Andric ///      'detach' '(' event-handler-expression ')'
34075ffd83dbSDimitry Andric ///
3408349cc55cSDimitry Andric ///    align-clause
3409349cc55cSDimitry Andric ///      'align' '(' positive-integer-constant ')'
3410349cc55cSDimitry Andric ///
ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,bool ParseOnly)34110b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
34120b57cec5SDimitry Andric                                                bool ParseOnly) {
34130b57cec5SDimitry Andric   SourceLocation Loc = ConsumeToken();
34140b57cec5SDimitry Andric   SourceLocation LLoc = Tok.getLocation();
34150b57cec5SDimitry Andric   SourceLocation RLoc;
34160b57cec5SDimitry Andric 
34170b57cec5SDimitry Andric   ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
34180b57cec5SDimitry Andric 
34190b57cec5SDimitry Andric   if (Val.isInvalid())
34200b57cec5SDimitry Andric     return nullptr;
34210b57cec5SDimitry Andric 
34220b57cec5SDimitry Andric   if (ParseOnly)
34230b57cec5SDimitry Andric     return nullptr;
3424*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
3425*0fca6ea1SDimitry Andric                                                       LLoc, RLoc);
34260b57cec5SDimitry Andric }
34270b57cec5SDimitry Andric 
342804eeddc0SDimitry Andric /// Parse indirect clause for '#pragma omp declare target' directive.
342904eeddc0SDimitry Andric ///  'indirect' '[' '(' invoked-by-fptr ')' ']'
343004eeddc0SDimitry Andric /// where invoked-by-fptr is a constant boolean expression that evaluates to
343104eeddc0SDimitry Andric /// true or false at compile time.
ParseOpenMPIndirectClause(SemaOpenMP::DeclareTargetContextInfo & DTCI,bool ParseOnly)3432*0fca6ea1SDimitry Andric bool Parser::ParseOpenMPIndirectClause(
3433*0fca6ea1SDimitry Andric     SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
343404eeddc0SDimitry Andric   SourceLocation Loc = ConsumeToken();
343504eeddc0SDimitry Andric   SourceLocation RLoc;
343604eeddc0SDimitry Andric 
343704eeddc0SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
343804eeddc0SDimitry Andric     if (ParseOnly)
343904eeddc0SDimitry Andric       return false;
344004eeddc0SDimitry Andric     DTCI.Indirect = nullptr;
344104eeddc0SDimitry Andric     return true;
344204eeddc0SDimitry Andric   }
344304eeddc0SDimitry Andric 
344404eeddc0SDimitry Andric   ExprResult Val =
344504eeddc0SDimitry Andric       ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
344604eeddc0SDimitry Andric   if (Val.isInvalid())
344704eeddc0SDimitry Andric     return false;
344804eeddc0SDimitry Andric 
344904eeddc0SDimitry Andric   if (ParseOnly)
345004eeddc0SDimitry Andric     return false;
345104eeddc0SDimitry Andric 
345204eeddc0SDimitry Andric   if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
345304eeddc0SDimitry Andric       !Val.get()->isInstantiationDependent() &&
345404eeddc0SDimitry Andric       !Val.get()->containsUnexpandedParameterPack()) {
345504eeddc0SDimitry Andric     ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
345604eeddc0SDimitry Andric     if (Ret.isInvalid())
345704eeddc0SDimitry Andric       return false;
345804eeddc0SDimitry Andric     llvm::APSInt Result;
345904eeddc0SDimitry Andric     Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
346004eeddc0SDimitry Andric                                                   Sema::AllowFold);
346104eeddc0SDimitry Andric     if (Ret.isInvalid())
346204eeddc0SDimitry Andric       return false;
346304eeddc0SDimitry Andric     DTCI.Indirect = Val.get();
346404eeddc0SDimitry Andric     return true;
346504eeddc0SDimitry Andric   }
346604eeddc0SDimitry Andric   return false;
346704eeddc0SDimitry Andric }
346804eeddc0SDimitry Andric 
3469bdd1243dSDimitry Andric /// Parses a comma-separated list of interop-types and a prefer_type list.
3470bdd1243dSDimitry Andric ///
ParseOMPInteropInfo(OMPInteropInfo & InteropInfo,OpenMPClauseKind Kind)3471bdd1243dSDimitry Andric bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3472bdd1243dSDimitry Andric                                  OpenMPClauseKind Kind) {
3473bdd1243dSDimitry Andric   const Token &Tok = getCurToken();
3474bdd1243dSDimitry Andric   bool HasError = false;
3475bdd1243dSDimitry Andric   bool IsTarget = false;
3476bdd1243dSDimitry Andric   bool IsTargetSync = false;
3477bdd1243dSDimitry Andric 
3478bdd1243dSDimitry Andric   while (Tok.is(tok::identifier)) {
3479bdd1243dSDimitry Andric     // Currently prefer_type is only allowed with 'init' and it must be first.
3480bdd1243dSDimitry Andric     bool PreferTypeAllowed = Kind == OMPC_init &&
3481bdd1243dSDimitry Andric                              InteropInfo.PreferTypes.empty() && !IsTarget &&
3482bdd1243dSDimitry Andric                              !IsTargetSync;
3483bdd1243dSDimitry Andric     if (Tok.getIdentifierInfo()->isStr("target")) {
3484bdd1243dSDimitry Andric       // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3485bdd1243dSDimitry Andric       // Each interop-type may be specified on an action-clause at most
3486bdd1243dSDimitry Andric       // once.
3487bdd1243dSDimitry Andric       if (IsTarget)
3488bdd1243dSDimitry Andric         Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3489bdd1243dSDimitry Andric       IsTarget = true;
3490bdd1243dSDimitry Andric       ConsumeToken();
3491bdd1243dSDimitry Andric     } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
3492bdd1243dSDimitry Andric       if (IsTargetSync)
3493bdd1243dSDimitry Andric         Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3494bdd1243dSDimitry Andric       IsTargetSync = true;
3495bdd1243dSDimitry Andric       ConsumeToken();
3496bdd1243dSDimitry Andric     } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
3497bdd1243dSDimitry Andric                PreferTypeAllowed) {
3498bdd1243dSDimitry Andric       ConsumeToken();
3499bdd1243dSDimitry Andric       BalancedDelimiterTracker PT(*this, tok::l_paren,
3500bdd1243dSDimitry Andric                                   tok::annot_pragma_openmp_end);
3501bdd1243dSDimitry Andric       if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3502bdd1243dSDimitry Andric         HasError = true;
3503bdd1243dSDimitry Andric 
3504bdd1243dSDimitry Andric       while (Tok.isNot(tok::r_paren)) {
3505bdd1243dSDimitry Andric         SourceLocation Loc = Tok.getLocation();
3506bdd1243dSDimitry Andric         ExprResult LHS = ParseCastExpression(AnyCastExpr);
3507bdd1243dSDimitry Andric         ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
3508bdd1243dSDimitry Andric             ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3509bdd1243dSDimitry Andric         PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
3510bdd1243dSDimitry Andric                                              /*DiscardedValue=*/false);
3511bdd1243dSDimitry Andric         if (PTExpr.isUsable()) {
3512bdd1243dSDimitry Andric           InteropInfo.PreferTypes.push_back(PTExpr.get());
3513bdd1243dSDimitry Andric         } else {
3514bdd1243dSDimitry Andric           HasError = true;
3515bdd1243dSDimitry Andric           SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3516bdd1243dSDimitry Andric                     StopBeforeMatch);
3517bdd1243dSDimitry Andric         }
3518bdd1243dSDimitry Andric 
3519bdd1243dSDimitry Andric         if (Tok.is(tok::comma))
3520bdd1243dSDimitry Andric           ConsumeToken();
3521bdd1243dSDimitry Andric       }
3522bdd1243dSDimitry Andric       PT.consumeClose();
3523bdd1243dSDimitry Andric     } else {
3524bdd1243dSDimitry Andric       HasError = true;
3525bdd1243dSDimitry Andric       Diag(Tok, diag::err_omp_expected_interop_type);
3526bdd1243dSDimitry Andric       ConsumeToken();
3527bdd1243dSDimitry Andric     }
3528bdd1243dSDimitry Andric     if (!Tok.is(tok::comma))
3529bdd1243dSDimitry Andric       break;
3530bdd1243dSDimitry Andric     ConsumeToken();
3531bdd1243dSDimitry Andric   }
3532bdd1243dSDimitry Andric 
3533bdd1243dSDimitry Andric   if (!HasError && !IsTarget && !IsTargetSync) {
3534bdd1243dSDimitry Andric     Diag(Tok, diag::err_omp_expected_interop_type);
3535bdd1243dSDimitry Andric     HasError = true;
3536bdd1243dSDimitry Andric   }
3537bdd1243dSDimitry Andric 
3538bdd1243dSDimitry Andric   if (Kind == OMPC_init) {
3539bdd1243dSDimitry Andric     if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
3540bdd1243dSDimitry Andric       Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
3541bdd1243dSDimitry Andric     if (Tok.is(tok::colon))
3542bdd1243dSDimitry Andric       ConsumeToken();
3543bdd1243dSDimitry Andric   }
3544bdd1243dSDimitry Andric 
3545bdd1243dSDimitry Andric   // As of OpenMP 5.1,there are two interop-types, "target" and
3546bdd1243dSDimitry Andric   // "targetsync". Either or both are allowed for a single interop.
3547bdd1243dSDimitry Andric   InteropInfo.IsTarget = IsTarget;
3548bdd1243dSDimitry Andric   InteropInfo.IsTargetSync = IsTargetSync;
3549bdd1243dSDimitry Andric 
3550bdd1243dSDimitry Andric   return HasError;
3551bdd1243dSDimitry Andric }
3552bdd1243dSDimitry Andric 
3553fe6060f1SDimitry Andric /// Parsing of OpenMP clauses that use an interop-var.
3554fe6060f1SDimitry Andric ///
3555fe6060f1SDimitry Andric /// init-clause:
3556fe6060f1SDimitry Andric ///   init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
3557fe6060f1SDimitry Andric ///
3558fe6060f1SDimitry Andric /// destroy-clause:
3559fe6060f1SDimitry Andric ///   destroy(interop-var)
3560fe6060f1SDimitry Andric ///
3561fe6060f1SDimitry Andric /// use-clause:
3562fe6060f1SDimitry Andric ///   use(interop-var)
3563fe6060f1SDimitry Andric ///
3564fe6060f1SDimitry Andric /// interop-modifier:
3565fe6060f1SDimitry Andric ///   prefer_type(preference-list)
3566fe6060f1SDimitry Andric ///
3567fe6060f1SDimitry Andric /// preference-list:
3568fe6060f1SDimitry Andric ///   foreign-runtime-id [, foreign-runtime-id]...
3569fe6060f1SDimitry Andric ///
3570fe6060f1SDimitry Andric /// foreign-runtime-id:
3571fe6060f1SDimitry Andric ///   <string-literal> | <constant-integral-expression>
3572fe6060f1SDimitry Andric ///
3573fe6060f1SDimitry Andric /// interop-type:
3574fe6060f1SDimitry Andric ///   target | targetsync
3575fe6060f1SDimitry Andric ///
ParseOpenMPInteropClause(OpenMPClauseKind Kind,bool ParseOnly)3576fe6060f1SDimitry Andric OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3577fe6060f1SDimitry Andric                                             bool ParseOnly) {
3578fe6060f1SDimitry Andric   SourceLocation Loc = ConsumeToken();
3579fe6060f1SDimitry Andric   // Parse '('.
3580fe6060f1SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3581fe6060f1SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
3582fe6060f1SDimitry Andric                          getOpenMPClauseName(Kind).data()))
3583fe6060f1SDimitry Andric     return nullptr;
3584fe6060f1SDimitry Andric 
3585bdd1243dSDimitry Andric   bool InteropError = false;
3586bdd1243dSDimitry Andric   OMPInteropInfo InteropInfo;
3587bdd1243dSDimitry Andric   if (Kind == OMPC_init)
3588bdd1243dSDimitry Andric     InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3589fe6060f1SDimitry Andric 
3590fe6060f1SDimitry Andric   // Parse the variable.
3591fe6060f1SDimitry Andric   SourceLocation VarLoc = Tok.getLocation();
3592fe6060f1SDimitry Andric   ExprResult InteropVarExpr =
3593fe6060f1SDimitry Andric       Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
3594fe6060f1SDimitry Andric   if (!InteropVarExpr.isUsable()) {
3595fe6060f1SDimitry Andric     SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3596fe6060f1SDimitry Andric               StopBeforeMatch);
3597fe6060f1SDimitry Andric   }
3598fe6060f1SDimitry Andric 
3599fe6060f1SDimitry Andric   // Parse ')'.
3600fe6060f1SDimitry Andric   SourceLocation RLoc = Tok.getLocation();
3601fe6060f1SDimitry Andric   if (!T.consumeClose())
3602fe6060f1SDimitry Andric     RLoc = T.getCloseLocation();
3603fe6060f1SDimitry Andric 
3604bdd1243dSDimitry Andric   if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
3605fe6060f1SDimitry Andric     return nullptr;
3606fe6060f1SDimitry Andric 
3607fe6060f1SDimitry Andric   if (Kind == OMPC_init)
3608*0fca6ea1SDimitry Andric     return Actions.OpenMP().ActOnOpenMPInitClause(
3609*0fca6ea1SDimitry Andric         InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
3610*0fca6ea1SDimitry Andric         RLoc);
3611fe6060f1SDimitry Andric   if (Kind == OMPC_use)
3612*0fca6ea1SDimitry Andric     return Actions.OpenMP().ActOnOpenMPUseClause(
3613*0fca6ea1SDimitry Andric         InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3614fe6060f1SDimitry Andric 
3615fe6060f1SDimitry Andric   if (Kind == OMPC_destroy)
3616*0fca6ea1SDimitry Andric     return Actions.OpenMP().ActOnOpenMPDestroyClause(
3617*0fca6ea1SDimitry Andric         InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3618fe6060f1SDimitry Andric 
3619fe6060f1SDimitry Andric   llvm_unreachable("Unexpected interop variable clause.");
3620fe6060f1SDimitry Andric }
3621fe6060f1SDimitry Andric 
ParseOpenMPOMPXAttributesClause(bool ParseOnly)36225f757f3fSDimitry Andric OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
36235f757f3fSDimitry Andric   SourceLocation Loc = ConsumeToken();
36245f757f3fSDimitry Andric   // Parse '('.
36255f757f3fSDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
36265f757f3fSDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
36275f757f3fSDimitry Andric                          getOpenMPClauseName(OMPC_ompx_attribute).data()))
36285f757f3fSDimitry Andric     return nullptr;
36295f757f3fSDimitry Andric 
36305f757f3fSDimitry Andric   ParsedAttributes ParsedAttrs(AttrFactory);
36315f757f3fSDimitry Andric   ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
36325f757f3fSDimitry Andric 
36335f757f3fSDimitry Andric   // Parse ')'.
36345f757f3fSDimitry Andric   if (T.consumeClose())
36355f757f3fSDimitry Andric     return nullptr;
36365f757f3fSDimitry Andric 
36375f757f3fSDimitry Andric   if (ParseOnly)
36385f757f3fSDimitry Andric     return nullptr;
36395f757f3fSDimitry Andric 
36405f757f3fSDimitry Andric   SmallVector<Attr *> Attrs;
36415f757f3fSDimitry Andric   for (const ParsedAttr &PA : ParsedAttrs) {
36425f757f3fSDimitry Andric     switch (PA.getKind()) {
36435f757f3fSDimitry Andric     case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
36445f757f3fSDimitry Andric       if (!PA.checkExactlyNumArgs(Actions, 2))
36455f757f3fSDimitry Andric         continue;
3646*0fca6ea1SDimitry Andric       if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
36475f757f3fSDimitry Andric               PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
36485f757f3fSDimitry Andric         Attrs.push_back(A);
36495f757f3fSDimitry Andric       continue;
36505f757f3fSDimitry Andric     case ParsedAttr::AT_AMDGPUWavesPerEU:
36515f757f3fSDimitry Andric       if (!PA.checkAtLeastNumArgs(Actions, 1) ||
36525f757f3fSDimitry Andric           !PA.checkAtMostNumArgs(Actions, 2))
36535f757f3fSDimitry Andric         continue;
3654*0fca6ea1SDimitry Andric       if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
36555f757f3fSDimitry Andric               PA, PA.getArgAsExpr(0),
36565f757f3fSDimitry Andric               PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
36575f757f3fSDimitry Andric         Attrs.push_back(A);
36585f757f3fSDimitry Andric       continue;
36595f757f3fSDimitry Andric     case ParsedAttr::AT_CUDALaunchBounds:
36605f757f3fSDimitry Andric       if (!PA.checkAtLeastNumArgs(Actions, 1) ||
36615f757f3fSDimitry Andric           !PA.checkAtMostNumArgs(Actions, 2))
36625f757f3fSDimitry Andric         continue;
36635f757f3fSDimitry Andric       if (auto *A = Actions.CreateLaunchBoundsAttr(
36645f757f3fSDimitry Andric               PA, PA.getArgAsExpr(0),
36655f757f3fSDimitry Andric               PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
36665f757f3fSDimitry Andric               PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))
36675f757f3fSDimitry Andric         Attrs.push_back(A);
36685f757f3fSDimitry Andric       continue;
36695f757f3fSDimitry Andric     default:
36705f757f3fSDimitry Andric       Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
36715f757f3fSDimitry Andric       continue;
36725f757f3fSDimitry Andric     };
36735f757f3fSDimitry Andric   }
36745f757f3fSDimitry Andric 
3675*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPXAttributeClause(
3676*0fca6ea1SDimitry Andric       Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
36775f757f3fSDimitry Andric }
36785f757f3fSDimitry Andric 
36790b57cec5SDimitry Andric /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
36800b57cec5SDimitry Andric ///
36810b57cec5SDimitry Andric ///    default-clause:
368281ad6265SDimitry Andric ///         'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')'
36830b57cec5SDimitry Andric ///
36840b57cec5SDimitry Andric ///    proc_bind-clause:
36855ffd83dbSDimitry Andric ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')'
36865ffd83dbSDimitry Andric ///
3687349cc55cSDimitry Andric ///    bind-clause:
3688349cc55cSDimitry Andric ///         'bind' '(' 'teams' | 'parallel' | 'thread' ')'
3689349cc55cSDimitry Andric ///
36905ffd83dbSDimitry Andric ///    update-clause:
369181ad6265SDimitry Andric ///         'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' |
369281ad6265SDimitry Andric ///         'inoutset' ')'
36930b57cec5SDimitry Andric ///
ParseOpenMPSimpleClause(OpenMPClauseKind Kind,bool ParseOnly)36940b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
36950b57cec5SDimitry Andric                                            bool ParseOnly) {
3696bdd1243dSDimitry Andric   std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
3697a7dea167SDimitry Andric   if (!Val || ParseOnly)
36980b57cec5SDimitry Andric     return nullptr;
36995ffd83dbSDimitry Andric   if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3700bdd1243dSDimitry Andric       (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
3701bdd1243dSDimitry Andric        static_cast<DefaultKind>(Val->Type) ==
370281ad6265SDimitry Andric            OMP_DEFAULT_firstprivate)) {
3703bdd1243dSDimitry Andric     Diag(Val->LOpen, diag::err_omp_invalid_dsa)
3704bdd1243dSDimitry Andric         << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
370581ad6265SDimitry Andric                                        OMP_DEFAULT_private
370681ad6265SDimitry Andric                                    ? OMPC_private
370781ad6265SDimitry Andric                                    : OMPC_firstprivate)
37085ffd83dbSDimitry Andric         << getOpenMPClauseName(OMPC_default) << "5.1";
37095ffd83dbSDimitry Andric     return nullptr;
37105ffd83dbSDimitry Andric   }
3711*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPSimpleClause(
3712*0fca6ea1SDimitry Andric       Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
37130b57cec5SDimitry Andric }
37140b57cec5SDimitry Andric 
37150b57cec5SDimitry Andric /// Parsing of OpenMP clauses like 'ordered'.
37160b57cec5SDimitry Andric ///
37170b57cec5SDimitry Andric ///    ordered-clause:
37180b57cec5SDimitry Andric ///         'ordered'
37190b57cec5SDimitry Andric ///
37200b57cec5SDimitry Andric ///    nowait-clause:
37210b57cec5SDimitry Andric ///         'nowait'
37220b57cec5SDimitry Andric ///
37230b57cec5SDimitry Andric ///    untied-clause:
37240b57cec5SDimitry Andric ///         'untied'
37250b57cec5SDimitry Andric ///
37260b57cec5SDimitry Andric ///    mergeable-clause:
37270b57cec5SDimitry Andric ///         'mergeable'
37280b57cec5SDimitry Andric ///
37290b57cec5SDimitry Andric ///    read-clause:
37300b57cec5SDimitry Andric ///         'read'
37310b57cec5SDimitry Andric ///
37320b57cec5SDimitry Andric ///    threads-clause:
37330b57cec5SDimitry Andric ///         'threads'
37340b57cec5SDimitry Andric ///
37350b57cec5SDimitry Andric ///    simd-clause:
37360b57cec5SDimitry Andric ///         'simd'
37370b57cec5SDimitry Andric ///
37380b57cec5SDimitry Andric ///    nogroup-clause:
37390b57cec5SDimitry Andric ///         'nogroup'
37400b57cec5SDimitry Andric ///
ParseOpenMPClause(OpenMPClauseKind Kind,bool ParseOnly)37410b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
37420b57cec5SDimitry Andric   SourceLocation Loc = Tok.getLocation();
37430b57cec5SDimitry Andric   ConsumeAnyToken();
37440b57cec5SDimitry Andric 
37450b57cec5SDimitry Andric   if (ParseOnly)
37460b57cec5SDimitry Andric     return nullptr;
3747*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
37480b57cec5SDimitry Andric }
37490b57cec5SDimitry Andric 
37500b57cec5SDimitry Andric /// Parsing of OpenMP clauses with single expressions and some additional
37510b57cec5SDimitry Andric /// argument like 'schedule' or 'dist_schedule'.
37520b57cec5SDimitry Andric ///
37530b57cec5SDimitry Andric ///    schedule-clause:
37540b57cec5SDimitry Andric ///      'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
37550b57cec5SDimitry Andric ///      ')'
37560b57cec5SDimitry Andric ///
37570b57cec5SDimitry Andric ///    if-clause:
37580b57cec5SDimitry Andric ///      'if' '(' [ directive-name-modifier ':' ] expression ')'
37590b57cec5SDimitry Andric ///
37600b57cec5SDimitry Andric ///    defaultmap:
37615ffd83dbSDimitry Andric ///      'defaultmap' '(' modifier [ ':' kind ] ')'
37620b57cec5SDimitry Andric ///
37635ffd83dbSDimitry Andric ///    device-clause:
37645ffd83dbSDimitry Andric ///      'device' '(' [ device-modifier ':' ] expression ')'
37655ffd83dbSDimitry Andric ///
ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,bool ParseOnly)37665ffd83dbSDimitry Andric OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
37675ffd83dbSDimitry Andric                                                       OpenMPClauseKind Kind,
37680b57cec5SDimitry Andric                                                       bool ParseOnly) {
37690b57cec5SDimitry Andric   SourceLocation Loc = ConsumeToken();
37700b57cec5SDimitry Andric   SourceLocation DelimLoc;
37710b57cec5SDimitry Andric   // Parse '('.
37720b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
37730b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
37745ffd83dbSDimitry Andric                          getOpenMPClauseName(Kind).data()))
37750b57cec5SDimitry Andric     return nullptr;
37760b57cec5SDimitry Andric 
37770b57cec5SDimitry Andric   ExprResult Val;
37780b57cec5SDimitry Andric   SmallVector<unsigned, 4> Arg;
37790b57cec5SDimitry Andric   SmallVector<SourceLocation, 4> KLoc;
37800b57cec5SDimitry Andric   if (Kind == OMPC_schedule) {
37810b57cec5SDimitry Andric     enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
37820b57cec5SDimitry Andric     Arg.resize(NumberOfElements);
37830b57cec5SDimitry Andric     KLoc.resize(NumberOfElements);
37840b57cec5SDimitry Andric     Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
37850b57cec5SDimitry Andric     Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
37860b57cec5SDimitry Andric     Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
37870b57cec5SDimitry Andric     unsigned KindModifier = getOpenMPSimpleClauseType(
3788349cc55cSDimitry Andric         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
37890b57cec5SDimitry Andric     if (KindModifier > OMPC_SCHEDULE_unknown) {
37900b57cec5SDimitry Andric       // Parse 'modifier'
37910b57cec5SDimitry Andric       Arg[Modifier1] = KindModifier;
37920b57cec5SDimitry Andric       KLoc[Modifier1] = Tok.getLocation();
37930b57cec5SDimitry Andric       if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
37940b57cec5SDimitry Andric           Tok.isNot(tok::annot_pragma_openmp_end))
37950b57cec5SDimitry Andric         ConsumeAnyToken();
37960b57cec5SDimitry Andric       if (Tok.is(tok::comma)) {
37970b57cec5SDimitry Andric         // Parse ',' 'modifier'
37980b57cec5SDimitry Andric         ConsumeAnyToken();
37990b57cec5SDimitry Andric         KindModifier = getOpenMPSimpleClauseType(
3800349cc55cSDimitry Andric             Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
38010b57cec5SDimitry Andric         Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
38020b57cec5SDimitry Andric                              ? KindModifier
38030b57cec5SDimitry Andric                              : (unsigned)OMPC_SCHEDULE_unknown;
38040b57cec5SDimitry Andric         KLoc[Modifier2] = Tok.getLocation();
38050b57cec5SDimitry Andric         if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
38060b57cec5SDimitry Andric             Tok.isNot(tok::annot_pragma_openmp_end))
38070b57cec5SDimitry Andric           ConsumeAnyToken();
38080b57cec5SDimitry Andric       }
38090b57cec5SDimitry Andric       // Parse ':'
38100b57cec5SDimitry Andric       if (Tok.is(tok::colon))
38110b57cec5SDimitry Andric         ConsumeAnyToken();
38120b57cec5SDimitry Andric       else
38130b57cec5SDimitry Andric         Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
38140b57cec5SDimitry Andric       KindModifier = getOpenMPSimpleClauseType(
3815349cc55cSDimitry Andric           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
38160b57cec5SDimitry Andric     }
38170b57cec5SDimitry Andric     Arg[ScheduleKind] = KindModifier;
38180b57cec5SDimitry Andric     KLoc[ScheduleKind] = Tok.getLocation();
38190b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
38200b57cec5SDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end))
38210b57cec5SDimitry Andric       ConsumeAnyToken();
38220b57cec5SDimitry Andric     if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
38230b57cec5SDimitry Andric          Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
38240b57cec5SDimitry Andric          Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
38250b57cec5SDimitry Andric         Tok.is(tok::comma))
38260b57cec5SDimitry Andric       DelimLoc = ConsumeAnyToken();
38270b57cec5SDimitry Andric   } else if (Kind == OMPC_dist_schedule) {
38280b57cec5SDimitry Andric     Arg.push_back(getOpenMPSimpleClauseType(
3829349cc55cSDimitry Andric         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
38300b57cec5SDimitry Andric     KLoc.push_back(Tok.getLocation());
38310b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
38320b57cec5SDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end))
38330b57cec5SDimitry Andric       ConsumeAnyToken();
38340b57cec5SDimitry Andric     if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
38350b57cec5SDimitry Andric       DelimLoc = ConsumeAnyToken();
38360b57cec5SDimitry Andric   } else if (Kind == OMPC_defaultmap) {
38370b57cec5SDimitry Andric     // Get a defaultmap modifier
3838480093f4SDimitry Andric     unsigned Modifier = getOpenMPSimpleClauseType(
3839349cc55cSDimitry Andric         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3840480093f4SDimitry Andric     // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
3841480093f4SDimitry Andric     // pointer
3842480093f4SDimitry Andric     if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
3843480093f4SDimitry Andric       Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
3844480093f4SDimitry Andric     Arg.push_back(Modifier);
38450b57cec5SDimitry Andric     KLoc.push_back(Tok.getLocation());
38460b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
38470b57cec5SDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end))
38480b57cec5SDimitry Andric       ConsumeAnyToken();
38490b57cec5SDimitry Andric     // Parse ':'
38505ffd83dbSDimitry Andric     if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
38510b57cec5SDimitry Andric       if (Tok.is(tok::colon))
38520b57cec5SDimitry Andric         ConsumeAnyToken();
38530b57cec5SDimitry Andric       else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
38540b57cec5SDimitry Andric         Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
38550b57cec5SDimitry Andric       // Get a defaultmap kind
38560b57cec5SDimitry Andric       Arg.push_back(getOpenMPSimpleClauseType(
3857349cc55cSDimitry Andric           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
38580b57cec5SDimitry Andric       KLoc.push_back(Tok.getLocation());
38590b57cec5SDimitry Andric       if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
38600b57cec5SDimitry Andric           Tok.isNot(tok::annot_pragma_openmp_end))
38610b57cec5SDimitry Andric         ConsumeAnyToken();
38620b57cec5SDimitry Andric     } else {
38635ffd83dbSDimitry Andric       Arg.push_back(OMPC_DEFAULTMAP_unknown);
38645ffd83dbSDimitry Andric       KLoc.push_back(SourceLocation());
38655ffd83dbSDimitry Andric     }
3866bdd1243dSDimitry Andric   } else if (Kind == OMPC_order) {
3867bdd1243dSDimitry Andric     enum { Modifier, OrderKind, NumberOfElements };
3868bdd1243dSDimitry Andric     Arg.resize(NumberOfElements);
3869bdd1243dSDimitry Andric     KLoc.resize(NumberOfElements);
3870bdd1243dSDimitry Andric     Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
3871bdd1243dSDimitry Andric     Arg[OrderKind] = OMPC_ORDER_unknown;
3872bdd1243dSDimitry Andric     unsigned KindModifier = getOpenMPSimpleClauseType(
3873bdd1243dSDimitry Andric         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3874bdd1243dSDimitry Andric     if (KindModifier > OMPC_ORDER_unknown) {
3875bdd1243dSDimitry Andric       // Parse 'modifier'
3876bdd1243dSDimitry Andric       Arg[Modifier] = KindModifier;
3877bdd1243dSDimitry Andric       KLoc[Modifier] = Tok.getLocation();
3878bdd1243dSDimitry Andric       if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3879bdd1243dSDimitry Andric           Tok.isNot(tok::annot_pragma_openmp_end))
3880bdd1243dSDimitry Andric         ConsumeAnyToken();
3881bdd1243dSDimitry Andric       // Parse ':'
3882bdd1243dSDimitry Andric       if (Tok.is(tok::colon))
3883bdd1243dSDimitry Andric         ConsumeAnyToken();
3884bdd1243dSDimitry Andric       else
3885bdd1243dSDimitry Andric         Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
3886bdd1243dSDimitry Andric       KindModifier = getOpenMPSimpleClauseType(
3887bdd1243dSDimitry Andric           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3888bdd1243dSDimitry Andric     }
3889bdd1243dSDimitry Andric     Arg[OrderKind] = KindModifier;
3890bdd1243dSDimitry Andric     KLoc[OrderKind] = Tok.getLocation();
3891bdd1243dSDimitry Andric     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3892bdd1243dSDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end))
3893bdd1243dSDimitry Andric       ConsumeAnyToken();
38945ffd83dbSDimitry Andric   } else if (Kind == OMPC_device) {
38955ffd83dbSDimitry Andric     // Only target executable directives support extended device construct.
38965ffd83dbSDimitry Andric     if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
38975ffd83dbSDimitry Andric         NextToken().is(tok::colon)) {
38985ffd83dbSDimitry Andric       // Parse optional <device modifier> ':'
38995ffd83dbSDimitry Andric       Arg.push_back(getOpenMPSimpleClauseType(
3900349cc55cSDimitry Andric           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
39015ffd83dbSDimitry Andric       KLoc.push_back(Tok.getLocation());
39025ffd83dbSDimitry Andric       ConsumeAnyToken();
39035ffd83dbSDimitry Andric       // Parse ':'
39045ffd83dbSDimitry Andric       ConsumeAnyToken();
39055ffd83dbSDimitry Andric     } else {
39065ffd83dbSDimitry Andric       Arg.push_back(OMPC_DEVICE_unknown);
39075ffd83dbSDimitry Andric       KLoc.emplace_back();
39085ffd83dbSDimitry Andric     }
3909bdd1243dSDimitry Andric   } else if (Kind == OMPC_grainsize) {
3910bdd1243dSDimitry Andric     // Parse optional <grainsize modifier> ':'
3911bdd1243dSDimitry Andric     OpenMPGrainsizeClauseModifier Modifier =
3912bdd1243dSDimitry Andric         static_cast<OpenMPGrainsizeClauseModifier>(getOpenMPSimpleClauseType(
3913bdd1243dSDimitry Andric             Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3914bdd1243dSDimitry Andric             getLangOpts()));
3915bdd1243dSDimitry Andric     if (getLangOpts().OpenMP >= 51) {
3916bdd1243dSDimitry Andric       if (NextToken().is(tok::colon)) {
3917bdd1243dSDimitry Andric         Arg.push_back(Modifier);
3918bdd1243dSDimitry Andric         KLoc.push_back(Tok.getLocation());
3919bdd1243dSDimitry Andric         // Parse modifier
3920bdd1243dSDimitry Andric         ConsumeAnyToken();
3921bdd1243dSDimitry Andric         // Parse ':'
3922bdd1243dSDimitry Andric         ConsumeAnyToken();
3923bdd1243dSDimitry Andric       } else {
3924bdd1243dSDimitry Andric         if (Modifier == OMPC_GRAINSIZE_strict) {
3925bdd1243dSDimitry Andric           Diag(Tok, diag::err_modifier_expected_colon) << "strict";
3926bdd1243dSDimitry Andric           // Parse modifier
3927bdd1243dSDimitry Andric           ConsumeAnyToken();
3928bdd1243dSDimitry Andric         }
3929bdd1243dSDimitry Andric         Arg.push_back(OMPC_GRAINSIZE_unknown);
3930bdd1243dSDimitry Andric         KLoc.emplace_back();
3931bdd1243dSDimitry Andric       }
3932bdd1243dSDimitry Andric     } else {
3933bdd1243dSDimitry Andric       Arg.push_back(OMPC_GRAINSIZE_unknown);
3934bdd1243dSDimitry Andric       KLoc.emplace_back();
3935bdd1243dSDimitry Andric     }
3936bdd1243dSDimitry Andric   } else if (Kind == OMPC_num_tasks) {
3937bdd1243dSDimitry Andric     // Parse optional <num_tasks modifier> ':'
3938bdd1243dSDimitry Andric     OpenMPNumTasksClauseModifier Modifier =
3939bdd1243dSDimitry Andric         static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType(
3940bdd1243dSDimitry Andric             Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3941bdd1243dSDimitry Andric             getLangOpts()));
3942bdd1243dSDimitry Andric     if (getLangOpts().OpenMP >= 51) {
3943bdd1243dSDimitry Andric       if (NextToken().is(tok::colon)) {
3944bdd1243dSDimitry Andric         Arg.push_back(Modifier);
3945bdd1243dSDimitry Andric         KLoc.push_back(Tok.getLocation());
3946bdd1243dSDimitry Andric         // Parse modifier
3947bdd1243dSDimitry Andric         ConsumeAnyToken();
3948bdd1243dSDimitry Andric         // Parse ':'
3949bdd1243dSDimitry Andric         ConsumeAnyToken();
3950bdd1243dSDimitry Andric       } else {
3951bdd1243dSDimitry Andric         if (Modifier == OMPC_NUMTASKS_strict) {
3952bdd1243dSDimitry Andric           Diag(Tok, diag::err_modifier_expected_colon) << "strict";
3953bdd1243dSDimitry Andric           // Parse modifier
3954bdd1243dSDimitry Andric           ConsumeAnyToken();
3955bdd1243dSDimitry Andric         }
3956bdd1243dSDimitry Andric         Arg.push_back(OMPC_NUMTASKS_unknown);
3957bdd1243dSDimitry Andric         KLoc.emplace_back();
3958bdd1243dSDimitry Andric       }
3959bdd1243dSDimitry Andric     } else {
3960bdd1243dSDimitry Andric       Arg.push_back(OMPC_NUMTASKS_unknown);
3961bdd1243dSDimitry Andric       KLoc.emplace_back();
3962bdd1243dSDimitry Andric     }
39635ffd83dbSDimitry Andric   } else {
39640b57cec5SDimitry Andric     assert(Kind == OMPC_if);
39650b57cec5SDimitry Andric     KLoc.push_back(Tok.getLocation());
39660b57cec5SDimitry Andric     TentativeParsingAction TPA(*this);
3967480093f4SDimitry Andric     auto DK = parseOpenMPDirectiveKind(*this);
3968480093f4SDimitry Andric     Arg.push_back(DK);
3969480093f4SDimitry Andric     if (DK != OMPD_unknown) {
39700b57cec5SDimitry Andric       ConsumeToken();
39710b57cec5SDimitry Andric       if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
39720b57cec5SDimitry Andric         TPA.Commit();
39730b57cec5SDimitry Andric         DelimLoc = ConsumeToken();
39740b57cec5SDimitry Andric       } else {
39750b57cec5SDimitry Andric         TPA.Revert();
3976480093f4SDimitry Andric         Arg.back() = unsigned(OMPD_unknown);
39770b57cec5SDimitry Andric       }
39780b57cec5SDimitry Andric     } else {
39790b57cec5SDimitry Andric       TPA.Revert();
39800b57cec5SDimitry Andric     }
39810b57cec5SDimitry Andric   }
39820b57cec5SDimitry Andric 
39830b57cec5SDimitry Andric   bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
39840b57cec5SDimitry Andric                           (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
3985bdd1243dSDimitry Andric                           Kind == OMPC_if || Kind == OMPC_device ||
3986bdd1243dSDimitry Andric                           Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
39870b57cec5SDimitry Andric   if (NeedAnExpression) {
39880b57cec5SDimitry Andric     SourceLocation ELoc = Tok.getLocation();
3989480093f4SDimitry Andric     ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
39900b57cec5SDimitry Andric     Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
39910b57cec5SDimitry Andric     Val =
39920b57cec5SDimitry Andric         Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
39930b57cec5SDimitry Andric   }
39940b57cec5SDimitry Andric 
39950b57cec5SDimitry Andric   // Parse ')'.
39960b57cec5SDimitry Andric   SourceLocation RLoc = Tok.getLocation();
39970b57cec5SDimitry Andric   if (!T.consumeClose())
39980b57cec5SDimitry Andric     RLoc = T.getCloseLocation();
39990b57cec5SDimitry Andric 
40000b57cec5SDimitry Andric   if (NeedAnExpression && Val.isInvalid())
40010b57cec5SDimitry Andric     return nullptr;
40020b57cec5SDimitry Andric 
40030b57cec5SDimitry Andric   if (ParseOnly)
40040b57cec5SDimitry Andric     return nullptr;
4005*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
40060b57cec5SDimitry Andric       Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
40070b57cec5SDimitry Andric }
40080b57cec5SDimitry Andric 
ParseReductionId(Parser & P,CXXScopeSpec & ReductionIdScopeSpec,UnqualifiedId & ReductionId)40090b57cec5SDimitry Andric static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
40100b57cec5SDimitry Andric                              UnqualifiedId &ReductionId) {
40110b57cec5SDimitry Andric   if (ReductionIdScopeSpec.isEmpty()) {
40120b57cec5SDimitry Andric     auto OOK = OO_None;
40130b57cec5SDimitry Andric     switch (P.getCurToken().getKind()) {
40140b57cec5SDimitry Andric     case tok::plus:
40150b57cec5SDimitry Andric       OOK = OO_Plus;
40160b57cec5SDimitry Andric       break;
40170b57cec5SDimitry Andric     case tok::minus:
40180b57cec5SDimitry Andric       OOK = OO_Minus;
40190b57cec5SDimitry Andric       break;
40200b57cec5SDimitry Andric     case tok::star:
40210b57cec5SDimitry Andric       OOK = OO_Star;
40220b57cec5SDimitry Andric       break;
40230b57cec5SDimitry Andric     case tok::amp:
40240b57cec5SDimitry Andric       OOK = OO_Amp;
40250b57cec5SDimitry Andric       break;
40260b57cec5SDimitry Andric     case tok::pipe:
40270b57cec5SDimitry Andric       OOK = OO_Pipe;
40280b57cec5SDimitry Andric       break;
40290b57cec5SDimitry Andric     case tok::caret:
40300b57cec5SDimitry Andric       OOK = OO_Caret;
40310b57cec5SDimitry Andric       break;
40320b57cec5SDimitry Andric     case tok::ampamp:
40330b57cec5SDimitry Andric       OOK = OO_AmpAmp;
40340b57cec5SDimitry Andric       break;
40350b57cec5SDimitry Andric     case tok::pipepipe:
40360b57cec5SDimitry Andric       OOK = OO_PipePipe;
40370b57cec5SDimitry Andric       break;
40380b57cec5SDimitry Andric     default:
40390b57cec5SDimitry Andric       break;
40400b57cec5SDimitry Andric     }
40410b57cec5SDimitry Andric     if (OOK != OO_None) {
40420b57cec5SDimitry Andric       SourceLocation OpLoc = P.ConsumeToken();
40430b57cec5SDimitry Andric       SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
40440b57cec5SDimitry Andric       ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
40450b57cec5SDimitry Andric       return false;
40460b57cec5SDimitry Andric     }
40470b57cec5SDimitry Andric   }
40485ffd83dbSDimitry Andric   return P.ParseUnqualifiedId(
40495ffd83dbSDimitry Andric       ReductionIdScopeSpec, /*ObjectType=*/nullptr,
40505ffd83dbSDimitry Andric       /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
40510b57cec5SDimitry Andric       /*AllowDestructorName*/ false,
40520b57cec5SDimitry Andric       /*AllowConstructorName*/ false,
40535ffd83dbSDimitry Andric       /*AllowDeductionGuide*/ false, nullptr, ReductionId);
40540b57cec5SDimitry Andric }
40550b57cec5SDimitry Andric 
40560b57cec5SDimitry Andric /// Checks if the token is a valid map-type-modifier.
4057e8d8bef9SDimitry Andric /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
isMapModifier(Parser & P)40580b57cec5SDimitry Andric static OpenMPMapModifierKind isMapModifier(Parser &P) {
40590b57cec5SDimitry Andric   Token Tok = P.getCurToken();
40600b57cec5SDimitry Andric   if (!Tok.is(tok::identifier))
40610b57cec5SDimitry Andric     return OMPC_MAP_MODIFIER_unknown;
40620b57cec5SDimitry Andric 
40630b57cec5SDimitry Andric   Preprocessor &PP = P.getPreprocessor();
4064e8d8bef9SDimitry Andric   OpenMPMapModifierKind TypeModifier =
4065e8d8bef9SDimitry Andric       static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType(
4066349cc55cSDimitry Andric           OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
40670b57cec5SDimitry Andric   return TypeModifier;
40680b57cec5SDimitry Andric }
40690b57cec5SDimitry Andric 
40700b57cec5SDimitry Andric /// Parse the mapper modifier in map, to, and from clauses.
parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy & Data)4071*0fca6ea1SDimitry Andric bool Parser::parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data) {
40720b57cec5SDimitry Andric   // Parse '('.
40730b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
40740b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
40750b57cec5SDimitry Andric     SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
40760b57cec5SDimitry Andric               StopBeforeMatch);
40770b57cec5SDimitry Andric     return true;
40780b57cec5SDimitry Andric   }
40790b57cec5SDimitry Andric   // Parse mapper-identifier
40800b57cec5SDimitry Andric   if (getLangOpts().CPlusPlus)
40810b57cec5SDimitry Andric     ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
40820b57cec5SDimitry Andric                                    /*ObjectType=*/nullptr,
408304eeddc0SDimitry Andric                                    /*ObjectHasErrors=*/false,
40840b57cec5SDimitry Andric                                    /*EnteringContext=*/false);
40850b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
40860b57cec5SDimitry Andric     Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
40870b57cec5SDimitry Andric     SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
40880b57cec5SDimitry Andric               StopBeforeMatch);
40890b57cec5SDimitry Andric     return true;
40900b57cec5SDimitry Andric   }
40910b57cec5SDimitry Andric   auto &DeclNames = Actions.getASTContext().DeclarationNames;
40920b57cec5SDimitry Andric   Data.ReductionOrMapperId = DeclarationNameInfo(
40930b57cec5SDimitry Andric       DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
40940b57cec5SDimitry Andric   ConsumeToken();
40950b57cec5SDimitry Andric   // Parse ')'.
40960b57cec5SDimitry Andric   return T.consumeClose();
40970b57cec5SDimitry Andric }
40980b57cec5SDimitry Andric 
4099*0fca6ea1SDimitry Andric static OpenMPMapClauseKind isMapType(Parser &P);
4100*0fca6ea1SDimitry Andric 
41010b57cec5SDimitry Andric /// Parse map-type-modifiers in map clause.
4102*0fca6ea1SDimitry Andric /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] [map-type] : ] list)
4103e8d8bef9SDimitry Andric /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) |
4104e8d8bef9SDimitry Andric /// present
4105*0fca6ea1SDimitry Andric /// where, map-type ::= alloc | delete | from | release | to | tofrom
parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy & Data)4106*0fca6ea1SDimitry Andric bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) {
4107*0fca6ea1SDimitry Andric   bool HasMapType = false;
4108*0fca6ea1SDimitry Andric   SourceLocation PreMapLoc = Tok.getLocation();
4109*0fca6ea1SDimitry Andric   StringRef PreMapName = "";
41100b57cec5SDimitry Andric   while (getCurToken().isNot(tok::colon)) {
41110b57cec5SDimitry Andric     OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
4112*0fca6ea1SDimitry Andric     OpenMPMapClauseKind MapKind = isMapType(*this);
41130b57cec5SDimitry Andric     if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4114e8d8bef9SDimitry Andric         TypeModifier == OMPC_MAP_MODIFIER_close ||
4115349cc55cSDimitry Andric         TypeModifier == OMPC_MAP_MODIFIER_present ||
4116349cc55cSDimitry Andric         TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
41170b57cec5SDimitry Andric       Data.MapTypeModifiers.push_back(TypeModifier);
41180b57cec5SDimitry Andric       Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
41195f757f3fSDimitry Andric       if (PP.LookAhead(0).isNot(tok::comma) &&
41205f757f3fSDimitry Andric           PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
41215f757f3fSDimitry Andric         Diag(Tok.getLocation(), diag::err_omp_missing_comma)
41225f757f3fSDimitry Andric             << "map type modifier";
41230b57cec5SDimitry Andric       ConsumeToken();
41240b57cec5SDimitry Andric     } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
41250b57cec5SDimitry Andric       Data.MapTypeModifiers.push_back(TypeModifier);
41260b57cec5SDimitry Andric       Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
41270b57cec5SDimitry Andric       ConsumeToken();
41280b57cec5SDimitry Andric       if (parseMapperModifier(Data))
41290b57cec5SDimitry Andric         return true;
41305f757f3fSDimitry Andric       if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
41315f757f3fSDimitry Andric           getLangOpts().OpenMP >= 52)
41325f757f3fSDimitry Andric         Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
41335f757f3fSDimitry Andric             << "map type modifier";
41345f757f3fSDimitry Andric 
4135*0fca6ea1SDimitry Andric     } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4136*0fca6ea1SDimitry Andric       if (!HasMapType) {
4137*0fca6ea1SDimitry Andric         HasMapType = true;
4138*0fca6ea1SDimitry Andric         Data.ExtraModifier = MapKind;
4139*0fca6ea1SDimitry Andric         MapKind = OMPC_MAP_unknown;
4140*0fca6ea1SDimitry Andric         PreMapLoc = Tok.getLocation();
4141*0fca6ea1SDimitry Andric         PreMapName = Tok.getIdentifierInfo()->getName();
4142*0fca6ea1SDimitry Andric       } else {
4143*0fca6ea1SDimitry Andric         Diag(Tok, diag::err_omp_more_one_map_type);
4144*0fca6ea1SDimitry Andric         Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4145*0fca6ea1SDimitry Andric             << PreMapName;
4146*0fca6ea1SDimitry Andric       }
4147*0fca6ea1SDimitry Andric       ConsumeToken();
41480b57cec5SDimitry Andric     } else {
41490b57cec5SDimitry Andric       // For the case of unknown map-type-modifier or a map-type.
41500b57cec5SDimitry Andric       // Map-type is followed by a colon; the function returns when it
41510b57cec5SDimitry Andric       // encounters a token followed by a colon.
41520b57cec5SDimitry Andric       if (Tok.is(tok::comma)) {
41530b57cec5SDimitry Andric         Diag(Tok, diag::err_omp_map_type_modifier_missing);
41540b57cec5SDimitry Andric         ConsumeToken();
41550b57cec5SDimitry Andric         continue;
41560b57cec5SDimitry Andric       }
41570b57cec5SDimitry Andric       // Potential map-type token as it is followed by a colon.
4158*0fca6ea1SDimitry Andric       if (PP.LookAhead(0).is(tok::colon)) {
4159*0fca6ea1SDimitry Andric         if (getLangOpts().OpenMP >= 60) {
4160*0fca6ea1SDimitry Andric           break;
4161*0fca6ea1SDimitry Andric         } else {
41620b57cec5SDimitry Andric           return false;
4163*0fca6ea1SDimitry Andric         }
4164*0fca6ea1SDimitry Andric       }
4165*0fca6ea1SDimitry Andric 
4166e8d8bef9SDimitry Andric       Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4167bdd1243dSDimitry Andric           << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4168bdd1243dSDimitry Andric                                          : 0)
4169349cc55cSDimitry Andric           << getLangOpts().OpenMPExtensions;
41700b57cec5SDimitry Andric       ConsumeToken();
41710b57cec5SDimitry Andric     }
41720b57cec5SDimitry Andric     if (getCurToken().is(tok::comma))
41730b57cec5SDimitry Andric       ConsumeToken();
41740b57cec5SDimitry Andric   }
4175*0fca6ea1SDimitry Andric   if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4176*0fca6ea1SDimitry Andric     if (!Tok.is(tok::colon)) {
4177*0fca6ea1SDimitry Andric       Diag(Tok, diag::err_omp_unknown_map_type);
4178*0fca6ea1SDimitry Andric       ConsumeToken();
4179*0fca6ea1SDimitry Andric     } else {
4180*0fca6ea1SDimitry Andric       Data.ExtraModifier = OMPC_MAP_unknown;
4181*0fca6ea1SDimitry Andric     }
4182*0fca6ea1SDimitry Andric   }
41830b57cec5SDimitry Andric   return false;
41840b57cec5SDimitry Andric }
41850b57cec5SDimitry Andric 
41860b57cec5SDimitry Andric /// Checks if the token is a valid map-type.
4187*0fca6ea1SDimitry Andric /// If it is not MapType kind, OMPC_MAP_unknown is returned.
isMapType(Parser & P)41880b57cec5SDimitry Andric static OpenMPMapClauseKind isMapType(Parser &P) {
41890b57cec5SDimitry Andric   Token Tok = P.getCurToken();
41900b57cec5SDimitry Andric   // The map-type token can be either an identifier or the C++ delete keyword.
41910b57cec5SDimitry Andric   if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
41920b57cec5SDimitry Andric     return OMPC_MAP_unknown;
41930b57cec5SDimitry Andric   Preprocessor &PP = P.getPreprocessor();
4194*0fca6ea1SDimitry Andric   unsigned MapType =
4195*0fca6ea1SDimitry Andric       getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok), P.getLangOpts());
4196*0fca6ea1SDimitry Andric   if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4197*0fca6ea1SDimitry Andric       MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4198*0fca6ea1SDimitry Andric       MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4199*0fca6ea1SDimitry Andric     return static_cast<OpenMPMapClauseKind>(MapType);
4200*0fca6ea1SDimitry Andric   return OMPC_MAP_unknown;
42010b57cec5SDimitry Andric }
42020b57cec5SDimitry Andric 
42030b57cec5SDimitry Andric /// Parse map-type in map clause.
42040b57cec5SDimitry Andric /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
42050b57cec5SDimitry Andric /// where, map-type ::= to | from | tofrom | alloc | release | delete
parseMapType(Parser & P,SemaOpenMP::OpenMPVarListDataTy & Data)4206*0fca6ea1SDimitry Andric static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data) {
42070b57cec5SDimitry Andric   Token Tok = P.getCurToken();
42080b57cec5SDimitry Andric   if (Tok.is(tok::colon)) {
42090b57cec5SDimitry Andric     P.Diag(Tok, diag::err_omp_map_type_missing);
42100b57cec5SDimitry Andric     return;
42110b57cec5SDimitry Andric   }
4212480093f4SDimitry Andric   Data.ExtraModifier = isMapType(P);
4213480093f4SDimitry Andric   if (Data.ExtraModifier == OMPC_MAP_unknown)
42140b57cec5SDimitry Andric     P.Diag(Tok, diag::err_omp_unknown_map_type);
42150b57cec5SDimitry Andric   P.ConsumeToken();
42160b57cec5SDimitry Andric }
42170b57cec5SDimitry Andric 
42185ffd83dbSDimitry Andric /// Parses simple expression in parens for single-expression clauses of OpenMP
42195ffd83dbSDimitry Andric /// constructs.
ParseOpenMPIteratorsExpr()42205ffd83dbSDimitry Andric ExprResult Parser::ParseOpenMPIteratorsExpr() {
42215ffd83dbSDimitry Andric   assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
42225ffd83dbSDimitry Andric          "Expected 'iterator' token.");
42235ffd83dbSDimitry Andric   SourceLocation IteratorKwLoc = ConsumeToken();
42245ffd83dbSDimitry Andric 
42255ffd83dbSDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
42265ffd83dbSDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
42275ffd83dbSDimitry Andric     return ExprError();
42285ffd83dbSDimitry Andric 
42295ffd83dbSDimitry Andric   SourceLocation LLoc = T.getOpenLocation();
4230*0fca6ea1SDimitry Andric   SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
42315ffd83dbSDimitry Andric   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
42325ffd83dbSDimitry Andric     // Check if the type parsing is required.
42335ffd83dbSDimitry Andric     ParsedType IteratorType;
42345ffd83dbSDimitry Andric     if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
42355ffd83dbSDimitry Andric       // identifier '=' is not found - parse type.
42365ffd83dbSDimitry Andric       TypeResult TR = ParseTypeName();
42375ffd83dbSDimitry Andric       if (TR.isInvalid()) {
42385ffd83dbSDimitry Andric         T.skipToEnd();
42395ffd83dbSDimitry Andric         return ExprError();
42405ffd83dbSDimitry Andric       }
42415ffd83dbSDimitry Andric       IteratorType = TR.get();
42425ffd83dbSDimitry Andric     }
42435ffd83dbSDimitry Andric 
42445ffd83dbSDimitry Andric     // Parse identifier.
42455ffd83dbSDimitry Andric     IdentifierInfo *II = nullptr;
42465ffd83dbSDimitry Andric     SourceLocation IdLoc;
42475ffd83dbSDimitry Andric     if (Tok.is(tok::identifier)) {
42485ffd83dbSDimitry Andric       II = Tok.getIdentifierInfo();
42495ffd83dbSDimitry Andric       IdLoc = ConsumeToken();
42505ffd83dbSDimitry Andric     } else {
42515ffd83dbSDimitry Andric       Diag(Tok, diag::err_expected_unqualified_id) << 0;
42525ffd83dbSDimitry Andric     }
42535ffd83dbSDimitry Andric 
42545ffd83dbSDimitry Andric     // Parse '='.
42555ffd83dbSDimitry Andric     SourceLocation AssignLoc;
42565ffd83dbSDimitry Andric     if (Tok.is(tok::equal))
42575ffd83dbSDimitry Andric       AssignLoc = ConsumeToken();
42585ffd83dbSDimitry Andric     else
42595ffd83dbSDimitry Andric       Diag(Tok, diag::err_omp_expected_equal_in_iterator);
42605ffd83dbSDimitry Andric 
42615ffd83dbSDimitry Andric     // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
42625ffd83dbSDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
42635ffd83dbSDimitry Andric     // Parse <begin>
42645ffd83dbSDimitry Andric     SourceLocation Loc = Tok.getLocation();
42655ffd83dbSDimitry Andric     ExprResult LHS = ParseCastExpression(AnyCastExpr);
42665ffd83dbSDimitry Andric     ExprResult Begin = Actions.CorrectDelayedTyposInExpr(
42675ffd83dbSDimitry Andric         ParseRHSOfBinaryExpression(LHS, prec::Conditional));
42685ffd83dbSDimitry Andric     Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
42695ffd83dbSDimitry Andric                                         /*DiscardedValue=*/false);
42705ffd83dbSDimitry Andric     // Parse ':'.
42715ffd83dbSDimitry Andric     SourceLocation ColonLoc;
42725ffd83dbSDimitry Andric     if (Tok.is(tok::colon))
42735ffd83dbSDimitry Andric       ColonLoc = ConsumeToken();
42745ffd83dbSDimitry Andric 
42755ffd83dbSDimitry Andric     // Parse <end>
42765ffd83dbSDimitry Andric     Loc = Tok.getLocation();
42775ffd83dbSDimitry Andric     LHS = ParseCastExpression(AnyCastExpr);
42785ffd83dbSDimitry Andric     ExprResult End = Actions.CorrectDelayedTyposInExpr(
42795ffd83dbSDimitry Andric         ParseRHSOfBinaryExpression(LHS, prec::Conditional));
42805ffd83dbSDimitry Andric     End = Actions.ActOnFinishFullExpr(End.get(), Loc,
42815ffd83dbSDimitry Andric                                       /*DiscardedValue=*/false);
42825ffd83dbSDimitry Andric 
42835ffd83dbSDimitry Andric     SourceLocation SecColonLoc;
42845ffd83dbSDimitry Andric     ExprResult Step;
42855ffd83dbSDimitry Andric     // Parse optional step.
42865ffd83dbSDimitry Andric     if (Tok.is(tok::colon)) {
42875ffd83dbSDimitry Andric       // Parse ':'
42885ffd83dbSDimitry Andric       SecColonLoc = ConsumeToken();
42895ffd83dbSDimitry Andric       // Parse <step>
42905ffd83dbSDimitry Andric       Loc = Tok.getLocation();
42915ffd83dbSDimitry Andric       LHS = ParseCastExpression(AnyCastExpr);
42925ffd83dbSDimitry Andric       Step = Actions.CorrectDelayedTyposInExpr(
42935ffd83dbSDimitry Andric           ParseRHSOfBinaryExpression(LHS, prec::Conditional));
42945ffd83dbSDimitry Andric       Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
42955ffd83dbSDimitry Andric                                          /*DiscardedValue=*/false);
42965ffd83dbSDimitry Andric     }
42975ffd83dbSDimitry Andric 
42985ffd83dbSDimitry Andric     // Parse ',' or ')'
42995ffd83dbSDimitry Andric     if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
43005ffd83dbSDimitry Andric       Diag(Tok, diag::err_omp_expected_punc_after_iterator);
43015ffd83dbSDimitry Andric     if (Tok.is(tok::comma))
43025ffd83dbSDimitry Andric       ConsumeToken();
43035ffd83dbSDimitry Andric 
4304*0fca6ea1SDimitry Andric     SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
43055ffd83dbSDimitry Andric     D.DeclIdent = II;
43065ffd83dbSDimitry Andric     D.DeclIdentLoc = IdLoc;
43075ffd83dbSDimitry Andric     D.Type = IteratorType;
43085ffd83dbSDimitry Andric     D.AssignLoc = AssignLoc;
43095ffd83dbSDimitry Andric     D.ColonLoc = ColonLoc;
43105ffd83dbSDimitry Andric     D.SecColonLoc = SecColonLoc;
43115ffd83dbSDimitry Andric     D.Range.Begin = Begin.get();
43125ffd83dbSDimitry Andric     D.Range.End = End.get();
43135ffd83dbSDimitry Andric     D.Range.Step = Step.get();
43145ffd83dbSDimitry Andric   }
43155ffd83dbSDimitry Andric 
43165ffd83dbSDimitry Andric   // Parse ')'.
43175ffd83dbSDimitry Andric   SourceLocation RLoc = Tok.getLocation();
43185ffd83dbSDimitry Andric   if (!T.consumeClose())
43195ffd83dbSDimitry Andric     RLoc = T.getCloseLocation();
43205ffd83dbSDimitry Andric 
4321*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4322*0fca6ea1SDimitry Andric                                                LLoc, RLoc, Data);
43235ffd83dbSDimitry Andric }
43245ffd83dbSDimitry Andric 
ParseOpenMPReservedLocator(OpenMPClauseKind Kind,SemaOpenMP::OpenMPVarListDataTy & Data,const LangOptions & LangOpts)432581ad6265SDimitry Andric bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind,
4326*0fca6ea1SDimitry Andric                                         SemaOpenMP::OpenMPVarListDataTy &Data,
432781ad6265SDimitry Andric                                         const LangOptions &LangOpts) {
432881ad6265SDimitry Andric   // Currently the only reserved locator is 'omp_all_memory' which is only
432981ad6265SDimitry Andric   // allowed on a depend clause.
433081ad6265SDimitry Andric   if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
433181ad6265SDimitry Andric     return false;
433281ad6265SDimitry Andric 
433381ad6265SDimitry Andric   if (Tok.is(tok::identifier) &&
433481ad6265SDimitry Andric       Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
433581ad6265SDimitry Andric 
433681ad6265SDimitry Andric     if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
433781ad6265SDimitry Andric         Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
433881ad6265SDimitry Andric       Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
433981ad6265SDimitry Andric     else if (Data.ExtraModifier != OMPC_DEPEND_out &&
434081ad6265SDimitry Andric              Data.ExtraModifier != OMPC_DEPEND_inout)
434181ad6265SDimitry Andric       Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
434281ad6265SDimitry Andric     else
434381ad6265SDimitry Andric       Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
434481ad6265SDimitry Andric                                ? OMPC_DEPEND_outallmemory
434581ad6265SDimitry Andric                                : OMPC_DEPEND_inoutallmemory;
434681ad6265SDimitry Andric     ConsumeToken();
434781ad6265SDimitry Andric     return true;
434881ad6265SDimitry Andric   }
434981ad6265SDimitry Andric   return false;
435081ad6265SDimitry Andric }
435181ad6265SDimitry Andric 
43525f757f3fSDimitry Andric /// Parse step size expression. Returns true if parsing is successfull,
43535f757f3fSDimitry Andric /// otherwise returns false.
parseStepSize(Parser & P,SemaOpenMP::OpenMPVarListDataTy & Data,OpenMPClauseKind CKind,SourceLocation ELoc)4354*0fca6ea1SDimitry Andric static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data,
43555f757f3fSDimitry Andric                           OpenMPClauseKind CKind, SourceLocation ELoc) {
43565f757f3fSDimitry Andric   ExprResult Tail = P.ParseAssignmentExpression();
43575f757f3fSDimitry Andric   Sema &Actions = P.getActions();
43585f757f3fSDimitry Andric   Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
43595f757f3fSDimitry Andric                                      /*DiscardedValue*/ false);
43605f757f3fSDimitry Andric   if (Tail.isUsable()) {
43615f757f3fSDimitry Andric     Data.DepModOrTailExpr = Tail.get();
43625f757f3fSDimitry Andric     Token CurTok = P.getCurToken();
43635f757f3fSDimitry Andric     if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
43645f757f3fSDimitry Andric       P.Diag(CurTok, diag::err_expected_punc) << "step expression";
43655f757f3fSDimitry Andric     }
43665f757f3fSDimitry Andric     return true;
43675f757f3fSDimitry Andric   }
43685f757f3fSDimitry Andric   return false;
43695f757f3fSDimitry Andric }
43705f757f3fSDimitry Andric 
43710b57cec5SDimitry Andric /// Parses clauses with list.
ParseOpenMPVarList(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,SmallVectorImpl<Expr * > & Vars,SemaOpenMP::OpenMPVarListDataTy & Data)43720b57cec5SDimitry Andric bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
43730b57cec5SDimitry Andric                                 OpenMPClauseKind Kind,
43740b57cec5SDimitry Andric                                 SmallVectorImpl<Expr *> &Vars,
4375*0fca6ea1SDimitry Andric                                 SemaOpenMP::OpenMPVarListDataTy &Data) {
43760b57cec5SDimitry Andric   UnqualifiedId UnqualifiedReductionId;
43770b57cec5SDimitry Andric   bool InvalidReductionId = false;
43780b57cec5SDimitry Andric   bool IsInvalidMapperModifier = false;
43790b57cec5SDimitry Andric 
43800b57cec5SDimitry Andric   // Parse '('.
43810b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
43820b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
43835ffd83dbSDimitry Andric                          getOpenMPClauseName(Kind).data()))
43840b57cec5SDimitry Andric     return true;
43850b57cec5SDimitry Andric 
43865ffd83dbSDimitry Andric   bool HasIterator = false;
4387bdd1243dSDimitry Andric   bool InvalidIterator = false;
43880b57cec5SDimitry Andric   bool NeedRParenForLinear = false;
43890b57cec5SDimitry Andric   BalancedDelimiterTracker LinearT(*this, tok::l_paren,
43900b57cec5SDimitry Andric                                    tok::annot_pragma_openmp_end);
43910b57cec5SDimitry Andric   // Handle reduction-identifier for reduction clause.
43920b57cec5SDimitry Andric   if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
43930b57cec5SDimitry Andric       Kind == OMPC_in_reduction) {
43945ffd83dbSDimitry Andric     Data.ExtraModifier = OMPC_REDUCTION_unknown;
43955ffd83dbSDimitry Andric     if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
43965ffd83dbSDimitry Andric         (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
43975ffd83dbSDimitry Andric         NextToken().is(tok::comma)) {
43985ffd83dbSDimitry Andric       // Parse optional reduction modifier.
4399349cc55cSDimitry Andric       Data.ExtraModifier =
4400349cc55cSDimitry Andric           getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
44015ffd83dbSDimitry Andric       Data.ExtraModifierLoc = Tok.getLocation();
44025ffd83dbSDimitry Andric       ConsumeToken();
44035ffd83dbSDimitry Andric       assert(Tok.is(tok::comma) && "Expected comma.");
44045ffd83dbSDimitry Andric       (void)ConsumeToken();
44055ffd83dbSDimitry Andric     }
44060b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
44070b57cec5SDimitry Andric     if (getLangOpts().CPlusPlus)
44080b57cec5SDimitry Andric       ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
44090b57cec5SDimitry Andric                                      /*ObjectType=*/nullptr,
441004eeddc0SDimitry Andric                                      /*ObjectHasErrors=*/false,
44110b57cec5SDimitry Andric                                      /*EnteringContext=*/false);
44120b57cec5SDimitry Andric     InvalidReductionId = ParseReductionId(
44130b57cec5SDimitry Andric         *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
44140b57cec5SDimitry Andric     if (InvalidReductionId) {
44150b57cec5SDimitry Andric       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
44160b57cec5SDimitry Andric                 StopBeforeMatch);
44170b57cec5SDimitry Andric     }
44180b57cec5SDimitry Andric     if (Tok.is(tok::colon))
44190b57cec5SDimitry Andric       Data.ColonLoc = ConsumeToken();
44200b57cec5SDimitry Andric     else
44210b57cec5SDimitry Andric       Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
44220b57cec5SDimitry Andric     if (!InvalidReductionId)
44230b57cec5SDimitry Andric       Data.ReductionOrMapperId =
44240b57cec5SDimitry Andric           Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
442506c3fb27SDimitry Andric   } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
44265ffd83dbSDimitry Andric     if (getLangOpts().OpenMP >= 50) {
44275ffd83dbSDimitry Andric       if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
44285ffd83dbSDimitry Andric         // Handle optional dependence modifier.
44295ffd83dbSDimitry Andric         // iterator(iterators-definition)
44305ffd83dbSDimitry Andric         // where iterators-definition is iterator-specifier [,
44315ffd83dbSDimitry Andric         // iterators-definition ]
44325ffd83dbSDimitry Andric         // where iterator-specifier is [ iterator-type ] identifier =
44335ffd83dbSDimitry Andric         // range-specification
44345ffd83dbSDimitry Andric         HasIterator = true;
44355ffd83dbSDimitry Andric         EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
44365ffd83dbSDimitry Andric         ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
44375ffd83dbSDimitry Andric         Data.DepModOrTailExpr = IteratorRes.get();
44385ffd83dbSDimitry Andric         // Parse ','
44395ffd83dbSDimitry Andric         ExpectAndConsume(tok::comma);
44405ffd83dbSDimitry Andric       }
44415ffd83dbSDimitry Andric     }
44420b57cec5SDimitry Andric     // Handle dependency type for depend clause.
44430b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
4444480093f4SDimitry Andric     Data.ExtraModifier = getOpenMPSimpleClauseType(
4445e8d8bef9SDimitry Andric         Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4446349cc55cSDimitry Andric         getLangOpts());
44475ffd83dbSDimitry Andric     Data.ExtraModifierLoc = Tok.getLocation();
444806c3fb27SDimitry Andric     if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
444906c3fb27SDimitry Andric         (Kind == OMPC_doacross &&
445006c3fb27SDimitry Andric          Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
44510b57cec5SDimitry Andric       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
44520b57cec5SDimitry Andric                 StopBeforeMatch);
44530b57cec5SDimitry Andric     } else {
44540b57cec5SDimitry Andric       ConsumeToken();
44550b57cec5SDimitry Andric       // Special processing for depend(source) clause.
445606c3fb27SDimitry Andric       if (DKind == OMPD_ordered && Kind == OMPC_depend &&
445706c3fb27SDimitry Andric           Data.ExtraModifier == OMPC_DEPEND_source) {
44580b57cec5SDimitry Andric         // Parse ')'.
44590b57cec5SDimitry Andric         T.consumeClose();
44600b57cec5SDimitry Andric         return false;
44610b57cec5SDimitry Andric       }
44620b57cec5SDimitry Andric     }
44630b57cec5SDimitry Andric     if (Tok.is(tok::colon)) {
44640b57cec5SDimitry Andric       Data.ColonLoc = ConsumeToken();
446506c3fb27SDimitry Andric     } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
44660b57cec5SDimitry Andric       Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
44670b57cec5SDimitry Andric                                       : diag::warn_pragma_expected_colon)
446806c3fb27SDimitry Andric           << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
446906c3fb27SDimitry Andric     }
447006c3fb27SDimitry Andric     if (Kind == OMPC_doacross) {
447106c3fb27SDimitry Andric       if (Tok.is(tok::identifier) &&
447206c3fb27SDimitry Andric           Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
447306c3fb27SDimitry Andric         Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
447406c3fb27SDimitry Andric                                  ? OMPC_DOACROSS_source_omp_cur_iteration
447506c3fb27SDimitry Andric                                  : OMPC_DOACROSS_sink_omp_cur_iteration;
447606c3fb27SDimitry Andric         ConsumeToken();
447706c3fb27SDimitry Andric       }
447806c3fb27SDimitry Andric       if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
447906c3fb27SDimitry Andric         if (Tok.isNot(tok::minus)) {
448006c3fb27SDimitry Andric           Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
448106c3fb27SDimitry Andric               << getOpenMPClauseName(Kind) << 0 << 0;
448206c3fb27SDimitry Andric           SkipUntil(tok::r_paren);
448306c3fb27SDimitry Andric           return false;
448406c3fb27SDimitry Andric         } else {
448506c3fb27SDimitry Andric           ConsumeToken();
448606c3fb27SDimitry Andric           SourceLocation Loc = Tok.getLocation();
448706c3fb27SDimitry Andric           uint64_t Value = 0;
448806c3fb27SDimitry Andric           if (Tok.isNot(tok::numeric_constant) ||
448906c3fb27SDimitry Andric               (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
449006c3fb27SDimitry Andric             Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
449106c3fb27SDimitry Andric                 << getOpenMPClauseName(Kind) << 0 << 0;
449206c3fb27SDimitry Andric             SkipUntil(tok::r_paren);
449306c3fb27SDimitry Andric             return false;
449406c3fb27SDimitry Andric           }
449506c3fb27SDimitry Andric         }
449606c3fb27SDimitry Andric       }
449706c3fb27SDimitry Andric       if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
449806c3fb27SDimitry Andric         if (Tok.isNot(tok::r_paren)) {
449906c3fb27SDimitry Andric           Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
450006c3fb27SDimitry Andric               << getOpenMPClauseName(Kind) << 1 << 1;
450106c3fb27SDimitry Andric           SkipUntil(tok::r_paren);
450206c3fb27SDimitry Andric           return false;
450306c3fb27SDimitry Andric         }
450406c3fb27SDimitry Andric       }
450506c3fb27SDimitry Andric       // Only the 'sink' case has the expression list.
450606c3fb27SDimitry Andric       if (Kind == OMPC_doacross &&
450706c3fb27SDimitry Andric           (Data.ExtraModifier == OMPC_DOACROSS_source ||
450806c3fb27SDimitry Andric            Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
450906c3fb27SDimitry Andric            Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
451006c3fb27SDimitry Andric         // Parse ')'.
451106c3fb27SDimitry Andric         T.consumeClose();
451206c3fb27SDimitry Andric         return false;
451306c3fb27SDimitry Andric       }
45140b57cec5SDimitry Andric     }
45150b57cec5SDimitry Andric   } else if (Kind == OMPC_linear) {
45160b57cec5SDimitry Andric     // Try to parse modifier if any.
4517480093f4SDimitry Andric     Data.ExtraModifier = OMPC_LINEAR_val;
45180b57cec5SDimitry Andric     if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
4519349cc55cSDimitry Andric       Data.ExtraModifier =
4520349cc55cSDimitry Andric           getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
45215ffd83dbSDimitry Andric       Data.ExtraModifierLoc = ConsumeToken();
45220b57cec5SDimitry Andric       LinearT.consumeOpen();
45230b57cec5SDimitry Andric       NeedRParenForLinear = true;
45245f757f3fSDimitry Andric       if (getLangOpts().OpenMP >= 52)
45255f757f3fSDimitry Andric         Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
45265f757f3fSDimitry Andric             << "linear-modifier(list)" << getOpenMPClauseName(Kind)
45275f757f3fSDimitry Andric             << "linear(list: [linear-modifier,] step(step-size))";
45280b57cec5SDimitry Andric     }
4529480093f4SDimitry Andric   } else if (Kind == OMPC_lastprivate) {
4530480093f4SDimitry Andric     // Try to parse modifier if any.
4531480093f4SDimitry Andric     Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
4532480093f4SDimitry Andric     // Conditional modifier allowed only in OpenMP 5.0 and not supported in
4533480093f4SDimitry Andric     // distribute and taskloop based directives.
4534480093f4SDimitry Andric     if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
4535480093f4SDimitry Andric          !isOpenMPTaskLoopDirective(DKind)) &&
4536480093f4SDimitry Andric         Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
4537349cc55cSDimitry Andric       Data.ExtraModifier =
4538349cc55cSDimitry Andric           getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
45395ffd83dbSDimitry Andric       Data.ExtraModifierLoc = Tok.getLocation();
4540480093f4SDimitry Andric       ConsumeToken();
4541480093f4SDimitry Andric       assert(Tok.is(tok::colon) && "Expected colon.");
4542480093f4SDimitry Andric       Data.ColonLoc = ConsumeToken();
4543480093f4SDimitry Andric     }
45440b57cec5SDimitry Andric   } else if (Kind == OMPC_map) {
4545bdd1243dSDimitry Andric     // Handle optional iterator map modifier.
4546bdd1243dSDimitry Andric     if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4547bdd1243dSDimitry Andric       HasIterator = true;
4548bdd1243dSDimitry Andric       EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
4549bdd1243dSDimitry Andric       Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
4550bdd1243dSDimitry Andric       Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4551bdd1243dSDimitry Andric       ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4552bdd1243dSDimitry Andric       Data.IteratorExpr = IteratorRes.get();
4553bdd1243dSDimitry Andric       // Parse ','
4554bdd1243dSDimitry Andric       ExpectAndConsume(tok::comma);
4555bdd1243dSDimitry Andric       if (getLangOpts().OpenMP < 52) {
4556bdd1243dSDimitry Andric         Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4557bdd1243dSDimitry Andric             << (getLangOpts().OpenMP >= 51 ? 1 : 0)
4558bdd1243dSDimitry Andric             << getLangOpts().OpenMPExtensions;
4559bdd1243dSDimitry Andric         InvalidIterator = true;
4560bdd1243dSDimitry Andric       }
4561bdd1243dSDimitry Andric     }
45620b57cec5SDimitry Andric     // Handle map type for map clause.
45630b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
45640b57cec5SDimitry Andric 
45650b57cec5SDimitry Andric     // The first identifier may be a list item, a map-type or a
45660b57cec5SDimitry Andric     // map-type-modifier. The map-type can also be delete which has the same
45670b57cec5SDimitry Andric     // spelling of the C++ delete keyword.
4568480093f4SDimitry Andric     Data.ExtraModifier = OMPC_MAP_unknown;
45695ffd83dbSDimitry Andric     Data.ExtraModifierLoc = Tok.getLocation();
45700b57cec5SDimitry Andric 
45710b57cec5SDimitry Andric     // Check for presence of a colon in the map clause.
45720b57cec5SDimitry Andric     TentativeParsingAction TPA(*this);
45730b57cec5SDimitry Andric     bool ColonPresent = false;
45740b57cec5SDimitry Andric     if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
45750b57cec5SDimitry Andric                   StopBeforeMatch)) {
45760b57cec5SDimitry Andric       if (Tok.is(tok::colon))
45770b57cec5SDimitry Andric         ColonPresent = true;
45780b57cec5SDimitry Andric     }
45790b57cec5SDimitry Andric     TPA.Revert();
45800b57cec5SDimitry Andric     // Only parse map-type-modifier[s] and map-type if a colon is present in
45810b57cec5SDimitry Andric     // the map clause.
45820b57cec5SDimitry Andric     if (ColonPresent) {
4583*0fca6ea1SDimitry Andric       if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
4584*0fca6ea1SDimitry Andric         Diag(Tok, diag::err_omp_map_modifier_specification_list);
45850b57cec5SDimitry Andric       IsInvalidMapperModifier = parseMapTypeModifiers(Data);
4586*0fca6ea1SDimitry Andric       if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
45870b57cec5SDimitry Andric         parseMapType(*this, Data);
45880b57cec5SDimitry Andric       else
45890b57cec5SDimitry Andric         SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
45900b57cec5SDimitry Andric     }
4591480093f4SDimitry Andric     if (Data.ExtraModifier == OMPC_MAP_unknown) {
4592480093f4SDimitry Andric       Data.ExtraModifier = OMPC_MAP_tofrom;
4593bdd1243dSDimitry Andric       if (getLangOpts().OpenMP >= 52) {
4594bdd1243dSDimitry Andric         if (DKind == OMPD_target_enter_data)
4595bdd1243dSDimitry Andric           Data.ExtraModifier = OMPC_MAP_to;
4596bdd1243dSDimitry Andric         else if (DKind == OMPD_target_exit_data)
4597bdd1243dSDimitry Andric           Data.ExtraModifier = OMPC_MAP_from;
4598bdd1243dSDimitry Andric       }
45990b57cec5SDimitry Andric       Data.IsMapTypeImplicit = true;
46000b57cec5SDimitry Andric     }
46010b57cec5SDimitry Andric 
46020b57cec5SDimitry Andric     if (Tok.is(tok::colon))
46030b57cec5SDimitry Andric       Data.ColonLoc = ConsumeToken();
46040b57cec5SDimitry Andric   } else if (Kind == OMPC_to || Kind == OMPC_from) {
4605e8d8bef9SDimitry Andric     while (Tok.is(tok::identifier)) {
4606349cc55cSDimitry Andric       auto Modifier = static_cast<OpenMPMotionModifierKind>(
4607349cc55cSDimitry Andric           getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
4608e8d8bef9SDimitry Andric       if (Modifier == OMPC_MOTION_MODIFIER_unknown)
4609e8d8bef9SDimitry Andric         break;
4610e8d8bef9SDimitry Andric       Data.MotionModifiers.push_back(Modifier);
4611e8d8bef9SDimitry Andric       Data.MotionModifiersLoc.push_back(Tok.getLocation());
46120b57cec5SDimitry Andric       ConsumeToken();
4613e8d8bef9SDimitry Andric       if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
46140b57cec5SDimitry Andric         IsInvalidMapperModifier = parseMapperModifier(Data);
4615e8d8bef9SDimitry Andric         if (IsInvalidMapperModifier)
4616e8d8bef9SDimitry Andric           break;
4617e8d8bef9SDimitry Andric       }
4618e8d8bef9SDimitry Andric       // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
4619e8d8bef9SDimitry Andric       if (getLangOpts().OpenMP < 51)
4620e8d8bef9SDimitry Andric         break;
4621e8d8bef9SDimitry Andric       // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
4622e8d8bef9SDimitry Andric       // TODO: Is that intentional?
4623e8d8bef9SDimitry Andric       if (Tok.is(tok::comma))
4624e8d8bef9SDimitry Andric         ConsumeToken();
4625e8d8bef9SDimitry Andric     }
4626e8d8bef9SDimitry Andric     if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
4627e8d8bef9SDimitry Andric       if (!IsInvalidMapperModifier) {
4628e8d8bef9SDimitry Andric         if (getLangOpts().OpenMP < 51)
46290b57cec5SDimitry Andric           Diag(Tok, diag::warn_pragma_expected_colon) << ")";
4630e8d8bef9SDimitry Andric         else
4631e8d8bef9SDimitry Andric           Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
4632e8d8bef9SDimitry Andric       }
46330b57cec5SDimitry Andric       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
46340b57cec5SDimitry Andric                 StopBeforeMatch);
46350b57cec5SDimitry Andric     }
4636e8d8bef9SDimitry Andric     // OpenMP 5.1 permits a ':' even without a preceding modifier.  TODO: Is
4637e8d8bef9SDimitry Andric     // that intentional?
4638e8d8bef9SDimitry Andric     if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
4639e8d8bef9SDimitry Andric         Tok.is(tok::colon))
4640e8d8bef9SDimitry Andric       Data.ColonLoc = ConsumeToken();
46415ffd83dbSDimitry Andric   } else if (Kind == OMPC_allocate ||
46425ffd83dbSDimitry Andric              (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
46435ffd83dbSDimitry Andric               PP.getSpelling(Tok) == "iterator")) {
46440b57cec5SDimitry Andric     // Handle optional allocator expression followed by colon delimiter.
46450b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
46460b57cec5SDimitry Andric     TentativeParsingAction TPA(*this);
46475ffd83dbSDimitry Andric     // OpenMP 5.0, 2.10.1, task Construct.
46485ffd83dbSDimitry Andric     // where aff-modifier is one of the following:
46495ffd83dbSDimitry Andric     // iterator(iterators-definition)
46505ffd83dbSDimitry Andric     ExprResult Tail;
46515ffd83dbSDimitry Andric     if (Kind == OMPC_allocate) {
46525ffd83dbSDimitry Andric       Tail = ParseAssignmentExpression();
46535ffd83dbSDimitry Andric     } else {
46545ffd83dbSDimitry Andric       HasIterator = true;
46555ffd83dbSDimitry Andric       EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
46565ffd83dbSDimitry Andric       Tail = ParseOpenMPIteratorsExpr();
46575ffd83dbSDimitry Andric     }
46585ffd83dbSDimitry Andric     Tail = Actions.CorrectDelayedTyposInExpr(Tail);
46590b57cec5SDimitry Andric     Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
46600b57cec5SDimitry Andric                                        /*DiscardedValue=*/false);
46610b57cec5SDimitry Andric     if (Tail.isUsable()) {
46620b57cec5SDimitry Andric       if (Tok.is(tok::colon)) {
46635ffd83dbSDimitry Andric         Data.DepModOrTailExpr = Tail.get();
46640b57cec5SDimitry Andric         Data.ColonLoc = ConsumeToken();
46650b57cec5SDimitry Andric         TPA.Commit();
46660b57cec5SDimitry Andric       } else {
46675ffd83dbSDimitry Andric         // Colon not found, parse only list of variables.
46680b57cec5SDimitry Andric         TPA.Revert();
46690b57cec5SDimitry Andric       }
46700b57cec5SDimitry Andric     } else {
46710b57cec5SDimitry Andric       // Parsing was unsuccessfull, revert and skip to the end of clause or
46720b57cec5SDimitry Andric       // directive.
46730b57cec5SDimitry Andric       TPA.Revert();
46740b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
46750b57cec5SDimitry Andric                 StopBeforeMatch);
46760b57cec5SDimitry Andric     }
4677349cc55cSDimitry Andric   } else if (Kind == OMPC_adjust_args) {
4678349cc55cSDimitry Andric     // Handle adjust-op for adjust_args clause.
4679349cc55cSDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
4680349cc55cSDimitry Andric     Data.ExtraModifier = getOpenMPSimpleClauseType(
4681349cc55cSDimitry Andric         Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4682349cc55cSDimitry Andric         getLangOpts());
4683349cc55cSDimitry Andric     Data.ExtraModifierLoc = Tok.getLocation();
4684349cc55cSDimitry Andric     if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
4685*0fca6ea1SDimitry Andric       Diag(Tok, diag::err_omp_unknown_adjust_args_op);
4686*0fca6ea1SDimitry Andric       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
4687349cc55cSDimitry Andric     } else {
4688349cc55cSDimitry Andric       ConsumeToken();
4689349cc55cSDimitry Andric       if (Tok.is(tok::colon))
4690349cc55cSDimitry Andric         Data.ColonLoc = Tok.getLocation();
4691349cc55cSDimitry Andric       ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
4692349cc55cSDimitry Andric                        "adjust-op");
4693349cc55cSDimitry Andric     }
46940b57cec5SDimitry Andric   }
46950b57cec5SDimitry Andric 
46960b57cec5SDimitry Andric   bool IsComma =
46970b57cec5SDimitry Andric       (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
469806c3fb27SDimitry Andric        Kind != OMPC_in_reduction && Kind != OMPC_depend &&
4699*0fca6ea1SDimitry Andric        Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
47000b57cec5SDimitry Andric       (Kind == OMPC_reduction && !InvalidReductionId) ||
4701480093f4SDimitry Andric       (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
4702349cc55cSDimitry Andric       (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
470306c3fb27SDimitry Andric       (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
4704349cc55cSDimitry Andric       (Kind == OMPC_adjust_args &&
4705349cc55cSDimitry Andric        Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
47060b57cec5SDimitry Andric   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
47070b57cec5SDimitry Andric   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
47080b57cec5SDimitry Andric                      Tok.isNot(tok::annot_pragma_openmp_end))) {
47095ffd83dbSDimitry Andric     ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
47100b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
471181ad6265SDimitry Andric     if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) {
47120b57cec5SDimitry Andric       // Parse variable
47130b57cec5SDimitry Andric       ExprResult VarExpr =
47140b57cec5SDimitry Andric           Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
47150b57cec5SDimitry Andric       if (VarExpr.isUsable()) {
47160b57cec5SDimitry Andric         Vars.push_back(VarExpr.get());
47170b57cec5SDimitry Andric       } else {
47180b57cec5SDimitry Andric         SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
47190b57cec5SDimitry Andric                   StopBeforeMatch);
47200b57cec5SDimitry Andric       }
472181ad6265SDimitry Andric     }
47220b57cec5SDimitry Andric     // Skip ',' if any
47230b57cec5SDimitry Andric     IsComma = Tok.is(tok::comma);
47240b57cec5SDimitry Andric     if (IsComma)
47250b57cec5SDimitry Andric       ConsumeToken();
47260b57cec5SDimitry Andric     else if (Tok.isNot(tok::r_paren) &&
47270b57cec5SDimitry Andric              Tok.isNot(tok::annot_pragma_openmp_end) &&
47280b57cec5SDimitry Andric              (!MayHaveTail || Tok.isNot(tok::colon)))
47290b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_expected_punc)
47300b57cec5SDimitry Andric           << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
47310b57cec5SDimitry Andric                                    : getOpenMPClauseName(Kind))
47320b57cec5SDimitry Andric           << (Kind == OMPC_flush);
47330b57cec5SDimitry Andric   }
47340b57cec5SDimitry Andric 
47350b57cec5SDimitry Andric   // Parse ')' for linear clause with modifier.
47360b57cec5SDimitry Andric   if (NeedRParenForLinear)
47370b57cec5SDimitry Andric     LinearT.consumeClose();
47380b57cec5SDimitry Andric 
47395f757f3fSDimitry Andric   // Parse ':' linear modifiers (val, uval, ref or step(step-size))
47405f757f3fSDimitry Andric   // or parse ':' alignment.
47410b57cec5SDimitry Andric   const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
47425f757f3fSDimitry Andric   bool StepFound = false;
47435f757f3fSDimitry Andric   bool ModifierFound = false;
47440b57cec5SDimitry Andric   if (MustHaveTail) {
47450b57cec5SDimitry Andric     Data.ColonLoc = Tok.getLocation();
47460b57cec5SDimitry Andric     SourceLocation ELoc = ConsumeToken();
47475f757f3fSDimitry Andric 
47485f757f3fSDimitry Andric     if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
47495f757f3fSDimitry Andric       while (Tok.isNot(tok::r_paren)) {
47505f757f3fSDimitry Andric         if (Tok.is(tok::identifier)) {
47515f757f3fSDimitry Andric           // identifier could be a linear kind (val, uval, ref) or step
47525f757f3fSDimitry Andric           // modifier or step size
47535f757f3fSDimitry Andric           OpenMPLinearClauseKind LinKind =
47545f757f3fSDimitry Andric               static_cast<OpenMPLinearClauseKind>(getOpenMPSimpleClauseType(
47555f757f3fSDimitry Andric                   Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
47565f757f3fSDimitry Andric                   getLangOpts()));
47575f757f3fSDimitry Andric 
47585f757f3fSDimitry Andric           if (LinKind == OMPC_LINEAR_step) {
47595f757f3fSDimitry Andric             if (StepFound)
47605f757f3fSDimitry Andric               Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
47615f757f3fSDimitry Andric 
47625f757f3fSDimitry Andric             BalancedDelimiterTracker StepT(*this, tok::l_paren,
47635f757f3fSDimitry Andric                                            tok::annot_pragma_openmp_end);
47645f757f3fSDimitry Andric             SourceLocation StepModifierLoc = ConsumeToken();
47655f757f3fSDimitry Andric             // parse '('
47665f757f3fSDimitry Andric             if (StepT.consumeOpen())
47675f757f3fSDimitry Andric               Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
47685f757f3fSDimitry Andric 
47695f757f3fSDimitry Andric             // parse step size expression
47705f757f3fSDimitry Andric             StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
47715f757f3fSDimitry Andric             if (StepFound)
47725f757f3fSDimitry Andric               Data.StepModifierLoc = StepModifierLoc;
47735f757f3fSDimitry Andric 
47745f757f3fSDimitry Andric             // parse ')'
47755f757f3fSDimitry Andric             StepT.consumeClose();
47765f757f3fSDimitry Andric           } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
47775f757f3fSDimitry Andric             if (ModifierFound)
47785f757f3fSDimitry Andric               Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
47795f757f3fSDimitry Andric 
47805f757f3fSDimitry Andric             Data.ExtraModifier = LinKind;
47815f757f3fSDimitry Andric             Data.ExtraModifierLoc = ConsumeToken();
47825f757f3fSDimitry Andric             ModifierFound = true;
47835f757f3fSDimitry Andric           } else {
47845f757f3fSDimitry Andric             StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
47855f757f3fSDimitry Andric           }
47865f757f3fSDimitry Andric         } else {
47875f757f3fSDimitry Andric           // parse an integer expression as step size
47885f757f3fSDimitry Andric           StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
47895f757f3fSDimitry Andric         }
47905f757f3fSDimitry Andric 
47915f757f3fSDimitry Andric         if (Tok.is(tok::comma))
47925f757f3fSDimitry Andric           ConsumeToken();
47935f757f3fSDimitry Andric         if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
47945f757f3fSDimitry Andric           break;
47955f757f3fSDimitry Andric       }
47965f757f3fSDimitry Andric       if (!StepFound && !ModifierFound)
47975f757f3fSDimitry Andric         Diag(ELoc, diag::err_expected_expression);
47985f757f3fSDimitry Andric     } else {
47995f757f3fSDimitry Andric       // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
48000b57cec5SDimitry Andric       ExprResult Tail = ParseAssignmentExpression();
48015f757f3fSDimitry Andric       Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
48025f757f3fSDimitry Andric                                          /*DiscardedValue*/ false);
48030b57cec5SDimitry Andric       if (Tail.isUsable())
48045ffd83dbSDimitry Andric         Data.DepModOrTailExpr = Tail.get();
48050b57cec5SDimitry Andric       else
48060b57cec5SDimitry Andric         SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
48070b57cec5SDimitry Andric                   StopBeforeMatch);
48080b57cec5SDimitry Andric     }
48095f757f3fSDimitry Andric   }
48100b57cec5SDimitry Andric 
48110b57cec5SDimitry Andric   // Parse ')'.
48120b57cec5SDimitry Andric   Data.RLoc = Tok.getLocation();
48130b57cec5SDimitry Andric   if (!T.consumeClose())
48140b57cec5SDimitry Andric     Data.RLoc = T.getCloseLocation();
48155ffd83dbSDimitry Andric   // Exit from scope when the iterator is used in depend clause.
48165ffd83dbSDimitry Andric   if (HasIterator)
48175ffd83dbSDimitry Andric     ExitScope();
481806c3fb27SDimitry Andric   return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
481906c3fb27SDimitry Andric           Vars.empty()) ||
48205f757f3fSDimitry Andric          (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
48215f757f3fSDimitry Andric          InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
48220b57cec5SDimitry Andric }
48230b57cec5SDimitry Andric 
48240b57cec5SDimitry Andric /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
48255ffd83dbSDimitry Andric /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction',
48265ffd83dbSDimitry Andric /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'.
48270b57cec5SDimitry Andric ///
48280b57cec5SDimitry Andric ///    private-clause:
48290b57cec5SDimitry Andric ///       'private' '(' list ')'
48300b57cec5SDimitry Andric ///    firstprivate-clause:
48310b57cec5SDimitry Andric ///       'firstprivate' '(' list ')'
48320b57cec5SDimitry Andric ///    lastprivate-clause:
48330b57cec5SDimitry Andric ///       'lastprivate' '(' list ')'
48340b57cec5SDimitry Andric ///    shared-clause:
48350b57cec5SDimitry Andric ///       'shared' '(' list ')'
48360b57cec5SDimitry Andric ///    linear-clause:
48370b57cec5SDimitry Andric ///       'linear' '(' linear-list [ ':' linear-step ] ')'
48380b57cec5SDimitry Andric ///    aligned-clause:
48390b57cec5SDimitry Andric ///       'aligned' '(' list [ ':' alignment ] ')'
48400b57cec5SDimitry Andric ///    reduction-clause:
48415ffd83dbSDimitry Andric ///       'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')'
48420b57cec5SDimitry Andric ///    task_reduction-clause:
48430b57cec5SDimitry Andric ///       'task_reduction' '(' reduction-identifier ':' list ')'
48440b57cec5SDimitry Andric ///    in_reduction-clause:
48450b57cec5SDimitry Andric ///       'in_reduction' '(' reduction-identifier ':' list ')'
48460b57cec5SDimitry Andric ///    copyprivate-clause:
48470b57cec5SDimitry Andric ///       'copyprivate' '(' list ')'
48480b57cec5SDimitry Andric ///    flush-clause:
48490b57cec5SDimitry Andric ///       'flush' '(' list ')'
48500b57cec5SDimitry Andric ///    depend-clause:
48510b57cec5SDimitry Andric ///       'depend' '(' in | out | inout : list | source ')'
48520b57cec5SDimitry Andric ///    map-clause:
48530b57cec5SDimitry Andric ///       'map' '(' [ [ always [,] ] [ close [,] ]
48540b57cec5SDimitry Andric ///          [ mapper '(' mapper-identifier ')' [,] ]
48550b57cec5SDimitry Andric ///          to | from | tofrom | alloc | release | delete ':' ] list ')';
48560b57cec5SDimitry Andric ///    to-clause:
48570b57cec5SDimitry Andric ///       'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
48580b57cec5SDimitry Andric ///    from-clause:
48590b57cec5SDimitry Andric ///       'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
48600b57cec5SDimitry Andric ///    use_device_ptr-clause:
48610b57cec5SDimitry Andric ///       'use_device_ptr' '(' list ')'
48625ffd83dbSDimitry Andric ///    use_device_addr-clause:
48635ffd83dbSDimitry Andric ///       'use_device_addr' '(' list ')'
48640b57cec5SDimitry Andric ///    is_device_ptr-clause:
48650b57cec5SDimitry Andric ///       'is_device_ptr' '(' list ')'
486681ad6265SDimitry Andric ///    has_device_addr-clause:
486781ad6265SDimitry Andric ///       'has_device_addr' '(' list ')'
48680b57cec5SDimitry Andric ///    allocate-clause:
48690b57cec5SDimitry Andric ///       'allocate' '(' [ allocator ':' ] list ')'
48705ffd83dbSDimitry Andric ///    nontemporal-clause:
48715ffd83dbSDimitry Andric ///       'nontemporal' '(' list ')'
48725ffd83dbSDimitry Andric ///    inclusive-clause:
48735ffd83dbSDimitry Andric ///       'inclusive' '(' list ')'
48745ffd83dbSDimitry Andric ///    exclusive-clause:
48755ffd83dbSDimitry Andric ///       'exclusive' '(' list ')'
48760b57cec5SDimitry Andric ///
48770b57cec5SDimitry Andric /// For 'linear' clause linear-list may have the following forms:
48780b57cec5SDimitry Andric ///  list
48790b57cec5SDimitry Andric ///  modifier(list)
48800b57cec5SDimitry Andric /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,bool ParseOnly)48810b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
48820b57cec5SDimitry Andric                                             OpenMPClauseKind Kind,
48830b57cec5SDimitry Andric                                             bool ParseOnly) {
48840b57cec5SDimitry Andric   SourceLocation Loc = Tok.getLocation();
48850b57cec5SDimitry Andric   SourceLocation LOpen = ConsumeToken();
48860b57cec5SDimitry Andric   SmallVector<Expr *, 4> Vars;
4887*0fca6ea1SDimitry Andric   SemaOpenMP::OpenMPVarListDataTy Data;
48880b57cec5SDimitry Andric 
48890b57cec5SDimitry Andric   if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
48900b57cec5SDimitry Andric     return nullptr;
48910b57cec5SDimitry Andric 
48920b57cec5SDimitry Andric   if (ParseOnly)
48930b57cec5SDimitry Andric     return nullptr;
48940b57cec5SDimitry Andric   OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
4895*0fca6ea1SDimitry Andric   return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
4896*0fca6ea1SDimitry Andric }
4897*0fca6ea1SDimitry Andric 
ParseOpenMPExprListClause(OpenMPClauseKind Kind,SourceLocation & ClauseNameLoc,SourceLocation & OpenLoc,SourceLocation & CloseLoc,SmallVectorImpl<Expr * > & Exprs,bool ReqIntConst)4898*0fca6ea1SDimitry Andric bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
4899*0fca6ea1SDimitry Andric                                        SourceLocation &ClauseNameLoc,
4900*0fca6ea1SDimitry Andric                                        SourceLocation &OpenLoc,
4901*0fca6ea1SDimitry Andric                                        SourceLocation &CloseLoc,
4902*0fca6ea1SDimitry Andric                                        SmallVectorImpl<Expr *> &Exprs,
4903*0fca6ea1SDimitry Andric                                        bool ReqIntConst) {
4904*0fca6ea1SDimitry Andric   assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
4905*0fca6ea1SDimitry Andric          "Expected parsing to start at clause name");
4906*0fca6ea1SDimitry Andric   ClauseNameLoc = ConsumeToken();
4907*0fca6ea1SDimitry Andric 
4908*0fca6ea1SDimitry Andric   // Parse inside of '(' and ')'.
4909*0fca6ea1SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4910*0fca6ea1SDimitry Andric   if (T.consumeOpen()) {
4911*0fca6ea1SDimitry Andric     Diag(Tok, diag::err_expected) << tok::l_paren;
4912*0fca6ea1SDimitry Andric     return true;
4913*0fca6ea1SDimitry Andric   }
4914*0fca6ea1SDimitry Andric 
4915*0fca6ea1SDimitry Andric   // Parse the list with interleaved commas.
4916*0fca6ea1SDimitry Andric   do {
4917*0fca6ea1SDimitry Andric     ExprResult Val =
4918*0fca6ea1SDimitry Andric         ReqIntConst ? ParseConstantExpression() : ParseAssignmentExpression();
4919*0fca6ea1SDimitry Andric     if (!Val.isUsable()) {
4920*0fca6ea1SDimitry Andric       // Encountered something other than an expression; abort to ')'.
4921*0fca6ea1SDimitry Andric       T.skipToEnd();
4922*0fca6ea1SDimitry Andric       return true;
4923*0fca6ea1SDimitry Andric     }
4924*0fca6ea1SDimitry Andric     Exprs.push_back(Val.get());
4925*0fca6ea1SDimitry Andric   } while (TryConsumeToken(tok::comma));
4926*0fca6ea1SDimitry Andric 
4927*0fca6ea1SDimitry Andric   bool Result = T.consumeClose();
4928*0fca6ea1SDimitry Andric   OpenLoc = T.getOpenLocation();
4929*0fca6ea1SDimitry Andric   CloseLoc = T.getCloseLocation();
4930*0fca6ea1SDimitry Andric   return Result;
49310b57cec5SDimitry Andric }
4932