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