[Clang][Unittest] Support for target update directive and from clause in clang unittests (#150580)

Added support for detecting `OMPTargetUpdateDirective` , `OMPFromClause`
and `OMPToClause` in Clang Unit Test Framework
This commit is contained in:
Amit Tiwari 2026-01-21 13:49:36 +05:30 committed by GitHub
parent 324888bdb6
commit f369d23cea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 660 additions and 0 deletions

View File

@ -8766,6 +8766,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
@ -8879,6 +8894,30 @@ 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;
/// 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.
//----------------------------------------------------------------------------//

View File

@ -1136,8 +1136,13 @@ 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<OMPClause, OMPToClause> ompToClause;
const internal::VariadicDynCastAllOfMatcher<Decl, CXXDeductionGuideDecl>
cxxDeductionGuideDecl;

View File

@ -530,7 +530,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(ofClass);
REGISTER_MATCHER(ofKind);
REGISTER_MATCHER(ompDefaultClause);
REGISTER_MATCHER(ompFromClause);
REGISTER_MATCHER(ompToClause);
REGISTER_MATCHER(ompExecutableDirective);
REGISTER_MATCHER(ompTargetUpdateDirective);
REGISTER_MATCHER(on);
REGISTER_MATCHER(onImplicitObjectArgument);
REGISTER_MATCHER(opaqueValueExpr);

View File

@ -4770,6 +4770,400 @@ void x() {
EXPECT_TRUE(matchesWithOpenMP(Source8, Matcher));
}
TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_From_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_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];
#pragma omp target update from(arr[0:8:2])
;
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(
Source0, ompTargetUpdateDirective(hasStructuredBlock(nullStmt()))));
}
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"(
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);
const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound);
ASSERT_TRUE(LowerBoundLiteral)
<< "Expected lower bound to be an integer literal";
EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 0u);
// length (8)
const Expr *Length = ArraySection->getLength();
ASSERT_TRUE(Length);
const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length);
ASSERT_TRUE(LengthLiteral) << "Expected length to be an integer literal";
EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 8u);
// stride (2)
const Expr *Stride = ArraySection->getStride();
ASSERT_TRUE(Stride);
const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride);
ASSERT_TRUE(StrideLiteral) << "Expected stride to be an integer literal";
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);
const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound);
ASSERT_TRUE(LowerBoundLiteral)
<< "Expected lower bound to be an integer literal";
EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 2u);
const Expr *Length = ArraySection->getLength();
ASSERT_TRUE(Length);
const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length);
ASSERT_TRUE(LengthLiteral) << "Expected length to be an integer literal";
EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 10u);
// Stride is optional (defaults to 1 when omitted)
const Expr *Stride = ArraySection->getStride();
if (Stride) {
const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride);
ASSERT_TRUE(StrideLiteral) << "Expected stride to be an integer literal";
EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 1u);
}
}
}
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 auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound);
ASSERT_TRUE(LowerBoundLiteral)
<< "Expected lower bound to be an integer literal";
EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 0u);
const Expr *Length = ArraySection->getLength();
ASSERT_TRUE(Length);
const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length);
ASSERT_TRUE(LengthLiteral) << "Expected length to be an integer literal";
EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 8u);
const Expr *Stride = ArraySection->getStride();
ASSERT_TRUE(Stride);
const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride);
ASSERT_TRUE(StrideLiteral) << "Expected stride to be an integer literal";
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);
const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound);
ASSERT_TRUE(LowerBoundLiteral)
<< "Expected lower bound to be an integer literal";
EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 1u);
const Expr *Length = ArraySection->getLength();
ASSERT_TRUE(Length);
const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length);
ASSERT_TRUE(LengthLiteral) << "Expected length to be an integer literal";
EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 15u);
// Stride is optional (defaults to 1 when omitted)
const Expr *Stride = ArraySection->getStride();
if (Stride) {
const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride);
ASSERT_TRUE(StrideLiteral) << "Expected stride to be an integer literal";
EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 1u);
}
}
}
TEST_P(ASTMatchersTest,
OMPTargetUpdateDirective_IsAllowedToContainClauseKind_From) {
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,
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, 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_DoesNotMatchTarget) {
auto Matcher = ompTargetUpdateDirective();
StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target map(tofrom:arr)
{ arr[0] = 1; }
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
}
TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_DoesNotMatchTargetData) {
auto Matcher = ompTargetUpdateDirective();
StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target data map(to:arr)
{ }
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
}
TEST_P(ASTMatchersTest, OMPFromClause_DoesNotMatchMapClause) {
auto Matcher = ompExecutableDirective(hasAnyClause(ompFromClause()));
StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target map(from:arr)
{ }
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
}
TEST_P(ASTMatchersTest, HasAnyBase_DirectBase) {
if (!GetParam().isCXX()) {
return;

View File

@ -2791,6 +2791,225 @@ void x() {
EXPECT_TRUE(notMatchesWithOpenMP(Source2, Matcher));
}
TEST(ASTMatchersTestOpenMP, OMPTargetUpdateDirective_From) {
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, 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()));
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);
const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound);
ASSERT_TRUE(LowerBoundLiteral)
<< "Expected lower bound to be an integer literal";
EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 0u);
// length (8)
const Expr *Length = ArraySection->getLength();
ASSERT_TRUE(Length);
const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length);
ASSERT_TRUE(LengthLiteral) << "Expected length to be an integer literal";
EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 8u);
// stride (2)
const Expr *Stride = ArraySection->getStride();
ASSERT_TRUE(Stride);
const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride);
ASSERT_TRUE(StrideLiteral) << "Expected stride to be an integer literal";
EXPECT_EQ(StrideLiteral->getValue().getZExtValue(), 2u);
}
}
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);
const auto *LowerBoundLiteral = dyn_cast<IntegerLiteral>(LowerBound);
ASSERT_TRUE(LowerBoundLiteral)
<< "Expected lower bound to be an integer literal";
EXPECT_EQ(LowerBoundLiteral->getValue().getZExtValue(), 0u);
// length (8)
const Expr *Length = ArraySection->getLength();
ASSERT_TRUE(Length);
const auto *LengthLiteral = dyn_cast<IntegerLiteral>(Length);
ASSERT_TRUE(LengthLiteral) << "Expected length to be an integer literal";
EXPECT_EQ(LengthLiteral->getValue().getZExtValue(), 8u);
// stride (2)
const Expr *Stride = ArraySection->getStride();
ASSERT_TRUE(Stride);
const auto *StrideLiteral = dyn_cast<IntegerLiteral>(Stride);
ASSERT_TRUE(StrideLiteral) << "Expected stride to be an integer literal";
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, OMPTargetUpdateDirective_DoesNotMatchTarget) {
auto Matcher = ompTargetUpdateDirective();
StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target map(tofrom:arr)
{ arr[0] = 1; }
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
}
TEST(ASTMatchersTestOpenMP, OMPTargetUpdateDirective_DoesNotMatchTargetData) {
auto Matcher = ompTargetUpdateDirective();
StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target data map(to:arr)
{ }
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
}
TEST(ASTMatchersTestOpenMP, OMPFromClause_DoesNotMatchMapClause) {
auto Matcher = ompExecutableDirective(hasAnyClause(ompFromClause()));
StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target map(from:arr)
{ }
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
}
TEST(ASTMatchersTestOpenMP, OMPDefaultClause) {
auto Matcher = ompExecutableDirective(hasAnyClause(ompDefaultClause()));