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" 21 using 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 /// 32 Parser::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 /// 82 StmtResult 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 /// 192 bool 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 /// 259 OMPClause *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 /// 307 OMPClause *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 /// 341 OMPClause *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