21 #include "llvm/ADT/PointerIntPair.h"
22 using namespace clang;
34 OMPD_cancellation_point},
35 {OMPD_for, OMPD_simd, OMPD_for_simd},
36 {OMPD_parallel, OMPD_for, OMPD_parallel_for},
37 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
38 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}};
44 bool TokenMatched =
false;
45 for (
unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
51 TokenMatched = DKind == F[i][0] && DKind !=
OMPD_unknown;
63 TokenMatched = SDKind == F[i][1] && SDKind !=
OMPD_unknown;
80 assert(Tok.
is(tok::annot_pragma_openmp) &&
"Not an OpenMP directive!");
88 case OMPD_threadprivate:
90 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers,
true)) {
93 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
94 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
104 Diag(Tok, diag::err_omp_unknown_directive);
122 case OMPD_parallel_for:
123 case OMPD_parallel_for_simd:
124 case OMPD_parallel_sections:
128 case OMPD_cancellation_point:
130 Diag(Tok, diag::err_omp_unexpected_directive)
154 Parser::ParseOpenMPDeclarativeOrExecutableDirective(
bool StandAloneAllowed) {
155 assert(Tok.
is(tok::annot_pragma_openmp) &&
"Not an OpenMP directive!");
161 unsigned ScopeFlags =
169 bool HasAssociatedStatement =
true;
170 bool FlushHasClause =
false;
173 case OMPD_threadprivate:
175 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers,
false)) {
178 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
179 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
191 FlushHasClause =
true;
199 case OMPD_cancellation_point:
201 if (!StandAloneAllowed) {
202 Diag(Tok, diag::err_omp_immediate_directive)
205 HasAssociatedStatement =
false;
216 case OMPD_parallel_for:
217 case OMPD_parallel_for_simd:
218 case OMPD_parallel_sections:
224 case OMPD_taskgroup: {
227 if (DKind == OMPD_critical) {
229 tok::annot_pragma_openmp_end);
230 if (!T.consumeOpen()) {
236 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
240 }
else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
242 if (Tok.
isNot(tok::annot_pragma_openmp_end))
250 ParseScope OMPDirectiveScope(
this, ScopeFlags);
253 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
257 : FlushHasClause ? OMPC_flush
260 FlushHasClause =
false;
262 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
263 FirstClauses[CKind].setInt(
true);
265 FirstClauses[CKind].setPointer(Clause);
266 Clauses.push_back(Clause);
270 if (Tok.
is(tok::comma))
280 bool CreateDirective =
true;
281 if (HasAssociatedStatement) {
287 AssociatedStmt = ParseStatement();
290 CreateDirective = AssociatedStmt.
isUsable();
294 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.
get(), Loc,
299 OMPDirectiveScope.Exit();
303 Diag(Tok, diag::err_omp_unknown_directive);
318 bool AllowScopeSpecifier) {
322 if (T.expectAndConsume(diag::err_expected_lparen_after,
325 bool IsCorrect =
true;
326 bool NoIdentIsFound =
true;
329 while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end)) {
335 NoIdentIsFound =
false;
337 if (AllowScopeSpecifier &&
getLangOpts().CPlusPlus &&
338 ParseOptionalCXXScopeSpecifier(SS,
ParsedType(),
false)) {
340 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
343 TemplateKWLoc, Name)) {
345 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
347 }
else if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren) &&
348 Tok.
isNot(tok::annot_pragma_openmp_end)) {
350 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
360 VarList.push_back(Res.
get());
363 if (Tok.
is(tok::comma)) {
368 if (NoIdentIsFound) {
369 Diag(Tok, diag::err_expected) << tok::identifier;
374 IsCorrect = !T.consumeClose() && IsCorrect;
376 return !IsCorrect && VarList.empty();
393 bool ErrorFound =
false;
404 case OMPC_num_threads:
422 Clause = ParseOpenMPSingleExprClause(CKind);
437 Clause = ParseOpenMPSimpleClause(CKind);
448 Clause = ParseOpenMPSingleExprWithArgClause(CKind);
469 Clause = ParseOpenMPClause(CKind);
472 case OMPC_firstprivate:
473 case OMPC_lastprivate:
479 case OMPC_copyprivate:
482 Clause = ParseOpenMPVarListClause(CKind);
485 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
495 return ErrorFound ?
nullptr : Clause;
521 if (T.expectAndConsume(diag::err_expected_lparen_after,
535 Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
551 if (T.expectAndConsume(diag::err_expected_lparen_after,
558 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
559 Tok.
isNot(tok::annot_pragma_openmp_end))
605 if (T.expectAndConsume(diag::err_expected_lparen_after,
613 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
614 Tok.
isNot(tok::annot_pragma_openmp_end))
617 if (Kind == OMPC_schedule &&
618 (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
619 Type == OMPC_SCHEDULE_guided) &&
620 Tok.
is(tok::comma)) {
621 CommaLoc = ConsumeAnyToken();
632 Kind, Type, Val.
get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
633 T.getCloseLocation());
639 if (ReductionIdScopeSpec.
isEmpty()) {
679 TemplateKWLoc, ReductionId);
713 bool InvalidReductionId =
false;
719 if (T.expectAndConsume(diag::err_expected_lparen_after,
724 if (Kind == OMPC_reduction) {
727 ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec,
ParsedType(),
false);
731 if (InvalidReductionId) {
732 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
735 if (Tok.
is(tok::colon)) {
738 Diag(Tok, diag::warn_pragma_expected_colon) <<
"reduction identifier";
740 }
else if (Kind == OMPC_depend) {
748 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
753 if (Tok.
is(tok::colon)) {
756 Diag(Tok, diag::warn_pragma_expected_colon) <<
"dependency type";
761 bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) ||
762 ((Kind == OMPC_reduction) && !InvalidReductionId) ||
764 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
765 while (IsComma || (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::colon) &&
766 Tok.
isNot(tok::annot_pragma_openmp_end))) {
772 Vars.push_back(VarExpr.
get());
774 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
778 IsComma = Tok.
is(tok::comma);
781 else if (Tok.
isNot(tok::r_paren) &&
782 Tok.
isNot(tok::annot_pragma_openmp_end) &&
783 (!MayHaveTail || Tok.
isNot(tok::colon)))
784 Diag(Tok, diag::err_omp_expected_punc)
787 << (Kind == OMPC_flush);
791 Expr *TailExpr =
nullptr;
792 const bool MustHaveTail = MayHaveTail && Tok.
is(tok::colon);
799 TailExpr = Tail.
get();
801 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
808 (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
813 Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.
getLocation(),
814 ReductionIdScopeSpec,
Defines the clang::ASTContext interface.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Called on correct id-expression from the '#pragma omp threadprivate'.
Scope * getCurScope() const
Retrieve the parser's current scope.
const Token & getCurToken() const
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
const LangOptions & getLangOpts() const
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
This indicates that the scope corresponds to a function, which means that labels are set here...
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind)
static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P)
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
Wrapper for void* pointer.
void EnterToken(const Token &Tok)
Enters a token in the token stream to be lexed next.
bool isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing...
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
bool isEmpty() const
No scope specifier.
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
Base wrapper for a particular "section" of type source info.
const char * getOpenMPClauseName(OpenMPClauseKind Kind)
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name)
Retrieves the declaration name from a parsed unqualified-id.
OpaquePtr< QualType > ParsedType
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ...
void EndOpenMPClause()
End analysis of clauses.
VerifyDiagnosticConsumer::Directive Directive
Represents a C++ unqualified-id that has been parsed.
OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str)
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
Represents a C++ nested-name-specifier or a global scope specifier.
tok::TokenKind getKind() const
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
A RAII object to enter scope of a compound statement.
void ActOnFinishOfCompoundStmt()
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
This is the scope of OpenMP executable directive.
OpenMPClauseKind
OpenMP clauses.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
bool isNot(tok::TokenKind K) const
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
bool isValid() const
Determine whether this unqualified-id refers to a valid name.
void ActOnStartOfCompoundStmt()
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
OpenMPDirectiveKind
OpenMP directives.
Scope * getCurScope() const
This is a basic class for representing single OpenMP clause.
Preprocessor & getPreprocessor() const
bool is(tok::TokenKind K) const
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, ParsedType ObjectType, SourceLocation &TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
This is the scope of some OpenMP simd directive. For example, it is used for 'omp simd'...
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, unsigned Argument, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ArgumentLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Not an overloaded operator.
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str)
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
This file defines OpenMP AST classes for executable directives and clauses.
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)
Parse an expr that doesn't include (top-level) commas.
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str)
const char * getOpenMPDirectiveName(OpenMPDirectiveKind Kind)
This is a scope that can contain a declaration. Some scopes just contain loop constructs but don't co...
SourceLocation ConsumeToken()
ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult{return E;})
Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...
This is the scope of some OpenMP loop directive.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, Expr *TailExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind, SourceLocation DepLoc)
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
A trivial tuple used to represent a source range.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
SourceLocation ColonLoc
Location of ':'.
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Stop skipping at specified token, but don't skip the token itself.
IdentifierInfo * getIdentifierInfo() const