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