12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801 |
- //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// \file
- /// This file implements parsing of all OpenMP directives and clauses.
- ///
- //===----------------------------------------------------------------------===//
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/StmtOpenMP.h"
- #include "clang/Parse/ParseDiagnostic.h"
- #include "clang/Parse/Parser.h"
- #include "clang/Parse/RAIIObjectsForParser.h"
- #include "clang/Sema/Scope.h"
- #include "llvm/ADT/PointerIntPair.h"
- using namespace clang;
- //===----------------------------------------------------------------------===//
- // OpenMP declarative directives.
- //===----------------------------------------------------------------------===//
- namespace {
- enum OpenMPDirectiveKindEx {
- OMPD_cancellation = OMPD_unknown + 1,
- OMPD_data,
- OMPD_declare,
- OMPD_end,
- OMPD_end_declare,
- OMPD_enter,
- OMPD_exit,
- OMPD_point,
- OMPD_reduction,
- OMPD_target_enter,
- OMPD_target_exit,
- OMPD_update,
- OMPD_distribute_parallel,
- OMPD_teams_distribute_parallel,
- OMPD_target_teams_distribute_parallel,
- OMPD_mapper,
- OMPD_variant,
- };
- class DeclDirectiveListParserHelper final {
- SmallVector<Expr *, 4> Identifiers;
- Parser *P;
- OpenMPDirectiveKind Kind;
- public:
- DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
- : P(P), Kind(Kind) {}
- void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
- ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
- P->getCurScope(), SS, NameInfo, Kind);
- if (Res.isUsable())
- Identifiers.push_back(Res.get());
- }
- llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
- };
- } // namespace
- // Map token string to extended OMP token kind that are
- // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
- static unsigned getOpenMPDirectiveKindEx(StringRef S) {
- auto DKind = getOpenMPDirectiveKind(S);
- if (DKind != OMPD_unknown)
- return DKind;
- return llvm::StringSwitch<unsigned>(S)
- .Case("cancellation", OMPD_cancellation)
- .Case("data", OMPD_data)
- .Case("declare", OMPD_declare)
- .Case("end", OMPD_end)
- .Case("enter", OMPD_enter)
- .Case("exit", OMPD_exit)
- .Case("point", OMPD_point)
- .Case("reduction", OMPD_reduction)
- .Case("update", OMPD_update)
- .Case("mapper", OMPD_mapper)
- .Case("variant", OMPD_variant)
- .Default(OMPD_unknown);
- }
- static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
- // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
- // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
- // TODO: add other combined directives in topological order.
- static const unsigned F[][3] = {
- {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
- {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
- {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
- {OMPD_declare, OMPD_simd, OMPD_declare_simd},
- {OMPD_declare, OMPD_target, OMPD_declare_target},
- {OMPD_declare, OMPD_variant, OMPD_declare_variant},
- {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
- {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
- {OMPD_distribute_parallel_for, OMPD_simd,
- OMPD_distribute_parallel_for_simd},
- {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
- {OMPD_end, OMPD_declare, OMPD_end_declare},
- {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
- {OMPD_target, OMPD_data, OMPD_target_data},
- {OMPD_target, OMPD_enter, OMPD_target_enter},
- {OMPD_target, OMPD_exit, OMPD_target_exit},
- {OMPD_target, OMPD_update, OMPD_target_update},
- {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
- {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
- {OMPD_for, OMPD_simd, OMPD_for_simd},
- {OMPD_parallel, OMPD_for, OMPD_parallel_for},
- {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
- {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
- {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
- {OMPD_target, OMPD_parallel, OMPD_target_parallel},
- {OMPD_target, OMPD_simd, OMPD_target_simd},
- {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
- {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
- {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
- {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
- {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
- {OMPD_teams_distribute_parallel, OMPD_for,
- OMPD_teams_distribute_parallel_for},
- {OMPD_teams_distribute_parallel_for, OMPD_simd,
- OMPD_teams_distribute_parallel_for_simd},
- {OMPD_target, OMPD_teams, OMPD_target_teams},
- {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
- {OMPD_target_teams_distribute, OMPD_parallel,
- OMPD_target_teams_distribute_parallel},
- {OMPD_target_teams_distribute, OMPD_simd,
- OMPD_target_teams_distribute_simd},
- {OMPD_target_teams_distribute_parallel, OMPD_for,
- OMPD_target_teams_distribute_parallel_for},
- {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
- OMPD_target_teams_distribute_parallel_for_simd}};
- enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
- Token Tok = P.getCurToken();
- unsigned DKind =
- Tok.isAnnotation()
- ? static_cast<unsigned>(OMPD_unknown)
- : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
- if (DKind == OMPD_unknown)
- return OMPD_unknown;
- for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
- if (DKind != F[I][0])
- continue;
- Tok = P.getPreprocessor().LookAhead(0);
- unsigned SDKind =
- Tok.isAnnotation()
- ? static_cast<unsigned>(OMPD_unknown)
- : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
- if (SDKind == OMPD_unknown)
- continue;
- if (SDKind == F[I][1]) {
- P.ConsumeToken();
- DKind = F[I][2];
- }
- }
- return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
- : OMPD_unknown;
- }
- static DeclarationName parseOpenMPReductionId(Parser &P) {
- Token Tok = P.getCurToken();
- Sema &Actions = P.getActions();
- OverloadedOperatorKind OOK = OO_None;
- // Allow to use 'operator' keyword for C++ operators
- bool WithOperator = false;
- if (Tok.is(tok::kw_operator)) {
- P.ConsumeToken();
- Tok = P.getCurToken();
- WithOperator = true;
- }
- switch (Tok.getKind()) {
- case tok::plus: // '+'
- OOK = OO_Plus;
- break;
- case tok::minus: // '-'
- OOK = OO_Minus;
- break;
- case tok::star: // '*'
- OOK = OO_Star;
- break;
- case tok::amp: // '&'
- OOK = OO_Amp;
- break;
- case tok::pipe: // '|'
- OOK = OO_Pipe;
- break;
- case tok::caret: // '^'
- OOK = OO_Caret;
- break;
- case tok::ampamp: // '&&'
- OOK = OO_AmpAmp;
- break;
- case tok::pipepipe: // '||'
- OOK = OO_PipePipe;
- break;
- case tok::identifier: // identifier
- if (!WithOperator)
- break;
- LLVM_FALLTHROUGH;
- default:
- P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
- P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
- Parser::StopBeforeMatch);
- return DeclarationName();
- }
- P.ConsumeToken();
- auto &DeclNames = Actions.getASTContext().DeclarationNames;
- return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
- : DeclNames.getCXXOperatorName(OOK);
- }
- /// Parse 'omp declare reduction' construct.
- ///
- /// declare-reduction-directive:
- /// annot_pragma_openmp 'declare' 'reduction'
- /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
- /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
- /// annot_pragma_openmp_end
- /// <reduction_id> is either a base language identifier or one of the following
- /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
- ///
- Parser::DeclGroupPtrTy
- Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
- // Parse '('.
- BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPDirectiveName(OMPD_declare_reduction))) {
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- return DeclGroupPtrTy();
- }
- DeclarationName Name = parseOpenMPReductionId(*this);
- if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
- return DeclGroupPtrTy();
- // Consume ':'.
- bool IsCorrect = !ExpectAndConsume(tok::colon);
- if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
- return DeclGroupPtrTy();
- IsCorrect = IsCorrect && !Name.isEmpty();
- if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
- Diag(Tok.getLocation(), diag::err_expected_type);
- IsCorrect = false;
- }
- if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
- return DeclGroupPtrTy();
- SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
- // Parse list of types until ':' token.
- do {
- ColonProtectionRAIIObject ColonRAII(*this);
- SourceRange Range;
- TypeResult TR =
- ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
- if (TR.isUsable()) {
- QualType ReductionType =
- Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
- if (!ReductionType.isNull()) {
- ReductionTypes.push_back(
- std::make_pair(ReductionType, Range.getBegin()));
- }
- } else {
- SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- }
- if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
- break;
- // Consume ','.
- if (ExpectAndConsume(tok::comma)) {
- IsCorrect = false;
- if (Tok.is(tok::annot_pragma_openmp_end)) {
- Diag(Tok.getLocation(), diag::err_expected_type);
- return DeclGroupPtrTy();
- }
- }
- } while (Tok.isNot(tok::annot_pragma_openmp_end));
- if (ReductionTypes.empty()) {
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- return DeclGroupPtrTy();
- }
- if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
- return DeclGroupPtrTy();
- // Consume ':'.
- if (ExpectAndConsume(tok::colon))
- IsCorrect = false;
- if (Tok.is(tok::annot_pragma_openmp_end)) {
- Diag(Tok.getLocation(), diag::err_expected_expression);
- return DeclGroupPtrTy();
- }
- DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
- getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
- // Parse <combiner> expression and then parse initializer if any for each
- // correct type.
- unsigned I = 0, E = ReductionTypes.size();
- for (Decl *D : DRD.get()) {
- TentativeParsingAction TPA(*this);
- ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
- Scope::CompoundStmtScope |
- Scope::OpenMPDirectiveScope);
- // Parse <combiner> expression.
- Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
- ExprResult CombinerResult =
- Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
- D->getLocation(), /*DiscardedValue*/ false);
- Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
- if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
- Tok.isNot(tok::annot_pragma_openmp_end)) {
- TPA.Commit();
- IsCorrect = false;
- break;
- }
- IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
- ExprResult InitializerResult;
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- // Parse <initializer> expression.
- if (Tok.is(tok::identifier) &&
- Tok.getIdentifierInfo()->isStr("initializer")) {
- ConsumeToken();
- } else {
- Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
- TPA.Commit();
- IsCorrect = false;
- break;
- }
- // Parse '('.
- BalancedDelimiterTracker T(*this, tok::l_paren,
- tok::annot_pragma_openmp_end);
- IsCorrect =
- !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
- IsCorrect;
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
- Scope::CompoundStmtScope |
- Scope::OpenMPDirectiveScope);
- // Parse expression.
- VarDecl *OmpPrivParm =
- Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
- D);
- // Check if initializer is omp_priv <init_expr> or something else.
- if (Tok.is(tok::identifier) &&
- Tok.getIdentifierInfo()->isStr("omp_priv")) {
- if (Actions.getLangOpts().CPlusPlus) {
- InitializerResult = Actions.ActOnFinishFullExpr(
- ParseAssignmentExpression().get(), D->getLocation(),
- /*DiscardedValue*/ false);
- } else {
- ConsumeToken();
- ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
- }
- } else {
- InitializerResult = Actions.ActOnFinishFullExpr(
- ParseAssignmentExpression().get(), D->getLocation(),
- /*DiscardedValue*/ false);
- }
- Actions.ActOnOpenMPDeclareReductionInitializerEnd(
- D, InitializerResult.get(), OmpPrivParm);
- if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
- Tok.isNot(tok::annot_pragma_openmp_end)) {
- TPA.Commit();
- IsCorrect = false;
- break;
- }
- IsCorrect =
- !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
- }
- }
- ++I;
- // Revert parsing if not the last type, otherwise accept it, we're done with
- // parsing.
- if (I != E)
- TPA.Revert();
- else
- TPA.Commit();
- }
- return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
- IsCorrect);
- }
- void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
- // Parse declarator '=' initializer.
- // If a '==' or '+=' is found, suggest a fixit to '='.
- if (isTokenEqualOrEqualTypo()) {
- ConsumeToken();
- if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
- Actions.FinalizeDeclaration(OmpPrivParm);
- cutOffParsing();
- return;
- }
- ExprResult Init(ParseInitializer());
- if (Init.isInvalid()) {
- SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
- Actions.ActOnInitializerError(OmpPrivParm);
- } else {
- Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
- /*DirectInit=*/false);
- }
- } else if (Tok.is(tok::l_paren)) {
- // Parse C++ direct initializer: '(' expression-list ')'
- BalancedDelimiterTracker T(*this, tok::l_paren);
- T.consumeOpen();
- ExprVector Exprs;
- CommaLocsTy CommaLocs;
- SourceLocation LParLoc = T.getOpenLocation();
- auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
- QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
- getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
- OmpPrivParm->getLocation(), Exprs, LParLoc);
- CalledSignatureHelp = true;
- return PreferredType;
- };
- if (ParseExpressionList(Exprs, CommaLocs, [&] {
- PreferredType.enterFunctionArgument(Tok.getLocation(),
- RunSignatureHelp);
- })) {
- if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
- RunSignatureHelp();
- Actions.ActOnInitializerError(OmpPrivParm);
- SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
- } else {
- // Match the ')'.
- SourceLocation RLoc = Tok.getLocation();
- if (!T.consumeClose())
- RLoc = T.getCloseLocation();
- assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
- "Unexpected number of commas!");
- ExprResult Initializer =
- Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
- Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
- /*DirectInit=*/true);
- }
- } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
- // Parse C++0x braced-init-list.
- Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
- ExprResult Init(ParseBraceInitializer());
- if (Init.isInvalid()) {
- Actions.ActOnInitializerError(OmpPrivParm);
- } else {
- Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
- /*DirectInit=*/true);
- }
- } else {
- Actions.ActOnUninitializedDecl(OmpPrivParm);
- }
- }
- /// Parses 'omp declare mapper' directive.
- ///
- /// declare-mapper-directive:
- /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
- /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
- /// annot_pragma_openmp_end
- /// <mapper-identifier> and <var> are base language identifiers.
- ///
- Parser::DeclGroupPtrTy
- Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
- bool IsCorrect = true;
- // Parse '('
- BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPDirectiveName(OMPD_declare_mapper))) {
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- return DeclGroupPtrTy();
- }
- // Parse <mapper-identifier>
- auto &DeclNames = Actions.getASTContext().DeclarationNames;
- DeclarationName MapperId;
- if (PP.LookAhead(0).is(tok::colon)) {
- if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
- Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
- IsCorrect = false;
- } else {
- MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
- }
- ConsumeToken();
- // Consume ':'.
- ExpectAndConsume(tok::colon);
- } else {
- // If no mapper identifier is provided, its name is "default" by default
- MapperId =
- DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
- }
- if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
- return DeclGroupPtrTy();
- // Parse <type> <var>
- DeclarationName VName;
- QualType MapperType;
- SourceRange Range;
- TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
- if (ParsedType.isUsable())
- MapperType =
- Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
- if (MapperType.isNull())
- IsCorrect = false;
- if (!IsCorrect) {
- SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
- return DeclGroupPtrTy();
- }
- // Consume ')'.
- IsCorrect &= !T.consumeClose();
- if (!IsCorrect) {
- SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
- return DeclGroupPtrTy();
- }
- // Enter scope.
- OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart(
- getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
- Range.getBegin(), VName, AS);
- DeclarationNameInfo DirName;
- SourceLocation Loc = Tok.getLocation();
- unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
- Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
- ParseScope OMPDirectiveScope(this, ScopeFlags);
- Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
- // Add the mapper variable declaration.
- Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
- DMD, getCurScope(), MapperType, Range.getBegin(), VName);
- // Parse map clauses.
- SmallVector<OMPClause *, 6> Clauses;
- while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- OpenMPClauseKind CKind = Tok.isAnnotation()
- ? OMPC_unknown
- : getOpenMPClauseKind(PP.getSpelling(Tok));
- Actions.StartOpenMPClause(CKind);
- OMPClause *Clause =
- ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
- if (Clause)
- Clauses.push_back(Clause);
- else
- IsCorrect = false;
- // Skip ',' if any.
- if (Tok.is(tok::comma))
- ConsumeToken();
- Actions.EndOpenMPClause();
- }
- if (Clauses.empty()) {
- Diag(Tok, diag::err_omp_expected_clause)
- << getOpenMPDirectiveName(OMPD_declare_mapper);
- IsCorrect = false;
- }
- // Exit scope.
- Actions.EndOpenMPDSABlock(nullptr);
- OMPDirectiveScope.Exit();
- DeclGroupPtrTy DGP =
- Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
- if (!IsCorrect)
- return DeclGroupPtrTy();
- return DGP;
- }
- TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
- DeclarationName &Name,
- AccessSpecifier AS) {
- // Parse the common declaration-specifiers piece.
- Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
- DeclSpec DS(AttrFactory);
- ParseSpecifierQualifierList(DS, AS, DSC);
- // Parse the declarator.
- DeclaratorContext Context = DeclaratorContext::PrototypeContext;
- Declarator DeclaratorInfo(DS, Context);
- ParseDeclarator(DeclaratorInfo);
- Range = DeclaratorInfo.getSourceRange();
- if (DeclaratorInfo.getIdentifier() == nullptr) {
- Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
- return true;
- }
- Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
- return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
- }
- namespace {
- /// RAII that recreates function context for correct parsing of clauses of
- /// 'declare simd' construct.
- /// OpenMP, 2.8.2 declare simd Construct
- /// The expressions appearing in the clauses of this directive are evaluated in
- /// the scope of the arguments of the function declaration or definition.
- class FNContextRAII final {
- Parser &P;
- Sema::CXXThisScopeRAII *ThisScope;
- Parser::ParseScope *TempScope;
- Parser::ParseScope *FnScope;
- bool HasTemplateScope = false;
- bool HasFunScope = false;
- FNContextRAII() = delete;
- FNContextRAII(const FNContextRAII &) = delete;
- FNContextRAII &operator=(const FNContextRAII &) = delete;
- public:
- FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
- Decl *D = *Ptr.get().begin();
- NamedDecl *ND = dyn_cast<NamedDecl>(D);
- RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
- Sema &Actions = P.getActions();
- // Allow 'this' within late-parsed attributes.
- ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
- ND && ND->isCXXInstanceMember());
- // If the Decl is templatized, add template parameters to scope.
- HasTemplateScope = D->isTemplateDecl();
- TempScope =
- new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
- if (HasTemplateScope)
- Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
- // If the Decl is on a function, add function parameters to the scope.
- HasFunScope = D->isFunctionOrFunctionTemplate();
- FnScope = new Parser::ParseScope(
- &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
- HasFunScope);
- if (HasFunScope)
- Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
- }
- ~FNContextRAII() {
- if (HasFunScope) {
- P.getActions().ActOnExitFunctionContext();
- FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
- }
- if (HasTemplateScope)
- TempScope->Exit();
- delete FnScope;
- delete TempScope;
- delete ThisScope;
- }
- };
- } // namespace
- /// Parses clauses for 'declare simd' directive.
- /// clause:
- /// 'inbranch' | 'notinbranch'
- /// 'simdlen' '(' <expr> ')'
- /// { 'uniform' '(' <argument_list> ')' }
- /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
- /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
- static bool parseDeclareSimdClauses(
- Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
- SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
- SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
- SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
- SourceRange BSRange;
- const Token &Tok = P.getCurToken();
- bool IsError = false;
- while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- if (Tok.isNot(tok::identifier))
- break;
- OMPDeclareSimdDeclAttr::BranchStateTy Out;
- IdentifierInfo *II = Tok.getIdentifierInfo();
- StringRef ClauseName = II->getName();
- // Parse 'inranch|notinbranch' clauses.
- if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
- if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
- P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
- << ClauseName
- << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
- IsError = true;
- }
- BS = Out;
- BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
- P.ConsumeToken();
- } else if (ClauseName.equals("simdlen")) {
- if (SimdLen.isUsable()) {
- P.Diag(Tok, diag::err_omp_more_one_clause)
- << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
- IsError = true;
- }
- P.ConsumeToken();
- SourceLocation RLoc;
- SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
- if (SimdLen.isInvalid())
- IsError = true;
- } else {
- OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
- if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
- CKind == OMPC_linear) {
- Parser::OpenMPVarListDataTy Data;
- SmallVectorImpl<Expr *> *Vars = &Uniforms;
- if (CKind == OMPC_aligned)
- Vars = &Aligneds;
- else if (CKind == OMPC_linear)
- Vars = &Linears;
- P.ConsumeToken();
- if (P.ParseOpenMPVarList(OMPD_declare_simd,
- getOpenMPClauseKind(ClauseName), *Vars, Data))
- IsError = true;
- if (CKind == OMPC_aligned) {
- Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
- } else if (CKind == OMPC_linear) {
- if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
- Data.DepLinMapLoc))
- Data.LinKind = OMPC_LINEAR_val;
- LinModifiers.append(Linears.size() - LinModifiers.size(),
- Data.LinKind);
- Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
- }
- } else
- // TODO: add parsing of other clauses.
- break;
- }
- // Skip ',' if any.
- if (Tok.is(tok::comma))
- P.ConsumeToken();
- }
- return IsError;
- }
- /// Parse clauses for '#pragma omp declare simd'.
- Parser::DeclGroupPtrTy
- Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
- CachedTokens &Toks, SourceLocation Loc) {
- PP.EnterToken(Tok, /*IsReinject*/ true);
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject*/ true);
- // Consume the previously pushed token.
- ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- FNContextRAII FnContext(*this, Ptr);
- OMPDeclareSimdDeclAttr::BranchStateTy BS =
- OMPDeclareSimdDeclAttr::BS_Undefined;
- ExprResult Simdlen;
- SmallVector<Expr *, 4> Uniforms;
- SmallVector<Expr *, 4> Aligneds;
- SmallVector<Expr *, 4> Alignments;
- SmallVector<Expr *, 4> Linears;
- SmallVector<unsigned, 4> LinModifiers;
- SmallVector<Expr *, 4> Steps;
- bool IsError =
- parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
- Alignments, Linears, LinModifiers, Steps);
- // Need to check for extra tokens.
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_declare_simd);
- while (Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- }
- // Skip the last annot_pragma_openmp_end.
- SourceLocation EndLoc = ConsumeAnnotationToken();
- if (IsError)
- return Ptr;
- return Actions.ActOnOpenMPDeclareSimdDirective(
- Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
- LinModifiers, Steps, SourceRange(Loc, EndLoc));
- }
- /// Parse optional 'score' '(' <expr> ')' ':'.
- static ExprResult parseContextScore(Parser &P) {
- ExprResult ScoreExpr;
- SmallString<16> Buffer;
- StringRef SelectorName =
- P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
- OMPDeclareVariantAttr::ScoreType ScoreKind =
- OMPDeclareVariantAttr::ScoreUnknown;
- (void)OMPDeclareVariantAttr::ConvertStrToScoreType(SelectorName, ScoreKind);
- if (ScoreKind == OMPDeclareVariantAttr::ScoreUnknown)
- return ScoreExpr;
- assert(ScoreKind == OMPDeclareVariantAttr::ScoreSpecified &&
- "Expected \"score\" clause.");
- (void)P.ConsumeToken();
- SourceLocation RLoc;
- ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
- // Parse ':'
- if (P.getCurToken().is(tok::colon))
- (void)P.ConsumeAnyToken();
- else
- P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon)
- << "context selector score clause";
- return ScoreExpr;
- }
- /// Parse context selector for 'implementation' selector set:
- /// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> }
- /// ')'
- static void parseImplementationSelector(
- Parser &P, SourceLocation Loc,
- llvm::function_ref<void(SourceRange,
- const Sema::OpenMPDeclareVariantCtsSelectorData &)>
- Callback) {
- const Token &Tok = P.getCurToken();
- // Parse inner context selector set name, if any.
- if (!Tok.is(tok::identifier)) {
- P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
- << "implementation";
- // Skip until either '}', ')', or end of directive.
- while (!P.SkipUntil(tok::r_brace, tok::r_paren,
- tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
- ;
- return;
- }
- SmallString<16> Buffer;
- StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
- OMPDeclareVariantAttr::CtxSelectorType CSKind =
- OMPDeclareVariantAttr::CtxUnknown;
- (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorType(CtxSelectorName,
- CSKind);
- (void)P.ConsumeToken();
- switch (CSKind) {
- case OMPDeclareVariantAttr::CtxVendor: {
- // Parse '('.
- BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
- (void)T.expectAndConsume(diag::err_expected_lparen_after,
- CtxSelectorName.data());
- const ExprResult Score = parseContextScore(P);
- do {
- // Parse <vendor>.
- StringRef VendorName;
- if (Tok.is(tok::identifier)) {
- Buffer.clear();
- VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
- (void)P.ConsumeToken();
- } else {
- P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
- << "vendor identifier"
- << "vendor"
- << "implementation";
- }
- if (!VendorName.empty()) {
- Sema::OpenMPDeclareVariantCtsSelectorData Data(
- OMPDeclareVariantAttr::CtxSetImplementation, CSKind, VendorName,
- Score);
- Callback(SourceRange(Loc, Tok.getLocation()), Data);
- }
- if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
- P.Diag(Tok, diag::err_expected_punc)
- << (VendorName.empty() ? "vendor name" : VendorName);
- }
- } while (Tok.is(tok::identifier));
- // Parse ')'.
- (void)T.consumeClose();
- break;
- }
- case OMPDeclareVariantAttr::CtxUnknown:
- P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
- << "implementation";
- // Skip until either '}', ')', or end of directive.
- while (!P.SkipUntil(tok::r_brace, tok::r_paren,
- tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
- ;
- return;
- }
- }
- /// Parses clauses for 'declare variant' directive.
- /// clause:
- /// <selector_set_name> '=' '{' <context_selectors> '}'
- /// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
- bool Parser::parseOpenMPContextSelectors(
- SourceLocation Loc,
- llvm::function_ref<void(SourceRange,
- const Sema::OpenMPDeclareVariantCtsSelectorData &)>
- Callback) {
- do {
- // Parse inner context selector set name.
- if (!Tok.is(tok::identifier)) {
- Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector)
- << getOpenMPClauseName(OMPC_match);
- return true;
- }
- SmallString<16> Buffer;
- StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer);
- // Parse '='.
- (void)ConsumeToken();
- if (Tok.isNot(tok::equal)) {
- Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
- << CtxSelectorSetName;
- return true;
- }
- (void)ConsumeToken();
- // TBD: add parsing of known context selectors.
- // Unknown selector - just ignore it completely.
- {
- // Parse '{'.
- BalancedDelimiterTracker TBr(*this, tok::l_brace,
- tok::annot_pragma_openmp_end);
- if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
- return true;
- OMPDeclareVariantAttr::CtxSelectorSetType CSSKind =
- OMPDeclareVariantAttr::CtxSetUnknown;
- (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorSetType(
- CtxSelectorSetName, CSSKind);
- switch (CSSKind) {
- case OMPDeclareVariantAttr::CtxSetImplementation:
- parseImplementationSelector(*this, Loc, Callback);
- break;
- case OMPDeclareVariantAttr::CtxSetUnknown:
- // Skip until either '}', ')', or end of directive.
- while (!SkipUntil(tok::r_brace, tok::r_paren,
- tok::annot_pragma_openmp_end, StopBeforeMatch))
- ;
- break;
- }
- // Parse '}'.
- (void)TBr.consumeClose();
- }
- // Consume ','
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end))
- (void)ExpectAndConsume(tok::comma);
- } while (Tok.isAnyIdentifier());
- return false;
- }
- /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
- void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
- CachedTokens &Toks,
- SourceLocation Loc) {
- PP.EnterToken(Tok, /*IsReinject*/ true);
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject*/ true);
- // Consume the previously pushed token.
- ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- FNContextRAII FnContext(*this, Ptr);
- // Parse function declaration id.
- SourceLocation RLoc;
- // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
- // instead of MemberExprs.
- ExprResult AssociatedFunction =
- ParseOpenMPParensExpr(getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
- /*IsAddressOfOperand=*/true);
- if (!AssociatedFunction.isUsable()) {
- if (!Tok.is(tok::annot_pragma_openmp_end))
- while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
- ;
- // Skip the last annot_pragma_openmp_end.
- (void)ConsumeAnnotationToken();
- return;
- }
- Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
- Actions.checkOpenMPDeclareVariantFunction(
- Ptr, AssociatedFunction.get(), SourceRange(Loc, Tok.getLocation()));
- // Parse 'match'.
- OpenMPClauseKind CKind = Tok.isAnnotation()
- ? OMPC_unknown
- : getOpenMPClauseKind(PP.getSpelling(Tok));
- if (CKind != OMPC_match) {
- Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
- << getOpenMPClauseName(OMPC_match);
- while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
- ;
- // Skip the last annot_pragma_openmp_end.
- (void)ConsumeAnnotationToken();
- return;
- }
- (void)ConsumeToken();
- // Parse '('.
- BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPClauseName(OMPC_match))) {
- while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
- ;
- // Skip the last annot_pragma_openmp_end.
- (void)ConsumeAnnotationToken();
- return;
- }
- // Parse inner context selectors.
- if (!parseOpenMPContextSelectors(
- Loc, [this, &DeclVarData](
- SourceRange SR,
- const Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
- if (DeclVarData.hasValue())
- Actions.ActOnOpenMPDeclareVariantDirective(
- DeclVarData.getValue().first, DeclVarData.getValue().second,
- SR, Data);
- })) {
- // Parse ')'.
- (void)T.consumeClose();
- // Need to check for extra tokens.
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_declare_variant);
- }
- }
- // Skip last tokens.
- while (Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- // Skip the last annot_pragma_openmp_end.
- (void)ConsumeAnnotationToken();
- }
- /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
- ///
- /// default-clause:
- /// 'default' '(' 'none' | 'shared' ')
- ///
- /// proc_bind-clause:
- /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
- ///
- /// device_type-clause:
- /// 'device_type' '(' 'host' | 'nohost' | 'any' )'
- namespace {
- struct SimpleClauseData {
- unsigned Type;
- SourceLocation Loc;
- SourceLocation LOpen;
- SourceLocation TypeLoc;
- SourceLocation RLoc;
- SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
- SourceLocation TypeLoc, SourceLocation RLoc)
- : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
- };
- } // anonymous namespace
- static Optional<SimpleClauseData>
- parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
- const Token &Tok = P.getCurToken();
- SourceLocation Loc = Tok.getLocation();
- SourceLocation LOpen = P.ConsumeToken();
- // Parse '('.
- BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPClauseName(Kind)))
- return llvm::None;
- unsigned Type = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok));
- SourceLocation TypeLoc = Tok.getLocation();
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- P.ConsumeAnyToken();
- // Parse ')'.
- SourceLocation RLoc = Tok.getLocation();
- if (!T.consumeClose())
- RLoc = T.getCloseLocation();
- return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
- }
- Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
- // OpenMP 4.5 syntax with list of entities.
- Sema::NamedDeclSetType SameDirectiveDecls;
- SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation,
- NamedDecl *>,
- 4>
- DeclareTargetDecls;
- OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
- SourceLocation DeviceTypeLoc;
- while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
- if (Tok.is(tok::identifier)) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
- StringRef ClauseName = II->getName();
- bool IsDeviceTypeClause =
- getLangOpts().OpenMP >= 50 &&
- getOpenMPClauseKind(ClauseName) == OMPC_device_type;
- // Parse 'to|link|device_type' clauses.
- if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
- !IsDeviceTypeClause) {
- Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
- << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
- break;
- }
- // Parse 'device_type' clause and go to next clause if any.
- if (IsDeviceTypeClause) {
- Optional<SimpleClauseData> DevTypeData =
- parseOpenMPSimpleClause(*this, OMPC_device_type);
- if (DevTypeData.hasValue()) {
- if (DeviceTypeLoc.isValid()) {
- // We already saw another device_type clause, diagnose it.
- Diag(DevTypeData.getValue().Loc,
- diag::warn_omp_more_one_device_type_clause);
- }
- switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
- case OMPC_DEVICE_TYPE_any:
- DT = OMPDeclareTargetDeclAttr::DT_Any;
- break;
- case OMPC_DEVICE_TYPE_host:
- DT = OMPDeclareTargetDeclAttr::DT_Host;
- break;
- case OMPC_DEVICE_TYPE_nohost:
- DT = OMPDeclareTargetDeclAttr::DT_NoHost;
- break;
- case OMPC_DEVICE_TYPE_unknown:
- llvm_unreachable("Unexpected device_type");
- }
- DeviceTypeLoc = DevTypeData.getValue().Loc;
- }
- continue;
- }
- ConsumeToken();
- }
- auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls](
- CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
- NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName(
- getCurScope(), SS, NameInfo, SameDirectiveDecls);
- if (ND)
- DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);
- };
- if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
- /*AllowScopeSpecifier=*/true))
- break;
- // Consume optional ','.
- if (Tok.is(tok::comma))
- ConsumeToken();
- }
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- ConsumeAnyToken();
- for (auto &MTLocDecl : DeclareTargetDecls) {
- OMPDeclareTargetDeclAttr::MapTypeTy MT;
- SourceLocation Loc;
- NamedDecl *ND;
- std::tie(MT, Loc, ND) = MTLocDecl;
- // device_type clause is applied only to functions.
- Actions.ActOnOpenMPDeclareTargetName(
- ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT);
- }
- SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
- SameDirectiveDecls.end());
- if (Decls.empty())
- return DeclGroupPtrTy();
- return Actions.BuildDeclaratorGroup(Decls);
- }
- void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
- SourceLocation DTLoc) {
- if (DKind != OMPD_end_declare_target) {
- Diag(Tok, diag::err_expected_end_declare_target);
- Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
- return;
- }
- ConsumeAnyToken();
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_end_declare_target);
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- }
- // Skip the last annot_pragma_openmp_end.
- ConsumeAnyToken();
- }
- /// Parsing of declarative OpenMP directives.
- ///
- /// threadprivate-directive:
- /// annot_pragma_openmp 'threadprivate' simple-variable-list
- /// annot_pragma_openmp_end
- ///
- /// allocate-directive:
- /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
- /// annot_pragma_openmp_end
- ///
- /// declare-reduction-directive:
- /// annot_pragma_openmp 'declare' 'reduction' [...]
- /// annot_pragma_openmp_end
- ///
- /// declare-mapper-directive:
- /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
- /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
- /// annot_pragma_openmp_end
- ///
- /// declare-simd-directive:
- /// annot_pragma_openmp 'declare simd' {<clause> [,]}
- /// annot_pragma_openmp_end
- /// <function declaration/definition>
- ///
- /// requires directive:
- /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
- /// annot_pragma_openmp_end
- ///
- Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
- AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
- DeclSpec::TST TagType, Decl *Tag) {
- assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
- ParenBraceBracketBalancer BalancerRAIIObj(*this);
- SourceLocation Loc = ConsumeAnnotationToken();
- OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
- switch (DKind) {
- case OMPD_threadprivate: {
- ConsumeToken();
- DeclDirectiveListParserHelper Helper(this, DKind);
- if (!ParseOpenMPSimpleVarList(DKind, Helper,
- /*AllowScopeSpecifier=*/true)) {
- // The last seen token is annot_pragma_openmp_end - need to check for
- // extra tokens.
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(DKind);
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- }
- // Skip the last annot_pragma_openmp_end.
- ConsumeAnnotationToken();
- return Actions.ActOnOpenMPThreadprivateDirective(Loc,
- Helper.getIdentifiers());
- }
- break;
- }
- case OMPD_allocate: {
- ConsumeToken();
- DeclDirectiveListParserHelper Helper(this, DKind);
- if (!ParseOpenMPSimpleVarList(DKind, Helper,
- /*AllowScopeSpecifier=*/true)) {
- SmallVector<OMPClause *, 1> Clauses;
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
- OMPC_unknown + 1>
- FirstClauses(OMPC_unknown + 1);
- while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- OpenMPClauseKind CKind =
- Tok.isAnnotation() ? OMPC_unknown
- : getOpenMPClauseKind(PP.getSpelling(Tok));
- Actions.StartOpenMPClause(CKind);
- OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
- !FirstClauses[CKind].getInt());
- SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- FirstClauses[CKind].setInt(true);
- if (Clause != nullptr)
- Clauses.push_back(Clause);
- if (Tok.is(tok::annot_pragma_openmp_end)) {
- Actions.EndOpenMPClause();
- break;
- }
- // Skip ',' if any.
- if (Tok.is(tok::comma))
- ConsumeToken();
- Actions.EndOpenMPClause();
- }
- // The last seen token is annot_pragma_openmp_end - need to check for
- // extra tokens.
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(DKind);
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- }
- }
- // Skip the last annot_pragma_openmp_end.
- ConsumeAnnotationToken();
- return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
- Clauses);
- }
- break;
- }
- case OMPD_requires: {
- SourceLocation StartLoc = ConsumeToken();
- SmallVector<OMPClause *, 5> Clauses;
- SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
- FirstClauses(OMPC_unknown + 1);
- if (Tok.is(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::err_omp_expected_clause)
- << getOpenMPDirectiveName(OMPD_requires);
- break;
- }
- while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- OpenMPClauseKind CKind = Tok.isAnnotation()
- ? OMPC_unknown
- : getOpenMPClauseKind(PP.getSpelling(Tok));
- Actions.StartOpenMPClause(CKind);
- OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
- !FirstClauses[CKind].getInt());
- SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- FirstClauses[CKind].setInt(true);
- if (Clause != nullptr)
- Clauses.push_back(Clause);
- if (Tok.is(tok::annot_pragma_openmp_end)) {
- Actions.EndOpenMPClause();
- break;
- }
- // Skip ',' if any.
- if (Tok.is(tok::comma))
- ConsumeToken();
- Actions.EndOpenMPClause();
- }
- // Consume final annot_pragma_openmp_end
- if (Clauses.size() == 0) {
- Diag(Tok, diag::err_omp_expected_clause)
- << getOpenMPDirectiveName(OMPD_requires);
- ConsumeAnnotationToken();
- return nullptr;
- }
- ConsumeAnnotationToken();
- return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
- }
- case OMPD_declare_reduction:
- ConsumeToken();
- if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
- // The last seen token is annot_pragma_openmp_end - need to check for
- // extra tokens.
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_declare_reduction);
- while (Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- }
- // Skip the last annot_pragma_openmp_end.
- ConsumeAnnotationToken();
- return Res;
- }
- break;
- case OMPD_declare_mapper: {
- ConsumeToken();
- if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
- // Skip the last annot_pragma_openmp_end.
- ConsumeAnnotationToken();
- return Res;
- }
- break;
- }
- case OMPD_declare_variant:
- case OMPD_declare_simd: {
- // The syntax is:
- // { #pragma omp declare {simd|variant} }
- // <function-declaration-or-definition>
- //
- CachedTokens Toks;
- Toks.push_back(Tok);
- ConsumeToken();
- while(Tok.isNot(tok::annot_pragma_openmp_end)) {
- Toks.push_back(Tok);
- ConsumeAnyToken();
- }
- Toks.push_back(Tok);
- ConsumeAnyToken();
- DeclGroupPtrTy Ptr;
- if (Tok.is(tok::annot_pragma_openmp)) {
- Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
- } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
- // Here we expect to see some function declaration.
- if (AS == AS_none) {
- assert(TagType == DeclSpec::TST_unspecified);
- MaybeParseCXX11Attributes(Attrs);
- ParsingDeclSpec PDS(*this);
- Ptr = ParseExternalDeclaration(Attrs, &PDS);
- } else {
- Ptr =
- ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
- }
- }
- if (!Ptr) {
- Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
- << (DKind == OMPD_declare_simd ? 0 : 1);
- return DeclGroupPtrTy();
- }
- if (DKind == OMPD_declare_simd)
- return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
- assert(DKind == OMPD_declare_variant &&
- "Expected declare variant directive only");
- ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
- return Ptr;
- }
- case OMPD_declare_target: {
- SourceLocation DTLoc = ConsumeAnyToken();
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- return ParseOMPDeclareTargetClauses();
- }
- // Skip the last annot_pragma_openmp_end.
- ConsumeAnyToken();
- if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
- return DeclGroupPtrTy();
- llvm::SmallVector<Decl *, 4> Decls;
- DKind = parseOpenMPDirectiveKind(*this);
- while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
- Tok.isNot(tok::r_brace)) {
- DeclGroupPtrTy Ptr;
- // Here we expect to see some function declaration.
- if (AS == AS_none) {
- assert(TagType == DeclSpec::TST_unspecified);
- MaybeParseCXX11Attributes(Attrs);
- ParsingDeclSpec PDS(*this);
- Ptr = ParseExternalDeclaration(Attrs, &PDS);
- } else {
- Ptr =
- ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
- }
- if (Ptr) {
- DeclGroupRef Ref = Ptr.get();
- Decls.append(Ref.begin(), Ref.end());
- }
- if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
- TentativeParsingAction TPA(*this);
- ConsumeAnnotationToken();
- DKind = parseOpenMPDirectiveKind(*this);
- if (DKind != OMPD_end_declare_target)
- TPA.Revert();
- else
- TPA.Commit();
- }
- }
- ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
- Actions.ActOnFinishOpenMPDeclareTargetDirective();
- return Actions.BuildDeclaratorGroup(Decls);
- }
- case OMPD_unknown:
- Diag(Tok, diag::err_omp_unknown_directive);
- break;
- case OMPD_parallel:
- case OMPD_simd:
- case OMPD_task:
- case OMPD_taskyield:
- case OMPD_barrier:
- case OMPD_taskwait:
- case OMPD_taskgroup:
- case OMPD_flush:
- case OMPD_for:
- case OMPD_for_simd:
- case OMPD_sections:
- case OMPD_section:
- case OMPD_single:
- case OMPD_master:
- case OMPD_ordered:
- case OMPD_critical:
- case OMPD_parallel_for:
- case OMPD_parallel_for_simd:
- case OMPD_parallel_sections:
- case OMPD_atomic:
- case OMPD_target:
- case OMPD_teams:
- case OMPD_cancellation_point:
- case OMPD_cancel:
- case OMPD_target_data:
- case OMPD_target_enter_data:
- case OMPD_target_exit_data:
- case OMPD_target_parallel:
- case OMPD_target_parallel_for:
- case OMPD_taskloop:
- case OMPD_taskloop_simd:
- case OMPD_distribute:
- case OMPD_end_declare_target:
- case OMPD_target_update:
- case OMPD_distribute_parallel_for:
- case OMPD_distribute_parallel_for_simd:
- case OMPD_distribute_simd:
- case OMPD_target_parallel_for_simd:
- case OMPD_target_simd:
- case OMPD_teams_distribute:
- case OMPD_teams_distribute_simd:
- case OMPD_teams_distribute_parallel_for_simd:
- case OMPD_teams_distribute_parallel_for:
- case OMPD_target_teams:
- case OMPD_target_teams_distribute:
- case OMPD_target_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute_parallel_for_simd:
- case OMPD_target_teams_distribute_simd:
- Diag(Tok, diag::err_omp_unexpected_directive)
- << 1 << getOpenMPDirectiveName(DKind);
- break;
- }
- while (Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- ConsumeAnyToken();
- return nullptr;
- }
- /// Parsing of declarative or executable OpenMP directives.
- ///
- /// threadprivate-directive:
- /// annot_pragma_openmp 'threadprivate' simple-variable-list
- /// annot_pragma_openmp_end
- ///
- /// allocate-directive:
- /// annot_pragma_openmp 'allocate' simple-variable-list
- /// annot_pragma_openmp_end
- ///
- /// declare-reduction-directive:
- /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
- /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
- /// ('omp_priv' '=' <expression>|<function_call>) ')']
- /// annot_pragma_openmp_end
- ///
- /// declare-mapper-directive:
- /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
- /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
- /// annot_pragma_openmp_end
- ///
- /// executable-directive:
- /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
- /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
- /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
- /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
- /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
- /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
- /// 'distribute' | 'target enter data' | 'target exit data' |
- /// 'target parallel' | 'target parallel for' |
- /// 'target update' | 'distribute parallel for' |
- /// 'distribute paralle for simd' | 'distribute simd' |
- /// 'target parallel for simd' | 'target simd' |
- /// 'teams distribute' | 'teams distribute simd' |
- /// 'teams distribute parallel for simd' |
- /// 'teams distribute parallel for' | 'target teams' |
- /// 'target teams distribute' |
- /// 'target teams distribute parallel for' |
- /// 'target teams distribute parallel for simd' |
- /// 'target teams distribute simd' {clause}
- /// annot_pragma_openmp_end
- ///
- StmtResult
- Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
- assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
- ParenBraceBracketBalancer BalancerRAIIObj(*this);
- SmallVector<OMPClause *, 5> Clauses;
- SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
- FirstClauses(OMPC_unknown + 1);
- unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
- Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
- SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
- OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
- OpenMPDirectiveKind CancelRegion = OMPD_unknown;
- // Name of critical directive.
- DeclarationNameInfo DirName;
- StmtResult Directive = StmtError();
- bool HasAssociatedStatement = true;
- bool FlushHasClause = false;
- switch (DKind) {
- case OMPD_threadprivate: {
- // FIXME: Should this be permitted in C++?
- if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
- ParsedStmtContext()) {
- Diag(Tok, diag::err_omp_immediate_directive)
- << getOpenMPDirectiveName(DKind) << 0;
- }
- ConsumeToken();
- DeclDirectiveListParserHelper Helper(this, DKind);
- if (!ParseOpenMPSimpleVarList(DKind, Helper,
- /*AllowScopeSpecifier=*/false)) {
- // The last seen token is annot_pragma_openmp_end - need to check for
- // extra tokens.
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(DKind);
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- }
- DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
- Loc, Helper.getIdentifiers());
- Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
- }
- SkipUntil(tok::annot_pragma_openmp_end);
- break;
- }
- case OMPD_allocate: {
- // FIXME: Should this be permitted in C++?
- if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
- ParsedStmtContext()) {
- Diag(Tok, diag::err_omp_immediate_directive)
- << getOpenMPDirectiveName(DKind) << 0;
- }
- ConsumeToken();
- DeclDirectiveListParserHelper Helper(this, DKind);
- if (!ParseOpenMPSimpleVarList(DKind, Helper,
- /*AllowScopeSpecifier=*/false)) {
- SmallVector<OMPClause *, 1> Clauses;
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
- OMPC_unknown + 1>
- FirstClauses(OMPC_unknown + 1);
- while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- OpenMPClauseKind CKind =
- Tok.isAnnotation() ? OMPC_unknown
- : getOpenMPClauseKind(PP.getSpelling(Tok));
- Actions.StartOpenMPClause(CKind);
- OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
- !FirstClauses[CKind].getInt());
- SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- FirstClauses[CKind].setInt(true);
- if (Clause != nullptr)
- Clauses.push_back(Clause);
- if (Tok.is(tok::annot_pragma_openmp_end)) {
- Actions.EndOpenMPClause();
- break;
- }
- // Skip ',' if any.
- if (Tok.is(tok::comma))
- ConsumeToken();
- Actions.EndOpenMPClause();
- }
- // The last seen token is annot_pragma_openmp_end - need to check for
- // extra tokens.
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(DKind);
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- }
- }
- DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
- Loc, Helper.getIdentifiers(), Clauses);
- Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
- }
- SkipUntil(tok::annot_pragma_openmp_end);
- break;
- }
- case OMPD_declare_reduction:
- ConsumeToken();
- if (DeclGroupPtrTy Res =
- ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
- // The last seen token is annot_pragma_openmp_end - need to check for
- // extra tokens.
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_declare_reduction);
- while (Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- }
- ConsumeAnyToken();
- Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
- } else {
- SkipUntil(tok::annot_pragma_openmp_end);
- }
- break;
- case OMPD_declare_mapper: {
- ConsumeToken();
- if (DeclGroupPtrTy Res =
- ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
- // Skip the last annot_pragma_openmp_end.
- ConsumeAnnotationToken();
- Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
- } else {
- SkipUntil(tok::annot_pragma_openmp_end);
- }
- break;
- }
- case OMPD_flush:
- if (PP.LookAhead(0).is(tok::l_paren)) {
- FlushHasClause = true;
- // Push copy of the current token back to stream to properly parse
- // pseudo-clause OMPFlushClause.
- PP.EnterToken(Tok, /*IsReinject*/ true);
- }
- LLVM_FALLTHROUGH;
- case OMPD_taskyield:
- case OMPD_barrier:
- case OMPD_taskwait:
- case OMPD_cancellation_point:
- case OMPD_cancel:
- case OMPD_target_enter_data:
- case OMPD_target_exit_data:
- case OMPD_target_update:
- if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
- ParsedStmtContext()) {
- Diag(Tok, diag::err_omp_immediate_directive)
- << getOpenMPDirectiveName(DKind) << 0;
- }
- HasAssociatedStatement = false;
- // Fall through for further analysis.
- LLVM_FALLTHROUGH;
- case OMPD_parallel:
- case OMPD_simd:
- case OMPD_for:
- case OMPD_for_simd:
- case OMPD_sections:
- case OMPD_single:
- case OMPD_section:
- case OMPD_master:
- case OMPD_critical:
- case OMPD_parallel_for:
- case OMPD_parallel_for_simd:
- case OMPD_parallel_sections:
- case OMPD_task:
- case OMPD_ordered:
- case OMPD_atomic:
- case OMPD_target:
- case OMPD_teams:
- case OMPD_taskgroup:
- case OMPD_target_data:
- case OMPD_target_parallel:
- case OMPD_target_parallel_for:
- case OMPD_taskloop:
- case OMPD_taskloop_simd:
- case OMPD_distribute:
- case OMPD_distribute_parallel_for:
- case OMPD_distribute_parallel_for_simd:
- case OMPD_distribute_simd:
- case OMPD_target_parallel_for_simd:
- case OMPD_target_simd:
- case OMPD_teams_distribute:
- case OMPD_teams_distribute_simd:
- case OMPD_teams_distribute_parallel_for_simd:
- case OMPD_teams_distribute_parallel_for:
- case OMPD_target_teams:
- case OMPD_target_teams_distribute:
- case OMPD_target_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute_parallel_for_simd:
- case OMPD_target_teams_distribute_simd: {
- ConsumeToken();
- // Parse directive name of the 'critical' directive if any.
- if (DKind == OMPD_critical) {
- BalancedDelimiterTracker T(*this, tok::l_paren,
- tok::annot_pragma_openmp_end);
- if (!T.consumeOpen()) {
- if (Tok.isAnyIdentifier()) {
- DirName =
- DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
- ConsumeAnyToken();
- } else {
- Diag(Tok, diag::err_omp_expected_identifier_for_critical);
- }
- T.consumeClose();
- }
- } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
- CancelRegion = parseOpenMPDirectiveKind(*this);
- if (Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeToken();
- }
- if (isOpenMPLoopDirective(DKind))
- ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
- if (isOpenMPSimdDirective(DKind))
- ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
- ParseScope OMPDirectiveScope(this, ScopeFlags);
- Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
- while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- OpenMPClauseKind CKind =
- Tok.isAnnotation()
- ? OMPC_unknown
- : FlushHasClause ? OMPC_flush
- : getOpenMPClauseKind(PP.getSpelling(Tok));
- Actions.StartOpenMPClause(CKind);
- FlushHasClause = false;
- OMPClause *Clause =
- ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
- FirstClauses[CKind].setInt(true);
- if (Clause) {
- FirstClauses[CKind].setPointer(Clause);
- Clauses.push_back(Clause);
- }
- // Skip ',' if any.
- if (Tok.is(tok::comma))
- ConsumeToken();
- Actions.EndOpenMPClause();
- }
- // End location of the directive.
- EndLoc = Tok.getLocation();
- // Consume final annot_pragma_openmp_end.
- ConsumeAnnotationToken();
- // OpenMP [2.13.8, ordered Construct, Syntax]
- // If the depend clause is specified, the ordered construct is a stand-alone
- // directive.
- if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
- if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
- ParsedStmtContext()) {
- Diag(Loc, diag::err_omp_immediate_directive)
- << getOpenMPDirectiveName(DKind) << 1
- << getOpenMPClauseName(OMPC_depend);
- }
- HasAssociatedStatement = false;
- }
- StmtResult AssociatedStmt;
- if (HasAssociatedStatement) {
- // The body is a block scope like in Lambdas and Blocks.
- Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
- // FIXME: We create a bogus CompoundStmt scope to hold the contents of
- // the captured region. Code elsewhere assumes that any FunctionScopeInfo
- // should have at least one compound statement scope within it.
- AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
- AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
- } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
- DKind == OMPD_target_exit_data) {
- Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
- AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
- Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
- /*isStmtExpr=*/false));
- AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
- }
- Directive = Actions.ActOnOpenMPExecutableDirective(
- DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
- EndLoc);
- // Exit scope.
- Actions.EndOpenMPDSABlock(Directive.get());
- OMPDirectiveScope.Exit();
- break;
- }
- case OMPD_declare_simd:
- case OMPD_declare_target:
- case OMPD_end_declare_target:
- case OMPD_requires:
- case OMPD_declare_variant:
- Diag(Tok, diag::err_omp_unexpected_directive)
- << 1 << getOpenMPDirectiveName(DKind);
- SkipUntil(tok::annot_pragma_openmp_end);
- break;
- case OMPD_unknown:
- Diag(Tok, diag::err_omp_unknown_directive);
- SkipUntil(tok::annot_pragma_openmp_end);
- break;
- }
- return Directive;
- }
- // Parses simple list:
- // simple-variable-list:
- // '(' id-expression {, id-expression} ')'
- //
- bool Parser::ParseOpenMPSimpleVarList(
- OpenMPDirectiveKind Kind,
- const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
- Callback,
- bool AllowScopeSpecifier) {
- // Parse '('.
- BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPDirectiveName(Kind)))
- return true;
- bool IsCorrect = true;
- bool NoIdentIsFound = true;
- // Read tokens while ')' or annot_pragma_openmp_end is not found.
- while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
- CXXScopeSpec SS;
- UnqualifiedId Name;
- // Read var name.
- Token PrevTok = Tok;
- NoIdentIsFound = false;
- if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
- ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
- IsCorrect = false;
- SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
- nullptr, Name)) {
- IsCorrect = false;
- SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
- Tok.isNot(tok::annot_pragma_openmp_end)) {
- IsCorrect = false;
- SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- Diag(PrevTok.getLocation(), diag::err_expected)
- << tok::identifier
- << SourceRange(PrevTok.getLocation(), PrevTokLocation);
- } else {
- Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
- }
- // Consume ','.
- if (Tok.is(tok::comma)) {
- ConsumeToken();
- }
- }
- if (NoIdentIsFound) {
- Diag(Tok, diag::err_expected) << tok::identifier;
- IsCorrect = false;
- }
- // Parse ')'.
- IsCorrect = !T.consumeClose() && IsCorrect;
- return !IsCorrect;
- }
- /// Parsing of OpenMP clauses.
- ///
- /// clause:
- /// if-clause | final-clause | num_threads-clause | safelen-clause |
- /// default-clause | private-clause | firstprivate-clause | shared-clause
- /// | linear-clause | aligned-clause | collapse-clause |
- /// lastprivate-clause | reduction-clause | proc_bind-clause |
- /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
- /// mergeable-clause | flush-clause | read-clause | write-clause |
- /// update-clause | capture-clause | seq_cst-clause | device-clause |
- /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
- /// thread_limit-clause | priority-clause | grainsize-clause |
- /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
- /// from-clause | is_device_ptr-clause | task_reduction-clause |
- /// in_reduction-clause | allocator-clause | allocate-clause
- ///
- OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
- OpenMPClauseKind CKind, bool FirstClause) {
- OMPClause *Clause = nullptr;
- bool ErrorFound = false;
- bool WrongDirective = false;
- // Check if clause is allowed for the given directive.
- if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
- Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
- << getOpenMPDirectiveName(DKind);
- ErrorFound = true;
- WrongDirective = true;
- }
- switch (CKind) {
- case OMPC_final:
- case OMPC_num_threads:
- case OMPC_safelen:
- case OMPC_simdlen:
- case OMPC_collapse:
- case OMPC_ordered:
- case OMPC_device:
- case OMPC_num_teams:
- case OMPC_thread_limit:
- case OMPC_priority:
- case OMPC_grainsize:
- case OMPC_num_tasks:
- case OMPC_hint:
- case OMPC_allocator:
- // OpenMP [2.5, Restrictions]
- // At most one num_threads clause can appear on the directive.
- // OpenMP [2.8.1, simd construct, Restrictions]
- // Only one safelen clause can appear on a simd directive.
- // Only one simdlen clause can appear on a simd directive.
- // Only one collapse clause can appear on a simd directive.
- // OpenMP [2.9.1, target data construct, Restrictions]
- // At most one device clause can appear on the directive.
- // OpenMP [2.11.1, task Construct, Restrictions]
- // At most one if clause can appear on the directive.
- // At most one final clause can appear on the directive.
- // OpenMP [teams Construct, Restrictions]
- // At most one num_teams clause can appear on the directive.
- // At most one thread_limit clause can appear on the directive.
- // OpenMP [2.9.1, task Construct, Restrictions]
- // At most one priority clause can appear on the directive.
- // OpenMP [2.9.2, taskloop Construct, Restrictions]
- // At most one grainsize clause can appear on the directive.
- // OpenMP [2.9.2, taskloop Construct, Restrictions]
- // At most one num_tasks clause can appear on the directive.
- // OpenMP [2.11.3, allocate Directive, Restrictions]
- // At most one allocator clause can appear on the directive.
- if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause)
- << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
- ErrorFound = true;
- }
- if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
- Clause = ParseOpenMPClause(CKind, WrongDirective);
- else
- Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
- break;
- case OMPC_default:
- case OMPC_proc_bind:
- case OMPC_atomic_default_mem_order:
- // OpenMP [2.14.3.1, Restrictions]
- // Only a single default clause may be specified on a parallel, task or
- // teams directive.
- // OpenMP [2.5, parallel Construct, Restrictions]
- // At most one proc_bind clause can appear on the directive.
- // OpenMP [5.0, Requires directive, Restrictions]
- // At most one atomic_default_mem_order clause can appear
- // on the directive
- if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause)
- << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
- ErrorFound = true;
- }
- Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
- break;
- case OMPC_schedule:
- case OMPC_dist_schedule:
- case OMPC_defaultmap:
- // OpenMP [2.7.1, Restrictions, p. 3]
- // Only one schedule clause can appear on a loop directive.
- // OpenMP [2.10.4, Restrictions, p. 106]
- // At most one defaultmap clause can appear on the directive.
- if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause)
- << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
- ErrorFound = true;
- }
- LLVM_FALLTHROUGH;
- case OMPC_if:
- Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
- break;
- case OMPC_nowait:
- case OMPC_untied:
- case OMPC_mergeable:
- case OMPC_read:
- case OMPC_write:
- case OMPC_update:
- case OMPC_capture:
- case OMPC_seq_cst:
- case OMPC_threads:
- case OMPC_simd:
- case OMPC_nogroup:
- case OMPC_unified_address:
- case OMPC_unified_shared_memory:
- case OMPC_reverse_offload:
- case OMPC_dynamic_allocators:
- // OpenMP [2.7.1, Restrictions, p. 9]
- // Only one ordered clause can appear on a loop directive.
- // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
- // Only one nowait clause can appear on a for directive.
- // OpenMP [5.0, Requires directive, Restrictions]
- // Each of the requires clauses can appear at most once on the directive.
- if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause)
- << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
- ErrorFound = true;
- }
- Clause = ParseOpenMPClause(CKind, WrongDirective);
- break;
- case OMPC_private:
- case OMPC_firstprivate:
- case OMPC_lastprivate:
- case OMPC_shared:
- case OMPC_reduction:
- case OMPC_task_reduction:
- case OMPC_in_reduction:
- case OMPC_linear:
- case OMPC_aligned:
- case OMPC_copyin:
- case OMPC_copyprivate:
- case OMPC_flush:
- case OMPC_depend:
- case OMPC_map:
- case OMPC_to:
- case OMPC_from:
- case OMPC_use_device_ptr:
- case OMPC_is_device_ptr:
- case OMPC_allocate:
- Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
- break;
- case OMPC_device_type:
- case OMPC_unknown:
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(DKind);
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- break;
- case OMPC_threadprivate:
- case OMPC_uniform:
- case OMPC_match:
- if (!WrongDirective)
- Diag(Tok, diag::err_omp_unexpected_clause)
- << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
- SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
- break;
- }
- return ErrorFound ? nullptr : Clause;
- }
- /// Parses simple expression in parens for single-expression clauses of OpenMP
- /// constructs.
- /// \param RLoc Returned location of right paren.
- ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
- SourceLocation &RLoc,
- bool IsAddressOfOperand) {
- BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
- return ExprError();
- SourceLocation ELoc = Tok.getLocation();
- ExprResult LHS(ParseCastExpression(
- /*isUnaryExpression=*/false, IsAddressOfOperand, NotTypeCast));
- ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
- Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
- // Parse ')'.
- RLoc = Tok.getLocation();
- if (!T.consumeClose())
- RLoc = T.getCloseLocation();
- return Val;
- }
- /// Parsing of OpenMP clauses with single expressions like 'final',
- /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
- /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
- ///
- /// final-clause:
- /// 'final' '(' expression ')'
- ///
- /// num_threads-clause:
- /// 'num_threads' '(' expression ')'
- ///
- /// safelen-clause:
- /// 'safelen' '(' expression ')'
- ///
- /// simdlen-clause:
- /// 'simdlen' '(' expression ')'
- ///
- /// collapse-clause:
- /// 'collapse' '(' expression ')'
- ///
- /// priority-clause:
- /// 'priority' '(' expression ')'
- ///
- /// grainsize-clause:
- /// 'grainsize' '(' expression ')'
- ///
- /// num_tasks-clause:
- /// 'num_tasks' '(' expression ')'
- ///
- /// hint-clause:
- /// 'hint' '(' expression ')'
- ///
- /// allocator-clause:
- /// 'allocator' '(' expression ')'
- ///
- OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
- bool ParseOnly) {
- SourceLocation Loc = ConsumeToken();
- SourceLocation LLoc = Tok.getLocation();
- SourceLocation RLoc;
- ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
- if (Val.isInvalid())
- return nullptr;
- if (ParseOnly)
- return nullptr;
- return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
- }
- /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
- ///
- /// default-clause:
- /// 'default' '(' 'none' | 'shared' ')
- ///
- /// proc_bind-clause:
- /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
- ///
- OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
- bool ParseOnly) {
- llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
- if (!Val || ParseOnly)
- return nullptr;
- return Actions.ActOnOpenMPSimpleClause(
- Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
- Val.getValue().Loc, Val.getValue().RLoc);
- }
- /// Parsing of OpenMP clauses like 'ordered'.
- ///
- /// ordered-clause:
- /// 'ordered'
- ///
- /// nowait-clause:
- /// 'nowait'
- ///
- /// untied-clause:
- /// 'untied'
- ///
- /// mergeable-clause:
- /// 'mergeable'
- ///
- /// read-clause:
- /// 'read'
- ///
- /// threads-clause:
- /// 'threads'
- ///
- /// simd-clause:
- /// 'simd'
- ///
- /// nogroup-clause:
- /// 'nogroup'
- ///
- OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
- SourceLocation Loc = Tok.getLocation();
- ConsumeAnyToken();
- if (ParseOnly)
- return nullptr;
- return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
- }
- /// Parsing of OpenMP clauses with single expressions and some additional
- /// argument like 'schedule' or 'dist_schedule'.
- ///
- /// schedule-clause:
- /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
- /// ')'
- ///
- /// if-clause:
- /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
- ///
- /// defaultmap:
- /// 'defaultmap' '(' modifier ':' kind ')'
- ///
- OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
- bool ParseOnly) {
- SourceLocation Loc = ConsumeToken();
- SourceLocation DelimLoc;
- // Parse '('.
- BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPClauseName(Kind)))
- return nullptr;
- ExprResult Val;
- SmallVector<unsigned, 4> Arg;
- SmallVector<SourceLocation, 4> KLoc;
- if (Kind == OMPC_schedule) {
- enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
- Arg.resize(NumberOfElements);
- KLoc.resize(NumberOfElements);
- Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
- Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
- Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
- unsigned KindModifier = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
- if (KindModifier > OMPC_SCHEDULE_unknown) {
- // Parse 'modifier'
- Arg[Modifier1] = KindModifier;
- KLoc[Modifier1] = Tok.getLocation();
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- if (Tok.is(tok::comma)) {
- // Parse ',' 'modifier'
- ConsumeAnyToken();
- KindModifier = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
- Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
- ? KindModifier
- : (unsigned)OMPC_SCHEDULE_unknown;
- KLoc[Modifier2] = Tok.getLocation();
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- }
- // Parse ':'
- if (Tok.is(tok::colon))
- ConsumeAnyToken();
- else
- Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
- KindModifier = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
- }
- Arg[ScheduleKind] = KindModifier;
- KLoc[ScheduleKind] = Tok.getLocation();
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
- Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
- Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
- Tok.is(tok::comma))
- DelimLoc = ConsumeAnyToken();
- } else if (Kind == OMPC_dist_schedule) {
- Arg.push_back(getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
- KLoc.push_back(Tok.getLocation());
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
- DelimLoc = ConsumeAnyToken();
- } else if (Kind == OMPC_defaultmap) {
- // Get a defaultmap modifier
- Arg.push_back(getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
- KLoc.push_back(Tok.getLocation());
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- // Parse ':'
- if (Tok.is(tok::colon))
- ConsumeAnyToken();
- else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
- Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
- // Get a defaultmap kind
- Arg.push_back(getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
- KLoc.push_back(Tok.getLocation());
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
- } else {
- assert(Kind == OMPC_if);
- KLoc.push_back(Tok.getLocation());
- TentativeParsingAction TPA(*this);
- Arg.push_back(parseOpenMPDirectiveKind(*this));
- if (Arg.back() != OMPD_unknown) {
- ConsumeToken();
- if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
- TPA.Commit();
- DelimLoc = ConsumeToken();
- } else {
- TPA.Revert();
- Arg.back() = OMPD_unknown;
- }
- } else {
- TPA.Revert();
- }
- }
- bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
- (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
- Kind == OMPC_if;
- if (NeedAnExpression) {
- SourceLocation ELoc = Tok.getLocation();
- ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
- Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
- Val =
- Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
- }
- // Parse ')'.
- SourceLocation RLoc = Tok.getLocation();
- if (!T.consumeClose())
- RLoc = T.getCloseLocation();
- if (NeedAnExpression && Val.isInvalid())
- return nullptr;
- if (ParseOnly)
- return nullptr;
- return Actions.ActOnOpenMPSingleExprWithArgClause(
- Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
- }
- static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
- UnqualifiedId &ReductionId) {
- if (ReductionIdScopeSpec.isEmpty()) {
- auto OOK = OO_None;
- switch (P.getCurToken().getKind()) {
- case tok::plus:
- OOK = OO_Plus;
- break;
- case tok::minus:
- OOK = OO_Minus;
- break;
- case tok::star:
- OOK = OO_Star;
- break;
- case tok::amp:
- OOK = OO_Amp;
- break;
- case tok::pipe:
- OOK = OO_Pipe;
- break;
- case tok::caret:
- OOK = OO_Caret;
- break;
- case tok::ampamp:
- OOK = OO_AmpAmp;
- break;
- case tok::pipepipe:
- OOK = OO_PipePipe;
- break;
- default:
- break;
- }
- if (OOK != OO_None) {
- SourceLocation OpLoc = P.ConsumeToken();
- SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
- ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
- return false;
- }
- }
- return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
- /*AllowDestructorName*/ false,
- /*AllowConstructorName*/ false,
- /*AllowDeductionGuide*/ false,
- nullptr, nullptr, ReductionId);
- }
- /// Checks if the token is a valid map-type-modifier.
- static OpenMPMapModifierKind isMapModifier(Parser &P) {
- Token Tok = P.getCurToken();
- if (!Tok.is(tok::identifier))
- return OMPC_MAP_MODIFIER_unknown;
- Preprocessor &PP = P.getPreprocessor();
- OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
- getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
- return TypeModifier;
- }
- /// Parse the mapper modifier in map, to, and from clauses.
- bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
- // Parse '('.
- BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
- if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
- SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- return true;
- }
- // Parse mapper-identifier
- if (getLangOpts().CPlusPlus)
- ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
- /*ObjectType=*/nullptr,
- /*EnteringContext=*/false);
- if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
- Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
- SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- return true;
- }
- auto &DeclNames = Actions.getASTContext().DeclarationNames;
- Data.ReductionOrMapperId = DeclarationNameInfo(
- DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
- ConsumeToken();
- // Parse ')'.
- return T.consumeClose();
- }
- /// Parse map-type-modifiers in map clause.
- /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
- /// where, map-type-modifier ::= always | close | mapper(mapper-identifier)
- bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
- while (getCurToken().isNot(tok::colon)) {
- OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
- if (TypeModifier == OMPC_MAP_MODIFIER_always ||
- TypeModifier == OMPC_MAP_MODIFIER_close) {
- Data.MapTypeModifiers.push_back(TypeModifier);
- Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
- ConsumeToken();
- } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
- Data.MapTypeModifiers.push_back(TypeModifier);
- Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
- ConsumeToken();
- if (parseMapperModifier(Data))
- return true;
- } else {
- // For the case of unknown map-type-modifier or a map-type.
- // Map-type is followed by a colon; the function returns when it
- // encounters a token followed by a colon.
- if (Tok.is(tok::comma)) {
- Diag(Tok, diag::err_omp_map_type_modifier_missing);
- ConsumeToken();
- continue;
- }
- // Potential map-type token as it is followed by a colon.
- if (PP.LookAhead(0).is(tok::colon))
- return false;
- Diag(Tok, diag::err_omp_unknown_map_type_modifier);
- ConsumeToken();
- }
- if (getCurToken().is(tok::comma))
- ConsumeToken();
- }
- return false;
- }
- /// Checks if the token is a valid map-type.
- static OpenMPMapClauseKind isMapType(Parser &P) {
- Token Tok = P.getCurToken();
- // The map-type token can be either an identifier or the C++ delete keyword.
- if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
- return OMPC_MAP_unknown;
- Preprocessor &PP = P.getPreprocessor();
- OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
- getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
- return MapType;
- }
- /// Parse map-type in map clause.
- /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
- /// where, map-type ::= to | from | tofrom | alloc | release | delete
- static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
- Token Tok = P.getCurToken();
- if (Tok.is(tok::colon)) {
- P.Diag(Tok, diag::err_omp_map_type_missing);
- return;
- }
- Data.MapType = isMapType(P);
- if (Data.MapType == OMPC_MAP_unknown)
- P.Diag(Tok, diag::err_omp_unknown_map_type);
- P.ConsumeToken();
- }
- /// Parses clauses with list.
- bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
- OpenMPClauseKind Kind,
- SmallVectorImpl<Expr *> &Vars,
- OpenMPVarListDataTy &Data) {
- UnqualifiedId UnqualifiedReductionId;
- bool InvalidReductionId = false;
- bool IsInvalidMapperModifier = false;
- // Parse '('.
- BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPClauseName(Kind)))
- return true;
- bool NeedRParenForLinear = false;
- BalancedDelimiterTracker LinearT(*this, tok::l_paren,
- tok::annot_pragma_openmp_end);
- // Handle reduction-identifier for reduction clause.
- if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
- Kind == OMPC_in_reduction) {
- ColonProtectionRAIIObject ColonRAII(*this);
- if (getLangOpts().CPlusPlus)
- ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
- /*ObjectType=*/nullptr,
- /*EnteringContext=*/false);
- InvalidReductionId = ParseReductionId(
- *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
- if (InvalidReductionId) {
- SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- }
- if (Tok.is(tok::colon))
- Data.ColonLoc = ConsumeToken();
- else
- Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
- if (!InvalidReductionId)
- Data.ReductionOrMapperId =
- Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
- } else if (Kind == OMPC_depend) {
- // Handle dependency type for depend clause.
- ColonProtectionRAIIObject ColonRAII(*this);
- Data.DepKind =
- static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
- Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
- Data.DepLinMapLoc = Tok.getLocation();
- if (Data.DepKind == OMPC_DEPEND_unknown) {
- SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- } else {
- ConsumeToken();
- // Special processing for depend(source) clause.
- if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
- // Parse ')'.
- T.consumeClose();
- return false;
- }
- }
- if (Tok.is(tok::colon)) {
- Data.ColonLoc = ConsumeToken();
- } else {
- Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
- : diag::warn_pragma_expected_colon)
- << "dependency type";
- }
- } else if (Kind == OMPC_linear) {
- // Try to parse modifier if any.
- if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
- Data.LinKind = static_cast<OpenMPLinearClauseKind>(
- getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
- Data.DepLinMapLoc = ConsumeToken();
- LinearT.consumeOpen();
- NeedRParenForLinear = true;
- }
- } else if (Kind == OMPC_map) {
- // Handle map type for map clause.
- ColonProtectionRAIIObject ColonRAII(*this);
- // The first identifier may be a list item, a map-type or a
- // map-type-modifier. The map-type can also be delete which has the same
- // spelling of the C++ delete keyword.
- Data.DepLinMapLoc = Tok.getLocation();
- // Check for presence of a colon in the map clause.
- TentativeParsingAction TPA(*this);
- bool ColonPresent = false;
- if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch)) {
- if (Tok.is(tok::colon))
- ColonPresent = true;
- }
- TPA.Revert();
- // Only parse map-type-modifier[s] and map-type if a colon is present in
- // the map clause.
- if (ColonPresent) {
- IsInvalidMapperModifier = parseMapTypeModifiers(Data);
- if (!IsInvalidMapperModifier)
- parseMapType(*this, Data);
- else
- SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
- }
- if (Data.MapType == OMPC_MAP_unknown) {
- Data.MapType = OMPC_MAP_tofrom;
- Data.IsMapTypeImplicit = true;
- }
- if (Tok.is(tok::colon))
- Data.ColonLoc = ConsumeToken();
- } else if (Kind == OMPC_to || Kind == OMPC_from) {
- if (Tok.is(tok::identifier)) {
- bool IsMapperModifier = false;
- if (Kind == OMPC_to) {
- auto Modifier = static_cast<OpenMPToModifierKind>(
- getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
- if (Modifier == OMPC_TO_MODIFIER_mapper)
- IsMapperModifier = true;
- } else {
- auto Modifier = static_cast<OpenMPFromModifierKind>(
- getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
- if (Modifier == OMPC_FROM_MODIFIER_mapper)
- IsMapperModifier = true;
- }
- if (IsMapperModifier) {
- // Parse the mapper modifier.
- ConsumeToken();
- IsInvalidMapperModifier = parseMapperModifier(Data);
- if (Tok.isNot(tok::colon)) {
- if (!IsInvalidMapperModifier)
- Diag(Tok, diag::warn_pragma_expected_colon) << ")";
- SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- }
- // Consume ':'.
- if (Tok.is(tok::colon))
- ConsumeToken();
- }
- }
- } else if (Kind == OMPC_allocate) {
- // Handle optional allocator expression followed by colon delimiter.
- ColonProtectionRAIIObject ColonRAII(*this);
- TentativeParsingAction TPA(*this);
- ExprResult Tail =
- Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
- Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
- /*DiscardedValue=*/false);
- if (Tail.isUsable()) {
- if (Tok.is(tok::colon)) {
- Data.TailExpr = Tail.get();
- Data.ColonLoc = ConsumeToken();
- TPA.Commit();
- } else {
- // colon not found, no allocator specified, parse only list of
- // variables.
- TPA.Revert();
- }
- } else {
- // Parsing was unsuccessfull, revert and skip to the end of clause or
- // directive.
- TPA.Revert();
- SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- }
- }
- bool IsComma =
- (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
- Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
- (Kind == OMPC_reduction && !InvalidReductionId) ||
- (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) ||
- (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
- const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
- while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
- Tok.isNot(tok::annot_pragma_openmp_end))) {
- ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
- // Parse variable
- ExprResult VarExpr =
- Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
- if (VarExpr.isUsable()) {
- Vars.push_back(VarExpr.get());
- } else {
- SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- }
- // Skip ',' if any
- IsComma = Tok.is(tok::comma);
- if (IsComma)
- ConsumeToken();
- else if (Tok.isNot(tok::r_paren) &&
- Tok.isNot(tok::annot_pragma_openmp_end) &&
- (!MayHaveTail || Tok.isNot(tok::colon)))
- Diag(Tok, diag::err_omp_expected_punc)
- << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
- : getOpenMPClauseName(Kind))
- << (Kind == OMPC_flush);
- }
- // Parse ')' for linear clause with modifier.
- if (NeedRParenForLinear)
- LinearT.consumeClose();
- // Parse ':' linear-step (or ':' alignment).
- const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
- if (MustHaveTail) {
- Data.ColonLoc = Tok.getLocation();
- SourceLocation ELoc = ConsumeToken();
- ExprResult Tail = ParseAssignmentExpression();
- Tail =
- Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
- if (Tail.isUsable())
- Data.TailExpr = Tail.get();
- else
- SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
- }
- // Parse ')'.
- Data.RLoc = Tok.getLocation();
- if (!T.consumeClose())
- Data.RLoc = T.getCloseLocation();
- return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
- Vars.empty()) ||
- (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
- (MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
- IsInvalidMapperModifier;
- }
- /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
- /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
- /// 'in_reduction'.
- ///
- /// private-clause:
- /// 'private' '(' list ')'
- /// firstprivate-clause:
- /// 'firstprivate' '(' list ')'
- /// lastprivate-clause:
- /// 'lastprivate' '(' list ')'
- /// shared-clause:
- /// 'shared' '(' list ')'
- /// linear-clause:
- /// 'linear' '(' linear-list [ ':' linear-step ] ')'
- /// aligned-clause:
- /// 'aligned' '(' list [ ':' alignment ] ')'
- /// reduction-clause:
- /// 'reduction' '(' reduction-identifier ':' list ')'
- /// task_reduction-clause:
- /// 'task_reduction' '(' reduction-identifier ':' list ')'
- /// in_reduction-clause:
- /// 'in_reduction' '(' reduction-identifier ':' list ')'
- /// copyprivate-clause:
- /// 'copyprivate' '(' list ')'
- /// flush-clause:
- /// 'flush' '(' list ')'
- /// depend-clause:
- /// 'depend' '(' in | out | inout : list | source ')'
- /// map-clause:
- /// 'map' '(' [ [ always [,] ] [ close [,] ]
- /// [ mapper '(' mapper-identifier ')' [,] ]
- /// to | from | tofrom | alloc | release | delete ':' ] list ')';
- /// to-clause:
- /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
- /// from-clause:
- /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
- /// use_device_ptr-clause:
- /// 'use_device_ptr' '(' list ')'
- /// is_device_ptr-clause:
- /// 'is_device_ptr' '(' list ')'
- /// allocate-clause:
- /// 'allocate' '(' [ allocator ':' ] list ')'
- ///
- /// For 'linear' clause linear-list may have the following forms:
- /// list
- /// modifier(list)
- /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
- OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
- OpenMPClauseKind Kind,
- bool ParseOnly) {
- SourceLocation Loc = Tok.getLocation();
- SourceLocation LOpen = ConsumeToken();
- SmallVector<Expr *, 4> Vars;
- OpenMPVarListDataTy Data;
- if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
- return nullptr;
- if (ParseOnly)
- return nullptr;
- OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
- return Actions.ActOnOpenMPVarListClause(
- Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc,
- Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, Data.DepKind,
- Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
- Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc);
- }
|