blob: 623bed388c0246b55543b03f74239e375a8ed620 [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})";
105 ASSERT_TRUE(
106 PrintedOMPStmtMatches(Source, OMPInnermostStructuredBlockMatcher(), R"({
107 #pragma omp cancel parallel
108}
109)"));
110 ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
111 "#pragma omp cancel parallel\n"));
112}
113
114TEST(OMPStructuredBlock, TestCancellationPoint) {
115 const char *Source =
116 R"(
117void test() {
118#pragma omp parallel
119{
120#pragma omp cancellation point parallel
121}
122})";
123 ASSERT_TRUE(
124 PrintedOMPStmtMatches(Source, OMPInnermostStructuredBlockMatcher(), R"({
125 #pragma omp cancellation point parallel
126}
127)"));
128 ASSERT_TRUE(
129 PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
130 "#pragma omp cancellation point parallel\n"));
131}
132
133TEST(OMPStructuredBlock, TestCritical) {
134 const char *Source =
135 R"(
136void test() {
137#pragma omp critical
138;
139})";
140 ASSERT_TRUE(PrintedOMPStmtMatches(
141 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
142}
143
144//----------------------------------------------------------------------------//
145// Loop tests
146//----------------------------------------------------------------------------//
147
148class OMPStructuredBlockLoop : public ::testing::TestWithParam<const char *> {};
149
150TEST_P(OMPStructuredBlockLoop, TestDirective0) {
151 const std::string Source =
152 R"(
153void test(int x) {
154#pragma omp )" +
155 std::string(GetParam()) + R"(
156for (int i = 0; i < x; i++)
157;
158})";
159 ASSERT_TRUE(PrintedOMPStmtMatches(
160 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
161}
162
163TEST_P(OMPStructuredBlockLoop, TestDirective1) {
164 const std::string Source =
165 R"(
166void test(int x, int y) {
167#pragma omp )" +
168 std::string(GetParam()) + R"(
169for (int i = 0; i < x; i++)
170for (int i = 0; i < y; i++)
171;
172})";
173 ASSERT_TRUE(PrintedOMPStmtMatches(Source,
174 OMPInnermostStructuredBlockMatcher(),
175 "for (int i = 0; i < y; i++)\n ;\n"));
176}
177
178TEST_P(OMPStructuredBlockLoop, TestDirectiveCollapse1) {
179 const std::string Source =
180 R"(
181void test(int x, int y) {
182#pragma omp )" +
183 std::string(GetParam()) + R"( collapse(1)
184for (int i = 0; i < x; i++)
185for (int i = 0; i < y; i++)
186;
187})";
188 ASSERT_TRUE(PrintedOMPStmtMatches(Source,
189 OMPInnermostStructuredBlockMatcher(),
190 "for (int i = 0; i < y; i++)\n ;\n"));
191}
192
193TEST_P(OMPStructuredBlockLoop, TestDirectiveCollapse2) {
194 const std::string Source =
195 R"(
196void test(int x, int y) {
197#pragma omp )" +
198 std::string(GetParam()) + R"( collapse(2)
199for (int i = 0; i < x; i++)
200for (int i = 0; i < y; i++)
201;
202})";
203 ASSERT_TRUE(PrintedOMPStmtMatches(
204 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
205}
206
207TEST_P(OMPStructuredBlockLoop, TestDirectiveCollapse22) {
208 const std::string Source =
209 R"(
210void test(int x, int y, int z) {
211#pragma omp )" +
212 std::string(GetParam()) + R"( collapse(2)
213for (int i = 0; i < x; i++)
214for (int i = 0; i < y; i++)
215for (int i = 0; i < z; i++)
216;
217})";
218 ASSERT_TRUE(PrintedOMPStmtMatches(Source,
219 OMPInnermostStructuredBlockMatcher(),
220 "for (int i = 0; i < z; i++)\n ;\n"));
221}
222
223INSTANTIATE_TEST_CASE_P(
224 OMPStructuredBlockLoopDirectives, OMPStructuredBlockLoop,
225 ::testing::Values("simd", "for", "for simd", "parallel for",
226 "parallel for simd", "target parallel for", "taskloop",
227 "taskloop simd", "distribute", "distribute parallel for",
228 "distribute parallel for simd", "distribute simd",
229 "target parallel for simd", "target simd",
230 "target\n#pragma omp teams distribute",
231 "target\n#pragma omp teams distribute simd",
232 "target\n#pragma omp teams distribute parallel for simd",
233 "target\n#pragma omp teams distribute parallel for",
234 "target teams distribute",
235 "target teams distribute parallel for",
236 "target teams distribute parallel for simd",
237 "target teams distribute simd"), );
238
239//----------------------------------------------------------------------------//
240// End Loop tests
241//----------------------------------------------------------------------------//
242
243TEST(OMPStructuredBlock, TestFlush) {
244 const char *Source =
245 R"(
246void test() {
247#pragma omp flush
248})";
249 ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
250 "#pragma omp flush\n"));
251 ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
252}
253
254TEST(OMPStructuredBlock, TestMaster) {
255 const char *Source =
256 R"(
257void test() {
258#pragma omp master
259;
260})";
261 ASSERT_TRUE(PrintedOMPStmtMatches(
262 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
263}
264
265TEST(OMPStructuredBlock, TestOrdered0) {
266 const char *Source =
267 R"(
268void test() {
269#pragma omp ordered
270;
271})";
272 ASSERT_TRUE(PrintedOMPStmtMatches(
273 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
274}
275
276TEST(OMPStructuredBlock, TestOrdered1) {
277 const char *Source =
278 R"(
279void test(int x) {
280#pragma omp for ordered
281for (int i = 0; i < x; i++)
282;
283})";
284 ASSERT_TRUE(PrintedOMPStmtMatches(
285 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
286}
287
288TEST(OMPStructuredBlock, TestOrdered2) {
289 const char *Source =
290 R"(
291void test(int x) {
292#pragma omp for ordered(1)
293for (int i = 0; i < x; i++) {
294#pragma omp ordered depend(source)
295}
296})";
297 ASSERT_TRUE(
298 PrintedOMPStmtMatches(Source, OMPInnermostStructuredBlockMatcher(),
299 "{\n #pragma omp ordered depend(source)\n}\n"));
300 ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
301 "#pragma omp ordered depend(source)\n"));
302}
303
304TEST(OMPStructuredBlock, DISABLED_TestParallelMaster0XFAIL) {
305 const char *Source =
306 R"(
307void test() {
308#pragma omp parallel master
309;
310})";
311 ASSERT_TRUE(PrintedOMPStmtMatches(
312 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
313}
314
315TEST(OMPStructuredBlock, DISABLED_TestParallelMaster1XFAIL) {
316 const char *Source =
317 R"(
318void test() {
319#pragma omp parallel master
320{ ; }
321})";
322 ASSERT_TRUE(PrintedOMPStmtMatches(
323 Source, OMPInnermostStructuredBlockMatcher(), "{\n ;\n}\n"));
324}
325
326TEST(OMPStructuredBlock, TestParallelSections) {
327 const char *Source =
328 R"(
329void test() {
330#pragma omp parallel sections
331{ ; }
332})";
333 ASSERT_TRUE(PrintedOMPStmtMatches(
334 Source, OMPInnermostStructuredBlockMatcher(), "{\n ;\n}\n"));
335}
336
337TEST(OMPStructuredBlock, TestParallelDirective) {
338 const char *Source =
339 R"(
340void test() {
341#pragma omp parallel
342;
343})";
344 ASSERT_TRUE(PrintedOMPStmtMatches(
345 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
346}
347
348const ast_matchers::internal::VariadicDynCastAllOfMatcher<
349 OMPExecutableDirective, OMPSectionsDirective>
350 ompSectionsDirective;
351
352const ast_matchers::internal::VariadicDynCastAllOfMatcher<
353 OMPExecutableDirective, OMPSectionDirective>
354 ompSectionDirective;
355
356StatementMatcher OMPSectionsDirectiveMatcher() {
357 return stmt(
358 isOMPStructuredBlock(),
359 hasAncestor(ompExecutableDirective(ompSectionsDirective())),
360 unless(hasAncestor(ompExecutableDirective(ompSectionDirective()))))
361 .bind("id");
362}
363
364TEST(OMPStructuredBlock, TestSectionDirective) {
365 const char *Source =
366 R"(
367void test() {
368#pragma omp sections
369{
370#pragma omp section
371;
372}
373})";
374 ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPSectionsDirectiveMatcher(),
375 "{\n"
376 " #pragma omp section\n"
377 " ;\n"
378 "}\n"));
379 ASSERT_TRUE(PrintedOMPStmtMatches(
380 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
381}
382
383TEST(OMPStructuredBlock, TestSections) {
384 const char *Source =
385 R"(
386void test() {
387#pragma omp sections
388{ ; }
389})";
390 ASSERT_TRUE(PrintedOMPStmtMatches(
391 Source, OMPInnermostStructuredBlockMatcher(), "{\n ;\n}\n"));
392}
393
394TEST(OMPStructuredBlock, TestSingleDirective) {
395 const char *Source =
396 R"(
397void test() {
398#pragma omp single
399;
400})";
401 ASSERT_TRUE(PrintedOMPStmtMatches(
402 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
403}
404
405TEST(OMPStructuredBlock, TesTargetDataDirective) {
406 const char *Source =
407 R"(
408void test(int x) {
409#pragma omp target data map(x)
410;
411})";
412 ASSERT_TRUE(PrintedOMPStmtMatches(
413 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
414}
415
416TEST(OMPStructuredBlock, TesTargetEnterDataDirective) {
417 const char *Source =
418 R"(
419void test(int x) {
420#pragma omp target enter data map(to : x)
421})";
422 ASSERT_TRUE(
423 PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
424 "#pragma omp target enter data map(to: x)\n"));
425 ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
426}
427
428TEST(OMPStructuredBlock, TesTargetExitDataDirective) {
429 const char *Source =
430 R"(
431void test(int x) {
432#pragma omp target exit data map(from : x)
433})";
434 ASSERT_TRUE(
435 PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
436 "#pragma omp target exit data map(from: x)\n"));
437 ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
438}
439
440TEST(OMPStructuredBlock, TestTargetParallelDirective) {
441 const char *Source =
442 R"(
443void test() {
444#pragma omp target parallel
445;
446})";
447 ASSERT_TRUE(PrintedOMPStmtMatches(
448 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
449}
450
451TEST(OMPStructuredBlock, TestTargetTeams) {
452 const char *Source =
453 R"(
454void test() {
455#pragma omp target teams
456;
457})";
458 ASSERT_TRUE(PrintedOMPStmtMatches(
459 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
460}
461
462TEST(OMPStructuredBlock, TestTargetUpdateDirective) {
463 const char *Source =
464 R"(
465void test(int x) {
466#pragma omp target update to(x)
467})";
468 ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
469 "#pragma omp target update to(x)\n"));
470 ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
471}
472
473TEST(OMPStructuredBlock, TestTarget) {
474 const char *Source =
475 R"(
476void test() {
477#pragma omp target
478;
479})";
480 ASSERT_TRUE(PrintedOMPStmtMatches(
481 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
482}
483
484TEST(OMPStructuredBlock, TestTask) {
485 const char *Source =
486 R"(
487void test() {
488#pragma omp task
489;
490})";
491 ASSERT_TRUE(PrintedOMPStmtMatches(
492 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
493}
494
495TEST(OMPStructuredBlock, TestTaskgroup) {
496 const char *Source =
497 R"(
498void test() {
499#pragma omp taskgroup
500;
501})";
502 ASSERT_TRUE(PrintedOMPStmtMatches(
503 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
504}
505
506TEST(OMPStructuredBlock, TestTaskwaitDirective) {
507 const char *Source =
508 R"(
509void test() {
510#pragma omp taskwait
511})";
512 ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
513 "#pragma omp taskwait\n"));
514 ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
515}
516
517TEST(OMPStructuredBlock, TestTaskyieldDirective) {
518 const char *Source =
519 R"(
520void test() {
521#pragma omp taskyield
522})";
523 ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
524 "#pragma omp taskyield\n"));
525 ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
526}
527
528TEST(OMPStructuredBlock, TestTeams) {
529 const char *Source =
530 R"(
531void test() {
532#pragma omp target
533#pragma omp teams
534;
535})";
536 ASSERT_TRUE(PrintedOMPStmtMatches(
537 Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
538}