Clang Project

clang_source_code/unittests/AST/OMPStructuredBlockTest.cpp
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
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/ASTMatchers/ASTMatchers.h"
18#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
29const ast_matchers::internal::VariadicDynCastAllOfMatcher<
30    OMPExecutableDirective, OMPTargetDirective>
31    ompTargetDirective;
32
33StatementMatcher OMPInnermostStructuredBlockMatcher() {
34  return stmt(isOMPStructuredBlock(),
35              unless(hasDescendant(stmt(isOMPStructuredBlock()))))
36      .bind("id");
37}
38
39StatementMatcher 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::stringArgs = {
49      "-fopenmp=libomp",
50  };
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<FrontendActionFactoryFactory(
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      SourceOMPInnermostStructuredBlockMatcher(), "++i"));
83}
84
85TEST(OMPStructuredBlock, TestBarrier) {
86  const char *Source =
87      R"(
88void test() {
89#pragma omp barrier
90})";
91  ASSERT_TRUE(PrintedOMPStmtMatches(SourceOMPStandaloneDirectiveMatcher(),
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  const char *Expected = R"({
106    #pragma omp cancel parallel
107}
108)";
109  ASSERT_TRUE(PrintedOMPStmtMatches(
110      SourceOMPInnermostStructuredBlockMatcher(), Expected));
111  ASSERT_TRUE(PrintedOMPStmtMatches(SourceOMPStandaloneDirectiveMatcher(),
112                                    "#pragma omp cancel parallel\n"));
113}
114
115TEST(OMPStructuredBlock, TestCancellationPoint) {
116  const char *Source =
117      R"(
118void test() {
119#pragma omp parallel
120{
121    #pragma omp cancellation point parallel
122}
123})";
124  const char *Expected = R"({
125    #pragma omp cancellation point parallel
126}
127)";
128  ASSERT_TRUE(PrintedOMPStmtMatches(
129      SourceOMPInnermostStructuredBlockMatcher(), Expected));
130  ASSERT_TRUE(
131      PrintedOMPStmtMatches(SourceOMPStandaloneDirectiveMatcher(),
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      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), ";\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(SourceOMPStandaloneDirectiveMatcher(),
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      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), ";\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(SourceOMPInnermostStructuredBlockMatcher(),
301                            "{\n    #pragma omp ordered depend(source)\n}\n"));
302  ASSERT_TRUE(PrintedOMPStmtMatches(SourceOMPStandaloneDirectiveMatcher(),
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      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), "{\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      SourceOMPInnermostStructuredBlockMatcher(), "{\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      SourceOMPInnermostStructuredBlockMatcher(), ";\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(SourceOMPSectionsDirectiveMatcher(),
377                                    "{\n"
378                                    "    #pragma omp section\n"
379                                    "        ;\n"
380                                    "}\n"));
381  ASSERT_TRUE(PrintedOMPStmtMatches(
382      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), "{\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      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), ";\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(SourceOMPStandaloneDirectiveMatcher(),
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(SourceOMPStandaloneDirectiveMatcher(),
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      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), ";\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(SourceOMPStandaloneDirectiveMatcher(),
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      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), ";\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      SourceOMPInnermostStructuredBlockMatcher(), ";\n"));
506}
507
508TEST(OMPStructuredBlock, TestTaskwaitDirective) {
509  const char *Source =
510      R"(
511void test() {
512#pragma omp taskwait
513})";
514  ASSERT_TRUE(PrintedOMPStmtMatches(SourceOMPStandaloneDirectiveMatcher(),
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(SourceOMPStandaloneDirectiveMatcher(),
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      SourceOMPInnermostStructuredBlockMatcher(), ";\n"));
540}
541