OMPStructuredBlockTest.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. //===- unittests/AST/OMPStructuredBlockTest.cpp ---------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Fine-grained tests for IsOMPStructuredBlock bit of Stmt.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "ASTPrint.h"
  13. #include "clang/AST/ASTContext.h"
  14. #include "clang/AST/StmtOpenMP.h"
  15. #include "clang/ASTMatchers/ASTMatchFinder.h"
  16. #include "clang/ASTMatchers/ASTMatchers.h"
  17. #include "clang/Tooling/Tooling.h"
  18. #include "llvm/ADT/SmallString.h"
  19. #include "gmock/gmock.h"
  20. #include "gtest/gtest.h"
  21. using namespace clang;
  22. using namespace ast_matchers;
  23. using namespace tooling;
  24. namespace {
  25. const ast_matchers::internal::VariadicDynCastAllOfMatcher<
  26. OMPExecutableDirective, OMPTargetDirective>
  27. ompTargetDirective;
  28. StatementMatcher OMPInnermostStructuredBlockMatcher() {
  29. return stmt(isOMPStructuredBlock(),
  30. unless(hasDescendant(stmt(isOMPStructuredBlock()))))
  31. .bind("id");
  32. }
  33. StatementMatcher OMPStandaloneDirectiveMatcher() {
  34. return stmt(ompExecutableDirective(isStandaloneDirective())).bind("id");
  35. }
  36. template <typename T>
  37. ::testing::AssertionResult
  38. PrintedOMPStmtMatches(StringRef Code, const T &NodeMatch,
  39. StringRef ExpectedPrinted,
  40. PolicyAdjusterType PolicyAdjuster = None) {
  41. std::vector<std::string> Args = {
  42. "-fopenmp=libomp",
  43. };
  44. return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted,
  45. PolicyAdjuster);
  46. }
  47. static testing::AssertionResult NoMatches(StringRef Code,
  48. const StatementMatcher &StmtMatch) {
  49. PrintMatch Printer((PolicyAdjusterType()));
  50. MatchFinder Finder;
  51. Finder.addMatcher(StmtMatch, &Printer);
  52. std::unique_ptr<FrontendActionFactory> Factory(
  53. newFrontendActionFactory(&Finder));
  54. if (!runToolOnCode(Factory->create(), Code))
  55. return testing::AssertionFailure()
  56. << "Parsing error in \"" << Code.str() << "\"";
  57. if (Printer.getNumFoundStmts() == 0)
  58. return testing::AssertionSuccess();
  59. return testing::AssertionFailure()
  60. << "Matcher should match only zero statements (found "
  61. << Printer.getNumFoundStmts() << ")";
  62. }
  63. } // unnamed namespace
  64. TEST(OMPStructuredBlock, TestAtomic) {
  65. const char *Source =
  66. R"(
  67. void test(int i) {
  68. #pragma omp atomic
  69. ++i;
  70. })";
  71. ASSERT_TRUE(PrintedOMPStmtMatches(
  72. Source, OMPInnermostStructuredBlockMatcher(), "++i"));
  73. }
  74. TEST(OMPStructuredBlock, TestBarrier) {
  75. const char *Source =
  76. R"(
  77. void test() {
  78. #pragma omp barrier
  79. })";
  80. ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  81. "#pragma omp barrier\n"));
  82. ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
  83. }
  84. TEST(OMPStructuredBlock, TestCancel) {
  85. const char *Source =
  86. R"(
  87. void test() {
  88. #pragma omp parallel
  89. {
  90. #pragma omp cancel parallel
  91. }
  92. })";
  93. const char *Expected = R"({
  94. #pragma omp cancel parallel
  95. }
  96. )";
  97. ASSERT_TRUE(PrintedOMPStmtMatches(
  98. Source, OMPInnermostStructuredBlockMatcher(), Expected));
  99. ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  100. "#pragma omp cancel parallel\n"));
  101. }
  102. TEST(OMPStructuredBlock, TestCancellationPoint) {
  103. const char *Source =
  104. R"(
  105. void test() {
  106. #pragma omp parallel
  107. {
  108. #pragma omp cancellation point parallel
  109. }
  110. })";
  111. const char *Expected = R"({
  112. #pragma omp cancellation point parallel
  113. }
  114. )";
  115. ASSERT_TRUE(PrintedOMPStmtMatches(
  116. Source, OMPInnermostStructuredBlockMatcher(), Expected));
  117. ASSERT_TRUE(
  118. PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  119. "#pragma omp cancellation point parallel\n"));
  120. }
  121. TEST(OMPStructuredBlock, TestCritical) {
  122. const char *Source =
  123. R"(
  124. void test() {
  125. #pragma omp critical
  126. ;
  127. })";
  128. ASSERT_TRUE(PrintedOMPStmtMatches(
  129. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  130. }
  131. //----------------------------------------------------------------------------//
  132. // Loop tests
  133. //----------------------------------------------------------------------------//
  134. class OMPStructuredBlockLoop : public ::testing::TestWithParam<const char *> {};
  135. TEST_P(OMPStructuredBlockLoop, TestDirective0) {
  136. const std::string Source =
  137. R"(
  138. void test(int x) {
  139. #pragma omp )" +
  140. std::string(GetParam()) + R"(
  141. for (int i = 0; i < x; i++)
  142. ;
  143. })";
  144. ASSERT_TRUE(PrintedOMPStmtMatches(
  145. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  146. }
  147. TEST_P(OMPStructuredBlockLoop, TestDirective1) {
  148. const std::string Source =
  149. R"(
  150. void test(int x, int y) {
  151. #pragma omp )" +
  152. std::string(GetParam()) + R"(
  153. for (int i = 0; i < x; i++)
  154. for (int i = 0; i < y; i++)
  155. ;
  156. })";
  157. ASSERT_TRUE(PrintedOMPStmtMatches(Source,
  158. OMPInnermostStructuredBlockMatcher(),
  159. "for (int i = 0; i < y; i++)\n ;\n"));
  160. }
  161. TEST_P(OMPStructuredBlockLoop, TestDirectiveCollapse1) {
  162. const std::string Source =
  163. R"(
  164. void test(int x, int y) {
  165. #pragma omp )" +
  166. std::string(GetParam()) + R"( collapse(1)
  167. for (int i = 0; i < x; i++)
  168. for (int i = 0; i < y; i++)
  169. ;
  170. })";
  171. ASSERT_TRUE(PrintedOMPStmtMatches(Source,
  172. OMPInnermostStructuredBlockMatcher(),
  173. "for (int i = 0; i < y; i++)\n ;\n"));
  174. }
  175. TEST_P(OMPStructuredBlockLoop, TestDirectiveCollapse2) {
  176. const std::string Source =
  177. R"(
  178. void test(int x, int y) {
  179. #pragma omp )" +
  180. std::string(GetParam()) + R"( collapse(2)
  181. for (int i = 0; i < x; i++)
  182. for (int i = 0; i < y; i++)
  183. ;
  184. })";
  185. ASSERT_TRUE(PrintedOMPStmtMatches(
  186. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  187. }
  188. TEST_P(OMPStructuredBlockLoop, TestDirectiveCollapse22) {
  189. const std::string Source =
  190. R"(
  191. void test(int x, int y, int z) {
  192. #pragma omp )" +
  193. std::string(GetParam()) + R"( collapse(2)
  194. for (int i = 0; i < x; i++)
  195. for (int i = 0; i < y; i++)
  196. for (int i = 0; i < z; i++)
  197. ;
  198. })";
  199. ASSERT_TRUE(PrintedOMPStmtMatches(Source,
  200. OMPInnermostStructuredBlockMatcher(),
  201. "for (int i = 0; i < z; i++)\n ;\n"));
  202. }
  203. INSTANTIATE_TEST_CASE_P(
  204. OMPStructuredBlockLoopDirectives, OMPStructuredBlockLoop,
  205. ::testing::Values("simd", "for", "for simd", "parallel for",
  206. "parallel for simd", "target parallel for", "taskloop",
  207. "taskloop simd", "distribute", "distribute parallel for",
  208. "distribute parallel for simd", "distribute simd",
  209. "target parallel for simd", "target simd",
  210. "target\n#pragma omp teams distribute",
  211. "target\n#pragma omp teams distribute simd",
  212. "target\n#pragma omp teams distribute parallel for simd",
  213. "target\n#pragma omp teams distribute parallel for",
  214. "target teams distribute",
  215. "target teams distribute parallel for",
  216. "target teams distribute parallel for simd",
  217. "target teams distribute simd"), );
  218. //----------------------------------------------------------------------------//
  219. // End Loop tests
  220. //----------------------------------------------------------------------------//
  221. TEST(OMPStructuredBlock, TestFlush) {
  222. const char *Source =
  223. R"(
  224. void test() {
  225. #pragma omp flush
  226. })";
  227. ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  228. "#pragma omp flush\n"));
  229. ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
  230. }
  231. TEST(OMPStructuredBlock, TestMaster) {
  232. const char *Source =
  233. R"(
  234. void test() {
  235. #pragma omp master
  236. ;
  237. })";
  238. ASSERT_TRUE(PrintedOMPStmtMatches(
  239. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  240. }
  241. TEST(OMPStructuredBlock, TestOrdered0) {
  242. const char *Source =
  243. R"(
  244. void test() {
  245. #pragma omp ordered
  246. ;
  247. })";
  248. ASSERT_TRUE(PrintedOMPStmtMatches(
  249. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  250. }
  251. TEST(OMPStructuredBlock, TestOrdered1) {
  252. const char *Source =
  253. R"(
  254. void test(int x) {
  255. #pragma omp for ordered
  256. for (int i = 0; i < x; i++)
  257. ;
  258. })";
  259. ASSERT_TRUE(PrintedOMPStmtMatches(
  260. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  261. }
  262. TEST(OMPStructuredBlock, TestOrdered2) {
  263. const char *Source =
  264. R"(
  265. void test(int x) {
  266. #pragma omp for ordered(1)
  267. for (int i = 0; i < x; i++) {
  268. #pragma omp ordered depend(source)
  269. }
  270. })";
  271. ASSERT_TRUE(
  272. PrintedOMPStmtMatches(Source, OMPInnermostStructuredBlockMatcher(),
  273. "{\n #pragma omp ordered depend(source)\n}\n"));
  274. ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  275. "#pragma omp ordered depend(source)\n"));
  276. }
  277. TEST(OMPStructuredBlock, DISABLED_TestParallelMaster0XFAIL) {
  278. const char *Source =
  279. R"(
  280. void test() {
  281. #pragma omp parallel master
  282. ;
  283. })";
  284. ASSERT_TRUE(PrintedOMPStmtMatches(
  285. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  286. }
  287. TEST(OMPStructuredBlock, DISABLED_TestParallelMaster1XFAIL) {
  288. const char *Source =
  289. R"(
  290. void test() {
  291. #pragma omp parallel master
  292. { ; }
  293. })";
  294. ASSERT_TRUE(PrintedOMPStmtMatches(
  295. Source, OMPInnermostStructuredBlockMatcher(), "{\n ;\n}\n"));
  296. }
  297. TEST(OMPStructuredBlock, TestParallelSections) {
  298. const char *Source =
  299. R"(
  300. void test() {
  301. #pragma omp parallel sections
  302. { ; }
  303. })";
  304. ASSERT_TRUE(PrintedOMPStmtMatches(
  305. Source, OMPInnermostStructuredBlockMatcher(), "{\n ;\n}\n"));
  306. }
  307. TEST(OMPStructuredBlock, TestParallelDirective) {
  308. const char *Source =
  309. R"(
  310. void test() {
  311. #pragma omp parallel
  312. ;
  313. })";
  314. ASSERT_TRUE(PrintedOMPStmtMatches(
  315. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  316. }
  317. const ast_matchers::internal::VariadicDynCastAllOfMatcher<
  318. OMPExecutableDirective, OMPSectionsDirective>
  319. ompSectionsDirective;
  320. const ast_matchers::internal::VariadicDynCastAllOfMatcher<
  321. OMPExecutableDirective, OMPSectionDirective>
  322. ompSectionDirective;
  323. StatementMatcher OMPSectionsDirectiveMatcher() {
  324. return stmt(
  325. isOMPStructuredBlock(),
  326. hasAncestor(ompExecutableDirective(ompSectionsDirective())),
  327. unless(hasAncestor(ompExecutableDirective(ompSectionDirective()))))
  328. .bind("id");
  329. }
  330. TEST(OMPStructuredBlock, TestSectionDirective) {
  331. const char *Source =
  332. R"(
  333. void test() {
  334. #pragma omp sections
  335. {
  336. #pragma omp section
  337. ;
  338. }
  339. })";
  340. ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPSectionsDirectiveMatcher(),
  341. "{\n"
  342. " #pragma omp section\n"
  343. " ;\n"
  344. "}\n"));
  345. ASSERT_TRUE(PrintedOMPStmtMatches(
  346. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  347. }
  348. TEST(OMPStructuredBlock, TestSections) {
  349. const char *Source =
  350. R"(
  351. void test() {
  352. #pragma omp sections
  353. { ; }
  354. })";
  355. ASSERT_TRUE(PrintedOMPStmtMatches(
  356. Source, OMPInnermostStructuredBlockMatcher(), "{\n ;\n}\n"));
  357. }
  358. TEST(OMPStructuredBlock, TestSingleDirective) {
  359. const char *Source =
  360. R"(
  361. void test() {
  362. #pragma omp single
  363. ;
  364. })";
  365. ASSERT_TRUE(PrintedOMPStmtMatches(
  366. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  367. }
  368. TEST(OMPStructuredBlock, TesTargetDataDirective) {
  369. const char *Source =
  370. R"(
  371. void test(int x) {
  372. #pragma omp target data map(x)
  373. ;
  374. })";
  375. ASSERT_TRUE(PrintedOMPStmtMatches(
  376. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  377. }
  378. TEST(OMPStructuredBlock, TesTargetEnterDataDirective) {
  379. const char *Source =
  380. R"(
  381. void test(int x) {
  382. #pragma omp target enter data map(to : x)
  383. })";
  384. ASSERT_TRUE(
  385. PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  386. "#pragma omp target enter data map(to: x)\n"));
  387. ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
  388. }
  389. TEST(OMPStructuredBlock, TesTargetExitDataDirective) {
  390. const char *Source =
  391. R"(
  392. void test(int x) {
  393. #pragma omp target exit data map(from : x)
  394. })";
  395. ASSERT_TRUE(
  396. PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  397. "#pragma omp target exit data map(from: x)\n"));
  398. ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
  399. }
  400. TEST(OMPStructuredBlock, TestTargetParallelDirective) {
  401. const char *Source =
  402. R"(
  403. void test() {
  404. #pragma omp target parallel
  405. ;
  406. })";
  407. ASSERT_TRUE(PrintedOMPStmtMatches(
  408. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  409. }
  410. TEST(OMPStructuredBlock, TestTargetTeams) {
  411. const char *Source =
  412. R"(
  413. void test() {
  414. #pragma omp target teams
  415. ;
  416. })";
  417. ASSERT_TRUE(PrintedOMPStmtMatches(
  418. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  419. }
  420. TEST(OMPStructuredBlock, TestTargetUpdateDirective) {
  421. const char *Source =
  422. R"(
  423. void test(int x) {
  424. #pragma omp target update to(x)
  425. })";
  426. ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  427. "#pragma omp target update to(x)\n"));
  428. ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
  429. }
  430. TEST(OMPStructuredBlock, TestTarget) {
  431. const char *Source =
  432. R"(
  433. void test() {
  434. #pragma omp target
  435. ;
  436. })";
  437. ASSERT_TRUE(PrintedOMPStmtMatches(
  438. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  439. }
  440. TEST(OMPStructuredBlock, TestTask) {
  441. const char *Source =
  442. R"(
  443. void test() {
  444. #pragma omp task
  445. ;
  446. })";
  447. ASSERT_TRUE(PrintedOMPStmtMatches(
  448. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  449. }
  450. TEST(OMPStructuredBlock, TestTaskgroup) {
  451. const char *Source =
  452. R"(
  453. void test() {
  454. #pragma omp taskgroup
  455. ;
  456. })";
  457. ASSERT_TRUE(PrintedOMPStmtMatches(
  458. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  459. }
  460. TEST(OMPStructuredBlock, TestTaskwaitDirective) {
  461. const char *Source =
  462. R"(
  463. void test() {
  464. #pragma omp taskwait
  465. })";
  466. ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  467. "#pragma omp taskwait\n"));
  468. ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
  469. }
  470. TEST(OMPStructuredBlock, TestTaskyieldDirective) {
  471. const char *Source =
  472. R"(
  473. void test() {
  474. #pragma omp taskyield
  475. })";
  476. ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
  477. "#pragma omp taskyield\n"));
  478. ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
  479. }
  480. TEST(OMPStructuredBlock, TestTeams) {
  481. const char *Source =
  482. R"(
  483. void test() {
  484. #pragma omp target
  485. #pragma omp teams
  486. ;
  487. })";
  488. ASSERT_TRUE(PrintedOMPStmtMatches(
  489. Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
  490. }