PageRenderTime 1764ms CodeModel.GetById 55ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Parse/ParseOpenMP.cpp

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