https://github.com/amitamd7 updated https://github.com/llvm/llvm-project/pull/150580
>From a7a8256e75aa6670f417540fc61998469b032596 Mon Sep 17 00:00:00 2001 From: amtiwari <[email protected]> Date: Fri, 25 Jul 2025 02:45:34 -0400 Subject: [PATCH 1/3] support_for_target_directive_clang_unittests --- clang/include/clang/ASTMatchers/ASTMatchers.h | 27 +++++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 4 + clang/lib/ASTMatchers/Dynamic/Registry.cpp | 2 + .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 99 +++++++++++++++++++ .../ASTMatchers/ASTMatchersNodeTest.cpp | 67 +++++++++++++ 5 files changed, 199 insertions(+) diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index f1d88a9523838..0ddf29095c548 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -8723,6 +8723,21 @@ AST_MATCHER_P(OMPExecutableDirective, hasAnyClause, Builder) != Clauses.end(); } +/// Matches any ``#pragma omp target update`` executable directive. +/// +/// Given +/// +/// \code +/// #pragma omp target update from(a) +/// #pragma omp target update to(b) +/// \endcode +/// +/// ``ompTargetUpdateDirective()`` matches both ``omp target update from(a)`` +/// and ``omp target update to(b)``. +extern const internal::VariadicDynCastAllOfMatcher<Stmt, + OMPTargetUpdateDirective> + ompTargetUpdateDirective; + /// Matches OpenMP ``default`` clause. /// /// Given @@ -8836,6 +8851,18 @@ AST_MATCHER_P(OMPExecutableDirective, isAllowedToContainClauseKind, Finder->getASTContext().getLangOpts().OpenMP); } +/// Matches OpenMP ``from`` clause. +/// +/// Given +/// +/// \code +/// #pragma omp target update from(a) +/// \endcode +/// +/// ``ompFromClause()`` matches ``from(a)``. +extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPFromClause> + ompFromClause; + //----------------------------------------------------------------------------// // End OpenMP handling. //----------------------------------------------------------------------------// diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 653b3810cb68b..1b01be069d9aa 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -1124,8 +1124,12 @@ AST_TYPELOC_TRAVERSE_MATCHER_DEF( const internal::VariadicDynCastAllOfMatcher<Stmt, OMPExecutableDirective> ompExecutableDirective; +const internal::VariadicDynCastAllOfMatcher<Stmt, OMPTargetUpdateDirective> + ompTargetUpdateDirective; const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause> ompDefaultClause; +const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPFromClause> + ompFromClause; const internal::VariadicDynCastAllOfMatcher<Decl, CXXDeductionGuideDecl> cxxDeductionGuideDecl; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 48a7b91969aef..a268e97f7aa18 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -528,7 +528,9 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(ofClass); REGISTER_MATCHER(ofKind); REGISTER_MATCHER(ompDefaultClause); + REGISTER_MATCHER(ompFromClause); REGISTER_MATCHER(ompExecutableDirective); + REGISTER_MATCHER(ompTargetUpdateDirective); REGISTER_MATCHER(on); REGISTER_MATCHER(onImplicitObjectArgument); REGISTER_MATCHER(opaqueValueExpr); diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index 8a957864cdd12..c30398605af5d 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -4734,6 +4734,105 @@ void x() { EXPECT_TRUE(matchesWithOpenMP(Source8, Matcher)); } +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_IsStandaloneDirective) { + auto Matcher = ompTargetUpdateDirective(isStandaloneDirective()); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update from(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_HasStructuredBlock) { + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update from(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(notMatchesWithOpenMP( + Source0, ompTargetUpdateDirective(hasStructuredBlock(nullStmt())))); +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_HasClause) { + auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompFromClause())); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update from(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + // base (arr) + const Expr *Base = ArraySection->getBase(); + ASSERT_TRUE(Base); + + // lower bound (0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + + // length (8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + + // stride (2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + } +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_IsAllowedToContainClauseKind) { + auto Matcher = ompTargetUpdateDirective( + isAllowedToContainClauseKind(llvm::omp::OMPC_from)); + + StringRef Source0 = R"( + void x() { + ; + } + )"; + EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); + + StringRef Source1 = R"( + void foo() { + int arr[8]; + #pragma omp target update from(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher)); +} + TEST_P(ASTMatchersTest, HasAnyBase_DirectBase) { if (!GetParam().isCXX()) { return; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index d7df9cae01f33..f2155a92a88e8 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -2742,6 +2742,73 @@ void x() { EXPECT_TRUE(notMatchesWithOpenMP(Source2, Matcher)); } +TEST(ASTMatchersTestOpenMP, OMPTargetUpdateDirective) { + auto Matcher = stmt(ompTargetUpdateDirective()); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update from(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); +} + +TEST(ASTMatchersTestOpenMP, OMPFromClause) { + auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompFromClause())); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update from(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // base (arr) + const Expr *Base = ArraySection->getBase(); + ASSERT_TRUE(Base); + + // lower bound (0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + + // length (8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + + // stride (2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + } +} + TEST(ASTMatchersTestOpenMP, OMPDefaultClause) { auto Matcher = ompExecutableDirective(hasAnyClause(ompDefaultClause())); >From b60f187f75c5167cfa980b7779b2d2f985f4ff2c Mon Sep 17 00:00:00 2001 From: amtiwari <[email protected]> Date: Fri, 5 Dec 2025 02:58:08 -0500 Subject: [PATCH 2/3] update_to clause support --- clang/include/clang/ASTMatchers/ASTMatchers.h | 12 ++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 1 + clang/lib/ASTMatchers/Dynamic/Registry.cpp | 1 + .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 106 +++++++++++++++++- .../ASTMatchers/ASTMatchersNodeTest.cpp | 69 +++++++++++- 5 files changed, 184 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 0ddf29095c548..f007ef3bdf88d 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -8863,6 +8863,18 @@ AST_MATCHER_P(OMPExecutableDirective, isAllowedToContainClauseKind, extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPFromClause> ompFromClause; +/// Matches OpenMP ``to`` clause. +/// +/// Given +/// +/// \code +/// #pragma omp target update to(a) +/// \endcode +/// +/// ``ompToClause()`` matches ``to(a)``. +extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPToClause> + ompToClause; + //----------------------------------------------------------------------------// // End OpenMP handling. //----------------------------------------------------------------------------// diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 1b01be069d9aa..5efa7f162789c 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -1130,6 +1130,7 @@ const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause> ompDefaultClause; const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPFromClause> ompFromClause; +const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPToClause> ompToClause; const internal::VariadicDynCastAllOfMatcher<Decl, CXXDeductionGuideDecl> cxxDeductionGuideDecl; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index a268e97f7aa18..447c70dc6f9af 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -529,6 +529,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(ofKind); REGISTER_MATCHER(ompDefaultClause); REGISTER_MATCHER(ompFromClause); + REGISTER_MATCHER(ompToClause); REGISTER_MATCHER(ompExecutableDirective); REGISTER_MATCHER(ompTargetUpdateDirective); REGISTER_MATCHER(on); diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index c30398605af5d..63639cc890ec9 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -4734,7 +4734,7 @@ void x() { EXPECT_TRUE(matchesWithOpenMP(Source8, Matcher)); } -TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_IsStandaloneDirective) { +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_From_IsStandaloneDirective) { auto Matcher = ompTargetUpdateDirective(isStandaloneDirective()); StringRef Source0 = R"( @@ -4747,7 +4747,20 @@ TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_IsStandaloneDirective) { EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); } -TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_HasStructuredBlock) { +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_IsStandaloneDirective) { + auto Matcher = ompTargetUpdateDirective(isStandaloneDirective()); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update to(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_From_HasStructuredBlock) { StringRef Source0 = R"( void foo() { int arr[8]; @@ -4759,7 +4772,19 @@ TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_HasStructuredBlock) { Source0, ompTargetUpdateDirective(hasStructuredBlock(nullStmt())))); } -TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_HasClause) { +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_HasStructuredBlock) { + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update to(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(notMatchesWithOpenMP( + Source0, ompTargetUpdateDirective(hasStructuredBlock(nullStmt())))); +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_From_HasClause) { auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompFromClause())); StringRef Source0 = R"( @@ -4812,7 +4837,58 @@ TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_HasClause) { } } -TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_IsAllowedToContainClauseKind) { +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_HasClause) { + auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompToClause())); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update to(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + const Expr *Base = ArraySection->getBase(); + ASSERT_TRUE(Base); + + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + } +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_IsAllowedToContainClauseKind_From) { auto Matcher = ompTargetUpdateDirective( isAllowedToContainClauseKind(llvm::omp::OMPC_from)); @@ -4833,6 +4909,28 @@ TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_IsAllowedToContainClauseKind) { EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher)); } +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_IsAllowedToContainClauseKind_To) { + auto Matcher = ompTargetUpdateDirective( + isAllowedToContainClauseKind(llvm::omp::OMPC_to)); + + StringRef Source0 = R"( + void x() { + ; + } + )"; + EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); + + StringRef Source1 = R"( + void foo() { + int arr[8]; + #pragma omp target update to(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher)); +} + TEST_P(ASTMatchersTest, HasAnyBase_DirectBase) { if (!GetParam().isCXX()) { return; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index f2155a92a88e8..edc84704b5ed2 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -2742,7 +2742,7 @@ void x() { EXPECT_TRUE(notMatchesWithOpenMP(Source2, Matcher)); } -TEST(ASTMatchersTestOpenMP, OMPTargetUpdateDirective) { +TEST(ASTMatchersTestOpenMP, OMPTargetUpdateDirective_From) { auto Matcher = stmt(ompTargetUpdateDirective()); StringRef Source0 = R"( @@ -2755,6 +2755,19 @@ TEST(ASTMatchersTestOpenMP, OMPTargetUpdateDirective) { EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); } +TEST(ASTMatchersTestOpenMP, OMPTargetUpdateDirective_To) { + auto Matcher = stmt(ompTargetUpdateDirective()); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update to(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); +} + TEST(ASTMatchersTestOpenMP, OMPFromClause) { auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompFromClause())); @@ -2809,6 +2822,60 @@ TEST(ASTMatchersTestOpenMP, OMPFromClause) { } } +TEST(ASTMatchersTestOpenMP, OMPToClause) { + auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompToClause())); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update to(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher)); + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // base (arr) + const Expr *Base = ArraySection->getBase(); + ASSERT_TRUE(Base); + + // lower bound (0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + + // length (8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + + // stride (2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + } +} + TEST(ASTMatchersTestOpenMP, OMPDefaultClause) { auto Matcher = ompExecutableDirective(hasAnyClause(ompDefaultClause())); >From 900f8d05135702bd35772c8d45de90bc48fdbd3f Mon Sep 17 00:00:00 2001 From: amtiwari <[email protected]> Date: Mon, 12 Jan 2026 06:56:52 -0500 Subject: [PATCH 3/3] handled_negative_checks --- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 720 ++++++++++++++++++ .../ASTMatchers/ASTMatchersNodeTest.cpp | 302 ++++++++ 2 files changed, 1022 insertions(+) diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index fb93e56e8069c..0c9f074a259fd 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -4839,14 +4839,77 @@ TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_From_HasClause) { // lower bound (0) const Expr *LowerBound = ArraySection->getLowerBound(); ASSERT_TRUE(LowerBound); + if (const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound)) { + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 0u); + } // length (8) const Expr *Length = ArraySection->getLength(); ASSERT_TRUE(Length); + if (const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length)) { + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 8u); + } // stride (2) const Expr *Stride = ArraySection->getStride(); ASSERT_TRUE(Stride); + if (const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride)) { + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 2u); + } + } +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_From_ArraySection_NoStride) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update from(arr[2:10]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + if (const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound)) { + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 2u); + } + + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + if (const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length)) { + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 10u); + } + + const Expr *Stride = ArraySection->getStride(); + if (Stride) { + if (const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride)) { + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 1u); + } + } } } @@ -4891,12 +4954,75 @@ TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_HasClause) { const Expr *LowerBound = ArraySection->getLowerBound(); ASSERT_TRUE(LowerBound); + if (const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound)) { + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 0u); + } const Expr *Length = ArraySection->getLength(); ASSERT_TRUE(Length); + if (const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length)) { + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 8u); + } const Expr *Stride = ArraySection->getStride(); ASSERT_TRUE(Stride); + if (const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride)) { + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 2u); + } + } +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_ArraySection_NoStride) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update to(arr[1:15]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + if (const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound)) { + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 1u); + } + + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + if (const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length)) { + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 15u); + } + + const Expr *Stride = ArraySection->getStride(); + if (Stride) { + if (const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride)) { + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 1u); + } + } } } @@ -4944,6 +5070,600 @@ TEST_P(ASTMatchersTest, EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher)); } +TEST_P(ASTMatchersTest, OMPFromClause_DoesNotMatchToClause) { + auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompFromClause())); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update to(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); +} + +TEST_P(ASTMatchersTest, OMPToClause_DoesNotMatchFromClause) { + auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompToClause())); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update from(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_From_ArraySection_WrongOffset) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update from(arr[5:8:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (5, not 0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + ASSERT_TRUE(isa<IntegerLiteral>(LowerBound)); + const auto *LowerBoundLiteral = cast<IntegerLiteral>(LowerBound); + EXPECT_NE(LowerBoundLiteral->getValue().getZExtValue(), 0u); + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 5u); + + // length (8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + + // stride (2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + } +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_From_ArraySection_OffsetVariable) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + int offset = 5; + #pragma omp target update from(arr[offset:8:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (variable, not literal) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + EXPECT_FALSE(isa<IntegerLiteral>(LowerBound)); + EXPECT_TRUE(isa<ImplicitCastExpr>(LowerBound) || + isa<DeclRefExpr>(LowerBound)); + } +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_From_ArraySection_WrongLength) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update from(arr[0:10:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + + // length (10, not 8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + ASSERT_TRUE(isa<IntegerLiteral>(Length)); + const auto *LengthLiteral = cast<IntegerLiteral>(Length); + EXPECT_NE(LengthLiteral->getValue().getZExtValue(), 8u); + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 10u); + + // stride (2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + } +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_From_ArraySection_LengthVariable) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + int len = 10; + #pragma omp target update from(arr[0:len:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // length (variable, not literal) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + EXPECT_FALSE(isa<IntegerLiteral>(Length)); + EXPECT_TRUE(isa<ImplicitCastExpr>(Length) || isa<DeclRefExpr>(Length)); + } +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_From_ArraySection_WrongStride) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update from(arr[0:8:4]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + + // length (8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + + // stride (4, not 2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + ASSERT_TRUE(isa<IntegerLiteral>(Stride)); + const auto *StrideLiteral = cast<IntegerLiteral>(Stride); + EXPECT_NE(StrideLiteral->getValue().getZExtValue(), 2u); + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 4u); + } +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_From_ArraySection_StrideVariable) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + int step = 4; + #pragma omp target update from(arr[0:8:step]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // stride (variable, not literal) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + EXPECT_FALSE(isa<IntegerLiteral>(Stride)); + EXPECT_TRUE(isa<ImplicitCastExpr>(Stride) || isa<DeclRefExpr>(Stride)); + } +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_ArraySection_WrongOffset) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update to(arr[3:8:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (3, not 0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + ASSERT_TRUE(isa<IntegerLiteral>(LowerBound)); + const auto *LowerBoundLiteral = cast<IntegerLiteral>(LowerBound); + EXPECT_NE(LowerBoundLiteral->getValue().getZExtValue(), 0u); + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 3u); + + // length (8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + + // stride (2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + } +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_To_ArraySection_OffsetVariable) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + int idx = 3; + #pragma omp target update to(arr[idx:8:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (variable, not literal) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + EXPECT_FALSE(isa<IntegerLiteral>(LowerBound)); + EXPECT_TRUE(isa<ImplicitCastExpr>(LowerBound) || + isa<DeclRefExpr>(LowerBound)); + } +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_ArraySection_WrongLength) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update to(arr[0:12:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + + // length (12, not 8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + ASSERT_TRUE(isa<IntegerLiteral>(Length)); + const auto *LengthLiteral = cast<IntegerLiteral>(Length); + EXPECT_NE(LengthLiteral->getValue().getZExtValue(), 8u); + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 12u); + + // stride (2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + } +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_To_ArraySection_LengthVariable) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + int count = 12; + #pragma omp target update to(arr[0:count:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // length (variable, not literal) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + EXPECT_FALSE(isa<IntegerLiteral>(Length)); + EXPECT_TRUE(isa<ImplicitCastExpr>(Length) || isa<DeclRefExpr>(Length)); + } +} + +TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_ArraySection_WrongStride) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update to(arr[0:8:3]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + + // length (8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + + // stride (3, not 2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + ASSERT_TRUE(isa<IntegerLiteral>(Stride)); + const auto *StrideLiteral = cast<IntegerLiteral>(Stride); + EXPECT_NE(StrideLiteral->getValue().getZExtValue(), 2u); + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 3u); + } +} + +TEST_P(ASTMatchersTest, + OMPTargetUpdateDirective_To_ArraySection_StrideVariable) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + int stride = 3; + #pragma omp target update to(arr[0:8:stride]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + EXPECT_FALSE(isa<IntegerLiteral>(Stride)); + EXPECT_TRUE(isa<ImplicitCastExpr>(Stride) || isa<DeclRefExpr>(Stride)); + } +} + TEST_P(ASTMatchersTest, HasAnyBase_DirectBase) { if (!GetParam().isCXX()) { return; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 8bf97d1ac0a8b..b1b09cfedd4c6 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -2839,14 +2839,23 @@ TEST(ASTMatchersTestOpenMP, OMPFromClause) { // lower bound (0) const Expr *LowerBound = ArraySection->getLowerBound(); ASSERT_TRUE(LowerBound); + if (const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound)) { + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 0u); + } // length (8) const Expr *Length = ArraySection->getLength(); ASSERT_TRUE(Length); + if (const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length)) { + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 8u); + } // stride (2) const Expr *Stride = ArraySection->getStride(); ASSERT_TRUE(Stride); + if (const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride)) { + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 2u); + } } } @@ -2893,14 +2902,307 @@ TEST(ASTMatchersTestOpenMP, OMPToClause) { // lower bound (0) const Expr *LowerBound = ArraySection->getLowerBound(); ASSERT_TRUE(LowerBound); + if (const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound)) { + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 0u); + } // length (8) const Expr *Length = ArraySection->getLength(); ASSERT_TRUE(Length); + if (const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length)) { + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 8u); + } // stride (2) const Expr *Stride = ArraySection->getStride(); ASSERT_TRUE(Stride); + if (const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride)) { + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 2u); + } + } +} + +TEST(ASTMatchersTestOpenMP, OMPFromClause_DoesNotMatchToClause) { + auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompFromClause())); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update to(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); +} + +TEST(ASTMatchersTestOpenMP, OMPToClause_DoesNotMatchFromClause) { + auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompToClause())); + + StringRef Source0 = R"( + void foo() { + int arr[8]; + #pragma omp target update from(arr[0:8:2]) + ; + } + )"; + EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); +} + +TEST(ASTMatchersTestOpenMP, OMPFromClause_ArraySection_DifferentOffsetValue) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update from(arr[7:8:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (7, not 0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + ASSERT_TRUE(isa<IntegerLiteral>(LowerBound)); + const auto *LowerBoundLiteral = cast<IntegerLiteral>(LowerBound); + EXPECT_NE(LowerBoundLiteral->getValue().getZExtValue(), 0u); + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 7u); + } +} + +TEST(ASTMatchersTestOpenMP, OMPFromClause_ArraySection_DifferentLengthValue) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update from(arr[0:15:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // length (15, not 8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + ASSERT_TRUE(isa<IntegerLiteral>(Length)); + const auto *LengthLiteral = cast<IntegerLiteral>(Length); + EXPECT_NE(LengthLiteral->getValue().getZExtValue(), 8u); + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 15u); + } +} + +TEST(ASTMatchersTestOpenMP, OMPFromClause_ArraySection_DifferentStrideValue) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update from(arr[0:8:5]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPFromClause *FromClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((FromClause = dyn_cast<OMPFromClause>(Clause))) { + break; + } + } + ASSERT_TRUE(FromClause); + + for (const auto *VarExpr : FromClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // stride (5, not 2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + ASSERT_TRUE(isa<IntegerLiteral>(Stride)); + const auto *StrideLiteral = cast<IntegerLiteral>(Stride); + EXPECT_NE(StrideLiteral->getValue().getZExtValue(), 2u); + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 5u); + } +} + +TEST(ASTMatchersTestOpenMP, OMPToClause_ArraySection_DifferentOffsetValue) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update to(arr[4:8:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // lower bound (4, not 0) + const Expr *LowerBound = ArraySection->getLowerBound(); + ASSERT_TRUE(LowerBound); + ASSERT_TRUE(isa<IntegerLiteral>(LowerBound)); + const auto *LowerBoundLiteral = cast<IntegerLiteral>(LowerBound); + EXPECT_NE(LowerBoundLiteral->getValue().getZExtValue(), 0u); + EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 4u); + } +} + +TEST(ASTMatchersTestOpenMP, OMPToClause_ArraySection_DifferentLengthValue) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update to(arr[0:20:2]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // length (20, not 8) + const Expr *Length = ArraySection->getLength(); + ASSERT_TRUE(Length); + ASSERT_TRUE(isa<IntegerLiteral>(Length)); + const auto *LengthLiteral = cast<IntegerLiteral>(Length); + EXPECT_NE(LengthLiteral->getValue().getZExtValue(), 8u); + EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 20u); + } +} + +TEST(ASTMatchersTestOpenMP, OMPToClause_ArraySection_DifferentStrideValue) { + StringRef Source0 = R"( + void foo() { + int arr[20]; + #pragma omp target update to(arr[0:8:6]) + ; + } + )"; + + auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"}); + ASSERT_TRUE(astUnit); + + auto Results = match(ompTargetUpdateDirective().bind("directive"), + astUnit->getASTContext()); + ASSERT_FALSE(Results.empty()); + + const auto *Directive = + Results[0].getNodeAs<OMPTargetUpdateDirective>("directive"); + ASSERT_TRUE(Directive); + + OMPToClause *ToClause = nullptr; + for (auto *Clause : Directive->clauses()) { + if ((ToClause = dyn_cast<OMPToClause>(Clause))) { + break; + } + } + ASSERT_TRUE(ToClause); + + for (const auto *VarExpr : ToClause->varlist()) { + const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr); + if (!ArraySection) + continue; + + // stride (6, not 2) + const Expr *Stride = ArraySection->getStride(); + ASSERT_TRUE(Stride); + ASSERT_TRUE(isa<IntegerLiteral>(Stride)); + const auto *StrideLiteral = cast<IntegerLiteral>(Stride); + EXPECT_NE(StrideLiteral->getValue().getZExtValue(), 2u); + EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 6u); } } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
