1//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9/// \file 10/// \brief This file implements parsing of all OpenMP directives and clauses. 11/// 12//===----------------------------------------------------------------------===// 13 14#include "clang/AST/ASTConsumer.h" 15#include "clang/AST/StmtOpenMP.h" 16#include "clang/Parse/ParseDiagnostic.h" 17#include "clang/Parse/Parser.h" 18#include "clang/Sema/Scope.h" 19#include "llvm/ADT/PointerIntPair.h" 20#include "RAIIObjectsForParser.h" 21using namespace clang; 22 23//===----------------------------------------------------------------------===// 24// OpenMP declarative directives. 25//===----------------------------------------------------------------------===// 26 27/// \brief Parsing of declarative OpenMP directives. 28/// 29/// threadprivate-directive: 30/// annot_pragma_openmp 'threadprivate' simple-variable-list 31/// 32Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { 33 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 34 ParenBraceBracketBalancer BalancerRAIIObj(*this); 35 36 SourceLocation Loc = ConsumeToken(); 37 SmallVector<Expr *, 5> Identifiers; 38 OpenMPDirectiveKind DKind = Tok.isAnnotation() ? 39 OMPD_unknown : 40 getOpenMPDirectiveKind(PP.getSpelling(Tok)); 41 42 switch (DKind) { 43 case OMPD_threadprivate: 44 ConsumeToken(); 45 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) { 46 // The last seen token is annot_pragma_openmp_end - need to check for 47 // extra tokens. 48 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 49 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 50 << getOpenMPDirectiveName(OMPD_threadprivate); 51 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 52 } 53 // Skip the last annot_pragma_openmp_end. 54 ConsumeToken(); 55 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 56 Identifiers); 57 } 58 break; 59 case OMPD_unknown: 60 Diag(Tok, diag::err_omp_unknown_directive); 61 break; 62 case OMPD_parallel: 63 case OMPD_task: 64 case NUM_OPENMP_DIRECTIVES: 65 Diag(Tok, diag::err_omp_unexpected_directive) 66 << getOpenMPDirectiveName(DKind); 67 break; 68 } 69 SkipUntil(tok::annot_pragma_openmp_end); 70 return DeclGroupPtrTy(); 71} 72 73/// \brief Parsing of declarative or executable OpenMP directives. 74/// 75/// threadprivate-directive: 76/// annot_pragma_openmp 'threadprivate' simple-variable-list 77/// annot_pragma_openmp_end 78/// 79/// parallel-directive: 80/// annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end 81/// 82StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { 83 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 84 ParenBraceBracketBalancer BalancerRAIIObj(*this); 85 SmallVector<Expr *, 5> Identifiers; 86 SmallVector<OMPClause *, 5> Clauses; 87 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES> 88 FirstClauses(NUM_OPENMP_CLAUSES); 89 const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 90 Scope::OpenMPDirectiveScope; 91 SourceLocation Loc = ConsumeToken(), EndLoc; 92 OpenMPDirectiveKind DKind = Tok.isAnnotation() ? 93 OMPD_unknown : 94 getOpenMPDirectiveKind(PP.getSpelling(Tok)); 95 // Name of critical directive. 96 DeclarationNameInfo DirName; 97 StmtResult Directive = StmtError(); 98 99 switch (DKind) { 100 case OMPD_threadprivate: 101 ConsumeToken(); 102 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) { 103 // The last seen token is annot_pragma_openmp_end - need to check for 104 // extra tokens. 105 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 106 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 107 << getOpenMPDirectiveName(OMPD_threadprivate); 108 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 109 } 110 DeclGroupPtrTy Res = 111 Actions.ActOnOpenMPThreadprivateDirective(Loc, 112 Identifiers); 113 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 114 } 115 SkipUntil(tok::annot_pragma_openmp_end); 116 break; 117 case OMPD_parallel: { 118 ConsumeToken(); 119 120 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope()); 121 122 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 123 OpenMPClauseKind CKind = Tok.isAnnotation() ? 124 OMPC_unknown : 125 getOpenMPClauseKind(PP.getSpelling(Tok)); 126 OMPClause *Clause = ParseOpenMPClause(DKind, CKind, 127 !FirstClauses[CKind].getInt()); 128 FirstClauses[CKind].setInt(true); 129 if (Clause) { 130 FirstClauses[CKind].setPointer(Clause); 131 Clauses.push_back(Clause); 132 } 133 134 // Skip ',' if any. 135 if (Tok.is(tok::comma)) 136 ConsumeToken(); 137 } 138 // End location of the directive. 139 EndLoc = Tok.getLocation(); 140 // Consume final annot_pragma_openmp_end. 141 ConsumeToken(); 142 143 StmtResult AssociatedStmt; 144 bool CreateDirective = true; 145 ParseScope OMPDirectiveScope(this, ScopeFlags); 146 { 147 // The body is a block scope like in Lambdas and Blocks. 148 Sema::CompoundScopeRAII CompoundScope(Actions); 149 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1); 150 Actions.ActOnStartOfCompoundStmt(); 151 // Parse statement 152 AssociatedStmt = ParseStatement(); 153 Actions.ActOnFinishOfCompoundStmt(); 154 if (!AssociatedStmt.isUsable()) { 155 Actions.ActOnCapturedRegionError(); 156 CreateDirective = false; 157 } else { 158 AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take()); 159 CreateDirective = AssociatedStmt.isUsable(); 160 } 161 } 162 if (CreateDirective) 163 Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses, 164 AssociatedStmt.take(), 165 Loc, EndLoc); 166 167 // Exit scope. 168 Actions.EndOpenMPDSABlock(Directive.get()); 169 OMPDirectiveScope.Exit(); 170 } 171 break; 172 case OMPD_unknown: 173 Diag(Tok, diag::err_omp_unknown_directive); 174 SkipUntil(tok::annot_pragma_openmp_end); 175 break; 176 case OMPD_task: 177 case NUM_OPENMP_DIRECTIVES: 178 Diag(Tok, diag::err_omp_unexpected_directive) 179 << getOpenMPDirectiveName(DKind); 180 SkipUntil(tok::annot_pragma_openmp_end); 181 break; 182 } 183 return Directive; 184} 185 186/// \brief Parses list of simple variables for '#pragma omp threadprivate' 187/// directive. 188/// 189/// simple-variable-list: 190/// '(' id-expression {, id-expression} ')' 191/// 192bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, 193 SmallVectorImpl<Expr *> &VarList, 194 bool AllowScopeSpecifier) { 195 VarList.clear(); 196 // Parse '('. 197 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 198 if (T.expectAndConsume(diag::err_expected_lparen_after, 199 getOpenMPDirectiveName(Kind))) 200 return true; 201 bool IsCorrect = true; 202 bool NoIdentIsFound = true; 203 204 // Read tokens while ')' or annot_pragma_openmp_end is not found. 205 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 206 CXXScopeSpec SS; 207 SourceLocation TemplateKWLoc; 208 UnqualifiedId Name; 209 // Read var name. 210 Token PrevTok = Tok; 211 NoIdentIsFound = false; 212 213 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 214 ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) { 215 IsCorrect = false; 216 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 217 StopBeforeMatch); 218 } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(), 219 TemplateKWLoc, Name)) { 220 IsCorrect = false; 221 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 222 StopBeforeMatch); 223 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 224 Tok.isNot(tok::annot_pragma_openmp_end)) { 225 IsCorrect = false; 226 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 227 StopBeforeMatch); 228 Diag(PrevTok.getLocation(), diag::err_expected_ident) 229 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 230 } else { 231 DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name); 232 ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS, 233 NameInfo); 234 if (Res.isUsable()) 235 VarList.push_back(Res.take()); 236 } 237 // Consume ','. 238 if (Tok.is(tok::comma)) { 239 ConsumeToken(); 240 } 241 } 242 243 if (NoIdentIsFound) { 244 Diag(Tok, diag::err_expected_ident); 245 IsCorrect = false; 246 } 247 248 // Parse ')'. 249 IsCorrect = !T.consumeClose() && IsCorrect; 250 251 return !IsCorrect && VarList.empty(); 252} 253 254/// \brief Parsing of OpenMP clauses. 255/// 256/// clause: 257/// default-clause|private-clause|firstprivate-clause|shared-clause 258/// 259OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 260 OpenMPClauseKind CKind, bool FirstClause) { 261 OMPClause *Clause = 0; 262 bool ErrorFound = false; 263 // Check if clause is allowed for the given directive. 264 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { 265 Diag(Tok, diag::err_omp_unexpected_clause) 266 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 267 ErrorFound = true; 268 } 269 270 switch (CKind) { 271 case OMPC_default: 272 // OpenMP [2.9.3.1, Restrictions] 273 // Only a single default clause may be specified on a parallel or task 274 // directive. 275 if (!FirstClause) { 276 Diag(Tok, diag::err_omp_more_one_clause) 277 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); 278 } 279 280 Clause = ParseOpenMPSimpleClause(CKind); 281 break; 282 case OMPC_private: 283 case OMPC_firstprivate: 284 case OMPC_shared: 285 Clause = ParseOpenMPVarListClause(CKind); 286 break; 287 case OMPC_unknown: 288 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 289 << getOpenMPDirectiveName(DKind); 290 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 291 break; 292 case OMPC_threadprivate: 293 case NUM_OPENMP_CLAUSES: 294 Diag(Tok, diag::err_omp_unexpected_clause) 295 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 296 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 297 break; 298 } 299 return ErrorFound ? 0 : Clause; 300} 301 302/// \brief Parsing of simple OpenMP clauses like 'default'. 303/// 304/// default-clause: 305/// 'default' '(' 'none' | 'shared' ') 306/// 307OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { 308 SourceLocation Loc = Tok.getLocation(); 309 SourceLocation LOpen = ConsumeToken(); 310 // Parse '('. 311 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 312 if (T.expectAndConsume(diag::err_expected_lparen_after, 313 getOpenMPClauseName(Kind))) 314 return 0; 315 316 unsigned Type = Tok.isAnnotation() ? 317 unsigned(OMPC_DEFAULT_unknown) : 318 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); 319 SourceLocation TypeLoc = Tok.getLocation(); 320 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 321 Tok.isNot(tok::annot_pragma_openmp_end)) 322 ConsumeAnyToken(); 323 324 // Parse ')'. 325 T.consumeClose(); 326 327 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, 328 Tok.getLocation()); 329} 330 331/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 332/// 'shared', 'copyin', or 'reduction'. 333/// 334/// private-clause: 335/// 'private' '(' list ')' 336/// firstprivate-clause: 337/// 'firstprivate' '(' list ')' 338/// shared-clause: 339/// 'shared' '(' list ')' 340/// 341OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { 342 SourceLocation Loc = Tok.getLocation(); 343 SourceLocation LOpen = ConsumeToken(); 344 // Parse '('. 345 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 346 if (T.expectAndConsume(diag::err_expected_lparen_after, 347 getOpenMPClauseName(Kind))) 348 return 0; 349 350 SmallVector<Expr *, 5> Vars; 351 bool IsComma = true; 352 while (IsComma || (Tok.isNot(tok::r_paren) && 353 Tok.isNot(tok::annot_pragma_openmp_end))) { 354 // Parse variable 355 ExprResult VarExpr = ParseAssignmentExpression(); 356 if (VarExpr.isUsable()) { 357 Vars.push_back(VarExpr.take()); 358 } else { 359 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 360 StopBeforeMatch); 361 } 362 // Skip ',' if any 363 IsComma = Tok.is(tok::comma); 364 if (IsComma) { 365 ConsumeToken(); 366 } else if (Tok.isNot(tok::r_paren) && 367 Tok.isNot(tok::annot_pragma_openmp_end)) { 368 Diag(Tok, diag::err_omp_expected_punc) 369 << 1 << getOpenMPClauseName(Kind); 370 } 371 } 372 373 // Parse ')'. 374 T.consumeClose(); 375 if (Vars.empty()) 376 return 0; 377 378 return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen, 379 Tok.getLocation()); 380} 381 382