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