1249261Sdim//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// 2249261Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6249261Sdim// 7249261Sdim//===----------------------------------------------------------------------===// 8249261Sdim/// \file 9341825Sdim/// This file implements parsing of all OpenMP directives and clauses. 10249261Sdim/// 11249261Sdim//===----------------------------------------------------------------------===// 12249261Sdim 13276479Sdim#include "clang/AST/ASTContext.h" 14261991Sdim#include "clang/AST/StmtOpenMP.h" 15360784Sdim#include "clang/Basic/OpenMPKinds.h" 16261991Sdim#include "clang/Parse/ParseDiagnostic.h" 17249261Sdim#include "clang/Parse/Parser.h" 18321369Sdim#include "clang/Parse/RAIIObjectsForParser.h" 19261991Sdim#include "clang/Sema/Scope.h" 20261991Sdim#include "llvm/ADT/PointerIntPair.h" 21360784Sdim#include "llvm/ADT/UniqueVector.h" 22296417Sdim 23249261Sdimusing namespace clang; 24360784Sdimusing namespace llvm::omp; 25249261Sdim 26249261Sdim//===----------------------------------------------------------------------===// 27249261Sdim// OpenMP declarative directives. 28249261Sdim//===----------------------------------------------------------------------===// 29249261Sdim 30309124Sdimnamespace { 31309124Sdimenum OpenMPDirectiveKindEx { 32360784Sdim OMPD_cancellation = unsigned(OMPD_unknown) + 1, 33309124Sdim OMPD_data, 34309124Sdim OMPD_declare, 35309124Sdim OMPD_end, 36309124Sdim OMPD_end_declare, 37309124Sdim OMPD_enter, 38309124Sdim OMPD_exit, 39309124Sdim OMPD_point, 40309124Sdim OMPD_reduction, 41309124Sdim OMPD_target_enter, 42309124Sdim OMPD_target_exit, 43309124Sdim OMPD_update, 44314564Sdim OMPD_distribute_parallel, 45314564Sdim OMPD_teams_distribute_parallel, 46353358Sdim OMPD_target_teams_distribute_parallel, 47353358Sdim OMPD_mapper, 48360784Sdim OMPD_variant, 49309124Sdim}; 50309124Sdim 51360784Sdim// Helper to unify the enum class OpenMPDirectiveKind with its extension 52360784Sdim// the OpenMPDirectiveKindEx enum which allows to use them together as if they 53360784Sdim// are unsigned values. 54360784Sdimstruct OpenMPDirectiveKindExWrapper { 55360784Sdim OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {} 56360784Sdim OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {} 57360784Sdim bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); } 58360784Sdim bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); } 59360784Sdim bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); } 60360784Sdim operator unsigned() const { return Value; } 61360784Sdim operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); } 62360784Sdim unsigned Value; 63360784Sdim}; 64360784Sdim 65353358Sdimclass DeclDirectiveListParserHelper final { 66309124Sdim SmallVector<Expr *, 4> Identifiers; 67309124Sdim Parser *P; 68353358Sdim OpenMPDirectiveKind Kind; 69309124Sdim 70309124Sdimpublic: 71353358Sdim DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind) 72353358Sdim : P(P), Kind(Kind) {} 73309124Sdim void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 74353358Sdim ExprResult Res = P->getActions().ActOnOpenMPIdExpression( 75353358Sdim P->getCurScope(), SS, NameInfo, Kind); 76309124Sdim if (Res.isUsable()) 77309124Sdim Identifiers.push_back(Res.get()); 78309124Sdim } 79309124Sdim llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } 80309124Sdim}; 81309124Sdim} // namespace 82309124Sdim 83309124Sdim// Map token string to extended OMP token kind that are 84309124Sdim// OpenMPDirectiveKind + OpenMPDirectiveKindEx. 85309124Sdimstatic unsigned getOpenMPDirectiveKindEx(StringRef S) { 86360784Sdim OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S); 87309124Sdim if (DKind != OMPD_unknown) 88309124Sdim return DKind; 89309124Sdim 90360784Sdim return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S) 91309124Sdim .Case("cancellation", OMPD_cancellation) 92309124Sdim .Case("data", OMPD_data) 93309124Sdim .Case("declare", OMPD_declare) 94309124Sdim .Case("end", OMPD_end) 95309124Sdim .Case("enter", OMPD_enter) 96309124Sdim .Case("exit", OMPD_exit) 97309124Sdim .Case("point", OMPD_point) 98309124Sdim .Case("reduction", OMPD_reduction) 99309124Sdim .Case("update", OMPD_update) 100353358Sdim .Case("mapper", OMPD_mapper) 101360784Sdim .Case("variant", OMPD_variant) 102309124Sdim .Default(OMPD_unknown); 103309124Sdim} 104309124Sdim 105360784Sdimstatic OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) { 106280031Sdim // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 107280031Sdim // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 108280031Sdim // TODO: add other combined directives in topological order. 109360784Sdim static const OpenMPDirectiveKindExWrapper F[][3] = { 110341825Sdim {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, 111341825Sdim {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, 112353358Sdim {OMPD_declare, OMPD_mapper, OMPD_declare_mapper}, 113341825Sdim {OMPD_declare, OMPD_simd, OMPD_declare_simd}, 114341825Sdim {OMPD_declare, OMPD_target, OMPD_declare_target}, 115360784Sdim {OMPD_declare, OMPD_variant, OMPD_declare_variant}, 116341825Sdim {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, 117341825Sdim {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, 118341825Sdim {OMPD_distribute_parallel_for, OMPD_simd, 119341825Sdim OMPD_distribute_parallel_for_simd}, 120341825Sdim {OMPD_distribute, OMPD_simd, OMPD_distribute_simd}, 121341825Sdim {OMPD_end, OMPD_declare, OMPD_end_declare}, 122341825Sdim {OMPD_end_declare, OMPD_target, OMPD_end_declare_target}, 123341825Sdim {OMPD_target, OMPD_data, OMPD_target_data}, 124341825Sdim {OMPD_target, OMPD_enter, OMPD_target_enter}, 125341825Sdim {OMPD_target, OMPD_exit, OMPD_target_exit}, 126341825Sdim {OMPD_target, OMPD_update, OMPD_target_update}, 127341825Sdim {OMPD_target_enter, OMPD_data, OMPD_target_enter_data}, 128341825Sdim {OMPD_target_exit, OMPD_data, OMPD_target_exit_data}, 129341825Sdim {OMPD_for, OMPD_simd, OMPD_for_simd}, 130341825Sdim {OMPD_parallel, OMPD_for, OMPD_parallel_for}, 131341825Sdim {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, 132341825Sdim {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, 133341825Sdim {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, 134341825Sdim {OMPD_target, OMPD_parallel, OMPD_target_parallel}, 135341825Sdim {OMPD_target, OMPD_simd, OMPD_target_simd}, 136341825Sdim {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, 137341825Sdim {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, 138341825Sdim {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, 139341825Sdim {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd}, 140341825Sdim {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel}, 141341825Sdim {OMPD_teams_distribute_parallel, OMPD_for, 142341825Sdim OMPD_teams_distribute_parallel_for}, 143341825Sdim {OMPD_teams_distribute_parallel_for, OMPD_simd, 144341825Sdim OMPD_teams_distribute_parallel_for_simd}, 145341825Sdim {OMPD_target, OMPD_teams, OMPD_target_teams}, 146341825Sdim {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, 147341825Sdim {OMPD_target_teams_distribute, OMPD_parallel, 148341825Sdim OMPD_target_teams_distribute_parallel}, 149341825Sdim {OMPD_target_teams_distribute, OMPD_simd, 150341825Sdim OMPD_target_teams_distribute_simd}, 151341825Sdim {OMPD_target_teams_distribute_parallel, OMPD_for, 152341825Sdim OMPD_target_teams_distribute_parallel_for}, 153341825Sdim {OMPD_target_teams_distribute_parallel_for, OMPD_simd, 154360784Sdim OMPD_target_teams_distribute_parallel_for_simd}, 155360784Sdim {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, 156360784Sdim {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, 157360784Sdim {OMPD_parallel, OMPD_master, OMPD_parallel_master}, 158360784Sdim {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}, 159360784Sdim {OMPD_parallel_master_taskloop, OMPD_simd, 160360784Sdim OMPD_parallel_master_taskloop_simd}}; 161309124Sdim enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; 162341825Sdim Token Tok = P.getCurToken(); 163360784Sdim OpenMPDirectiveKindExWrapper DKind = 164276479Sdim Tok.isAnnotation() 165309124Sdim ? static_cast<unsigned>(OMPD_unknown) 166309124Sdim : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 167309124Sdim if (DKind == OMPD_unknown) 168309124Sdim return OMPD_unknown; 169296417Sdim 170341825Sdim for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) { 171341825Sdim if (DKind != F[I][0]) 172309124Sdim continue; 173309124Sdim 174309124Sdim Tok = P.getPreprocessor().LookAhead(0); 175360784Sdim OpenMPDirectiveKindExWrapper SDKind = 176309124Sdim Tok.isAnnotation() 177309124Sdim ? static_cast<unsigned>(OMPD_unknown) 178309124Sdim : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 179309124Sdim if (SDKind == OMPD_unknown) 180309124Sdim continue; 181309124Sdim 182341825Sdim if (SDKind == F[I][1]) { 183309124Sdim P.ConsumeToken(); 184341825Sdim DKind = F[I][2]; 185309124Sdim } 186309124Sdim } 187309124Sdim return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind) 188309124Sdim : OMPD_unknown; 189309124Sdim} 190309124Sdim 191309124Sdimstatic DeclarationName parseOpenMPReductionId(Parser &P) { 192309124Sdim Token Tok = P.getCurToken(); 193309124Sdim Sema &Actions = P.getActions(); 194309124Sdim OverloadedOperatorKind OOK = OO_None; 195309124Sdim // Allow to use 'operator' keyword for C++ operators 196309124Sdim bool WithOperator = false; 197309124Sdim if (Tok.is(tok::kw_operator)) { 198309124Sdim P.ConsumeToken(); 199309124Sdim Tok = P.getCurToken(); 200309124Sdim WithOperator = true; 201309124Sdim } 202309124Sdim switch (Tok.getKind()) { 203309124Sdim case tok::plus: // '+' 204309124Sdim OOK = OO_Plus; 205309124Sdim break; 206309124Sdim case tok::minus: // '-' 207309124Sdim OOK = OO_Minus; 208309124Sdim break; 209309124Sdim case tok::star: // '*' 210309124Sdim OOK = OO_Star; 211309124Sdim break; 212309124Sdim case tok::amp: // '&' 213309124Sdim OOK = OO_Amp; 214309124Sdim break; 215309124Sdim case tok::pipe: // '|' 216309124Sdim OOK = OO_Pipe; 217309124Sdim break; 218309124Sdim case tok::caret: // '^' 219309124Sdim OOK = OO_Caret; 220309124Sdim break; 221309124Sdim case tok::ampamp: // '&&' 222309124Sdim OOK = OO_AmpAmp; 223309124Sdim break; 224309124Sdim case tok::pipepipe: // '||' 225309124Sdim OOK = OO_PipePipe; 226309124Sdim break; 227309124Sdim case tok::identifier: // identifier 228309124Sdim if (!WithOperator) 229309124Sdim break; 230321369Sdim LLVM_FALLTHROUGH; 231309124Sdim default: 232309124Sdim P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); 233309124Sdim P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 234309124Sdim Parser::StopBeforeMatch); 235309124Sdim return DeclarationName(); 236309124Sdim } 237309124Sdim P.ConsumeToken(); 238309124Sdim auto &DeclNames = Actions.getASTContext().DeclarationNames; 239309124Sdim return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo()) 240309124Sdim : DeclNames.getCXXOperatorName(OOK); 241309124Sdim} 242309124Sdim 243341825Sdim/// Parse 'omp declare reduction' construct. 244309124Sdim/// 245309124Sdim/// declare-reduction-directive: 246309124Sdim/// annot_pragma_openmp 'declare' 'reduction' 247309124Sdim/// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')' 248309124Sdim/// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')'] 249309124Sdim/// annot_pragma_openmp_end 250309124Sdim/// <reduction_id> is either a base language identifier or one of the following 251309124Sdim/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'. 252309124Sdim/// 253309124SdimParser::DeclGroupPtrTy 254309124SdimParser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { 255309124Sdim // Parse '('. 256309124Sdim BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 257360784Sdim if (T.expectAndConsume( 258360784Sdim diag::err_expected_lparen_after, 259360784Sdim getOpenMPDirectiveName(OMPD_declare_reduction).data())) { 260309124Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 261309124Sdim return DeclGroupPtrTy(); 262309124Sdim } 263309124Sdim 264309124Sdim DeclarationName Name = parseOpenMPReductionId(*this); 265309124Sdim if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end)) 266309124Sdim return DeclGroupPtrTy(); 267309124Sdim 268309124Sdim // Consume ':'. 269309124Sdim bool IsCorrect = !ExpectAndConsume(tok::colon); 270309124Sdim 271309124Sdim if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 272309124Sdim return DeclGroupPtrTy(); 273309124Sdim 274309124Sdim IsCorrect = IsCorrect && !Name.isEmpty(); 275309124Sdim 276309124Sdim if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) { 277309124Sdim Diag(Tok.getLocation(), diag::err_expected_type); 278309124Sdim IsCorrect = false; 279309124Sdim } 280309124Sdim 281309124Sdim if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 282309124Sdim return DeclGroupPtrTy(); 283309124Sdim 284309124Sdim SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes; 285309124Sdim // Parse list of types until ':' token. 286309124Sdim do { 287309124Sdim ColonProtectionRAIIObject ColonRAII(*this); 288309124Sdim SourceRange Range; 289327952Sdim TypeResult TR = 290327952Sdim ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS); 291309124Sdim if (TR.isUsable()) { 292341825Sdim QualType ReductionType = 293309124Sdim Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); 294309124Sdim if (!ReductionType.isNull()) { 295309124Sdim ReductionTypes.push_back( 296309124Sdim std::make_pair(ReductionType, Range.getBegin())); 297309124Sdim } 298288943Sdim } else { 299309124Sdim SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end, 300309124Sdim StopBeforeMatch); 301288943Sdim } 302296417Sdim 303309124Sdim if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) 304309124Sdim break; 305296417Sdim 306309124Sdim // Consume ','. 307309124Sdim if (ExpectAndConsume(tok::comma)) { 308309124Sdim IsCorrect = false; 309309124Sdim if (Tok.is(tok::annot_pragma_openmp_end)) { 310309124Sdim Diag(Tok.getLocation(), diag::err_expected_type); 311309124Sdim return DeclGroupPtrTy(); 312288943Sdim } 313309124Sdim } 314309124Sdim } while (Tok.isNot(tok::annot_pragma_openmp_end)); 315296417Sdim 316309124Sdim if (ReductionTypes.empty()) { 317309124Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 318309124Sdim return DeclGroupPtrTy(); 319309124Sdim } 320309124Sdim 321309124Sdim if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 322309124Sdim return DeclGroupPtrTy(); 323309124Sdim 324309124Sdim // Consume ':'. 325309124Sdim if (ExpectAndConsume(tok::colon)) 326309124Sdim IsCorrect = false; 327309124Sdim 328309124Sdim if (Tok.is(tok::annot_pragma_openmp_end)) { 329309124Sdim Diag(Tok.getLocation(), diag::err_expected_expression); 330309124Sdim return DeclGroupPtrTy(); 331309124Sdim } 332309124Sdim 333309124Sdim DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart( 334309124Sdim getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS); 335309124Sdim 336309124Sdim // Parse <combiner> expression and then parse initializer if any for each 337309124Sdim // correct type. 338309124Sdim unsigned I = 0, E = ReductionTypes.size(); 339341825Sdim for (Decl *D : DRD.get()) { 340309124Sdim TentativeParsingAction TPA(*this); 341309124Sdim ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 342327952Sdim Scope::CompoundStmtScope | 343309124Sdim Scope::OpenMPDirectiveScope); 344309124Sdim // Parse <combiner> expression. 345309124Sdim Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); 346360784Sdim ExprResult CombinerResult = Actions.ActOnFinishFullExpr( 347360784Sdim ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false); 348309124Sdim Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); 349309124Sdim 350309124Sdim if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && 351309124Sdim Tok.isNot(tok::annot_pragma_openmp_end)) { 352309124Sdim TPA.Commit(); 353309124Sdim IsCorrect = false; 354309124Sdim break; 355309124Sdim } 356309124Sdim IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable(); 357309124Sdim ExprResult InitializerResult; 358309124Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 359309124Sdim // Parse <initializer> expression. 360309124Sdim if (Tok.is(tok::identifier) && 361341825Sdim Tok.getIdentifierInfo()->isStr("initializer")) { 362309124Sdim ConsumeToken(); 363341825Sdim } else { 364309124Sdim Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; 365309124Sdim TPA.Commit(); 366309124Sdim IsCorrect = false; 367309124Sdim break; 368280031Sdim } 369309124Sdim // Parse '('. 370309124Sdim BalancedDelimiterTracker T(*this, tok::l_paren, 371309124Sdim tok::annot_pragma_openmp_end); 372309124Sdim IsCorrect = 373309124Sdim !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && 374309124Sdim IsCorrect; 375309124Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 376309124Sdim ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 377327952Sdim Scope::CompoundStmtScope | 378309124Sdim Scope::OpenMPDirectiveScope); 379309124Sdim // Parse expression. 380327952Sdim VarDecl *OmpPrivParm = 381327952Sdim Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), 382327952Sdim D); 383327952Sdim // Check if initializer is omp_priv <init_expr> or something else. 384327952Sdim if (Tok.is(tok::identifier) && 385327952Sdim Tok.getIdentifierInfo()->isStr("omp_priv")) { 386360784Sdim ConsumeToken(); 387360784Sdim ParseOpenMPReductionInitializerForDecl(OmpPrivParm); 388327952Sdim } else { 389327952Sdim InitializerResult = Actions.ActOnFinishFullExpr( 390327952Sdim ParseAssignmentExpression().get(), D->getLocation(), 391353358Sdim /*DiscardedValue*/ false); 392327952Sdim } 393309124Sdim Actions.ActOnOpenMPDeclareReductionInitializerEnd( 394327952Sdim D, InitializerResult.get(), OmpPrivParm); 395309124Sdim if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && 396309124Sdim Tok.isNot(tok::annot_pragma_openmp_end)) { 397309124Sdim TPA.Commit(); 398309124Sdim IsCorrect = false; 399309124Sdim break; 400309124Sdim } 401309124Sdim IsCorrect = 402309124Sdim !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid(); 403309124Sdim } 404276479Sdim } 405309124Sdim 406309124Sdim ++I; 407309124Sdim // Revert parsing if not the last type, otherwise accept it, we're done with 408309124Sdim // parsing. 409309124Sdim if (I != E) 410309124Sdim TPA.Revert(); 411309124Sdim else 412309124Sdim TPA.Commit(); 413276479Sdim } 414309124Sdim return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD, 415309124Sdim IsCorrect); 416276479Sdim} 417276479Sdim 418327952Sdimvoid Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { 419327952Sdim // Parse declarator '=' initializer. 420327952Sdim // If a '==' or '+=' is found, suggest a fixit to '='. 421327952Sdim if (isTokenEqualOrEqualTypo()) { 422327952Sdim ConsumeToken(); 423327952Sdim 424327952Sdim if (Tok.is(tok::code_completion)) { 425327952Sdim Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); 426327952Sdim Actions.FinalizeDeclaration(OmpPrivParm); 427327952Sdim cutOffParsing(); 428327952Sdim return; 429327952Sdim } 430327952Sdim 431360784Sdim PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm); 432360784Sdim ExprResult Init = ParseInitializer(); 433327952Sdim 434327952Sdim if (Init.isInvalid()) { 435327952Sdim SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 436327952Sdim Actions.ActOnInitializerError(OmpPrivParm); 437327952Sdim } else { 438327952Sdim Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 439327952Sdim /*DirectInit=*/false); 440327952Sdim } 441327952Sdim } else if (Tok.is(tok::l_paren)) { 442327952Sdim // Parse C++ direct initializer: '(' expression-list ')' 443327952Sdim BalancedDelimiterTracker T(*this, tok::l_paren); 444327952Sdim T.consumeOpen(); 445327952Sdim 446327952Sdim ExprVector Exprs; 447327952Sdim CommaLocsTy CommaLocs; 448327952Sdim 449344779Sdim SourceLocation LParLoc = T.getOpenLocation(); 450353358Sdim auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() { 451353358Sdim QualType PreferredType = Actions.ProduceConstructorSignatureHelp( 452353358Sdim getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), 453353358Sdim OmpPrivParm->getLocation(), Exprs, LParLoc); 454353358Sdim CalledSignatureHelp = true; 455353358Sdim return PreferredType; 456353358Sdim }; 457353358Sdim if (ParseExpressionList(Exprs, CommaLocs, [&] { 458353358Sdim PreferredType.enterFunctionArgument(Tok.getLocation(), 459353358Sdim RunSignatureHelp); 460353358Sdim })) { 461353358Sdim if (PP.isCodeCompletionReached() && !CalledSignatureHelp) 462353358Sdim RunSignatureHelp(); 463327952Sdim Actions.ActOnInitializerError(OmpPrivParm); 464327952Sdim SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 465327952Sdim } else { 466327952Sdim // Match the ')'. 467341825Sdim SourceLocation RLoc = Tok.getLocation(); 468341825Sdim if (!T.consumeClose()) 469341825Sdim RLoc = T.getCloseLocation(); 470327952Sdim 471327952Sdim assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && 472327952Sdim "Unexpected number of commas!"); 473327952Sdim 474341825Sdim ExprResult Initializer = 475341825Sdim Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs); 476327952Sdim Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), 477327952Sdim /*DirectInit=*/true); 478327952Sdim } 479327952Sdim } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 480327952Sdim // Parse C++0x braced-init-list. 481327952Sdim Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 482327952Sdim 483327952Sdim ExprResult Init(ParseBraceInitializer()); 484327952Sdim 485327952Sdim if (Init.isInvalid()) { 486327952Sdim Actions.ActOnInitializerError(OmpPrivParm); 487327952Sdim } else { 488327952Sdim Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 489327952Sdim /*DirectInit=*/true); 490327952Sdim } 491327952Sdim } else { 492327952Sdim Actions.ActOnUninitializedDecl(OmpPrivParm); 493327952Sdim } 494327952Sdim} 495327952Sdim 496353358Sdim/// Parses 'omp declare mapper' directive. 497353358Sdim/// 498353358Sdim/// declare-mapper-directive: 499353358Sdim/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':'] 500353358Sdim/// <type> <var> ')' [<clause>[[,] <clause>] ... ] 501353358Sdim/// annot_pragma_openmp_end 502353358Sdim/// <mapper-identifier> and <var> are base language identifiers. 503353358Sdim/// 504353358SdimParser::DeclGroupPtrTy 505353358SdimParser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) { 506353358Sdim bool IsCorrect = true; 507353358Sdim // Parse '(' 508353358Sdim BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 509353358Sdim if (T.expectAndConsume(diag::err_expected_lparen_after, 510360784Sdim getOpenMPDirectiveName(OMPD_declare_mapper).data())) { 511353358Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 512353358Sdim return DeclGroupPtrTy(); 513353358Sdim } 514353358Sdim 515353358Sdim // Parse <mapper-identifier> 516353358Sdim auto &DeclNames = Actions.getASTContext().DeclarationNames; 517353358Sdim DeclarationName MapperId; 518353358Sdim if (PP.LookAhead(0).is(tok::colon)) { 519353358Sdim if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 520353358Sdim Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 521353358Sdim IsCorrect = false; 522353358Sdim } else { 523353358Sdim MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo()); 524353358Sdim } 525353358Sdim ConsumeToken(); 526353358Sdim // Consume ':'. 527353358Sdim ExpectAndConsume(tok::colon); 528353358Sdim } else { 529353358Sdim // If no mapper identifier is provided, its name is "default" by default 530353358Sdim MapperId = 531353358Sdim DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default")); 532353358Sdim } 533353358Sdim 534353358Sdim if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 535353358Sdim return DeclGroupPtrTy(); 536353358Sdim 537353358Sdim // Parse <type> <var> 538353358Sdim DeclarationName VName; 539353358Sdim QualType MapperType; 540353358Sdim SourceRange Range; 541353358Sdim TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS); 542353358Sdim if (ParsedType.isUsable()) 543353358Sdim MapperType = 544353358Sdim Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType); 545353358Sdim if (MapperType.isNull()) 546353358Sdim IsCorrect = false; 547353358Sdim if (!IsCorrect) { 548353358Sdim SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 549353358Sdim return DeclGroupPtrTy(); 550353358Sdim } 551353358Sdim 552353358Sdim // Consume ')'. 553353358Sdim IsCorrect &= !T.consumeClose(); 554353358Sdim if (!IsCorrect) { 555353358Sdim SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 556353358Sdim return DeclGroupPtrTy(); 557353358Sdim } 558353358Sdim 559353358Sdim // Enter scope. 560353358Sdim OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart( 561353358Sdim getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType, 562353358Sdim Range.getBegin(), VName, AS); 563353358Sdim DeclarationNameInfo DirName; 564353358Sdim SourceLocation Loc = Tok.getLocation(); 565353358Sdim unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 566353358Sdim Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 567353358Sdim ParseScope OMPDirectiveScope(this, ScopeFlags); 568353358Sdim Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc); 569353358Sdim 570353358Sdim // Add the mapper variable declaration. 571353358Sdim Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl( 572353358Sdim DMD, getCurScope(), MapperType, Range.getBegin(), VName); 573353358Sdim 574353358Sdim // Parse map clauses. 575353358Sdim SmallVector<OMPClause *, 6> Clauses; 576353358Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) { 577353358Sdim OpenMPClauseKind CKind = Tok.isAnnotation() 578353358Sdim ? OMPC_unknown 579353358Sdim : getOpenMPClauseKind(PP.getSpelling(Tok)); 580353358Sdim Actions.StartOpenMPClause(CKind); 581353358Sdim OMPClause *Clause = 582353358Sdim ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0); 583353358Sdim if (Clause) 584353358Sdim Clauses.push_back(Clause); 585353358Sdim else 586353358Sdim IsCorrect = false; 587353358Sdim // Skip ',' if any. 588353358Sdim if (Tok.is(tok::comma)) 589353358Sdim ConsumeToken(); 590353358Sdim Actions.EndOpenMPClause(); 591353358Sdim } 592353358Sdim if (Clauses.empty()) { 593353358Sdim Diag(Tok, diag::err_omp_expected_clause) 594353358Sdim << getOpenMPDirectiveName(OMPD_declare_mapper); 595353358Sdim IsCorrect = false; 596353358Sdim } 597353358Sdim 598353358Sdim // Exit scope. 599353358Sdim Actions.EndOpenMPDSABlock(nullptr); 600353358Sdim OMPDirectiveScope.Exit(); 601353358Sdim 602353358Sdim DeclGroupPtrTy DGP = 603353358Sdim Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses); 604353358Sdim if (!IsCorrect) 605353358Sdim return DeclGroupPtrTy(); 606353358Sdim return DGP; 607353358Sdim} 608353358Sdim 609353358SdimTypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range, 610353358Sdim DeclarationName &Name, 611353358Sdim AccessSpecifier AS) { 612353358Sdim // Parse the common declaration-specifiers piece. 613353358Sdim Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier; 614353358Sdim DeclSpec DS(AttrFactory); 615353358Sdim ParseSpecifierQualifierList(DS, AS, DSC); 616353358Sdim 617353358Sdim // Parse the declarator. 618353358Sdim DeclaratorContext Context = DeclaratorContext::PrototypeContext; 619353358Sdim Declarator DeclaratorInfo(DS, Context); 620353358Sdim ParseDeclarator(DeclaratorInfo); 621353358Sdim Range = DeclaratorInfo.getSourceRange(); 622353358Sdim if (DeclaratorInfo.getIdentifier() == nullptr) { 623353358Sdim Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator); 624353358Sdim return true; 625353358Sdim } 626353358Sdim Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName(); 627353358Sdim 628353358Sdim return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo); 629353358Sdim} 630353358Sdim 631309124Sdimnamespace { 632309124Sdim/// RAII that recreates function context for correct parsing of clauses of 633309124Sdim/// 'declare simd' construct. 634309124Sdim/// OpenMP, 2.8.2 declare simd Construct 635309124Sdim/// The expressions appearing in the clauses of this directive are evaluated in 636309124Sdim/// the scope of the arguments of the function declaration or definition. 637309124Sdimclass FNContextRAII final { 638309124Sdim Parser &P; 639309124Sdim Sema::CXXThisScopeRAII *ThisScope; 640309124Sdim Parser::ParseScope *TempScope; 641309124Sdim Parser::ParseScope *FnScope; 642309124Sdim bool HasTemplateScope = false; 643309124Sdim bool HasFunScope = false; 644309124Sdim FNContextRAII() = delete; 645309124Sdim FNContextRAII(const FNContextRAII &) = delete; 646309124Sdim FNContextRAII &operator=(const FNContextRAII &) = delete; 647309124Sdim 648309124Sdimpublic: 649309124Sdim FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) { 650309124Sdim Decl *D = *Ptr.get().begin(); 651309124Sdim NamedDecl *ND = dyn_cast<NamedDecl>(D); 652309124Sdim RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); 653309124Sdim Sema &Actions = P.getActions(); 654309124Sdim 655309124Sdim // Allow 'this' within late-parsed attributes. 656344779Sdim ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(), 657309124Sdim ND && ND->isCXXInstanceMember()); 658309124Sdim 659309124Sdim // If the Decl is templatized, add template parameters to scope. 660309124Sdim HasTemplateScope = D->isTemplateDecl(); 661309124Sdim TempScope = 662309124Sdim new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope); 663309124Sdim if (HasTemplateScope) 664309124Sdim Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D); 665309124Sdim 666309124Sdim // If the Decl is on a function, add function parameters to the scope. 667309124Sdim HasFunScope = D->isFunctionOrFunctionTemplate(); 668327952Sdim FnScope = new Parser::ParseScope( 669327952Sdim &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope, 670327952Sdim HasFunScope); 671309124Sdim if (HasFunScope) 672309124Sdim Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D); 673309124Sdim } 674309124Sdim ~FNContextRAII() { 675309124Sdim if (HasFunScope) { 676309124Sdim P.getActions().ActOnExitFunctionContext(); 677309124Sdim FnScope->Exit(); // Pop scope, and remove Decls from IdResolver 678309124Sdim } 679309124Sdim if (HasTemplateScope) 680309124Sdim TempScope->Exit(); 681309124Sdim delete FnScope; 682309124Sdim delete TempScope; 683309124Sdim delete ThisScope; 684309124Sdim } 685309124Sdim}; 686309124Sdim} // namespace 687309124Sdim 688309124Sdim/// Parses clauses for 'declare simd' directive. 689309124Sdim/// clause: 690309124Sdim/// 'inbranch' | 'notinbranch' 691309124Sdim/// 'simdlen' '(' <expr> ')' 692309124Sdim/// { 'uniform' '(' <argument_list> ')' } 693309124Sdim/// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } 694309124Sdim/// { 'linear '(' <argument_list> [ ':' <step> ] ')' } 695309124Sdimstatic bool parseDeclareSimdClauses( 696309124Sdim Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, 697309124Sdim SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds, 698309124Sdim SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears, 699309124Sdim SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) { 700309124Sdim SourceRange BSRange; 701309124Sdim const Token &Tok = P.getCurToken(); 702309124Sdim bool IsError = false; 703309124Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) { 704309124Sdim if (Tok.isNot(tok::identifier)) 705309124Sdim break; 706309124Sdim OMPDeclareSimdDeclAttr::BranchStateTy Out; 707309124Sdim IdentifierInfo *II = Tok.getIdentifierInfo(); 708309124Sdim StringRef ClauseName = II->getName(); 709309124Sdim // Parse 'inranch|notinbranch' clauses. 710309124Sdim if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { 711309124Sdim if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { 712309124Sdim P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) 713309124Sdim << ClauseName 714309124Sdim << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; 715309124Sdim IsError = true; 716309124Sdim } 717309124Sdim BS = Out; 718309124Sdim BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); 719309124Sdim P.ConsumeToken(); 720309124Sdim } else if (ClauseName.equals("simdlen")) { 721309124Sdim if (SimdLen.isUsable()) { 722309124Sdim P.Diag(Tok, diag::err_omp_more_one_clause) 723309124Sdim << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; 724309124Sdim IsError = true; 725309124Sdim } 726309124Sdim P.ConsumeToken(); 727309124Sdim SourceLocation RLoc; 728309124Sdim SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); 729309124Sdim if (SimdLen.isInvalid()) 730309124Sdim IsError = true; 731309124Sdim } else { 732309124Sdim OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); 733309124Sdim if (CKind == OMPC_uniform || CKind == OMPC_aligned || 734309124Sdim CKind == OMPC_linear) { 735309124Sdim Parser::OpenMPVarListDataTy Data; 736341825Sdim SmallVectorImpl<Expr *> *Vars = &Uniforms; 737360784Sdim if (CKind == OMPC_aligned) { 738309124Sdim Vars = &Aligneds; 739360784Sdim } else if (CKind == OMPC_linear) { 740360784Sdim Data.ExtraModifier = OMPC_LINEAR_val; 741309124Sdim Vars = &Linears; 742360784Sdim } 743309124Sdim 744309124Sdim P.ConsumeToken(); 745309124Sdim if (P.ParseOpenMPVarList(OMPD_declare_simd, 746309124Sdim getOpenMPClauseKind(ClauseName), *Vars, Data)) 747309124Sdim IsError = true; 748341825Sdim if (CKind == OMPC_aligned) { 749309124Sdim Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr); 750341825Sdim } else if (CKind == OMPC_linear) { 751360784Sdim assert(0 <= Data.ExtraModifier && 752360784Sdim Data.ExtraModifier <= OMPC_LINEAR_unknown && 753360784Sdim "Unexpected linear modifier."); 754360784Sdim if (P.getActions().CheckOpenMPLinearModifier( 755360784Sdim static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier), 756360784Sdim Data.DepLinMapLastLoc)) 757360784Sdim Data.ExtraModifier = OMPC_LINEAR_val; 758309124Sdim LinModifiers.append(Linears.size() - LinModifiers.size(), 759360784Sdim Data.ExtraModifier); 760309124Sdim Steps.append(Linears.size() - Steps.size(), Data.TailExpr); 761309124Sdim } 762309124Sdim } else 763309124Sdim // TODO: add parsing of other clauses. 764309124Sdim break; 765309124Sdim } 766309124Sdim // Skip ',' if any. 767309124Sdim if (Tok.is(tok::comma)) 768309124Sdim P.ConsumeToken(); 769309124Sdim } 770309124Sdim return IsError; 771309124Sdim} 772309124Sdim 773309124Sdim/// Parse clauses for '#pragma omp declare simd'. 774309124SdimParser::DeclGroupPtrTy 775309124SdimParser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, 776309124Sdim CachedTokens &Toks, SourceLocation Loc) { 777353358Sdim PP.EnterToken(Tok, /*IsReinject*/ true); 778353358Sdim PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 779353358Sdim /*IsReinject*/ true); 780309124Sdim // Consume the previously pushed token. 781309124Sdim ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 782360784Sdim ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 783309124Sdim 784309124Sdim FNContextRAII FnContext(*this, Ptr); 785309124Sdim OMPDeclareSimdDeclAttr::BranchStateTy BS = 786309124Sdim OMPDeclareSimdDeclAttr::BS_Undefined; 787309124Sdim ExprResult Simdlen; 788309124Sdim SmallVector<Expr *, 4> Uniforms; 789309124Sdim SmallVector<Expr *, 4> Aligneds; 790309124Sdim SmallVector<Expr *, 4> Alignments; 791309124Sdim SmallVector<Expr *, 4> Linears; 792309124Sdim SmallVector<unsigned, 4> LinModifiers; 793309124Sdim SmallVector<Expr *, 4> Steps; 794309124Sdim bool IsError = 795309124Sdim parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, 796309124Sdim Alignments, Linears, LinModifiers, Steps); 797309124Sdim // Need to check for extra tokens. 798309124Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 799309124Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 800309124Sdim << getOpenMPDirectiveName(OMPD_declare_simd); 801309124Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) 802309124Sdim ConsumeAnyToken(); 803309124Sdim } 804309124Sdim // Skip the last annot_pragma_openmp_end. 805321369Sdim SourceLocation EndLoc = ConsumeAnnotationToken(); 806341825Sdim if (IsError) 807341825Sdim return Ptr; 808341825Sdim return Actions.ActOnOpenMPDeclareSimdDirective( 809341825Sdim Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, 810341825Sdim LinModifiers, Steps, SourceRange(Loc, EndLoc)); 811309124Sdim} 812309124Sdim 813360784Sdim/// Parse optional 'score' '(' <expr> ')' ':'. 814360784Sdimstatic ExprResult parseContextScore(Parser &P) { 815360784Sdim ExprResult ScoreExpr; 816360784Sdim Sema::OMPCtxStringType Buffer; 817360784Sdim StringRef SelectorName = 818360784Sdim P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); 819360784Sdim if (!SelectorName.equals("score")) 820360784Sdim return ScoreExpr; 821360784Sdim (void)P.ConsumeToken(); 822360784Sdim SourceLocation RLoc; 823360784Sdim ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); 824360784Sdim // Parse ':' 825360784Sdim if (P.getCurToken().is(tok::colon)) 826360784Sdim (void)P.ConsumeAnyToken(); 827360784Sdim else 828360784Sdim P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon) 829360784Sdim << "context selector score clause"; 830360784Sdim return ScoreExpr; 831360784Sdim} 832360784Sdim 833360784Sdim/// Parse context selector for 'implementation' selector set: 834360784Sdim/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> } 835360784Sdim/// ')' 836360784Sdimstatic void 837360784SdimparseImplementationSelector(Parser &P, SourceLocation Loc, 838360784Sdim llvm::StringMap<SourceLocation> &UsedCtx, 839360784Sdim SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) { 840360784Sdim const Token &Tok = P.getCurToken(); 841360784Sdim // Parse inner context selector set name, if any. 842360784Sdim if (!Tok.is(tok::identifier)) { 843360784Sdim P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) 844360784Sdim << "implementation"; 845360784Sdim // Skip until either '}', ')', or end of directive. 846360784Sdim while (!P.SkipUntil(tok::r_brace, tok::r_paren, 847360784Sdim tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 848360784Sdim ; 849360784Sdim return; 850360784Sdim } 851360784Sdim Sema::OMPCtxStringType Buffer; 852360784Sdim StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer); 853360784Sdim auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation()); 854360784Sdim if (!Res.second) { 855360784Sdim // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. 856360784Sdim // Each trait-selector-name can only be specified once. 857360784Sdim P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use) 858360784Sdim << CtxSelectorName << "implementation"; 859360784Sdim P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) 860360784Sdim << CtxSelectorName; 861360784Sdim } 862360784Sdim OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName); 863360784Sdim (void)P.ConsumeToken(); 864360784Sdim switch (CSKind) { 865360784Sdim case OMP_CTX_vendor: { 866360784Sdim // Parse '('. 867360784Sdim BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); 868360784Sdim (void)T.expectAndConsume(diag::err_expected_lparen_after, 869360784Sdim CtxSelectorName.data()); 870360784Sdim ExprResult Score = parseContextScore(P); 871360784Sdim llvm::UniqueVector<Sema::OMPCtxStringType> Vendors; 872360784Sdim do { 873360784Sdim // Parse <vendor>. 874360784Sdim StringRef VendorName; 875360784Sdim if (Tok.is(tok::identifier)) { 876360784Sdim Buffer.clear(); 877360784Sdim VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); 878360784Sdim (void)P.ConsumeToken(); 879360784Sdim if (!VendorName.empty()) 880360784Sdim Vendors.insert(VendorName); 881360784Sdim } else { 882360784Sdim P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) 883360784Sdim << "vendor identifier" 884360784Sdim << "vendor" 885360784Sdim << "implementation"; 886360784Sdim } 887360784Sdim if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) { 888360784Sdim P.Diag(Tok, diag::err_expected_punc) 889360784Sdim << (VendorName.empty() ? "vendor name" : VendorName); 890360784Sdim } 891360784Sdim } while (Tok.is(tok::identifier)); 892360784Sdim // Parse ')'. 893360784Sdim (void)T.consumeClose(); 894360784Sdim if (!Vendors.empty()) 895360784Sdim Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors); 896360784Sdim break; 897360784Sdim } 898360784Sdim case OMP_CTX_kind: 899360784Sdim case OMP_CTX_unknown: 900360784Sdim P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) 901360784Sdim << "implementation"; 902360784Sdim // Skip until either '}', ')', or end of directive. 903360784Sdim while (!P.SkipUntil(tok::r_brace, tok::r_paren, 904360784Sdim tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 905360784Sdim ; 906360784Sdim return; 907360784Sdim } 908360784Sdim} 909360784Sdim 910360784Sdim/// Parse context selector for 'device' selector set: 911360784Sdim/// 'kind' '(' <kind> { ',' <kind> } ')' 912360784Sdimstatic void 913360784SdimparseDeviceSelector(Parser &P, SourceLocation Loc, 914360784Sdim llvm::StringMap<SourceLocation> &UsedCtx, 915360784Sdim SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) { 916360784Sdim const Token &Tok = P.getCurToken(); 917360784Sdim // Parse inner context selector set name, if any. 918360784Sdim if (!Tok.is(tok::identifier)) { 919360784Sdim P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) 920360784Sdim << "device"; 921360784Sdim // Skip until either '}', ')', or end of directive. 922360784Sdim while (!P.SkipUntil(tok::r_brace, tok::r_paren, 923360784Sdim tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 924360784Sdim ; 925360784Sdim return; 926360784Sdim } 927360784Sdim Sema::OMPCtxStringType Buffer; 928360784Sdim StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer); 929360784Sdim auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation()); 930360784Sdim if (!Res.second) { 931360784Sdim // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. 932360784Sdim // Each trait-selector-name can only be specified once. 933360784Sdim P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use) 934360784Sdim << CtxSelectorName << "device"; 935360784Sdim P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) 936360784Sdim << CtxSelectorName; 937360784Sdim } 938360784Sdim OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName); 939360784Sdim (void)P.ConsumeToken(); 940360784Sdim switch (CSKind) { 941360784Sdim case OMP_CTX_kind: { 942360784Sdim // Parse '('. 943360784Sdim BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); 944360784Sdim (void)T.expectAndConsume(diag::err_expected_lparen_after, 945360784Sdim CtxSelectorName.data()); 946360784Sdim llvm::UniqueVector<Sema::OMPCtxStringType> Kinds; 947360784Sdim do { 948360784Sdim // Parse <kind>. 949360784Sdim StringRef KindName; 950360784Sdim if (Tok.is(tok::identifier)) { 951360784Sdim Buffer.clear(); 952360784Sdim KindName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); 953360784Sdim SourceLocation SLoc = P.getCurToken().getLocation(); 954360784Sdim (void)P.ConsumeToken(); 955360784Sdim if (llvm::StringSwitch<bool>(KindName) 956360784Sdim .Case("host", false) 957360784Sdim .Case("nohost", false) 958360784Sdim .Case("cpu", false) 959360784Sdim .Case("gpu", false) 960360784Sdim .Case("fpga", false) 961360784Sdim .Default(true)) { 962360784Sdim P.Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName; 963360784Sdim } else { 964360784Sdim Kinds.insert(KindName); 965360784Sdim } 966360784Sdim } else { 967360784Sdim P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) 968360784Sdim << "'host', 'nohost', 'cpu', 'gpu', or 'fpga'" 969360784Sdim << "kind" 970360784Sdim << "device"; 971360784Sdim } 972360784Sdim if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) { 973360784Sdim P.Diag(Tok, diag::err_expected_punc) 974360784Sdim << (KindName.empty() ? "kind of device" : KindName); 975360784Sdim } 976360784Sdim } while (Tok.is(tok::identifier)); 977360784Sdim // Parse ')'. 978360784Sdim (void)T.consumeClose(); 979360784Sdim if (!Kinds.empty()) 980360784Sdim Data.emplace_back(OMP_CTX_SET_device, CSKind, ExprResult(), Kinds); 981360784Sdim break; 982360784Sdim } 983360784Sdim case OMP_CTX_vendor: 984360784Sdim case OMP_CTX_unknown: 985360784Sdim P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) 986360784Sdim << "device"; 987360784Sdim // Skip until either '}', ')', or end of directive. 988360784Sdim while (!P.SkipUntil(tok::r_brace, tok::r_paren, 989360784Sdim tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 990360784Sdim ; 991360784Sdim return; 992360784Sdim } 993360784Sdim} 994360784Sdim 995360784Sdim/// Parses clauses for 'declare variant' directive. 996360784Sdim/// clause: 997360784Sdim/// <selector_set_name> '=' '{' <context_selectors> '}' 998360784Sdim/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ] 999360784Sdimbool Parser::parseOpenMPContextSelectors( 1000360784Sdim SourceLocation Loc, SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) { 1001360784Sdim llvm::StringMap<SourceLocation> UsedCtxSets; 1002360784Sdim do { 1003360784Sdim // Parse inner context selector set name. 1004360784Sdim if (!Tok.is(tok::identifier)) { 1005360784Sdim Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector) 1006360784Sdim << getOpenMPClauseName(OMPC_match); 1007360784Sdim return true; 1008360784Sdim } 1009360784Sdim Sema::OMPCtxStringType Buffer; 1010360784Sdim StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer); 1011360784Sdim auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation()); 1012360784Sdim if (!Res.second) { 1013360784Sdim // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. 1014360784Sdim // Each trait-set-selector-name can only be specified once. 1015360784Sdim Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_set_mutiple_use) 1016360784Sdim << CtxSelectorSetName; 1017360784Sdim Diag(Res.first->getValue(), 1018360784Sdim diag::note_omp_declare_variant_ctx_set_used_here) 1019360784Sdim << CtxSelectorSetName; 1020360784Sdim } 1021360784Sdim // Parse '='. 1022360784Sdim (void)ConsumeToken(); 1023360784Sdim if (Tok.isNot(tok::equal)) { 1024360784Sdim Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected) 1025360784Sdim << CtxSelectorSetName; 1026360784Sdim return true; 1027360784Sdim } 1028360784Sdim (void)ConsumeToken(); 1029360784Sdim // TBD: add parsing of known context selectors. 1030360784Sdim // Unknown selector - just ignore it completely. 1031360784Sdim { 1032360784Sdim // Parse '{'. 1033360784Sdim BalancedDelimiterTracker TBr(*this, tok::l_brace, 1034360784Sdim tok::annot_pragma_openmp_end); 1035360784Sdim if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "=")) 1036360784Sdim return true; 1037360784Sdim OpenMPContextSelectorSetKind CSSKind = 1038360784Sdim getOpenMPContextSelectorSet(CtxSelectorSetName); 1039360784Sdim llvm::StringMap<SourceLocation> UsedCtx; 1040360784Sdim do { 1041360784Sdim switch (CSSKind) { 1042360784Sdim case OMP_CTX_SET_implementation: 1043360784Sdim parseImplementationSelector(*this, Loc, UsedCtx, Data); 1044360784Sdim break; 1045360784Sdim case OMP_CTX_SET_device: 1046360784Sdim parseDeviceSelector(*this, Loc, UsedCtx, Data); 1047360784Sdim break; 1048360784Sdim case OMP_CTX_SET_unknown: 1049360784Sdim // Skip until either '}', ')', or end of directive. 1050360784Sdim while (!SkipUntil(tok::r_brace, tok::r_paren, 1051360784Sdim tok::annot_pragma_openmp_end, StopBeforeMatch)) 1052360784Sdim ; 1053360784Sdim break; 1054360784Sdim } 1055360784Sdim const Token PrevTok = Tok; 1056360784Sdim if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace)) 1057360784Sdim Diag(Tok, diag::err_omp_expected_comma_brace) 1058360784Sdim << (PrevTok.isAnnotation() ? "context selector trait" 1059360784Sdim : PP.getSpelling(PrevTok)); 1060360784Sdim } while (Tok.is(tok::identifier)); 1061360784Sdim // Parse '}'. 1062360784Sdim (void)TBr.consumeClose(); 1063360784Sdim } 1064360784Sdim // Consume ',' 1065360784Sdim if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) 1066360784Sdim (void)ExpectAndConsume(tok::comma); 1067360784Sdim } while (Tok.isAnyIdentifier()); 1068360784Sdim return false; 1069360784Sdim} 1070360784Sdim 1071360784Sdim/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'. 1072360784Sdimvoid Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, 1073360784Sdim CachedTokens &Toks, 1074360784Sdim SourceLocation Loc) { 1075360784Sdim PP.EnterToken(Tok, /*IsReinject*/ true); 1076360784Sdim PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 1077360784Sdim /*IsReinject*/ true); 1078360784Sdim // Consume the previously pushed token. 1079360784Sdim ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1080360784Sdim ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1081360784Sdim 1082360784Sdim FNContextRAII FnContext(*this, Ptr); 1083360784Sdim // Parse function declaration id. 1084360784Sdim SourceLocation RLoc; 1085360784Sdim // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs 1086360784Sdim // instead of MemberExprs. 1087360784Sdim ExprResult AssociatedFunction; 1088360784Sdim { 1089360784Sdim // Do not mark function as is used to prevent its emission if this is the 1090360784Sdim // only place where it is used. 1091360784Sdim EnterExpressionEvaluationContext Unevaluated( 1092360784Sdim Actions, Sema::ExpressionEvaluationContext::Unevaluated); 1093360784Sdim AssociatedFunction = ParseOpenMPParensExpr( 1094360784Sdim getOpenMPDirectiveName(OMPD_declare_variant), RLoc, 1095360784Sdim /*IsAddressOfOperand=*/true); 1096360784Sdim } 1097360784Sdim if (!AssociatedFunction.isUsable()) { 1098360784Sdim if (!Tok.is(tok::annot_pragma_openmp_end)) 1099360784Sdim while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1100360784Sdim ; 1101360784Sdim // Skip the last annot_pragma_openmp_end. 1102360784Sdim (void)ConsumeAnnotationToken(); 1103360784Sdim return; 1104360784Sdim } 1105360784Sdim Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = 1106360784Sdim Actions.checkOpenMPDeclareVariantFunction( 1107360784Sdim Ptr, AssociatedFunction.get(), SourceRange(Loc, Tok.getLocation())); 1108360784Sdim 1109360784Sdim // Parse 'match'. 1110360784Sdim OpenMPClauseKind CKind = Tok.isAnnotation() 1111360784Sdim ? OMPC_unknown 1112360784Sdim : getOpenMPClauseKind(PP.getSpelling(Tok)); 1113360784Sdim if (CKind != OMPC_match) { 1114360784Sdim Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1115360784Sdim << getOpenMPClauseName(OMPC_match); 1116360784Sdim while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 1117360784Sdim ; 1118360784Sdim // Skip the last annot_pragma_openmp_end. 1119360784Sdim (void)ConsumeAnnotationToken(); 1120360784Sdim return; 1121360784Sdim } 1122360784Sdim (void)ConsumeToken(); 1123360784Sdim // Parse '('. 1124360784Sdim BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1125360784Sdim if (T.expectAndConsume(diag::err_expected_lparen_after, 1126360784Sdim getOpenMPClauseName(OMPC_match))) { 1127360784Sdim while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1128360784Sdim ; 1129360784Sdim // Skip the last annot_pragma_openmp_end. 1130360784Sdim (void)ConsumeAnnotationToken(); 1131360784Sdim return; 1132360784Sdim } 1133360784Sdim 1134360784Sdim // Parse inner context selectors. 1135360784Sdim SmallVector<Sema::OMPCtxSelectorData, 4> Data; 1136360784Sdim if (!parseOpenMPContextSelectors(Loc, Data)) { 1137360784Sdim // Parse ')'. 1138360784Sdim (void)T.consumeClose(); 1139360784Sdim // Need to check for extra tokens. 1140360784Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1141360784Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1142360784Sdim << getOpenMPDirectiveName(OMPD_declare_variant); 1143360784Sdim } 1144360784Sdim } 1145360784Sdim 1146360784Sdim // Skip last tokens. 1147360784Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) 1148360784Sdim ConsumeAnyToken(); 1149360784Sdim if (DeclVarData.hasValue()) 1150360784Sdim Actions.ActOnOpenMPDeclareVariantDirective( 1151360784Sdim DeclVarData.getValue().first, DeclVarData.getValue().second, 1152360784Sdim SourceRange(Loc, Tok.getLocation()), Data); 1153360784Sdim // Skip the last annot_pragma_openmp_end. 1154360784Sdim (void)ConsumeAnnotationToken(); 1155360784Sdim} 1156360784Sdim 1157360784Sdim/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1158360784Sdim/// 1159360784Sdim/// default-clause: 1160360784Sdim/// 'default' '(' 'none' | 'shared' ') 1161360784Sdim/// 1162360784Sdim/// proc_bind-clause: 1163360784Sdim/// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1164360784Sdim/// 1165360784Sdim/// device_type-clause: 1166360784Sdim/// 'device_type' '(' 'host' | 'nohost' | 'any' )' 1167360784Sdimnamespace { 1168360784Sdim struct SimpleClauseData { 1169360784Sdim unsigned Type; 1170360784Sdim SourceLocation Loc; 1171360784Sdim SourceLocation LOpen; 1172360784Sdim SourceLocation TypeLoc; 1173360784Sdim SourceLocation RLoc; 1174360784Sdim SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen, 1175360784Sdim SourceLocation TypeLoc, SourceLocation RLoc) 1176360784Sdim : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {} 1177360784Sdim }; 1178360784Sdim} // anonymous namespace 1179360784Sdim 1180360784Sdimstatic Optional<SimpleClauseData> 1181360784SdimparseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { 1182360784Sdim const Token &Tok = P.getCurToken(); 1183360784Sdim SourceLocation Loc = Tok.getLocation(); 1184360784Sdim SourceLocation LOpen = P.ConsumeToken(); 1185360784Sdim // Parse '('. 1186360784Sdim BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); 1187360784Sdim if (T.expectAndConsume(diag::err_expected_lparen_after, 1188360784Sdim getOpenMPClauseName(Kind))) 1189360784Sdim return llvm::None; 1190360784Sdim 1191360784Sdim unsigned Type = getOpenMPSimpleClauseType( 1192360784Sdim Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok)); 1193360784Sdim SourceLocation TypeLoc = Tok.getLocation(); 1194360784Sdim if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1195360784Sdim Tok.isNot(tok::annot_pragma_openmp_end)) 1196360784Sdim P.ConsumeAnyToken(); 1197360784Sdim 1198360784Sdim // Parse ')'. 1199360784Sdim SourceLocation RLoc = Tok.getLocation(); 1200360784Sdim if (!T.consumeClose()) 1201360784Sdim RLoc = T.getCloseLocation(); 1202360784Sdim 1203360784Sdim return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc); 1204360784Sdim} 1205360784Sdim 1206344779SdimParser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() { 1207344779Sdim // OpenMP 4.5 syntax with list of entities. 1208344779Sdim Sema::NamedDeclSetType SameDirectiveDecls; 1209360784Sdim SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation, 1210360784Sdim NamedDecl *>, 1211360784Sdim 4> 1212360784Sdim DeclareTargetDecls; 1213360784Sdim OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any; 1214360784Sdim SourceLocation DeviceTypeLoc; 1215344779Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1216344779Sdim OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; 1217344779Sdim if (Tok.is(tok::identifier)) { 1218344779Sdim IdentifierInfo *II = Tok.getIdentifierInfo(); 1219344779Sdim StringRef ClauseName = II->getName(); 1220360784Sdim bool IsDeviceTypeClause = 1221360784Sdim getLangOpts().OpenMP >= 50 && 1222360784Sdim getOpenMPClauseKind(ClauseName) == OMPC_device_type; 1223360784Sdim // Parse 'to|link|device_type' clauses. 1224360784Sdim if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) && 1225360784Sdim !IsDeviceTypeClause) { 1226360784Sdim Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 1227360784Sdim << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0); 1228344779Sdim break; 1229344779Sdim } 1230360784Sdim // Parse 'device_type' clause and go to next clause if any. 1231360784Sdim if (IsDeviceTypeClause) { 1232360784Sdim Optional<SimpleClauseData> DevTypeData = 1233360784Sdim parseOpenMPSimpleClause(*this, OMPC_device_type); 1234360784Sdim if (DevTypeData.hasValue()) { 1235360784Sdim if (DeviceTypeLoc.isValid()) { 1236360784Sdim // We already saw another device_type clause, diagnose it. 1237360784Sdim Diag(DevTypeData.getValue().Loc, 1238360784Sdim diag::warn_omp_more_one_device_type_clause); 1239360784Sdim } 1240360784Sdim switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) { 1241360784Sdim case OMPC_DEVICE_TYPE_any: 1242360784Sdim DT = OMPDeclareTargetDeclAttr::DT_Any; 1243360784Sdim break; 1244360784Sdim case OMPC_DEVICE_TYPE_host: 1245360784Sdim DT = OMPDeclareTargetDeclAttr::DT_Host; 1246360784Sdim break; 1247360784Sdim case OMPC_DEVICE_TYPE_nohost: 1248360784Sdim DT = OMPDeclareTargetDeclAttr::DT_NoHost; 1249360784Sdim break; 1250360784Sdim case OMPC_DEVICE_TYPE_unknown: 1251360784Sdim llvm_unreachable("Unexpected device_type"); 1252360784Sdim } 1253360784Sdim DeviceTypeLoc = DevTypeData.getValue().Loc; 1254360784Sdim } 1255360784Sdim continue; 1256360784Sdim } 1257344779Sdim ConsumeToken(); 1258344779Sdim } 1259360784Sdim auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls]( 1260360784Sdim CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 1261360784Sdim NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName( 1262360784Sdim getCurScope(), SS, NameInfo, SameDirectiveDecls); 1263360784Sdim if (ND) 1264360784Sdim DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND); 1265344779Sdim }; 1266344779Sdim if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 1267344779Sdim /*AllowScopeSpecifier=*/true)) 1268344779Sdim break; 1269344779Sdim 1270344779Sdim // Consume optional ','. 1271344779Sdim if (Tok.is(tok::comma)) 1272344779Sdim ConsumeToken(); 1273344779Sdim } 1274344779Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1275344779Sdim ConsumeAnyToken(); 1276360784Sdim for (auto &MTLocDecl : DeclareTargetDecls) { 1277360784Sdim OMPDeclareTargetDeclAttr::MapTypeTy MT; 1278360784Sdim SourceLocation Loc; 1279360784Sdim NamedDecl *ND; 1280360784Sdim std::tie(MT, Loc, ND) = MTLocDecl; 1281360784Sdim // device_type clause is applied only to functions. 1282360784Sdim Actions.ActOnOpenMPDeclareTargetName( 1283360784Sdim ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT); 1284360784Sdim } 1285344779Sdim SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), 1286344779Sdim SameDirectiveDecls.end()); 1287344779Sdim if (Decls.empty()) 1288344779Sdim return DeclGroupPtrTy(); 1289344779Sdim return Actions.BuildDeclaratorGroup(Decls); 1290344779Sdim} 1291344779Sdim 1292344779Sdimvoid Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, 1293344779Sdim SourceLocation DTLoc) { 1294344779Sdim if (DKind != OMPD_end_declare_target) { 1295344779Sdim Diag(Tok, diag::err_expected_end_declare_target); 1296344779Sdim Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'"; 1297344779Sdim return; 1298344779Sdim } 1299344779Sdim ConsumeAnyToken(); 1300344779Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1301344779Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1302344779Sdim << getOpenMPDirectiveName(OMPD_end_declare_target); 1303344779Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1304344779Sdim } 1305344779Sdim // Skip the last annot_pragma_openmp_end. 1306344779Sdim ConsumeAnyToken(); 1307344779Sdim} 1308344779Sdim 1309341825Sdim/// Parsing of declarative OpenMP directives. 1310249261Sdim/// 1311261991Sdim/// threadprivate-directive: 1312261991Sdim/// annot_pragma_openmp 'threadprivate' simple-variable-list 1313309124Sdim/// annot_pragma_openmp_end 1314261991Sdim/// 1315353358Sdim/// allocate-directive: 1316353358Sdim/// annot_pragma_openmp 'allocate' simple-variable-list [<clause>] 1317353358Sdim/// annot_pragma_openmp_end 1318353358Sdim/// 1319309124Sdim/// declare-reduction-directive: 1320309124Sdim/// annot_pragma_openmp 'declare' 'reduction' [...] 1321309124Sdim/// annot_pragma_openmp_end 1322309124Sdim/// 1323353358Sdim/// declare-mapper-directive: 1324353358Sdim/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 1325353358Sdim/// <type> <var> ')' [<clause>[[,] <clause>] ... ] 1326353358Sdim/// annot_pragma_openmp_end 1327353358Sdim/// 1328309124Sdim/// declare-simd-directive: 1329309124Sdim/// annot_pragma_openmp 'declare simd' {<clause> [,]} 1330309124Sdim/// annot_pragma_openmp_end 1331309124Sdim/// <function declaration/definition> 1332309124Sdim/// 1333344779Sdim/// requires directive: 1334344779Sdim/// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 1335344779Sdim/// annot_pragma_openmp_end 1336344779Sdim/// 1337309124SdimParser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 1338360784Sdim AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed, 1339309124Sdim DeclSpec::TST TagType, Decl *Tag) { 1340249261Sdim assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 1341360784Sdim ParsingOpenMPDirectiveRAII DirScope(*this); 1342261991Sdim ParenBraceBracketBalancer BalancerRAIIObj(*this); 1343249261Sdim 1344360784Sdim SourceLocation Loc; 1345360784Sdim OpenMPDirectiveKind DKind; 1346360784Sdim if (Delayed) { 1347360784Sdim TentativeParsingAction TPA(*this); 1348360784Sdim Loc = ConsumeAnnotationToken(); 1349360784Sdim DKind = parseOpenMPDirectiveKind(*this); 1350360784Sdim if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) { 1351360784Sdim // Need to delay parsing until completion of the parent class. 1352360784Sdim TPA.Revert(); 1353360784Sdim CachedTokens Toks; 1354360784Sdim unsigned Cnt = 1; 1355360784Sdim Toks.push_back(Tok); 1356360784Sdim while (Cnt && Tok.isNot(tok::eof)) { 1357360784Sdim (void)ConsumeAnyToken(); 1358360784Sdim if (Tok.is(tok::annot_pragma_openmp)) 1359360784Sdim ++Cnt; 1360360784Sdim else if (Tok.is(tok::annot_pragma_openmp_end)) 1361360784Sdim --Cnt; 1362360784Sdim Toks.push_back(Tok); 1363360784Sdim } 1364360784Sdim // Skip last annot_pragma_openmp_end. 1365360784Sdim if (Cnt == 0) 1366360784Sdim (void)ConsumeAnyToken(); 1367360784Sdim auto *LP = new LateParsedPragma(this, AS); 1368360784Sdim LP->takeToks(Toks); 1369360784Sdim getCurrentClass().LateParsedDeclarations.push_back(LP); 1370360784Sdim return nullptr; 1371360784Sdim } 1372360784Sdim TPA.Commit(); 1373360784Sdim } else { 1374360784Sdim Loc = ConsumeAnnotationToken(); 1375360784Sdim DKind = parseOpenMPDirectiveKind(*this); 1376360784Sdim } 1377261991Sdim 1378261991Sdim switch (DKind) { 1379309124Sdim case OMPD_threadprivate: { 1380249261Sdim ConsumeToken(); 1381353358Sdim DeclDirectiveListParserHelper Helper(this, DKind); 1382353358Sdim if (!ParseOpenMPSimpleVarList(DKind, Helper, 1383353358Sdim /*AllowScopeSpecifier=*/true)) { 1384249261Sdim // The last seen token is annot_pragma_openmp_end - need to check for 1385249261Sdim // extra tokens. 1386249261Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1387249261Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1388353358Sdim << getOpenMPDirectiveName(DKind); 1389261991Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1390249261Sdim } 1391261991Sdim // Skip the last annot_pragma_openmp_end. 1392321369Sdim ConsumeAnnotationToken(); 1393309124Sdim return Actions.ActOnOpenMPThreadprivateDirective(Loc, 1394309124Sdim Helper.getIdentifiers()); 1395249261Sdim } 1396249261Sdim break; 1397309124Sdim } 1398353358Sdim case OMPD_allocate: { 1399353358Sdim ConsumeToken(); 1400353358Sdim DeclDirectiveListParserHelper Helper(this, DKind); 1401353358Sdim if (!ParseOpenMPSimpleVarList(DKind, Helper, 1402353358Sdim /*AllowScopeSpecifier=*/true)) { 1403353358Sdim SmallVector<OMPClause *, 1> Clauses; 1404353358Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1405353358Sdim SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1406353358Sdim OMPC_unknown + 1> 1407353358Sdim FirstClauses(OMPC_unknown + 1); 1408353358Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1409353358Sdim OpenMPClauseKind CKind = 1410353358Sdim Tok.isAnnotation() ? OMPC_unknown 1411353358Sdim : getOpenMPClauseKind(PP.getSpelling(Tok)); 1412353358Sdim Actions.StartOpenMPClause(CKind); 1413353358Sdim OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind, 1414353358Sdim !FirstClauses[CKind].getInt()); 1415353358Sdim SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1416353358Sdim StopBeforeMatch); 1417353358Sdim FirstClauses[CKind].setInt(true); 1418353358Sdim if (Clause != nullptr) 1419353358Sdim Clauses.push_back(Clause); 1420353358Sdim if (Tok.is(tok::annot_pragma_openmp_end)) { 1421353358Sdim Actions.EndOpenMPClause(); 1422353358Sdim break; 1423353358Sdim } 1424353358Sdim // Skip ',' if any. 1425353358Sdim if (Tok.is(tok::comma)) 1426353358Sdim ConsumeToken(); 1427353358Sdim Actions.EndOpenMPClause(); 1428353358Sdim } 1429353358Sdim // The last seen token is annot_pragma_openmp_end - need to check for 1430353358Sdim // extra tokens. 1431353358Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1432353358Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1433353358Sdim << getOpenMPDirectiveName(DKind); 1434353358Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1435353358Sdim } 1436353358Sdim } 1437353358Sdim // Skip the last annot_pragma_openmp_end. 1438353358Sdim ConsumeAnnotationToken(); 1439353358Sdim return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(), 1440353358Sdim Clauses); 1441353358Sdim } 1442353358Sdim break; 1443353358Sdim } 1444344779Sdim case OMPD_requires: { 1445344779Sdim SourceLocation StartLoc = ConsumeToken(); 1446344779Sdim SmallVector<OMPClause *, 5> Clauses; 1447344779Sdim SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 1448344779Sdim FirstClauses(OMPC_unknown + 1); 1449344779Sdim if (Tok.is(tok::annot_pragma_openmp_end)) { 1450353358Sdim Diag(Tok, diag::err_omp_expected_clause) 1451344779Sdim << getOpenMPDirectiveName(OMPD_requires); 1452344779Sdim break; 1453344779Sdim } 1454344779Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1455344779Sdim OpenMPClauseKind CKind = Tok.isAnnotation() 1456344779Sdim ? OMPC_unknown 1457344779Sdim : getOpenMPClauseKind(PP.getSpelling(Tok)); 1458344779Sdim Actions.StartOpenMPClause(CKind); 1459353358Sdim OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind, 1460353358Sdim !FirstClauses[CKind].getInt()); 1461353358Sdim SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1462353358Sdim StopBeforeMatch); 1463344779Sdim FirstClauses[CKind].setInt(true); 1464344779Sdim if (Clause != nullptr) 1465344779Sdim Clauses.push_back(Clause); 1466344779Sdim if (Tok.is(tok::annot_pragma_openmp_end)) { 1467344779Sdim Actions.EndOpenMPClause(); 1468344779Sdim break; 1469344779Sdim } 1470344779Sdim // Skip ',' if any. 1471344779Sdim if (Tok.is(tok::comma)) 1472344779Sdim ConsumeToken(); 1473344779Sdim Actions.EndOpenMPClause(); 1474344779Sdim } 1475344779Sdim // Consume final annot_pragma_openmp_end 1476344779Sdim if (Clauses.size() == 0) { 1477344779Sdim Diag(Tok, diag::err_omp_expected_clause) 1478344779Sdim << getOpenMPDirectiveName(OMPD_requires); 1479344779Sdim ConsumeAnnotationToken(); 1480344779Sdim return nullptr; 1481344779Sdim } 1482344779Sdim ConsumeAnnotationToken(); 1483344779Sdim return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 1484344779Sdim } 1485309124Sdim case OMPD_declare_reduction: 1486309124Sdim ConsumeToken(); 1487341825Sdim if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 1488309124Sdim // The last seen token is annot_pragma_openmp_end - need to check for 1489309124Sdim // extra tokens. 1490309124Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1491309124Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1492309124Sdim << getOpenMPDirectiveName(OMPD_declare_reduction); 1493309124Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) 1494309124Sdim ConsumeAnyToken(); 1495309124Sdim } 1496309124Sdim // Skip the last annot_pragma_openmp_end. 1497321369Sdim ConsumeAnnotationToken(); 1498309124Sdim return Res; 1499309124Sdim } 1500309124Sdim break; 1501353358Sdim case OMPD_declare_mapper: { 1502353358Sdim ConsumeToken(); 1503353358Sdim if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) { 1504353358Sdim // Skip the last annot_pragma_openmp_end. 1505353358Sdim ConsumeAnnotationToken(); 1506353358Sdim return Res; 1507353358Sdim } 1508353358Sdim break; 1509353358Sdim } 1510360784Sdim case OMPD_declare_variant: 1511309124Sdim case OMPD_declare_simd: { 1512309124Sdim // The syntax is: 1513360784Sdim // { #pragma omp declare {simd|variant} } 1514309124Sdim // <function-declaration-or-definition> 1515309124Sdim // 1516360784Sdim CachedTokens Toks; 1517360784Sdim Toks.push_back(Tok); 1518309124Sdim ConsumeToken(); 1519309124Sdim while(Tok.isNot(tok::annot_pragma_openmp_end)) { 1520309124Sdim Toks.push_back(Tok); 1521309124Sdim ConsumeAnyToken(); 1522309124Sdim } 1523309124Sdim Toks.push_back(Tok); 1524309124Sdim ConsumeAnyToken(); 1525309124Sdim 1526309124Sdim DeclGroupPtrTy Ptr; 1527341825Sdim if (Tok.is(tok::annot_pragma_openmp)) { 1528360784Sdim Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, 1529360784Sdim TagType, Tag); 1530341825Sdim } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 1531309124Sdim // Here we expect to see some function declaration. 1532309124Sdim if (AS == AS_none) { 1533309124Sdim assert(TagType == DeclSpec::TST_unspecified); 1534309124Sdim MaybeParseCXX11Attributes(Attrs); 1535309124Sdim ParsingDeclSpec PDS(*this); 1536309124Sdim Ptr = ParseExternalDeclaration(Attrs, &PDS); 1537309124Sdim } else { 1538309124Sdim Ptr = 1539309124Sdim ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1540309124Sdim } 1541309124Sdim } 1542309124Sdim if (!Ptr) { 1543360784Sdim Diag(Loc, diag::err_omp_decl_in_declare_simd_variant) 1544360784Sdim << (DKind == OMPD_declare_simd ? 0 : 1); 1545309124Sdim return DeclGroupPtrTy(); 1546309124Sdim } 1547360784Sdim if (DKind == OMPD_declare_simd) 1548360784Sdim return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 1549360784Sdim assert(DKind == OMPD_declare_variant && 1550360784Sdim "Expected declare variant directive only"); 1551360784Sdim ParseOMPDeclareVariantClauses(Ptr, Toks, Loc); 1552360784Sdim return Ptr; 1553309124Sdim } 1554309124Sdim case OMPD_declare_target: { 1555309124Sdim SourceLocation DTLoc = ConsumeAnyToken(); 1556309124Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1557344779Sdim return ParseOMPDeclareTargetClauses(); 1558309124Sdim } 1559309124Sdim 1560309124Sdim // Skip the last annot_pragma_openmp_end. 1561309124Sdim ConsumeAnyToken(); 1562309124Sdim 1563309124Sdim if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc)) 1564309124Sdim return DeclGroupPtrTy(); 1565309124Sdim 1566341825Sdim llvm::SmallVector<Decl *, 4> Decls; 1567341825Sdim DKind = parseOpenMPDirectiveKind(*this); 1568344779Sdim while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) && 1569344779Sdim Tok.isNot(tok::r_brace)) { 1570327952Sdim DeclGroupPtrTy Ptr; 1571327952Sdim // Here we expect to see some function declaration. 1572327952Sdim if (AS == AS_none) { 1573327952Sdim assert(TagType == DeclSpec::TST_unspecified); 1574327952Sdim MaybeParseCXX11Attributes(Attrs); 1575327952Sdim ParsingDeclSpec PDS(*this); 1576327952Sdim Ptr = ParseExternalDeclaration(Attrs, &PDS); 1577327952Sdim } else { 1578327952Sdim Ptr = 1579327952Sdim ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1580327952Sdim } 1581341825Sdim if (Ptr) { 1582341825Sdim DeclGroupRef Ref = Ptr.get(); 1583341825Sdim Decls.append(Ref.begin(), Ref.end()); 1584341825Sdim } 1585309124Sdim if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { 1586309124Sdim TentativeParsingAction TPA(*this); 1587321369Sdim ConsumeAnnotationToken(); 1588341825Sdim DKind = parseOpenMPDirectiveKind(*this); 1589309124Sdim if (DKind != OMPD_end_declare_target) 1590309124Sdim TPA.Revert(); 1591309124Sdim else 1592309124Sdim TPA.Commit(); 1593309124Sdim } 1594309124Sdim } 1595309124Sdim 1596344779Sdim ParseOMPEndDeclareTargetDirective(DKind, DTLoc); 1597309124Sdim Actions.ActOnFinishOpenMPDeclareTargetDirective(); 1598341825Sdim return Actions.BuildDeclaratorGroup(Decls); 1599309124Sdim } 1600249261Sdim case OMPD_unknown: 1601249261Sdim Diag(Tok, diag::err_omp_unknown_directive); 1602249261Sdim break; 1603261991Sdim case OMPD_parallel: 1604276479Sdim case OMPD_simd: 1605261991Sdim case OMPD_task: 1606276479Sdim case OMPD_taskyield: 1607276479Sdim case OMPD_barrier: 1608276479Sdim case OMPD_taskwait: 1609288943Sdim case OMPD_taskgroup: 1610276479Sdim case OMPD_flush: 1611276479Sdim case OMPD_for: 1612280031Sdim case OMPD_for_simd: 1613276479Sdim case OMPD_sections: 1614276479Sdim case OMPD_section: 1615276479Sdim case OMPD_single: 1616276479Sdim case OMPD_master: 1617280031Sdim case OMPD_ordered: 1618276479Sdim case OMPD_critical: 1619276479Sdim case OMPD_parallel_for: 1620280031Sdim case OMPD_parallel_for_simd: 1621276479Sdim case OMPD_parallel_sections: 1622360784Sdim case OMPD_parallel_master: 1623280031Sdim case OMPD_atomic: 1624280031Sdim case OMPD_target: 1625280031Sdim case OMPD_teams: 1626288943Sdim case OMPD_cancellation_point: 1627288943Sdim case OMPD_cancel: 1628296417Sdim case OMPD_target_data: 1629309124Sdim case OMPD_target_enter_data: 1630309124Sdim case OMPD_target_exit_data: 1631309124Sdim case OMPD_target_parallel: 1632309124Sdim case OMPD_target_parallel_for: 1633296417Sdim case OMPD_taskloop: 1634296417Sdim case OMPD_taskloop_simd: 1635360784Sdim case OMPD_master_taskloop: 1636360784Sdim case OMPD_master_taskloop_simd: 1637360784Sdim case OMPD_parallel_master_taskloop: 1638360784Sdim case OMPD_parallel_master_taskloop_simd: 1639296417Sdim case OMPD_distribute: 1640309124Sdim case OMPD_end_declare_target: 1641309124Sdim case OMPD_target_update: 1642309124Sdim case OMPD_distribute_parallel_for: 1643309124Sdim case OMPD_distribute_parallel_for_simd: 1644309124Sdim case OMPD_distribute_simd: 1645309124Sdim case OMPD_target_parallel_for_simd: 1646314564Sdim case OMPD_target_simd: 1647314564Sdim case OMPD_teams_distribute: 1648314564Sdim case OMPD_teams_distribute_simd: 1649314564Sdim case OMPD_teams_distribute_parallel_for_simd: 1650314564Sdim case OMPD_teams_distribute_parallel_for: 1651314564Sdim case OMPD_target_teams: 1652314564Sdim case OMPD_target_teams_distribute: 1653314564Sdim case OMPD_target_teams_distribute_parallel_for: 1654314564Sdim case OMPD_target_teams_distribute_parallel_for_simd: 1655314564Sdim case OMPD_target_teams_distribute_simd: 1656249261Sdim Diag(Tok, diag::err_omp_unexpected_directive) 1657341825Sdim << 1 << getOpenMPDirectiveName(DKind); 1658249261Sdim break; 1659249261Sdim } 1660309124Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) 1661309124Sdim ConsumeAnyToken(); 1662309124Sdim ConsumeAnyToken(); 1663309124Sdim return nullptr; 1664249261Sdim} 1665249261Sdim 1666341825Sdim/// Parsing of declarative or executable OpenMP directives. 1667261991Sdim/// 1668261991Sdim/// threadprivate-directive: 1669261991Sdim/// annot_pragma_openmp 'threadprivate' simple-variable-list 1670261991Sdim/// annot_pragma_openmp_end 1671261991Sdim/// 1672353358Sdim/// allocate-directive: 1673353358Sdim/// annot_pragma_openmp 'allocate' simple-variable-list 1674353358Sdim/// annot_pragma_openmp_end 1675353358Sdim/// 1676309124Sdim/// declare-reduction-directive: 1677309124Sdim/// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 1678309124Sdim/// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 1679309124Sdim/// ('omp_priv' '=' <expression>|<function_call>) ')'] 1680309124Sdim/// annot_pragma_openmp_end 1681309124Sdim/// 1682353358Sdim/// declare-mapper-directive: 1683353358Sdim/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 1684353358Sdim/// <type> <var> ')' [<clause>[[,] <clause>] ... ] 1685353358Sdim/// annot_pragma_openmp_end 1686353358Sdim/// 1687276479Sdim/// executable-directive: 1688276479Sdim/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 1689276479Sdim/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 1690360784Sdim/// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' | 1691360784Sdim/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 1692360784Sdim/// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target 1693360784Sdim/// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 1694360784Sdim/// 'master taskloop' | 'master taskloop simd' | 'parallel master 1695360784Sdim/// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target 1696360784Sdim/// enter data' | 'target exit data' | 'target parallel' | 'target 1697360784Sdim/// parallel for' | 'target update' | 'distribute parallel for' | 1698360784Sdim/// 'distribute paralle for simd' | 'distribute simd' | 'target parallel 1699360784Sdim/// for simd' | 'target simd' | 'teams distribute' | 'teams distribute 1700360784Sdim/// simd' | 'teams distribute parallel for simd' | 'teams distribute 1701360784Sdim/// parallel for' | 'target teams' | 'target teams distribute' | 'target 1702360784Sdim/// teams distribute parallel for' | 'target teams distribute parallel 1703360784Sdim/// for simd' | 'target teams distribute simd' {clause} 1704280031Sdim/// annot_pragma_openmp_end 1705261991Sdim/// 1706353358SdimStmtResult 1707353358SdimParser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { 1708261991Sdim assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 1709360784Sdim ParsingOpenMPDirectiveRAII DirScope(*this); 1710261991Sdim ParenBraceBracketBalancer BalancerRAIIObj(*this); 1711261991Sdim SmallVector<OMPClause *, 5> Clauses; 1712276479Sdim SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 1713276479Sdim FirstClauses(OMPC_unknown + 1); 1714327952Sdim unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 1715327952Sdim Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 1716321369Sdim SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; 1717341825Sdim OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 1718288943Sdim OpenMPDirectiveKind CancelRegion = OMPD_unknown; 1719261991Sdim // Name of critical directive. 1720261991Sdim DeclarationNameInfo DirName; 1721261991Sdim StmtResult Directive = StmtError(); 1722276479Sdim bool HasAssociatedStatement = true; 1723276479Sdim bool FlushHasClause = false; 1724261991Sdim 1725261991Sdim switch (DKind) { 1726309124Sdim case OMPD_threadprivate: { 1727353358Sdim // FIXME: Should this be permitted in C++? 1728353358Sdim if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 1729353358Sdim ParsedStmtContext()) { 1730296417Sdim Diag(Tok, diag::err_omp_immediate_directive) 1731296417Sdim << getOpenMPDirectiveName(DKind) << 0; 1732296417Sdim } 1733261991Sdim ConsumeToken(); 1734353358Sdim DeclDirectiveListParserHelper Helper(this, DKind); 1735353358Sdim if (!ParseOpenMPSimpleVarList(DKind, Helper, 1736353358Sdim /*AllowScopeSpecifier=*/false)) { 1737261991Sdim // The last seen token is annot_pragma_openmp_end - need to check for 1738261991Sdim // extra tokens. 1739261991Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1740261991Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1741353358Sdim << getOpenMPDirectiveName(DKind); 1742261991Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1743261991Sdim } 1744309124Sdim DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 1745309124Sdim Loc, Helper.getIdentifiers()); 1746261991Sdim Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1747261991Sdim } 1748261991Sdim SkipUntil(tok::annot_pragma_openmp_end); 1749261991Sdim break; 1750309124Sdim } 1751353358Sdim case OMPD_allocate: { 1752353358Sdim // FIXME: Should this be permitted in C++? 1753353358Sdim if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 1754353358Sdim ParsedStmtContext()) { 1755353358Sdim Diag(Tok, diag::err_omp_immediate_directive) 1756353358Sdim << getOpenMPDirectiveName(DKind) << 0; 1757353358Sdim } 1758353358Sdim ConsumeToken(); 1759353358Sdim DeclDirectiveListParserHelper Helper(this, DKind); 1760353358Sdim if (!ParseOpenMPSimpleVarList(DKind, Helper, 1761353358Sdim /*AllowScopeSpecifier=*/false)) { 1762353358Sdim SmallVector<OMPClause *, 1> Clauses; 1763353358Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1764353358Sdim SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1765353358Sdim OMPC_unknown + 1> 1766353358Sdim FirstClauses(OMPC_unknown + 1); 1767353358Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1768353358Sdim OpenMPClauseKind CKind = 1769353358Sdim Tok.isAnnotation() ? OMPC_unknown 1770353358Sdim : getOpenMPClauseKind(PP.getSpelling(Tok)); 1771353358Sdim Actions.StartOpenMPClause(CKind); 1772353358Sdim OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind, 1773353358Sdim !FirstClauses[CKind].getInt()); 1774353358Sdim SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1775353358Sdim StopBeforeMatch); 1776353358Sdim FirstClauses[CKind].setInt(true); 1777353358Sdim if (Clause != nullptr) 1778353358Sdim Clauses.push_back(Clause); 1779353358Sdim if (Tok.is(tok::annot_pragma_openmp_end)) { 1780353358Sdim Actions.EndOpenMPClause(); 1781353358Sdim break; 1782353358Sdim } 1783353358Sdim // Skip ',' if any. 1784353358Sdim if (Tok.is(tok::comma)) 1785353358Sdim ConsumeToken(); 1786353358Sdim Actions.EndOpenMPClause(); 1787353358Sdim } 1788353358Sdim // The last seen token is annot_pragma_openmp_end - need to check for 1789353358Sdim // extra tokens. 1790353358Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1791353358Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1792353358Sdim << getOpenMPDirectiveName(DKind); 1793353358Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1794353358Sdim } 1795353358Sdim } 1796353358Sdim DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( 1797353358Sdim Loc, Helper.getIdentifiers(), Clauses); 1798353358Sdim Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1799353358Sdim } 1800353358Sdim SkipUntil(tok::annot_pragma_openmp_end); 1801353358Sdim break; 1802353358Sdim } 1803309124Sdim case OMPD_declare_reduction: 1804309124Sdim ConsumeToken(); 1805341825Sdim if (DeclGroupPtrTy Res = 1806341825Sdim ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 1807309124Sdim // The last seen token is annot_pragma_openmp_end - need to check for 1808309124Sdim // extra tokens. 1809309124Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1810309124Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1811309124Sdim << getOpenMPDirectiveName(OMPD_declare_reduction); 1812309124Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) 1813309124Sdim ConsumeAnyToken(); 1814309124Sdim } 1815309124Sdim ConsumeAnyToken(); 1816309124Sdim Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1817341825Sdim } else { 1818309124Sdim SkipUntil(tok::annot_pragma_openmp_end); 1819341825Sdim } 1820309124Sdim break; 1821353358Sdim case OMPD_declare_mapper: { 1822353358Sdim ConsumeToken(); 1823353358Sdim if (DeclGroupPtrTy Res = 1824353358Sdim ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 1825353358Sdim // Skip the last annot_pragma_openmp_end. 1826353358Sdim ConsumeAnnotationToken(); 1827353358Sdim Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1828353358Sdim } else { 1829353358Sdim SkipUntil(tok::annot_pragma_openmp_end); 1830353358Sdim } 1831353358Sdim break; 1832353358Sdim } 1833276479Sdim case OMPD_flush: 1834276479Sdim if (PP.LookAhead(0).is(tok::l_paren)) { 1835276479Sdim FlushHasClause = true; 1836276479Sdim // Push copy of the current token back to stream to properly parse 1837276479Sdim // pseudo-clause OMPFlushClause. 1838353358Sdim PP.EnterToken(Tok, /*IsReinject*/ true); 1839276479Sdim } 1840321369Sdim LLVM_FALLTHROUGH; 1841276479Sdim case OMPD_taskyield: 1842276479Sdim case OMPD_barrier: 1843276479Sdim case OMPD_taskwait: 1844288943Sdim case OMPD_cancellation_point: 1845288943Sdim case OMPD_cancel: 1846309124Sdim case OMPD_target_enter_data: 1847309124Sdim case OMPD_target_exit_data: 1848309124Sdim case OMPD_target_update: 1849353358Sdim if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 1850353358Sdim ParsedStmtContext()) { 1851276479Sdim Diag(Tok, diag::err_omp_immediate_directive) 1852296417Sdim << getOpenMPDirectiveName(DKind) << 0; 1853276479Sdim } 1854276479Sdim HasAssociatedStatement = false; 1855276479Sdim // Fall through for further analysis. 1856321369Sdim LLVM_FALLTHROUGH; 1857276479Sdim case OMPD_parallel: 1858276479Sdim case OMPD_simd: 1859276479Sdim case OMPD_for: 1860280031Sdim case OMPD_for_simd: 1861276479Sdim case OMPD_sections: 1862276479Sdim case OMPD_single: 1863276479Sdim case OMPD_section: 1864276479Sdim case OMPD_master: 1865276479Sdim case OMPD_critical: 1866276479Sdim case OMPD_parallel_for: 1867280031Sdim case OMPD_parallel_for_simd: 1868276479Sdim case OMPD_parallel_sections: 1869360784Sdim case OMPD_parallel_master: 1870280031Sdim case OMPD_task: 1871280031Sdim case OMPD_ordered: 1872280031Sdim case OMPD_atomic: 1873280031Sdim case OMPD_target: 1874288943Sdim case OMPD_teams: 1875296417Sdim case OMPD_taskgroup: 1876296417Sdim case OMPD_target_data: 1877309124Sdim case OMPD_target_parallel: 1878309124Sdim case OMPD_target_parallel_for: 1879296417Sdim case OMPD_taskloop: 1880296417Sdim case OMPD_taskloop_simd: 1881360784Sdim case OMPD_master_taskloop: 1882360784Sdim case OMPD_master_taskloop_simd: 1883360784Sdim case OMPD_parallel_master_taskloop: 1884360784Sdim case OMPD_parallel_master_taskloop_simd: 1885309124Sdim case OMPD_distribute: 1886309124Sdim case OMPD_distribute_parallel_for: 1887309124Sdim case OMPD_distribute_parallel_for_simd: 1888309124Sdim case OMPD_distribute_simd: 1889314564Sdim case OMPD_target_parallel_for_simd: 1890314564Sdim case OMPD_target_simd: 1891314564Sdim case OMPD_teams_distribute: 1892314564Sdim case OMPD_teams_distribute_simd: 1893314564Sdim case OMPD_teams_distribute_parallel_for_simd: 1894314564Sdim case OMPD_teams_distribute_parallel_for: 1895314564Sdim case OMPD_target_teams: 1896314564Sdim case OMPD_target_teams_distribute: 1897314564Sdim case OMPD_target_teams_distribute_parallel_for: 1898314564Sdim case OMPD_target_teams_distribute_parallel_for_simd: 1899314564Sdim case OMPD_target_teams_distribute_simd: { 1900261991Sdim ConsumeToken(); 1901276479Sdim // Parse directive name of the 'critical' directive if any. 1902276479Sdim if (DKind == OMPD_critical) { 1903276479Sdim BalancedDelimiterTracker T(*this, tok::l_paren, 1904276479Sdim tok::annot_pragma_openmp_end); 1905276479Sdim if (!T.consumeOpen()) { 1906276479Sdim if (Tok.isAnyIdentifier()) { 1907276479Sdim DirName = 1908276479Sdim DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 1909276479Sdim ConsumeAnyToken(); 1910276479Sdim } else { 1911276479Sdim Diag(Tok, diag::err_omp_expected_identifier_for_critical); 1912276479Sdim } 1913276479Sdim T.consumeClose(); 1914276479Sdim } 1915288943Sdim } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 1916341825Sdim CancelRegion = parseOpenMPDirectiveKind(*this); 1917288943Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) 1918288943Sdim ConsumeToken(); 1919276479Sdim } 1920261991Sdim 1921276479Sdim if (isOpenMPLoopDirective(DKind)) 1922276479Sdim ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 1923276479Sdim if (isOpenMPSimdDirective(DKind)) 1924276479Sdim ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 1925276479Sdim ParseScope OMPDirectiveScope(this, ScopeFlags); 1926276479Sdim Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 1927261991Sdim 1928261991Sdim while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1929276479Sdim OpenMPClauseKind CKind = 1930276479Sdim Tok.isAnnotation() 1931276479Sdim ? OMPC_unknown 1932276479Sdim : FlushHasClause ? OMPC_flush 1933276479Sdim : getOpenMPClauseKind(PP.getSpelling(Tok)); 1934288943Sdim Actions.StartOpenMPClause(CKind); 1935276479Sdim FlushHasClause = false; 1936276479Sdim OMPClause *Clause = 1937276479Sdim ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); 1938261991Sdim FirstClauses[CKind].setInt(true); 1939261991Sdim if (Clause) { 1940261991Sdim FirstClauses[CKind].setPointer(Clause); 1941261991Sdim Clauses.push_back(Clause); 1942261991Sdim } 1943261991Sdim 1944261991Sdim // Skip ',' if any. 1945261991Sdim if (Tok.is(tok::comma)) 1946261991Sdim ConsumeToken(); 1947288943Sdim Actions.EndOpenMPClause(); 1948261991Sdim } 1949261991Sdim // End location of the directive. 1950261991Sdim EndLoc = Tok.getLocation(); 1951261991Sdim // Consume final annot_pragma_openmp_end. 1952321369Sdim ConsumeAnnotationToken(); 1953261991Sdim 1954296417Sdim // OpenMP [2.13.8, ordered Construct, Syntax] 1955296417Sdim // If the depend clause is specified, the ordered construct is a stand-alone 1956296417Sdim // directive. 1957296417Sdim if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) { 1958353358Sdim if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 1959353358Sdim ParsedStmtContext()) { 1960296417Sdim Diag(Loc, diag::err_omp_immediate_directive) 1961296417Sdim << getOpenMPDirectiveName(DKind) << 1 1962296417Sdim << getOpenMPClauseName(OMPC_depend); 1963296417Sdim } 1964296417Sdim HasAssociatedStatement = false; 1965296417Sdim } 1966296417Sdim 1967261991Sdim StmtResult AssociatedStmt; 1968276479Sdim if (HasAssociatedStatement) { 1969261991Sdim // The body is a block scope like in Lambdas and Blocks. 1970276479Sdim Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1971341825Sdim // FIXME: We create a bogus CompoundStmt scope to hold the contents of 1972341825Sdim // the captured region. Code elsewhere assumes that any FunctionScopeInfo 1973341825Sdim // should have at least one compound statement scope within it. 1974341825Sdim AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement()); 1975288943Sdim AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1976327952Sdim } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 1977327952Sdim DKind == OMPD_target_exit_data) { 1978327952Sdim Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1979341825Sdim AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 1980341825Sdim Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 1981341825Sdim /*isStmtExpr=*/false)); 1982327952Sdim AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1983261991Sdim } 1984296417Sdim Directive = Actions.ActOnOpenMPExecutableDirective( 1985296417Sdim DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 1986296417Sdim EndLoc); 1987261991Sdim 1988261991Sdim // Exit scope. 1989261991Sdim Actions.EndOpenMPDSABlock(Directive.get()); 1990261991Sdim OMPDirectiveScope.Exit(); 1991261991Sdim break; 1992276479Sdim } 1993309124Sdim case OMPD_declare_simd: 1994309124Sdim case OMPD_declare_target: 1995309124Sdim case OMPD_end_declare_target: 1996344779Sdim case OMPD_requires: 1997360784Sdim case OMPD_declare_variant: 1998309124Sdim Diag(Tok, diag::err_omp_unexpected_directive) 1999341825Sdim << 1 << getOpenMPDirectiveName(DKind); 2000309124Sdim SkipUntil(tok::annot_pragma_openmp_end); 2001309124Sdim break; 2002261991Sdim case OMPD_unknown: 2003261991Sdim Diag(Tok, diag::err_omp_unknown_directive); 2004261991Sdim SkipUntil(tok::annot_pragma_openmp_end); 2005261991Sdim break; 2006261991Sdim } 2007261991Sdim return Directive; 2008261991Sdim} 2009261991Sdim 2010309124Sdim// Parses simple list: 2011309124Sdim// simple-variable-list: 2012309124Sdim// '(' id-expression {, id-expression} ')' 2013309124Sdim// 2014309124Sdimbool Parser::ParseOpenMPSimpleVarList( 2015309124Sdim OpenMPDirectiveKind Kind, 2016309124Sdim const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & 2017309124Sdim Callback, 2018309124Sdim bool AllowScopeSpecifier) { 2019249261Sdim // Parse '('. 2020261991Sdim BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2021261991Sdim if (T.expectAndConsume(diag::err_expected_lparen_after, 2022360784Sdim getOpenMPDirectiveName(Kind).data())) 2023261991Sdim return true; 2024249261Sdim bool IsCorrect = true; 2025261991Sdim bool NoIdentIsFound = true; 2026249261Sdim 2027249261Sdim // Read tokens while ')' or annot_pragma_openmp_end is not found. 2028261991Sdim while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 2029249261Sdim CXXScopeSpec SS; 2030249261Sdim UnqualifiedId Name; 2031249261Sdim // Read var name. 2032249261Sdim Token PrevTok = Tok; 2033261991Sdim NoIdentIsFound = false; 2034249261Sdim 2035261991Sdim if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 2036309124Sdim ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) { 2037249261Sdim IsCorrect = false; 2038249261Sdim SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2039261991Sdim StopBeforeMatch); 2040321369Sdim } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr, 2041341825Sdim nullptr, Name)) { 2042249261Sdim IsCorrect = false; 2043249261Sdim SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2044261991Sdim StopBeforeMatch); 2045261991Sdim } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 2046261991Sdim Tok.isNot(tok::annot_pragma_openmp_end)) { 2047261991Sdim IsCorrect = false; 2048261991Sdim SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2049261991Sdim StopBeforeMatch); 2050276479Sdim Diag(PrevTok.getLocation(), diag::err_expected) 2051276479Sdim << tok::identifier 2052276479Sdim << SourceRange(PrevTok.getLocation(), PrevTokLocation); 2053249261Sdim } else { 2054309124Sdim Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 2055249261Sdim } 2056249261Sdim // Consume ','. 2057249261Sdim if (Tok.is(tok::comma)) { 2058249261Sdim ConsumeToken(); 2059249261Sdim } 2060261991Sdim } 2061249261Sdim 2062261991Sdim if (NoIdentIsFound) { 2063276479Sdim Diag(Tok, diag::err_expected) << tok::identifier; 2064261991Sdim IsCorrect = false; 2065249261Sdim } 2066249261Sdim 2067261991Sdim // Parse ')'. 2068261991Sdim IsCorrect = !T.consumeClose() && IsCorrect; 2069261991Sdim 2070309124Sdim return !IsCorrect; 2071249261Sdim} 2072261991Sdim 2073341825Sdim/// Parsing of OpenMP clauses. 2074261991Sdim/// 2075261991Sdim/// clause: 2076276479Sdim/// if-clause | final-clause | num_threads-clause | safelen-clause | 2077276479Sdim/// default-clause | private-clause | firstprivate-clause | shared-clause 2078276479Sdim/// | linear-clause | aligned-clause | collapse-clause | 2079276479Sdim/// lastprivate-clause | reduction-clause | proc_bind-clause | 2080276479Sdim/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 2081280031Sdim/// mergeable-clause | flush-clause | read-clause | write-clause | 2082296417Sdim/// update-clause | capture-clause | seq_cst-clause | device-clause | 2083296417Sdim/// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 2084296417Sdim/// thread_limit-clause | priority-clause | grainsize-clause | 2085309124Sdim/// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 2086327952Sdim/// from-clause | is_device_ptr-clause | task_reduction-clause | 2087353358Sdim/// in_reduction-clause | allocator-clause | allocate-clause 2088261991Sdim/// 2089261991SdimOMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 2090261991Sdim OpenMPClauseKind CKind, bool FirstClause) { 2091276479Sdim OMPClause *Clause = nullptr; 2092261991Sdim bool ErrorFound = false; 2093341825Sdim bool WrongDirective = false; 2094261991Sdim // Check if clause is allowed for the given directive. 2095360784Sdim if (CKind != OMPC_unknown && 2096360784Sdim !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { 2097276479Sdim Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 2098276479Sdim << getOpenMPDirectiveName(DKind); 2099261991Sdim ErrorFound = true; 2100341825Sdim WrongDirective = true; 2101261991Sdim } 2102261991Sdim 2103261991Sdim switch (CKind) { 2104276479Sdim case OMPC_final: 2105276479Sdim case OMPC_num_threads: 2106276479Sdim case OMPC_safelen: 2107296417Sdim case OMPC_simdlen: 2108276479Sdim case OMPC_collapse: 2109296417Sdim case OMPC_ordered: 2110296417Sdim case OMPC_device: 2111296417Sdim case OMPC_num_teams: 2112296417Sdim case OMPC_thread_limit: 2113296417Sdim case OMPC_priority: 2114296417Sdim case OMPC_grainsize: 2115296417Sdim case OMPC_num_tasks: 2116296417Sdim case OMPC_hint: 2117353358Sdim case OMPC_allocator: 2118276479Sdim // OpenMP [2.5, Restrictions] 2119276479Sdim // At most one num_threads clause can appear on the directive. 2120276479Sdim // OpenMP [2.8.1, simd construct, Restrictions] 2121276479Sdim // Only one safelen clause can appear on a simd directive. 2122296417Sdim // Only one simdlen clause can appear on a simd directive. 2123276479Sdim // Only one collapse clause can appear on a simd directive. 2124296417Sdim // OpenMP [2.9.1, target data construct, Restrictions] 2125296417Sdim // At most one device clause can appear on the directive. 2126276479Sdim // OpenMP [2.11.1, task Construct, Restrictions] 2127276479Sdim // At most one if clause can appear on the directive. 2128276479Sdim // At most one final clause can appear on the directive. 2129296417Sdim // OpenMP [teams Construct, Restrictions] 2130296417Sdim // At most one num_teams clause can appear on the directive. 2131296417Sdim // At most one thread_limit clause can appear on the directive. 2132296417Sdim // OpenMP [2.9.1, task Construct, Restrictions] 2133296417Sdim // At most one priority clause can appear on the directive. 2134296417Sdim // OpenMP [2.9.2, taskloop Construct, Restrictions] 2135296417Sdim // At most one grainsize clause can appear on the directive. 2136296417Sdim // OpenMP [2.9.2, taskloop Construct, Restrictions] 2137296417Sdim // At most one num_tasks clause can appear on the directive. 2138353358Sdim // OpenMP [2.11.3, allocate Directive, Restrictions] 2139353358Sdim // At most one allocator clause can appear on the directive. 2140276479Sdim if (!FirstClause) { 2141296417Sdim Diag(Tok, diag::err_omp_more_one_clause) 2142296417Sdim << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2143280031Sdim ErrorFound = true; 2144276479Sdim } 2145276479Sdim 2146296417Sdim if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 2147341825Sdim Clause = ParseOpenMPClause(CKind, WrongDirective); 2148296417Sdim else 2149341825Sdim Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 2150276479Sdim break; 2151261991Sdim case OMPC_default: 2152276479Sdim case OMPC_proc_bind: 2153344779Sdim case OMPC_atomic_default_mem_order: 2154276479Sdim // OpenMP [2.14.3.1, Restrictions] 2155276479Sdim // Only a single default clause may be specified on a parallel, task or 2156276479Sdim // teams directive. 2157276479Sdim // OpenMP [2.5, parallel Construct, Restrictions] 2158276479Sdim // At most one proc_bind clause can appear on the directive. 2159344779Sdim // OpenMP [5.0, Requires directive, Restrictions] 2160344779Sdim // At most one atomic_default_mem_order clause can appear 2161344779Sdim // on the directive 2162261991Sdim if (!FirstClause) { 2163296417Sdim Diag(Tok, diag::err_omp_more_one_clause) 2164296417Sdim << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2165280031Sdim ErrorFound = true; 2166261991Sdim } 2167261991Sdim 2168341825Sdim Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 2169261991Sdim break; 2170276479Sdim case OMPC_schedule: 2171309124Sdim case OMPC_dist_schedule: 2172309124Sdim case OMPC_defaultmap: 2173276479Sdim // OpenMP [2.7.1, Restrictions, p. 3] 2174276479Sdim // Only one schedule clause can appear on a loop directive. 2175360784Sdim // OpenMP 4.5 [2.10.4, Restrictions, p. 106] 2176309124Sdim // At most one defaultmap clause can appear on the directive. 2177360784Sdim if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && 2178360784Sdim !FirstClause) { 2179296417Sdim Diag(Tok, diag::err_omp_more_one_clause) 2180296417Sdim << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2181280031Sdim ErrorFound = true; 2182276479Sdim } 2183321369Sdim LLVM_FALLTHROUGH; 2184296417Sdim case OMPC_if: 2185341825Sdim Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective); 2186276479Sdim break; 2187276479Sdim case OMPC_nowait: 2188276479Sdim case OMPC_untied: 2189276479Sdim case OMPC_mergeable: 2190280031Sdim case OMPC_read: 2191280031Sdim case OMPC_write: 2192280031Sdim case OMPC_update: 2193280031Sdim case OMPC_capture: 2194280031Sdim case OMPC_seq_cst: 2195296417Sdim case OMPC_threads: 2196296417Sdim case OMPC_simd: 2197296417Sdim case OMPC_nogroup: 2198344779Sdim case OMPC_unified_address: 2199344779Sdim case OMPC_unified_shared_memory: 2200344779Sdim case OMPC_reverse_offload: 2201344779Sdim case OMPC_dynamic_allocators: 2202276479Sdim // OpenMP [2.7.1, Restrictions, p. 9] 2203276479Sdim // Only one ordered clause can appear on a loop directive. 2204276479Sdim // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 2205276479Sdim // Only one nowait clause can appear on a for directive. 2206344779Sdim // OpenMP [5.0, Requires directive, Restrictions] 2207344779Sdim // Each of the requires clauses can appear at most once on the directive. 2208276479Sdim if (!FirstClause) { 2209296417Sdim Diag(Tok, diag::err_omp_more_one_clause) 2210296417Sdim << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2211280031Sdim ErrorFound = true; 2212276479Sdim } 2213276479Sdim 2214341825Sdim Clause = ParseOpenMPClause(CKind, WrongDirective); 2215276479Sdim break; 2216261991Sdim case OMPC_private: 2217261991Sdim case OMPC_firstprivate: 2218276479Sdim case OMPC_lastprivate: 2219261991Sdim case OMPC_shared: 2220276479Sdim case OMPC_reduction: 2221321369Sdim case OMPC_task_reduction: 2222327952Sdim case OMPC_in_reduction: 2223276479Sdim case OMPC_linear: 2224276479Sdim case OMPC_aligned: 2225276479Sdim case OMPC_copyin: 2226276479Sdim case OMPC_copyprivate: 2227276479Sdim case OMPC_flush: 2228288943Sdim case OMPC_depend: 2229296417Sdim case OMPC_map: 2230309124Sdim case OMPC_to: 2231309124Sdim case OMPC_from: 2232309124Sdim case OMPC_use_device_ptr: 2233309124Sdim case OMPC_is_device_ptr: 2234353358Sdim case OMPC_allocate: 2235360784Sdim case OMPC_nontemporal: 2236341825Sdim Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 2237261991Sdim break; 2238360784Sdim case OMPC_device_type: 2239261991Sdim case OMPC_unknown: 2240261991Sdim Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 2241276479Sdim << getOpenMPDirectiveName(DKind); 2242261991Sdim SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 2243261991Sdim break; 2244261991Sdim case OMPC_threadprivate: 2245309124Sdim case OMPC_uniform: 2246360784Sdim case OMPC_match: 2247341825Sdim if (!WrongDirective) 2248341825Sdim Diag(Tok, diag::err_omp_unexpected_clause) 2249341825Sdim << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 2250261991Sdim SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 2251261991Sdim break; 2252261991Sdim } 2253276479Sdim return ErrorFound ? nullptr : Clause; 2254261991Sdim} 2255261991Sdim 2256309124Sdim/// Parses simple expression in parens for single-expression clauses of OpenMP 2257309124Sdim/// constructs. 2258309124Sdim/// \param RLoc Returned location of right paren. 2259309124SdimExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 2260360784Sdim SourceLocation &RLoc, 2261360784Sdim bool IsAddressOfOperand) { 2262309124Sdim BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2263309124Sdim if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 2264309124Sdim return ExprError(); 2265309124Sdim 2266309124Sdim SourceLocation ELoc = Tok.getLocation(); 2267360784Sdim ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand, 2268360784Sdim NotTypeCast)); 2269309124Sdim ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 2270353358Sdim Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 2271309124Sdim 2272309124Sdim // Parse ')'. 2273341825Sdim RLoc = Tok.getLocation(); 2274341825Sdim if (!T.consumeClose()) 2275341825Sdim RLoc = T.getCloseLocation(); 2276309124Sdim 2277309124Sdim return Val; 2278309124Sdim} 2279309124Sdim 2280341825Sdim/// Parsing of OpenMP clauses with single expressions like 'final', 2281296417Sdim/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 2282296417Sdim/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'. 2283261991Sdim/// 2284276479Sdim/// final-clause: 2285276479Sdim/// 'final' '(' expression ')' 2286276479Sdim/// 2287276479Sdim/// num_threads-clause: 2288276479Sdim/// 'num_threads' '(' expression ')' 2289276479Sdim/// 2290276479Sdim/// safelen-clause: 2291276479Sdim/// 'safelen' '(' expression ')' 2292276479Sdim/// 2293296417Sdim/// simdlen-clause: 2294296417Sdim/// 'simdlen' '(' expression ')' 2295296417Sdim/// 2296276479Sdim/// collapse-clause: 2297276479Sdim/// 'collapse' '(' expression ')' 2298276479Sdim/// 2299296417Sdim/// priority-clause: 2300296417Sdim/// 'priority' '(' expression ')' 2301296417Sdim/// 2302296417Sdim/// grainsize-clause: 2303296417Sdim/// 'grainsize' '(' expression ')' 2304296417Sdim/// 2305296417Sdim/// num_tasks-clause: 2306296417Sdim/// 'num_tasks' '(' expression ')' 2307296417Sdim/// 2308296417Sdim/// hint-clause: 2309296417Sdim/// 'hint' '(' expression ')' 2310296417Sdim/// 2311353358Sdim/// allocator-clause: 2312353358Sdim/// 'allocator' '(' expression ')' 2313353358Sdim/// 2314341825SdimOMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 2315341825Sdim bool ParseOnly) { 2316276479Sdim SourceLocation Loc = ConsumeToken(); 2317309124Sdim SourceLocation LLoc = Tok.getLocation(); 2318309124Sdim SourceLocation RLoc; 2319276479Sdim 2320309124Sdim ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 2321276479Sdim 2322276479Sdim if (Val.isInvalid()) 2323276479Sdim return nullptr; 2324276479Sdim 2325341825Sdim if (ParseOnly) 2326341825Sdim return nullptr; 2327309124Sdim return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 2328276479Sdim} 2329276479Sdim 2330341825Sdim/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 2331276479Sdim/// 2332261991Sdim/// default-clause: 2333261991Sdim/// 'default' '(' 'none' | 'shared' ') 2334261991Sdim/// 2335276479Sdim/// proc_bind-clause: 2336276479Sdim/// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 2337276479Sdim/// 2338341825SdimOMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 2339341825Sdim bool ParseOnly) { 2340360784Sdim llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); 2341360784Sdim if (!Val || ParseOnly) 2342276479Sdim return nullptr; 2343360784Sdim return Actions.ActOnOpenMPSimpleClause( 2344360784Sdim Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, 2345360784Sdim Val.getValue().Loc, Val.getValue().RLoc); 2346261991Sdim} 2347261991Sdim 2348341825Sdim/// Parsing of OpenMP clauses like 'ordered'. 2349261991Sdim/// 2350276479Sdim/// ordered-clause: 2351276479Sdim/// 'ordered' 2352276479Sdim/// 2353276479Sdim/// nowait-clause: 2354276479Sdim/// 'nowait' 2355276479Sdim/// 2356276479Sdim/// untied-clause: 2357276479Sdim/// 'untied' 2358276479Sdim/// 2359276479Sdim/// mergeable-clause: 2360276479Sdim/// 'mergeable' 2361276479Sdim/// 2362280031Sdim/// read-clause: 2363280031Sdim/// 'read' 2364280031Sdim/// 2365296417Sdim/// threads-clause: 2366296417Sdim/// 'threads' 2367296417Sdim/// 2368296417Sdim/// simd-clause: 2369296417Sdim/// 'simd' 2370296417Sdim/// 2371296417Sdim/// nogroup-clause: 2372296417Sdim/// 'nogroup' 2373296417Sdim/// 2374341825SdimOMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 2375276479Sdim SourceLocation Loc = Tok.getLocation(); 2376276479Sdim ConsumeAnyToken(); 2377276479Sdim 2378341825Sdim if (ParseOnly) 2379341825Sdim return nullptr; 2380276479Sdim return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 2381276479Sdim} 2382276479Sdim 2383276479Sdim 2384341825Sdim/// Parsing of OpenMP clauses with single expressions and some additional 2385276479Sdim/// argument like 'schedule' or 'dist_schedule'. 2386276479Sdim/// 2387276479Sdim/// schedule-clause: 2388296417Sdim/// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 2389296417Sdim/// ')' 2390276479Sdim/// 2391296417Sdim/// if-clause: 2392296417Sdim/// 'if' '(' [ directive-name-modifier ':' ] expression ')' 2393296417Sdim/// 2394309124Sdim/// defaultmap: 2395309124Sdim/// 'defaultmap' '(' modifier ':' kind ')' 2396309124Sdim/// 2397341825SdimOMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, 2398341825Sdim bool ParseOnly) { 2399276479Sdim SourceLocation Loc = ConsumeToken(); 2400296417Sdim SourceLocation DelimLoc; 2401276479Sdim // Parse '('. 2402276479Sdim BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2403276479Sdim if (T.expectAndConsume(diag::err_expected_lparen_after, 2404276479Sdim getOpenMPClauseName(Kind))) 2405276479Sdim return nullptr; 2406276479Sdim 2407276479Sdim ExprResult Val; 2408296417Sdim SmallVector<unsigned, 4> Arg; 2409296417Sdim SmallVector<SourceLocation, 4> KLoc; 2410296417Sdim if (Kind == OMPC_schedule) { 2411296417Sdim enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 2412296417Sdim Arg.resize(NumberOfElements); 2413296417Sdim KLoc.resize(NumberOfElements); 2414296417Sdim Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 2415296417Sdim Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 2416296417Sdim Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 2417341825Sdim unsigned KindModifier = getOpenMPSimpleClauseType( 2418296417Sdim Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2419296417Sdim if (KindModifier > OMPC_SCHEDULE_unknown) { 2420296417Sdim // Parse 'modifier' 2421296417Sdim Arg[Modifier1] = KindModifier; 2422296417Sdim KLoc[Modifier1] = Tok.getLocation(); 2423296417Sdim if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2424296417Sdim Tok.isNot(tok::annot_pragma_openmp_end)) 2425296417Sdim ConsumeAnyToken(); 2426296417Sdim if (Tok.is(tok::comma)) { 2427296417Sdim // Parse ',' 'modifier' 2428296417Sdim ConsumeAnyToken(); 2429296417Sdim KindModifier = getOpenMPSimpleClauseType( 2430296417Sdim Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2431296417Sdim Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 2432296417Sdim ? KindModifier 2433296417Sdim : (unsigned)OMPC_SCHEDULE_unknown; 2434296417Sdim KLoc[Modifier2] = Tok.getLocation(); 2435296417Sdim if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2436296417Sdim Tok.isNot(tok::annot_pragma_openmp_end)) 2437296417Sdim ConsumeAnyToken(); 2438296417Sdim } 2439296417Sdim // Parse ':' 2440296417Sdim if (Tok.is(tok::colon)) 2441296417Sdim ConsumeAnyToken(); 2442296417Sdim else 2443296417Sdim Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 2444296417Sdim KindModifier = getOpenMPSimpleClauseType( 2445296417Sdim Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2446296417Sdim } 2447296417Sdim Arg[ScheduleKind] = KindModifier; 2448296417Sdim KLoc[ScheduleKind] = Tok.getLocation(); 2449296417Sdim if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2450296417Sdim Tok.isNot(tok::annot_pragma_openmp_end)) 2451296417Sdim ConsumeAnyToken(); 2452296417Sdim if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 2453296417Sdim Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 2454296417Sdim Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 2455296417Sdim Tok.is(tok::comma)) 2456296417Sdim DelimLoc = ConsumeAnyToken(); 2457309124Sdim } else if (Kind == OMPC_dist_schedule) { 2458309124Sdim Arg.push_back(getOpenMPSimpleClauseType( 2459309124Sdim Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 2460309124Sdim KLoc.push_back(Tok.getLocation()); 2461309124Sdim if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2462309124Sdim Tok.isNot(tok::annot_pragma_openmp_end)) 2463309124Sdim ConsumeAnyToken(); 2464309124Sdim if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 2465309124Sdim DelimLoc = ConsumeAnyToken(); 2466309124Sdim } else if (Kind == OMPC_defaultmap) { 2467309124Sdim // Get a defaultmap modifier 2468360784Sdim unsigned Modifier = getOpenMPSimpleClauseType( 2469360784Sdim Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2470360784Sdim // Set defaultmap modifier to unknown if it is either scalar, aggregate, or 2471360784Sdim // pointer 2472360784Sdim if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) 2473360784Sdim Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; 2474360784Sdim Arg.push_back(Modifier); 2475309124Sdim KLoc.push_back(Tok.getLocation()); 2476309124Sdim if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2477309124Sdim Tok.isNot(tok::annot_pragma_openmp_end)) 2478309124Sdim ConsumeAnyToken(); 2479309124Sdim // Parse ':' 2480309124Sdim if (Tok.is(tok::colon)) 2481309124Sdim ConsumeAnyToken(); 2482309124Sdim else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 2483309124Sdim Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 2484309124Sdim // Get a defaultmap kind 2485309124Sdim Arg.push_back(getOpenMPSimpleClauseType( 2486309124Sdim Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 2487309124Sdim KLoc.push_back(Tok.getLocation()); 2488309124Sdim if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2489309124Sdim Tok.isNot(tok::annot_pragma_openmp_end)) 2490309124Sdim ConsumeAnyToken(); 2491296417Sdim } else { 2492296417Sdim assert(Kind == OMPC_if); 2493296417Sdim KLoc.push_back(Tok.getLocation()); 2494314564Sdim TentativeParsingAction TPA(*this); 2495360784Sdim auto DK = parseOpenMPDirectiveKind(*this); 2496360784Sdim Arg.push_back(DK); 2497360784Sdim if (DK != OMPD_unknown) { 2498296417Sdim ConsumeToken(); 2499314564Sdim if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 2500314564Sdim TPA.Commit(); 2501296417Sdim DelimLoc = ConsumeToken(); 2502314564Sdim } else { 2503314564Sdim TPA.Revert(); 2504360784Sdim Arg.back() = unsigned(OMPD_unknown); 2505314564Sdim } 2506341825Sdim } else { 2507314564Sdim TPA.Revert(); 2508341825Sdim } 2509296417Sdim } 2510276479Sdim 2511309124Sdim bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 2512309124Sdim (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 2513309124Sdim Kind == OMPC_if; 2514296417Sdim if (NeedAnExpression) { 2515296417Sdim SourceLocation ELoc = Tok.getLocation(); 2516360784Sdim ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); 2517276479Sdim Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 2518353358Sdim Val = 2519353358Sdim Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 2520276479Sdim } 2521276479Sdim 2522276479Sdim // Parse ')'. 2523341825Sdim SourceLocation RLoc = Tok.getLocation(); 2524341825Sdim if (!T.consumeClose()) 2525341825Sdim RLoc = T.getCloseLocation(); 2526276479Sdim 2527296417Sdim if (NeedAnExpression && Val.isInvalid()) 2528296417Sdim return nullptr; 2529296417Sdim 2530341825Sdim if (ParseOnly) 2531341825Sdim return nullptr; 2532276479Sdim return Actions.ActOnOpenMPSingleExprWithArgClause( 2533341825Sdim Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 2534276479Sdim} 2535276479Sdim 2536276479Sdimstatic bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 2537276479Sdim UnqualifiedId &ReductionId) { 2538276479Sdim if (ReductionIdScopeSpec.isEmpty()) { 2539276479Sdim auto OOK = OO_None; 2540276479Sdim switch (P.getCurToken().getKind()) { 2541276479Sdim case tok::plus: 2542276479Sdim OOK = OO_Plus; 2543276479Sdim break; 2544276479Sdim case tok::minus: 2545276479Sdim OOK = OO_Minus; 2546276479Sdim break; 2547276479Sdim case tok::star: 2548276479Sdim OOK = OO_Star; 2549276479Sdim break; 2550276479Sdim case tok::amp: 2551276479Sdim OOK = OO_Amp; 2552276479Sdim break; 2553276479Sdim case tok::pipe: 2554276479Sdim OOK = OO_Pipe; 2555276479Sdim break; 2556276479Sdim case tok::caret: 2557276479Sdim OOK = OO_Caret; 2558276479Sdim break; 2559276479Sdim case tok::ampamp: 2560276479Sdim OOK = OO_AmpAmp; 2561276479Sdim break; 2562276479Sdim case tok::pipepipe: 2563276479Sdim OOK = OO_PipePipe; 2564276479Sdim break; 2565276479Sdim default: 2566276479Sdim break; 2567276479Sdim } 2568276479Sdim if (OOK != OO_None) { 2569276479Sdim SourceLocation OpLoc = P.ConsumeToken(); 2570276479Sdim SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 2571276479Sdim ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 2572276479Sdim return false; 2573276479Sdim } 2574276479Sdim } 2575276479Sdim return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, 2576276479Sdim /*AllowDestructorName*/ false, 2577321369Sdim /*AllowConstructorName*/ false, 2578321369Sdim /*AllowDeductionGuide*/ false, 2579341825Sdim nullptr, nullptr, ReductionId); 2580276479Sdim} 2581276479Sdim 2582344779Sdim/// Checks if the token is a valid map-type-modifier. 2583344779Sdimstatic OpenMPMapModifierKind isMapModifier(Parser &P) { 2584344779Sdim Token Tok = P.getCurToken(); 2585344779Sdim if (!Tok.is(tok::identifier)) 2586344779Sdim return OMPC_MAP_MODIFIER_unknown; 2587344779Sdim 2588344779Sdim Preprocessor &PP = P.getPreprocessor(); 2589344779Sdim OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>( 2590344779Sdim getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 2591344779Sdim return TypeModifier; 2592344779Sdim} 2593344779Sdim 2594353358Sdim/// Parse the mapper modifier in map, to, and from clauses. 2595353358Sdimbool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { 2596353358Sdim // Parse '('. 2597353358Sdim BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 2598353358Sdim if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 2599353358Sdim SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2600353358Sdim StopBeforeMatch); 2601353358Sdim return true; 2602353358Sdim } 2603353358Sdim // Parse mapper-identifier 2604353358Sdim if (getLangOpts().CPlusPlus) 2605353358Sdim ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 2606353358Sdim /*ObjectType=*/nullptr, 2607353358Sdim /*EnteringContext=*/false); 2608353358Sdim if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 2609353358Sdim Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 2610353358Sdim SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2611353358Sdim StopBeforeMatch); 2612353358Sdim return true; 2613353358Sdim } 2614353358Sdim auto &DeclNames = Actions.getASTContext().DeclarationNames; 2615353358Sdim Data.ReductionOrMapperId = DeclarationNameInfo( 2616353358Sdim DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 2617353358Sdim ConsumeToken(); 2618353358Sdim // Parse ')'. 2619353358Sdim return T.consumeClose(); 2620353358Sdim} 2621353358Sdim 2622344779Sdim/// Parse map-type-modifiers in map clause. 2623344779Sdim/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 2624353358Sdim/// where, map-type-modifier ::= always | close | mapper(mapper-identifier) 2625353358Sdimbool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { 2626353358Sdim while (getCurToken().isNot(tok::colon)) { 2627353358Sdim OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 2628344779Sdim if (TypeModifier == OMPC_MAP_MODIFIER_always || 2629344779Sdim TypeModifier == OMPC_MAP_MODIFIER_close) { 2630344779Sdim Data.MapTypeModifiers.push_back(TypeModifier); 2631344779Sdim Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 2632353358Sdim ConsumeToken(); 2633353358Sdim } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 2634353358Sdim Data.MapTypeModifiers.push_back(TypeModifier); 2635353358Sdim Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 2636353358Sdim ConsumeToken(); 2637353358Sdim if (parseMapperModifier(Data)) 2638353358Sdim return true; 2639344779Sdim } else { 2640344779Sdim // For the case of unknown map-type-modifier or a map-type. 2641344779Sdim // Map-type is followed by a colon; the function returns when it 2642344779Sdim // encounters a token followed by a colon. 2643344779Sdim if (Tok.is(tok::comma)) { 2644353358Sdim Diag(Tok, diag::err_omp_map_type_modifier_missing); 2645353358Sdim ConsumeToken(); 2646344779Sdim continue; 2647344779Sdim } 2648344779Sdim // Potential map-type token as it is followed by a colon. 2649344779Sdim if (PP.LookAhead(0).is(tok::colon)) 2650353358Sdim return false; 2651353358Sdim Diag(Tok, diag::err_omp_unknown_map_type_modifier); 2652353358Sdim ConsumeToken(); 2653344779Sdim } 2654353358Sdim if (getCurToken().is(tok::comma)) 2655353358Sdim ConsumeToken(); 2656344779Sdim } 2657353358Sdim return false; 2658344779Sdim} 2659344779Sdim 2660344779Sdim/// Checks if the token is a valid map-type. 2661344779Sdimstatic OpenMPMapClauseKind isMapType(Parser &P) { 2662344779Sdim Token Tok = P.getCurToken(); 2663344779Sdim // The map-type token can be either an identifier or the C++ delete keyword. 2664344779Sdim if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 2665344779Sdim return OMPC_MAP_unknown; 2666344779Sdim Preprocessor &PP = P.getPreprocessor(); 2667344779Sdim OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>( 2668344779Sdim getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 2669344779Sdim return MapType; 2670344779Sdim} 2671344779Sdim 2672344779Sdim/// Parse map-type in map clause. 2673344779Sdim/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 2674353358Sdim/// where, map-type ::= to | from | tofrom | alloc | release | delete 2675344779Sdimstatic void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { 2676344779Sdim Token Tok = P.getCurToken(); 2677344779Sdim if (Tok.is(tok::colon)) { 2678344779Sdim P.Diag(Tok, diag::err_omp_map_type_missing); 2679344779Sdim return; 2680344779Sdim } 2681360784Sdim Data.ExtraModifier = isMapType(P); 2682360784Sdim if (Data.ExtraModifier == OMPC_MAP_unknown) 2683344779Sdim P.Diag(Tok, diag::err_omp_unknown_map_type); 2684344779Sdim P.ConsumeToken(); 2685344779Sdim} 2686344779Sdim 2687309124Sdim/// Parses clauses with list. 2688309124Sdimbool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 2689309124Sdim OpenMPClauseKind Kind, 2690309124Sdim SmallVectorImpl<Expr *> &Vars, 2691309124Sdim OpenMPVarListDataTy &Data) { 2692309124Sdim UnqualifiedId UnqualifiedReductionId; 2693276479Sdim bool InvalidReductionId = false; 2694353358Sdim bool IsInvalidMapperModifier = false; 2695288943Sdim 2696261991Sdim // Parse '('. 2697261991Sdim BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2698261991Sdim if (T.expectAndConsume(diag::err_expected_lparen_after, 2699261991Sdim getOpenMPClauseName(Kind))) 2700309124Sdim return true; 2701261991Sdim 2702296417Sdim bool NeedRParenForLinear = false; 2703296417Sdim BalancedDelimiterTracker LinearT(*this, tok::l_paren, 2704296417Sdim tok::annot_pragma_openmp_end); 2705276479Sdim // Handle reduction-identifier for reduction clause. 2706327952Sdim if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 2707327952Sdim Kind == OMPC_in_reduction) { 2708276479Sdim ColonProtectionRAIIObject ColonRAII(*this); 2709309124Sdim if (getLangOpts().CPlusPlus) 2710353358Sdim ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 2711309124Sdim /*ObjectType=*/nullptr, 2712309124Sdim /*EnteringContext=*/false); 2713353358Sdim InvalidReductionId = ParseReductionId( 2714353358Sdim *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 2715276479Sdim if (InvalidReductionId) { 2716276479Sdim SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2717276479Sdim StopBeforeMatch); 2718276479Sdim } 2719309124Sdim if (Tok.is(tok::colon)) 2720309124Sdim Data.ColonLoc = ConsumeToken(); 2721309124Sdim else 2722276479Sdim Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 2723309124Sdim if (!InvalidReductionId) 2724353358Sdim Data.ReductionOrMapperId = 2725309124Sdim Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 2726288943Sdim } else if (Kind == OMPC_depend) { 2727360784Sdim // Handle dependency type for depend clause. 2728288943Sdim ColonProtectionRAIIObject ColonRAII(*this); 2729360784Sdim Data.ExtraModifier = getOpenMPSimpleClauseType( 2730360784Sdim Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""); 2731360784Sdim Data.DepLinMapLastLoc = Tok.getLocation(); 2732360784Sdim if (Data.ExtraModifier == OMPC_DEPEND_unknown) { 2733288943Sdim SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2734288943Sdim StopBeforeMatch); 2735288943Sdim } else { 2736288943Sdim ConsumeToken(); 2737296417Sdim // Special processing for depend(source) clause. 2738360784Sdim if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { 2739296417Sdim // Parse ')'. 2740296417Sdim T.consumeClose(); 2741309124Sdim return false; 2742296417Sdim } 2743288943Sdim } 2744341825Sdim if (Tok.is(tok::colon)) { 2745309124Sdim Data.ColonLoc = ConsumeToken(); 2746341825Sdim } else { 2747296417Sdim Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 2748296417Sdim : diag::warn_pragma_expected_colon) 2749296417Sdim << "dependency type"; 2750288943Sdim } 2751296417Sdim } else if (Kind == OMPC_linear) { 2752296417Sdim // Try to parse modifier if any. 2753360784Sdim Data.ExtraModifier = OMPC_LINEAR_val; 2754296417Sdim if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 2755360784Sdim Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); 2756360784Sdim Data.DepLinMapLastLoc = ConsumeToken(); 2757296417Sdim LinearT.consumeOpen(); 2758296417Sdim NeedRParenForLinear = true; 2759296417Sdim } 2760360784Sdim } else if (Kind == OMPC_lastprivate) { 2761360784Sdim // Try to parse modifier if any. 2762360784Sdim Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; 2763360784Sdim // Conditional modifier allowed only in OpenMP 5.0 and not supported in 2764360784Sdim // distribute and taskloop based directives. 2765360784Sdim if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && 2766360784Sdim !isOpenMPTaskLoopDirective(DKind)) && 2767360784Sdim Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { 2768360784Sdim Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); 2769360784Sdim Data.DepLinMapLastLoc = Tok.getLocation(); 2770360784Sdim if (Data.ExtraModifier == OMPC_LASTPRIVATE_unknown) { 2771360784Sdim SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2772360784Sdim StopBeforeMatch); 2773360784Sdim } else { 2774360784Sdim ConsumeToken(); 2775360784Sdim } 2776360784Sdim assert(Tok.is(tok::colon) && "Expected colon."); 2777360784Sdim Data.ColonLoc = ConsumeToken(); 2778360784Sdim } 2779296417Sdim } else if (Kind == OMPC_map) { 2780296417Sdim // Handle map type for map clause. 2781296417Sdim ColonProtectionRAIIObject ColonRAII(*this); 2782296417Sdim 2783309124Sdim // The first identifier may be a list item, a map-type or a 2784344779Sdim // map-type-modifier. The map-type can also be delete which has the same 2785309124Sdim // spelling of the C++ delete keyword. 2786360784Sdim Data.ExtraModifier = OMPC_MAP_unknown; 2787360784Sdim Data.DepLinMapLastLoc = Tok.getLocation(); 2788296417Sdim 2789344779Sdim // Check for presence of a colon in the map clause. 2790344779Sdim TentativeParsingAction TPA(*this); 2791344779Sdim bool ColonPresent = false; 2792344779Sdim if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2793344779Sdim StopBeforeMatch)) { 2794344779Sdim if (Tok.is(tok::colon)) 2795344779Sdim ColonPresent = true; 2796344779Sdim } 2797344779Sdim TPA.Revert(); 2798344779Sdim // Only parse map-type-modifier[s] and map-type if a colon is present in 2799344779Sdim // the map clause. 2800344779Sdim if (ColonPresent) { 2801353358Sdim IsInvalidMapperModifier = parseMapTypeModifiers(Data); 2802353358Sdim if (!IsInvalidMapperModifier) 2803353358Sdim parseMapType(*this, Data); 2804353358Sdim else 2805353358Sdim SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 2806344779Sdim } 2807360784Sdim if (Data.ExtraModifier == OMPC_MAP_unknown) { 2808360784Sdim Data.ExtraModifier = OMPC_MAP_tofrom; 2809309124Sdim Data.IsMapTypeImplicit = true; 2810296417Sdim } 2811296417Sdim 2812309124Sdim if (Tok.is(tok::colon)) 2813309124Sdim Data.ColonLoc = ConsumeToken(); 2814353358Sdim } else if (Kind == OMPC_to || Kind == OMPC_from) { 2815353358Sdim if (Tok.is(tok::identifier)) { 2816353358Sdim bool IsMapperModifier = false; 2817353358Sdim if (Kind == OMPC_to) { 2818353358Sdim auto Modifier = static_cast<OpenMPToModifierKind>( 2819353358Sdim getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2820353358Sdim if (Modifier == OMPC_TO_MODIFIER_mapper) 2821353358Sdim IsMapperModifier = true; 2822353358Sdim } else { 2823353358Sdim auto Modifier = static_cast<OpenMPFromModifierKind>( 2824353358Sdim getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2825353358Sdim if (Modifier == OMPC_FROM_MODIFIER_mapper) 2826353358Sdim IsMapperModifier = true; 2827353358Sdim } 2828353358Sdim if (IsMapperModifier) { 2829353358Sdim // Parse the mapper modifier. 2830353358Sdim ConsumeToken(); 2831353358Sdim IsInvalidMapperModifier = parseMapperModifier(Data); 2832353358Sdim if (Tok.isNot(tok::colon)) { 2833353358Sdim if (!IsInvalidMapperModifier) 2834353358Sdim Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 2835353358Sdim SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2836353358Sdim StopBeforeMatch); 2837353358Sdim } 2838353358Sdim // Consume ':'. 2839353358Sdim if (Tok.is(tok::colon)) 2840353358Sdim ConsumeToken(); 2841353358Sdim } 2842353358Sdim } 2843353358Sdim } else if (Kind == OMPC_allocate) { 2844353358Sdim // Handle optional allocator expression followed by colon delimiter. 2845353358Sdim ColonProtectionRAIIObject ColonRAII(*this); 2846353358Sdim TentativeParsingAction TPA(*this); 2847353358Sdim ExprResult Tail = 2848353358Sdim Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 2849353358Sdim Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), 2850353358Sdim /*DiscardedValue=*/false); 2851353358Sdim if (Tail.isUsable()) { 2852353358Sdim if (Tok.is(tok::colon)) { 2853353358Sdim Data.TailExpr = Tail.get(); 2854353358Sdim Data.ColonLoc = ConsumeToken(); 2855353358Sdim TPA.Commit(); 2856353358Sdim } else { 2857353358Sdim // colon not found, no allocator specified, parse only list of 2858353358Sdim // variables. 2859353358Sdim TPA.Revert(); 2860353358Sdim } 2861353358Sdim } else { 2862353358Sdim // Parsing was unsuccessfull, revert and skip to the end of clause or 2863353358Sdim // directive. 2864353358Sdim TPA.Revert(); 2865353358Sdim SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2866353358Sdim StopBeforeMatch); 2867353358Sdim } 2868276479Sdim } 2869276479Sdim 2870327952Sdim bool IsComma = 2871327952Sdim (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 2872327952Sdim Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 2873327952Sdim (Kind == OMPC_reduction && !InvalidReductionId) || 2874360784Sdim (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || 2875360784Sdim (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown); 2876276479Sdim const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 2877276479Sdim while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 2878261991Sdim Tok.isNot(tok::annot_pragma_openmp_end))) { 2879276479Sdim ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 2880261991Sdim // Parse variable 2881280031Sdim ExprResult VarExpr = 2882280031Sdim Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 2883341825Sdim if (VarExpr.isUsable()) { 2884276479Sdim Vars.push_back(VarExpr.get()); 2885341825Sdim } else { 2886261991Sdim SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2887261991Sdim StopBeforeMatch); 2888261991Sdim } 2889261991Sdim // Skip ',' if any 2890261991Sdim IsComma = Tok.is(tok::comma); 2891276479Sdim if (IsComma) 2892261991Sdim ConsumeToken(); 2893276479Sdim else if (Tok.isNot(tok::r_paren) && 2894276479Sdim Tok.isNot(tok::annot_pragma_openmp_end) && 2895276479Sdim (!MayHaveTail || Tok.isNot(tok::colon))) 2896261991Sdim Diag(Tok, diag::err_omp_expected_punc) 2897276479Sdim << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 2898276479Sdim : getOpenMPClauseName(Kind)) 2899276479Sdim << (Kind == OMPC_flush); 2900261991Sdim } 2901261991Sdim 2902296417Sdim // Parse ')' for linear clause with modifier. 2903296417Sdim if (NeedRParenForLinear) 2904296417Sdim LinearT.consumeClose(); 2905296417Sdim 2906276479Sdim // Parse ':' linear-step (or ':' alignment). 2907276479Sdim const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 2908276479Sdim if (MustHaveTail) { 2909309124Sdim Data.ColonLoc = Tok.getLocation(); 2910296417Sdim SourceLocation ELoc = ConsumeToken(); 2911296417Sdim ExprResult Tail = ParseAssignmentExpression(); 2912353358Sdim Tail = 2913353358Sdim Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 2914276479Sdim if (Tail.isUsable()) 2915309124Sdim Data.TailExpr = Tail.get(); 2916276479Sdim else 2917276479Sdim SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2918276479Sdim StopBeforeMatch); 2919276479Sdim } 2920276479Sdim 2921261991Sdim // Parse ')'. 2922341825Sdim Data.RLoc = Tok.getLocation(); 2923341825Sdim if (!T.consumeClose()) 2924341825Sdim Data.RLoc = T.getCloseLocation(); 2925360784Sdim return (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown && 2926341825Sdim Vars.empty()) || 2927341825Sdim (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 2928353358Sdim (MustHaveTail && !Data.TailExpr) || InvalidReductionId || 2929353358Sdim IsInvalidMapperModifier; 2930309124Sdim} 2931309124Sdim 2932341825Sdim/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 2933327952Sdim/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or 2934327952Sdim/// 'in_reduction'. 2935309124Sdim/// 2936309124Sdim/// private-clause: 2937309124Sdim/// 'private' '(' list ')' 2938309124Sdim/// firstprivate-clause: 2939309124Sdim/// 'firstprivate' '(' list ')' 2940309124Sdim/// lastprivate-clause: 2941309124Sdim/// 'lastprivate' '(' list ')' 2942309124Sdim/// shared-clause: 2943309124Sdim/// 'shared' '(' list ')' 2944309124Sdim/// linear-clause: 2945309124Sdim/// 'linear' '(' linear-list [ ':' linear-step ] ')' 2946309124Sdim/// aligned-clause: 2947309124Sdim/// 'aligned' '(' list [ ':' alignment ] ')' 2948309124Sdim/// reduction-clause: 2949309124Sdim/// 'reduction' '(' reduction-identifier ':' list ')' 2950321369Sdim/// task_reduction-clause: 2951321369Sdim/// 'task_reduction' '(' reduction-identifier ':' list ')' 2952327952Sdim/// in_reduction-clause: 2953327952Sdim/// 'in_reduction' '(' reduction-identifier ':' list ')' 2954309124Sdim/// copyprivate-clause: 2955309124Sdim/// 'copyprivate' '(' list ')' 2956309124Sdim/// flush-clause: 2957309124Sdim/// 'flush' '(' list ')' 2958309124Sdim/// depend-clause: 2959309124Sdim/// 'depend' '(' in | out | inout : list | source ')' 2960309124Sdim/// map-clause: 2961344779Sdim/// 'map' '(' [ [ always [,] ] [ close [,] ] 2962353358Sdim/// [ mapper '(' mapper-identifier ')' [,] ] 2963309124Sdim/// to | from | tofrom | alloc | release | delete ':' ] list ')'; 2964309124Sdim/// to-clause: 2965353358Sdim/// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 2966309124Sdim/// from-clause: 2967353358Sdim/// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 2968309124Sdim/// use_device_ptr-clause: 2969309124Sdim/// 'use_device_ptr' '(' list ')' 2970309124Sdim/// is_device_ptr-clause: 2971309124Sdim/// 'is_device_ptr' '(' list ')' 2972353358Sdim/// allocate-clause: 2973353358Sdim/// 'allocate' '(' [ allocator ':' ] list ')' 2974309124Sdim/// 2975309124Sdim/// For 'linear' clause linear-list may have the following forms: 2976309124Sdim/// list 2977309124Sdim/// modifier(list) 2978309124Sdim/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 2979309124SdimOMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 2980341825Sdim OpenMPClauseKind Kind, 2981341825Sdim bool ParseOnly) { 2982309124Sdim SourceLocation Loc = Tok.getLocation(); 2983309124Sdim SourceLocation LOpen = ConsumeToken(); 2984309124Sdim SmallVector<Expr *, 4> Vars; 2985309124Sdim OpenMPVarListDataTy Data; 2986309124Sdim 2987309124Sdim if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 2988276479Sdim return nullptr; 2989261991Sdim 2990341825Sdim if (ParseOnly) 2991341825Sdim return nullptr; 2992353358Sdim OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 2993276479Sdim return Actions.ActOnOpenMPVarListClause( 2994353358Sdim Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc, 2995360784Sdim Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, 2996360784Sdim Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 2997360784Sdim Data.IsMapTypeImplicit, Data.DepLinMapLastLoc); 2998261991Sdim} 2999261991Sdim 3000