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