ParseOpenMP.cpp revision 263509
1193326Sed//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed/// \file 10193326Sed/// \brief This file implements parsing of all OpenMP directives and clauses. 11193326Sed/// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14193326Sed#include "clang/AST/ASTConsumer.h" 15193326Sed#include "clang/AST/StmtOpenMP.h" 16212904Sdim#include "clang/Parse/ParseDiagnostic.h" 17212904Sdim#include "clang/Parse/Parser.h" 18212904Sdim#include "clang/Sema/Scope.h" 19200583Srdivacky#include "llvm/ADT/PointerIntPair.h" 20221345Sdim#include "RAIIObjectsForParser.h" 21221345Sdimusing namespace clang; 22193326Sed 23193326Sed//===----------------------------------------------------------------------===// 24193326Sed// OpenMP declarative directives. 25193326Sed//===----------------------------------------------------------------------===// 26212904Sdim 27193326Sed/// \brief Parsing of declarative OpenMP directives. 28193326Sed/// 29226890Sdim/// threadprivate-directive: 30226890Sdim/// annot_pragma_openmp 'threadprivate' simple-variable-list 31226890Sdim/// 32226890SdimParser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { 33226890Sdim assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 34198092Srdivacky ParenBraceBracketBalancer BalancerRAIIObj(*this); 35226890Sdim 36226890Sdim SourceLocation Loc = ConsumeToken(); 37226890Sdim SmallVector<Expr *, 5> Identifiers; 38226890Sdim OpenMPDirectiveKind DKind = Tok.isAnnotation() ? 39193326Sed OMPD_unknown : 40193326Sed getOpenMPDirectiveKind(PP.getSpelling(Tok)); 41198092Srdivacky 42198092Srdivacky switch (DKind) { 43199990Srdivacky case OMPD_threadprivate: 44198092Srdivacky ConsumeToken(); 45198092Srdivacky if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) { 46198092Srdivacky // The last seen token is annot_pragma_openmp_end - need to check for 47198092Srdivacky // extra tokens. 48198092Srdivacky if (Tok.isNot(tok::annot_pragma_openmp_end)) { 49198092Srdivacky Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 50198092Srdivacky << getOpenMPDirectiveName(OMPD_threadprivate); 51198092Srdivacky SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 52198092Srdivacky } 53198092Srdivacky // Skip the last annot_pragma_openmp_end. 54198092Srdivacky ConsumeToken(); 55198092Srdivacky return Actions.ActOnOpenMPThreadprivateDirective(Loc, 56198092Srdivacky Identifiers); 57198092Srdivacky } 58198092Srdivacky break; 59198092Srdivacky case OMPD_unknown: 60198092Srdivacky Diag(Tok, diag::err_omp_unknown_directive); 61198092Srdivacky break; 62198092Srdivacky case OMPD_parallel: 63198092Srdivacky case OMPD_task: 64193326Sed case NUM_OPENMP_DIRECTIVES: 65193326Sed Diag(Tok, diag::err_omp_unexpected_directive) 66193326Sed << getOpenMPDirectiveName(DKind); 67193326Sed break; 68193326Sed } 69193326Sed SkipUntil(tok::annot_pragma_openmp_end); 70193326Sed return DeclGroupPtrTy(); 71193326Sed} 72193326Sed 73193326Sed/// \brief Parsing of declarative or executable OpenMP directives. 74193326Sed/// 75193326Sed/// threadprivate-directive: 76193326Sed/// annot_pragma_openmp 'threadprivate' simple-variable-list 77193326Sed/// annot_pragma_openmp_end 78193326Sed/// 79212904Sdim/// parallel-directive: 80193326Sed/// annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end 81193326Sed/// 82226890SdimStmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { 83226890Sdim assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 84198092Srdivacky ParenBraceBracketBalancer BalancerRAIIObj(*this); 85198092Srdivacky SmallVector<Expr *, 5> Identifiers; 86198092Srdivacky SmallVector<OMPClause *, 5> Clauses; 87193326Sed SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES> 88193326Sed FirstClauses(NUM_OPENMP_CLAUSES); 89193326Sed const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 90212904Sdim Scope::OpenMPDirectiveScope; 91212904Sdim SourceLocation Loc = ConsumeToken(), EndLoc; 92212904Sdim OpenMPDirectiveKind DKind = Tok.isAnnotation() ? 93212904Sdim OMPD_unknown : 94193326Sed getOpenMPDirectiveKind(PP.getSpelling(Tok)); 95193326Sed // Name of critical directive. 96193326Sed DeclarationNameInfo DirName; 97193326Sed StmtResult Directive = StmtError(); 98193326Sed 99193326Sed switch (DKind) { 100193326Sed case OMPD_threadprivate: 101193326Sed ConsumeToken(); 102193326Sed if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) { 103193326Sed // The last seen token is annot_pragma_openmp_end - need to check for 104193326Sed // extra tokens. 105193326Sed if (Tok.isNot(tok::annot_pragma_openmp_end)) { 106193326Sed Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 107193326Sed << getOpenMPDirectiveName(OMPD_threadprivate); 108193326Sed SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 109193326Sed } 110193326Sed DeclGroupPtrTy Res = 111193326Sed Actions.ActOnOpenMPThreadprivateDirective(Loc, 112193326Sed Identifiers); 113193326Sed Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 114193326Sed } 115198092Srdivacky SkipUntil(tok::annot_pragma_openmp_end); 116198893Srdivacky break; 117193326Sed case OMPD_parallel: { 118198092Srdivacky ConsumeToken(); 119193326Sed 120193326Sed Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope()); 121193326Sed 122193326Sed while (Tok.isNot(tok::annot_pragma_openmp_end)) { 123193326Sed OpenMPClauseKind CKind = Tok.isAnnotation() ? 124193326Sed OMPC_unknown : 125193326Sed getOpenMPClauseKind(PP.getSpelling(Tok)); 126193326Sed OMPClause *Clause = ParseOpenMPClause(DKind, CKind, 127193326Sed !FirstClauses[CKind].getInt()); 128193326Sed FirstClauses[CKind].setInt(true); 129193326Sed if (Clause) { 130193326Sed FirstClauses[CKind].setPointer(Clause); 131193326Sed Clauses.push_back(Clause); 132212904Sdim } 133193326Sed 134198092Srdivacky // Skip ',' if any. 135193326Sed if (Tok.is(tok::comma)) 136193326Sed ConsumeToken(); 137226890Sdim } 138198092Srdivacky // End location of the directive. 139198092Srdivacky EndLoc = Tok.getLocation(); 140198092Srdivacky // Consume final annot_pragma_openmp_end. 141198092Srdivacky ConsumeToken(); 142198092Srdivacky 143198092Srdivacky StmtResult AssociatedStmt; 144212904Sdim bool CreateDirective = true; 145198092Srdivacky ParseScope OMPDirectiveScope(this, ScopeFlags); 146193326Sed { 147193326Sed // The body is a block scope like in Lambdas and Blocks. 148198092Srdivacky Sema::CompoundScopeRAII CompoundScope(Actions); 149198092Srdivacky Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1); 150193326Sed Actions.ActOnStartOfCompoundStmt(); 151193326Sed // Parse statement 152198092Srdivacky AssociatedStmt = ParseStatement(); 153198092Srdivacky Actions.ActOnFinishOfCompoundStmt(); 154198092Srdivacky if (!AssociatedStmt.isUsable()) { 155198092Srdivacky Actions.ActOnCapturedRegionError(); 156198893Srdivacky CreateDirective = false; 157198893Srdivacky } else { 158198092Srdivacky AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take()); 159193326Sed CreateDirective = AssociatedStmt.isUsable(); 160193326Sed } 161193326Sed } 162198092Srdivacky if (CreateDirective) 163193326Sed Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses, 164198893Srdivacky AssociatedStmt.take(), 165198893Srdivacky Loc, EndLoc); 166212904Sdim 167226890Sdim // Exit scope. 168193326Sed Actions.EndOpenMPDSABlock(Directive.get()); 169193326Sed OMPDirectiveScope.Exit(); 170193326Sed } 171193326Sed break; 172193326Sed case OMPD_unknown: 173193326Sed Diag(Tok, diag::err_omp_unknown_directive); 174193326Sed SkipUntil(tok::annot_pragma_openmp_end); 175193326Sed break; 176193326Sed case OMPD_task: 177193326Sed case NUM_OPENMP_DIRECTIVES: 178193326Sed Diag(Tok, diag::err_omp_unexpected_directive) 179193326Sed << getOpenMPDirectiveName(DKind); 180193326Sed SkipUntil(tok::annot_pragma_openmp_end); 181193326Sed break; 182193326Sed } 183193326Sed return Directive; 184193326Sed} 185193326Sed 186193326Sed/// \brief Parses list of simple variables for '#pragma omp threadprivate' 187193326Sed/// directive. 188193326Sed/// 189193326Sed/// simple-variable-list: 190212904Sdim/// '(' id-expression {, id-expression} ')' 191193326Sed/// 192193326Sedbool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, 193193326Sed SmallVectorImpl<Expr *> &VarList, 194212904Sdim bool AllowScopeSpecifier) { 195193326Sed VarList.clear(); 196226890Sdim // Parse '('. 197226890Sdim BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 198193326Sed if (T.expectAndConsume(diag::err_expected_lparen_after, 199193326Sed getOpenMPDirectiveName(Kind))) 200193326Sed return true; 201198092Srdivacky bool IsCorrect = true; 202198092Srdivacky bool NoIdentIsFound = true; 203226890Sdim 204226890Sdim // Read tokens while ')' or annot_pragma_openmp_end is not found. 205212904Sdim while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 206198092Srdivacky CXXScopeSpec SS; 207198092Srdivacky SourceLocation TemplateKWLoc; 208221345Sdim UnqualifiedId Name; 209218893Sdim // Read var name. 210218893Sdim Token PrevTok = Tok; 211218893Sdim NoIdentIsFound = false; 212218893Sdim 213218893Sdim if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 214218893Sdim ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) { 215212904Sdim IsCorrect = false; 216212904Sdim SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 217221345Sdim StopBeforeMatch); 218199990Srdivacky } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(), 219218893Sdim TemplateKWLoc, Name)) { 220199990Srdivacky IsCorrect = false; 221202379Srdivacky SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 222202379Srdivacky StopBeforeMatch); 223193326Sed } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 224193326Sed Tok.isNot(tok::annot_pragma_openmp_end)) { 225193326Sed IsCorrect = false; 226212904Sdim SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 227198893Srdivacky StopBeforeMatch); 228198893Srdivacky Diag(PrevTok.getLocation(), diag::err_expected_ident) 229193326Sed << SourceRange(PrevTok.getLocation(), PrevTokLocation); 230193326Sed } else { 231193326Sed DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name); 232198893Srdivacky ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS, 233193326Sed NameInfo); 234193326Sed if (Res.isUsable()) 235193326Sed VarList.push_back(Res.take()); 236193326Sed } 237193326Sed // Consume ','. 238193326Sed if (Tok.is(tok::comma)) { 239193326Sed ConsumeToken(); 240212904Sdim } 241193326Sed } 242198092Srdivacky 243193326Sed if (NoIdentIsFound) { 244193326Sed Diag(Tok, diag::err_expected_ident); 245193326Sed IsCorrect = false; 246212904Sdim } 247212904Sdim 248193326Sed // Parse ')'. 249193326Sed IsCorrect = !T.consumeClose() && IsCorrect; 250193326Sed 251193326Sed return !IsCorrect && VarList.empty(); 252193326Sed} 253193326Sed 254193326Sed/// \brief Parsing of OpenMP clauses. 255193326Sed/// 256193326Sed/// clause: 257198092Srdivacky/// default-clause|private-clause|firstprivate-clause|shared-clause 258218893Sdim/// 259193326SedOMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 260193326Sed OpenMPClauseKind CKind, bool FirstClause) { 261193326Sed OMPClause *Clause = 0; 262193326Sed bool ErrorFound = false; 263210299Sed // Check if clause is allowed for the given directive. 264193326Sed if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { 265193326Sed Diag(Tok, diag::err_omp_unexpected_clause) 266193326Sed << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 267193326Sed ErrorFound = true; 268193326Sed } 269193326Sed 270193326Sed switch (CKind) { 271193326Sed case OMPC_default: 272193326Sed // OpenMP [2.9.3.1, Restrictions] 273193326Sed // Only a single default clause may be specified on a parallel or task 274193326Sed // directive. 275193326Sed if (!FirstClause) { 276212904Sdim Diag(Tok, diag::err_omp_more_one_clause) 277193326Sed << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); 278195099Sed } 279193326Sed 280193326Sed Clause = ParseOpenMPSimpleClause(CKind); 281193326Sed break; 282193326Sed case OMPC_private: 283193326Sed case OMPC_firstprivate: 284193326Sed case OMPC_shared: 285193326Sed Clause = ParseOpenMPVarListClause(CKind); 286212904Sdim break; 287193326Sed case OMPC_unknown: 288193326Sed Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 289193326Sed << getOpenMPDirectiveName(DKind); 290193326Sed SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 291193326Sed break; 292193326Sed case OMPC_threadprivate: 293193326Sed case NUM_OPENMP_CLAUSES: 294198092Srdivacky Diag(Tok, diag::err_omp_unexpected_clause) 295193326Sed << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 296198092Srdivacky SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 297198092Srdivacky break; 298193326Sed } 299226890Sdim return ErrorFound ? 0 : Clause; 300193326Sed} 301193326Sed 302193326Sed/// \brief Parsing of simple OpenMP clauses like 'default'. 303198092Srdivacky/// 304193326Sed/// default-clause: 305198092Srdivacky/// 'default' '(' 'none' | 'shared' ') 306193326Sed/// 307193326SedOMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { 308198092Srdivacky SourceLocation Loc = Tok.getLocation(); 309193326Sed SourceLocation LOpen = ConsumeToken(); 310193326Sed // Parse '('. 311193326Sed BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 312198092Srdivacky if (T.expectAndConsume(diag::err_expected_lparen_after, 313198092Srdivacky getOpenMPClauseName(Kind))) 314193326Sed return 0; 315198092Srdivacky 316193326Sed unsigned Type = Tok.isAnnotation() ? 317193326Sed unsigned(OMPC_DEFAULT_unknown) : 318193326Sed getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); 319198092Srdivacky SourceLocation TypeLoc = Tok.getLocation(); 320193326Sed if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 321193326Sed Tok.isNot(tok::annot_pragma_openmp_end)) 322193326Sed ConsumeAnyToken(); 323193326Sed 324193326Sed // Parse ')'. 325198092Srdivacky T.consumeClose(); 326193326Sed 327193326Sed return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, 328193326Sed Tok.getLocation()); 329193326Sed} 330198092Srdivacky 331193326Sed/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 332226890Sdim/// 'shared', 'copyin', or 'reduction'. 333198092Srdivacky/// 334212904Sdim/// private-clause: 335193326Sed/// 'private' '(' list ')' 336193326Sed/// firstprivate-clause: 337193326Sed/// 'firstprivate' '(' list ')' 338193326Sed/// shared-clause: 339193326Sed/// 'shared' '(' list ')' 340193326Sed/// 341193326SedOMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { 342198092Srdivacky SourceLocation Loc = Tok.getLocation(); 343193326Sed SourceLocation LOpen = ConsumeToken(); 344198092Srdivacky // Parse '('. 345193326Sed BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 346198092Srdivacky if (T.expectAndConsume(diag::err_expected_lparen_after, 347193326Sed getOpenMPClauseName(Kind))) 348193326Sed return 0; 349193326Sed 350193326Sed SmallVector<Expr *, 5> Vars; 351193326Sed bool IsComma = true; 352193326Sed while (IsComma || (Tok.isNot(tok::r_paren) && 353193326Sed Tok.isNot(tok::annot_pragma_openmp_end))) { 354193326Sed // Parse variable 355218893Sdim ExprResult VarExpr = ParseAssignmentExpression(); 356193326Sed if (VarExpr.isUsable()) { 357193326Sed Vars.push_back(VarExpr.take()); 358193326Sed } else { 359193326Sed SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 360193326Sed StopBeforeMatch); 361193326Sed } 362193326Sed // Skip ',' if any 363199990Srdivacky IsComma = Tok.is(tok::comma); 364199990Srdivacky if (IsComma) { 365199990Srdivacky ConsumeToken(); 366210299Sed } else if (Tok.isNot(tok::r_paren) && 367210299Sed Tok.isNot(tok::annot_pragma_openmp_end)) { 368210299Sed Diag(Tok, diag::err_omp_expected_punc) 369210299Sed << 1 << getOpenMPClauseName(Kind); 370210299Sed } 371210299Sed } 372210299Sed 373210299Sed // Parse ')'. 374210299Sed T.consumeClose(); 375210299Sed if (Vars.empty()) 376210299Sed return 0; 377210299Sed 378210299Sed return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen, 379210299Sed Tok.getLocation()); 380210299Sed} 381210299Sed 382210299Sed