1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// \brief This file implements parsing of all OpenMP directives and clauses.
12 //===----------------------------------------------------------------------===//
14 #include "RAIIObjectsForParser.h"
15 #include "clang/AST/ASTConsumer.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/StmtOpenMP.h"
18 #include "clang/Parse/ParseDiagnostic.h"
19 #include "clang/Parse/Parser.h"
20 #include "clang/Sema/Scope.h"
21 #include "llvm/ADT/PointerIntPair.h"
22 using namespace clang;
24 //===----------------------------------------------------------------------===//
25 // OpenMP declarative directives.
26 //===----------------------------------------------------------------------===//
28 static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
29 auto Tok = P.getCurToken();
33 : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
34 if (DKind == OMPD_parallel) {
35 Tok = P.getPreprocessor().LookAhead(0);
39 : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
40 if (SDKind == OMPD_for) {
42 DKind = OMPD_parallel_for;
43 } else if (SDKind == OMPD_sections) {
45 DKind = OMPD_parallel_sections;
51 /// \brief Parsing of declarative OpenMP directives.
53 /// threadprivate-directive:
54 /// annot_pragma_openmp 'threadprivate' simple-variable-list
56 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
57 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
58 ParenBraceBracketBalancer BalancerRAIIObj(*this);
60 SourceLocation Loc = ConsumeToken();
61 SmallVector<Expr *, 5> Identifiers;
62 auto DKind = ParseOpenMPDirectiveKind(*this);
65 case OMPD_threadprivate:
67 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
68 // The last seen token is annot_pragma_openmp_end - need to check for
70 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
71 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
72 << getOpenMPDirectiveName(OMPD_threadprivate);
73 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
75 // Skip the last annot_pragma_openmp_end.
77 return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
81 Diag(Tok, diag::err_omp_unknown_directive);
96 case OMPD_parallel_for:
97 case OMPD_parallel_sections:
98 Diag(Tok, diag::err_omp_unexpected_directive)
99 << getOpenMPDirectiveName(DKind);
102 SkipUntil(tok::annot_pragma_openmp_end);
103 return DeclGroupPtrTy();
106 /// \brief Parsing of declarative or executable OpenMP directives.
108 /// threadprivate-directive:
109 /// annot_pragma_openmp 'threadprivate' simple-variable-list
110 /// annot_pragma_openmp_end
112 /// executable-directive:
113 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
114 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
115 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
116 /// 'barrier' | 'taskwait' | 'flush' {clause} annot_pragma_openmp_end
119 Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
120 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
121 ParenBraceBracketBalancer BalancerRAIIObj(*this);
122 SmallVector<Expr *, 5> Identifiers;
123 SmallVector<OMPClause *, 5> Clauses;
124 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
125 FirstClauses(OMPC_unknown + 1);
126 unsigned ScopeFlags =
127 Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
128 SourceLocation Loc = ConsumeToken(), EndLoc;
129 auto DKind = ParseOpenMPDirectiveKind(*this);
130 // Name of critical directive.
131 DeclarationNameInfo DirName;
132 StmtResult Directive = StmtError();
133 bool HasAssociatedStatement = true;
134 bool FlushHasClause = false;
137 case OMPD_threadprivate:
139 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
140 // The last seen token is annot_pragma_openmp_end - need to check for
142 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
143 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
144 << getOpenMPDirectiveName(OMPD_threadprivate);
145 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
148 Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
149 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
151 SkipUntil(tok::annot_pragma_openmp_end);
154 if (PP.LookAhead(0).is(tok::l_paren)) {
155 FlushHasClause = true;
156 // Push copy of the current token back to stream to properly parse
157 // pseudo-clause OMPFlushClause.
163 if (!StandAloneAllowed) {
164 Diag(Tok, diag::err_omp_immediate_directive)
165 << getOpenMPDirectiveName(DKind);
167 HasAssociatedStatement = false;
168 // Fall through for further analysis.
177 case OMPD_parallel_for:
178 case OMPD_parallel_sections:
181 // Parse directive name of the 'critical' directive if any.
182 if (DKind == OMPD_critical) {
183 BalancedDelimiterTracker T(*this, tok::l_paren,
184 tok::annot_pragma_openmp_end);
185 if (!T.consumeOpen()) {
186 if (Tok.isAnyIdentifier()) {
188 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
191 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
197 if (isOpenMPLoopDirective(DKind))
198 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
199 if (isOpenMPSimdDirective(DKind))
200 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
201 ParseScope OMPDirectiveScope(this, ScopeFlags);
202 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
204 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
205 OpenMPClauseKind CKind =
208 : FlushHasClause ? OMPC_flush
209 : getOpenMPClauseKind(PP.getSpelling(Tok));
210 FlushHasClause = false;
212 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
213 FirstClauses[CKind].setInt(true);
215 FirstClauses[CKind].setPointer(Clause);
216 Clauses.push_back(Clause);
220 if (Tok.is(tok::comma))
223 // End location of the directive.
224 EndLoc = Tok.getLocation();
225 // Consume final annot_pragma_openmp_end.
228 StmtResult AssociatedStmt;
229 bool CreateDirective = true;
230 if (HasAssociatedStatement) {
231 // The body is a block scope like in Lambdas and Blocks.
232 Sema::CompoundScopeRAII CompoundScope(Actions);
233 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
234 Actions.ActOnStartOfCompoundStmt();
236 AssociatedStmt = ParseStatement();
237 Actions.ActOnFinishOfCompoundStmt();
238 if (!AssociatedStmt.isUsable()) {
239 Actions.ActOnCapturedRegionError();
240 CreateDirective = false;
242 AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
243 CreateDirective = AssociatedStmt.isUsable();
247 Directive = Actions.ActOnOpenMPExecutableDirective(
248 DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
251 Actions.EndOpenMPDSABlock(Directive.get());
252 OMPDirectiveScope.Exit();
256 Diag(Tok, diag::err_omp_unknown_directive);
257 SkipUntil(tok::annot_pragma_openmp_end);
263 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
266 /// simple-variable-list:
267 /// '(' id-expression {, id-expression} ')'
269 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
270 SmallVectorImpl<Expr *> &VarList,
271 bool AllowScopeSpecifier) {
274 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
275 if (T.expectAndConsume(diag::err_expected_lparen_after,
276 getOpenMPDirectiveName(Kind)))
278 bool IsCorrect = true;
279 bool NoIdentIsFound = true;
281 // Read tokens while ')' or annot_pragma_openmp_end is not found.
282 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
284 SourceLocation TemplateKWLoc;
288 NoIdentIsFound = false;
290 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
291 ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
293 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
295 } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
296 TemplateKWLoc, Name)) {
298 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
300 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
301 Tok.isNot(tok::annot_pragma_openmp_end)) {
303 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
305 Diag(PrevTok.getLocation(), diag::err_expected)
307 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
309 DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
311 Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
313 VarList.push_back(Res.get());
316 if (Tok.is(tok::comma)) {
321 if (NoIdentIsFound) {
322 Diag(Tok, diag::err_expected) << tok::identifier;
327 IsCorrect = !T.consumeClose() && IsCorrect;
329 return !IsCorrect && VarList.empty();
332 /// \brief Parsing of OpenMP clauses.
335 /// if-clause | final-clause | num_threads-clause | safelen-clause |
336 /// default-clause | private-clause | firstprivate-clause | shared-clause
337 /// | linear-clause | aligned-clause | collapse-clause |
338 /// lastprivate-clause | reduction-clause | proc_bind-clause |
339 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
340 /// mergeable-clause | flush-clause
342 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
343 OpenMPClauseKind CKind, bool FirstClause) {
344 OMPClause *Clause = nullptr;
345 bool ErrorFound = false;
346 // Check if clause is allowed for the given directive.
347 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
348 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
349 << getOpenMPDirectiveName(DKind);
356 case OMPC_num_threads:
359 // OpenMP [2.5, Restrictions]
360 // At most one if clause can appear on the directive.
361 // At most one num_threads clause can appear on the directive.
362 // OpenMP [2.8.1, simd construct, Restrictions]
363 // Only one safelen clause can appear on a simd directive.
364 // Only one collapse clause can appear on a simd directive.
365 // OpenMP [2.11.1, task Construct, Restrictions]
366 // At most one if clause can appear on the directive.
367 // At most one final clause can appear on the directive.
369 Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
370 << getOpenMPClauseName(CKind);
373 Clause = ParseOpenMPSingleExprClause(CKind);
377 // OpenMP [2.14.3.1, Restrictions]
378 // Only a single default clause may be specified on a parallel, task or
380 // OpenMP [2.5, parallel Construct, Restrictions]
381 // At most one proc_bind clause can appear on the directive.
383 Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
384 << getOpenMPClauseName(CKind);
387 Clause = ParseOpenMPSimpleClause(CKind);
390 // OpenMP [2.7.1, Restrictions, p. 3]
391 // Only one schedule clause can appear on a loop directive.
393 Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
394 << getOpenMPClauseName(CKind);
397 Clause = ParseOpenMPSingleExprWithArgClause(CKind);
403 // OpenMP [2.7.1, Restrictions, p. 9]
404 // Only one ordered clause can appear on a loop directive.
405 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
406 // Only one nowait clause can appear on a for directive.
408 Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
409 << getOpenMPClauseName(CKind);
412 Clause = ParseOpenMPClause(CKind);
415 case OMPC_firstprivate:
416 case OMPC_lastprivate:
422 case OMPC_copyprivate:
424 Clause = ParseOpenMPVarListClause(CKind);
427 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
428 << getOpenMPDirectiveName(DKind);
429 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
431 case OMPC_threadprivate:
432 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
433 << getOpenMPDirectiveName(DKind);
434 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
437 return ErrorFound ? nullptr : Clause;
440 /// \brief Parsing of OpenMP clauses with single expressions like 'if',
441 /// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
445 /// 'if' '(' expression ')'
448 /// 'final' '(' expression ')'
450 /// num_threads-clause:
451 /// 'num_threads' '(' expression ')'
454 /// 'safelen' '(' expression ')'
457 /// 'collapse' '(' expression ')'
459 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
460 SourceLocation Loc = ConsumeToken();
462 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
463 if (T.expectAndConsume(diag::err_expected_lparen_after,
464 getOpenMPClauseName(Kind)))
467 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
468 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
476 return Actions.ActOnOpenMPSingleExprClause(
477 Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
480 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
483 /// 'default' '(' 'none' | 'shared' ')
485 /// proc_bind-clause:
486 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
488 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
489 SourceLocation Loc = Tok.getLocation();
490 SourceLocation LOpen = ConsumeToken();
492 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
493 if (T.expectAndConsume(diag::err_expected_lparen_after,
494 getOpenMPClauseName(Kind)))
497 unsigned Type = getOpenMPSimpleClauseType(
498 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
499 SourceLocation TypeLoc = Tok.getLocation();
500 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
501 Tok.isNot(tok::annot_pragma_openmp_end))
507 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
511 /// \brief Parsing of OpenMP clauses like 'ordered'.
522 /// mergeable-clause:
525 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
526 SourceLocation Loc = Tok.getLocation();
529 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
533 /// \brief Parsing of OpenMP clauses with single expressions and some additional
534 /// argument like 'schedule' or 'dist_schedule'.
537 /// 'schedule' '(' kind [',' expression ] ')'
539 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
540 SourceLocation Loc = ConsumeToken();
541 SourceLocation CommaLoc;
543 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
544 if (T.expectAndConsume(diag::err_expected_lparen_after,
545 getOpenMPClauseName(Kind)))
549 unsigned Type = getOpenMPSimpleClauseType(
550 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
551 SourceLocation KLoc = Tok.getLocation();
552 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
553 Tok.isNot(tok::annot_pragma_openmp_end))
556 if (Kind == OMPC_schedule &&
557 (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
558 Type == OMPC_SCHEDULE_guided) &&
559 Tok.is(tok::comma)) {
560 CommaLoc = ConsumeAnyToken();
561 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
562 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
570 return Actions.ActOnOpenMPSingleExprWithArgClause(
571 Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
572 T.getCloseLocation());
575 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
576 UnqualifiedId &ReductionId) {
577 SourceLocation TemplateKWLoc;
578 if (ReductionIdScopeSpec.isEmpty()) {
580 switch (P.getCurToken().getKind()) {
608 if (OOK != OO_None) {
609 SourceLocation OpLoc = P.ConsumeToken();
610 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
611 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
615 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
616 /*AllowDestructorName*/ false,
617 /*AllowConstructorName*/ false, ParsedType(),
618 TemplateKWLoc, ReductionId);
621 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
622 /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
625 /// 'private' '(' list ')'
626 /// firstprivate-clause:
627 /// 'firstprivate' '(' list ')'
628 /// lastprivate-clause:
629 /// 'lastprivate' '(' list ')'
631 /// 'shared' '(' list ')'
633 /// 'linear' '(' list [ ':' linear-step ] ')'
635 /// 'aligned' '(' list [ ':' alignment ] ')'
636 /// reduction-clause:
637 /// 'reduction' '(' reduction-identifier ':' list ')'
638 /// copyprivate-clause:
639 /// 'copyprivate' '(' list ')'
641 /// 'flush' '(' list ')'
643 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
644 SourceLocation Loc = Tok.getLocation();
645 SourceLocation LOpen = ConsumeToken();
646 SourceLocation ColonLoc = SourceLocation();
647 // Optional scope specifier and unqualified id for reduction identifier.
648 CXXScopeSpec ReductionIdScopeSpec;
649 UnqualifiedId ReductionId;
650 bool InvalidReductionId = false;
652 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
653 if (T.expectAndConsume(diag::err_expected_lparen_after,
654 getOpenMPClauseName(Kind)))
657 // Handle reduction-identifier for reduction clause.
658 if (Kind == OMPC_reduction) {
659 ColonProtectionRAIIObject ColonRAII(*this);
660 if (getLangOpts().CPlusPlus) {
661 ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
664 ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
665 if (InvalidReductionId) {
666 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
669 if (Tok.is(tok::colon)) {
670 ColonLoc = ConsumeToken();
672 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
676 SmallVector<Expr *, 5> Vars;
677 bool IsComma = !InvalidReductionId;
678 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
679 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
680 Tok.isNot(tok::annot_pragma_openmp_end))) {
681 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
683 ExprResult VarExpr = ParseAssignmentExpression();
684 if (VarExpr.isUsable()) {
685 Vars.push_back(VarExpr.get());
687 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
691 IsComma = Tok.is(tok::comma);
694 else if (Tok.isNot(tok::r_paren) &&
695 Tok.isNot(tok::annot_pragma_openmp_end) &&
696 (!MayHaveTail || Tok.isNot(tok::colon)))
697 Diag(Tok, diag::err_omp_expected_punc)
698 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
699 : getOpenMPClauseName(Kind))
700 << (Kind == OMPC_flush);
703 // Parse ':' linear-step (or ':' alignment).
704 Expr *TailExpr = nullptr;
705 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
707 ColonLoc = Tok.getLocation();
709 ExprResult Tail = ParseAssignmentExpression();
711 TailExpr = Tail.get();
713 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
719 if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
722 return Actions.ActOnOpenMPVarListClause(
723 Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
724 ReductionIdScopeSpec,
725 ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
726 : DeclarationNameInfo());