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