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