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