1*0b57cec5SDimitry Andric //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric /// \file 9*0b57cec5SDimitry Andric /// This file implements parsing of all OpenMP directives and clauses. 10*0b57cec5SDimitry Andric /// 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 14*0b57cec5SDimitry Andric #include "clang/AST/StmtOpenMP.h" 15*0b57cec5SDimitry Andric #include "clang/Parse/ParseDiagnostic.h" 16*0b57cec5SDimitry Andric #include "clang/Parse/Parser.h" 17*0b57cec5SDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h" 18*0b57cec5SDimitry Andric #include "clang/Sema/Scope.h" 19*0b57cec5SDimitry Andric #include "llvm/ADT/PointerIntPair.h" 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric using namespace clang; 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 24*0b57cec5SDimitry Andric // OpenMP declarative directives. 25*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric namespace { 28*0b57cec5SDimitry Andric enum OpenMPDirectiveKindEx { 29*0b57cec5SDimitry Andric OMPD_cancellation = OMPD_unknown + 1, 30*0b57cec5SDimitry Andric OMPD_data, 31*0b57cec5SDimitry Andric OMPD_declare, 32*0b57cec5SDimitry Andric OMPD_end, 33*0b57cec5SDimitry Andric OMPD_end_declare, 34*0b57cec5SDimitry Andric OMPD_enter, 35*0b57cec5SDimitry Andric OMPD_exit, 36*0b57cec5SDimitry Andric OMPD_point, 37*0b57cec5SDimitry Andric OMPD_reduction, 38*0b57cec5SDimitry Andric OMPD_target_enter, 39*0b57cec5SDimitry Andric OMPD_target_exit, 40*0b57cec5SDimitry Andric OMPD_update, 41*0b57cec5SDimitry Andric OMPD_distribute_parallel, 42*0b57cec5SDimitry Andric OMPD_teams_distribute_parallel, 43*0b57cec5SDimitry Andric OMPD_target_teams_distribute_parallel, 44*0b57cec5SDimitry Andric OMPD_mapper, 45*0b57cec5SDimitry Andric }; 46*0b57cec5SDimitry Andric 47*0b57cec5SDimitry Andric class DeclDirectiveListParserHelper final { 48*0b57cec5SDimitry Andric SmallVector<Expr *, 4> Identifiers; 49*0b57cec5SDimitry Andric Parser *P; 50*0b57cec5SDimitry Andric OpenMPDirectiveKind Kind; 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric public: 53*0b57cec5SDimitry Andric DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind) 54*0b57cec5SDimitry Andric : P(P), Kind(Kind) {} 55*0b57cec5SDimitry Andric void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 56*0b57cec5SDimitry Andric ExprResult Res = P->getActions().ActOnOpenMPIdExpression( 57*0b57cec5SDimitry Andric P->getCurScope(), SS, NameInfo, Kind); 58*0b57cec5SDimitry Andric if (Res.isUsable()) 59*0b57cec5SDimitry Andric Identifiers.push_back(Res.get()); 60*0b57cec5SDimitry Andric } 61*0b57cec5SDimitry Andric llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } 62*0b57cec5SDimitry Andric }; 63*0b57cec5SDimitry Andric } // namespace 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric // Map token string to extended OMP token kind that are 66*0b57cec5SDimitry Andric // OpenMPDirectiveKind + OpenMPDirectiveKindEx. 67*0b57cec5SDimitry Andric static unsigned getOpenMPDirectiveKindEx(StringRef S) { 68*0b57cec5SDimitry Andric auto DKind = getOpenMPDirectiveKind(S); 69*0b57cec5SDimitry Andric if (DKind != OMPD_unknown) 70*0b57cec5SDimitry Andric return DKind; 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric return llvm::StringSwitch<unsigned>(S) 73*0b57cec5SDimitry Andric .Case("cancellation", OMPD_cancellation) 74*0b57cec5SDimitry Andric .Case("data", OMPD_data) 75*0b57cec5SDimitry Andric .Case("declare", OMPD_declare) 76*0b57cec5SDimitry Andric .Case("end", OMPD_end) 77*0b57cec5SDimitry Andric .Case("enter", OMPD_enter) 78*0b57cec5SDimitry Andric .Case("exit", OMPD_exit) 79*0b57cec5SDimitry Andric .Case("point", OMPD_point) 80*0b57cec5SDimitry Andric .Case("reduction", OMPD_reduction) 81*0b57cec5SDimitry Andric .Case("update", OMPD_update) 82*0b57cec5SDimitry Andric .Case("mapper", OMPD_mapper) 83*0b57cec5SDimitry Andric .Default(OMPD_unknown); 84*0b57cec5SDimitry Andric } 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { 87*0b57cec5SDimitry Andric // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 88*0b57cec5SDimitry Andric // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 89*0b57cec5SDimitry Andric // TODO: add other combined directives in topological order. 90*0b57cec5SDimitry Andric static const unsigned F[][3] = { 91*0b57cec5SDimitry Andric {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, 92*0b57cec5SDimitry Andric {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, 93*0b57cec5SDimitry Andric {OMPD_declare, OMPD_mapper, OMPD_declare_mapper}, 94*0b57cec5SDimitry Andric {OMPD_declare, OMPD_simd, OMPD_declare_simd}, 95*0b57cec5SDimitry Andric {OMPD_declare, OMPD_target, OMPD_declare_target}, 96*0b57cec5SDimitry Andric {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, 97*0b57cec5SDimitry Andric {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, 98*0b57cec5SDimitry Andric {OMPD_distribute_parallel_for, OMPD_simd, 99*0b57cec5SDimitry Andric OMPD_distribute_parallel_for_simd}, 100*0b57cec5SDimitry Andric {OMPD_distribute, OMPD_simd, OMPD_distribute_simd}, 101*0b57cec5SDimitry Andric {OMPD_end, OMPD_declare, OMPD_end_declare}, 102*0b57cec5SDimitry Andric {OMPD_end_declare, OMPD_target, OMPD_end_declare_target}, 103*0b57cec5SDimitry Andric {OMPD_target, OMPD_data, OMPD_target_data}, 104*0b57cec5SDimitry Andric {OMPD_target, OMPD_enter, OMPD_target_enter}, 105*0b57cec5SDimitry Andric {OMPD_target, OMPD_exit, OMPD_target_exit}, 106*0b57cec5SDimitry Andric {OMPD_target, OMPD_update, OMPD_target_update}, 107*0b57cec5SDimitry Andric {OMPD_target_enter, OMPD_data, OMPD_target_enter_data}, 108*0b57cec5SDimitry Andric {OMPD_target_exit, OMPD_data, OMPD_target_exit_data}, 109*0b57cec5SDimitry Andric {OMPD_for, OMPD_simd, OMPD_for_simd}, 110*0b57cec5SDimitry Andric {OMPD_parallel, OMPD_for, OMPD_parallel_for}, 111*0b57cec5SDimitry Andric {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, 112*0b57cec5SDimitry Andric {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, 113*0b57cec5SDimitry Andric {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, 114*0b57cec5SDimitry Andric {OMPD_target, OMPD_parallel, OMPD_target_parallel}, 115*0b57cec5SDimitry Andric {OMPD_target, OMPD_simd, OMPD_target_simd}, 116*0b57cec5SDimitry Andric {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, 117*0b57cec5SDimitry Andric {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, 118*0b57cec5SDimitry Andric {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, 119*0b57cec5SDimitry Andric {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd}, 120*0b57cec5SDimitry Andric {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel}, 121*0b57cec5SDimitry Andric {OMPD_teams_distribute_parallel, OMPD_for, 122*0b57cec5SDimitry Andric OMPD_teams_distribute_parallel_for}, 123*0b57cec5SDimitry Andric {OMPD_teams_distribute_parallel_for, OMPD_simd, 124*0b57cec5SDimitry Andric OMPD_teams_distribute_parallel_for_simd}, 125*0b57cec5SDimitry Andric {OMPD_target, OMPD_teams, OMPD_target_teams}, 126*0b57cec5SDimitry Andric {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, 127*0b57cec5SDimitry Andric {OMPD_target_teams_distribute, OMPD_parallel, 128*0b57cec5SDimitry Andric OMPD_target_teams_distribute_parallel}, 129*0b57cec5SDimitry Andric {OMPD_target_teams_distribute, OMPD_simd, 130*0b57cec5SDimitry Andric OMPD_target_teams_distribute_simd}, 131*0b57cec5SDimitry Andric {OMPD_target_teams_distribute_parallel, OMPD_for, 132*0b57cec5SDimitry Andric OMPD_target_teams_distribute_parallel_for}, 133*0b57cec5SDimitry Andric {OMPD_target_teams_distribute_parallel_for, OMPD_simd, 134*0b57cec5SDimitry Andric OMPD_target_teams_distribute_parallel_for_simd}}; 135*0b57cec5SDimitry Andric enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; 136*0b57cec5SDimitry Andric Token Tok = P.getCurToken(); 137*0b57cec5SDimitry Andric unsigned DKind = 138*0b57cec5SDimitry Andric Tok.isAnnotation() 139*0b57cec5SDimitry Andric ? static_cast<unsigned>(OMPD_unknown) 140*0b57cec5SDimitry Andric : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 141*0b57cec5SDimitry Andric if (DKind == OMPD_unknown) 142*0b57cec5SDimitry Andric return OMPD_unknown; 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) { 145*0b57cec5SDimitry Andric if (DKind != F[I][0]) 146*0b57cec5SDimitry Andric continue; 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric Tok = P.getPreprocessor().LookAhead(0); 149*0b57cec5SDimitry Andric unsigned SDKind = 150*0b57cec5SDimitry Andric Tok.isAnnotation() 151*0b57cec5SDimitry Andric ? static_cast<unsigned>(OMPD_unknown) 152*0b57cec5SDimitry Andric : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 153*0b57cec5SDimitry Andric if (SDKind == OMPD_unknown) 154*0b57cec5SDimitry Andric continue; 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric if (SDKind == F[I][1]) { 157*0b57cec5SDimitry Andric P.ConsumeToken(); 158*0b57cec5SDimitry Andric DKind = F[I][2]; 159*0b57cec5SDimitry Andric } 160*0b57cec5SDimitry Andric } 161*0b57cec5SDimitry Andric return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind) 162*0b57cec5SDimitry Andric : OMPD_unknown; 163*0b57cec5SDimitry Andric } 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric static DeclarationName parseOpenMPReductionId(Parser &P) { 166*0b57cec5SDimitry Andric Token Tok = P.getCurToken(); 167*0b57cec5SDimitry Andric Sema &Actions = P.getActions(); 168*0b57cec5SDimitry Andric OverloadedOperatorKind OOK = OO_None; 169*0b57cec5SDimitry Andric // Allow to use 'operator' keyword for C++ operators 170*0b57cec5SDimitry Andric bool WithOperator = false; 171*0b57cec5SDimitry Andric if (Tok.is(tok::kw_operator)) { 172*0b57cec5SDimitry Andric P.ConsumeToken(); 173*0b57cec5SDimitry Andric Tok = P.getCurToken(); 174*0b57cec5SDimitry Andric WithOperator = true; 175*0b57cec5SDimitry Andric } 176*0b57cec5SDimitry Andric switch (Tok.getKind()) { 177*0b57cec5SDimitry Andric case tok::plus: // '+' 178*0b57cec5SDimitry Andric OOK = OO_Plus; 179*0b57cec5SDimitry Andric break; 180*0b57cec5SDimitry Andric case tok::minus: // '-' 181*0b57cec5SDimitry Andric OOK = OO_Minus; 182*0b57cec5SDimitry Andric break; 183*0b57cec5SDimitry Andric case tok::star: // '*' 184*0b57cec5SDimitry Andric OOK = OO_Star; 185*0b57cec5SDimitry Andric break; 186*0b57cec5SDimitry Andric case tok::amp: // '&' 187*0b57cec5SDimitry Andric OOK = OO_Amp; 188*0b57cec5SDimitry Andric break; 189*0b57cec5SDimitry Andric case tok::pipe: // '|' 190*0b57cec5SDimitry Andric OOK = OO_Pipe; 191*0b57cec5SDimitry Andric break; 192*0b57cec5SDimitry Andric case tok::caret: // '^' 193*0b57cec5SDimitry Andric OOK = OO_Caret; 194*0b57cec5SDimitry Andric break; 195*0b57cec5SDimitry Andric case tok::ampamp: // '&&' 196*0b57cec5SDimitry Andric OOK = OO_AmpAmp; 197*0b57cec5SDimitry Andric break; 198*0b57cec5SDimitry Andric case tok::pipepipe: // '||' 199*0b57cec5SDimitry Andric OOK = OO_PipePipe; 200*0b57cec5SDimitry Andric break; 201*0b57cec5SDimitry Andric case tok::identifier: // identifier 202*0b57cec5SDimitry Andric if (!WithOperator) 203*0b57cec5SDimitry Andric break; 204*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 205*0b57cec5SDimitry Andric default: 206*0b57cec5SDimitry Andric P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); 207*0b57cec5SDimitry Andric P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 208*0b57cec5SDimitry Andric Parser::StopBeforeMatch); 209*0b57cec5SDimitry Andric return DeclarationName(); 210*0b57cec5SDimitry Andric } 211*0b57cec5SDimitry Andric P.ConsumeToken(); 212*0b57cec5SDimitry Andric auto &DeclNames = Actions.getASTContext().DeclarationNames; 213*0b57cec5SDimitry Andric return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo()) 214*0b57cec5SDimitry Andric : DeclNames.getCXXOperatorName(OOK); 215*0b57cec5SDimitry Andric } 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric /// Parse 'omp declare reduction' construct. 218*0b57cec5SDimitry Andric /// 219*0b57cec5SDimitry Andric /// declare-reduction-directive: 220*0b57cec5SDimitry Andric /// annot_pragma_openmp 'declare' 'reduction' 221*0b57cec5SDimitry Andric /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')' 222*0b57cec5SDimitry Andric /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')'] 223*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 224*0b57cec5SDimitry Andric /// <reduction_id> is either a base language identifier or one of the following 225*0b57cec5SDimitry Andric /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'. 226*0b57cec5SDimitry Andric /// 227*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy 228*0b57cec5SDimitry Andric Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { 229*0b57cec5SDimitry Andric // Parse '('. 230*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 231*0b57cec5SDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, 232*0b57cec5SDimitry Andric getOpenMPDirectiveName(OMPD_declare_reduction))) { 233*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 234*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 235*0b57cec5SDimitry Andric } 236*0b57cec5SDimitry Andric 237*0b57cec5SDimitry Andric DeclarationName Name = parseOpenMPReductionId(*this); 238*0b57cec5SDimitry Andric if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end)) 239*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 240*0b57cec5SDimitry Andric 241*0b57cec5SDimitry Andric // Consume ':'. 242*0b57cec5SDimitry Andric bool IsCorrect = !ExpectAndConsume(tok::colon); 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 245*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 246*0b57cec5SDimitry Andric 247*0b57cec5SDimitry Andric IsCorrect = IsCorrect && !Name.isEmpty(); 248*0b57cec5SDimitry Andric 249*0b57cec5SDimitry Andric if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) { 250*0b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected_type); 251*0b57cec5SDimitry Andric IsCorrect = false; 252*0b57cec5SDimitry Andric } 253*0b57cec5SDimitry Andric 254*0b57cec5SDimitry Andric if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 255*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 256*0b57cec5SDimitry Andric 257*0b57cec5SDimitry Andric SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes; 258*0b57cec5SDimitry Andric // Parse list of types until ':' token. 259*0b57cec5SDimitry Andric do { 260*0b57cec5SDimitry Andric ColonProtectionRAIIObject ColonRAII(*this); 261*0b57cec5SDimitry Andric SourceRange Range; 262*0b57cec5SDimitry Andric TypeResult TR = 263*0b57cec5SDimitry Andric ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS); 264*0b57cec5SDimitry Andric if (TR.isUsable()) { 265*0b57cec5SDimitry Andric QualType ReductionType = 266*0b57cec5SDimitry Andric Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); 267*0b57cec5SDimitry Andric if (!ReductionType.isNull()) { 268*0b57cec5SDimitry Andric ReductionTypes.push_back( 269*0b57cec5SDimitry Andric std::make_pair(ReductionType, Range.getBegin())); 270*0b57cec5SDimitry Andric } 271*0b57cec5SDimitry Andric } else { 272*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end, 273*0b57cec5SDimitry Andric StopBeforeMatch); 274*0b57cec5SDimitry Andric } 275*0b57cec5SDimitry Andric 276*0b57cec5SDimitry Andric if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) 277*0b57cec5SDimitry Andric break; 278*0b57cec5SDimitry Andric 279*0b57cec5SDimitry Andric // Consume ','. 280*0b57cec5SDimitry Andric if (ExpectAndConsume(tok::comma)) { 281*0b57cec5SDimitry Andric IsCorrect = false; 282*0b57cec5SDimitry Andric if (Tok.is(tok::annot_pragma_openmp_end)) { 283*0b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected_type); 284*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 285*0b57cec5SDimitry Andric } 286*0b57cec5SDimitry Andric } 287*0b57cec5SDimitry Andric } while (Tok.isNot(tok::annot_pragma_openmp_end)); 288*0b57cec5SDimitry Andric 289*0b57cec5SDimitry Andric if (ReductionTypes.empty()) { 290*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 291*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 292*0b57cec5SDimitry Andric } 293*0b57cec5SDimitry Andric 294*0b57cec5SDimitry Andric if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 295*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric // Consume ':'. 298*0b57cec5SDimitry Andric if (ExpectAndConsume(tok::colon)) 299*0b57cec5SDimitry Andric IsCorrect = false; 300*0b57cec5SDimitry Andric 301*0b57cec5SDimitry Andric if (Tok.is(tok::annot_pragma_openmp_end)) { 302*0b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected_expression); 303*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 304*0b57cec5SDimitry Andric } 305*0b57cec5SDimitry Andric 306*0b57cec5SDimitry Andric DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart( 307*0b57cec5SDimitry Andric getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS); 308*0b57cec5SDimitry Andric 309*0b57cec5SDimitry Andric // Parse <combiner> expression and then parse initializer if any for each 310*0b57cec5SDimitry Andric // correct type. 311*0b57cec5SDimitry Andric unsigned I = 0, E = ReductionTypes.size(); 312*0b57cec5SDimitry Andric for (Decl *D : DRD.get()) { 313*0b57cec5SDimitry Andric TentativeParsingAction TPA(*this); 314*0b57cec5SDimitry Andric ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 315*0b57cec5SDimitry Andric Scope::CompoundStmtScope | 316*0b57cec5SDimitry Andric Scope::OpenMPDirectiveScope); 317*0b57cec5SDimitry Andric // Parse <combiner> expression. 318*0b57cec5SDimitry Andric Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); 319*0b57cec5SDimitry Andric ExprResult CombinerResult = 320*0b57cec5SDimitry Andric Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), 321*0b57cec5SDimitry Andric D->getLocation(), /*DiscardedValue*/ false); 322*0b57cec5SDimitry Andric Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); 323*0b57cec5SDimitry Andric 324*0b57cec5SDimitry Andric if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && 325*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) { 326*0b57cec5SDimitry Andric TPA.Commit(); 327*0b57cec5SDimitry Andric IsCorrect = false; 328*0b57cec5SDimitry Andric break; 329*0b57cec5SDimitry Andric } 330*0b57cec5SDimitry Andric IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable(); 331*0b57cec5SDimitry Andric ExprResult InitializerResult; 332*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 333*0b57cec5SDimitry Andric // Parse <initializer> expression. 334*0b57cec5SDimitry Andric if (Tok.is(tok::identifier) && 335*0b57cec5SDimitry Andric Tok.getIdentifierInfo()->isStr("initializer")) { 336*0b57cec5SDimitry Andric ConsumeToken(); 337*0b57cec5SDimitry Andric } else { 338*0b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; 339*0b57cec5SDimitry Andric TPA.Commit(); 340*0b57cec5SDimitry Andric IsCorrect = false; 341*0b57cec5SDimitry Andric break; 342*0b57cec5SDimitry Andric } 343*0b57cec5SDimitry Andric // Parse '('. 344*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, 345*0b57cec5SDimitry Andric tok::annot_pragma_openmp_end); 346*0b57cec5SDimitry Andric IsCorrect = 347*0b57cec5SDimitry Andric !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && 348*0b57cec5SDimitry Andric IsCorrect; 349*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 350*0b57cec5SDimitry Andric ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 351*0b57cec5SDimitry Andric Scope::CompoundStmtScope | 352*0b57cec5SDimitry Andric Scope::OpenMPDirectiveScope); 353*0b57cec5SDimitry Andric // Parse expression. 354*0b57cec5SDimitry Andric VarDecl *OmpPrivParm = 355*0b57cec5SDimitry Andric Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), 356*0b57cec5SDimitry Andric D); 357*0b57cec5SDimitry Andric // Check if initializer is omp_priv <init_expr> or something else. 358*0b57cec5SDimitry Andric if (Tok.is(tok::identifier) && 359*0b57cec5SDimitry Andric Tok.getIdentifierInfo()->isStr("omp_priv")) { 360*0b57cec5SDimitry Andric if (Actions.getLangOpts().CPlusPlus) { 361*0b57cec5SDimitry Andric InitializerResult = Actions.ActOnFinishFullExpr( 362*0b57cec5SDimitry Andric ParseAssignmentExpression().get(), D->getLocation(), 363*0b57cec5SDimitry Andric /*DiscardedValue*/ false); 364*0b57cec5SDimitry Andric } else { 365*0b57cec5SDimitry Andric ConsumeToken(); 366*0b57cec5SDimitry Andric ParseOpenMPReductionInitializerForDecl(OmpPrivParm); 367*0b57cec5SDimitry Andric } 368*0b57cec5SDimitry Andric } else { 369*0b57cec5SDimitry Andric InitializerResult = Actions.ActOnFinishFullExpr( 370*0b57cec5SDimitry Andric ParseAssignmentExpression().get(), D->getLocation(), 371*0b57cec5SDimitry Andric /*DiscardedValue*/ false); 372*0b57cec5SDimitry Andric } 373*0b57cec5SDimitry Andric Actions.ActOnOpenMPDeclareReductionInitializerEnd( 374*0b57cec5SDimitry Andric D, InitializerResult.get(), OmpPrivParm); 375*0b57cec5SDimitry Andric if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && 376*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) { 377*0b57cec5SDimitry Andric TPA.Commit(); 378*0b57cec5SDimitry Andric IsCorrect = false; 379*0b57cec5SDimitry Andric break; 380*0b57cec5SDimitry Andric } 381*0b57cec5SDimitry Andric IsCorrect = 382*0b57cec5SDimitry Andric !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid(); 383*0b57cec5SDimitry Andric } 384*0b57cec5SDimitry Andric } 385*0b57cec5SDimitry Andric 386*0b57cec5SDimitry Andric ++I; 387*0b57cec5SDimitry Andric // Revert parsing if not the last type, otherwise accept it, we're done with 388*0b57cec5SDimitry Andric // parsing. 389*0b57cec5SDimitry Andric if (I != E) 390*0b57cec5SDimitry Andric TPA.Revert(); 391*0b57cec5SDimitry Andric else 392*0b57cec5SDimitry Andric TPA.Commit(); 393*0b57cec5SDimitry Andric } 394*0b57cec5SDimitry Andric return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD, 395*0b57cec5SDimitry Andric IsCorrect); 396*0b57cec5SDimitry Andric } 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { 399*0b57cec5SDimitry Andric // Parse declarator '=' initializer. 400*0b57cec5SDimitry Andric // If a '==' or '+=' is found, suggest a fixit to '='. 401*0b57cec5SDimitry Andric if (isTokenEqualOrEqualTypo()) { 402*0b57cec5SDimitry Andric ConsumeToken(); 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 405*0b57cec5SDimitry Andric Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); 406*0b57cec5SDimitry Andric Actions.FinalizeDeclaration(OmpPrivParm); 407*0b57cec5SDimitry Andric cutOffParsing(); 408*0b57cec5SDimitry Andric return; 409*0b57cec5SDimitry Andric } 410*0b57cec5SDimitry Andric 411*0b57cec5SDimitry Andric ExprResult Init(ParseInitializer()); 412*0b57cec5SDimitry Andric 413*0b57cec5SDimitry Andric if (Init.isInvalid()) { 414*0b57cec5SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 415*0b57cec5SDimitry Andric Actions.ActOnInitializerError(OmpPrivParm); 416*0b57cec5SDimitry Andric } else { 417*0b57cec5SDimitry Andric Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 418*0b57cec5SDimitry Andric /*DirectInit=*/false); 419*0b57cec5SDimitry Andric } 420*0b57cec5SDimitry Andric } else if (Tok.is(tok::l_paren)) { 421*0b57cec5SDimitry Andric // Parse C++ direct initializer: '(' expression-list ')' 422*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 423*0b57cec5SDimitry Andric T.consumeOpen(); 424*0b57cec5SDimitry Andric 425*0b57cec5SDimitry Andric ExprVector Exprs; 426*0b57cec5SDimitry Andric CommaLocsTy CommaLocs; 427*0b57cec5SDimitry Andric 428*0b57cec5SDimitry Andric SourceLocation LParLoc = T.getOpenLocation(); 429*0b57cec5SDimitry Andric auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() { 430*0b57cec5SDimitry Andric QualType PreferredType = Actions.ProduceConstructorSignatureHelp( 431*0b57cec5SDimitry Andric getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), 432*0b57cec5SDimitry Andric OmpPrivParm->getLocation(), Exprs, LParLoc); 433*0b57cec5SDimitry Andric CalledSignatureHelp = true; 434*0b57cec5SDimitry Andric return PreferredType; 435*0b57cec5SDimitry Andric }; 436*0b57cec5SDimitry Andric if (ParseExpressionList(Exprs, CommaLocs, [&] { 437*0b57cec5SDimitry Andric PreferredType.enterFunctionArgument(Tok.getLocation(), 438*0b57cec5SDimitry Andric RunSignatureHelp); 439*0b57cec5SDimitry Andric })) { 440*0b57cec5SDimitry Andric if (PP.isCodeCompletionReached() && !CalledSignatureHelp) 441*0b57cec5SDimitry Andric RunSignatureHelp(); 442*0b57cec5SDimitry Andric Actions.ActOnInitializerError(OmpPrivParm); 443*0b57cec5SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 444*0b57cec5SDimitry Andric } else { 445*0b57cec5SDimitry Andric // Match the ')'. 446*0b57cec5SDimitry Andric SourceLocation RLoc = Tok.getLocation(); 447*0b57cec5SDimitry Andric if (!T.consumeClose()) 448*0b57cec5SDimitry Andric RLoc = T.getCloseLocation(); 449*0b57cec5SDimitry Andric 450*0b57cec5SDimitry Andric assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && 451*0b57cec5SDimitry Andric "Unexpected number of commas!"); 452*0b57cec5SDimitry Andric 453*0b57cec5SDimitry Andric ExprResult Initializer = 454*0b57cec5SDimitry Andric Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs); 455*0b57cec5SDimitry Andric Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), 456*0b57cec5SDimitry Andric /*DirectInit=*/true); 457*0b57cec5SDimitry Andric } 458*0b57cec5SDimitry Andric } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 459*0b57cec5SDimitry Andric // Parse C++0x braced-init-list. 460*0b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 461*0b57cec5SDimitry Andric 462*0b57cec5SDimitry Andric ExprResult Init(ParseBraceInitializer()); 463*0b57cec5SDimitry Andric 464*0b57cec5SDimitry Andric if (Init.isInvalid()) { 465*0b57cec5SDimitry Andric Actions.ActOnInitializerError(OmpPrivParm); 466*0b57cec5SDimitry Andric } else { 467*0b57cec5SDimitry Andric Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 468*0b57cec5SDimitry Andric /*DirectInit=*/true); 469*0b57cec5SDimitry Andric } 470*0b57cec5SDimitry Andric } else { 471*0b57cec5SDimitry Andric Actions.ActOnUninitializedDecl(OmpPrivParm); 472*0b57cec5SDimitry Andric } 473*0b57cec5SDimitry Andric } 474*0b57cec5SDimitry Andric 475*0b57cec5SDimitry Andric /// Parses 'omp declare mapper' directive. 476*0b57cec5SDimitry Andric /// 477*0b57cec5SDimitry Andric /// declare-mapper-directive: 478*0b57cec5SDimitry Andric /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':'] 479*0b57cec5SDimitry Andric /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 480*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 481*0b57cec5SDimitry Andric /// <mapper-identifier> and <var> are base language identifiers. 482*0b57cec5SDimitry Andric /// 483*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy 484*0b57cec5SDimitry Andric Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) { 485*0b57cec5SDimitry Andric bool IsCorrect = true; 486*0b57cec5SDimitry Andric // Parse '(' 487*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 488*0b57cec5SDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, 489*0b57cec5SDimitry Andric getOpenMPDirectiveName(OMPD_declare_mapper))) { 490*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 491*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 492*0b57cec5SDimitry Andric } 493*0b57cec5SDimitry Andric 494*0b57cec5SDimitry Andric // Parse <mapper-identifier> 495*0b57cec5SDimitry Andric auto &DeclNames = Actions.getASTContext().DeclarationNames; 496*0b57cec5SDimitry Andric DeclarationName MapperId; 497*0b57cec5SDimitry Andric if (PP.LookAhead(0).is(tok::colon)) { 498*0b57cec5SDimitry Andric if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 499*0b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 500*0b57cec5SDimitry Andric IsCorrect = false; 501*0b57cec5SDimitry Andric } else { 502*0b57cec5SDimitry Andric MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo()); 503*0b57cec5SDimitry Andric } 504*0b57cec5SDimitry Andric ConsumeToken(); 505*0b57cec5SDimitry Andric // Consume ':'. 506*0b57cec5SDimitry Andric ExpectAndConsume(tok::colon); 507*0b57cec5SDimitry Andric } else { 508*0b57cec5SDimitry Andric // If no mapper identifier is provided, its name is "default" by default 509*0b57cec5SDimitry Andric MapperId = 510*0b57cec5SDimitry Andric DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default")); 511*0b57cec5SDimitry Andric } 512*0b57cec5SDimitry Andric 513*0b57cec5SDimitry Andric if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 514*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 515*0b57cec5SDimitry Andric 516*0b57cec5SDimitry Andric // Parse <type> <var> 517*0b57cec5SDimitry Andric DeclarationName VName; 518*0b57cec5SDimitry Andric QualType MapperType; 519*0b57cec5SDimitry Andric SourceRange Range; 520*0b57cec5SDimitry Andric TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS); 521*0b57cec5SDimitry Andric if (ParsedType.isUsable()) 522*0b57cec5SDimitry Andric MapperType = 523*0b57cec5SDimitry Andric Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType); 524*0b57cec5SDimitry Andric if (MapperType.isNull()) 525*0b57cec5SDimitry Andric IsCorrect = false; 526*0b57cec5SDimitry Andric if (!IsCorrect) { 527*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 528*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 529*0b57cec5SDimitry Andric } 530*0b57cec5SDimitry Andric 531*0b57cec5SDimitry Andric // Consume ')'. 532*0b57cec5SDimitry Andric IsCorrect &= !T.consumeClose(); 533*0b57cec5SDimitry Andric if (!IsCorrect) { 534*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 535*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 536*0b57cec5SDimitry Andric } 537*0b57cec5SDimitry Andric 538*0b57cec5SDimitry Andric // Enter scope. 539*0b57cec5SDimitry Andric OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart( 540*0b57cec5SDimitry Andric getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType, 541*0b57cec5SDimitry Andric Range.getBegin(), VName, AS); 542*0b57cec5SDimitry Andric DeclarationNameInfo DirName; 543*0b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation(); 544*0b57cec5SDimitry Andric unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 545*0b57cec5SDimitry Andric Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 546*0b57cec5SDimitry Andric ParseScope OMPDirectiveScope(this, ScopeFlags); 547*0b57cec5SDimitry Andric Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc); 548*0b57cec5SDimitry Andric 549*0b57cec5SDimitry Andric // Add the mapper variable declaration. 550*0b57cec5SDimitry Andric Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl( 551*0b57cec5SDimitry Andric DMD, getCurScope(), MapperType, Range.getBegin(), VName); 552*0b57cec5SDimitry Andric 553*0b57cec5SDimitry Andric // Parse map clauses. 554*0b57cec5SDimitry Andric SmallVector<OMPClause *, 6> Clauses; 555*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) { 556*0b57cec5SDimitry Andric OpenMPClauseKind CKind = Tok.isAnnotation() 557*0b57cec5SDimitry Andric ? OMPC_unknown 558*0b57cec5SDimitry Andric : getOpenMPClauseKind(PP.getSpelling(Tok)); 559*0b57cec5SDimitry Andric Actions.StartOpenMPClause(CKind); 560*0b57cec5SDimitry Andric OMPClause *Clause = 561*0b57cec5SDimitry Andric ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0); 562*0b57cec5SDimitry Andric if (Clause) 563*0b57cec5SDimitry Andric Clauses.push_back(Clause); 564*0b57cec5SDimitry Andric else 565*0b57cec5SDimitry Andric IsCorrect = false; 566*0b57cec5SDimitry Andric // Skip ',' if any. 567*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) 568*0b57cec5SDimitry Andric ConsumeToken(); 569*0b57cec5SDimitry Andric Actions.EndOpenMPClause(); 570*0b57cec5SDimitry Andric } 571*0b57cec5SDimitry Andric if (Clauses.empty()) { 572*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_expected_clause) 573*0b57cec5SDimitry Andric << getOpenMPDirectiveName(OMPD_declare_mapper); 574*0b57cec5SDimitry Andric IsCorrect = false; 575*0b57cec5SDimitry Andric } 576*0b57cec5SDimitry Andric 577*0b57cec5SDimitry Andric // Exit scope. 578*0b57cec5SDimitry Andric Actions.EndOpenMPDSABlock(nullptr); 579*0b57cec5SDimitry Andric OMPDirectiveScope.Exit(); 580*0b57cec5SDimitry Andric 581*0b57cec5SDimitry Andric DeclGroupPtrTy DGP = 582*0b57cec5SDimitry Andric Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses); 583*0b57cec5SDimitry Andric if (!IsCorrect) 584*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 585*0b57cec5SDimitry Andric return DGP; 586*0b57cec5SDimitry Andric } 587*0b57cec5SDimitry Andric 588*0b57cec5SDimitry Andric TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range, 589*0b57cec5SDimitry Andric DeclarationName &Name, 590*0b57cec5SDimitry Andric AccessSpecifier AS) { 591*0b57cec5SDimitry Andric // Parse the common declaration-specifiers piece. 592*0b57cec5SDimitry Andric Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier; 593*0b57cec5SDimitry Andric DeclSpec DS(AttrFactory); 594*0b57cec5SDimitry Andric ParseSpecifierQualifierList(DS, AS, DSC); 595*0b57cec5SDimitry Andric 596*0b57cec5SDimitry Andric // Parse the declarator. 597*0b57cec5SDimitry Andric DeclaratorContext Context = DeclaratorContext::PrototypeContext; 598*0b57cec5SDimitry Andric Declarator DeclaratorInfo(DS, Context); 599*0b57cec5SDimitry Andric ParseDeclarator(DeclaratorInfo); 600*0b57cec5SDimitry Andric Range = DeclaratorInfo.getSourceRange(); 601*0b57cec5SDimitry Andric if (DeclaratorInfo.getIdentifier() == nullptr) { 602*0b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator); 603*0b57cec5SDimitry Andric return true; 604*0b57cec5SDimitry Andric } 605*0b57cec5SDimitry Andric Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName(); 606*0b57cec5SDimitry Andric 607*0b57cec5SDimitry Andric return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo); 608*0b57cec5SDimitry Andric } 609*0b57cec5SDimitry Andric 610*0b57cec5SDimitry Andric namespace { 611*0b57cec5SDimitry Andric /// RAII that recreates function context for correct parsing of clauses of 612*0b57cec5SDimitry Andric /// 'declare simd' construct. 613*0b57cec5SDimitry Andric /// OpenMP, 2.8.2 declare simd Construct 614*0b57cec5SDimitry Andric /// The expressions appearing in the clauses of this directive are evaluated in 615*0b57cec5SDimitry Andric /// the scope of the arguments of the function declaration or definition. 616*0b57cec5SDimitry Andric class FNContextRAII final { 617*0b57cec5SDimitry Andric Parser &P; 618*0b57cec5SDimitry Andric Sema::CXXThisScopeRAII *ThisScope; 619*0b57cec5SDimitry Andric Parser::ParseScope *TempScope; 620*0b57cec5SDimitry Andric Parser::ParseScope *FnScope; 621*0b57cec5SDimitry Andric bool HasTemplateScope = false; 622*0b57cec5SDimitry Andric bool HasFunScope = false; 623*0b57cec5SDimitry Andric FNContextRAII() = delete; 624*0b57cec5SDimitry Andric FNContextRAII(const FNContextRAII &) = delete; 625*0b57cec5SDimitry Andric FNContextRAII &operator=(const FNContextRAII &) = delete; 626*0b57cec5SDimitry Andric 627*0b57cec5SDimitry Andric public: 628*0b57cec5SDimitry Andric FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) { 629*0b57cec5SDimitry Andric Decl *D = *Ptr.get().begin(); 630*0b57cec5SDimitry Andric NamedDecl *ND = dyn_cast<NamedDecl>(D); 631*0b57cec5SDimitry Andric RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); 632*0b57cec5SDimitry Andric Sema &Actions = P.getActions(); 633*0b57cec5SDimitry Andric 634*0b57cec5SDimitry Andric // Allow 'this' within late-parsed attributes. 635*0b57cec5SDimitry Andric ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(), 636*0b57cec5SDimitry Andric ND && ND->isCXXInstanceMember()); 637*0b57cec5SDimitry Andric 638*0b57cec5SDimitry Andric // If the Decl is templatized, add template parameters to scope. 639*0b57cec5SDimitry Andric HasTemplateScope = D->isTemplateDecl(); 640*0b57cec5SDimitry Andric TempScope = 641*0b57cec5SDimitry Andric new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope); 642*0b57cec5SDimitry Andric if (HasTemplateScope) 643*0b57cec5SDimitry Andric Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D); 644*0b57cec5SDimitry Andric 645*0b57cec5SDimitry Andric // If the Decl is on a function, add function parameters to the scope. 646*0b57cec5SDimitry Andric HasFunScope = D->isFunctionOrFunctionTemplate(); 647*0b57cec5SDimitry Andric FnScope = new Parser::ParseScope( 648*0b57cec5SDimitry Andric &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope, 649*0b57cec5SDimitry Andric HasFunScope); 650*0b57cec5SDimitry Andric if (HasFunScope) 651*0b57cec5SDimitry Andric Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D); 652*0b57cec5SDimitry Andric } 653*0b57cec5SDimitry Andric ~FNContextRAII() { 654*0b57cec5SDimitry Andric if (HasFunScope) { 655*0b57cec5SDimitry Andric P.getActions().ActOnExitFunctionContext(); 656*0b57cec5SDimitry Andric FnScope->Exit(); // Pop scope, and remove Decls from IdResolver 657*0b57cec5SDimitry Andric } 658*0b57cec5SDimitry Andric if (HasTemplateScope) 659*0b57cec5SDimitry Andric TempScope->Exit(); 660*0b57cec5SDimitry Andric delete FnScope; 661*0b57cec5SDimitry Andric delete TempScope; 662*0b57cec5SDimitry Andric delete ThisScope; 663*0b57cec5SDimitry Andric } 664*0b57cec5SDimitry Andric }; 665*0b57cec5SDimitry Andric } // namespace 666*0b57cec5SDimitry Andric 667*0b57cec5SDimitry Andric /// Parses clauses for 'declare simd' directive. 668*0b57cec5SDimitry Andric /// clause: 669*0b57cec5SDimitry Andric /// 'inbranch' | 'notinbranch' 670*0b57cec5SDimitry Andric /// 'simdlen' '(' <expr> ')' 671*0b57cec5SDimitry Andric /// { 'uniform' '(' <argument_list> ')' } 672*0b57cec5SDimitry Andric /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } 673*0b57cec5SDimitry Andric /// { 'linear '(' <argument_list> [ ':' <step> ] ')' } 674*0b57cec5SDimitry Andric static bool parseDeclareSimdClauses( 675*0b57cec5SDimitry Andric Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, 676*0b57cec5SDimitry Andric SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds, 677*0b57cec5SDimitry Andric SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears, 678*0b57cec5SDimitry Andric SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) { 679*0b57cec5SDimitry Andric SourceRange BSRange; 680*0b57cec5SDimitry Andric const Token &Tok = P.getCurToken(); 681*0b57cec5SDimitry Andric bool IsError = false; 682*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) { 683*0b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) 684*0b57cec5SDimitry Andric break; 685*0b57cec5SDimitry Andric OMPDeclareSimdDeclAttr::BranchStateTy Out; 686*0b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo(); 687*0b57cec5SDimitry Andric StringRef ClauseName = II->getName(); 688*0b57cec5SDimitry Andric // Parse 'inranch|notinbranch' clauses. 689*0b57cec5SDimitry Andric if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { 690*0b57cec5SDimitry Andric if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { 691*0b57cec5SDimitry Andric P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) 692*0b57cec5SDimitry Andric << ClauseName 693*0b57cec5SDimitry Andric << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; 694*0b57cec5SDimitry Andric IsError = true; 695*0b57cec5SDimitry Andric } 696*0b57cec5SDimitry Andric BS = Out; 697*0b57cec5SDimitry Andric BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); 698*0b57cec5SDimitry Andric P.ConsumeToken(); 699*0b57cec5SDimitry Andric } else if (ClauseName.equals("simdlen")) { 700*0b57cec5SDimitry Andric if (SimdLen.isUsable()) { 701*0b57cec5SDimitry Andric P.Diag(Tok, diag::err_omp_more_one_clause) 702*0b57cec5SDimitry Andric << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; 703*0b57cec5SDimitry Andric IsError = true; 704*0b57cec5SDimitry Andric } 705*0b57cec5SDimitry Andric P.ConsumeToken(); 706*0b57cec5SDimitry Andric SourceLocation RLoc; 707*0b57cec5SDimitry Andric SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); 708*0b57cec5SDimitry Andric if (SimdLen.isInvalid()) 709*0b57cec5SDimitry Andric IsError = true; 710*0b57cec5SDimitry Andric } else { 711*0b57cec5SDimitry Andric OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); 712*0b57cec5SDimitry Andric if (CKind == OMPC_uniform || CKind == OMPC_aligned || 713*0b57cec5SDimitry Andric CKind == OMPC_linear) { 714*0b57cec5SDimitry Andric Parser::OpenMPVarListDataTy Data; 715*0b57cec5SDimitry Andric SmallVectorImpl<Expr *> *Vars = &Uniforms; 716*0b57cec5SDimitry Andric if (CKind == OMPC_aligned) 717*0b57cec5SDimitry Andric Vars = &Aligneds; 718*0b57cec5SDimitry Andric else if (CKind == OMPC_linear) 719*0b57cec5SDimitry Andric Vars = &Linears; 720*0b57cec5SDimitry Andric 721*0b57cec5SDimitry Andric P.ConsumeToken(); 722*0b57cec5SDimitry Andric if (P.ParseOpenMPVarList(OMPD_declare_simd, 723*0b57cec5SDimitry Andric getOpenMPClauseKind(ClauseName), *Vars, Data)) 724*0b57cec5SDimitry Andric IsError = true; 725*0b57cec5SDimitry Andric if (CKind == OMPC_aligned) { 726*0b57cec5SDimitry Andric Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr); 727*0b57cec5SDimitry Andric } else if (CKind == OMPC_linear) { 728*0b57cec5SDimitry Andric if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind, 729*0b57cec5SDimitry Andric Data.DepLinMapLoc)) 730*0b57cec5SDimitry Andric Data.LinKind = OMPC_LINEAR_val; 731*0b57cec5SDimitry Andric LinModifiers.append(Linears.size() - LinModifiers.size(), 732*0b57cec5SDimitry Andric Data.LinKind); 733*0b57cec5SDimitry Andric Steps.append(Linears.size() - Steps.size(), Data.TailExpr); 734*0b57cec5SDimitry Andric } 735*0b57cec5SDimitry Andric } else 736*0b57cec5SDimitry Andric // TODO: add parsing of other clauses. 737*0b57cec5SDimitry Andric break; 738*0b57cec5SDimitry Andric } 739*0b57cec5SDimitry Andric // Skip ',' if any. 740*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) 741*0b57cec5SDimitry Andric P.ConsumeToken(); 742*0b57cec5SDimitry Andric } 743*0b57cec5SDimitry Andric return IsError; 744*0b57cec5SDimitry Andric } 745*0b57cec5SDimitry Andric 746*0b57cec5SDimitry Andric /// Parse clauses for '#pragma omp declare simd'. 747*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy 748*0b57cec5SDimitry Andric Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, 749*0b57cec5SDimitry Andric CachedTokens &Toks, SourceLocation Loc) { 750*0b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject*/ true); 751*0b57cec5SDimitry Andric PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 752*0b57cec5SDimitry Andric /*IsReinject*/ true); 753*0b57cec5SDimitry Andric // Consume the previously pushed token. 754*0b57cec5SDimitry Andric ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 755*0b57cec5SDimitry Andric 756*0b57cec5SDimitry Andric FNContextRAII FnContext(*this, Ptr); 757*0b57cec5SDimitry Andric OMPDeclareSimdDeclAttr::BranchStateTy BS = 758*0b57cec5SDimitry Andric OMPDeclareSimdDeclAttr::BS_Undefined; 759*0b57cec5SDimitry Andric ExprResult Simdlen; 760*0b57cec5SDimitry Andric SmallVector<Expr *, 4> Uniforms; 761*0b57cec5SDimitry Andric SmallVector<Expr *, 4> Aligneds; 762*0b57cec5SDimitry Andric SmallVector<Expr *, 4> Alignments; 763*0b57cec5SDimitry Andric SmallVector<Expr *, 4> Linears; 764*0b57cec5SDimitry Andric SmallVector<unsigned, 4> LinModifiers; 765*0b57cec5SDimitry Andric SmallVector<Expr *, 4> Steps; 766*0b57cec5SDimitry Andric bool IsError = 767*0b57cec5SDimitry Andric parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, 768*0b57cec5SDimitry Andric Alignments, Linears, LinModifiers, Steps); 769*0b57cec5SDimitry Andric // Need to check for extra tokens. 770*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 771*0b57cec5SDimitry Andric Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 772*0b57cec5SDimitry Andric << getOpenMPDirectiveName(OMPD_declare_simd); 773*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) 774*0b57cec5SDimitry Andric ConsumeAnyToken(); 775*0b57cec5SDimitry Andric } 776*0b57cec5SDimitry Andric // Skip the last annot_pragma_openmp_end. 777*0b57cec5SDimitry Andric SourceLocation EndLoc = ConsumeAnnotationToken(); 778*0b57cec5SDimitry Andric if (IsError) 779*0b57cec5SDimitry Andric return Ptr; 780*0b57cec5SDimitry Andric return Actions.ActOnOpenMPDeclareSimdDirective( 781*0b57cec5SDimitry Andric Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, 782*0b57cec5SDimitry Andric LinModifiers, Steps, SourceRange(Loc, EndLoc)); 783*0b57cec5SDimitry Andric } 784*0b57cec5SDimitry Andric 785*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() { 786*0b57cec5SDimitry Andric // OpenMP 4.5 syntax with list of entities. 787*0b57cec5SDimitry Andric Sema::NamedDeclSetType SameDirectiveDecls; 788*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) { 789*0b57cec5SDimitry Andric OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; 790*0b57cec5SDimitry Andric if (Tok.is(tok::identifier)) { 791*0b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo(); 792*0b57cec5SDimitry Andric StringRef ClauseName = II->getName(); 793*0b57cec5SDimitry Andric // Parse 'to|link' clauses. 794*0b57cec5SDimitry Andric if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) { 795*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName; 796*0b57cec5SDimitry Andric break; 797*0b57cec5SDimitry Andric } 798*0b57cec5SDimitry Andric ConsumeToken(); 799*0b57cec5SDimitry Andric } 800*0b57cec5SDimitry Andric auto &&Callback = [this, MT, &SameDirectiveDecls]( 801*0b57cec5SDimitry Andric CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 802*0b57cec5SDimitry Andric Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, 803*0b57cec5SDimitry Andric SameDirectiveDecls); 804*0b57cec5SDimitry Andric }; 805*0b57cec5SDimitry Andric if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 806*0b57cec5SDimitry Andric /*AllowScopeSpecifier=*/true)) 807*0b57cec5SDimitry Andric break; 808*0b57cec5SDimitry Andric 809*0b57cec5SDimitry Andric // Consume optional ','. 810*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) 811*0b57cec5SDimitry Andric ConsumeToken(); 812*0b57cec5SDimitry Andric } 813*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 814*0b57cec5SDimitry Andric ConsumeAnyToken(); 815*0b57cec5SDimitry Andric SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), 816*0b57cec5SDimitry Andric SameDirectiveDecls.end()); 817*0b57cec5SDimitry Andric if (Decls.empty()) 818*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 819*0b57cec5SDimitry Andric return Actions.BuildDeclaratorGroup(Decls); 820*0b57cec5SDimitry Andric } 821*0b57cec5SDimitry Andric 822*0b57cec5SDimitry Andric void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, 823*0b57cec5SDimitry Andric SourceLocation DTLoc) { 824*0b57cec5SDimitry Andric if (DKind != OMPD_end_declare_target) { 825*0b57cec5SDimitry Andric Diag(Tok, diag::err_expected_end_declare_target); 826*0b57cec5SDimitry Andric Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'"; 827*0b57cec5SDimitry Andric return; 828*0b57cec5SDimitry Andric } 829*0b57cec5SDimitry Andric ConsumeAnyToken(); 830*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 831*0b57cec5SDimitry Andric Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 832*0b57cec5SDimitry Andric << getOpenMPDirectiveName(OMPD_end_declare_target); 833*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 834*0b57cec5SDimitry Andric } 835*0b57cec5SDimitry Andric // Skip the last annot_pragma_openmp_end. 836*0b57cec5SDimitry Andric ConsumeAnyToken(); 837*0b57cec5SDimitry Andric } 838*0b57cec5SDimitry Andric 839*0b57cec5SDimitry Andric /// Parsing of declarative OpenMP directives. 840*0b57cec5SDimitry Andric /// 841*0b57cec5SDimitry Andric /// threadprivate-directive: 842*0b57cec5SDimitry Andric /// annot_pragma_openmp 'threadprivate' simple-variable-list 843*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 844*0b57cec5SDimitry Andric /// 845*0b57cec5SDimitry Andric /// allocate-directive: 846*0b57cec5SDimitry Andric /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>] 847*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 848*0b57cec5SDimitry Andric /// 849*0b57cec5SDimitry Andric /// declare-reduction-directive: 850*0b57cec5SDimitry Andric /// annot_pragma_openmp 'declare' 'reduction' [...] 851*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 852*0b57cec5SDimitry Andric /// 853*0b57cec5SDimitry Andric /// declare-mapper-directive: 854*0b57cec5SDimitry Andric /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 855*0b57cec5SDimitry Andric /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 856*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 857*0b57cec5SDimitry Andric /// 858*0b57cec5SDimitry Andric /// declare-simd-directive: 859*0b57cec5SDimitry Andric /// annot_pragma_openmp 'declare simd' {<clause> [,]} 860*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 861*0b57cec5SDimitry Andric /// <function declaration/definition> 862*0b57cec5SDimitry Andric /// 863*0b57cec5SDimitry Andric /// requires directive: 864*0b57cec5SDimitry Andric /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 865*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 866*0b57cec5SDimitry Andric /// 867*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 868*0b57cec5SDimitry Andric AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, 869*0b57cec5SDimitry Andric DeclSpec::TST TagType, Decl *Tag) { 870*0b57cec5SDimitry Andric assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 871*0b57cec5SDimitry Andric ParenBraceBracketBalancer BalancerRAIIObj(*this); 872*0b57cec5SDimitry Andric 873*0b57cec5SDimitry Andric SourceLocation Loc = ConsumeAnnotationToken(); 874*0b57cec5SDimitry Andric OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 875*0b57cec5SDimitry Andric 876*0b57cec5SDimitry Andric switch (DKind) { 877*0b57cec5SDimitry Andric case OMPD_threadprivate: { 878*0b57cec5SDimitry Andric ConsumeToken(); 879*0b57cec5SDimitry Andric DeclDirectiveListParserHelper Helper(this, DKind); 880*0b57cec5SDimitry Andric if (!ParseOpenMPSimpleVarList(DKind, Helper, 881*0b57cec5SDimitry Andric /*AllowScopeSpecifier=*/true)) { 882*0b57cec5SDimitry Andric // The last seen token is annot_pragma_openmp_end - need to check for 883*0b57cec5SDimitry Andric // extra tokens. 884*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 885*0b57cec5SDimitry Andric Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 886*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind); 887*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 888*0b57cec5SDimitry Andric } 889*0b57cec5SDimitry Andric // Skip the last annot_pragma_openmp_end. 890*0b57cec5SDimitry Andric ConsumeAnnotationToken(); 891*0b57cec5SDimitry Andric return Actions.ActOnOpenMPThreadprivateDirective(Loc, 892*0b57cec5SDimitry Andric Helper.getIdentifiers()); 893*0b57cec5SDimitry Andric } 894*0b57cec5SDimitry Andric break; 895*0b57cec5SDimitry Andric } 896*0b57cec5SDimitry Andric case OMPD_allocate: { 897*0b57cec5SDimitry Andric ConsumeToken(); 898*0b57cec5SDimitry Andric DeclDirectiveListParserHelper Helper(this, DKind); 899*0b57cec5SDimitry Andric if (!ParseOpenMPSimpleVarList(DKind, Helper, 900*0b57cec5SDimitry Andric /*AllowScopeSpecifier=*/true)) { 901*0b57cec5SDimitry Andric SmallVector<OMPClause *, 1> Clauses; 902*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 903*0b57cec5SDimitry Andric SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 904*0b57cec5SDimitry Andric OMPC_unknown + 1> 905*0b57cec5SDimitry Andric FirstClauses(OMPC_unknown + 1); 906*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) { 907*0b57cec5SDimitry Andric OpenMPClauseKind CKind = 908*0b57cec5SDimitry Andric Tok.isAnnotation() ? OMPC_unknown 909*0b57cec5SDimitry Andric : getOpenMPClauseKind(PP.getSpelling(Tok)); 910*0b57cec5SDimitry Andric Actions.StartOpenMPClause(CKind); 911*0b57cec5SDimitry Andric OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind, 912*0b57cec5SDimitry Andric !FirstClauses[CKind].getInt()); 913*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 914*0b57cec5SDimitry Andric StopBeforeMatch); 915*0b57cec5SDimitry Andric FirstClauses[CKind].setInt(true); 916*0b57cec5SDimitry Andric if (Clause != nullptr) 917*0b57cec5SDimitry Andric Clauses.push_back(Clause); 918*0b57cec5SDimitry Andric if (Tok.is(tok::annot_pragma_openmp_end)) { 919*0b57cec5SDimitry Andric Actions.EndOpenMPClause(); 920*0b57cec5SDimitry Andric break; 921*0b57cec5SDimitry Andric } 922*0b57cec5SDimitry Andric // Skip ',' if any. 923*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) 924*0b57cec5SDimitry Andric ConsumeToken(); 925*0b57cec5SDimitry Andric Actions.EndOpenMPClause(); 926*0b57cec5SDimitry Andric } 927*0b57cec5SDimitry Andric // The last seen token is annot_pragma_openmp_end - need to check for 928*0b57cec5SDimitry Andric // extra tokens. 929*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 930*0b57cec5SDimitry Andric Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 931*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind); 932*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 933*0b57cec5SDimitry Andric } 934*0b57cec5SDimitry Andric } 935*0b57cec5SDimitry Andric // Skip the last annot_pragma_openmp_end. 936*0b57cec5SDimitry Andric ConsumeAnnotationToken(); 937*0b57cec5SDimitry Andric return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(), 938*0b57cec5SDimitry Andric Clauses); 939*0b57cec5SDimitry Andric } 940*0b57cec5SDimitry Andric break; 941*0b57cec5SDimitry Andric } 942*0b57cec5SDimitry Andric case OMPD_requires: { 943*0b57cec5SDimitry Andric SourceLocation StartLoc = ConsumeToken(); 944*0b57cec5SDimitry Andric SmallVector<OMPClause *, 5> Clauses; 945*0b57cec5SDimitry Andric SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 946*0b57cec5SDimitry Andric FirstClauses(OMPC_unknown + 1); 947*0b57cec5SDimitry Andric if (Tok.is(tok::annot_pragma_openmp_end)) { 948*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_expected_clause) 949*0b57cec5SDimitry Andric << getOpenMPDirectiveName(OMPD_requires); 950*0b57cec5SDimitry Andric break; 951*0b57cec5SDimitry Andric } 952*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) { 953*0b57cec5SDimitry Andric OpenMPClauseKind CKind = Tok.isAnnotation() 954*0b57cec5SDimitry Andric ? OMPC_unknown 955*0b57cec5SDimitry Andric : getOpenMPClauseKind(PP.getSpelling(Tok)); 956*0b57cec5SDimitry Andric Actions.StartOpenMPClause(CKind); 957*0b57cec5SDimitry Andric OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind, 958*0b57cec5SDimitry Andric !FirstClauses[CKind].getInt()); 959*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 960*0b57cec5SDimitry Andric StopBeforeMatch); 961*0b57cec5SDimitry Andric FirstClauses[CKind].setInt(true); 962*0b57cec5SDimitry Andric if (Clause != nullptr) 963*0b57cec5SDimitry Andric Clauses.push_back(Clause); 964*0b57cec5SDimitry Andric if (Tok.is(tok::annot_pragma_openmp_end)) { 965*0b57cec5SDimitry Andric Actions.EndOpenMPClause(); 966*0b57cec5SDimitry Andric break; 967*0b57cec5SDimitry Andric } 968*0b57cec5SDimitry Andric // Skip ',' if any. 969*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) 970*0b57cec5SDimitry Andric ConsumeToken(); 971*0b57cec5SDimitry Andric Actions.EndOpenMPClause(); 972*0b57cec5SDimitry Andric } 973*0b57cec5SDimitry Andric // Consume final annot_pragma_openmp_end 974*0b57cec5SDimitry Andric if (Clauses.size() == 0) { 975*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_expected_clause) 976*0b57cec5SDimitry Andric << getOpenMPDirectiveName(OMPD_requires); 977*0b57cec5SDimitry Andric ConsumeAnnotationToken(); 978*0b57cec5SDimitry Andric return nullptr; 979*0b57cec5SDimitry Andric } 980*0b57cec5SDimitry Andric ConsumeAnnotationToken(); 981*0b57cec5SDimitry Andric return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 982*0b57cec5SDimitry Andric } 983*0b57cec5SDimitry Andric case OMPD_declare_reduction: 984*0b57cec5SDimitry Andric ConsumeToken(); 985*0b57cec5SDimitry Andric if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 986*0b57cec5SDimitry Andric // The last seen token is annot_pragma_openmp_end - need to check for 987*0b57cec5SDimitry Andric // extra tokens. 988*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 989*0b57cec5SDimitry Andric Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 990*0b57cec5SDimitry Andric << getOpenMPDirectiveName(OMPD_declare_reduction); 991*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) 992*0b57cec5SDimitry Andric ConsumeAnyToken(); 993*0b57cec5SDimitry Andric } 994*0b57cec5SDimitry Andric // Skip the last annot_pragma_openmp_end. 995*0b57cec5SDimitry Andric ConsumeAnnotationToken(); 996*0b57cec5SDimitry Andric return Res; 997*0b57cec5SDimitry Andric } 998*0b57cec5SDimitry Andric break; 999*0b57cec5SDimitry Andric case OMPD_declare_mapper: { 1000*0b57cec5SDimitry Andric ConsumeToken(); 1001*0b57cec5SDimitry Andric if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) { 1002*0b57cec5SDimitry Andric // Skip the last annot_pragma_openmp_end. 1003*0b57cec5SDimitry Andric ConsumeAnnotationToken(); 1004*0b57cec5SDimitry Andric return Res; 1005*0b57cec5SDimitry Andric } 1006*0b57cec5SDimitry Andric break; 1007*0b57cec5SDimitry Andric } 1008*0b57cec5SDimitry Andric case OMPD_declare_simd: { 1009*0b57cec5SDimitry Andric // The syntax is: 1010*0b57cec5SDimitry Andric // { #pragma omp declare simd } 1011*0b57cec5SDimitry Andric // <function-declaration-or-definition> 1012*0b57cec5SDimitry Andric // 1013*0b57cec5SDimitry Andric ConsumeToken(); 1014*0b57cec5SDimitry Andric CachedTokens Toks; 1015*0b57cec5SDimitry Andric while(Tok.isNot(tok::annot_pragma_openmp_end)) { 1016*0b57cec5SDimitry Andric Toks.push_back(Tok); 1017*0b57cec5SDimitry Andric ConsumeAnyToken(); 1018*0b57cec5SDimitry Andric } 1019*0b57cec5SDimitry Andric Toks.push_back(Tok); 1020*0b57cec5SDimitry Andric ConsumeAnyToken(); 1021*0b57cec5SDimitry Andric 1022*0b57cec5SDimitry Andric DeclGroupPtrTy Ptr; 1023*0b57cec5SDimitry Andric if (Tok.is(tok::annot_pragma_openmp)) { 1024*0b57cec5SDimitry Andric Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag); 1025*0b57cec5SDimitry Andric } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 1026*0b57cec5SDimitry Andric // Here we expect to see some function declaration. 1027*0b57cec5SDimitry Andric if (AS == AS_none) { 1028*0b57cec5SDimitry Andric assert(TagType == DeclSpec::TST_unspecified); 1029*0b57cec5SDimitry Andric MaybeParseCXX11Attributes(Attrs); 1030*0b57cec5SDimitry Andric ParsingDeclSpec PDS(*this); 1031*0b57cec5SDimitry Andric Ptr = ParseExternalDeclaration(Attrs, &PDS); 1032*0b57cec5SDimitry Andric } else { 1033*0b57cec5SDimitry Andric Ptr = 1034*0b57cec5SDimitry Andric ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1035*0b57cec5SDimitry Andric } 1036*0b57cec5SDimitry Andric } 1037*0b57cec5SDimitry Andric if (!Ptr) { 1038*0b57cec5SDimitry Andric Diag(Loc, diag::err_omp_decl_in_declare_simd); 1039*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 1040*0b57cec5SDimitry Andric } 1041*0b57cec5SDimitry Andric return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 1042*0b57cec5SDimitry Andric } 1043*0b57cec5SDimitry Andric case OMPD_declare_target: { 1044*0b57cec5SDimitry Andric SourceLocation DTLoc = ConsumeAnyToken(); 1045*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1046*0b57cec5SDimitry Andric return ParseOMPDeclareTargetClauses(); 1047*0b57cec5SDimitry Andric } 1048*0b57cec5SDimitry Andric 1049*0b57cec5SDimitry Andric // Skip the last annot_pragma_openmp_end. 1050*0b57cec5SDimitry Andric ConsumeAnyToken(); 1051*0b57cec5SDimitry Andric 1052*0b57cec5SDimitry Andric if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc)) 1053*0b57cec5SDimitry Andric return DeclGroupPtrTy(); 1054*0b57cec5SDimitry Andric 1055*0b57cec5SDimitry Andric llvm::SmallVector<Decl *, 4> Decls; 1056*0b57cec5SDimitry Andric DKind = parseOpenMPDirectiveKind(*this); 1057*0b57cec5SDimitry Andric while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) && 1058*0b57cec5SDimitry Andric Tok.isNot(tok::r_brace)) { 1059*0b57cec5SDimitry Andric DeclGroupPtrTy Ptr; 1060*0b57cec5SDimitry Andric // Here we expect to see some function declaration. 1061*0b57cec5SDimitry Andric if (AS == AS_none) { 1062*0b57cec5SDimitry Andric assert(TagType == DeclSpec::TST_unspecified); 1063*0b57cec5SDimitry Andric MaybeParseCXX11Attributes(Attrs); 1064*0b57cec5SDimitry Andric ParsingDeclSpec PDS(*this); 1065*0b57cec5SDimitry Andric Ptr = ParseExternalDeclaration(Attrs, &PDS); 1066*0b57cec5SDimitry Andric } else { 1067*0b57cec5SDimitry Andric Ptr = 1068*0b57cec5SDimitry Andric ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1069*0b57cec5SDimitry Andric } 1070*0b57cec5SDimitry Andric if (Ptr) { 1071*0b57cec5SDimitry Andric DeclGroupRef Ref = Ptr.get(); 1072*0b57cec5SDimitry Andric Decls.append(Ref.begin(), Ref.end()); 1073*0b57cec5SDimitry Andric } 1074*0b57cec5SDimitry Andric if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { 1075*0b57cec5SDimitry Andric TentativeParsingAction TPA(*this); 1076*0b57cec5SDimitry Andric ConsumeAnnotationToken(); 1077*0b57cec5SDimitry Andric DKind = parseOpenMPDirectiveKind(*this); 1078*0b57cec5SDimitry Andric if (DKind != OMPD_end_declare_target) 1079*0b57cec5SDimitry Andric TPA.Revert(); 1080*0b57cec5SDimitry Andric else 1081*0b57cec5SDimitry Andric TPA.Commit(); 1082*0b57cec5SDimitry Andric } 1083*0b57cec5SDimitry Andric } 1084*0b57cec5SDimitry Andric 1085*0b57cec5SDimitry Andric ParseOMPEndDeclareTargetDirective(DKind, DTLoc); 1086*0b57cec5SDimitry Andric Actions.ActOnFinishOpenMPDeclareTargetDirective(); 1087*0b57cec5SDimitry Andric return Actions.BuildDeclaratorGroup(Decls); 1088*0b57cec5SDimitry Andric } 1089*0b57cec5SDimitry Andric case OMPD_unknown: 1090*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_unknown_directive); 1091*0b57cec5SDimitry Andric break; 1092*0b57cec5SDimitry Andric case OMPD_parallel: 1093*0b57cec5SDimitry Andric case OMPD_simd: 1094*0b57cec5SDimitry Andric case OMPD_task: 1095*0b57cec5SDimitry Andric case OMPD_taskyield: 1096*0b57cec5SDimitry Andric case OMPD_barrier: 1097*0b57cec5SDimitry Andric case OMPD_taskwait: 1098*0b57cec5SDimitry Andric case OMPD_taskgroup: 1099*0b57cec5SDimitry Andric case OMPD_flush: 1100*0b57cec5SDimitry Andric case OMPD_for: 1101*0b57cec5SDimitry Andric case OMPD_for_simd: 1102*0b57cec5SDimitry Andric case OMPD_sections: 1103*0b57cec5SDimitry Andric case OMPD_section: 1104*0b57cec5SDimitry Andric case OMPD_single: 1105*0b57cec5SDimitry Andric case OMPD_master: 1106*0b57cec5SDimitry Andric case OMPD_ordered: 1107*0b57cec5SDimitry Andric case OMPD_critical: 1108*0b57cec5SDimitry Andric case OMPD_parallel_for: 1109*0b57cec5SDimitry Andric case OMPD_parallel_for_simd: 1110*0b57cec5SDimitry Andric case OMPD_parallel_sections: 1111*0b57cec5SDimitry Andric case OMPD_atomic: 1112*0b57cec5SDimitry Andric case OMPD_target: 1113*0b57cec5SDimitry Andric case OMPD_teams: 1114*0b57cec5SDimitry Andric case OMPD_cancellation_point: 1115*0b57cec5SDimitry Andric case OMPD_cancel: 1116*0b57cec5SDimitry Andric case OMPD_target_data: 1117*0b57cec5SDimitry Andric case OMPD_target_enter_data: 1118*0b57cec5SDimitry Andric case OMPD_target_exit_data: 1119*0b57cec5SDimitry Andric case OMPD_target_parallel: 1120*0b57cec5SDimitry Andric case OMPD_target_parallel_for: 1121*0b57cec5SDimitry Andric case OMPD_taskloop: 1122*0b57cec5SDimitry Andric case OMPD_taskloop_simd: 1123*0b57cec5SDimitry Andric case OMPD_distribute: 1124*0b57cec5SDimitry Andric case OMPD_end_declare_target: 1125*0b57cec5SDimitry Andric case OMPD_target_update: 1126*0b57cec5SDimitry Andric case OMPD_distribute_parallel_for: 1127*0b57cec5SDimitry Andric case OMPD_distribute_parallel_for_simd: 1128*0b57cec5SDimitry Andric case OMPD_distribute_simd: 1129*0b57cec5SDimitry Andric case OMPD_target_parallel_for_simd: 1130*0b57cec5SDimitry Andric case OMPD_target_simd: 1131*0b57cec5SDimitry Andric case OMPD_teams_distribute: 1132*0b57cec5SDimitry Andric case OMPD_teams_distribute_simd: 1133*0b57cec5SDimitry Andric case OMPD_teams_distribute_parallel_for_simd: 1134*0b57cec5SDimitry Andric case OMPD_teams_distribute_parallel_for: 1135*0b57cec5SDimitry Andric case OMPD_target_teams: 1136*0b57cec5SDimitry Andric case OMPD_target_teams_distribute: 1137*0b57cec5SDimitry Andric case OMPD_target_teams_distribute_parallel_for: 1138*0b57cec5SDimitry Andric case OMPD_target_teams_distribute_parallel_for_simd: 1139*0b57cec5SDimitry Andric case OMPD_target_teams_distribute_simd: 1140*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_unexpected_directive) 1141*0b57cec5SDimitry Andric << 1 << getOpenMPDirectiveName(DKind); 1142*0b57cec5SDimitry Andric break; 1143*0b57cec5SDimitry Andric } 1144*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) 1145*0b57cec5SDimitry Andric ConsumeAnyToken(); 1146*0b57cec5SDimitry Andric ConsumeAnyToken(); 1147*0b57cec5SDimitry Andric return nullptr; 1148*0b57cec5SDimitry Andric } 1149*0b57cec5SDimitry Andric 1150*0b57cec5SDimitry Andric /// Parsing of declarative or executable OpenMP directives. 1151*0b57cec5SDimitry Andric /// 1152*0b57cec5SDimitry Andric /// threadprivate-directive: 1153*0b57cec5SDimitry Andric /// annot_pragma_openmp 'threadprivate' simple-variable-list 1154*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 1155*0b57cec5SDimitry Andric /// 1156*0b57cec5SDimitry Andric /// allocate-directive: 1157*0b57cec5SDimitry Andric /// annot_pragma_openmp 'allocate' simple-variable-list 1158*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 1159*0b57cec5SDimitry Andric /// 1160*0b57cec5SDimitry Andric /// declare-reduction-directive: 1161*0b57cec5SDimitry Andric /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 1162*0b57cec5SDimitry Andric /// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 1163*0b57cec5SDimitry Andric /// ('omp_priv' '=' <expression>|<function_call>) ')'] 1164*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 1165*0b57cec5SDimitry Andric /// 1166*0b57cec5SDimitry Andric /// declare-mapper-directive: 1167*0b57cec5SDimitry Andric /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 1168*0b57cec5SDimitry Andric /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 1169*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 1170*0b57cec5SDimitry Andric /// 1171*0b57cec5SDimitry Andric /// executable-directive: 1172*0b57cec5SDimitry Andric /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 1173*0b57cec5SDimitry Andric /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 1174*0b57cec5SDimitry Andric /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | 1175*0b57cec5SDimitry Andric /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | 1176*0b57cec5SDimitry Andric /// 'for simd' | 'parallel for simd' | 'target' | 'target data' | 1177*0b57cec5SDimitry Andric /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 1178*0b57cec5SDimitry Andric /// 'distribute' | 'target enter data' | 'target exit data' | 1179*0b57cec5SDimitry Andric /// 'target parallel' | 'target parallel for' | 1180*0b57cec5SDimitry Andric /// 'target update' | 'distribute parallel for' | 1181*0b57cec5SDimitry Andric /// 'distribute paralle for simd' | 'distribute simd' | 1182*0b57cec5SDimitry Andric /// 'target parallel for simd' | 'target simd' | 1183*0b57cec5SDimitry Andric /// 'teams distribute' | 'teams distribute simd' | 1184*0b57cec5SDimitry Andric /// 'teams distribute parallel for simd' | 1185*0b57cec5SDimitry Andric /// 'teams distribute parallel for' | 'target teams' | 1186*0b57cec5SDimitry Andric /// 'target teams distribute' | 1187*0b57cec5SDimitry Andric /// 'target teams distribute parallel for' | 1188*0b57cec5SDimitry Andric /// 'target teams distribute parallel for simd' | 1189*0b57cec5SDimitry Andric /// 'target teams distribute simd' {clause} 1190*0b57cec5SDimitry Andric /// annot_pragma_openmp_end 1191*0b57cec5SDimitry Andric /// 1192*0b57cec5SDimitry Andric StmtResult 1193*0b57cec5SDimitry Andric Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { 1194*0b57cec5SDimitry Andric assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 1195*0b57cec5SDimitry Andric ParenBraceBracketBalancer BalancerRAIIObj(*this); 1196*0b57cec5SDimitry Andric SmallVector<OMPClause *, 5> Clauses; 1197*0b57cec5SDimitry Andric SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 1198*0b57cec5SDimitry Andric FirstClauses(OMPC_unknown + 1); 1199*0b57cec5SDimitry Andric unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 1200*0b57cec5SDimitry Andric Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 1201*0b57cec5SDimitry Andric SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; 1202*0b57cec5SDimitry Andric OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 1203*0b57cec5SDimitry Andric OpenMPDirectiveKind CancelRegion = OMPD_unknown; 1204*0b57cec5SDimitry Andric // Name of critical directive. 1205*0b57cec5SDimitry Andric DeclarationNameInfo DirName; 1206*0b57cec5SDimitry Andric StmtResult Directive = StmtError(); 1207*0b57cec5SDimitry Andric bool HasAssociatedStatement = true; 1208*0b57cec5SDimitry Andric bool FlushHasClause = false; 1209*0b57cec5SDimitry Andric 1210*0b57cec5SDimitry Andric switch (DKind) { 1211*0b57cec5SDimitry Andric case OMPD_threadprivate: { 1212*0b57cec5SDimitry Andric // FIXME: Should this be permitted in C++? 1213*0b57cec5SDimitry Andric if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 1214*0b57cec5SDimitry Andric ParsedStmtContext()) { 1215*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_immediate_directive) 1216*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind) << 0; 1217*0b57cec5SDimitry Andric } 1218*0b57cec5SDimitry Andric ConsumeToken(); 1219*0b57cec5SDimitry Andric DeclDirectiveListParserHelper Helper(this, DKind); 1220*0b57cec5SDimitry Andric if (!ParseOpenMPSimpleVarList(DKind, Helper, 1221*0b57cec5SDimitry Andric /*AllowScopeSpecifier=*/false)) { 1222*0b57cec5SDimitry Andric // The last seen token is annot_pragma_openmp_end - need to check for 1223*0b57cec5SDimitry Andric // extra tokens. 1224*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1225*0b57cec5SDimitry Andric Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1226*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind); 1227*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1228*0b57cec5SDimitry Andric } 1229*0b57cec5SDimitry Andric DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 1230*0b57cec5SDimitry Andric Loc, Helper.getIdentifiers()); 1231*0b57cec5SDimitry Andric Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1232*0b57cec5SDimitry Andric } 1233*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end); 1234*0b57cec5SDimitry Andric break; 1235*0b57cec5SDimitry Andric } 1236*0b57cec5SDimitry Andric case OMPD_allocate: { 1237*0b57cec5SDimitry Andric // FIXME: Should this be permitted in C++? 1238*0b57cec5SDimitry Andric if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 1239*0b57cec5SDimitry Andric ParsedStmtContext()) { 1240*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_immediate_directive) 1241*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind) << 0; 1242*0b57cec5SDimitry Andric } 1243*0b57cec5SDimitry Andric ConsumeToken(); 1244*0b57cec5SDimitry Andric DeclDirectiveListParserHelper Helper(this, DKind); 1245*0b57cec5SDimitry Andric if (!ParseOpenMPSimpleVarList(DKind, Helper, 1246*0b57cec5SDimitry Andric /*AllowScopeSpecifier=*/false)) { 1247*0b57cec5SDimitry Andric SmallVector<OMPClause *, 1> Clauses; 1248*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1249*0b57cec5SDimitry Andric SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1250*0b57cec5SDimitry Andric OMPC_unknown + 1> 1251*0b57cec5SDimitry Andric FirstClauses(OMPC_unknown + 1); 1252*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1253*0b57cec5SDimitry Andric OpenMPClauseKind CKind = 1254*0b57cec5SDimitry Andric Tok.isAnnotation() ? OMPC_unknown 1255*0b57cec5SDimitry Andric : getOpenMPClauseKind(PP.getSpelling(Tok)); 1256*0b57cec5SDimitry Andric Actions.StartOpenMPClause(CKind); 1257*0b57cec5SDimitry Andric OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind, 1258*0b57cec5SDimitry Andric !FirstClauses[CKind].getInt()); 1259*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1260*0b57cec5SDimitry Andric StopBeforeMatch); 1261*0b57cec5SDimitry Andric FirstClauses[CKind].setInt(true); 1262*0b57cec5SDimitry Andric if (Clause != nullptr) 1263*0b57cec5SDimitry Andric Clauses.push_back(Clause); 1264*0b57cec5SDimitry Andric if (Tok.is(tok::annot_pragma_openmp_end)) { 1265*0b57cec5SDimitry Andric Actions.EndOpenMPClause(); 1266*0b57cec5SDimitry Andric break; 1267*0b57cec5SDimitry Andric } 1268*0b57cec5SDimitry Andric // Skip ',' if any. 1269*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) 1270*0b57cec5SDimitry Andric ConsumeToken(); 1271*0b57cec5SDimitry Andric Actions.EndOpenMPClause(); 1272*0b57cec5SDimitry Andric } 1273*0b57cec5SDimitry Andric // The last seen token is annot_pragma_openmp_end - need to check for 1274*0b57cec5SDimitry Andric // extra tokens. 1275*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1276*0b57cec5SDimitry Andric Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1277*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind); 1278*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1279*0b57cec5SDimitry Andric } 1280*0b57cec5SDimitry Andric } 1281*0b57cec5SDimitry Andric DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( 1282*0b57cec5SDimitry Andric Loc, Helper.getIdentifiers(), Clauses); 1283*0b57cec5SDimitry Andric Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1284*0b57cec5SDimitry Andric } 1285*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end); 1286*0b57cec5SDimitry Andric break; 1287*0b57cec5SDimitry Andric } 1288*0b57cec5SDimitry Andric case OMPD_declare_reduction: 1289*0b57cec5SDimitry Andric ConsumeToken(); 1290*0b57cec5SDimitry Andric if (DeclGroupPtrTy Res = 1291*0b57cec5SDimitry Andric ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 1292*0b57cec5SDimitry Andric // The last seen token is annot_pragma_openmp_end - need to check for 1293*0b57cec5SDimitry Andric // extra tokens. 1294*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1295*0b57cec5SDimitry Andric Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1296*0b57cec5SDimitry Andric << getOpenMPDirectiveName(OMPD_declare_reduction); 1297*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) 1298*0b57cec5SDimitry Andric ConsumeAnyToken(); 1299*0b57cec5SDimitry Andric } 1300*0b57cec5SDimitry Andric ConsumeAnyToken(); 1301*0b57cec5SDimitry Andric Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1302*0b57cec5SDimitry Andric } else { 1303*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end); 1304*0b57cec5SDimitry Andric } 1305*0b57cec5SDimitry Andric break; 1306*0b57cec5SDimitry Andric case OMPD_declare_mapper: { 1307*0b57cec5SDimitry Andric ConsumeToken(); 1308*0b57cec5SDimitry Andric if (DeclGroupPtrTy Res = 1309*0b57cec5SDimitry Andric ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 1310*0b57cec5SDimitry Andric // Skip the last annot_pragma_openmp_end. 1311*0b57cec5SDimitry Andric ConsumeAnnotationToken(); 1312*0b57cec5SDimitry Andric Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1313*0b57cec5SDimitry Andric } else { 1314*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end); 1315*0b57cec5SDimitry Andric } 1316*0b57cec5SDimitry Andric break; 1317*0b57cec5SDimitry Andric } 1318*0b57cec5SDimitry Andric case OMPD_flush: 1319*0b57cec5SDimitry Andric if (PP.LookAhead(0).is(tok::l_paren)) { 1320*0b57cec5SDimitry Andric FlushHasClause = true; 1321*0b57cec5SDimitry Andric // Push copy of the current token back to stream to properly parse 1322*0b57cec5SDimitry Andric // pseudo-clause OMPFlushClause. 1323*0b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject*/ true); 1324*0b57cec5SDimitry Andric } 1325*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 1326*0b57cec5SDimitry Andric case OMPD_taskyield: 1327*0b57cec5SDimitry Andric case OMPD_barrier: 1328*0b57cec5SDimitry Andric case OMPD_taskwait: 1329*0b57cec5SDimitry Andric case OMPD_cancellation_point: 1330*0b57cec5SDimitry Andric case OMPD_cancel: 1331*0b57cec5SDimitry Andric case OMPD_target_enter_data: 1332*0b57cec5SDimitry Andric case OMPD_target_exit_data: 1333*0b57cec5SDimitry Andric case OMPD_target_update: 1334*0b57cec5SDimitry Andric if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 1335*0b57cec5SDimitry Andric ParsedStmtContext()) { 1336*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_immediate_directive) 1337*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind) << 0; 1338*0b57cec5SDimitry Andric } 1339*0b57cec5SDimitry Andric HasAssociatedStatement = false; 1340*0b57cec5SDimitry Andric // Fall through for further analysis. 1341*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 1342*0b57cec5SDimitry Andric case OMPD_parallel: 1343*0b57cec5SDimitry Andric case OMPD_simd: 1344*0b57cec5SDimitry Andric case OMPD_for: 1345*0b57cec5SDimitry Andric case OMPD_for_simd: 1346*0b57cec5SDimitry Andric case OMPD_sections: 1347*0b57cec5SDimitry Andric case OMPD_single: 1348*0b57cec5SDimitry Andric case OMPD_section: 1349*0b57cec5SDimitry Andric case OMPD_master: 1350*0b57cec5SDimitry Andric case OMPD_critical: 1351*0b57cec5SDimitry Andric case OMPD_parallel_for: 1352*0b57cec5SDimitry Andric case OMPD_parallel_for_simd: 1353*0b57cec5SDimitry Andric case OMPD_parallel_sections: 1354*0b57cec5SDimitry Andric case OMPD_task: 1355*0b57cec5SDimitry Andric case OMPD_ordered: 1356*0b57cec5SDimitry Andric case OMPD_atomic: 1357*0b57cec5SDimitry Andric case OMPD_target: 1358*0b57cec5SDimitry Andric case OMPD_teams: 1359*0b57cec5SDimitry Andric case OMPD_taskgroup: 1360*0b57cec5SDimitry Andric case OMPD_target_data: 1361*0b57cec5SDimitry Andric case OMPD_target_parallel: 1362*0b57cec5SDimitry Andric case OMPD_target_parallel_for: 1363*0b57cec5SDimitry Andric case OMPD_taskloop: 1364*0b57cec5SDimitry Andric case OMPD_taskloop_simd: 1365*0b57cec5SDimitry Andric case OMPD_distribute: 1366*0b57cec5SDimitry Andric case OMPD_distribute_parallel_for: 1367*0b57cec5SDimitry Andric case OMPD_distribute_parallel_for_simd: 1368*0b57cec5SDimitry Andric case OMPD_distribute_simd: 1369*0b57cec5SDimitry Andric case OMPD_target_parallel_for_simd: 1370*0b57cec5SDimitry Andric case OMPD_target_simd: 1371*0b57cec5SDimitry Andric case OMPD_teams_distribute: 1372*0b57cec5SDimitry Andric case OMPD_teams_distribute_simd: 1373*0b57cec5SDimitry Andric case OMPD_teams_distribute_parallel_for_simd: 1374*0b57cec5SDimitry Andric case OMPD_teams_distribute_parallel_for: 1375*0b57cec5SDimitry Andric case OMPD_target_teams: 1376*0b57cec5SDimitry Andric case OMPD_target_teams_distribute: 1377*0b57cec5SDimitry Andric case OMPD_target_teams_distribute_parallel_for: 1378*0b57cec5SDimitry Andric case OMPD_target_teams_distribute_parallel_for_simd: 1379*0b57cec5SDimitry Andric case OMPD_target_teams_distribute_simd: { 1380*0b57cec5SDimitry Andric ConsumeToken(); 1381*0b57cec5SDimitry Andric // Parse directive name of the 'critical' directive if any. 1382*0b57cec5SDimitry Andric if (DKind == OMPD_critical) { 1383*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, 1384*0b57cec5SDimitry Andric tok::annot_pragma_openmp_end); 1385*0b57cec5SDimitry Andric if (!T.consumeOpen()) { 1386*0b57cec5SDimitry Andric if (Tok.isAnyIdentifier()) { 1387*0b57cec5SDimitry Andric DirName = 1388*0b57cec5SDimitry Andric DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 1389*0b57cec5SDimitry Andric ConsumeAnyToken(); 1390*0b57cec5SDimitry Andric } else { 1391*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_expected_identifier_for_critical); 1392*0b57cec5SDimitry Andric } 1393*0b57cec5SDimitry Andric T.consumeClose(); 1394*0b57cec5SDimitry Andric } 1395*0b57cec5SDimitry Andric } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 1396*0b57cec5SDimitry Andric CancelRegion = parseOpenMPDirectiveKind(*this); 1397*0b57cec5SDimitry Andric if (Tok.isNot(tok::annot_pragma_openmp_end)) 1398*0b57cec5SDimitry Andric ConsumeToken(); 1399*0b57cec5SDimitry Andric } 1400*0b57cec5SDimitry Andric 1401*0b57cec5SDimitry Andric if (isOpenMPLoopDirective(DKind)) 1402*0b57cec5SDimitry Andric ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 1403*0b57cec5SDimitry Andric if (isOpenMPSimdDirective(DKind)) 1404*0b57cec5SDimitry Andric ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 1405*0b57cec5SDimitry Andric ParseScope OMPDirectiveScope(this, ScopeFlags); 1406*0b57cec5SDimitry Andric Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 1407*0b57cec5SDimitry Andric 1408*0b57cec5SDimitry Andric while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1409*0b57cec5SDimitry Andric OpenMPClauseKind CKind = 1410*0b57cec5SDimitry Andric Tok.isAnnotation() 1411*0b57cec5SDimitry Andric ? OMPC_unknown 1412*0b57cec5SDimitry Andric : FlushHasClause ? OMPC_flush 1413*0b57cec5SDimitry Andric : getOpenMPClauseKind(PP.getSpelling(Tok)); 1414*0b57cec5SDimitry Andric Actions.StartOpenMPClause(CKind); 1415*0b57cec5SDimitry Andric FlushHasClause = false; 1416*0b57cec5SDimitry Andric OMPClause *Clause = 1417*0b57cec5SDimitry Andric ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); 1418*0b57cec5SDimitry Andric FirstClauses[CKind].setInt(true); 1419*0b57cec5SDimitry Andric if (Clause) { 1420*0b57cec5SDimitry Andric FirstClauses[CKind].setPointer(Clause); 1421*0b57cec5SDimitry Andric Clauses.push_back(Clause); 1422*0b57cec5SDimitry Andric } 1423*0b57cec5SDimitry Andric 1424*0b57cec5SDimitry Andric // Skip ',' if any. 1425*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) 1426*0b57cec5SDimitry Andric ConsumeToken(); 1427*0b57cec5SDimitry Andric Actions.EndOpenMPClause(); 1428*0b57cec5SDimitry Andric } 1429*0b57cec5SDimitry Andric // End location of the directive. 1430*0b57cec5SDimitry Andric EndLoc = Tok.getLocation(); 1431*0b57cec5SDimitry Andric // Consume final annot_pragma_openmp_end. 1432*0b57cec5SDimitry Andric ConsumeAnnotationToken(); 1433*0b57cec5SDimitry Andric 1434*0b57cec5SDimitry Andric // OpenMP [2.13.8, ordered Construct, Syntax] 1435*0b57cec5SDimitry Andric // If the depend clause is specified, the ordered construct is a stand-alone 1436*0b57cec5SDimitry Andric // directive. 1437*0b57cec5SDimitry Andric if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) { 1438*0b57cec5SDimitry Andric if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 1439*0b57cec5SDimitry Andric ParsedStmtContext()) { 1440*0b57cec5SDimitry Andric Diag(Loc, diag::err_omp_immediate_directive) 1441*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind) << 1 1442*0b57cec5SDimitry Andric << getOpenMPClauseName(OMPC_depend); 1443*0b57cec5SDimitry Andric } 1444*0b57cec5SDimitry Andric HasAssociatedStatement = false; 1445*0b57cec5SDimitry Andric } 1446*0b57cec5SDimitry Andric 1447*0b57cec5SDimitry Andric StmtResult AssociatedStmt; 1448*0b57cec5SDimitry Andric if (HasAssociatedStatement) { 1449*0b57cec5SDimitry Andric // The body is a block scope like in Lambdas and Blocks. 1450*0b57cec5SDimitry Andric Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1451*0b57cec5SDimitry Andric // FIXME: We create a bogus CompoundStmt scope to hold the contents of 1452*0b57cec5SDimitry Andric // the captured region. Code elsewhere assumes that any FunctionScopeInfo 1453*0b57cec5SDimitry Andric // should have at least one compound statement scope within it. 1454*0b57cec5SDimitry Andric AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement()); 1455*0b57cec5SDimitry Andric AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1456*0b57cec5SDimitry Andric } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 1457*0b57cec5SDimitry Andric DKind == OMPD_target_exit_data) { 1458*0b57cec5SDimitry Andric Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1459*0b57cec5SDimitry Andric AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 1460*0b57cec5SDimitry Andric Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 1461*0b57cec5SDimitry Andric /*isStmtExpr=*/false)); 1462*0b57cec5SDimitry Andric AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1463*0b57cec5SDimitry Andric } 1464*0b57cec5SDimitry Andric Directive = Actions.ActOnOpenMPExecutableDirective( 1465*0b57cec5SDimitry Andric DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 1466*0b57cec5SDimitry Andric EndLoc); 1467*0b57cec5SDimitry Andric 1468*0b57cec5SDimitry Andric // Exit scope. 1469*0b57cec5SDimitry Andric Actions.EndOpenMPDSABlock(Directive.get()); 1470*0b57cec5SDimitry Andric OMPDirectiveScope.Exit(); 1471*0b57cec5SDimitry Andric break; 1472*0b57cec5SDimitry Andric } 1473*0b57cec5SDimitry Andric case OMPD_declare_simd: 1474*0b57cec5SDimitry Andric case OMPD_declare_target: 1475*0b57cec5SDimitry Andric case OMPD_end_declare_target: 1476*0b57cec5SDimitry Andric case OMPD_requires: 1477*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_unexpected_directive) 1478*0b57cec5SDimitry Andric << 1 << getOpenMPDirectiveName(DKind); 1479*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end); 1480*0b57cec5SDimitry Andric break; 1481*0b57cec5SDimitry Andric case OMPD_unknown: 1482*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_unknown_directive); 1483*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end); 1484*0b57cec5SDimitry Andric break; 1485*0b57cec5SDimitry Andric } 1486*0b57cec5SDimitry Andric return Directive; 1487*0b57cec5SDimitry Andric } 1488*0b57cec5SDimitry Andric 1489*0b57cec5SDimitry Andric // Parses simple list: 1490*0b57cec5SDimitry Andric // simple-variable-list: 1491*0b57cec5SDimitry Andric // '(' id-expression {, id-expression} ')' 1492*0b57cec5SDimitry Andric // 1493*0b57cec5SDimitry Andric bool Parser::ParseOpenMPSimpleVarList( 1494*0b57cec5SDimitry Andric OpenMPDirectiveKind Kind, 1495*0b57cec5SDimitry Andric const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & 1496*0b57cec5SDimitry Andric Callback, 1497*0b57cec5SDimitry Andric bool AllowScopeSpecifier) { 1498*0b57cec5SDimitry Andric // Parse '('. 1499*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1500*0b57cec5SDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, 1501*0b57cec5SDimitry Andric getOpenMPDirectiveName(Kind))) 1502*0b57cec5SDimitry Andric return true; 1503*0b57cec5SDimitry Andric bool IsCorrect = true; 1504*0b57cec5SDimitry Andric bool NoIdentIsFound = true; 1505*0b57cec5SDimitry Andric 1506*0b57cec5SDimitry Andric // Read tokens while ')' or annot_pragma_openmp_end is not found. 1507*0b57cec5SDimitry Andric while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 1508*0b57cec5SDimitry Andric CXXScopeSpec SS; 1509*0b57cec5SDimitry Andric UnqualifiedId Name; 1510*0b57cec5SDimitry Andric // Read var name. 1511*0b57cec5SDimitry Andric Token PrevTok = Tok; 1512*0b57cec5SDimitry Andric NoIdentIsFound = false; 1513*0b57cec5SDimitry Andric 1514*0b57cec5SDimitry Andric if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 1515*0b57cec5SDimitry Andric ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) { 1516*0b57cec5SDimitry Andric IsCorrect = false; 1517*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1518*0b57cec5SDimitry Andric StopBeforeMatch); 1519*0b57cec5SDimitry Andric } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr, 1520*0b57cec5SDimitry Andric nullptr, Name)) { 1521*0b57cec5SDimitry Andric IsCorrect = false; 1522*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1523*0b57cec5SDimitry Andric StopBeforeMatch); 1524*0b57cec5SDimitry Andric } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 1525*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) { 1526*0b57cec5SDimitry Andric IsCorrect = false; 1527*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1528*0b57cec5SDimitry Andric StopBeforeMatch); 1529*0b57cec5SDimitry Andric Diag(PrevTok.getLocation(), diag::err_expected) 1530*0b57cec5SDimitry Andric << tok::identifier 1531*0b57cec5SDimitry Andric << SourceRange(PrevTok.getLocation(), PrevTokLocation); 1532*0b57cec5SDimitry Andric } else { 1533*0b57cec5SDimitry Andric Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 1534*0b57cec5SDimitry Andric } 1535*0b57cec5SDimitry Andric // Consume ','. 1536*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) { 1537*0b57cec5SDimitry Andric ConsumeToken(); 1538*0b57cec5SDimitry Andric } 1539*0b57cec5SDimitry Andric } 1540*0b57cec5SDimitry Andric 1541*0b57cec5SDimitry Andric if (NoIdentIsFound) { 1542*0b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier; 1543*0b57cec5SDimitry Andric IsCorrect = false; 1544*0b57cec5SDimitry Andric } 1545*0b57cec5SDimitry Andric 1546*0b57cec5SDimitry Andric // Parse ')'. 1547*0b57cec5SDimitry Andric IsCorrect = !T.consumeClose() && IsCorrect; 1548*0b57cec5SDimitry Andric 1549*0b57cec5SDimitry Andric return !IsCorrect; 1550*0b57cec5SDimitry Andric } 1551*0b57cec5SDimitry Andric 1552*0b57cec5SDimitry Andric /// Parsing of OpenMP clauses. 1553*0b57cec5SDimitry Andric /// 1554*0b57cec5SDimitry Andric /// clause: 1555*0b57cec5SDimitry Andric /// if-clause | final-clause | num_threads-clause | safelen-clause | 1556*0b57cec5SDimitry Andric /// default-clause | private-clause | firstprivate-clause | shared-clause 1557*0b57cec5SDimitry Andric /// | linear-clause | aligned-clause | collapse-clause | 1558*0b57cec5SDimitry Andric /// lastprivate-clause | reduction-clause | proc_bind-clause | 1559*0b57cec5SDimitry Andric /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 1560*0b57cec5SDimitry Andric /// mergeable-clause | flush-clause | read-clause | write-clause | 1561*0b57cec5SDimitry Andric /// update-clause | capture-clause | seq_cst-clause | device-clause | 1562*0b57cec5SDimitry Andric /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 1563*0b57cec5SDimitry Andric /// thread_limit-clause | priority-clause | grainsize-clause | 1564*0b57cec5SDimitry Andric /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 1565*0b57cec5SDimitry Andric /// from-clause | is_device_ptr-clause | task_reduction-clause | 1566*0b57cec5SDimitry Andric /// in_reduction-clause | allocator-clause | allocate-clause 1567*0b57cec5SDimitry Andric /// 1568*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 1569*0b57cec5SDimitry Andric OpenMPClauseKind CKind, bool FirstClause) { 1570*0b57cec5SDimitry Andric OMPClause *Clause = nullptr; 1571*0b57cec5SDimitry Andric bool ErrorFound = false; 1572*0b57cec5SDimitry Andric bool WrongDirective = false; 1573*0b57cec5SDimitry Andric // Check if clause is allowed for the given directive. 1574*0b57cec5SDimitry Andric if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { 1575*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 1576*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind); 1577*0b57cec5SDimitry Andric ErrorFound = true; 1578*0b57cec5SDimitry Andric WrongDirective = true; 1579*0b57cec5SDimitry Andric } 1580*0b57cec5SDimitry Andric 1581*0b57cec5SDimitry Andric switch (CKind) { 1582*0b57cec5SDimitry Andric case OMPC_final: 1583*0b57cec5SDimitry Andric case OMPC_num_threads: 1584*0b57cec5SDimitry Andric case OMPC_safelen: 1585*0b57cec5SDimitry Andric case OMPC_simdlen: 1586*0b57cec5SDimitry Andric case OMPC_collapse: 1587*0b57cec5SDimitry Andric case OMPC_ordered: 1588*0b57cec5SDimitry Andric case OMPC_device: 1589*0b57cec5SDimitry Andric case OMPC_num_teams: 1590*0b57cec5SDimitry Andric case OMPC_thread_limit: 1591*0b57cec5SDimitry Andric case OMPC_priority: 1592*0b57cec5SDimitry Andric case OMPC_grainsize: 1593*0b57cec5SDimitry Andric case OMPC_num_tasks: 1594*0b57cec5SDimitry Andric case OMPC_hint: 1595*0b57cec5SDimitry Andric case OMPC_allocator: 1596*0b57cec5SDimitry Andric // OpenMP [2.5, Restrictions] 1597*0b57cec5SDimitry Andric // At most one num_threads clause can appear on the directive. 1598*0b57cec5SDimitry Andric // OpenMP [2.8.1, simd construct, Restrictions] 1599*0b57cec5SDimitry Andric // Only one safelen clause can appear on a simd directive. 1600*0b57cec5SDimitry Andric // Only one simdlen clause can appear on a simd directive. 1601*0b57cec5SDimitry Andric // Only one collapse clause can appear on a simd directive. 1602*0b57cec5SDimitry Andric // OpenMP [2.9.1, target data construct, Restrictions] 1603*0b57cec5SDimitry Andric // At most one device clause can appear on the directive. 1604*0b57cec5SDimitry Andric // OpenMP [2.11.1, task Construct, Restrictions] 1605*0b57cec5SDimitry Andric // At most one if clause can appear on the directive. 1606*0b57cec5SDimitry Andric // At most one final clause can appear on the directive. 1607*0b57cec5SDimitry Andric // OpenMP [teams Construct, Restrictions] 1608*0b57cec5SDimitry Andric // At most one num_teams clause can appear on the directive. 1609*0b57cec5SDimitry Andric // At most one thread_limit clause can appear on the directive. 1610*0b57cec5SDimitry Andric // OpenMP [2.9.1, task Construct, Restrictions] 1611*0b57cec5SDimitry Andric // At most one priority clause can appear on the directive. 1612*0b57cec5SDimitry Andric // OpenMP [2.9.2, taskloop Construct, Restrictions] 1613*0b57cec5SDimitry Andric // At most one grainsize clause can appear on the directive. 1614*0b57cec5SDimitry Andric // OpenMP [2.9.2, taskloop Construct, Restrictions] 1615*0b57cec5SDimitry Andric // At most one num_tasks clause can appear on the directive. 1616*0b57cec5SDimitry Andric // OpenMP [2.11.3, allocate Directive, Restrictions] 1617*0b57cec5SDimitry Andric // At most one allocator clause can appear on the directive. 1618*0b57cec5SDimitry Andric if (!FirstClause) { 1619*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_more_one_clause) 1620*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1621*0b57cec5SDimitry Andric ErrorFound = true; 1622*0b57cec5SDimitry Andric } 1623*0b57cec5SDimitry Andric 1624*0b57cec5SDimitry Andric if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 1625*0b57cec5SDimitry Andric Clause = ParseOpenMPClause(CKind, WrongDirective); 1626*0b57cec5SDimitry Andric else 1627*0b57cec5SDimitry Andric Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 1628*0b57cec5SDimitry Andric break; 1629*0b57cec5SDimitry Andric case OMPC_default: 1630*0b57cec5SDimitry Andric case OMPC_proc_bind: 1631*0b57cec5SDimitry Andric case OMPC_atomic_default_mem_order: 1632*0b57cec5SDimitry Andric // OpenMP [2.14.3.1, Restrictions] 1633*0b57cec5SDimitry Andric // Only a single default clause may be specified on a parallel, task or 1634*0b57cec5SDimitry Andric // teams directive. 1635*0b57cec5SDimitry Andric // OpenMP [2.5, parallel Construct, Restrictions] 1636*0b57cec5SDimitry Andric // At most one proc_bind clause can appear on the directive. 1637*0b57cec5SDimitry Andric // OpenMP [5.0, Requires directive, Restrictions] 1638*0b57cec5SDimitry Andric // At most one atomic_default_mem_order clause can appear 1639*0b57cec5SDimitry Andric // on the directive 1640*0b57cec5SDimitry Andric if (!FirstClause) { 1641*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_more_one_clause) 1642*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1643*0b57cec5SDimitry Andric ErrorFound = true; 1644*0b57cec5SDimitry Andric } 1645*0b57cec5SDimitry Andric 1646*0b57cec5SDimitry Andric Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 1647*0b57cec5SDimitry Andric break; 1648*0b57cec5SDimitry Andric case OMPC_schedule: 1649*0b57cec5SDimitry Andric case OMPC_dist_schedule: 1650*0b57cec5SDimitry Andric case OMPC_defaultmap: 1651*0b57cec5SDimitry Andric // OpenMP [2.7.1, Restrictions, p. 3] 1652*0b57cec5SDimitry Andric // Only one schedule clause can appear on a loop directive. 1653*0b57cec5SDimitry Andric // OpenMP [2.10.4, Restrictions, p. 106] 1654*0b57cec5SDimitry Andric // At most one defaultmap clause can appear on the directive. 1655*0b57cec5SDimitry Andric if (!FirstClause) { 1656*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_more_one_clause) 1657*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1658*0b57cec5SDimitry Andric ErrorFound = true; 1659*0b57cec5SDimitry Andric } 1660*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 1661*0b57cec5SDimitry Andric 1662*0b57cec5SDimitry Andric case OMPC_if: 1663*0b57cec5SDimitry Andric Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective); 1664*0b57cec5SDimitry Andric break; 1665*0b57cec5SDimitry Andric case OMPC_nowait: 1666*0b57cec5SDimitry Andric case OMPC_untied: 1667*0b57cec5SDimitry Andric case OMPC_mergeable: 1668*0b57cec5SDimitry Andric case OMPC_read: 1669*0b57cec5SDimitry Andric case OMPC_write: 1670*0b57cec5SDimitry Andric case OMPC_update: 1671*0b57cec5SDimitry Andric case OMPC_capture: 1672*0b57cec5SDimitry Andric case OMPC_seq_cst: 1673*0b57cec5SDimitry Andric case OMPC_threads: 1674*0b57cec5SDimitry Andric case OMPC_simd: 1675*0b57cec5SDimitry Andric case OMPC_nogroup: 1676*0b57cec5SDimitry Andric case OMPC_unified_address: 1677*0b57cec5SDimitry Andric case OMPC_unified_shared_memory: 1678*0b57cec5SDimitry Andric case OMPC_reverse_offload: 1679*0b57cec5SDimitry Andric case OMPC_dynamic_allocators: 1680*0b57cec5SDimitry Andric // OpenMP [2.7.1, Restrictions, p. 9] 1681*0b57cec5SDimitry Andric // Only one ordered clause can appear on a loop directive. 1682*0b57cec5SDimitry Andric // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 1683*0b57cec5SDimitry Andric // Only one nowait clause can appear on a for directive. 1684*0b57cec5SDimitry Andric // OpenMP [5.0, Requires directive, Restrictions] 1685*0b57cec5SDimitry Andric // Each of the requires clauses can appear at most once on the directive. 1686*0b57cec5SDimitry Andric if (!FirstClause) { 1687*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_more_one_clause) 1688*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1689*0b57cec5SDimitry Andric ErrorFound = true; 1690*0b57cec5SDimitry Andric } 1691*0b57cec5SDimitry Andric 1692*0b57cec5SDimitry Andric Clause = ParseOpenMPClause(CKind, WrongDirective); 1693*0b57cec5SDimitry Andric break; 1694*0b57cec5SDimitry Andric case OMPC_private: 1695*0b57cec5SDimitry Andric case OMPC_firstprivate: 1696*0b57cec5SDimitry Andric case OMPC_lastprivate: 1697*0b57cec5SDimitry Andric case OMPC_shared: 1698*0b57cec5SDimitry Andric case OMPC_reduction: 1699*0b57cec5SDimitry Andric case OMPC_task_reduction: 1700*0b57cec5SDimitry Andric case OMPC_in_reduction: 1701*0b57cec5SDimitry Andric case OMPC_linear: 1702*0b57cec5SDimitry Andric case OMPC_aligned: 1703*0b57cec5SDimitry Andric case OMPC_copyin: 1704*0b57cec5SDimitry Andric case OMPC_copyprivate: 1705*0b57cec5SDimitry Andric case OMPC_flush: 1706*0b57cec5SDimitry Andric case OMPC_depend: 1707*0b57cec5SDimitry Andric case OMPC_map: 1708*0b57cec5SDimitry Andric case OMPC_to: 1709*0b57cec5SDimitry Andric case OMPC_from: 1710*0b57cec5SDimitry Andric case OMPC_use_device_ptr: 1711*0b57cec5SDimitry Andric case OMPC_is_device_ptr: 1712*0b57cec5SDimitry Andric case OMPC_allocate: 1713*0b57cec5SDimitry Andric Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 1714*0b57cec5SDimitry Andric break; 1715*0b57cec5SDimitry Andric case OMPC_unknown: 1716*0b57cec5SDimitry Andric Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1717*0b57cec5SDimitry Andric << getOpenMPDirectiveName(DKind); 1718*0b57cec5SDimitry Andric SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1719*0b57cec5SDimitry Andric break; 1720*0b57cec5SDimitry Andric case OMPC_threadprivate: 1721*0b57cec5SDimitry Andric case OMPC_uniform: 1722*0b57cec5SDimitry Andric if (!WrongDirective) 1723*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_unexpected_clause) 1724*0b57cec5SDimitry Andric << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 1725*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 1726*0b57cec5SDimitry Andric break; 1727*0b57cec5SDimitry Andric } 1728*0b57cec5SDimitry Andric return ErrorFound ? nullptr : Clause; 1729*0b57cec5SDimitry Andric } 1730*0b57cec5SDimitry Andric 1731*0b57cec5SDimitry Andric /// Parses simple expression in parens for single-expression clauses of OpenMP 1732*0b57cec5SDimitry Andric /// constructs. 1733*0b57cec5SDimitry Andric /// \param RLoc Returned location of right paren. 1734*0b57cec5SDimitry Andric ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 1735*0b57cec5SDimitry Andric SourceLocation &RLoc) { 1736*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1737*0b57cec5SDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 1738*0b57cec5SDimitry Andric return ExprError(); 1739*0b57cec5SDimitry Andric 1740*0b57cec5SDimitry Andric SourceLocation ELoc = Tok.getLocation(); 1741*0b57cec5SDimitry Andric ExprResult LHS(ParseCastExpression( 1742*0b57cec5SDimitry Andric /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); 1743*0b57cec5SDimitry Andric ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 1744*0b57cec5SDimitry Andric Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 1745*0b57cec5SDimitry Andric 1746*0b57cec5SDimitry Andric // Parse ')'. 1747*0b57cec5SDimitry Andric RLoc = Tok.getLocation(); 1748*0b57cec5SDimitry Andric if (!T.consumeClose()) 1749*0b57cec5SDimitry Andric RLoc = T.getCloseLocation(); 1750*0b57cec5SDimitry Andric 1751*0b57cec5SDimitry Andric return Val; 1752*0b57cec5SDimitry Andric } 1753*0b57cec5SDimitry Andric 1754*0b57cec5SDimitry Andric /// Parsing of OpenMP clauses with single expressions like 'final', 1755*0b57cec5SDimitry Andric /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 1756*0b57cec5SDimitry Andric /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'. 1757*0b57cec5SDimitry Andric /// 1758*0b57cec5SDimitry Andric /// final-clause: 1759*0b57cec5SDimitry Andric /// 'final' '(' expression ')' 1760*0b57cec5SDimitry Andric /// 1761*0b57cec5SDimitry Andric /// num_threads-clause: 1762*0b57cec5SDimitry Andric /// 'num_threads' '(' expression ')' 1763*0b57cec5SDimitry Andric /// 1764*0b57cec5SDimitry Andric /// safelen-clause: 1765*0b57cec5SDimitry Andric /// 'safelen' '(' expression ')' 1766*0b57cec5SDimitry Andric /// 1767*0b57cec5SDimitry Andric /// simdlen-clause: 1768*0b57cec5SDimitry Andric /// 'simdlen' '(' expression ')' 1769*0b57cec5SDimitry Andric /// 1770*0b57cec5SDimitry Andric /// collapse-clause: 1771*0b57cec5SDimitry Andric /// 'collapse' '(' expression ')' 1772*0b57cec5SDimitry Andric /// 1773*0b57cec5SDimitry Andric /// priority-clause: 1774*0b57cec5SDimitry Andric /// 'priority' '(' expression ')' 1775*0b57cec5SDimitry Andric /// 1776*0b57cec5SDimitry Andric /// grainsize-clause: 1777*0b57cec5SDimitry Andric /// 'grainsize' '(' expression ')' 1778*0b57cec5SDimitry Andric /// 1779*0b57cec5SDimitry Andric /// num_tasks-clause: 1780*0b57cec5SDimitry Andric /// 'num_tasks' '(' expression ')' 1781*0b57cec5SDimitry Andric /// 1782*0b57cec5SDimitry Andric /// hint-clause: 1783*0b57cec5SDimitry Andric /// 'hint' '(' expression ')' 1784*0b57cec5SDimitry Andric /// 1785*0b57cec5SDimitry Andric /// allocator-clause: 1786*0b57cec5SDimitry Andric /// 'allocator' '(' expression ')' 1787*0b57cec5SDimitry Andric /// 1788*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 1789*0b57cec5SDimitry Andric bool ParseOnly) { 1790*0b57cec5SDimitry Andric SourceLocation Loc = ConsumeToken(); 1791*0b57cec5SDimitry Andric SourceLocation LLoc = Tok.getLocation(); 1792*0b57cec5SDimitry Andric SourceLocation RLoc; 1793*0b57cec5SDimitry Andric 1794*0b57cec5SDimitry Andric ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 1795*0b57cec5SDimitry Andric 1796*0b57cec5SDimitry Andric if (Val.isInvalid()) 1797*0b57cec5SDimitry Andric return nullptr; 1798*0b57cec5SDimitry Andric 1799*0b57cec5SDimitry Andric if (ParseOnly) 1800*0b57cec5SDimitry Andric return nullptr; 1801*0b57cec5SDimitry Andric return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 1802*0b57cec5SDimitry Andric } 1803*0b57cec5SDimitry Andric 1804*0b57cec5SDimitry Andric /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1805*0b57cec5SDimitry Andric /// 1806*0b57cec5SDimitry Andric /// default-clause: 1807*0b57cec5SDimitry Andric /// 'default' '(' 'none' | 'shared' ') 1808*0b57cec5SDimitry Andric /// 1809*0b57cec5SDimitry Andric /// proc_bind-clause: 1810*0b57cec5SDimitry Andric /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1811*0b57cec5SDimitry Andric /// 1812*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 1813*0b57cec5SDimitry Andric bool ParseOnly) { 1814*0b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation(); 1815*0b57cec5SDimitry Andric SourceLocation LOpen = ConsumeToken(); 1816*0b57cec5SDimitry Andric // Parse '('. 1817*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1818*0b57cec5SDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, 1819*0b57cec5SDimitry Andric getOpenMPClauseName(Kind))) 1820*0b57cec5SDimitry Andric return nullptr; 1821*0b57cec5SDimitry Andric 1822*0b57cec5SDimitry Andric unsigned Type = getOpenMPSimpleClauseType( 1823*0b57cec5SDimitry Andric Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1824*0b57cec5SDimitry Andric SourceLocation TypeLoc = Tok.getLocation(); 1825*0b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1826*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) 1827*0b57cec5SDimitry Andric ConsumeAnyToken(); 1828*0b57cec5SDimitry Andric 1829*0b57cec5SDimitry Andric // Parse ')'. 1830*0b57cec5SDimitry Andric SourceLocation RLoc = Tok.getLocation(); 1831*0b57cec5SDimitry Andric if (!T.consumeClose()) 1832*0b57cec5SDimitry Andric RLoc = T.getCloseLocation(); 1833*0b57cec5SDimitry Andric 1834*0b57cec5SDimitry Andric if (ParseOnly) 1835*0b57cec5SDimitry Andric return nullptr; 1836*0b57cec5SDimitry Andric return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc); 1837*0b57cec5SDimitry Andric } 1838*0b57cec5SDimitry Andric 1839*0b57cec5SDimitry Andric /// Parsing of OpenMP clauses like 'ordered'. 1840*0b57cec5SDimitry Andric /// 1841*0b57cec5SDimitry Andric /// ordered-clause: 1842*0b57cec5SDimitry Andric /// 'ordered' 1843*0b57cec5SDimitry Andric /// 1844*0b57cec5SDimitry Andric /// nowait-clause: 1845*0b57cec5SDimitry Andric /// 'nowait' 1846*0b57cec5SDimitry Andric /// 1847*0b57cec5SDimitry Andric /// untied-clause: 1848*0b57cec5SDimitry Andric /// 'untied' 1849*0b57cec5SDimitry Andric /// 1850*0b57cec5SDimitry Andric /// mergeable-clause: 1851*0b57cec5SDimitry Andric /// 'mergeable' 1852*0b57cec5SDimitry Andric /// 1853*0b57cec5SDimitry Andric /// read-clause: 1854*0b57cec5SDimitry Andric /// 'read' 1855*0b57cec5SDimitry Andric /// 1856*0b57cec5SDimitry Andric /// threads-clause: 1857*0b57cec5SDimitry Andric /// 'threads' 1858*0b57cec5SDimitry Andric /// 1859*0b57cec5SDimitry Andric /// simd-clause: 1860*0b57cec5SDimitry Andric /// 'simd' 1861*0b57cec5SDimitry Andric /// 1862*0b57cec5SDimitry Andric /// nogroup-clause: 1863*0b57cec5SDimitry Andric /// 'nogroup' 1864*0b57cec5SDimitry Andric /// 1865*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 1866*0b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation(); 1867*0b57cec5SDimitry Andric ConsumeAnyToken(); 1868*0b57cec5SDimitry Andric 1869*0b57cec5SDimitry Andric if (ParseOnly) 1870*0b57cec5SDimitry Andric return nullptr; 1871*0b57cec5SDimitry Andric return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 1872*0b57cec5SDimitry Andric } 1873*0b57cec5SDimitry Andric 1874*0b57cec5SDimitry Andric 1875*0b57cec5SDimitry Andric /// Parsing of OpenMP clauses with single expressions and some additional 1876*0b57cec5SDimitry Andric /// argument like 'schedule' or 'dist_schedule'. 1877*0b57cec5SDimitry Andric /// 1878*0b57cec5SDimitry Andric /// schedule-clause: 1879*0b57cec5SDimitry Andric /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 1880*0b57cec5SDimitry Andric /// ')' 1881*0b57cec5SDimitry Andric /// 1882*0b57cec5SDimitry Andric /// if-clause: 1883*0b57cec5SDimitry Andric /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 1884*0b57cec5SDimitry Andric /// 1885*0b57cec5SDimitry Andric /// defaultmap: 1886*0b57cec5SDimitry Andric /// 'defaultmap' '(' modifier ':' kind ')' 1887*0b57cec5SDimitry Andric /// 1888*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, 1889*0b57cec5SDimitry Andric bool ParseOnly) { 1890*0b57cec5SDimitry Andric SourceLocation Loc = ConsumeToken(); 1891*0b57cec5SDimitry Andric SourceLocation DelimLoc; 1892*0b57cec5SDimitry Andric // Parse '('. 1893*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1894*0b57cec5SDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, 1895*0b57cec5SDimitry Andric getOpenMPClauseName(Kind))) 1896*0b57cec5SDimitry Andric return nullptr; 1897*0b57cec5SDimitry Andric 1898*0b57cec5SDimitry Andric ExprResult Val; 1899*0b57cec5SDimitry Andric SmallVector<unsigned, 4> Arg; 1900*0b57cec5SDimitry Andric SmallVector<SourceLocation, 4> KLoc; 1901*0b57cec5SDimitry Andric if (Kind == OMPC_schedule) { 1902*0b57cec5SDimitry Andric enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 1903*0b57cec5SDimitry Andric Arg.resize(NumberOfElements); 1904*0b57cec5SDimitry Andric KLoc.resize(NumberOfElements); 1905*0b57cec5SDimitry Andric Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 1906*0b57cec5SDimitry Andric Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 1907*0b57cec5SDimitry Andric Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 1908*0b57cec5SDimitry Andric unsigned KindModifier = getOpenMPSimpleClauseType( 1909*0b57cec5SDimitry Andric Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1910*0b57cec5SDimitry Andric if (KindModifier > OMPC_SCHEDULE_unknown) { 1911*0b57cec5SDimitry Andric // Parse 'modifier' 1912*0b57cec5SDimitry Andric Arg[Modifier1] = KindModifier; 1913*0b57cec5SDimitry Andric KLoc[Modifier1] = Tok.getLocation(); 1914*0b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1915*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) 1916*0b57cec5SDimitry Andric ConsumeAnyToken(); 1917*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) { 1918*0b57cec5SDimitry Andric // Parse ',' 'modifier' 1919*0b57cec5SDimitry Andric ConsumeAnyToken(); 1920*0b57cec5SDimitry Andric KindModifier = getOpenMPSimpleClauseType( 1921*0b57cec5SDimitry Andric Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1922*0b57cec5SDimitry Andric Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 1923*0b57cec5SDimitry Andric ? KindModifier 1924*0b57cec5SDimitry Andric : (unsigned)OMPC_SCHEDULE_unknown; 1925*0b57cec5SDimitry Andric KLoc[Modifier2] = Tok.getLocation(); 1926*0b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1927*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) 1928*0b57cec5SDimitry Andric ConsumeAnyToken(); 1929*0b57cec5SDimitry Andric } 1930*0b57cec5SDimitry Andric // Parse ':' 1931*0b57cec5SDimitry Andric if (Tok.is(tok::colon)) 1932*0b57cec5SDimitry Andric ConsumeAnyToken(); 1933*0b57cec5SDimitry Andric else 1934*0b57cec5SDimitry Andric Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 1935*0b57cec5SDimitry Andric KindModifier = getOpenMPSimpleClauseType( 1936*0b57cec5SDimitry Andric Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1937*0b57cec5SDimitry Andric } 1938*0b57cec5SDimitry Andric Arg[ScheduleKind] = KindModifier; 1939*0b57cec5SDimitry Andric KLoc[ScheduleKind] = Tok.getLocation(); 1940*0b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1941*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) 1942*0b57cec5SDimitry Andric ConsumeAnyToken(); 1943*0b57cec5SDimitry Andric if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 1944*0b57cec5SDimitry Andric Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 1945*0b57cec5SDimitry Andric Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 1946*0b57cec5SDimitry Andric Tok.is(tok::comma)) 1947*0b57cec5SDimitry Andric DelimLoc = ConsumeAnyToken(); 1948*0b57cec5SDimitry Andric } else if (Kind == OMPC_dist_schedule) { 1949*0b57cec5SDimitry Andric Arg.push_back(getOpenMPSimpleClauseType( 1950*0b57cec5SDimitry Andric Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1951*0b57cec5SDimitry Andric KLoc.push_back(Tok.getLocation()); 1952*0b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1953*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) 1954*0b57cec5SDimitry Andric ConsumeAnyToken(); 1955*0b57cec5SDimitry Andric if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 1956*0b57cec5SDimitry Andric DelimLoc = ConsumeAnyToken(); 1957*0b57cec5SDimitry Andric } else if (Kind == OMPC_defaultmap) { 1958*0b57cec5SDimitry Andric // Get a defaultmap modifier 1959*0b57cec5SDimitry Andric Arg.push_back(getOpenMPSimpleClauseType( 1960*0b57cec5SDimitry Andric Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1961*0b57cec5SDimitry Andric KLoc.push_back(Tok.getLocation()); 1962*0b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1963*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) 1964*0b57cec5SDimitry Andric ConsumeAnyToken(); 1965*0b57cec5SDimitry Andric // Parse ':' 1966*0b57cec5SDimitry Andric if (Tok.is(tok::colon)) 1967*0b57cec5SDimitry Andric ConsumeAnyToken(); 1968*0b57cec5SDimitry Andric else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 1969*0b57cec5SDimitry Andric Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 1970*0b57cec5SDimitry Andric // Get a defaultmap kind 1971*0b57cec5SDimitry Andric Arg.push_back(getOpenMPSimpleClauseType( 1972*0b57cec5SDimitry Andric Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1973*0b57cec5SDimitry Andric KLoc.push_back(Tok.getLocation()); 1974*0b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1975*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end)) 1976*0b57cec5SDimitry Andric ConsumeAnyToken(); 1977*0b57cec5SDimitry Andric } else { 1978*0b57cec5SDimitry Andric assert(Kind == OMPC_if); 1979*0b57cec5SDimitry Andric KLoc.push_back(Tok.getLocation()); 1980*0b57cec5SDimitry Andric TentativeParsingAction TPA(*this); 1981*0b57cec5SDimitry Andric Arg.push_back(parseOpenMPDirectiveKind(*this)); 1982*0b57cec5SDimitry Andric if (Arg.back() != OMPD_unknown) { 1983*0b57cec5SDimitry Andric ConsumeToken(); 1984*0b57cec5SDimitry Andric if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 1985*0b57cec5SDimitry Andric TPA.Commit(); 1986*0b57cec5SDimitry Andric DelimLoc = ConsumeToken(); 1987*0b57cec5SDimitry Andric } else { 1988*0b57cec5SDimitry Andric TPA.Revert(); 1989*0b57cec5SDimitry Andric Arg.back() = OMPD_unknown; 1990*0b57cec5SDimitry Andric } 1991*0b57cec5SDimitry Andric } else { 1992*0b57cec5SDimitry Andric TPA.Revert(); 1993*0b57cec5SDimitry Andric } 1994*0b57cec5SDimitry Andric } 1995*0b57cec5SDimitry Andric 1996*0b57cec5SDimitry Andric bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 1997*0b57cec5SDimitry Andric (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 1998*0b57cec5SDimitry Andric Kind == OMPC_if; 1999*0b57cec5SDimitry Andric if (NeedAnExpression) { 2000*0b57cec5SDimitry Andric SourceLocation ELoc = Tok.getLocation(); 2001*0b57cec5SDimitry Andric ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); 2002*0b57cec5SDimitry Andric Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 2003*0b57cec5SDimitry Andric Val = 2004*0b57cec5SDimitry Andric Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 2005*0b57cec5SDimitry Andric } 2006*0b57cec5SDimitry Andric 2007*0b57cec5SDimitry Andric // Parse ')'. 2008*0b57cec5SDimitry Andric SourceLocation RLoc = Tok.getLocation(); 2009*0b57cec5SDimitry Andric if (!T.consumeClose()) 2010*0b57cec5SDimitry Andric RLoc = T.getCloseLocation(); 2011*0b57cec5SDimitry Andric 2012*0b57cec5SDimitry Andric if (NeedAnExpression && Val.isInvalid()) 2013*0b57cec5SDimitry Andric return nullptr; 2014*0b57cec5SDimitry Andric 2015*0b57cec5SDimitry Andric if (ParseOnly) 2016*0b57cec5SDimitry Andric return nullptr; 2017*0b57cec5SDimitry Andric return Actions.ActOnOpenMPSingleExprWithArgClause( 2018*0b57cec5SDimitry Andric Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 2019*0b57cec5SDimitry Andric } 2020*0b57cec5SDimitry Andric 2021*0b57cec5SDimitry Andric static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 2022*0b57cec5SDimitry Andric UnqualifiedId &ReductionId) { 2023*0b57cec5SDimitry Andric if (ReductionIdScopeSpec.isEmpty()) { 2024*0b57cec5SDimitry Andric auto OOK = OO_None; 2025*0b57cec5SDimitry Andric switch (P.getCurToken().getKind()) { 2026*0b57cec5SDimitry Andric case tok::plus: 2027*0b57cec5SDimitry Andric OOK = OO_Plus; 2028*0b57cec5SDimitry Andric break; 2029*0b57cec5SDimitry Andric case tok::minus: 2030*0b57cec5SDimitry Andric OOK = OO_Minus; 2031*0b57cec5SDimitry Andric break; 2032*0b57cec5SDimitry Andric case tok::star: 2033*0b57cec5SDimitry Andric OOK = OO_Star; 2034*0b57cec5SDimitry Andric break; 2035*0b57cec5SDimitry Andric case tok::amp: 2036*0b57cec5SDimitry Andric OOK = OO_Amp; 2037*0b57cec5SDimitry Andric break; 2038*0b57cec5SDimitry Andric case tok::pipe: 2039*0b57cec5SDimitry Andric OOK = OO_Pipe; 2040*0b57cec5SDimitry Andric break; 2041*0b57cec5SDimitry Andric case tok::caret: 2042*0b57cec5SDimitry Andric OOK = OO_Caret; 2043*0b57cec5SDimitry Andric break; 2044*0b57cec5SDimitry Andric case tok::ampamp: 2045*0b57cec5SDimitry Andric OOK = OO_AmpAmp; 2046*0b57cec5SDimitry Andric break; 2047*0b57cec5SDimitry Andric case tok::pipepipe: 2048*0b57cec5SDimitry Andric OOK = OO_PipePipe; 2049*0b57cec5SDimitry Andric break; 2050*0b57cec5SDimitry Andric default: 2051*0b57cec5SDimitry Andric break; 2052*0b57cec5SDimitry Andric } 2053*0b57cec5SDimitry Andric if (OOK != OO_None) { 2054*0b57cec5SDimitry Andric SourceLocation OpLoc = P.ConsumeToken(); 2055*0b57cec5SDimitry Andric SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 2056*0b57cec5SDimitry Andric ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 2057*0b57cec5SDimitry Andric return false; 2058*0b57cec5SDimitry Andric } 2059*0b57cec5SDimitry Andric } 2060*0b57cec5SDimitry Andric return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, 2061*0b57cec5SDimitry Andric /*AllowDestructorName*/ false, 2062*0b57cec5SDimitry Andric /*AllowConstructorName*/ false, 2063*0b57cec5SDimitry Andric /*AllowDeductionGuide*/ false, 2064*0b57cec5SDimitry Andric nullptr, nullptr, ReductionId); 2065*0b57cec5SDimitry Andric } 2066*0b57cec5SDimitry Andric 2067*0b57cec5SDimitry Andric /// Checks if the token is a valid map-type-modifier. 2068*0b57cec5SDimitry Andric static OpenMPMapModifierKind isMapModifier(Parser &P) { 2069*0b57cec5SDimitry Andric Token Tok = P.getCurToken(); 2070*0b57cec5SDimitry Andric if (!Tok.is(tok::identifier)) 2071*0b57cec5SDimitry Andric return OMPC_MAP_MODIFIER_unknown; 2072*0b57cec5SDimitry Andric 2073*0b57cec5SDimitry Andric Preprocessor &PP = P.getPreprocessor(); 2074*0b57cec5SDimitry Andric OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>( 2075*0b57cec5SDimitry Andric getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 2076*0b57cec5SDimitry Andric return TypeModifier; 2077*0b57cec5SDimitry Andric } 2078*0b57cec5SDimitry Andric 2079*0b57cec5SDimitry Andric /// Parse the mapper modifier in map, to, and from clauses. 2080*0b57cec5SDimitry Andric bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { 2081*0b57cec5SDimitry Andric // Parse '('. 2082*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 2083*0b57cec5SDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 2084*0b57cec5SDimitry Andric SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2085*0b57cec5SDimitry Andric StopBeforeMatch); 2086*0b57cec5SDimitry Andric return true; 2087*0b57cec5SDimitry Andric } 2088*0b57cec5SDimitry Andric // Parse mapper-identifier 2089*0b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) 2090*0b57cec5SDimitry Andric ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 2091*0b57cec5SDimitry Andric /*ObjectType=*/nullptr, 2092*0b57cec5SDimitry Andric /*EnteringContext=*/false); 2093*0b57cec5SDimitry Andric if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 2094*0b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 2095*0b57cec5SDimitry Andric SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2096*0b57cec5SDimitry Andric StopBeforeMatch); 2097*0b57cec5SDimitry Andric return true; 2098*0b57cec5SDimitry Andric } 2099*0b57cec5SDimitry Andric auto &DeclNames = Actions.getASTContext().DeclarationNames; 2100*0b57cec5SDimitry Andric Data.ReductionOrMapperId = DeclarationNameInfo( 2101*0b57cec5SDimitry Andric DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 2102*0b57cec5SDimitry Andric ConsumeToken(); 2103*0b57cec5SDimitry Andric // Parse ')'. 2104*0b57cec5SDimitry Andric return T.consumeClose(); 2105*0b57cec5SDimitry Andric } 2106*0b57cec5SDimitry Andric 2107*0b57cec5SDimitry Andric /// Parse map-type-modifiers in map clause. 2108*0b57cec5SDimitry Andric /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 2109*0b57cec5SDimitry Andric /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) 2110*0b57cec5SDimitry Andric bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { 2111*0b57cec5SDimitry Andric while (getCurToken().isNot(tok::colon)) { 2112*0b57cec5SDimitry Andric OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 2113*0b57cec5SDimitry Andric if (TypeModifier == OMPC_MAP_MODIFIER_always || 2114*0b57cec5SDimitry Andric TypeModifier == OMPC_MAP_MODIFIER_close) { 2115*0b57cec5SDimitry Andric Data.MapTypeModifiers.push_back(TypeModifier); 2116*0b57cec5SDimitry Andric Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 2117*0b57cec5SDimitry Andric ConsumeToken(); 2118*0b57cec5SDimitry Andric } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 2119*0b57cec5SDimitry Andric Data.MapTypeModifiers.push_back(TypeModifier); 2120*0b57cec5SDimitry Andric Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 2121*0b57cec5SDimitry Andric ConsumeToken(); 2122*0b57cec5SDimitry Andric if (parseMapperModifier(Data)) 2123*0b57cec5SDimitry Andric return true; 2124*0b57cec5SDimitry Andric } else { 2125*0b57cec5SDimitry Andric // For the case of unknown map-type-modifier or a map-type. 2126*0b57cec5SDimitry Andric // Map-type is followed by a colon; the function returns when it 2127*0b57cec5SDimitry Andric // encounters a token followed by a colon. 2128*0b57cec5SDimitry Andric if (Tok.is(tok::comma)) { 2129*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_map_type_modifier_missing); 2130*0b57cec5SDimitry Andric ConsumeToken(); 2131*0b57cec5SDimitry Andric continue; 2132*0b57cec5SDimitry Andric } 2133*0b57cec5SDimitry Andric // Potential map-type token as it is followed by a colon. 2134*0b57cec5SDimitry Andric if (PP.LookAhead(0).is(tok::colon)) 2135*0b57cec5SDimitry Andric return false; 2136*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_unknown_map_type_modifier); 2137*0b57cec5SDimitry Andric ConsumeToken(); 2138*0b57cec5SDimitry Andric } 2139*0b57cec5SDimitry Andric if (getCurToken().is(tok::comma)) 2140*0b57cec5SDimitry Andric ConsumeToken(); 2141*0b57cec5SDimitry Andric } 2142*0b57cec5SDimitry Andric return false; 2143*0b57cec5SDimitry Andric } 2144*0b57cec5SDimitry Andric 2145*0b57cec5SDimitry Andric /// Checks if the token is a valid map-type. 2146*0b57cec5SDimitry Andric static OpenMPMapClauseKind isMapType(Parser &P) { 2147*0b57cec5SDimitry Andric Token Tok = P.getCurToken(); 2148*0b57cec5SDimitry Andric // The map-type token can be either an identifier or the C++ delete keyword. 2149*0b57cec5SDimitry Andric if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 2150*0b57cec5SDimitry Andric return OMPC_MAP_unknown; 2151*0b57cec5SDimitry Andric Preprocessor &PP = P.getPreprocessor(); 2152*0b57cec5SDimitry Andric OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>( 2153*0b57cec5SDimitry Andric getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 2154*0b57cec5SDimitry Andric return MapType; 2155*0b57cec5SDimitry Andric } 2156*0b57cec5SDimitry Andric 2157*0b57cec5SDimitry Andric /// Parse map-type in map clause. 2158*0b57cec5SDimitry Andric /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 2159*0b57cec5SDimitry Andric /// where, map-type ::= to | from | tofrom | alloc | release | delete 2160*0b57cec5SDimitry Andric static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { 2161*0b57cec5SDimitry Andric Token Tok = P.getCurToken(); 2162*0b57cec5SDimitry Andric if (Tok.is(tok::colon)) { 2163*0b57cec5SDimitry Andric P.Diag(Tok, diag::err_omp_map_type_missing); 2164*0b57cec5SDimitry Andric return; 2165*0b57cec5SDimitry Andric } 2166*0b57cec5SDimitry Andric Data.MapType = isMapType(P); 2167*0b57cec5SDimitry Andric if (Data.MapType == OMPC_MAP_unknown) 2168*0b57cec5SDimitry Andric P.Diag(Tok, diag::err_omp_unknown_map_type); 2169*0b57cec5SDimitry Andric P.ConsumeToken(); 2170*0b57cec5SDimitry Andric } 2171*0b57cec5SDimitry Andric 2172*0b57cec5SDimitry Andric /// Parses clauses with list. 2173*0b57cec5SDimitry Andric bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 2174*0b57cec5SDimitry Andric OpenMPClauseKind Kind, 2175*0b57cec5SDimitry Andric SmallVectorImpl<Expr *> &Vars, 2176*0b57cec5SDimitry Andric OpenMPVarListDataTy &Data) { 2177*0b57cec5SDimitry Andric UnqualifiedId UnqualifiedReductionId; 2178*0b57cec5SDimitry Andric bool InvalidReductionId = false; 2179*0b57cec5SDimitry Andric bool IsInvalidMapperModifier = false; 2180*0b57cec5SDimitry Andric 2181*0b57cec5SDimitry Andric // Parse '('. 2182*0b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2183*0b57cec5SDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, 2184*0b57cec5SDimitry Andric getOpenMPClauseName(Kind))) 2185*0b57cec5SDimitry Andric return true; 2186*0b57cec5SDimitry Andric 2187*0b57cec5SDimitry Andric bool NeedRParenForLinear = false; 2188*0b57cec5SDimitry Andric BalancedDelimiterTracker LinearT(*this, tok::l_paren, 2189*0b57cec5SDimitry Andric tok::annot_pragma_openmp_end); 2190*0b57cec5SDimitry Andric // Handle reduction-identifier for reduction clause. 2191*0b57cec5SDimitry Andric if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 2192*0b57cec5SDimitry Andric Kind == OMPC_in_reduction) { 2193*0b57cec5SDimitry Andric ColonProtectionRAIIObject ColonRAII(*this); 2194*0b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) 2195*0b57cec5SDimitry Andric ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 2196*0b57cec5SDimitry Andric /*ObjectType=*/nullptr, 2197*0b57cec5SDimitry Andric /*EnteringContext=*/false); 2198*0b57cec5SDimitry Andric InvalidReductionId = ParseReductionId( 2199*0b57cec5SDimitry Andric *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 2200*0b57cec5SDimitry Andric if (InvalidReductionId) { 2201*0b57cec5SDimitry Andric SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2202*0b57cec5SDimitry Andric StopBeforeMatch); 2203*0b57cec5SDimitry Andric } 2204*0b57cec5SDimitry Andric if (Tok.is(tok::colon)) 2205*0b57cec5SDimitry Andric Data.ColonLoc = ConsumeToken(); 2206*0b57cec5SDimitry Andric else 2207*0b57cec5SDimitry Andric Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 2208*0b57cec5SDimitry Andric if (!InvalidReductionId) 2209*0b57cec5SDimitry Andric Data.ReductionOrMapperId = 2210*0b57cec5SDimitry Andric Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 2211*0b57cec5SDimitry Andric } else if (Kind == OMPC_depend) { 2212*0b57cec5SDimitry Andric // Handle dependency type for depend clause. 2213*0b57cec5SDimitry Andric ColonProtectionRAIIObject ColonRAII(*this); 2214*0b57cec5SDimitry Andric Data.DepKind = 2215*0b57cec5SDimitry Andric static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( 2216*0b57cec5SDimitry Andric Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); 2217*0b57cec5SDimitry Andric Data.DepLinMapLoc = Tok.getLocation(); 2218*0b57cec5SDimitry Andric 2219*0b57cec5SDimitry Andric if (Data.DepKind == OMPC_DEPEND_unknown) { 2220*0b57cec5SDimitry Andric SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2221*0b57cec5SDimitry Andric StopBeforeMatch); 2222*0b57cec5SDimitry Andric } else { 2223*0b57cec5SDimitry Andric ConsumeToken(); 2224*0b57cec5SDimitry Andric // Special processing for depend(source) clause. 2225*0b57cec5SDimitry Andric if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) { 2226*0b57cec5SDimitry Andric // Parse ')'. 2227*0b57cec5SDimitry Andric T.consumeClose(); 2228*0b57cec5SDimitry Andric return false; 2229*0b57cec5SDimitry Andric } 2230*0b57cec5SDimitry Andric } 2231*0b57cec5SDimitry Andric if (Tok.is(tok::colon)) { 2232*0b57cec5SDimitry Andric Data.ColonLoc = ConsumeToken(); 2233*0b57cec5SDimitry Andric } else { 2234*0b57cec5SDimitry Andric Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 2235*0b57cec5SDimitry Andric : diag::warn_pragma_expected_colon) 2236*0b57cec5SDimitry Andric << "dependency type"; 2237*0b57cec5SDimitry Andric } 2238*0b57cec5SDimitry Andric } else if (Kind == OMPC_linear) { 2239*0b57cec5SDimitry Andric // Try to parse modifier if any. 2240*0b57cec5SDimitry Andric if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 2241*0b57cec5SDimitry Andric Data.LinKind = static_cast<OpenMPLinearClauseKind>( 2242*0b57cec5SDimitry Andric getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2243*0b57cec5SDimitry Andric Data.DepLinMapLoc = ConsumeToken(); 2244*0b57cec5SDimitry Andric LinearT.consumeOpen(); 2245*0b57cec5SDimitry Andric NeedRParenForLinear = true; 2246*0b57cec5SDimitry Andric } 2247*0b57cec5SDimitry Andric } else if (Kind == OMPC_map) { 2248*0b57cec5SDimitry Andric // Handle map type for map clause. 2249*0b57cec5SDimitry Andric ColonProtectionRAIIObject ColonRAII(*this); 2250*0b57cec5SDimitry Andric 2251*0b57cec5SDimitry Andric // The first identifier may be a list item, a map-type or a 2252*0b57cec5SDimitry Andric // map-type-modifier. The map-type can also be delete which has the same 2253*0b57cec5SDimitry Andric // spelling of the C++ delete keyword. 2254*0b57cec5SDimitry Andric Data.DepLinMapLoc = Tok.getLocation(); 2255*0b57cec5SDimitry Andric 2256*0b57cec5SDimitry Andric // Check for presence of a colon in the map clause. 2257*0b57cec5SDimitry Andric TentativeParsingAction TPA(*this); 2258*0b57cec5SDimitry Andric bool ColonPresent = false; 2259*0b57cec5SDimitry Andric if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2260*0b57cec5SDimitry Andric StopBeforeMatch)) { 2261*0b57cec5SDimitry Andric if (Tok.is(tok::colon)) 2262*0b57cec5SDimitry Andric ColonPresent = true; 2263*0b57cec5SDimitry Andric } 2264*0b57cec5SDimitry Andric TPA.Revert(); 2265*0b57cec5SDimitry Andric // Only parse map-type-modifier[s] and map-type if a colon is present in 2266*0b57cec5SDimitry Andric // the map clause. 2267*0b57cec5SDimitry Andric if (ColonPresent) { 2268*0b57cec5SDimitry Andric IsInvalidMapperModifier = parseMapTypeModifiers(Data); 2269*0b57cec5SDimitry Andric if (!IsInvalidMapperModifier) 2270*0b57cec5SDimitry Andric parseMapType(*this, Data); 2271*0b57cec5SDimitry Andric else 2272*0b57cec5SDimitry Andric SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 2273*0b57cec5SDimitry Andric } 2274*0b57cec5SDimitry Andric if (Data.MapType == OMPC_MAP_unknown) { 2275*0b57cec5SDimitry Andric Data.MapType = OMPC_MAP_tofrom; 2276*0b57cec5SDimitry Andric Data.IsMapTypeImplicit = true; 2277*0b57cec5SDimitry Andric } 2278*0b57cec5SDimitry Andric 2279*0b57cec5SDimitry Andric if (Tok.is(tok::colon)) 2280*0b57cec5SDimitry Andric Data.ColonLoc = ConsumeToken(); 2281*0b57cec5SDimitry Andric } else if (Kind == OMPC_to || Kind == OMPC_from) { 2282*0b57cec5SDimitry Andric if (Tok.is(tok::identifier)) { 2283*0b57cec5SDimitry Andric bool IsMapperModifier = false; 2284*0b57cec5SDimitry Andric if (Kind == OMPC_to) { 2285*0b57cec5SDimitry Andric auto Modifier = static_cast<OpenMPToModifierKind>( 2286*0b57cec5SDimitry Andric getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2287*0b57cec5SDimitry Andric if (Modifier == OMPC_TO_MODIFIER_mapper) 2288*0b57cec5SDimitry Andric IsMapperModifier = true; 2289*0b57cec5SDimitry Andric } else { 2290*0b57cec5SDimitry Andric auto Modifier = static_cast<OpenMPFromModifierKind>( 2291*0b57cec5SDimitry Andric getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2292*0b57cec5SDimitry Andric if (Modifier == OMPC_FROM_MODIFIER_mapper) 2293*0b57cec5SDimitry Andric IsMapperModifier = true; 2294*0b57cec5SDimitry Andric } 2295*0b57cec5SDimitry Andric if (IsMapperModifier) { 2296*0b57cec5SDimitry Andric // Parse the mapper modifier. 2297*0b57cec5SDimitry Andric ConsumeToken(); 2298*0b57cec5SDimitry Andric IsInvalidMapperModifier = parseMapperModifier(Data); 2299*0b57cec5SDimitry Andric if (Tok.isNot(tok::colon)) { 2300*0b57cec5SDimitry Andric if (!IsInvalidMapperModifier) 2301*0b57cec5SDimitry Andric Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 2302*0b57cec5SDimitry Andric SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2303*0b57cec5SDimitry Andric StopBeforeMatch); 2304*0b57cec5SDimitry Andric } 2305*0b57cec5SDimitry Andric // Consume ':'. 2306*0b57cec5SDimitry Andric if (Tok.is(tok::colon)) 2307*0b57cec5SDimitry Andric ConsumeToken(); 2308*0b57cec5SDimitry Andric } 2309*0b57cec5SDimitry Andric } 2310*0b57cec5SDimitry Andric } else if (Kind == OMPC_allocate) { 2311*0b57cec5SDimitry Andric // Handle optional allocator expression followed by colon delimiter. 2312*0b57cec5SDimitry Andric ColonProtectionRAIIObject ColonRAII(*this); 2313*0b57cec5SDimitry Andric TentativeParsingAction TPA(*this); 2314*0b57cec5SDimitry Andric ExprResult Tail = 2315*0b57cec5SDimitry Andric Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 2316*0b57cec5SDimitry Andric Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), 2317*0b57cec5SDimitry Andric /*DiscardedValue=*/false); 2318*0b57cec5SDimitry Andric if (Tail.isUsable()) { 2319*0b57cec5SDimitry Andric if (Tok.is(tok::colon)) { 2320*0b57cec5SDimitry Andric Data.TailExpr = Tail.get(); 2321*0b57cec5SDimitry Andric Data.ColonLoc = ConsumeToken(); 2322*0b57cec5SDimitry Andric TPA.Commit(); 2323*0b57cec5SDimitry Andric } else { 2324*0b57cec5SDimitry Andric // colon not found, no allocator specified, parse only list of 2325*0b57cec5SDimitry Andric // variables. 2326*0b57cec5SDimitry Andric TPA.Revert(); 2327*0b57cec5SDimitry Andric } 2328*0b57cec5SDimitry Andric } else { 2329*0b57cec5SDimitry Andric // Parsing was unsuccessfull, revert and skip to the end of clause or 2330*0b57cec5SDimitry Andric // directive. 2331*0b57cec5SDimitry Andric TPA.Revert(); 2332*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2333*0b57cec5SDimitry Andric StopBeforeMatch); 2334*0b57cec5SDimitry Andric } 2335*0b57cec5SDimitry Andric } 2336*0b57cec5SDimitry Andric 2337*0b57cec5SDimitry Andric bool IsComma = 2338*0b57cec5SDimitry Andric (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 2339*0b57cec5SDimitry Andric Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 2340*0b57cec5SDimitry Andric (Kind == OMPC_reduction && !InvalidReductionId) || 2341*0b57cec5SDimitry Andric (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) || 2342*0b57cec5SDimitry Andric (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); 2343*0b57cec5SDimitry Andric const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 2344*0b57cec5SDimitry Andric while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 2345*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end))) { 2346*0b57cec5SDimitry Andric ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 2347*0b57cec5SDimitry Andric // Parse variable 2348*0b57cec5SDimitry Andric ExprResult VarExpr = 2349*0b57cec5SDimitry Andric Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 2350*0b57cec5SDimitry Andric if (VarExpr.isUsable()) { 2351*0b57cec5SDimitry Andric Vars.push_back(VarExpr.get()); 2352*0b57cec5SDimitry Andric } else { 2353*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2354*0b57cec5SDimitry Andric StopBeforeMatch); 2355*0b57cec5SDimitry Andric } 2356*0b57cec5SDimitry Andric // Skip ',' if any 2357*0b57cec5SDimitry Andric IsComma = Tok.is(tok::comma); 2358*0b57cec5SDimitry Andric if (IsComma) 2359*0b57cec5SDimitry Andric ConsumeToken(); 2360*0b57cec5SDimitry Andric else if (Tok.isNot(tok::r_paren) && 2361*0b57cec5SDimitry Andric Tok.isNot(tok::annot_pragma_openmp_end) && 2362*0b57cec5SDimitry Andric (!MayHaveTail || Tok.isNot(tok::colon))) 2363*0b57cec5SDimitry Andric Diag(Tok, diag::err_omp_expected_punc) 2364*0b57cec5SDimitry Andric << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 2365*0b57cec5SDimitry Andric : getOpenMPClauseName(Kind)) 2366*0b57cec5SDimitry Andric << (Kind == OMPC_flush); 2367*0b57cec5SDimitry Andric } 2368*0b57cec5SDimitry Andric 2369*0b57cec5SDimitry Andric // Parse ')' for linear clause with modifier. 2370*0b57cec5SDimitry Andric if (NeedRParenForLinear) 2371*0b57cec5SDimitry Andric LinearT.consumeClose(); 2372*0b57cec5SDimitry Andric 2373*0b57cec5SDimitry Andric // Parse ':' linear-step (or ':' alignment). 2374*0b57cec5SDimitry Andric const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 2375*0b57cec5SDimitry Andric if (MustHaveTail) { 2376*0b57cec5SDimitry Andric Data.ColonLoc = Tok.getLocation(); 2377*0b57cec5SDimitry Andric SourceLocation ELoc = ConsumeToken(); 2378*0b57cec5SDimitry Andric ExprResult Tail = ParseAssignmentExpression(); 2379*0b57cec5SDimitry Andric Tail = 2380*0b57cec5SDimitry Andric Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 2381*0b57cec5SDimitry Andric if (Tail.isUsable()) 2382*0b57cec5SDimitry Andric Data.TailExpr = Tail.get(); 2383*0b57cec5SDimitry Andric else 2384*0b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2385*0b57cec5SDimitry Andric StopBeforeMatch); 2386*0b57cec5SDimitry Andric } 2387*0b57cec5SDimitry Andric 2388*0b57cec5SDimitry Andric // Parse ')'. 2389*0b57cec5SDimitry Andric Data.RLoc = Tok.getLocation(); 2390*0b57cec5SDimitry Andric if (!T.consumeClose()) 2391*0b57cec5SDimitry Andric Data.RLoc = T.getCloseLocation(); 2392*0b57cec5SDimitry Andric return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && 2393*0b57cec5SDimitry Andric Vars.empty()) || 2394*0b57cec5SDimitry Andric (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 2395*0b57cec5SDimitry Andric (MustHaveTail && !Data.TailExpr) || InvalidReductionId || 2396*0b57cec5SDimitry Andric IsInvalidMapperModifier; 2397*0b57cec5SDimitry Andric } 2398*0b57cec5SDimitry Andric 2399*0b57cec5SDimitry Andric /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 2400*0b57cec5SDimitry Andric /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or 2401*0b57cec5SDimitry Andric /// 'in_reduction'. 2402*0b57cec5SDimitry Andric /// 2403*0b57cec5SDimitry Andric /// private-clause: 2404*0b57cec5SDimitry Andric /// 'private' '(' list ')' 2405*0b57cec5SDimitry Andric /// firstprivate-clause: 2406*0b57cec5SDimitry Andric /// 'firstprivate' '(' list ')' 2407*0b57cec5SDimitry Andric /// lastprivate-clause: 2408*0b57cec5SDimitry Andric /// 'lastprivate' '(' list ')' 2409*0b57cec5SDimitry Andric /// shared-clause: 2410*0b57cec5SDimitry Andric /// 'shared' '(' list ')' 2411*0b57cec5SDimitry Andric /// linear-clause: 2412*0b57cec5SDimitry Andric /// 'linear' '(' linear-list [ ':' linear-step ] ')' 2413*0b57cec5SDimitry Andric /// aligned-clause: 2414*0b57cec5SDimitry Andric /// 'aligned' '(' list [ ':' alignment ] ')' 2415*0b57cec5SDimitry Andric /// reduction-clause: 2416*0b57cec5SDimitry Andric /// 'reduction' '(' reduction-identifier ':' list ')' 2417*0b57cec5SDimitry Andric /// task_reduction-clause: 2418*0b57cec5SDimitry Andric /// 'task_reduction' '(' reduction-identifier ':' list ')' 2419*0b57cec5SDimitry Andric /// in_reduction-clause: 2420*0b57cec5SDimitry Andric /// 'in_reduction' '(' reduction-identifier ':' list ')' 2421*0b57cec5SDimitry Andric /// copyprivate-clause: 2422*0b57cec5SDimitry Andric /// 'copyprivate' '(' list ')' 2423*0b57cec5SDimitry Andric /// flush-clause: 2424*0b57cec5SDimitry Andric /// 'flush' '(' list ')' 2425*0b57cec5SDimitry Andric /// depend-clause: 2426*0b57cec5SDimitry Andric /// 'depend' '(' in | out | inout : list | source ')' 2427*0b57cec5SDimitry Andric /// map-clause: 2428*0b57cec5SDimitry Andric /// 'map' '(' [ [ always [,] ] [ close [,] ] 2429*0b57cec5SDimitry Andric /// [ mapper '(' mapper-identifier ')' [,] ] 2430*0b57cec5SDimitry Andric /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 2431*0b57cec5SDimitry Andric /// to-clause: 2432*0b57cec5SDimitry Andric /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 2433*0b57cec5SDimitry Andric /// from-clause: 2434*0b57cec5SDimitry Andric /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 2435*0b57cec5SDimitry Andric /// use_device_ptr-clause: 2436*0b57cec5SDimitry Andric /// 'use_device_ptr' '(' list ')' 2437*0b57cec5SDimitry Andric /// is_device_ptr-clause: 2438*0b57cec5SDimitry Andric /// 'is_device_ptr' '(' list ')' 2439*0b57cec5SDimitry Andric /// allocate-clause: 2440*0b57cec5SDimitry Andric /// 'allocate' '(' [ allocator ':' ] list ')' 2441*0b57cec5SDimitry Andric /// 2442*0b57cec5SDimitry Andric /// For 'linear' clause linear-list may have the following forms: 2443*0b57cec5SDimitry Andric /// list 2444*0b57cec5SDimitry Andric /// modifier(list) 2445*0b57cec5SDimitry Andric /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 2446*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 2447*0b57cec5SDimitry Andric OpenMPClauseKind Kind, 2448*0b57cec5SDimitry Andric bool ParseOnly) { 2449*0b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation(); 2450*0b57cec5SDimitry Andric SourceLocation LOpen = ConsumeToken(); 2451*0b57cec5SDimitry Andric SmallVector<Expr *, 4> Vars; 2452*0b57cec5SDimitry Andric OpenMPVarListDataTy Data; 2453*0b57cec5SDimitry Andric 2454*0b57cec5SDimitry Andric if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 2455*0b57cec5SDimitry Andric return nullptr; 2456*0b57cec5SDimitry Andric 2457*0b57cec5SDimitry Andric if (ParseOnly) 2458*0b57cec5SDimitry Andric return nullptr; 2459*0b57cec5SDimitry Andric OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 2460*0b57cec5SDimitry Andric return Actions.ActOnOpenMPVarListClause( 2461*0b57cec5SDimitry Andric Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc, 2462*0b57cec5SDimitry Andric Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, Data.DepKind, 2463*0b57cec5SDimitry Andric Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 2464*0b57cec5SDimitry Andric Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc); 2465*0b57cec5SDimitry Andric } 2466*0b57cec5SDimitry Andric 2467